Unified · Split
| @@ -54,8 +54,12 @@ enum · 53 unmodified lines | ||
| 54 | 54 | /* possible item types */ |
| 55 | 55 | IWEAPON = 0, |
| 56 | 56 | IHELMET, |
| 57 | + ICLOAK, | |
| 57 | 58 | ISHIELD, |
| 58 | 59 | IARMOR, |
| 60 | + IGLOVES, | |
| 61 | + IBOOTS, | |
| 62 | + NEQUIP, | |
| 59 | 63 | |
| 60 | 64 | /* item flags */ |
| 61 | 65 | IFSTACKS = 0x1, |
| @@ -119,6 +123,7 @@ struct ItemList · 57 unmodified lines | ||
| 119 | 123 | |
| 120 | 124 | /* item.c */ |
| 121 | 125 | #pragma varargck type "i" Item* |
| 126 | +char *itypetoname(int type); | |
| 122 | 127 | int itemdbopen(char *file); |
| 123 | 128 | ItemData *idbyname(char *item); |
| 124 | 129 | Item *ibyname(char *item); |
| @@ -240,10 +245,7 @@ struct Monster · 115 unmodified lines | ||
| 240 | 245 | ItemList inv; |
| 241 | 246 | |
| 242 | 247 | /* equipped weapon & armor */ |
| 243 | − Item *weapon; | |
| 244 | − Item *helmet; | |
| 245 | − Item *shield; | |
| 246 | − Item *armor; | |
| 248 | + Item *armor[NEQUIP]; | |
| 247 | 249 | |
| 248 | 250 | /* no free */ |
| 249 | 251 | MonsterData *md; |
| @@ -33,10 +33,21 @@ static char *itemdbcmd[] = { · 32 unmodified lines | ||
| 33 | 33 | static char *itemtype[] = { |
| 34 | 34 | [IWEAPON] "weapon", |
| 35 | 35 | [IHELMET] "helmet", |
| 36 | +[ICLOAK] "cloak", | |
| 36 | 37 | [ISHIELD] "shield", |
| 37 | 38 | [IARMOR] "armor", |
| 39 | +[IGLOVES] "gloves", | |
| 40 | +[IBOOTS] "boots", | |
| 38 | 41 | }; |
| 39 | 42 | |
| 43 | +char* | |
| 44 | +itypetoname(int type) | |
| 45 | +{ | |
| 46 | + if(type < 0 || type > nelem(itemtype)-1) | |
| 47 | + return nil; | |
| 48 | + return itemtype[type]; | |
| 49 | +} | |
| 50 | + | |
| 40 | 51 | static Ndb *itemdb; |
| 41 | 52 | |
| 42 | 53 | static int |
| @@ -58,8 +69,11 @@ ifmt(Fmt *f) · 15 unmodified lines | ||
| 58 | 69 | snprint(extra, sizeof(extra), " (%dd%d)", i->id->rolls, i->id->atk); |
| 59 | 70 | break; |
| 60 | 71 | case IHELMET: |
| 72 | + case ICLOAK: | |
| 61 | 73 | case ISHIELD: |
| 62 | 74 | case IARMOR: |
| 75 | + case IGLOVES: | |
| 76 | + case IBOOTS: | |
| 63 | 77 | snprint(extra, sizeof(extra), " (ac %d)", i->id->ac); |
| 64 | 78 | break; |
| 65 | 79 | } |
| @@ -150,7 +164,7 @@ idbylistname(char *list) · 84 unmodified lines | ||
| 150 | 164 | |
| 151 | 165 | t = ndbsearch(itemdb, &search, "itemlist", list); |
| 152 | 166 | if(t == nil) |
| 153 | − sysfatal("no such item list '%s'", list); | |
| 167 | + sysfatal("no such itemlist '%s'", list); | |
| 154 | 168 | |
| 155 | 169 | /* count items */ |
| 156 | 170 | cnt = 0; |
| @@ -160,7 +174,7 @@ idbylistname(char *list) · 3 unmodified lines | ||
| 160 | 174 | } |
| 161 | 175 | |
| 162 | 176 | if(cnt == 0) |
| 163 | − sysfatal("no items in list '%s'", list); | |
| 177 | + sysfatal("no items in itemlist '%s'", list); | |
| 164 | 178 | |
| 165 | 179 | /* pick random item */ |
| 166 | 180 | pick = nrand(cnt); |
| @@ -168,9 +182,8 @@ idbylistname(char *list) · 1 unmodified line | ||
| 168 | 182 | /* walk this many forward */ |
| 169 | 183 | i = 0; |
| 170 | 184 | for(nt = t; nt != nil; nt = nt->entry){ |
| 171 | − if(i == pick) | |
| 185 | + if(strcmp(nt->attr, "items") == 0 && i++ == pick) | |
| 172 | 186 | return idbyname(nt->val); |
| 173 | − i++; | |
| 174 | 187 | } |
| 175 | 188 | return nil; |
| 176 | 189 | } |
| @@ -11,16 +11,25 @@ item="runesword" · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | # armor |
| 13 | 13 | item="helmet" |
| 14 | − tile=472 type=helmet cost=5 weight=2 ac=2 | |
| 14 | + tile=472 type=helmet cost=5 weight=2 ac=1 | |
| 15 | +item="tattered cape" | |
| 16 | + tile=521 type=cloak cost=5 weight=2 ac=1 | |
| 15 | 17 | item="shield" |
| 16 | − tile=525 type=shield cost=5 weight=10 ac=2 | |
| 18 | + tile=525 type=shield cost=5 weight=10 ac=1 | |
| 17 | 19 | item="plate armor" |
| 18 | 20 | tile=496 type=armor cost=50 weight=15 ac=4 |
| 21 | +item="old gloves" | |
| 22 | + tile=532 type=gloves cost=5 weight=1 ac=1 | |
| 23 | +item="walking shoes" | |
| 24 | + tile=536 type=boots cost=5 weight=1 ac=1 | |
| 19 | 25 | |
| 20 | 26 | # item lists |
| 21 | 27 | itemlist="common" |
| 22 | 28 | items="dagger" |
| 23 | 29 | items="helmet" |
| 30 | + items="tattered cape" | |
| 31 | + items="old gloves" | |
| 32 | + items="walking shoes" | |
| 24 | 33 | itemlist="uncommon" |
| 25 | 34 | items="longsword" |
| 26 | 35 | items="shield" |
| @@ -434,16 +434,16 @@ mklgraveyard(Level *l) · 433 unmodified lines | ||
| 434 | 434 | |
| 435 | 435 | addspawn(l, p, "lich", 101, 1); |
| 436 | 436 | addspawn(l, p, "demilich", 157, 0); |
| 437 | − addspawn(l, p, "ghost", 39, 2); | |
| 438 | − addspawn(l, p, "human zombie", 43, 2); | |
| 439 | − addspawn(l, p, "skeleton", 127, 1); | |
| 437 | + addspawn(l, p, "ghost", 15, 2); | |
| 438 | + addspawn(l, p, "human zombie", 27, 2); | |
| 439 | + addspawn(l, p, "skeleton", 71, 1); | |
| 440 | 440 | |
| 441 | 441 | several(l, &p2, 1, "gnome king", 0); |
| 442 | 442 | several(l, &p2, 1, "gnome wizard", 1); |
| 443 | − addspawn(l, p2, "gnome", 23, 1); | |
| 444 | − addspawn(l, p2, "gnome lord", 25, 2); | |
| 445 | − addspawn(l, p2, "gnome wizard", 37, 2); | |
| 446 | − addspawn(l, p2, "gnome king", 53, 1); | |
| 443 | + addspawn(l, p2, "gnome", 29, 1); | |
| 444 | + addspawn(l, p2, "gnome lord", 45, 2); | |
| 445 | + addspawn(l, p2, "gnome wizard", 57, 2); | |
| 446 | + addspawn(l, p2, "gnome king", 71, 1); | |
| 447 | 447 | |
| 448 | 448 | genmonsters(l, "ghost", space/64); |
| 449 | 449 | genmonsters(l, "gnome", space/64); |
| @@ -204,6 +204,7 @@ missing: · 203 unmodified lines | ||
| 204 | 204 | void |
| 205 | 205 | mfree(Monster *m) |
| 206 | 206 | { |
| 207 | + int n; | |
| 207 | 208 | AIState *a; |
| 208 | 209 | |
| 209 | 210 | if(decref(&m->ref) != 0) |
| @@ -219,11 +220,13 @@ mfree(Monster *m) · 9 unmodified lines | ||
| 219 | 220 | freestate(a); |
| 220 | 221 | } |
| 221 | 222 | |
| 223 | + for(n = 0; n < NEQUIP; n++){ | |
| 224 | + if(m->armor[n] != nil){ | |
| 225 | + munwield(m, n); | |
| 226 | + } | |
| 227 | + } | |
| 228 | + | |
| 222 | 229 | ilfree(&m->inv); |
| 223 | − ifree(m->weapon); | |
| 224 | − ifree(m->helmet); | |
| 225 | − ifree(m->shield); | |
| 226 | − ifree(m->armor); | |
| 227 | 230 | |
| 228 | 231 | free(m); |
| 229 | 232 | } |
| @@ -249,12 +252,8 @@ mupdate(Monster *m) · 19 unmodified lines | ||
| 249 | 252 | |
| 250 | 253 | /* gain some hp if you aren't dead. */ |
| 251 | 254 | if((m->flags & Mdead) == 0) |
| 252 | − if(m->hp < m->maxhp){ | |
| 253 | − /* below half, 2%. above, 0.5%. */ | |
| 254 | − if(m->hp < m->maxhp/2) | |
| 255 | − m->hp += 1.0 + (double)m->maxhp/50.0; | |
| 256 | − else | |
| 257 | − m->hp += (double)m->maxhp/200.0; | |
| 255 | + if(m->hp < m->maxhp && m->turns % (42+(m->xpl+2)+1) == 0){ | |
| 256 | + m->hp+=1.0; | |
| 258 | 257 | if(m->hp > m->maxhp) |
| 259 | 258 | m->hp = m->maxhp; |
| 260 | 259 | } |
| @@ -314,12 +313,14 @@ maddxp(Monster *m, int xp) · 53 unmodified lines | ||
| 314 | 313 | static int |
| 315 | 314 | mattack(Monster *m, Monster *mt) |
| 316 | 315 | { |
| 317 | − int hit, crit, dmg, xp; | |
| 316 | + int n, hit, ac, crit, dmg, xp; | |
| 318 | 317 | Item *i, *weap; |
| 319 | 318 | Tile *t; |
| 320 | 319 | |
| 321 | − hit = roll(1, 100); | |
| 322 | − if(hit < 10+abs(mt->ac-10)*2){ | |
| 320 | + hit = roll(1, 20); | |
| 321 | + ac = mt->ac >= 0 ? mt->ac : -(1+nrand(mt->ac)); | |
| 322 | + | |
| 323 | + if(hit > 10 + ac + m->xpl){ | |
| 323 | 324 | if(nearyou(m->pt)) |
| 324 | 325 | warn("the %s misses the %s!", m->md->name, mt->md->name); |
| 325 | 326 | return 0; |
| @@ -328,7 +329,7 @@ mattack(Monster *m, Monster *mt) · 2 unmodified lines | ||
| 328 | 329 | dmg = roll(m->md->rolls, m->md->atk); |
| 329 | 330 | |
| 330 | 331 | /* factor in weapon damage */ |
| 331 | − weap = m->weapon; | |
| 332 | + weap = m->armor[IWEAPON]; | |
| 332 | 333 | if(weap != nil) |
| 333 | 334 | dmg += roll(weap->id->rolls, weap->id->atk); |
| 334 | 335 | |
| @@ -355,11 +356,14 @@ mattack(Monster *m, Monster *mt) · 20 unmodified lines | ||
| 355 | 356 | mt->hp = 0; |
| 356 | 357 | mt->flags = Mdead; |
| 357 | 358 | |
| 359 | + /* take off all armor */ | |
| 360 | + for(n = 0; n < NEQUIP; n++){ | |
| 361 | + if(mt->armor[n] != nil){ | |
| 362 | + munwield(mt, n); | |
| 363 | + } | |
| 364 | + } | |
| 365 | + | |
| 358 | 366 | /* drop dead guy's stuff */ |
| 359 | − munwield(mt, IWEAPON); | |
| 360 | − munwield(mt, IHELMET); | |
| 361 | − munwield(mt, ISHIELD); | |
| 362 | − munwield(mt, IARMOR); | |
| 363 | 367 | while(mt->inv.count > 0){ |
| 364 | 368 | i = iltakenth(&mt->inv, 0); |
| 365 | 369 | t = tileat(mt->l, mt->pt); |
| @@ -367,7 +371,7 @@ mattack(Monster *m, Monster *mt) · 1 unmodified line | ||
| 367 | 371 | iladd(&t->items, i); |
| 368 | 372 | } |
| 369 | 373 | |
| 370 | − xp = 10+10*pow(mt->xpl, 1.75); | |
| 374 | + xp = 10 + pow(mt->xpl, 2.0); | |
| 371 | 375 | if(nearyou(m->pt)) |
| 372 | 376 | bad("the %s kills the %s, and gains %ld xp.", m->md->name, mt->md->name, xp); |
| 373 | 377 | |
| @@ -393,6 +397,7 @@ mattack(Monster *m, Monster *mt) · 19 unmodified lines | ||
| 393 | 397 | int |
| 394 | 398 | maction(Monster *m, int what, Point where) |
| 395 | 399 | { |
| 400 | + int n; | |
| 396 | 401 | Tile *cur, *targ; |
| 397 | 402 | Item *i; |
| 398 | 403 | |
| @@ -431,8 +436,9 @@ maction(Monster *m, int what, Point where) · 32 unmodified lines | ||
| 431 | 436 | m->pt = where; |
| 432 | 437 | |
| 433 | 438 | if(isyou(m) && hasflagat(m->l, where, Fhasitem)){ |
| 434 | − i = ilnth(&targ->items, 0); | |
| 435 | − warn("you see %i here.", i); | |
| 439 | + n = 0; | |
| 440 | + while((i = ilnth(&targ->items, n++)) != nil) | |
| 441 | + warn("you see %i here.", i); | |
| 436 | 442 | } |
| 437 | 443 | |
| 438 | 444 | if(isyou(m) && hasflagat(m->l, where, Fportal)){ |
| @@ -498,30 +504,21 @@ maction(Monster *m, int what, Point where) · 59 unmodified lines | ||
| 498 | 504 | int |
| 499 | 505 | mwield(Monster *m, int n) |
| 500 | 506 | { |
| 507 | + int type; | |
| 501 | 508 | Item **ptr, *old, *new; |
| 502 | 509 | |
| 503 | 510 | old = nil; |
| 504 | − new = iltakenth(&m->inv, n); | |
| 511 | + new = ilnth(&m->inv, n); | |
| 505 | 512 | if(new == nil) |
| 506 | 513 | return 0; |
| 507 | 514 | |
| 508 | − switch(new->id->type){ | |
| 509 | − case IWEAPON: | |
| 510 | − ptr = &m->weapon; | |
| 511 | − break; | |
| 512 | − case IHELMET: | |
| 513 | − ptr = &m->helmet; | |
| 514 | − break; | |
| 515 | − case ISHIELD: | |
| 516 | − ptr = &m->shield; | |
| 517 | − break; | |
| 518 | − case IARMOR: | |
| 519 | − ptr = &m->armor; | |
| 520 | − break; | |
| 521 | − default: | |
| 522 | − iladd(&m->inv, new); | |
| 515 | + type = new->id->type; | |
| 516 | + if(type < IWEAPON || type >= NEQUIP) | |
| 523 | 517 | return 0; |
| 524 | − } | |
| 518 | + | |
| 519 | + new = iltakenth(&m->inv, n); | |
| 520 | + type = new->id->type; | |
| 521 | + ptr = &m->armor[type]; | |
| 525 | 522 | |
| 526 | 523 | if(*ptr != nil) |
| 527 | 524 | old = *ptr; |
| @@ -544,22 +541,9 @@ munwield(Monster *m, int type) · 16 unmodified lines | ||
| 544 | 541 | { |
| 545 | 542 | Item **ptr; |
| 546 | 543 | |
| 547 | − switch(type){ | |
| 548 | − case IWEAPON: | |
| 549 | − ptr = &m->weapon; | |
| 550 | − break; | |
| 551 | − case IHELMET: | |
| 552 | − ptr = &m->helmet; | |
| 553 | − break; | |
| 554 | − case ISHIELD: | |
| 555 | − ptr = &m->shield; | |
| 556 | − break; | |
| 557 | − case IARMOR: | |
| 558 | − ptr = &m->armor; | |
| 559 | − break; | |
| 560 | − default: | |
| 561 | − return 0; | |
| 562 | − } | |
| 544 | + assert(type >= IWEAPON && type < NEQUIP); | |
| 545 | + | |
| 546 | + ptr = &m->armor[type]; | |
| 563 | 547 | |
| 564 | 548 | if(*ptr == nil) |
| 565 | 549 | return 0; |
| @@ -18,7 +18,7 @@ monster="gnome wizard" · 17 unmodified lines | ||
| 18 | 18 | monster="gnome king" |
| 19 | 19 | tile=169 xpl=5 align=50 mvr=10 hp=48 ac=10 atk=2d6 |
| 20 | 20 | equip="uncommon" eqprob=0.2 |
| 21 | − equip="rare" eqprob=0.5 | |
| 21 | + equip="rare" eqprob=0.01 | |
| 22 | 22 | |
| 23 | 23 | # undead |
| 24 | 24 | monster="lich" |
| @@ -34,8 +34,10 @@ monster="human zombie" · 9 unmodified lines | ||
| 34 | 34 | monster="skeleton" |
| 35 | 35 | tile=250 xpl=12 align=-50 mvr=8 hp=48 ac=4 atk=2d6 |
| 36 | 36 | equip="uncommon" eqprob=0.05 |
| 37 | + equip="rare" eqprob=0.01 | |
| 37 | 38 | monster="ghost" |
| 38 | − tile=290 xpl=1 align=-50 mvr=6 hp=16 ac=-5 atk=1d4 | |
| 39 | + tile=290 xpl=10 align=-50 mvr=3 hp=16 ac=-5 atk=1d4 | |
| 40 | + equip="tattered cape" eqprob=0.05 | |
| 39 | 41 | |
| 40 | 42 | # military |
| 41 | 43 | monster="soldier" |
| @@ -51,11 +53,16 @@ monster="lieutenant" · 9 unmodified lines | ||
| 51 | 53 | equip="uncommon" eqprob=0.05 |
| 52 | 54 | monster="captain" |
| 53 | 55 | tile=283 xpl=12 align=-20 mvr=10 hp=48 ac=10 atk=4d4 |
| 54 | − equip="common" eqprob=0.1 | |
| 55 | − equip="uncommon" eqprob=0.05 | |
| 56 | − equip="rare" eqprob=0.01 | |
| 56 | + equip="longsword" | |
| 57 | + equip="runesword" eqprob=0.1 | |
| 58 | + equip="helmet" | |
| 59 | + equip="tattered cape" | |
| 60 | + equip="shield" | |
| 61 | + equip="plate armor" | |
| 62 | + equip="old gloves" | |
| 63 | + equip="walking shoes" | |
| 57 | 64 | |
| 58 | 65 | # player |
| 59 | 66 | monster="wizard" |
| 60 | − tile=349 xpl=0 align=127 mvr=14 hp=64 ac=5 atk=2d3 | |
| 67 | + tile=349 xpl=1 align=127 mvr=14 hp=64 ac=5 atk=2d3 | |
| 61 | 68 | |
| @@ -458,33 +458,20 @@ inventorymenu(int idx, char *s, int sz) · 457 unmodified lines | ||
| 458 | 458 | static Rune |
| 459 | 459 | equipmenu(int idx, char *s, int sz) |
| 460 | 460 | { |
| 461 | − switch(idx){ | |
| 462 | − case 0: | |
| 463 | − if(player->weapon != nil){ | |
| 464 | − snprint(s, sz, "weapon: %i", player->weapon); | |
| 465 | − return 'w'; | |
| 466 | − } | |
| 467 | − return 0; | |
| 468 | − case 1: | |
| 469 | − if(player->helmet != nil){ | |
| 470 | − snprint(s, sz, "helmet: %i", player->helmet); | |
| 471 | − return 'h'; | |
| 472 | − } | |
| 473 | − return 0; | |
| 474 | − case 2: | |
| 475 | − if(player->shield != nil){ | |
| 476 | − snprint(s, sz, "shield: %i", player->shield); | |
| 477 | − return 's'; | |
| 478 | − } | |
| 479 | − return 0; | |
| 480 | − case 3: | |
| 481 | − if(player->armor!= nil){ | |
| 482 | − snprint(s, sz, "armor: %i", player->armor); | |
| 483 | − return 'a'; | |
| 484 | − } | |
| 485 | − return 0; | |
| 461 | + Item *ptr; | |
| 462 | + Rune key[NEQUIP] = { 'w', 'c', 'h', 's', 'a', 'g', 'b' }; | |
| 463 | + | |
| 464 | + if(idx >= NEQUIP) | |
| 465 | + return Runemax; | |
| 466 | + | |
| 467 | + ptr = player->armor[idx]; | |
| 468 | + | |
| 469 | + if(ptr != nil){ | |
| 470 | + snprint(s, sz, "%s: %i", itypetoname(ptr->id->type), ptr); | |
| 471 | + return key[idx]; | |
| 486 | 472 | } |
| 487 | − return Runemax; | |
| 473 | + | |
| 474 | + return 0; | |
| 488 | 475 | } |
| 489 | 476 | |
| 490 | 477 | static Rune |
| @@ -597,8 +584,11 @@ cuse(Rune c) · 106 unmodified lines | ||
| 597 | 584 | switch(item->id->type){ |
| 598 | 585 | case IWEAPON: |
| 599 | 586 | case IHELMET: |
| 587 | + case ICLOAK: | |
| 600 | 588 | case ISHIELD: |
| 601 | 589 | case IARMOR: |
| 590 | + case IGLOVES: | |
| 591 | + case IBOOTS: | |
| 602 | 592 | if(!mwield(player, i)){ |
| 603 | 593 | bad("can't equip that"); |
| 604 | 594 | return 0; |
| @@ -650,7 +640,7 @@ cstrip(Rune c) · 45 unmodified lines | ||
| 650 | 640 | /* take off armor */ |
| 651 | 641 | km = (KeyMenu){"take off what?", equipmenu}; |
| 652 | 642 | i = menu(ui.kc, ui.mc, &km); |
| 653 | − if(i >= 0 && i <= 3){ | |
| 643 | + if(i >= 0 && i < NEQUIP){ | |
| 654 | 644 | munwield(player, i); |
| 655 | 645 | item = ilnth(&player->inv, 0); |
| 656 | 646 | warn("you take off the %i.", item); |