1 | /* |
1 | /* |
2 | * This file is part of Deliantra, the Roguelike Realtime MMORPG. |
2 | * This file is part of Deliantra, the Roguelike Realtime MMORPG. |
3 | * |
3 | * |
|
|
4 | * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team |
4 | * Copyright (©) 2005,2006,2007,2008,2009,2010,2011 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
5 | * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
5 | * Copyright (©) 2001-2003 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 2001-2003 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 1992 Frank Tore Johansen |
7 | * Copyright (©) 1992 Frank Tore Johansen |
7 | * |
8 | * |
8 | * Deliantra is free software: you can redistribute it and/or modify it under |
9 | * Deliantra is free software: you can redistribute it and/or modify it under |
9 | * the terms of the Affero GNU General Public License as published by the |
10 | * the terms of the Affero GNU General Public License as published by the |
10 | * Free Software Foundation, either version 3 of the License, or (at your |
11 | * Free Software Foundation, either version 3 of the License, or (at your |
11 | * option) any later version. |
12 | * option) any later version. |
12 | * |
13 | * |
13 | * This program is distributed in the hope that it will be useful, |
14 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. |
17 | * GNU General Public License for more details. |
17 | * |
18 | * |
18 | * You should have received a copy of the Affero GNU General Public License |
19 | * You should have received a copy of the Affero GNU General Public License |
19 | * and the GNU General Public License along with this program. If not, see |
20 | * and the GNU General Public License along with this program. If not, see |
20 | * <http://www.gnu.org/licenses/>. |
21 | * <http://www.gnu.org/licenses/>. |
21 | * |
22 | * |
22 | * The authors can be reached via e-mail to <support@deliantra.net> |
23 | * The authors can be reached via e-mail to <support@deliantra.net> |
23 | */ |
24 | */ |
24 | |
25 | |
25 | #include <unistd.h> |
26 | #include <unistd.h> |
26 | |
27 | |
… | |
… | |
59 | return mp->at (newx, newy).flags () | (mp != oldmap ? P_NEW_MAP : 0); |
60 | return mp->at (newx, newy).flags () | (mp != oldmap ? P_NEW_MAP : 0); |
60 | } |
61 | } |
61 | |
62 | |
62 | /* |
63 | /* |
63 | * Returns true if the given coordinate is blocked except by the |
64 | * Returns true if the given coordinate is blocked except by the |
64 | * object passed is not blocking. This is used with |
65 | * object passed is not blocking. This is used with |
65 | * multipart monsters - if we want to see if a 2x2 monster |
66 | * multipart monsters - if we want to see if a 2x2 monster |
66 | * can move 1 space to the left, we don't want its own area |
67 | * can move 1 space to the left, we don't want its own area |
67 | * to block it from moving there. |
68 | * to block it from moving there. |
68 | * Returns TRUE if the space is blocked by something other than the |
69 | * Returns TRUE if the space is blocked by something other than the |
69 | * monster. |
70 | * monster. |
… | |
… | |
405 | |
406 | |
406 | for (object *op = spaces [i].bot; op; op = op->above) |
407 | for (object *op = spaces [i].bot; op; op = op->above) |
407 | { |
408 | { |
408 | unique |= op->flag [FLAG_UNIQUE] && op->flag [FLAG_IS_FLOOR]; |
409 | unique |= op->flag [FLAG_UNIQUE] && op->flag [FLAG_IS_FLOOR]; |
409 | |
410 | |
410 | if (expect_false (!op->can_map_save ())) |
411 | if (ecb_expect_false (!op->can_map_save ())) |
411 | continue; |
412 | continue; |
412 | |
413 | |
413 | if (expect_false (unique || op->flag [FLAG_UNIQUE])) |
414 | if (ecb_expect_false (unique || op->flag [FLAG_UNIQUE])) |
414 | { |
415 | { |
415 | if (flags & IO_UNIQUES) |
416 | if (flags & IO_UNIQUES) |
416 | op->write (f); |
417 | op->write (f); |
417 | } |
418 | } |
418 | else if (expect_true (flags & IO_OBJECTS)) |
419 | else if (ecb_expect_true (flags & IO_OBJECTS)) |
419 | op->write (f); |
420 | op->write (f); |
420 | } |
421 | } |
421 | } |
422 | } |
422 | |
423 | |
423 | coroapi::cede_to_tick (); |
424 | coroapi::cede_to_tick (); |
… | |
… | |
483 | spaces = salloc0<mapspace> (size ()); |
484 | spaces = salloc0<mapspace> (size ()); |
484 | } |
485 | } |
485 | |
486 | |
486 | //+GPL |
487 | //+GPL |
487 | |
488 | |
488 | /* Takes a string from a map definition and outputs a pointer to the array of shopitems |
489 | /* Takes a string from a map definition and outputs a pointer to the array of shopitems |
489 | * corresponding to that string. Memory is allocated for this, it must be freed |
490 | * corresponding to that string. Memory is allocated for this, it must be freed |
490 | * at a later date. |
491 | * at a later date. |
491 | * Called by parse_map_headers below. |
492 | * Called by parse_map_headers below. |
492 | */ |
493 | */ |
493 | static shopitems * |
494 | static shopitems * |
494 | parse_shop_string (const char *input_string) |
495 | parse_shop_string (const char *input_string) |
… | |
… | |
549 | items[i].typenum = current_type->number; |
550 | items[i].typenum = current_type->number; |
550 | items[i].name_pl = current_type->name_pl; |
551 | items[i].name_pl = current_type->name_pl; |
551 | } |
552 | } |
552 | else |
553 | else |
553 | { /* oh uh, something's wrong, let's free up this one, and try |
554 | { /* oh uh, something's wrong, let's free up this one, and try |
554 | * the next entry while we're at it, better print a warning |
555 | * the next entry while we're at it, better print a warning |
555 | */ |
556 | */ |
556 | LOG (llevError, "invalid type %s defined in shopitems in string %s\n", p, input_string); |
557 | LOG (llevError, "invalid type %s defined in shopitems in string %s\n", p, input_string); |
557 | } |
558 | } |
558 | } |
559 | } |
559 | |
560 | |
… | |
… | |
837 | msg = 0; |
838 | msg = 0; |
838 | maplore = 0; |
839 | maplore = 0; |
839 | shoprace = 0; |
840 | shoprace = 0; |
840 | delete [] shopitems, shopitems = 0; |
841 | delete [] shopitems, shopitems = 0; |
841 | |
842 | |
842 | for (int i = 0; i < array_length (tile_path); i++) |
843 | for (int i = 0; i < ecb_array_length (tile_path); i++) |
843 | tile_path [i] = 0; |
844 | tile_path [i] = 0; |
844 | } |
845 | } |
845 | |
846 | |
846 | maptile::~maptile () |
847 | maptile::~maptile () |
847 | { |
848 | { |
… | |
… | |
854 | /* We need to look through all the maps and see if any maps |
855 | /* We need to look through all the maps and see if any maps |
855 | * are pointing at this one for tiling information. Since |
856 | * are pointing at this one for tiling information. Since |
856 | * tiling can be asymetric, we just can not look to see which |
857 | * tiling can be asymetric, we just can not look to see which |
857 | * maps this map tiles with and clears those. |
858 | * maps this map tiles with and clears those. |
858 | */ |
859 | */ |
859 | for (int i = 0; i < array_length (tile_path); i++) |
860 | for (int i = 0; i < ecb_array_length (tile_path); i++) |
860 | if (tile_map[i] == m) |
861 | if (tile_map[i] == m) |
861 | tile_map[i] = 0; |
862 | tile_map[i] = 0; |
862 | } |
863 | } |
863 | |
864 | |
864 | void |
865 | void |
… | |
… | |
1017 | update_all_map_los (this); |
1018 | update_all_map_los (this); |
1018 | |
1019 | |
1019 | return 1; |
1020 | return 1; |
1020 | } |
1021 | } |
1021 | |
1022 | |
1022 | /* |
1023 | /* |
1023 | * This function updates various attributes about a specific space |
1024 | * This function updates various attributes about a specific space |
1024 | * on the map (what it looks like, whether it blocks magic, |
1025 | * on the map (what it looks like, whether it blocks magic, |
1025 | * has a living creatures, prevents people from passing |
1026 | * has a living creatures, prevents people from passing |
1026 | * through, etc) |
1027 | * through, etc) |
1027 | */ |
1028 | */ |
… | |
… | |
1058 | * 3 times each time the player moves, because many of the |
1059 | * 3 times each time the player moves, because many of the |
1059 | * functions the move_player calls eventualy call this. |
1060 | * functions the move_player calls eventualy call this. |
1060 | * |
1061 | * |
1061 | * Always put the player down for drawing. |
1062 | * Always put the player down for drawing. |
1062 | */ |
1063 | */ |
1063 | if (expect_true (!tmp->invisible)) |
1064 | if (ecb_expect_true (!tmp->invisible)) |
1064 | { |
1065 | { |
1065 | if (expect_false (tmp->type == PLAYER || tmp->flag [FLAG_MONSTER])) |
1066 | if (ecb_expect_false (tmp->type == PLAYER || tmp->flag [FLAG_MONSTER])) |
1066 | top = tmp; |
1067 | top = tmp; |
1067 | else if (expect_false (tmp->flag [FLAG_IS_FLOOR])) |
1068 | else if (ecb_expect_false (tmp->flag [FLAG_IS_FLOOR])) |
1068 | { |
1069 | { |
1069 | /* If we got a floor, that means middle and top were below it, |
1070 | /* If we got a floor, that means middle and top were below it, |
1070 | * so should not be visible, so we clear them. |
1071 | * so should not be visible, so we clear them. |
1071 | */ |
1072 | */ |
1072 | middle = 0; |
1073 | middle = 0; |
… | |
… | |
1075 | volume = 0; |
1076 | volume = 0; |
1076 | items = 0; |
1077 | items = 0; |
1077 | } |
1078 | } |
1078 | else |
1079 | else |
1079 | { |
1080 | { |
1080 | if (expect_true (!tmp->flag [FLAG_NO_PICK])) |
1081 | if (ecb_expect_true (!tmp->flag [FLAG_NO_PICK])) |
1081 | { |
1082 | { |
1082 | ++items; |
1083 | ++items; |
1083 | volume += tmp->volume (); |
1084 | volume += tmp->volume (); |
1084 | } |
1085 | } |
1085 | |
1086 | |
1086 | /* Flag anywhere have high priority */ |
1087 | /* Flag anywhere have high priority */ |
1087 | if (expect_false (tmp->flag [FLAG_SEE_ANYWHERE])) |
1088 | if (ecb_expect_false (tmp->flag [FLAG_SEE_ANYWHERE])) |
1088 | anywhere = tmp; |
1089 | anywhere = tmp; |
1089 | |
1090 | |
1090 | /* Find the highest visible face around. If equal |
1091 | /* Find the highest visible face around. If equal |
1091 | * visibilities, we still want the one nearer to the |
1092 | * visibilities, we still want the one nearer to the |
1092 | * top |
1093 | * top |
1093 | */ |
1094 | */ |
1094 | if (expect_false (::faces [tmp->face].visibility >= middle_visibility)) |
1095 | if (ecb_expect_false (::faces [tmp->face].visibility >= middle_visibility)) |
1095 | { |
1096 | { |
1096 | middle_visibility = ::faces [tmp->face].visibility; |
1097 | middle_visibility = ::faces [tmp->face].visibility; |
1097 | middle = tmp; |
1098 | middle = tmp; |
1098 | } |
1099 | } |
1099 | } |
1100 | } |
… | |
… | |
1131 | this->items_ = upos_min (items, 65535); // assume nrof <= 2**31 |
1132 | this->items_ = upos_min (items, 65535); // assume nrof <= 2**31 |
1132 | |
1133 | |
1133 | /* At this point, we have a floor face (if there is a floor), |
1134 | /* At this point, we have a floor face (if there is a floor), |
1134 | * and the floor is set - we are not going to touch it at |
1135 | * and the floor is set - we are not going to touch it at |
1135 | * this point. |
1136 | * this point. |
1136 | * middle contains the highest visibility face. |
1137 | * middle contains the highest visibility face. |
1137 | * top contains a player/monster face, if there is one. |
1138 | * top contains a player/monster face, if there is one. |
1138 | * |
1139 | * |
1139 | * We now need to fill in top.face and/or middle.face. |
1140 | * We now need to fill in top.face and/or middle.face. |
1140 | */ |
1141 | */ |
1141 | |
1142 | |
1142 | /* If the top face also happens to be high visibility, re-do our |
1143 | /* If the top face also happens to be high visibility, re-do our |
1143 | * middle face. This should not happen, as we already have the |
1144 | * middle face. This should not happen, as we already have the |
1144 | * else statement above so middle should not get set. OTOH, it |
1145 | * else statement above so middle should not get set. OTOH, it |
1145 | * may be possible for the faces to match but be different objects. |
1146 | * may be possible for the faces to match but be different objects. |
1146 | */ |
1147 | */ |
1147 | if (top == middle) |
1148 | if (top == middle) |
1148 | middle = 0; |
1149 | middle = 0; |
1149 | |
1150 | |
… | |
… | |
1178 | /* top is already set - we should only get here if |
1179 | /* top is already set - we should only get here if |
1179 | * middle is not set |
1180 | * middle is not set |
1180 | * |
1181 | * |
1181 | * Set the middle face and break out, since there is nothing |
1182 | * Set the middle face and break out, since there is nothing |
1182 | * more to fill in. We don't check visiblity here, since |
1183 | * more to fill in. We don't check visiblity here, since |
1183 | * |
1184 | * |
1184 | */ |
1185 | */ |
1185 | if (tmp != top) |
1186 | if (tmp != top) |
1186 | { |
1187 | { |
1187 | middle = tmp; |
1188 | middle = tmp; |
1188 | break; |
1189 | break; |
… | |
… | |
1292 | /* this returns TRUE if the coordinates (x,y) are out of |
1293 | /* this returns TRUE if the coordinates (x,y) are out of |
1293 | * map m. This function also takes into account any |
1294 | * map m. This function also takes into account any |
1294 | * tiling considerations, loading adjacant maps as needed. |
1295 | * tiling considerations, loading adjacant maps as needed. |
1295 | * This is the function should always be used when it |
1296 | * This is the function should always be used when it |
1296 | * necessary to check for valid coordinates. |
1297 | * necessary to check for valid coordinates. |
1297 | * This function will recursively call itself for the |
1298 | * This function will recursively call itself for the |
1298 | * tiled maps. |
1299 | * tiled maps. |
1299 | */ |
1300 | */ |
1300 | int |
1301 | int |
1301 | out_of_map (maptile *m, int x, int y) |
1302 | out_of_map (maptile *m, int x, int y) |
1302 | { |
1303 | { |
… | |
… | |
1346 | } |
1347 | } |
1347 | |
1348 | |
1348 | /* This is basically the same as out_of_map above, but |
1349 | /* This is basically the same as out_of_map above, but |
1349 | * instead we return NULL if no map is valid (coordinates |
1350 | * instead we return NULL if no map is valid (coordinates |
1350 | * out of bounds and no tiled map), otherwise it returns |
1351 | * out of bounds and no tiled map), otherwise it returns |
1351 | * the map as that the coordinates are really on, and |
1352 | * the map as that the coordinates are really on, and |
1352 | * updates x and y to be the localised coordinates. |
1353 | * updates x and y to be the localised coordinates. |
1353 | * Using this is more efficient of calling out_of_map |
1354 | * Using this is more efficient of calling out_of_map |
1354 | * and then figuring out what the real map is |
1355 | * and then figuring out what the real map is |
1355 | */ |
1356 | */ |
1356 | maptile * |
1357 | maptile * |
… | |
… | |
1504 | * so you just can not look the the map coordinates and get the |
1505 | * so you just can not look the the map coordinates and get the |
1505 | * righte value. distance_x/y are distance away, which |
1506 | * righte value. distance_x/y are distance away, which |
1506 | * can be negative. direction is the crossfire direction scheme |
1507 | * can be negative. direction is the crossfire direction scheme |
1507 | * that the creature should head. part is the part of the |
1508 | * that the creature should head. part is the part of the |
1508 | * monster that is closest. |
1509 | * monster that is closest. |
1509 | * |
1510 | * |
1510 | * get_rangevector looks at op1 and op2, and fills in the |
1511 | * get_rangevector looks at op1 and op2, and fills in the |
1511 | * structure for op1 to get to op2. |
1512 | * structure for op1 to get to op2. |
1512 | * We already trust that the caller has verified that the |
1513 | * We already trust that the caller has verified that the |
1513 | * two objects are at least on adjacent maps. If not, |
1514 | * two objects are at least on adjacent maps. If not, |
1514 | * results are not likely to be what is desired. |
1515 | * results are not likely to be what is desired. |
… | |
… | |
1570 | retval->distance = upos_max (abs (retval->distance_x), abs (retval->distance_y)); |
1571 | retval->distance = upos_max (abs (retval->distance_x), abs (retval->distance_y)); |
1571 | retval->direction = find_dir_2 (retval->distance_x, retval->distance_y); |
1572 | retval->direction = find_dir_2 (retval->distance_x, retval->distance_y); |
1572 | } |
1573 | } |
1573 | } |
1574 | } |
1574 | |
1575 | |
1575 | /* this is basically the same as get_rangevector above, but instead of |
1576 | /* this is basically the same as get_rangevector above, but instead of |
1576 | * the first parameter being an object, it instead is the map |
1577 | * the first parameter being an object, it instead is the map |
1577 | * and x,y coordinates - this is used for path to player - |
1578 | * and x,y coordinates - this is used for path to player - |
1578 | * since the object is not infact moving but we are trying to traverse |
1579 | * since the object is not infact moving but we are trying to traverse |
1579 | * the path, we need this. |
1580 | * the path, we need this. |
1580 | * flags has no meaning for this function at this time - I kept it in to |
1581 | * flags has no meaning for this function at this time - I kept it in to |
1581 | * be more consistant with the above function and also in case they are needed |
1582 | * be more consistant with the above function and also in case they are needed |
1582 | * for something in the future. Also, since no object is pasted, the best |
1583 | * for something in the future. Also, since no object is pasted, the best |