… | |
… | |
1015 | * Handle apply on containers. |
1015 | * Handle apply on containers. |
1016 | * By Eneq(@csd.uu.se). |
1016 | * By Eneq(@csd.uu.se). |
1017 | * Moved to own function and added many features [Tero.Haatanen@lut.fi] |
1017 | * Moved to own function and added many features [Tero.Haatanen@lut.fi] |
1018 | * added the alchemical cauldron to the code -b.t. |
1018 | * added the alchemical cauldron to the code -b.t. |
1019 | */ |
1019 | */ |
1020 | |
|
|
1021 | int |
1020 | int |
1022 | apply_container (object *op, object *sack) |
1021 | apply_container (object *op, object *sack) |
1023 | { |
1022 | { |
1024 | char buf[MAX_BUF]; |
1023 | if (op->type != PLAYER || !op->contr->ns) |
1025 | object *tmp; |
|
|
1026 | |
|
|
1027 | if (op->type != PLAYER) |
|
|
1028 | return 0; /* This might change */ |
1024 | return 0; /* This might change */ |
1029 | |
1025 | |
1030 | if (sack == NULL || sack->type != CONTAINER) |
1026 | if (!sack || sack->type != CONTAINER) |
1031 | { |
1027 | { |
1032 | LOG (llevError, "apply_container: %s is not container!\n", sack ? &sack->name : "[nullobject]"); |
1028 | LOG (llevError, "apply_container: %s is not container!\n", sack ? &sack->name : "[nullobject]"); |
1033 | return 0; |
1029 | return 0; |
1034 | } |
1030 | } |
1035 | |
1031 | |
1036 | op->contr->last_used = 0; |
1032 | op->contr->last_used = 0; |
1037 | |
1033 | |
1038 | if (sack->env != op) |
1034 | if (sack->env && sack->env != op) |
|
|
1035 | { |
|
|
1036 | new_draw_info (NDI_UNIQUE, 0, op, "You must put it onto the floor or into your inventory first."); |
|
|
1037 | return 1; |
1039 | { |
1038 | } |
1040 | if (sack->other_arch == NULL || sack->env != NULL) |
1039 | |
|
|
1040 | // already applied == open on ground, or open in inv, or active in inv |
|
|
1041 | if (sack->flag [FLAG_APPLIED]) |
|
|
1042 | { |
|
|
1043 | if (op->container == sack) |
1041 | { |
1044 | { |
1042 | new_draw_info (NDI_UNIQUE, 0, op, "You must get it first."); |
1045 | // open on ground or inv, so close |
|
|
1046 | op->close_container (); |
1043 | return 1; |
1047 | return 1; |
1044 | } |
1048 | } |
1045 | |
1049 | else if (!sack->env) |
1046 | /* It's on the ground, the problems begin */ |
|
|
1047 | if (op->container != sack) |
|
|
1048 | { |
|
|
1049 | /* it's closed OR some player has opened it */ |
|
|
1050 | if (QUERY_FLAG (sack, FLAG_APPLIED)) |
|
|
1051 | { |
1050 | { |
1052 | for (tmp = GET_MAP_OB (sack->map, sack->x, sack->y); tmp && tmp->container != sack; tmp = tmp->above); |
1051 | // active, but not ours: some other player has opened it |
1053 | if (tmp) |
|
|
1054 | { |
|
|
1055 | /* some other player have opened it */ |
|
|
1056 | new_draw_info_format (NDI_UNIQUE, 0, op, "%s is already occupied.", query_name (sack)); |
1052 | new_draw_info_format (NDI_UNIQUE, 0, op, "%s is already occupied.", query_name (sack)); |
1057 | return 1; |
1053 | return 1; |
1058 | } |
|
|
1059 | } |
|
|
1060 | } |
|
|
1061 | if (QUERY_FLAG (sack, FLAG_APPLIED)) |
|
|
1062 | { |
1054 | } |
1063 | if (op->container == NULL) |
|
|
1064 | { |
|
|
1065 | tmp = arch_to_object (sack->other_arch); |
|
|
1066 | /* not good, but insert_ob_in_ob() is too smart */ |
|
|
1067 | CLEAR_FLAG (tmp, FLAG_REMOVED); |
|
|
1068 | tmp->x = tmp->y = 0; |
|
|
1069 | tmp->map = NULL; |
|
|
1070 | tmp->env = sack; |
|
|
1071 | if (sack->inv) |
|
|
1072 | sack->inv->above = tmp; |
|
|
1073 | tmp->below = sack->inv; |
|
|
1074 | tmp->above = NULL; |
|
|
1075 | sack->inv = tmp; |
|
|
1076 | sack->move_off = MOVE_ALL; /* trying force closing it */ |
|
|
1077 | } |
|
|
1078 | else |
|
|
1079 | { |
|
|
1080 | sack->move_off = 0; |
|
|
1081 | tmp = sack->inv; |
|
|
1082 | |
1055 | |
1083 | if (tmp && tmp->type == CLOSE_CON) |
1056 | // fall through to opening it (active in inv) |
1084 | tmp->destroy (); |
|
|
1085 | } |
|
|
1086 | } |
|
|
1087 | } |
|
|
1088 | |
|
|
1089 | if (QUERY_FLAG (sack, FLAG_APPLIED)) |
|
|
1090 | { |
1057 | } |
|
|
1058 | else if (sack->env) |
|
|
1059 | { |
|
|
1060 | // it is in our env, so activate it, do not open yet |
1091 | if (op->container) |
1061 | op->close_container (); |
1092 | { |
1062 | sack->flag [FLAG_APPLIED] = 1; |
1093 | if (op->container != sack) |
1063 | esrv_update_item (UPD_FLAGS, op, sack); |
1094 | { |
1064 | return 1; |
1095 | tmp = op->container; |
1065 | } |
1096 | apply_container (op, tmp); |
1066 | |
1097 | sprintf (buf, "You close %s and open ", query_name (tmp)); |
1067 | // it's locked? |
1098 | op->container = sack; |
1068 | if (sack->slaying) |
1099 | strcat (buf, query_name (sack)); |
1069 | { |
1100 | strcat (buf, "."); |
1070 | if (object *tmp = find_key (op, op, sack)) |
1101 | } |
1071 | new_draw_info_format (NDI_UNIQUE, 0, op, "You unlock %s with %s.", query_name (sack), query_name (tmp)); |
1102 | else |
|
|
1103 | { |
|
|
1104 | CLEAR_FLAG (sack, FLAG_APPLIED); |
|
|
1105 | op->container = NULL; |
|
|
1106 | sprintf (buf, "You close %s.", query_name (sack)); |
|
|
1107 | } |
|
|
1108 | } |
|
|
1109 | else |
1072 | else |
1110 | { |
1073 | { |
1111 | CLEAR_FLAG (sack, FLAG_APPLIED); |
|
|
1112 | sprintf (buf, "You open %s.", query_name (sack)); |
|
|
1113 | SET_FLAG (sack, FLAG_APPLIED); |
|
|
1114 | op->container = sack; |
|
|
1115 | } |
|
|
1116 | } |
|
|
1117 | else |
|
|
1118 | { /* not applied */ |
|
|
1119 | if (sack->slaying) |
|
|
1120 | { /* it's locked */ |
|
|
1121 | tmp = find_key (op, op, sack); |
|
|
1122 | if (tmp) |
|
|
1123 | { |
|
|
1124 | sprintf (buf, "You unlock %s with %s.", query_name (sack), query_name (tmp)); |
|
|
1125 | SET_FLAG (sack, FLAG_APPLIED); |
|
|
1126 | |
|
|
1127 | if (sack->env == NULL) |
|
|
1128 | { /* if it's on ground,open it also */ |
|
|
1129 | new_draw_info (NDI_UNIQUE, 0, op, buf); |
|
|
1130 | apply_container (op, sack); |
|
|
1131 | return 1; |
|
|
1132 | } |
|
|
1133 | } |
|
|
1134 | else |
|
|
1135 | sprintf (buf, "You don't have the key to unlock %s.", query_name (sack)); |
1074 | new_draw_info_format (NDI_UNIQUE, 0, op, "You don't have the key to unlock %s.", query_name (sack)); |
1136 | } |
|
|
1137 | else |
|
|
1138 | { |
|
|
1139 | sprintf (buf, "You readied %s.", query_name (sack)); |
|
|
1140 | SET_FLAG (sack, FLAG_APPLIED); |
|
|
1141 | |
|
|
1142 | if (sack->env == NULL) |
|
|
1143 | { /* if it's on ground,open it also */ |
|
|
1144 | new_draw_info (NDI_UNIQUE, 0, op, buf); |
|
|
1145 | apply_container (op, sack); |
|
|
1146 | return 1; |
1075 | return 1; |
1147 | } |
1076 | } |
1148 | } |
|
|
1149 | } |
1077 | } |
1150 | |
1078 | |
1151 | new_draw_info (NDI_UNIQUE, 0, op, buf); |
1079 | op->open_container (sack); |
1152 | |
|
|
1153 | if (op->contr) |
|
|
1154 | op->contr->ns->floorbox_update (); |
|
|
1155 | |
1080 | |
1156 | return 1; |
1081 | return 1; |
1157 | } |
1082 | } |
1158 | |
|
|
1159 | /** |
|
|
1160 | * Eneq(@csd.uu.se): Handle apply on containers. This is for containers |
|
|
1161 | * the player has in their inventory, eg, sacks, luggages, etc. |
|
|
1162 | * |
|
|
1163 | * Moved to own function and added many features [Tero.Haatanen@lut.fi] |
|
|
1164 | * This version is for client/server mode. |
|
|
1165 | * op is the player, sack is the container the player is opening or closing. |
|
|
1166 | * return 1 if an object is apllied somehow or another, 0 if error/no apply |
|
|
1167 | * |
|
|
1168 | * Reminder - there are three states for any container - closed (non applied), |
|
|
1169 | * applied (not open, but objects that match get tossed into it), and open |
|
|
1170 | * (applied flag set, and op->container points to the open container) |
|
|
1171 | */ |
|
|
1172 | |
|
|
1173 | int |
|
|
1174 | esrv_apply_container (object *op, object *sack) |
|
|
1175 | { |
|
|
1176 | object *tmp = op->container; |
|
|
1177 | |
|
|
1178 | if (op->type != PLAYER) |
|
|
1179 | return 0; /* This might change */ |
|
|
1180 | |
|
|
1181 | if (sack == NULL || sack->type != CONTAINER) |
|
|
1182 | { |
|
|
1183 | LOG (llevError, "esrv_apply_container: %s is not container!\n", sack ? &sack->name : "[nullobject]"); |
|
|
1184 | return 0; |
|
|
1185 | } |
|
|
1186 | |
|
|
1187 | /* If we have a currently open container, then it needs to be closed in all cases |
|
|
1188 | * if we are opening this one up. We then fall through if appropriate for |
|
|
1189 | * openening the new container. |
|
|
1190 | */ |
|
|
1191 | |
|
|
1192 | if (op->container && QUERY_FLAG (sack, FLAG_APPLIED)) |
|
|
1193 | { |
|
|
1194 | if (op->container->env != op) |
|
|
1195 | { /* if container is on the ground */ |
|
|
1196 | op->container->move_off = 0; |
|
|
1197 | } |
|
|
1198 | |
|
|
1199 | if (INVOKE_OBJECT (CLOSE, tmp, ARG_OBJECT (op))) |
|
|
1200 | return 1; |
|
|
1201 | |
|
|
1202 | new_draw_info_format (NDI_UNIQUE, 0, op, "You close %s.", query_name (op->container)); |
|
|
1203 | CLEAR_FLAG (op->container, FLAG_APPLIED); |
|
|
1204 | op->container = NULL; |
|
|
1205 | esrv_update_item (UPD_FLAGS, op, tmp); |
|
|
1206 | if (tmp == sack) |
|
|
1207 | return 1; |
|
|
1208 | } |
|
|
1209 | |
|
|
1210 | |
|
|
1211 | /* If the player is trying to open it (which he must be doing if we got here), |
|
|
1212 | * and it is locked, check to see if player has the equipment to open it. |
|
|
1213 | */ |
|
|
1214 | |
|
|
1215 | if (sack->slaying) |
|
|
1216 | { /* it's locked */ |
|
|
1217 | tmp = find_key (op, op, sack); |
|
|
1218 | if (tmp) |
|
|
1219 | { |
|
|
1220 | new_draw_info_format (NDI_UNIQUE, 0, op, "You unlock %s with %s.", query_name (sack), query_name (tmp)); |
|
|
1221 | } |
|
|
1222 | else |
|
|
1223 | { |
|
|
1224 | new_draw_info_format (NDI_UNIQUE, 0, op, "You don't have the key to unlock %s.", query_name (sack)); |
|
|
1225 | return 0; |
|
|
1226 | } |
|
|
1227 | } |
|
|
1228 | |
|
|
1229 | /* By the time we get here, we have made sure any other container has been closed and |
|
|
1230 | * if this is a locked container, the player they key to open it. |
|
|
1231 | */ |
|
|
1232 | |
|
|
1233 | /* There are really two cases - the sack is either on the ground, or the sack is |
|
|
1234 | * part of the players inventory. If on the ground, we assume that the player is |
|
|
1235 | * opening it, since if it was being closed, that would have been taken care of above. |
|
|
1236 | */ |
|
|
1237 | |
|
|
1238 | |
|
|
1239 | if (sack->env != op) |
|
|
1240 | { |
|
|
1241 | /* Hypothetical case - the player is trying to open a sack that belong to someone |
|
|
1242 | * else. This normally should not happen, but a misbehaving client/player could |
|
|
1243 | * try to do it, so lets handle it gracefully. |
|
|
1244 | */ |
|
|
1245 | if (sack->env) |
|
|
1246 | { |
|
|
1247 | new_draw_info_format (NDI_UNIQUE, 0, op, "You can't open %s", query_name (sack)); |
|
|
1248 | return 0; |
|
|
1249 | } |
|
|
1250 | /* set these so when the player walks off, we can unapply the sack */ |
|
|
1251 | sack->move_off = MOVE_ALL; /* trying force closing it */ |
|
|
1252 | |
|
|
1253 | CLEAR_FLAG (sack, FLAG_APPLIED); |
|
|
1254 | new_draw_info_format (NDI_UNIQUE, 0, op, "You open %s.", query_name (sack)); |
|
|
1255 | SET_FLAG (sack, FLAG_APPLIED); |
|
|
1256 | op->container = sack; |
|
|
1257 | esrv_update_item (UPD_FLAGS, op, sack); |
|
|
1258 | esrv_send_inventory (op, sack); |
|
|
1259 | |
|
|
1260 | } |
|
|
1261 | else |
|
|
1262 | { /* sack is in players inventory */ |
|
|
1263 | if (QUERY_FLAG (sack, FLAG_APPLIED)) |
|
|
1264 | { /* readied sack becoming open */ |
|
|
1265 | CLEAR_FLAG (sack, FLAG_APPLIED); |
|
|
1266 | new_draw_info_format (NDI_UNIQUE, 0, op, "You open %s.", query_name (sack)); |
|
|
1267 | SET_FLAG (sack, FLAG_APPLIED); |
|
|
1268 | op->container = sack; |
|
|
1269 | esrv_update_item (UPD_FLAGS, op, sack); |
|
|
1270 | esrv_send_inventory (op, sack); |
|
|
1271 | } |
|
|
1272 | else |
|
|
1273 | { |
|
|
1274 | CLEAR_FLAG (sack, FLAG_APPLIED); |
|
|
1275 | new_draw_info_format (NDI_UNIQUE, 0, op, "You readied %s.", query_name (sack)); |
|
|
1276 | SET_FLAG (sack, FLAG_APPLIED); |
|
|
1277 | esrv_update_item (UPD_FLAGS, op, sack); |
|
|
1278 | } |
|
|
1279 | } |
|
|
1280 | return 1; |
|
|
1281 | } |
|
|
1282 | |
|
|
1283 | |
1083 | |
1284 | /** |
1084 | /** |
1285 | * Handles dropping things on altar. |
1085 | * Handles dropping things on altar. |
1286 | * Returns true if sacrifice was accepted. |
1086 | * Returns true if sacrifice was accepted. |
1287 | */ |
1087 | */ |
… | |
… | |
1700 | |
1500 | |
1701 | apply_sign (victim, trap, 1); |
1501 | apply_sign (victim, trap, 1); |
1702 | goto leave; |
1502 | goto leave; |
1703 | |
1503 | |
1704 | case CONTAINER: |
1504 | case CONTAINER: |
1705 | if (victim->type == PLAYER) |
|
|
1706 | (void) esrv_apply_container (victim, trap); |
|
|
1707 | else |
|
|
1708 | (void) apply_container (victim, trap); |
1505 | apply_container (victim, trap); |
1709 | goto leave; |
1506 | goto leave; |
1710 | |
1507 | |
1711 | case RUNE: |
1508 | case RUNE: |
1712 | case TRAP: |
1509 | case TRAP: |
1713 | if (trap->level && QUERY_FLAG (victim, FLAG_ALIVE)) |
1510 | if (trap->level && QUERY_FLAG (victim, FLAG_ALIVE)) |
… | |
… | |
2610 | case POTION: |
2407 | case POTION: |
2611 | (void) apply_potion (op, tmp); |
2408 | (void) apply_potion (op, tmp); |
2612 | return 1; |
2409 | return 1; |
2613 | |
2410 | |
2614 | /* Eneq(@csd.uu.se): Handle apply on containers. */ |
2411 | /* Eneq(@csd.uu.se): Handle apply on containers. */ |
|
|
2412 | //TODO: remove, as it is unsed? |
2615 | case CLOSE_CON: |
2413 | case CLOSE_CON: |
2616 | if (op->type == PLAYER) |
|
|
2617 | (void) esrv_apply_container (op, tmp->env); |
|
|
2618 | else |
|
|
2619 | (void) apply_container (op, tmp->env); |
2414 | apply_container (op, tmp->env); |
2620 | return 1; |
2415 | return 1; |
2621 | |
2416 | |
2622 | case CONTAINER: |
2417 | case CONTAINER: |
2623 | if (op->type == PLAYER) |
|
|
2624 | (void) esrv_apply_container (op, tmp); |
|
|
2625 | else |
|
|
2626 | (void) apply_container (op, tmp); |
2418 | apply_container (op, tmp); |
2627 | return 1; |
2419 | return 1; |
2628 | |
2420 | |
2629 | case TREASURE: |
2421 | case TREASURE: |
2630 | if (op->type == PLAYER) |
2422 | if (op->type == PLAYER) |
2631 | { |
2423 | { |
2632 | apply_treasure (op, tmp); |
2424 | apply_treasure (op, tmp); |
2633 | return 1; |
2425 | return 1; |
2634 | } |
2426 | } |
2635 | else |
2427 | else |
2636 | { |
|
|
2637 | return 0; |
2428 | return 0; |
2638 | } |
|
|
2639 | |
2429 | |
2640 | case WEAPON: |
2430 | case WEAPON: |
2641 | case ARMOUR: |
2431 | case ARMOUR: |
2642 | case BOOTS: |
2432 | case BOOTS: |
2643 | case GLOVES: |
2433 | case GLOVES: |
… | |
… | |
2795 | */ |
2585 | */ |
2796 | |
2586 | |
2797 | void |
2587 | void |
2798 | player_apply_below (object *pl) |
2588 | player_apply_below (object *pl) |
2799 | { |
2589 | { |
2800 | object *tmp, *next; |
|
|
2801 | int floors; |
2590 | int floors = 0; |
2802 | |
2591 | |
2803 | /* If using a container, set the starting item to be the top |
2592 | /* If using a container, set the starting item to be the top |
2804 | * item in the container. Otherwise, use the map. |
2593 | * item in the container. Otherwise, use the map. |
2805 | */ |
|
|
2806 | tmp = (pl->container != NULL) ? pl->container->inv : pl->below; |
|
|
2807 | |
|
|
2808 | /* This is perhaps more complicated. However, I want to make sure that |
2594 | * This is perhaps more complicated. However, I want to make sure that |
2809 | * we don't use a corrupt pointer for the next object, so we get the |
2595 | * we don't use a corrupt pointer for the next object, so we get the |
2810 | * next object in the stack before applying. This is can only be a |
2596 | * next object in the stack before applying. This is can only be a |
2811 | * problem if player_apply() has a bug in that it uses the object but does |
2597 | * problem if player_apply() has a bug in that it uses the object but does |
2812 | * not return a proper value. |
2598 | * not return a proper value. |
2813 | */ |
2599 | */ |
2814 | for (floors = 0; tmp != NULL; tmp = next) |
2600 | for (object *next, *tmp = pl->container ? pl->container->inv : pl->below; tmp; tmp = next) |
2815 | { |
2601 | { |
2816 | next = tmp->below; |
2602 | next = tmp->below; |
|
|
2603 | |
2817 | if (QUERY_FLAG (tmp, FLAG_IS_FLOOR)) |
2604 | if (QUERY_FLAG (tmp, FLAG_IS_FLOOR)) |
2818 | floors++; |
2605 | floors++; |
2819 | else if (floors > 0) |
2606 | else if (floors > 0) |
2820 | return; /* process only floor objects after first floor object */ |
2607 | return; /* process only floor objects after first floor object */ |
2821 | |
2608 | |
… | |
… | |
3677 | } |
3464 | } |
3678 | return tmp ? 1 : 0; |
3465 | return tmp ? 1 : 0; |
3679 | } |
3466 | } |
3680 | |
3467 | |
3681 | /** |
3468 | /** |
3682 | * fix_auto_apply goes through the entire map (only the first time |
3469 | * fix_auto_apply goes through the entire map every time a map |
3683 | * when an original map is loaded) and performs special actions for |
3470 | * is loaded or swapped in and performs special actions for |
3684 | * certain objects (most initialization of chests and creation of |
3471 | * certain objects (most initialization of chests and creation of |
3685 | * treasures and stuff). Calls auto_apply if appropriate. |
3472 | * treasures and stuff). Calls auto_apply if appropriate. |
3686 | */ |
3473 | */ |
3687 | void |
3474 | void |
3688 | maptile::fix_auto_apply () |
3475 | maptile::fix_auto_apply () |
… | |
… | |
3765 | && tmp->type != PLAYER_CHANGER && tmp->type != CLASS && tmp->has_random_items ()) |
3552 | && tmp->type != PLAYER_CHANGER && tmp->type != CLASS && tmp->has_random_items ()) |
3766 | { |
3553 | { |
3767 | create_treasure (tmp->randomitems, tmp, GT_APPLY, difficulty, 0); |
3554 | create_treasure (tmp->randomitems, tmp, GT_APPLY, difficulty, 0); |
3768 | tmp->randomitems = NULL; |
3555 | tmp->randomitems = NULL; |
3769 | } |
3556 | } |
|
|
3557 | // close all containers |
|
|
3558 | else if (tmp->type == CONTAINER) |
|
|
3559 | tmp->flag [FLAG_APPLIED] = 0; |
3770 | |
3560 | |
3771 | tmp = above; |
3561 | tmp = above; |
3772 | } |
3562 | } |
3773 | |
3563 | |
3774 | for (mapspace *ms = spaces + size (); ms-- > spaces; ) |
3564 | for (mapspace *ms = spaces + size (); ms-- > spaces; ) |