1 | /* |
1 | /* |
2 | * static char *rcsid_living_c = |
2 | * static char *rcsid_living_c = |
3 | * "$Id: living.C,v 1.1 2006/08/13 17:16:00 elmex Exp $"; |
3 | * "$Id: living.C,v 1.4 2006/09/01 17:16:47 elmex 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 | }; |
217 | const char *const gain_msg[NUM_STATS] = { |
217 | const 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 | }; |
226 | const char *const lose_msg[NUM_STATS] = { |
226 | const 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 | |
236 | const char *const statname[NUM_STATS] = { |
236 | const 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 | evt = find_event(tmp,EVENT_ATTACK); |
|
|
1089 | if (evt != NULL) { |
|
|
1090 | if (op->current_weapon_script) |
|
|
1091 | free_string(op->current_weapon_script); |
|
|
1092 | op->current_weapon_script=add_string(query_name(tmp)); |
|
|
1093 | } |
|
|
1094 | op->current_weapon = tmp; |
1088 | op->current_weapon = tmp; |
1095 | if(settings.spell_encumbrance == TRUE && op->type==PLAYER) |
1089 | if(settings.spell_encumbrance == TRUE && op->type==PLAYER) |
1096 | op->contr->encumbrance+=(int)3*tmp->weight/1000; |
1090 | op->contr->encumbrance+=(int)3*tmp->weight/1000; |
1097 | break; |
1091 | break; |
1098 | |
1092 | |
1099 | case ARMOUR: /* Only the best of these three are used: */ |
1093 | case ARMOUR: /* Only the best of these three are used: */ |
1100 | if(settings.spell_encumbrance == TRUE && op->type==PLAYER) |
1094 | if(settings.spell_encumbrance == TRUE && op->type==PLAYER) |
1101 | op->contr->encumbrance+=(int)tmp->weight/1000; |
1095 | op->contr->encumbrance+=(int)tmp->weight/1000; |
1102 | |
1096 | |
1103 | case BRACERS: |
1097 | case BRACERS: |
1104 | case FORCE: |
1098 | case FORCE: |
1105 | if(tmp->stats.wc) { |
1099 | if(tmp->stats.wc) { |
1106 | if(best_wc<tmp->stats.wc+tmp->magic) { |
1100 | if(best_wc<tmp->stats.wc+tmp->magic) { |
1107 | wc+=best_wc; |
1101 | wc+=best_wc; |
1108 | best_wc=tmp->stats.wc+tmp->magic; |
1102 | best_wc=tmp->stats.wc+tmp->magic; |
1109 | } else |
1103 | } else |
1110 | wc+=tmp->stats.wc+tmp->magic; |
1104 | wc+=tmp->stats.wc+tmp->magic; |
1111 | } |
1105 | } |
1112 | if(tmp->stats.ac) { |
1106 | if(tmp->stats.ac) { |
1113 | if(best_ac<tmp->stats.ac+tmp->magic) { |
1107 | if(best_ac<tmp->stats.ac+tmp->magic) { |
1114 | ac+=best_ac; /* Remove last bonus */ |
1108 | ac+=best_ac; /* Remove last bonus */ |
1115 | best_ac=tmp->stats.ac+tmp->magic; |
1109 | best_ac=tmp->stats.ac+tmp->magic; |
1116 | } |
1110 | } |
1117 | else /* To nullify the below effect */ |
1111 | else /* To nullify the below effect */ |
1118 | ac+=tmp->stats.ac+tmp->magic; |
1112 | ac+=tmp->stats.ac+tmp->magic; |
1119 | } |
1113 | } |
1120 | if(tmp->stats.wc) wc-=(tmp->stats.wc+tmp->magic); |
1114 | if(tmp->stats.wc) wc-=(tmp->stats.wc+tmp->magic); |
1121 | if(tmp->stats.ac) ac-=(tmp->stats.ac+tmp->magic); |
1115 | if(tmp->stats.ac) ac-=(tmp->stats.ac+tmp->magic); |
1122 | if(ARMOUR_SPEED(tmp)&&ARMOUR_SPEED(tmp)/10.0<max) |
1116 | if(ARMOUR_SPEED(tmp)&&ARMOUR_SPEED(tmp)/10.0<max) |
1123 | max=ARMOUR_SPEED(tmp)/10.0; |
1117 | max=ARMOUR_SPEED(tmp)/10.0; |
1124 | break; |
1118 | break; |
1125 | } /* switch tmp->type */ |
1119 | } /* switch tmp->type */ |
1126 | } /* item is equipped */ |
1120 | } /* item is equipped */ |
1127 | } /* for loop of items */ |
1121 | } /* for loop of items */ |
1128 | |
1122 | |
1129 | /* 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 |
1130 | * have generated intermediate values which we now need to assign. |
1124 | * have generated intermediate values which we now need to assign. |
1131 | */ |
1125 | */ |
… | |
… | |
1135 | * than that, we take: 'total resistance = resistance from potion'. |
1129 | * than that, we take: 'total resistance = resistance from potion'. |
1136 | * 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 |
1137 | * 'total resistance = vulnerability from cursed potion'. |
1131 | * 'total resistance = vulnerability from cursed potion'. |
1138 | */ |
1132 | */ |
1139 | for (i=0; i<NROFATTACKS; i++) { |
1133 | for (i=0; i<NROFATTACKS; i++) { |
1140 | op->resist[i] = prot[i] - vuln[i]; |
1134 | op->resist[i] = prot[i] - vuln[i]; |
1141 | if (potion_resist[i] && ((potion_resist[i] > op->resist[i]) || |
1135 | if (potion_resist[i] && ((potion_resist[i] > op->resist[i]) || |
1142 | (potion_resist[i] < 0))) |
1136 | (potion_resist[i] < 0))) |
1143 | op->resist[i] = potion_resist[i]; |
1137 | op->resist[i] = potion_resist[i]; |
1144 | } |
1138 | } |
1145 | |
1139 | |
1146 | /* Figure out the players sp/mana/hp totals. */ |
1140 | /* Figure out the players sp/mana/hp totals. */ |
1147 | if(op->type==PLAYER) { |
1141 | if(op->type==PLAYER) { |
1148 | int pl_level; |
1142 | int pl_level; |
1149 | |
1143 | |
1150 | check_stat_bounds(&(op->stats)); |
1144 | check_stat_bounds(&(op->stats)); |
1151 | pl_level=op->level; |
1145 | pl_level=op->level; |
1152 | |
1146 | |
1153 | 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! */ |
1154 | |
1148 | |
1155 | /* 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, |
1156 | * 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. |
1157 | */ |
1151 | */ |
1158 | 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++) { |
1159 | j=op->contr->levhp[i]+con_bonus[op->stats.Con]/2; |
1153 | j=op->contr->levhp[i]+con_bonus[op->stats.Con]/2; |
1160 | if(i%2 && con_bonus[op->stats.Con]%2) { |
1154 | if(i%2 && con_bonus[op->stats.Con]%2) { |
1161 | if (con_bonus[op->stats.Con]>0) |
1155 | if (con_bonus[op->stats.Con]>0) |
1162 | j++; |
1156 | j++; |
1163 | else |
1157 | else |
1164 | j--; |
1158 | j--; |
1165 | } |
1159 | } |
1166 | 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 */ |
1167 | } |
1161 | } |
1168 | |
1162 | |
1169 | for(i=11;i<=op->level;i++) |
1163 | for(i=11;i<=op->level;i++) |
1170 | op->stats.maxhp+=2; |
1164 | op->stats.maxhp+=2; |
1171 | |
1165 | |
1172 | if(op->stats.hp>op->stats.maxhp) |
1166 | if(op->stats.hp>op->stats.maxhp) |
1173 | op->stats.hp=op->stats.maxhp; |
1167 | op->stats.hp=op->stats.maxhp; |
1174 | |
1168 | |
1175 | /* Sp gain is controlled by the level of the player's |
1169 | /* Sp gain is controlled by the level of the player's |
1176 | * relevant experience object (mana_obj, see above) |
1170 | * relevant experience object (mana_obj, see above) |
1177 | */ |
1171 | */ |
1178 | /* following happen when skills system is not used */ |
1172 | /* following happen when skills system is not used */ |
1179 | if(!mana_obj) mana_obj = op; |
1173 | if(!mana_obj) mana_obj = op; |
1180 | if(!grace_obj) grace_obj = op; |
1174 | if(!grace_obj) grace_obj = op; |
1181 | /* set maxsp */ |
1175 | /* set maxsp */ |
1182 | 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; |
1183 | |
1177 | |
1184 | if (mana_obj == op && op->type == PLAYER) { |
1178 | if (mana_obj == op && op->type == PLAYER) { |
1185 | op->stats.maxsp = 1; |
1179 | op->stats.maxsp = 1; |
1186 | } else { |
1180 | } else { |
1187 | sp_tmp=0.0; |
1181 | sp_tmp=0.0; |
1188 | for(i=1;i<=mana_obj->level&&i<=10;i++) { |
1182 | for(i=1;i<=mana_obj->level&&i<=10;i++) { |
1189 | float stmp; |
1183 | float stmp; |
1190 | |
1184 | |
1191 | /* Got some extra bonus at first level */ |
1185 | /* Got some extra bonus at first level */ |
1192 | if(i<2) { |
1186 | if(i<2) { |
1193 | 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] + |
1194 | (float)sp_bonus[op->stats.Int])/6.0); |
1188 | (float)sp_bonus[op->stats.Int])/6.0); |
1195 | } else { |
1189 | } else { |
1196 | stmp=(float)op->contr->levsp[i] |
1190 | stmp=(float)op->contr->levsp[i] |
1197 | +(2.0 * (float)sp_bonus[op->stats.Pow] + |
1191 | +(2.0 * (float)sp_bonus[op->stats.Pow] + |
1198 | (float)sp_bonus[op->stats.Int])/12.0; |
1192 | (float)sp_bonus[op->stats.Int])/12.0; |
1199 | } |
1193 | } |
1200 | if (stmp<1.0) stmp=1.0; |
1194 | if (stmp<1.0) stmp=1.0; |
1201 | sp_tmp+=stmp; |
1195 | sp_tmp+=stmp; |
1202 | } |
1196 | } |
1203 | op->stats.maxsp=(int)sp_tmp; |
1197 | op->stats.maxsp=(int)sp_tmp; |
1204 | |
1198 | |
1205 | for(i=11;i<=mana_obj->level;i++) |
1199 | for(i=11;i<=mana_obj->level;i++) |
1206 | op->stats.maxsp+=2; |
1200 | op->stats.maxsp+=2; |
1207 | } |
1201 | } |
1208 | /* Characters can get their sp supercharged via rune of transferrance */ |
1202 | /* Characters can get their sp supercharged via rune of transferrance */ |
1209 | if(op->stats.sp>op->stats.maxsp*2) |
1203 | if(op->stats.sp>op->stats.maxsp*2) |
1210 | op->stats.sp=op->stats.maxsp*2; |
1204 | op->stats.sp=op->stats.maxsp*2; |
1211 | |
1205 | |
1212 | /* 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 */ |
1213 | 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; |
1214 | |
1208 | |
1215 | if (grace_obj == op && op->type == PLAYER) { |
1209 | if (grace_obj == op && op->type == PLAYER) { |
1216 | op->stats.maxgrace = 1; |
1210 | op->stats.maxgrace = 1; |
1217 | } else { |
1211 | } else { |
1218 | /* 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 |
1219 | * 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 |
1220 | * 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 |
1221 | * step of 8 - with floats, even fractional ones are useful. |
1215 | * step of 8 - with floats, even fractional ones are useful. |
1222 | */ |
1216 | */ |
1223 | sp_tmp=0.0; |
1217 | sp_tmp=0.0; |
1224 | 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++) { |
1225 | float grace_tmp=0.0; |
1219 | float grace_tmp=0.0; |
1226 | |
1220 | |
1227 | /* Got some extra bonus at first level */ |
1221 | /* Got some extra bonus at first level */ |
1228 | if(i<2) { |
1222 | if(i<2) { |
1229 | 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] + |
1230 | 2.0 * (float)grace_bonus[op->stats.Wis])/6.0); |
1224 | 2.0 * (float)grace_bonus[op->stats.Wis])/6.0); |
1231 | } else { |
1225 | } else { |
1232 | grace_tmp=(float)op->contr->levgrace[i] |
1226 | grace_tmp=(float)op->contr->levgrace[i] |
1233 | +((float)grace_bonus[op->stats.Pow] + |
1227 | +((float)grace_bonus[op->stats.Pow] + |
1234 | 2.0 * (float)grace_bonus[op->stats.Wis])/12.0; |
1228 | 2.0 * (float)grace_bonus[op->stats.Wis])/12.0; |
1235 | } |
1229 | } |
1236 | if (grace_tmp<1.0) grace_tmp=1.0; |
1230 | if (grace_tmp<1.0) grace_tmp=1.0; |
1237 | sp_tmp+=grace_tmp; |
1231 | sp_tmp+=grace_tmp; |
1238 | } |
1232 | } |
1239 | op->stats.maxgrace=(int)sp_tmp; |
1233 | op->stats.maxgrace=(int)sp_tmp; |
1240 | |
1234 | |
1241 | /* two grace points per level after 11 */ |
1235 | /* two grace points per level after 11 */ |
1242 | for(i=11;i<=grace_obj->level;i++) |
1236 | for(i=11;i<=grace_obj->level;i++) |
1243 | op->stats.maxgrace+=2; |
1237 | op->stats.maxgrace+=2; |
1244 | } |
1238 | } |
1245 | /* No limit on grace vs maxgrace */ |
1239 | /* No limit on grace vs maxgrace */ |
1246 | |
1240 | |
1247 | if(op->contr->braced) { |
1241 | if(op->contr->braced) { |
1248 | ac+=2; |
1242 | ac+=2; |
1249 | wc+=4; |
1243 | wc+=4; |
1250 | } |
1244 | } |
1251 | else |
1245 | else |
1252 | ac-=dex_bonus[op->stats.Dex]; |
1246 | ac-=dex_bonus[op->stats.Dex]; |
1253 | |
1247 | |
1254 | /* In new exp/skills system, wc bonuses are related to |
1248 | /* In new exp/skills system, wc bonuses are related to |
1255 | * the players level in a relevant exp object (wc_obj) |
1249 | * the players level in a relevant exp object (wc_obj) |
1256 | * not the general player level -b.t. |
1250 | * not the general player level -b.t. |
1257 | * I changed this slightly so that wc bonuses are better |
1251 | * I changed this slightly so that wc bonuses are better |
1258 | * than before. This is to balance out the fact that |
1252 | * than before. This is to balance out the fact that |
1259 | * the player no longer gets a personal weapon w/ 1 |
1253 | * the player no longer gets a personal weapon w/ 1 |
1260 | * improvement every level, now its fighterlevel/5. So |
1254 | * improvement every level, now its fighterlevel/5. So |
1261 | * we give the player a bonus here in wc and dam |
1255 | * we give the player a bonus here in wc and dam |
1262 | * to make up for the change. Note that I left the |
1256 | * to make up for the change. Note that I left the |
1263 | * monster bonus the same as before. -b.t. |
1257 | * monster bonus the same as before. -b.t. |
1264 | */ |
1258 | */ |
1265 | |
1259 | |
1266 | if(op->type==PLAYER && wc_obj && wc_obj->level>1) { |
1260 | if(op->type==PLAYER && wc_obj && wc_obj->level>1) { |
1267 | wc-=(wc_obj->level+thaco_bonus[op->stats.Str]); |
1261 | wc-=(wc_obj->level+thaco_bonus[op->stats.Str]); |
1268 | for(i=1;i<wc_obj->level;i++) { |
1262 | for(i=1;i<wc_obj->level;i++) { |
1269 | /* addtional wc every 6 levels */ |
1263 | /* addtional wc every 6 levels */ |
1270 | if(!(i%6)) wc--; |
1264 | if(!(i%6)) wc--; |
1271 | /* addtional dam every 4 levels. */ |
1265 | /* addtional dam every 4 levels. */ |
1272 | if(!(i%4) && (dam_bonus[op->stats.Str]>=0)) |
1266 | if(!(i%4) && (dam_bonus[op->stats.Str]>=0)) |
1273 | op->stats.dam+=(1+(dam_bonus[op->stats.Str]/5)); |
1267 | op->stats.dam+=(1+(dam_bonus[op->stats.Str]/5)); |
1274 | } |
1268 | } |
1275 | } else |
1269 | } else |
1276 | wc-=(op->level+thaco_bonus[op->stats.Str]); |
1270 | wc-=(op->level+thaco_bonus[op->stats.Str]); |
1277 | |
1271 | |
1278 | op->stats.dam+=dam_bonus[op->stats.Str]; |
1272 | op->stats.dam+=dam_bonus[op->stats.Str]; |
1279 | |
1273 | |
1280 | if(op->stats.dam<1) |
1274 | if(op->stats.dam<1) |
1281 | op->stats.dam=1; |
1275 | op->stats.dam=1; |
1282 | |
1276 | |
1283 | op->speed=1.0+speed_bonus[op->stats.Dex]; |
1277 | op->speed=1.0+speed_bonus[op->stats.Dex]; |
1284 | if (settings.search_items && op->contr->search_str[0]) |
1278 | if (settings.search_items && op->contr->search_str[0]) |
1285 | op->speed -= 1; |
1279 | op->speed -= 1; |
1286 | if (op->attacktype==0) |
1280 | if (op->attacktype==0) |
1287 | op->attacktype=op->arch->clone.attacktype; |
1281 | op->attacktype=op->arch->clone.attacktype; |
1288 | |
1282 | |
1289 | } /* End if player */ |
1283 | } /* End if player */ |
1290 | |
1284 | |
1291 | if(added_speed>=0) |
1285 | if(added_speed>=0) |
1292 | op->speed+=added_speed/10.0; |
1286 | op->speed+=added_speed/10.0; |
1293 | else /* Something wrong here...: */ |
1287 | else /* Something wrong here...: */ |
1294 | op->speed /= (float)(1.0-added_speed); |
1288 | op->speed /= (float)(1.0-added_speed); |
1295 | |
1289 | |
1296 | /* Max is determined by armour */ |
1290 | /* Max is determined by armour */ |
1297 | if(op->speed>max) |
1291 | if(op->speed>max) |
1298 | op->speed=max; |
1292 | op->speed=max; |
1299 | |
1293 | |
1300 | if(op->type == PLAYER) { |
1294 | if(op->type == PLAYER) { |
1301 | /* 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) |
1302 | * or below (negative number) that the player is carrying. If above |
1296 | * or below (negative number) that the player is carrying. If above |
1303 | * weight limit, then player suffers a speed reduction based on how |
1297 | * weight limit, then player suffers a speed reduction based on how |
1304 | * much above he is, and what is max carry is |
1298 | * much above he is, and what is max carry is |
1305 | */ |
1299 | */ |
1306 | f=(op->carrying/1000)-max_carry[op->stats.Str]; |
1300 | f=(op->carrying/1000)-max_carry[op->stats.Str]; |
1307 | 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]); |
1308 | } |
1302 | } |
1309 | |
1303 | |
1310 | op->speed+=bonus_speed/10.0; /* Not affected by limits */ |
1304 | op->speed+=bonus_speed/10.0; /* Not affected by limits */ |
1311 | |
1305 | |
1312 | /* 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 |
… | |
… | |
1315 | op->speed = op->speed * speed_reduce_from_disease; |
1309 | op->speed = op->speed * speed_reduce_from_disease; |
1316 | |
1310 | |
1317 | 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; |
1318 | |
1312 | |
1319 | if(op->type == PLAYER) { |
1313 | if(op->type == PLAYER) { |
1320 | float M,W,s,D,K,S,M2; |
1314 | float M,W,s,D,K,S,M2; |
1321 | |
1315 | |
1322 | /* (This formula was made by vidarl@ifi.uio.no) |
1316 | /* (This formula was made by vidarl@ifi.uio.no) |
1323 | * Note that we never used these values again - basically |
1317 | * Note that we never used these values again - basically |
1324 | * all of these could be subbed into one big equation, but |
1318 | * all of these could be subbed into one big equation, but |
1325 | * that would just be a real pain to read. |
1319 | * that would just be a real pain to read. |
1326 | */ |
1320 | */ |
1327 | M=(max_carry[op->stats.Str]-121)/121.0; |
1321 | M=(max_carry[op->stats.Str]-121)/121.0; |
1328 | M2=max_carry[op->stats.Str]/100.0; |
1322 | M2=max_carry[op->stats.Str]/100.0; |
1329 | W=weapon_weight/20000.0; |
1323 | W=weapon_weight/20000.0; |
1330 | s=2-weapon_speed/10.0; |
1324 | s=2-weapon_speed/10.0; |
1331 | D=(op->stats.Dex-14)/14.0; |
1325 | D=(op->stats.Dex-14)/14.0; |
1332 | 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; |
1333 | K*=(4+op->level)/(float)(6+op->level)*1.2; |
1327 | K*=(4+op->level)/(float)(6+op->level)*1.2; |
1334 | if(K<=0) K=0.01; |
1328 | if(K<=0) K=0.01; |
1335 | S=op->speed/(K*s); |
1329 | S=op->speed/(K*s); |
1336 | op->contr->weapon_sp=S; |
1330 | op->contr->weapon_sp=S; |
1337 | } |
1331 | } |
1338 | /* 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: */ |
1339 | if(op->type!=PLAYER&&op->arch!=NULL&& |
1333 | if(op->type!=PLAYER&&op->arch!=NULL&& |
1340 | op->stats.dam>op->arch->clone.stats.dam*3) |
1334 | op->stats.dam>op->arch->clone.stats.dam*3) |
1341 | op->stats.dam=op->arch->clone.stats.dam*3; |
1335 | op->stats.dam=op->arch->clone.stats.dam*3; |
1342 | |
1336 | |
1343 | /* 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 |
1344 | * 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, |
1345 | * so its value is the same. |
1339 | * so its value is the same. |
1346 | */ |
1340 | */ |
… | |
… | |
1378 | */ |
1372 | */ |
1379 | |
1373 | |
1380 | int allowed_class(const object *op) { |
1374 | int allowed_class(const object *op) { |
1381 | 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&& |
1382 | 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&& |
1383 | op->stats.Cha>0; |
1377 | op->stats.Cha>0; |
1384 | } |
1378 | } |
1385 | |
1379 | |
1386 | /* |
1380 | /* |
1387 | * set the new dragon name after gaining levels or |
1381 | * set the new dragon name after gaining levels or |
1388 | * changing ability focus (later this can be extended to |
1382 | * changing ability focus (later this can be extended to |
… | |
… | |
1402 | if (!abil || !skin) return; |
1396 | if (!abil || !skin) return; |
1403 | |
1397 | |
1404 | /* first, look for the highest level */ |
1398 | /* first, look for the highest level */ |
1405 | for(i=0; i<NROFATTACKS; i++) { |
1399 | for(i=0; i<NROFATTACKS; i++) { |
1406 | if (atnr_is_dragon_enabled(i) && |
1400 | if (atnr_is_dragon_enabled(i) && |
1407 | (atnr==-1 || abil->resist[i] > abil->resist[atnr])) { |
1401 | (atnr==-1 || abil->resist[i] > abil->resist[atnr])) { |
1408 | level = abil->resist[i]; |
1402 | level = abil->resist[i]; |
1409 | atnr = i; |
1403 | atnr = i; |
1410 | } |
1404 | } |
1411 | } |
1405 | } |
1412 | |
1406 | |
… | |
… | |
1429 | else if (level == 3) |
1423 | else if (level == 3) |
1430 | sprintf(pl->contr->title, "%s dragon", attacks[atnr]); |
1424 | sprintf(pl->contr->title, "%s dragon", attacks[atnr]); |
1431 | else { |
1425 | else { |
1432 | /* special titles for extra high resistance! */ |
1426 | /* special titles for extra high resistance! */ |
1433 | if (skin->resist[atnr] > 80) |
1427 | if (skin->resist[atnr] > 80) |
1434 | sprintf(pl->contr->title, "legendary %s dragon", attacks[atnr]); |
1428 | sprintf(pl->contr->title, "legendary %s dragon", attacks[atnr]); |
1435 | else if (skin->resist[atnr] > 50) |
1429 | else if (skin->resist[atnr] > 50) |
1436 | sprintf(pl->contr->title, "ancient %s dragon", attacks[atnr]); |
1430 | sprintf(pl->contr->title, "ancient %s dragon", attacks[atnr]); |
1437 | else |
1431 | else |
1438 | sprintf(pl->contr->title, "big %s dragon", attacks[atnr]); |
1432 | sprintf(pl->contr->title, "big %s dragon", attacks[atnr]); |
1439 | } |
1433 | } |
1440 | } |
1434 | } |
1441 | |
1435 | |
1442 | strcpy(pl->contr->own_title, ""); |
1436 | strcpy(pl->contr->own_title, ""); |
1443 | } |
1437 | } |
… | |
… | |
1453 | object *tmp = NULL; /* tmp. object */ |
1447 | object *tmp = NULL; /* tmp. object */ |
1454 | char buf[MAX_BUF]; /* tmp. string buffer */ |
1448 | char buf[MAX_BUF]; /* tmp. string buffer */ |
1455 | |
1449 | |
1456 | /* now grab the 'dragon_ability'-forces from the player's inventory */ |
1450 | /* now grab the 'dragon_ability'-forces from the player's inventory */ |
1457 | for (tmp=who->inv; tmp!=NULL; tmp=tmp->below) { |
1451 | for (tmp=who->inv; tmp!=NULL; tmp=tmp->below) { |
1458 | if (tmp->type == FORCE) { |
1452 | if (tmp->type == FORCE) { |
1459 | if (strcmp(tmp->arch->name, "dragon_ability_force")==0) |
1453 | if (strcmp(tmp->arch->name, "dragon_ability_force")==0) |
1460 | abil = tmp; |
1454 | abil = tmp; |
1461 | if (strcmp(tmp->arch->name, "dragon_skin_force")==0) |
1455 | if (strcmp(tmp->arch->name, "dragon_skin_force")==0) |
1462 | skin = tmp; |
1456 | skin = tmp; |
1463 | } |
1457 | } |
1464 | } |
1458 | } |
1465 | /* if the force is missing -> bail out */ |
1459 | /* if the force is missing -> bail out */ |
1466 | if (abil == NULL) return; |
1460 | if (abil == NULL) return; |
1467 | |
1461 | |
1468 | /* The ability_force keeps track of maximum level ever achieved. |
1462 | /* The ability_force keeps track of maximum level ever achieved. |
1469 | * New abilties can only be gained by surpassing this max level |
1463 | * New abilties can only be gained by surpassing this max level |
1470 | */ |
1464 | */ |
1471 | if (who->level > abil->level) { |
1465 | if (who->level > abil->level) { |
1472 | /* increase our focused ability */ |
1466 | /* increase our focused ability */ |
1473 | abil->resist[abil->stats.exp]++; |
1467 | abil->resist[abil->stats.exp]++; |
1474 | |
1468 | |
1475 | |
1469 | |
1476 | 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) { |
1477 | /* time to hand out a new ability-gift */ |
1471 | /* time to hand out a new ability-gift */ |
1478 | dragon_ability_gain(who, (int)abil->stats.exp, |
1472 | dragon_ability_gain(who, (int)abil->stats.exp, |
1479 | (int)((1+abil->resist[abil->stats.exp])/5.)); |
1473 | (int)((1+abil->resist[abil->stats.exp])/5.)); |
1480 | } |
1474 | } |
1481 | |
1475 | |
1482 | 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)) { |
1483 | /* apply new ability focus */ |
1477 | /* apply new ability focus */ |
1484 | sprintf(buf, "Your metabolism now focuses on %s!", |
1478 | sprintf(buf, "Your metabolism now focuses on %s!", |
1485 | change_resist_msg[abil->last_eat]); |
1479 | change_resist_msg[abil->last_eat]); |
1486 | new_draw_info(NDI_UNIQUE|NDI_BLUE, 0, who, buf); |
1480 | new_draw_info(NDI_UNIQUE|NDI_BLUE, 0, who, buf); |
1487 | |
1481 | |
1488 | abil->stats.exp = abil->last_eat; |
1482 | abil->stats.exp = abil->last_eat; |
1489 | abil->last_eat = 0; |
1483 | abil->last_eat = 0; |
1490 | } |
1484 | } |
1491 | |
1485 | |
1492 | abil->level = who->level; |
1486 | abil->level = who->level; |
1493 | } |
1487 | } |
1494 | |
1488 | |
1495 | /* last but not least, set the new title for the dragon */ |
1489 | /* last but not least, set the new title for the dragon */ |
1496 | set_dragon_name(who, abil, skin); |
1490 | set_dragon_name(who, abil, skin); |
1497 | } |
1491 | } |
… | |
… | |
1506 | { |
1500 | { |
1507 | object *skill_obj; |
1501 | object *skill_obj; |
1508 | |
1502 | |
1509 | skill_obj = get_archetype_by_skill_name(skill_name, SKILL); |
1503 | skill_obj = get_archetype_by_skill_name(skill_name, SKILL); |
1510 | if (!skill_obj) { |
1504 | if (!skill_obj) { |
1511 | 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); |
1512 | return NULL; |
1506 | return NULL; |
1513 | } |
1507 | } |
1514 | /* clear the flag - exp goes into this bucket, but player |
1508 | /* clear the flag - exp goes into this bucket, but player |
1515 | * still doesn't know it. |
1509 | * still doesn't know it. |
1516 | */ |
1510 | */ |
1517 | CLEAR_FLAG(skill_obj, FLAG_CAN_USE_SKILL); |
1511 | CLEAR_FLAG(skill_obj, FLAG_CAN_USE_SKILL); |
1518 | skill_obj->stats.exp = 0; |
1512 | skill_obj->stats.exp = 0; |
1519 | skill_obj->level = 1; |
1513 | skill_obj->level = 1; |
1520 | insert_ob_in_ob(skill_obj, op); |
1514 | insert_ob_in_ob(skill_obj, op); |
1521 | if (op->contr) { |
1515 | if (op->contr) { |
1522 | op->contr->last_skill_ob[skill_obj->subtype] = skill_obj; |
1516 | op->contr->last_skill_ob[skill_obj->subtype] = skill_obj; |
1523 | op->contr->last_skill_exp[skill_obj->subtype] = -1; |
1517 | op->contr->last_skill_exp[skill_obj->subtype] = -1; |
1524 | } |
1518 | } |
1525 | return skill_obj; |
1519 | return skill_obj; |
1526 | } |
1520 | } |
1527 | |
1521 | |
1528 | |
1522 | |
… | |
… | |
1535 | */ |
1529 | */ |
1536 | void player_lvl_adj(object *who, object *op) { |
1530 | void player_lvl_adj(object *who, object *op) { |
1537 | char buf[MAX_BUF]; |
1531 | char buf[MAX_BUF]; |
1538 | |
1532 | |
1539 | if(!op) /* when rolling stats */ |
1533 | if(!op) /* when rolling stats */ |
1540 | op = who; |
1534 | op = who; |
1541 | |
1535 | |
1542 | 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)) { |
1543 | op->level++; |
1537 | op->level++; |
1544 | |
1538 | |
1545 | 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)) |
1546 | dragon_level_gain(who); |
1540 | dragon_level_gain(who); |
1547 | |
1541 | |
1548 | /* 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 */ |
1549 | if(op==who && (who->level < 11) && who->type==PLAYER) { |
1543 | if(op==who && (who->level < 11) && who->type==PLAYER) { |
1550 | 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; |
1551 | 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); |
1552 | 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; |
1553 | } |
1547 | } |
1554 | |
1548 | |
1555 | fix_player(who); |
1549 | fix_player(who); |
1556 | if(op->level>1) { |
1550 | if(op->level>1) { |
1557 | if (op->type!=PLAYER) |
1551 | if (op->type!=PLAYER) |
1558 | 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); |
1559 | else |
1553 | else |
1560 | sprintf(buf,"You are now level %d.",op->level); |
1554 | sprintf(buf,"You are now level %d.",op->level); |
1561 | 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); |
1562 | } |
1556 | } |
1563 | player_lvl_adj(who,op); /* To increase more levels */ |
1557 | player_lvl_adj(who,op); /* To increase more levels */ |
1564 | } 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)) { |
1565 | op->level--; |
1559 | op->level--; |
1566 | fix_player(who); |
1560 | fix_player(who); |
1567 | if(op->type!=PLAYER) { |
1561 | if(op->type!=PLAYER) { |
1568 | 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); |
1569 | new_draw_info(NDI_UNIQUE|NDI_RED, 0, who,buf); |
1563 | new_draw_info(NDI_UNIQUE|NDI_RED, 0, who,buf); |
1570 | } |
1564 | } |
1571 | player_lvl_adj(who,op); /* To decrease more levels */ |
1565 | player_lvl_adj(who,op); /* To decrease more levels */ |
1572 | } |
1566 | } |
1573 | /* check if the spell data has changed */ |
1567 | /* check if the spell data has changed */ |
1574 | esrv_update_spells(who->contr); |
1568 | esrv_update_spells(who->contr); |
1575 | } |
1569 | } |
1576 | |
1570 | |
… | |
… | |
1579 | * the given level. level should really never exceed max_level |
1573 | * the given level. level should really never exceed max_level |
1580 | */ |
1574 | */ |
1581 | |
1575 | |
1582 | sint64 level_exp(int level,double expmul) { |
1576 | sint64 level_exp(int level,double expmul) { |
1583 | if (level > settings.max_level) |
1577 | if (level > settings.max_level) |
1584 | return (sint64) (expmul * levels[settings.max_level]); |
1578 | return (sint64) (expmul * levels[settings.max_level]); |
1585 | return (sint64) (expmul * levels[level]); |
1579 | return (sint64) (expmul * levels[level]); |
1586 | } |
1580 | } |
1587 | |
1581 | |
1588 | /* |
1582 | /* |
1589 | * 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. |
… | |
… | |
1618 | * NULL, in which case exp increases the players general |
1612 | * NULL, in which case exp increases the players general |
1619 | * total, but not any particular skill. |
1613 | * total, but not any particular skill. |
1620 | * flag is what to do if the player doesn't have the skill: |
1614 | * flag is what to do if the player doesn't have the skill: |
1621 | */ |
1615 | */ |
1622 | |
1616 | |
1623 | static void add_player_exp(object *op, sint64 exp, const char *skill_name, int flag) |
1617 | static void add_player_exp (object * op, sint64 exp, const char *skill_name, int flag) |
1624 | { |
1618 | { |
1625 | object *skill_obj=NULL; |
1619 | object *skill_obj = NULL; |
1626 | sint64 limit, exp_to_add; |
1620 | sint64 limit, exp_to_add; |
1627 | int i; |
1621 | int i; |
1628 | |
1622 | |
1629 | /* prevents some forms of abuse. */ |
1623 | /* prevents some forms of abuse. */ |
1630 | if(op->contr->braced) exp=exp/5; |
1624 | if (op->contr->braced) |
|
|
1625 | exp = exp / 5; |
1631 | |
1626 | |
1632 | /* Try to find the matching skill. |
1627 | /* Try to find the matching skill. |
1633 | * We do a shortcut/time saving mechanism first - see if it matches |
1628 | * We do a shortcut/time saving mechanism first - see if it matches |
1634 | * chosen_skill. This means we don't need to search through |
1629 | * chosen_skill. This means we don't need to search through |
1635 | * the players inventory. |
1630 | * the players inventory. |
1636 | */ |
1631 | */ |
1637 | if (skill_name) { |
1632 | if (skill_name) |
|
|
1633 | { |
1638 | if (op->chosen_skill && op->chosen_skill->type == SKILL && |
1634 | if (op->chosen_skill && op->chosen_skill->type == SKILL && |
1639 | !strcmp(skill_name, op->chosen_skill->skill)) |
1635 | !strcmp (skill_name, op->chosen_skill->skill)) |
1640 | skill_obj = op->chosen_skill; |
1636 | skill_obj = op->chosen_skill; |
1641 | else { |
1637 | else |
|
|
1638 | { |
1642 | for (i=0; i<NUM_SKILLS; i++) |
1639 | for (i = 0; i < NUM_SKILLS; i++) |
1643 | if (op->contr->last_skill_ob[i] && |
1640 | if (op->contr->last_skill_ob[i] && |
1644 | !strcmp(op->contr->last_skill_ob[i]->skill, skill_name)) { |
1641 | !strcmp (op->contr->last_skill_ob[i]->skill, skill_name)) |
|
|
1642 | { |
1645 | skill_obj = op->contr->last_skill_ob[i]; |
1643 | skill_obj = op->contr->last_skill_ob[i]; |
1646 | break; |
1644 | break; |
1647 | } |
1645 | } |
1648 | |
1646 | |
1649 | /* Player doesn't have the skill. Check to see what to do, and give |
1647 | /* Player doesn't have the skill. Check to see what to do, and give |
1650 | * it to the player if necessary |
1648 | * it to the player if necessary |
1651 | */ |
1649 | */ |
1652 | if (!skill_obj) { |
1650 | if (!skill_obj) |
1653 | if (flag == SK_EXP_NONE) return; |
1651 | { |
|
|
1652 | if (flag == SK_EXP_NONE) |
|
|
1653 | return; |
1654 | else if (flag == SK_EXP_ADD_SKILL) |
1654 | else if (flag == SK_EXP_ADD_SKILL) |
1655 | give_skill_by_name(op, skill_name); |
1655 | give_skill_by_name (op, skill_name); |
|
|
1656 | } |
|
|
1657 | } |
1656 | } |
1658 | } |
1657 | } |
1659 | |
|
|
1660 | if (flag != SK_EXP_SKILL_ONLY) |
1658 | } |
1661 | { |
1659 | |
|
|
1660 | /* Basically, you can never gain more experience in one shot |
1662 | /* Basically, you can never gain more experience in one shot |
1661 | * than half what you need to gain for next level. |
1663 | * than half what you need to gain for next level. |
1662 | */ |
1664 | */ |
1663 | exp_to_add = exp; |
1665 | exp_to_add = exp; |
1664 | limit=(levels[op->level+1]-levels[op->level])/2; |
1666 | limit = (levels[op->level + 1] - levels[op->level]) / 2; |
1665 | if (exp_to_add > limit) exp_to_add=limit; |
1667 | if (exp_to_add > limit) |
|
|
1668 | exp_to_add = limit; |
1666 | |
1669 | |
1667 | ADD_EXP(op->stats.exp, (sint64) ((float) exp_to_add * (skill_obj? skill_obj->expmul:1))); |
1670 | ADD_EXP (op->stats.exp, |
|
|
1671 | (sint64) ((float) exp_to_add * |
|
|
1672 | (skill_obj ? skill_obj->expmul : 1))); |
1668 | if (settings.permanent_exp_ratio) { |
1673 | if (settings.permanent_exp_ratio) |
1669 | ADD_EXP(op->perm_exp, (sint64) ((float) exp_to_add * PERM_EXP_GAIN_RATIO * (skill_obj? skill_obj->expmul:1))); |
1674 | { |
|
|
1675 | ADD_EXP (op->perm_exp, |
|
|
1676 | (sint64) ((float) exp_to_add * PERM_EXP_GAIN_RATIO * |
|
|
1677 | (skill_obj ? skill_obj->expmul : 1))); |
1670 | calc_perm_exp(op); |
1678 | calc_perm_exp (op); |
1671 | } |
1679 | } |
1672 | |
1680 | |
1673 | player_lvl_adj(op,NULL); |
1681 | player_lvl_adj (op, NULL); |
|
|
1682 | } |
|
|
1683 | |
1674 | if (skill_obj) { |
1684 | if (skill_obj) |
|
|
1685 | { |
1675 | exp_to_add = exp; |
1686 | exp_to_add = exp; |
1676 | limit=(levels[skill_obj->level+1]-levels[skill_obj->level])/2; |
1687 | limit = (levels[skill_obj->level + 1] - levels[skill_obj->level]) / 2; |
1677 | if (exp_to_add > limit) exp_to_add=limit; |
1688 | if (exp_to_add > limit) |
|
|
1689 | exp_to_add = limit; |
|
|
1690 | |
1678 | ADD_EXP(skill_obj->stats.exp, exp_to_add); |
1691 | ADD_EXP (skill_obj->stats.exp, exp_to_add); |
1679 | if (settings.permanent_exp_ratio) { |
1692 | if (settings.permanent_exp_ratio) |
1680 | skill_obj->perm_exp += (sint64) ((float) exp_to_add * PERM_EXP_GAIN_RATIO); |
1693 | { |
|
|
1694 | skill_obj->perm_exp += |
|
|
1695 | (sint64) ((float) exp_to_add * PERM_EXP_GAIN_RATIO); |
1681 | calc_perm_exp(skill_obj); |
1696 | calc_perm_exp (skill_obj); |
1682 | } |
1697 | } |
|
|
1698 | |
1683 | player_lvl_adj(op,skill_obj); |
1699 | player_lvl_adj (op, skill_obj); |
1684 | } |
1700 | } |
1685 | } |
1701 | } |
1686 | |
1702 | |
1687 | /* This function checks to make sure that object 'op' can |
1703 | /* This function checks to make sure that object 'op' can |
1688 | * lost 'exp' experience. It returns the amount of exp |
1704 | * lost 'exp' experience. It returns the amount of exp |
… | |
… | |
1696 | { |
1712 | { |
1697 | sint64 del_exp; |
1713 | sint64 del_exp; |
1698 | |
1714 | |
1699 | if (exp > op->stats.exp) exp = op->stats.exp; |
1715 | if (exp > op->stats.exp) exp = op->stats.exp; |
1700 | if (settings.permanent_exp_ratio) { |
1716 | if (settings.permanent_exp_ratio) { |
1701 | del_exp = (sint64) ((op->stats.exp - op->perm_exp) * PERM_EXP_MAX_LOSS_RATIO); |
1717 | del_exp = (sint64) ((op->stats.exp - op->perm_exp) * PERM_EXP_MAX_LOSS_RATIO); |
1702 | if (del_exp < 0) del_exp = 0; |
1718 | if (del_exp < 0) del_exp = 0; |
1703 | if (exp > del_exp) exp=del_exp; |
1719 | if (exp > del_exp) exp=del_exp; |
1704 | } |
1720 | } |
1705 | return exp; |
1721 | return exp; |
1706 | } |
1722 | } |
1707 | |
1723 | |
1708 | sint64 check_exp_adjust(const object *op, sint64 exp) |
1724 | sint64 check_exp_adjust(const object *op, sint64 exp) |
… | |
… | |
1729 | float fraction = (float) exp/(float) op->stats.exp; |
1745 | float fraction = (float) exp/(float) op->stats.exp; |
1730 | object *tmp; |
1746 | object *tmp; |
1731 | sint64 del_exp; |
1747 | sint64 del_exp; |
1732 | |
1748 | |
1733 | for(tmp=op->inv;tmp;tmp=tmp->below) |
1749 | for(tmp=op->inv;tmp;tmp=tmp->below) |
1734 | if(tmp->type==SKILL && tmp->stats.exp) { |
1750 | if(tmp->type==SKILL && tmp->stats.exp) { |
1735 | if (flag == SK_SUBTRACT_SKILL_EXP && skill && !strcmp(tmp->skill, skill)) { |
1751 | if (flag == SK_SUBTRACT_SKILL_EXP && skill && !strcmp(tmp->skill, skill)) { |
1736 | del_exp = check_exp_loss(tmp, exp); |
1752 | del_exp = check_exp_loss(tmp, exp); |
1737 | tmp->stats.exp -= del_exp; |
1753 | tmp->stats.exp -= del_exp; |
1738 | player_lvl_adj(op, tmp); |
1754 | player_lvl_adj(op, tmp); |
1739 | } else if (flag != SK_SUBTRACT_SKILL_EXP) { |
1755 | } else if (flag != SK_SUBTRACT_SKILL_EXP) { |
1740 | /* only want to process other skills if we are not trying |
1756 | /* only want to process other skills if we are not trying |
1741 | * to match a specific skill. |
1757 | * to match a specific skill. |
1742 | */ |
1758 | */ |
1743 | del_exp = check_exp_loss(tmp, (sint64) (tmp->stats.exp * fraction)); |
1759 | del_exp = check_exp_loss(tmp, (sint64) (tmp->stats.exp * fraction)); |
1744 | tmp->stats.exp -= del_exp; |
1760 | tmp->stats.exp -= del_exp; |
1745 | player_lvl_adj(op, tmp); |
1761 | player_lvl_adj(op, tmp); |
1746 | } |
1762 | } |
1747 | } |
1763 | } |
1748 | if (flag != SK_SUBTRACT_SKILL_EXP) { |
1764 | if (flag != SK_SUBTRACT_SKILL_EXP) { |
1749 | del_exp = check_exp_loss(op, exp); |
1765 | del_exp = check_exp_loss(op, exp); |
1750 | op->stats.exp -= del_exp; |
1766 | op->stats.exp -= del_exp; |
1751 | player_lvl_adj(op,NULL); |
1767 | player_lvl_adj(op,NULL); |
1752 | } |
1768 | } |
1753 | } |
1769 | } |
1754 | |
1770 | |
1755 | |
1771 | |
1756 | |
1772 | |
… | |
… | |
1774 | #endif |
1790 | #endif |
1775 | #endif |
1791 | #endif |
1776 | |
1792 | |
1777 | /* safety */ |
1793 | /* safety */ |
1778 | if(!op) { |
1794 | if(!op) { |
1779 | LOG(llevError,"change_exp() called for null object!\n"); |
1795 | LOG(llevError,"change_exp() called for null object!\n"); |
1780 | return; |
1796 | return; |
1781 | } |
1797 | } |
1782 | |
1798 | |
1783 | /* if no change in exp, just return - most of the below code |
1799 | /* if no change in exp, just return - most of the below code |
1784 | * won't do anything if the value is 0 anyways. |
1800 | * won't do anything if the value is 0 anyways. |
1785 | */ |
1801 | */ |
… | |
… | |
1789 | * don't adjust level, since in most cases it is unrelated to |
1805 | * don't adjust level, since in most cases it is unrelated to |
1790 | * the exp they have - the monsters exp represents what its |
1806 | * the exp they have - the monsters exp represents what its |
1791 | * worth. |
1807 | * worth. |
1792 | */ |
1808 | */ |
1793 | if(op->type != PLAYER) { |
1809 | if(op->type != PLAYER) { |
1794 | /* Sanity check */ |
1810 | /* Sanity check */ |
1795 | if (!QUERY_FLAG(op, FLAG_ALIVE)) return; |
1811 | if (!QUERY_FLAG(op, FLAG_ALIVE)) return; |
1796 | |
1812 | |
1797 | /* reset exp to max allowed value. We subtract from |
1813 | /* reset exp to max allowed value. We subtract from |
1798 | * MAX_EXPERIENCE to prevent overflows. If the player somehow has |
1814 | * MAX_EXPERIENCE to prevent overflows. If the player somehow has |
1799 | * more than max exp, just return. |
1815 | * more than max exp, just return. |
1800 | */ |
1816 | */ |
1801 | if (exp > 0 && ( op->stats.exp > (MAX_EXPERIENCE - exp))) { |
1817 | if (exp > 0 && ( op->stats.exp > (MAX_EXPERIENCE - exp))) { |
1802 | exp = MAX_EXPERIENCE - op->stats.exp; |
1818 | exp = MAX_EXPERIENCE - op->stats.exp; |
1803 | if (exp < 0) return; |
1819 | if (exp < 0) return; |
1804 | } |
1820 | } |
1805 | |
1821 | |
1806 | op->stats.exp += exp; |
1822 | op->stats.exp += exp; |
1807 | } |
1823 | } |
1808 | else { /* Players only */ |
1824 | else { /* Players only */ |
1809 | if(exp>0) |
1825 | if(exp>0) |
1810 | add_player_exp(op, exp, skill_name, flag); |
1826 | add_player_exp(op, exp, skill_name, flag); |
1811 | else |
1827 | else |
1812 | /* note that when you lose exp, it doesn't go against |
1828 | /* note that when you lose exp, it doesn't go against |
1813 | * a particular skill, so we don't need to pass that |
1829 | * a particular skill, so we don't need to pass that |
1814 | * along. |
1830 | * along. |
1815 | */ |
1831 | */ |
1816 | subtract_player_exp(op, FABS(exp), skill_name, flag); |
1832 | subtract_player_exp(op, FABS(exp), skill_name, flag); |
1817 | |
1833 | |
1818 | } |
1834 | } |
1819 | } |
1835 | } |
1820 | |
1836 | |
1821 | /* Applies a death penalty experience, the size of this is defined by the |
1837 | /* Applies a death penalty experience, the size of this is defined by the |
… | |
… | |
1828 | sint64 loss; |
1844 | sint64 loss; |
1829 | sint64 percentage_loss; /* defined by the setting 'death_penalty_percent' */ |
1845 | sint64 percentage_loss; /* defined by the setting 'death_penalty_percent' */ |
1830 | sint64 level_loss; /* defined by the setting 'death_penalty_levels */ |
1846 | sint64 level_loss; /* defined by the setting 'death_penalty_levels */ |
1831 | |
1847 | |
1832 | for(tmp=op->inv;tmp;tmp=tmp->below) |
1848 | for(tmp=op->inv;tmp;tmp=tmp->below) |
1833 | if(tmp->type==SKILL && tmp->stats.exp) { |
1849 | if(tmp->type==SKILL && tmp->stats.exp) { |
1834 | |
1850 | |
1835 | percentage_loss = tmp->stats.exp * settings.death_penalty_ratio/100; |
1851 | percentage_loss = tmp->stats.exp * settings.death_penalty_ratio/100; |
1836 | level_loss = tmp->stats.exp - levels[MAX(0,tmp->level - settings.death_penalty_level)]; |
1852 | level_loss = tmp->stats.exp - levels[MAX(0,tmp->level - settings.death_penalty_level)]; |
1837 | |
1853 | |
1838 | /* With the revised exp system, you can get cases where |
1854 | /* With the revised exp system, you can get cases where |
1839 | * losing several levels would still require that you have more |
1855 | * losing several levels would still require that you have more |
1840 | * exp than you currently have - this is true if the levels |
1856 | * exp than you currently have - this is true if the levels |
1841 | * tables is a lot harder. |
1857 | * tables is a lot harder. |
1842 | */ |
1858 | */ |
1843 | if (level_loss < 0) level_loss = 0; |
1859 | if (level_loss < 0) level_loss = 0; |
1844 | |
1860 | |
1845 | loss = check_exp_loss(tmp, MIN(level_loss, percentage_loss)); |
1861 | loss = check_exp_loss(tmp, MIN(level_loss, percentage_loss)); |
1846 | |
1862 | |
1847 | tmp->stats.exp -= loss; |
1863 | tmp->stats.exp -= loss; |
1848 | player_lvl_adj(op,tmp); |
1864 | player_lvl_adj(op,tmp); |
1849 | } |
1865 | } |
1850 | |
1866 | |
1851 | percentage_loss = op->stats.exp * settings.death_penalty_ratio/100; |
1867 | percentage_loss = op->stats.exp * settings.death_penalty_ratio/100; |
1852 | level_loss = op->stats.exp - levels[MAX(0,op->level - settings.death_penalty_level)]; |
1868 | level_loss = op->stats.exp - levels[MAX(0,op->level - settings.death_penalty_level)]; |
1853 | if (level_loss < 0) level_loss = 0; |
1869 | if (level_loss < 0) level_loss = 0; |
1854 | loss = check_exp_loss(op, MIN(level_loss, percentage_loss)); |
1870 | loss = check_exp_loss(op, MIN(level_loss, percentage_loss)); |
… | |
… | |
1867 | int did_make_save(const object *op, int level, int bonus) |
1883 | int did_make_save(const object *op, int level, int bonus) |
1868 | { |
1884 | { |
1869 | if (level > MAX_SAVE_LEVEL) level = MAX_SAVE_LEVEL; |
1885 | if (level > MAX_SAVE_LEVEL) level = MAX_SAVE_LEVEL; |
1870 | |
1886 | |
1871 | if ((random_roll(1, 20, op, PREFER_HIGH) + bonus) < savethrow[level]) |
1887 | if ((random_roll(1, 20, op, PREFER_HIGH) + bonus) < savethrow[level]) |
1872 | return 0; |
1888 | return 0; |
1873 | return 1; |
1889 | return 1; |
1874 | } |
1890 | } |
1875 | |
1891 | |