1 | /* |
1 | /* |
2 | CrossFire, A Multiplayer game for X-windows |
2 | CrossFire, A Multiplayer game for X-windows |
3 | |
3 | |
|
|
4 | Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team |
4 | Copyright (C) 2002 Mark Wedel & Crossfire Development Team |
5 | Copyright (C) 2002 Mark Wedel & Crossfire Development Team |
5 | Copyright (C) 1992 Frank Tore Johansen |
6 | Copyright (C) 1992 Frank Tore Johansen |
6 | |
7 | |
7 | 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 |
8 | 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 |
… | |
… | |
1006 | |
1007 | |
1007 | INVOKE_PLAYER (LOGOUT, op->contr); |
1008 | INVOKE_PLAYER (LOGOUT, op->contr); |
1008 | INVOKE_PLAYER (QUIT, op->contr); |
1009 | INVOKE_PLAYER (QUIT, op->contr); |
1009 | |
1010 | |
1010 | op->contr->enable_save = false; |
1011 | op->contr->enable_save = false; |
|
|
1012 | delete_character (op->name); |
1011 | |
1013 | |
1012 | terminate_all_pets (op); |
1014 | terminate_all_pets (op); |
1013 | op->remove (); |
1015 | op->remove (); |
1014 | op->direction = 0; |
1016 | op->direction = 0; |
1015 | new_draw_info_format (NDI_UNIQUE | NDI_ALL, 5, NULL, "%s quits the game.", &op->name); |
1017 | new_draw_info_format (NDI_UNIQUE | NDI_ALL, 5, NULL, "%s quits the game.", &op->name); |
… | |
… | |
2084 | */ |
2086 | */ |
2085 | if ((op->contr->braced || !move_ob (op, dir, op)) && !out_of_map (op->map, nx, ny)) |
2087 | if ((op->contr->braced || !move_ob (op, dir, op)) && !out_of_map (op->map, nx, ny)) |
2086 | { |
2088 | { |
2087 | if (OUT_OF_REAL_MAP (op->map, nx, ny)) |
2089 | if (OUT_OF_REAL_MAP (op->map, nx, ny)) |
2088 | { |
2090 | { |
2089 | m = get_map_from_coord (op->map, &nx, &ny); |
2091 | m = op->map->xy_find (nx, ny); |
2090 | if (!m) |
2092 | if (!m) |
2091 | return; /* Don't think this should happen */ |
2093 | return; /* Don't think this should happen */ |
2092 | } |
2094 | } |
2093 | else |
2095 | else |
2094 | m = op->map; |
2096 | m = op->map; |
2095 | |
2097 | |
2096 | if ((tmp = GET_MAP_OB (m, nx, ny)) == NULL) |
2098 | if (!(tmp = m->at (nx, ny).bot)) |
2097 | { |
|
|
2098 | /* LOG(llevError,"player_move_attack: GET_MAP_OB returns NULL, but player can not move there.\n"); */ |
|
|
2099 | return; |
2099 | return; |
2100 | } |
|
|
2101 | |
2100 | |
2102 | mon = 0; |
2101 | mon = 0; |
2103 | /* Go through all the objects, and find ones of interest. Only stop if |
2102 | /* Go through all the objects, and find ones of interest. Only stop if |
2104 | * we find a monster - that is something we know we want to attack. |
2103 | * we find a monster - that is something we know we want to attack. |
2105 | * if its a door or barrel (can roll) see if there may be monsters |
2104 | * if its a door or barrel (can roll) see if there may be monsters |
… | |
… | |
2158 | && (QUERY_FLAG (mon, FLAG_UNAGGRESSIVE) || QUERY_FLAG (mon, FLAG_FRIENDLY))) |
2157 | && (QUERY_FLAG (mon, FLAG_UNAGGRESSIVE) || QUERY_FLAG (mon, FLAG_FRIENDLY))) |
2159 | { |
2158 | { |
2160 | /* If we're braced, we don't want to switch places with it */ |
2159 | /* If we're braced, we don't want to switch places with it */ |
2161 | if (op->contr->braced) |
2160 | if (op->contr->braced) |
2162 | return; |
2161 | return; |
|
|
2162 | |
2163 | play_sound_map (op->map, op->x, op->y, SOUND_PUSH_PLAYER); |
2163 | play_sound_map (op->map, op->x, op->y, SOUND_PUSH_PLAYER); |
2164 | (void) push_ob (mon, dir, op); |
2164 | (void) push_ob (mon, dir, op); |
2165 | if (op->contr->tmp_invis || op->hide) |
2165 | if (op->contr->tmp_invis || op->hide) |
2166 | make_visible (op); |
2166 | make_visible (op); |
|
|
2167 | |
2167 | return; |
2168 | return; |
2168 | } |
2169 | } |
2169 | |
2170 | |
2170 | /* in certain circumstances, you shouldn't attack friendly |
2171 | /* in certain circumstances, you shouldn't attack friendly |
2171 | * creatures. Note that if you are braced, you can't push |
2172 | * creatures. Note that if you are braced, you can't push |
… | |
… | |
2185 | !on_battleground)) |
2186 | !on_battleground)) |
2186 | { |
2187 | { |
2187 | if (!op->contr->braced) |
2188 | if (!op->contr->braced) |
2188 | { |
2189 | { |
2189 | play_sound_map (op->map, op->x, op->y, SOUND_PUSH_PLAYER); |
2190 | play_sound_map (op->map, op->x, op->y, SOUND_PUSH_PLAYER); |
2190 | (void) push_ob (mon, dir, op); |
2191 | push_ob (mon, dir, op); |
2191 | } |
2192 | } |
2192 | else |
2193 | else |
2193 | new_draw_info (0, 0, op, "You withhold your attack"); |
2194 | new_draw_info (0, 0, op, "You withhold your attack"); |
2194 | |
2195 | |
2195 | if (op->contr->tmp_invis || op->hide) |
2196 | if (op->contr->tmp_invis || op->hide) |
… | |
… | |
2210 | * Way it works is like this: First, it must have some hit points |
2211 | * Way it works is like this: First, it must have some hit points |
2211 | * and be living. Then, it must be one of the following: |
2212 | * and be living. Then, it must be one of the following: |
2212 | * 1) Not a player, 2) A player, but of a different party. Note |
2213 | * 1) Not a player, 2) A player, but of a different party. Note |
2213 | * that party_number -1 is no party, so attacks can still happen. |
2214 | * that party_number -1 is no party, so attacks can still happen. |
2214 | */ |
2215 | */ |
2215 | |
|
|
2216 | else if ((mon->stats.hp >= 0) && QUERY_FLAG (mon, FLAG_ALIVE) && |
2216 | else if ((mon->stats.hp >= 0) && QUERY_FLAG (mon, FLAG_ALIVE) && |
2217 | ((mon->type != PLAYER || op->contr->party == NULL || op->contr->party != mon->contr->party))) |
2217 | ((mon->type != PLAYER || op->contr->party == NULL || op->contr->party != mon->contr->party))) |
2218 | { |
2218 | { |
2219 | |
2219 | |
2220 | /* If the player hasn't hit something this tick, and does |
2220 | /* If the player hasn't hit something this tick, and does |
… | |
… | |
2254 | int |
2254 | int |
2255 | move_player (object *op, int dir) |
2255 | move_player (object *op, int dir) |
2256 | { |
2256 | { |
2257 | int pick; |
2257 | int pick; |
2258 | |
2258 | |
2259 | if (op->map == NULL || op->map->in_memory != MAP_IN_MEMORY) |
2259 | if (!op->map || op->map->in_memory != MAP_IN_MEMORY) |
2260 | return 0; |
2260 | return 0; |
2261 | |
2261 | |
2262 | /* Sanity check: make sure dir is valid */ |
2262 | /* Sanity check: make sure dir is valid */ |
2263 | if ((dir < 0) || (dir >= 9)) |
2263 | if ((dir < 0) || (dir >= 9)) |
2264 | { |
2264 | { |
2265 | LOG (llevError, "move_player: invalid direction %d\n", dir); |
2265 | LOG (llevError, "move_player: invalid direction %d\n", dir); |
2266 | return 0; |
2266 | return 0; |
2267 | } |
2267 | } |
2268 | |
2268 | |
2269 | /* peterm: added following line */ |
2269 | /* peterm: added following line */ |
2270 | if (QUERY_FLAG (op, FLAG_CONFUSED) && dir) |
2270 | if (QUERY_FLAG (op, FLAG_CONFUSED) && dir) |
2271 | dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); |
2271 | dir = absdir (dir + RANDOM () % 3 + RANDOM () % 3 - 2); |
2272 | |
2272 | |
2273 | op->facing = dir; |
2273 | op->facing = dir; |
2274 | |
2274 | |
… | |
… | |
2352 | |
2352 | |
2353 | /* call this here - we also will call this in do_ericserver, but |
2353 | /* call this here - we also will call this in do_ericserver, but |
2354 | * the players time has been increased when doericserver has been |
2354 | * the players time has been increased when doericserver has been |
2355 | * called, so we recheck it here. |
2355 | * called, so we recheck it here. |
2356 | */ |
2356 | */ |
2357 | op->contr->ns->handle_command (); |
2357 | if (op->contr->ns->handle_command ()) |
|
|
2358 | return 1; |
2358 | |
2359 | |
2359 | if (op->speed_left < 0) |
2360 | if (op->speed_left > 0) |
2360 | return 0; |
2361 | { |
2361 | |
|
|
2362 | if (op->direction && (op->contr->run_on || op->contr->fire_on)) |
2362 | if (op->direction && (op->contr->run_on || op->contr->fire_on)) |
2363 | { |
2363 | { |
2364 | /* All move commands take 1 tick, at least for now */ |
2364 | /* All move commands take 1 tick, at least for now */ |
2365 | op->speed_left--; |
2365 | op->speed_left--; |
2366 | |
2366 | |
2367 | /* Instead of all the stuff below, let move_player take care |
2367 | /* Instead of all the stuff below, let move_player take care |
2368 | * of it. Also, some of the skill stuff is only put in |
2368 | * of it. Also, some of the skill stuff is only put in |
2369 | * there, as well as the confusion stuff. |
2369 | * there, as well as the confusion stuff. |
2370 | */ |
2370 | */ |
2371 | move_player (op, op->direction); |
2371 | move_player (op, op->direction); |
2372 | if (op->speed_left > 0) |
2372 | |
2373 | return 1; |
2373 | return op->speed_left > 0; |
2374 | else |
2374 | } |
2375 | return 0; |
|
|
2376 | } |
2375 | } |
2377 | |
2376 | |
2378 | return 0; |
2377 | return 0; |
2379 | } |
2378 | } |
2380 | |
2379 | |
… | |
… | |
2761 | " the %s, when he was defeated at\n level %d by %s.\n", |
2760 | " the %s, when he was defeated at\n level %d by %s.\n", |
2762 | &op->name, op->contr->title, (int) (op->level), op->contr->killer); |
2761 | &op->name, op->contr->title, (int) (op->level), op->contr->killer); |
2763 | tmp->msg = buf; |
2762 | tmp->msg = buf; |
2764 | tmp->value = 0, tmp->material = 0, tmp->type = 0; |
2763 | tmp->value = 0, tmp->material = 0, tmp->type = 0; |
2765 | tmp->materialname = NULL; |
2764 | tmp->materialname = NULL; |
2766 | op->insert_at (tmp, op); |
2765 | tmp->insert_at (op, tmp); |
2767 | } |
2766 | } |
2768 | |
2767 | |
2769 | /* teleport defeated player to new destination */ |
2768 | /* teleport defeated player to new destination */ |
2770 | transfer_ob (op, x, y, 0, NULL); |
2769 | transfer_ob (op, x, y, 0, NULL); |
2771 | op->contr->braced = 0; |
2770 | op->contr->braced = 0; |
… | |
… | |
3225 | |
3224 | |
3226 | skop = find_obj_by_type_subtype (op, SKILL, SK_HIDING); |
3225 | skop = find_obj_by_type_subtype (op, SKILL, SK_HIDING); |
3227 | |
3226 | |
3228 | /* its *extremely* hard to run and sneak/hide at the same time! */ |
3227 | /* its *extremely* hard to run and sneak/hide at the same time! */ |
3229 | if (op->type == PLAYER && op->contr->run_on) |
3228 | if (op->type == PLAYER && op->contr->run_on) |
3230 | { |
|
|
3231 | if (!skop || num >= skop->level) |
3229 | if (!skop || num >= skop->level) |
3232 | { |
3230 | { |
3233 | new_draw_info (NDI_UNIQUE, 0, op, "You ran too much! You are no longer hidden!"); |
3231 | new_draw_info (NDI_UNIQUE, 0, op, "You ran too much! You are no longer hidden!"); |
3234 | make_visible (op); |
3232 | make_visible (op); |
3235 | return; |
3233 | return; |
3236 | } |
3234 | } |
3237 | else |
3235 | else |
3238 | num += 20; |
3236 | num += 20; |
3239 | } |
3237 | |
3240 | num += op->map->difficulty; |
3238 | num += op->map->difficulty; |
3241 | hide = hideability (op); /* modify by terrain hidden level */ |
3239 | hide = hideability (op); /* modify by terrain hidden level */ |
3242 | num -= hide; |
3240 | num -= hide; |
|
|
3241 | |
3243 | if ((op->type == PLAYER && hide < -10) || ((op->invisible -= num) <= 0)) |
3242 | if ((op->type == PLAYER && hide < -10) || ((op->invisible -= num) <= 0)) |
3244 | { |
3243 | { |
3245 | make_visible (op); |
3244 | make_visible (op); |
3246 | if (op->type == PLAYER) |
3245 | if (op->type == PLAYER) |
3247 | new_draw_info (NDI_UNIQUE, 0, op, "You moved out of hiding! You are visible!"); |
3246 | new_draw_info (NDI_UNIQUE, 0, op, "You moved out of hiding! You are visible!"); |
3248 | } |
3247 | } |
3249 | else if (op->type == PLAYER && skop) |
3248 | else if (op->type == PLAYER && skop) |
3250 | { |
|
|
3251 | change_exp (op, calc_skill_exp (op, NULL, skop), skop->skill, 0); |
3249 | change_exp (op, calc_skill_exp (op, NULL, skop), skop->skill, 0); |
3252 | } |
|
|
3253 | } |
3250 | } |
3254 | |
3251 | |
3255 | /* determine if who is standing near a hostile creature. */ |
3252 | /* determine if who is standing near a hostile creature. */ |
3256 | |
3253 | |
3257 | int |
3254 | int |