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

Comparing deliantra/server/server/login.C (file contents):
Revision 1.11 by root, Sun Sep 3 22:45:57 2006 UTC vs.
Revision 1.19 by root, Fri Sep 15 00:55:08 2006 UTC

1/*
2 * static char *rcsid_login_c =
3 * "$Id: login.C,v 1.11 2006/09/03 22:45:57 root Exp $";
4 */
5
6/* 1/*
7 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
8 3
9 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
21 16
22 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 20
26 The authors can be reached via e-mail at crossfire-devel@real-time.com 21 The authors can be reached via e-mail at <crossfire@schmorp.de>
27*/ 22*/
28 23
29#include <global.h> 24#include <global.h>
30#ifndef __CEXTRACT__ 25#ifndef __CEXTRACT__
31#include <sproto.h> 26# include <sproto.h>
32#endif 27#endif
33#include <spells.h> 28#include <spells.h>
34#include <loader.h> 29#include <loader.h>
35#include <define.h> 30#include <define.h>
36 31
39extern long pticks; 34extern long pticks;
40 35
41/* If flag is non zero, it means that we want to try and save everyone, but 36/* If flag is non zero, it means that we want to try and save everyone, but
42 * keep the game running. Thus, we don't want to free any information. 37 * keep the game running. Thus, we don't want to free any information.
43 */ 38 */
39void
44void emergency_save(int flag) { 40emergency_save (int flag)
41{
45 player *pl; 42 player *pl;
43
46#ifndef NO_EMERGENCY_SAVE 44#ifndef NO_EMERGENCY_SAVE
47 trying_emergency_save = 1; 45 trying_emergency_save = 1;
48 if(editor) 46 if (editor)
49 return; 47 return;
50 LOG(llevError,"Emergency save: "); 48 LOG (llevError, "Emergency save: ");
51 for(pl=first_player;pl!=NULL;pl=pl->next) { 49 for (pl = first_player; pl != NULL; pl = pl->next)
50 {
52 if(!pl->ob) { 51 if (!pl->ob)
52 {
53 LOG(llevError, "No name, ignoring this.\n"); 53 LOG (llevError, "No name, ignoring this.\n");
54 continue; 54 continue;
55 } 55 }
56 LOG(llevError,"%s ",pl->ob->name); 56 LOG (llevError, "%s ", pl->ob->name);
57 new_draw_info(NDI_UNIQUE, 0,pl->ob,"Emergency save..."); 57 new_draw_info (NDI_UNIQUE, 0, pl->ob, "Emergency save...");
58 58
59/* If we are not exiting the game (ie, this is sort of a backup save), then 59/* If we are not exiting the game (ie, this is sort of a backup save), then
60 * don't change the location back to the village. Note that there are other 60 * don't change the location back to the village. Note that there are other
61 * options to have backup saves be done at the starting village 61 * options to have backup saves be done at the starting village
62 */ 62 */
63 if (!flag) { 63 if (!flag)
64 {
64 strcpy(pl->maplevel, first_map_path); 65 strcpy (pl->maplevel, first_map_path);
65 if(pl->ob->map!=NULL) 66 if (pl->ob->map != NULL)
66 pl->ob->map = NULL; 67 pl->ob->map = NULL;
67 pl->ob->x = -1; 68 pl->ob->x = -1;
68 pl->ob->y = -1; 69 pl->ob->y = -1;
69 } 70 }
70 if(!save_player(pl->ob,flag)) { 71 if (!save_player (pl->ob, flag))
72 {
71 LOG(llevError, "(failed) "); 73 LOG (llevError, "(failed) ");
72 new_draw_info(NDI_UNIQUE, 0,pl->ob,"Emergency save failed, checking score..."); 74 new_draw_info (NDI_UNIQUE, 0, pl->ob, "Emergency save failed, checking score...");
73 } 75 }
74 check_score(pl->ob); 76 check_score (pl->ob);
75 } 77 }
76 LOG(llevError,"\n"); 78 LOG (llevError, "\n");
77#else 79#else
78 LOG(llevInfo,"Emergency saves disabled, no save attempted\n"); 80 LOG (llevInfo, "Emergency saves disabled, no save attempted\n");
79#endif 81#endif
80 /* If the game is exiting, remove the player locks */ 82 /* If the game is exiting, remove the player locks */
81 if (!flag) { 83 if (!flag)
84 {
82 for(pl=first_player;pl!=NULL;pl=pl->next) { 85 for (pl = first_player; pl != NULL; pl = pl->next)
86 {
83 if(pl->ob) { 87 if (pl->ob)
88 {
89 }
84 } 90 }
85 }
86 } 91 }
87} 92}
88 93
89/* Delete character with name. if new is set, also delete the new 94/* Delete character with name. if new is set, also delete the new
90 * style directory, otherwise, just delete the old style playfile 95 * style directory, otherwise, just delete the old style playfile
91 * (needed for transition) 96 * (needed for transition)
92 */ 97 */
98void
93void delete_character(const char *name, int newchar) { 99delete_character (const char *name, int newchar)
100{
94 char buf[MAX_BUF]; 101 char buf[MAX_BUF];
95 102
96 sprintf(buf,"%s/%s/%s.pl",settings.localdir,settings.playerdir,name); 103 sprintf (buf, "%s/%s/%s.pl", settings.localdir, settings.playerdir, name);
97 if(unlink(buf)== -1) 104 if (unlink (buf) == -1)
98 LOG(llevDebug, "Cannot delete character file %s: %s\n", buf, strerror(errno)); 105 LOG (llevDebug, "Cannot delete character file %s: %s\n", buf, strerror (errno));
99 if (newchar) { 106 if (newchar)
107 {
100 sprintf(buf,"%s/%s/%s",settings.localdir,settings.playerdir,name); 108 sprintf (buf, "%s/%s/%s", settings.localdir, settings.playerdir, name);
101 /* this effectively does an rm -rf on the directory */ 109 /* this effectively does an rm -rf on the directory */
102 remove_directory(buf); 110 remove_directory (buf);
103 } 111 }
104} 112}
105 113
106/* This verify that a character of name exits, and that it matches 114/* This verify that a character of name exits, and that it matches
107 * password. It return 0 if there is match, 1 if no such player, 115 * password. It return 0 if there is match, 1 if no such player,
108 * 2 if incorrect password. 116 * 2 if incorrect password.
109 */ 117 */
110 118
119int
111int verify_player(const char *name, char *password) 120verify_player (const char *name, char *password)
112{ 121{
113 char buf[MAX_BUF]; 122 char buf[MAX_BUF];
114 int comp; 123 int comp;
115 FILE *fp; 124 FILE *fp;
116 125
117 if (strpbrk(name, "/.\\") != NULL) { 126 if (strpbrk (name, "/.\\") != NULL)
127 {
118 LOG(llevError, "Username contains illegal characters: %s\n", name); 128 LOG (llevError, "Username contains illegal characters: %s\n", name);
119 return 1; 129 return 1;
120 } 130 }
121 131
122 snprintf(buf, sizeof(buf), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, name, name); 132 snprintf (buf, sizeof (buf), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, name, name);
123 if (strlen(buf) >= sizeof(buf)-1) { 133 if (strlen (buf) >= sizeof (buf) - 1)
134 {
124 LOG(llevError, "Username too long: %s\n", name); 135 LOG (llevError, "Username too long: %s\n", name);
125 return 1; 136 return 1;
126 } 137 }
127 138
128 if ((fp=open_and_uncompress(buf,0,&comp))==NULL) return 1; 139 if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL)
140 return 1;
129 141
130 /* Read in the file until we find the password line. Our logic could 142 /* Read in the file until we find the password line. Our logic could
131 * be a bit better on cleaning up the password from the file, but since 143 * be a bit better on cleaning up the password from the file, but since
132 * it is written by the program, I think it is fair to assume that the 144 * it is written by the program, I think it is fair to assume that the
133 * syntax should be pretty standard. 145 * syntax should be pretty standard.
134 */ 146 */
135 while (fgets(buf, MAX_BUF-1, fp) != NULL) { 147 while (fgets (buf, MAX_BUF - 1, fp) != NULL)
148 {
136 if (!strncmp(buf,"password ",9)) { 149 if (!strncmp (buf, "password ", 9))
150 {
137 buf[strlen(buf)-1]=0; /* remove newline */ 151 buf[strlen (buf) - 1] = 0; /* remove newline */
138 if (check_password(password, buf+9)) { 152 if (check_password (password, buf + 9))
153 {
139 close_and_delete(fp, comp); 154 close_and_delete (fp, comp);
140 return 0; 155 return 0;
141 } 156 }
142 else { 157 else
158 {
143 close_and_delete(fp, comp); 159 close_and_delete (fp, comp);
144 return 2; 160 return 2;
145 } 161 }
146 } 162 }
147 } 163 }
148 LOG(llevDebug,"Could not find a password line in player %s\n", name); 164 LOG (llevDebug, "Could not find a password line in player %s\n", name);
149 close_and_delete(fp, comp); 165 close_and_delete (fp, comp);
150 return 1; 166 return 1;
151} 167}
152 168
153/* Checks to see if anyone else by 'name' is currently playing. 169/* Checks to see if anyone else by 'name' is currently playing.
154 * If we find that file or another character of some name is already in the 170 * If we find that file or another character of some name is already in the
155 * game, we don't let this person join (we should really let the new player 171 * game, we don't let this person join (we should really let the new player
158 * If no one by that name is currently playing, we then make sure the name 174 * If no one by that name is currently playing, we then make sure the name
159 * doesn't include any bogus characters. 175 * doesn't include any bogus characters.
160 * We return 0 if the name is in use/bad, 1 if it is OK to use this name. 176 * We return 0 if the name is in use/bad, 1 if it is OK to use this name.
161 */ 177 */
162 178
179int
163int check_name(player *me,const char *name) { 180check_name (player *me, const char *name)
181{
164 player *pl; 182 player *pl;
165 183
166 for(pl=first_player;pl!=NULL;pl=pl->next) 184 for (pl = first_player; pl != NULL; pl = pl->next)
167 if(pl!=me&&pl->ob->name!=NULL&&!strcmp(pl->ob->name,name)) { 185 if (pl != me && pl->ob->name != NULL && !strcmp (pl->ob->name, name))
186 {
168 new_draw_info(NDI_UNIQUE, 0,me->ob,"That name is already in use."); 187 new_draw_info (NDI_UNIQUE, 0, me->ob, "That name is already in use.");
169 return 0;
170 }
171
172 if (*name=='\0') {
173 new_draw_info(NDI_UNIQUE, 0,me->ob,"Null names are not allowed.");
174 return 0; 188 return 0;
175 } 189 }
176 190
191 if (*name == '\0')
192 {
193 new_draw_info (NDI_UNIQUE, 0, me->ob, "Null names are not allowed.");
194 return 0;
195 }
196
177 if(!playername_ok(name)) { 197 if (!playername_ok (name))
198 {
178 new_draw_info(NDI_UNIQUE, 0,me->ob,"That name contains illegal characters."); 199 new_draw_info (NDI_UNIQUE, 0, me->ob, "That name contains illegal characters.");
179 return 0; 200 return 0;
180 } 201 }
181 if (strlen(name) >= MAX_NAME) { 202 if (strlen (name) >= MAX_NAME)
203 {
182 new_draw_info(NDI_UNIQUE, 0,me->ob,"That name is too long."); 204 new_draw_info (NDI_UNIQUE, 0, me->ob, "That name is too long.");
183 return 0; 205 return 0;
184 } 206 }
185 207
186 return 1; 208 return 1;
187} 209}
188 210
211int
189int create_savedir_if_needed(char *savedir) 212create_savedir_if_needed (char *savedir)
190{ 213{
191 struct stat *buf; 214 struct stat *buf;
192 215
193 if ((buf = (struct stat *) malloc(sizeof(struct stat))) == NULL) { 216 if ((buf = (struct stat *) malloc (sizeof (struct stat))) == NULL)
217 {
194 LOG(llevError, "Unable to save playerfile... out of memory.\n"); 218 LOG (llevError, "Unable to save playerfile... out of memory.\n");
195 return 0; 219 return 0;
220 }
196 } else { 221 else
222 {
197 stat(savedir, buf); 223 stat (savedir, buf);
198 if (!S_ISDIR(buf->st_mode)) 224 if (!S_ISDIR (buf->st_mode))
199 if (mkdir(savedir, SAVE_DIR_MODE)) 225 if (mkdir (savedir, SAVE_DIR_MODE))
200 { 226 {
201 LOG(llevError, "Unable to create player savedir %s: %s\n", savedir, strerror(errno)); 227 LOG (llevError, "Unable to create player savedir %s: %s\n", savedir, strerror (errno));
202 return 0; 228 return 0;
203 } 229 }
204 free(buf); 230 free (buf);
205 } 231 }
206 return 1; 232 return 1;
207} 233}
208 234
235void
209void destroy_object (object *op) 236destroy_object (object *op)
210{ 237{
211 object *tmp; 238 object *tmp;
239
212 while ((tmp = op->inv)) 240 while ((tmp = op->inv))
213 destroy_object (tmp); 241 destroy_object (tmp);
214 242
215 if (!QUERY_FLAG(op, FLAG_REMOVED)) 243 if (!QUERY_FLAG (op, FLAG_REMOVED))
216 remove_ob(op); 244 remove_ob (op);
217 free_object(op); 245 free_object (op);
218} 246}
219 247
220/* 248/*
221 * If flag is set, it's only backup, ie dont remove objects from inventory 249 * If flag is set, it's only backup, ie dont remove objects from inventory
222 * If BACKUP_SAVE_AT_HOME is set, and the flag is set, then the player 250 * If BACKUP_SAVE_AT_HOME is set, and the flag is set, then the player
223 * will be saved at the emergency save location. 251 * will be saved at the emergency save location.
224 * Returns non zero if successful. 252 * Returns non zero if successful.
225 */ 253 */
226 254
255int
227int save_player(object *op, int flag) { 256save_player (object *op, int flag)
257{
228 object *tmp, *container=NULL; 258 object *tmp, *container = NULL;
229 player *pl = op->contr; 259 player *pl = op->contr;
230 int i,wiz=QUERY_FLAG(op,FLAG_WIZ); 260 int i, wiz = QUERY_FLAG (op, FLAG_WIZ);
231 long checksum; 261
232#ifdef BACKUP_SAVE_AT_HOME 262#ifdef BACKUP_SAVE_AT_HOME
233 sint16 backup_x, backup_y; 263 sint16 backup_x, backup_y;
234#endif 264#endif
235 265
236 if (!op->stats.exp) return 0; /* no experience, no save */ 266 if (!op->stats.exp)
267 return 0; /* no experience, no save */
237 268
238 flag&=1; 269 flag &= 1;
239 270
240 if(!pl->name_changed||(!flag&&!op->stats.exp)) { 271 if (!pl->name_changed || (!flag && !op->stats.exp))
272 {
241 if(!flag) { 273 if (!flag)
274 {
242 new_draw_info(NDI_UNIQUE, 0,op,"Your game is not valid,"); 275 new_draw_info (NDI_UNIQUE, 0, op, "Your game is not valid,");
243 new_draw_info(NDI_UNIQUE, 0,op,"Game not saved."); 276 new_draw_info (NDI_UNIQUE, 0, op, "Game not saved.");
277 }
278 return 0;
244 } 279 }
280
281 /* Sanity check - some stuff changes this when player is exiting */
282 if (op->type != PLAYER)
245 return 0; 283 return 0;
246 }
247 284
248 /* Sanity check - some stuff changes this when player is exiting */
249 if (op->type != PLAYER) return 0;
250
251 /* Prevent accidental saves if connection is reset after player has 285 /* Prevent accidental saves if connection is reset after player has
252 * mostly exited. 286 * mostly exited.
253 */ 287 */
254 if (pl->state != ST_PLAYING && pl->state != ST_GET_PARTY_PASSWORD) 288 if (pl->state != ST_PLAYING && pl->state != ST_GET_PARTY_PASSWORD)
255 return 0; 289 return 0;
256 290
257 INVOKE_PLAYER (SAVE, op->contr); 291 INVOKE_PLAYER (SAVE, op->contr);
258 292
259 if (flag == 0) 293 if (flag == 0)
260 terminate_all_pets(op); 294 terminate_all_pets (op);
261 295
262 object_freezer freezer; 296 object_freezer freezer;
263 297
264 /* Eneq(@csd.uu.se): If we have an open container hide it. */ 298 /* Eneq(@csd.uu.se): If we have an open container hide it. */
265 if (op->container) 299 if (op->container)
266 { 300 {
267 container = op->container; 301 container = op->container;
268 op->container = NULL; 302 op->container = NULL;
269 } 303 }
270 304
271 fprintf(freezer,"password %s\n",pl->password); 305 fprintf (freezer, "password %s\n", pl->password);
272 306
273 if (settings.set_title == TRUE) 307 if (settings.set_title == TRUE)
274 if(pl->own_title[0]!='\0') 308 if (pl->own_title[0] != '\0')
275 fprintf(freezer,"title %s\n",pl->own_title); 309 fprintf (freezer, "title %s\n", pl->own_title);
276 310
277 fprintf(freezer,"explore %d\n",pl->explore); 311 fprintf (freezer, "explore %d\n", pl->explore);
278 fprintf(freezer,"gen_hp %d\n",pl->gen_hp); 312 fprintf (freezer, "gen_hp %d\n", pl->gen_hp);
279 fprintf(freezer,"gen_sp %d\n",pl->gen_sp); 313 fprintf (freezer, "gen_sp %d\n", pl->gen_sp);
280 fprintf(freezer,"gen_grace %d\n",pl->gen_grace); 314 fprintf (freezer, "gen_grace %d\n", pl->gen_grace);
281 fprintf(freezer,"listening %d\n",pl->listening); 315 fprintf (freezer, "listening %d\n", pl->listening);
282 fprintf(freezer,"shoottype %d\n",pl->shoottype); 316 fprintf (freezer, "shoottype %d\n", pl->shoottype);
283 fprintf(freezer,"bowtype %d\n",pl->bowtype); 317 fprintf (freezer, "bowtype %d\n", pl->bowtype);
284 fprintf(freezer,"petmode %d\n",pl->petmode); 318 fprintf (freezer, "petmode %d\n", pl->petmode);
285 fprintf(freezer,"peaceful %d\n",pl->peaceful); 319 fprintf (freezer, "peaceful %d\n", pl->peaceful);
286 fprintf(freezer,"no_shout %d\n",pl->no_shout); 320 fprintf (freezer, "no_shout %d\n", pl->no_shout);
287 fprintf(freezer,"digestion %d\n",pl->digestion); 321 fprintf (freezer, "digestion %d\n", pl->digestion);
288 fprintf(freezer,"pickup %d\n", pl->mode); 322 fprintf (freezer, "pickup %d\n", pl->mode);
289 fprintf(freezer,"outputs_sync %d\n", pl->outputs_sync); 323 fprintf (freezer, "outputs_sync %d\n", pl->outputs_sync);
290 fprintf(freezer,"outputs_count %d\n", pl->outputs_count); 324 fprintf (freezer, "outputs_count %d\n", pl->outputs_count);
291 /* Match the enumerations but in string form */ 325 /* Match the enumerations but in string form */
292 fprintf(freezer,"usekeys %s\n", pl->usekeys==key_inventory?"key_inventory": 326 fprintf (freezer, "usekeys %s\n", pl->usekeys == key_inventory ? "key_inventory" : (pl->usekeys == keyrings ? "keyrings" : "containers"));
293 (pl->usekeys==keyrings?"keyrings":"containers"));
294 /* Match the enumerations but in string form */ 327 /* Match the enumerations but in string form */
295 fprintf(freezer,"unapply %s\n", pl->unapply==unapply_nochoice?"unapply_nochoice": 328 fprintf (freezer, "unapply %s\n", pl->unapply == unapply_nochoice ? "unapply_nochoice" :
296 (pl->unapply==unapply_never?"unapply_never":"unapply_always")); 329 (pl->unapply == unapply_never ? "unapply_never" : "unapply_always"));
297 330
298#ifdef BACKUP_SAVE_AT_HOME 331#ifdef BACKUP_SAVE_AT_HOME
299 if (op->map!=NULL && flag==0) 332 if (op->map != NULL && flag == 0)
300#else 333#else
301 if (op->map!=NULL) 334 if (op->map != NULL)
302#endif 335#endif
303 fprintf(freezer,"map %s\n",op->map->path); 336 fprintf (freezer, "map %s\n", op->map->path);
304 else 337 else
305 fprintf(freezer,"map %s\n",settings.emergency_mapname); 338 fprintf (freezer, "map %s\n", settings.emergency_mapname);
306 339
307 fprintf(freezer,"savebed_map %s\n", pl->savebed_map); 340 fprintf (freezer, "savebed_map %s\n", pl->savebed_map);
308 fprintf(freezer,"bed_x %d\nbed_y %d\n", pl->bed_x, pl->bed_y); 341 fprintf (freezer, "bed_x %d\nbed_y %d\n", pl->bed_x, pl->bed_y);
309 fprintf(freezer,"weapon_sp %f\n",pl->weapon_sp); 342 fprintf (freezer, "weapon_sp %f\n", pl->weapon_sp);
310 fprintf(freezer,"Str %d\n",pl->orig_stats.Str); 343 fprintf (freezer, "Str %d\n", pl->orig_stats.Str);
311 fprintf(freezer,"Dex %d\n",pl->orig_stats.Dex); 344 fprintf (freezer, "Dex %d\n", pl->orig_stats.Dex);
312 fprintf(freezer,"Con %d\n",pl->orig_stats.Con); 345 fprintf (freezer, "Con %d\n", pl->orig_stats.Con);
313 fprintf(freezer,"Int %d\n",pl->orig_stats.Int); 346 fprintf (freezer, "Int %d\n", pl->orig_stats.Int);
314 fprintf(freezer,"Pow %d\n",pl->orig_stats.Pow); 347 fprintf (freezer, "Pow %d\n", pl->orig_stats.Pow);
315 fprintf(freezer,"Wis %d\n",pl->orig_stats.Wis); 348 fprintf (freezer, "Wis %d\n", pl->orig_stats.Wis);
316 fprintf(freezer,"Cha %d\n",pl->orig_stats.Cha); 349 fprintf (freezer, "Cha %d\n", pl->orig_stats.Cha);
317 350
318 fprintf(freezer,"lev_array %d\n",op->level>10?10:op->level); 351 fprintf (freezer, "lev_array %d\n", op->level > 10 ? 10 : op->level);
319 for(i=1;i<=pl->last_level&&i<=10;i++) { 352 for (i = 1; i <= pl->last_level && i <= 10; i++)
353 {
320 fprintf(freezer,"%d\n",pl->levhp[i]); 354 fprintf (freezer, "%d\n", pl->levhp[i]);
321 fprintf(freezer,"%d\n",pl->levsp[i]); 355 fprintf (freezer, "%d\n", pl->levsp[i]);
322 fprintf(freezer,"%d\n",pl->levgrace[i]); 356 fprintf (freezer, "%d\n", pl->levgrace[i]);
323 } 357 }
324 358
325 freezer.put (op->contr); 359 freezer.put (op->contr);
326 360
327 fprintf(freezer,"endplst\n"); 361 fprintf (freezer, "endplst\n");
328 362
329 SET_FLAG(op, FLAG_NO_FIX_PLAYER); 363 SET_FLAG (op, FLAG_NO_FIX_PLAYER);
330 CLEAR_FLAG(op, FLAG_WIZ); 364 CLEAR_FLAG (op, FLAG_WIZ);
331#ifdef BACKUP_SAVE_AT_HOME 365#ifdef BACKUP_SAVE_AT_HOME
332 if (flag) { 366 if (flag)
367 {
333 backup_x = op->x; 368 backup_x = op->x;
334 backup_y = op->y; 369 backup_y = op->y;
335 op->x = -1; 370 op->x = -1;
336 op->y = -1; 371 op->y = -1;
337 } 372 }
338 /* Save objects, but not unpaid objects. Don't remove objects from 373 /* Save objects, but not unpaid objects. Don't remove objects from
339 * inventory. 374 * inventory.
340 */ 375 */
341 save_object(freezer, op, 2); 376 save_object (freezer, op, 2);
342 if (flag) { 377 if (flag)
378 {
343 op->x = backup_x; 379 op->x = backup_x;
344 op->y = backup_y; 380 op->y = backup_y;
345 } 381 }
346#else 382#else
347 save_object(freezer, op, 3); /* don't check and don't remove */ 383 save_object (freezer, op, 3); /* don't check and don't remove */
348#endif 384#endif
349 385
350 char filename[MAX_BUF]; 386 char filename[MAX_BUF];
387
351 sprintf(filename,"%s/%s/%s/%s.pl",settings.localdir,settings.playerdir,&op->name,&op->name); 388 sprintf (filename, "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, &op->name, &op->name);
352 make_path_to_file(filename); 389 make_path_to_file (filename);
353 freezer.save (filename); 390 freezer.save (filename);
354 391
355 CLEAR_FLAG(op, FLAG_NO_FIX_PLAYER); 392 CLEAR_FLAG (op, FLAG_NO_FIX_PLAYER);
356 393
357 if(!flag) 394 if (!flag)
358 while ((tmp = op->inv)) 395 while ((tmp = op->inv))
359 destroy_object (tmp); 396 destroy_object (tmp);
360 397
361 /* Eneq(@csd.uu.se): Reveal the container if we have one. */ 398 /* Eneq(@csd.uu.se): Reveal the container if we have one. */
362 if (flag && container!=NULL) 399 if (flag && container != NULL)
363 op->container = container; 400 op->container = container;
364 401
402 if (wiz)
365 if (wiz) SET_FLAG (op, FLAG_WIZ); 403 SET_FLAG (op, FLAG_WIZ);
366 404
367 if(!flag) 405 if (!flag)
368 esrv_send_inventory(op, op); 406 esrv_send_inventory (op, op);
369 407
370 return 1; 408 return 1;
371} 409}
372 410
411void
373void check_login(object *op) { 412check_login (object *op)
413{
374 char filename[MAX_BUF]; 414 char filename[MAX_BUF];
375 char buf[MAX_BUF],bufall[MAX_BUF]; 415 char buf[MAX_BUF], bufall[MAX_BUF];
376 int i,value,comp; 416 int i, value;
377 long checksum = 0;
378 player *pl = op->contr; 417 player *pl = op->contr;
379 int correct = 0; 418 int correct = 0;
380 419
381 strcpy (pl->maplevel,first_map_path); 420 strcpy (pl->maplevel, first_map_path);
382 sprintf(filename,"%s/%s/%s/%s.pl",settings.localdir,settings.playerdir,&op->name,&op->name); 421 sprintf (filename, "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, &op->name, &op->name);
383 422
384 object_thawer thawer (filename); 423 object_thawer thawer (filename);
424
385 /* If no file, must be a new player, so lets get confirmation of 425 /* If no file, must be a new player, so lets get confirmation of
386 * the password. Return control to the higher level dispatch, 426 * the password. Return control to the higher level dispatch,
387 * since the rest of this just deals with loading of the file. 427 * since the rest of this just deals with loading of the file.
388 */ 428 */
389 if (!thawer) { 429 if (!thawer)
430 {
390 confirm_password(op); 431 confirm_password (op);
432 return;
433 }
434
435 if (fgets (bufall, MAX_BUF, thawer) != NULL)
436 {
437 if (sscanf (bufall, "password %s\n", buf))
438 {
439 /* New password scheme: */
440 correct = check_password (pl->write_buf + 1, buf);
441 }
442 }
443
444 if (!correct)
445 {
446 new_draw_info (NDI_UNIQUE, 0, op, " ");
447 new_draw_info (NDI_UNIQUE, 0, op, "Wrong Password!");
448 new_draw_info (NDI_UNIQUE, 0, op, " ");
449 op->name = op->name_pl = "noname";
450 op->contr->socket.password_fails++;
451 if (op->contr->socket.password_fails >= MAX_PASSWORD_FAILURES)
452 {
453 new_draw_info (NDI_UNIQUE, 0, op, "You gave an incorrect password too many times, you will now be dropped from the server.");
454 LOG (llevInfo, "A player connecting from %s has been dropped for password failure\n", op->contr->socket.host);
455 op->contr->socket.status = Ns_Dead; /* the socket loop should handle the rest for us */
456 }
457 else
458 get_name (op);
459
460 return; /* Once again, rest of code just loads the char */
461 }
462
463#ifdef SAVE_INTERVAL
464 pl->last_save_time = time (NULL);
465#endif /* SAVE_INTERVAL */
466 pl->party = NULL;
467 if (settings.search_items == TRUE)
468 pl->search_str[0] = '\0';
469 pl->name_changed = 1;
470 pl->orig_stats.Str = 0;
471 pl->orig_stats.Dex = 0;
472 pl->orig_stats.Con = 0;
473 pl->orig_stats.Int = 0;
474 pl->orig_stats.Pow = 0;
475 pl->orig_stats.Wis = 0;
476 pl->orig_stats.Cha = 0;
477 strcpy (pl->savebed_map, first_map_path);
478 pl->bed_x = 0, pl->bed_y = 0;
479 pl->spellparam[0] = '\0';
480
481 /* Loop through the file, loading the rest of the values */
482 while (fgets (bufall, MAX_BUF, thawer) != NULL)
483 {
484 sscanf (bufall, "%s %d\n", buf, &value);
485 if (!strcmp (buf, "endplst"))
486 break;
487 else if (!strcmp (buf, "oid"))
488 thawer.get (pl, value);
489 else if (!strcmp (buf, "title") && settings.set_title == TRUE)
490 sscanf (bufall, "title %[^\n]", pl->own_title);
491 else if (!strcmp (buf, "explore"))
492 pl->explore = value;
493 else if (!strcmp (buf, "gen_hp"))
494 pl->gen_hp = value;
495 else if (!strcmp (buf, "shoottype"))
496 pl->shoottype = (rangetype) value;
497 else if (!strcmp (buf, "bowtype"))
498 pl->bowtype = (bowtype_t) value;
499 else if (!strcmp (buf, "petmode"))
500 pl->petmode = (petmode_t) value;
501 else if (!strcmp (buf, "gen_sp"))
502 pl->gen_sp = value;
503 else if (!strcmp (buf, "gen_grace"))
504 pl->gen_grace = value;
505 else if (!strcmp (buf, "listening"))
506 pl->listening = value;
507 else if (!strcmp (buf, "peaceful"))
508 pl->peaceful = value;
509 else if (!strcmp (buf, "no_shout"))
510 pl->no_shout = value;
511 else if (!strcmp (buf, "digestion"))
512 pl->digestion = value;
513 else if (!strcmp (buf, "pickup"))
514 pl->mode = value;
515 else if (!strcmp (buf, "outputs_sync"))
516 pl->outputs_sync = value;
517 else if (!strcmp (buf, "outputs_count"))
518 pl->outputs_count = value;
519 else if (!strcmp (buf, "map"))
520 sscanf (bufall, "map %s", pl->maplevel);
521 else if (!strcmp (buf, "savebed_map"))
522 sscanf (bufall, "savebed_map %s", pl->savebed_map);
523 else if (!strcmp (buf, "bed_x"))
524 pl->bed_x = value;
525 else if (!strcmp (buf, "bed_y"))
526 pl->bed_y = value;
527 else if (!strcmp (buf, "weapon_sp"))
528 sscanf (buf, "weapon_sp %f", &pl->weapon_sp);
529 else if (!strcmp (buf, "Str"))
530 pl->orig_stats.Str = value;
531 else if (!strcmp (buf, "Dex"))
532 pl->orig_stats.Dex = value;
533 else if (!strcmp (buf, "Con"))
534 pl->orig_stats.Con = value;
535 else if (!strcmp (buf, "Int"))
536 pl->orig_stats.Int = value;
537 else if (!strcmp (buf, "Pow"))
538 pl->orig_stats.Pow = value;
539 else if (!strcmp (buf, "Wis"))
540 pl->orig_stats.Wis = value;
541 else if (!strcmp (buf, "Cha"))
542 pl->orig_stats.Cha = value;
543 else if (!strcmp (buf, "usekeys"))
544 {
545 if (!strcmp (bufall + 8, "key_inventory\n"))
546 pl->usekeys = key_inventory;
547 else if (!strcmp (bufall + 8, "keyrings\n"))
548 pl->usekeys = keyrings;
549 else if (!strcmp (bufall + 8, "containers\n"))
550 pl->usekeys = containers;
551 else
552 LOG (llevDebug, "load_player: got unknown usekeys type: %s\n", bufall + 8);
553 }
554 else if (!strcmp (buf, "unapply"))
555 {
556 if (!strcmp (bufall + 8, "unapply_nochoice\n"))
557 pl->unapply = unapply_nochoice;
558 else if (!strcmp (bufall + 8, "unapply_never\n"))
559 pl->unapply = unapply_never;
560 else if (!strcmp (bufall + 8, "unapply_always\n"))
561 pl->unapply = unapply_always;
562 else
563 LOG (llevDebug, "load_player: got unknown unapply type: %s\n", bufall + 8);
564 }
565 else if (!strcmp (buf, "lev_array"))
566 {
567 for (i = 1; i <= value; i++)
568 {
569 char line[128];
570
571 fgets (line, 128, thawer);
572 pl->levhp[i] = atoi (line);
573 fgets (line, 128, thawer);
574 pl->levsp[i] = atoi (line);
575 fgets (line, 128, thawer);
576 pl->levgrace[i] = atoi (line);
577 }
578 /* spell_array code removed - don't know when that was last used.
579 * Even the load code below will someday be replaced by spells being
580 * objects.
581 */
582 }
583 else if (!strcmp (buf, "known_spell"))
584 {
585#if 0
586 /* Logic is left here in case someone wants to try
587 * and write code to update to spell objects.
588 */
589 char *cp = strchr (bufall, '\n');
590
591 *cp = '\0';
592 cp = strchr (bufall, ' ');
593 cp++;
594 for (i = 0; i < NROFREALSPELLS; i++)
595 if (!strcmp (spells[i].name, cp))
596 {
597 pl->known_spells[pl->nrofknownspells++] = i;
598 break;
599 }
600 if (i == NROFREALSPELLS)
601 LOG (llevDebug, "Error: unknown spell (%s)\n", cp);
602#endif
603 }
604 } /* End of loop loading the character file */
605
606 leave_map (op);
607 op->speed = 0;
608 update_ob_speed (op);
609
610 clear_object (op);
611
612 op->contr = pl;
613 pl->ob = op;
614
615 /* this loads the standard objects values. */
616 load_object (thawer, op, 0);
617
618 CLEAR_FLAG (op, FLAG_NO_FIX_PLAYER);
619
620 assign (pl->title, op->arch->clone.name);
621
622 /* If the map where the person was last saved does not exist,
623 * restart them on their home-savebed. This is good for when
624 * maps change between versions
625 * First, we check for partial path, then check to see if the full
626 * path (for unique player maps)
627 */
628 if (check_path (pl->maplevel, 1) == -1)
629 {
630 if (check_path (pl->maplevel, 0) == -1)
631 {
632 strcpy (pl->maplevel, pl->savebed_map);
633 op->x = pl->bed_x, op->y = pl->bed_y;
634 }
635 }
636
637 /* make sure he's a player--needed because of class change. */
638 op->type = PLAYER;
639
640 enter_exit (op, NULL);
641
642 pl->name_changed = 1;
643 pl->state = ST_PLAYING;
644#ifdef AUTOSAVE
645 pl->last_save_tick = pticks;
646#endif
647 op->carrying = sum_weight (op);
648 /* Need to call fix_player now - program modified so that it is not
649 * called during the load process (FLAG_NO_FIX_PLAYER set when
650 * saved)
651 * Moved ahead of the esrv functions, so proper weights will be
652 * sent to the client.
653 */
654 link_player_skills (op);
655
656 if (!legal_range (op, op->contr->shoottype))
657 op->contr->shoottype = range_none;
658
659 fix_player (op);
660
661 /* if it's a dragon player, set the correct title here */
662 if (is_dragon_pl (op) && op->inv != NULL)
663 {
664 object *tmp, *abil = NULL, *skin = NULL;
665
666 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
667 {
668 if (tmp->type == FORCE)
669 {
670 if (strcmp (tmp->arch->name, "dragon_ability_force") == 0)
671 abil = tmp;
672 else if (strcmp (tmp->arch->name, "dragon_skin_force") == 0)
673 skin = tmp;
674 }
675 }
676 set_dragon_name (op, abil, skin);
677 }
678
679 new_draw_info (NDI_UNIQUE, 0, op, "Welcome Back!");
680 new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL, "%s has entered the game.", &pl->ob->name);
681
682 INVOKE_PLAYER (LOAD, pl, ARG_STRING (filename));
683 INVOKE_PLAYER (LOGIN, pl);
684
685 op->contr->socket.update_look = 1;
686 /* If the player should be dead, call kill_player for them
687 * Only check for hp - if player lacks food, let the normal
688 * logic for that to take place. If player is permanently
689 * dead, and not using permadeath mode, the kill_player will
690 * set the play_again flag, so return.
691 */
692 if (op->stats.hp < 0)
693 {
694 new_draw_info (NDI_UNIQUE, 0, op, "Your character was dead last your played.");
695 kill_player (op);
696 if (pl->state != ST_PLAYING)
391 return; 697 return;
392 } 698 }
393
394 if(fgets(bufall,MAX_BUF,thawer) != NULL) {
395 if(!strncmp(bufall,"checksum ",9)) {
396 checksum = strtol(bufall+9,(char **) NULL, 16);
397 (void) fgets(bufall,MAX_BUF,thawer);
398 }
399 if(sscanf(bufall,"password %s\n",buf)) {
400 /* New password scheme: */
401 correct=check_password(pl->write_buf+1,buf);
402 }
403 /* Old password mode removed - I have no idea what it
404 * was, and the current password mechanism has been used
405 * for at least several years.
406 */
407 }
408 if (!correct) {
409 new_draw_info(NDI_UNIQUE, 0,op," ");
410 new_draw_info(NDI_UNIQUE, 0,op,"Wrong Password!");
411 new_draw_info(NDI_UNIQUE, 0,op," ");
412 op->name =
413 op->name_pl = "noname";
414 op->contr->socket.password_fails++;
415 if (op->contr->socket.password_fails >= MAX_PASSWORD_FAILURES) {
416 new_draw_info(NDI_UNIQUE, 0,op,
417 "You gave an incorrect password too many times, you will now be dropped from the server.");
418 LOG(llevInfo, "A player connecting from %s has been dropped for password failure\n",
419 op->contr->socket.host);
420 op->contr->socket.status = Ns_Dead; /* the socket loop should handle the rest for us */
421 }
422 else get_name(op);
423 return; /* Once again, rest of code just loads the char */
424 }
425
426#ifdef SAVE_INTERVAL
427 pl->last_save_time=time(NULL);
428#endif /* SAVE_INTERVAL */
429 pl->party = NULL;
430 if (settings.search_items == TRUE)
431 pl->search_str[0]='\0';
432 pl->name_changed=1;
433 pl->orig_stats.Str=0;
434 pl->orig_stats.Dex=0;
435 pl->orig_stats.Con=0;
436 pl->orig_stats.Int=0;
437 pl->orig_stats.Pow=0;
438 pl->orig_stats.Wis=0;
439 pl->orig_stats.Cha=0;
440 strcpy(pl->savebed_map, first_map_path);
441 pl->bed_x=0, pl->bed_y=0;
442 pl->spellparam[0] = '\0';
443
444 /* Loop through the file, loading the rest of the values */
445 while (fgets(bufall,MAX_BUF,thawer)!=NULL) {
446 sscanf(bufall,"%s %d\n",buf,&value);
447 if (!strcmp(buf,"endplst"))
448 break;
449 else if (!strcmp(buf,"oid"))
450 thawer.get (pl, value);
451 else if (!strcmp(buf,"title") && settings.set_title == TRUE)
452 sscanf(bufall,"title %[^\n]",pl->own_title);
453 else if (!strcmp(buf,"explore"))
454 pl->explore = value;
455 else if (!strcmp(buf,"gen_hp"))
456 pl->gen_hp=value;
457 else if (!strcmp(buf,"shoottype"))
458 pl->shoottype=(rangetype)value;
459 else if (!strcmp(buf,"bowtype"))
460 pl->bowtype=(bowtype_t)value;
461 else if (!strcmp(buf,"petmode"))
462 pl->petmode=(petmode_t)value;
463 else if (!strcmp(buf,"gen_sp"))
464 pl->gen_sp=value;
465 else if (!strcmp(buf,"gen_grace"))
466 pl->gen_grace=value;
467 else if (!strcmp(buf,"listening"))
468 pl->listening=value;
469 else if (!strcmp(buf,"peaceful"))
470 pl->peaceful=value;
471 else if (!strcmp(buf,"no_shout"))
472 pl->no_shout=value;
473 else if (!strcmp(buf,"digestion"))
474 pl->digestion=value;
475 else if (!strcmp(buf,"pickup"))
476 pl->mode=value;
477 else if (!strcmp(buf,"outputs_sync"))
478 pl->outputs_sync = value;
479 else if (!strcmp(buf,"outputs_count"))
480 pl->outputs_count = value;
481 else if (!strcmp(buf,"map"))
482 sscanf(bufall,"map %s", pl->maplevel);
483 else if (!strcmp(buf,"savebed_map"))
484 sscanf(bufall,"savebed_map %s", pl->savebed_map);
485 else if (!strcmp(buf,"bed_x"))
486 pl->bed_x=value;
487 else if (!strcmp(buf,"bed_y"))
488 pl->bed_y=value;
489 else if (!strcmp(buf,"weapon_sp"))
490 sscanf(buf,"weapon_sp %f",&pl->weapon_sp);
491 else if (!strcmp(buf,"Str"))
492 pl->orig_stats.Str=value;
493 else if (!strcmp(buf,"Dex"))
494 pl->orig_stats.Dex=value;
495 else if (!strcmp(buf,"Con"))
496 pl->orig_stats.Con=value;
497 else if (!strcmp(buf,"Int"))
498 pl->orig_stats.Int=value;
499 else if (!strcmp(buf,"Pow"))
500 pl->orig_stats.Pow=value;
501 else if (!strcmp(buf,"Wis"))
502 pl->orig_stats.Wis=value;
503 else if (!strcmp(buf,"Cha"))
504 pl->orig_stats.Cha=value;
505 else if (!strcmp(buf,"usekeys")) {
506 if (!strcmp(bufall+8,"key_inventory\n"))
507 pl->usekeys=key_inventory;
508 else if (!strcmp(bufall+8,"keyrings\n"))
509 pl->usekeys=keyrings;
510 else if (!strcmp(bufall+8,"containers\n"))
511 pl->usekeys=containers;
512 else LOG(llevDebug,"load_player: got unknown usekeys type: %s\n", bufall+8);
513 }
514 else if (!strcmp(buf,"unapply")) {
515 if (!strcmp(bufall+8,"unapply_nochoice\n"))
516 pl->unapply=unapply_nochoice;
517 else if (!strcmp(bufall+8,"unapply_never\n"))
518 pl->unapply=unapply_never;
519 else if (!strcmp(bufall+8,"unapply_always\n"))
520 pl->unapply=unapply_always;
521 else LOG(llevDebug,"load_player: got unknown unapply type: %s\n", bufall+8);
522 }
523 else if (!strcmp(buf,"lev_array")){
524 for(i=1;i<=value;i++)
525 {
526 char line[128];
527 fgets (line, 128, thawer); pl->levhp[i] = atoi (line);
528 fgets (line, 128, thawer); pl->levsp[i] = atoi (line);
529 fgets (line, 128, thawer); pl->levgrace[i] = atoi (line);
530 }
531 /* spell_array code removed - don't know when that was last used.
532 * Even the load code below will someday be replaced by spells being
533 * objects.
534 */
535 } else if (!strcmp(buf,"known_spell")) {
536#if 0
537 /* Logic is left here in case someone wants to try
538 * and write code to update to spell objects.
539 */
540 char *cp=strchr(bufall,'\n');
541 *cp='\0';
542 cp=strchr(bufall,' ');
543 cp++;
544 for(i=0;i<NROFREALSPELLS;i++)
545 if(!strcmp(spells[i].name,cp)) {
546 pl->known_spells[pl->nrofknownspells++]=i;
547 break;
548 }
549 if(i==NROFREALSPELLS)
550 LOG(llevDebug, "Error: unknown spell (%s)\n",cp);
551#endif
552 }
553 } /* End of loop loading the character file */
554 leave_map(op);
555 op->speed=0;
556 update_ob_speed(op);
557 reset_object(op);
558 op->contr = pl;
559 pl->ob = op;
560
561 /* this loads the standard objects values. */
562 load_object (thawer, op, 0);
563
564 CLEAR_FLAG(op, FLAG_NO_FIX_PLAYER);
565
566 strncpy(pl->title, op->arch->clone.name, sizeof(pl->title)-1);
567 pl->title[sizeof(pl->title)-1] = '\0';
568
569 /* If the map where the person was last saved does not exist,
570 * restart them on their home-savebed. This is good for when
571 * maps change between versions
572 * First, we check for partial path, then check to see if the full
573 * path (for unique player maps)
574 */
575 if (check_path(pl->maplevel,1)==-1) {
576 if (check_path(pl->maplevel,0)==-1) {
577 strcpy(pl->maplevel, pl->savebed_map);
578 op->x = pl->bed_x, op->y = pl->bed_y;
579 }
580 }
581
582 /* make sure he's a player--needed because of class change. */
583 op->type = PLAYER;
584
585 enter_exit(op,NULL);
586
587 pl->name_changed=1;
588 pl->state = ST_PLAYING;
589#ifdef AUTOSAVE
590 pl->last_save_tick = pticks;
591#endif
592 op->carrying = sum_weight (op);
593 /* Need to call fix_player now - program modified so that it is not
594 * called during the load process (FLAG_NO_FIX_PLAYER set when
595 * saved)
596 * Moved ahead of the esrv functions, so proper weights will be
597 * sent to the client.
598 */
599 link_player_skills(op);
600
601 if ( ! legal_range (op, op->contr->shoottype))
602 op->contr->shoottype = range_none;
603
604 fix_player (op);
605
606 /* if it's a dragon player, set the correct title here */
607 if (is_dragon_pl(op) && op->inv != NULL) {
608 object *tmp, *abil=NULL, *skin=NULL;
609 for (tmp=op->inv; tmp!=NULL; tmp=tmp->below) {
610 if (tmp->type == FORCE) {
611 if (strcmp(tmp->arch->name, "dragon_ability_force")==0)
612 abil = tmp;
613 else if (strcmp(tmp->arch->name, "dragon_skin_force")==0)
614 skin = tmp;
615 }
616 }
617 set_dragon_name(op, abil, skin);
618 }
619
620 new_draw_info(NDI_UNIQUE, 0,op,"Welcome Back!");
621 new_draw_info_format(NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL,
622 "%s has entered the game.", &pl->ob->name);
623
624 INVOKE_PLAYER (LOAD, pl, ARG_STRING (filename));
625 INVOKE_PLAYER (LOGIN, pl);
626
627 op->contr->socket.update_look=1;
628 /* If the player should be dead, call kill_player for them
629 * Only check for hp - if player lacks food, let the normal
630 * logic for that to take place. If player is permanently
631 * dead, and not using permadeath mode, the kill_player will
632 * set the play_again flag, so return.
633 */
634 if (op->stats.hp<0) {
635 new_draw_info(NDI_UNIQUE, 0,op,"Your character was dead last your played.");
636 kill_player(op);
637 if (pl->state != ST_PLAYING) return;
638 }
639 LOG(llevInfo,"LOGIN: Player named %s from ip %s\n", &op->name, op->contr->socket.host); 699 LOG (llevInfo, "LOGIN: Player named %s from ip %s\n", &op->name, op->contr->socket.host);
640 700
641 /* Do this after checking for death - no reason sucking up bandwidth if 701 /* Do this after checking for death - no reason sucking up bandwidth if
642 * the data isn't needed. 702 * the data isn't needed.
643 */ 703 */
644 esrv_new_player(op->contr,op->weight+op->carrying); 704 esrv_new_player (op->contr, op->weight + op->carrying);
645 esrv_send_inventory(op, op); 705 esrv_send_inventory (op, op);
646 esrv_add_spells(op->contr, NULL); 706 esrv_add_spells (op->contr, NULL);
647 707
648 CLEAR_FLAG(op, FLAG_FRIENDLY); 708 CLEAR_FLAG (op, FLAG_FRIENDLY);
649 709
650 /* can_use_shield is a new flag. However, the can_use.. seems to largely come 710 /* can_use_shield is a new flag. However, the can_use.. seems to largely come
651 * from the class, and not race. I don't see any way to get the class information 711 * from the class, and not race. I don't see any way to get the class information
652 * to then update this. I don't think this will actually break anything - anyone 712 * to then update this. I don't think this will actually break anything - anyone
653 * that can use armour should be able to use a shield. What this may 'break' 713 * that can use armour should be able to use a shield. What this may 'break'
654 * are features new characters get, eg, if someone starts up with a Q, they 714 * are features new characters get, eg, if someone starts up with a Q, they
655 * should be able to use a shield. However, old Q's won't get that advantage. 715 * should be able to use a shield. However, old Q's won't get that advantage.
656 */ 716 */
657 if (QUERY_FLAG(op, FLAG_USE_ARMOUR)) SET_FLAG(op, FLAG_USE_SHIELD); 717 if (QUERY_FLAG (op, FLAG_USE_ARMOUR))
718 SET_FLAG (op, FLAG_USE_SHIELD);
658 return; 719 return;
659} 720}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines