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 "item.h"
22 
23 #include "creature.h"
24 
25 
XItem()26 XItem::XItem()
27 {
28 	total_it++;
29 
30 	ttm = 0;
31 	ttmb = 0;
32 	durability = 10;
33 
34 	is_selected = 0;
35 
36 	view = '*';
37 	color = xBLUE;
38 	it = IT_OTHER;
39 	im = IM_OTHER;
40 	wt = WSK_OTHER;
41 	bp = BP_OTHER;
42 	identify = 1;
43 	_DV = _PV = _HIT = RNG = 0;
44 	dice.Setup("0d0");
45 	special_number = -1;
46 	brt = BR_NONE;
47 	owner = NULL;
48 }
49 
Invalidate()50 void XItem::Invalidate()
51 {
52 	total_it--;
53 	XBaseObject::Invalidate();
54 }
55 
BasicFill(ITEM_TYPE it,_MAIN_ITEM_STRUCT * is,int is_rcount)56 int XItem::BasicFill(ITEM_TYPE it, _MAIN_ITEM_STRUCT * is, int is_rcount)
57 {
58 	_MAIN_ITEM_STRUCT * x_struct = NULL;
59 
60 	if (it == IT_RANDOM)
61 	{
62 		int r_val = vRand() % is_rcount;
63 		x_struct = (is + r_val);
64 	} else
65 	{
66 		for (int i = 0; i < is_rcount; i++)
67 			if ((is + i)->it == it)
68 			{
69 				x_struct = (is + i);
70 				break;
71 			}
72 	}
73 
74 	if (x_struct)
75 	{
76 		MainFill(x_struct);
77 		PropFill(x_struct->iset);
78 		if (vRand() % 20 > 18)
79 			SpecialFill();
80 		return 1;
81 	} else
82 		return 0;
83 }
84 
MainFill(_MAIN_ITEM_STRUCT * is)85 void XItem::MainFill(_MAIN_ITEM_STRUCT *is)
86 {
87 	strcpy(name, is->name);
88 	it = is->it;
89 	view = is->view;
90 	weight = is->valume;
91 	value = is->value;
92 
93 	XDice * d;
94 
95 	d = new XDice(is->dv);
96 	_DV = d->Throw();
97 
98 	d->Setup(is->pv);
99 	_PV = d->Throw();
100 
101 	d->Setup(is->hit);
102 	_HIT = d->Throw();
103 
104 	d->Setup(is->dice);
105 	int tx = d->X;
106 	int ty = d->Y;
107 
108 	d->Setup(is->z);
109 	dice.Setup(tx, ty, d->Throw());
110 
111 	d->Setup(is->r);
112 	RNG = d->Throw();
113 	delete d;
114 }
115 
PropFill(ITEM_SET is,int val)116 void XItem::PropFill(ITEM_SET is, int val)
117 {
118 	int tval = 0;
119 	for (int i = 0; i < DB_PROP_SZ; i++)
120 	{
121 		if (item_prop[i].iflag & is)
122 			tval += item_prop[i].probability;
123 	}
124 	assert(tval > 0);
125 
126 	int trnd = vRand() % tval;
127 	int r_val = 0;
128 	while (1)
129 	{
130 		if (item_prop[r_val].iflag & is)
131 			trnd -= item_prop[r_val].probability;
132 		if (trnd < 0)
133 			break;
134 		r_val++;
135 	}
136 
137 
138 /*	int r_val;
139 	int fail_count = 0;
140 	static int tryes = 0;
141 	static int sum = 0;
142 	while (1)
143 	{
144 		r_val = vRand() % DB_PROP_SZ;
145 		if ((item_prop[r_val].iflag & is) &&
146 			item_prop[r_val].probability >= (vRand() % val))
147 			break;
148 		fail_count++;
149 	}
150 	tryes++;
151 	sum += fail_count;
152 	float avg = (float)sum / tryes;
153 	material_index = r_val;
154 */
155 	material_index = r_val;
156 	char buf[100];
157 	sprintf(buf, "%s %s", item_prop[r_val].propname, name);
158 	strcpy(name, buf);
159 
160 	color = item_prop[r_val].color;
161 	weight *= item_prop[r_val].density;
162 	value =	item_prop[r_val].value * value / 10;
163 
164 //	if (item_prop[r_val].probability <= vRand() % 1000)
165 //	{
166 		XDice d;
167 
168 		if (_DV)
169 		{
170 			d.Setup(item_prop[r_val].dv);
171 			_DV += d.S;
172 		}
173 
174 		if (_PV)
175 		{
176 			d.Setup(item_prop[r_val].pv);
177 			_PV += d.S;
178 		}
179 
180 		d.Setup(item_prop[r_val].hit);
181 		_HIT += d.S;
182 
183 		d.Setup(item_prop[r_val].dice);
184 		int tx = dice.X + d.X;
185 		int ty = dice.Y + d.Y;
186 		d.Setup(item_prop[r_val].z);
187 		dice.Setup(tx, ty, dice.Z + d.S);
188 //	}
189    assert(r == NULL);
190 	r = new XResistance(item_prop[r_val].resistance);
191    assert(s == NULL);
192 	s = new XStats();
193 }
194 
SpecialFill()195 void XItem::SpecialFill()
196 {
197 //	if (vRand() % 100 < 90)
198 //		return;
199 
200 	int r_val;
201 	if (im & IM_WEAPON)
202 		int uu = 0;
203 //	int try_count = 1000;
204 //	while (try_count-- > 0)
205 //	{
206 	r_val = vRand() % ENH_DB_SZ;
207 	if (!(ienh_db[r_val].val < vRand() % 101 && (im & ienh_db[r_val].im)))
208 		return;
209 //	}
210 //	if (try_count == 0)
211 //		return;
212 
213 /*	char buf[100];
214 	sprintf(buf, "%s %s", name, ienh_db[r_val].name);
215 	strcpy(name, buf);
216 */
217 	special_number = r_val;
218 
219 	if (ienh_db[r_val].color)
220 		color = ienh_db[r_val].color;
221 
222 //	weight *= item_prop[r_val].density;
223 //	value =	item_prop[r_val].value * value;
224 
225 	XDice * d;
226 
227 	d = new XDice(ienh_db[r_val].dv);
228 	_DV += d->Throw();
229 
230 	d->Setup(ienh_db[r_val].pv);
231 	_PV += d->Throw();
232 
233 	d->Setup(ienh_db[r_val].hit);
234 	_HIT += d->Throw();
235 
236 	d->Setup(ienh_db[r_val].dice);
237 	int tx = dice.X + d->X;
238 	int ty = dice.Y + d->Y;
239 	d->Setup(ienh_db[r_val].z);
240 	dice.Setup(tx, ty, dice.Z + d->Throw());
241 	delete d;
242 
243 	XResistance xres(ienh_db[r_val].r);
244 	XStats xst(ienh_db[r_val].s);
245 	r->Add(&xres);
246 	s->Add(&xst);
247 
248 	brt = ienh_db[r_val].brt;
249 }
250 
XItem(XItem * copy)251 XItem::XItem(XItem * copy) : XBaseObject((XBaseObject *)copy)
252 {
253 	total_it++;
254 
255 	bp = copy->bp;
256 	durability = copy->durability;
257 	identify = copy->identify;
258 	is_selected = copy->is_selected;
259 	it = copy->it;
260 	material_index = copy->material_index;
261 //	shop_flag = copy->shop_flag;
262 	special_number = copy->special_number;
263 	special_property = copy->special_property;
264 	value = copy->value;
265 	wt = copy->wt;
266 	brt = copy->brt;
267 	owner = copy->owner.get();
268 }
269 
Compare(XObject * o)270 int XItem::Compare(XObject * o)
271 {
272 	assert(dynamic_cast<XItem *>(o));
273 	XItem * tit = (XItem *)o;
274 	if (it == tit->it && tit->brt == brt && XBaseObject::Compare(o) == 0)
275 		return 0;
276 	else
277 		return 1;
278 }
279 
280 
toString(char * buf)281 void XItem::toString(char * buf)
282 {
283   assert(0);
284 }
285 
286 /*
287 void XItem::Run()
288 {
289 	ttm = ttmb;
290 	if (it == IT_CORPSE)
291 	{
292 		assert(0);
293 //		nutrio--;
294 	}
295 }
296 */
297 
ModifyDur(int val)298 int XItem::ModifyDur(int val)
299 {
300 	if (durability == DUR_INFINITE) return 0;
301 	durability -= val;
302 	if (durability <= 0)
303 		return 0;
304 	else
305 		return 1;
306 }
307 
GetValue()308 int XItem::GetValue()
309 {
310 	int xdice = 0;
311 	int xdvpv = 0;
312 	int xhitdmg = 0;
313 
314 	if (im & IM_VALUEDICE)
315 		xdice = (dice.X * dice.Y + dice.X) * 3;
316 
317 	if (im & IM_VALUEDVPV)
318 		xdvpv = (_DV + 6 * _PV) * 4;
319 
320 	if (im & IM_SHIELD)
321 		xdvpv = xdvpv + _DV * 5;
322 
323 	if (im & IM_VALUEHITDMG)
324 		xhitdmg = (_HIT + dice.Z * 3) * 3;
325 
326 	int xrng = RNG * (abs(RNG) + 5);
327 
328 
329 
330 	int xstats = 0;
331 	int i;
332 	if (s)
333 		for (i = S_STR; i < S_EOF; i++)
334 			xstats += s->Get((STATS)i);
335 
336 	int xresist = 0;
337 	if (r)
338 		for (i = R_WHITE; i < R_EOF; i++)
339 		{
340 			int tr = r->GetResistance((RESISTANCE)i);
341 			if (tr < 10)
342 				xresist += tr * 2;
343 			else if (tr < 30)
344 				xresist += tr * 4;
345 			else if (tr < 50)
346 				xresist += tr * 8;
347 			else if (tr < 75)
348 				xresist += tr * 10;
349 			else
350 				xresist += tr * 20;
351 		}
352 
353 	int brtval = 0;
354 
355 	if (brt & BR_FIRE)
356 		brtval += 200;
357 
358 	if (brt & BR_COLD)
359 		brtval += 150;
360 
361 	if (brt & BR_ORCSLAYER)
362 		brtval += 300;
363 
364 	if (brt & BR_DEMONSLAYER)
365 		brtval += 220;
366 
367 	int xval = brtval + value + xdice + xdvpv + xhitdmg + xstats * 150 + xresist + xrng;
368 	if (im & IM_MISSILE)
369 		xval /= 7;
370 	if (xval <= 0)
371 		return 1;
372 	else
373 		return xval;
374 }
375 
PriceToString(char * buf)376 void XItem::PriceToString(char * buf)
377 {
378 /*	if (shop_flag)
379 		sprintf(buf, "{%dgp}", GetValue());
380 	else
381 		strcpy(buf, "");
382 */
383 }
384 
StatsToString(char * buf)385 void XItem::StatsToString(char * buf)
386 {
387 	char tb[256];
388 	strcpy(buf, "");
389 	if (s)
390 	{
391 		strcpy(tb, "{");
392 		int flag = 0;
393 		for (int i = S_STR; i < S_EOF; i++)
394 			if (s->Get((STATS)i) != 0)
395 			{
396 				if (flag)
397 					strcat(tb, " ");
398 				strcat(tb, s->GetName((STATS)i));
399 				strcat(tb, ":");
400 				char tmpbuf[20];
401 				sprintf(tmpbuf, "%d", s->Get((STATS)i));
402 				strcat(tb, tmpbuf);
403 				flag++;
404 			}
405 		if (flag)
406 		{
407 			strcat(tb, "}");
408 			strcpy(buf, tb);
409 		}
410 	}
411 //	PriceToString(tb);
412 //	strcat(buf, tb);
413 }
414 
415 
GetFullName(char * buf,char * templ)416 void XItem::GetFullName(char * buf, char * templ)
417 {
418 	if (special_number >= 0)
419 	{
420 		if (quantity == 1)
421 			sprintf(buf, ienh_db[special_number].name, name);
422 		else
423 		{
424 			char tbuf[128];
425 			sprintf(buf, "heap of (%d)", quantity);
426 			if (im & (IM_BOOTS | IM_GLOVES))
427 			{
428 				sprintf(tbuf, ienh_db[special_number].name, name);
429 				strcat(buf, tbuf);
430 			} else
431 			{
432 				char rbuf[128];
433 				strcpy(rbuf, name);
434 				strcat(rbuf, "s");
435 				sprintf(tbuf, ienh_db[special_number].name, rbuf);
436 				strcat(buf, tbuf);
437 			}
438 		}
439 		strcat(buf, " ");
440 	} else
441 	{
442 		if (quantity == 1)
443 			sprintf(buf, "%s ", name);
444 		else
445 		{
446 			if (im & (IM_BOOTS | IM_GLOVES))
447 				sprintf(buf, "heap of (%d) %s ", quantity, name);
448 			else
449 				sprintf(buf, "heap of (%d) %ss ", quantity, name);
450 		}
451 	}
452 }
453 
GetArtifactName(char * buf,char * real_name)454 void XItem::GetArtifactName(char * buf, char * real_name)
455 {
456 	if (isIdentifed())
457 	{
458 		char tbuf[256];
459 		strcpy(buf, real_name);
460 		if (RNG != 0)
461 		{
462 			sprintf(tbuf, "<%+d>", RNG);
463 			strcat(buf, tbuf);
464 		}
465 
466 		if (_DV != 0 || _PV != 0)
467 		{
468 			sprintf(tbuf, "[%+d, %+d]", _DV, _PV);
469 			strcat(buf, tbuf);
470 		}
471 		if (im & IM_WEAPON)
472 		{
473 			sprintf(tbuf, "(%+d, %dd%d%+d)", _HIT, dice.X, dice.Y, dice.Z);
474 			strcat(buf, tbuf);
475 		}
476 
477 		StatsToString(tbuf);
478 		strcat(buf, tbuf);
479 	} else
480 	{
481 		strcpy(buf, name);
482 	}
483 }
484 
Store(XFile * f)485 void XItem::Store(XFile * f)
486 {
487 	XBaseObject::Store(f);
488 
489 	f->Write(&bp, sizeof(BODYPART));
490 	f->Write(&brt, sizeof(BRAND_TYPE));
491 	f->Write(&durability, sizeof(int));
492 	f->Write(&identify, sizeof(int));
493 
494 	f->Write(&is_selected, sizeof(int));
495 	f->Write(&it, sizeof(ITEM_TYPE));
496 	f->Write(&material_index, sizeof(int));
497 
498 //	f->Write(&shop_flag, sizeof(int));
499 
500 	f->Write(&special_number, sizeof(int));
501 	f->Write(&special_property, sizeof(SPECIAL_PROPERTY));
502 
503 	f->Write(&value, sizeof(int));
504 	f->Write(&wt, sizeof(WSK_TYPE));
505 
506    owner.Store(f);
507 }
508 
509 
Restore(XFile * f)510 void XItem::Restore(XFile * f)
511 {
512 	XBaseObject::Restore(f);
513 
514 	f->Read(&bp, sizeof(BODYPART));
515 	f->Read(&brt, sizeof(BRAND_TYPE));
516 	f->Read(&durability, sizeof(int));
517 	f->Read(&identify, sizeof(int));
518 
519 	f->Read(&is_selected, sizeof(int));
520 	f->Read(&it, sizeof(ITEM_TYPE));
521 	f->Read(&material_index, sizeof(int));
522 
523 //	f->Read(&shop_flag, sizeof(int));
524 
525 	f->Read(&special_number, sizeof(int));
526 	f->Read(&special_property, sizeof(SPECIAL_PROPERTY));
527 
528 	f->Read(&value, sizeof(int));
529 	f->Read(&wt, sizeof(WSK_TYPE));
530 
531    owner.Restore(f);
532 }
533 
onWear(XCreature * cr)534 int XItem::onWear(XCreature * cr)
535 {
536 	cr->added_stats.Add(s); //modify stats;
537 	cr->added_resists.Add(r); //modify resist;
538 
539 	if (im != IM_SHIELD)
540 		cr->added_DV	+= _DV;
541 
542 	cr->added_PV	+= _PV;
543 
544 	if (im & IM_TOHIT)
545 	{
546 		cr->added_HIT	+= _HIT;
547 	}
548 
549 	if (!(im & (IM_WEAPON | IM_MISSILE | IM_MISSILEW)))
550 	{
551 		cr->added_DMG	+= dice.Z;
552 	}
553 
554 	cr->added_RNG	+= RNG;
555 
556 	cr->added_HP	+= _HP;
557 	cr->added_PP	+= _PP;
558 
559 	return 1;
560 }
561 
onUnWear(XCreature * cr)562 int XItem::onUnWear(XCreature * cr)
563 {
564 	cr->added_stats.Sub(s); //modify stats;
565 	cr->added_resists.Sub(r); //modify resist;
566 
567 	if (im != IM_SHIELD)
568 		cr->added_DV	-= _DV;
569 	cr->added_PV	-= _PV;
570 
571 	if (im & IM_TOHIT)
572 	{
573 		cr->added_HIT	-= _HIT;
574 	}
575 
576 	if (!(im & IM_WEAPON | IM_MISSILE | IM_MISSILEW))
577 	{
578 		cr->added_DMG	-= dice.Z;
579 	}
580 
581 	cr->added_RNG	-= RNG;
582 
583 	cr->added_HP	-= _HP;
584 	cr->added_PP	-= _PP;
585 	return 1;
586 }
587 
onPickUp(XCreature * cr)588 int XItem::onPickUp(XCreature * cr)
589 {
590 	SetOwner(cr);
591 	return 1;
592 }
593 
onPutOn(XCreature * cr)594 int XItem::onPutOn(XCreature * cr)
595 {
596 	return 1;
597 }
598 
onHit(XCreature * user,XCreature * target)599 int XItem::onHit(XCreature * user, XCreature * target)
600 {
601 	if (ienh_db[special_number].brt & BR_FIRE)
602 	{
603 //		user->MagicAttack(target, dice.Throw(), R_FIRE);
604 	}
605 	return 1;
606 }
607 
608 
GetMaterial(int index)609 _ITEMPROP * XItem::GetMaterial(int index)
610 {
611 	return &item_prop[index];
612 }
613 
Drop(XLocation * location,int _x,int _y)614 void XItem::Drop(XLocation * location, int _x, int _y)
615 {
616 	SetOwner(NULL);
617 	SetLocation(location);
618 	l->map->PutItem(_x, _y, this);
619 }
620 
SetOwner(XCreature * new_owner)621 bool XItem::SetOwner(XCreature * new_owner)
622 {
623 	owner = new_owner;
624 	if(owner) SetLocation(NULL);
625 	return true;
626 }
627 
Pickup(XCreature * picker)628 void XItem::Pickup(XCreature * picker)
629 {
630 	assert(0);
631 }
632 
UnCarry()633 void XItem::UnCarry()
634 {
635 	if (owner)
636 		owner->UnCarryItem(this);
637 }
638 
639