Unified · Split
| @@ -51,6 +51,8 @@ enum · 50 unmodified lines | |||
| 51 | { | 51 | { |
| 52 | /* possible item types */ | 52 | /* possible item types */ |
| 53 | IWEAPON = 0, | 53 | IWEAPON = 0, |
| 54 | IHELMET, | ||
| 55 | ISHIELD, | ||
| 54 | IARMOR, | 56 | IARMOR, |
| 55 | 57 | ||
| 56 | /* item flags */ | 58 | /* item flags */ |
| @@ -82,10 +84,18 @@ struct ItemData · 25 unmodified lines | |||
| 82 | int flags; | 84 | int flags; |
| 83 | }; | 85 | }; |
| 84 | 86 | ||
| 87 | enum | ||
| 88 | { | ||
| 89 | IMAXAGE = 250, | ||
| 90 | }; | ||
| 91 | |||
| 85 | struct Item | 92 | struct Item |
| 86 | { | 93 | { |
| 87 | Ref ref; | 94 | Ref ref; |
| 88 | 95 | ||
| 96 | /* age, for automatic deletion */ | ||
| 97 | int age; | ||
| 98 | |||
| 89 | /* count of items in stack */ | 99 | /* count of items in stack */ |
| 90 | int count; | 100 | int count; |
| 91 | 101 | ||
| @@ -215,10 +225,11 @@ struct Monster · 123 unmodified lines | |||
| 215 | /* inventory */ | 225 | /* inventory */ |
| 216 | ItemList inv; | 226 | ItemList inv; |
| 217 | 227 | ||
| 218 | /* equipped weapon */ | 228 | /* equipped weapon & armor */ |
| 219 | Item *weapon; | 229 | Item *weapon; |
| 220 | /* equipped armor */ | 230 | Item *helmet; |
| 221 | ItemList armor; | 231 | Item *shield; |
| 232 | Item *armor; | ||
| 222 | 233 | ||
| 223 | /* no free */ | 234 | /* no free */ |
| 224 | MonsterData *md; | 235 | MonsterData *md; |
| @@ -234,9 +245,7 @@ void mpushstate(Monster *m, AIState *a); · 9 unmodified lines | |||
| 234 | AIState *mpopstate(Monster *m); | 245 | AIState *mpopstate(Monster *m); |
| 235 | int maction(Monster *m, int what, Point where); | 246 | int maction(Monster *m, int what, Point where); |
| 236 | int mwield(Monster *m, int n); | 247 | int mwield(Monster *m, int n); |
| 237 | int munwield(Monster *m); | 248 | int munwield(Monster *m, int type); |
| 238 | int mwear(Monster *m, int n); | ||
| 239 | void mnaked(Monster *m); | ||
| 240 | void maddinv(Monster *m, Item *i); | 249 | void maddinv(Monster *m, Item *i); |
| 241 | int xpcalc(int level); | 250 | int xpcalc(int level); |
| 242 | 251 | ||
| @@ -32,6 +32,8 @@ static char *itemdbcmd[] = { · 31 unmodified lines | |||
| 32 | 32 | ||
| 33 | static char *itemtype[] = { | 33 | static char *itemtype[] = { |
| 34 | [IWEAPON] "weapon", | 34 | [IWEAPON] "weapon", |
| 35 | [IHELMET] "helmet", | ||
| 36 | [ISHIELD] "shield", | ||
| 35 | [IARMOR] "armor", | 37 | [IARMOR] "armor", |
| 36 | }; | 38 | }; |
| 37 | 39 | ||
| @@ -55,6 +57,8 @@ ifmt(Fmt *f) · 17 unmodified lines | |||
| 55 | case IWEAPON: | 57 | case IWEAPON: |
| 56 | snprint(extra, sizeof(extra), " (%dd%d)", i->id->rolls, i->id->atk); | 58 | snprint(extra, sizeof(extra), " (%dd%d)", i->id->rolls, i->id->atk); |
| 57 | break; | 59 | break; |
| 60 | case IHELMET: | ||
| 61 | case ISHIELD: | ||
| 58 | case IARMOR: | 62 | case IARMOR: |
| 59 | snprint(extra, sizeof(extra), " (ac %d)", i->id->ac); | 63 | snprint(extra, sizeof(extra), " (ac %d)", i->id->ac); |
| 60 | break; | 64 | break; |
| @@ -213,6 +217,9 @@ missing: · 152 unmodified lines | |||
| 213 | void | 217 | void |
| 214 | ifree(Item *i) | 218 | ifree(Item *i) |
| 215 | { | 219 | { |
| 220 | if(i == nil) | ||
| 221 | return; | ||
| 222 | |||
| 216 | if(decref(&i->ref) != 0) | 223 | if(decref(&i->ref) != 0) |
| 217 | return; | 224 | return; |
| 218 | 225 | ||
| @@ -4,8 +4,16 @@ · 3 unmodified lines | |||
| 4 | item="dagger" | 4 | item="dagger" |
| 5 | tile=411 type=weapon cost=5 weight=5 atk=1d4 | 5 | tile=411 type=weapon cost=5 weight=5 atk=1d4 |
| 6 | stacks | 6 | stacks |
| 7 | item="longsword" | ||
| 8 | tile=431 type=weapon cost=10 weight=10 atk=1d8 | ||
| 9 | item="runesword" | ||
| 10 | tile=435 type=weapon cost=50 weight=10 atk=4d4 | ||
| 7 | 11 | ||
| 8 | # armor | 12 | # armor |
| 13 | item="helmet" | ||
| 14 | tile=472 type=helmet cost=5 weight=2 ac=2 | ||
| 9 | item="shield" | 15 | item="shield" |
| 10 | tile=525 type=armor cost=5 weight=10 ac=2 | 16 | tile=525 type=shield cost=5 weight=10 ac=2 |
| 17 | item="plate armor" | ||
| 18 | tile=496 type=armor cost=50 weight=15 ac=4 | ||
| 11 | 19 | ||
| @@ -191,12 +191,27 @@ mkmons(Level *l, Point p, char *type) · 190 unmodified lines | |||
| 191 | idle(m); | 191 | idle(m); |
| 192 | 192 | ||
| 193 | /* items! */ | 193 | /* items! */ |
| 194 | if(nrand(5) == 0){ | 194 | switch(nrand(100)){ |
| 195 | case 0: | ||
| 195 | m->weapon = ibyname("dagger"); | 196 | m->weapon = ibyname("dagger"); |
| 197 | break; | ||
| 198 | case 1: | ||
| 199 | m->weapon = ibyname("longsword"); | ||
| 200 | case 3: | ||
| 201 | m->weapon = ibyname("runesword"); | ||
| 202 | break; | ||
| 196 | } | 203 | } |
| 197 | if(nrand(5) == 0){ | 204 | if(nrand(50) == 0){ |
| 205 | maddinv(m, ibyname("helmet")); | ||
| 206 | mwield(m, 0); | ||
| 207 | } | ||
| 208 | if(nrand(50) == 0){ | ||
| 198 | maddinv(m, ibyname("shield")); | 209 | maddinv(m, ibyname("shield")); |
| 199 | mwear(m, 0); | 210 | mwield(m, 0); |
| 211 | } | ||
| 212 | if(nrand(100) == 0){ | ||
| 213 | maddinv(m, ibyname("plate armor")); | ||
| 214 | mwield(m, 0); | ||
| 200 | } | 215 | } |
| 201 | return m; | 216 | return m; |
| 202 | } | 217 | } |
| @@ -261,6 +276,7 @@ levelexec(AIState *a) · 58 unmodified lines | |||
| 261 | Tile *t; | 276 | Tile *t; |
| 262 | MonsterData *md; | 277 | MonsterData *md; |
| 263 | Monster *m; | 278 | Monster *m; |
| 279 | Item *it; | ||
| 264 | 280 | ||
| 265 | l = a->aux; | 281 | l = a->aux; |
| 266 | 282 | ||
| @@ -293,6 +309,22 @@ levelexec(AIState *a) · 26 unmodified lines | |||
| 293 | several(l, &p, 1, sp->what, 0); | 309 | several(l, &p, 1, sp->what, 0); |
| 294 | } | 310 | } |
| 295 | } | 311 | } |
| 312 | |||
| 313 | for(p.x = 0; p.x < l->width; p.x++){ | ||
| 314 | for(p.y = 0; p.y < l->height; p.y++){ | ||
| 315 | if(hasflagat(l, p, Fhasitem)){ | ||
| 316 | t = tileat(l, p); | ||
| 317 | for(i = 0; i < t->items.count; i++){ | ||
| 318 | it = ilnth(&t->items, i); | ||
| 319 | if(++it->age > IMAXAGE){ | ||
| 320 | ifree(iltakenth(&t->items, i)); | ||
| 321 | if(t->items.count == 0) | ||
| 322 | clrflagat(l, p, Fhasitem); | ||
| 323 | } | ||
| 324 | } | ||
| 325 | } | ||
| 326 | } | ||
| 327 | } | ||
| 296 | } | 328 | } |
| 297 | 329 | ||
| 298 | Level* | 330 | Level* |
| @@ -195,7 +195,10 @@ mfree(Monster *m) · 194 unmodified lines | |||
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | ilfree(&m->inv); | 197 | ilfree(&m->inv); |
| 198 | ilfree(&m->armor); | 198 | ifree(m->weapon); |
| 199 | ifree(m->helmet); | ||
| 200 | ifree(m->shield); | ||
| 201 | ifree(m->armor); | ||
| 199 | 202 | ||
| 200 | free(m); | 203 | free(m); |
| 201 | } | 204 | } |
| @@ -328,8 +331,10 @@ mattack(Monster *m, Monster *mt) · 126 unmodified lines | |||
| 328 | mt->flags = Mdead; | 331 | mt->flags = Mdead; |
| 329 | 332 | ||
| 330 | /* drop dead guy's stuff */ | 333 | /* drop dead guy's stuff */ |
| 331 | munwield(mt); | 334 | munwield(mt, IWEAPON); |
| 332 | mnaked(mt); | 335 | munwield(mt, IHELMET); |
| 336 | munwield(mt, ISHIELD); | ||
| 337 | munwield(mt, IARMOR); | ||
| 333 | while(mt->inv.count > 0){ | 338 | while(mt->inv.count > 0){ |
| 334 | i = iltakenth(&mt->inv, 0); | 339 | i = iltakenth(&mt->inv, 0); |
| 335 | t = tileat(mt->l, mt->pt); | 340 | t = tileat(mt->l, mt->pt); |
| @@ -464,74 +469,89 @@ maction(Monster *m, int what, Point where) · 128 unmodified lines | |||
| 464 | return -1; | 469 | return -1; |
| 465 | } | 470 | } |
| 466 | 471 | ||
| 467 | /* wield n'th item in inventory. */ | 472 | /* wield/wear n'th item in inventory. */ |
| 468 | int | 473 | int |
| 469 | mwield(Monster *m, int n) | 474 | mwield(Monster *m, int n) |
| 470 | { | 475 | { |
| 471 | Item *i; | 476 | Item **ptr, *old, *new; |
| 472 | |||
| 473 | i = nil; | ||
| 474 | 477 | ||
| 475 | if(m->weapon != nil) | 478 | old = nil; |
| 476 | i = m->weapon; | 479 | new = iltakenth(&m->inv, n); |
| 480 | if(new == nil) | ||
| 481 | return 0; | ||
| 477 | 482 | ||
| 478 | m->weapon = iltakenth(&m->inv, n); | 483 | switch(new->id->type){ |
| 479 | if(m->weapon == nil){ | 484 | case IWEAPON: |
| 480 | m->weapon = i; | 485 | ptr = &m->weapon; |
| 486 | break; | ||
| 487 | case IHELMET: | ||
| 488 | ptr = &m->helmet; | ||
| 489 | break; | ||
| 490 | case ISHIELD: | ||
| 491 | ptr = &m->shield; | ||
| 492 | break; | ||
| 493 | case IARMOR: | ||
| 494 | ptr = &m->armor; | ||
| 495 | break; | ||
| 496 | default: | ||
| 497 | iladd(&m->inv, new); | ||
| 481 | return 0; | 498 | return 0; |
| 482 | } | 499 | } |
| 483 | 500 | ||
| 484 | if(i != nil) | 501 | if(*ptr != nil) |
| 485 | iladd(&m->inv, i); | 502 | old = *ptr; |
| 486 | 503 | ||
| 487 | return 1; | 504 | *ptr = new; |
| 488 | } | ||
| 489 | 505 | ||
| 490 | int | 506 | if(old != nil){ |
| 491 | munwield(Monster *m) | 507 | m->ac += old->id->ac; |
| 492 | { | 508 | maddinv(m, old); |
| 493 | if(m->weapon == nil) | 509 | } |
| 494 | return 0; | 510 | |
| 511 | /* account for ac */ | ||
| 512 | m->ac -= new->id->ac; | ||
| 495 | 513 | ||
| 496 | maddinv(m, m->weapon); | ||
| 497 | m->weapon = nil; | ||
| 498 | return 1; | 514 | return 1; |
| 499 | } | 515 | } |
| 500 | 516 | ||
| 501 | /* put n'th inventory item on */ | ||
| 502 | int | 517 | int |
| 503 | mwear(Monster *m, int n) | 518 | munwield(Monster *m, int type) |
| 504 | { | 519 | { |
| 505 | Item *i; | 520 | Item **ptr; |
| 506 | 521 | ||
| 507 | i = iltakenth(&m->inv, n); | 522 | switch(type){ |
| 508 | if(i == nil){ | 523 | case IWEAPON: |
| 524 | ptr = &m->weapon; | ||
| 525 | break; | ||
| 526 | case IHELMET: | ||
| 527 | ptr = &m->helmet; | ||
| 528 | break; | ||
| 529 | case ISHIELD: | ||
| 530 | ptr = &m->shield; | ||
| 531 | break; | ||
| 532 | case IARMOR: | ||
| 533 | ptr = &m->armor; | ||
| 534 | break; | ||
| 535 | default: | ||
| 509 | return 0; | 536 | return 0; |
| 510 | } | 537 | } |
| 511 | 538 | ||
| 512 | iladd(&m->armor, i); | 539 | if(*ptr == nil) |
| 540 | return 0; | ||
| 513 | 541 | ||
| 514 | m->ac -= i->id->ac; | 542 | m->ac += (*ptr)->id->ac; |
| 543 | maddinv(m, *ptr); | ||
| 544 | *ptr = nil; | ||
| 515 | return 1; | 545 | return 1; |
| 516 | } | 546 | } |
| 517 | 547 | ||
| 518 | /* take off all armor */ | ||
| 519 | void | ||
| 520 | mnaked(Monster *m) | ||
| 521 | { | ||
| 522 | Item *i; | ||
| 523 | |||
| 524 | while((i = iltakenth(&m->armor, 0)) != nil){ | ||
| 525 | m->ac += i->id->ac; | ||
| 526 | iladd(&m->inv, i); | ||
| 527 | } | ||
| 528 | } | ||
| 529 | |||
| 530 | void | 548 | void |
| 531 | maddinv(Monster *m, Item *i) | 549 | maddinv(Monster *m, Item *i) |
| 532 | { | 550 | { |
| 533 | Item *it; | 551 | Item *it; |
| 534 | 552 | ||
| 553 | i->age = 0; | ||
| 554 | |||
| 535 | /* dedup item */ | 555 | /* dedup item */ |
| 536 | if(i->id->flags & IFSTACKS){ | 556 | if(i->id->flags & IFSTACKS){ |
| 537 | for(it = m->inv.head; it != nil; it = it->next){ | 557 | for(it = m->inv.head; it != nil; it = it->next){ |
| @@ -454,6 +454,38 @@ inventorymenu(int idx, char *s, int sz) · 453 unmodified lines | |||
| 454 | return idx+'a'; | 454 | return idx+'a'; |
| 455 | } | 455 | } |
| 456 | 456 | ||
| 457 | static Rune | ||
| 458 | equipmenu(int idx, char *s, int sz) | ||
| 459 | { | ||
| 460 | switch(idx){ | ||
| 461 | case 0: | ||
| 462 | if(player->weapon != nil){ | ||
| 463 | snprint(s, sz, "weapon: %i", player->weapon); | ||
| 464 | return 'w'; | ||
| 465 | } | ||
| 466 | return 0; | ||
| 467 | case 1: | ||
| 468 | if(player->helmet != nil){ | ||
| 469 | snprint(s, sz, "helmet: %i", player->helmet); | ||
| 470 | return 'h'; | ||
| 471 | } | ||
| 472 | return 0; | ||
| 473 | case 2: | ||
| 474 | if(player->shield != nil){ | ||
| 475 | snprint(s, sz, "shield: %i", player->shield); | ||
| 476 | return 's'; | ||
| 477 | } | ||
| 478 | return 0; | ||
| 479 | case 3: | ||
| 480 | if(player->armor!= nil){ | ||
| 481 | snprint(s, sz, "armor: %i", player->armor); | ||
| 482 | return 'a'; | ||
| 483 | } | ||
| 484 | return 0; | ||
| 485 | } | ||
| 486 | return Runemax; | ||
| 487 | } | ||
| 488 | |||
| 457 | static Rune | 489 | static Rune |
| 458 | dirmenu(int idx, char *s, int /*sz*/) | 490 | dirmenu(int idx, char *s, int /*sz*/) |
| 459 | { | 491 | { |
| @@ -584,23 +616,17 @@ uiexec(AIState *ai) · 124 unmodified lines | |||
| 584 | item = ilnth(&player->inv, i); | 616 | item = ilnth(&player->inv, i); |
| 585 | switch(item->id->type){ | 617 | switch(item->id->type){ |
| 586 | case IWEAPON: | 618 | case IWEAPON: |
| 587 | if(!mwield(player, i)) | 619 | case IHELMET: |
| 588 | warn("can't equip that"); | 620 | case ISHIELD: |
| 589 | else { | ||
| 590 | item = player->weapon; | ||
| 591 | good("you are now wielding the %i!", item); | ||
| 592 | } | ||
| 593 | break; | ||
| 594 | case IARMOR: | 621 | case IARMOR: |
| 595 | if(!mwear(player, i)) | 622 | if(!mwield(player, i)) |
| 596 | warn("can't equip that"); | 623 | warn("can't equip that"); |
| 597 | else { | 624 | else |
| 598 | item = player->armor.head; | 625 | good("you are now %sing the %i!", item->id->type==IWEAPON?"wield":"wear", item); |
| 599 | good("you are now wearing the %i!", item); | ||
| 600 | } | ||
| 601 | break; | 626 | break; |
| 602 | default: | 627 | default: |
| 603 | bad("you aren't sure what to do with the %i...", item); | 628 | bad("you aren't sure what to do with the %i...", item); |
| 629 | break; | ||
| 604 | } | 630 | } |
| 605 | } | 631 | } |
| 606 | redraw(&ui, 0, 0); | 632 | redraw(&ui, 0, 0); |
| @@ -622,17 +648,15 @@ uiexec(AIState *ai) · 15 unmodified lines | |||
| 622 | } | 648 | } |
| 623 | redraw(&ui, 0, 0); | 649 | redraw(&ui, 0, 0); |
| 624 | break; | 650 | break; |
| 625 | case 'W': | ||
| 626 | /* take off weapon */ | ||
| 627 | if(player->weapon != nil){ | ||
| 628 | bad("you stop wielding the %i.", player->weapon); | ||
| 629 | munwield(player); | ||
| 630 | } | ||
| 631 | break; | ||
| 632 | case 'A': | 651 | case 'A': |
| 633 | /* take off armor */ | 652 | /* take off armor */ |
| 634 | bad("you take off all your armor."); | 653 | km = (KeyMenu){"take off what?", equipmenu}; |
| 635 | mnaked(player); | 654 | i = menu(ui.kc, ui.mc, &km); |
| 655 | if(i >= 0 && i <= 3){ | ||
| 656 | munwield(player, i); | ||
| 657 | item = ilnth(&player->inv, 0); | ||
| 658 | bad("you take off the %i.", item); | ||
| 659 | } | ||
| 636 | break; | 660 | break; |
| 637 | case 'h': | 661 | case 'h': |
| 638 | case Kleft: | 662 | case Kleft: |