Instance map fixes (#3539)
* Fixed #3517, new map from instance doesn't use unused map slots * Fixed #3528, crashed on reloadscript if there is instance map * Cleared map flags on reloadscript
This commit is contained in:
110
src/map/map.cpp
110
src/map/map.cpp
@@ -2639,11 +2639,6 @@ int map_addinstancemap(const char *name, unsigned short instance_id)
|
||||
}
|
||||
|
||||
struct map_data *src_map = map_getmapdata(src_m);
|
||||
|
||||
// Copy the map
|
||||
memcpy(&map[dst_m], src_map, sizeof(struct map_data));
|
||||
|
||||
// Retrieve new map data
|
||||
struct map_data *dst_map = map_getmapdata(dst_m);
|
||||
|
||||
strcpy(iname, name);
|
||||
@@ -2658,17 +2653,15 @@ int map_addinstancemap(const char *name, unsigned short instance_id)
|
||||
snprintf(dst_map->name, sizeof(dst_map->name),"%.3hu%s", instance_id, iname);
|
||||
dst_map->name[MAP_NAME_LENGTH-1] = '\0';
|
||||
|
||||
// Mimic questinfo
|
||||
if( src_map->qi_count ) {
|
||||
dst_map->qi_count = src_map->qi_count;
|
||||
CREATE( dst_map->qi_data, struct questinfo, dst_map->qi_count );
|
||||
memcpy( dst_map->qi_data, src_map->qi_data, dst_map->qi_count * sizeof(struct questinfo) );
|
||||
}
|
||||
|
||||
dst_map->m = dst_m;
|
||||
dst_map->instance_id = instance_id;
|
||||
dst_map->instance_src_map = src_m;
|
||||
dst_map->users = 0;
|
||||
dst_map->xs = src_map->xs;
|
||||
dst_map->ys = src_map->ys;
|
||||
dst_map->bxs = src_map->bxs;
|
||||
dst_map->bys = src_map->bys;
|
||||
dst_map->iwall_num = src_map->iwall_num;
|
||||
|
||||
memset(dst_map->npc, 0, sizeof(dst_map->npc));
|
||||
dst_map->npc_num = 0;
|
||||
@@ -2686,6 +2679,10 @@ int map_addinstancemap(const char *name, unsigned short instance_id)
|
||||
dst_map->channel = NULL;
|
||||
dst_map->mob_delete_timer = INVALID_TIMER;
|
||||
|
||||
map_data_copy(dst_map, src_map);
|
||||
|
||||
ShowInfo("[Instance] Created map '%s' ('%d') from map '%s' ('%d')\n", dst_map->name, dst_map->m, name, src_map->m);
|
||||
|
||||
map_addmap2db(dst_map);
|
||||
|
||||
return dst_m;
|
||||
@@ -2734,7 +2731,7 @@ static int map_instancemap_clean(struct block_list *bl, va_list ap)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void map_free_questinfo(int m);
|
||||
static void map_free_questinfo(struct map_data *mapdata);
|
||||
|
||||
/*==========================================
|
||||
* Deleting an instance map
|
||||
@@ -2754,16 +2751,28 @@ int map_delinstancemap(int m)
|
||||
|
||||
if( mapdata->mob_delete_timer != INVALID_TIMER )
|
||||
delete_timer(mapdata->mob_delete_timer, map_removemobs_timer);
|
||||
mapdata->mob_delete_timer = INVALID_TIMER;
|
||||
|
||||
// Free memory
|
||||
aFree(mapdata->cell);
|
||||
aFree(mapdata->block);
|
||||
aFree(mapdata->block_mob);
|
||||
map_free_questinfo(m);
|
||||
mapdata->damage_adjust = {};
|
||||
if (mapdata->cell)
|
||||
aFree(mapdata->cell);
|
||||
mapdata->cell = NULL;
|
||||
if (mapdata->block)
|
||||
aFree(mapdata->block);
|
||||
mapdata->block = NULL;
|
||||
if (mapdata->block_mob)
|
||||
aFree(mapdata->block_mob);
|
||||
mapdata->block_mob = NULL;
|
||||
|
||||
mapindex_removemap( mapdata->index );
|
||||
map_free_questinfo(mapdata);
|
||||
mapdata->damage_adjust = {};
|
||||
mapdata->flag.clear();
|
||||
mapdata->skill_damage.clear();
|
||||
|
||||
mapindex_removemap(mapdata->index);
|
||||
map_removemapdb(mapdata);
|
||||
|
||||
memset(&mapdata->name, '\0', sizeof(map[0].name)); // just remove the name
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -3546,6 +3555,7 @@ void map_flags_init(void){
|
||||
struct map_data *mapdata = &map[i];
|
||||
union u_mapflag_args args = {};
|
||||
|
||||
mapdata->flag.clear();
|
||||
mapdata->flag.reserve(MF_MAX); // Reserve the bucket size
|
||||
args.flag_val = 100;
|
||||
|
||||
@@ -3555,14 +3565,59 @@ void map_flags_init(void){
|
||||
map_setmapflag_sub(i, MF_BEXP, true, &args); // per map base exp multiplicator
|
||||
map_setmapflag_sub(i, MF_JEXP, true, &args); // per map job exp multiplicator
|
||||
|
||||
// skill damage
|
||||
// Clear adjustment data, will be reset after loading NPC
|
||||
mapdata->damage_adjust = {};
|
||||
mapdata->skill_damage.clear();
|
||||
map_free_questinfo(mapdata);
|
||||
|
||||
if (instance_start && i >= instance_start)
|
||||
continue;
|
||||
|
||||
// adjustments
|
||||
if( battle_config.pk_mode && !mapdata->flag[MF_PVP] )
|
||||
mapdata->flag[MF_PVP] = true; // make all maps pvp for pk_mode [Valaris]
|
||||
}
|
||||
}
|
||||
|
||||
map_free_questinfo(i);
|
||||
/**
|
||||
* Copying map data from parent map for instance map
|
||||
* @param dst_map Mapdata will be copied to
|
||||
* @param src_map Copying data from
|
||||
*/
|
||||
void map_data_copy(struct map_data *dst_map, struct map_data *src_map) {
|
||||
nullpo_retv(dst_map);
|
||||
nullpo_retv(src_map);
|
||||
|
||||
memcpy(&dst_map->save, &src_map->save, sizeof(struct point));
|
||||
memcpy(&dst_map->damage_adjust, &src_map->damage_adjust, sizeof(struct s_skill_damage));
|
||||
|
||||
dst_map->flag.insert(src_map->flag.begin(), src_map->flag.end());
|
||||
dst_map->skill_damage.insert(dst_map->skill_damage.begin(), src_map->skill_damage.begin(), src_map->skill_damage.end());
|
||||
|
||||
dst_map->zone = src_map->zone;
|
||||
dst_map->qi_count = 0;
|
||||
dst_map->qi_data = NULL;
|
||||
|
||||
// Mimic questinfo
|
||||
if (src_map->qi_count) {
|
||||
dst_map->qi_count = src_map->qi_count;
|
||||
CREATE(dst_map->qi_data, struct questinfo, dst_map->qi_count);
|
||||
memcpy(dst_map->qi_data, src_map->qi_data, dst_map->qi_count * sizeof(struct questinfo));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy map data for instance maps from its parents
|
||||
* that were cleared in map_flags_init() after reloadscript
|
||||
*/
|
||||
void map_data_copyall (void) {
|
||||
if (!instance_start)
|
||||
return;
|
||||
for (int i = instance_start; i < map_num; i++) {
|
||||
struct map_data *mapdata = &map[i];
|
||||
if (!mapdata || mapdata->name[0] == '\0' || !mapdata->instance_src_map)
|
||||
continue;
|
||||
map_data_copy(mapdata, &map[mapdata->instance_src_map]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3760,6 +3815,12 @@ int map_readallmaps (void)
|
||||
size = mapdata->bxs * mapdata->bys * sizeof(struct block_list*);
|
||||
mapdata->block = (struct block_list**)aCalloc(size, 1);
|
||||
mapdata->block_mob = (struct block_list**)aCalloc(size, 1);
|
||||
|
||||
memset(&mapdata->save, 0, sizeof(struct point));
|
||||
mapdata->damage_adjust = {};
|
||||
mapdata->qi_count = 0;
|
||||
mapdata->qi_data = NULL;
|
||||
mapdata->channel = NULL;
|
||||
}
|
||||
|
||||
// intialization and configuration-dependent adjustments of mapflags
|
||||
@@ -4275,9 +4336,10 @@ bool map_remove_questinfo(int m, struct npc_data *nd) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void map_free_questinfo(int m) {
|
||||
static void map_free_questinfo(struct map_data *mapdata) {
|
||||
unsigned short i;
|
||||
struct map_data *mapdata = map_getmapdata(m);
|
||||
if (!mapdata)
|
||||
return;
|
||||
|
||||
for(i = 0; i < mapdata->qi_count; i++) {
|
||||
if (mapdata->qi_data[i].jobid)
|
||||
@@ -4871,7 +4933,7 @@ void do_final(void){
|
||||
for (int j=0; j<MAX_MOB_LIST_PER_MAP; j++)
|
||||
if (mapdata->moblist[j]) aFree(mapdata->moblist[j]);
|
||||
}
|
||||
map_free_questinfo(i);
|
||||
map_free_questinfo(mapdata);
|
||||
mapdata->damage_adjust = {};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user