1 /*
2 This file is part of "Avanor, the Land of Mystery" roguelike game
3 Home page: http://www.avanor.com/
4 Copyright (C) 2000-2003 Vadim Gaidukevich
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 
21 #include "xbook.h"
22 #include "effect.h"
23 #include "creature.h"
24 
25 REGISTER_CLASS(XBook);
26 
27 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
28 
29 char * books_descr[] =
30 {
31 "old tome", "small tome", "ancient tome", "dirty tome", "heavy tome",
32 "old book", "small book", "ancient book", "dirty book", "heavy book",
33 "wrapped tome", "pocket book", "leather-bound tome", "parchment book",
34 "thin book", "gold decorated", "silver decorated"
35 };
36 
37 #define BOOKS_DESCR_SZ	ARRAY_SIZE(books_descr)
38 
39 int BOOK_REC::current_descr = 0;
40 int BOOK_REC::total_value = 0;
41 
BOOK_REC(int _rarity,BOOK_NAME bn,SPELL_NAME sn)42 BOOK_REC::BOOK_REC(int _rarity, BOOK_NAME bn, SPELL_NAME sn)
43 : book_name(bn), spell_name(sn), identify(0), name_index(current_descr), rarity(_rarity)
44 {
45 	current_descr++;
46 	assert(current_descr <= BOOKS_DESCR_SZ);
47 	total_value += rarity;
48 }
49 
50 
51 BOOK_REC book_descr[] = {
52 	BOOK_REC(100,	BOOK_BURNING_HANDS, SPELL_BURNING_HANDS),
53 	BOOK_REC(100,	BOOK_ICE_TOUCH, SPELL_ICE_TOUCH),
54 	BOOK_REC(150,	BOOK_CURE_LIGHT_WOUNDS, SPELL_CURE_LIGHT_WOUNDS),
55 	BOOK_REC(70,	BOOK_DRAIN_LIFE, SPELL_DRAIN_LIFE),
56 	BOOK_REC(20,	BOOK_IDENTIFY, SPELL_IDENTIFY),
57 	BOOK_REC(200,	BOOK_MAGIC_ARROW, SPELL_MAGIC_ARROW),
58 	BOOK_REC(50,	BOOK_FIRE_BOLT, SPELL_FIRE_BOLT),
59 	BOOK_REC(50,	BOOK_ICE_BOLT, SPELL_ICE_BOLT),
60 	BOOK_REC(20,	BOOK_LIGHTNING_BOLT, SPELL_LIGHTNING_BOLT),
61 	BOOK_REC(10,	BOOK_ACID_BOLT, SPELL_ACID_BOLT),
62 	BOOK_REC(60,	BOOK_CURE_DISEASE, SPELL_CURE_DISEASE),
63 	BOOK_REC(80,	BOOK_CURE_POISON, SPELL_CURE_POISON),
64 	BOOK_REC(15,	BOOK_BLINK, SPELL_BLINK),
65 	BOOK_REC(5,		BOOK_SELF_KNOWLEDGE, SPELL_SELF_KNOWLEDGE),
66 };
67 
Store(XFile * f)68 void BOOK_REC::Store(XFile * f)
69 {
70 	f->Write(&identify, sizeof(identify));
71 	f->Write(&name_index, sizeof(name_index));
72 	f->Write(&spell_name, sizeof(spell_name));
73 	f->Write(&book_name, sizeof(book_name));
74 }
75 
Restore(XFile * f)76 void BOOK_REC::Restore(XFile * f)
77 {
78 	f->Read(&identify, sizeof(identify));
79 	f->Read(&name_index, sizeof(name_index));
80 	f->Read(&spell_name, sizeof(spell_name));
81 	f->Read(&book_name, sizeof(book_name));
82 }
83 
GetBook(BOOK_NAME bn)84 int BOOK_REC::GetBook(BOOK_NAME bn)
85 {
86 	if (bn != BOOK_RANDOM)
87 	{
88 		for (int i = 0; i < BOOK_RANDOM; i++)
89 			if (book_descr[i].book_name == bn)
90 				return i;
91 	} else
92 	{
93 		int val = vRand(total_value);
94 		int pos = -1;
95 		do
96 		{
97 			pos++;
98 			val -= book_descr[pos].rarity;
99 		} while (val >= 0);
100 
101 		assert(pos < BOOK_RANDOM);
102 		return pos;
103 	}
104 	assert(0);
105 	return -1;
106 }
107 
108 
StoreTable(XFile * f)109 void XBook::StoreTable(XFile * f)
110 {
111 	for (int i = 0; i < ARRAY_SIZE(book_descr); i++)
112 	{
113 		book_descr[i].Store(f);
114 	}
115 }
116 
RestoreTable(XFile * f)117 void XBook::RestoreTable(XFile * f)
118 {
119 	for (int i = 0; i < ARRAY_SIZE(book_descr); i++)
120 	{
121 		book_descr[i].Restore(f);
122 	}
123 }
124 
125 
XBook(BOOK_NAME bn)126 XBook::XBook(BOOK_NAME bn)
127 {
128 	descr = BOOK_REC::GetBook(bn);
129 	assert(descr > -1 && descr < BOOK_RANDOM);
130 
131 	value = 20000 / book_descr[descr].rarity;
132 	strcpy(name, XSpell::GetName(book_descr[descr].spell_name));
133 
134 	im = IM_BOOK;
135 	bp = BP_OTHER;
136 	it = IT_BOOK;
137 
138 	view = '"';
139 	color =	xBROWN;
140 	weight = 100;
141 	dice.Setup("1d3");
142 	left_to_read = value * 10;
143 	reader_guid = 0;
144 }
145 
146 
isIdentifed()147 int XBook::isIdentifed()
148 {
149 	return book_descr[descr].identify;
150 }
151 
Identify(int level)152 void XBook::Identify(int level)
153 {
154 	book_descr[descr].identify = level;
155 }
156 
Compare(XObject * o)157 int XBook::Compare(XObject * o)
158 {
159 	assert(dynamic_cast<XBook *>(o));
160 	XBook * tit = (XBook *)o;
161 
162 	if (descr == tit->descr && x == tit->x && y == tit->y)
163 		return 0;
164 	else
165 	{
166 		if (quantity > tit->quantity)
167 			return -1;
168 		else
169 			return 1;
170 	}
171 }
172 
toString(char * buf)173 void XBook::toString(char * buf)
174 {
175 	if (!isIdentifed())
176 	{
177 		if (quantity == 1)
178 			sprintf(buf, "%s", books_descr[book_descr[descr].name_index]);
179 		else
180 			sprintf(buf, "heap of (%d) %ss", quantity, books_descr[book_descr[descr].name_index]);
181 	} else
182 	{
183 		if (quantity == 1)
184 			sprintf(buf, "book of %s", name);
185 		else
186 			sprintf(buf, "heap of (%d) books of %s", quantity, name);
187 	}
188 }
189 
onRead(XCreature * reader)190 int XBook::onRead(XCreature * reader)
191 {
192 	if (reader->xguid != reader_guid)
193 	{
194 		left_to_read = value * 20;
195 		reader_guid = reader->xguid;
196 	}
197 
198 
199 	XSkill * skill = reader->sk->GetSkill(SKT_LITERACY);
200 	left_to_read -= (skill->GetLevel() + reader->GetStats(S_LEN));
201 
202 	if (left_to_read <= 0)
203 	{
204 		reader->m->Learn(book_descr[descr].spell_name);
205 		skill->UseSkill(10);
206 		if (reader->isHero())
207 		{
208 			char buf[256];
209 			toString(buf);
210 			msgwin.Add("You read the");
211 			msgwin.AddLast(buf);
212 			if (!isIdentifed())
213 			{
214 				Identify(1);
215 				msgwin.Add("It was");
216 				toString(buf);
217 				msgwin.AddLast(buf);
218 			}
219 		}
220 		else if (reader->isVisible())
221 		{
222 			char buf[256];
223 			toString(buf);
224 			msgwin.Add(reader->GetNameEx(CRN_T1));
225 			msgwin.Add(reader->GetVerb("read"));
226 			msgwin.AddLast(buf);
227 			if (!isIdentifed())
228 			{
229 				Identify(1);
230 				msgwin.Add("It was");
231 				toString(buf);
232 				msgwin.AddLast(buf);
233 			}
234 		}
235 	}
236 	return 1;
237 }
238 
Store(XFile * f)239 void XBook::Store(XFile * f)
240 {
241 	XItem::Store(f);
242 	f->Write(&descr, sizeof(int));
243 	f->Write(&left_to_read, sizeof(int));
244 	f->Write(&reader_guid, sizeof(XGUID));
245 }
246 
Restore(XFile * f)247 void XBook::Restore(XFile * f)
248 {
249 	XItem::Restore(f);
250 	f->Read(&descr, sizeof(int));
251 	f->Read(&left_to_read, sizeof(int));
252 	f->Read(&reader_guid, sizeof(XGUID));
253 }
254