summaryrefslogtreecommitdiff
path: root/src/map/map.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/map.c')
-rw-r--r--src/map/map.c214
1 files changed, 138 insertions, 76 deletions
diff --git a/src/map/map.c b/src/map/map.c
index 70623ae22..c88118b43 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -261,11 +261,13 @@ static int map_addblock(struct block_list *bl)
pos = x/BLOCK_SIZE+(y/BLOCK_SIZE)*map->list[m].bxs;
if (bl->type == BL_MOB) {
+ Assert_ret(map->list[m].block_mob != NULL);
bl->next = map->list[m].block_mob[pos];
bl->prev = &map->bl_head;
if (bl->next) bl->next->prev = bl;
map->list[m].block_mob[pos] = bl;
} else {
+ Assert_ret(map->list[m].block != NULL);
bl->next = map->list[m].block[pos];
bl->prev = &map->bl_head;
if (bl->next) bl->next->prev = bl;
@@ -307,8 +309,10 @@ static int map_delblock(struct block_list *bl)
if (bl->prev == &map->bl_head) {
//Since the head of the list, update the block_list map of []
if (bl->type == BL_MOB) {
+ Assert_ret(map->list[bl->m].block_mob != NULL);
map->list[bl->m].block_mob[pos] = bl->next;
} else {
+ Assert_ret(map->list[bl->m].block != NULL);
map->list[bl->m].block[pos] = bl->next;
}
} else {
@@ -450,6 +454,12 @@ static int map_count_oncell(int16 m, int16 x, int16 y, int type, int flag)
struct block_list *bl;
int count = 0;
+ Assert_ret(m >= -1);
+ if (m < 0)
+ return 0;
+ Assert_ret(m < map->count);
+ Assert_ret(map->list[m].block != NULL);
+
if (x < 0 || y < 0 || (x >= map->list[m].xs) || (y >= map->list[m].ys))
return 0;
@@ -512,6 +522,12 @@ static struct skill_unit *map_find_skill_unit_oncell(struct block_list *target,
nullpo_retr(NULL, target);
m = target->m;
+ Assert_ret(m >= -1);
+ if (m < 0)
+ return 0;
+ Assert_ret(m < map->count);
+ Assert_ret(map->list[m].block != NULL);
+
if (x < 0 || y < 0 || (x >= map->list[m].xs) || (y >= map->list[m].ys))
return NULL;
@@ -586,8 +602,11 @@ static int map_vforeachinmap(int (*func)(struct block_list*, va_list), int16 m,
struct block_list *bl;
int blockcount = map->bl_list_count;
+ Assert_ret(m >= -1);
if (m < 0)
return 0;
+ Assert_ret(m < map->count);
+ Assert_ret(map->list[m].block != NULL);
bsize = map->list[m].bxs * map->list[m].bys;
for (i = 0; i < bsize; i++) {
@@ -719,24 +738,28 @@ static int bl_getall_area(int type, int m, int x0, int y0, int x1, int y1, int (
struct block_list *bl;
int found = 0;
+ Assert_ret(m >= -1);
if (m < 0)
return 0;
+ Assert_ret(m < map->count);
+ const struct map_data *const listm = &map->list[m];
+ Assert_ret(listm->xs > 0 && listm->ys > 0);
+ Assert_ret(listm->block != NULL);
+
+ // Limit search area to map size
+ x0 = min(max(x0, 0), map->list[m].xs - 1);
+ y0 = min(max(y0, 0), map->list[m].ys - 1);
+ x1 = min(max(x1, 0), map->list[m].xs - 1);
+ y1 = min(max(y1, 0), map->list[m].ys - 1);
if (x1 < x0) swap(x0, x1);
if (y1 < y0) swap(y0, y1);
- // Limit search area to map size
- x0 = max(x0, 0);
- y0 = max(y0, 0);
- x1 = min(x1, map->list[m].xs - 1);
- y1 = min(y1, map->list[m].ys - 1);
-
{
const int x0b = x0 / BLOCK_SIZE;
const int x1b = x1 / BLOCK_SIZE;
const int y0b = y0 / BLOCK_SIZE;
const int y1b = y1 / BLOCK_SIZE;
- const struct map_data *const listm = &map->list[m];
const int bxs0 = listm->bxs;
// duplication for better performance
@@ -1670,7 +1693,7 @@ static int map_search_freecell(struct block_list *src, int16 m, int16 *x, int16
*------------------------------------------*/
static bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x, int16 *y, int type, int flag)
{
- uint8 dir = 6;
+ enum unit_dir dir = UNIT_DIR_EAST;
int16 tx;
int16 ty;
int costrange = 10;
@@ -1689,7 +1712,7 @@ static bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x,
short dy = diry[dir];
//Linear search
- if(dir%2 == 0 && costrange%MOVE_COST == 0) {
+ if (!unit_is_diagonal_dir(dir) && (costrange % MOVE_COST) == 0) {
tx = *x+dx*(costrange/MOVE_COST);
ty = *y+dy*(costrange/MOVE_COST);
if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) {
@@ -1699,7 +1722,7 @@ static bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x,
}
}
//Full diagonal search
- else if(dir%2 == 1 && costrange%MOVE_DIAGONAL_COST == 0) {
+ else if (unit_is_diagonal_dir(dir) && (costrange % MOVE_DIAGONAL_COST) == 0) {
tx = *x+dx*(costrange/MOVE_DIAGONAL_COST);
ty = *y+dy*(costrange/MOVE_DIAGONAL_COST);
if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) {
@@ -1709,16 +1732,24 @@ static bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x,
}
}
//One cell diagonal, rest linear (TODO: Find a better algorithm for this)
- else if(dir%2 == 1 && costrange%MOVE_COST == 4) {
- tx = *x+dx*((dir%4==3)?(costrange/MOVE_COST):1);
- ty = *y+dy*((dir%4==1)?(costrange/MOVE_COST):1);
+ else if (unit_is_diagonal_dir(dir) && (costrange % MOVE_COST) == 4) {
+ tx = *x + dx;
+ ty = *y + dy;
+ if (unit_is_dir_or_opposite(dir, UNIT_DIR_SOUTHWEST))
+ tx = tx * costrange / MOVE_COST;
+ if (unit_is_dir_or_opposite(dir, UNIT_DIR_NORTHWEST))
+ ty = ty * costrange / MOVE_COST;
if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) {
*x = tx;
*y = ty;
return true;
}
- tx = *x+dx*((dir%4==1)?(costrange/MOVE_COST):1);
- ty = *y+dy*((dir%4==3)?(costrange/MOVE_COST):1);
+ tx = *x + dx;
+ ty = *y + dy;
+ if (unit_is_dir_or_opposite(dir, UNIT_DIR_NORTHWEST))
+ tx = tx * costrange / MOVE_COST;
+ if (unit_is_dir_or_opposite(dir, UNIT_DIR_SOUTHWEST))
+ ty = ty * costrange / MOVE_COST;
if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) {
*x = tx;
*y = ty;
@@ -1727,17 +1758,17 @@ static bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x,
}
//Get next direction
- if (dir == 5) {
+ if (dir == UNIT_DIR_SOUTHEAST) {
//Diagonal search complete, repeat with higher cost range
if(costrange == 14) costrange += 6;
else if(costrange == 28 || costrange >= 38) costrange += 2;
else costrange += 4;
- dir = 6;
- } else if (dir == 4) {
+ dir = UNIT_DIR_EAST;
+ } else if (dir == UNIT_DIR_SOUTH) {
//Linear search complete, switch to diagonal directions
- dir = 7;
+ dir = UNIT_DIR_NORTHEAST;
} else {
- dir = (dir+2)%8;
+ dir = unit_get_ccw90_dir(dir);
}
}
@@ -1880,6 +1911,7 @@ static void map_reqnickdb(struct map_session_data *sd, int charid)
}
// not in cache, request it
CREATE(req, struct charid_request, 1);
+ req->charid = sd->status.char_id;
req->next = p->requests;
p->requests = req;
chrif->searchcharid(charid);
@@ -2845,63 +2877,70 @@ static int map_mapname2ipport(unsigned short name, uint32 *ip, uint16 *port)
return 0;
}
-/*==========================================
+/**
* Checks if both dirs point in the same direction.
- *------------------------------------------*/
-static int map_check_dir(int s_dir, int t_dir)
+ * @param s_dir: direction source is facing
+ * @param t_dir: direction target is facing
+ * @return 0: success(both face the same direction), 1: failure
+ **/
+static int map_check_dir(enum unit_dir s_dir, enum unit_dir t_dir)
{
- if(s_dir == t_dir)
+ if (s_dir == t_dir || ((t_dir + UNIT_DIR_MAX - 1) % UNIT_DIR_MAX) == s_dir
+ || ((t_dir + UNIT_DIR_MAX + 1) % UNIT_DIR_MAX) == s_dir)
return 0;
- switch(s_dir) {
- case 0: if(t_dir == 7 || t_dir == 1 || t_dir == 0) return 0; break;
- case 1: if(t_dir == 0 || t_dir == 2 || t_dir == 1) return 0; break;
- case 2: if(t_dir == 1 || t_dir == 3 || t_dir == 2) return 0; break;
- case 3: if(t_dir == 2 || t_dir == 4 || t_dir == 3) return 0; break;
- case 4: if(t_dir == 3 || t_dir == 5 || t_dir == 4) return 0; break;
- case 5: if(t_dir == 4 || t_dir == 6 || t_dir == 5) return 0; break;
- case 6: if(t_dir == 5 || t_dir == 7 || t_dir == 6) return 0; break;
- case 7: if(t_dir == 6 || t_dir == 0 || t_dir == 7) return 0; break;
- }
return 1;
}
-/*==========================================
+/**
* Returns the direction of the given cell, relative to 'src'
- *------------------------------------------*/
-static uint8 map_calc_dir(struct block_list *src, int16 x, int16 y)
+ * @param src: object to put in relation between coordinates
+ * @param x: x-coordinate of cell
+ * @param y: y-coordinate of cell
+ * @return the direction of the given cell, relative to 'src'
+ **/
+static enum unit_dir map_calc_dir(const struct block_list *src, int16 x, int16 y)
{
- uint8 dir = 0;
- int dx, dy;
-
- nullpo_ret(src);
+ nullpo_retr(UNIT_DIR_NORTH, src);
+ enum unit_dir dir = UNIT_DIR_NORTH;
- dx = x-src->x;
- dy = y-src->y;
+ int dx = x - src->x;
+ int dy = y - src->y;
if (dx == 0 && dy == 0) {
// both are standing on the same spot.
// aegis-style, makes knockback default to the left.
// athena-style, makes knockback default to behind 'src'.
- dir = (battle_config.knockback_left ? 6 : unit->getdir(src));
- } else if (dx >= 0 && dy >=0) {
- // upper-right
- if( dx*2 < dy || dx == 0 ) dir = 0; // up
- else if( dx > dy*2+1 || dy == 0 ) dir = 6; // right
- else dir = 7; // up-right
+ if (battle_config.knockback_left != 0)
+ dir = UNIT_DIR_EAST;
+ else
+ dir = unit->getdir(src);
+ } else if (dx >= 0 && dy >= 0) {
+ if (dx * 2 < dy || dx == 0)
+ dir = UNIT_DIR_NORTH;
+ else if (dx > dy * 2 + 1 || dy == 0)
+ dir = UNIT_DIR_EAST;
+ else
+ dir = UNIT_DIR_NORTHEAST;
} else if (dx >= 0 && dy <= 0) {
- // lower-right
- if( dx*2 < -dy || dx == 0 ) dir = 4; // down
- else if( dx > -dy*2+1 || dy == 0 ) dir = 6; // right
- else dir = 5; // down-right
+ if (dx * 2 < -dy || dx == 0)
+ dir = UNIT_DIR_SOUTH;
+ else if (dx > -dy * 2 + 1 || dy == 0)
+ dir = UNIT_DIR_EAST;
+ else
+ dir = UNIT_DIR_SOUTHEAST;
} else if (dx <= 0 && dy <= 0) {
- // lower-left
- if( dx*2 > dy || dx == 0 ) dir = 4; // down
- else if( dx < dy*2-1 || dy == 0 ) dir = 2; // left
- else dir = 3; // down-left
+ if (dx * 2 > dy || dx == 0 )
+ dir = UNIT_DIR_SOUTH;
+ else if (dx < dy * 2 + 1 || dy == 0)
+ dir = UNIT_DIR_WEST;
+ else
+ dir = UNIT_DIR_SOUTHWEST;
} else {
- // upper-left
- if( -dx*2 < dy || dx == 0 ) dir = 0; // up
- else if( -dx > dy*2+1 || dy == 0) dir = 2; // left
- else dir = 1; // up-left
+ if (-dx * 2 < dy || dx == 0 )
+ dir = UNIT_DIR_NORTH;
+ else if (-dx > dy * 2 + 1 || dy == 0)
+ dir = UNIT_DIR_WEST;
+ else
+ dir = UNIT_DIR_NORTHWEST;
}
return dir;
}
@@ -2929,11 +2968,11 @@ static int map_random_dir(struct block_list *bl, int16 *x, int16 *y)
if (dist < 1) dist =1;
do {
- int j = 1 + 2*(rnd()%4); //Pick a random diagonal direction
+ enum unit_dir dir = unit_get_rnd_diagonal_dir();
short segment = 1+(rnd()%dist); //Pick a random interval from the whole vector in that direction
- xi = bl->x + segment*dirx[j];
+ xi = bl->x + segment * dirx[dir];
segment = (short)sqrt((float)(dist2 - segment*segment)); //The complement of the previously picked segment
- yi = bl->y + segment*diry[j];
+ yi = bl->y + segment * diry[dir];
} while ((map->getcell(bl->m, bl, xi, yi, CELL_CHKNOPASS) || !path->search(NULL, bl, bl->m, bl->x, bl->y, xi, yi, 1, CELL_CHKNOREACH))
&& (++i)<100);
@@ -3062,6 +3101,8 @@ static int map_getcellp(struct map_data *m, const struct block_list *bl, int16 x
return (cell.icewall);
case CELL_CHKNOICEWALL:
return (cell.noicewall);
+ case CELL_CHKNOSKILL:
+ return (cell.noskill);
// special checks
case CELL_CHKPASS:
@@ -3126,6 +3167,7 @@ static void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag)
case CELL_NOCHAT: map->list[m].cell[j].nochat = flag; break;
case CELL_ICEWALL: map->list[m].cell[j].icewall = flag; break;
case CELL_NOICEWALL: map->list[m].cell[j].noicewall = flag; break;
+ case CELL_NOSKILL: map->list[m].cell[j].noskill = flag; break;
default:
ShowWarning("map_setcell: invalid cell type '%d'\n", (int)cell);
@@ -4441,7 +4483,6 @@ static bool inter_config_read_connection(const char *filename, const struct conf
static bool inter_config_read_database_names(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
- bool retval = true;
nullpo_retr(false, filename);
nullpo_retr(false, config);
@@ -4459,16 +4500,14 @@ static bool inter_config_read_database_names(const char *filename, const struct
libconfig->setting_lookup_mutable_string(setting, "npc_barter_data_db", map->npc_barter_data_db, sizeof(map->npc_barter_data_db));
libconfig->setting_lookup_mutable_string(setting, "npc_expanded_barter_data_db", map->npc_expanded_barter_data_db, sizeof(map->npc_expanded_barter_data_db));
- if (!mapreg->config_read(filename, setting, imported))
- retval = false;
-
if ((setting = libconfig->lookup(config, "inter_configuration/database_names/registry")) == NULL) {
if (imported)
- return retval;
+ return true;
ShowError("inter_config_read: inter_configuration/database_names/registry was not found in %s!\n", filename);
return false;
}
- return retval;
+
+ return mapreg->config_read_registry(filename, setting, imported);
}
/*=======================================
@@ -5250,7 +5289,7 @@ static bool map_zone_mf_cache(int m, char *flag, char *params)
}
}
- if( modifier[0] == '\0' || !( skill_id = skill->name2id(skill_name) ) || !skill->get_unit_id( skill->name2id(skill_name), 0) || atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) {
+ if (modifier[0] == '\0' || (skill_id = skill->name2id(skill_name)) == 0 || skill->get_unit_id(skill->name2id(skill_name), 1, 0) == 0 || atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX) {
;/* we don't mind it, the server will take care of it next. */
} else {
int idx = map->list[m].unit_count;
@@ -5430,6 +5469,19 @@ static bool map_zone_mf_cache(int m, char *flag, char *params)
map_zone_mf_cache_add(m, rflag);
}
}
+ } else if (strcmpi(flag, "nopet") == 0) {
+ if (state == 0) {
+ if (map->list[m].flag.nopet != 0) {
+ sprintf(rflag, "nopet\t%d", map->list[m].flag.nopet);
+ map_zone_mf_cache_add(m, rflag);
+ }
+ }
+ if (sscanf(params, "%d", &state) == 1) {
+ if (state != map->list[m].flag.nopet) {
+ sprintf(rflag, "nopet\t%d", state);
+ map_zone_mf_cache_add(m, rflag);
+ }
+ }
}
return false;
@@ -6032,11 +6084,15 @@ static bool map_add_questinfo(int m, struct npc_data *nd)
nullpo_retr(false, nd);
Assert_retr(false, m >= 0 && m < map->count);
- if (&VECTOR_LAST(map->list[m].qi_list) == nd)
+ int i;
+ ARR_FIND(0, VECTOR_LENGTH(map->list[m].qi_list), i, VECTOR_INDEX(map->list[m].qi_list, i) == nd);
+
+ if (i < VECTOR_LENGTH(map->list[m].qi_list)) {
return false;
+ }
VECTOR_ENSURE(map->list[m].qi_list, 1, 1);
- VECTOR_PUSH(map->list[m].qi_list, *nd);
+ VECTOR_PUSH(map->list[m].qi_list, nd);
return true;
}
@@ -6047,7 +6103,7 @@ static bool map_remove_questinfo(int m, struct npc_data *nd)
Assert_retr(false, m >= 0 && m < map->count);
int i;
- ARR_FIND(0, VECTOR_LENGTH(map->list[m].qi_list), i, &VECTOR_INDEX(map->list[m].qi_list, i) == nd);
+ ARR_FIND(0, VECTOR_LENGTH(map->list[m].qi_list), i, VECTOR_INDEX(map->list[m].qi_list, i) == nd);
if (i != VECTOR_LENGTH(map->list[m].qi_list)) {
VECTOR_ERASE(map->list[m].qi_list, i);
return true;
@@ -6649,6 +6705,8 @@ int do_init(int argc, char *argv[])
atcommand->msg_read(map->MSG_CONF_NAME, false);
map->inter_config_read(map->INTER_CONF_NAME, false);
logs->config_read(map->LOG_CONF_NAME, false);
+ } else {
+ battle->config_read(map->BATTLE_CONF_FILENAME, false);
}
script->config_read(map->SCRIPT_CONF_NAME, false);
@@ -6699,8 +6757,8 @@ int do_init(int argc, char *argv[])
timer->add_func_list(map->removemobs_timer, "map_removemobs_timer");
timer->add_interval(timer->gettick()+1000, map->freeblock_timer, 0, 0, 60*1000);
- HPM->event(HPET_INIT);
}
+ HPM->event(HPET_INIT);
atcommand->init(minimal);
battle->init(minimal);
@@ -6747,8 +6805,12 @@ int do_init(int argc, char *argv[])
exit(EXIT_SUCCESS);
}
- if( minimal ) {
+ if (minimal) {
HPM->event(HPET_READY);
+ HPM->event(HPET_FINAL);
+ battle->final();
+ HPM_map_do_final();
+ HPM->event(HPET_POST_FINAL);
exit(EXIT_SUCCESS);
}