1 | /* |
1 | /* |
2 | * static char *rcsid_player_c = |
2 | * static char *rcsid_player_c = |
3 | * "$Id: player.C,v 1.12 2006/08/29 10:51:43 elmex Exp $"; |
3 | * "$Id: player.C,v 1.16 2006/09/05 18:18:09 root Exp $"; |
4 | */ |
4 | */ |
5 | |
5 | |
6 | /* |
6 | /* |
7 | CrossFire, A Multiplayer game for X-windows |
7 | CrossFire, A Multiplayer game for X-windows |
8 | |
8 | |
… | |
… | |
197 | * Hopefully this will be less bugfree and simpler. |
197 | * Hopefully this will be less bugfree and simpler. |
198 | * Returns the player structure. If 'p' is null, |
198 | * Returns the player structure. If 'p' is null, |
199 | * we create a new one. Otherwise, we recycle |
199 | * we create a new one. Otherwise, we recycle |
200 | * the one that is passed. |
200 | * the one that is passed. |
201 | */ |
201 | */ |
202 | static player* get_player(player *p) { |
202 | static player * |
|
|
203 | get_player (player * p) |
|
|
204 | { |
203 | object *op=arch_to_object(get_player_archetype(NULL)); |
205 | object *op = arch_to_object (get_player_archetype (NULL)); |
204 | int i; |
206 | int i; |
205 | |
207 | |
206 | if (!p) { |
208 | if (!p) |
207 | p = (player *) malloc(sizeof(player)); |
209 | { |
208 | if(p==NULL) |
210 | p = new player; |
209 | fatal(OUT_OF_MEMORY); |
|
|
210 | |
211 | |
211 | /* This adds the player in the linked list. There is extra |
212 | /* This adds the player in the linked list. There is extra |
212 | * complexity here because we want to add the new player at the |
213 | * complexity here because we want to add the new player at the |
213 | * end of the list - there is in fact no compelling reason that |
214 | * end of the list - there is in fact no compelling reason that |
214 | * that needs to be done except for things like output of |
215 | * that needs to be done except for things like output of |
215 | * 'who'. |
216 | * 'who'. |
216 | */ |
217 | */ |
217 | player *tmp = first_player; |
218 | player *tmp = first_player; |
218 | while(tmp!=NULL&&tmp->next!=NULL) |
219 | while (tmp != NULL && tmp->next != NULL) |
219 | tmp=tmp->next; |
220 | tmp = tmp->next; |
220 | if(tmp!=NULL) |
221 | if (tmp != NULL) |
221 | tmp->next=p; |
222 | tmp->next = p; |
222 | else |
223 | else |
223 | first_player=p; |
224 | first_player = p; |
224 | |
225 | |
225 | p->next = NULL; |
226 | p->next = NULL; |
226 | } |
227 | } |
227 | |
228 | |
228 | /* Clears basically the entire player structure except |
229 | /* Clears basically the entire player structure except |
229 | * for next and socket. |
230 | * for next and socket. |
230 | */ |
231 | */ |
231 | memset (static_cast<player_memset *>(p), 0, sizeof (player_memset)); |
232 | p->clear (); |
232 | p->attachable_init (); //HACK |
|
|
233 | |
233 | |
234 | /* There are some elements we want initialized to non zero value - |
234 | /* There are some elements we want initialized to non zero value - |
235 | * we deal with that below this point. |
235 | * we deal with that below this point. |
236 | */ |
236 | */ |
237 | p->party=NULL; |
237 | p->party = NULL; |
238 | p->outputs_sync=16; /* Every 2 seconds */ |
238 | p->outputs_sync = 16; /* Every 2 seconds */ |
239 | p->outputs_count=1; /* Keeps present behaviour */ |
239 | p->outputs_count = 8; /* Keeps present behaviour */ |
240 | p->unapply = unapply_nochoice; |
240 | p->unapply = unapply_nochoice; |
241 | p->Swap_First = -1; |
241 | p->Swap_First = -1; |
242 | |
242 | |
243 | #ifdef AUTOSAVE |
243 | #ifdef AUTOSAVE |
244 | p->last_save_tick = 9999999; |
244 | p->last_save_tick = 9999999; |
245 | #endif |
245 | #endif |
246 | |
246 | |
247 | strcpy(p->savebed_map, first_map_path); /* Init. respawn position */ |
247 | strcpy (p->savebed_map, first_map_path); /* Init. respawn position */ |
248 | |
248 | |
249 | op->contr=p; /* this aren't yet in archetype */ |
249 | op->contr = p; /* this aren't yet in archetype */ |
250 | p->ob = op; |
250 | p->ob = op; |
251 | op->speed_left=0.5; |
251 | op->speed_left = 0.5; |
252 | op->speed=1.0; |
252 | op->speed = 1.0; |
253 | op->direction=5; /* So player faces south */ |
253 | op->direction = 5; /* So player faces south */ |
254 | op->stats.wc=2; |
254 | op->stats.wc = 2; |
255 | op->run_away = 25; /* Then we panick... */ |
255 | op->run_away = 25; /* Then we panick... */ |
256 | p->socket.monitor_spells = 0; /* Needed because esrv_update_spells( ) gets called by roll_stats */ |
256 | p->socket.monitor_spells = 0; /* Needed because esrv_update_spells( ) gets called by roll_stats */ |
257 | |
257 | |
258 | roll_stats(op); |
258 | roll_stats (op); |
259 | p->state=ST_ROLL_STAT; |
259 | p->state = ST_ROLL_STAT; |
260 | clear_los(op); |
260 | clear_los (op); |
261 | |
261 | |
262 | p->gen_sp_armour=10; |
262 | p->gen_sp_armour = 10; |
263 | p->last_speed= -1; |
263 | p->last_speed = -1; |
264 | p->shoottype=range_none; |
264 | p->shoottype = range_none; |
265 | p->bowtype=bow_normal; |
265 | p->bowtype = bow_normal; |
266 | p->petmode=pet_normal; |
266 | p->petmode = pet_normal; |
267 | p->listening=10; |
267 | p->listening = 10; |
268 | p->usekeys=containers; |
268 | p->usekeys = containers; |
269 | p->last_weapon_sp= -1; |
269 | p->last_weapon_sp = -1; |
270 | p->peaceful=1; /* default peaceful */ |
270 | p->peaceful = 1; /* default peaceful */ |
271 | p->do_los=1; |
271 | p->do_los = 1; |
272 | p->explore=0; |
272 | p->explore = 0; |
273 | p->no_shout=0; /* default can shout */ |
273 | p->no_shout = 0; /* default can shout */ |
274 | |
274 | |
275 | strncpy(p->title, op->arch->clone.name, sizeof(p->title)-1); |
275 | strncpy (p->title, op->arch->clone.name, sizeof (p->title) - 1); |
276 | p->title[sizeof(p->title)-1] = '\0'; |
276 | p->title[sizeof (p->title) - 1] = '\0'; |
277 | op->race = add_string (op->arch->clone.race); |
277 | op->race = op->arch->clone.race; |
278 | |
278 | |
279 | CLEAR_FLAG(op,FLAG_READY_SKILL); |
279 | CLEAR_FLAG (op, FLAG_READY_SKILL); |
280 | |
280 | |
281 | /* we need to clear these to -1 and not zero - otherwise, |
281 | /* we need to clear these to -1 and not zero - otherwise, |
282 | * if a player quits and starts a new character, we wont |
282 | * if a player quits and starts a new character, we wont |
283 | * send new values to the client, as things like exp start |
283 | * send new values to the client, as things like exp start |
284 | * at zero. |
284 | * at zero. |
285 | */ |
285 | */ |
286 | for (i=0; i < NUM_SKILLS; i++) { |
286 | for (i = 0; i < NUM_SKILLS; i++) |
|
|
287 | { |
287 | p->last_skill_exp[i] = -1; |
288 | p->last_skill_exp[i] = -1; |
288 | p->last_skill_ob[i] = NULL; |
289 | p->last_skill_ob[i] = NULL; |
289 | } |
290 | } |
290 | for (i=0; i < NROFATTACKS; i++) { |
291 | for (i = 0; i < NROFATTACKS; i++) |
|
|
292 | { |
291 | p->last_resist[i] = -1; |
293 | p->last_resist[i] = -1; |
292 | } |
294 | } |
293 | p->last_stats.exp = -1; |
295 | p->last_stats.exp = -1; |
294 | p->last_weight = (uint32)-1; |
296 | p->last_weight = (uint32) - 1; |
295 | |
297 | |
296 | p->socket.update_look=0; |
298 | p->socket.update_look = 0; |
297 | p->socket.look_position=0; |
299 | p->socket.look_position = 0; |
298 | return p; |
300 | return p; |
299 | } |
301 | } |
300 | |
|
|
301 | |
302 | |
302 | /* This loads the first map an puts the player on it. */ |
303 | /* This loads the first map an puts the player on it. */ |
303 | static void set_first_map(object *op) |
304 | static void set_first_map(object *op) |
304 | { |
305 | { |
305 | strcpy(op->contr->maplevel, first_map_path); |
306 | strcpy(op->contr->maplevel, first_map_path); |
… | |
… | |
409 | lastdist=rv.distance; |
410 | lastdist=rv.distance; |
410 | } |
411 | } |
411 | } |
412 | } |
412 | } |
413 | } |
413 | #if 0 |
414 | #if 0 |
414 | LOG(llevDebug,"get_nearest_player() finds player: %s\n",op?op->name:"(null)"); |
415 | LOG(llevDebug,"get_nearest_player() finds player: %s\n",op?&op->name:"(null)"); |
415 | #endif |
416 | #endif |
416 | return op; |
417 | return op; |
417 | } |
418 | } |
418 | |
419 | |
419 | /* I believe this can safely go to 2, 3 is questionable, 4 will likely |
420 | /* I believe this can safely go to 2, 3 is questionable, 4 will likely |
… | |
… | |
615 | |
616 | |
616 | if (tmp) { |
617 | if (tmp) { |
617 | remove_ob(op); |
618 | remove_ob(op); |
618 | free_object(op); |
619 | free_object(op); |
619 | LOG(llevError,"give_initial_items: Removing duplicate object %s\n", |
620 | LOG(llevError,"give_initial_items: Removing duplicate object %s\n", |
620 | tmp->name); |
621 | &tmp->name); |
621 | continue; |
622 | continue; |
622 | } |
623 | } |
623 | if (op->nrof > 1) op->nrof = 1; |
624 | if (op->nrof > 1) op->nrof = 1; |
624 | } |
625 | } |
625 | |
626 | |
… | |
… | |
696 | leave(op->contr,0); /* ericserver will draw the message */ |
697 | leave(op->contr,0); /* ericserver will draw the message */ |
697 | return 2; |
698 | return 2; |
698 | } |
699 | } |
699 | else if(key=='a'||key=='A') { |
700 | else if(key=='a'||key=='A') { |
700 | player *pl = op->contr; |
701 | player *pl = op->contr; |
701 | const char *name = op->name; |
702 | shstr name = op->name; |
702 | |
703 | |
703 | add_refcount(name); |
|
|
704 | remove_friendly_object(op); |
704 | remove_friendly_object(op); |
705 | free_object(op); |
705 | free_object(op); |
706 | pl = get_player(pl); |
706 | pl = get_player(pl); |
707 | op = pl->ob; |
707 | op = pl->ob; |
708 | add_friendly_object(op); |
708 | add_friendly_object(op); |
709 | op->contr->password[0]='~'; |
709 | op->contr->password[0]='~'; |
710 | FREE_AND_CLEAR_STR(op->name); |
710 | op->name = op->name_pl = 0; |
711 | FREE_AND_CLEAR_STR(op->name_pl); |
|
|
712 | |
|
|
713 | /* Lets put a space in here */ |
711 | /* Lets put a space in here */ |
714 | new_draw_info(NDI_UNIQUE, 0, op, "\n"); |
712 | new_draw_info(NDI_UNIQUE, 0, op, "\n"); |
715 | get_name(op); |
713 | get_name(op); |
716 | op->name = name; /* Alrady added a refcount above */ |
714 | op->name = op->name_pl = name; |
717 | op->name_pl = add_string(name); |
|
|
718 | set_first_map(op); |
715 | set_first_map(op); |
719 | } else { |
716 | } else { |
720 | /* user pressed something else so just ask again... */ |
717 | /* user pressed something else so just ask again... */ |
721 | play_again(op); |
718 | play_again(op); |
722 | } |
719 | } |
… | |
… | |
730 | send_query(&op->contr->socket, CS_QUERY_HIDEINPUT, "Please type your password again.\n:"); |
727 | send_query(&op->contr->socket, CS_QUERY_HIDEINPUT, "Please type your password again.\n:"); |
731 | } |
728 | } |
732 | |
729 | |
733 | void get_party_password(object *op, partylist *party) { |
730 | void get_party_password(object *op, partylist *party) { |
734 | if (party == NULL) { |
731 | if (party == NULL) { |
735 | LOG(llevError, "get_party_password(): tried to make player %s join a NULL party", op->name); |
732 | LOG(llevError, "get_party_password(): tried to make player %s join a NULL party", &op->name); |
736 | return; |
733 | return; |
737 | } |
734 | } |
738 | op->contr->write_buf[0]='\0'; |
735 | op->contr->write_buf[0]='\0'; |
739 | op->contr->state=ST_GET_PARTY_PASSWORD; |
736 | op->contr->state=ST_GET_PARTY_PASSWORD; |
740 | op->contr->party_to_join = party; |
737 | op->contr->party_to_join = party; |
… | |
… | |
977 | INVOKE_PLAYER (BIRTH, op->contr); |
974 | INVOKE_PLAYER (BIRTH, op->contr); |
978 | INVOKE_PLAYER (LOGIN, op->contr); |
975 | INVOKE_PLAYER (LOGIN, op->contr); |
979 | |
976 | |
980 | op->contr->state=ST_PLAYING; |
977 | op->contr->state=ST_PLAYING; |
981 | |
978 | |
982 | if (op->msg) { |
979 | if (op->msg) |
983 | free_string(op->msg); |
|
|
984 | op->msg=NULL; |
980 | op->msg=NULL; |
985 | } |
|
|
986 | |
981 | |
987 | /* We create this now because some of the unique maps will need it |
982 | /* We create this now because some of the unique maps will need it |
988 | * to save here. |
983 | * to save here. |
989 | */ |
984 | */ |
990 | sprintf(buf,"%s/%s/%s",settings.localdir,settings.playerdir,op->name); |
985 | sprintf(buf,"%s/%s/%s",settings.localdir,settings.playerdir,&op->name); |
991 | make_path_to_file(buf); |
986 | make_path_to_file(buf); |
992 | |
987 | |
993 | #ifdef AUTOSAVE |
988 | #ifdef AUTOSAVE |
994 | op->contr->last_save_tick = pticks; |
989 | op->contr->last_save_tick = pticks; |
995 | #endif |
990 | #endif |
… | |
… | |
1006 | if(*first_map_ext_path) { |
1001 | if(*first_map_ext_path) { |
1007 | object *tmp; |
1002 | object *tmp; |
1008 | mapstruct *oldmap = op->map; |
1003 | mapstruct *oldmap = op->map; |
1009 | char mapname[MAX_BUF]; |
1004 | char mapname[MAX_BUF]; |
1010 | snprintf(mapname, MAX_BUF-1, "%s/%s", |
1005 | snprintf(mapname, MAX_BUF-1, "%s/%s", |
1011 | first_map_ext_path, op->arch->name); |
1006 | first_map_ext_path, &op->arch->name); |
1012 | tmp=get_object(); |
1007 | tmp=get_object(); |
1013 | EXIT_PATH(tmp) = add_string(mapname); |
1008 | EXIT_PATH(tmp) = mapname; |
1014 | EXIT_X(tmp) = op->x; |
1009 | EXIT_X(tmp) = op->x; |
1015 | EXIT_Y(tmp) = op->y; |
1010 | EXIT_Y(tmp) = op->y; |
1016 | enter_exit(op,tmp); /* we don't really care if it succeeded; |
1011 | enter_exit(op,tmp); /* we don't really care if it succeeded; |
1017 | * if the map isn't there, then stay on the |
1012 | * if the map isn't there, then stay on the |
1018 | * default initial map */ |
1013 | * default initial map */ |
… | |
… | |
1027 | * if we don't match with one of the options above. |
1022 | * if we don't match with one of the options above. |
1028 | */ |
1023 | */ |
1029 | |
1024 | |
1030 | tmp_loop = 0; |
1025 | tmp_loop = 0; |
1031 | while(!tmp_loop) { |
1026 | while(!tmp_loop) { |
1032 | const char *name = add_string (op->name); |
1027 | shstr name = op->name; |
1033 | int x = op->x, y = op->y; |
1028 | int x = op->x, y = op->y; |
1034 | remove_statbonus(op); |
1029 | remove_statbonus(op); |
1035 | remove_ob (op); |
1030 | remove_ob (op); |
1036 | op->arch = get_player_archetype(op->arch); |
1031 | op->arch = get_player_archetype(op->arch); |
1037 | copy_object (&op->arch->clone, op); |
1032 | copy_object (&op->arch->clone, op); |
1038 | op->instantiate (); |
1033 | op->instantiate (); |
1039 | op->stats = op->contr->orig_stats; |
1034 | op->stats = op->contr->orig_stats; |
1040 | free_string (op->name); |
|
|
1041 | op->name = name; |
1035 | op->name = op->name_pl = name; |
1042 | free_string(op->name_pl); |
|
|
1043 | op->name_pl = add_string(name); |
|
|
1044 | op->x = x; |
1036 | op->x = x; |
1045 | op->y = y; |
1037 | op->y = y; |
1046 | SET_ANIMATION(op, 2); /* So player faces south */ |
1038 | SET_ANIMATION(op, 2); /* So player faces south */ |
1047 | insert_ob_in_map (op, op->map, op,0); |
1039 | insert_ob_in_map (op, op->map, op,0); |
1048 | strncpy(op->contr->title, op->arch->clone.name, sizeof(op->contr->title)-1); |
1040 | strncpy(op->contr->title, op->arch->clone.name, sizeof(op->contr->title)-1); |
1049 | op->contr->title[sizeof(op->contr->title)-1] = '\0'; |
1041 | op->contr->title[sizeof(op->contr->title)-1] = '\0'; |
1050 | add_statbonus(op); |
1042 | add_statbonus(op); |
1051 | tmp_loop=allowed_class(op); |
1043 | tmp_loop=allowed_class(op); |
1052 | |
|
|
1053 | if (!strncmp (op->msg, "Edit me", 7)) tmp_loop = 0; // pippijn fucked it up //D//TODO |
|
|
1054 | } |
1044 | } |
1055 | update_object(op,UP_OBJ_FACE); |
1045 | update_object(op,UP_OBJ_FACE); |
1056 | esrv_update_item(UPD_FACE,op,op); |
1046 | esrv_update_item(UPD_FACE,op,op); |
1057 | fix_player(op); |
1047 | fix_player(op); |
1058 | op->stats.hp=op->stats.maxhp; |
1048 | op->stats.hp=op->stats.maxhp; |
… | |
… | |
1079 | |
1069 | |
1080 | terminate_all_pets(op); |
1070 | terminate_all_pets(op); |
1081 | leave_map(op); |
1071 | leave_map(op); |
1082 | op->direction=0; |
1072 | op->direction=0; |
1083 | new_draw_info_format(NDI_UNIQUE | NDI_ALL, 5, NULL, |
1073 | new_draw_info_format(NDI_UNIQUE | NDI_ALL, 5, NULL, |
1084 | "%s quits the game.",op->name); |
1074 | "%s quits the game.", &op->name); |
1085 | |
1075 | |
1086 | strcpy(op->contr->killer,"quit"); |
1076 | strcpy(op->contr->killer,"quit"); |
1087 | check_score(op); |
1077 | check_score(op); |
1088 | op->contr->party=NULL; |
1078 | op->contr->party=NULL; |
1089 | if (settings.set_title == TRUE) |
1079 | if (settings.set_title == TRUE) |
… | |
… | |
1094 | |
1084 | |
1095 | /* We need to hunt for any per player unique maps in memory and |
1085 | /* We need to hunt for any per player unique maps in memory and |
1096 | * get rid of them. The trailing slash in the path is intentional, |
1086 | * get rid of them. The trailing slash in the path is intentional, |
1097 | * so that players named 'Ab' won't match against players 'Abe' pathname |
1087 | * so that players named 'Ab' won't match against players 'Abe' pathname |
1098 | */ |
1088 | */ |
1099 | sprintf(buf,"%s/%s/%s/", settings.localdir, settings.playerdir, op->name); |
1089 | sprintf(buf,"%s/%s/%s/", settings.localdir, settings.playerdir, &op->name); |
1100 | for (mp=first_map; mp!=NULL; mp=next) { |
1090 | for (mp=first_map; mp!=NULL; mp=next) { |
1101 | next = mp->next; |
1091 | next = mp->next; |
1102 | if (!strncmp(mp->path, buf, strlen(buf))) |
1092 | if (!strncmp(mp->path, buf, strlen(buf))) |
1103 | delete_map(mp); |
1093 | delete_map(mp); |
1104 | } |
1094 | } |
… | |
… | |
1239 | if(op->contr->mode & PU_DEBUG) |
1229 | if(op->contr->mode & PU_DEBUG) |
1240 | { |
1230 | { |
1241 | /* some debugging code to figure out item information */ |
1231 | /* some debugging code to figure out item information */ |
1242 | if(tmp->name!=NULL) |
1232 | if(tmp->name!=NULL) |
1243 | sprintf(putstring,"item name: %s item type: %d weight/value: %d", |
1233 | sprintf(putstring,"item name: %s item type: %d weight/value: %d", |
1244 | tmp->name, tmp->type, |
1234 | &tmp->name, tmp->type, |
1245 | (int)(query_cost(tmp, op, F_TRUE)*100 / (tmp->weight * MAX(tmp->nrof,1)))); |
1235 | (int)(query_cost(tmp, op, F_TRUE)*100 / (tmp->weight * MAX(tmp->nrof,1)))); |
1246 | else |
1236 | else |
1247 | sprintf(putstring,"item name: %s item type: %d weight/value: %d", |
1237 | sprintf(putstring,"item name: %s item type: %d weight/value: %d", |
1248 | tmp->arch->name, tmp->type, |
1238 | &tmp->arch->name, tmp->type, |
1249 | (int)(query_cost(tmp, op, F_TRUE)*100 / (tmp->weight * MAX(tmp->nrof,1)))); |
1239 | (int)(query_cost(tmp, op, F_TRUE)*100 / (tmp->weight * MAX(tmp->nrof,1)))); |
1250 | new_draw_info(NDI_UNIQUE, 0,op,putstring); |
1240 | new_draw_info(NDI_UNIQUE, 0,op,putstring); |
1251 | |
1241 | |
1252 | sprintf(putstring,"...flags: "); |
1242 | sprintf(putstring,"...flags: "); |
1253 | for(k=0;k<4;k++) |
1243 | for(k=0;k<4;k++) |
… | |
… | |
1613 | */ |
1603 | */ |
1614 | if(bow->type==BOW) |
1604 | if(bow->type==BOW) |
1615 | break; |
1605 | break; |
1616 | |
1606 | |
1617 | if (!bow) { |
1607 | if (!bow) { |
1618 | LOG (llevError, "Range: bow without activated bow (%s).\n", op->name); |
1608 | LOG (llevError, "Range: bow without activated bow (%s).\n", &op->name); |
1619 | return 0; |
1609 | return 0; |
1620 | } |
1610 | } |
1621 | } |
1611 | } |
1622 | if( !bow->race || !bow->skill) { |
1612 | if( !bow->race || !bow->skill) { |
1623 | new_draw_info_format(NDI_UNIQUE, 0, op, "Your %s is broken.", bow->name); |
1613 | new_draw_info_format(NDI_UNIQUE, 0, op, "Your %s is broken.", &bow->name); |
1624 | return 0; |
1614 | return 0; |
1625 | } |
1615 | } |
1626 | |
1616 | |
1627 | bowspeed = bow->stats.sp + dex_bonus[op->stats.Dex]; |
1617 | bowspeed = bow->stats.sp + dex_bonus[op->stats.Dex]; |
1628 | |
1618 | |
… | |
… | |
1634 | |
1624 | |
1635 | if (arrow == NULL) { |
1625 | if (arrow == NULL) { |
1636 | if ((arrow=find_arrow(op, bow->race)) == NULL) { |
1626 | if ((arrow=find_arrow(op, bow->race)) == NULL) { |
1637 | if (op->type == PLAYER) |
1627 | if (op->type == PLAYER) |
1638 | new_draw_info_format(NDI_UNIQUE, 0, op, |
1628 | new_draw_info_format(NDI_UNIQUE, 0, op, |
1639 | "You have no %s left.", bow->race); |
1629 | "You have no %s left.", &bow->race); |
1640 | /* FLAG_READY_BOW will get reset if the monsters picks up some arrows */ |
1630 | /* FLAG_READY_BOW will get reset if the monsters picks up some arrows */ |
1641 | else |
1631 | else |
1642 | CLEAR_FLAG(op, FLAG_READY_BOW); |
1632 | CLEAR_FLAG(op, FLAG_READY_BOW); |
1643 | return 0; |
1633 | return 0; |
1644 | } |
1634 | } |
… | |
… | |
1661 | |
1651 | |
1662 | left = arrow; /* these are arrows left to the player */ |
1652 | left = arrow; /* these are arrows left to the player */ |
1663 | left_tag = left->count; |
1653 | left_tag = left->count; |
1664 | arrow = get_split_ob(arrow, 1); |
1654 | arrow = get_split_ob(arrow, 1); |
1665 | if (arrow == NULL) { |
1655 | if (arrow == NULL) { |
1666 | new_draw_info_format(NDI_UNIQUE, 0, op, "You have no %s left.", |
1656 | new_draw_info_format(NDI_UNIQUE, 0, op, "You have no %s left.", &bow->race); |
1667 | bow->race); |
|
|
1668 | return 0; |
1657 | return 0; |
1669 | } |
1658 | } |
1670 | set_owner(arrow, op); |
1659 | set_owner(arrow, op); |
1671 | if (arrow->skill) free_string(arrow->skill); |
|
|
1672 | arrow->skill = add_refcount(bow->skill); |
1660 | arrow->skill = bow->skill; |
1673 | |
1661 | |
1674 | arrow->direction=dir; |
1662 | arrow->direction=dir; |
1675 | arrow->x = sx; |
1663 | arrow->x = sx; |
1676 | arrow->y = sy; |
1664 | arrow->y = sy; |
1677 | |
1665 | |
… | |
… | |
1720 | arrow->level = op->level; |
1708 | arrow->level = op->level; |
1721 | } |
1709 | } |
1722 | if (arrow->attacktype == AT_PHYSICAL) |
1710 | if (arrow->attacktype == AT_PHYSICAL) |
1723 | arrow->attacktype |= bow->attacktype; |
1711 | arrow->attacktype |= bow->attacktype; |
1724 | if (bow->slaying != NULL) |
1712 | if (bow->slaying != NULL) |
1725 | arrow->slaying = add_string(bow->slaying); |
1713 | arrow->slaying = bow->slaying; |
1726 | |
1714 | |
1727 | arrow->map = m; |
1715 | arrow->map = m; |
1728 | arrow->move_type = MOVE_FLY_LOW; |
1716 | arrow->move_type = MOVE_FLY_LOW; |
1729 | arrow->move_on = MOVE_FLY_LOW | MOVE_WALK; |
1717 | arrow->move_on = MOVE_FLY_LOW | MOVE_WALK; |
1730 | |
1718 | |
… | |
… | |
1793 | return; |
1781 | return; |
1794 | } |
1782 | } |
1795 | |
1783 | |
1796 | item = op->contr->ranges[range_misc]; |
1784 | item = op->contr->ranges[range_misc]; |
1797 | if (!item->inv) { |
1785 | if (!item->inv) { |
1798 | LOG(llevError,"Object %s lacks a spell\n", item->name); |
1786 | LOG(llevError,"Object %s lacks a spell\n", &item->name); |
1799 | return; |
1787 | return; |
1800 | } |
1788 | } |
1801 | if (item->type == WAND) { |
1789 | if (item->type == WAND) { |
1802 | if(item->stats.food<=0) { |
1790 | if(item->stats.food<=0) { |
1803 | play_sound_player_only(op->contr, SOUND_WAND_POOF,0,0); |
1791 | play_sound_player_only(op->contr, SOUND_WAND_POOF,0,0); |
… | |
… | |
2368 | char buf[MAX_BUF]; |
2356 | char buf[MAX_BUF]; |
2369 | time_t now = time (NULL); |
2357 | time_t now = time (NULL); |
2370 | |
2358 | |
2371 | strcpy (buf2, " R.I.P.\n\n"); |
2359 | strcpy (buf2, " R.I.P.\n\n"); |
2372 | if (op->type == PLAYER) |
2360 | if (op->type == PLAYER) |
2373 | sprintf (buf, "%s the %s\n", op->name, op->contr->title); |
2361 | sprintf (buf, "%s the %s\n", &op->name, op->contr->title); |
2374 | else |
2362 | else |
2375 | sprintf (buf, "%s\n", op->name); |
2363 | sprintf (buf, "%s\n", &op->name); |
2376 | strncat (buf2, " ", 20 - strlen (buf) / 2); |
2364 | strncat (buf2, " ", 20 - strlen (buf) / 2); |
2377 | strcat (buf2, buf); |
2365 | strcat (buf2, buf); |
2378 | if (op->type == PLAYER) |
2366 | if (op->type == PLAYER) |
2379 | sprintf (buf, "who was in level %d when killed\n", op->level); |
2367 | sprintf (buf, "who was in level %d when killed\n", op->level); |
2380 | else |
2368 | else |
… | |
… | |
2626 | |
2614 | |
2627 | /* create a bodypart-trophy to make the winner happy */ |
2615 | /* create a bodypart-trophy to make the winner happy */ |
2628 | tmp=arch_to_object(find_archetype("finger")); |
2616 | tmp=arch_to_object(find_archetype("finger")); |
2629 | if (tmp != NULL) |
2617 | if (tmp != NULL) |
2630 | { |
2618 | { |
2631 | sprintf(buf,"%s's finger",op->name); |
2619 | sprintf(buf,"%s's finger", &op->name); |
2632 | tmp->name = add_string(buf); |
2620 | tmp->name = buf; |
2633 | sprintf(buf," This finger has been cut off %s\n" |
2621 | sprintf(buf," This finger has been cut off %s\n" |
2634 | " the %s, when he was defeated at\n level %d by %s.\n", |
2622 | " the %s, when he was defeated at\n level %d by %s.\n", |
2635 | op->name, op->contr->title, (int)(op->level), |
2623 | &op->name, op->contr->title, (int)(op->level), |
2636 | op->contr->killer); |
2624 | op->contr->killer); |
2637 | tmp->msg=add_string(buf); |
2625 | tmp->msg=buf; |
2638 | tmp->value=0, tmp->material=0, tmp->type=0; |
2626 | tmp->value=0, tmp->material=0, tmp->type=0; |
2639 | tmp->materialname = NULL; |
2627 | tmp->materialname = NULL; |
2640 | tmp->x = op->x, tmp->y = op->y; |
2628 | tmp->x = op->x, tmp->y = op->y; |
2641 | insert_ob_in_map(tmp,op->map,op,0); |
2629 | insert_ob_in_map(tmp,op->map,op,0); |
2642 | } |
2630 | } |
… | |
… | |
2656 | new_draw_info(NDI_UNIQUE, 0,op,"You would have starved, but you are"); |
2644 | new_draw_info(NDI_UNIQUE, 0,op,"You would have starved, but you are"); |
2657 | new_draw_info(NDI_UNIQUE, 0,op,"in explore mode, so..."); |
2645 | new_draw_info(NDI_UNIQUE, 0,op,"in explore mode, so..."); |
2658 | op->stats.food=999; |
2646 | op->stats.food=999; |
2659 | return; |
2647 | return; |
2660 | } |
2648 | } |
2661 | sprintf(buf,"%s starved to death.",op->name); |
2649 | sprintf(buf,"%s starved to death.",&op->name); |
2662 | strcpy(op->contr->killer,"starvation"); |
2650 | strcpy(op->contr->killer,"starvation"); |
2663 | } |
2651 | } |
2664 | else { |
2652 | else { |
2665 | if (op->contr->explore) { |
2653 | if (op->contr->explore) { |
2666 | new_draw_info(NDI_UNIQUE, 0,op,"You would have died, but you are"); |
2654 | new_draw_info(NDI_UNIQUE, 0,op,"You would have died, but you are"); |
2667 | new_draw_info(NDI_UNIQUE, 0,op,"in explore mode, so..."); |
2655 | new_draw_info(NDI_UNIQUE, 0,op,"in explore mode, so..."); |
2668 | op->stats.hp=op->stats.maxhp; |
2656 | op->stats.hp=op->stats.maxhp; |
2669 | return; |
2657 | return; |
2670 | } |
2658 | } |
2671 | sprintf(buf,"%s died.",op->name); |
2659 | sprintf(buf,"%s died.", &op->name); |
2672 | } |
2660 | } |
2673 | play_sound_player_only(op->contr, SOUND_PLAYER_DIES,0,0); |
2661 | play_sound_player_only(op->contr, SOUND_PLAYER_DIES,0,0); |
2674 | |
2662 | |
2675 | /* save the map location for corpse, gravestone*/ |
2663 | /* save the map location for corpse, gravestone*/ |
2676 | x=op->x;y=op->y;map=op->map; |
2664 | x=op->x;y=op->y;map=op->map; |
… | |
… | |
2793 | |
2781 | |
2794 | /* Put a gravestone up where the character 'almost' died. List the |
2782 | /* Put a gravestone up where the character 'almost' died. List the |
2795 | * exp loss on the stone. |
2783 | * exp loss on the stone. |
2796 | */ |
2784 | */ |
2797 | tmp=arch_to_object(find_archetype("gravestone")); |
2785 | tmp=arch_to_object(find_archetype("gravestone")); |
2798 | sprintf(buf,"%s's gravestone",op->name); |
2786 | sprintf(buf,"%s's gravestone",&op->name); tmp->name = buf; |
2799 | FREE_AND_COPY(tmp->name, buf); |
|
|
2800 | sprintf(buf,"%s's gravestones",op->name); |
2787 | sprintf(buf,"%s's gravestones",&op->name); tmp->name_pl = buf; |
2801 | FREE_AND_COPY(tmp->name_pl, buf); |
|
|
2802 | sprintf(buf,"RIP\nHere rests the hero %s the %s,\n" |
2788 | sprintf(buf,"RIP\nHere rests the hero %s the %s,\n" |
2803 | "who was killed\n" |
2789 | "who was killed\n" |
2804 | "by %s.\n", |
2790 | "by %s.\n", |
2805 | op->name, op->contr->title, |
2791 | &op->name, op->contr->title, |
2806 | op->contr->killer); |
2792 | op->contr->killer); |
2807 | tmp->msg = add_string(buf); |
2793 | tmp->msg = buf; |
2808 | tmp->x=op->x,tmp->y=op->y; |
2794 | tmp->x=op->x,tmp->y=op->y; |
2809 | insert_ob_in_map (tmp, op->map, NULL,0); |
2795 | insert_ob_in_map (tmp, op->map, NULL,0); |
2810 | |
2796 | |
2811 | /**************************************/ |
2797 | /**************************************/ |
2812 | /* */ |
2798 | /* */ |
… | |
… | |
2952 | } |
2938 | } |
2953 | play_again(op); |
2939 | play_again(op); |
2954 | |
2940 | |
2955 | /* peterm: added to create a corpse at deathsite. */ |
2941 | /* peterm: added to create a corpse at deathsite. */ |
2956 | tmp=arch_to_object(find_archetype("corpse_pl")); |
2942 | tmp=arch_to_object(find_archetype("corpse_pl")); |
2957 | sprintf(buf,"%s", op->name); |
2943 | sprintf(buf,"%s", &op->name); |
2958 | FREE_AND_COPY(tmp->name, buf); |
2944 | tmp->name = tmp->name_pl = buf; |
2959 | FREE_AND_COPY(tmp->name_pl, buf); |
|
|
2960 | tmp->level=op->level; |
2945 | tmp->level=op->level; |
2961 | tmp->x=x;tmp->y=y; |
2946 | tmp->x=x;tmp->y=y; |
2962 | if (tmp->msg) |
|
|
2963 | free_string(tmp->msg); |
|
|
2964 | tmp->msg = add_string (gravestone_text(op)); |
2947 | tmp->msg = gravestone_text(op); |
2965 | SET_FLAG (tmp, FLAG_UNIQUE); |
2948 | SET_FLAG (tmp, FLAG_UNIQUE); |
2966 | insert_ob_in_map (tmp, map, NULL,0); |
2949 | insert_ob_in_map (tmp, map, NULL,0); |
2967 | } |
2950 | } |
2968 | } |
2951 | } |
2969 | |
2952 | |
… | |
… | |
3008 | int old = pl->ob->carrying, sum = sum_weight(pl->ob); |
2991 | int old = pl->ob->carrying, sum = sum_weight(pl->ob); |
3009 | if(old == sum) |
2992 | if(old == sum) |
3010 | continue; |
2993 | continue; |
3011 | fix_player(pl->ob); |
2994 | fix_player(pl->ob); |
3012 | LOG(llevDebug,"Fixed inventory in %s (%d -> %d)\n", |
2995 | LOG(llevDebug,"Fixed inventory in %s (%d -> %d)\n", |
3013 | pl->ob->name, old, sum); |
2996 | &pl->ob->name, old, sum); |
3014 | } |
2997 | } |
3015 | } |
2998 | } |
3016 | |
2999 | |
3017 | void fix_luck(void) { |
3000 | void fix_luck(void) { |
3018 | player *pl; |
3001 | player *pl; |
… | |
… | |
3036 | |
3019 | |
3037 | /* casting POTION 'dusts' is really a use_magic_item skill */ |
3020 | /* casting POTION 'dusts' is really a use_magic_item skill */ |
3038 | if (op->type == PLAYER && throw_ob->type == POTION && !skop) |
3021 | if (op->type == PLAYER && throw_ob->type == POTION && !skop) |
3039 | { |
3022 | { |
3040 | LOG (llevError, "Player %s lacks critical skill use_magic_item!\n", |
3023 | LOG (llevError, "Player %s lacks critical skill use_magic_item!\n", |
3041 | op->name); |
3024 | &op->name); |
3042 | return; |
3025 | return; |
3043 | } |
3026 | } |
3044 | |
3027 | |
3045 | spob = throw_ob->inv; |
3028 | spob = throw_ob->inv; |
3046 | |
3029 | |
… | |
… | |
3048 | // not pass NULL to cast_spell (which did indeed check itself, but |
3031 | // not pass NULL to cast_spell (which did indeed check itself, but |
3049 | // errors should be reported as early as possible IMHO) |
3032 | // errors should be reported as early as possible IMHO) |
3050 | if (!spob) |
3033 | if (!spob) |
3051 | { |
3034 | { |
3052 | LOG (llevError, "cast_dust: thrown object %s (by %s) had no spell in it!", |
3035 | LOG (llevError, "cast_dust: thrown object %s (by %s) had no spell in it!", |
3053 | throw_ob->name, op->name); |
3036 | &throw_ob->name, &op->name); |
3054 | return; |
3037 | return; |
3055 | } |
3038 | } |
3056 | |
3039 | |
3057 | if (op->type == PLAYER) |
3040 | if (op->type == PLAYER) |
3058 | new_draw_info_format (NDI_UNIQUE, 0, op, "You cast %s.", spob->name); |
3041 | new_draw_info_format (NDI_UNIQUE, 0, op, "You cast %s.", &spob->name); |
3059 | |
3042 | |
3060 | cast_spell (op, throw_ob, dir, spob, NULL); |
3043 | cast_spell (op, throw_ob, dir, spob, NULL); |
3061 | |
3044 | |
3062 | if (!QUERY_FLAG (throw_ob, FLAG_REMOVED)) |
3045 | if (!QUERY_FLAG (throw_ob, FLAG_REMOVED)) |
3063 | remove_ob (throw_ob); |
3046 | remove_ob (throw_ob); |
… | |
… | |
3067 | void make_visible (object *op) { |
3050 | void make_visible (object *op) { |
3068 | op->hide = 0; |
3051 | op->hide = 0; |
3069 | op->invisible = 0; |
3052 | op->invisible = 0; |
3070 | if(op->type==PLAYER) { |
3053 | if(op->type==PLAYER) { |
3071 | op->contr->tmp_invis = 0; |
3054 | op->contr->tmp_invis = 0; |
3072 | if (op->contr->invis_race) FREE_AND_CLEAR_STR(op->contr->invis_race); |
3055 | op->contr->invis_race = 0; |
3073 | } |
3056 | } |
3074 | update_object(op,UP_OBJ_FACE); |
3057 | update_object(op,UP_OBJ_FACE); |
3075 | } |
3058 | } |
3076 | |
3059 | |
3077 | int is_true_undead(object *op) { |
3060 | int is_true_undead(object *op) { |
… | |
… | |
3356 | |
3339 | |
3357 | if (item->type == SPELL) { |
3340 | if (item->type == SPELL) { |
3358 | if (check_spell_known (who, item->name)) |
3341 | if (check_spell_known (who, item->name)) |
3359 | return; |
3342 | return; |
3360 | |
3343 | |
3361 | new_draw_info_format(NDI_UNIQUE|NDI_BLUE, 0, who, "You gained the ability of %s", item->name); |
3344 | new_draw_info_format(NDI_UNIQUE|NDI_BLUE, 0, who, "You gained the ability of %s", &item->name); |
3362 | do_learn_spell (who, item, 0); |
3345 | do_learn_spell (who, item, 0); |
3363 | return; |
3346 | return; |
3364 | } |
3347 | } |
3365 | |
3348 | |
3366 | /* grant direct spell */ |
3349 | /* grant direct spell */ |
3367 | if (item->type == SPELLBOOK) { |
3350 | if (item->type == SPELLBOOK) { |
3368 | if (!item->inv) { |
3351 | if (!item->inv) { |
3369 | LOG(llevDebug,"dragon_ability_gain: Broken spellbook %s\n", |
3352 | LOG(llevDebug,"dragon_ability_gain: Broken spellbook %s\n", &item->name); |
3370 | item->name); |
|
|
3371 | return; |
3353 | return; |
3372 | } |
3354 | } |
3373 | if (check_spell_known (who, item->inv->name)) |
3355 | if (check_spell_known (who, item->inv->name)) |
3374 | return; |
3356 | return; |
3375 | if (item->invisible) { |
3357 | if (item->invisible) { |
3376 | new_draw_info_format(NDI_UNIQUE|NDI_BLUE, 0, who, "You gained the ability of %s", item->inv->name); |
3358 | new_draw_info_format(NDI_UNIQUE|NDI_BLUE, 0, who, "You gained the ability of %s", &item->inv->name); |
3377 | do_learn_spell (who, item->inv, 0); |
3359 | do_learn_spell (who, item->inv, 0); |
3378 | return; |
3360 | return; |
3379 | } |
3361 | } |
3380 | } |
3362 | } |
3381 | else if (item->type == SKILL_TOOL && item->invisible) { |
3363 | else if (item->type == SKILL_TOOL && item->invisible) { |