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.c235
1 files changed, 172 insertions, 63 deletions
diff --git a/src/map/map.c b/src/map/map.c
index 0c8c2d949..25d7ce692 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -309,7 +309,7 @@ int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) {
skill->unit_move(bl,tick,2);
status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER);
status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER);
- // status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); //Won't stop when you are knocked away, go figure...
+ //status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); //Won't stop when you are knocked away, go figure...
status_change_end(bl, SC_NJ_TATAMIGAESHI, INVALID_TIMER);
status_change_end(bl, SC_MAGICROD, INVALID_TIMER);
if (sc && sc->data[SC_PROPERTYWALK] &&
@@ -395,9 +395,12 @@ int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) {
/*==========================================
* Counts specified number of objects on given cell.
+ * flag:
+ * 0x1 - only count standing units
+ * 0x2 - don't count invinsible units
* TODO: merge with bl_getall_area
*------------------------------------------*/
-int map_count_oncell(int16 m, int16 x, int16 y, int type) {
+int map_count_oncell(int16 m, int16 x, int16 y, int type, int flag) {
int bx,by;
struct block_list *bl;
int count = 0;
@@ -408,15 +411,41 @@ int map_count_oncell(int16 m, int16 x, int16 y, int type) {
bx = x/BLOCK_SIZE;
by = y/BLOCK_SIZE;
- if (type&~BL_MOB)
- for( bl = map->list[m].block[bx+by*map->list[m].bxs] ; bl != NULL ; bl = bl->next )
- if(bl->x == x && bl->y == y && bl->type&type)
+ if (type&~BL_MOB) {
+ for (bl = map->list[m].block[bx+by*map->list[m].bxs]; bl != NULL; bl = bl->next) {
+ if (bl->x == x && bl->y == y && bl->type&type) {
+ if (flag&0x2) {
+ struct status_change *sc = status->get_sc(bl);
+ if (sc && (sc->option&OPTION_INVISIBLE))
+ continue;
+ }
+ if (flag&0x1) {
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud && ud->walktimer != INVALID_TIMER)
+ continue;
+ }
count++;
+ }
+ }
+ }
- if (type&BL_MOB)
- for( bl = map->list[m].block_mob[bx+by*map->list[m].bxs] ; bl != NULL ; bl = bl->next )
- if(bl->x == x && bl->y == y)
+ if (type&BL_MOB) {
+ for (bl = map->list[m].block_mob[bx+by*map->list[m].bxs]; bl != NULL; bl = bl->next) {
+ if (bl->x == x && bl->y == y) {
+ if (flag&0x2) {
+ struct status_change *sc = status->get_sc(bl);
+ if (sc && (sc->option&OPTION_INVISIBLE))
+ continue;
+ }
+ if (flag&0x1) {
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud && ud->walktimer != INVALID_TIMER)
+ continue;
+ }
count++;
+ }
+ }
+ }
return count;
}
@@ -1379,7 +1408,7 @@ int map_searchrandfreecell(int16 m,int16 *x,int16 *y,int stack) {
if(map->getcell(m,j+*x,i+*y,CELL_CHKNOPASS) && !map->getcell(m,j+*x,i+*y,CELL_CHKICEWALL))
continue;
//Avoid item stacking to prevent against exploits. [Skotlex]
- if(stack && map->count_oncell(m,j+*x,i+*y, BL_ITEM) > stack)
+ if(stack && map->count_oncell(m,j+*x,i+*y, BL_ITEM, 0) > stack)
continue;
free_cells[free_cell][0] = j+*x;
free_cells[free_cell++][1] = i+*y;
@@ -1473,6 +1502,85 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
}
/*==========================================
+ * Locates the closest, walkable cell with no blocks of a certain type on it
+ * Returns true on success and sets x and y to cell found.
+ * Otherwise returns false and x and y are not changed.
+ * type: Types of block to count
+ * flag:
+ * 0x1 - only count standing units
+ *------------------------------------------*/
+bool map_closest_freecell(int16 m, int16 *x, int16 *y, int type, int flag)
+{
+ uint8 dir = 6;
+ int16 tx = *x;
+ int16 ty = *y;
+ int costrange = 10;
+
+ if(!map->count_oncell(m, tx, ty, type, flag))
+ return true; //Current cell is free
+
+ //Algorithm only works up to costrange of 34
+ while(costrange <= 34) {
+ short dx = dirx[dir];
+ short dy = diry[dir];
+
+ //Linear search
+ if(dir%2 == 0 && 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,tx,ty,CELL_CHKPASS)) {
+ *x = tx;
+ *y = ty;
+ return true;
+ }
+ }
+ //Full diagonal search
+ else if(dir%2 == 1 && 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,tx,ty,CELL_CHKPASS)) {
+ *x = tx;
+ *y = ty;
+ return true;
+ }
+ }
+ //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);
+ if(!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m,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);
+ if(!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m,tx,ty,CELL_CHKPASS)) {
+ *x = tx;
+ *y = ty;
+ return true;
+ }
+ }
+
+ //Get next direction
+ if (dir == 5) {
+ //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) {
+ //Linear search complete, switch to diagonal directions
+ dir = 7;
+ } else {
+ dir = (dir+2)%8;
+ }
+ }
+
+ return false;
+}
+
+/*==========================================
* Add an item to location (m,x,y)
* Parameters
* @item_data item attributes
@@ -1692,7 +1800,7 @@ int map_quit(struct map_session_data *sd) {
if( sd->bg_id && !sd->bg_queue.arena ) /* TODO: dump this chunk after bg_queue is fully enabled */
bg->team_leave(sd,BGTL_QUIT);
- if( sd->state.autotrade && runflag != MAPSERVER_ST_SHUTDOWN && !hChSys.closing )
+ if (sd->state.autotrade && runflag != MAPSERVER_ST_SHUTDOWN && !clif->hChSys->closing)
pc->autotrade_update(sd,PAUC_REMOVE);
skill->cooldown_save(sd);
@@ -1749,7 +1857,7 @@ int map_quit(struct map_session_data *sd) {
unit->remove_map(&sd->ed->bl,CLR_TELEPORT,ALC_MARK);
}
- if( hChSys.local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id) ) {
+ if (clif->hChSys->local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id)) {
clif->chsys_left(map->list[sd->bl.m].channel,sd);
}
@@ -2412,36 +2520,31 @@ uint8 map_calc_dir(struct block_list* src, int16 x, int16 y)
dx = x-src->x;
dy = y-src->y;
- if( dx == 0 && dy == 0 )
- { // both are standing on the same spot.
+ 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 ) dir = 0; // up
- else if( dx > dy*2 ) dir = 6; // right
- else dir = 7; // up-right
- }
- else if( dx >= 0 && dy <= 0 )
- { // lower-right
- if( dx*2 <= -dy ) dir = 4; // down
- else if( dx > -dy*2 ) dir = 6; // right
- else dir = 5; // down-right
- }
- else if( dx <= 0 && dy <= 0 )
- { // lower-left
- if( dx*2 >= dy ) dir = 4; // down
- else if( dx < dy*2 ) dir = 2; // left
- else dir = 3; // down-left
- }
- else
- { // upper-left
- if( -dx*2 <= dy ) dir = 0; // up
- else if( -dx > dy*2 ) dir = 2; // left
- else dir = 1; // up-left
-
+ } 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
+ } 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
+ } 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
+ } 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
}
return dir;
}
@@ -2479,7 +2582,7 @@ int map_random_dir(struct block_list *bl, int16 *x, int16 *y)
}
// gat system
-inline static struct mapcell map_gat2cell(int gat) {
+struct mapcell map_gat2cell(int gat) {
struct mapcell cell;
memset(&cell,0,sizeof(struct mapcell));
@@ -2526,9 +2629,6 @@ void map_cellfromcache(struct map_data *m) {
// Set cell properties
for( xy = 0; xy < size; ++xy ) {
m->cell[xy] = map->gat2cell(decode_buffer[xy]);
-#ifdef CELL_NOSTACK
- m->cell[xy].cell_bl = 0;
-#endif
}
m->getcellp = map->getcellp;
@@ -2587,25 +2687,27 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) {
return (cell.nochat);
case CELL_CHKICEWALL:
return (cell.icewall);
+ case CELL_CHKNOICEWALL:
+ return (cell.noicewall);
// special checks
case CELL_CHKPASS:
#ifdef CELL_NOSTACK
- if (cell.cell_bl >= battle_config.cell_stack_limit) return 0;
+ if (cell.cell_bl >= battle_config.custom_cell_stack_limit) return 0;
#endif
case CELL_CHKREACH:
return (cell.walkable);
case CELL_CHKNOPASS:
#ifdef CELL_NOSTACK
- if (cell.cell_bl >= battle_config.cell_stack_limit) return 1;
+ if (cell.cell_bl >= battle_config.custom_cell_stack_limit) return 1;
#endif
case CELL_CHKNOREACH:
return (!cell.walkable);
case CELL_CHKSTACK:
#ifdef CELL_NOSTACK
- return (cell.cell_bl >= battle_config.cell_stack_limit);
+ return (cell.cell_bl >= battle_config.custom_cell_stack_limit);
#else
return 0;
#endif
@@ -2646,6 +2748,8 @@ void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag) {
case CELL_NOVENDING: map->list[m].cell[j].novending = flag; break;
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;
+
default:
ShowWarning("map_setcell: invalid cell type '%d'\n", (int)cell);
break;
@@ -3300,9 +3404,6 @@ int map_readgat (struct map_data* m)
type = 3; // Cell is 0 (walkable) but under water level, set to 3 (walkable water)
m->cell[xy] = map->gat2cell(type);
-#ifdef CELL_NOSTACK
- m->cell[xy].cell_bl = 0;
-#endif
}
aFree(gat);
@@ -3384,8 +3485,8 @@ int map_readallmaps (void) {
map->list[i].m = i;
map->addmap2db(&map->list[i]);
- memset(map->list[i].moblist, 0, sizeof(map->list[i].moblist)); //Initialize moblist [Skotlex]
- map->list[i].mob_delete_timer = INVALID_TIMER; //Initialize timer [Skotlex]
+ memset(map->list[i].moblist, 0, sizeof(map->list[i].moblist)); //Initialize moblist [Skotlex]
+ map->list[i].mob_delete_timer = INVALID_TIMER; //Initialize timer [Skotlex]
map->list[i].bxs = (map->list[i].xs + BLOCK_SIZE - 1) / BLOCK_SIZE;
map->list[i].bys = (map->list[i].ys + BLOCK_SIZE - 1) / BLOCK_SIZE;
@@ -3621,15 +3722,19 @@ int inter_config_read(char *cfgName) {
if(strcmpi(w1,"item_db_db")==0)
strcpy(map->item_db_db,w2);
else if(strcmpi(w1,"mob_db_db")==0)
- strcpy(map->mob_db_db,w2);
+ strcpy(map->mob_db_db, w2);
+ else if (strcmpi(w1, "mob_db_re_db") == 0)
+ strcpy(map->mob_db_re_db, w2);
else if(strcmpi(w1,"item_db2_db")==0)
strcpy(map->item_db2_db,w2);
else if(strcmpi(w1,"item_db_re_db")==0)
strcpy(map->item_db_re_db,w2);
else if(strcmpi(w1,"mob_db2_db")==0)
- strcpy(map->mob_db2_db,w2);
- else if(strcmpi(w1,"mob_skill_db_db")==0)
- strcpy(map->mob_skill_db_db,w2);
+ strcpy(map->mob_db2_db, w2);
+ else if(strcmpi(w1, "mob_skill_db_db") == 0)
+ strcpy(map->mob_skill_db_db, w2);
+ else if(strcmpi(w1, "mob_skill_db_re_db") == 0)
+ strcpy(map->mob_skill_db_re_db, w2);
else if(strcmpi(w1,"mob_skill_db2_db")==0)
strcpy(map->mob_skill_db2_db,w2);
else if(strcmpi(w1,"interreg_db")==0)
@@ -3682,6 +3787,8 @@ int inter_config_read(char *cfgName) {
/* import */
else if(strcmpi(w1,"import")==0)
map->inter_config_read(w2);
+ else
+ HPM->parseConf(w1, w2, HPCT_MAP_INTER);
}
fclose(fp);
@@ -5020,6 +5127,7 @@ void read_map_zone_db(void) {
CREATE( entry, struct map_zone_disabled_skill_entry, 1 );
entry->nameid = izone->disabled_skills[j]->nameid;
entry->type = izone->disabled_skills[j]->type;
+ entry->subtype = izone->disabled_skills[j]->subtype;
zone->disabled_skills[zone->disabled_skills_count-1] = entry;
}
}
@@ -5114,6 +5222,7 @@ void read_map_zone_db(void) {
entry->nameid = izone->capped_skills[j]->nameid;
entry->cap = izone->capped_skills[j]->cap;
entry->type = izone->capped_skills[j]->type;
+ entry->subtype = izone->capped_skills[j]->subtype;
zone->capped_skills[zone->capped_skills_count-1] = entry;
}
}
@@ -5248,7 +5357,7 @@ int do_final(void) {
ShowStatus("Terminating...\n");
- hChSys.closing = true;
+ clif->hChSys->closing = true;
HPM->event(HPET_FINAL);
if (map->cpsd) aFree(map->cpsd);
@@ -5392,7 +5501,7 @@ void map_helpscreen(bool do_exit)
ShowInfo(" scripts passed through --load-script.\n");
ShowInfo(" --load-script <file> Loads an additional script (can be repeated).\n");
ShowInfo(" --load-plugin <name> Loads an additional plugin (can be repeated).\n");
- HPM->arg_help();/* display help for commands implemented thru HPM */
+ HPM->arg_help(); /* display help for commands implemented through HPM */
if( do_exit )
exit(EXIT_SUCCESS);
}
@@ -5489,9 +5598,9 @@ void map_cp_defaults(void) {
/* default HCP data */
map->cpsd = pc->get_dummy_sd();
strcpy(map->cpsd->status.name, "Hercules Console");
- map->cpsd->bl.x = MAP_DEFAULT_X;
- map->cpsd->bl.y = MAP_DEFAULT_Y;
- map->cpsd->bl.m = map->mapname2mapid(MAP_DEFAULT);
+ map->cpsd->bl.x = mapindex->default_x;
+ map->cpsd->bl.y = mapindex->default_y;
+ map->cpsd->bl.m = map->mapname2mapid(mapindex->default_map);
console->input->addCommand("gm:info",CPCMD_A(gm_position));
console->input->addCommand("gm:use",CPCMD_A(gm_use));
@@ -5609,10 +5718,7 @@ int do_init(int argc, char *argv[])
map_load_defaults();
HPM_map_do_init();
- HPM->DataCheck = HPM_map_DataCheck;
- HPM->load_sub = HPM_map_plugin_load_sub;
HPM->symbol_defaults_sub = map_hp_symbols;
- HPM->grabHPDataSub = HPM_map_grabHPData;
for( i = 1; i < argc; i++ ) {
const char* arg = argv[i];
if( strcmp(arg, "--load-plugin") == 0 ) {
@@ -5841,7 +5947,7 @@ int do_init(int argc, char *argv[])
exit(EXIT_SUCCESS);
}
- npc->event_do_oninit( false ); // Init npcs (OnInit)
+ npc->event_do_oninit( false ); // Init npcs (OnInit)
npc->market_fromsql(); /* after OnInit */
if (battle_config.pk_mode)
@@ -5903,8 +6009,10 @@ void map_defaults(void) {
sprintf(map->item_db2_db, "item_db2");
sprintf(map->item_db_re_db, "item_db_re");
sprintf(map->mob_db_db, "mob_db");
+ sprintf(map->mob_db_re_db, "mob_db_re");
sprintf(map->mob_db2_db, "mob_db2");
sprintf(map->mob_skill_db_db, "mob_skill_db");
+ sprintf(map->mob_skill_db_re_db, "mob_skill_db_re");
sprintf(map->mob_skill_db2_db, "mob_skill_db2");
sprintf(map->interreg_db, "interreg");
@@ -5998,6 +6106,7 @@ void map_defaults(void) {
// search and creation
map->get_new_object_id = map_get_new_object_id;
map->search_freecell = map_search_freecell;
+ map->closest_freecell = map_closest_freecell;
//
map->quit = map_quit;
// npc