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