From 50bc76c412b6618d90fdbdb24d43da2bda0525a2 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Mon, 3 Feb 2014 14:09:58 -0200 Subject: Fixed Bug 7333 Zones are now able to merge during runtime. Special Thanks to Haru, kyeme. http://hercules.ws/board/tracker/issue-7333-map-zone-db/ Signed-off-by: shennetsind --- src/common/HPM.c | 11 +++--- src/map/HPMmap.c | 1 - src/map/map.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/map/map.h | 6 ++- src/map/npc.c | 17 +++++--- 5 files changed, 137 insertions(+), 16 deletions(-) diff --git a/src/common/HPM.c b/src/common/HPM.c index cf296e593..bd2ce93ab 100644 --- a/src/common/HPM.c +++ b/src/common/HPM.c @@ -217,7 +217,7 @@ struct hplugin *hplugin_load(const char* filename) { return NULL; } - if( !HPM->DataCheck(HPMDataCheck,*HPMDataCheckLen,plugin->info->name) ) { + if( HPM->DataCheck && !HPM->DataCheck(HPMDataCheck,*HPMDataCheckLen,plugin->info->name) ) { ShowWarning("HPM:plugin_load: '"CL_WHITE"%s"CL_RESET"' failed DataCheck, out of sync from the core (recompile plugin), skipping...\n", filename); HPM->unload(plugin); return NULL; @@ -275,10 +275,11 @@ void hplugins_config_read(void) { const char *config_filename = "conf/plugins.conf"; // FIXME hardcoded name FILE *fp; - if( !HPM->DataCheck ) { - ShowError("HPM:config_read: HPM->DataCheck not set! Failure\n"); - return; - } +// uncomment once login/char support is wrapped up +// if( !HPM->DataCheck ) { +// ShowError("HPM:config_read: HPM->DataCheck not set! Failure\n"); +// return; +// } /* yes its ugly, its temporary and will be gone as soon as the new inter-server.conf is set */ if( (fp = fopen("conf/import/plugins.conf","r")) ) { diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c index 1688f37ce..a67acfd16 100644 --- a/src/map/HPMmap.c +++ b/src/map/HPMmap.c @@ -133,7 +133,6 @@ bool HPM_map_DataCheck (struct s_HPMDataCheck *src, unsigned int size, char *nam return false; } else { j = strdb_uiget(datacheck_db, src[i].name);/* not double lookup; exists sets cache to found data */ - ShowDebug("Testing[%s/%s] %u vs %u\n",src[i].name,HPMDataCheck[j].name,src[i].size,HPMDataCheck[j].size); if( src[i].size != HPMDataCheck[j].size ) { ShowWarning("HPMDataCheck:%s: '%s' size mismatch %u != %u\n",name,src[i].name,src[i].size,HPMDataCheck[j].size); return false; diff --git a/src/map/map.c b/src/map/map.c index 2be61587f..74b81f467 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -3675,14 +3675,115 @@ int map_sql_close(void) return 0; } +/** + * Merges two zones into a new one + * @param main the zone whose data must override the others upon conflict, + * e.g. enabling pvp on a town means that main is the pvp zone, while "other" is the towns previous zone + * + * @return the newly created zone from merging main and other + **/ +struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone_data *other) { + char newzone[MAP_ZONE_NAME_LENGTH]; + struct map_zone_data *zone = NULL; + int cursor, i; + + sprintf(newzone, "%s+%s",main->name,other->name); + + if( (zone = strdb_get(map->zone_db, newzone)) ) + return zone;/* this zone has already been merged */ + + CREATE(zone, struct map_zone_data, 1); + + safestrncpy(zone->name, newzone, MAP_ZONE_NAME_LENGTH); + + zone->disabled_skills_count = main->disabled_skills_count + other->disabled_skills_count; + zone->disabled_items_count = main->disabled_items_count + other->disabled_items_count; + zone->mapflags_count = main->mapflags_count + other->mapflags_count; + zone->disabled_commands_count = main->disabled_commands_count + other->disabled_commands_count; + zone->capped_skills_count = main->capped_skills_count + other->capped_skills_count; + + CREATE(zone->disabled_skills, struct map_zone_disabled_skill_entry *, zone->disabled_skills_count ); + + for(i = 0, cursor = 0; i < main->disabled_skills_count; i++, cursor++ ) { + CREATE(zone->disabled_skills[cursor], struct map_zone_disabled_skill_entry, 1 ); + memcpy(zone->disabled_skills[cursor], main->disabled_skills[i], sizeof(struct map_zone_disabled_skill_entry)); + } + + for(i = 0; i < other->disabled_skills_count; i++, cursor++ ) { + CREATE(zone->disabled_skills[cursor], struct map_zone_disabled_skill_entry, 1 ); + memcpy(zone->disabled_skills[cursor], other->disabled_skills[i], sizeof(struct map_zone_disabled_skill_entry)); + } + + CREATE(zone->disabled_items, int, zone->disabled_items_count ); + + for(i = 0, cursor = 0; i < main->disabled_items_count; i++, cursor++ ) { + zone->disabled_items[cursor] = main->disabled_items[i]; + } + + for(i = 0; i < other->disabled_items_count; i++, cursor++ ) { + zone->disabled_items[cursor] = other->disabled_items[i]; + } + + CREATE(zone->mapflags, char *, zone->mapflags_count ); + + for(i = 0, cursor = 0; i < main->mapflags_count; i++, cursor++ ) { + CREATE(zone->mapflags[cursor], char, MAP_ZONE_MAPFLAG_LENGTH ); + safestrncpy(zone->mapflags[cursor], main->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH); + } + + for(i = 0; i < other->mapflags_count; i++, cursor++ ) { + CREATE(zone->mapflags[cursor], char, MAP_ZONE_MAPFLAG_LENGTH ); + safestrncpy(zone->mapflags[cursor], other->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH); + } + + CREATE(zone->disabled_commands, struct map_zone_disabled_command_entry *, zone->disabled_commands_count); + + for(i = 0, cursor = 0; i < main->disabled_commands_count; i++, cursor++ ) { + CREATE(zone->disabled_commands[cursor], struct map_zone_disabled_command_entry, 1); + memcpy(zone->disabled_commands[cursor], main->disabled_commands[i], sizeof(struct map_zone_disabled_command_entry)); + } + + for(i = 0; i < other->disabled_commands_count; i++, cursor++ ) { + CREATE(zone->disabled_commands[cursor], struct map_zone_disabled_command_entry, 1); + memcpy(zone->disabled_commands[cursor], other->disabled_commands[i], sizeof(struct map_zone_disabled_command_entry)); + } + + CREATE(zone->capped_skills, struct map_zone_skill_damage_cap_entry *, zone->capped_skills_count); + + + for(i = 0, cursor = 0; i < main->capped_skills_count; i++, cursor++ ) { + CREATE(zone->capped_skills[cursor], struct map_zone_skill_damage_cap_entry, 1); + memcpy(zone->capped_skills[cursor], main->disabled_commands[i], sizeof(struct map_zone_skill_damage_cap_entry)); + } + + for(i = 0; i < other->capped_skills_count; i++, cursor++ ) { + CREATE(zone->capped_skills[cursor], struct map_zone_skill_damage_cap_entry, 1); + memcpy(zone->capped_skills[cursor], other->capped_skills[i], sizeof(struct map_zone_skill_damage_cap_entry)); + } + + zone->info.special = 2; + + strdb_put(map->zone_db, newzone, zone); + + return zone; +} + void map_zone_change2(int m, struct map_zone_data *zone) { char empty[1] = "\0"; - map->list[m].prev_zone = map->list[m].zone; - + if( map->list[m].zone == zone ) + return; + + if( map->list[m].zone->info.special != 2 ) /* we don't update it for merged zones! */ + map->list[m].prev_zone = map->list[m].zone; + if( map->list[m].zone_mf_count ) map->zone_remove(m); + if( zone->info.special ) { + zone = map->merge_zone(zone,map->list[m].prev_zone); + } + map->zone_apply(m,zone,empty,empty,empty); } /* when changing from a mapflag to another during runtime */ @@ -4640,7 +4741,7 @@ void read_map_zone_db(void) { zone->disabled_skills_count = 0; zone->disabled_items_count = 0; } - safestrncpy(zone->name, zonename, MAP_ZONE_NAME_LENGTH); + safestrncpy(zone->name, zonename, MAP_ZONE_NAME_LENGTH/2); if( (skills = libconfig->setting_get_member(zone_e, "disabled_skills")) != NULL ) { disabled_skills_count = libconfig->setting_length(skills); @@ -4981,6 +5082,14 @@ void read_map_zone_db(void) { ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' zones in '"CL_WHITE"%s"CL_RESET"'.\n", zone_count, config_filename); /* not supposed to go in here but in skill_final whatever */ libconfig->destroy(&map_zone_db); + + /* post-load processing */ + if( (zone = strdb_get(map->zone_db, MAP_ZONE_PVP_NAME)) ) + zone->info.special = 1; + if( (zone = strdb_get(map->zone_db, MAP_ZONE_GVG_NAME)) ) + zone->info.special = 1; + if( (zone = strdb_get(map->zone_db, MAP_ZONE_BG_NAME)) ) + zone->info.special = 1; } } @@ -5943,6 +6052,8 @@ void map_defaults(void) { map->add_questinfo = map_add_questinfo; map->remove_questinfo = map_remove_questinfo; + map->merge_zone = map_merge_zone; + /** * mapit interface **/ @@ -5956,4 +6067,5 @@ void map_defaults(void) { mapit->next = mapit_next; mapit->prev = mapit_prev; mapit->exists = mapit_exists; + } diff --git a/src/map/map.h b/src/map/map.h index 8faf6388e..a4e9499b3 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -531,7 +531,7 @@ struct map_zone_skill_damage_cap_entry { enum map_zone_skill_subtype subtype; }; -#define MAP_ZONE_NAME_LENGTH 30 +#define MAP_ZONE_NAME_LENGTH 60 #define MAP_ZONE_ALL_NAME "All" #define MAP_ZONE_NORMAL_NAME "Normal" #define MAP_ZONE_PVP_NAME "PvP" @@ -552,6 +552,9 @@ struct map_zone_data { int disabled_commands_count; struct map_zone_skill_damage_cap_entry **capped_skills; int capped_skills_count; + struct { + unsigned int special : 2;/* 1: whether this is a mergeable zone; 2: whether it is a merged zone */ + } info; }; struct map_drop_list { @@ -1060,6 +1063,7 @@ struct map_interface { int (*get_new_bonus_id) (void); void (*add_questinfo) (int m, struct questinfo *qi); bool (*remove_questinfo) (int m, struct npc_data *nd); + struct map_zone_data *(*merge_zone) (struct map_zone_data *main, struct map_zone_data *other); }; struct map_interface *map; diff --git a/src/map/npc.c b/src/map/npc.c index 458fc52ed..36efc7267 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -3173,12 +3173,17 @@ void npc_unsetcells(struct npc_data* nd) { int16 m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys; int i,j, x0, x1, y0, y1; - if (nd->subtype == WARP) { - xs = nd->u.warp.xs; - ys = nd->u.warp.ys; - } else { - xs = nd->u.scr.xs; - ys = nd->u.scr.ys; + switch(nd->subtype) { + case WARP: + xs = nd->u.warp.xs; + ys = nd->u.warp.ys; + break; + case SCRIPT: + xs = nd->u.scr.xs; + ys = nd->u.scr.ys; + break; + default: + return; // Other types doesn't have touch area } if (m < 0 || xs < 0 || ys < 0 || map->list[m].cell == (struct mapcell *)0xdeadbeaf) -- cgit v1.2.3-60-g2f50