diff --git a/src/map/map.cpp b/src/map/map.cpp index 3baa0aa80f..cf0d3289f4 100644 --- a/src/map/map.cpp +++ b/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; jmoblist[j]) aFree(mapdata->moblist[j]); } - map_free_questinfo(i); + map_free_questinfo(mapdata); mapdata->damage_adjust = {}; } diff --git a/src/map/map.hpp b/src/map/map.hpp index 5200ff6b49..cb93afce4f 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -1024,6 +1024,8 @@ int map_addflooritem(struct item *item, int amount, int16 m, int16 x, int16 y, i // instances int map_addinstancemap(const char *name, unsigned short instance_id); int map_delinstancemap(int m); +void map_data_copyall(void); +void map_data_copy(struct map_data *dst_map, struct map_data *src_map); // player to map session void map_addnickdb(int charid, const char* nick); diff --git a/src/map/npc.cpp b/src/map/npc.cpp index d8fab977e7..7d6f6869f5 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -4537,6 +4537,7 @@ int npc_reload(void) { //Execute the OnInit event for freshly loaded npcs. [Skotlex] npc_event_runall(script_config.init_event_name); + map_data_copyall(); do_reload_instance(); // Execute rest of the startup events if connected to char-server. [Lance]