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 "deity.h"
22 #include "creature.h"
23 #include "item.h"
24 
25 XCreature * XDeity::death = NULL;
26 XCreature * XDeity::life = NULL;
27 
28 /*int XSimpleAttack::AskHelp(XCreature * asker)
29 {
30 	SPELL_NAME spn;
31 	if (vRand(2) == 0)
32 		spn = SPELL_MAGIC_ARROW;
33 	else
34 		spn = SPELL_DRAIN_LIFE;
35 
36 XBasicSpell * spell = XSpellFactory::Get(spn);
37 	return spell->onCast(asker, 50);
38 	return 0;
39 }
40 
41 int XMediumAttack::AskHelp(XCreature * asker)
42 {
43 	SPELL_NAME spn;
44 	if (vRand(2) == 0)
45 		spn = SPELL_FIRE_BOLT;
46 	else
47 		spn = SPELL_ICE_BOLT;
48 
49 	XBasicSpell * spell = XSpellFactory::Get(spn);
50 	return spell->onCast(asker, 50);
51 	return 0;
52 }
53 
54 int XHardAttack::AskHelp(XCreature * asker)
55 {
56 	SPELL_NAME spn;
57 	if (vRand(2) == 0)
58 		spn = SPELL_LIGHTNING_BOLT;
59 	else
60 		spn = SPELL_ACID_BOLT;
61 
62 	XBasicSpell * spell = XSpellFactory::Get(spn);
63 	return spell->onCast(asker, 50);
64 	return 0;
65 }
66 */
67 
68 DEITY_HELP life_help[] = {
69 	{"cure light wounds",			3,	PRAY_CURE_LIGHT_WOUNDS},
70 	{"minor divine intervention",	5,	PRAY_MINOR_INTERVENTION},
71 
72 	{"cure poison",					10, PRAY_CURE_POISON},
73 	{"heroism",						10, PRAY_HEROISM},
74 
75 	{"cure critical wounds",		20, PRAY_CURE_CRITICAL_WOUNDS},
76 
77 	{"great knowledge",				30, PRAY_IDENTIFY},
78 
79 	{"divine restoration",			50, PRAY_RESTORATION}
80 };
81 
82 DEITY_HELP death_help[] =
83 {
84 	{"cure light wounds",			5,	PRAY_CURE_LIGHT_WOUNDS},
85 	{"minor divine intervention",	5,	PRAY_MINOR_INTERVENTION},
86 
87 	{"divine intervention",			5,	PRAY_INTERVENTION},
88 	{"divine escape",				50, PRAY_TELEPORT},
89 
90 	{"cure critical wounds",		30, PRAY_CURE_CRITICAL_WOUNDS},
91 
92 	{"knowledge of insight",		50, PRAY_SELF_KNOWLEDGE},
93 
94 	{"major divine intervention",	5,	PRAY_MAJOR_INTERVENTION},
95 };
96 
97 
98 struct DEITY_ACT
99 {
100 	int good;
101 	int bad;
102 };
103 
104 DEITY_ACT life_deity_act[] = {
105 	{5, -15}, {5, -14}, {5, -12}, {5, -10}, {10, -10},
106 	{10, -9}, {10, -8}, {10, -7}, {10, -6}, {10, -5},
107 	{10, -4}, {10, -3}, {10, -2}, {10, -1}, {10, 0}, {10, 0}
108 };
109 
110 
111 
112 
KillCreature(XCreature * killer,XCreature * victim)113 void XReligion::KillCreature(XCreature * killer, XCreature * victim)
114 {
115 	int val = killer->sk->GetLevel(SKT_RELIGION);
116 	int bad = life_deity_act[val].bad;
117 	int good = life_deity_act[val].good;
118 	if (victim->creature_class == CR_UNDEAD)
119 	{
120 		death_act += bad;
121 		life_act += good;
122 	} else
123 	{
124 		death_act += good;
125 		life_act += bad;
126 	}
127 }
128 
SacrificeItem(XCreature * cr,XItem * item,DEITY deity)129 int XReligion::SacrificeItem(XCreature * cr, XItem * item, DEITY deity)
130 {
131 	int val = cr->sk->GetLevel(SKT_RELIGION);
132 	if (deity == D_UNKNOWN)
133 	{
134 		if (life_act > death_act)
135 			deity = D_LIFE;
136 		else
137 			deity = D_DEATH;
138 	}
139 
140 	XMapObject * tmo = cr->l->map->GetSpecial(cr->x, cr->y);
141 	if (tmo && tmo->im & IM_ALTAR)
142 	{
143 		if (tmo->color == xWHITE)
144 			deity = D_LIFE;
145 		else
146 			deity = D_DEATH;
147 	}
148 
149 	if (cr->isVisible())
150 	{
151 		char buf[256];
152 		sprintf(buf, "%s prays to %s.", cr->name, GetDeityName(deity));
153 		msgwin.Add(buf);
154 		item->toString(buf);
155 		msgwin.Add(buf);
156 		msgwin.Add("disappears in a bright light.");
157 	}
158 
159 	int sacrifice_value;
160 	if (item->im & IM_MONEY)
161 		sacrifice_value = (int)(sqrt(item->quantity) + 1) * (val / 4 + 1);
162 	else
163 		sacrifice_value = (int)((sqrt(item->GetValue()) * item->quantity) + 1) * (val / 4 + 1);
164 
165 	cr->sk->UseSkill(SKT_RELIGION);
166 
167 	if (tmo && tmo->im & IM_ALTAR)
168 	{
169 		sacrifice_value *= 3;
170 		cr->sk->UseSkill(SKT_RELIGION, 5);
171 	}
172 
173 	item->UnCarry();
174 	item->Invalidate();
175 
176 	if (deity == D_LIFE)
177 	{
178 		life_act += sacrifice_value;
179 	} else
180 	{
181 		death_act += sacrifice_value;
182 	}
183 
184 	if (!cr->isHero() && vRand(5) == 0)
185 	{
186 		cr->s->Modify(XStats::Random(), 1);
187 		if (cr->isVisible())
188 		{
189 			msgwin.Add(cr->name);
190 			msgwin.Add("looks more powerful!");
191 		}
192 	}
193 
194 	return 1;
195 }
196 
GetRelation(DEITY deity)197 DEITY_RELATION XReligion::GetRelation(DEITY deity)
198 {
199 	int val = 0;
200 	switch (deity)
201 	{
202 		case D_LIFE: val = life_act; break;
203 		case D_DEATH: val = death_act; break;
204 	}
205 	if (val < -10000000)
206 		return DR_FALLEN_CHAMPION;
207 	else if (val < -100)
208 		return DR_VERY_BAD;
209 	else if (val < 0)
210 		return DR_BAD;
211 	else if (val < 100)
212 		return DR_NORMAL;
213 	else if (val < 1000)
214 		return DR_ADEPT;
215 	else if (val < 3000)
216 		return DR_FOLLOWER;
217 	else if (val < 10000)
218 		return DR_MESSIAH;
219 	else
220 		return DR_CHAMPION;
221 }
222 
223 char * relation_name[] = {
224 MSG_RED "fallen champion", MSG_RED "very bad", MSG_RED "bad",
225 MSG_LIGHTGRAY "normal", MSG_LIGHTGRAY "adept", MSG_LIGHTGREEN "follower",
226 MSG_YELLOW "messiah", MSG_WHITE "champion"
227 };
228 
GetRelationName(DEITY_RELATION dr)229 char * XReligion::GetRelationName(DEITY_RELATION dr)
230 {
231 	return relation_name[dr];
232 }
233 
GetDeityName(DEITY deity)234 char * XReligion::GetDeityName(DEITY deity)
235 {
236 	if (deity == D_LIFE)
237 		return "Tiamat";
238 	else
239 		return "Marduk";
240 }
241 
GetAvailHelp(DEITY deity,DEITY_HELP ** help)242 int XReligion::GetAvailHelp(DEITY deity, DEITY_HELP ** help)
243 {
244 	if (deity == D_LIFE)
245 	{
246 		*help = &life_help[0];
247 
248 	} else
249 	{
250 		*help = &death_help[0];
251 	}
252 
253 	DEITY_RELATION rel = GetRelation(deity);
254 	if (rel < DR_ADEPT)
255 		return 0;
256 	if (rel < DR_FOLLOWER)
257 		return 2;
258 	if (rel < DR_MESSIAH)
259 		return 4;
260 	if (rel < DR_CHAMPION)
261 		return 6;
262 	return 7;
263 }
264 
Pray(DEITY deity,DEITY_HELP * pray,XCreature * prayer)265 int XReligion::Pray(DEITY deity, DEITY_HELP * pray, XCreature * prayer)
266 {
267 	EFFECT effect = E_CURE_LIGHT_WOUNDS;
268 	switch (pray->pray)
269 	{
270 		case PRAY_CURE_LIGHT_WOUNDS:	effect = E_CURE_LIGHT_WOUNDS; break;
271 		case PRAY_CURE_CRITICAL_WOUNDS:	effect = E_CURE_CRITICAL_WOUNDS; break;
272 		case PRAY_RESTORATION:			effect = E_RESTORATION; break;
273 		case PRAY_IDENTIFY:				effect = E_IDENTIFY; break;
274 		case PRAY_SELF_KNOWLEDGE:		effect = E_SELF_KNOWLEDGE; break;
275 		case PRAY_CURE_POISON:			effect = E_CURE_POISON; break;
276 		case PRAY_HEROISM:				effect = E_HEROISM; break;
277 		case PRAY_TELEPORT:				effect = E_TELEPORT; break;
278 
279 		case PRAY_MINOR_PUNISHMENT:		effect = E_MAGIC_ARROW; break;
280 		case PRAY_MINOR_INTERVENTION:	effect = E_MAGIC_ARROW; break;
281 		case PRAY_INTERVENTION:			effect = vRand(2) == 0 ? E_FIRE_BOLT : E_ICE_BOLT; break;
282 		case PRAY_MAJOR_INTERVENTION:	effect = vRand(2) == 0 ? E_LIGHTNING_BOLT : E_ACID_BOLT; break;
283 	}
284 
285 	RESULT res = XEffect::Make(prayer, effect, 50);
286 
287 	if (res == SUCCESS)
288 	{
289 		if (deity == D_LIFE)
290 		{
291 			life_act -= pray->help_cost;
292 		} else
293 		{
294 			death_act -= pray->help_cost;
295 		}
296 		prayer->sk->UseSkill(SKT_RELIGION, 3);
297 	} if (res != ABORT)
298 	{
299 		msgwin.Add("Your prayer was unheard.");
300 	}
301 	return 1;
302 }
303 
Store(XFile * f)304 void XReligion::Store(XFile * f)
305 {
306 	f->Write(&life_act);
307 	f->Write(&death_act);
308 }
309 
Restore(XFile * f)310 void XReligion::Restore(XFile * f)
311 {
312 	f->Read(&life_act);
313 	f->Read(&death_act);
314 }
315