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

Comparing deliantra/server/server/skill_util.C (file contents):
Revision 1.9 by root, Sun Sep 10 15:59:57 2006 UTC vs.
Revision 1.25 by root, Mon Jan 8 18:18:35 2007 UTC

1
2/*
3 * static char *rcsid_skill_util_c =
4 * "$Id: skill_util.C,v 1.9 2006/09/10 15:59:57 root Exp $";
5 */
6
7/* 1/*
8 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
9 3
4 Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
10 Copryight (C) 2002 Mark Wedel & Crossfire Development Team 5 Copryight (C) 2002 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 6 Copyright (C) 1992 Frank Tore Johansen
12 7
13 This program is free software; you can redistribute it and/or modify 8 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by 9 it under the terms of the GNU General Public License as published by
22 17
23 You should have received a copy of the GNU General Public License 18 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software 19 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 21
27 The author can be reached via e-mail to crossfire-devel@real-time.com 22 The author can be reached via e-mail to <crossfire@schmorp.de>
28*/ 23*/
29 24
30/* Created July 95 to separate skill utilities from actual skills -b.t. */ 25/* Created July 95 to separate skill utilities from actual skills -b.t. */
31 26
32/* Reconfigured skills code to allow linking of skills to experience 27/* Reconfigured skills code to allow linking of skills to experience
43 38
44/* define the following for skills utility debuging */ 39/* define the following for skills utility debuging */
45 40
46/* #define SKILL_UTIL_DEBUG */ 41/* #define SKILL_UTIL_DEBUG */
47 42
48#define WANT_UNARMED_SKILLS
49
50#include <global.h> 43#include <global.h>
51#include <object.h> 44#include <object.h>
52#ifndef __CEXTRACT__
53# include <sproto.h> 45#include <sproto.h>
54#endif
55#include <living.h> /* for defs of STR,CON,DEX,etc. -b.t. */ 46#include <living.h> /* for defs of STR,CON,DEX,etc. -b.t. */
56#include <spells.h> 47#include <spells.h>
57 48
49/* Table of unarmed attack skills. Terminated by -1. This
50 * is also the list that we should try to use skills when
51 * automatically applying one for the player.
52 */
53static uint8 unarmed_skills[] = {
54 SK_KARATE,
55 SK_CLAWING,
56 SK_FLAME_TOUCH,
57 SK_SPARK_TOUCH,
58 SK_SHIVER,
59 SK_ACID_SPLASH,
60 SK_POISON_NAIL,
61 SK_PUNCHING,
62 (uint8)-1
63};
64
58static int attack_hth (object *pl, int dir, const char *string, object *skill); 65static int attack_hth (object *pl, int dir, const char *string, object *skill);
59static int attack_melee_weapon (object *op, int dir, const char *string, object *skill); 66static int attack_melee_weapon (object *op, int dir, const char *string, object *skill);
60
61shstr skill_names[NUM_SKILLS];
62 67
63/* init_skills basically just sets up the skill_names table 68/* init_skills basically just sets up the skill_names table
64 * above. The index into the array is set up by the 69 * above. The index into the array is set up by the
65 * subtypes. 70 * subtypes.
66 */ 71 */
69{ 74{
70 int i; 75 int i;
71 archetype *at; 76 archetype *at;
72 77
73 for (at = first_archetype; at != NULL; at = at->next) 78 for (at = first_archetype; at != NULL; at = at->next)
74 {
75 if (at->clone.type == SKILL) 79 if (at->clone.type == SKILL)
76 { 80 {
77 if (skill_names[at->clone.subtype] != NULL) 81 if (skill_names[at->clone.subtype] != NULL)
78 {
79 LOG (llevError, "init_skills: multiple skill using same subtype %d, %s, %s\n", 82 LOG (llevError, "init_skills: multiple skill using same subtype %d, %s, %s\n",
80 at->clone.subtype, &skill_names[at->clone.subtype], &at->clone.skill); 83 at->clone.subtype, &skill_names[at->clone.subtype], &at->clone.skill);
81 }
82 else 84 else
83 {
84 skill_names[at->clone.subtype] = at->clone.skill; 85 skill_names[at->clone.subtype] = at->clone.skill;
85 }
86 } 86 }
87 }
88 87
89 /* This isn't really an error if there is no skill subtype set, but 88 /* This isn't really an error if there is no skill subtype set, but
90 * checking for this may catch some user errors. 89 * checking for this may catch some user errors.
91 */ 90 */
92 for (i = 1; i < NUM_SKILLS; i++) 91 for (i = 1; i < NUM_SKILLS; i++)
93 { 92 {
94 if (!skill_names[i]) 93 if (!skill_names[i])
95 LOG (llevError, "init_skills: skill subtype %d doesn't have a name?\n", i); 94 LOG (llevError, "init_skills: skill subtype %d doesn't have a name?\n", i);
96 } 95 }
97} 96}
98
99 97
100/* This function goes through the player inventory and sets 98/* This function goes through the player inventory and sets
101 * up the last_skills[] array in the player object. 99 * up the last_skills[] array in the player object.
102 * the last_skills[] is used to more quickly lookup skills - 100 * the last_skills[] is used to more quickly lookup skills -
103 * mostly used for sending exp. 101 * mostly used for sending exp.
104 */ 102 */
105void 103void
106link_player_skills (object *op) 104link_player_skills (object *op)
107{ 105{
108 object *tmp;
109
110 for (tmp = op->inv; tmp; tmp = tmp->below) 106 for (object *tmp = op->inv; tmp; tmp = tmp->below)
111 {
112 if (tmp->type == SKILL) 107 if (tmp->type == SKILL)
113 { 108 {
114 /* This is really a warning, hence no else below */ 109 /* This is really a warning, hence no else below */
115 if (op->contr->last_skill_ob[tmp->subtype] && op->contr->last_skill_ob[tmp->subtype] != tmp) 110 if (op->contr->last_skill_ob[tmp->subtype] && op->contr->last_skill_ob[tmp->subtype] != tmp)
116 {
117 LOG (llevError, "Multiple skills with the same subtype? %s, %s\n", 111 LOG (llevError, "Multiple skills with the same subtype? %s, %s\n",
118 &op->contr->last_skill_ob[tmp->subtype]->skill, &tmp->skill); 112 &op->contr->last_skill_ob[tmp->subtype]->skill, &tmp->skill);
119 } 113
120 if (tmp->subtype >= NUM_SKILLS) 114 if (tmp->subtype >= NUM_SKILLS)
121 {
122 LOG (llevError, "Invalid subtype number %d (range 0-%d)\n", tmp->subtype, NUM_SKILLS); 115 LOG (llevError, "Invalid subtype number %d (range 0-%d)\n", tmp->subtype, NUM_SKILLS);
123 }
124 else 116 else
125 { 117 {
126 op->contr->last_skill_ob[tmp->subtype] = tmp; 118 op->contr->last_skill_ob[tmp->subtype] = tmp;
127 op->contr->last_skill_exp[tmp->subtype] = -1; 119 op->contr->ns->last_skill_exp[tmp->subtype] = -1; //TODO: this should go
128 } 120 }
129 } 121 }
130 }
131} 122}
132 123
133/* This returns the skill pointer of the given name (the 124/* This returns the skill pointer of the given name (the
134 * one that accumlates exp, has the level, etc). 125 * one that accumlates exp, has the level, etc).
135 * 126 *
239 if (!QUERY_FLAG (skill_tool, FLAG_APPLIED)) 230 if (!QUERY_FLAG (skill_tool, FLAG_APPLIED))
240 { 231 {
241 if (apply_special (who, skill_tool, 0)) 232 if (apply_special (who, skill_tool, 0))
242 return NULL; 233 return NULL;
243 } 234 }
235
244 if (!skill) 236 if (!skill)
245 { 237 {
246 skill = give_skill_by_name (who, skill_tool->skill); 238 skill = give_skill_by_name (who, skill_tool->skill);
247 link_player_skills (who); 239 link_player_skills (who);
248 } 240 }
241
249 return skill; 242 return skill;
250 } 243 }
244
251 return NULL; 245 return NULL;
252} 246}
253 247
254/* This changes the objects skill to new_skill. 248/* This changes the objects skill to new_skill.
255 * note that this function doesn't always need to get used - 249 * note that this function doesn't always need to get used -
276 if (who->chosen_skill && who->chosen_skill == new_skill) 270 if (who->chosen_skill && who->chosen_skill == new_skill)
277 { 271 {
278 /* optimization for changing skill to current skill */ 272 /* optimization for changing skill to current skill */
279 if (who->type == PLAYER && !(flag & 0x1)) 273 if (who->type == PLAYER && !(flag & 0x1))
280 who->contr->shoottype = range_skill; 274 who->contr->shoottype = range_skill;
275
281 return 1; 276 return 1;
282 } 277 }
278
279 // move skill to front, so it will be preferred next time
280 new_skill->remove ();
281 who->insert (new_skill);
283 282
284 if (!new_skill || who->chosen_skill) 283 if (!new_skill || who->chosen_skill)
285 if (who->chosen_skill) 284 if (who->chosen_skill)
286 apply_special (who, who->chosen_skill, AP_UNAPPLY); 285 apply_special (who, who->chosen_skill, AP_UNAPPLY);
287 286
288 /* Only goal in this case was to unapply a skill */ 287 /* Only goal in this case was to unapply a skill */
289 if (!new_skill) 288 if (!new_skill)
290 return 0; 289 return 0;
291 290
292 if (apply_special (who, new_skill, AP_APPLY)) 291 if (apply_special (who, new_skill, AP_APPLY))
293 {
294 return 0; 292 return 0;
295 } 293
296 if (flag & 0x1) 294 if (flag & 0x1)
297 who->contr->shoottype = (rangetype) old_range; 295 who->contr->shoottype = (rangetype)old_range;
298 296
299 return 1; 297 return 1;
300} 298}
301 299
302/* This function just clears the chosen_skill and range_skill values 300/* This function just clears the chosen_skill and range_skill values
373 else 371 else
374 { 372 {
375 SET_FLAG (skill, FLAG_APPLIED); 373 SET_FLAG (skill, FLAG_APPLIED);
376 new_draw_info (NDI_UNIQUE, 0, op, "You rise into the air!."); 374 new_draw_info (NDI_UNIQUE, 0, op, "You rise into the air!.");
377 } 375 }
378 fix_player (op); 376 op->update_stats ();
379 success = 1; 377 success = 1;
380 break; 378 break;
381 379
382 case SK_STEALING: 380 case SK_STEALING:
383 exp = success = steal (op, dir, skill); 381 exp = success = steal (op, dir, skill);
462 case SK_LITERACY: 460 case SK_LITERACY:
463 case SK_WOODSMAN: 461 case SK_WOODSMAN:
464 /* first, we try to find a cauldron, and do the alchemy thing. 462 /* first, we try to find a cauldron, and do the alchemy thing.
465 * failing that, we go and identify stuff. 463 * failing that, we go and identify stuff.
466 */ 464 */
467 for (tmp = get_map_ob (op->map, op->x, op->y); tmp != NULL; tmp = next) 465 for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp != NULL; tmp = next)
468 { 466 {
469 next = tmp->above; 467 next = tmp->above;
468
470 if (QUERY_FLAG (tmp, FLAG_IS_CAULDRON)) 469 if (QUERY_FLAG (tmp, FLAG_IS_CAULDRON))
471 { 470 {
472 attempt_do_alchemy (op, tmp); 471 attempt_do_alchemy (op, tmp);
472
473 if (QUERY_FLAG (tmp, FLAG_APPLIED)) 473 if (QUERY_FLAG (tmp, FLAG_APPLIED))
474 esrv_send_inventory (op, tmp); 474 esrv_send_inventory (op, tmp);
475
475 did_alc = 1; 476 did_alc = 1;
476 } 477 }
477 } 478 }
479
478 if (did_alc == 0) 480 if (did_alc == 0)
479 exp = success = skill_ident (op, skill); 481 exp = success = skill_ident (op, skill);
482
480 break; 483 break;
481 484
482 case SK_DET_MAGIC: 485 case SK_DET_MAGIC:
483 case SK_DET_CURSE: 486 case SK_DET_CURSE:
484 exp = success = skill_ident (op, skill); 487 exp = success = skill_ident (op, skill);
689 692
690 /* player already knows it */ 693 /* player already knows it */
691 if (tmp && QUERY_FLAG (tmp, FLAG_CAN_USE_SKILL)) 694 if (tmp && QUERY_FLAG (tmp, FLAG_CAN_USE_SKILL))
692 return 0; 695 return 0;
693 696
694
695
696 /* now a random change to learn, based on player Int. 697 /* now a random change to learn, based on player Int.
697 * give bonus based on level - otherwise stupid characters 698 * give bonus based on level - otherwise stupid characters
698 * might never be able to learn anything. 699 * might never be able to learn anything.
699 */ 700 */
700 if (random_roll (0, 99, pl, PREFER_LOW) > (learn_spell[pl->stats.Int] + (pl->level / 5))) 701 if (random_roll (0, 99, pl, PREFER_LOW) > (learn_spell[pl->stats.Int] + (pl->level / 5)))
769 sprintf (buf, "%s%s", &tmp->name, periods); 770 sprintf (buf, "%s%s", &tmp->name, periods);
770 buf[40] = 0; 771 buf[40] = 0;
771 772
772 if (settings.permanent_exp_ratio) 773 if (settings.permanent_exp_ratio)
773 { 774 {
774 sprintf (skills[num_skills_found++], "%slvl:%3d (xp:%lld/%lld/%d%%)", 775 sprintf (skills[num_skills_found++], "%slvl:%3d (xp:%" PRId64 "/%" PRId64 "/%d%%)",
775 buf, tmp->level, 776 buf, tmp->level, tmp->stats.exp,
776 (long long) tmp->stats.exp,
777 (long long) level_exp (tmp->level + 1, op->expmul), clipped_percent (tmp->perm_exp, tmp->stats.exp)); 777 level_exp (tmp->level + 1, op->expmul), clipped_percent (tmp->perm_exp, tmp->stats.exp));
778 } 778 }
779 else 779 else
780 { 780 {
781 sprintf (skills[num_skills_found++], "%slvl:%3d (xp:%lld/%lld)", 781 sprintf (skills[num_skills_found++], "%slvl:%3d (xp:%" PRId64 "/%" PRId64 ")",
782 buf, tmp->level, (long long) tmp->stats.exp, (long long) level_exp (tmp->level + 1, op->expmul)); 782 buf, tmp->level, tmp->stats.exp, level_exp (tmp->level + 1, op->expmul));
783 } 783 }
784 /* I don't know why some characters get a bunch of skills, but 784 /* I don't know why some characters get a bunch of skills, but
785 * it sometimes happens (maybe a leftover from bugier earlier code 785 * it sometimes happens (maybe a leftover from bugier earlier code
786 * and those character are still about). In any case, lets handle 786 * and those character are still about). In any case, lets handle
787 * it so it doesn't crash the server - otherwise, one character may 787 * it so it doesn't crash the server - otherwise, one character may
874 return 1; 874 return 1;
875 875
876 return 0; 876 return 0;
877} 877}
878 878
879static bool
880hth_skill_p (object *skill)
881{
882 for (unsigned int i = 0; i < sizeof (unarmed_skills); ++i)
883 if (skill->subtype == unarmed_skills[i])
884 return 1;
879 885
886 return 0;
887}
880 888
881/* This finds the best unarmed skill the player has, and returns 889/* This finds the first unarmed skill the player has, and returns it.
882 * it. Best can vary a little - we consider clawing to always
883 * be the best for dragons.
884 * This could be more intelligent, eg, look at the skill level
885 * of the skill and go from there (eg, a level 40 puncher is
886 * is probably better than level 1 karate). OTOH, if you
887 * don't bother to set up your skill properly, that is the players
888 * problem (although, it might be nice to have a preferred skill
889 * field the player can set.
890 * Unlike the old code, we don't give out any skills - it is
891 * possible you just don't have any ability to get into unarmed
892 * combat. If everyone race/class should have one, this should
893 * be handled in the starting treasurelists, not in the code.
894 */ 890 */
895static object * 891static object *
896find_best_player_hth_skill (object *op) 892find_player_hth_skill (object *op)
897{ 893{
898 object *tmp, *best_skill = NULL;
899 int dragon = is_dragon_pl (op), last_skill = sizeof (unarmed_skills), i;
900
901 for (tmp = op->inv; tmp; tmp = tmp->below) 894 for (object *tmp = op->inv; tmp; tmp = tmp->below)
902 { 895 if (tmp->type == SKILL && QUERY_FLAG (tmp, FLAG_CAN_USE_SKILL) && hth_skill_p (tmp))
903 if (tmp->type == SKILL)
904 {
905 if (dragon && tmp->subtype == SK_CLAWING)
906 return tmp; 896 return tmp;
907 897
908 /* The order in the array is preferred order. So basically, 898 return 0;
909 * we just cut down the number to search - eg, if we find a skill
910 * early on in flame touch, then we only need to look into the unarmed_array
911 * to the entry before flame touch - don't care about the entries afterward,
912 * because they are infrerior skills.
913 * if we end up finding the best skill (i==0) might as well return
914 * right away - can't get any better than that.
915 */
916 for (i = 0; i < last_skill; i++)
917 {
918 if (tmp->subtype == unarmed_skills[i] && QUERY_FLAG (tmp, FLAG_CAN_USE_SKILL))
919 {
920 best_skill = tmp;
921 last_skill = i;
922 if (i == 0)
923 return best_skill;
924 }
925 }
926 }
927 }
928 return best_skill;
929} 899}
930 900
931/* do_skill_attack() - We have got an appropriate opponent from either 901/* do_skill_attack() - We have got an appropriate opponent from either
932 * move_player_attack() or skill_attack(). In this part we get on with 902 * move_player_attack() or skill_attack(). In this part we get on with
933 * attacking, take care of messages from the attack and changes in invisible. 903 * attacking, take care of messages from the attack and changes in invisible.
954 */ 924 */
955 if (op->type == PLAYER) 925 if (op->type == PLAYER)
956 { 926 {
957 if (!QUERY_FLAG (op, FLAG_READY_WEAPON)) 927 if (!QUERY_FLAG (op, FLAG_READY_WEAPON))
958 { 928 {
959 size_t i;
960
961 if (!skill) 929 if (!skill)
962 { 930 {
963 /* See if the players chosen skill is a combat skill, and use 931 /* See if the players chosen skill is a combat skill, and use
964 * it if appropriate. 932 * it if appropriate.
965 */ 933 */
934 if (op->chosen_skill && hth_skill_p (op->chosen_skill))
966 if (op->chosen_skill) 935 skill = op->chosen_skill;
936 else
967 { 937 {
968 for (i = 0; i < sizeof (unarmed_skills); i++)
969 if (op->chosen_skill->subtype == unarmed_skills[i])
970 {
971 skill = op->chosen_skill;
972 break;
973 }
974 }
975 /* If we didn't find a skill above, look harder for a good skill */
976 if (!skill)
977 {
978 skill = find_best_player_hth_skill (op); 938 skill = find_player_hth_skill (op);
979 939
980 if (!skill) 940 if (!skill)
981 { 941 {
982 new_draw_info (NDI_BLACK, 0, op, "You have no unarmed combat skills!"); 942 new_draw_info (NDI_BLACK, 0, op, "You have no unarmed combat skills!");
983 return 0; 943 return 0;
984 } 944 }
985 } 945 }
986 } 946 }
987 if (skill != op->chosen_skill) 947
988 {
989 /* now try to ready the new skill */ 948 /* now try to ready the new skill */
990 if (!change_skill (op, skill, 0)) 949 if (!change_skill (op, skill, 0))
991 { /* oh oh, trouble! */ 950 { /* oh oh, trouble! */
992 new_draw_info_format (NDI_UNIQUE, 0, tmp, "Couldn't change to skill %s", &skill->name); 951 new_draw_info_format (NDI_UNIQUE, 0, tmp, "Couldn't change to skill %s", &skill->name);
993 return 0; 952 return 0;
994 }
995 } 953 }
996 } 954 }
997 else 955 else
998 { 956 {
999 /* Seen some crashes below where current_weapon is not set, 957 /* Seen some crashes below where current_weapon is not set,
1019 { 977 {
1020 op->current_weapon = tmp; 978 op->current_weapon = tmp;
1021 } 979 }
1022 } 980 }
1023 981
1024 /* Has ready weapon - make sure chosen_skill is set up properly */
1025 if (!op->chosen_skill || op->current_weapon->skill != op->chosen_skill->skill)
1026 {
1027 change_skill (op, find_skill_by_name (op, op->current_weapon->skill), 1); 982 change_skill (op, find_skill_by_name (op, op->current_weapon->skill), 1);
1028 }
1029 } 983 }
1030 } 984 }
1031 985
1032 /* lose invisiblity/hiding status for running attacks */ 986 /* lose invisiblity/hiding status for running attacks */
1033 987
1068 1022
1069int 1023int
1070skill_attack (object *tmp, object *pl, int dir, const char *string, object *skill) 1024skill_attack (object *tmp, object *pl, int dir, const char *string, object *skill)
1071{ 1025{
1072 sint16 tx, ty; 1026 sint16 tx, ty;
1073 mapstruct *m; 1027 maptile *m;
1074 int mflags; 1028 int mflags;
1075 1029
1076 if (!dir) 1030 if (!dir)
1077 dir = pl->facing; 1031 dir = pl->facing;
1032
1078 tx = freearr_x[dir]; 1033 tx = freearr_x[dir];
1079 ty = freearr_y[dir]; 1034 ty = freearr_y[dir];
1080 1035
1081 /* If we don't yet have an opponent, find if one exists, and attack. 1036 /* If we don't yet have an opponent, find if one exists, and attack.
1082 * Legal opponents are the same as outlined in move_player_attack() 1037 * Legal opponents are the same as outlined in move_player_attack()
1094 1049
1095 /* space must be blocked for there to be anything interesting to do */ 1050 /* space must be blocked for there to be anything interesting to do */
1096 if (!OB_TYPE_MOVE_BLOCK (pl, GET_MAP_MOVE_BLOCK (m, tx, ty))) 1051 if (!OB_TYPE_MOVE_BLOCK (pl, GET_MAP_MOVE_BLOCK (m, tx, ty)))
1097 return 0; 1052 return 0;
1098 1053
1099 for (tmp = get_map_ob (m, tx, ty); tmp; tmp = tmp->above) 1054 for (tmp = GET_MAP_OB (m, tx, ty); tmp; tmp = tmp->above)
1100 if ((QUERY_FLAG (tmp, FLAG_ALIVE) && tmp->stats.hp >= 0) || QUERY_FLAG (tmp, FLAG_CAN_ROLL) || tmp->type == LOCKED_DOOR) 1055 if ((QUERY_FLAG (tmp, FLAG_ALIVE) && tmp->stats.hp >= 0) || QUERY_FLAG (tmp, FLAG_CAN_ROLL) || tmp->type == LOCKED_DOOR)
1101 { 1056 {
1102 /* Don't attack party members */ 1057 /* Don't attack party members */
1103 if ((pl->type == PLAYER && tmp->type == PLAYER) && (pl->contr->party != NULL && pl->contr->party == tmp->contr->party)) 1058 if ((pl->type == PLAYER && tmp->type == PLAYER) && (pl->contr->party != NULL && pl->contr->party == tmp->contr->party))
1104 return 0; 1059 return 0;
1133 { 1088 {
1134 if (weapon->type == WEAPON && QUERY_FLAG (weapon, FLAG_APPLIED)) 1089 if (weapon->type == WEAPON && QUERY_FLAG (weapon, FLAG_APPLIED))
1135 { 1090 {
1136 CLEAR_FLAG (weapon, FLAG_APPLIED); 1091 CLEAR_FLAG (weapon, FLAG_APPLIED);
1137 CLEAR_FLAG (pl, FLAG_READY_WEAPON); 1092 CLEAR_FLAG (pl, FLAG_READY_WEAPON);
1138 fix_player (pl); 1093 pl->update_stats ();
1139 if (pl->type == PLAYER) 1094 if (pl->type == PLAYER)
1140 { 1095 {
1141 new_draw_info (NDI_UNIQUE, 0, pl, "You unwield your weapon in order to attack."); 1096 new_draw_info (NDI_UNIQUE, 0, pl, "You unwield your weapon in order to attack.");
1142 esrv_update_item (UPD_FLAGS, pl, weapon); 1097 esrv_update_item (UPD_FLAGS, pl, weapon);
1143 } 1098 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines