summaryrefslogtreecommitdiff
path: root/src/map/map.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/map.c')
-rw-r--r--src/map/map.c314
1 files changed, 180 insertions, 134 deletions
diff --git a/src/map/map.c b/src/map/map.c
index 343f219b8..9db868329 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -45,7 +45,6 @@
#include "map/mapreg.h"
#include "map/mercenary.h"
#include "map/mob.h"
-#include "map/npc.h"
#include "map/npc.h" // npc_setcells(), npc_unsetcells()
#include "map/party.h"
#include "map/path.h"
@@ -56,7 +55,9 @@
#include "map/skill.h"
#include "map/status.h"
#include "map/storage.h"
+#include "map/stylist.h"
#include "map/rodex.h"
+#include "map/refine.h"
#include "map/trade.h"
#include "map/unit.h"
#include "map/achievement.h"
@@ -635,6 +636,18 @@ static int map_foreachinmap(int (*func)(struct block_list*, va_list), int16 m, i
return returnCount;
}
+static int map_forcountinmap(int (*func)(struct block_list*, va_list), int16 m, int count, int type, ...)
+{
+ int returnCount;
+ va_list ap;
+
+ va_start(ap, type);
+ returnCount = map->vforcountinarea(func, m, 0, 0, map->list[m].xs, map->list[m].ys, count, type, ap);
+ va_end(ap);
+
+ return returnCount;
+}
+
/**
* Applies func to every block_list object of bl_type type on all maps
* of instance instance_id.
@@ -2254,30 +2267,25 @@ static struct map_session_data *map_charid2sd(int charid)
* (without sensitive case if necessary)
* return map_session_data pointer or NULL
*------------------------------------------*/
-static struct map_session_data *map_nick2sd(const char *nick)
+static struct map_session_data *map_nick2sd(const char *nick, bool allow_partial)
{
- struct map_session_data* sd;
- struct map_session_data* found_sd;
- struct s_mapiterator* iter;
- size_t nicklen;
- int qty = 0;
-
- if( nick == NULL )
+ if (nick == NULL)
return NULL;
- nicklen = strlen(nick);
- iter = mapit_getallusers();
+ struct s_mapiterator *iter = mapit_getallusers();
+ struct map_session_data *found_sd = NULL;
+
+ if (battle_config.partial_name_scan && allow_partial) {
+ int nicklen = (int)strlen(nick);
+ int qty = 0;
- found_sd = NULL;
- for (sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
- if( battle_config.partial_name_scan )
- {// partial name search
- if( strnicmp(sd->status.name, nick, nicklen) == 0 )
- {
+ // partial name search
+ for (struct map_session_data *sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
+ if (strnicmp(sd->status.name, nick, nicklen) == 0) {
found_sd = sd;
- if( strcmp(sd->status.name, nick) == 0 )
- {// Perfect Match
+ if (strcmp(sd->status.name, nick) == 0) {
+ // Perfect Match
qty = 1;
break;
}
@@ -2285,17 +2293,20 @@ static struct map_session_data *map_nick2sd(const char *nick)
qty++;
}
}
- else if( strcasecmp(sd->status.name, nick) == 0 )
- {// exact search only
- found_sd = sd;
- break;
+
+ if (qty != 1)
+ found_sd = NULL;
+ } else {
+ // exact search only
+ for (struct map_session_data *sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
+ if (strcasecmp(sd->status.name, nick) == 0) {
+ found_sd = sd;
+ break;
+ }
}
}
mapit->free(iter);
- if( battle_config.partial_name_scan && qty != 1 )
- found_sd = NULL;
-
return found_sd;
}
@@ -3572,23 +3583,27 @@ static void map_zone_db_clear(void)
}
static void map_clean(int i)
{
- int v;
Assert_retv(i >= 0 && i < map->count);
- if(map->list[i].cell && map->list[i].cell != (struct mapcell *)0xdeadbeaf) aFree(map->list[i].cell);
- if(map->list[i].block) aFree(map->list[i].block);
- if(map->list[i].block_mob) aFree(map->list[i].block_mob);
- if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random]
- int j;
- if(map->list[i].mob_delete_timer != INVALID_TIMER)
+ if (map->list[i].cell && map->list[i].cell != (struct mapcell *)0xdeadbeaf)
+ aFree(map->list[i].cell);
+ if (map->list[i].block)
+ aFree(map->list[i].block);
+ if (map->list[i].block_mob)
+ aFree(map->list[i].block_mob);
+
+ if (battle_config.dynamic_mobs != 0) { //Dynamic mobs flag by [random]
+ if (map->list[i].mob_delete_timer != INVALID_TIMER)
timer->delete(map->list[i].mob_delete_timer, map->removemobs_timer);
- for (j=0; j<MAX_MOB_LIST_PER_MAP; j++)
- if (map->list[i].moblist[j]) aFree(map->list[i].moblist[j]);
+ for (int j = 0; j < MAX_MOB_LIST_PER_MAP; j++) {
+ if (map->list[i].moblist[j] != NULL)
+ aFree(map->list[i].moblist[j]);
+ }
}
- if( map->list[i].unit_count ) {
- if( map->list[i].units ) {
- for(v = 0; v < map->list[i].unit_count; v++) {
+ if (map->list[i].unit_count != 0) {
+ if (map->list[i].units != NULL) {
+ for (int v = 0; v < map->list[i].unit_count; v++) {
aFree(map->list[i].units[v]);
}
aFree(map->list[i].units);
@@ -3597,105 +3612,51 @@ static void map_clean(int i)
map->list[i].unit_count = 0;
}
- if( map->list[i].skill_count ) {
- if( map->list[i].skills ) {
- for(v = 0; v < map->list[i].skill_count; v++) {
- aFree(map->list[i].skills[v]);
- }
+ if (map->list[i].skill_count != 0) {
+ if (map->list[i].skills != NULL) {
+ for (int v = 0; v < map->list[i].skill_count; v++) {
+ aFree(map->list[i].skills[v]);
+ }
aFree(map->list[i].skills);
map->list[i].skills = NULL;
}
map->list[i].skill_count = 0;
}
- if( map->list[i].zone_mf_count ) {
- if( map->list[i].zone_mf ) {
- for(v = 0; v < map->list[i].zone_mf_count; v++) {
- aFree(map->list[i].zone_mf[v]);
- }
+ if (map->list[i].zone_mf_count != 0) {
+ if (map->list[i].zone_mf != NULL) {
+ for (int v = 0; v < map->list[i].zone_mf_count; v++) {
+ aFree(map->list[i].zone_mf[v]);
+ }
aFree(map->list[i].zone_mf);
map->list[i].zone_mf = NULL;
}
map->list[i].zone_mf_count = 0;
}
- if( map->list[i].channel )
+ if (map->list[i].drop_list_count != 0)
+ map->list[i].drop_list_count = 0;
+ if (map->list[i].drop_list != NULL)
+ aFree(map->list[i].drop_list);
+
+ if (map->list[i].channel != NULL)
channel->delete(map->list[i].channel);
+
+ VECTOR_CLEAR(map->list[i].qi_list);
+ HPM->data_store_destroy(&map->list[i].hdata);
}
static void do_final_maps(void)
{
- int i, v = 0;
-
- for( i = 0; i < map->count; i++ ) {
-
- if(map->list[i].cell && map->list[i].cell != (struct mapcell *)0xdeadbeaf ) aFree(map->list[i].cell);
- if(map->list[i].block) aFree(map->list[i].block);
- if(map->list[i].block_mob) aFree(map->list[i].block_mob);
-
- if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random]
- int j;
- if(map->list[i].mob_delete_timer != INVALID_TIMER)
- timer->delete(map->list[i].mob_delete_timer, map->removemobs_timer);
- for (j=0; j<MAX_MOB_LIST_PER_MAP; j++)
- if (map->list[i].moblist[j]) aFree(map->list[i].moblist[j]);
- }
-
- if( map->list[i].unit_count ) {
- if( map->list[i].units ) {
- for(v = 0; v < map->list[i].unit_count; v++) {
- aFree(map->list[i].units[v]);
- }
- aFree(map->list[i].units);
- map->list[i].units = NULL;
- }
- map->list[i].unit_count = 0;
- }
-
- if( map->list[i].skill_count ) {
- if( map->list[i].skills ) {
- for(v = 0; v < map->list[i].skill_count; v++) {
- aFree(map->list[i].skills[v]);
- }
- aFree(map->list[i].skills);
- map->list[i].skills = NULL;
- }
- map->list[i].skill_count = 0;
- }
-
- if( map->list[i].zone_mf_count ) {
- if( map->list[i].zone_mf ) {
- for(v = 0; v < map->list[i].zone_mf_count; v++) {
- aFree(map->list[i].zone_mf[v]);
- }
- aFree(map->list[i].zone_mf);
- map->list[i].zone_mf = NULL;
- }
- map->list[i].zone_mf_count = 0;
- }
-
- if( map->list[i].drop_list_count ) {
- map->list[i].drop_list_count = 0;
- }
- if( map->list[i].drop_list != NULL )
- aFree(map->list[i].drop_list);
-
- if( map->list[i].channel )
- channel->delete(map->list[i].channel);
-
- quest->questinfo_vector_clear(i);
-
- HPM->data_store_destroy(&map->list[i].hdata);
- }
-
+ for (int i = 0; i < map->count; i++)
+ map->clean(i);
map->zone_db_clear();
-
}
static void map_zonedb_reload(void)
{
// first, reset maps to their initial zones:
for (int i = 0; i < map->count; i++) {
- map->zone_remove(i);
+ map->zone_remove_all(i);
if (battle_config.pk_mode) {
map->list[i].flag.pvp = 1;
@@ -3779,7 +3740,8 @@ static void map_flags_init(void)
map->list[i].short_damage_rate = 100;
map->list[i].long_damage_rate = 100;
- VECTOR_INIT(map->list[i].qi_data);
+ VECTOR_CLEAR(map->list[i].qi_list);
+ VECTOR_INIT(map->list[i].qi_list);
}
}
@@ -3807,8 +3769,29 @@ static int map_waterheight(char *mapname)
// read & convert fn
rsw = grfio_read(fn);
if (rsw) {
+ if (memcmp(rsw, "GRSW", 4) != 0) {
+ ShowWarning("Failed to find water level for %s (%s)\n", mapname, fn);
+ aFree(rsw);
+ return NO_WATER;
+ }
+ int major_version = rsw[4];
+ int minor_version = rsw[5];
+ if (major_version > 2 || (major_version == 2 && minor_version > 2)) {
+ ShowWarning("Failed to find water level for %s (%s)\n", mapname, fn);
+ aFree(rsw);
+ return NO_WATER;
+ }
+ if (major_version < 1 || (major_version == 1 && minor_version <= 4)) {
+ ShowWarning("Failed to find water level for %s (%s)\n", mapname, fn);
+ aFree(rsw);
+ return NO_WATER;
+ }
+ int offset = 166;
+ if (major_version == 2 && minor_version >= 2) {
+ offset = 167;
+ }
//Load water height from file
- int wh = (int) *(float*)(rsw+166);
+ int wh = (int)*(float*)(rsw + offset);
aFree(rsw);
return wh;
}
@@ -4092,6 +4075,7 @@ static bool map_config_read_database(const char *filename, struct config_t *conf
return false;
}
libconfig->setting_lookup_mutable_string(setting, "db_path", map->db_path, sizeof(map->db_path));
+ libconfig->set_db_path(map->db_path);
libconfig->setting_lookup_int(setting, "save_settings", &map->save_settings);
if (libconfig->setting_lookup_int(setting, "autosave_time", &map->autosave_interval) == CONFIG_TRUE) {
@@ -4467,6 +4451,7 @@ static bool inter_config_read_database_names(const char *filename, const struct
libconfig->setting_lookup_mutable_string(setting, "autotrade_merchants_db", map->autotrade_merchants_db, sizeof(map->autotrade_merchants_db));
libconfig->setting_lookup_mutable_string(setting, "autotrade_data_db", map->autotrade_data_db, sizeof(map->autotrade_data_db));
libconfig->setting_lookup_mutable_string(setting, "npc_market_data_db", map->npc_market_data_db, sizeof(map->npc_market_data_db));
+ libconfig->setting_lookup_mutable_string(setting, "npc_barter_data_db", map->npc_barter_data_db, sizeof(map->npc_barter_data_db));
if (!mapreg->config_read(filename, setting, imported))
retval = false;
@@ -4676,6 +4661,27 @@ static void map_zone_remove(int m)
map->list[m].zone_mf = NULL;
map->list[m].zone_mf_count = 0;
}
+// this one removes every flag, even if they were previously turned on before
+// the current zone was applied
+static void map_zone_remove_all(int m)
+{
+ Assert_retv(m >= 0 && m < map->count);
+
+ for (unsigned short k = 0; k < map->list[m].zone_mf_count; k++) {
+ char flag[MAP_ZONE_MAPFLAG_LENGTH];
+
+ memcpy(flag, map->list[m].zone_mf[k], MAP_ZONE_MAPFLAG_LENGTH);
+ strtok(flag, "\t");
+
+ npc->parse_mapflag(map->list[m].name, "", flag, "off", "", "", "", NULL);
+ aFree(map->list[m].zone_mf[k]);
+ map->list[m].zone_mf[k] = NULL;
+ }
+
+ aFree(map->list[m].zone_mf);
+ map->list[m].zone_mf = NULL;
+ map->list[m].zone_mf_count = 0;
+}
static inline void map_zone_mf_cache_add(int m, char *rflag)
{
Assert_retv(m >= 0 && m < map->count);
@@ -5392,6 +5398,32 @@ static bool map_zone_mf_cache(int m, char *flag, char *params)
else if( map->list[m].flag.nocashshop )
map_zone_mf_cache_add(m,"nocashshop");
}
+ } else if (strcmpi(flag, "nostorage") == 0) {
+ if (!state) {
+ if (map->list[m].flag.nostorage != 0) {
+ sprintf(rflag, "nostorage\t%d", map->list[m].flag.nostorage);
+ map_zone_mf_cache_add(m, rflag);
+ }
+ }
+ if (sscanf(params, "%d", &state) == 1) {
+ if (state != map->list[m].flag.nostorage) {
+ sprintf(rflag, "nostorage\t%d", state);
+ map_zone_mf_cache_add(m, rflag);
+ }
+ }
+ } else if (strcmpi(flag, "nogstorage") == 0) {
+ if (!state) {
+ if (map->list[m].flag.nogstorage != 0) {
+ sprintf(rflag, "nogstorage\t%d", map->list[m].flag.nogstorage);
+ map_zone_mf_cache_add(m, rflag);
+ }
+ }
+ if (sscanf(params, "%d", &state) == 1) {
+ if (state != map->list[m].flag.nogstorage) {
+ sprintf(rflag, "nogstorage\t%d", state);
+ map_zone_mf_cache_add(m, rflag);
+ }
+ }
}
return false;
@@ -5563,12 +5595,8 @@ static void read_map_zone_db(void)
{
struct config_t map_zone_db;
struct config_setting_t *zones = NULL;
- /* TODO: #ifndef required for re/pre-re */
-#ifdef RENEWAL
- const char *config_filename = "db/re/map_zone_db.conf"; // FIXME hardcoded name
-#else
- const char *config_filename = "db/pre-re/map_zone_db.conf"; // FIXME hardcoded name
-#endif
+ char config_filename[256];
+ libconfig->format_db_path(DBPATH"map_zone_db.conf", config_filename, sizeof(config_filename));
if (!libconfig->load_file(&map_zone_db, config_filename))
return;
@@ -5993,28 +6021,30 @@ static int map_get_new_bonus_id(void)
return map->bonus_id++;
}
-static void map_add_questinfo(int m, struct questinfo *qi)
+static bool map_add_questinfo(int m, struct npc_data *nd)
{
- nullpo_retv(qi);
- Assert_retv(m >= 0 && m < map->count);
+ nullpo_retr(false, nd);
+ Assert_retr(false, m >= 0 && m < map->count);
+
+ if (&VECTOR_LAST(map->list[m].qi_list) == nd)
+ return false;
- VECTOR_ENSURE(map->list[m].qi_data, 1, 1);
- VECTOR_PUSH(map->list[m].qi_data, *qi);
+ VECTOR_ENSURE(map->list[m].qi_list, 1, 1);
+ VECTOR_PUSH(map->list[m].qi_list, *nd);
+ return true;
}
static bool map_remove_questinfo(int m, struct npc_data *nd)
{
- unsigned short i;
nullpo_retr(false, nd);
Assert_retr(false, m >= 0 && m < map->count);
- for (i = 0; i < VECTOR_LENGTH(map->list[m].qi_data); i++) {
- struct questinfo *qi_data = &VECTOR_INDEX(map->list[m].qi_data, i);
- if (qi_data->nd == nd) {
- VECTOR_ERASE(map->list[m].qi_data, i);
- return true;
- }
+ int i;
+ ARR_FIND(0, VECTOR_LENGTH(map->list[m].qi_list), i, &VECTOR_INDEX(map->list[m].qi_list, i) == nd);
+ if (i != VECTOR_LENGTH(map->list[m].qi_list)) {
+ VECTOR_ERASE(map->list[m].qi_list, i);
+ return true;
}
return false;
}
@@ -6155,6 +6185,7 @@ int do_final(void)
atcommand->final_msg();
skill->final();
status->final();
+ refine->final();
unit->final();
bg->final();
duel->final();
@@ -6163,6 +6194,7 @@ int do_final(void)
vending->final();
rodex->final();
achievement->final();
+ stylist->final();
HPM_map_do_final();
@@ -6290,6 +6322,7 @@ static CPCMD(gm_position)
map->cpsd->bl.x = x;
map->cpsd->bl.y = y;
map->cpsd->bl.m = m;
+ map->cpsd->mapindex = map_id2index(m);
}
static CPCMD(gm_use)
{
@@ -6318,6 +6351,8 @@ static void map_cp_defaults(void)
map->cpsd->bl.x = mapindex->default_x;
map->cpsd->bl.y = mapindex->default_y;
map->cpsd->bl.m = map->mapname2mapid(mapindex->default_map);
+ Assert_retv(map->cpsd->bl.m >= 0);
+ map->cpsd->mapindex = map_id2index(map->cpsd->bl.m);
console->input->addCommand("gm:info",CPCMD_A(gm_position));
console->input->addCommand("gm:use",CPCMD_A(gm_use));
@@ -6370,6 +6405,8 @@ static void map_load_defaults(void)
achievement_defaults();
npc_chat_defaults();
rodex_defaults();
+ stylist_defaults();
+ refine_defaults();
}
/**
* --run-once handler
@@ -6674,6 +6711,7 @@ int do_init(int argc, char *argv[])
map->read_zone_db();/* read after item and skill initialization */
mob->init(minimal);
pc->init(minimal);
+ refine->init(minimal);
status->init(minimal);
party->init(minimal);
guild->init(minimal);
@@ -6684,6 +6722,7 @@ int do_init(int argc, char *argv[])
elemental->init(minimal);
quest->init(minimal);
achievement->init(minimal);
+ stylist->init(minimal);
npc->init(minimal);
unit->init(minimal);
bg->init(minimal);
@@ -6709,6 +6748,7 @@ int do_init(int argc, char *argv[])
npc->event_do_oninit( false ); // Init npcs (OnInit)
npc->market_fromsql(); /* after OnInit */
+ npc->barter_fromsql(); /* after OnInit */
if (battle_config.pk_mode)
ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n");
@@ -6754,6 +6794,7 @@ void map_defaults(void)
map->extra_scripts_count = 0;
sprintf(map->db_path ,"db");
+ libconfig->set_db_path(map->db_path);
sprintf(map->help_txt ,"conf/help.txt");
sprintf(map->charhelp_txt ,"conf/charhelp.txt");
@@ -6815,7 +6856,10 @@ void map_defaults(void)
map->bl_list_size = 0;
//all in a big chunk, respects order
+PRAGMA_GCC9(GCC diagnostic push)
+PRAGMA_GCC9(GCC diagnostic ignored "-Warray-bounds")
memset(ZEROED_BLOCK_POS(map), 0, ZEROED_BLOCK_SIZE(map));
+PRAGMA_GCC9(GCC diagnostic pop)
map->cpsd = NULL;
map->list = NULL;
@@ -6828,6 +6872,7 @@ void map_defaults(void)
/* funcs */
map->zone_init = map_zone_init;
map->zone_remove = map_zone_remove;
+ map->zone_remove_all = map_zone_remove_all;
map->zone_apply = map_zone_apply;
map->zone_change = map_zone_change;
map->zone_change2 = map_zone_change2;
@@ -6901,6 +6946,7 @@ void map_defaults(void)
map->foreachinpath = map_foreachinpath;
map->vforeachinmap = map_vforeachinmap;
map->foreachinmap = map_foreachinmap;
+ map->forcountinmap = map_forcountinmap;
map->vforeachininstance = map_vforeachininstance;
map->foreachininstance = map_foreachininstance;