diff --git a/doc/editor/appendix/Items.html b/doc/editor/appendix/Items.html
index 27133c1c..a7fe7121 100644
--- a/doc/editor/appendix/Items.html
+++ b/doc/editor/appendix/Items.html
@@ -363,6 +363,12 @@ Item Adjust setting is ignored.
Ability 84 - Quickfire
Creates quickfire on space where its used. The Magic Item Adjust setting is ignored, as
are the extra data fields..
+Ability 85 - Book
+The item is a book which gives some textual information when used. A book does not
+consume any charges when used. To set the contents of the book, edit the item description.
+At the end of the description, add three vertical bars (|
) followed by the
+content of the book. If you want, you can add another three vertical bars followed by a
+second string. Note that there is limited space for the strings in the dialog.
Reagents (Inherent)
diff --git a/rsrc/strings/item-abilities.txt b/rsrc/strings/item-abilities.txt
index 4fe18097..f467215e 100644
--- a/rsrc/strings/item-abilities.txt
+++ b/rsrc/strings/item-abilities.txt
@@ -82,7 +82,7 @@ Call special when used
Summoning
Mass summoning
Quickfire
-
+Readable item
diff --git a/src/boe.infodlg.cpp b/src/boe.infodlg.cpp
index f94d2912..13300fdf 100644
--- a/src/boe.infodlg.cpp
+++ b/src/boe.infodlg.cpp
@@ -216,7 +216,7 @@ static void put_item_info(cDialog& me,const cItem& s_i) {
me["name"].setText(s_i.full_name);
me["weight"].setTextToNum(s_i.item_weight());
- me["desc"].setText(s_i.desc);
+ me["desc"].setText(s_i.desc.substr(0,s_i.desc.find("|||")));
// TODO: This calculation (value for an item with charges) should be in a member function of cItem
me["val"].setTextToNum((s_i.charges > 0) ? s_i.value * s_i.charges : s_i.value);
diff --git a/src/boe.newgraph.cpp b/src/boe.newgraph.cpp
index 919919e7..37f711a6 100644
--- a/src/boe.newgraph.cpp
+++ b/src/boe.newgraph.cpp
@@ -928,7 +928,7 @@ std::string get_item_interesting_string(cItem item) {
got_string = false;
break;
}
- if(item.charges > 0) {
+ if(item.charges > 0 && item.ability != eItemAbil::MESSAGE) {
if(got_string) sout << "; ";
sout << "Uses: " << item.charges;
}
diff --git a/src/boe.specials.cpp b/src/boe.specials.cpp
index d90f9340..5bb6ef52 100644
--- a/src/boe.specials.cpp
+++ b/src/boe.specials.cpp
@@ -85,7 +85,7 @@ std::map abil_chart = {
{eItemAbil::POISON_WEAPON,13}, {eItemAbil::AFFECT_STATUS,3}, {eItemAbil::BLISS_DOOM,3}, {eItemAbil::AFFECT_EXPERIENCE,4},
{eItemAbil::AFFECT_SKILL_POINTS,4}, {eItemAbil::AFFECT_HEALTH,4}, {eItemAbil::AFFECT_SPELL_POINTS,4},
{eItemAbil::LIGHT,13}, {eItemAbil::AFFECT_PARTY_STATUS,3}, {eItemAbil::HEALTH_POISON,4},
- {eItemAbil::CALL_SPECIAL,4}, {eItemAbil::CAST_SPELL,4},
+ {eItemAbil::CALL_SPECIAL,4}, {eItemAbil::CAST_SPELL,4}, {eItemAbil::MESSAGE,14},
};
// which is unused
@@ -557,6 +557,7 @@ void use_item(short pc,short item) {
bool take_charge = true,inept_ok = false;
short level,i,j,item_use_code,str,r1;
short sp[3] = {}; // Dummy values to pass to run_special; not actually used
+ std::string str1, str2; // Used by books
eStatus status;
eItemUse type;
eSpell spell;
@@ -1150,6 +1151,18 @@ void use_item(short pc,short item) {
add_string_to_buf("Fire pours out!");
univ.town.set_quickfire(user_loc.x,user_loc.y,true);
break;
+ case eItemAbil::MESSAGE:
+ take_charge = false;
+ j = univ.party[pc].items[item].desc.find("|||");
+ str1 = univ.party[pc].items[item].desc.substr(j + 3);
+ j = str1.find("|||");
+ if(j != std::string::npos) {
+ str2 = str1.substr(j + 3);
+ str1 = str1.substr(0, j);
+ }
+ j = univ.party[pc].items[item].graphic_num;
+ cStrDlog(str1, str2, "Reading " + univ.party[pc].items[item].name, j, PIC_ITEM).show();
+ break;
// Now for all the non-usable abilities. These are enumerated here so that the compiler can catch if we've missed one.
case eItemAbil::ACCURACY: case eItemAbil::ANTIMAGIC_WEAPON: case eItemAbil::ASPTONGUE: case eItemAbil::BOOST_MAGIC:
case eItemAbil::BOOST_STAT: case eItemAbil::BOOST_WAR: case eItemAbil::CAUSES_FEAR: case eItemAbil::COMFREY:
diff --git a/src/boe.text.cpp b/src/boe.text.cpp
index fa175123..4aeb80e5 100644
--- a/src/boe.text.cpp
+++ b/src/boe.text.cpp
@@ -322,7 +322,7 @@ void put_item_screen(short screen_num) {
else { /// Don't place # of charges when Sell button up and space tight
sout << univ.party[pc].items[i_num].full_name << ' ';
// TODO: Why are bashing weapons excluded from this?
- if(univ.party[pc].items[i_num].charges > 0 && univ.party[pc].items[i_num].weap_type != eSkill::BASHING_WEAPONS
+ if(univ.party[pc].items[i_num].charges > 0 && univ.party[pc].items[i_num].ability != eItemAbil::MESSAGE
&& (stat_screen_mode == MODE_INVEN || stat_screen_mode == MODE_SHOP))
sout << '(' << int(univ.party[pc].items[i_num].charges) << ')';
}
diff --git a/src/classes/estreams.cpp b/src/classes/estreams.cpp
index 8fe034b8..7a7e3b32 100644
--- a/src/classes/estreams.cpp
+++ b/src/classes/estreams.cpp
@@ -209,7 +209,7 @@ cEnumLookup item_abils = {
"regen", "poison-aug", "radiant", "will", "freedom", "speed", "slow", "prot-race", "lockpick", "missile-drain",
"spec-drop", "", "", "", "", "", "", "", "", "",
"use-poison", "use-status", "use-spell", "bliss-doom", "use-xp", "use-skillpt", "use-hp", "use-sp", "use-light", "use-party-stat",
- "major-heal", "spec-use", "use-summon", "use-summon-mass", "use-quickfire", "", "", "", "", "",
+ "major-heal", "spec-use", "use-summon", "use-summon-mass", "use-quickfire", "use-read", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
diff --git a/src/classes/item.cpp b/src/classes/item.cpp
index d76a463b..d07c0589 100644
--- a/src/classes/item.cpp
+++ b/src/classes/item.cpp
@@ -1243,6 +1243,9 @@ std::string cItem::getAbilName() const {
case eItemAbil::MASS_SUMMONING:
sout << "Mass summon %s";
break;
+ case eItemAbil::MESSAGE:
+ sout << "Readable";
+ break;
}
return sout.str();
}
diff --git a/src/classes/simpletypes.hpp b/src/classes/simpletypes.hpp
index 590d2717..967e7e23 100644
--- a/src/classes/simpletypes.hpp
+++ b/src/classes/simpletypes.hpp
@@ -443,6 +443,7 @@ enum class eItemAbil {
SUMMONING = 82,
MASS_SUMMONING = 83,
QUICKFIRE = 84,
+ MESSAGE = 85,
// Reagents
HOLLY = 150, // Holly/Toadstool
COMFREY = 151, // Comfrey Root
diff --git a/src/scenedit/scen.core.cpp b/src/scenedit/scen.core.cpp
index 62ce5ac2..59fbf726 100644
--- a/src/scenedit/scen.core.cpp
+++ b/src/scenedit/scen.core.cpp
@@ -1915,7 +1915,7 @@ static bool edit_item_abil_event_filter(cDialog& me, std::string hit, cItem& ite
showError("You can't give an ability of this sort to a missile.",&me);
return true;
}
- i = choose_text_res("item-abilities", 70, 84, int(item.ability), &me, "Choose Usable Ability");
+ i = choose_text_res("item-abilities", 70, 85, int(item.ability), &me, "Choose Usable Ability");
if(i < 0) return true;
item.ability = eItemAbil(i + 70);
put_item_abils_in_dlog(me, item, which);