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.31 by pippijn, Mon Dec 11 19:46:47 2006 UTC vs.
Revision 1.48 by root, Tue Dec 19 05:41:22 2006 UTC

21 The author can be reached via e-mail to <crossfire@schmorp.de> 21 The author can be reached via e-mail to <crossfire@schmorp.de>
22*/ 22*/
23 23
24#include <global.h> 24#include <global.h>
25#include <pwd.h> 25#include <pwd.h>
26#ifndef __CEXTRACT__
27# include <sproto.h> 26#include <sproto.h>
28#endif
29#include <sounds.h> 27#include <sounds.h>
30#include <living.h> 28#include <living.h>
31#include <object.h> 29#include <object.h>
32#include <spells.h> 30#include <spells.h>
33#include <skills.h> 31#include <skills.h>
34#include <newclient.h>
35 32
36#ifdef COZY_SERVER 33#ifdef COZY_SERVER
37extern int same_party (partylist *a, partylist *b); 34extern int same_party (partylist *a, partylist *b);
38#endif 35#endif
39 36
85 int comp; 82 int comp;
86 int size; 83 int size;
87 84
88 sprintf (buf, "%s/%s", settings.confdir, settings.motd); 85 sprintf (buf, "%s/%s", settings.confdir, settings.motd);
89 if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL) 86 if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL)
90 {
91 return; 87 return;
92 } 88
93 motd[0] = '\0'; 89 motd[0] = '\0';
94 size = 0; 90 size = 0;
91
95 while (fgets (buf, MAX_BUF, fp) != NULL) 92 while (fgets (buf, MAX_BUF, fp) != NULL)
96 { 93 {
97 if (*buf == '#') 94 if (*buf == '#')
98 continue; 95 continue;
96
99 strncat (motd + size, buf, HUGE_BUF - size); 97 strncat (motd + size, buf, HUGE_BUF - size);
100 size += strlen (buf); 98 size += strlen (buf);
101 } 99 }
100
102 draw_ext_info (NDI_UNIQUE | NDI_GREEN, 0, op, MSG_TYPE_MOTD, MSG_SUBTYPE_NONE, motd, NULL); 101 draw_ext_info (NDI_UNIQUE | NDI_GREEN, 0, op, MSG_TYPE_MOTD, MSG_SUBTYPE_NONE, motd, NULL);
103 close_and_delete (fp, comp); 102 close_and_delete (fp, comp);
104} 103}
105 104
106void 105void
112 int comp; 111 int comp;
113 int size; 112 int size;
114 113
115 sprintf (buf, "%s/%s", settings.confdir, settings.rules); 114 sprintf (buf, "%s/%s", settings.confdir, settings.rules);
116 if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL) 115 if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL)
117 {
118 return; 116 return;
119 } 117
120 rules[0] = '\0'; 118 rules[0] = '\0';
121 size = 0; 119 size = 0;
120
122 while (fgets (buf, MAX_BUF, fp) != NULL) 121 while (fgets (buf, MAX_BUF, fp) != NULL)
123 { 122 {
124 if (*buf == '#') 123 if (*buf == '#')
125 continue; 124 continue;
125
126 if (size + strlen (buf) >= HUGE_BUF) 126 if (size + strlen (buf) >= HUGE_BUF)
127 { 127 {
128 LOG (llevDebug, "Warning, rules size is > %d bytes.\n", HUGE_BUF); 128 LOG (llevDebug, "Warning, rules size is > %d bytes.\n", HUGE_BUF);
129 break; 129 break;
130 } 130 }
131
131 strncat (rules + size, buf, HUGE_BUF - size); 132 strncat (rules + size, buf, HUGE_BUF - size);
132 size += strlen (buf); 133 size += strlen (buf);
133 } 134 }
135
134 draw_ext_info (NDI_UNIQUE | NDI_GREEN, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_RULES, rules, NULL); 136 draw_ext_info (NDI_UNIQUE | NDI_GREEN, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_RULES, rules, NULL);
135 close_and_delete (fp, comp); 137 close_and_delete (fp, comp);
136} 138}
137 139
138void 140void
146 int size; 148 int size;
147 149
148 sprintf (buf, "%s/%s", settings.confdir, settings.news); 150 sprintf (buf, "%s/%s", settings.confdir, settings.news);
149 if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL) 151 if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL)
150 return; 152 return;
153
151 news[0] = '\0'; 154 news[0] = '\0';
152 subject[0] = '\0'; 155 subject[0] = '\0';
153 size = 0; 156 size = 0;
157
154 while (fgets (buf, MAX_BUF, fp) != NULL) 158 while (fgets (buf, MAX_BUF, fp) != NULL)
155 { 159 {
156 if (*buf == '#') 160 if (*buf == '#')
157 continue; 161 continue;
162
158 if (*buf == '%') 163 if (*buf == '%')
159 { /* send one news */ 164 { /* send one news */
160 if (size > 0) 165 if (size > 0)
161 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 */ 166 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 */
162 strcpy (subject, buf + 1); 167 strcpy (subject, buf + 1);
189 return 0; 194 return 0;
190 195
191 for (; *cp != '\0'; cp++) 196 for (; *cp != '\0'; cp++)
192 if (!((*cp >= 'a' && *cp <= 'z') || (*cp >= 'A' && *cp <= 'Z')) && *cp != '-' && *cp != '_') 197 if (!((*cp >= 'a' && *cp <= 'z') || (*cp >= 'A' && *cp <= 'Z')) && *cp != '-' && *cp != '_')
193 return 0; 198 return 0;
199
194 return 1; 200 return 1;
195} 201}
196 202
197/* This no longer sets the player map. Also, it now updates 203/* This no longer sets the player map. Also, it now updates
198 * all the pointers so the caller doesn't need to do that. 204 * all the pointers so the caller doesn't need to do that.
206 * the one that is passed. 212 * the one that is passed.
207 */ 213 */
208static player * 214static player *
209get_player (player *p) 215get_player (player *p)
210{ 216{
211 object *op = arch_to_object (get_player_archetype (NULL)); 217 object *op = arch_to_object (get_player_archetype (0));
212 int i; 218 int i;
213
214 if (!p)
215 {
216 p = new player;
217
218 /* This adds the player in the linked list. There is extra
219 * complexity here because we want to add the new player at the
220 * end of the list - there is in fact no compelling reason that
221 * that needs to be done except for things like output of
222 * 'who'.
223 */
224 player *tmp = first_player;
225
226 while (tmp != NULL && tmp->next != NULL)
227 tmp = tmp->next;
228 if (tmp != NULL)
229 tmp->next = p;
230 else
231 first_player = p;
232
233 p->next = NULL;
234 }
235 219
236 /* Clears basically the entire player structure except 220 /* Clears basically the entire player structure except
237 * for next and socket. 221 * for next and socket.
238 */ 222 */
239 p->clear (); 223 p->clear ();
258 op->speed_left = 0.5; 242 op->speed_left = 0.5;
259 op->speed = 1.0; 243 op->speed = 1.0;
260 op->direction = 5; /* So player faces south */ 244 op->direction = 5; /* So player faces south */
261 op->stats.wc = 2; 245 op->stats.wc = 2;
262 op->run_away = 25; /* Then we panick... */ 246 op->run_away = 25; /* Then we panick... */
247
248 {
249 int oldmon = p->socket->monitor_spells; // what a hack
263 p->socket.monitor_spells = 0; /* Needed because esrv_update_spells( ) gets called by roll_stats */ 250 p->socket->monitor_spells = 0; /* Needed because esrv_update_spells( ) gets called by roll_stats */
264
265 roll_stats (op); 251 roll_stats (op);
252 p->socket->monitor_spells = oldmon;
253 }
266 p->state = ST_ROLL_STAT; 254 p->state = ST_ROLL_STAT;
267 clear_los (op); 255 clear_los (op);
268 256
269 p->gen_sp_armour = 10; 257 p->gen_sp_armour = 10;
270 p->last_speed = -1; 258 p->last_speed = -1;
275 p->usekeys = containers; 263 p->usekeys = containers;
276 p->last_weapon_sp = -1; 264 p->last_weapon_sp = -1;
277 p->peaceful = 1; /* default peaceful */ 265 p->peaceful = 1; /* default peaceful */
278 p->do_los = 1; 266 p->do_los = 1;
279 p->explore = 0; 267 p->explore = 0;
280 p->no_shout = 0; /* default can shout */
281 268
282 assign (p->title, op->arch->clone.name); 269 assign (p->title, op->arch->clone.name);
283 op->race = op->arch->clone.race; 270 op->race = op->arch->clone.race;
284 271
285 CLEAR_FLAG (op, FLAG_READY_SKILL); 272 CLEAR_FLAG (op, FLAG_READY_SKILL);
292 for (i = 0; i < NUM_SKILLS; i++) 279 for (i = 0; i < NUM_SKILLS; i++)
293 { 280 {
294 p->last_skill_exp[i] = -1; 281 p->last_skill_exp[i] = -1;
295 p->last_skill_ob[i] = NULL; 282 p->last_skill_ob[i] = NULL;
296 } 283 }
284
297 for (i = 0; i < NROFATTACKS; i++) 285 for (i = 0; i < NROFATTACKS; i++)
298 {
299 p->last_resist[i] = -1; 286 p->last_resist[i] = -1;
300 } 287
301 p->last_stats.exp = -1; 288 p->last_stats.exp = -1;
302 p->last_weight = (uint32) - 1; 289 p->last_weight = (uint32) - 1;
303 290
304 p->socket.update_look = 0; 291 p->socket->update_look = 0;
305 p->socket.look_position = 0; 292 p->socket->look_position = 0;
293
306 return p; 294 return p;
307} 295}
308 296
309/* This loads the first map an puts the player on it. */ 297/* This loads the first map an puts the player on it. */
310static void 298static void
311set_first_map (object *op) 299set_first_map (object *op)
312{ 300{
313 strcpy (op->contr->maplevel, first_map_path); 301 strcpy (op->contr->maplevel, first_map_path);
314 op->x = -1; 302 op->x = -1;
315 op->y = -1; 303 op->y = -1;
316 enter_exit (op, NULL); 304 enter_exit (op, 0);
317} 305}
318 306
319/* Tries to add player on the connection passwd in ns. 307/* Tries to add player on the connection passwd in ns.
320 * All we can really get in this is some settings like host and display 308 * All we can really get in this is some settings like host and display
321 * mode. 309 * mode.
322 */ 310 */
323 311
324int 312int
325add_player (NewSocket * ns) 313add_player (client *ns)
326{ 314{
327 player *p; 315 player *p = new player;
328 316
329 p = get_player (NULL);
330 p->socket = *ns; 317 p->socket = ns;
331 p->socket.faces_sent = (uint8 *) malloc (p->socket.faces_sent_len * sizeof (*p->socket.faces_sent)); 318 ns->pl = p;
332 319
333 if (p->socket.faces_sent == NULL) 320 p->next = first_player;
334 fatal (OUT_OF_MEMORY); 321 first_player = p;
335 322
336 memcpy (p->socket.faces_sent, ns->faces_sent, p->socket.faces_sent_len * sizeof (*p->socket.faces_sent)); 323 p = get_player (p);
337 /* Needed because the socket we just copied over needs to be cleared. 324
338 * Note that this can result in a client reset if there is partial data
339 * on the uncoming socket.
340 */
341 p->socket.inbuf.len = 0;
342 set_first_map (p->ob); 325 set_first_map (p->ob);
343 326
344 CLEAR_FLAG (p->ob, FLAG_FRIENDLY); 327 CLEAR_FLAG (p->ob, FLAG_FRIENDLY);
345 add_friendly_object (p->ob); 328 add_friendly_object (p->ob);
346 send_rules (p->ob); 329 send_rules (p->ob);
365 { 348 {
366 if (at == NULL || at->next == NULL) 349 if (at == NULL || at->next == NULL)
367 at = first_archetype; 350 at = first_archetype;
368 else 351 else
369 at = at->next; 352 at = at->next;
353
370 if (at->clone.type == PLAYER) 354 if (at->clone.type == PLAYER)
371 return at; 355 return at;
356
372 if (at == start) 357 if (at == start)
373 { 358 {
374 LOG (llevError, "No Player archetypes\n"); 359 LOG (llevError, "No Player archetypes\n");
375 exit (-1); 360 exit (-1);
376 } 361 }
377 } 362 }
378} 363}
379
380 364
381object * 365object *
382get_nearest_player (object *mon) 366get_nearest_player (object *mon)
383{ 367{
384 object *op = NULL; 368 object *op = NULL;
644 (op->type == ARMOUR || op->type == BOOTS || 628 (op->type == ARMOUR || op->type == BOOTS ||
645 op->type == CLOAK || op->type == HELMET || 629 op->type == CLOAK || op->type == HELMET ||
646 op->type == SHIELD || op->type == GLOVES || 630 op->type == SHIELD || op->type == GLOVES ||
647 op->type == BRACERS || op->type == GIRDLE)) || (!QUERY_FLAG (pl, FLAG_USE_WEAPON) && op->type == WEAPON)) 631 op->type == BRACERS || op->type == GIRDLE)) || (!QUERY_FLAG (pl, FLAG_USE_WEAPON) && op->type == WEAPON))
648 { 632 {
649 remove_ob (op); 633 op->destroy ();
650 free_object (op);
651 continue; 634 continue;
652 } 635 }
653 } 636 }
654 637
655 /* This really needs to be better - we should really give 638 /* This really needs to be better - we should really give
666 if (tmp->type == op->type && tmp->name == op->name) 649 if (tmp->type == op->type && tmp->name == op->name)
667 break; 650 break;
668 651
669 if (tmp) 652 if (tmp)
670 { 653 {
671 remove_ob (op); 654 op->destroy ();
672 free_object (op);
673 LOG (llevError, "give_initial_items: Removing duplicate object %s\n", &tmp->name); 655 LOG (llevError, "give_initial_items: Removing duplicate object %s\n", &tmp->name);
674 continue; 656 continue;
675 } 657 }
658
676 if (op->nrof > 1) 659 if (op->nrof > 1)
677 op->nrof = 1; 660 op->nrof = 1;
678 } 661 }
679 662
680 if (op->type == SPELLBOOK && op->inv) 663 if (op->type == SPELLBOOK && op->inv)
692 CLEAR_FLAG (op, FLAG_CURSED); 675 CLEAR_FLAG (op, FLAG_CURSED);
693 CLEAR_FLAG (op, FLAG_DAMNED); 676 CLEAR_FLAG (op, FLAG_DAMNED);
694 } 677 }
695 if (op->type == SPELL) 678 if (op->type == SPELL)
696 { 679 {
697 remove_ob (op); 680 op->destroy ();
698 free_object (op);
699 continue; 681 continue;
700 } 682 }
701 else if (op->type == SKILL) 683 else if (op->type == SKILL)
702 { 684 {
703 SET_FLAG (op, FLAG_CAN_USE_SKILL); 685 SET_FLAG (op, FLAG_CAN_USE_SKILL);
716void 698void
717get_name (object *op) 699get_name (object *op)
718{ 700{
719 op->contr->write_buf[0] = '\0'; 701 op->contr->write_buf[0] = '\0';
720 op->contr->state = ST_GET_NAME; 702 op->contr->state = ST_GET_NAME;
721 send_query (&op->contr->socket, 0, "What is your name?\n:"); 703 send_query (op->contr->socket, 0, "What is your name?\n:");
722} 704}
723 705
724void 706void
725get_password (object *op) 707get_password (object *op)
726{ 708{
727 op->contr->write_buf[0] = '\0'; 709 op->contr->write_buf[0] = '\0';
728 op->contr->state = ST_GET_PASSWORD; 710 op->contr->state = ST_GET_PASSWORD;
729 send_query (&op->contr->socket, CS_QUERY_HIDEINPUT, "What is your password?\n:"); 711 send_query (op->contr->socket, CS_QUERY_HIDEINPUT, "What is your password?\n:");
730} 712}
731 713
732void 714void
733play_again (object *op) 715play_again (object *op)
734{ 716{
735 op->contr->state = ST_PLAY_AGAIN; 717 op->contr->state = ST_PLAY_AGAIN;
736 op->chosen_skill = NULL; 718 op->chosen_skill = NULL;
737 send_query (&op->contr->socket, CS_QUERY_SINGLECHAR, "Do you want to play again (a/q)?"); 719 send_query (op->contr->socket, CS_QUERY_SINGLECHAR, "Do you want to play again (a/q)?");
738 /* a bit of a hack, but there are various places early in th 720 /* a bit of a hack, but there are various places early in th
739 * player creation process that a user can quit (eg, roll 721 * player creation process that a user can quit (eg, roll
740 * stats) that isn't removing the player. Taking a quick 722 * stats) that isn't removing the player. Taking a quick
741 * look, there are many places that call play_again without 723 * look, there are many places that call play_again without
742 * removing the player - it probably makes more sense 724 * removing the player - it probably makes more sense
743 * to leave it to play_again to remove the object in all 725 * to leave it to play_again to remove the object in all
744 * cases. 726 * cases.
745 */ 727 */
746 if (!QUERY_FLAG (op, FLAG_REMOVED)) 728 if (!QUERY_FLAG (op, FLAG_REMOVED))
747 remove_ob (op); 729 op->remove ();
748 /* Need to set this to null - otherwise, it could point to garbage, 730 /* Need to set this to null - otherwise, it could point to garbage,
749 * and draw() doesn't check to see if the player is removed, only if 731 * and draw() doesn't check to see if the player is removed, only if
750 * the map is null or not swapped out. 732 * the map is null or not swapped out.
751 */ 733 */
752 op->map = NULL; 734 op->map = NULL;
791confirm_password (object *op) 773confirm_password (object *op)
792{ 774{
793 775
794 op->contr->write_buf[0] = '\0'; 776 op->contr->write_buf[0] = '\0';
795 op->contr->state = ST_CONFIRM_PASSWORD; 777 op->contr->state = ST_CONFIRM_PASSWORD;
796 send_query (&op->contr->socket, CS_QUERY_HIDEINPUT, "Please type your password again.\n:"); 778 send_query (op->contr->socket, CS_QUERY_HIDEINPUT, "Please type your password again.\n:");
797} 779}
798 780
799void 781void
800get_party_password (object *op, partylist *party) 782get_party_password (object *op, partylist *party)
801{ 783{
805 return; 787 return;
806 } 788 }
807 op->contr->write_buf[0] = '\0'; 789 op->contr->write_buf[0] = '\0';
808 op->contr->state = ST_GET_PARTY_PASSWORD; 790 op->contr->state = ST_GET_PARTY_PASSWORD;
809 op->contr->party_to_join = party; 791 op->contr->party_to_join = party;
810 send_query (&op->contr->socket, CS_QUERY_HIDEINPUT, "What is the password?\n:"); 792 send_query (op->contr->socket, CS_QUERY_HIDEINPUT, "What is the password?\n:");
811} 793}
812 794
813 795
814/* This rolls four 1-6 rolls and sums the best 3 of the 4. */ 796/* This rolls four 1-6 rolls and sums the best 3 of the 4. */
815int 797int
912 894
913void 895void
914Roll_Again (object *op) 896Roll_Again (object *op)
915{ 897{
916 esrv_new_player (op->contr, 0); 898 esrv_new_player (op->contr, 0);
917 send_query (&op->contr->socket, CS_QUERY_SINGLECHAR, 899 send_query (op->contr->socket, CS_QUERY_SINGLECHAR,
918 "[y] to roll new stats [n] to use stats\n[1-7] [1-7] to swap stats.\nRoll again (y/n/1-7)? "); 900 "[y] to roll new stats [n] to use stats\n[1-7] [1-7] to swap stats.\nRoll again (y/n/1-7)? ");
919} 901}
920 902
921void 903void
922Swap_Stat (object *op, int Swap_Second) 904Swap_Stat (object *op, int Swap_Second)
989 new_draw_info (NDI_UNIQUE, 0, op, buf); 971 new_draw_info (NDI_UNIQUE, 0, op, buf);
990 } 972 }
991 else 973 else
992 Swap_Stat (op, stat_trans[keynum]); 974 Swap_Stat (op, stat_trans[keynum]);
993 975
994 send_query (&op->contr->socket, CS_QUERY_SINGLECHAR, ""); 976 send_query (op->contr->socket, CS_QUERY_SINGLECHAR, "");
995 return 1; 977 return 1;
996 } 978 }
997 switch (key) 979 switch (key)
998 { 980 {
999 case 'n': 981 case 'n':
1013 enter_exit (op, NULL); 995 enter_exit (op, NULL);
1014#endif 996#endif
1015 SET_ANIMATION (op, 2); /* So player faces south */ 997 SET_ANIMATION (op, 2); /* So player faces south */
1016 /* Enter exit adds a player otherwise */ 998 /* Enter exit adds a player otherwise */
1017 add_statbonus (op); 999 add_statbonus (op);
1018 send_query (&op->contr->socket, CS_QUERY_SINGLECHAR, 1000 send_query (op->contr->socket, CS_QUERY_SINGLECHAR,
1019 "Now choose a character.\nPress any key to change outlook.\nPress `d' when you're pleased.\n"); 1001 "Now choose a character.\nPress any key to change outlook.\nPress `d' when you're pleased.\n");
1020 op->contr->state = ST_CHANGE_CLASS; 1002 op->contr->state = ST_CHANGE_CLASS;
1021 if (op->msg) 1003 if (op->msg)
1022 new_draw_info (NDI_BLUE, 0, op, op->msg); 1004 new_draw_info (NDI_BLUE, 0, op, op->msg);
1023 return 0; 1005 return 0;
1024 } 1006 }
1025 case 'y': 1007 case 'y':
1026 case 'Y': 1008 case 'Y':
1027 roll_stats (op); 1009 roll_stats (op);
1028 send_query (&op->contr->socket, CS_QUERY_SINGLECHAR, ""); 1010 send_query (op->contr->socket, CS_QUERY_SINGLECHAR, "");
1029 return 1; 1011 return 1;
1030 1012
1031 case 'q': 1013 case 'q':
1032 case 'Q': 1014 case 'Q':
1033 play_again (op); 1015 play_again (op);
1034 return 1; 1016 return 1;
1035 1017
1036 default: 1018 default:
1037 send_query (&op->contr->socket, CS_QUERY_SINGLECHAR, "Yes, No, Quit or 1-6. Roll again?"); 1019 send_query (op->contr->socket, CS_QUERY_SINGLECHAR, "Yes, No, Quit or 1-6. Roll again?");
1038 return 0; 1020 return 0;
1039 } 1021 }
1040 return 0; 1022 return 0;
1041} 1023}
1042 1024
1052{ 1034{
1053 int tmp_loop; 1035 int tmp_loop;
1054 1036
1055 if (key == 'q' || key == 'Q') 1037 if (key == 'q' || key == 'Q')
1056 { 1038 {
1057 remove_ob (op); 1039 op->remove ();
1058 play_again (op); 1040 play_again (op);
1059 return 0; 1041 return 0;
1060 } 1042 }
1061 if (key == 'd' || key == 'D') 1043 if (key == 'd' || key == 'D')
1062 { 1044 {
1063 char buf[MAX_BUF]; 1045 char buf[MAX_BUF];
1064 1046
1065 /* this must before then initial items are given */ 1047 /* this must before then initial items are given */
1066 esrv_new_player (op->contr, op->weight + op->carrying); 1048 esrv_new_player (op->contr, op->weight + op->carrying);
1049
1067 create_treasure (find_treasurelist ("starting_wealth"), op, 0, 0, 0); 1050 treasurelist *tl = find_treasurelist ("starting_wealth");
1051 if (tl)
1052 create_treasure (tl, op, 0, 0, 0);
1068 1053
1069 INVOKE_PLAYER (BIRTH, op->contr); 1054 INVOKE_PLAYER (BIRTH, op->contr);
1070 INVOKE_PLAYER (LOGIN, op->contr); 1055 INVOKE_PLAYER (LOGIN, op->contr);
1071 1056
1072 op->contr->state = ST_PLAYING; 1057 op->contr->state = ST_PLAYING;
1097 { 1082 {
1098 object *tmp; 1083 object *tmp;
1099 char mapname[MAX_BUF]; 1084 char mapname[MAX_BUF];
1100 1085
1101 snprintf (mapname, MAX_BUF - 1, "%s/%s", first_map_ext_path, &op->arch->name); 1086 snprintf (mapname, MAX_BUF - 1, "%s/%s", first_map_ext_path, &op->arch->name);
1102 tmp = get_object (); 1087 tmp = object::create ();
1103 EXIT_PATH (tmp) = mapname; 1088 EXIT_PATH (tmp) = mapname;
1104 EXIT_X (tmp) = op->x; 1089 EXIT_X (tmp) = op->x;
1105 EXIT_Y (tmp) = op->y; 1090 EXIT_Y (tmp) = op->y;
1106 enter_exit (op, tmp); /* we don't really care if it succeeded; 1091 enter_exit (op, tmp); /* we don't really care if it succeeded;
1107 * if the map isn't there, then stay on the 1092 * if the map isn't there, then stay on the
1108 * default initial map */ 1093 * default initial map */
1109 free_object (tmp); 1094 tmp->destroy ();
1110 } 1095 }
1111 else 1096 else
1112 {
1113 LOG (llevDebug, "first_map_ext_path not set\n"); 1097 LOG (llevDebug, "first_map_ext_path not set\n");
1114 } 1098
1115 return 0; 1099 return 0;
1116 } 1100 }
1117 1101
1118 /* Following actually changes the race - this is the default command 1102 /* Following actually changes the race - this is the default command
1119 * if we don't match with one of the options above. 1103 * if we don't match with one of the options above.
1124 { 1108 {
1125 shstr name = op->name; 1109 shstr name = op->name;
1126 int x = op->x, y = op->y; 1110 int x = op->x, y = op->y;
1127 1111
1128 remove_statbonus (op); 1112 remove_statbonus (op);
1129 remove_ob (op); 1113 op->remove ();
1130 op->arch = get_player_archetype (op->arch); 1114 op->arch = get_player_archetype (op->arch);
1131 copy_object (&op->arch->clone, op); 1115 op->arch->clone.copy_to (op);
1132 op->instantiate (); 1116 op->instantiate ();
1133 op->stats = op->contr->orig_stats; 1117 op->stats = op->contr->orig_stats;
1134 op->name = op->name_pl = name; 1118 op->name = op->name_pl = name;
1135 op->x = x; 1119 op->x = x;
1136 op->y = y; 1120 op->y = y;
1149 op->stats.grace = 0; 1133 op->stats.grace = 0;
1150 1134
1151 if (op->msg) 1135 if (op->msg)
1152 new_draw_info (NDI_BLUE, 0, op, op->msg); 1136 new_draw_info (NDI_BLUE, 0, op, op->msg);
1153 1137
1154 send_query (&op->contr->socket, CS_QUERY_SINGLECHAR, "Press any key for the next race.\nPress `d' to play this race.\n"); 1138 send_query (op->contr->socket, CS_QUERY_SINGLECHAR, "Press any key for the next race.\nPress `d' to play this race.\n");
1155 return 0; 1139 return 0;
1156} 1140}
1157 1141
1158int 1142int
1159key_confirm_quit (object *op, char key) 1143key_confirm_quit (object *op, char key)
1816 if (!dir) 1800 if (!dir)
1817 { 1801 {
1818 new_draw_info (NDI_UNIQUE, 0, op, "You can't shoot yourself!"); 1802 new_draw_info (NDI_UNIQUE, 0, op, "You can't shoot yourself!");
1819 return 0; 1803 return 0;
1820 } 1804 }
1805
1821 if (op->type == PLAYER) 1806 if (op->type == PLAYER)
1822 bow = op->contr->ranges[range_bow]; 1807 bow = op->contr->ranges[range_bow];
1823 else 1808 else
1824 { 1809 {
1825 for (bow = op->inv; bow; bow = bow->below) 1810 for (bow = op->inv; bow; bow = bow->below)
1833 { 1818 {
1834 LOG (llevError, "Range: bow without activated bow (%s).\n", &op->name); 1819 LOG (llevError, "Range: bow without activated bow (%s).\n", &op->name);
1835 return 0; 1820 return 0;
1836 } 1821 }
1837 } 1822 }
1823
1838 if (!bow->race || !bow->skill) 1824 if (!bow->race || !bow->skill)
1839 { 1825 {
1840 new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s is broken.", &bow->name); 1826 new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s is broken.", &bow->name);
1841 return 0; 1827 return 0;
1842 } 1828 }
1844 bowspeed = bow->stats.sp + dex_bonus[op->stats.Dex]; 1830 bowspeed = bow->stats.sp + dex_bonus[op->stats.Dex];
1845 1831
1846 /* penalize ROF for bestarrow */ 1832 /* penalize ROF for bestarrow */
1847 if (op->type == PLAYER && op->contr->bowtype == bow_bestarrow) 1833 if (op->type == PLAYER && op->contr->bowtype == bow_bestarrow)
1848 bowspeed -= dex_bonus[op->stats.Dex] + 5; 1834 bowspeed -= dex_bonus[op->stats.Dex] + 5;
1835
1849 if (bowspeed < 1) 1836 if (bowspeed < 1)
1850 bowspeed = 1; 1837 bowspeed = 1;
1851 1838
1852 if (arrow == NULL) 1839 if (arrow == NULL)
1853 { 1840 {
1859 else 1846 else
1860 CLEAR_FLAG (op, FLAG_READY_BOW); 1847 CLEAR_FLAG (op, FLAG_READY_BOW);
1861 return 0; 1848 return 0;
1862 } 1849 }
1863 } 1850 }
1851
1864 mflags = get_map_flags (op->map, &m, sx, sy, &sx, &sy); 1852 mflags = get_map_flags (op->map, &m, sx, sy, &sx, &sy);
1865 if (mflags & P_OUT_OF_MAP) 1853 if (mflags & P_OUT_OF_MAP)
1866 {
1867 return 0; 1854 return 0;
1868 } 1855
1869 if (GET_MAP_MOVE_BLOCK (m, sx, sy) == MOVE_FLY_LOW) 1856 if (GET_MAP_MOVE_BLOCK (m, sx, sy) == MOVE_FLY_LOW)
1870 { 1857 {
1871 new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way."); 1858 new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way.");
1872 return 0; 1859 return 0;
1873 } 1860 }
1874 1861
1875 /* this should not happen, but sometimes does */ 1862 /* this should not happen, but sometimes does */
1876 if (arrow->nrof == 0) 1863 if (arrow->nrof == 0)
1877 { 1864 {
1878 remove_ob (arrow); 1865 arrow->destroy ();
1879 free_object (arrow);
1880 return 0; 1866 return 0;
1881 } 1867 }
1882 1868
1883 left = arrow; /* these are arrows left to the player */ 1869 left = arrow; /* these are arrows left to the player */
1884 arrow = get_split_ob (arrow, 1); 1870 arrow = get_split_ob (arrow, 1);
1885 if (arrow == NULL) 1871 if (!arrow)
1886 { 1872 {
1887 new_draw_info_format (NDI_UNIQUE, 0, op, "You have no %s left.", &bow->race); 1873 new_draw_info_format (NDI_UNIQUE, 0, op, "You have no %s left.", &bow->race);
1888 return 0; 1874 return 0;
1889 } 1875 }
1890 set_owner (arrow, op); 1876
1877 arrow->set_owner (op);
1891 arrow->skill = bow->skill; 1878 arrow->skill = bow->skill;
1892 1879
1893 arrow->direction = dir; 1880 arrow->direction = dir;
1894 arrow->x = sx; 1881 arrow->x = sx;
1895 arrow->y = sy; 1882 arrow->y = sy;
1903 SET_ANIMATION (arrow, arrow->direction); 1890 SET_ANIMATION (arrow, arrow->direction);
1904 arrow->stats.sp = arrow->stats.wc; /* save original wc and dam */ 1891 arrow->stats.sp = arrow->stats.wc; /* save original wc and dam */
1905 arrow->stats.hp = arrow->stats.dam; 1892 arrow->stats.hp = arrow->stats.dam;
1906 arrow->stats.grace = arrow->attacktype; 1893 arrow->stats.grace = arrow->attacktype;
1907 if (arrow->slaying != NULL) 1894 if (arrow->slaying != NULL)
1908 arrow->spellarg = strdup_local (arrow->slaying); 1895 arrow->spellarg = strdup (arrow->slaying);
1909 1896
1910 /* Note that this was different for monsters - they got their level 1897 /* Note that this was different for monsters - they got their level
1911 * added to the damage. I think the strength bonus is more proper. 1898 * added to the damage. I think the strength bonus is more proper.
1912 */ 1899 */
1913 1900
1937 } 1924 }
1938 1925
1939 if (arrow->attacktype == AT_PHYSICAL) 1926 if (arrow->attacktype == AT_PHYSICAL)
1940 arrow->attacktype |= bow->attacktype; 1927 arrow->attacktype |= bow->attacktype;
1941 1928
1942 if (bow->slaying != NULL) 1929 if (bow->slaying)
1943 arrow->slaying = bow->slaying; 1930 arrow->slaying = bow->slaying;
1944 1931
1945 arrow->map = m; 1932 arrow->map = m;
1946 arrow->move_type = MOVE_FLY_LOW; 1933 arrow->move_type = MOVE_FLY_LOW;
1947 arrow->move_on = MOVE_FLY_LOW | MOVE_WALK; 1934 arrow->move_on = MOVE_FLY_LOW | MOVE_WALK;
2362 * player owns it and it is either friendly or unagressive. 2349 * player owns it and it is either friendly or unagressive.
2363 */ 2350 */
2364 if ((op->type == PLAYER) 2351 if ((op->type == PLAYER)
2365#if COZY_SERVER 2352#if COZY_SERVER
2366 && 2353 &&
2367 ((get_owner (mon) && get_owner (mon)->contr 2354 ((mon->owner && mon->owner->contr
2368 && same_party (get_owner (mon)->contr->party, op->contr->party)) || get_owner (mon) == op) 2355 && same_party (mon->owner->contr->party, op->contr->party)) || mon->owner == op)
2369#else 2356#else
2370 && get_owner (mon) == op 2357 && mon->owner == op
2371#endif 2358#endif
2372 && (QUERY_FLAG (mon, FLAG_UNAGGRESSIVE) || QUERY_FLAG (mon, FLAG_FRIENDLY))) 2359 && (QUERY_FLAG (mon, FLAG_UNAGGRESSIVE) || QUERY_FLAG (mon, FLAG_FRIENDLY)))
2373 { 2360 {
2374 /* If we're braced, we don't want to switch places with it */ 2361 /* If we're braced, we don't want to switch places with it */
2375 if (op->contr->braced) 2362 if (op->contr->braced)
2569 2556
2570 /* call this here - we also will call this in do_ericserver, but 2557 /* call this here - we also will call this in do_ericserver, but
2571 * the players time has been increased when doericserver has been 2558 * the players time has been increased when doericserver has been
2572 * called, so we recheck it here. 2559 * called, so we recheck it here.
2573 */ 2560 */
2574 HandleClient (&op->contr->socket, op->contr); 2561 //TODO: better than handling 8 commands, use some more intelligent rate-limiting
2562 for (int rep = 8; --rep && op->contr->socket->handle_command (); )
2563 ;
2564
2575 if (op->speed_left < 0) 2565 if (op->speed_left < 0)
2576 return 0; 2566 return 0;
2577 2567
2578 if (op->direction && (op->contr->run_on || op->contr->fire_on)) 2568 if (op->direction && (op->contr->run_on || op->contr->fire_on))
2579 { 2569 {
2588 if (op->speed_left > 0) 2578 if (op->speed_left > 0)
2589 return 1; 2579 return 1;
2590 else 2580 else
2591 return 0; 2581 return 0;
2592 } 2582 }
2583
2593 return 0; 2584 return 0;
2594} 2585}
2595 2586
2596int 2587int
2597save_life (object *op) 2588save_life (object *op)
2598{ 2589{
2599 object *tmp;
2600
2601 if (!QUERY_FLAG (op, FLAG_LIFESAVE)) 2590 if (!QUERY_FLAG (op, FLAG_LIFESAVE))
2602 return 0; 2591 return 0;
2603 2592
2604 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) 2593 for (object *tmp = op->inv; tmp; tmp = tmp->below)
2605 if (QUERY_FLAG (tmp, FLAG_APPLIED) && QUERY_FLAG (tmp, FLAG_LIFESAVE)) 2594 if (QUERY_FLAG (tmp, FLAG_APPLIED) && QUERY_FLAG (tmp, FLAG_LIFESAVE))
2606 { 2595 {
2607 play_sound_map (op->map, op->x, op->y, SOUND_OB_EVAPORATE); 2596 play_sound_map (op->map, op->x, op->y, SOUND_OB_EVAPORATE);
2608 new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s vibrates violently, then evaporates.", query_name (tmp)); 2597 new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s vibrates violently, then evaporates.", query_name (tmp));
2598
2609 if (op->contr) 2599 if (op->contr)
2610 esrv_del_item (op->contr, tmp->count); 2600 esrv_del_item (op->contr, tmp->count);
2611 remove_ob (tmp); 2601
2612 free_object (tmp); 2602 tmp->destroy ();
2613 CLEAR_FLAG (op, FLAG_LIFESAVE); 2603 CLEAR_FLAG (op, FLAG_LIFESAVE);
2604
2614 if (op->stats.hp < 0) 2605 if (op->stats.hp < 0)
2615 op->stats.hp = op->stats.maxhp; 2606 op->stats.hp = op->stats.maxhp;
2607
2616 if (op->stats.food < 0) 2608 if (op->stats.food < 0)
2617 op->stats.food = 999; 2609 op->stats.food = 999;
2610
2618 fix_player (op); 2611 fix_player (op);
2619 return 1; 2612 return 1;
2620 } 2613 }
2614
2621 LOG (llevError, "Error: LIFESAVE set without applied object.\n"); 2615 LOG (llevError, "Error: LIFESAVE set without applied object.\n");
2622 CLEAR_FLAG (op, FLAG_LIFESAVE); 2616 CLEAR_FLAG (op, FLAG_LIFESAVE);
2623 enter_player_savebed (op); /* bring him home. */ 2617 enter_player_savebed (op); /* bring him home. */
2624 return 0; 2618 return 0;
2625} 2619}
2639 next = op->below; /* Make sure we have a good value, in case 2633 next = op->below; /* Make sure we have a good value, in case
2640 * we remove object 'op' 2634 * we remove object 'op'
2641 */ 2635 */
2642 if (QUERY_FLAG (op, FLAG_UNPAID)) 2636 if (QUERY_FLAG (op, FLAG_UNPAID))
2643 { 2637 {
2644 remove_ob (op); 2638 op->remove ();
2645 op->x = env->x; 2639 op->x = env->x;
2646 op->y = env->y; 2640 op->y = env->y;
2647 if (env->type == PLAYER) 2641 if (env->type == PLAYER)
2648 esrv_del_item (env->contr, op->count); 2642 esrv_del_item (env->contr, op->count);
2649 insert_ob_in_map (op, env->map, NULL, 0); 2643 insert_ob_in_map (op, env->map, NULL, 0);
2650 } 2644 }
2651 else if (op->inv) 2645 else if (op->inv)
2652 remove_unpaid_objects (op->inv, env); 2646 remove_unpaid_objects (op->inv, env);
2647
2653 op = next; 2648 op = next;
2654 } 2649 }
2655} 2650}
2656 2651
2657 2652
2672 strcpy (buf2, " R.I.P.\n\n"); 2667 strcpy (buf2, " R.I.P.\n\n");
2673 if (op->type == PLAYER) 2668 if (op->type == PLAYER)
2674 sprintf (buf, "%s the %s\n", &op->name, op->contr->title); 2669 sprintf (buf, "%s the %s\n", &op->name, op->contr->title);
2675 else 2670 else
2676 sprintf (buf, "%s\n", &op->name); 2671 sprintf (buf, "%s\n", &op->name);
2672
2677 strncat (buf2, " ", 20 - strlen (buf) / 2); 2673 strncat (buf2, " ", 20 - strlen (buf) / 2);
2678 strcat (buf2, buf); 2674 strcat (buf2, buf);
2679 if (op->type == PLAYER) 2675 if (op->type == PLAYER)
2680 sprintf (buf, "who was in level %d when killed\n", op->level); 2676 sprintf (buf, "who was in level %d when killed\n", op->level);
2681 else 2677 else
2682 sprintf (buf, "who was in level %d when died.\n\n", op->level); 2678 sprintf (buf, "who was in level %d when died.\n\n", op->level);
2679
2683 strncat (buf2, " ", 20 - strlen (buf) / 2); 2680 strncat (buf2, " ", 20 - strlen (buf) / 2);
2684 strcat (buf2, buf); 2681 strcat (buf2, buf);
2685 if (op->type == PLAYER) 2682 if (op->type == PLAYER)
2686 { 2683 {
2687 sprintf (buf, "by %s.\n\n", op->contr->killer); 2684 sprintf (buf, "by %s.\n\n", op->contr->killer);
2688 strncat (buf2, " ", 21 - strlen (buf) / 2); 2685 strncat (buf2, " ", 21 - strlen (buf) / 2);
2689 strcat (buf2, buf); 2686 strcat (buf2, buf);
2690 } 2687 }
2688
2691 strftime (buf, MAX_BUF, "%b %d %Y\n", localtime (&now)); 2689 strftime (buf, MAX_BUF, "%b %d %Y\n", localtime (&now));
2692 strncat (buf2, " ", 20 - strlen (buf) / 2); 2690 strncat (buf2, " ", 20 - strlen (buf) / 2);
2693 strcat (buf2, buf); 2691 strcat (buf2, buf);
2692
2694 return buf2; 2693 return buf2;
2695} 2694}
2696 2695
2697 2696
2698 2697
2946 /* restore player */ 2945 /* restore player */
2947 at = archetype::find ("poisoning"); 2946 at = archetype::find ("poisoning");
2948 tmp = present_arch_in_ob (at, op); 2947 tmp = present_arch_in_ob (at, op);
2949 if (tmp) 2948 if (tmp)
2950 { 2949 {
2951 remove_ob (tmp); 2950 tmp->destroy ();
2952 free_object (tmp);
2953 new_draw_info (NDI_UNIQUE, 0, op, "Your body feels cleansed"); 2951 new_draw_info (NDI_UNIQUE, 0, op, "Your body feels cleansed");
2954 } 2952 }
2955 2953
2956 at = archetype::find ("confusion"); 2954 at = archetype::find ("confusion");
2957 tmp = present_arch_in_ob (at, op); 2955 tmp = present_arch_in_ob (at, op);
2958 if (tmp) 2956 if (tmp)
2959 { 2957 {
2960 remove_ob (tmp); 2958 tmp->destroy ();
2961 free_object (tmp);
2962 new_draw_info (NDI_UNIQUE, 0, tmp, "Your mind feels clearer"); 2959 new_draw_info (NDI_UNIQUE, 0, tmp, "Your mind feels clearer");
2963 } 2960 }
2964 2961
2965 cure_disease (op, 0); /* remove any disease */ 2962 cure_disease (op, 0); /* remove any disease */
2966 op->stats.hp = op->stats.maxhp; 2963 op->stats.hp = op->stats.maxhp;
3176 3173
3177 /* remove any poisoning and confusion the character may be suffering. */ 3174 /* remove any poisoning and confusion the character may be suffering. */
3178 /* restore player */ 3175 /* restore player */
3179 at = archetype::find ("poisoning"); 3176 at = archetype::find ("poisoning");
3180 tmp = present_arch_in_ob (at, op); 3177 tmp = present_arch_in_ob (at, op);
3178
3181 if (tmp) 3179 if (tmp)
3182 { 3180 {
3183 remove_ob (tmp); 3181 tmp->destroy ();
3184 free_object (tmp);
3185 new_draw_info (NDI_UNIQUE, 0, op, "Your body feels cleansed"); 3182 new_draw_info (NDI_UNIQUE, 0, op, "Your body feels cleansed");
3186 } 3183 }
3187 3184
3188 at = archetype::find ("confusion"); 3185 at = archetype::find ("confusion");
3189 tmp = present_arch_in_ob (at, op); 3186 tmp = present_arch_in_ob (at, op);
3190 if (tmp) 3187 if (tmp)
3191 { 3188 {
3192 remove_ob (tmp); 3189 tmp->destroy ();
3193 free_object (tmp);
3194 new_draw_info (NDI_UNIQUE, 0, tmp, "Your mind feels clearer"); 3190 new_draw_info (NDI_UNIQUE, 0, tmp, "Your mind feels clearer");
3195 } 3191 }
3196 3192
3197 cure_disease (op, 0); /* remove any disease */ 3193 cure_disease (op, 0); /* remove any disease */
3198 3194
3273 check_score (op); 3269 check_score (op);
3274 3270
3275 if (op->contr->ranges[range_golem]) 3271 if (op->contr->ranges[range_golem])
3276 { 3272 {
3277 remove_friendly_object (op->contr->ranges[range_golem]); 3273 remove_friendly_object (op->contr->ranges[range_golem]);
3278 remove_ob (op->contr->ranges[range_golem]); 3274 op->contr->ranges[range_golem]->destroy ();
3279 free_object (op->contr->ranges[range_golem]);
3280 op->contr->ranges[range_golem] = 0; 3275 op->contr->ranges[range_golem] = 0;
3281 } 3276 }
3282 3277
3283 loot_object (op); /* Remove some of the items for good */ 3278 loot_object (op); /* Remove some of the items for good */
3284 remove_ob (op); 3279 op->remove ();
3285 op->direction = 0; 3280 op->direction = 0;
3286 3281
3287 if (!QUERY_FLAG (op, FLAG_WAS_WIZ) && op->stats.exp) 3282 if (!QUERY_FLAG (op, FLAG_WAS_WIZ) && op->stats.exp)
3288 { 3283 {
3289 delete_character (op->name, 0); 3284 delete_character (op->name, 0);
3342 for (tmp = op->inv; tmp != NULL; tmp = next) 3337 for (tmp = op->inv; tmp != NULL; tmp = next)
3343 { 3338 {
3344 next = tmp->below; 3339 next = tmp->below;
3345 if (tmp->type == EXPERIENCE || tmp->invisible) 3340 if (tmp->type == EXPERIENCE || tmp->invisible)
3346 continue; 3341 continue;
3347 remove_ob (tmp); 3342 tmp->remove ();
3348 tmp->x = op->x, tmp->y = op->y; 3343 tmp->x = op->x, tmp->y = op->y;
3349 if (tmp->type == CONTAINER) 3344 if (tmp->type == CONTAINER)
3350 { /* empty container to ground */ 3345 { /* empty container to ground */
3351 loot_object (tmp); 3346 loot_object (tmp);
3352 } 3347 }
3353 if (!QUERY_FLAG (tmp, FLAG_UNIQUE) && (QUERY_FLAG (tmp, FLAG_STARTEQUIP) || QUERY_FLAG (tmp, FLAG_NO_DROP) || !(RANDOM () % 3))) 3348 if (!QUERY_FLAG (tmp, FLAG_UNIQUE) && (QUERY_FLAG (tmp, FLAG_STARTEQUIP) || QUERY_FLAG (tmp, FLAG_NO_DROP) || !(RANDOM () % 3)))
3354 { 3349 {
3355 if (tmp->nrof > 1) 3350 if (tmp->nrof > 1)
3356 { 3351 {
3357 tmp2 = get_split_ob (tmp, 1 + RANDOM () % (tmp->nrof - 1)); 3352 tmp2 = get_split_ob (tmp, 1 + RANDOM () % (tmp->nrof - 1));
3358 free_object (tmp2); 3353 tmp2->destroy ();
3359 insert_ob_in_map (tmp, op->map, NULL, 0); 3354 insert_ob_in_map (tmp, op->map, NULL, 0);
3360 } 3355 }
3361 else 3356 else
3362 free_object (tmp); 3357 tmp->destroy ();
3363 } 3358 }
3364 else 3359 else
3365 insert_ob_in_map (tmp, op->map, NULL, 0); 3360 insert_ob_in_map (tmp, op->map, NULL, 0);
3366 } 3361 }
3367} 3362}
3432 if (op->type == PLAYER) 3427 if (op->type == PLAYER)
3433 new_draw_info_format (NDI_UNIQUE, 0, op, "You cast %s.", &spob->name); 3428 new_draw_info_format (NDI_UNIQUE, 0, op, "You cast %s.", &spob->name);
3434 3429
3435 cast_spell (op, throw_ob, dir, spob, NULL); 3430 cast_spell (op, throw_ob, dir, spob, NULL);
3436 3431
3437 if (!QUERY_FLAG (throw_ob, FLAG_REMOVED)) 3432 throw_ob->destroy ();
3438 remove_ob (throw_ob);
3439 free_object (throw_ob);
3440} 3433}
3441 3434
3442void 3435void
3443make_visible (object *op) 3436make_visible (object *op)
3444{ 3437{
3651 3644
3652 /* only the viewable area the player sees is updated by LOS 3645 /* only the viewable area the player sees is updated by LOS
3653 * code, so we need to restrict ourselves to that range of values 3646 * code, so we need to restrict ourselves to that range of values
3654 * for any meaningful values. 3647 * for any meaningful values.
3655 */ 3648 */
3656 if (FABS (dx) <= (pl->contr->socket.mapx / 2) && 3649 if (FABS (dx) <= (pl->contr->socket->mapx / 2) &&
3657 FABS (dy) <= (pl->contr->socket.mapy / 2) && 3650 FABS (dy) <= (pl->contr->socket->mapy / 2) &&
3658 !pl->contr->blocked_los[dx + (pl->contr->socket.mapx / 2)][dy + (pl->contr->socket.mapy / 2)]) 3651 !pl->contr->blocked_los[dx + (pl->contr->socket->mapx / 2)][dy + (pl->contr->socket->mapy / 2)])
3659 return 1; 3652 return 1;
3660 op = op->more; 3653 op = op->more;
3661 } 3654 }
3662 return 0; 3655 return 0;
3663} 3656}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines