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

Comparing deliantra/server/server/player.C (file contents):
Revision 1.88 by pippijn, Sat Jan 6 14:42:31 2007 UTC vs.
Revision 1.97 by root, Mon Jan 8 22:32:11 2007 UTC

1/* 1/*
2 CrossFire, A Multiplayer game for X-windows 2 * CrossFire, A Multiplayer game
3 3 *
4 Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team 4 * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
5 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 5 * Copyright (C) 2002 Mark Wedel & Crossfire Development Team
6 Copyright (C) 1992 Frank Tore Johansen 6 * Copyright (C) 1992 Frank Tore Johansen
7 7 *
8 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
9 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
10 the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version. 11 * (at your option) any later version.
12 12 *
13 This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details. 16 * GNU General Public License for more details.
17 17 *
18 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
19 along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 21 *
22 The author can be reached via e-mail to <crossfire@schmorp.de> 22 * The author can be reached via e-mail to <crossfire@schmorp.de>
23*/ 23 */
24 24
25#include <global.h> 25#include <global.h>
26#include <pwd.h> 26#include <pwd.h>
27#include <sproto.h> 27#include <sproto.h>
28#include <sounds.h> 28#include <sounds.h>
32#include <skills.h> 32#include <skills.h>
33 33
34#include <algorithm> 34#include <algorithm>
35#include <functional> 35#include <functional>
36 36
37player * 37playervec players;
38find_player (const char *plname)
39{
40 for_all_players (pl)
41 if (pl->ob && !strcmp (query_name (pl->ob), plname))
42 return pl;
43
44 return 0;
45}
46 38
47void 39void
48display_motd (const object *op) 40display_motd (const object *op)
49{ 41{
50 char buf[MAX_BUF]; 42 char buf[MAX_BUF];
133 125
134 if (*buf == '%') 126 if (*buf == '%')
135 { /* send one news */ 127 { /* send one news */
136 if (size > 0) 128 if (size > 0)
137 draw_ext_info_format (NDI_UNIQUE | NDI_GREEN, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_NEWS, "INFORMATION: %s\n%s", "%s\n%s", subject, news); /*send previously read news */ 129 draw_ext_info_format (NDI_UNIQUE | NDI_GREEN, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_NEWS, "INFORMATION: %s\n%s", "%s\n%s", subject, news); /*send previously read news */
130
138 strcpy (subject, buf + 1); 131 strcpy (subject, buf + 1);
139 strip_endline (subject); 132 strip_endline (subject);
140 size = 0; 133 size = 0;
141 news[0] = '\0'; 134 news[0] = '\0';
142 } 135 }
177 ob->enter_exit (tmp); 170 ob->enter_exit (tmp);
178 171
179 tmp->destroy (); 172 tmp->destroy ();
180} 173}
181 174
175void
176player::activate ()
177{
178 if (active)
179 return;
180
181 players.insert (this);
182 ob->remove ();
183 ob->map = 0;
184 ob->activate_recursive ();
185 CLEAR_FLAG (ob, FLAG_FRIENDLY);
186 add_friendly_object (ob);
187 enter_map ();
188}
189
190void
191player::deactivate ()
192{
193 if (!active)
194 return;
195
196 terminate_all_pets (ob);
197 remove_friendly_object (ob);
198 ob->deactivate_recursive ();
199 ob->remove ();
200 ob->map = 0;
201
202 // for weird reasons, this is often "ob", keeping a circular reference
203 ranges [range_skill] = 0;
204
205 players.erase (this);
206}
207
182// connect the player with a specific client 208// connect the player with a specific client
183// also changed, rationalises, and fixes some incorrect settings 209// also changed, rationalises, and fixes some incorrect settings
184void 210void
185player::connect (client *ns) 211player::connect (client *ns)
186{ 212{
187 this->ns = ns; 213 this->ns = ns;
188 ns->pl = this; 214 ns->pl = this;
189 215
190 next = first_player; 216 run_on = 0;
191 first_player = this; 217 fire_on = 0;
218 ob->container = 0; //TODO: client-specific
192 219
193 ns->update_look = 0; 220 ns->update_look = 0;
194 ns->look_position = 0; 221 ns->look_position = 0;
195 222
196 clear_los (ob); 223 clear_los (ob);
224
225 ns->reset_stats ();
197 226
198 /* make sure he's a player -- needed because of class change. */ 227 /* make sure he's a player -- needed because of class change. */
199 ob->type = PLAYER; // we are paranoid 228 ob->type = PLAYER; // we are paranoid
200 ob->race = ob->arch->clone.race; 229 ob->race = ob->arch->clone.race;
201 230
235 skin = tmp; 264 skin = tmp;
236 265
237 set_dragon_name (ob, abil, skin); 266 set_dragon_name (ob, abil, skin);
238 } 267 }
239 268
240 CLEAR_FLAG (ob, FLAG_FRIENDLY);
241 add_friendly_object (ob);
242
243 LOG (llevInfo, "LOGIN: Player named %s from ip %s\n", &ob->name, ns->host);
244
245 new_draw_info (NDI_UNIQUE, 0, ob, "Welcome Back!"); 269 new_draw_info (NDI_UNIQUE, 0, ob, "Welcome Back!");
246 270
247 esrv_new_player (this, ob->weight + ob->carrying); 271 esrv_new_player (this, ob->weight + ob->carrying);
248 272
249 ob->update_stats (); 273 ob->update_stats ();
250 ns->floorbox_update (); 274 ns->floorbox_update ();
251 275
252 esrv_send_inventory (ob, ob); 276 esrv_send_inventory (ob, ob);
253 esrv_add_spells (this, 0); 277 esrv_add_spells (this, 0);
254 278
255 ob->activate_recursive (); 279 activate ();
256 enter_map ();
257 280
258 send_rules (ob); 281 send_rules (ob);
259 send_news (ob); 282 send_news (ob);
260 display_motd (ob); 283 display_motd (ob);
261 284
264} 287}
265 288
266void 289void
267player::disconnect () 290player::disconnect ()
268{ 291{
269 if (ob)
270 ob->deactivate_recursive ();
271
272 //TODO: don't be so harsh and destroy :)
273 if (ns) 292 if (ns)
274 { 293 {
275 if (enable_save) 294 if (active)
276 {
277 INVOKE_PLAYER (LOGOUT, this, ARG_INT (0)); 295 INVOKE_PLAYER (LOGOUT, this, ARG_INT (0));
278 save (true);
279 }
280 296
281 INVOKE_PLAYER (DISCONNECT, this); 297 INVOKE_PLAYER (DISCONNECT, this);
282 298
283 client *ns = this->ns; 299 ns->reset_stats ();
284 ns->send_packet ("goodbye");
285 ns->flush ();
286 ns->pl = 0; 300 ns->pl = 0;
287 this->ns = 0; 301 this->ns = 0;
288
289 ns->destroy ();
290 destroy ();
291 } 302 }
303
304 ob->container = 0; //TODO: client-specific
305 deactivate ();
292} 306}
293 307
294// the need for this function can be explained 308// the need for this function can be explained
295// by load_object not returning the object 309// by load_object not returning the object
296void 310void
318 unapply = unapply_nochoice; 332 unapply = unapply_nochoice;
319 333
320 savebed_map = first_map_path; /* Init. respawn position */ 334 savebed_map = first_map_path; /* Init. respawn position */
321 335
322 gen_sp_armour = 10; 336 gen_sp_armour = 10;
323 last_speed = -1;
324 shoottype = range_none; 337 shoottype = range_none;
325 bowtype = bow_normal; 338 bowtype = bow_normal;
326 petmode = pet_normal; 339 petmode = pet_normal;
327 listening = 10; 340 listening = 10;
328 usekeys = containers; 341 usekeys = containers;
329 last_weapon_sp = -1;
330 peaceful = 1; /* default peaceful */ 342 peaceful = 1; /* default peaceful */
331 do_los = 1; 343 do_los = 1;
332
333 /* we need to clear these to -1 and not zero - otherwise,
334 * if a player quits and starts a new character, we wont
335 * send new values to the client, as things like exp start
336 * at zero.
337 */
338 for (int i = 0; i < NUM_SKILLS; i++)
339 last_skill_exp[i] = -1;
340
341 for (int i = 0; i < NROFATTACKS; i++)
342 last_resist[i] = -1;
343
344 last_stats.exp = -1;
345 last_weight = (uint32) - 1;
346} 344}
347 345
348void 346void
349player::do_destroy () 347player::do_destroy ()
350{ 348{
351 disconnect (); 349 disconnect ();
352 350
353 save (false);
354 enable_save = false;
355
356 attachable::do_destroy (); 351 attachable::do_destroy ();
357
358 terminate_all_pets (ob);
359
360 if (first_player != this)
361 {
362 player *prev = first_player;
363
364 while (prev && prev->next && prev->next != this)
365 prev = prev->next;
366
367 if (prev->next != this)
368 {
369 LOG (llevError, "Free_player: Can't find previous player.\n");
370 abort ();
371 }
372
373 prev->next = next;
374 }
375 else
376 first_player = next;
377 352
378 if (ob) 353 if (ob)
379 { 354 {
380 ob->destroy_inv (false); 355 ob->destroy_inv (false);
381 ob->destroy (); 356 ob->destroy ();
437 object *op = NULL; 412 object *op = NULL;
438 objectlink *ol; 413 objectlink *ol;
439 unsigned lastdist; 414 unsigned lastdist;
440 rv_vector rv; 415 rv_vector rv;
441 416
442 for (ol = first_friendly_object, lastdist = 1000; ol != NULL; ol = ol->next) 417 for (ol = first_friendly_object, lastdist = 1000; ol; ol = ol->next)
443 { 418 {
444 /* We should not find free objects on this friendly list, but it 419 /* We should not find free objects on this friendly list, but it
445 * does periodically happen. Given that, lets deal with it. 420 * does periodically happen. Given that, lets deal with it.
446 * While unlikely, it is possible the next object on the friendly 421 * While unlikely, it is possible the next object on the friendly
447 * list is also free, so encapsulate this in a while loop. 422 * list is also free, so encapsulate this in a while loop.
451 object *tmp = ol->ob; 426 object *tmp = ol->ob;
452 427
453 /* Can't do much more other than log the fact, because the object 428 /* Can't do much more other than log the fact, because the object
454 * itself will have been cleared. 429 * itself will have been cleared.
455 */ 430 */
456 LOG (llevDebug, "get_nearest_player: Found free/non friendly object on friendly list\n"); 431 LOG (llevDebug, "get_nearest_player: Found free/non friendly object '%s' on friendly list\n",
432 tmp->debug_desc ());
457 ol = ol->next; 433 ol = ol->next;
458 remove_friendly_object (tmp); 434 remove_friendly_object (tmp);
459 if (!ol) 435 if (!ol)
460 return op; 436 return op;
461 } 437 }
919 * to save here. 895 * to save here.
920 */ 896 */
921 sprintf (buf, "%s/%s/%s", settings.localdir, settings.playerdir, &op->name); 897 sprintf (buf, "%s/%s/%s", settings.localdir, settings.playerdir, &op->name);
922 make_path_to_file (buf); 898 make_path_to_file (buf);
923 899
924#ifdef AUTOSAVE
925 op->contr->last_save_tick = pticks;
926#endif
927 start_info (op); 900 start_info (op);
928 CLEAR_FLAG (op, FLAG_WIZ); 901 CLEAR_FLAG (op, FLAG_WIZ);
929 give_initial_items (op, op->randomitems); 902 give_initial_items (op, op->randomitems);
930 link_player_skills (op); 903 link_player_skills (op);
931 esrv_send_inventory (op, op); 904 esrv_send_inventory (op, op);
991 if (op->msg) 964 if (op->msg)
992 new_draw_info (NDI_BLUE, 0, op, op->msg); 965 new_draw_info (NDI_BLUE, 0, op, op->msg);
993 966
994 send_query (op->contr->ns, CS_QUERY_SINGLECHAR, "Press any key for the next race.\nPress `d' to play this race.\n"); 967 send_query (op->contr->ns, CS_QUERY_SINGLECHAR, "Press any key for the next race.\nPress `d' to play this race.\n");
995 return 0; 968 return 0;
996}
997
998int
999key_confirm_quit (object *op, char key)
1000{
1001 if (key != 'y' && key != 'Y' && key != 'q' && key != 'Q')
1002 {
1003 op->contr->ns->state = ST_PLAYING;
1004 new_draw_info (NDI_UNIQUE, 0, op, "OK, continuing to play.");
1005 return 1;
1006 }
1007
1008 INVOKE_PLAYER (LOGOUT, op->contr);
1009 INVOKE_PLAYER (QUIT, op->contr);
1010
1011 op->contr->enable_save = false;
1012 delete_character (op->name);
1013
1014 terminate_all_pets (op);
1015 op->remove ();
1016 op->direction = 0;
1017 new_draw_info_format (NDI_UNIQUE | NDI_ALL, 5, NULL, "%s quits the game.", &op->name);
1018
1019 strcpy (op->contr->killer, "quit");
1020 check_score (op);
1021 op->contr->party = 0;
1022 op->contr->own_title[0] = '\0';
1023 op->contr->destroy ();
1024
1025 return 1;
1026} 969}
1027 970
1028void 971void
1029flee_player (object *op) 972flee_player (object *op)
1030{ 973{
1909 { 1852 {
1910 if (op->type == PLAYER) 1853 if (op->type == PLAYER)
1911 new_draw_info (NDI_UNIQUE, 0, op, "You have no applicable skill to use."); 1854 new_draw_info (NDI_UNIQUE, 0, op, "You have no applicable skill to use.");
1912 return; 1855 return;
1913 } 1856 }
1857
1914 (void) do_skill (op, op, op->chosen_skill, dir, NULL); 1858 do_skill (op, op, op->chosen_skill, dir, NULL);
1915 return; 1859 return;
1916 case range_builder: 1860 case range_builder:
1917 apply_map_builder (op, dir); 1861 apply_map_builder (op, dir);
1918 return; 1862 return;
1919 default: 1863 default:
2775 2719
2776 command_kill_pets (op, 0); 2720 command_kill_pets (op, 0);
2777 2721
2778 if (op->stats.food < 0) 2722 if (op->stats.food < 0)
2779 { 2723 {
2780 if (op->contr->explore)
2781 {
2782 new_draw_info (NDI_UNIQUE, 0, op, "You would have starved, but you are");
2783 new_draw_info (NDI_UNIQUE, 0, op, "in explore mode, so...");
2784 op->stats.food = 999;
2785 return;
2786 }
2787 sprintf (buf, "%s starved to death.", &op->name); 2724 sprintf (buf, "%s starved to death.", &op->name);
2788 strcpy (op->contr->killer, "starvation"); 2725 strcpy (op->contr->killer, "starvation");
2789 } 2726 }
2790 else 2727 else
2791 {
2792 if (op->contr->explore)
2793 {
2794 new_draw_info (NDI_UNIQUE, 0, op, "You would have died, but you are");
2795 new_draw_info (NDI_UNIQUE, 0, op, "in explore mode, so...");
2796 op->stats.hp = op->stats.maxhp;
2797 return;
2798 }
2799 sprintf (buf, "%s died.", &op->name); 2728 sprintf (buf, "%s died.", &op->name);
2800 }
2801 2729
2802 play_sound_player_only (op->contr, SOUND_PLAYER_DIES, 0, 0); 2730 play_sound_player_only (op->contr, SOUND_PLAYER_DIES, 0, 0);
2803 2731
2804 /* save the map location for corpse, gravestone */ 2732 /* save the map location for corpse, gravestone */
2805 x = op->x; 2733 x = op->x;
2998 /* */ 2926 /* */
2999 /****************************************/ 2927 /****************************************/
3000 2928
3001 enter_player_savebed (op); 2929 enter_player_savebed (op);
3002 2930
3003 /* Save the player before inserting the force to reduce
3004 * chance of abuse.
3005 */
3006 op->contr->braced = 0; 2931 op->contr->braced = 0;
3007 op->contr->save ();
3008 2932
3009 /* it is possible that the player has blown something up 2933 /* it is possible that the player has blown something up
3010 * at his savebed location, and that can have long lasting 2934 * at his savebed location, and that can have long lasting
3011 * spell effects. So first see if there is a spell effect 2935 * spell effects. So first see if there is a spell effect
3012 * on the space that might harm the player. 2936 * on the space that might harm the player.
3601 * not readied. 3525 * not readied.
3602 */ 3526 */
3603void 3527void
3604player_unready_range_ob (player *pl, object *ob) 3528player_unready_range_ob (player *pl, object *ob)
3605{ 3529{
3606 rangetype i;
3607
3608 for (i = (rangetype) 0; i < range_size; i = (rangetype) ((int) i + 1)) 3530 for (rangetype i = (rangetype) 0; i < range_size; i = (rangetype) ((int) i + 1))
3609 {
3610 if (pl->ranges[i] == ob) 3531 if (pl->ranges[i] == ob)
3611 { 3532 {
3612 pl->ranges[i] = NULL; 3533 pl->ranges[i] = 0;
3613 if (pl->shoottype == i) 3534 if (pl->shoottype == i)
3614 {
3615 pl->shoottype = range_none; 3535 pl->shoottype = range_none;
3616 }
3617 } 3536 }
3618 }
3619} 3537}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines