summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2014-02-03 14:09:58 -0200
committershennetsind <ind@henn.et>2014-02-03 14:09:58 -0200
commit50bc76c412b6618d90fdbdb24d43da2bda0525a2 (patch)
treea98a1b4cd9aaa335b3361f2ef5cd7081b7469df2
parent9132878d911cfe720eaad94ad3d4a5dd11958f99 (diff)
downloadhercules-50bc76c412b6618d90fdbdb24d43da2bda0525a2.tar.gz
hercules-50bc76c412b6618d90fdbdb24d43da2bda0525a2.tar.bz2
hercules-50bc76c412b6618d90fdbdb24d43da2bda0525a2.tar.xz
hercules-50bc76c412b6618d90fdbdb24d43da2bda0525a2.zip
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 <ind@henn.et>
-rw-r--r--src/common/HPM.c11
-rw-r--r--src/map/HPMmap.c1
-rw-r--r--src/map/map.c118
-rw-r--r--src/map/map.h6
-rw-r--r--src/map/npc.c17
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)