diff options
Diffstat (limited to 'src/map/map.c')
-rw-r--r-- | src/map/map.c | 235 |
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 |