ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/living.C
(Generate patch)

Comparing deliantra/server/common/living.C (file contents):
Revision 1.2 by root, Sat Aug 26 23:36:28 2006 UTC vs.
Revision 1.3 by root, Tue Aug 29 08:01:35 2006 UTC

1/* 1/*
2 * static char *rcsid_living_c = 2 * static char *rcsid_living_c =
3 * "$Id: living.C,v 1.2 2006/08/26 23:36:28 root Exp $"; 3 * "$Id: living.C,v 1.3 2006/08/29 08:01:35 root Exp $";
4 */ 4 */
5 5
6/* 6/*
7 CrossFire, A Multiplayer game for X-windows 7 CrossFire, A Multiplayer game for X-windows
8 8
213 "You feel your charisma return.", 213 "You feel your charisma return.",
214 "You feel your memory return.", 214 "You feel your memory return.",
215 "You feel your spirits return." 215 "You feel your spirits return."
216}; 216};
217const char *const gain_msg[NUM_STATS] = { 217const char *const gain_msg[NUM_STATS] = {
218 "You feel stronger.", 218 "You feel stronger.",
219 "You feel more agile.", 219 "You feel more agile.",
220 "You feel healthy.", 220 "You feel healthy.",
221 "You feel wiser.", 221 "You feel wiser.",
222 "You seem to look better.", 222 "You seem to look better.",
223 "You feel smarter.", 223 "You feel smarter.",
224 "You feel more potent." 224 "You feel more potent."
225}; 225};
226const char *const lose_msg[NUM_STATS] = { 226const char *const lose_msg[NUM_STATS] = {
227 "You feel weaker!", 227 "You feel weaker!",
228 "You feel clumsy!", 228 "You feel clumsy!",
229 "You feel less healthy!", 229 "You feel less healthy!",
230 "You lose some of your memory!", 230 "You lose some of your memory!",
231 "You look ugly!", 231 "You look ugly!",
232 "You feel stupid!", 232 "You feel stupid!",
233 "You feel less potent!" 233 "You feel less potent!"
234}; 234};
235 235
236const char *const statname[NUM_STATS] = { 236const char *const statname[NUM_STATS] = {
237 "strength", "dexterity", "constitution", "wisdom", "charisma", "intelligence","power" 237 "strength", "dexterity", "constitution", "wisdom", "charisma", "intelligence","power"
238}; 238};
302 break; 302 break;
303 case INT: 303 case INT:
304 stats->Int+=value; 304 stats->Int+=value;
305 break; 305 break;
306 default: 306 default:
307 LOG(llevError,"Invalid attribute in change_attr_value: %d\n", attr); 307 LOG(llevError,"Invalid attribute in change_attr_value: %d\n", attr);
308 } 308 }
309} 309}
310 310
311/* 311/*
312 * returns the specified stat. See also set_attr_value(). 312 * returns the specified stat. See also set_attr_value().
379 * found by fix_player. refop is not a real object 379 * found by fix_player. refop is not a real object
380 */ 380 */
381 memcpy(&refop, op, sizeof(object)); 381 memcpy(&refop, op, sizeof(object));
382 382
383 if(op->type==PLAYER) { 383 if(op->type==PLAYER) {
384 if (tmp->type==POTION) { 384 if (tmp->type==POTION) {
385 potion_max=1; 385 potion_max=1;
386 for(j=0;j<NUM_STATS;j++) { 386 for(j=0;j<NUM_STATS;j++) {
387 int nstat, ostat; 387 int nstat, ostat;
388 388
389 ostat = get_attr_value(&(op->contr->orig_stats),j); 389 ostat = get_attr_value(&(op->contr->orig_stats),j);
390 i = get_attr_value(&(tmp->stats),j); 390 i = get_attr_value(&(tmp->stats),j);
391 391
392 /* nstat is what the stat will be after use of the potion */ 392 /* nstat is what the stat will be after use of the potion */
393 nstat = flag*i + ostat; 393 nstat = flag*i + ostat;
394 394
395 /* Do some bounds checking. While I don't think any 395 /* Do some bounds checking. While I don't think any
396 * potions do so right now, there is the potential for potions 396 * potions do so right now, there is the potential for potions
397 * that adjust that stat by more than one point, so we need 397 * that adjust that stat by more than one point, so we need
398 * to allow for that. 398 * to allow for that.
399 */ 399 */
400 if (nstat < 1 && i*flag < 0 ) nstat = 1; 400 if (nstat < 1 && i*flag < 0 ) nstat = 1;
401 else if (nstat > 20 + get_attr_value(&(op->arch->clone.stats),j)) { 401 else if (nstat > 20 + get_attr_value(&(op->arch->clone.stats),j)) {
402 nstat = 20 + get_attr_value(&(op->arch->clone.stats),j); 402 nstat = 20 + get_attr_value(&(op->arch->clone.stats),j);
403 } 403 }
404 if (nstat != ostat) { 404 if (nstat != ostat) {
405 set_attr_value(&(op->contr->orig_stats), j, nstat); 405 set_attr_value(&(op->contr->orig_stats), j, nstat);
406 potion_max=0; 406 potion_max=0;
407 } 407 }
408 else if (i) { 408 else if (i) {
409 /* potion is useless - player has already hit the natural maximum */ 409 /* potion is useless - player has already hit the natural maximum */
410 potion_max = 1; 410 potion_max = 1;
411 } 411 }
412 } 412 }
413 /* This section of code ups the characters normal stats also. I am not 413 /* This section of code ups the characters normal stats also. I am not
414 * sure if this is strictly necessary, being that fix_player probably 414 * sure if this is strictly necessary, being that fix_player probably
415 * recalculates this anyway. 415 * recalculates this anyway.
416 */ 416 */
417 for(j=0;j<NUM_STATS;j++) 417 for(j=0;j<NUM_STATS;j++)
418 change_attr_value(&(op->stats),j,flag*get_attr_value(&(tmp->stats),j)); 418 change_attr_value(&(op->stats),j,flag*get_attr_value(&(tmp->stats),j));
419 check_stat_bounds(&(op->stats)); 419 check_stat_bounds(&(op->stats));
420 } /* end of potion handling code */ 420 } /* end of potion handling code */
421 } 421 }
422 422
423 /* reset attributes that fix_player doesn't reset since it doesn't search 423 /* reset attributes that fix_player doesn't reset since it doesn't search
424 * everything to set 424 * everything to set
425 */ 425 */
426 if(flag == -1) { 426 if(flag == -1) {
427 op->attacktype&=~tmp->attacktype; 427 op->attacktype&=~tmp->attacktype;
428 op->path_attuned&=~tmp->path_attuned; 428 op->path_attuned&=~tmp->path_attuned;
429 op->path_repelled&=~tmp->path_repelled; 429 op->path_repelled&=~tmp->path_repelled;
430 op->path_denied&=~tmp->path_denied; 430 op->path_denied&=~tmp->path_denied;
431 /* Presuming here that creatures only have move_type, 431 /* Presuming here that creatures only have move_type,
432 * and not the other move_ fields. 432 * and not the other move_ fields.
433 */ 433 */
434 op->move_type &= ~tmp->move_type; 434 op->move_type &= ~tmp->move_type;
435 } 435 }
436 436
437 /* call fix_player since op object could have whatever attribute due 437 /* call fix_player since op object could have whatever attribute due
438 * to multiple items. if fix_player always has to be called after 438 * to multiple items. if fix_player always has to be called after
439 * change_ability then might as well call it from here 439 * change_ability then might as well call it from here
442 442
443 /* Fix player won't add the bows ability to the player, so don't 443 /* Fix player won't add the bows ability to the player, so don't
444 * print out message if this is a bow. 444 * print out message if this is a bow.
445 */ 445 */
446 if(tmp->attacktype & AT_CONFUSION && tmp->type != BOW) { 446 if(tmp->attacktype & AT_CONFUSION && tmp->type != BOW) {
447 success=1; 447 success=1;
448 DIFF_MSG(flag, "Your hands begin to glow red.", 448 DIFF_MSG(flag, "Your hands begin to glow red.",
449 "Your hands stop glowing red."); 449 "Your hands stop glowing red.");
450 } 450 }
451 if ( QUERY_FLAG(op,FLAG_LIFESAVE) != QUERY_FLAG(&refop,FLAG_LIFESAVE)){ 451 if ( QUERY_FLAG(op,FLAG_LIFESAVE) != QUERY_FLAG(&refop,FLAG_LIFESAVE)){
452 success=1; 452 success=1;
453 DIFF_MSG(flag, "You feel very protected.", 453 DIFF_MSG(flag, "You feel very protected.",
454 "You don't feel protected anymore."); 454 "You don't feel protected anymore.");
455 } 455 }
456 if ( QUERY_FLAG(op,FLAG_REFL_MISSILE) != QUERY_FLAG(&refop,FLAG_REFL_MISSILE)){ 456 if ( QUERY_FLAG(op,FLAG_REFL_MISSILE) != QUERY_FLAG(&refop,FLAG_REFL_MISSILE)){
457 success=1; 457 success=1;
458 DIFF_MSG(flag, "A magic force shimmers around you.", 458 DIFF_MSG(flag, "A magic force shimmers around you.",
459 "The magic force fades away."); 459 "The magic force fades away.");
460 } 460 }
461 if ( QUERY_FLAG(op,FLAG_REFL_SPELL) != QUERY_FLAG(&refop,FLAG_REFL_SPELL)){ 461 if ( QUERY_FLAG(op,FLAG_REFL_SPELL) != QUERY_FLAG(&refop,FLAG_REFL_SPELL)){
462 success=1; 462 success=1;
463 DIFF_MSG(flag, "You feel more safe now, somehow.", 463 DIFF_MSG(flag, "You feel more safe now, somehow.",
464 "Suddenly you feel less safe, somehow."); 464 "Suddenly you feel less safe, somehow.");
465 } 465 }
466 /* movement type has changed. We don't care about cases where 466 /* movement type has changed. We don't care about cases where
467 * user has multiple items giving the same type appled like we 467 * user has multiple items giving the same type appled like we
468 * used to - that is more work than what we gain, plus messages 468 * used to - that is more work than what we gain, plus messages
469 * can be misleading (a little higher could be miscontrued from 469 * can be misleading (a little higher could be miscontrued from
470 * from fly high) 470 * from fly high)
471 */ 471 */
472 if (tmp->move_type && op->move_type != refop.move_type) { 472 if (tmp->move_type && op->move_type != refop.move_type) {
473 success=1; 473 success=1;
474 474
475 /* MOVE_FLY_HIGH trumps MOVE_FLY_LOW - changing your move_fly_low 475 /* MOVE_FLY_HIGH trumps MOVE_FLY_LOW - changing your move_fly_low
476 * status doesn't make a difference if you are flying high 476 * status doesn't make a difference if you are flying high
477 */ 477 */
478 if (tmp->move_type & MOVE_FLY_LOW && !(op->move_type & MOVE_FLY_HIGH)) { 478 if (tmp->move_type & MOVE_FLY_LOW && !(op->move_type & MOVE_FLY_HIGH)) {
479 DIFF_MSG(flag, "You start to float in the air!.", "You float down to the ground."); 479 DIFF_MSG(flag, "You start to float in the air!.", "You float down to the ground.");
480 } 480 }
481 481
482 if (tmp->move_type & MOVE_FLY_HIGH) { 482 if (tmp->move_type & MOVE_FLY_HIGH) {
483 /* double conditional - second case covers if you have move_fly_low - 483 /* double conditional - second case covers if you have move_fly_low -
484 * in that case, you don't actually land 484 * in that case, you don't actually land
485 */ 485 */
486 DIFF_MSG(flag, "You soar into the air air!.", 486 DIFF_MSG(flag, "You soar into the air air!.",
487 (op->move_type&MOVE_FLY_LOW ? "You fly lower in the air": 487 (op->move_type&MOVE_FLY_LOW ? "You fly lower in the air":
488 "You float down to the ground.")); 488 "You float down to the ground."));
489 } 489 }
490 if (tmp->move_type & MOVE_SWIM) 490 if (tmp->move_type & MOVE_SWIM)
491 DIFF_MSG(flag,"You feel ready for a swim", "You no longer feel like swimming"); 491 DIFF_MSG(flag,"You feel ready for a swim", "You no longer feel like swimming");
492 492
493 /* Changing move status may mean you are affected by things you weren't before */ 493 /* Changing move status may mean you are affected by things you weren't before */
494 check_move_on(op, op); 494 check_move_on(op, op);
495 } 495 }
496 496
497 /* becoming UNDEAD... a special treatment for this flag. Only those not 497 /* becoming UNDEAD... a special treatment for this flag. Only those not
498 * originally undead may change their status 498 * originally undead may change their status
499 */ 499 */
500 if(!QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD)) 500 if(!QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD))
501 if ( QUERY_FLAG(op,FLAG_UNDEAD) != QUERY_FLAG(&refop,FLAG_UNDEAD)) { 501 if ( QUERY_FLAG(op,FLAG_UNDEAD) != QUERY_FLAG(&refop,FLAG_UNDEAD)) {
502 success=1; 502 success=1;
503 if(flag>0) { 503 if(flag>0) {
504 if(op->race) free_string(op->race); 504 if(op->race) free_string(op->race);
505 op->race=add_string("undead"); 505 op->race=add_string("undead");
506 new_draw_info(NDI_UNIQUE, 0, op,"Your lifeforce drains away!"); 506 new_draw_info(NDI_UNIQUE, 0, op,"Your lifeforce drains away!");
507 } else { 507 } else {
508 if(op->race) free_string(op->race); 508 if(op->race) free_string(op->race);
509 if(op->arch->clone.race) 509 if(op->arch->clone.race)
510 op->race=add_string(op->arch->clone.race); 510 op->race=add_string(op->arch->clone.race);
511 else 511 else
512 op->race = NULL; 512 op->race = NULL;
513 new_draw_info(NDI_UNIQUE, 0, op,"Your lifeforce returns!"); 513 new_draw_info(NDI_UNIQUE, 0, op,"Your lifeforce returns!");
514 } 514 }
515 } 515 }
516 516
517 if ( QUERY_FLAG(op,FLAG_STEALTH) != QUERY_FLAG(&refop,FLAG_STEALTH)){ 517 if ( QUERY_FLAG(op,FLAG_STEALTH) != QUERY_FLAG(&refop,FLAG_STEALTH)){
518 success=1; 518 success=1;
519 DIFF_MSG(flag, "You walk more quietly.", "You walk more noisily."); 519 DIFF_MSG(flag, "You walk more quietly.", "You walk more noisily.");
520 } 520 }
521 if ( QUERY_FLAG(op,FLAG_MAKE_INVIS) != QUERY_FLAG(&refop,FLAG_MAKE_INVIS)){ 521 if ( QUERY_FLAG(op,FLAG_MAKE_INVIS) != QUERY_FLAG(&refop,FLAG_MAKE_INVIS)){
522 success=1; 522 success=1;
523 DIFF_MSG(flag, "You become transparent.", "You can see yourself."); 523 DIFF_MSG(flag, "You become transparent.", "You can see yourself.");
524 } 524 }
525 /* blinded you can tell if more blinded since blinded player has minimal 525 /* blinded you can tell if more blinded since blinded player has minimal
526 * vision 526 * vision
527 */ 527 */
528 if(QUERY_FLAG(tmp,FLAG_BLIND)) { 528 if(QUERY_FLAG(tmp,FLAG_BLIND)) {
529 success=1; 529 success=1;
530 if(flag>0) { 530 if(flag>0) {
531 if(QUERY_FLAG(op,FLAG_WIZ)) 531 if(QUERY_FLAG(op,FLAG_WIZ))
532 new_draw_info(NDI_UNIQUE, 0, op,"Your mortal self is blinded."); 532 new_draw_info(NDI_UNIQUE, 0, op,"Your mortal self is blinded.");
533 else { 533 else {
534 new_draw_info(NDI_UNIQUE, 0, op,"You are blinded."); 534 new_draw_info(NDI_UNIQUE, 0, op,"You are blinded.");
535 SET_FLAG(op,FLAG_BLIND); 535 SET_FLAG(op,FLAG_BLIND);
536 if(op->type==PLAYER) 536 if(op->type==PLAYER)
537 op->contr->do_los=1; 537 op->contr->do_los=1;
538 } 538 }
539 } else { 539 } else {
540 if(QUERY_FLAG(op,FLAG_WIZ)) 540 if(QUERY_FLAG(op,FLAG_WIZ))
541 new_draw_info(NDI_UNIQUE, 0, op,"Your mortal self can now see again."); 541 new_draw_info(NDI_UNIQUE, 0, op,"Your mortal self can now see again.");
542 else { 542 else {
543 new_draw_info(NDI_UNIQUE, 0, op,"Your vision returns."); 543 new_draw_info(NDI_UNIQUE, 0, op,"Your vision returns.");
544 CLEAR_FLAG(op,FLAG_BLIND); 544 CLEAR_FLAG(op,FLAG_BLIND);
545 if(op->type==PLAYER) 545 if(op->type==PLAYER)
546 op->contr->do_los=1; 546 op->contr->do_los=1;
547 } 547 }
548 } 548 }
549 } 549 }
550 550
551 if ( QUERY_FLAG(op,FLAG_SEE_IN_DARK) != QUERY_FLAG(&refop,FLAG_SEE_IN_DARK)){ 551 if ( QUERY_FLAG(op,FLAG_SEE_IN_DARK) != QUERY_FLAG(&refop,FLAG_SEE_IN_DARK)){
552 success=1; 552 success=1;
553 if(op->type==PLAYER) 553 if(op->type==PLAYER)
554 op->contr->do_los=1; 554 op->contr->do_los=1;
555 DIFF_MSG(flag, "Your vision is better in the dark.", "You see less well in the dark."); 555 DIFF_MSG(flag, "Your vision is better in the dark.", "You see less well in the dark.");
556 } 556 }
557 557
558 if ( QUERY_FLAG(op,FLAG_XRAYS) != QUERY_FLAG(&refop,FLAG_XRAYS)){ 558 if ( QUERY_FLAG(op,FLAG_XRAYS) != QUERY_FLAG(&refop,FLAG_XRAYS)){
559 success=1; 559 success=1;
560 if(flag>0) { 560 if(flag>0) {
561 if(QUERY_FLAG(op,FLAG_WIZ)) 561 if(QUERY_FLAG(op,FLAG_WIZ))
562 new_draw_info(NDI_UNIQUE, 0, op,"Your vision becomes a little clearer."); 562 new_draw_info(NDI_UNIQUE, 0, op,"Your vision becomes a little clearer.");
563 else { 563 else {
564 new_draw_info(NDI_UNIQUE, 0, op,"Everything becomes transparent."); 564 new_draw_info(NDI_UNIQUE, 0, op,"Everything becomes transparent.");
565 if(op->type==PLAYER) 565 if(op->type==PLAYER)
566 op->contr->do_los=1; 566 op->contr->do_los=1;
567 } 567 }
568 } else { 568 } else {
569 if(QUERY_FLAG(op,FLAG_WIZ)) 569 if(QUERY_FLAG(op,FLAG_WIZ))
570 new_draw_info(NDI_UNIQUE, 0, op,"Your vision becomes a bit out of focus."); 570 new_draw_info(NDI_UNIQUE, 0, op,"Your vision becomes a bit out of focus.");
571 else { 571 else {
572 new_draw_info(NDI_UNIQUE, 0, op,"Everything suddenly looks very solid."); 572 new_draw_info(NDI_UNIQUE, 0, op,"Everything suddenly looks very solid.");
573 if(op->type==PLAYER) 573 if(op->type==PLAYER)
574 op->contr->do_los=1; 574 op->contr->do_los=1;
575 } 575 }
576 } 576 }
577 } 577 }
578 578
579 if(tmp->stats.luck) { 579 if(tmp->stats.luck) {
580 success=1; 580 success=1;
581 DIFF_MSG(flag*tmp->stats.luck, "You feel more lucky.", "You feel less lucky."); 581 DIFF_MSG(flag*tmp->stats.luck, "You feel more lucky.", "You feel less lucky.");
582 } 582 }
583 583
584 if(tmp->stats.hp && op->type==PLAYER) { 584 if(tmp->stats.hp && op->type==PLAYER) {
585 success=1; 585 success=1;
586 DIFF_MSG(flag*tmp->stats.hp, "You feel much more healthy!", 586 DIFF_MSG(flag*tmp->stats.hp, "You feel much more healthy!",
587 "You feel much less healthy!"); 587 "You feel much less healthy!");
588 } 588 }
589 589
590 if(tmp->stats.sp && op->type==PLAYER && tmp->type!=SKILL) { 590 if(tmp->stats.sp && op->type==PLAYER && tmp->type!=SKILL) {
591 success=1; 591 success=1;
592 DIFF_MSG(flag*tmp->stats.sp, "You feel one with the powers of magic!", 592 DIFF_MSG(flag*tmp->stats.sp, "You feel one with the powers of magic!",
593 "You suddenly feel very mundane."); 593 "You suddenly feel very mundane.");
594 } 594 }
595 595
596 /* for the future when artifacts set this -b.t. */ 596 /* for the future when artifacts set this -b.t. */
597 if(tmp->stats.grace && op->type==PLAYER) { 597 if(tmp->stats.grace && op->type==PLAYER) {
598 success=1; 598 success=1;
599 DIFF_MSG(flag*tmp->stats.grace, "You feel closer to your god!", 599 DIFF_MSG(flag*tmp->stats.grace, "You feel closer to your god!",
600 "You suddenly feel less holy."); 600 "You suddenly feel less holy.");
601 } 601 }
602 602
603 if(tmp->stats.food && op->type==PLAYER) { 603 if(tmp->stats.food && op->type==PLAYER) {
604 success=1; 604 success=1;
605 DIFF_MSG(flag*tmp->stats.food, "You feel your digestion slowing down.", 605 DIFF_MSG(flag*tmp->stats.food, "You feel your digestion slowing down.",
606 "You feel your digestion speeding up."); 606 "You feel your digestion speeding up.");
607 } 607 }
608 608
609 /* Messages for changed resistance */ 609 /* Messages for changed resistance */
610 for (i=0; i<NROFATTACKS; i++) { 610 for (i=0; i<NROFATTACKS; i++) {
611 if (i==ATNR_PHYSICAL) continue; /* Don't display about armour */ 611 if (i==ATNR_PHYSICAL) continue; /* Don't display about armour */
612 612
613 if (op->resist[i] != refop.resist[i]) { 613 if (op->resist[i] != refop.resist[i]) {
614 success=1; 614 success=1;
615 if (op->resist[i] > refop.resist[i]) 615 if (op->resist[i] > refop.resist[i])
616 sprintf(message, "Your resistance to %s rises to %d%%.", 616 sprintf(message, "Your resistance to %s rises to %d%%.",
617 change_resist_msg[i], op->resist[i]); 617 change_resist_msg[i], op->resist[i]);
618 else 618 else
619 sprintf(message, "Your resistance to %s drops to %d%%.", 619 sprintf(message, "Your resistance to %s drops to %d%%.",
620 change_resist_msg[i], op->resist[i]); 620 change_resist_msg[i], op->resist[i]);
621 621
622 new_draw_info(NDI_UNIQUE|NDI_BLUE, 0, op, message); 622 new_draw_info(NDI_UNIQUE|NDI_BLUE, 0, op, message);
623 } 623 }
624 } 624 }
625 625
626 if(tmp->type!=EXPERIENCE && !potion_max) { 626 if(tmp->type!=EXPERIENCE && !potion_max) {
627 for (j=0; j<NUM_STATS; j++) { 627 for (j=0; j<NUM_STATS; j++) {
628 if ((i=get_attr_value(&(tmp->stats),j))!=0) { 628 if ((i=get_attr_value(&(tmp->stats),j))!=0) {
629 success=1; 629 success=1;
630 DIFF_MSG(i * flag, gain_msg[j], lose_msg[j]); 630 DIFF_MSG(i * flag, gain_msg[j], lose_msg[j]);
631 } 631 }
632 } 632 }
633 } 633 }
634 return success; 634 return success;
635} 635}
636 636
637/* 637/*
693 * in op itself). 693 * in op itself).
694 */ 694 */
695 new_luck = tmp->stats.luck+value; 695 new_luck = tmp->stats.luck+value;
696 if (new_luck >= -100 && new_luck <= 100) { 696 if (new_luck >= -100 && new_luck <= 100) {
697 op->stats.luck+=value; 697 op->stats.luck+=value;
698 tmp->stats.luck = new_luck; 698 tmp->stats.luck = new_luck;
699 } 699 }
700 } else { 700 } else {
701 if (!tmp->stats.luck) { 701 if (!tmp->stats.luck) {
702 return; 702 return;
703 } 703 }
775 int prot[NROFATTACKS], vuln[NROFATTACKS], potion_resist[NROFATTACKS]; 775 int prot[NROFATTACKS], vuln[NROFATTACKS], potion_resist[NROFATTACKS];
776 object *grace_obj=NULL,*mana_obj=NULL,*wc_obj=NULL,*tmp; 776 object *grace_obj=NULL,*mana_obj=NULL,*wc_obj=NULL,*tmp;
777 777
778 /* First task is to clear all the values back to their original values */ 778 /* First task is to clear all the values back to their original values */
779 if(op->type==PLAYER) { 779 if(op->type==PLAYER) {
780 for(i=0;i<NUM_STATS;i++) { 780 for(i=0;i<NUM_STATS;i++) {
781 set_attr_value(&(op->stats),i,get_attr_value(&(op->contr->orig_stats),i)); 781 set_attr_value(&(op->stats),i,get_attr_value(&(op->contr->orig_stats),i));
782 } 782 }
783 if (settings.spell_encumbrance == TRUE) 783 if (settings.spell_encumbrance == TRUE)
784 op->contr->encumbrance=0; 784 op->contr->encumbrance=0;
785 785
786 op->attacktype=0; 786 op->attacktype=0;
787 op->contr->digestion = 0; 787 op->contr->digestion = 0;
788 op->contr->gen_hp = 0; 788 op->contr->gen_hp = 0;
789 op->contr->gen_sp = 0; 789 op->contr->gen_sp = 0;
790 op->contr->gen_grace = 0; 790 op->contr->gen_grace = 0;
791 op->contr->gen_sp_armour = 10; 791 op->contr->gen_sp_armour = 10;
792 op->contr->item_power = 0; 792 op->contr->item_power = 0;
793 793
794 /* Don't clobber all the range_ values. range_golem otherwise 794 /* Don't clobber all the range_ values. range_golem otherwise
795 * gets reset for no good reason, and we don't want to reset 795 * gets reset for no good reason, and we don't want to reset
796 * range_magic (what spell is readied). These three below 796 * range_magic (what spell is readied). These three below
797 * well get filled in based on what the player has equipped. 797 * well get filled in based on what the player has equipped.
798 */ 798 */
799 op->contr->ranges[range_bow] = NULL; 799 op->contr->ranges[range_bow] = NULL;
800 op->contr->ranges[range_misc] = NULL; 800 op->contr->ranges[range_misc] = NULL;
801 op->contr->ranges[range_skill] = NULL; 801 op->contr->ranges[range_skill] = NULL;
802 } 802 }
803 memcpy(op->body_used, op->body_info, sizeof(op->body_info)); 803 memcpy(op->body_used, op->body_info, sizeof(op->body_info));
804 804
805 if(op->slaying!=NULL) { 805 if(op->slaying!=NULL) {
806 free_string(op->slaying); 806 free_string(op->slaying);
807 op->slaying=NULL; 807 op->slaying=NULL;
808 } 808 }
809 if(!QUERY_FLAG(op,FLAG_WIZ)) { 809 if(!QUERY_FLAG(op,FLAG_WIZ)) {
810 CLEAR_FLAG(op, FLAG_XRAYS); 810 CLEAR_FLAG(op, FLAG_XRAYS);
811 CLEAR_FLAG(op, FLAG_MAKE_INVIS); 811 CLEAR_FLAG(op, FLAG_MAKE_INVIS);
812 } 812 }
813 813
814 CLEAR_FLAG(op,FLAG_LIFESAVE); 814 CLEAR_FLAG(op,FLAG_LIFESAVE);
815 CLEAR_FLAG(op,FLAG_STEALTH); 815 CLEAR_FLAG(op,FLAG_STEALTH);
816 CLEAR_FLAG(op,FLAG_BLIND); 816 CLEAR_FLAG(op,FLAG_BLIND);
817 if ( ! QUERY_FLAG (&op->arch->clone, FLAG_REFL_SPELL)) 817 if ( ! QUERY_FLAG (&op->arch->clone, FLAG_REFL_SPELL))
818 CLEAR_FLAG(op,FLAG_REFL_SPELL); 818 CLEAR_FLAG(op,FLAG_REFL_SPELL);
819 if ( ! QUERY_FLAG (&op->arch->clone, FLAG_REFL_MISSILE)) 819 if ( ! QUERY_FLAG (&op->arch->clone, FLAG_REFL_MISSILE))
820 CLEAR_FLAG(op,FLAG_REFL_MISSILE); 820 CLEAR_FLAG(op,FLAG_REFL_MISSILE);
821 if(!QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD)) 821 if(!QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD))
822 CLEAR_FLAG(op,FLAG_UNDEAD); 822 CLEAR_FLAG(op,FLAG_UNDEAD);
823 if ( ! QUERY_FLAG (&op->arch->clone, FLAG_SEE_IN_DARK)) 823 if ( ! QUERY_FLAG (&op->arch->clone, FLAG_SEE_IN_DARK))
824 CLEAR_FLAG(op,FLAG_SEE_IN_DARK); 824 CLEAR_FLAG(op,FLAG_SEE_IN_DARK);
825 825
826 op->path_attuned=op->arch->clone.path_attuned; 826 op->path_attuned=op->arch->clone.path_attuned;
827 op->path_repelled=op->arch->clone.path_repelled; 827 op->path_repelled=op->arch->clone.path_repelled;
828 op->path_denied=op->arch->clone.path_denied; 828 op->path_denied=op->arch->clone.path_denied;
829 op->glow_radius=op->arch->clone.glow_radius; 829 op->glow_radius=op->arch->clone.glow_radius;
834 * archetype clone 834 * archetype clone
835 */ 835 */
836 memcpy(&op->resist, &op->arch->clone.resist, sizeof(op->resist)); 836 memcpy(&op->resist, &op->arch->clone.resist, sizeof(op->resist));
837 837
838 for (i=0;i<NROFATTACKS;i++) { 838 for (i=0;i<NROFATTACKS;i++) {
839 if (op->resist[i] > 0) 839 if (op->resist[i] > 0)
840 prot[i]= op->resist[i], vuln[i]=0; 840 prot[i]= op->resist[i], vuln[i]=0;
841 else 841 else
842 vuln[i]= -(op->resist[i]), prot[i]=0; 842 vuln[i]= -(op->resist[i]), prot[i]=0;
843 potion_resist[i]=0; 843 potion_resist[i]=0;
844 } 844 }
845 845
846 wc=op->arch->clone.stats.wc; 846 wc=op->arch->clone.stats.wc;
847 op->stats.dam=op->arch->clone.stats.dam; 847 op->stats.dam=op->arch->clone.stats.dam;
848 848
852 * we should probably give them some bonus and cap it off - otherwise, 852 * we should probably give them some bonus and cap it off - otherwise,
853 * basically, if a server updates its max level, these playes may find 853 * basically, if a server updates its max level, these playes may find
854 * that their protection from physical goes down 854 * that their protection from physical goes down
855 */ 855 */
856 if(!QUERY_FLAG(op,FLAG_USE_ARMOUR) && op->type==PLAYER) { 856 if(!QUERY_FLAG(op,FLAG_USE_ARMOUR) && op->type==PLAYER) {
857 ac=MAX(-10,op->arch->clone.stats.ac - op->level/3); 857 ac=MAX(-10,op->arch->clone.stats.ac - op->level/3);
858 prot[ATNR_PHYSICAL] += ((100-prot[AT_PHYSICAL])*(80*op->level/settings.max_level))/100; 858 prot[ATNR_PHYSICAL] += ((100-prot[AT_PHYSICAL])*(80*op->level/settings.max_level))/100;
859 } 859 }
860 else 860 else
861 ac=op->arch->clone.stats.ac; 861 ac=op->arch->clone.stats.ac;
862 862
863 op->stats.luck=op->arch->clone.stats.luck; 863 op->stats.luck=op->arch->clone.stats.luck;
864 op->speed = op->arch->clone.speed; 864 op->speed = op->arch->clone.speed;
865 865
866 /* OK - we've reset most all the objects attributes to sane values. 866 /* OK - we've reset most all the objects attributes to sane values.
867 * now go through and make adjustments for what the player has equipped. 867 * now go through and make adjustments for what the player has equipped.
868 */ 868 */
869 869
870 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) { 870 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) {
871 /* See note in map.c:update_position about making this additive 871 /* See note in map.c:update_position about making this additive
872 * since light sources are never applied, need to put check here. 872 * since light sources are never applied, need to put check here.
873 */ 873 */
874 if (tmp->glow_radius > op->glow_radius) op->glow_radius=tmp->glow_radius; 874 if (tmp->glow_radius > op->glow_radius) op->glow_radius=tmp->glow_radius;
875 875
876 /* This happens because apply_potion calls change_abil with the potion 876 /* This happens because apply_potion calls change_abil with the potion
877 * applied so we can tell the player what chagned. But change_abil 877 * applied so we can tell the player what chagned. But change_abil
878 * then calls this function. 878 * then calls this function.
879 */ 879 */
880 if (QUERY_FLAG(tmp, FLAG_APPLIED) && tmp->type == POTION) { 880 if (QUERY_FLAG(tmp, FLAG_APPLIED) && tmp->type == POTION) {
881 continue; 881 continue;
882 } 882 }
883 883
884 /* For some things, we don't care what is equipped */ 884 /* For some things, we don't care what is equipped */
885 if (tmp->type == SKILL) { 885 if (tmp->type == SKILL) {
886 /* Want to take the highest skill here. */ 886 /* Want to take the highest skill here. */
887 if (IS_MANA_SKILL(tmp->subtype)) { 887 if (IS_MANA_SKILL(tmp->subtype)) {
888 if (!mana_obj) mana_obj=tmp; 888 if (!mana_obj) mana_obj=tmp;
889 else if (tmp->level > mana_obj->level) mana_obj = tmp; 889 else if (tmp->level > mana_obj->level) mana_obj = tmp;
890 } 890 }
891 if (IS_GRACE_SKILL(tmp->subtype)) { 891 if (IS_GRACE_SKILL(tmp->subtype)) {
892 if (!grace_obj) grace_obj=tmp; 892 if (!grace_obj) grace_obj=tmp;
893 else if (tmp->level > grace_obj->level) grace_obj = tmp; 893 else if (tmp->level > grace_obj->level) grace_obj = tmp;
894 } 894 }
895 } 895 }
896 896
897 /* Container objects are not meant to adjust a players, but other applied 897 /* Container objects are not meant to adjust a players, but other applied
898 * objects need to make adjustments. 898 * objects need to make adjustments.
899 * This block should handle all player specific changes 899 * This block should handle all player specific changes
900 * The check for Praying is a bit of a hack - god given bonuses are put 900 * The check for Praying is a bit of a hack - god given bonuses are put
901 * in the praying skill, and the player should always get those. 901 * in the praying skill, and the player should always get those.
902 * It also means we need to put in additional checks for applied below, 902 * It also means we need to put in additional checks for applied below,
903 * because the skill shouldn't count against body positions being used 903 * because the skill shouldn't count against body positions being used
904 * up, etc. 904 * up, etc.
905 */ 905 */
906 if ((QUERY_FLAG(tmp,FLAG_APPLIED) && tmp->type!=CONTAINER && tmp->type!=CLOSE_CON) || 906 if ((QUERY_FLAG(tmp,FLAG_APPLIED) && tmp->type!=CONTAINER && tmp->type!=CLOSE_CON) ||
907 (tmp->type == SKILL && tmp->subtype == SK_PRAYING)) { 907 (tmp->type == SKILL && tmp->subtype == SK_PRAYING)) {
908 if(op->type==PLAYER) { 908 if(op->type==PLAYER) {
909 if (tmp->type == BOW) 909 if (tmp->type == BOW)
910 op->contr->ranges[range_bow] = tmp; 910 op->contr->ranges[range_bow] = tmp;
911 911
912 if (tmp->type == WAND || tmp->type == ROD || tmp->type==HORN) 912 if (tmp->type == WAND || tmp->type == ROD || tmp->type==HORN)
913 op->contr->ranges[range_misc] = tmp; 913 op->contr->ranges[range_misc] = tmp;
914 914
915 for(i=0;i<NUM_STATS;i++) 915 for(i=0;i<NUM_STATS;i++)
916 change_attr_value(&(op->stats),i,get_attr_value(&(tmp->stats),i)); 916 change_attr_value(&(op->stats),i,get_attr_value(&(tmp->stats),i));
917 917
918 /* these are the items that currently can change digestion, regeneration, 918 /* these are the items that currently can change digestion, regeneration,
919 * spell point recovery and mana point recovery. Seems sort of an arbitary 919 * spell point recovery and mana point recovery. Seems sort of an arbitary
920 * list, but other items store other info into stats array. 920 * list, but other items store other info into stats array.
921 */ 921 */
922 if ((tmp->type == EXPERIENCE) || (tmp->type == WEAPON) || 922 if ((tmp->type == EXPERIENCE) || (tmp->type == WEAPON) ||
923 (tmp->type == ARMOUR) || (tmp->type == HELMET) || 923 (tmp->type == ARMOUR) || (tmp->type == HELMET) ||
924 (tmp->type == SHIELD) || (tmp->type == RING) || 924 (tmp->type == SHIELD) || (tmp->type == RING) ||
925 (tmp->type == BOOTS) || (tmp->type == GLOVES) || 925 (tmp->type == BOOTS) || (tmp->type == GLOVES) ||
926 (tmp->type == AMULET ) || (tmp->type == GIRDLE) || 926 (tmp->type == AMULET ) || (tmp->type == GIRDLE) ||
927 (tmp->type == BRACERS ) || (tmp->type == CLOAK) || 927 (tmp->type == BRACERS ) || (tmp->type == CLOAK) ||
928 (tmp->type == DISEASE) || (tmp->type == FORCE) || 928 (tmp->type == DISEASE) || (tmp->type == FORCE) ||
929 (tmp->type == SKILL)) { 929 (tmp->type == SKILL)) {
930 op->contr->digestion += tmp->stats.food; 930 op->contr->digestion += tmp->stats.food;
931 op->contr->gen_hp += tmp->stats.hp; 931 op->contr->gen_hp += tmp->stats.hp;
932 op->contr->gen_sp += tmp->stats.sp; 932 op->contr->gen_sp += tmp->stats.sp;
933 op->contr->gen_grace += tmp->stats.grace; 933 op->contr->gen_grace += tmp->stats.grace;
934 op->contr->gen_sp_armour+= tmp->gen_sp_armour; 934 op->contr->gen_sp_armour+= tmp->gen_sp_armour;
935 op->contr->item_power += tmp->item_power; 935 op->contr->item_power += tmp->item_power;
936 } 936 }
937 } /* if this is a player */ 937 } /* if this is a player */
938 938
939 /* Update slots used for items */ 939 /* Update slots used for items */
940 if (QUERY_FLAG(tmp,FLAG_APPLIED)) { 940 if (QUERY_FLAG(tmp,FLAG_APPLIED)) {
941 for (i=0; i<NUM_BODY_LOCATIONS; i++) 941 for (i=0; i<NUM_BODY_LOCATIONS; i++)
942 op->body_used[i] += tmp->body_info[i]; 942 op->body_used[i] += tmp->body_info[i];
943 } 943 }
944 944
945 if(tmp->type==SYMPTOM) { 945 if(tmp->type==SYMPTOM) {
946 speed_reduce_from_disease = tmp->last_sp / 100.0; 946 speed_reduce_from_disease = tmp->last_sp / 100.0;
947 if(speed_reduce_from_disease ==0) speed_reduce_from_disease = 1; 947 if(speed_reduce_from_disease ==0) speed_reduce_from_disease = 1;
948 } 948 }
949 949
950 /* Pos. and neg. protections are counted seperate (-> pro/vuln). 950 /* Pos. and neg. protections are counted seperate (-> pro/vuln).
951 * (Negative protections are calculated extactly like positive.) 951 * (Negative protections are calculated extactly like positive.)
952 * Resistance from potions are treated special as well. If there's 952 * Resistance from potions are treated special as well. If there's
953 * more than one potion-effect, the bigger prot.-value is taken. 953 * more than one potion-effect, the bigger prot.-value is taken.
954 */ 954 */
955 if (tmp->type != POTION) { 955 if (tmp->type != POTION) {
956 for (i=0; i<NROFATTACKS; i++) { 956 for (i=0; i<NROFATTACKS; i++) {
957 /* Potential for cursed potions, in which case we just can use 957 /* Potential for cursed potions, in which case we just can use
958 * a straight MAX, as potion_resist is initialized to zero. 958 * a straight MAX, as potion_resist is initialized to zero.
959 */ 959 */
960 if (tmp->type==POTION_EFFECT) { 960 if (tmp->type==POTION_EFFECT) {
961 if (potion_resist[i]) 961 if (potion_resist[i])
962 potion_resist[i] = MAX(potion_resist[i], tmp->resist[i]); 962 potion_resist[i] = MAX(potion_resist[i], tmp->resist[i]);
963 else 963 else
964 potion_resist[i] = tmp->resist[i]; 964 potion_resist[i] = tmp->resist[i];
965 } 965 }
966 else if (tmp->resist[i] > 0) 966 else if (tmp->resist[i] > 0)
967 prot[i] += ((100-prot[i])*tmp->resist[i])/100; 967 prot[i] += ((100-prot[i])*tmp->resist[i])/100;
968 else if (tmp->resist[i] < 0) 968 else if (tmp->resist[i] < 0)
969 vuln[i] += ((100-vuln[i])*(-tmp->resist[i]))/100; 969 vuln[i] += ((100-vuln[i])*(-tmp->resist[i]))/100;
970 } 970 }
971 } 971 }
972 972
973 /* There may be other things that should not adjust the attacktype */ 973 /* There may be other things that should not adjust the attacktype */
974 if (tmp->type!=BOW && tmp->type != SYMPTOM) 974 if (tmp->type!=BOW && tmp->type != SYMPTOM)
975 op->attacktype|=tmp->attacktype; 975 op->attacktype|=tmp->attacktype;
976 976
977 op->path_attuned|=tmp->path_attuned; 977 op->path_attuned|=tmp->path_attuned;
978 op->path_repelled|=tmp->path_repelled; 978 op->path_repelled|=tmp->path_repelled;
979 op->path_denied|=tmp->path_denied; 979 op->path_denied|=tmp->path_denied;
980 op->stats.luck+=tmp->stats.luck; 980 op->stats.luck+=tmp->stats.luck;
981 op->move_type |= tmp->move_type; 981 op->move_type |= tmp->move_type;
982 982
983 if(QUERY_FLAG(tmp,FLAG_LIFESAVE)) SET_FLAG(op,FLAG_LIFESAVE); 983 if(QUERY_FLAG(tmp,FLAG_LIFESAVE)) SET_FLAG(op,FLAG_LIFESAVE);
984 if(QUERY_FLAG(tmp,FLAG_REFL_SPELL)) SET_FLAG(op,FLAG_REFL_SPELL); 984 if(QUERY_FLAG(tmp,FLAG_REFL_SPELL)) SET_FLAG(op,FLAG_REFL_SPELL);
985 if(QUERY_FLAG(tmp,FLAG_REFL_MISSILE)) SET_FLAG(op,FLAG_REFL_MISSILE); 985 if(QUERY_FLAG(tmp,FLAG_REFL_MISSILE)) SET_FLAG(op,FLAG_REFL_MISSILE);
986 if(QUERY_FLAG(tmp,FLAG_STEALTH)) SET_FLAG(op,FLAG_STEALTH); 986 if(QUERY_FLAG(tmp,FLAG_STEALTH)) SET_FLAG(op,FLAG_STEALTH);
987 if(QUERY_FLAG(tmp,FLAG_XRAYS)) SET_FLAG(op,FLAG_XRAYS); 987 if(QUERY_FLAG(tmp,FLAG_XRAYS)) SET_FLAG(op,FLAG_XRAYS);
988 if(QUERY_FLAG(tmp,FLAG_BLIND)) SET_FLAG(op,FLAG_BLIND); 988 if(QUERY_FLAG(tmp,FLAG_BLIND)) SET_FLAG(op,FLAG_BLIND);
989 if(QUERY_FLAG(tmp,FLAG_SEE_IN_DARK)) SET_FLAG(op,FLAG_SEE_IN_DARK); 989 if(QUERY_FLAG(tmp,FLAG_SEE_IN_DARK)) SET_FLAG(op,FLAG_SEE_IN_DARK);
990 990
991 if(QUERY_FLAG(tmp,FLAG_UNDEAD)&&!QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD)) 991 if(QUERY_FLAG(tmp,FLAG_UNDEAD)&&!QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD))
992 SET_FLAG(op,FLAG_UNDEAD); 992 SET_FLAG(op,FLAG_UNDEAD);
993 993
994 if(QUERY_FLAG(tmp,FLAG_MAKE_INVIS)) { 994 if(QUERY_FLAG(tmp,FLAG_MAKE_INVIS)) {
995 SET_FLAG(op,FLAG_MAKE_INVIS); 995 SET_FLAG(op,FLAG_MAKE_INVIS);
996 op->invisible=1; 996 op->invisible=1;
997 } 997 }
998 998
999 if(tmp->stats.exp && tmp->type!=SKILL) { 999 if(tmp->stats.exp && tmp->type!=SKILL) {
1000 if(tmp->stats.exp > 0) { 1000 if(tmp->stats.exp > 0) {
1001 added_speed+=(float)tmp->stats.exp/3.0; 1001 added_speed+=(float)tmp->stats.exp/3.0;
1002 bonus_speed+=1.0+(float)tmp->stats.exp/3.0; 1002 bonus_speed+=1.0+(float)tmp->stats.exp/3.0;
1003 } else 1003 } else
1004 added_speed+=(float)tmp->stats.exp; 1004 added_speed+=(float)tmp->stats.exp;
1005 } 1005 }
1006 1006
1007 switch(tmp->type) { 1007 switch(tmp->type) {
1008 /* skills modifying the character -b.t. */ 1008 /* skills modifying the character -b.t. */
1009 /* for all skills and skill granting objects */ 1009 /* for all skills and skill granting objects */
1010 case SKILL: 1010 case SKILL:
1011 if (!QUERY_FLAG(tmp,FLAG_APPLIED)) break; 1011 if (!QUERY_FLAG(tmp,FLAG_APPLIED)) break;
1012 1012
1013 if (IS_COMBAT_SKILL(tmp->subtype)) wc_obj=tmp; 1013 if (IS_COMBAT_SKILL(tmp->subtype)) wc_obj=tmp;
1014 1014
1015 if (op->chosen_skill) { 1015 if (op->chosen_skill) {
1016 LOG(llevDebug, "fix_player, op %s has multiple skills applied\n", op->name); 1016 LOG(llevDebug, "fix_player, op %s has multiple skills applied\n", op->name);
1017 } 1017 }
1018 op->chosen_skill = tmp; 1018 op->chosen_skill = tmp;
1019 if(tmp->stats.dam>0) { /* skill is a 'weapon' */ 1019 if(tmp->stats.dam>0) { /* skill is a 'weapon' */
1020 if(!QUERY_FLAG(op,FLAG_READY_WEAPON)) 1020 if(!QUERY_FLAG(op,FLAG_READY_WEAPON))
1021 weapon_speed = (int) WEAPON_SPEED(tmp); 1021 weapon_speed = (int) WEAPON_SPEED(tmp);
1022 if(weapon_speed<0) weapon_speed = 0; 1022 if(weapon_speed<0) weapon_speed = 0;
1023 weapon_weight=tmp->weight; 1023 weapon_weight=tmp->weight;
1024 op->stats.dam+=tmp->stats.dam*(1 + (op->chosen_skill->level/9)); 1024 op->stats.dam+=tmp->stats.dam*(1 + (op->chosen_skill->level/9));
1025 if(tmp->magic) op->stats.dam += tmp->magic; 1025 if(tmp->magic) op->stats.dam += tmp->magic;
1026 } 1026 }
1027 if(tmp->stats.wc) 1027 if(tmp->stats.wc)
1028 wc-=(tmp->stats.wc+tmp->magic); 1028 wc-=(tmp->stats.wc+tmp->magic);
1029 1029
1030 if(tmp->slaying!=NULL) { 1030 if(tmp->slaying!=NULL) {
1031 if (op->slaying != NULL) 1031 if (op->slaying != NULL)
1032 free_string (op->slaying); 1032 free_string (op->slaying);
1033 add_refcount(op->slaying = tmp->slaying); 1033 add_refcount(op->slaying = tmp->slaying);
1034 } 1034 }
1035 1035
1036 if(tmp->stats.ac) 1036 if(tmp->stats.ac)
1037 ac-=(tmp->stats.ac+tmp->magic); 1037 ac-=(tmp->stats.ac+tmp->magic);
1038 if(settings.spell_encumbrance == TRUE && op->type==PLAYER) 1038 if(settings.spell_encumbrance == TRUE && op->type==PLAYER)
1039 op->contr->encumbrance+=(int)3*tmp->weight/1000; 1039 op->contr->encumbrance+=(int)3*tmp->weight/1000;
1040 if (op->type == PLAYER) 1040 if (op->type == PLAYER)
1041 op->contr->ranges[range_skill] = op; 1041 op->contr->ranges[range_skill] = op;
1042 break; 1042 break;
1043 1043
1044 case SKILL_TOOL: 1044 case SKILL_TOOL:
1045 if (op->chosen_skill) { 1045 if (op->chosen_skill) {
1046 LOG(llevDebug, "fix_player, op %s has multiple skills applied\n", op->name); 1046 LOG(llevDebug, "fix_player, op %s has multiple skills applied\n", op->name);
1047 } 1047 }
1048 op->chosen_skill = tmp; 1048 op->chosen_skill = tmp;
1049 if (op->type == PLAYER) 1049 if (op->type == PLAYER)
1050 op->contr->ranges[range_skill] = op; 1050 op->contr->ranges[range_skill] = op;
1051 break; 1051 break;
1052 1052
1053 case SHIELD: 1053 case SHIELD:
1054 if(settings.spell_encumbrance == TRUE && op->type==PLAYER) 1054 if(settings.spell_encumbrance == TRUE && op->type==PLAYER)
1055 op->contr->encumbrance+=(int)tmp->weight/2000; 1055 op->contr->encumbrance+=(int)tmp->weight/2000;
1056 case RING: 1056 case RING:
1057 case AMULET: 1057 case AMULET:
1058 case GIRDLE: 1058 case GIRDLE:
1059 case HELMET: 1059 case HELMET:
1060 case BOOTS: 1060 case BOOTS:
1061 case GLOVES: 1061 case GLOVES:
1062 case CLOAK: 1062 case CLOAK:
1063 if(tmp->stats.wc) 1063 if(tmp->stats.wc)
1064 wc-=(tmp->stats.wc+tmp->magic); 1064 wc-=(tmp->stats.wc+tmp->magic);
1065 if(tmp->stats.dam) 1065 if(tmp->stats.dam)
1066 op->stats.dam+=(tmp->stats.dam+tmp->magic); 1066 op->stats.dam+=(tmp->stats.dam+tmp->magic);
1067 if(tmp->stats.ac) 1067 if(tmp->stats.ac)
1068 ac-=(tmp->stats.ac+tmp->magic); 1068 ac-=(tmp->stats.ac+tmp->magic);
1069 break; 1069 break;
1070 1070
1071 case WEAPON: 1071 case WEAPON:
1072 wc-=(tmp->stats.wc+tmp->magic); 1072 wc-=(tmp->stats.wc+tmp->magic);
1073 if(tmp->stats.ac&&tmp->stats.ac+tmp->magic>0) 1073 if(tmp->stats.ac&&tmp->stats.ac+tmp->magic>0)
1074 ac-=tmp->stats.ac+tmp->magic; 1074 ac-=tmp->stats.ac+tmp->magic;
1075 op->stats.dam+=(tmp->stats.dam+tmp->magic); 1075 op->stats.dam+=(tmp->stats.dam+tmp->magic);
1076 weapon_weight=tmp->weight; 1076 weapon_weight=tmp->weight;
1077 weapon_speed=((int)WEAPON_SPEED(tmp)*2-tmp->magic)/2; 1077 weapon_speed=((int)WEAPON_SPEED(tmp)*2-tmp->magic)/2;
1078 if(weapon_speed<0) weapon_speed=0; 1078 if(weapon_speed<0) weapon_speed=0;
1079 if(tmp->slaying!=NULL) { 1079 if(tmp->slaying!=NULL) {
1080 if (op->slaying != NULL) 1080 if (op->slaying != NULL)
1081 free_string (op->slaying); 1081 free_string (op->slaying);
1082 add_refcount(op->slaying = tmp->slaying); 1082 add_refcount(op->slaying = tmp->slaying);
1083 } 1083 }
1084 /* If there is desire that two handed weapons should do 1084 /* If there is desire that two handed weapons should do
1085 * extra strength damage, this is where the code should 1085 * extra strength damage, this is where the code should
1086 * go. 1086 * go.
1087 */ 1087 */
1088 op->current_weapon = tmp; 1088 op->current_weapon = tmp;
1089 if(settings.spell_encumbrance == TRUE && op->type==PLAYER) 1089 if(settings.spell_encumbrance == TRUE && op->type==PLAYER)
1090 op->contr->encumbrance+=(int)3*tmp->weight/1000; 1090 op->contr->encumbrance+=(int)3*tmp->weight/1000;
1091 break; 1091 break;
1092 1092
1093 case ARMOUR: /* Only the best of these three are used: */ 1093 case ARMOUR: /* Only the best of these three are used: */
1094 if(settings.spell_encumbrance == TRUE && op->type==PLAYER) 1094 if(settings.spell_encumbrance == TRUE && op->type==PLAYER)
1095 op->contr->encumbrance+=(int)tmp->weight/1000; 1095 op->contr->encumbrance+=(int)tmp->weight/1000;
1096 1096
1097 case BRACERS: 1097 case BRACERS:
1098 case FORCE: 1098 case FORCE:
1099 if(tmp->stats.wc) { 1099 if(tmp->stats.wc) {
1100 if(best_wc<tmp->stats.wc+tmp->magic) { 1100 if(best_wc<tmp->stats.wc+tmp->magic) {
1101 wc+=best_wc; 1101 wc+=best_wc;
1102 best_wc=tmp->stats.wc+tmp->magic; 1102 best_wc=tmp->stats.wc+tmp->magic;
1103 } else 1103 } else
1104 wc+=tmp->stats.wc+tmp->magic; 1104 wc+=tmp->stats.wc+tmp->magic;
1105 } 1105 }
1106 if(tmp->stats.ac) { 1106 if(tmp->stats.ac) {
1107 if(best_ac<tmp->stats.ac+tmp->magic) { 1107 if(best_ac<tmp->stats.ac+tmp->magic) {
1108 ac+=best_ac; /* Remove last bonus */ 1108 ac+=best_ac; /* Remove last bonus */
1109 best_ac=tmp->stats.ac+tmp->magic; 1109 best_ac=tmp->stats.ac+tmp->magic;
1110 } 1110 }
1111 else /* To nullify the below effect */ 1111 else /* To nullify the below effect */
1112 ac+=tmp->stats.ac+tmp->magic; 1112 ac+=tmp->stats.ac+tmp->magic;
1113 } 1113 }
1114 if(tmp->stats.wc) wc-=(tmp->stats.wc+tmp->magic); 1114 if(tmp->stats.wc) wc-=(tmp->stats.wc+tmp->magic);
1115 if(tmp->stats.ac) ac-=(tmp->stats.ac+tmp->magic); 1115 if(tmp->stats.ac) ac-=(tmp->stats.ac+tmp->magic);
1116 if(ARMOUR_SPEED(tmp)&&ARMOUR_SPEED(tmp)/10.0<max) 1116 if(ARMOUR_SPEED(tmp)&&ARMOUR_SPEED(tmp)/10.0<max)
1117 max=ARMOUR_SPEED(tmp)/10.0; 1117 max=ARMOUR_SPEED(tmp)/10.0;
1118 break; 1118 break;
1119 } /* switch tmp->type */ 1119 } /* switch tmp->type */
1120 } /* item is equipped */ 1120 } /* item is equipped */
1121 } /* for loop of items */ 1121 } /* for loop of items */
1122 1122
1123 /* We've gone through all the objects the player has equipped. For many things, we 1123 /* We've gone through all the objects the player has equipped. For many things, we
1124 * have generated intermediate values which we now need to assign. 1124 * have generated intermediate values which we now need to assign.
1125 */ 1125 */
1129 * than that, we take: 'total resistance = resistance from potion'. 1129 * than that, we take: 'total resistance = resistance from potion'.
1130 * If there is a cursed (and no uncursed) potion in effect, we take 1130 * If there is a cursed (and no uncursed) potion in effect, we take
1131 * 'total resistance = vulnerability from cursed potion'. 1131 * 'total resistance = vulnerability from cursed potion'.
1132 */ 1132 */
1133 for (i=0; i<NROFATTACKS; i++) { 1133 for (i=0; i<NROFATTACKS; i++) {
1134 op->resist[i] = prot[i] - vuln[i]; 1134 op->resist[i] = prot[i] - vuln[i];
1135 if (potion_resist[i] && ((potion_resist[i] > op->resist[i]) || 1135 if (potion_resist[i] && ((potion_resist[i] > op->resist[i]) ||
1136 (potion_resist[i] < 0))) 1136 (potion_resist[i] < 0)))
1137 op->resist[i] = potion_resist[i]; 1137 op->resist[i] = potion_resist[i];
1138 } 1138 }
1139 1139
1140 /* Figure out the players sp/mana/hp totals. */ 1140 /* Figure out the players sp/mana/hp totals. */
1141 if(op->type==PLAYER) { 1141 if(op->type==PLAYER) {
1142 int pl_level; 1142 int pl_level;
1143 1143
1144 check_stat_bounds(&(op->stats)); 1144 check_stat_bounds(&(op->stats));
1145 pl_level=op->level; 1145 pl_level=op->level;
1146 1146
1147 if(pl_level<1) pl_level=1; /* safety, we should always get 1 levels worth of hp! */ 1147 if(pl_level<1) pl_level=1; /* safety, we should always get 1 levels worth of hp! */
1148 1148
1149 /* You basically get half a con bonus/level. But we do take into account rounding, 1149 /* You basically get half a con bonus/level. But we do take into account rounding,
1150 * so if your bonus is 7, you still get 7 worth of bonus every 2 levels. 1150 * so if your bonus is 7, you still get 7 worth of bonus every 2 levels.
1151 */ 1151 */
1152 for(i=1,op->stats.maxhp=0;i<=pl_level&&i<=10;i++) { 1152 for(i=1,op->stats.maxhp=0;i<=pl_level&&i<=10;i++) {
1153 j=op->contr->levhp[i]+con_bonus[op->stats.Con]/2; 1153 j=op->contr->levhp[i]+con_bonus[op->stats.Con]/2;
1154 if(i%2 && con_bonus[op->stats.Con]%2) { 1154 if(i%2 && con_bonus[op->stats.Con]%2) {
1155 if (con_bonus[op->stats.Con]>0) 1155 if (con_bonus[op->stats.Con]>0)
1156 j++; 1156 j++;
1157 else 1157 else
1158 j--; 1158 j--;
1159 } 1159 }
1160 op->stats.maxhp+=j>1?j:1; /* always get at least 1 hp/level */ 1160 op->stats.maxhp+=j>1?j:1; /* always get at least 1 hp/level */
1161 } 1161 }
1162 1162
1163 for(i=11;i<=op->level;i++) 1163 for(i=11;i<=op->level;i++)
1164 op->stats.maxhp+=2; 1164 op->stats.maxhp+=2;
1165 1165
1166 if(op->stats.hp>op->stats.maxhp) 1166 if(op->stats.hp>op->stats.maxhp)
1167 op->stats.hp=op->stats.maxhp; 1167 op->stats.hp=op->stats.maxhp;
1168 1168
1169 /* Sp gain is controlled by the level of the player's 1169 /* Sp gain is controlled by the level of the player's
1170 * relevant experience object (mana_obj, see above) 1170 * relevant experience object (mana_obj, see above)
1171 */ 1171 */
1172 /* following happen when skills system is not used */ 1172 /* following happen when skills system is not used */
1173 if(!mana_obj) mana_obj = op; 1173 if(!mana_obj) mana_obj = op;
1174 if(!grace_obj) grace_obj = op; 1174 if(!grace_obj) grace_obj = op;
1175 /* set maxsp */ 1175 /* set maxsp */
1176 if(!mana_obj || !mana_obj->level || op->type!=PLAYER) mana_obj = op; 1176 if(!mana_obj || !mana_obj->level || op->type!=PLAYER) mana_obj = op;
1177 1177
1178 if (mana_obj == op && op->type == PLAYER) { 1178 if (mana_obj == op && op->type == PLAYER) {
1179 op->stats.maxsp = 1; 1179 op->stats.maxsp = 1;
1180 } else { 1180 } else {
1181 sp_tmp=0.0; 1181 sp_tmp=0.0;
1182 for(i=1;i<=mana_obj->level&&i<=10;i++) { 1182 for(i=1;i<=mana_obj->level&&i<=10;i++) {
1183 float stmp; 1183 float stmp;
1184 1184
1185 /* Got some extra bonus at first level */ 1185 /* Got some extra bonus at first level */
1186 if(i<2) { 1186 if(i<2) {
1187 stmp = op->contr->levsp[i] +((2.0 * (float)sp_bonus[op->stats.Pow] + 1187 stmp = op->contr->levsp[i] +((2.0 * (float)sp_bonus[op->stats.Pow] +
1188 (float)sp_bonus[op->stats.Int])/6.0); 1188 (float)sp_bonus[op->stats.Int])/6.0);
1189 } else { 1189 } else {
1190 stmp=(float)op->contr->levsp[i] 1190 stmp=(float)op->contr->levsp[i]
1191 +(2.0 * (float)sp_bonus[op->stats.Pow] + 1191 +(2.0 * (float)sp_bonus[op->stats.Pow] +
1192 (float)sp_bonus[op->stats.Int])/12.0; 1192 (float)sp_bonus[op->stats.Int])/12.0;
1193 } 1193 }
1194 if (stmp<1.0) stmp=1.0; 1194 if (stmp<1.0) stmp=1.0;
1195 sp_tmp+=stmp; 1195 sp_tmp+=stmp;
1196 } 1196 }
1197 op->stats.maxsp=(int)sp_tmp; 1197 op->stats.maxsp=(int)sp_tmp;
1198 1198
1199 for(i=11;i<=mana_obj->level;i++) 1199 for(i=11;i<=mana_obj->level;i++)
1200 op->stats.maxsp+=2; 1200 op->stats.maxsp+=2;
1201 } 1201 }
1202 /* Characters can get their sp supercharged via rune of transferrance */ 1202 /* Characters can get their sp supercharged via rune of transferrance */
1203 if(op->stats.sp>op->stats.maxsp*2) 1203 if(op->stats.sp>op->stats.maxsp*2)
1204 op->stats.sp=op->stats.maxsp*2; 1204 op->stats.sp=op->stats.maxsp*2;
1205 1205
1206 /* set maxgrace, notice 3-4 lines below it depends on both Wis and Pow */ 1206 /* set maxgrace, notice 3-4 lines below it depends on both Wis and Pow */
1207 if(!grace_obj || !grace_obj->level || op->type!=PLAYER) grace_obj = op; 1207 if(!grace_obj || !grace_obj->level || op->type!=PLAYER) grace_obj = op;
1208 1208
1209 if (grace_obj == op && op->type == PLAYER) { 1209 if (grace_obj == op && op->type == PLAYER) {
1210 op->stats.maxgrace = 1; 1210 op->stats.maxgrace = 1;
1211 } else { 1211 } else {
1212 /* store grace in a float - this way, the divisions below don't create 1212 /* store grace in a float - this way, the divisions below don't create
1213 * big jumps when you go from level to level - with int's, it then 1213 * big jumps when you go from level to level - with int's, it then
1214 * becomes big jumps when the sums of the bonuses jump to the next 1214 * becomes big jumps when the sums of the bonuses jump to the next
1215 * step of 8 - with floats, even fractional ones are useful. 1215 * step of 8 - with floats, even fractional ones are useful.
1216 */ 1216 */
1217 sp_tmp=0.0; 1217 sp_tmp=0.0;
1218 for(i=1,op->stats.maxgrace=0;i<=grace_obj->level&&i<=10;i++) { 1218 for(i=1,op->stats.maxgrace=0;i<=grace_obj->level&&i<=10;i++) {
1219 float grace_tmp=0.0; 1219 float grace_tmp=0.0;
1220 1220
1221 /* Got some extra bonus at first level */ 1221 /* Got some extra bonus at first level */
1222 if(i<2) { 1222 if(i<2) {
1223 grace_tmp = op->contr->levgrace[i]+(((float)grace_bonus[op->stats.Pow] + 1223 grace_tmp = op->contr->levgrace[i]+(((float)grace_bonus[op->stats.Pow] +
1224 2.0 * (float)grace_bonus[op->stats.Wis])/6.0); 1224 2.0 * (float)grace_bonus[op->stats.Wis])/6.0);
1225 } else { 1225 } else {
1226 grace_tmp=(float)op->contr->levgrace[i] 1226 grace_tmp=(float)op->contr->levgrace[i]
1227 +((float)grace_bonus[op->stats.Pow] + 1227 +((float)grace_bonus[op->stats.Pow] +
1228 2.0 * (float)grace_bonus[op->stats.Wis])/12.0; 1228 2.0 * (float)grace_bonus[op->stats.Wis])/12.0;
1229 } 1229 }
1230 if (grace_tmp<1.0) grace_tmp=1.0; 1230 if (grace_tmp<1.0) grace_tmp=1.0;
1231 sp_tmp+=grace_tmp; 1231 sp_tmp+=grace_tmp;
1232 } 1232 }
1233 op->stats.maxgrace=(int)sp_tmp; 1233 op->stats.maxgrace=(int)sp_tmp;
1234 1234
1235 /* two grace points per level after 11 */ 1235 /* two grace points per level after 11 */
1236 for(i=11;i<=grace_obj->level;i++) 1236 for(i=11;i<=grace_obj->level;i++)
1237 op->stats.maxgrace+=2; 1237 op->stats.maxgrace+=2;
1238 } 1238 }
1239 /* No limit on grace vs maxgrace */ 1239 /* No limit on grace vs maxgrace */
1240 1240
1241 if(op->contr->braced) { 1241 if(op->contr->braced) {
1242 ac+=2; 1242 ac+=2;
1243 wc+=4; 1243 wc+=4;
1244 } 1244 }
1245 else 1245 else
1246 ac-=dex_bonus[op->stats.Dex]; 1246 ac-=dex_bonus[op->stats.Dex];
1247 1247
1248 /* In new exp/skills system, wc bonuses are related to 1248 /* In new exp/skills system, wc bonuses are related to
1249 * the players level in a relevant exp object (wc_obj) 1249 * the players level in a relevant exp object (wc_obj)
1250 * not the general player level -b.t. 1250 * not the general player level -b.t.
1251 * I changed this slightly so that wc bonuses are better 1251 * I changed this slightly so that wc bonuses are better
1252 * than before. This is to balance out the fact that 1252 * than before. This is to balance out the fact that
1253 * the player no longer gets a personal weapon w/ 1 1253 * the player no longer gets a personal weapon w/ 1
1254 * improvement every level, now its fighterlevel/5. So 1254 * improvement every level, now its fighterlevel/5. So
1255 * we give the player a bonus here in wc and dam 1255 * we give the player a bonus here in wc and dam
1256 * to make up for the change. Note that I left the 1256 * to make up for the change. Note that I left the
1257 * monster bonus the same as before. -b.t. 1257 * monster bonus the same as before. -b.t.
1258 */ 1258 */
1259 1259
1260 if(op->type==PLAYER && wc_obj && wc_obj->level>1) { 1260 if(op->type==PLAYER && wc_obj && wc_obj->level>1) {
1261 wc-=(wc_obj->level+thaco_bonus[op->stats.Str]); 1261 wc-=(wc_obj->level+thaco_bonus[op->stats.Str]);
1262 for(i=1;i<wc_obj->level;i++) { 1262 for(i=1;i<wc_obj->level;i++) {
1263 /* addtional wc every 6 levels */ 1263 /* addtional wc every 6 levels */
1264 if(!(i%6)) wc--; 1264 if(!(i%6)) wc--;
1265 /* addtional dam every 4 levels. */ 1265 /* addtional dam every 4 levels. */
1266 if(!(i%4) && (dam_bonus[op->stats.Str]>=0)) 1266 if(!(i%4) && (dam_bonus[op->stats.Str]>=0))
1267 op->stats.dam+=(1+(dam_bonus[op->stats.Str]/5)); 1267 op->stats.dam+=(1+(dam_bonus[op->stats.Str]/5));
1268 } 1268 }
1269 } else 1269 } else
1270 wc-=(op->level+thaco_bonus[op->stats.Str]); 1270 wc-=(op->level+thaco_bonus[op->stats.Str]);
1271 1271
1272 op->stats.dam+=dam_bonus[op->stats.Str]; 1272 op->stats.dam+=dam_bonus[op->stats.Str];
1273 1273
1274 if(op->stats.dam<1) 1274 if(op->stats.dam<1)
1275 op->stats.dam=1; 1275 op->stats.dam=1;
1276 1276
1277 op->speed=1.0+speed_bonus[op->stats.Dex]; 1277 op->speed=1.0+speed_bonus[op->stats.Dex];
1278 if (settings.search_items && op->contr->search_str[0]) 1278 if (settings.search_items && op->contr->search_str[0])
1279 op->speed -= 1; 1279 op->speed -= 1;
1280 if (op->attacktype==0) 1280 if (op->attacktype==0)
1281 op->attacktype=op->arch->clone.attacktype; 1281 op->attacktype=op->arch->clone.attacktype;
1282 1282
1283 } /* End if player */ 1283 } /* End if player */
1284 1284
1285 if(added_speed>=0) 1285 if(added_speed>=0)
1286 op->speed+=added_speed/10.0; 1286 op->speed+=added_speed/10.0;
1287 else /* Something wrong here...: */ 1287 else /* Something wrong here...: */
1288 op->speed /= (float)(1.0-added_speed); 1288 op->speed /= (float)(1.0-added_speed);
1289 1289
1290 /* Max is determined by armour */ 1290 /* Max is determined by armour */
1291 if(op->speed>max) 1291 if(op->speed>max)
1292 op->speed=max; 1292 op->speed=max;
1293 1293
1294 if(op->type == PLAYER) { 1294 if(op->type == PLAYER) {
1295 /* f is a number the represents the number of kg above (positive num) 1295 /* f is a number the represents the number of kg above (positive num)
1296 * or below (negative number) that the player is carrying. If above 1296 * or below (negative number) that the player is carrying. If above
1297 * weight limit, then player suffers a speed reduction based on how 1297 * weight limit, then player suffers a speed reduction based on how
1298 * much above he is, and what is max carry is 1298 * much above he is, and what is max carry is
1299 */ 1299 */
1300 f=(op->carrying/1000)-max_carry[op->stats.Str]; 1300 f=(op->carrying/1000)-max_carry[op->stats.Str];
1301 if(f>0) op->speed=op->speed/(1.0+f/max_carry[op->stats.Str]); 1301 if(f>0) op->speed=op->speed/(1.0+f/max_carry[op->stats.Str]);
1302 } 1302 }
1303 1303
1304 op->speed+=bonus_speed/10.0; /* Not affected by limits */ 1304 op->speed+=bonus_speed/10.0; /* Not affected by limits */
1305 1305
1306 /* Put a lower limit on speed. Note with this speed, you move once every 1306 /* Put a lower limit on speed. Note with this speed, you move once every
1309 op->speed = op->speed * speed_reduce_from_disease; 1309 op->speed = op->speed * speed_reduce_from_disease;
1310 1310
1311 if (op->speed<0.01 && op->type==PLAYER) op->speed=0.01; 1311 if (op->speed<0.01 && op->type==PLAYER) op->speed=0.01;
1312 1312
1313 if(op->type == PLAYER) { 1313 if(op->type == PLAYER) {
1314 float M,W,s,D,K,S,M2; 1314 float M,W,s,D,K,S,M2;
1315 1315
1316 /* (This formula was made by vidarl@ifi.uio.no) 1316 /* (This formula was made by vidarl@ifi.uio.no)
1317 * Note that we never used these values again - basically 1317 * Note that we never used these values again - basically
1318 * all of these could be subbed into one big equation, but 1318 * all of these could be subbed into one big equation, but
1319 * that would just be a real pain to read. 1319 * that would just be a real pain to read.
1320 */ 1320 */
1321 M=(max_carry[op->stats.Str]-121)/121.0; 1321 M=(max_carry[op->stats.Str]-121)/121.0;
1322 M2=max_carry[op->stats.Str]/100.0; 1322 M2=max_carry[op->stats.Str]/100.0;
1323 W=weapon_weight/20000.0; 1323 W=weapon_weight/20000.0;
1324 s=2-weapon_speed/10.0; 1324 s=2-weapon_speed/10.0;
1325 D=(op->stats.Dex-14)/14.0; 1325 D=(op->stats.Dex-14)/14.0;
1326 K=1 + M/3.0 - W/(3*M2) + op->speed/5.0 + D/2.0; 1326 K=1 + M/3.0 - W/(3*M2) + op->speed/5.0 + D/2.0;
1327 K*=(4+op->level)/(float)(6+op->level)*1.2; 1327 K*=(4+op->level)/(float)(6+op->level)*1.2;
1328 if(K<=0) K=0.01; 1328 if(K<=0) K=0.01;
1329 S=op->speed/(K*s); 1329 S=op->speed/(K*s);
1330 op->contr->weapon_sp=S; 1330 op->contr->weapon_sp=S;
1331 } 1331 }
1332 /* I want to limit the power of small monsters with big weapons: */ 1332 /* I want to limit the power of small monsters with big weapons: */
1333 if(op->type!=PLAYER&&op->arch!=NULL&& 1333 if(op->type!=PLAYER&&op->arch!=NULL&&
1334 op->stats.dam>op->arch->clone.stats.dam*3) 1334 op->stats.dam>op->arch->clone.stats.dam*3)
1335 op->stats.dam=op->arch->clone.stats.dam*3; 1335 op->stats.dam=op->arch->clone.stats.dam*3;
1336 1336
1337 /* Prevent overflows of wc - best you can get is ABS(120) - this 1337 /* Prevent overflows of wc - best you can get is ABS(120) - this
1338 * should be more than enough - remember, AC is also in 8 bits, 1338 * should be more than enough - remember, AC is also in 8 bits,
1339 * so its value is the same. 1339 * so its value is the same.
1340 */ 1340 */
1372 */ 1372 */
1373 1373
1374int allowed_class(const object *op) { 1374int allowed_class(const object *op) {
1375 return op->stats.Dex>0&&op->stats.Str>0&&op->stats.Con>0&& 1375 return op->stats.Dex>0&&op->stats.Str>0&&op->stats.Con>0&&
1376 op->stats.Int>0&&op->stats.Wis>0&&op->stats.Pow>0&& 1376 op->stats.Int>0&&op->stats.Wis>0&&op->stats.Pow>0&&
1377 op->stats.Cha>0; 1377 op->stats.Cha>0;
1378} 1378}
1379 1379
1380/* 1380/*
1381 * set the new dragon name after gaining levels or 1381 * set the new dragon name after gaining levels or
1382 * changing ability focus (later this can be extended to 1382 * changing ability focus (later this can be extended to
1396 if (!abil || !skin) return; 1396 if (!abil || !skin) return;
1397 1397
1398 /* first, look for the highest level */ 1398 /* first, look for the highest level */
1399 for(i=0; i<NROFATTACKS; i++) { 1399 for(i=0; i<NROFATTACKS; i++) {
1400 if (atnr_is_dragon_enabled(i) && 1400 if (atnr_is_dragon_enabled(i) &&
1401 (atnr==-1 || abil->resist[i] > abil->resist[atnr])) { 1401 (atnr==-1 || abil->resist[i] > abil->resist[atnr])) {
1402 level = abil->resist[i]; 1402 level = abil->resist[i];
1403 atnr = i; 1403 atnr = i;
1404 } 1404 }
1405 } 1405 }
1406 1406
1423 else if (level == 3) 1423 else if (level == 3)
1424 sprintf(pl->contr->title, "%s dragon", attacks[atnr]); 1424 sprintf(pl->contr->title, "%s dragon", attacks[atnr]);
1425 else { 1425 else {
1426 /* special titles for extra high resistance! */ 1426 /* special titles for extra high resistance! */
1427 if (skin->resist[atnr] > 80) 1427 if (skin->resist[atnr] > 80)
1428 sprintf(pl->contr->title, "legendary %s dragon", attacks[atnr]); 1428 sprintf(pl->contr->title, "legendary %s dragon", attacks[atnr]);
1429 else if (skin->resist[atnr] > 50) 1429 else if (skin->resist[atnr] > 50)
1430 sprintf(pl->contr->title, "ancient %s dragon", attacks[atnr]); 1430 sprintf(pl->contr->title, "ancient %s dragon", attacks[atnr]);
1431 else 1431 else
1432 sprintf(pl->contr->title, "big %s dragon", attacks[atnr]); 1432 sprintf(pl->contr->title, "big %s dragon", attacks[atnr]);
1433 } 1433 }
1434 } 1434 }
1435 1435
1436 strcpy(pl->contr->own_title, ""); 1436 strcpy(pl->contr->own_title, "");
1437} 1437}
1447 object *tmp = NULL; /* tmp. object */ 1447 object *tmp = NULL; /* tmp. object */
1448 char buf[MAX_BUF]; /* tmp. string buffer */ 1448 char buf[MAX_BUF]; /* tmp. string buffer */
1449 1449
1450 /* now grab the 'dragon_ability'-forces from the player's inventory */ 1450 /* now grab the 'dragon_ability'-forces from the player's inventory */
1451 for (tmp=who->inv; tmp!=NULL; tmp=tmp->below) { 1451 for (tmp=who->inv; tmp!=NULL; tmp=tmp->below) {
1452 if (tmp->type == FORCE) { 1452 if (tmp->type == FORCE) {
1453 if (strcmp(tmp->arch->name, "dragon_ability_force")==0) 1453 if (strcmp(tmp->arch->name, "dragon_ability_force")==0)
1454 abil = tmp; 1454 abil = tmp;
1455 if (strcmp(tmp->arch->name, "dragon_skin_force")==0) 1455 if (strcmp(tmp->arch->name, "dragon_skin_force")==0)
1456 skin = tmp; 1456 skin = tmp;
1457 } 1457 }
1458 } 1458 }
1459 /* if the force is missing -> bail out */ 1459 /* if the force is missing -> bail out */
1460 if (abil == NULL) return; 1460 if (abil == NULL) return;
1461 1461
1462 /* The ability_force keeps track of maximum level ever achieved. 1462 /* The ability_force keeps track of maximum level ever achieved.
1463 * New abilties can only be gained by surpassing this max level 1463 * New abilties can only be gained by surpassing this max level
1464 */ 1464 */
1465 if (who->level > abil->level) { 1465 if (who->level > abil->level) {
1466 /* increase our focused ability */ 1466 /* increase our focused ability */
1467 abil->resist[abil->stats.exp]++; 1467 abil->resist[abil->stats.exp]++;
1468 1468
1469 1469
1470 if (abil->resist[abil->stats.exp]>0 && abil->resist[abil->stats.exp]%5 == 0) { 1470 if (abil->resist[abil->stats.exp]>0 && abil->resist[abil->stats.exp]%5 == 0) {
1471 /* time to hand out a new ability-gift */ 1471 /* time to hand out a new ability-gift */
1472 dragon_ability_gain(who, (int)abil->stats.exp, 1472 dragon_ability_gain(who, (int)abil->stats.exp,
1473 (int)((1+abil->resist[abil->stats.exp])/5.)); 1473 (int)((1+abil->resist[abil->stats.exp])/5.));
1474 } 1474 }
1475 1475
1476 if (abil->last_eat > 0 && atnr_is_dragon_enabled(abil->last_eat)) { 1476 if (abil->last_eat > 0 && atnr_is_dragon_enabled(abil->last_eat)) {
1477 /* apply new ability focus */ 1477 /* apply new ability focus */
1478 sprintf(buf, "Your metabolism now focuses on %s!", 1478 sprintf(buf, "Your metabolism now focuses on %s!",
1479 change_resist_msg[abil->last_eat]); 1479 change_resist_msg[abil->last_eat]);
1480 new_draw_info(NDI_UNIQUE|NDI_BLUE, 0, who, buf); 1480 new_draw_info(NDI_UNIQUE|NDI_BLUE, 0, who, buf);
1481 1481
1482 abil->stats.exp = abil->last_eat; 1482 abil->stats.exp = abil->last_eat;
1483 abil->last_eat = 0; 1483 abil->last_eat = 0;
1484 } 1484 }
1485 1485
1486 abil->level = who->level; 1486 abil->level = who->level;
1487 } 1487 }
1488 1488
1489 /* last but not least, set the new title for the dragon */ 1489 /* last but not least, set the new title for the dragon */
1490 set_dragon_name(who, abil, skin); 1490 set_dragon_name(who, abil, skin);
1491} 1491}
1500{ 1500{
1501 object *skill_obj; 1501 object *skill_obj;
1502 1502
1503 skill_obj = get_archetype_by_skill_name(skill_name, SKILL); 1503 skill_obj = get_archetype_by_skill_name(skill_name, SKILL);
1504 if (!skill_obj) { 1504 if (!skill_obj) {
1505 LOG(llevError, "add_player_exp: couldn't find skill %s\n", skill_name); 1505 LOG(llevError, "add_player_exp: couldn't find skill %s\n", skill_name);
1506 return NULL; 1506 return NULL;
1507 } 1507 }
1508 /* clear the flag - exp goes into this bucket, but player 1508 /* clear the flag - exp goes into this bucket, but player
1509 * still doesn't know it. 1509 * still doesn't know it.
1510 */ 1510 */
1511 CLEAR_FLAG(skill_obj, FLAG_CAN_USE_SKILL); 1511 CLEAR_FLAG(skill_obj, FLAG_CAN_USE_SKILL);
1512 skill_obj->stats.exp = 0; 1512 skill_obj->stats.exp = 0;
1513 skill_obj->level = 1; 1513 skill_obj->level = 1;
1514 insert_ob_in_ob(skill_obj, op); 1514 insert_ob_in_ob(skill_obj, op);
1515 if (op->contr) { 1515 if (op->contr) {
1516 op->contr->last_skill_ob[skill_obj->subtype] = skill_obj; 1516 op->contr->last_skill_ob[skill_obj->subtype] = skill_obj;
1517 op->contr->last_skill_exp[skill_obj->subtype] = -1; 1517 op->contr->last_skill_exp[skill_obj->subtype] = -1;
1518 } 1518 }
1519 return skill_obj; 1519 return skill_obj;
1520} 1520}
1521 1521
1522 1522
1529 */ 1529 */
1530void player_lvl_adj(object *who, object *op) { 1530void player_lvl_adj(object *who, object *op) {
1531 char buf[MAX_BUF]; 1531 char buf[MAX_BUF];
1532 1532
1533 if(!op) /* when rolling stats */ 1533 if(!op) /* when rolling stats */
1534 op = who; 1534 op = who;
1535 1535
1536 if(op->level < settings.max_level && op->stats.exp >= level_exp(op->level+1,who->expmul)) { 1536 if(op->level < settings.max_level && op->stats.exp >= level_exp(op->level+1,who->expmul)) {
1537 op->level++; 1537 op->level++;
1538 1538
1539 if (op != NULL && op == who && op->stats.exp > 1 && is_dragon_pl(who)) 1539 if (op != NULL && op == who && op->stats.exp > 1 && is_dragon_pl(who))
1540 dragon_level_gain(who); 1540 dragon_level_gain(who);
1541 1541
1542 /* Only roll these if it is the player (who) that gained the level */ 1542 /* Only roll these if it is the player (who) that gained the level */
1543 if(op==who && (who->level < 11) && who->type==PLAYER) { 1543 if(op==who && (who->level < 11) && who->type==PLAYER) {
1544 who->contr->levhp[who->level] = die_roll(2, 4, who, PREFER_HIGH)+1; 1544 who->contr->levhp[who->level] = die_roll(2, 4, who, PREFER_HIGH)+1;
1545 who->contr->levsp[who->level] = die_roll(2, 3, who, PREFER_HIGH); 1545 who->contr->levsp[who->level] = die_roll(2, 3, who, PREFER_HIGH);
1546 who->contr->levgrace[who->level]=die_roll(2, 2, who, PREFER_HIGH)-1; 1546 who->contr->levgrace[who->level]=die_roll(2, 2, who, PREFER_HIGH)-1;
1547 } 1547 }
1548 1548
1549 fix_player(who); 1549 fix_player(who);
1550 if(op->level>1) { 1550 if(op->level>1) {
1551 if (op->type!=PLAYER) 1551 if (op->type!=PLAYER)
1552 sprintf(buf,"You are now level %d in the %s skill.",op->level,op->name); 1552 sprintf(buf,"You are now level %d in the %s skill.",op->level,op->name);
1553 else 1553 else
1554 sprintf(buf,"You are now level %d.",op->level); 1554 sprintf(buf,"You are now level %d.",op->level);
1555 if(who) new_draw_info(NDI_UNIQUE|NDI_RED, 0, who,buf); 1555 if(who) new_draw_info(NDI_UNIQUE|NDI_RED, 0, who,buf);
1556 } 1556 }
1557 player_lvl_adj(who,op); /* To increase more levels */ 1557 player_lvl_adj(who,op); /* To increase more levels */
1558 } else if (op->level>1 && op->stats.exp<level_exp(op->level,who->expmul)) { 1558 } else if (op->level>1 && op->stats.exp<level_exp(op->level,who->expmul)) {
1559 op->level--; 1559 op->level--;
1560 fix_player(who); 1560 fix_player(who);
1561 if(op->type!=PLAYER) { 1561 if(op->type!=PLAYER) {
1562 sprintf(buf,"You are now level %d in the %s skill.",op->level,op->name); 1562 sprintf(buf,"You are now level %d in the %s skill.",op->level,op->name);
1563 new_draw_info(NDI_UNIQUE|NDI_RED, 0, who,buf); 1563 new_draw_info(NDI_UNIQUE|NDI_RED, 0, who,buf);
1564 } 1564 }
1565 player_lvl_adj(who,op); /* To decrease more levels */ 1565 player_lvl_adj(who,op); /* To decrease more levels */
1566 } 1566 }
1567 /* check if the spell data has changed */ 1567 /* check if the spell data has changed */
1568 esrv_update_spells(who->contr); 1568 esrv_update_spells(who->contr);
1569} 1569}
1570 1570
1573 * the given level. level should really never exceed max_level 1573 * the given level. level should really never exceed max_level
1574 */ 1574 */
1575 1575
1576sint64 level_exp(int level,double expmul) { 1576sint64 level_exp(int level,double expmul) {
1577 if (level > settings.max_level) 1577 if (level > settings.max_level)
1578 return (sint64) (expmul * levels[settings.max_level]); 1578 return (sint64) (expmul * levels[settings.max_level]);
1579 return (sint64) (expmul * levels[level]); 1579 return (sint64) (expmul * levels[level]);
1580} 1580}
1581 1581
1582/* 1582/*
1583 * Ensure that the permanent experience requirements in an exp object are met. 1583 * Ensure that the permanent experience requirements in an exp object are met.
1627 * We do a shortcut/time saving mechanism first - see if it matches 1627 * We do a shortcut/time saving mechanism first - see if it matches
1628 * chosen_skill. This means we don't need to search through 1628 * chosen_skill. This means we don't need to search through
1629 * the players inventory. 1629 * the players inventory.
1630 */ 1630 */
1631 if (skill_name) { 1631 if (skill_name) {
1632 if (op->chosen_skill && op->chosen_skill->type == SKILL && 1632 if (op->chosen_skill && op->chosen_skill->type == SKILL &&
1633 !strcmp(skill_name, op->chosen_skill->skill)) 1633 !strcmp(skill_name, op->chosen_skill->skill))
1634 skill_obj = op->chosen_skill; 1634 skill_obj = op->chosen_skill;
1635 else { 1635 else {
1636 for (i=0; i<NUM_SKILLS; i++) 1636 for (i=0; i<NUM_SKILLS; i++)
1637 if (op->contr->last_skill_ob[i] && 1637 if (op->contr->last_skill_ob[i] &&
1638 !strcmp(op->contr->last_skill_ob[i]->skill, skill_name)) { 1638 !strcmp(op->contr->last_skill_ob[i]->skill, skill_name)) {
1639 skill_obj = op->contr->last_skill_ob[i]; 1639 skill_obj = op->contr->last_skill_ob[i];
1640 break; 1640 break;
1641 } 1641 }
1642 1642
1643 /* Player doesn't have the skill. Check to see what to do, and give 1643 /* Player doesn't have the skill. Check to see what to do, and give
1644 * it to the player if necessary 1644 * it to the player if necessary
1645 */ 1645 */
1646 if (!skill_obj) { 1646 if (!skill_obj) {
1647 if (flag == SK_EXP_NONE) return; 1647 if (flag == SK_EXP_NONE) return;
1648 else if (flag == SK_EXP_ADD_SKILL) 1648 else if (flag == SK_EXP_ADD_SKILL)
1649 give_skill_by_name(op, skill_name); 1649 give_skill_by_name(op, skill_name);
1650 } 1650 }
1651 } 1651 }
1652 } 1652 }
1653 1653
1654 /* Basically, you can never gain more experience in one shot 1654 /* Basically, you can never gain more experience in one shot
1655 * than half what you need to gain for next level. 1655 * than half what you need to gain for next level.
1656 */ 1656 */
1658 limit=(levels[op->level+1]-levels[op->level])/2; 1658 limit=(levels[op->level+1]-levels[op->level])/2;
1659 if (exp_to_add > limit) exp_to_add=limit; 1659 if (exp_to_add > limit) exp_to_add=limit;
1660 1660
1661 ADD_EXP(op->stats.exp, (sint64) ((float) exp_to_add * (skill_obj? skill_obj->expmul:1))); 1661 ADD_EXP(op->stats.exp, (sint64) ((float) exp_to_add * (skill_obj? skill_obj->expmul:1)));
1662 if (settings.permanent_exp_ratio) { 1662 if (settings.permanent_exp_ratio) {
1663 ADD_EXP(op->perm_exp, (sint64) ((float) exp_to_add * PERM_EXP_GAIN_RATIO * (skill_obj? skill_obj->expmul:1))); 1663 ADD_EXP(op->perm_exp, (sint64) ((float) exp_to_add * PERM_EXP_GAIN_RATIO * (skill_obj? skill_obj->expmul:1)));
1664 calc_perm_exp(op); 1664 calc_perm_exp(op);
1665 } 1665 }
1666 1666
1667 player_lvl_adj(op,NULL); 1667 player_lvl_adj(op,NULL);
1668 if (skill_obj) { 1668 if (skill_obj) {
1669 exp_to_add = exp; 1669 exp_to_add = exp;
1670 limit=(levels[skill_obj->level+1]-levels[skill_obj->level])/2; 1670 limit=(levels[skill_obj->level+1]-levels[skill_obj->level])/2;
1671 if (exp_to_add > limit) exp_to_add=limit; 1671 if (exp_to_add > limit) exp_to_add=limit;
1672 ADD_EXP(skill_obj->stats.exp, exp_to_add); 1672 ADD_EXP(skill_obj->stats.exp, exp_to_add);
1673 if (settings.permanent_exp_ratio) { 1673 if (settings.permanent_exp_ratio) {
1674 skill_obj->perm_exp += (sint64) ((float) exp_to_add * PERM_EXP_GAIN_RATIO); 1674 skill_obj->perm_exp += (sint64) ((float) exp_to_add * PERM_EXP_GAIN_RATIO);
1675 calc_perm_exp(skill_obj); 1675 calc_perm_exp(skill_obj);
1676 } 1676 }
1677 player_lvl_adj(op,skill_obj); 1677 player_lvl_adj(op,skill_obj);
1678 } 1678 }
1679} 1679}
1680 1680
1681/* This function checks to make sure that object 'op' can 1681/* This function checks to make sure that object 'op' can
1682 * lost 'exp' experience. It returns the amount of exp 1682 * lost 'exp' experience. It returns the amount of exp
1690{ 1690{
1691 sint64 del_exp; 1691 sint64 del_exp;
1692 1692
1693 if (exp > op->stats.exp) exp = op->stats.exp; 1693 if (exp > op->stats.exp) exp = op->stats.exp;
1694 if (settings.permanent_exp_ratio) { 1694 if (settings.permanent_exp_ratio) {
1695 del_exp = (sint64) ((op->stats.exp - op->perm_exp) * PERM_EXP_MAX_LOSS_RATIO); 1695 del_exp = (sint64) ((op->stats.exp - op->perm_exp) * PERM_EXP_MAX_LOSS_RATIO);
1696 if (del_exp < 0) del_exp = 0; 1696 if (del_exp < 0) del_exp = 0;
1697 if (exp > del_exp) exp=del_exp; 1697 if (exp > del_exp) exp=del_exp;
1698 } 1698 }
1699 return exp; 1699 return exp;
1700} 1700}
1701 1701
1702sint64 check_exp_adjust(const object *op, sint64 exp) 1702sint64 check_exp_adjust(const object *op, sint64 exp)
1723 float fraction = (float) exp/(float) op->stats.exp; 1723 float fraction = (float) exp/(float) op->stats.exp;
1724 object *tmp; 1724 object *tmp;
1725 sint64 del_exp; 1725 sint64 del_exp;
1726 1726
1727 for(tmp=op->inv;tmp;tmp=tmp->below) 1727 for(tmp=op->inv;tmp;tmp=tmp->below)
1728 if(tmp->type==SKILL && tmp->stats.exp) { 1728 if(tmp->type==SKILL && tmp->stats.exp) {
1729 if (flag == SK_SUBTRACT_SKILL_EXP && skill && !strcmp(tmp->skill, skill)) { 1729 if (flag == SK_SUBTRACT_SKILL_EXP && skill && !strcmp(tmp->skill, skill)) {
1730 del_exp = check_exp_loss(tmp, exp); 1730 del_exp = check_exp_loss(tmp, exp);
1731 tmp->stats.exp -= del_exp; 1731 tmp->stats.exp -= del_exp;
1732 player_lvl_adj(op, tmp); 1732 player_lvl_adj(op, tmp);
1733 } else if (flag != SK_SUBTRACT_SKILL_EXP) { 1733 } else if (flag != SK_SUBTRACT_SKILL_EXP) {
1734 /* only want to process other skills if we are not trying 1734 /* only want to process other skills if we are not trying
1735 * to match a specific skill. 1735 * to match a specific skill.
1736 */ 1736 */
1737 del_exp = check_exp_loss(tmp, (sint64) (tmp->stats.exp * fraction)); 1737 del_exp = check_exp_loss(tmp, (sint64) (tmp->stats.exp * fraction));
1738 tmp->stats.exp -= del_exp; 1738 tmp->stats.exp -= del_exp;
1739 player_lvl_adj(op, tmp); 1739 player_lvl_adj(op, tmp);
1740 } 1740 }
1741 } 1741 }
1742 if (flag != SK_SUBTRACT_SKILL_EXP) { 1742 if (flag != SK_SUBTRACT_SKILL_EXP) {
1743 del_exp = check_exp_loss(op, exp); 1743 del_exp = check_exp_loss(op, exp);
1744 op->stats.exp -= del_exp; 1744 op->stats.exp -= del_exp;
1745 player_lvl_adj(op,NULL); 1745 player_lvl_adj(op,NULL);
1746 } 1746 }
1747} 1747}
1748 1748
1749 1749
1750 1750
1768#endif 1768#endif
1769#endif 1769#endif
1770 1770
1771 /* safety */ 1771 /* safety */
1772 if(!op) { 1772 if(!op) {
1773 LOG(llevError,"change_exp() called for null object!\n"); 1773 LOG(llevError,"change_exp() called for null object!\n");
1774 return; 1774 return;
1775 } 1775 }
1776 1776
1777 /* if no change in exp, just return - most of the below code 1777 /* if no change in exp, just return - most of the below code
1778 * won't do anything if the value is 0 anyways. 1778 * won't do anything if the value is 0 anyways.
1779 */ 1779 */
1783 * don't adjust level, since in most cases it is unrelated to 1783 * don't adjust level, since in most cases it is unrelated to
1784 * the exp they have - the monsters exp represents what its 1784 * the exp they have - the monsters exp represents what its
1785 * worth. 1785 * worth.
1786 */ 1786 */
1787 if(op->type != PLAYER) { 1787 if(op->type != PLAYER) {
1788 /* Sanity check */ 1788 /* Sanity check */
1789 if (!QUERY_FLAG(op, FLAG_ALIVE)) return; 1789 if (!QUERY_FLAG(op, FLAG_ALIVE)) return;
1790 1790
1791 /* reset exp to max allowed value. We subtract from 1791 /* reset exp to max allowed value. We subtract from
1792 * MAX_EXPERIENCE to prevent overflows. If the player somehow has 1792 * MAX_EXPERIENCE to prevent overflows. If the player somehow has
1793 * more than max exp, just return. 1793 * more than max exp, just return.
1794 */ 1794 */
1795 if (exp > 0 && ( op->stats.exp > (MAX_EXPERIENCE - exp))) { 1795 if (exp > 0 && ( op->stats.exp > (MAX_EXPERIENCE - exp))) {
1796 exp = MAX_EXPERIENCE - op->stats.exp; 1796 exp = MAX_EXPERIENCE - op->stats.exp;
1797 if (exp < 0) return; 1797 if (exp < 0) return;
1798 } 1798 }
1799 1799
1800 op->stats.exp += exp; 1800 op->stats.exp += exp;
1801 } 1801 }
1802 else { /* Players only */ 1802 else { /* Players only */
1803 if(exp>0) 1803 if(exp>0)
1804 add_player_exp(op, exp, skill_name, flag); 1804 add_player_exp(op, exp, skill_name, flag);
1805 else 1805 else
1806 /* note that when you lose exp, it doesn't go against 1806 /* note that when you lose exp, it doesn't go against
1807 * a particular skill, so we don't need to pass that 1807 * a particular skill, so we don't need to pass that
1808 * along. 1808 * along.
1809 */ 1809 */
1810 subtract_player_exp(op, FABS(exp), skill_name, flag); 1810 subtract_player_exp(op, FABS(exp), skill_name, flag);
1811 1811
1812 } 1812 }
1813} 1813}
1814 1814
1815/* Applies a death penalty experience, the size of this is defined by the 1815/* Applies a death penalty experience, the size of this is defined by the
1822 sint64 loss; 1822 sint64 loss;
1823 sint64 percentage_loss; /* defined by the setting 'death_penalty_percent' */ 1823 sint64 percentage_loss; /* defined by the setting 'death_penalty_percent' */
1824 sint64 level_loss; /* defined by the setting 'death_penalty_levels */ 1824 sint64 level_loss; /* defined by the setting 'death_penalty_levels */
1825 1825
1826 for(tmp=op->inv;tmp;tmp=tmp->below) 1826 for(tmp=op->inv;tmp;tmp=tmp->below)
1827 if(tmp->type==SKILL && tmp->stats.exp) { 1827 if(tmp->type==SKILL && tmp->stats.exp) {
1828 1828
1829 percentage_loss = tmp->stats.exp * settings.death_penalty_ratio/100; 1829 percentage_loss = tmp->stats.exp * settings.death_penalty_ratio/100;
1830 level_loss = tmp->stats.exp - levels[MAX(0,tmp->level - settings.death_penalty_level)]; 1830 level_loss = tmp->stats.exp - levels[MAX(0,tmp->level - settings.death_penalty_level)];
1831 1831
1832 /* With the revised exp system, you can get cases where 1832 /* With the revised exp system, you can get cases where
1833 * losing several levels would still require that you have more 1833 * losing several levels would still require that you have more
1834 * exp than you currently have - this is true if the levels 1834 * exp than you currently have - this is true if the levels
1835 * tables is a lot harder. 1835 * tables is a lot harder.
1836 */ 1836 */
1837 if (level_loss < 0) level_loss = 0; 1837 if (level_loss < 0) level_loss = 0;
1838 1838
1839 loss = check_exp_loss(tmp, MIN(level_loss, percentage_loss)); 1839 loss = check_exp_loss(tmp, MIN(level_loss, percentage_loss));
1840 1840
1841 tmp->stats.exp -= loss; 1841 tmp->stats.exp -= loss;
1842 player_lvl_adj(op,tmp); 1842 player_lvl_adj(op,tmp);
1843 } 1843 }
1844 1844
1845 percentage_loss = op->stats.exp * settings.death_penalty_ratio/100; 1845 percentage_loss = op->stats.exp * settings.death_penalty_ratio/100;
1846 level_loss = op->stats.exp - levels[MAX(0,op->level - settings.death_penalty_level)]; 1846 level_loss = op->stats.exp - levels[MAX(0,op->level - settings.death_penalty_level)];
1847 if (level_loss < 0) level_loss = 0; 1847 if (level_loss < 0) level_loss = 0;
1848 loss = check_exp_loss(op, MIN(level_loss, percentage_loss)); 1848 loss = check_exp_loss(op, MIN(level_loss, percentage_loss));
1861int did_make_save(const object *op, int level, int bonus) 1861int did_make_save(const object *op, int level, int bonus)
1862{ 1862{
1863 if (level > MAX_SAVE_LEVEL) level = MAX_SAVE_LEVEL; 1863 if (level > MAX_SAVE_LEVEL) level = MAX_SAVE_LEVEL;
1864 1864
1865 if ((random_roll(1, 20, op, PREFER_HIGH) + bonus) < savethrow[level]) 1865 if ((random_roll(1, 20, op, PREFER_HIGH) + bonus) < savethrow[level])
1866 return 0; 1866 return 0;
1867 return 1; 1867 return 1;
1868} 1868}
1869 1869

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines