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 | * |
… | |
… | |
237 | /* This changes the objects skill to new_skill. |
237 | /* This changes the objects skill to new_skill. |
238 | * note that this function doesn't always need to get used - |
238 | * note that this function doesn't always need to get used - |
239 | * you can now add skill exp to the player without the chosen_skill being |
239 | * you can now add skill exp to the player without the chosen_skill being |
240 | * set. This function is of most interest to players to update |
240 | * set. This function is of most interest to players to update |
241 | * the various range information. |
241 | * the various range information. |
242 | * if new_skill is null, this just unapplies the skill. |
|
|
243 | * flag has the current meaning: |
|
|
244 | * 0x1: If set, don't update the range pointer. This is useful when we |
|
|
245 | * need to ready a new skill, but don't want to clobber range. |
|
|
246 | * return 1 on success, 0 on error |
242 | * return 1 on success, 0 on error |
247 | */ |
243 | */ |
248 | int |
244 | int |
249 | change_skill (object *who, object *new_skill, int flag) |
245 | change_skill (object *who, object *new_skill, int flag) |
250 | { |
246 | { |
251 | int old_range; |
|
|
252 | |
|
|
253 | if (who->type != PLAYER) |
247 | if (who->type != PLAYER) |
254 | return 0; |
248 | return 0; |
255 | |
249 | |
|
|
250 | if (!new_skill) |
|
|
251 | { |
|
|
252 | LOG (llevError | logBacktrace, "change_skill called on %s with NULL skill\n", |
|
|
253 | who->debug_desc ()); |
|
|
254 | return 0; |
|
|
255 | } |
|
|
256 | |
256 | player *pl = who->contr; |
257 | 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 | |
258 | |
270 | // move skill to front, so it will be preferred next time |
259 | // move skill to front, so it will be preferred next time |
271 | new_skill->remove (); |
260 | new_skill->remove (); |
272 | who->insert (new_skill); |
261 | who->insert (new_skill); |
273 | |
262 | |
… | |
… | |
285 | { |
274 | { |
286 | who->chosen_skill = 0; |
275 | who->chosen_skill = 0; |
287 | CLEAR_FLAG (who, FLAG_READY_SKILL); |
276 | CLEAR_FLAG (who, FLAG_READY_SKILL); |
288 | |
277 | |
289 | if (who->type == PLAYER) |
278 | if (who->type == PLAYER) |
290 | { |
|
|
291 | if (who->contr->ranged_skill && who->contr->ranged_skill->type == SKILL) |
279 | if (who->contr->ranged_ob && who->contr->ranged_ob->type == SKILL) |
292 | { |
|
|
293 | who->contr->ranged_skill = 0; |
|
|
294 | who->contr->ranged_ob = 0; |
280 | who->contr->ranged_ob = 0; |
295 | } |
|
|
296 | } |
|
|
297 | } |
281 | } |
298 | |
282 | |
299 | /* do_skill() - Main skills use function-similar in scope to cast_spell(). |
283 | /* 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. |
284 | * We handle all requests for skill use outside of some combat here. |
301 | * We require a separate routine outside of fire() so as to allow monsters |
285 | * We require a separate routine outside of fire() so as to allow monsters |
… | |
… | |
892 | * is readied either then try to find a skill for the player to use. |
876 | * 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, |
877 | * 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 |
878 | * 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. |
879 | * through that code if skill is set to change to the skill. |
896 | */ |
880 | */ |
897 | if (op->type == PLAYER) |
881 | if (player *pl = op->contr) |
898 | { |
882 | { |
899 | if (!QUERY_FLAG (op, FLAG_READY_WEAPON)) |
883 | if (!pl->combat_ob) |
900 | { |
884 | { |
901 | if (!skill) |
885 | if (QUERY_FLAG (op, FLAG_READY_WEAPON)) |
902 | { |
886 | { |
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) |
887 | for (tmp = op->inv; tmp; tmp = tmp->below) |
939 | if (tmp->type == WEAPON && QUERY_FLAG (tmp, FLAG_APPLIED)) |
888 | if (tmp->type == WEAPON && QUERY_FLAG (tmp, FLAG_APPLIED)) |
940 | break; |
889 | break; |
941 | |
890 | |
942 | if (!tmp) |
891 | if (!tmp) |
943 | { |
892 | { |
944 | LOG (llevError, "Could not find applied weapon on %s\n", &op->name); |
893 | LOG (llevError, "Could not find applied weapon on %s\n", &op->name); |
945 | op->current_weapon = NULL; |
|
|
946 | return 0; |
894 | return 0; |
947 | } |
895 | } |
948 | else |
896 | |
949 | op->current_weapon = tmp; |
897 | change_skill (op, find_skill_by_name (op, tmp->skill), 1); |
950 | } |
898 | } |
|
|
899 | else |
|
|
900 | { |
|
|
901 | if (!skill) |
|
|
902 | { |
|
|
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); |
951 | |
911 | |
952 | change_skill (op, find_skill_by_name (op, op->current_weapon->skill), 1); |
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, op, "Couldn't change to skill %s", &skill->name); |
|
|
924 | return 0; |
|
|
925 | } |
953 | } |
926 | } |
954 | } |
|
|
955 | |
927 | |
|
|
928 | if (!pl->combat_ob) |
|
|
929 | { |
|
|
930 | LOG (llevError, "Could not find anything to attack on %s\n", &op->name); |
|
|
931 | return 0; |
|
|
932 | } |
|
|
933 | } |
|
|
934 | |
|
|
935 | op->set_weapon (pl->combat_ob); |
|
|
936 | |
956 | /* lose invisiblity/hiding status for running attacks */ |
937 | /* lose invisiblity/hiding status for running attacks */ |
957 | |
938 | if (pl->tmp_invis) |
958 | if (op->type == PLAYER && op->contr->tmp_invis) |
939 | { |
959 | { |
|
|
960 | op->contr->tmp_invis = 0; |
940 | pl->tmp_invis = 0; |
961 | op->invisible = 0; |
941 | op->invisible = 0; |
962 | op->hide = 0; |
942 | op->hide = 0; |
963 | update_object (op, UP_OBJ_CHANGE); |
943 | update_object (op, UP_OBJ_CHANGE); |
|
|
944 | } |
964 | } |
945 | } |
965 | |
946 | |
966 | int success = attack_ob (tmp, op); |
947 | int success = attack_ob (tmp, op); |
967 | |
948 | |
968 | /* print appropriate messages to the player */ |
949 | /* print appropriate messages to the player */ |
… | |
… | |
1039 | } |
1020 | } |
1040 | |
1021 | |
1041 | return do_skill_attack (tmp, pl, string, skill); |
1022 | return do_skill_attack (tmp, pl, string, skill); |
1042 | } |
1023 | } |
1043 | |
1024 | |
1044 | |
|
|
1045 | /* attack_hth() - this handles all hand-to-hand attacks -b.t. */ |
1025 | /* attack_hth() - this handles all hand-to-hand attacks -b.t. */ |
1046 | |
1026 | |
1047 | /* July 5, 1995 - I broke up attack_hth() into 2 parts. In the first |
1027 | /* July 5, 1995 - I broke up attack_hth() into 2 parts. In the first |
1048 | * (attack_hth) we check for weapon use, etc in the second (the new |
1028 | * (attack_hth) we check for weapon use, etc in the second (the new |
1049 | * function skill_attack() we actually attack. |
1029 | * function skill_attack() we actually attack. |
1050 | */ |
1030 | */ |
1051 | |
|
|
1052 | static int |
1031 | static int |
1053 | attack_hth (object *pl, int dir, const char *string, object *skill) |
1032 | attack_hth (object *pl, int dir, const char *string, object *skill) |
1054 | { |
1033 | { |
1055 | object *enemy = NULL, *weapon; |
1034 | object *enemy = NULL, *weapon; |
1056 | |
1035 | |
… | |
… | |
1065 | if (pl->type == PLAYER) |
1044 | if (pl->type == PLAYER) |
1066 | { |
1045 | { |
1067 | new_draw_info (NDI_UNIQUE, 0, pl, "You unwield your weapon in order to attack."); |
1046 | new_draw_info (NDI_UNIQUE, 0, pl, "You unwield your weapon in order to attack."); |
1068 | esrv_update_item (UPD_FLAGS, pl, weapon); |
1047 | esrv_update_item (UPD_FLAGS, pl, weapon); |
1069 | } |
1048 | } |
|
|
1049 | |
1070 | break; |
1050 | break; |
1071 | } |
1051 | } |
1072 | } |
1052 | } |
1073 | |
1053 | |
1074 | return skill_attack (enemy, pl, dir, string, skill); |
1054 | return skill_attack (enemy, pl, dir, string, skill); |