Crossfire Server, Branches 1.12  R18729
living.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_living_c =
3  * "$Id: living.c 11190 2009-01-19 05:07:11Z lalo $";
4  */
5 
6 /*
7  CrossFire, A Multiplayer game for X-windows
8 
9  Copyright (C) 2002-2006 Mark Wedel & Crossfire Development Team
10  Copyright (C) 1992 Frank Tore Johansen
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 
26  The authors can be reached via e-mail at crossfire-devel@real-time.com
27 */
28 
37 #include <stdlib.h>
38 #include <global.h>
39 #include <sproto.h>
40 
46 #define ADD_EXP(exptotal, exp) {exptotal += exp; if (exptotal > MAX_EXPERIENCE) exptotal = MAX_EXPERIENCE; }
47 
51 static const int con_bonus[MAX_STAT + 1]={
52  -6,-5,-4,-3,-2,-1,-1,0,0,0,0,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,
53  22,25,30,40,50
54 };
55 
62 static const int sp_bonus[MAX_STAT + 1]={
63  -10,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,12,15,20,25,
64  30,40,50,70,100
65 };
66 
70 static const int grace_bonus[MAX_STAT +1] = {
71  -10,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,12,15,20,25,
72  30,40,50,70,100
73 };
74 
94 const float cha_bonus[MAX_STAT + 1]={
95  10.0, 10.0, 9.0, 8.0, 7.0, 6.0, /*<-5*/
96  5.0, 4.5, 4.0, 3.5, 3.0, /*<-10*/
97  2.9, 2.8, 2.7, 2.6, 2.5, /*<-15*/
98  2.4, 2.3, 2.2, 2.1, 2.0, /*<-20*/
99  1.95, 1.90, 1.85, 1.80, 1.75, /*25 */
100  1.70, 1.65, 1.60, 1.55, 1.50 /*30 */
101 };
102 
104 const int dex_bonus[MAX_STAT + 1]={
105  -4,-3,-2,-2,-1,-1,-1,0,0,0,0,0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,6,6,7
106 };
107 
109 const float speed_bonus[MAX_STAT + 1]={
110  -0.4, -0.4, -0.3, -0.3, -0.2, -0.2, -0.2, -0.1, -0.1, -0.1, -0.05, 0, 0, 0,
111  0.05, 0.1, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0, 1.2, 1.4,
112  1.6, 1.8, 2.0, 2.5, 3.0
113 };
114 
119 const int dam_bonus[MAX_STAT + 1]={
120  -2,-2,-2,-1,-1,-1,0,0,0,0,0,0,1,1,1,2,2,2,3,3,3,4,4,5,5,6,6,7,8,10,15
121 };
122 
124 const int thaco_bonus[MAX_STAT + 1]={
125  -2,-2,-1,-1,0,0,0,0,0,0,0,0,0,0,1,1,1,2,2,2,3,3,3,4,4,5,5,6,7,8,10
126 };
127 
128 /* Max you can carry before you start getting extra speed penalties */
129 const int max_carry[MAX_STAT + 1]={
130  2,4,7,11,16,22,29,37,46,56,67,79,92,106,121,137,154,172,191,211,232,254,277,
131  301,326,352,400,450,500,600,1000
132 };
133 
144  200000, /* 0 */
145  250000,300000,350000,400000,500000, /* 5*/
146  600000,700000,800000,900000,1000000, /* 10 */
147  1100000,1200000,1300000,1400000,1500000, /* 15 */
148  1650000,1800000,1950000,2100000,2250000, /* 20 */
149  2400000,2550000,2700000,2850000,3000000, /* 25 */
150  3250000,3500000,3750000,4000000,4500000 /*30 */
151 };
152 
154 const int learn_spell[MAX_STAT + 1]={
155  0,0,0,1,2,4,8,12,16,25,36,45,55,65,70,75,80,85,90,95,100,100,100,100,100,
156  100,100,100,100,100,100
157 };
158 
160 const int cleric_chance[MAX_STAT + 1]={
161  100,100,100,100,90,80,70,60,50,40,35,30,25,20,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,0
162 };
163 
165 const int turn_bonus[MAX_STAT + 1]={
166  -1,-1,-1,-1,-1,-1,-1,-1,0,0,0,1,1,1,2,2,2,3,3,3,4,4,5,5,6,7,8,9,10,12,15
167 };
168 
170 const int fear_bonus[MAX_STAT + 1]={
171  3,3,3,3,2,2,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
172 };
173 
178 #define MAX_EXPERIENCE levels[settings.max_level]
179 
195 #define MAX_EXP_IN_OBJ levels[settings.max_level]/(MAX_EXP_CAT - 1)
196 
197 extern sint64 *levels;
198 
199 #define MAX_SAVE_LEVEL 110
200 
209 static const int savethrow[MAX_SAVE_LEVEL+1]={
210  18,
211  18,17,16,15,14,14,13,13,12,12,12,11,11,11,11,10,10,10,10, 9,
212  9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
213  6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4,
214  4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2,
215  2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
216  1, 1, 1, 1, 1, 1, 1, 1, 1, 1
217 };
218 
220 const char *const attacks[NROFATTACKS] = {
221  "physical", "magical", "fire", "electricity", "cold", "confusion",
222  "acid", "drain", "weaponmagic", "ghosthit", "poison", "slow",
223  "paralyze", "turn undead", "fear", "cancellation", "depletion", "death",
224  "chaos","counterspell","god power","holy power","blinding", "",
225  "life stealing"
226 };
227 
229 static const char *const drain_msg[NUM_STATS] = {
230  "Oh no! You are weakened!",
231  "You're feeling clumsy!",
232  "You feel less healthy",
233  "You suddenly begin to lose your memory!",
234  "Your face gets distorted!",
235  "Watch out, your mind is going!",
236  "Your spirit feels drained!"
237 };
238 
240 const char *const restore_msg[NUM_STATS] = {
241  "You feel your strength return.",
242  "You feel your agility return.",
243  "You feel your health return.",
244  "You feel your wisdom return.",
245  "You feel your charisma return.",
246  "You feel your memory return.",
247  "You feel your spirits return."
248 };
249 
251 const char *const gain_msg[NUM_STATS] = {
252  "You feel stronger.",
253  "You feel more agile.",
254  "You feel healthy.",
255  "You feel wiser.",
256  "You seem to look better.",
257  "You feel smarter.",
258  "You feel more potent."
259 };
260 
262 const char *const lose_msg[NUM_STATS] = {
263  "You feel weaker!",
264  "You feel clumsy!",
265  "You feel less healthy!",
266  "You lose some of your memory!",
267  "You look ugly!",
268  "You feel stupid!",
269  "You feel less potent!"
270 };
271 
273 const char *const statname[NUM_STATS] = {
274  "strength", "dexterity", "constitution", "wisdom", "charisma", "intelligence","power"
275 };
276 
278 const char *const short_stat_name[NUM_STATS] = {
279  "Str", "Dex", "Con", "Wis", "Cha", "Int","Pow"
280 };
281 
296 void set_attr_value(living *stats,int attr,sint8 value) {
297  switch (attr) {
298  case STR:
299  stats->Str=value;
300  break;
301  case DEX:
302  stats->Dex=value;
303  break;
304  case CON:
305  stats->Con=value;
306  break;
307  case WIS:
308  stats->Wis=value;
309  break;
310  case POW:
311  stats->Pow=value;
312  break;
313  case CHA:
314  stats->Cha=value;
315  break;
316  case INT:
317  stats->Int=value;
318  break;
319  }
320 }
321 
336 void change_attr_value(living *stats,int attr,sint8 value) {
337  if (value==0) return;
338  switch (attr) {
339  case STR:
340  stats->Str+=value;
341  break;
342  case DEX:
343  stats->Dex+=value;
344  break;
345  case CON:
346  stats->Con+=value;
347  break;
348  case WIS:
349  stats->Wis+=value;
350  break;
351  case POW:
352  stats->Pow+=value;
353  break;
354  case CHA:
355  stats->Cha+=value;
356  break;
357  case INT:
358  stats->Int+=value;
359  break;
360  default:
361  LOG(llevError,"Invalid attribute in change_attr_value: %d\n", attr);
362  }
363 }
364 
377 sint8 get_attr_value(const living *stats,int attr) {
378  switch (attr) {
379  case STR:
380  return(stats->Str);
381  case DEX:
382  return(stats->Dex);
383  case CON:
384  return(stats->Con);
385  case WIS:
386  return(stats->Wis);
387  case CHA:
388  return(stats->Cha);
389  case INT:
390  return(stats->Int);
391  case POW:
392  return(stats->Pow);
393  }
394  return 0;
395 }
396 
404 void check_stat_bounds(living *stats) {
405  int i,v;
406  for (i=0;i<NUM_STATS;i++)
407  if ((v=get_attr_value(stats,i))>MAX_STAT)
408  set_attr_value(stats,i,MAX_STAT);
409  else if (v<MIN_STAT)
410  set_attr_value(stats,i,MIN_STAT);
411 }
412 
418 #define DIFF_MSG(flag, subtype1, subtype2, msg1, msg2) \
419  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ATTRIBUTE, (flag>0)?subtype1:subtype2, (flag>0)?msg1:msg2, NULL);
420 
443 int change_abil(object *op, object *tmp) {
444  int flag=QUERY_FLAG(tmp,FLAG_APPLIED)?1:-1,i,j,success=0;
445  object refop;
446  int potion_max=0;
447 
448  /* remember what object was like before it was changed. note that
449  * refop is a local copy of op only to be used for detecting changes
450  * found by fix_object. refop is not a real object
451  */
452  memcpy(&refop, op, sizeof(object));
453 
454  if (op->type==PLAYER) {
455  if (tmp->type==POTION) {
456  potion_max=1;
457  for (j=0;j<NUM_STATS;j++) {
458  int nstat, ostat;
459 
460  ostat = get_attr_value(&(op->contr->orig_stats),j);
461  i = get_attr_value(&(tmp->stats),j);
462 
463  /* nstat is what the stat will be after use of the potion */
464  nstat = flag*i + ostat;
465 
466  /* Do some bounds checking. While I don't think any
467  * potions do so right now, there is the potential for potions
468  * that adjust that stat by more than one point, so we need
469  * to allow for that.
470  */
471  if (nstat < 1 && i*flag < 0) nstat = 1;
472  else if (nstat > 20 + get_attr_value(&(op->arch->clone.stats),j)) {
473  nstat = 20 + get_attr_value(&(op->arch->clone.stats),j);
474  }
475  if (nstat != ostat) {
476  set_attr_value(&(op->contr->orig_stats), j, nstat);
477  potion_max=0;
478  } else if (i) {
479  /* potion is useless - player has already hit the natural maximum */
480  potion_max = 1;
481  }
482  }
483  /* This section of code ups the characters normal stats also. I am not
484  * sure if this is strictly necessary, being that fix_object probably
485  * recalculates this anyway.
486  */
487  for (j=0;j<NUM_STATS;j++)
488  change_attr_value(&(op->stats),j,flag*get_attr_value(&(tmp->stats),j));
489  check_stat_bounds(&(op->stats));
490  } /* end of potion handling code */
491  }
492 
493  /* reset attributes that fix_object doesn't reset since it doesn't search
494  * everything to set
495  */
496  if (flag == -1) {
497  op->attacktype&=~tmp->attacktype;
498  op->path_attuned&=~tmp->path_attuned;
499  op->path_repelled&=~tmp->path_repelled;
500  op->path_denied&=~tmp->path_denied;
501  /* Presuming here that creatures only have move_type,
502  * and not the other move_ fields.
503  */
504  op->move_type &= ~tmp->move_type;
505  }
506 
507  /* call fix_object since op object could have whatever attribute due
508  * to multiple items. if fix_object always has to be called after
509  * change_ability then might as well call it from here
510  */
511  fix_object(op);
512 
513  /* Fix player won't add the bows ability to the player, so don't
514  * print out message if this is a bow.
515  */
516  if (tmp->attacktype & AT_CONFUSION && tmp->type != BOW) {
517  success=1;
519  "Your hands begin to glow red.",
520  "Your hands stop glowing red.");
521  }
522  if (QUERY_FLAG(op,FLAG_LIFESAVE) != QUERY_FLAG(&refop,FLAG_LIFESAVE)) {
523  success=1;
525  "You feel very protected.",
526  "You don't feel protected anymore.");
527  }
529  success=1;
531  "A magic force shimmers around you.",
532  "The magic force fades away.");
533  }
535  success=1;
537  "You feel more safe now, somehow.",
538  "Suddenly you feel less safe, somehow.");
539  }
540  /* movement type has changed. We don't care about cases where
541  * user has multiple items giving the same type appled like we
542  * used to - that is more work than what we gain, plus messages
543  * can be misleading (a little higher could be miscontrued from
544  * from fly high)
545  */
546  if (tmp->move_type && op->move_type != refop.move_type) {
547  success=1;
548 
549  /* MOVE_FLY_HIGH trumps MOVE_FLY_LOW - changing your move_fly_low
550  * status doesn't make a difference if you are flying high
551  */
552  if (tmp->move_type & MOVE_FLY_LOW && !(op->move_type & MOVE_FLY_HIGH)) {
554  "You start to float in the air!.",
555  "You float down to the ground.");
556  }
557 
558  if (tmp->move_type & MOVE_FLY_HIGH) {
559  /* double conditional - second case covers if you have move_fly_low -
560  * in that case, you don't actually land
561  */
563  "You soar into the air air!.",
564  (op->move_type&MOVE_FLY_LOW ? "You fly lower in the air":
565  "You float down to the ground."));
566  }
567  if (tmp->move_type & MOVE_SWIM)
569  "You feel ready for a swim",
570  "You no longer feel like swimming");
571 
572  /* Changing move status may mean you are affected by things you weren't before */
573  check_move_on(op, op);
574  }
575 
576  /* becoming UNDEAD... a special treatment for this flag. Only those not
577  * originally undead may change their status
578  */
579  if (!QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD))
580  if (QUERY_FLAG(op,FLAG_UNDEAD) != QUERY_FLAG(&refop,FLAG_UNDEAD)) {
581  success=1;
582  if (flag>0) {
583  if (op->race) free_string(op->race);
584  op->race=add_string("undead");
586  "Your lifeforce drains away!", NULL);
587  } else {
588  if (op->race) free_string(op->race);
589  if (op->arch->clone.race)
590  op->race=add_string(op->arch->clone.race);
591  else
592  op->race = NULL;
594  "Your lifeforce returns!", NULL);
595  }
596  }
597 
598  if (QUERY_FLAG(op,FLAG_STEALTH) != QUERY_FLAG(&refop,FLAG_STEALTH)) {
599  success=1;
601  "You walk more quietly.",
602  "You walk more noisily.");
603  }
605  success=1;
607  "You become transparent.",
608  "You can see yourself.");
609  }
610  /* blinded you can tell if more blinded since blinded player has minimal
611  * vision
612  */
613  if (QUERY_FLAG(tmp,FLAG_BLIND)) {
614  success=1;
615  if (flag>0) {
616  if (QUERY_FLAG(op,FLAG_WIZ))
618  "Your mortal self is blinded.", NULL);
619  else {
621  "You are blinded.", NULL);
622  SET_FLAG(op,FLAG_BLIND);
623  if (op->type==PLAYER)
624  op->contr->do_los=1;
625  }
626  } else {
627  if (QUERY_FLAG(op,FLAG_WIZ))
629  "Your mortal self can now see again.", NULL);
630  else {
632  "Your vision returns.", NULL);
634  if (op->type==PLAYER)
635  op->contr->do_los=1;
636  }
637  }
638  }
639 
641  success=1;
642  if (op->type==PLAYER)
643  op->contr->do_los=1;
645  "Your vision is better in the dark.",
646  "You see less well in the dark.");
647  }
648 
649  if (QUERY_FLAG(op,FLAG_XRAYS) != QUERY_FLAG(&refop,FLAG_XRAYS)) {
650  success=1;
651  if (flag>0) {
652  if (QUERY_FLAG(op,FLAG_WIZ))
654  "Your vision becomes a little clearer.", NULL);
655  else {
657  "Everything becomes transparent.", NULL);
658  if (op->type==PLAYER)
659  op->contr->do_los=1;
660  }
661  } else {
662  if (QUERY_FLAG(op,FLAG_WIZ))
664  "Your vision becomes a bit out of focus.", NULL);
665  else {
667  "Everything suddenly looks very solid.", NULL);
668  if (op->type==PLAYER)
669  op->contr->do_los=1;
670  }
671  }
672  }
673 
674  if (tmp->stats.luck) {
675  success=1;
677  "You feel more lucky.",
678  "You feel less lucky.");
679  }
680 
681  if (tmp->stats.hp && op->type==PLAYER) {
682  success=1;
684  "You feel much more healthy!",
685  "You feel much less healthy!");
686  }
687 
688  if (tmp->stats.sp && op->type==PLAYER && tmp->type!=SKILL) {
689  success=1;
691  "You feel one with the powers of magic!",
692  "You suddenly feel very mundane.");
693  }
694 
695  /* for the future when artifacts set this -b.t. */
696  if (tmp->stats.grace && op->type==PLAYER) {
697  success=1;
699  "You feel closer to your god!",
700  "You suddenly feel less holy.");
701  }
702 
703  if (tmp->stats.food && op->type==PLAYER) {
704  success=1;
706  "You feel your digestion slowing down.",
707  "You feel your digestion speeding up.");
708  }
709 
710  /* Messages for changed resistance */
711  for (i=0; i<NROFATTACKS; i++) {
712  if (i==ATNR_PHYSICAL) continue; /* Don't display about armour */
713 
714  if (op->resist[i] != refop.resist[i]) {
715  success=1;
716  if (op->resist[i] > refop.resist[i])
718  "Your resistance to %s rises to %d%%.",
719  "Your resistance to %s rises to %d%%.",
720  change_resist_msg[i], op->resist[i]);
721  else
723  "Your resistance to %s drops to %d%%.",
724  "Your resistance to %s drops to %d%%.",
725  change_resist_msg[i], op->resist[i]);
726  }
727  }
728 
729  if (tmp->type!=EXPERIENCE && !potion_max) {
730  for (j=0; j<NUM_STATS; j++) {
731  if ((i=get_attr_value(&(tmp->stats),j))!=0) {
732  success=1;
734  }
735  }
736  }
737  return success;
738 }
739 
748 void drain_stat(object *op) {
749  drain_specific_stat(op, RANDOM()%NUM_STATS);
750 }
751 
760 void drain_specific_stat(object *op, int deplete_stats) {
761  object *tmp;
762  archetype *at;
763 
765  if (!at) {
766  LOG(llevError, "Couldn't find archetype depletion.\n");
767  return;
768  } else {
769  tmp = present_arch_in_ob(at, op);
770  if (!tmp) {
771  tmp = arch_to_object(at);
772  tmp = insert_ob_in_ob(tmp, op);
773  SET_FLAG(tmp,FLAG_APPLIED);
774  }
775  }
776 
778  change_attr_value(&tmp->stats, deplete_stats, -1);
779  fix_object(op);
780 }
781 
791 void change_luck(object *op, int value) {
792  object *tmp;
793  archetype *at;
794  int new_luck;
795 
796  at = find_archetype("luck");
797  if (!at)
798  LOG(llevError, "Couldn't find archetype luck.\n");
799  else {
800  tmp = present_arch_in_ob(at, op);
801  if (!tmp) {
802  if (!value)
803  return;
804  tmp = arch_to_object(at);
805  tmp = insert_ob_in_ob(tmp, op);
806  SET_FLAG(tmp,FLAG_APPLIED);
807  }
808  if (value) {
809  /* Limit the luck value of the bad luck object to +/-100. This
810  * (arbitrary) value prevents overflows (both in the bad luck object and
811  * in op itself).
812  */
813  new_luck = tmp->stats.luck+value;
814  if (new_luck >= -100 && new_luck <= 100) {
815  op->stats.luck+=value;
816  tmp->stats.luck = new_luck;
817  }
818  } else {
819  if (!tmp->stats.luck) {
820  return;
821  }
822  /* Randomly change the players luck. Basically, we move it
823  * back neutral (if greater>0, subtract, otherwise add)
824  */
825  if (RANDOM()%(FABS(tmp->stats.luck)) >= RANDOM()%30) {
826  int diff = tmp->stats.luck>0?-1:1;
827  op->stats.luck += diff;
828  tmp->stats.luck += diff;
829  }
830  }
831  }
832 }
833 
840 void remove_statbonus(object *op) {
841  op->stats.Str -= op->arch->clone.stats.Str;
842  op->stats.Dex -= op->arch->clone.stats.Dex;
843  op->stats.Con -= op->arch->clone.stats.Con;
844  op->stats.Wis -= op->arch->clone.stats.Wis;
845  op->stats.Pow -= op->arch->clone.stats.Pow;
846  op->stats.Cha -= op->arch->clone.stats.Cha;
847  op->stats.Int -= op->arch->clone.stats.Int;
848  op->contr->orig_stats.Str -= op->arch->clone.stats.Str;
849  op->contr->orig_stats.Dex -= op->arch->clone.stats.Dex;
850  op->contr->orig_stats.Con -= op->arch->clone.stats.Con;
851  op->contr->orig_stats.Wis -= op->arch->clone.stats.Wis;
852  op->contr->orig_stats.Pow -= op->arch->clone.stats.Pow;
853  op->contr->orig_stats.Cha -= op->arch->clone.stats.Cha;
854  op->contr->orig_stats.Int -= op->arch->clone.stats.Int;
855 }
856 
863 void add_statbonus(object *op) {
864  op->stats.Str += op->arch->clone.stats.Str;
865  op->stats.Dex += op->arch->clone.stats.Dex;
866  op->stats.Con += op->arch->clone.stats.Con;
867  op->stats.Wis += op->arch->clone.stats.Wis;
868  op->stats.Pow += op->arch->clone.stats.Pow;
869  op->stats.Cha += op->arch->clone.stats.Cha;
870  op->stats.Int += op->arch->clone.stats.Int;
871  op->contr->orig_stats.Str += op->arch->clone.stats.Str;
872  op->contr->orig_stats.Dex += op->arch->clone.stats.Dex;
873  op->contr->orig_stats.Con += op->arch->clone.stats.Con;
874  op->contr->orig_stats.Wis += op->arch->clone.stats.Wis;
875  op->contr->orig_stats.Pow += op->arch->clone.stats.Pow;
876  op->contr->orig_stats.Cha += op->arch->clone.stats.Cha;
877  op->contr->orig_stats.Int += op->arch->clone.stats.Int;
878 }
879 
900 void fix_object(object *op) {
901  int i,j;
902  float f,max=9,added_speed=0,bonus_speed=0, sp_tmp,speed_reduce_from_disease=1;
903  int weapon_weight=0,weapon_speed=0;
904  int best_wc=0, best_ac=0, wc=0, ac=0;
905  int prot[NROFATTACKS], vuln[NROFATTACKS], potion_resist[NROFATTACKS];
906  object *grace_obj=NULL,*mana_obj=NULL,*wc_obj=NULL,*tmp;
907 
908  /* First task is to clear all the values back to their original values */
909  if (op->type==PLAYER) {
910  for (i=0;i<NUM_STATS;i++) {
911  set_attr_value(&(op->stats),i,get_attr_value(&(op->contr->orig_stats),i));
912  }
914  op->contr->encumbrance=0;
915 
916  op->attacktype=0;
917  op->contr->digestion = 0;
918  op->contr->gen_hp = 0;
919  op->contr->gen_sp = 0;
920  op->contr->gen_grace = 0;
921  op->contr->gen_sp_armour = 10;
922  op->contr->item_power = 0;
923 
924  /* Don't clobber all the range_ values. range_golem otherwise
925  * gets reset for no good reason, and we don't want to reset
926  * range_magic (what spell is readied). These three below
927  * well get filled in based on what the player has equipped.
928  */
929  op->contr->ranges[range_bow] = NULL;
930  op->contr->ranges[range_misc] = NULL;
931  op->contr->ranges[range_skill] = NULL;
932  } /* If player */
933  memcpy(op->body_used, op->body_info, sizeof(op->body_info));
934 
935  if (op->slaying!=NULL) {
936  free_string(op->slaying);
937  op->slaying=NULL;
938  }
939  if (!QUERY_FLAG(op,FLAG_WIZ)) {
940  CLEAR_FLAG(op, FLAG_XRAYS);
942  }
943 
947  if (!QUERY_FLAG(&op->arch->clone, FLAG_REFL_SPELL))
949  if (!QUERY_FLAG(&op->arch->clone, FLAG_REFL_MISSILE))
951  if (!QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD))
953  if (!QUERY_FLAG(&op->arch->clone, FLAG_SEE_IN_DARK))
955 
960  op->move_type = op->arch->clone.move_type;
961  op->chosen_skill = NULL;
962 
963  /* initializing resistances from the values in player/monster's
964  * archetype clone
965  */
966  memcpy(&op->resist, &op->arch->clone.resist, sizeof(op->resist));
967 
968  for (i=0;i<NROFATTACKS;i++) {
969  if (op->resist[i] > 0)
970  prot[i]= op->resist[i], vuln[i]=0;
971  else
972  vuln[i]= -(op->resist[i]), prot[i]=0;
973  potion_resist[i]=0;
974  }
975 
976  wc=op->arch->clone.stats.wc;
977  op->stats.dam=op->arch->clone.stats.dam;
978 
979  /* for players which cannot use armour, they gain AC -1 per 3 levels,
980  * plus a small amount of physical resist, those poor suckers. ;)
981  * the fact that maxlevel is factored in could be considered sort of bogus -
982  * we should probably give them some bonus and cap it off - otherwise,
983  * basically, if a server updates its max level, these playes may find
984  * that their protection from physical goes down
985  */
986  if (!QUERY_FLAG(op,FLAG_USE_ARMOUR) && op->type==PLAYER) {
987  ac=MAX(-10,op->arch->clone.stats.ac - op->level/3);
988  prot[ATNR_PHYSICAL] += ((100-prot[AT_PHYSICAL])*(80*op->level/settings.max_level))/100;
989  } else
990  ac=op->arch->clone.stats.ac;
991 
992  op->stats.luck=op->arch->clone.stats.luck;
993  op->speed = op->arch->clone.speed;
994 
995  /* OK - we've reset most all the objects attributes to sane values.
996  * now go through and make adjustments for what the player has equipped.
997  */
998 
999  for (tmp=op->inv;tmp!=NULL;tmp=tmp->below) {
1000  /* See note in map.c:update_position about making this additive
1001  * since light sources are never applied, need to put check here.
1002  */
1003  if (tmp->glow_radius > op->glow_radius)
1004  op->glow_radius=tmp->glow_radius;
1005 
1006  /* This happens because apply_potion calls change_abil with the potion
1007  * applied so we can tell the player what chagned. But change_abil
1008  * then calls this function.
1009  */
1010  if (QUERY_FLAG(tmp, FLAG_APPLIED) && tmp->type == POTION)
1011  continue;
1012 
1013  /* For some things, we don't care what is equipped */
1014  if (tmp->type == SKILL) {
1015  /* Want to take the highest skill here. */
1016  if (IS_MANA_SKILL(tmp->subtype)) {
1017  if (!mana_obj)
1018  mana_obj = tmp;
1019  else if (tmp->level > mana_obj->level)
1020  mana_obj = tmp;
1021  }
1022  if (IS_GRACE_SKILL(tmp->subtype)) {
1023  if (!grace_obj)
1024  grace_obj=tmp;
1025  else if (tmp->level > grace_obj->level)
1026  grace_obj = tmp;
1027  }
1028  }
1029 
1030  /* Container objects are not meant to adjust a players, but other applied
1031  * objects need to make adjustments.
1032  * This block should handle all player specific changes
1033  * The check for Praying is a bit of a hack - god given bonuses are put
1034  * in the praying skill, and the player should always get those.
1035  * It also means we need to put in additional checks for applied below,
1036  * because the skill shouldn't count against body positions being used
1037  * up, etc.
1038  */
1039  if ((QUERY_FLAG(tmp,FLAG_APPLIED) && tmp->type!=CONTAINER && tmp->type!=CLOSE_CON) ||
1040  (tmp->type == SKILL && tmp->subtype == SK_PRAYING)) {
1041  if (op->type==PLAYER) {
1042  if (tmp->type == BOW)
1043  op->contr->ranges[range_bow] = tmp;
1044 
1045  if (tmp->type == WAND || tmp->type == ROD || tmp->type==HORN)
1046  op->contr->ranges[range_misc] = tmp;
1047 
1048  for (i=0;i<NUM_STATS;i++)
1049  change_attr_value(&(op->stats),i,get_attr_value(&(tmp->stats),i));
1050 
1051  /* these are the items that currently can change digestion, regeneration,
1052  * spell point recovery and mana point recovery. Seems sort of an arbitary
1053  * list, but other items store other info into stats array.
1054  */
1055  if ((tmp->type == EXPERIENCE) || (tmp->type == WEAPON) ||
1056  (tmp->type == ARMOUR) || (tmp->type == HELMET) ||
1057  (tmp->type == SHIELD) || (tmp->type == RING) ||
1058  (tmp->type == BOOTS) || (tmp->type == GLOVES) ||
1059  (tmp->type == AMULET) || (tmp->type == GIRDLE) ||
1060  (tmp->type == BRACERS) || (tmp->type == CLOAK) ||
1061  (tmp->type == DISEASE) || (tmp->type == FORCE) ||
1062  (tmp->type == SKILL)) {
1063  op->contr->digestion += tmp->stats.food;
1064  op->contr->gen_hp += tmp->stats.hp;
1065  op->contr->gen_sp += tmp->stats.sp;
1066  op->contr->gen_grace += tmp->stats.grace;
1067  op->contr->gen_sp_armour+= tmp->gen_sp_armour;
1068  op->contr->item_power += tmp->item_power;
1069  }
1070  } /* if this is a player */
1071 
1072  /* Update slots used for items */
1073  if (QUERY_FLAG(tmp,FLAG_APPLIED)) {
1074  for (i=0; i<NUM_BODY_LOCATIONS; i++)
1075  op->body_used[i] += tmp->body_info[i];
1076  }
1077 
1078  if(tmp->type==SYMPTOM) {
1079  speed_reduce_from_disease = tmp->last_sp / 100.0;
1080  if(speed_reduce_from_disease ==0)
1081  speed_reduce_from_disease = 1;
1082  }
1083 
1084  /* Pos. and neg. protections are counted seperate (-> pro/vuln).
1085  * (Negative protections are calculated extactly like positive.)
1086  * Resistance from potions are treated special as well. If there's
1087  * more than one potion-effect, the bigger prot.-value is taken.
1088  */
1089  if (tmp->type != POTION) {
1090  for (i=0; i<NROFATTACKS; i++) {
1091  /* Potential for cursed potions, in which case we just can use
1092  * a straight MAX, as potion_resist is initialized to zero.
1093  */
1094  if (tmp->type==POTION_EFFECT) {
1095  if (potion_resist[i])
1096  potion_resist[i] = MAX(potion_resist[i], tmp->resist[i]);
1097  else
1098  potion_resist[i] = tmp->resist[i];
1099  } else if (tmp->resist[i] > 0)
1100  prot[i] += ((100-prot[i])*tmp->resist[i])/100;
1101  else if (tmp->resist[i] < 0)
1102  vuln[i] += ((100-vuln[i])*(-tmp->resist[i]))/100;
1103  }
1104  }
1105 
1106  /* There may be other things that should not adjust the attacktype */
1107  if (tmp->type!=BOW && tmp->type != SYMPTOM)
1108  op->attacktype|=tmp->attacktype;
1109 
1110  op->path_attuned|=tmp->path_attuned;
1111  op->path_repelled|=tmp->path_repelled;
1112  op->path_denied|=tmp->path_denied;
1113  op->stats.luck+=tmp->stats.luck;
1114  op->move_type |= tmp->move_type;
1115 
1116  if (QUERY_FLAG(tmp,FLAG_LIFESAVE))
1117  SET_FLAG(op,FLAG_LIFESAVE);
1118  if (QUERY_FLAG(tmp,FLAG_REFL_SPELL))
1120  if (QUERY_FLAG(tmp,FLAG_REFL_MISSILE))
1122  if (QUERY_FLAG(tmp,FLAG_STEALTH))
1123  SET_FLAG(op,FLAG_STEALTH);
1124  if (QUERY_FLAG(tmp,FLAG_XRAYS))
1125  SET_FLAG(op,FLAG_XRAYS);
1126  if (QUERY_FLAG(tmp,FLAG_BLIND))
1127  SET_FLAG(op,FLAG_BLIND);
1128  if (QUERY_FLAG(tmp,FLAG_SEE_IN_DARK))
1130 
1131  if (QUERY_FLAG(tmp,FLAG_UNDEAD) && !QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD))
1132  SET_FLAG(op,FLAG_UNDEAD);
1133 
1134  if (QUERY_FLAG(tmp,FLAG_MAKE_INVIS)) {
1136  op->invisible=1;
1137  }
1138 
1139  if (tmp->stats.exp && tmp->type!=SKILL) {
1140  if(tmp->stats.exp > 0) {
1141  added_speed+=(float)tmp->stats.exp/3.0;
1142  bonus_speed+=1.0+(float)tmp->stats.exp/3.0;
1143  } else
1144  added_speed+=(float)tmp->stats.exp;
1145  }
1146 
1147  switch (tmp->type) {
1148  /* skills modifying the character -b.t. */
1149  /* for all skills and skill granting objects */
1150  case SKILL:
1151  if (!QUERY_FLAG(tmp,FLAG_APPLIED))
1152  break;
1153 
1154  if (IS_COMBAT_SKILL(tmp->subtype))
1155  wc_obj=tmp;
1156 
1157  if (op->chosen_skill) {
1158  LOG(llevDebug, "fix_object, op %s has multiple skills applied\n", op->name);
1159  }
1160  op->chosen_skill = tmp;
1161  if (tmp->stats.dam>0) { /* skill is a 'weapon' */
1162  if (!QUERY_FLAG(op,FLAG_READY_WEAPON))
1163  weapon_speed = (int) WEAPON_SPEED(tmp);
1164  if (weapon_speed<0)
1165  weapon_speed = 0;
1166  weapon_weight=tmp->weight;
1167  op->stats.dam+=tmp->stats.dam*(1 + (op->chosen_skill->level/9));
1168  if (tmp->magic)
1169  op->stats.dam += tmp->magic;
1170  }
1171  if (tmp->stats.wc)
1172  wc-=(tmp->stats.wc+tmp->magic);
1173 
1174  if (tmp->slaying!=NULL) {
1175  if (op->slaying != NULL)
1176  free_string(op->slaying);
1177  add_refcount(op->slaying = tmp->slaying);
1178  }
1179 
1180  if (tmp->stats.ac)
1181  ac-=(tmp->stats.ac+tmp->magic);
1182  if (settings.spell_encumbrance == TRUE && op->type==PLAYER)
1183  op->contr->encumbrance+=(int)3*tmp->weight/1000;
1184  if (op->type == PLAYER)
1185  op->contr->ranges[range_skill] = op;
1186  break;
1187 
1188  case SKILL_TOOL:
1189  if (op->chosen_skill) {
1190  LOG(llevDebug, "fix_object, op %s has multiple skills applied\n", op->name);
1191  }
1192  op->chosen_skill = tmp;
1193  if (op->type == PLAYER)
1194  op->contr->ranges[range_skill] = op;
1195  break;
1196 
1197  case SHIELD:
1198  if (settings.spell_encumbrance == TRUE && op->type==PLAYER)
1199  op->contr->encumbrance+=(int)tmp->weight/2000;
1200  case RING:
1201  case AMULET:
1202  case GIRDLE:
1203  case HELMET:
1204  case BOOTS:
1205  case GLOVES:
1206  case CLOAK:
1207  if (tmp->stats.wc)
1208  wc-=(tmp->stats.wc+tmp->magic);
1209  if (tmp->stats.dam)
1210  op->stats.dam+=(tmp->stats.dam+tmp->magic);
1211  if (tmp->stats.ac)
1212  ac-=(tmp->stats.ac+tmp->magic);
1213  break;
1214 
1215  case WEAPON:
1216  wc-=(tmp->stats.wc+tmp->magic);
1217  if (tmp->stats.ac&&tmp->stats.ac+tmp->magic>0)
1218  ac-=tmp->stats.ac+tmp->magic;
1219  op->stats.dam+=(tmp->stats.dam+tmp->magic);
1220  weapon_weight=tmp->weight;
1221  weapon_speed=((int)WEAPON_SPEED(tmp)*2-tmp->magic)/2;
1222  if (weapon_speed<0)
1223  weapon_speed=0;
1224  if (tmp->slaying!=NULL) {
1225  if (op->slaying != NULL)
1226  free_string(op->slaying);
1227  add_refcount(op->slaying = tmp->slaying);
1228  }
1229  /* If there is desire that two handed weapons should do
1230  * extra strength damage, this is where the code should
1231  * go.
1232  */
1233  op->current_weapon = tmp;
1234  if (settings.spell_encumbrance == TRUE && op->type==PLAYER)
1235  op->contr->encumbrance+=(int)3*tmp->weight/1000;
1236  break;
1237 
1238  case ARMOUR: /* Only the best of these three are used: */
1239  if (settings.spell_encumbrance == TRUE && op->type==PLAYER)
1240  op->contr->encumbrance+=(int)tmp->weight/1000;
1241 
1242  case BRACERS:
1243  case FORCE:
1244  if (tmp->stats.wc) {
1245  if (best_wc<tmp->stats.wc+tmp->magic) {
1246  wc+=best_wc;
1247  best_wc=tmp->stats.wc+tmp->magic;
1248  } else
1249  wc+=tmp->stats.wc+tmp->magic;
1250  }
1251  if (tmp->stats.ac) {
1252  if (best_ac<tmp->stats.ac+tmp->magic) {
1253  ac+=best_ac; /* Remove last bonus */
1254  best_ac=tmp->stats.ac+tmp->magic;
1255  } else /* To nullify the below effect */
1256  ac+=tmp->stats.ac+tmp->magic;
1257  }
1258  if (tmp->stats.dam && tmp->type == BRACERS)
1259  op->stats.dam+=(tmp->stats.dam+tmp->magic);
1260  if (tmp->stats.wc)
1261  wc-=(tmp->stats.wc+tmp->magic);
1262  if (tmp->stats.ac)
1263  ac-=(tmp->stats.ac+tmp->magic);
1264  if (ARMOUR_SPEED(tmp) && ARMOUR_SPEED(tmp)/10.0<max)
1265  max=ARMOUR_SPEED(tmp)/10.0;
1266  break;
1267  } /* switch tmp->type */
1268  } /* item is equipped */
1269  } /* for loop of items */
1270 
1271  /* We've gone through all the objects the player has equipped. For many things, we
1272  * have generated intermediate values which we now need to assign.
1273  */
1274 
1275  /* 'total resistance = total protections - total vulnerabilities'.
1276  * If there is an uncursed potion in effect, granting more protection
1277  * than that, we take: 'total resistance = resistance from potion'.
1278  * If there is a cursed (and no uncursed) potion in effect, we take
1279  * 'total resistance = vulnerability from cursed potion'.
1280  */
1281  for (i=0; i<NROFATTACKS; i++) {
1282  op->resist[i] = prot[i] - vuln[i];
1283  if (potion_resist[i] && ((potion_resist[i] > op->resist[i]) ||
1284  (potion_resist[i] < 0)))
1285  op->resist[i] = potion_resist[i];
1286  }
1287 
1288  /* Figure out the players sp/mana/hp totals. */
1289  if (op->type==PLAYER) {
1290  int pl_level;
1291 
1292  check_stat_bounds(&(op->stats));
1293  pl_level=op->level;
1294 
1295  if (pl_level<1)
1296  pl_level=1; /* safety, we should always get 1 levels worth of hp! */
1297 
1298  /* You basically get half a con bonus/level. But we do take into account rounding,
1299  * so if your bonus is 7, you still get 7 worth of bonus every 2 levels.
1300  */
1301  for (i=1,op->stats.maxhp=0;i<=pl_level&&i<=10;i++) {
1302  j = op->contr->levhp[i] + con_bonus[op->stats.Con] / 2;
1303  if (i%2 && con_bonus[op->stats.Con]%2) {
1304  if (con_bonus[op->stats.Con]>0)
1305  j++;
1306  else
1307  j--;
1308  }
1309  op->stats.maxhp+=j>1?j:1; /* always get at least 1 hp/level */
1310  }
1311 
1312  for (i=11;i<=op->level;i++)
1313  op->stats.maxhp+=2;
1314 
1315  if (op->stats.hp>op->stats.maxhp)
1316  op->stats.hp=op->stats.maxhp;
1317 
1318  /* Sp gain is controlled by the level of the player's
1319  * relevant experience object (mana_obj, see above)
1320  */
1321  /* following happen when skills system is not used */
1322  if (!mana_obj)
1323  mana_obj = op;
1324  if (!grace_obj)
1325  grace_obj = op;
1326 
1327  /* set maxsp */
1328  if (!mana_obj || !mana_obj->level || op->type!=PLAYER)
1329  mana_obj = op;
1330 
1331  if (mana_obj == op && op->type == PLAYER) {
1332  op->stats.maxsp = 1;
1333  } else {
1334  sp_tmp=0.0;
1335  for (i=1;i<=mana_obj->level&&i<=10;i++) {
1336  float stmp;
1337 
1338  /* Got some extra bonus at first level */
1339  if (i<2) {
1340  stmp = op->contr->levsp[i] +((2.0 * (float)sp_bonus[op->stats.Pow] +
1341  (float)sp_bonus[op->stats.Int])/6.0);
1342  } else {
1343  stmp=(float)op->contr->levsp[i]
1344  +(2.0 * (float)sp_bonus[op->stats.Pow] +
1345  (float)sp_bonus[op->stats.Int])/12.0;
1346  }
1347  if (stmp<1.0)
1348  stmp=1.0;
1349  sp_tmp+=stmp;
1350  }
1351  op->stats.maxsp=(int)sp_tmp;
1352 
1353  for (i=11;i<=mana_obj->level;i++)
1354  op->stats.maxsp+=2;
1355  }
1356 
1357  /* Characters can get their sp supercharged via rune of transferrance */
1358  if (op->stats.sp>op->stats.maxsp*2)
1359  op->stats.sp=op->stats.maxsp*2;
1360 
1361  /* set maxgrace, notice 3-4 lines below it depends on both Wis and Pow */
1362  if (!grace_obj || !grace_obj->level || op->type!=PLAYER)
1363  grace_obj = op;
1364 
1365  if (grace_obj == op && op->type == PLAYER) {
1366  op->stats.maxgrace = 1;
1367  } else {
1368  /* store grace in a float - this way, the divisions below don't create
1369  * big jumps when you go from level to level - with int's, it then
1370  * becomes big jumps when the sums of the bonuses jump to the next
1371  * step of 8 - with floats, even fractional ones are useful.
1372  */
1373  sp_tmp=0.0;
1374  for (i=1,op->stats.maxgrace=0;i<=grace_obj->level&&i<=10;i++) {
1375  float grace_tmp=0.0;
1376 
1377  /* Got some extra bonus at first level */
1378  if (i<2) {
1379  grace_tmp = op->contr->levgrace[i]+(((float)grace_bonus[op->stats.Pow] +
1380  2.0 * (float)grace_bonus[op->stats.Wis])/6.0);
1381  } else {
1382  grace_tmp=(float)op->contr->levgrace[i]
1383  +((float)grace_bonus[op->stats.Pow] +
1384  2.0 * (float)grace_bonus[op->stats.Wis])/12.0;
1385  }
1386  if (grace_tmp<1.0)
1387  grace_tmp=1.0;
1388  sp_tmp+=grace_tmp;
1389  }
1390  op->stats.maxgrace=(int)sp_tmp;
1391 
1392  /* two grace points per level after 11 */
1393  for (i=11;i<=grace_obj->level;i++)
1394  op->stats.maxgrace+=2;
1395  }
1396  /* No limit on grace vs maxgrace */
1397 
1398  if (op->contr->braced) {
1399  ac+=2;
1400  wc+=4;
1401  } else
1402  ac-=dex_bonus[op->stats.Dex];
1403 
1404  /* In new exp/skills system, wc bonuses are related to
1405  * the players level in a relevant exp object (wc_obj)
1406  * not the general player level -b.t.
1407  * I changed this slightly so that wc bonuses are better
1408  * than before. This is to balance out the fact that
1409  * the player no longer gets a personal weapon w/ 1
1410  * improvement every level, now its fighterlevel/5. So
1411  * we give the player a bonus here in wc and dam
1412  * to make up for the change. Note that I left the
1413  * monster bonus the same as before. -b.t.
1414  */
1415 
1416  if (op->type==PLAYER && wc_obj && wc_obj->level>1) {
1417  wc-=(wc_obj->level+thaco_bonus[op->stats.Str]);
1418  for(i=1;i<wc_obj->level;i++) {
1419  /* addtional wc every 6 levels */
1420  if(!(i%6)) wc--;
1421  /* addtional dam every 4 levels. */
1422  if(!(i%4) && (dam_bonus[op->stats.Str]>=0))
1423  op->stats.dam+=(1+(dam_bonus[op->stats.Str]/5));
1424  }
1425  } else
1426  wc-=(op->level+thaco_bonus[op->stats.Str]);
1427 
1428  op->stats.dam+=dam_bonus[op->stats.Str];
1429 
1430  if(op->stats.dam<1)
1431  op->stats.dam=1;
1432 
1433  op->speed = 1.0 + speed_bonus[op->stats.Dex];
1434  if (settings.search_items && op->contr->search_str[0])
1435  op->speed -= 1;
1436  if (op->attacktype==0)
1437  op->attacktype=op->arch->clone.attacktype;
1438 
1439  } /* End if player */
1440 
1441  /* Max is determined by armour */
1442  if (op->speed>max)
1443  op->speed=max;
1444 
1445  if(added_speed>=0)
1446  op->speed+=added_speed/10.0;
1447  else /* Something wrong here...: */
1448  op->speed /= (float)(1.0-added_speed);
1449 
1450  op->speed+=bonus_speed/10.0; /* Not affected by limits */
1451 
1452  if(op->type == PLAYER) {
1453  /* f is a number the represents the number of kg above (positive num)
1454  * or below (negative number) that the player is carrying. If above
1455  * weight limit, then player suffers a speed reduction based on how
1456  * much above he is, and what is max carry is
1457  */
1458  f=(op->carrying/1000)-max_carry[op->stats.Str];
1459  if(f>0)
1460  op->speed=op->speed/(1.0+f/max_carry[op->stats.Str]);
1461  }
1462 
1463  /* Put a lower limit on speed. Note with this speed, you move once every
1464  * 100 ticks or so. This amounts to once every 12 seconds of realtime.
1465  */
1466  op->speed = op->speed * speed_reduce_from_disease;
1467 
1468  if (op->speed<0.01 && op->type==PLAYER)
1469  op->speed=0.01;
1470 
1471  if(op->type == PLAYER) {
1472  float M,W,s,D,K,S,M2;
1473 
1474  /* (This formula was made by vidarl@ifi.uio.no)
1475  * Note that we never used these values again - basically
1476  * all of these could be subbed into one big equation, but
1477  * that would just be a real pain to read.
1478  */
1479  M=(max_carry[op->stats.Str]-121)/121.0;
1480  M2=max_carry[op->stats.Str]/100.0;
1481  W=weapon_weight/20000.0;
1482  s=2-weapon_speed/10.0;
1483  D=(op->stats.Dex-14)/14.0;
1484  K=1 + M/3.0 - W/(3*M2) + op->speed/5.0 + D/2.0;
1485  K*=(4+op->level)/(float)(6+op->level)*1.2;
1486  if(K<=0)
1487  K=0.01;
1488  S=op->speed/(K*s);
1489  op->contr->weapon_sp=S;
1490  }
1491  /* I want to limit the power of small monsters with big weapons: */
1492  if (op->type!=PLAYER&&op->arch!=NULL&&
1493  op->stats.dam>op->arch->clone.stats.dam*3)
1494  op->stats.dam=op->arch->clone.stats.dam*3;
1495 
1496  /* Prevent overflows of wc - best you can get is ABS(120) - this
1497  * should be more than enough - remember, AC is also in 8 bits,
1498  * so its value is the same.
1499  */
1500  if (wc>120)
1501  wc=120;
1502  else if (wc<-120)
1503  wc=-120;
1504  op->stats.wc=wc;
1505 
1506  if (ac>120)
1507  ac=120;
1508  else if (ac<-120)
1509  ac=-120;
1510  op->stats.ac=ac;
1511 
1512  /* if for some reason the creature doesn't have any move type,
1513  * give them walking as a default.
1514  * The second case is a special case - to more closely mimic the
1515  * old behaviour - if your flying, your not walking - just
1516  * one or the other.
1517  */
1518  if (op->move_type == 0)
1519  op->move_type = MOVE_WALK;
1520  else if (op->move_type & (MOVE_FLY_LOW | MOVE_FLY_HIGH))
1521  op->move_type &= ~MOVE_WALK;
1522 
1523  update_ob_speed(op);
1524 
1525  /* It is quite possible that a player's spell costing might have changed,
1526  * so we will check that now.
1527  */
1528  if (op->type == PLAYER) esrv_update_spells(op->contr);
1529 }
1530 
1543 int allowed_class(const object *op) {
1544  return op->stats.Dex>0&&op->stats.Str>0&&op->stats.Con>0&&
1545  op->stats.Int>0&&op->stats.Wis>0&&op->stats.Pow>0&&
1546  op->stats.Cha>0;
1547 }
1548 
1566 void set_dragon_name(object *pl, const object *abil, const object *skin) {
1567  int atnr=-1; /* attacknumber of highest level */
1568  int level=0; /* highest level */
1569  int i;
1570 
1571  /* Perhaps do something more clever? */
1572  if (!abil || !skin) return;
1573 
1574  /* first, look for the highest level */
1575  for (i=0; i<NROFATTACKS; i++) {
1576  if (atnr_is_dragon_enabled(i) &&
1577  (atnr==-1 || abil->resist[i] > abil->resist[atnr])) {
1578  level = abil->resist[i];
1579  atnr = i;
1580  }
1581  }
1582 
1583  /* now if there are equals at highest level, pick the one with focus,
1584  or else at random */
1585  if (atnr_is_dragon_enabled(abil->stats.exp) &&
1586  abil->resist[abil->stats.exp] >= level)
1587  atnr = abil->stats.exp;
1588 
1589  level = (int)(level/5.);
1590 
1591  /* now set the new title */
1592  if (pl->contr != NULL) {
1593  if (level == 0)
1594  snprintf(pl->contr->title, sizeof(pl->contr->title), "%s hatchling", attacks[atnr]);
1595  else if (level == 1)
1596  snprintf(pl->contr->title, sizeof(pl->contr->title), "%s wyrm", attacks[atnr]);
1597  else if (level == 2)
1598  snprintf(pl->contr->title, sizeof(pl->contr->title), "%s wyvern", attacks[atnr]);
1599  else if (level == 3)
1600  snprintf(pl->contr->title, sizeof(pl->contr->title), "%s dragon", attacks[atnr]);
1601  else {
1602  /* special titles for extra high resistance! */
1603  if (skin->resist[atnr] > 80)
1604  snprintf(pl->contr->title, sizeof(pl->contr->title), "legendary %s dragon", attacks[atnr]);
1605  else if (skin->resist[atnr] > 50)
1606  snprintf(pl->contr->title, sizeof(pl->contr->title), "ancient %s dragon", attacks[atnr]);
1607  else
1608  snprintf(pl->contr->title, sizeof(pl->contr->title), "big %s dragon", attacks[atnr]);
1609  }
1610  }
1611 
1612  pl->contr->own_title[0] = '\0';
1613 }
1614 
1623 void dragon_level_gain(object *who) {
1624  object *abil = NULL; /* pointer to dragon ability force*/
1625  object *skin = NULL; /* pointer to dragon skin force*/
1626  object *tmp = NULL; /* tmp. object */
1627 
1628  /* now grab the 'dragon_ability'-forces from the player's inventory */
1629  for (tmp=who->inv; tmp!=NULL; tmp=tmp->below) {
1630  if (tmp->type == FORCE) {
1631  if (strcmp(tmp->arch->name, "dragon_ability_force")==0)
1632  abil = tmp;
1633  if (strcmp(tmp->arch->name, "dragon_skin_force")==0)
1634  skin = tmp;
1635  }
1636  }
1637  /* if the force is missing -> bail out */
1638  if (abil == NULL) return;
1639 
1640  /* The ability_force keeps track of maximum level ever achieved.
1641  * New abilties can only be gained by surpassing this max level
1642  */
1643  if (who->level > abil->level) {
1644  /* increase our focused ability */
1645  abil->resist[abil->stats.exp]++;
1646 
1647  if (abil->resist[abil->stats.exp]>0 && abil->resist[abil->stats.exp]%5 == 0) {
1648  /* time to hand out a new ability-gift */
1649  dragon_ability_gain(who, (int)abil->stats.exp,
1650  (int)((1+abil->resist[abil->stats.exp])/5.));
1651  }
1652 
1653  if (abil->last_eat > 0 && atnr_is_dragon_enabled(abil->last_eat)) {
1654  /* apply new ability focus */
1656  "Your metabolism now focuses on %s!",
1657  "Your metabolism now focuses on %s!",
1658  change_resist_msg[abil->last_eat]);
1659 
1660  abil->stats.exp = abil->last_eat;
1661  abil->last_eat = 0;
1662  }
1663 
1664  abil->level = who->level;
1665  }
1666 
1667  /* last but not least, set the new title for the dragon */
1668  set_dragon_name(who, abil, skin);
1669 }
1670 
1689 object *give_skill_by_name(object *op, const char *skill_name) {
1690  object *skill_obj;
1691  archetype *skill_arch;
1692 
1693  skill_arch = get_archetype_by_skill_name(skill_name, SKILL);
1694  if (!skill_arch) {
1695  LOG(llevError, "add_player_exp: couldn't find skill %s\n", skill_name);
1696  return NULL;
1697  }
1698  skill_obj = arch_to_object(skill_arch); /* never returns NULL. */
1699 
1700  /* clear the flag - exp goes into this bucket, but player
1701  * still doesn't know it.
1702  */
1703  CLEAR_FLAG(skill_obj, FLAG_CAN_USE_SKILL);
1704  skill_obj->stats.exp = 0;
1705  skill_obj->level = 1;
1706  insert_ob_in_ob(skill_obj, op);
1707  if (op->contr) {
1708  op->contr->last_skill_ob[skill_obj->subtype] = skill_obj;
1709  op->contr->last_skill_exp[skill_obj->subtype] = -1;
1710  }
1711  return skill_obj;
1712 }
1713 
1714 
1731 void player_lvl_adj(object *who, object *op) {
1732  char buf[MAX_BUF];
1733 
1734  if (!op) /* when rolling stats */
1735  op = who;
1736 
1737  if (op->level < settings.max_level && op->stats.exp >= level_exp(op->level+1,who->expmul)) {
1738  op->level++;
1739 
1740  if (op != NULL && op == who && op->stats.exp > 1 && is_dragon_pl(who))
1741  dragon_level_gain(who);
1742 
1743  /* Only roll these if it is the player (who) that gained the level */
1744  if (who && op==who && (who->level < 11) && who->type==PLAYER) {
1745  who->contr->levhp[who->level] = die_roll(2, 4, who, PREFER_HIGH)+1;
1746  who->contr->levsp[who->level] = die_roll(2, 3, who, PREFER_HIGH);
1747  who->contr->levgrace[who->level]=die_roll(2, 2, who, PREFER_HIGH)-1;
1748  }
1749 
1750  if (who)
1751  fix_object(who);
1752  if (op->level>1) {
1753  if (op->type!=PLAYER)
1754  snprintf(buf, sizeof(buf), "You are now level %d in the %s skill.",op->level,op->name);
1755  else
1756  snprintf(buf, sizeof(buf), "You are now level %d.",op->level);
1757 
1758  if (who)
1760  }
1761  player_lvl_adj(who,op); /* To increase more levels */
1762  } else if (op->level>1 && op->stats.exp<level_exp(op->level,who->expmul)) {
1763  op->level--;
1764  if (who)
1765  fix_object(who);
1766  if (op->type!=PLAYER) {
1767  if (who)
1769  "You are now level %d in the %s skill.",
1770  "You are now level %d in the %s skill.",
1771  op->level,op->name);
1772  }
1773  player_lvl_adj(who,op); /* To decrease more levels */
1774  }
1775  /* check if the spell data has changed */
1776  esrv_update_spells(who->contr);
1777 }
1778 
1788 sint64 level_exp(int level,double expmul) {
1789  if (level > settings.max_level)
1790  return expmul * levels[settings.max_level];
1791  return expmul * levels[level];
1792 }
1793 
1804 void calc_perm_exp(object *op) {
1805  sint64 p_exp_min;
1806 
1807  /* Ensure that our permanent experience minimum is met.
1808  * permenent_exp_ratio is an integer percentage, we divide by 100
1809  * to get the fraction */
1810  p_exp_min = settings.permanent_exp_ratio*op->stats.exp/100;
1811 
1812  if (op->perm_exp < p_exp_min)
1813  op->perm_exp = p_exp_min;
1814 
1815  /* Cap permanent experience. */
1816  if (op->perm_exp < 0)
1817  op->perm_exp = 0;
1818  else if (op->perm_exp > MAX_EXPERIENCE)
1819  op->perm_exp = MAX_EXPERIENCE;
1820 }
1821 
1822 
1837 static void add_player_exp(object *op, sint64 exp, const char *skill_name, int flag) {
1838  object *skill_obj=NULL;
1839  sint64 limit, exp_to_add;
1840  int i;
1841 
1842  /* prevents some forms of abuse. */
1843  if (op->contr->braced) exp=exp/5;
1844 
1845  /* Try to find the matching skill.
1846  * We do a shortcut/time saving mechanism first - see if it matches
1847  * chosen_skill. This means we don't need to search through
1848  * the players inventory.
1849  */
1850  if (skill_name) {
1851  if (op->chosen_skill && op->chosen_skill->type == SKILL &&
1852  !strcmp(skill_name, op->chosen_skill->skill))
1853  skill_obj = op->chosen_skill;
1854  else {
1855  for (i=0; i<NUM_SKILLS; i++)
1856  if (op->contr->last_skill_ob[i] &&
1857  !strcmp(op->contr->last_skill_ob[i]->skill, skill_name)) {
1858  skill_obj = op->contr->last_skill_ob[i];
1859  break;
1860  }
1861 
1862  /* Player doesn't have the skill. Check to see what to do, and give
1863  * it to the player if necessary
1864  */
1865  if (!skill_obj) {
1866  if (flag == SK_EXP_NONE) return;
1867  else if (flag == SK_EXP_ADD_SKILL)
1868  skill_obj = give_skill_by_name(op, skill_name);
1869  }
1870  }
1871  }
1872 
1873  /* Basically, you can never gain more experience in one shot
1874  * than half what you need to gain for next level.
1875  */
1876  exp_to_add = exp;
1877  limit=(levels[op->level+1]-levels[op->level])/2;
1878  if (exp_to_add > limit) exp_to_add=limit;
1879 
1880  ADD_EXP(op->stats.exp, (float) exp_to_add * (skill_obj? skill_obj->expmul:1));
1882  ADD_EXP(op->perm_exp, (float) exp_to_add * PERM_EXP_GAIN_RATIO * (skill_obj? skill_obj->expmul:1));
1883  calc_perm_exp(op);
1884  }
1885 
1886  player_lvl_adj(op,NULL);
1887  if (skill_obj) {
1888  exp_to_add = exp;
1889  limit=(levels[skill_obj->level+1]-levels[skill_obj->level])/2;
1890  if (exp_to_add > limit) exp_to_add=limit;
1891  ADD_EXP(skill_obj->stats.exp, exp_to_add);
1893  skill_obj->perm_exp += exp_to_add * PERM_EXP_GAIN_RATIO;
1894  calc_perm_exp(skill_obj);
1895  }
1896  player_lvl_adj(op,skill_obj);
1897  }
1898 }
1899 
1915 sint64 check_exp_loss(const object *op, sint64 exp) {
1916  sint64 del_exp;
1917 
1918  if (exp > op->stats.exp) exp = op->stats.exp;
1920  del_exp = (op->stats.exp - op->perm_exp) * PERM_EXP_MAX_LOSS_RATIO;
1921  if (del_exp < 0) del_exp = 0;
1922  if (exp > del_exp) exp=del_exp;
1923  }
1924  return exp;
1925 }
1926 
1937 sint64 check_exp_adjust(const object *op, sint64 exp) {
1938  if (exp<0) return check_exp_loss(op, exp);
1939  else return MIN(exp, MAX_EXPERIENCE - op->stats.exp);
1940 }
1941 
1942 
1965 static void subtract_player_exp(object *op, sint64 exp, const char *skill, int flag) {
1966  float fraction = (float) exp/(float) op->stats.exp;
1967  object *tmp;
1968  sint64 del_exp;
1969 
1970  for (tmp=op->inv;tmp;tmp=tmp->below)
1971  if (tmp->type==SKILL && tmp->stats.exp) {
1972  if (flag == SK_SUBTRACT_SKILL_EXP && skill && !strcmp(tmp->skill, skill)) {
1973  del_exp = check_exp_loss(tmp, exp);
1974  tmp->stats.exp -= del_exp;
1975  player_lvl_adj(op, tmp);
1976  } else if (flag != SK_SUBTRACT_SKILL_EXP) {
1977  /* only want to process other skills if we are not trying
1978  * to match a specific skill.
1979  */
1980  del_exp = check_exp_loss(tmp, tmp->stats.exp * fraction);
1981  tmp->stats.exp -= del_exp;
1982  player_lvl_adj(op, tmp);
1983  }
1984  }
1985  if (flag != SK_SUBTRACT_SKILL_EXP) {
1986  del_exp = check_exp_loss(op, exp);
1987  op->stats.exp -= del_exp;
1988  player_lvl_adj(op,NULL);
1989  }
1990 }
1991 
1992 
1993 
2015 void change_exp(object *op, sint64 exp, const char *skill_name, int flag) {
2016 
2017 #ifdef EXP_DEBUG
2018  char name[MAX_BUF];
2019  query_name(op, name, MAX_BUF);
2020 #ifndef WIN32
2021  LOG(llevDebug,"change_exp() called for %s, exp = %lld\n",name,exp);
2022 #else
2023  LOG(llevDebug,"change_exp() called for %s, exp = %I64d\n",name,exp);
2024 #endif
2025 #endif
2026 
2027  /* safety */
2028  if (!op) {
2029  LOG(llevError,"change_exp() called for null object!\n");
2030  return;
2031  }
2032 
2033  /* if no change in exp, just return - most of the below code
2034  * won't do anything if the value is 0 anyways.
2035  */
2036  if (exp == 0) return;
2037 
2038  /* Monsters are easy - we just adjust their exp - we
2039  * don't adjust level, since in most cases it is unrelated to
2040  * the exp they have - the monsters exp represents what its
2041  * worth.
2042  */
2043  if (op->type != PLAYER) {
2044  /* Sanity check */
2045  if (!QUERY_FLAG(op, FLAG_ALIVE)) return;
2046 
2047  /* reset exp to max allowed value. We subtract from
2048  * MAX_EXPERIENCE to prevent overflows. If the player somehow has
2049  * more than max exp, just return.
2050  */
2051  if (exp > 0 && (op->stats.exp > (MAX_EXPERIENCE - exp))) {
2052  exp = MAX_EXPERIENCE - op->stats.exp;
2053  if (exp < 0) return;
2054  }
2055 
2056  op->stats.exp += exp;
2057  } else { /* Players only */
2058  if (exp>0)
2059  add_player_exp(op, exp, skill_name, flag);
2060  else
2061  subtract_player_exp(op, FABS(exp), skill_name, flag);
2062  }
2063 }
2064 
2073 void apply_death_exp_penalty(object *op) {
2074  object *tmp;
2075  sint64 loss;
2076  sint64 percentage_loss; /* defined by the setting 'death_penalty_percent' */
2077  sint64 level_loss; /* defined by the setting 'death_penalty_levels */
2078 
2079  for (tmp=op->inv;tmp;tmp=tmp->below)
2080  if (tmp->type==SKILL && tmp->stats.exp) {
2081 
2082  percentage_loss = tmp->stats.exp * settings.death_penalty_ratio/100;
2083  level_loss = tmp->stats.exp - levels[MAX(0,tmp->level - settings.death_penalty_level)];
2084 
2085  /* With the revised exp system, you can get cases where
2086  * losing several levels would still require that you have more
2087  * exp than you currently have - this is true if the levels
2088  * tables is a lot harder.
2089  */
2090  if (level_loss < 0) level_loss = 0;
2091 
2092  loss = check_exp_loss(tmp, MIN(level_loss, percentage_loss));
2093 
2094  tmp->stats.exp -= loss;
2095  player_lvl_adj(op,tmp);
2096  }
2097 
2098  percentage_loss = op->stats.exp * settings.death_penalty_ratio/100;
2099  level_loss = op->stats.exp - levels[MAX(0,op->level - settings.death_penalty_level)];
2100  if (level_loss < 0) level_loss = 0;
2101  loss = check_exp_loss(op, MIN(level_loss, percentage_loss));
2102 
2103  op->stats.exp -= loss;
2104  player_lvl_adj(op,NULL);
2105 }
2106 
2121 int did_make_save(const object *op, int level, int bonus) {
2122  if (level > MAX_SAVE_LEVEL) level = MAX_SAVE_LEVEL;
2123 
2124  if ((random_roll(1, 20, op, PREFER_HIGH) + bonus) < savethrow[level])
2125  return 0;
2126  return 1;
2127 }
2128 
2150 void share_exp(object *op, sint64 exp, const char *skill, int flag) {
2151  int shares=0,count=0;
2152  player *pl;
2153  partylist *party;
2154 
2155  if (op->type!=PLAYER || op->contr->party==NULL) {
2156  change_exp(op,exp, skill, 0);
2157  return;
2158  }
2159 
2160  party = op->contr->party;
2161 
2162  for (pl=first_player;pl!=NULL;pl=pl->next) {
2163  if (party && pl->ob->contr->party==party && on_same_map(pl->ob, op)) {
2164  count++;
2165  shares += (pl->ob->level+4);
2166  }
2167  }
2168  if (count==1 || shares>exp)
2169  change_exp(op,exp, skill, flag);
2170  else {
2171  sint64 share=exp/shares,given=0,nexp;
2172  for (pl=first_player;pl!=NULL;pl=pl->next) {
2173  if (party && pl->ob->contr->party==party && on_same_map(pl->ob, op)) {
2174  nexp=(pl->ob->level+4)*share;
2175  change_exp(pl->ob,nexp, skill, SK_EXP_TOTAL);
2176  given+=nexp;
2177  }
2178  }
2179  exp-=given;
2180  /* give any remainder to the player */
2181  change_exp(op,exp, skill, flag);
2182  }
2183 }
uint8 spell_encumbrance
Definition: global.h:356
#define RING
Definition: define.h:232
signed char sint8
Definition: global.h:80
sint8 Int
Definition: living.h:78
const int fear_bonus[MAX_STAT+1]
Definition: living.c:170
#define NUM_BODY_LOCATIONS
Definition: object.h:41
Definition: player.h:146
#define FLAG_SEE_IN_DARK
Definition: define.h:634
archetype * find_archetype(const char *name)
Definition: arch.c:700
#define WEAPON_SPEED(xyz)
Definition: define.h:790
sint8 ac
Definition: living.h:79
#define MOVE_WALK
Definition: define.h:700
void share_exp(object *op, sint64 exp, const char *skill, int flag)
Definition: living.c:2150
#define DISEASE
Definition: define.h:331
MoveType move_type
Definition: object.h:277
void drain_stat(object *op)
Definition: living.c:748
void change_exp(object *op, sint64 exp, const char *skill_name, int flag)
Definition: living.c:2015
const char * race
Definition: object.h:171
#define MSG_TYPE_ATTRIBUTE_PROTECTION_GAIN
Definition: newclient.h:471
const char *const restore_msg[NUM_STATS]
Definition: living.c:240
const int dam_bonus[MAX_STAT+1]
Definition: living.c:119
#define MSG_TYPE_ATTRIBUTE_BAD_EFFECT_START
Definition: newclient.h:480
#define SET_FLAG(xyz, p)
Definition: define.h:510
sstring add_refcount(sstring str)
Definition: shstr.c:202
#define CLOSE_CON
Definition: define.h:303
char title[BIG_NAME]
Definition: player.h:216
#define FABS(x)
Definition: define.h:61
uint8 death_penalty_ratio
Definition: global.h:347
#define WAND
Definition: define.h:291
#define FLAG_USE_ARMOUR
Definition: define.h:592
#define ADD_EXP(exptotal, exp)
Definition: living.c:46
sint16 digestion
Definition: player.h:166
#define PERM_EXP_MAX_LOSS_RATIO
Definition: config.h:264
const int dex_bonus[MAX_STAT+1]
Definition: living.c:104
sint8 get_attr_value(const living *stats, int attr)
Definition: living.c:377
sint16 maxgrace
Definition: living.h:86
void free_string(sstring str)
Definition: shstr.c:272
sint16 encumbrance
Definition: player.h:230
#define NDI_BLUE
Definition: newclient.h:200
sint16 max_level
Definition: global.h:391
object clone
Definition: object.h:326
sint16 invisible
Definition: object.h:211
#define POTION
Definition: define.h:117
void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *message, const char *oldmessage)
Definition: standalone.c:171
const char * slaying
Definition: object.h:172
sint64 level_exp(int level, double expmul)
Definition: living.c:1788
static const int sp_bonus[MAX_STAT+1]
Definition: living.c:62
#define FLAG_STEALTH
Definition: define.h:609
object * ranges[range_size]
Definition: player.h:157
uint8 subtype
Definition: object.h:190
#define EXPERIENCE
Definition: define.h:158
sint64 exp
Definition: living.h:88
void change_luck(object *op, int value)
Definition: living.c:791
double expmul
Definition: object.h:246
#define BOOTS
Definition: define.h:281
Definition: living.h:77
#define CLOAK
Definition: define.h:268
#define GIRDLE
Definition: define.h:295
uint8 search_items
Definition: global.h:355
sint8 levsp[11]
Definition: player.h:219
uint32 path_attuned
Definition: object.h:194
sint16 sp
Definition: living.h:83
void change_attr_value(living *stats, int attr, sint8 value)
Definition: living.c:336
#define MAX_EXPERIENCE
Definition: living.c:178
uint32 path_repelled
Definition: object.h:195
void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format,...)
Definition: standalone.c:175
sint64 last_skill_exp[NUM_SKILLS]
Definition: player.h:192
#define MSG_TYPE_ATTRIBUTE_GOOD_EFFECT_START
Definition: newclient.h:486
#define ARMOUR
Definition: define.h:128
static const char *const drain_msg[NUM_STATS]
Definition: living.c:229
Definition: object.h:321
sint16 gen_hp
Definition: player.h:167
#define PLAYER
Definition: define.h:113
#define POTION_EFFECT
Definition: define.h:297
static const int con_bonus[MAX_STAT+1]
Definition: living.c:51
#define MSG_TYPE_ATTRIBUTE_BAD_EFFECT_END
Definition: newclient.h:481
sint16 maxsp
Definition: living.h:84
sint8 Con
Definition: living.h:78
#define MSG_TYPE_ATTRIBUTE_PROTECTION_LOSS
Definition: newclient.h:472
sint16 hp
Definition: living.h:81
#define MSG_TYPE_ATTRIBUTE_ATTACKTYPE_LOSS
Definition: newclient.h:467
partylist * party
Definition: player.h:237
#define IS_MANA_SKILL(num)
Definition: skills.h:131
#define CON
Definition: living.h:43
sint16 gen_grace
Definition: player.h:170
object * give_skill_by_name(object *op, const char *skill_name)
Definition: living.c:1689
#define MIN_STAT
Definition: define.h:79
#define MSG_TYPE_ATTRIBUTE_LEVEL_LOSS
Definition: newclient.h:485
#define AMULET
Definition: define.h:153
#define FLAG_UNDEAD
Definition: define.h:566
static void subtract_player_exp(object *op, sint64 exp, const char *skill, int flag)
Definition: living.c:1965
struct obj * chosen_skill
Definition: object.h:237
int change_abil(object *op, object *tmp)
Definition: living.c:443
sint64 check_exp_loss(const object *op, sint64 exp)
Definition: living.c:1915
#define NDI_RED
Definition: newclient.h:198
sint16 maxhp
Definition: living.h:82
void player_lvl_adj(object *who, object *op)
Definition: living.c:1731
sint64 * levels
Definition: exp.c:39
uint32 path_denied
Definition: object.h:196
#define FLAG_ALIVE
Definition: define.h:526
#define SYMPTOM
Definition: define.h:332
#define FLAG_REFL_SPELL
Definition: define.h:571
static void add_player_exp(object *op, sint64 exp, const char *skill_name, int flag)
Definition: living.c:1837
const char *const gain_msg[NUM_STATS]
Definition: living.c:251
static const int savethrow[MAX_SAVE_LEVEL+1]
Definition: living.c:209
#define SK_EXP_TOTAL
Definition: skills.h:104
sint16 gen_sp_armour
Definition: player.h:169
#define MOVE_SWIM
Definition: define.h:704
const int thaco_bonus[MAX_STAT+1]
Definition: living.c:124
#define FLAG_CAN_USE_SKILL
Definition: define.h:618
#define MOVE_FLY_LOW
Definition: define.h:701
#define MSG_TYPE_ATTRIBUTE_ATTACKTYPE_GAIN
Definition: newclient.h:466
const char *const statname[NUM_STATS]
Definition: living.c:273
#define MSG_TYPE_ATTRIBUTE_LEVEL_GAIN
Definition: newclient.h:484
sint8 Wis
Definition: living.h:78
sint16 item_power
Definition: player.h:171
int is_dragon_pl(const object *op)
Definition: player.c:125
char search_str[MAX_BUF]
Definition: player.h:243
void set_attr_value(living *stats, int attr, sint8 value)
Definition: living.c:296
#define ARCH_DEPLETION
Definition: object.h:405
void drain_specific_stat(object *op, int deplete_stats)
Definition: living.c:760
const float speed_bonus[MAX_STAT+1]
Definition: living.c:109
#define HORN
Definition: define.h:147
float weapon_sp
Definition: player.h:194
sint16 dam
Definition: living.h:87
int die_roll(int num, int size, const object *op, int goodbad)
Definition: utils.c:134
sint32 carrying
Definition: object.h:218
archetype * get_archetype_by_skill_name(const char *skill, int type)
Definition: arch.c:120
#define MSG_TYPE_ATTRIBUTE
Definition: newclient.h:327
const char * name
Definition: object.h:167
living orig_stats
Definition: player.h:203
sint64 perm_exp
Definition: object.h:220
#define ARMOUR_SPEED(xyz)
Definition: define.h:788
int allowed_class(const object *op)
Definition: living.c:1543
struct obj * below
Definition: object.h:145
#define POW
Definition: living.h:47
#define TRUE
Definition: exp.c:41
struct obj * current_weapon
Definition: object.h:221
#define PERM_EXP_GAIN_RATIO
Definition: config.h:263
sint8 Cha
Definition: living.h:78
EXTERN const char *const change_resist_msg[NROFATTACKS]
Definition: attack.h:163
const int cleric_chance[MAX_STAT+1]
Definition: living.c:160
#define DEX
Definition: living.h:42
const float cha_bonus[MAX_STAT+1]
Definition: living.c:94
void dragon_level_gain(object *who)
Definition: living.c:1623
struct pl * contr
Definition: object.h:134
#define WEAPON
Definition: define.h:127
void add_statbonus(object *op)
Definition: living.c:863
#define CHA
Definition: living.h:45
#define FLAG_XRAYS
Definition: define.h:597
#define ATNR_PHYSICAL
Definition: attack.h:77
#define MAX(x, y)
Definition: define.h:70
sint8 luck
Definition: living.h:80
#define AT_PHYSICAL
Definition: attack.h:104
float speed
Definition: object.h:181
int on_same_map(const object *op1, const object *op2)
Definition: map.c:2609
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
#define CLEAR_FLAG(xyz, p)
Definition: define.h:512
#define FLAG_WIZ
Definition: define.h:527
object * insert_ob_in_ob(object *op, object *where)
Definition: object.c:2510
#define MAX_BUF
Definition: define.h:81
#define GLOVES
Definition: define.h:282
#define SK_PRAYING
Definition: skills.h:77
char own_title[MAX_NAME]
Definition: player.h:214
#define BRACERS
Definition: define.h:286
const char * skill
Definition: object.h:174
sint32 last_eat
Definition: object.h:207
#define NUM_SKILLS
Definition: skills.h:95
sint8 wc
Definition: living.h:79
#define FLAG_READY_WEAPON
Definition: define.h:631
#define DIFF_MSG(flag, subtype1, subtype2, msg1, msg2)
Definition: living.c:418
#define MIN(x, y)
Definition: define.h:67
sint8 Str
Definition: living.h:78
void calc_perm_exp(object *op)
Definition: living.c:1804
const int turn_bonus[MAX_STAT+1]
Definition: living.c:165
sint16 resist[NROFATTACKS]
Definition: object.h:192
object * ob
Definition: player.h:207
#define MSG_TYPE_ATTRIBUTE_STAT_LOSS
Definition: newclient.h:483
const char *const lose_msg[NUM_STATS]
Definition: living.c:262
sint8 body_info[NUM_BODY_LOCATIONS]
Definition: object.h:223
#define SHIELD
Definition: define.h:145
#define MSG_TYPE_ATTRIBUTE_RACE
Definition: newclient.h:479
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
sint8 body_used[NUM_BODY_LOCATIONS]
Definition: object.h:224
#define WIS
Definition: living.h:44
#define FORCE
Definition: define.h:296
#define PREFER_HIGH
Definition: define.h:908
uint32 attacktype
Definition: object.h:193
#define NUM_STATS
Definition: living.h:48
#define FLAG_BLIND
Definition: define.h:633
#define CONTAINER
Definition: define.h:306
sint16 grace
Definition: living.h:85
living stats
Definition: object.h:219
uint8 death_penalty_level
Definition: global.h:348
sint8 Dex
Definition: living.h:78
struct archt * arch
Definition: object.h:263
object * present_arch_in_ob(const archetype *at, const object *op)
Definition: object.c:2859
uint32 do_los
Definition: player.h:180
#define SKILL
Definition: define.h:157
sint8 levgrace[11]
Definition: player.h:220
struct Settings settings
Definition: init.c:48
sint64 check_exp_adjust(const object *op, sint64 exp)
Definition: living.c:1937
#define SK_EXP_ADD_SKILL
Definition: skills.h:103
#define SK_EXP_NONE
Definition: skills.h:105
#define FLAG_APPLIED
Definition: define.h:531
#define NROFATTACKS
Definition: attack.h:45
#define FLAG_LIFESAVE
Definition: define.h:602
const uint32 weight_limit[MAX_STAT+1]
Definition: living.c:143
void check_stat_bounds(living *stats)
Definition: living.c:404
#define FLAG_MAKE_INVIS
Definition: define.h:625
void apply_death_exp_penalty(object *op)
Definition: living.c:2073
#define MSG_TYPE_ATTRIBUTE_GOOD_EFFECT_END
Definition: newclient.h:487
void update_ob_speed(object *op)
Definition: object.c:1008
#define BOW
Definition: define.h:126
#define MAX_SAVE_LEVEL
Definition: living.c:199
sstring add_string(const char *str)
Definition: shstr.c:116
EXTERN player * first_player
Definition: global.h:190
struct pl * next
Definition: player.h:147
sint16 gen_sp
Definition: player.h:168
sint8 glow_radius
Definition: object.h:215
#define INT
Definition: living.h:46
sint8 Pow
Definition: living.h:78
struct obj * inv
Definition: object.h:148
#define NDI_UNIQUE
Definition: newclient.h:219
#define HELMET
Definition: define.h:146
uint8 permanent_exp_ratio
Definition: global.h:346
#define MOVE_FLY_HIGH
Definition: define.h:702
void dragon_ability_gain(object *who, int atnr, int level)
Definition: standalone.c:203
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
const int learn_spell[MAX_STAT+1]
Definition: living.c:154
int did_make_save(const object *op, int level, int bonus)
Definition: living.c:2121
unsigned int uint32
Definition: global.h:58
#define ROD
Definition: define.h:115
sint8 levhp[11]
Definition: player.h:218
object * last_skill_ob[NUM_SKILLS]
Definition: player.h:191
#define SKILL_TOOL
Definition: define.h:236
void set_dragon_name(object *pl, const object *abil, const object *skin)
Definition: living.c:1566
static const int grace_bonus[MAX_STAT+1]
Definition: living.c:70
int check_move_on(object *op, object *originator)
Definition: object.c:2651
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:628
#define SK_SUBTRACT_SKILL_EXP
Definition: skills.h:106
void remove_statbonus(object *op)
Definition: living.c:840
void esrv_update_spells(player *pl)
Definition: standalone.c:216
#define IS_COMBAT_SKILL(num)
Definition: skills.h:116
uint32 braced
Definition: player.h:178
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.c:51
#define AT_CONFUSION
Definition: attack.h:109
const char *const short_stat_name[NUM_STATS]
Definition: living.c:278
#define FLAG_REFL_MISSILE
Definition: define.h:569
sint16 level
Definition: object.h:202
void fix_object(object *op)
Definition: living.c:900
#define IS_GRACE_SKILL(num)
Definition: skills.h:140
object * arch_to_object(archetype *at)
Definition: arch.c:576
#define STR
Definition: living.h:41
const int max_carry[MAX_STAT+1]
Definition: living.c:129
const char * name
Definition: object.h:322
#define MSG_TYPE_ATTRIBUTE_STAT_GAIN
Definition: newclient.h:482
uint8 type
Definition: object.h:189
#define MSG_TYPE_ATTRIBUTE_MOVE
Definition: newclient.h:477
#define MAX_STAT
Definition: define.h:78
const char *const attacks[NROFATTACKS]
Definition: living.c:220
int atnr_is_dragon_enabled(int attacknr)
Definition: player.c:106
sint32 food
Definition: living.h:89