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:
Cydh Ramdh
2018-10-10 18:05:24 +07:00
committed by GitHub
parent ed40872839
commit e66dc4f62e
3 changed files with 89 additions and 24 deletions

View File

@@ -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 = {};
}