$(srcdir)/pobj_comp $<
## Dependencies for the build
-combat.o: combat.cc combat.hh victrix-abyssi.hh monsters.hh objects.hh pobj_id.hh
+combat.o: combat.cc combat.hh victrix-abyssi.hh monsters.hh objects.hh notify.hh pobj_id.hh
display-nc.o: display-nc.cc victrix-abyssi.hh display.hh pobj_id.hh
-main.o: main.cc combat.hh victrix-abyssi.hh monsters.hh pobj_id.hh
+main.o: main.cc combat.hh victrix-abyssi.hh monsters.hh notify.hh pobj_id.hh
-map.o: map.cc victrix-abyssi.hh objects.hh
+map.o: map.cc victrix-abyssi.hh notify.hh objects.hh
-monsters.o: monsters.cc victrix-abyssi.hh monsters.hh objects.hh
+monsters.o: monsters.cc victrix-abyssi.hh monsters.hh notify.hh objects.hh
-mon2.o: mon2.cc victrix-abyssi.hh sorcery.hh monsters.hh objects.hh
+mon2.o: mon2.cc victrix-abyssi.hh sorcery.hh monsters.hh notify.hh objects.hh
notify-local-tty.o: notify-local-tty.cc victrix-abyssi.hh combat.hh monsters.hh notify.hh objects.hh sorcery.hh pobj_id.hh
permons.o: permons.cc victrix-abyssi.hh monsters.hh
-pmon2.o: pmon2.cc victrix-abyssi.hh monsters.hh
+pmon2.o: pmon2.cc victrix-abyssi.hh notify.hh monsters.hh
-objects.o: objects.cc victrix-abyssi.hh objects.hh monsters.hh pobj_id.hh
+objects.o: objects.cc victrix-abyssi.hh notify.hh objects.hh monsters.hh pobj_id.hh
-sorcery.o: sorcery.cc victrix-abyssi.hh sorcery.hh objects.hh monsters.hh
+sorcery.o: sorcery.cc victrix-abyssi.hh notify.hh sorcery.hh objects.hh monsters.hh
-u.o: u.cc combat.hh victrix-abyssi.hh monsters.hh objects.hh pobj_id.hh
+u.o: u.cc combat.hh victrix-abyssi.hh notify.hh monsters.hh objects.hh pobj_id.hh
# vim:ts=8:sts=8:sw=8:noexpandtab
switch (kb)
{
case 0:
- notify_knockback_mon_fail();
break;
case 1:
- notify_knockback_mon_pass();
break;
case 2:
/* message handled elsewhere */
step = mysign(delta);
/* Don't get the bonus that applies to melee attacks. */
tohit = zero_die(mptr->rtohit);
- print_mon_name(mon, 3);
dtype = permons[mptr->mon_id].rdtyp;
- if (dtype == DT_PHYS)
- {
- print_msg(" %s at you!\n", permons[mptr->mon_id].shootverb);
- }
- else
- {
- print_msg(" %s %s at you!\n", permons[mptr->mon_id].shootverb, damtype_names[dtype]);
- }
+ notify_mon_ranged_attack(mon);
if ((dtype == DT_NECRO) || (dtype == DT_ELEC))
{
/* Use agility-based defence for necromantic blasts and lightning
/* Move projectile one square before looking for targets. */
for ((done = 0), (c = mptr->pos + step); !done; c += step)
{
- int mon;
+ int victim;
if ((lvl.terrain_at(c) == WALL) || (lvl.terrain_at(c) == DOOR))
{
done = 1;
}
- mon = lvl.mon_at(c);
+ victim = lvl.mon_at(c);
if (c == u.pos)
{
if (tohit >= defence)
{
done = 1;
- print_msg("It hits you!\n");
+ notify_mon_ranged_hit_player(mon);
unaffected = u.resists(dtype);
if (!unaffected)
{
}
else
{
- print_msg("It misses you.\n");
+ notify_mon_ranged_missed_player(mon);
}
}
- else if (mon != NO_MON)
+ else if (victim != NO_MON)
{
done = 1;
- bystander = monsters + mon;
+ bystander = monsters + victim;
switch (dtype)
{
case DT_COLD:
}
if (tohit >= bystander->defence)
{
+ notify_mon_ranged_hit_mon(mon, victim);
damage = one_die(mptr->rdam);
- damage_mon(mon, dtype, false);
+ damage_mon(victim, dtype, false);
}
}
}
POWER 4
POWER2 0
DEPTH 1
+DAMAGEABLE
WEAPON long sword
PLURAL long swords
POWER 10
POWER2 0
DEPTH 4
+DAMAGEABLE
WEAPON mace
PLURAL maces
POWER 7
POWER2 0
DEPTH 2
+DAMAGEABLE
WEAPON runesword
PLURAL runeswords
POWER 20
POWER2 0
DEPTH 12
+DAMAGEABLE
WEAPON tormentor's lash
PLURAL tormentor's lashes
POWER2 0
DEPTH 30
NOTIFY_EQUIP
+DAMAGEABLE
+BREAK_REACT
WEAPON staff of fire
PLURAL staves of fire
POWER 10
POWER2 0
DEPTH 20
+DAMAGEABLE
+ACTIVATABLE
WEAPON bow
PLURAL bows
POWER 8
POWER2 0
DEPTH 1
+DAMAGEABLE
WEAPON crossbow
PLURAL crossbows
POWER 16
POWER2 0
DEPTH 6
+DAMAGEABLE
WEAPON thunderbow
PLURAL thunderbows
POWER 16
POWER2 0
DEPTH 30
+DAMAGEABLE
POTION healing potion
PLURAL healing potions
POWER 0
POWER2 0
DEPTH 1
+STACKABLE
POTION body potion
PLURAL body potions
POWER 0
POWER2 0
DEPTH 5
+STACKABLE
POTION agility potion
PLURAL agility potions
POWER 0
POWER2 0
DEPTH 5
+STACKABLE
POTION restoration potion
PLURAL restoration potions
POWER 0
POWER2 0
DEPTH 1
-
-#FLASK poison flask
-#PLURAL poison flask
-#DESC This fragile bottle is full of contact poison.
-#RARITY 10
-#ASCII '~'
-#UTF8 "~"
-#COLOUR l_grey
-#POWER 0
-#POWER2 0
-#DEPTH 1
-
-#FLASK fire flask
-#PLURAL fire flasks
-#DESC The volatile, phosphorus-laced liquid in this sealed flask will ignite spontaneously when exposed to the air.
-#RARITY 40
-#ASCII '~'
-#UTF8 "~"
-#COLOUR l_grey
-#POWER 0
-#POWER2 0
-#DEPTH 20
-
-#FLASK weakness flask
-#PLURAL weakness flasks
-#DESC Dousing the living in this vile liquid causes immediate and severe physical degeneration.
-#RARITY 40
-#ASCII '~'
-#UTF8 "~"
-#COLOUR l_grey
-#POWER 0
-#POWER2 0
-#DEPTH 20
+STACKABLE
SCROLL teleport scroll
PLURAL teleport scrolls
POWER 0
POWER2 0
DEPTH 1
+STACKABLE
SCROLL fire scroll
PLURAL fire scrolls
POWER 0
POWER2 0
DEPTH 1
+STACKABLE
SCROLL protection scroll
PLURAL protection scrolls
POWER 0
POWER2 0
DEPTH 8
+STACKABLE
ARMOUR leather armour
PLURAL suits of leather armour
POWER 3
POWER2 10
DEPTH 1
+DAMAGEABLE
ARMOUR chainmail
PLURAL suits of chainmail
POWER 6
POWER2 25
DEPTH 3
+DAMAGEABLE
ARMOUR plate armour
PLURAL suits of plate armour
POWER 10
POWER2 40
DEPTH 6
+DAMAGEABLE
ARMOUR mage armour
PLURAL suits of mage armour
POWER 15
POWER2 40
DEPTH 12
+DAMAGEABLE
ARMOUR mundane robe
PLURAL mundane robes
POWER 2
POWER2 5
DEPTH 1
+DAMAGEABLE
ARMOUR robe of swiftness
PLURAL robes of swiftness
POWER 8
POWER2 0
DEPTH 8
+DAMAGEABLE
ARMOUR robe of shadows
PLURAL robes of shadows
POWER 14
POWER2 -15
DEPTH 18
+DAMAGEABLE
ARMOUR dragonhide armour
PLURAL suits of dragonhide armour
POWER 12
POWER2 10
DEPTH 21
+DAMAGEABLE
ARMOUR meteoric plate armour
PLURAL suits of meteoric plate armour
POWER 18
POWER2 40
DEPTH 27
+DAMAGEABLE
ARMOUR sacred chainmail
PLURAL suits of sacred chainmail
POWER 15
POWER2 25
DEPTH 24
+DAMAGEABLE
ARMOUR ragged shift
PLURAL ragged shifts
POWER2 0
DEPTH 1
DRESS
+DAMAGEABLE
ARMOUR battle ballgown
PLURAL battle ballgowns
POWER2 10
DEPTH 1
DRESS
+DAMAGEABLE
+BREAK_REACT
ARMOUR imperatrix gown
PLURAL imperatrix gowns
POWER2 10
DEPTH 24
DRESS
+DAMAGEABLE
+BREAK_REACT
+
+ARMOUR foetid vestments
+PLURAL sets of foetid vestments
+DESC These stained, reeking robes seem to harbour great power despite their half-rotten state.
+RARITY 90
+ASCII '['
+UTF8 "["
+COLOUR l_green
+POWER 15
+POWER2 0
+DEPTH 30
+NOTIFY_EQUIP
+DAMAGEABLE
+BREAK_REACT
+
+ARMOUR lich's robe
+PLURAL lich's robes
+DESC Separated from its ancient owner, this robe hums with magical power.
+RARITY 100
+ASCII '['
+UTF8 "["
+COLOUR purple
+POWER 15
+POWER2 0
+DEPTH 30
+NOTIFY_EQUIP
# Mr Read would like to note that he invented the following item and its
# game mechanics *before* becoming aware of the anime series _Kill la Kill_.
+#
+# Mr Read would also like to note that this item is why a paperdoll sprite
+# for the princess is not a planned feature of any official graphical port
+# of Victrix Abyssi.
ARMOUR set of ribbons
PLURAL sets of ribbons
DESC These ribbons, arranged as if to form an alleged garment, make your fingers tingle with magic.
DEPTH 30
NOTIFY_EQUIP
DRESS
+DAMAGEABLE
+BREAK_REACT
RING regeneration ring
PLURAL regeneration rings
POWER 0
POWER2 0
DEPTH 1
+STACKABLE
FOOD parcel of dried fruit
PLURAL parcels of dried fruit
POWER 0
POWER2 0
DEPTH 1
+STACKABLE
FOOD round of elven waybread
PLURAL rounds of elven waybread
POWER 0
POWER2 0
DEPTH 1
+STACKABLE
FOOD devil spleen
PLURAL devil spleens
POWER 0
POWER2 0
DEPTH 1
+STACKABLE
CARRION corpse
PLURAL corpses
act->cmd = STAND_STILL;
return;
case '\x04':
- act->cmd = WIZARD_DESCEND;
- return;
+ if (wizard_mode)
+ {
+ act->cmd = WIZARD_DESCEND;
+ return;
+ }
+ break;
case '\x05':
- act->cmd = WIZARD_LEVELUP;
- return;
+ if (wizard_mode)
+ {
+ act->cmd = WIZARD_LEVELUP;
+ return;
+ }
+ break;
}
}
print_msg("BUG: broke out of input loop!\n");
}
}
+void welcome(void)
+{
+ print_msg("Welcome to the Abyss, Princess %s.\n", u.name);
+ print_msg("Press '?' for help.\n");
+}
+
+void describe_object(int obj)
+{
+ Obj *optr;
+ Permobj *poptr;
+ print_obj_name(obj);
+ optr = objects + obj;
+ poptr = permobjs + optr->obj_id;
+ print_msg("\n%s\n", poptr->description);
+}
+
+void print_obj_name(int obj)
+{
+ Obj *optr;
+ Permobj *poptr;
+ optr = objects + obj;
+ poptr = permobjs + optr->obj_id;
+ if (optr->quan > 1)
+ {
+ print_msg("%d %s", optr->quan, poptr->plural);
+ }
+ else if (po_is_stackable(optr->obj_id))
+ {
+ print_msg("1 %s", poptr->name);
+ }
+ else if ((poptr->poclass == POCLASS_WEAPON) ||
+ (poptr->poclass == POCLASS_ARMOUR))
+ {
+ print_msg("a%s %s (%d/%d)", is_vowel(poptr->name[0]) ? "n" : "", poptr->name, optr->durability, OBJ_MAX_DUR);
+ }
+ else
+ {
+ print_msg("a%s %s", is_vowel(poptr->name[0]) ? "n" : "", poptr->name);
+ }
+}
+
+void print_mon_name(int mon, int article)
+{
+ if (permons[monsters[mon].mon_id].name[0] == '\0')
+ {
+ print_msg("GROB THE VOID (%d)", monsters[mon].mon_id);
+ return;
+ }
+ switch (article)
+ {
+ case 0: /* a */
+ print_msg("a%s %s", is_vowel(permons[monsters[mon].mon_id].name[0]) ? "n" : "", permons[monsters[mon].mon_id].name);
+ break;
+ case 1: /* the */
+ print_msg("the %s", permons[monsters[mon].mon_id].name);
+ break;
+ case 2: /* A */
+ print_msg("A%s %s", is_vowel(permons[monsters[mon].mon_id].name[0]) ? "n" : "", permons[monsters[mon].mon_id].name);
+ break;
+ case 3: /* The */
+ print_msg("The %s", permons[monsters[mon].mon_id].name);
+ break;
+ }
+}
+
/* display-nc.cc */
// vim:cindent
extern void show_discoveries(void);
extern void touch_one_screen(Coord c);
extern bool query_wizmode_death(void);
+extern void welcome(void);
/* "I've changed things that need to be redisplayed" flags. */
extern bool hard_redraw;
break;
default:
- print_msg("FATAL: attempt to use unimplemented radiance evaluation order %d\n", rad->order);
+ debug_unimplemented_radiance_order(rad->order);
abort();
}
}
}
else
{
- print_msg("Nothing to get.\n");
+ notify_nothing_to_get();
return Cost_none;
}
case TAKE_OFF_ARMOUR:
if (u.armour != NO_OBJ)
{
+ int saved_armour = u.armour;
if ((u.resistances[DT_FIRE] == RESIST_ARMOUR) &&
(lvl.terrain_at(u.pos) == LAVA))
{
- print_msg("Your armour is your only current source of fire\nresistance; removing it here would incinerate you.\n");
+ notify_lava_blocks_unequip();
return Cost_none;
}
u.armour = NO_OBJ;
recalc_defence();
- print_msg("You take off your armour.\n");
+ notify_armour_unequip(saved_armour);
return Cost_std;
}
else
{
- print_msg("You aren't wearing any armour.\n");
+ debug_take_off_no_armour();
return Cost_none;
}
}
else
{
- print_msg("There are no stairs here.\n");
+ debug_descend_non_stairs();
}
return Cost_none;
}
else
{
- print_msg("You aren't a wizard.\n");
+ debug_wizmode_violation();
}
return Cost_none;
}
else
{
- print_msg("You aren't a wizard.\n");
+ debug_wizmode_violation();
}
return Cost_none;
}
{
int i;
int action_speed = 0;
- print_msg("Welcome to the Abyss, Princess %s.\n", u.name);
- print_msg("Press '?' for help.\n");
+ welcome();
while (!game_finished)
{
switch (game_tick & 3)
}
if (bailout < 1)
{
- print_msg("Bailed out while excavating level!\n");
+ debug_excavation_bailout();
}
-
}
/*! \brief Entry point for level generation.
static uint32_t deserializable_regions[CHUNK_EDGE][CHUNK_EDGE];
int i;
int j;
- i = fread(deserializable_terrain, 4, CHUNK_EDGE * CHUNK_EDGE, fp);
- if (i != CHUNK_EDGE * CHUNK_EDGE)
- {
- print_msg("deserialize_chunk expected %d got %d line %d\n",
- CHUNK_EDGE * CHUNK_EDGE, i, __LINE__);
- throw(errno);
- }
- i = fread(deserializable_flags, 4, CHUNK_EDGE * CHUNK_EDGE, fp);
- if (i != CHUNK_EDGE * CHUNK_EDGE)
- {
- print_msg("deserialize_chunk expected %d got %d line %d\n",
- CHUNK_EDGE * CHUNK_EDGE, i, __LINE__);
- throw(errno);
- }
- i = fread(deserializable_regions, 4, CHUNK_EDGE * CHUNK_EDGE, fp);
- if (i != CHUNK_EDGE * CHUNK_EDGE)
- {
- print_msg("deserialize_chunk expected %d got %d line %d\n",
- CHUNK_EDGE * CHUNK_EDGE, i, __LINE__);
- throw(errno);
- }
+ wrapped_fread(deserializable_terrain, 4, CHUNK_EDGE * CHUNK_EDGE, fp);
+ wrapped_fread(deserializable_flags, 4, CHUNK_EDGE * CHUNK_EDGE, fp);
+ wrapped_fread(deserializable_regions, 4, CHUNK_EDGE * CHUNK_EDGE, fp);
for (i = 0; i < CHUNK_EDGE; ++i)
{
for (j = 0; j < CHUNK_EDGE; ++j)
oncardinal = delta.rcardinal();
if (delta.len_cheb() == 0)
{
- print_msg("Program disordered: monster in player's square.\n");
- print_msg("Discarding misplaced monster.\n");
+ debug_misplaced_monster();
mptr->used = false;
lvl.set_mon_at(c, NO_MON);
return;
}
if (lvl.mon_at(c) != mon)
{
- print_msg("Program disordered: monster(s) misplaced.\n");
+ debug_misplaced_monster();
mptr->used = false;
if (lvl.mon_at(c) != NO_MON)
{
* \brief Monster-related functions
*/
-/* Copyright 2005-2013 Martin Read
+/* Copyright 2005-2014 Martin Read
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
int mon;
if (lvl.mon_at(c) != NO_MON)
{
- print_msg("Attempt to create monster at occupied space %d %d\n", c.y, c.x);
+ debug_create_mon_occupied(c);
return NO_MON;
}
if (pm_idx == NO_PMON)
pm_idx = get_random_pmon();
if (pm_idx == NO_PMON)
{
+ debug_pmon_select_failed();
return NO_MON;
}
}
return true;
}
-void print_mon_name(int mon, int article)
-{
- if (permons[monsters[mon].mon_id].name[0] == '\0')
- {
- print_msg("GROB THE VOID (%d)", monsters[mon].mon_id);
- return;
- }
- switch (article)
- {
- case 0: /* a */
- print_msg("a%s %s", is_vowel(permons[monsters[mon].mon_id].name[0]) ? "n" : "", permons[monsters[mon].mon_id].name);
- break;
- case 1: /* the */
- print_msg("the %s", permons[monsters[mon].mon_id].name);
- break;
- case 2: /* A */
- print_msg("A%s %s", is_vowel(permons[monsters[mon].mon_id].name[0]) ? "n" : "", permons[monsters[mon].mon_id].name);
- break;
- case 3: /* The */
- print_msg("The %s", permons[monsters[mon].mon_id].name);
- break;
- }
-}
-
void heal_mon(int mon, int amount, int cansee)
{
if (amount > (monsters[mon].hpmax - monsters[mon].hpcur))
{
if (cansee)
{
- print_mon_name(mon, 3);
- print_msg(" looks healthier.\n");
+ notify_mon_healed(mon);
}
monsters[mon].hpcur += amount;
}
{
if (by_you)
{
- print_msg("You kill ");
- if (mon_visible(mon))
- {
- print_mon_name(mon, 1);
- }
- else
- {
- print_msg("something");
- }
- print_msg("!\n");
+ notify_player_killed_mon(mon);
gain_experience(permons[mptr->mon_id].exp);
}
else if (mon_visible(mon))
{
- print_mon_name(mon, 2);
- print_msg(" dies.\n");
+ notify_mon_dies(mon);
}
death_drop(mon);
lvl.set_mon_at(mptr->pos, NO_MON);
Coord c;
int success = 0;
Mon *mptr = monsters + mon;
+ Coord oldpos = mptr->pos;
for (tryct = 0; tryct < 40; tryct++)
{
delta = random_step();
if (success)
{
reloc_mon(mon, c);
- print_mon_name(mon, 2);
- print_msg(" appears in a puff of smoke.\n");
+ notify_mon_appears(mon);
return You_pass;
}
return You_fail;
{
if (cansee)
{
- print_mon_name(mon, 3);
- print_msg(" wobbles slightly.\n");
+ notify_knockback_mon_resisted(mon);
}
return 0;
}
if (terrain_blocks_beings(terr))
{
- print_mon_name(mon, 3);
- print_msg(" is slammed against the wall.\n");
+ if (cansee)
+ {
+ notify_knockback_mon_blocked(mon);
+ }
return 0;
}
switch (terr)
{
if (cansee)
{
- print_mon_name(mon, 3);
- print_msg(" is hurled out over the lava.\n");
+ notify_knockback_mon_hover_lava(mon);
}
}
else
{
if (cansee)
{
- print_mon_name(mon, 3);
- print_msg(" tumbles into a pool of molten rock.\n");
+ notify_knockback_mon_immersed_lava(mon);
}
else
{
- print_msg("Splut!\n");
+ notify_knockback_mon_lava_offscreen();
}
if (!mptr->resists(DT_FIRE))
{
{
if (cansee)
{
- print_mon_name(mon, 3);
- print_msg(" is hurled out over the water.\n");
+ notify_knockback_mon_hover_water(mon);
}
}
else
{
if (cansee)
{
- print_mon_name(mon, 3);
- print_msg(" tumbles into the water.\n");
+ notify_knockback_mon_immersed_water(mon);
}
else
{
- print_msg("Splash!\n");
+ notify_knockback_mon_water_offscreen();
}
if (!mptr->resists(DT_DROWNING))
{
mptr = monsters + mon;
if (!mptr->can_pass(c))
{
- print_msg("Warning: monster attempted an invalid move.\n");
+ debug_mon_invalid_move(mon, c);
return;
}
if (lvl.mon_at(mptr->pos) != mon)
{
- print_msg("Monster map array in disorder.\n");
- press_enter();
+ debug_misplaced_monster();
return;
}
reloc_mon(mon, c);
void summon_demon_near(Coord c)
{
Coord c2 = c + random_step();
- int i;
+ int mon;
if ((lvl.terrain_at(c2) == FLOOR) && (lvl.mon_at(c2) == NO_MON) &&
(c2 != u.pos))
{
- i = create_mon(PM_DEMON, c2);
- if (i != NO_MON)
- {
- print_msg("Another demon appears!\n");
- }
- else
- {
- print_msg("You smell sulphurous fumes.\n");
- }
+ mon = create_mon(PM_DEMON, c2);
+ notify_summon_demon(mon);
}
}
if (monsters[mon].hpcur < monsters[mon].hpmax)
{
cansee = mon_visible(mon);
+ // TODO modify regen handling to use flags/fields instead of switching on mon_id
switch (monsters[mon].mon_id)
{
case PM_TROLL:
{
if (cansee)
{
- print_msg("The troll regenerates.\n");
+ notify_mon_regenerates(mon);
}
heal_mon(mon, one_die(3) + 3, 0);
}
}
}
+void notify_summon_demon(int mon)
+{
+ if (mon != NO_MON)
+ {
+ print_msg("Another demon appears!\n");
+ }
+ else
+ {
+ print_msg("You smell sulphurous fumes.\n");
+ }
+}
+
void notify_mon_disappear(int mon)
{
print_mon_name(mon, 3);
print_msg("Nothing to attack.\n");
}
-void notify_knockback_mon_fail(void)
-{
- print_msg("Your foe staggers a little.\n");
-}
-
void notify_knockback_mon_pass(void)
{
print_msg("Your foe is knocked backwards by the force of the shot.\n");
print_msg("You do %d damage.\n", damage);
}
+void notify_player_killed_mon(int mon)
+{
+ print_msg("You kill ");
+ if (mon_visible(mon))
+ {
+ print_mon_name(mon, 1);
+ }
+ else
+ {
+ print_msg("something");
+ }
+ print_msg("!\n");
+}
+
+void notify_mon_dies(int mon)
+{
+ print_mon_name(mon, 2);
+ print_msg(" dies.\n");
+}
+
+void notify_knockback_mon_resisted(int mon)
+{
+ print_mon_name(mon, 3);
+ print_msg(" wobbles slightly.\n");
+}
+
+void notify_knockback_mon_blocked(int mon)
+{
+ print_mon_name(mon, 3);
+ print_msg(" is slammed against the wall.\n");
+}
+
+void notify_knockback_mon_hover_lava(int mon)
+{
+ print_mon_name(mon, 3);
+ print_msg(" is hurled out over the lava.\n");
+}
+
+void notify_knockback_mon_hover_water(int mon)
+{
+ print_mon_name(mon, 3);
+ print_msg(" is hurled out over the water.\n");
+}
+
+void notify_knockback_mon_immersed_lava(int mon)
+{
+ print_mon_name(mon, 3);
+ print_msg(" tumbles into a pool of molten rock.\n");
+}
+
+void notify_knockback_mon_immersed_water(int mon)
+{
+ print_mon_name(mon, 3);
+ print_msg(" tumbles into the water.\n");
+}
+
+void notify_knockback_mon_lava_offscreen(void)
+{
+ print_msg("Splut!\n");
+}
+
+void notify_knockback_mon_water_offscreen(void)
+{
+ print_msg("Splash!\n");
+}
+
+void notify_mon_disappears(int mon, Coord oldpos)
+{
+}
+
+void notify_mon_appears(int mon)
+{
+ print_mon_name(mon, 2);
+ print_msg(" appears in a puff of smoke.\n");
+}
+
void notify_mon_hit_armour(int mon)
{
print_msg("Your armour deflects ");
print_msg(" hits you.\n");
}
+void notify_mon_ranged_attack(int mon)
+{
+ int pm = monsters[mon].mon_id;
+ Damtyp dt = permons[pm].rdtyp;
+ print_mon_name(mon, 3);
+ if (dt == DT_PHYS)
+ {
+ print_msg(" %s at you!\n", permons[pm].shootverb);
+ }
+ else
+ {
+ print_msg(" %s %s at you!\n", permons[pm].shootverb, damtype_names[dt]);
+ }
+}
+
+void notify_mon_ranged_hit_mon(int er, int ee)
+{
+ // TODO make this message specific and non-sucky.
+ print_msg("It hits a bystander.\n");
+}
+
+void notify_mon_ranged_missed_player(int mon)
+{
+ print_msg("It misses you.\n");
+}
+
+void notify_mon_ranged_hit_player(int mon)
+{
+ print_msg("It hits you!\n");
+}
+
+
void notify_no_flask_target(void)
{
print_msg("That would be a waste; there's nobody to throw it at.\n");
print_msg("You have no weapon in hand.\n");
}
+void notify_magic_powerless_ring(void)
+{
+ print_msg("Your current ring seems to have no magic powers to activate.\n");
+}
+
+void notify_emanate_powerless_armour(void)
+{
+ print_msg("Your current attire seems to have no magic powers to activate.\n");
+}
+
+void notify_zap_powerless_weapon(void)
+{
+ print_msg("Your current weapon seems to have no magic powers to activate.\n");
+}
+
void notify_armour_equip(void)
{
Permobj *pobj = permobjs + objects[u.armour].obj_id;
}
}
+void notify_armour_unequip(int obj)
+{
+ // TODO add unequip messages for NOTIFY_EQUIP armours.
+ print_msg("You take off your armour.\n");
+}
+
+void notify_lava_blocks_unequip(void)
+{
+ print_msg("That item is your only current source of fire resistance; setting it aside here would incinerate you.\n");
+}
+
+void notify_water_blocks_unequip(void)
+{
+ print_msg("Setting that item aside here would cause your death by drowning.\n");
+}
+
void notify_player_touch_effect(Damtyp dt)
{
switch (dt)
print_msg("You feel like something is helping you.\n");
}
+void notify_telering_activation(int specific)
+{
+ switch (specific)
+ {
+ case 0:
+ print_msg("You are too hungry to activate your ring's power.\n");
+ break;
+ case 1:
+ print_msg("You activate your ring's power of teleportation.\n");
+ break;
+ case 2:
+ print_msg("BUG: Some clown thinks teleport rings have a 'item isn't hungry' message.\n");
+ break;
+ case 3:
+ print_msg("BUG: Some clown thinks teleport rings have a 'item force-activates itself' message.\n");
+ break;
+ default:
+ print_msg("BUG: notify_telering_activation called with invalid subcode %d\n", specific);
+ break;
+ }
+}
+
+void notify_firestaff_activation(int specific)
+{
+ switch (specific)
+ {
+ case 0:
+ print_msg("You are too hungry to activate your staff's power.\n");
+ break;
+ case 1:
+ print_msg("You unleash the fiery powers of your staff!\n");
+ break;
+ case 2:
+ print_msg("BUG: Some clown thinks staves of fire have a 'item isn't hungry' message.\n");
+ break;
+ case 3:
+ print_msg("BUG: Some clown thinks staves of fire have a 'item force-activates itself' message.\n");
+ break;
+ default:
+ print_msg("BUG: notify_firestaff_activation called with invalid subcode %d\n", specific);
+ break;
+ }
+}
+
+void notify_fireitem_hit(int mon)
+{
+ print_mon_name(mon, 3);
+ print_msg(" is engulfed in roaring flames.\n");
+}
+
+void notify_lash_activation(int specific)
+{
+ switch (specific)
+ {
+ case 0:
+ print_msg("You are too hungry to willingly let the lash draw on your strength.\n");
+ break;
+ case 1:
+ if (u.sympathy[FePo_flesh] > 10)
+ {
+ print_msg("A delightful tingle runs up your arm as the lash draws on your strength to repair itself.\n");
+ }
+ else
+ {
+ print_msg("A pins-and-needles sensation runs up your arm as the lash draws on your strength to repair itself.\n");
+ }
+ break;
+ case 2:
+ print_msg("The lash is undamaged; it hungers not for your strength.\n");
+ break;
+ case 3:
+ print_msg("Pain explodes%s through your arm as the lash restores itself!\n", (u.sympathy[FePo_flesh] > 10) ? " delightfully" : "");
+ break;
+ default:
+ print_msg("BUG: notify_ribbon_activation called with invalid subcode %d\n", specific);
+ break;
+ }
+}
+
+void notify_ribbon_activation(int specific)
+{
+ switch (specific)
+ {
+ case 0:
+ print_msg("You are too hungry to willingly let the ribbons draw on your strength.\n");
+ break;
+ case 1:
+ print_msg("You gasp%s as the ribbons draw on your strength to repair themselves.\n", (u.sympathy[FePo_flesh] > 10) ? " in delight" : "");
+ break;
+ case 2:
+ print_msg("The ribbons are undamaged; they hunger not for your strength.\n");
+ break;
+ default:
+ print_msg("BUG: notify_ribbon_activation called with invalid subcode %d\n", specific);
+ break;
+ }
+}
+
void notify_dress_shredded(void)
{
print_msg("Your dress has been reduced to a tattered wreck.\n");
print_msg(ravenous ? "You ravenously devour your food!\n" : "You eat some food.\n");
}
+void notify_ingest_spleen(void)
+{
+ print_msg("%s power suffuses your body as you devour the devil spleen.\n", u.corrupt() ? "Delicious" : "Vile");
+}
+
void notify_quaff_potion_restoration(void)
{
print_msg("This potion makes you feel warm all over.\n");
}
+void notify_nothing_to_get(void)
+{
+ print_msg("Nothing to get.\n");
+}
+
+void notify_mon_healed(int mon)
+{
+ print_mon_name(mon, 3);
+ print_msg(" looks healthier.\n");
+}
+
+void notify_mon_regenerates(int mon)
+{
+ // TODO allow things that aren't trolls to be regenerators
+ print_msg("The troll regenerates.\n");
+}
+
+void notify_unwield(int obj, Noisiness noisy)
+{
+ if (noisy == Noise_std)
+ {
+ print_msg("Weapon unwielded.\n");
+ }
+}
+
+void notify_wield_weapon(int obj)
+{
+ print_msg("Wielding ");
+ print_obj_name(obj);
+ print_msg(".\n");
+}
+
+void notify_weapon_broke(int obj)
+{
+ print_msg("Your weapon breaks!\n");
+}
+
+void notify_armour_broke(int obj)
+{
+ print_msg("Your armour is ruined!\n");
+}
+
+void notify_drop_item(int obj)
+{
+ print_msg("You drop ");
+ print_obj_name(obj);
+ print_msg(".\n");
+}
+
+void notify_drop_blocked(void)
+{
+ print_msg("There is already an item here.\n");
+}
+
+void notify_get_item(int from, int slot)
+{
+ if (from)
+ {
+ print_msg("You get ");
+ print_obj_name(from);
+ print_msg(".\nYou now have\n");
+ print_msg("%c) ", 'a' + slot);
+ print_obj_name(u.inventory[slot]);
+ print_msg("\n");
+ }
+ else
+ {
+ print_msg("You now have\n");
+ print_msg("%c) ", 'a' + slot);
+ print_obj_name(u.inventory[slot]);
+ print_msg("\n");
+ }
+}
+
+void notify_pack_full(void)
+{
+ print_msg("Your pack is full.\n");
+}
/* Debugging notifications */
void debug_bad_monspell(int spell)
print_msg("Impossible: quaffing non-potion\n");
}
+void debug_descend_non_stairs(void)
+{
+ print_msg("BUG: Received use-stairs command standing on non-stairs.\n");
+}
+
+void debug_wizmode_violation(void)
+{
+ print_msg("BUG: Received wizmode command when not in wizmode.\n");
+}
+
+void debug_take_off_no_armour(void)
+{
+ print_msg("BUG: Taking off armour when no armour equipped.\n");
+}
+
+void debug_excavation_bailout(void)
+{
+ print_msg("BUG: Bailed out while excavating level!\n");
+}
+
+void debug_object_pool_exhausted(void)
+{
+ print_msg("NOTICE: Ran out of objects[].\n");
+}
+
+void debug_pobj_select_failed(void)
+{
+ print_msg("NOTICE: Failed to choose a permobj.\n");
+}
+
+void debug_misplaced_monster(void)
+{
+ print_msg("BUG: Misplaced monster detected.\n");
+}
+
+void debug_create_mon_occupied(Coord c)
+{
+ print_msg("BUG: Attempt to create mon at occupied space y=%d x=%d\n", c.y, c.x);
+}
+
+void debug_monster_pool_exhauseted(void)
+{
+ print_msg("NOTICE: Ran out of monsters[].\n");
+}
+
+void debug_pmon_select_failed(void)
+{
+ print_msg("BUG: Failed to choose a permon.\n");
+}
+
+void debug_dump_write_failed(void)
+{
+ print_msg("NOTICE: Couldn't create dump file. Dump failed.\n");
+}
+
+void debug_unwield_nothing(void)
+{
+ print_msg("BUG: got to player_unwield() with no weapon wielded - have a quiet word with your HCI module's author, please.\n");
+}
+
+void debug_unimplemented_activation(int po)
+{
+ print_msg("BUG: permobj %d should be activatable but has no activation handler.\n");
+}
+
+void debug_unimplemented_break_reaction(int po)
+{
+ print_msg("BUG: permobj %d should react to hitting durability 0 but has no break reaction handler.\n");
+}
+
+void debug_mon_invalid_move(int mon, Coord c)
+{
+ print_msg("BUG: monster %d attempted move to impassable location y=%d x=%d\n", mon, c.y, c.x);
+}
+
+void debug_unimplemented_radiance_order(int order)
+{
+ print_msg("FATAL: attempt to use unimplemented radiance evaluation order %d\n", order);
+}
+
/* notify-local-tty.cc */
// vim:cindent
// Unsorted notifications
void notify_obj_at(Coord c);
void notify_dress_shredded(void);
+void notify_mon_healed(int mon);
+void notify_mon_regenerates(int mon);
+void notify_mon_disappears(int mon, Coord oldpos);
+void notify_mon_appears(int mon);
// Item manipulation notifications
void notify_magic_no_ring(void);
void notify_emanate_no_armour(void);
void notify_zap_no_weapon(void);
+void notify_magic_powerless_ring(void);
+void notify_emanate_powerless_armour(void);
+void notify_zap_powerless_weapon(void);
void notify_armour_equip(void);
+void notify_armour_unequip(int obj);
+void notify_lava_blocks_unequip(void);
+void notify_water_blocks_unequip(void);
+void notify_nothing_to_get(void);
+void notify_unwield(int obj, Noisiness noisy);
+void notify_wield_weapon(int obj);
+void notify_weapon_broke(int obj);
+void notify_armour_broke(int obj);
+void notify_drop_item(int obj);
+void notify_drop_blocked(void);
+void notify_get_item(int from, int slot);
+void notify_pack_full(void);
// Magic item use releated notifications
void notify_read_scroll_protection(void);
void notify_quaff_potion_restoration(void);
+void notify_ribbon_activation(int specific);
+void notify_lash_activation(int specific);
+void notify_firestaff_activation(int specific);
+void notify_fireitem_hit(int mon);
+void notify_telering_activation(int specific);
+
void notify_item_explodes_flames(int obj);
void notify_eat_food(bool ravenous);
+void notify_ingest_spleen(void);
// combat notifications
void notify_swing_bow(void);
void notify_ring_boost(int mon, int pobj);
void notify_player_hit_mon(int mon);
void notify_player_hurt_mon(int mon, int damage);
-void notify_knockback_mon_pass(void);
-void notify_knockback_mon_fail(void);
+void notify_player_killed_mon(int mon);
+void notify_knockback_mon_resisted(int mon);
+void notify_knockback_mon_blocked(int mon);
+void notify_knockback_mon_hover_lava(int mon);
+void notify_knockback_mon_hover_water(int mon);
+void notify_knockback_mon_immersed_lava(int mon);
+void notify_knockback_mon_immersed_water(int mon);
+void notify_knockback_mon_water_offscreen(void);
+void notify_knockback_mon_lava_offscreen(void);
+
void notify_player_shot_terrain(int obj, Coord c);
+
void notify_mon_hit_armour(int mon);
void notify_mon_missed_player(int mon);
void notify_mon_hit_player(int mon);
+void notify_mon_ranged_attack(int mon);
+void notify_mon_ranged_hit_player(int mon);
+void notify_mon_ranged_missed_player(int mon);
+void notify_mon_ranged_hit_mon(int er, int ee);
+void notify_mon_dies(int mon);
+
void notify_player_damage_taken(int amount);
void notify_player_touch_effect(Damtyp dt);
void notify_player_ignore_damage(Damtyp dt);
// Sorcery notifications
void notify_summon_help(int mon, bool success);
+void notify_summon_demon(int mon);
void notify_monster_cursing(int mon);
void notify_mon_disappear(int mon);
void notify_moncurse_fail(void);
void debug_unimplemented(void);
void debug_wear_while_wearing(void);
void debug_wear_uncarried_armour(void);
+void debug_unwield_nothing(void);
+void debug_take_off_no_armour(void);
void debug_remove_no_ring(void);
void debug_put_on_second_ring(void);
void debug_put_on_uncarried_ring(void);
void debug_eat_non_food(int obj);
void debug_read_non_scroll(void);
void debug_quaff_non_potion(void);
+void debug_descend_non_stairs(void);
+void debug_wizmode_violation(void);
+void debug_excavation_bailout(void);
+void debug_object_pool_exhausted(void);
+void debug_pobj_select_failed(void);
+void debug_misplaced_monster(void);
+void debug_create_mon_occupied(Coord c);
+void debug_monster_pool_exhausted(void);
+void debug_mon_invalid_move(int mon, Coord c);
+void debug_pmon_select_failed(void);
+void debug_dump_write_failed(void);
+void debug_unimplemented_activation(int po);
+void debug_unimplemented_break_reaction(int po);
+void debug_unimplemented_radiance_order(int order);
#endif
{
if (!pmon_resists_fire(monsters[i].mon_id))
{
- //print_mon_name(i, 3);
- //print_msg(" is burned.\n");
+ notify_fireitem_hit(i);
damage_mon(i, dice(4, 10), true);
}
}
{
if (obj == u.armour)
{
- if ((objects[obj].obj_id == PO_BATTLE_BALLGOWN) ||
- (objects[obj].obj_id == PO_IMPERATRIX_GOWN))
- {
- objects[obj].quan = 1;
- objects[obj].used = true;
- objects[obj].durability = 50 + zero_die(51);
- objects[obj].obj_id = PO_RAGGED_SHIFT;
- notify_dress_shredded();
- }
- else
- {
- u.armour = NO_OBJ;
- }
+ u.armour = NO_OBJ;
recalc_defence();
+ notify_armour_broke(obj);
}
else if (obj == u.weapon)
{
u.weapon = NO_OBJ;
recalc_defence();
+ notify_weapon_broke(obj);
}
else if (obj == u.ring)
{
}
if (optr->obj_id == PO_DEVIL_SPLEEN)
{
- print_msg("Vile power suffuses your body as you devour the devil\nspleen.\n");
+ notify_ingest_spleen();
if (zero_die(2))
{
gain_body(1);
{
gain_agility(1);
}
- // TODO
- // gain_power(Power_demonic);
+ // TODO add more tracking state to this item so we don't have to randomize the fell power choice
+ ++u.sympathy[zero_die(TOTAL_FELL_POWERS)];
}
else
{
permobjs[PO_RESTORATION_POTION].power = colour_choices[3];
}
-int create_obj_class(enum poclass_num po_class, int quantity, bool with_you, Coord c)
+int get_first_free_obj(void)
{
int obj;
- int po_idx;
- int tryct;
for (obj = 0; obj < 100; obj++)
{
if (!objects[obj].used)
break;
}
}
+ return (obj == 100) ? NO_OBJ : obj;
+}
+
+int create_obj_class(enum poclass_num po_class, int quantity, bool with_you, Coord c)
+{
+ int po_idx;
+ int tryct;
+ int obj = get_first_free_obj();
if (obj == 100)
{
- print_msg("ERROR: Ran out of objects[].\n");
+ debug_object_pool_exhausted();
return NO_OBJ;
}
for (tryct = 0; tryct < 200; tryct++)
int create_obj(int po_idx, int quantity, bool with_you, Coord c)
{
- int i;
- for (i = 0; i < 100; i++)
- {
- if (!objects[i].used)
- {
- break;
- }
- }
- if (i == 100)
+ int obj = get_first_free_obj();
+ if (obj == 100)
{
- print_msg("ERROR: Ran out of objects[].\n");
+ debug_object_pool_exhausted();
return NO_OBJ;
}
if (po_idx == NO_POBJ)
po_idx = get_random_pobj();
if (po_idx == NO_POBJ)
{
+ debug_pobj_select_failed();
return NO_OBJ;
}
}
- objects[i].obj_id = po_idx;
- objects[i].with_you = with_you;
- objects[i].used = true;
- objects[i].pos = c;
- objects[i].quan = quantity;
+ objects[obj].obj_id = po_idx;
+ objects[obj].with_you = with_you;
+ objects[obj].used = true;
+ objects[obj].pos = c;
+ objects[obj].quan = quantity;
switch (permobjs[po_idx].poclass)
{
case POCLASS_WEAPON:
/* Set durability of weapons and armour to a suitable value.
* 100 has been chosen for the moment, but this may need
* tuning. */
- objects[i].durability = OBJ_MAX_DUR;
+ objects[obj].durability = OBJ_MAX_DUR;
break;
default:
break;
}
- if (!objects[i].with_you)
+ if (!objects[obj].with_you)
{
- lvl.set_obj_at(c, i);
+ lvl.set_obj_at(c, obj);
}
- return i;
+ return obj;
}
void sprint_obj_name(char *buf, int obj, int len)
}
}
-void print_obj_name(int obj)
-{
- Obj *optr;
- Permobj *poptr;
- optr = objects + obj;
- poptr = permobjs + optr->obj_id;
- if (optr->quan > 1)
- {
- print_msg("%d %s", optr->quan, poptr->plural);
- }
- else if (po_is_stackable(optr->obj_id))
- {
- print_msg("1 %s", poptr->name);
- }
- else if ((poptr->poclass == POCLASS_WEAPON) ||
- (poptr->poclass == POCLASS_ARMOUR))
- {
- print_msg("a%s %s (%d/%d)", is_vowel(poptr->name[0]) ? "n" : "", poptr->name, optr->durability, OBJ_MAX_DUR);
- }
- else
- {
- print_msg("a%s %s", is_vowel(poptr->name[0]) ? "n" : "", poptr->name);
- }
-}
-
Action_cost drop_obj(int inv_idx)
{
Obj *optr;
}
u.inventory[inv_idx] = NO_OBJ;
optr->with_you = false;
- print_msg("You drop ");
- print_obj_name(lvl.obj_at(u.pos));
- print_msg(".\n");
+ notify_drop_item(lvl.obj_at(u.pos));
return Cost_std;
}
else
{
- print_msg("There is already an item here.\n");
+ notify_drop_blocked();
return Cost_none;
}
}
{
if ((objects[u.inventory[i]].obj_id == objects[lvl.obj_at(u.pos)].obj_id))
{
- print_msg("You get ");
- print_obj_name(lvl.obj_at(u.pos));
- print_msg(".\nYou now have\n");
+ int stale_obj = lvl.obj_at(u.pos);
objects[u.inventory[i]].quan += objects[lvl.obj_at(u.pos)].quan;
- objects[lvl.obj_at(u.pos)].used = false;
+ objects[stale_obj].used = false;
lvl.set_obj_at(u.pos, NO_OBJ);
- print_msg("%c) ", 'a' + i);
- print_obj_name(u.inventory[i]);
- print_msg("\n");
+ notify_get_item(stale_obj, i);
return;
}
}
}
if (i == 19)
{
- print_msg("Your pack is full.\n");
+ notify_pack_full();
return;
}
u.inventory[i] = lvl.obj_at(u.pos);
lvl.set_obj_at(u.pos, NO_OBJ);
objects[u.inventory[i]].with_you = true;
objects[u.inventory[i]].pos = Nowhere;
- print_msg("You now have\n");
- print_msg("%c) ", 'a' + i);
- print_obj_name(u.inventory[i]);
- print_msg("\n");
+ notify_get_item(NO_OBJ, i);
}
-void damage_obj(int obj)
+void break_reaction(int obj)
{
- /* Only weapons and armour have non-zero durability. */
- if (objects[obj].durability == 0)
+ switch (objects[obj].obj_id)
{
- /* Break the object. Weapons and armour don't stack. */
- if (obj == u.weapon)
+ case PO_SET_OF_RIBBONS:
+ if (u.food < 500)
{
- print_msg("Your weapon breaks!\n");
+ int shortfall = (u.food < 0) ? 500 : 500 - u.food;
+ int damage = (shortfall + 24) / 25;
+ u.food = (u.food < 0) ? u.food : 0;
+ notify_ribbon_activation(3);
+ damage_u(damage, DEATH_RIBBONS, "");
}
- else if (obj == u.armour)
+ else
{
- print_msg("Your armour is ruined!\n");
+ u.food -= 500;
+ objects[obj].durability = 100;
+ notify_ribbon_activation(1);
}
+ break;
+
+ case PO_TORMENTORS_LASH:
+ if (u.food < 500)
+ {
+ int shortfall = (u.food < 0) ? 500 : 500 - u.food;
+ int damage = (shortfall + 24) / 25;
+ u.food = (u.food < 0) ? u.food : 0;
+ notify_lash_activation(3);
+ damage_u(damage, DEATH_LASH, "");
+ }
+ else
+ {
+ u.food -= 500;
+ objects[obj].durability = 100;
+ notify_lash_activation(1);
+ }
+ break;
+
+ default:
+ if (permobjs[objects[obj].obj_id].flags[0] & POF_DRESS)
+ {
+ objects[obj].durability = 50 + zero_die(51);
+ objects[obj].obj_id = PO_RAGGED_SHIFT;
+ notify_dress_shredded();
+ recalc_defence();
+ }
+ else
+ {
+ debug_unimplemented_break_reaction(objects[obj].obj_id);
+ }
+ break;
+ }
+}
+
+void damage_obj(int obj)
+{
+ /* Only weapons and armour have non-zero durability. */
+ if (objects[obj].durability == 0)
+ {
+ /* Break the object. Weapons and armour don't stack. */
consume_obj(obj);
}
else
{
objects[obj].durability--;
- if (objects[obj].durability == 0)
+ if ((objects[obj].durability == 0) && (permobjs[objects[obj].obj_id].flags[0] & POF_BREAK_REACT))
{
- switch (objects[obj].obj_id)
- {
- case PO_SET_OF_RIBBONS:
- if (u.food < 500)
- {
- int shortfall = (u.food < 0) ? 500 : 500 - u.food;
- int damage = (shortfall + 24) / 25;
- u.food = (u.food < 0) ? u.food : 0;
- print_msg("Blood trickles from your nose as the ribbons drain your\nstrength repair themselves.\n");
- damage_u(damage, DEATH_RIBBONS, "");
- }
- else
- {
- print_msg("You gasp as the ribbons drain your strength to repair\nthemselves.\n");
- u.food -= 500;
- }
- break;
-
- case PO_TORMENTORS_LASH:
- if (u.food < 500)
- {
- int shortfall = (u.food < 0) ? 500 : 500 - u.food;
- int damage = (shortfall + 24) / 25;
- u.food = (u.food < 0) ? u.food : 0;
- print_msg("Pain explodes through your arm as the lash restores\nitself!\n");
- damage_u(damage, DEATH_LASH, "");
- }
- else
- {
- print_msg("A pins-and-needles sensation washes over you as the lash\nrestores itself.\n");
- u.food -= 500;
- }
- break;
- }
+ break_reaction(obj);
}
}
}
-void describe_object(int obj)
-{
- Obj *optr;
- Permobj *poptr;
- print_obj_name(obj);
- optr = objects + obj;
- poptr = permobjs + optr->obj_id;
- print_msg("\n%s\n", poptr->description);
-}
-
int evasion_penalty(int obj)
{
if (permobjs[objects[obj].obj_id].poclass == POCLASS_ARMOUR)
{
return permobjs[objects[obj].obj_id].power2;
}
- /* Haxx0r. Or maybe a bug. */
- print_msg("Trying to find evasion penalty of non-armour!\n");
return 100;
}
if (u.food >= 50)
{
u.food -= 50;
- print_msg("You activate your ring's power of teleportation.\n");
+ notify_telering_activation(1);
teleport_u();
return Cost_std;
}
else
{
- print_msg("You're too hungry to activate your ring.\n");
+ notify_telering_activation(0);
}
return Cost_none;
default:
- print_msg("Your current ring has no activatable power.\n");
+ if (permobjs[optr->obj_id].flags[0] & POF_ACTIVATABLE)
+ {
+ debug_unimplemented_activation(optr->obj_id);
+ }
+ else
+ {
+ notify_magic_powerless_ring();
+ }
return Cost_none;
}
}
{
if (u.food < 5 * (OBJ_MAX_DUR - optr->durability))
{
- print_msg("You are too hungry to willingly let the ribbons draw on\nyour strength.\n");
+ notify_ribbon_activation(0);
}
else
{
- print_msg("You gasp as the ribbons draw on your strength to\nrepair themselves.\n");
+ notify_ribbon_activation(1);
u.food -= 5 * (OBJ_MAX_DUR - optr->durability);
optr->durability = OBJ_MAX_DUR;
cost = Cost_std;
}
else
{
- print_msg("The ribbons are undamaged.\n");
+ notify_ribbon_activation(2);
}
break;
default:
- print_msg("Your current attire has no activatable powers.\n");
+ if (permobjs[optr->obj_id].flags[0] & POF_ACTIVATABLE)
+ {
+ debug_unimplemented_activation(optr->obj_id);
+ }
+ else
+ {
+ notify_emanate_powerless_armour();
+ }
break;
}
return Cost_none;
{
Coord c;
u.food -= 150;
- print_msg("You unleash the fiery powers of your staff!\n");
+ notify_firestaff_activation(1);
for (c.y = u.pos.y - 1; c.y <= u.pos.y + 1; ++c.y)
{
if ((c.y < 0) || (c.y >= DUN_HEIGHT))
Mon *mptr = monsters + mon;
if (!pmon_resists_fire(mptr->mon_id))
{
- print_mon_name(mon, 3);
- print_msg(" is engulfed in roaring flames.\n");
+ notify_fireitem_hit(mon);
damage_mon(mon, dice(4, 10), true);
}
}
}
else
{
- print_msg("You are too hungry to activate your staff's power.\n");
+ notify_firestaff_activation(0);
+ return Cost_none;
}
return Cost_std;
default:
- print_msg("Your current weapon has no activatable powers.\n");
+ if (permobjs[optr->obj_id].flags[0] & POF_ACTIVATABLE)
+ {
+ debug_unimplemented_activation(optr->obj_id);
+ }
+ else
+ {
+ notify_zap_powerless_weapon();
+ }
return Cost_none;
}
}
*/
Action_cost player_unwield(Noisiness noisy)
{
+ int saved_weapon = u.weapon;
if (u.weapon == NO_OBJ)
{
- print_msg("BUG: got to player_unwield() with no weapon wielded - have a quiet word with your HCI module's author, please.\n");
+ debug_unwield_nothing();
return Cost_none;
}
u.weapon = NO_OBJ;
- if (noisy == Noise_std)
- {
- print_msg("Weapon unwielded.\n");
- }
+ recalc_defence();
+ notify_unwield(saved_weapon, Noise_std);
return Cost_std;
}
player_unwield(Noise_low);
}
u.weapon = u.inventory[slot];
- print_msg("Wielding ");
- print_obj_name(u.weapon);
- print_msg(".\n");
+ notify_wield_weapon(u.weapon);
recalc_defence();
return Cost_std;
}
{
if (noisy != Noise_silent)
{
- print_msg("That ring is your only current source of fire resistance. Removing it here would incinerate you.\n");
+ notify_lava_blocks_unequip();
}
return You_fail;
}
{
if (noisy != Noise_silent)
{
- print_msg("Since nobody ever taught you to swim, removing that ring here would result in your death by drowning.\n");
+ notify_water_blocks_unequip();
}
return You_fail;
}
#define POBJ_FLAG_WORDS 1
// POF field 0
-#define POF_NOTIFY_EQUIP 0x00000001u
+#define POF_NOTIFY_EQUIP 0x00000001u // item has special messages when changing equip status
+#define POF_ACTIVATABLE 0x00000002u // item can be activated when equipped
+#define POF_STACKABLE 0x00000004u // item can stack
+#define POF_DAMAGEABLE 0x00000008u // track durability
+#define POF_BREAK_REACT 0x00000010u // item reacts to breakage attempts
#define POF_DRESS 0x00010000u
/*! \brief The 'permanent object' database */
our %flag_indices =
(
- 'NOTIFY_EQUIP' => 0, # the first of probably many.
- 'DRESS' => 0
+ 'NOTIFY_EQUIP' => 0,
+ 'ACTIVATABLE' => 0,
+ 'STACKABLE' => 0,
+ 'DAMAGEABLE' => 0,
+ 'BREAK_REACT' => 0,
+ 'DRESS' => 0,
);
fp = fopen(filename, "w");
if (fp == NULL)
{
- print_msg("Couldn't create dump file. Dump failed.\n");
+ debug_dump_write_failed();
return;
}
fprintf(fp, "%s, level %d princess (%d XP)\n", u.name, u.level, u.experience);
DEATH_LASH, DEATH_RIBBONS
};
+enum Fell_powers {
+ FePo_iron, // boosted by ironguard armour, hellglaive
+ FePo_decay, // boosted by foetid vestments,
+ FePo_bone, // boosted by lich's robe, vampire ring
+ FePo_flesh // boosted by t's lash or the ribbons,
+};
+
+#define TOTAL_FELL_POWERS (1 + FePo_flesh)
+
#define RESIST_MASK_TEMPORARY 0x0000FFFFu
#define RESIST_MASK_PERM_EQUIP 0xFFFF0000u
#define RESIST_RING 0x00010000u
int weapon; /* For now, you can only wield one weapon. */
int armour; /* For now, you can only wear one item of armour. */
int ring; /* For now, you can only wear one magic ring. */
+ // TODO make these meters mean something - cosmetically for starters
+ int sympathy[TOTAL_FELL_POWERS];
bool resists(Damtyp dtype) const;
+ bool martial(void) const { return sympathy[FePo_iron] > 10; }
+ bool rotten(void) const { return sympathy[FePo_decay] > 10; }
+ bool thanatoic(void) const { return sympathy[FePo_bone] > 10; }
+ bool sybaritic(void) const { return sympathy[FePo_flesh] > 10; }
+ bool corrupt(void) const { return martial() || rotten() || thanatoic() || sybaritic(); }
};
/*! \brief Represent an in-game action in more detail than Game_cmd