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 | * Copryight (C) 2002 Mark Wedel & Crossfire Development Team |
5 | * Copryight (C) 2002 Mark Wedel & Crossfire Development Team |
6 | * Copyright (C) 1992 Frank Tore Johansen |
6 | * Copyright (C) 1992 Frank Tore Johansen |
7 | * |
7 | * |
… | |
… | |
246 | * return 1 on success, 0 on error |
246 | * return 1 on success, 0 on error |
247 | */ |
247 | */ |
248 | int |
248 | int |
249 | change_skill (object *who, object *new_skill, int flag) |
249 | change_skill (object *who, object *new_skill, int flag) |
250 | { |
250 | { |
251 | int old_range; |
|
|
252 | |
|
|
253 | if (who->type != PLAYER) |
251 | if (who->type != PLAYER) |
254 | return 0; |
252 | return 0; |
255 | |
253 | |
|
|
254 | if (!new_skill) |
|
|
255 | { |
|
|
256 | LOG (llevError | logBacktrace, "change_skill called on %s with NULL skill\n", |
|
|
257 | who->debug_desc ()); |
|
|
258 | return 0; |
|
|
259 | } |
|
|
260 | |
256 | player *pl = who->contr; |
261 | player *pl = who->contr; |
257 | |
|
|
258 | if (pl->ranged_skill && pl->ranged_skill == new_skill) |
|
|
259 | return 1; |
|
|
260 | |
|
|
261 | if (!new_skill) |
|
|
262 | { |
|
|
263 | if (pl->ranged_skill) |
|
|
264 | apply_special (who, pl->ranged_skill, AP_UNAPPLY); |
|
|
265 | |
|
|
266 | /* Only goal in this case was to unapply a skill */ |
|
|
267 | return 0; |
|
|
268 | } |
|
|
269 | |
262 | |
270 | // move skill to front, so it will be preferred next time |
263 | // move skill to front, so it will be preferred next time |
271 | new_skill->remove (); |
264 | new_skill->remove (); |
272 | who->insert (new_skill); |
265 | who->insert (new_skill); |
273 | |
266 | |
… | |
… | |
286 | who->chosen_skill = 0; |
279 | who->chosen_skill = 0; |
287 | CLEAR_FLAG (who, FLAG_READY_SKILL); |
280 | CLEAR_FLAG (who, FLAG_READY_SKILL); |
288 | |
281 | |
289 | if (who->type == PLAYER) |
282 | if (who->type == PLAYER) |
290 | { |
283 | { |
291 | if (who->contr->ranged_skill && who->contr->ranged_skill->type == SKILL) |
284 | if (who->contr->ranged_ob && who->contr->ranged_ob->type == SKILL) |
292 | { |
|
|
293 | who->contr->ranged_skill = 0; |
|
|
294 | who->contr->ranged_ob = 0; |
285 | who->contr->ranged_ob = 0; |
295 | } |
|
|
296 | } |
286 | } |
297 | } |
287 | } |
298 | |
288 | |
299 | /* do_skill() - Main skills use function-similar in scope to cast_spell(). |
289 | /* do_skill() - Main skills use function-similar in scope to cast_spell(). |
300 | * We handle all requests for skill use outside of some combat here. |
290 | * We handle all requests for skill use outside of some combat here. |
… | |
… | |
892 | * is readied either then try to find a skill for the player to use. |
882 | * is readied either then try to find a skill for the player to use. |
893 | * it is presumed that if skill is set, it is a valid attack skill (eg, |
883 | * it is presumed that if skill is set, it is a valid attack skill (eg, |
894 | * the caller should have set it appropriately). We still want to pass |
884 | * the caller should have set it appropriately). We still want to pass |
895 | * through that code if skill is set to change to the skill. |
885 | * through that code if skill is set to change to the skill. |
896 | */ |
886 | */ |
897 | if (op->type == PLAYER) |
887 | if (player *pl = op->contr) |
898 | { |
888 | { |
|
|
889 | if (!pl->combat_ob) |
|
|
890 | { |
899 | if (!QUERY_FLAG (op, FLAG_READY_WEAPON)) |
891 | if (QUERY_FLAG (op, FLAG_READY_WEAPON)) |
900 | { |
|
|
901 | if (!skill) |
|
|
902 | { |
892 | { |
903 | /* See if the players chosen skill is a combat skill, and use |
|
|
904 | * it if appropriate. |
|
|
905 | */ |
|
|
906 | if (op->chosen_skill && hth_skill_p (op->chosen_skill)) |
|
|
907 | skill = op->chosen_skill; |
|
|
908 | else |
|
|
909 | { |
|
|
910 | skill = find_player_hth_skill (op); |
|
|
911 | |
|
|
912 | if (!skill) |
|
|
913 | { |
|
|
914 | new_draw_info (NDI_BLACK, 0, op, "You have no unarmed combat skills!"); |
|
|
915 | return 0; |
|
|
916 | } |
|
|
917 | } |
|
|
918 | } |
|
|
919 | |
|
|
920 | /* now try to ready the new skill */ |
|
|
921 | if (!change_skill (op, skill, 0)) |
|
|
922 | { /* oh oh, trouble! */ |
|
|
923 | new_draw_info_format (NDI_UNIQUE, 0, tmp, "Couldn't change to skill %s", &skill->name); |
|
|
924 | return 0; |
|
|
925 | } |
|
|
926 | } |
|
|
927 | else |
|
|
928 | { |
|
|
929 | /* Seen some crashes below where current_weapon is not set, |
|
|
930 | * even though the flag says it is. So if current weapon isn't set, |
|
|
931 | * do some work in trying to find the object to use. |
|
|
932 | */ |
|
|
933 | if (!op->current_weapon) |
|
|
934 | { |
|
|
935 | object *tmp; |
|
|
936 | |
|
|
937 | LOG (llevError, "Player %s does not have current weapon set but flag_ready_weapon is set\n", &op->name); |
|
|
938 | for (tmp = op->inv; tmp; tmp = tmp->below) |
893 | for (tmp = op->inv; tmp; tmp = tmp->below) |
939 | if (tmp->type == WEAPON && QUERY_FLAG (tmp, FLAG_APPLIED)) |
894 | if (tmp->type == WEAPON && QUERY_FLAG (tmp, FLAG_APPLIED)) |
940 | break; |
895 | break; |
941 | |
896 | |
942 | if (!tmp) |
897 | if (!tmp) |
943 | { |
898 | { |
944 | LOG (llevError, "Could not find applied weapon on %s\n", &op->name); |
899 | LOG (llevError, "Could not find applied weapon on %s\n", &op->name); |
945 | op->current_weapon = NULL; |
|
|
946 | return 0; |
900 | return 0; |
947 | } |
901 | } |
948 | else |
902 | |
949 | op->current_weapon = tmp; |
903 | change_skill (op, find_skill_by_name (op, tmp->skill), 1); |
950 | } |
904 | } |
|
|
905 | else |
|
|
906 | { |
|
|
907 | if (!skill) |
|
|
908 | { |
|
|
909 | /* See if the players chosen skill is a combat skill, and use |
|
|
910 | * it if appropriate. |
|
|
911 | */ |
|
|
912 | if (op->chosen_skill && hth_skill_p (op->chosen_skill)) |
|
|
913 | skill = op->chosen_skill; |
|
|
914 | else |
|
|
915 | { |
|
|
916 | skill = find_player_hth_skill (op); |
951 | |
917 | |
952 | change_skill (op, find_skill_by_name (op, op->current_weapon->skill), 1); |
918 | if (!skill) |
|
|
919 | { |
|
|
920 | new_draw_info (NDI_BLACK, 0, op, "You have no unarmed combat skills!"); |
|
|
921 | return 0; |
|
|
922 | } |
|
|
923 | } |
|
|
924 | } |
|
|
925 | |
|
|
926 | /* now try to ready the new skill */ |
|
|
927 | if (!change_skill (op, skill, 0)) |
|
|
928 | { /* oh oh, trouble! */ |
|
|
929 | new_draw_info_format (NDI_UNIQUE, 0, tmp, "Couldn't change to skill %s", &skill->name); |
|
|
930 | return 0; |
|
|
931 | } |
|
|
932 | } |
|
|
933 | |
|
|
934 | if (!pl->combat_ob) |
|
|
935 | { |
|
|
936 | LOG (llevError, "Could not find anything to attack on %s\n", &op->name); |
|
|
937 | return 0; |
|
|
938 | } |
|
|
939 | } |
|
|
940 | |
|
|
941 | if (op->current_weapon != pl->combat_ob) |
953 | } |
942 | { |
954 | } |
943 | op->current_weapon = pl->combat_ob; |
|
|
944 | op->update_stats (); |
|
|
945 | } |
955 | |
946 | |
956 | /* lose invisiblity/hiding status for running attacks */ |
947 | /* lose invisiblity/hiding status for running attacks */ |
957 | |
948 | |
958 | if (op->type == PLAYER && op->contr->tmp_invis) |
949 | if (pl->tmp_invis) |
959 | { |
950 | { |
960 | op->contr->tmp_invis = 0; |
951 | pl->tmp_invis = 0; |
961 | op->invisible = 0; |
952 | op->invisible = 0; |
962 | op->hide = 0; |
953 | op->hide = 0; |
963 | update_object (op, UP_OBJ_CHANGE); |
954 | update_object (op, UP_OBJ_CHANGE); |
|
|
955 | } |
964 | } |
956 | } |
965 | |
957 | |
966 | int success = attack_ob (tmp, op); |
958 | int success = attack_ob (tmp, op); |
967 | |
959 | |
968 | /* print appropriate messages to the player */ |
960 | /* print appropriate messages to the player */ |