diff options
Diffstat (limited to 'src/map')
40 files changed, 3233 insertions, 4274 deletions
diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 56ff2ab..c066a46 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -127,10 +127,6 @@ ATCOMMAND_FUNC(enablenpc); ATCOMMAND_FUNC(disablenpc); ATCOMMAND_FUNC(servertime); // by Yor ATCOMMAND_FUNC(chardelitem); // by Yor -ATCOMMAND_FUNC(ignorelist); // by Yor -ATCOMMAND_FUNC(charignorelist); // by Yor -ATCOMMAND_FUNC(inall); // by Yor -ATCOMMAND_FUNC(exall); // by Yor ATCOMMAND_FUNC(email); // by Yor ATCOMMAND_FUNC(effect); //by Apple ATCOMMAND_FUNC(character_item_list); // by Yor @@ -293,10 +289,6 @@ AtCommandInfo atcommand_info[] = {"@servertime", 0, atcommand_servertime}, // by Yor {"@chardelitem", 60, atcommand_chardelitem}, // by Yor {"@listnearby", 40, atcommand_list_nearby}, // by Yor - {"@ignorelist", 0, atcommand_ignorelist}, // by Yor - {"@charignorelist", 20, atcommand_charignorelist}, // by Yor - {"@inall", 20, atcommand_inall}, // by Yor - {"@exall", 20, atcommand_exall}, // by Yor {"@email", 0, atcommand_email}, // by Yor {"@effect", 40, atcommand_effect}, // by Apple {"@charitemlist", 40, atcommand_character_item_list}, // by Yor @@ -372,19 +364,19 @@ void log_atcommand(dumb_ptr<map_session_data> sd, const_string cmd) stamp_time(tmpstr); fprintf(fp, "[%s] %s(%d,%d) %s(%d) : ", tmpstr, - map[sd->bl_m].name, sd->bl_x, sd->bl_y, + sd->bl_m->name, sd->bl_x, sd->bl_y, sd->status.name, sd->status.account_id); fwrite(cmd.data(), 1, cmd.size(), fp); } -char *gm_logfile_name = NULL; +std::string gm_logfile_name; /*========================================== * Log a timestamped line to GM log file *------------------------------------------ */ FILE *get_gm_log() { - if (!gm_logfile_name) + if (gm_logfile_name.empty()) return NULL; struct tm ctime = TimeT::now(); @@ -410,7 +402,7 @@ FILE *get_gm_log() if (!gm_logfile) { perror("GM log file"); - gm_logfile_name = NULL; + gm_logfile_name.clear(); } return gm_logfile; } @@ -642,7 +634,6 @@ int atcommand_charwarp(const int fd, dumb_ptr<map_session_data> sd, char character[100]; int x = 0, y = 0; dumb_ptr<map_session_data> pl_sd; - int m; memset(map_name, '\0', sizeof(map_name)); memset(character, '\0', sizeof(character)); @@ -669,15 +660,15 @@ int atcommand_charwarp(const int fd, dumb_ptr<map_session_data> sd, { // you can rura+ only lower or same GM level if (x > 0 && x < 800 && y > 0 && y < 800) { - m = map_mapname2mapid(map_name); - if (m >= 0 && map[m].flag.nowarpto + map_local *m = map_mapname2mapid(map_name); + if (m != nullptr && m->flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, "You are not authorised to warp someone to this map."); return -1; } - if (pl_sd->bl_m >= 0 && map[pl_sd->bl_m].flag.nowarp + if (pl_sd->bl_m != nullptr && pl_sd->bl_m->flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, @@ -725,7 +716,6 @@ int atcommand_warp(const int fd, dumb_ptr<map_session_data> sd, { char map_name[100]; int x = 0, y = 0; - int m; memset(map_name, '\0', sizeof(map_name)); @@ -747,15 +737,15 @@ int atcommand_warp(const int fd, dumb_ptr<map_session_data> sd, if (x > 0 && x < 800 && y > 0 && y < 800) { - m = map_mapname2mapid(map_name); - if (m >= 0 && map[m].flag.nowarpto + map_local *m = map_mapname2mapid(map_name); + if (m != nullptr && m->flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, "You are not authorised to warp you to this map."); return -1; } - if (sd->bl_m >= 0 && map[sd->bl_m].flag.nowarp + if (sd->bl_m != nullptr && sd->bl_m->flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, @@ -834,14 +824,14 @@ int atcommand_goto(const int fd, dumb_ptr<map_session_data> sd, if ((pl_sd = map_nick2sd(character)) != NULL) { - if (pl_sd->bl_m >= 0 && map[pl_sd->bl_m].flag.nowarpto + if (pl_sd->bl_m != nullptr && pl_sd->bl_m->flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, "You are not authorised to warp you to the map of this player."); return -1; } - if (sd->bl_m >= 0 && map[sd->bl_m].flag.nowarp + if (sd->bl_m != nullptr && sd->bl_m->flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, @@ -877,14 +867,14 @@ int atcommand_jump(const int fd, dumb_ptr<map_session_data> sd, y = random_::in(1, 399); if (x > 0 && x < 800 && y > 0 && y < 800) { - if (sd->bl_m >= 0 && map[sd->bl_m].flag.nowarpto + if (sd->bl_m != nullptr && sd->bl_m->flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, "You are not authorised to warp you to your actual map."); return -1; } - if (sd->bl_m >= 0 && map[sd->bl_m].flag.nowarp + if (sd->bl_m != nullptr && sd->bl_m->flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, @@ -1056,7 +1046,7 @@ int atcommand_whomap(const int fd, dumb_ptr<map_session_data> sd, { int count; int pl_GM_level, GM_level; - int map_id; + map_local *map_id; char map_name[100]; memset(map_name, '\0', sizeof(map_name)); @@ -1068,7 +1058,8 @@ int atcommand_whomap(const int fd, dumb_ptr<map_session_data> sd, sscanf(message, "%99s", map_name); if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat) strcat(map_name, ".gat"); - if ((map_id = map_mapname2mapid(map_name)) < 0) + map_id = map_mapname2mapid(map_name); + if (map_id == nullptr) map_id = sd->bl_m; } @@ -1108,7 +1099,7 @@ int atcommand_whomap(const int fd, dumb_ptr<map_session_data> sd, } std::string output = STRPRINTF("%d players found in map '%s'.", - count, map[map_id].name); + count, map_id->name); clif_displaymessage(fd, output); return 0; @@ -1123,12 +1114,12 @@ int atcommand_whomapgroup(const int fd, dumb_ptr<map_session_data> sd, { int count; int pl_GM_level, GM_level; - int map_id = 0; char map_name[100]; struct party *p; memset(map_name, '\0', sizeof(map_name)); + map_local *map_id; if (!message || !*message) map_id = sd->bl_m; else @@ -1136,7 +1127,8 @@ int atcommand_whomapgroup(const int fd, dumb_ptr<map_session_data> sd, sscanf(message, "%99s", map_name); if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat) strcat(map_name, ".gat"); - if ((map_id = map_mapname2mapid(map_name)) < 0) + map_id = map_mapname2mapid(map_name); + if (map_id == nullptr) map_id = sd->bl_m; } @@ -1176,12 +1168,12 @@ int atcommand_whomapgroup(const int fd, dumb_ptr<map_session_data> sd, std::string output; if (count == 0) - output = STRPRINTF("No player found in map '%s'.", map[map_id].name); + output = STRPRINTF("No player found in map '%s'.", map_id->name); else if (count == 1) - output = STRPRINTF("1 player found in map '%s'.", map[map_id].name); + output = STRPRINTF("1 player found in map '%s'.", map_id->name); else { - output = STRPRINTF("%d players found in map '%s'.", count, map[map_id].name); + output = STRPRINTF("%d players found in map '%s'.", count, map_id->name); } clif_displaymessage(fd, output); @@ -1295,17 +1287,15 @@ int atcommand_save(const int fd, dumb_ptr<map_session_data> sd, int atcommand_load(const int fd, dumb_ptr<map_session_data> sd, const char *, const char *) { - int m; - - m = map_mapname2mapid(sd->status.save_point.map); - if (m >= 0 && map[m].flag.nowarpto + map_local *m = map_mapname2mapid(sd->status.save_point.map); + if (m != nullptr && m->flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, "You are not authorised to warp you to your save map."); return -1; } - if (sd->bl_m >= 0 && map[sd->bl_m].flag.nowarp + if (sd->bl_m != nullptr && sd->bl_m->flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, @@ -1894,9 +1884,9 @@ int atcommand_pvpoff(const int fd, dumb_ptr<map_session_data> sd, return -1; } - if (map[sd->bl_m].flag.pvp) + if (sd->bl_m->flag.pvp) { - map[sd->bl_m].flag.pvp = 0; + sd->bl_m->flag.pvp = 0; for (int i = 0; i < fd_max; i++) { if (!session[i]) @@ -1934,9 +1924,9 @@ int atcommand_pvpon(const int fd, dumb_ptr<map_session_data> sd, return -1; } - if (!map[sd->bl_m].flag.pvp && !map[sd->bl_m].flag.nopvp) + if (!sd->bl_m->flag.pvp && !sd->bl_m->flag.nopvp) { - map[sd->bl_m].flag.pvp = 1; + sd->bl_m->flag.pvp = 1; for (int i = 0; i < fd_max; i++) { if (!session[i]) @@ -2210,23 +2200,27 @@ static void atcommand_killmonster_sub(const int fd, dumb_ptr<map_session_data> sd, const char *message, const int drop) { - int map_id; char map_name[100]; memset(map_name, '\0', sizeof(map_name)); + map_local *map_id; if (!message || !*message || sscanf(message, "%99s", map_name) < 1) map_id = sd->bl_m; else { if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat) strcat(map_name, ".gat"); - if ((map_id = map_mapname2mapid(map_name)) < 0) + map_id = map_mapname2mapid(map_name); + if (map_id == nullptr) map_id = sd->bl_m; } - map_foreachinarea(std::bind(atkillmonster_sub, ph::_1, drop), map_id, 0, 0, map[map_id].xs, - map[map_id].ys, BL::MOB); + map_foreachinarea(std::bind(atkillmonster_sub, ph::_1, drop), + map_id, + 0, 0, + map_id->xs, map_id->ys, + BL::MOB); clif_displaymessage(fd, "All monsters killed!"); @@ -2268,8 +2262,10 @@ int atcommand_list_nearby(const int fd, dumb_ptr<map_session_data> sd, { clif_displaymessage(fd, "Nearby players:"); map_foreachinarea(std::bind(atlist_nearby_sub, ph::_1, fd), - sd->bl_m, sd->bl_x - 1, sd->bl_y - 1, - sd->bl_x + 1, sd->bl_x + 1, BL::PC); + sd->bl_m, + sd->bl_x - 1, sd->bl_y - 1, + sd->bl_x + 1, sd->bl_x + 1, + BL::PC); return 0; } @@ -2299,7 +2295,7 @@ int atcommand_gat(const int fd, dumb_ptr<map_session_data> sd, { std::string output = STRPRINTF( "%s (x= %d, y= %d) %02X %02X %02X %02X %02X", - map[sd->bl_m].name, sd->bl_x - 2, sd->bl_y + y, + sd->bl_m->name, sd->bl_x - 2, sd->bl_y + y, map_getcell(sd->bl_m, sd->bl_x - 2, sd->bl_y + y), map_getcell(sd->bl_m, sd->bl_x - 1, sd->bl_y + y), map_getcell(sd->bl_m, sd->bl_x, sd->bl_y + y), @@ -2348,15 +2344,15 @@ int atcommand_statuspoint(const int fd, dumb_ptr<map_session_data> sd, return -1; } - new_status_point = (int) sd->status.status_point + point; + new_status_point = sd->status.status_point + point; if (point > 0 && (point > 0x7FFF || new_status_point > 0x7FFF)) // fix positiv overflow new_status_point = 0x7FFF; else if (point < 0 && (point < -0x7FFF || new_status_point < 0)) // fix negativ overflow new_status_point = 0; - if (new_status_point != (int) sd->status.status_point) + if (new_status_point != sd->status.status_point) { - sd->status.status_point = (short) new_status_point; + sd->status.status_point = new_status_point; clif_updatestatus(sd, SP::STATUSPOINT); clif_displaymessage(fd, "Number of status points changed!"); } @@ -2388,15 +2384,15 @@ int atcommand_skillpoint(const int fd, dumb_ptr<map_session_data> sd, return -1; } - new_skill_point = (int) sd->status.skill_point + point; + new_skill_point = sd->status.skill_point + point; if (point > 0 && (point > 0x7FFF || new_skill_point > 0x7FFF)) // fix positiv overflow new_skill_point = 0x7FFF; else if (point < 0 && (point < -0x7FFF || new_skill_point < 0)) // fix negativ overflow new_skill_point = 0; - if (new_skill_point != (int) sd->status.skill_point) + if (new_skill_point != sd->status.skill_point) { - sd->status.skill_point = (short) new_skill_point; + sd->status.skill_point = new_skill_point; clif_updatestatus(sd, SP::SKILLPOINT); clif_displaymessage(fd, "Number of skill points changed!"); } @@ -2473,7 +2469,7 @@ int atcommand_param(const int fd, dumb_ptr<map_session_data> sd, return -1; } - new_value = (int) sd->status.attrs[attr] + value; + new_value = sd->status.attrs[attr] + value; if (value > 0 && (value > battle_config.max_parameter || new_value > battle_config.max_parameter)) // fix positiv overflow new_value = battle_config.max_parameter; else if (value < 0 && (value < -battle_config.max_parameter || new_value < 1)) // fix negativ overflow @@ -2569,14 +2565,14 @@ int atcommand_recall(const int fd, dumb_ptr<map_session_data> sd, { if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can recall only lower or same level - if (sd->bl_m >= 0 && map[sd->bl_m].flag.nowarpto + if (sd->bl_m != nullptr && sd->bl_m->flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, "You are not authorised to warp somenone to your actual map."); return -1; } - if (pl_sd->bl_m >= 0 && map[pl_sd->bl_m].flag.nowarp + if (pl_sd->bl_m != nullptr && pl_sd->bl_m->flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, @@ -3094,7 +3090,6 @@ int atcommand_character_save(const int fd, dumb_ptr<map_session_data> sd, char character[100]; dumb_ptr<map_session_data> pl_sd; int x = 0, y = 0; - int m; memset(map_name, '\0', sizeof(map_name)); memset(character, '\0', sizeof(character)); @@ -3114,16 +3109,17 @@ int atcommand_character_save(const int fd, dumb_ptr<map_session_data> sd, if ((pl_sd = map_nick2sd(character)) != NULL) { if (pc_isGM(sd) >= pc_isGM(pl_sd)) - { // you can change save point only to lower or same gm level - m = map_mapname2mapid(map_name); - if (m < 0) + { + // you can change save point only to lower or same gm level + map_local *m = map_mapname2mapid(map_name); + if (m == nullptr) { clif_displaymessage(fd, "Map not found."); return -1; } else { - if (m >= 0 && map[m].flag.nowarpto + if (m != nullptr && m->flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, @@ -4113,12 +4109,12 @@ int atcommand_charskpoint(const int fd, dumb_ptr<map_session_data>, if ((pl_sd = map_nick2sd(character)) != NULL) { - new_skill_point = (int) pl_sd->status.skill_point + point; + new_skill_point = pl_sd->status.skill_point + point; if (point > 0 && (point > 0x7FFF || new_skill_point > 0x7FFF)) // fix positiv overflow new_skill_point = 0x7FFF; else if (point < 0 && (point < -0x7FFF || new_skill_point < 0)) // fix negativ overflow new_skill_point = 0; - if (new_skill_point != (int) pl_sd->status.skill_point) + if (new_skill_point != pl_sd->status.skill_point) { pl_sd->status.skill_point = new_skill_point; clif_updatestatus(pl_sd, SP::SKILLPOINT); @@ -4167,12 +4163,12 @@ int atcommand_charstpoint(const int fd, dumb_ptr<map_session_data>, if ((pl_sd = map_nick2sd(character)) != NULL) { - new_status_point = (int) pl_sd->status.status_point + point; + new_status_point = pl_sd->status.status_point + point; if (point > 0 && (point > 0x7FFF || new_status_point > 0x7FFF)) // fix positiv overflow new_status_point = 0x7FFF; else if (point < 0 && (point < -0x7FFF || new_status_point < 0)) // fix negativ overflow new_status_point = 0; - if (new_status_point != (int) pl_sd->status.status_point) + if (new_status_point != pl_sd->status.status_point) { pl_sd->status.status_point = new_status_point; clif_updatestatus(pl_sd, SP::STATUSPOINT); @@ -4257,7 +4253,7 @@ int atcommand_recallall(const int fd, dumb_ptr<map_session_data> sd, { int count; - if (sd->bl_m >= 0 && map[sd->bl_m].flag.nowarpto + if (sd->bl_m != nullptr && sd->bl_m->flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, @@ -4277,7 +4273,7 @@ int atcommand_recallall(const int fd, dumb_ptr<map_session_data> sd, && pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can recall only lower or same level - if (pl_sd->bl_m >= 0 && map[pl_sd->bl_m].flag.nowarp + if (pl_sd->bl_m != nullptr && pl_sd->bl_m->flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) count++; else @@ -4317,7 +4313,7 @@ int atcommand_partyrecall(const int fd, dumb_ptr<map_session_data> sd, return -1; } - if (sd->bl_m >= 0 && map[sd->bl_m].flag.nowarpto + if (sd->bl_m != nullptr && sd->bl_m->flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, @@ -4338,7 +4334,7 @@ int atcommand_partyrecall(const int fd, dumb_ptr<map_session_data> sd, && sd->status.account_id != pl_sd->status.account_id && pl_sd->status.party_id == p->party_id) { - if (pl_sd->bl_m >= 0 && map[pl_sd->bl_m].flag.nowarp + if (pl_sd->bl_m != nullptr && pl_sd->bl_m->flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) count++; else @@ -4448,7 +4444,7 @@ int atcommand_mapinfo(const int fd, dumb_ptr<map_session_data> sd, dumb_ptr<npc_data> nd = NULL; char map_name[100]; const char *direction = NULL; - int m_id, list = 0; + int list = 0; memset(map_name, '\0', sizeof(map_name)); @@ -4466,7 +4462,8 @@ int atcommand_mapinfo(const int fd, dumb_ptr<map_session_data> sd, if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat) strcat(map_name, ".gat"); - if ((m_id = map_mapname2mapid(map_name)) < 0) + map_local *m_id = map_mapname2mapid(map_name); + if (m_id != nullptr) { clif_displaymessage(fd, "Map not found."); return -1; @@ -4475,38 +4472,38 @@ int atcommand_mapinfo(const int fd, dumb_ptr<map_session_data> sd, clif_displaymessage(fd, "------ Map Info ------"); std::string output = STRPRINTF("Map Name: %s", map_name); clif_displaymessage(fd, output); - output = STRPRINTF("Players In Map: %d", map[m_id].users); + output = STRPRINTF("Players In Map: %d", m_id->users); clif_displaymessage(fd, output); - output = STRPRINTF("NPCs In Map: %d", map[m_id].npc_num); + output = STRPRINTF("NPCs In Map: %d", m_id->npc_num); clif_displaymessage(fd, output); clif_displaymessage(fd, "------ Map Flags ------"); output = STRPRINTF("Player vs Player: %s | No Party: %s", - (map[m_id].flag.pvp) ? "True" : "False", - (map[m_id].flag.pvp_noparty) ? "True" : "False"); + (m_id->flag.pvp) ? "True" : "False", + (m_id->flag.pvp_noparty) ? "True" : "False"); clif_displaymessage(fd, output); output = STRPRINTF("No Dead Branch: %s", - (map[m_id].flag.nobranch) ? "True" : "False"); + (m_id->flag.nobranch) ? "True" : "False"); clif_displaymessage(fd, output); output = STRPRINTF("No Memo: %s", - (map[m_id].flag.nomemo) ? "True" : "False"); + (m_id->flag.nomemo) ? "True" : "False"); clif_displaymessage(fd, output); output = STRPRINTF("No Penalty: %s", - (map[m_id].flag.nopenalty) ? "True" : "False"); + (m_id->flag.nopenalty) ? "True" : "False"); clif_displaymessage(fd, output); output = STRPRINTF("No Return: %s", - (map[m_id].flag.noreturn) ? "True" : "False"); + (m_id->flag.noreturn) ? "True" : "False"); clif_displaymessage(fd, output); output = STRPRINTF("No Save: %s", - (map[m_id].flag.nosave) ? "True" : "False"); + (m_id->flag.nosave) ? "True" : "False"); clif_displaymessage(fd, output); output = STRPRINTF("No Teleport: %s", - (map[m_id].flag.noteleport) ? "True" : "False"); + (m_id->flag.noteleport) ? "True" : "False"); clif_displaymessage(fd, output); output = STRPRINTF("No Monster Teleport: %s", - (map[m_id].flag.monster_noteleport) ? "True" : "False"); + (m_id->flag.monster_noteleport) ? "True" : "False"); clif_displaymessage(fd, output); output = STRPRINTF("No Zeny Penalty: %s", - (map[m_id].flag.nozenypenalty) ? "True" : "False"); + (m_id->flag.nozenypenalty) ? "True" : "False"); clif_displaymessage(fd, output); switch (list) @@ -4533,9 +4530,9 @@ int atcommand_mapinfo(const int fd, dumb_ptr<map_session_data> sd, break; case 2: clif_displaymessage(fd, "----- NPCs in Map -----"); - for (int i = 0; i < map[m_id].npc_num;) + for (int i = 0; i < m_id->npc_num;) { - nd = map[m_id].npc[i]; + nd = m_id->npc[i]; switch (nd->dir) { case DIR::S: @@ -4845,249 +4842,6 @@ int atcommand_localbroadcast(const int fd, dumb_ptr<map_session_data> sd, } /*========================================== - * @ignorelist by [Yor] - *------------------------------------------ - */ -int atcommand_ignorelist(const int fd, dumb_ptr<map_session_data> sd, - const char *, const char *) -{ - int count; - int i; - - count = 0; - for (i = 0; i < (int)(sizeof(sd->ignore) / sizeof(sd->ignore[0])); i++) - if (sd->ignore[i].name[0]) - count++; - - if (sd->ignoreAll == 0) - if (count == 0) - clif_displaymessage(fd, "You accept any wisp (no wisper is refused)."); - else - { - std::string output = STRPRINTF( - "You accept any wisp, except thoses from %d player (s):", - count); - clif_displaymessage(fd, output); - } - else if (count == 0) - clif_displaymessage(fd, "You refuse all wisps (no specifical wisper is refused)."); - else - { - std::string output = STRPRINTF( - "You refuse all wisps, AND refuse wisps from %d player (s):", - count); - clif_displaymessage(fd, output); - } - - if (count > 0) - for (i = 0; i < (int)(sizeof(sd->ignore) / sizeof(sd->ignore[0])); - i++) - if (sd->ignore[i].name[0]) - clif_displaymessage(fd, sd->ignore[i].name); - - return 0; -} - -/*========================================== - * @charignorelist <player_name> by [Yor] - *------------------------------------------ - */ -int atcommand_charignorelist(const int fd, dumb_ptr<map_session_data>, - const char *, const char *message) -{ - char character[100]; - dumb_ptr<map_session_data> pl_sd; - int count; - int i; - - memset(character, '\0', sizeof(character)); - - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) - { - clif_displaymessage(fd, - "Please, enter a player name (usage: @charignorelist <char name>)."); - return -1; - } - - if ((pl_sd = map_nick2sd(character)) != NULL) - { - count = 0; - for (i = 0; - i < (int)(sizeof(pl_sd->ignore) / sizeof(pl_sd->ignore[0])); - i++) - if (pl_sd->ignore[i].name[0]) - count++; - - if (pl_sd->ignoreAll == 0) - if (count == 0) - { - std::string output = STRPRINTF( - "'%s' accept any wisp (no wisper is refused).", - pl_sd->status.name); - clif_displaymessage(fd, output); - } - else - { - std::string output = STRPRINTF( - "'%s' accept any wisp, except thoses from %d player(s):", - pl_sd->status.name, count); - clif_displaymessage(fd, output); - } - else if (count == 0) - { - std::string output = STRPRINTF( - "'%s' refuse all wisps (no specifical wisper is refused).", - pl_sd->status.name); - clif_displaymessage(fd, output); - } - else - { - std::string output = STRPRINTF( - "'%s' refuse all wisps, AND refuse wisps from %d player(s):", - pl_sd->status.name, count); - clif_displaymessage(fd, output); - } - - if (count > 0) - for (i = 0; - i < (int)(sizeof(pl_sd->ignore) / sizeof(pl_sd->ignore[0])); - i++) - if (pl_sd->ignore[i].name[0]) - clif_displaymessage(fd, pl_sd->ignore[i].name); - - } - else - { - clif_displaymessage(fd, "Character not found."); - return -1; - } - - return 0; -} - -/*========================================== - * @inall <player_name> by [Yor] - *------------------------------------------ - */ -int atcommand_inall(const int fd, dumb_ptr<map_session_data> sd, - const char *, const char *message) -{ - char character[100]; - dumb_ptr<map_session_data> pl_sd; - - memset(character, '\0', sizeof(character)); - - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) - { - clif_displaymessage(fd, - "Please, enter a player name (usage: @inall <char name>)."); - return -1; - } - - if ((pl_sd = map_nick2sd(character)) != NULL) - { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) - { // you can change wisp option only to lower or same level - if (pl_sd->ignoreAll == 0) - { - std::string output = STRPRINTF( - "'%s' already accepts all wispers.", - pl_sd->status.name); - clif_displaymessage(fd, output); - return -1; - } - else - { - pl_sd->ignoreAll = 0; - std::string output = STRPRINTF( - "'%s' now accepts all wispers.", - pl_sd->status.name); - clif_displaymessage(fd, output); - // message to player - clif_displaymessage(pl_sd->fd, "A GM has authorised all wispers for you."); - WFIFOW(pl_sd->fd, 0) = 0x0d2; // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail - WFIFOB(pl_sd->fd, 2) = 1; - WFIFOB(pl_sd->fd, 3) = 0; // success - WFIFOSET(pl_sd->fd, 4); // packet_len_table[0x0d2] - } - } - else - { - clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player."); - return -1; - } - } - else - { - clif_displaymessage(fd, "Character not found."); - return -1; - } - - return 0; -} - -/*========================================== - * @exall <player_name> by [Yor] - *------------------------------------------ - */ -int atcommand_exall(const int fd, dumb_ptr<map_session_data> sd, - const char *, const char *message) -{ - char character[100]; - dumb_ptr<map_session_data> pl_sd; - - memset(character, '\0', sizeof(character)); - - if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) - { - clif_displaymessage(fd, - "Please, enter a player name (usage: @exall <char name>)."); - return -1; - } - - if ((pl_sd = map_nick2sd(character)) != NULL) - { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) - { // you can change wisp option only to lower or same level - if (pl_sd->ignoreAll == 1) - { - std::string output = STRPRINTF( - "'%s' already blocks all wispers.", - pl_sd->status.name); - clif_displaymessage(fd, output); - return -1; - } - else - { - pl_sd->ignoreAll = 1; - std::string output = STRPRINTF( - "'%s' blocks now all wispers.", - pl_sd->status.name); - clif_displaymessage(fd, output); - // message to player - clif_displaymessage(pl_sd->fd, "A GM has blocked all wispers for you."); - WFIFOW(pl_sd->fd, 0) = 0x0d2; // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail - WFIFOB(pl_sd->fd, 2) = 0; - WFIFOB(pl_sd->fd, 3) = 0; // success - WFIFOSET(pl_sd->fd, 4); // packet_len_table[0x0d2] - } - } - else - { - clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player."); - return -1; - } - } - else - { - clif_displaymessage(fd, "Character not found."); - return -1; - } - - return 0; -} - -/*========================================== * @email <actual@email> <new@email> by [Yor] *------------------------------------------ */ @@ -5901,10 +5655,10 @@ int atcommand_rain(const int, dumb_ptr<map_session_data> sd, int effno = 0; effno = 161; nullpo_retr(-1, sd); - if (effno < 0 || map[sd->bl_m].flag.rain) + if (effno < 0 || sd->bl_m->flag.rain) return -1; - map[sd->bl_m].flag.rain = 1; + sd->bl_m->flag.rain = 1; clif_specialeffect(sd, effno, 2); return 0; } @@ -5919,10 +5673,10 @@ int atcommand_snow(const int, dumb_ptr<map_session_data> sd, int effno = 0; effno = 162; nullpo_retr(-1, sd); - if (effno < 0 || map[sd->bl_m].flag.snow) + if (effno < 0 || sd->bl_m->flag.snow) return -1; - map[sd->bl_m].flag.snow = 1; + sd->bl_m->flag.snow = 1; clif_specialeffect(sd, effno, 2); return 0; } @@ -5937,10 +5691,10 @@ int atcommand_sakura(const int, dumb_ptr<map_session_data> sd, int effno = 0; effno = 163; nullpo_retr(-1, sd); - if (effno < 0 || map[sd->bl_m].flag.sakura) + if (effno < 0 || sd->bl_m->flag.sakura) return -1; - map[sd->bl_m].flag.sakura = 1; + sd->bl_m->flag.sakura = 1; clif_specialeffect(sd, effno, 2); return 0; } @@ -5955,10 +5709,10 @@ int atcommand_fog(const int, dumb_ptr<map_session_data> sd, int effno = 0; effno = 233; nullpo_retr(-1, sd); - if (effno < 0 || map[sd->bl_m].flag.fog) + if (effno < 0 || sd->bl_m->flag.fog) return -1; - map[sd->bl_m].flag.fog = 1; + sd->bl_m->flag.fog = 1; clif_specialeffect(sd, effno, 2); return 0; @@ -5974,10 +5728,10 @@ int atcommand_leaves(const int, dumb_ptr<map_session_data> sd, int effno = 0; effno = 333; nullpo_retr(-1, sd); - if (effno < 0 || map[sd->bl_m].flag.leaves) + if (effno < 0 || sd->bl_m->flag.leaves) return -1; - map[sd->bl_m].flag.leaves = 1; + sd->bl_m->flag.leaves = 1; clif_specialeffect(sd, effno, 2); return 0; } @@ -6077,7 +5831,8 @@ int atcommand_adjgmlvl(const int fd, dumb_ptr<map_session_data>, dumb_ptr<map_session_data> pl_sd; if (!message || !*message - || sscanf(message, "%d %s", &newlev, user) != 2) + || sscanf(message, "%d %s", &newlev, user) != 2 + || newlev < 0 || newlev > 99) { clif_displaymessage(fd, "usage: @adjgmlvl <lvl> <user>."); return -1; @@ -6301,21 +6056,21 @@ int atcommand_jump_iterate(const int fd, dumb_ptr<map_session_data> sd, pl_sd = get_start(); } - if (pl_sd->bl_m >= 0 && map[pl_sd->bl_m].flag.nowarpto + if (pl_sd->bl_m != nullptr && pl_sd->bl_m->flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, "You are not authorised to warp you to the map of this player."); return -1; } - if (sd->bl_m >= 0 && map[sd->bl_m].flag.nowarp + if (sd->bl_m != nullptr && sd->bl_m->flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { clif_displaymessage(fd, "You are not authorised to warp you from your actual map."); return -1; } - pc_setpos(sd, map[pl_sd->bl_m].name, pl_sd->bl_x, pl_sd->bl_y, BeingRemoveWhy::WARPED); + pc_setpos(sd, pl_sd->bl_m->name, pl_sd->bl_x, pl_sd->bl_y, BeingRemoveWhy::WARPED); std::string output = STRPRINTF("Jump to %s", pl_sd->status.name); clif_displaymessage(fd, output); @@ -6395,7 +6150,7 @@ int atcommand_skillpool_info(const int fd, dumb_ptr<map_session_data>, for (i = 0; i < skill_pool_skills_size; ++i) { - const char *name = skill_name(skill_pool_skills[i]); + const std::string& name = skill_name(skill_pool_skills[i]); int lvl = pl_sd->status.skill[skill_pool_skills[i]].lv; if (lvl) @@ -6522,7 +6277,7 @@ int atcommand_ipcheck(const int fd, dumb_ptr<map_session_data>, return -1; } - if (getpeername(pl_sd->fd, (struct sockaddr *)&sai, &sa_len)) + if (getpeername(pl_sd->fd, reinterpret_cast<struct sockaddr *>(&sai), &sa_len)) { clif_displaymessage(fd, "Guru Meditation Error: getpeername() failed"); @@ -6541,7 +6296,7 @@ int atcommand_ipcheck(const int fd, dumb_ptr<map_session_data>, pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get())); if (pl_sd && pl_sd->state.auth) { - if (getpeername(pl_sd->fd, (struct sockaddr *)&sai, &sa_len)) + if (getpeername(pl_sd->fd, reinterpret_cast<struct sockaddr *>(&sai), &sa_len)) continue; // Is checking GM levels really needed here? diff --git a/src/map/atcommand.hpp b/src/map/atcommand.hpp index 7033972..d81f04d 100644 --- a/src/map/atcommand.hpp +++ b/src/map/atcommand.hpp @@ -13,6 +13,6 @@ int atcommand_config_read(const char *cfgName); void log_atcommand(dumb_ptr<map_session_data> sd, const_string cmd); // only used by map.cpp -extern char *gm_logfile_name; +extern std::string gm_logfile_name; #endif // ATCOMMAND_HPP diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 8e7b174..81e606f 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -12,6 +12,7 @@ #include "itemdb.hpp" #include "map.hpp" #include "mob.hpp" +#include "path.hpp" #include "pc.hpp" #include "skill.hpp" @@ -2039,8 +2040,8 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, && bool(sd->status.inventory[weapon_index].equip & EPOS::WEAPON)) weapon = sd->inventory_data[weapon_index]->nameid; - MAP_LOG("PC%d %d:%d,%d WPNDMG %s%d %d FOR %d WPN %d", - sd->status.char_id, src->bl_m, src->bl_x, src->bl_y, + MAP_LOG("PC%d %s:%d,%d WPNDMG %s%d %d FOR %d WPN %d", + sd->status.char_id, src->bl_m->name, src->bl_x, src->bl_y, (target->bl_type == BL::PC) ? "PC" : "MOB", (target->bl_type == BL::PC) ? target->as_player()-> status.char_id @@ -2052,8 +2053,8 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target, if (target->bl_type == BL::PC) { dumb_ptr<map_session_data> sd2 = target->as_player(); - MAP_LOG("PC%d %d:%d,%d WPNINJURY %s%d %d FOR %d", - sd2->status.char_id, target->bl_m, target->bl_x, target->bl_y, + MAP_LOG("PC%d %s:%d,%d WPNINJURY %s%d %d FOR %d", + sd2->status.char_id, target->bl_m->name, target->bl_x, target->bl_y, (src->bl_type == BL::PC) ? "PC" : "MOB", (src->bl_type == BL::PC) ? src->as_player()->status.char_id @@ -2226,12 +2227,12 @@ int battle_check_target(dumb_ptr<block_list> src, dumb_ptr<block_list> target, if (ss->bl_type == BL::PC && target->bl_type == BL::PC) { // 両方PVPモードなら否定(敵) - if (map[ss->bl_m].flag.pvp + if (ss->bl_m->flag.pvp || pc_iskiller(ss->as_player(), target->as_player())) { // [MouseJstr] if (battle_config.pk_mode) return 1; // prevent novice engagement in pk_mode [Valaris] - else if (map[ss->bl_m].flag.pvp_noparty && s_p > 0 && t_p > 0 + else if (ss->bl_m->flag.pvp_noparty && s_p > 0 && t_p > 0 && s_p == t_p) return 1; return 0; @@ -2313,7 +2314,7 @@ int battle_config_read(const char *cfgName) battle_config.defnotenemy = 1; battle_config.random_monster_checklv = 1; battle_config.attr_recover = 1; - battle_config.flooritem_lifetime = (int)std::chrono::duration_cast<std::chrono::milliseconds>(LIFETIME_FLOORITEM).count(); + battle_config.flooritem_lifetime = std::chrono::duration_cast<std::chrono::milliseconds>(LIFETIME_FLOORITEM).count(); battle_config.item_auto_get = 0; battle_config.drop_pickup_safety_zone = 20; battle_config.item_first_get_time = 3000; @@ -2341,7 +2342,6 @@ int battle_config_read(const char *cfgName) battle_config.wp_rate = 100; battle_config.pp_rate = 100; battle_config.monster_active_enable = 1; - battle_config.monster_loot_type = 0; battle_config.mob_skill_use = 1; battle_config.mob_count_rate = 100; battle_config.quest_skill_learn = 0; @@ -2524,7 +2524,6 @@ int battle_config_read(const char *cfgName) {"weapon_produce_rate", &battle_config.wp_rate}, {"potion_produce_rate", &battle_config.pp_rate}, {"monster_active_enable", &battle_config.monster_active_enable}, - {"monster_loot_type", &battle_config.monster_loot_type}, {"mob_skill_use", &battle_config.mob_skill_use}, {"mob_count_rate", &battle_config.mob_count_rate}, {"quest_skill_learn", &battle_config.quest_skill_learn}, @@ -2666,7 +2665,7 @@ int battle_config_read(const char *cfgName) if (--count == 0) { if (static_cast<interval_t>(battle_config.flooritem_lifetime) < std::chrono::seconds(1)) - battle_config.flooritem_lifetime = (int)std::chrono::duration_cast<std::chrono::milliseconds>(LIFETIME_FLOORITEM).count(); + battle_config.flooritem_lifetime = std::chrono::duration_cast<std::chrono::milliseconds>(LIFETIME_FLOORITEM).count(); if (battle_config.restart_hp_rate < 0) battle_config.restart_hp_rate = 0; else if (battle_config.restart_hp_rate > 100) diff --git a/src/map/battle.hpp b/src/map/battle.hpp index 8b7c1bd..168cf60 100644 --- a/src/map/battle.hpp +++ b/src/map/battle.hpp @@ -132,7 +132,6 @@ extern struct Battle_Config int wp_rate; int pp_rate; int monster_active_enable; - int monster_loot_type; int mob_skill_use; int mob_count_rate; int quest_skill_learn; diff --git a/src/map/battle.t.hpp b/src/map/battle.t.hpp index e374298..f730cc5 100644 --- a/src/map/battle.t.hpp +++ b/src/map/battle.t.hpp @@ -25,6 +25,10 @@ ENUM_BITWISE_OPERATORS(BF) } using e::BF; +namespace e +{ +// not actually an enum, but put in the namespace to hide the operators +// from non-ADL. struct BCT { // former representation: @@ -56,6 +60,8 @@ constexpr bool operator == (BCT l, BCT r) { return l.lo == r.lo && l.mid == r.mid && l.classic == r.classic && l.level == r.level && l.unused == r.unused; } constexpr bool operator != (BCT l, BCT r) { return !(l == r); } +} // namespace e +using e::BCT; constexpr BCT BCT_NOENEMY = {0x00, 0x00, 0x0, 0x0, 0x00}; diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp index aaa727e..ebed281 100644 --- a/src/map/chrif.cpp +++ b/src/map/chrif.cpp @@ -145,14 +145,17 @@ int chrif_connect(int fd) static int chrif_sendmap(int fd) { - int i; + int i = 0; WFIFOW(fd, 0) = 0x2afa; - for (i = 0; i < map_num; i++) - if (map[i].alias[0] != '\0') // [MouseJstr] map aliasing - memcpy(WFIFOP(fd, 4 + i * 16), map[i].alias, 16); - else - memcpy(WFIFOP(fd, 4 + i * 16), map[i].name, 16); + for (auto& pair : maps_db) + { + map_abstract *ma = pair.second.get(); + if (!ma->gat) + continue; + memcpy(WFIFOP(fd, 4 + i * 16), ma->name, 16); + i++; + } WFIFOW(fd, 2) = 4 + i * 16; WFIFOSET(fd, WFIFOW(fd, 2)); @@ -176,7 +179,7 @@ int chrif_recvmap(int fd) port = RFIFOW(fd, 8); for (i = 10, j = 0; i < RFIFOW(fd, 2); i += 16, j++) { - map_setipport((const char *)RFIFOP(fd, i), ip, port); + map_setipport(static_cast<const char *>(RFIFOP(fd, i)), ip, port); // if (battle_config.etc_log) // PRINTF("recv map %d %s\n", j, RFIFOP(fd,i)); } @@ -241,7 +244,7 @@ int chrif_changemapserverack(int fd) pc_authfail(sd->fd); return 0; } - clif_changemapserver(sd, (const char *)RFIFOP(fd, 18), RFIFOW(fd, 34), + clif_changemapserver(sd, static_cast<const char *>(RFIFOP(fd, 18)), RFIFOW(fd, 34), RFIFOW(fd, 36), in_addr{RFIFOL(fd, 38)}, RFIFOW(fd, 42)); return 0; @@ -989,9 +992,8 @@ void ladmin_itemfrob_c2(dumb_ptr<block_list> bl, int source_id, int dest_id) case BL::MOB: { dumb_ptr<mob_data> mob = bl->as_mob(); - int i; - for (i = 0; i < mob->lootitem_count; i++) - FIX(mob->lootitem[i]); + for (struct item& itm : mob->lootitemv) + FIX(itm); break; } @@ -1017,10 +1019,11 @@ void ladmin_itemfrob(int fd) { int source_id = RFIFOL(fd, 2); int dest_id = RFIFOL(fd, 6); - dumb_ptr<block_list> bl = (dumb_ptr<block_list>) map_get_first_session(); + dumb_ptr<block_list> bl = map_get_first_session(); // flooritems - map_foreachobject(std::bind(ladmin_itemfrob_c, ph::_1, source_id, dest_id), BL::NUL /* any object */); + map_foreachobject(std::bind(ladmin_itemfrob_c, ph::_1, source_id, dest_id), + BL::NUL /* any object */); // player characters (and, hopefully, mobs) while (bl->bl_next) @@ -1097,7 +1100,7 @@ void chrif_parse(int fd) case 0x2afd: pc_authok(RFIFOL(fd, 4), RFIFOL(fd, 8), static_cast<time_t>(RFIFOL(fd, 12)), RFIFOW(fd, 16), - (const struct mmo_charstatus *) RFIFOP(fd, 18)); + static_cast<const struct mmo_charstatus *>(RFIFOP(fd, 18))); break; case 0x2afe: pc_authfail(RFIFOL(fd, 2)); @@ -1115,7 +1118,7 @@ void chrif_parse(int fd) chrif_changemapserverack(fd); break; case 0x2b09: - map_addchariddb(RFIFOL(fd, 2), (const char *)RFIFOP(fd, 6)); + map_addchariddb(RFIFOL(fd, 2), static_cast<const char *>(RFIFOP(fd, 6))); break; case 0x2b0b: chrif_changedgm(fd); diff --git a/src/map/clif.cpp b/src/map/clif.cpp index fbba044..f20c887 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -203,9 +203,16 @@ static void clif_emotion_towards(dumb_ptr<block_list> bl, dumb_ptr<block_list> target, int type); + +enum class ChatType +{ + Party, + Whisper, + Global, +}; + static -char *clif_validate_chat(dumb_ptr<map_session_data> sd, int type, - const char **message, size_t *message_len); +std::string clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type); /*========================================== * clif_sendでSendWho::AREA*指定時用 @@ -337,13 +344,17 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type case SendWho::AREA: case SendWho::AREA_WOS: map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, len, bl, type), - bl->bl_m, bl->bl_x - AREA_SIZE, bl->bl_y - AREA_SIZE, - bl->bl_x + AREA_SIZE, bl->bl_y + AREA_SIZE, BL::PC); + bl->bl_m, + bl->bl_x - AREA_SIZE, bl->bl_y - AREA_SIZE, + bl->bl_x + AREA_SIZE, bl->bl_y + AREA_SIZE, + BL::PC); break; case SendWho::AREA_CHAT_WOC: map_foreachinarea(std::bind(clif_send_sub, ph::_1, buf, len, bl, SendWho::AREA_CHAT_WOC), - bl->bl_m, bl->bl_x - (AREA_SIZE), bl->bl_y - (AREA_SIZE), - bl->bl_x + (AREA_SIZE), bl->bl_y + (AREA_SIZE), BL::PC); + bl->bl_m, + bl->bl_x - (AREA_SIZE), bl->bl_y - (AREA_SIZE), + bl->bl_x + (AREA_SIZE), bl->bl_y + (AREA_SIZE), + BL::PC); break; case SendWho::PARTY_AREA: // 同じ画面内の全パーティーメンバに送信 @@ -912,15 +923,15 @@ int clif_spawnpc(dumb_ptr<map_session_data> sd) WBUFW(buf, 51) = 0; clif_send(buf, clif_parse_func_table[0x1d9].len, sd, SendWho::AREA_WOS); - if (map[sd->bl_m].flag.snow) + if (sd->bl_m->flag.snow) clif_specialeffect(sd, 162, 1); - if (map[sd->bl_m].flag.fog) + if (sd->bl_m->flag.fog) clif_specialeffect(sd, 233, 1); - if (map[sd->bl_m].flag.sakura) + if (sd->bl_m->flag.sakura) clif_specialeffect(sd, 163, 1); - if (map[sd->bl_m].flag.leaves) + if (sd->bl_m->flag.leaves) clif_specialeffect(sd, 333, 1); - if (map[sd->bl_m].flag.rain) + if (sd->bl_m->flag.rain) clif_specialeffect(sd, 161, 1); // clif_changelook_accessories(sd, NULL); @@ -1281,7 +1292,7 @@ int clif_scriptmes(dumb_ptr<map_session_data> sd, int npcid, const char *mes) WFIFOW(fd, 0) = 0xb4; WFIFOW(fd, 2) = strlen(mes) + 9; WFIFOL(fd, 4) = npcid; - strcpy((char *)WFIFOP(fd, 8), mes); + strcpy(static_cast<char *>(WFIFOP(fd, 8)), mes); WFIFOSET(fd, WFIFOW(fd, 2)); return 0; @@ -1337,7 +1348,7 @@ int clif_scriptmenu(dumb_ptr<map_session_data> sd, int npcid, const char *mes) WFIFOW(fd, 0) = 0xb7; WFIFOW(fd, 2) = strlen(mes) + 8; WFIFOL(fd, 4) = npcid; - strcpy((char *)WFIFOP(fd, 8), mes); + strcpy(static_cast<char *>(WFIFOP(fd, 8)), mes); WFIFOSET(fd, WFIFOW(fd, 2)); return 0; @@ -1469,7 +1480,7 @@ int clif_additem(dumb_ptr<map_session_data> sd, int n, int amount, PickupFail fa WFIFOB(fd, 10) = sd->status.inventory[n].refine; if (sd->status.inventory[n].card[0] == 0x00ff || sd->status.inventory[n].card[0] == 0x00fe - || sd->status.inventory[n].card[0] == (short) 0xff00) + || sd->status.inventory[n].card[0] == static_cast<short>(0xff00)) { WFIFOW(fd, 11) = sd->status.inventory[n].card[0]; WFIFOW(fd, 13) = sd->status.inventory[n].card[1]; @@ -1617,7 +1628,7 @@ int clif_equiplist(dumb_ptr<map_session_data> sd) WFIFOB(fd, n * 20 + 15) = sd->status.inventory[i].refine; if (sd->status.inventory[i].card[0] == 0x00ff || sd->status.inventory[i].card[0] == 0x00fe - || sd->status.inventory[i].card[0] == (short) 0xff00) + || sd->status.inventory[i].card[0] == static_cast<short>(0xff00)) { WFIFOW(fd, n * 20 + 16) = sd->status.inventory[i].card[0]; WFIFOW(fd, n * 20 + 18) = sd->status.inventory[i].card[1]; @@ -1742,7 +1753,7 @@ int clif_storageequiplist(dumb_ptr<map_session_data> sd, struct storage *stor) WFIFOB(fd, n * 20 + 15) = stor->storage_[i].refine; if (stor->storage_[i].card[0] == 0x00ff || stor->storage_[i].card[0] == 0x00fe - || stor->storage_[i].card[0] == (short) 0xff00) + || stor->storage_[i].card[0] == static_cast<short>(0xff00)) { WFIFOW(fd, n * 20 + 16) = stor->storage_[i].card[0]; WFIFOW(fd, n * 20 + 18) = stor->storage_[i].card[1]; @@ -2312,7 +2323,7 @@ int clif_traderequest(dumb_ptr<map_session_data> sd, const char *name) fd = sd->fd; WFIFOW(fd, 0) = 0xe5; - strcpy((char *)WFIFOP(fd, 2), name); + strcpy(static_cast<char *>(WFIFOP(fd, 2)), name); WFIFOSET(fd, clif_parse_func_table[0xe5].len); return 0; @@ -2378,7 +2389,7 @@ int clif_tradeadditem(dumb_ptr<map_session_data> sd, WFIFOB(fd, 10) = sd->status.inventory[index].refine; //refine if (sd->status.inventory[index].card[0] == 0x00ff || sd->status.inventory[index].card[0] == 0x00fe - || sd->status.inventory[index].card[0] == (short) 0xff00) + || sd->status.inventory[index].card[0] == static_cast<short>(0xff00)) { WFIFOW(fd, 11) = sd->status.inventory[index].card[0]; //card (4w) WFIFOW(fd, 13) = sd->status.inventory[index].card[1]; //card (4w) @@ -2541,7 +2552,7 @@ int clif_storageitemadded(dumb_ptr<map_session_data> sd, struct storage *stor, WFIFOB(fd, 12) = stor->storage_[index].refine; //refine if (stor->storage_[index].card[0] == 0x00ff || stor->storage_[index].card[0] == 0x00fe - || stor->storage_[index].card[0] == (short) 0xff00) + || stor->storage_[index].card[0] == static_cast<short>(0xff00)) { WFIFOW(fd, 13) = stor->storage_[index].card[0]; //card (4w) WFIFOW(fd, 15) = stor->storage_[index].card[1]; //card (4w) @@ -3790,7 +3801,7 @@ void clif_parse_LoadEndAck(int, dumb_ptr<map_session_data> sd) if (!battle_config.pk_mode) sd->pvp_timer.cancel(); - if (map[sd->bl_m].flag.pvp) + if (sd->bl_m->flag.pvp) { if (!battle_config.pk_mode) { @@ -3832,9 +3843,11 @@ void clif_parse_LoadEndAck(int, dumb_ptr<map_session_data> sd) // clif_changelook_accessories(sd, NULL); - map_foreachinarea(std::bind(clif_getareachar, ph::_1, sd), sd->bl_m, sd->bl_x - AREA_SIZE, - sd->bl_y - AREA_SIZE, sd->bl_x + AREA_SIZE, - sd->bl_y + AREA_SIZE, BL::NUL); + map_foreachinarea(std::bind(clif_getareachar, ph::_1, sd), + sd->bl_m, + sd->bl_x - AREA_SIZE, sd->bl_y - AREA_SIZE, + sd->bl_x + AREA_SIZE, sd->bl_y + AREA_SIZE, + BL::NUL); } /*========================================== @@ -3998,7 +4011,7 @@ void clif_parse_GetCharNameRequest(int fd, dumb_ptr<map_session_data> sd) case BL::NPC: memcpy(WFIFOP(fd, 6), bl->as_npc()->name, 24); { - char *start = (char *)WFIFOP(fd, 6); + char *start = static_cast<char *>(WFIFOP(fd, 6)); char *end = strchr(start, '#'); // [fate] elim hashed out/invisible names for the client if (end) while (*end) @@ -4038,52 +4051,41 @@ void clif_parse_GetCharNameRequest(int fd, dumb_ptr<map_session_data> sd) static void clif_parse_GlobalMessage(int fd, dumb_ptr<map_session_data> sd) { - int msg_len = RFIFOW(fd, 2) - 4; /* Header(2) + length(2). */ - size_t message_len = 0; - // sometimes uint8_t - char *buf = NULL; - const char *message = NULL; /* The message text only. */ - nullpo_retv(sd); - if (!(buf = clif_validate_chat(sd, 2, &message, &message_len))) + std::string mbuf = clif_validate_chat(sd, ChatType::Global); + if (mbuf.empty()) { clif_displaymessage(fd, "Your message could not be sent."); return; } - if (is_atcommand(fd, sd, message, 0)) //チャット禁止 - { - free(buf); + if (is_atcommand(fd, sd, mbuf.c_str(), 0)) return; - } - if (!magic_message(sd, buf, msg_len)) + if (!magic_message(sd, mbuf)) { /* Don't send chat that results in an automatic ban. */ - if (tmw_CheckChatSpam(sd, message)) + if (tmw_CheckChatSpam(sd, mbuf.c_str())) { - free(buf); clif_displaymessage(fd, "Your message could not be sent."); return; } /* It's not a spell/magic message, so send the message to others. */ - WBUFW(reinterpret_cast<uint8_t *>(buf), 0) = 0x8d; - WBUFW(reinterpret_cast<uint8_t *>(buf), 2) = msg_len + 8; /* Header(2) + length(2) + ID(4). */ - WBUFL(reinterpret_cast<uint8_t *>(buf), 4) = sd->bl_id; + uint8_t sendbuf[mbuf.size() + 8]; + WBUFW(sendbuf, 0) = 0x8d; + WBUFW(sendbuf, 2) = mbuf.size() + 8; /* Header(2) + length(2) + ID(4). */ + WBUFL(sendbuf, 4) = sd->bl_id; + memcpy(WBUFP(sendbuf, 8), mbuf.data(), mbuf.size()); - // evil multiuse buffer! - clif_send((const uint8_t *)buf, msg_len + 8, sd, SendWho::AREA_CHAT_WOC); + clif_send(sendbuf, mbuf.size() + 8, sd, SendWho::AREA_CHAT_WOC); } /* Send the message back to the speaker. */ memcpy(WFIFOP(fd, 0), RFIFOP(fd, 0), RFIFOW(fd, 2)); WFIFOW(fd, 0) = 0x8e; WFIFOSET(fd, WFIFOW(fd, 2)); - - free(buf); - return; } int clif_message(dumb_ptr<block_list> bl, const char *msg) @@ -4290,29 +4292,25 @@ void clif_parse_Restart(int fd, dumb_ptr<map_session_data> sd) static void clif_parse_Wis(int fd, dumb_ptr<map_session_data> sd) { - size_t message_len = 0; - char *buf = NULL; - const char *message = NULL; /* The message text only. */ dumb_ptr<map_session_data> dstsd = NULL; nullpo_retv(sd); - if (!(buf = clif_validate_chat(sd, 1, &message, &message_len))) + std::string mbuf = clif_validate_chat(sd, ChatType::Whisper); + if (mbuf.empty()) { clif_displaymessage(fd, "Your message could not be sent."); return; } - if (is_atcommand(fd, sd, message, 0)) + if (is_atcommand(fd, sd, mbuf.c_str(), 0)) { - free(buf); return; } /* Don't send chat that results in an automatic ban. */ - if (tmw_CheckChatSpam(sd, message)) + if (tmw_CheckChatSpam(sd, mbuf.c_str())) { - free(buf); clif_displaymessage(fd, "Your message could not be sent."); return; } @@ -4323,9 +4321,10 @@ void clif_parse_Wis(int fd, dumb_ptr<map_session_data> sd) * conflict (for instance, "Test" versus "test"), the char-server must * settle the discrepancy. */ - if (!(dstsd = map_nick2sd((const char *)RFIFOP(fd, 4))) - || strcmp(dstsd->status.name, (const char *)RFIFOP(fd, 4)) != 0) - intif_wis_message(sd, (const char *)RFIFOP(fd, 4), message, RFIFOW(fd, 2) - 28); + const char *tname = static_cast<const char *>(RFIFOP(fd, 4)); + if (!(dstsd = map_nick2sd(tname)) + || strcmp(dstsd->status.name, tname) != 0) + intif_wis_message(sd, tname, mbuf.c_str(), RFIFOW(fd, 2) - 28); else { /* Refuse messages addressed to self. */ @@ -4336,28 +4335,10 @@ void clif_parse_Wis(int fd, dumb_ptr<map_session_data> sd) } else { - /* The target is ignoring all whispers. */ - if (dstsd->ignoreAll == 1) - /* Ignored by target. */ - clif_wis_end(fd, 2); - else { - int i; - size_t end = sizeof(dstsd->ignore) / sizeof(dstsd->ignore[0]); - - /* See if the source player is being ignored. */ - for (i = 0; i < end; ++i) - if (strcmp(dstsd->ignore[i].name, sd->status.name) == 0) - { - /* Ignored by target. */ - clif_wis_end(fd, 2); - break; - } - /* The player is not being ignored. */ - if (i == end) { - clif_wis_message(dstsd->fd, sd->status.name, message, + clif_wis_message(dstsd->fd, sd->status.name, mbuf.c_str(), RFIFOW(fd, 2) - 28); /* The whisper was sent successfully. */ clif_wis_end(fd, 0); @@ -4365,8 +4346,6 @@ void clif_parse_Wis(int fd, dumb_ptr<map_session_data> sd) } } } - - free(buf); } /*========================================== @@ -4423,7 +4402,7 @@ void clif_parse_DropItem(int fd, dumb_ptr<map_session_data> sd) clif_clearchar(sd, BeingRemoveWhy::DEAD); return; } - if (map[sd->bl_m].flag.no_player_drops) + if (sd->bl_m->flag.no_player_drops) { clif_displaymessage(sd->fd, "Can't drop items here."); return; @@ -4765,7 +4744,7 @@ void clif_parse_NpcStringInput(int fd, dumb_ptr<map_session_data> sd) } if (len > 0) - strncpy(sd->npc_str, (const char *)RFIFOP(fd, 8), len); + strncpy(sd->npc_str, static_cast<const char *>(RFIFOP(fd, 8)), len); sd->npc_str[len] = '\0'; map_scriptcont(sd, RFIFOL(fd, 4)); @@ -4851,7 +4830,7 @@ void clif_parse_CreateParty(int fd, dumb_ptr<map_session_data> sd) if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, SkillID::NV_PARTY) >= 2) { - party_create(sd, (const char *)RFIFOP(fd, 2)); + party_create(sd, static_cast<const char *>(RFIFOP(fd, 2))); } else clif_skill_fail(sd, SkillID::ONE, 0, 4); @@ -4909,7 +4888,7 @@ void clif_parse_LeaveParty(int, dumb_ptr<map_session_data> sd) static void clif_parse_RemovePartyMember(int fd, dumb_ptr<map_session_data> sd) { - party_removemember(sd, RFIFOL(fd, 2), (const char *)RFIFOP(fd, 6)); + party_removemember(sd, RFIFOL(fd, 2), static_cast<const char *>(RFIFOP(fd, 6))); } /*========================================== @@ -4933,81 +4912,26 @@ void clif_parse_PartyChangeOption(int fd, dumb_ptr<map_session_data> sd) static void clif_parse_PartyMessage(int fd, dumb_ptr<map_session_data> sd) { - size_t message_len = 0; - char *buf = NULL; - const char *message = NULL; /* The message text only. */ - nullpo_retv(sd); - if (!(buf = clif_validate_chat(sd, 0, &message, &message_len))) + std::string mbuf = clif_validate_chat(sd, ChatType::Party); + if (mbuf.empty()) { clif_displaymessage(fd, "Your message could not be sent."); return; } - if (is_atcommand(fd, sd, message, 0)) //チャット禁止 - { - free(buf); + if (is_atcommand(fd, sd, mbuf.c_str(), 0)) return; - } /* Don't send chat that results in an automatic ban. */ - if (tmw_CheckChatSpam(sd, message)) + if (tmw_CheckChatSpam(sd, mbuf.c_str())) { - free(buf); clif_displaymessage(fd, "Your message could not be sent."); return; } - party_send_message(sd, message, RFIFOW(fd, 2) - 4); - free(buf); -} - -// 4144 wants this, but I don't like it ... -static -void clif_parse_PMIgnoreAll(int fd, dumb_ptr<map_session_data> sd) -{ // Rewritten by [Yor] - //PRINTF("Ignore all: state: %d\n", RFIFOB(fd,2)); - if (RFIFOB(fd, 2) == 0) - { // S 00d0 <type>len.B: 00 (/exall) deny all speech, 01 (/inall) allow all speech - WFIFOW(fd, 0) = 0x0d2; // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail - WFIFOB(fd, 2) = 0; - if (sd->ignoreAll == 0) - { - sd->ignoreAll = 1; - WFIFOB(fd, 3) = 0; // success - WFIFOSET(fd, clif_parse_func_table[0x0d2].len); - } - else - { - WFIFOB(fd, 3) = 1; // fail - WFIFOSET(fd, clif_parse_func_table[0x0d2].len); - clif_wis_message(fd, wisp_server_name, - "You already block everyone.", - strlen("You already block everyone.") + 1); - } - } - else - { - WFIFOW(fd, 0) = 0x0d2; // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail - WFIFOB(fd, 2) = 1; - if (sd->ignoreAll == 1) - { - sd->ignoreAll = 0; - WFIFOB(fd, 3) = 0; // success - WFIFOSET(fd, clif_parse_func_table[0x0d2].len); - } - else - { - WFIFOB(fd, 3) = 1; // fail - WFIFOSET(fd, clif_parse_func_table[0x0d2].len); - clif_wis_message(fd, wisp_server_name, - "You already allow everyone.", - strlen("You already allow everyone.") + 1); - } - } - - return; + party_send_message(sd, mbuf.c_str(), RFIFOW(fd, 2) - 4); } func_table clif_parse_func_table[0x0220] = @@ -5220,7 +5144,7 @@ func_table clif_parse_func_table[0x0220] = {0, 6, NULL, }, // 0x00cd {0, 2, NULL, }, // 0x00ce {0, 27, NULL, }, // 0x00cf - {0, 3, clif_parse_PMIgnoreAll, }, // 0x00d0 + {0, 3, NULL, }, // 0x00d0 {0, 4, NULL, }, // 0x00d1 {0, 4, NULL, }, // 0x00d2 {0, 2, NULL, }, // 0x00d3 @@ -5653,35 +5577,22 @@ void WARN_MALFORMED_MSG(dumb_ptr<map_session_data> sd, const char *msg) * 0 for when the sender's name is not included (party chat) * 1 for when the target's name is included (whisper chat) * 2 for when the sender's name is given ("sender : text", public/guild chat) - * @param[out] message the message text (pointing within return value, or NULL) - * @param[out] message_len the length of the actual text, excluding NUL - * @return a dynamically allocated copy of the message, or NULL upon failure + * @return a dynamically allocated copy of the message, or empty string upon failure */ static -char *clif_validate_chat(dumb_ptr<map_session_data> sd, int type, - const char **message, size_t *message_len) +std::string clif_validate_chat(dumb_ptr<map_session_data> sd, ChatType type) { - int fd; - unsigned int buf_len; /* Actual message length. */ - unsigned int msg_len; /* Reported message length. */ - unsigned int min_len; /* Minimum message length. */ - size_t name_len; /* Sender's name length. */ - char *buf = NULL; /* Copy of actual message data. */ - - *message = NULL; - *message_len = 0; - - nullpo_retr(NULL, sd); + nullpo_retr(std::string(), sd); /* * Don't send chat in the period between the ban and the connection's * closure. */ - if (type < 0 || type > 2 || sd->auto_ban_info.in_progress) - return NULL; + if (sd->auto_ban_info.in_progress) + return std::string(); - fd = sd->fd; - msg_len = RFIFOW(fd, 2) - 4; - name_len = strlen(sd->status.name); + int fd = sd->fd; + size_t msg_len = RFIFOW(fd, 2) - 4; + size_t name_len = strlen(sd->status.name); /* * At least one character is required in all instances. * Notes for length checks: @@ -5692,33 +5603,42 @@ char *clif_validate_chat(dumb_ptr<map_session_data> sd, int type, * For type 2, the message must be longer than the sender's name length * plus the length of the separator (" : "). */ - min_len = (type == 1) ? 24 : (type == 2) ? name_len + 3 : 0; + size_t min_len = + (type == ChatType::Whisper) ? 24 + : (type == ChatType::Global) ? name_len + 3 + : 0; /* The player just sent the header (2) and length (2) words. */ if (!msg_len) { WARN_MALFORMED_MSG(sd, "no message sent"); - return NULL; + return std::string(); } /* The client sent (or claims to have sent) an empty message. */ if (msg_len == min_len) { WARN_MALFORMED_MSG(sd, "empty message"); - return NULL; + return std::string(); } /* The protocol specifies that the target must be 24 bytes long. */ - if (type == 1 && msg_len < min_len) + if (type == ChatType::Whisper && msg_len < min_len) { /* Disallow malformed messages. */ clif_setwaitclose(fd); WARN_MALFORMED_MSG(sd, "illegal target name"); - return NULL; + return std::string(); } - const char *p = static_cast<const char *>((type != 1) ? RFIFOP(fd, 4) : RFIFOP(fd, 28)); - buf_len = (type == 1) ? msg_len - min_len: msg_len; + const char *p = static_cast<const char *>(RFIFOP(fd, 4)); + size_t buf_len = msg_len; + if (type == ChatType::Whisper) + { + p += 24; + buf_len -= 24; + } + const char *pend = p + buf_len; /* * The client attempted to exceed the maximum message length. @@ -5730,43 +5650,25 @@ char *clif_validate_chat(dumb_ptr<map_session_data> sd, int type, if (buf_len >= battle_config.chat_maxline) { WARN_MALFORMED_MSG(sd, "exceeded maximum message length"); - return NULL; + return std::string(); } - /* We're leaving an extra eight bytes for public/global chat, 1 for NUL. */ - buf_len += (type == 2) ? 8 + 1 : 1; - - buf = (char *) malloc(buf_len); - memcpy((type != 2) ? buf : buf + 8, p, - (type != 2) ? buf_len - 1 : buf_len - 8 - 1); - buf[buf_len - 1] = '\0'; - p = (type != 2) ? buf : buf + 8; - - if (type != 2) - { - *message = buf; - /* Don't count the NUL. */ - *message_len = buf_len - 1; - } - else + if (type == ChatType::Global) { - const char *pos = NULL; - if (!(pos = strstr(p, " : ")) - || strncmp(p, sd->status.name, name_len) - || pos - p != name_len) + const char *pos = strstr(p, " : "); + if (!pos || pos != p + name_len || memcmp(p, sd->status.name, name_len)) { - free(buf); /* Disallow malformed/spoofed messages. */ clif_setwaitclose(fd); WARN_MALFORMED_MSG(sd, "spoofed name/invalid format"); - return NULL; + return std::string(); } /* Step beyond the separator. */ - *message = pos + 3; - /* Don't count the sender's name, the extra eight bytes, or the NUL. */ - *message_len = buf_len - min_len - 8 - 1; + p = pos + 3; } + std::string buf(p, pend); + return buf; } diff --git a/src/map/intif.cpp b/src/map/intif.cpp index 53ff80e..1010047 100644 --- a/src/map/intif.cpp +++ b/src/map/intif.cpp @@ -88,7 +88,7 @@ int intif_wis_message_to_gm(const char *Wisp_name, int min_gm_level, const char WFIFOW(char_fd, 0) = 0x3003; WFIFOW(char_fd, 2) = mes_len + 30; memcpy(WFIFOP(char_fd, 4), Wisp_name, 24); - WFIFOW(char_fd, 28) = (short) min_gm_level; + WFIFOW(char_fd, 28) = min_gm_level; memcpy(WFIFOP(char_fd, 30), mes, mes_len); WFIFOSET(char_fd, WFIFOW(char_fd, 2)); @@ -159,7 +159,7 @@ int intif_create_party(dumb_ptr<map_session_data> sd, const char *name) WFIFOL(char_fd, 2) = sd->status.account_id; memcpy(WFIFOP(char_fd, 6), name, 24); memcpy(WFIFOP(char_fd, 30), sd->status.name, 24); - memcpy(WFIFOP(char_fd, 54), map[sd->bl_m].name, 16); + memcpy(WFIFOP(char_fd, 54), sd->bl_m->name, 16); WFIFOW(char_fd, 70) = sd->status.base_level; WFIFOSET(char_fd, 72); // if(battle_config.etc_log) @@ -191,7 +191,7 @@ int intif_party_addmember(int party_id, int account_id) WFIFOL(char_fd, 2) = party_id; WFIFOL(char_fd, 6) = account_id; memcpy(WFIFOP(char_fd, 10), sd->status.name, 24); - memcpy(WFIFOP(char_fd, 34), map[sd->bl_m].name, 16); + memcpy(WFIFOP(char_fd, 34), sd->bl_m->name, 16); WFIFOW(char_fd, 50) = sd->status.base_level; WFIFOSET(char_fd, 52); } @@ -230,7 +230,7 @@ int intif_party_changemap(dumb_ptr<map_session_data> sd, int online) WFIFOW(char_fd, 0) = 0x3025; WFIFOL(char_fd, 2) = sd->status.party_id; WFIFOL(char_fd, 6) = sd->status.account_id; - memcpy(WFIFOP(char_fd, 10), map[sd->bl_m].name, 16); + memcpy(WFIFOP(char_fd, 10), sd->bl_m->name, 16); WFIFOB(char_fd, 26) = online; WFIFOW(char_fd, 27) = sd->status.base_level; WFIFOSET(char_fd, 29); @@ -273,7 +273,6 @@ static int intif_parse_WisMessage(int fd) { // rewritten by [Yor] dumb_ptr<map_session_data> sd; - int i; if (battle_config.etc_log) PRINTF("intif_parse_wismessage: id: %d, from: %s, to: %s, message: '%s'\n", @@ -281,27 +280,14 @@ int intif_parse_WisMessage(int fd) static_cast<const char *>(RFIFOP(fd, 8)), static_cast<const char *>(RFIFOP(fd, 32)), static_cast<const char *>(RFIFOP(fd, 56))); - sd = map_nick2sd((const char *)RFIFOP(fd, 32)); // Searching destination player - if (sd != NULL && strcmp(sd->status.name, (const char *)RFIFOP(fd, 32)) == 0) - { // exactly same name (inter-server have checked the name before) - // if player ignore all - if (sd->ignoreAll == 1) - intif_wis_replay(RFIFOL(fd, 4), 2); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - else + sd = map_nick2sd(static_cast<const char *>(RFIFOP(fd, 32))); // Searching destination player + if (sd != NULL && strcmp(sd->status.name, static_cast<const char *>(RFIFOP(fd, 32))) == 0) + { + // exactly same name (inter-server have checked the name before) { - const char *wisp_source = (const char *)RFIFOP(fd, 8); // speed up - // if player ignore the source character - for (i = 0; i < (sizeof(sd->ignore) / sizeof(sd->ignore[0])); - i++) - if (strcmp(sd->ignore[i].name, wisp_source) == 0) - { - intif_wis_replay(RFIFOL(fd, 4), 2); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - break; - } // if source player not found in ignore list - if (i == (sizeof(sd->ignore) / sizeof(sd->ignore[0]))) { - clif_wis_message(sd->fd, (const char *)RFIFOP(fd, 8), (const char *)RFIFOP(fd, 56), + clif_wis_message(sd->fd, static_cast<const char *>(RFIFOP(fd, 8)), static_cast<const char *>(RFIFOP(fd, 56)), RFIFOW(fd, 2) - 56); intif_wis_replay(RFIFOL(fd, 4), 0); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target } @@ -322,7 +308,7 @@ int intif_parse_WisEnd(int fd) // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target PRINTF("intif_parse_wisend: player: %s, flag: %d\n", static_cast<const char *>(RFIFOP(fd, 2)), RFIFOB(fd, 26)); - sd = map_nick2sd((const char *)RFIFOP(fd, 2)); + sd = map_nick2sd(static_cast<const char *>(RFIFOP(fd, 2))); if (sd != NULL) clif_wis_end(sd->fd, RFIFOB(fd, 26)); @@ -336,19 +322,18 @@ int mapif_parse_WisToGM(int fd) // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B int min_gm_level, len; char Wisp_name[24]; - char mbuf[255]; if (RFIFOW(fd, 2) - 30 <= 0) return 0; len = RFIFOW(fd, 2) - 30; - char *message = ((len) >= 255) ? (char *) malloc(len) : mbuf; + char message[len + 1]; - min_gm_level = (int) RFIFOW(fd, 28); + min_gm_level = RFIFOW(fd, 28); memcpy(Wisp_name, RFIFOP(fd, 4), 24); Wisp_name[23] = '\0'; memcpy(message, RFIFOP(fd, 30), len); - message[len - 1] = '\0'; + message[len] = '\0'; // information is sended to all online GM for (int i = 0; i < fd_max; i++) { @@ -361,9 +346,6 @@ int mapif_parse_WisToGM(int fd) strlen(message) + 1); } - if (message != mbuf) - free(message); - return 0; } @@ -457,7 +439,7 @@ int intif_parse_PartyCreated(int fd) if (battle_config.etc_log) PRINTF("intif: party created\n"); party_created(RFIFOL(fd, 2), RFIFOB(fd, 6), RFIFOL(fd, 7), - (const char *)RFIFOP(fd, 11)); + static_cast<const char *>(RFIFOP(fd, 11))); return 0; } @@ -511,8 +493,8 @@ int intif_parse_PartyMemberLeaved(int fd) { if (battle_config.etc_log) PRINTF("intif: party member leaved %d %d %s\n", RFIFOL(fd, 2), - RFIFOL(fd, 6), (const char *)RFIFOP(fd, 10)); - party_member_leaved(RFIFOL(fd, 2), RFIFOL(fd, 6), (const char *)RFIFOP(fd, 10)); + RFIFOL(fd, 6), static_cast<const char *>(RFIFOP(fd, 10))); + party_member_leaved(RFIFOL(fd, 2), RFIFOL(fd, 6), static_cast<const char *>(RFIFOP(fd, 10))); return 0; } @@ -530,7 +512,7 @@ int intif_parse_PartyMove(int fd) { // if(battle_config.etc_log) // PRINTF("intif: party move %d %d %s %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27)); - party_recv_movemap(RFIFOL(fd, 2), RFIFOL(fd, 6), (const char *)RFIFOP(fd, 10), + party_recv_movemap(RFIFOL(fd, 2), RFIFOL(fd, 6), static_cast<const char *>(RFIFOP(fd, 10)), RFIFOB(fd, 26), RFIFOW(fd, 27)); return 0; } @@ -541,7 +523,7 @@ int intif_parse_PartyMessage(int fd) { // if(battle_config.etc_log) // PRINTF("intif_parse_PartyMessage: %s\n",RFIFOP(fd,12)); - party_recv_message(RFIFOL(fd, 4), RFIFOL(fd, 8), (const char *)RFIFOP(fd, 12), + party_recv_message(RFIFOL(fd, 4), RFIFOL(fd, 8), static_cast<const char *>(RFIFOP(fd, 12)), RFIFOW(fd, 2) - 12); return 0; } @@ -581,7 +563,7 @@ int intif_parse(int fd) { case 0x3800: clif_GMmessage(NULL, - const_string((const char *)RFIFOP(fd, 4), + const_string(static_cast<const char *>(RFIFOP(fd, 4)), (packet_len - 4) - 1), 0); break; case 0x3801: diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp index f60dc53..147db91 100644 --- a/src/map/itemdb.cpp +++ b/src/map/itemdb.cpp @@ -367,10 +367,8 @@ int itemdb_read_noequip(void) static void itemdb_final(struct item_data *id) { - if (id->use_script) - free(const_cast<ScriptCode *>(id->use_script)); - if (id->equip_script) - free(const_cast<ScriptCode *>(id->equip_script)); + id->use_script.reset(); + id->equip_script.reset(); } void itemdb_reload(void) diff --git a/src/map/itemdb.hpp b/src/map/itemdb.hpp index 279c7a8..02da73a 100644 --- a/src/map/itemdb.hpp +++ b/src/map/itemdb.hpp @@ -27,8 +27,8 @@ struct item_data int elv; int wlv; int refine; - const ScriptCode *use_script; - const ScriptCode *equip_script; + std::unique_ptr<const ScriptBuffer> use_script; + std::unique_ptr<const ScriptBuffer> equip_script; struct { unsigned available:1; @@ -67,9 +67,9 @@ int itemdb_weight(int n) return itemdb_search(n)->weight; } inline -const ScriptCode *itemdb_equipscript(int n) +const ScriptBuffer *itemdb_equipscript(int n) { - return itemdb_search(n)->equip_script; + return itemdb_search(n)->equip_script.get(); } inline int itemdb_wlv(int n) diff --git a/src/map/magic-expr-eval.hpp b/src/map/magic-expr-eval.hpp index bc5ce6e..9c9591b 100644 --- a/src/map/magic-expr-eval.hpp +++ b/src/map/magic-expr-eval.hpp @@ -10,13 +10,13 @@ int magic_signature_check(const char *opname, const char *funname, const char *signature, int args_nr, val_t *args, int line, int column); -void magic_area_rect(int *m, int *x, int *y, int *width, int *height, - area_t *area); +void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height, + area_t& area); #define ARGINT(x) args[x].v.v_int #define ARGDIR(x) args[x].v.v_dir #define ARGSTR(x) args[x].v.v_string -#define ARGENTITY(x) dumb_ptr<block_list>(args[x].v.v_entity) +#define ARGENTITY(x) args[x].v.v_entity #define ARGLOCATION(x) args[x].v.v_location #define ARGAREA(x) args[x].v.v_area #define ARGSPELL(x) args[x].v.v_spell diff --git a/src/map/magic-expr.cpp b/src/map/magic-expr.cpp index c0eaf9f..7739847 100644 --- a/src/map/magic-expr.cpp +++ b/src/map/magic-expr.cpp @@ -16,7 +16,7 @@ #include "../poison.hpp" static -void free_area(area_t *area) +void free_area(dumb_ptr<area_t> area) { if (!area) return; @@ -31,13 +31,13 @@ void free_area(area_t *area) break; } - free(area); + area.delete_(); } static -area_t *dup_area(area_t *area) +dumb_ptr<area_t> dup_area(dumb_ptr<area_t> area) { - area_t *retval = (area_t *)malloc(sizeof(area_t)); + dumb_ptr<area_t> retval = dumb_ptr<area_t>::make(); *retval = *area; switch (area->ty) @@ -60,7 +60,7 @@ void magic_copy_var(val_t *dest, val_t *src) switch (dest->ty) { case TYPE::STRING: - dest->v.v_string = strdup(dest->v.v_string); + dest->v.v_string = dest->v.v_string.dup(); break; case TYPE::AREA: dest->v.v_area = dup_area(dest->v.v_area); @@ -76,7 +76,7 @@ void magic_clear_var(val_t *v) switch (v->ty) { case TYPE::STRING: - free(v->v.v_string); + v->v.v_string.delete_(); break; case TYPE::AREA: free_area(v->v.v_area); @@ -139,12 +139,12 @@ void stringify(val_t *v, int within_op) break; case TYPE::ENTITY: - buf = show_entity(dumb_ptr<block_list>(v->v.v_entity)); + buf = show_entity(v->v.v_entity); break; case TYPE::LOCATION: buf = STRPRINTF("<\"%s\", %d, %d>", - map[v->v.v_location.m].name, + v->v.v_location.m->name, v->v.v_location.x, v->v.v_location.y); break; @@ -161,7 +161,7 @@ void stringify(val_t *v, int within_op) case TYPE::INVOCATION: { dumb_ptr<invocation> invocation_ = within_op - ? dumb_ptr<invocation>(v->v.v_invocation) + ? v->v.v_invocation : map_id2bl(v->v.v_int)->as_spell(); buf = invocation_->spell->name; } @@ -173,7 +173,7 @@ void stringify(val_t *v, int within_op) return; } - v->v.v_string = strdup(buf.c_str()); + v->v.v_string = dumb_string::copys(buf); v->ty = TYPE::STRING; } @@ -189,18 +189,17 @@ void intify(val_t *v) } static -area_t *area_new(AREA ty) +dumb_ptr<area_t> area_new(AREA ty) { - area_t *retval; - CREATE(retval, area_t, 1); + auto retval = dumb_ptr<area_t>::make(); retval->ty = ty; return retval; } static -area_t *area_union(area_t *area, area_t *other_area) +dumb_ptr<area_t> area_union(dumb_ptr<area_t> area, dumb_ptr<area_t> other_area) { - area_t *retval = area_new(AREA::UNION); + dumb_ptr<area_t> retval = area_new(AREA::UNION); retval->a.a_union[0] = area; retval->a.a_union[1] = other_area; retval->size = area->size + other_area->size; /* Assume no overlap */ @@ -215,7 +214,7 @@ void make_area(val_t *v) { if (v->ty == TYPE::LOCATION) { - area_t *a = (area_t *)malloc(sizeof(area_t)); + auto a = dumb_ptr<area_t>::make(); v->ty = TYPE::AREA; a->ty = AREA::LOCATION; a->a.a_loc = v->v.v_location; @@ -240,7 +239,7 @@ void make_spell(val_t *v) { if (v->ty == TYPE::INVOCATION) { - dumb_ptr<invocation> invoc = dumb_ptr<invocation>(v->v.v_invocation); + dumb_ptr<invocation> invoc = v->v.v_invocation; //invoc = (dumb_ptr<invocation>) map_id2bl(v->v.v_int); if (!invoc) v->ty = TYPE::FAIL; @@ -253,7 +252,7 @@ void make_spell(val_t *v) } static -int fun_add(env_t *, int, val_t *result, val_t *args) +int fun_add(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (ARG_TYPE(0) == TYPE::INT && ARG_TYPE(1) == TYPE::INT) { @@ -277,31 +276,29 @@ int fun_add(env_t *, int, val_t *result, val_t *args) stringify(&args[0], 1); stringify(&args[1], 1); /* Yes, we could speed this up. */ - RESULTSTR = - (char *) malloc(1 + strlen(ARGSTR(0)) + strlen(ARGSTR(1))); - strcpy(RESULTSTR, ARGSTR(0)); - strcat(RESULTSTR, ARGSTR(1)); + // ugh + RESULTSTR = dumb_string::copys(ARGSTR(0).str() + ARGSTR(1).str()); result->ty = TYPE::STRING; } return 0; } static -int fun_sub(env_t *, int, val_t *result, val_t *args) +int fun_sub(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = ARGINT(0) - ARGINT(1); return 0; } static -int fun_mul(env_t *, int, val_t *result, val_t *args) +int fun_mul(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = ARGINT(0) * ARGINT(1); return 0; } static -int fun_div(env_t *, int, val_t *result, val_t *args) +int fun_div(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (!ARGINT(1)) return 1; /* division by zero */ @@ -310,7 +307,7 @@ int fun_div(env_t *, int, val_t *result, val_t *args) } static -int fun_mod(env_t *, int, val_t *result, val_t *args) +int fun_mod(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (!ARGINT(1)) return 1; /* division by zero */ @@ -319,41 +316,42 @@ int fun_mod(env_t *, int, val_t *result, val_t *args) } static -int fun_or(env_t *, int, val_t *result, val_t *args) +int fun_or(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = ARGINT(0) || ARGINT(1); return 0; } static -int fun_and(env_t *, int, val_t *result, val_t *args) +int fun_and(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = ARGINT(0) && ARGINT(1); return 0; } static -int fun_not(env_t *, int, val_t *result, val_t *args) +int fun_not(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = !ARGINT(0); return 0; } static -int fun_neg(env_t *, int, val_t *result, val_t *args) +int fun_neg(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = ~ARGINT(0); return 0; } static -int fun_gte(env_t *, int, val_t *result, val_t *args) +int fun_gte(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (ARG_TYPE(0) == TYPE::STRING || ARG_TYPE(1) == TYPE::STRING) { stringify(&args[0], 1); stringify(&args[1], 1); - RESULTINT = strcmp(ARGSTR(0), ARGSTR(1)) >= 0; + using namespace operators; + RESULTINT = ARGSTR(0) >= ARGSTR(1); } else { @@ -365,13 +363,14 @@ int fun_gte(env_t *, int, val_t *result, val_t *args) } static -int fun_gt(env_t *, int, val_t *result, val_t *args) +int fun_gt(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (ARG_TYPE(0) == TYPE::STRING || ARG_TYPE(1) == TYPE::STRING) { stringify(&args[0], 1); stringify(&args[1], 1); - RESULTINT = strcmp(ARGSTR(0), ARGSTR(1)) > 0; + using namespace operators; + RESULTINT = ARGSTR(0) > ARGSTR(1); } else { @@ -383,13 +382,14 @@ int fun_gt(env_t *, int, val_t *result, val_t *args) } static -int fun_eq(env_t *, int, val_t *result, val_t *args) +int fun_eq(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (ARG_TYPE(0) == TYPE::STRING || ARG_TYPE(1) == TYPE::STRING) { stringify(&args[0], 1); stringify(&args[1], 1); - RESULTINT = strcmp(ARGSTR(0), ARGSTR(1)) == 0; + using namespace operators; + RESULTINT = ARGSTR(0) == ARGSTR(1); } else if (ARG_TYPE(0) == TYPE::DIR && ARG_TYPE(1) == TYPE::DIR) RESULTINT = ARGDIR(0) == ARGDIR(1); @@ -415,56 +415,56 @@ int fun_eq(env_t *, int, val_t *result, val_t *args) } static -int fun_bitand(env_t *, int, val_t *result, val_t *args) +int fun_bitand(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = ARGINT(0) & ARGINT(1); return 0; } static -int fun_bitor(env_t *, int, val_t *result, val_t *args) +int fun_bitor(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = ARGINT(0) | ARGINT(1); return 0; } static -int fun_bitxor(env_t *, int, val_t *result, val_t *args) +int fun_bitxor(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = ARGINT(0) ^ ARGINT(1); return 0; } static -int fun_bitshl(env_t *, int, val_t *result, val_t *args) +int fun_bitshl(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = ARGINT(0) << ARGINT(1); return 0; } static -int fun_bitshr(env_t *, int, val_t *result, val_t *args) +int fun_bitshr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = ARGINT(0) >> ARGINT(1); return 0; } static -int fun_max(env_t *, int, val_t *result, val_t *args) +int fun_max(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = max(ARGINT(0), ARGINT(1)); return 0; } static -int fun_min(env_t *, int, val_t *result, val_t *args) +int fun_min(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = min(ARGINT(0), ARGINT(1)); return 0; } static -int fun_if_then_else(env_t *, int, val_t *result, val_t *args) +int fun_if_then_else(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (ARGINT(0)) magic_copy_var(result, &args[1]); @@ -473,9 +473,10 @@ int fun_if_then_else(env_t *, int, val_t *result, val_t *args) return 0; } -void magic_area_rect(int *m, int *x, int *y, int *width, int *height, - area_t *area) +void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height, + area_t& area_) { + area_t *area = &area_; // diff hack switch (area->ty) { case AREA::UNION: @@ -547,7 +548,7 @@ void magic_area_rect(int *m, int *x, int *y, int *width, int *height, } } -int magic_location_in_area(int m, int x, int y, area_t *area) +int magic_location_in_area(map_local *m, int x, int y, dumb_ptr<area_t> area) { switch (area->ty) { @@ -558,9 +559,9 @@ int magic_location_in_area(int m, int x, int y, area_t *area) case AREA::RECT: case AREA::BAR: { - int am; + map_local *am; int ax, ay, awidth, aheight; - magic_area_rect(&am, &ax, &ay, &awidth, &aheight, area); + magic_area_rect(&am, &ax, &ay, &awidth, &aheight, *area); return (am == m && (x >= ax) && (y >= ay) && (x < ax + awidth) && (y < ay + aheight)); @@ -572,7 +573,7 @@ int magic_location_in_area(int m, int x, int y, area_t *area) } static -int fun_is_in(env_t *, int, val_t *result, val_t *args) +int fun_is_in(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = magic_location_in_area(ARGLOCATION(0).m, ARGLOCATION(0).x, @@ -581,7 +582,7 @@ int fun_is_in(env_t *, int, val_t *result, val_t *args) } static -int fun_skill(env_t *, int, val_t *result, val_t *args) +int fun_skill(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (ENTITY_TYPE(0) != BL::PC // don't convert to enum until after the range check @@ -599,7 +600,7 @@ int fun_skill(env_t *, int, val_t *result, val_t *args) } static -int fun_has_shroud(env_t *, int, val_t *result, val_t *args) +int fun_has_shroud(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = (ENTITY_TYPE(0) == BL::PC && ARGPC(0)->state.shroud_active); return 0; @@ -607,7 +608,7 @@ int fun_has_shroud(env_t *, int, val_t *result, val_t *args) #define BATTLE_GETTER(name) \ static \ -int fun_get_##name(env_t *, int, val_t *result, val_t *args) \ +int fun_get_##name(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) \ { \ RESULTINT = battle_get_##name(ARGENTITY(0)); \ return 0; \ @@ -625,7 +626,7 @@ BATTLE_GETTER(mdef) BATTLE_GETTER(def) BATTLE_GETTER(max_hp) static -int fun_get_dir(env_t *, int, val_t *result, val_t *args) +int fun_get_dir(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTDIR = battle_get_dir(ARGENTITY(0)); return 0; @@ -633,7 +634,7 @@ int fun_get_dir(env_t *, int, val_t *result, val_t *args) #define MMO_GETTER(name) \ static \ -int fun_get_##name(env_t *, int, val_t *result, val_t *args) \ +int fun_get_##name(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) \ { \ if (ENTITY_TYPE(0) == BL::PC) \ RESULTINT = ARGPC(0)->status.name; \ @@ -646,21 +647,21 @@ MMO_GETTER(sp) MMO_GETTER(max_sp) static -int fun_name_of(env_t *, int, val_t *result, val_t *args) +int fun_name_of(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (ARG_TYPE(0) == TYPE::ENTITY) { - RESULTSTR = strdup(show_entity(ARGENTITY(0))); + RESULTSTR = dumb_string::copy(show_entity(ARGENTITY(0))); return 0; } else if (ARG_TYPE(0) == TYPE::SPELL) { - RESULTSTR = strdup(ARGSPELL(0)->name); + RESULTSTR = dumb_string::copys(ARGSPELL(0)->name); return 0; } else if (ARG_TYPE(0) == TYPE::INVOCATION) { - RESULTSTR = strdup(ARGINVOCATION(0)->spell->name); + RESULTSTR = dumb_string::copys(ARGINVOCATION(0)->spell->name); return 0; } return 1; @@ -668,7 +669,7 @@ int fun_name_of(env_t *, int, val_t *result, val_t *args) /* [Freeyorp] I'm putting this one in as name_of seems to have issues with summoned or spawned mobs. */ static -int fun_mob_id(env_t *, int, val_t *result, val_t *args) +int fun_mob_id(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (ENTITY_TYPE(0) != BL::MOB) return 1; @@ -693,14 +694,14 @@ void COPY_LOCATION(location_t& dest, block_list& src) } static -int fun_location(env_t *, int, val_t *result, val_t *args) +int fun_location(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { COPY_LOCATION(RESULTLOCATION, *(ARGENTITY(0))); return 0; } static -int fun_random(env_t *, int, val_t *result, val_t *args) +int fun_random(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { int delta = ARGINT(0); if (delta < 0) @@ -718,7 +719,7 @@ int fun_random(env_t *, int, val_t *result, val_t *args) } static -int fun_random_dir(env_t *, int, val_t *result, val_t *args) +int fun_random_dir(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (ARGINT(0)) RESULTDIR = random_::choice({DIR::S, DIR::SW, DIR::W, DIR::NW, DIR::N, DIR::NE, DIR::E, DIR::SE}); @@ -728,14 +729,14 @@ int fun_random_dir(env_t *, int, val_t *result, val_t *args) } static -int fun_hash_entity(env_t *, int, val_t *result, val_t *args) +int fun_hash_entity(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = ARGENTITY(0)->bl_id; return 0; } int // ret -1: not a string, ret 1: no such item, ret 0: OK -magic_find_item(val_t *args, int index, struct item *item, int *stackable) +magic_find_item(const_array<val_t> args, int index, struct item *item, int *stackable) { struct item_data *item_data; int must_add_sequentially; @@ -743,7 +744,7 @@ magic_find_item(val_t *args, int index, struct item *item, int *stackable) if (ARG_TYPE(index) == TYPE::INT) item_data = itemdb_exists(ARGINT(index)); else if (ARG_TYPE(index) == TYPE::STRING) - item_data = itemdb_searchname(ARGSTR(index)); + item_data = itemdb_searchname(ARGSTR(index).c_str()); else return -1; @@ -768,7 +769,7 @@ magic_find_item(val_t *args, int index, struct item *item, int *stackable) } static -int fun_count_item(env_t *, int, val_t *result, val_t *args) +int fun_count_item(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { dumb_ptr<map_session_data> chr = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; int stackable; @@ -784,7 +785,7 @@ int fun_count_item(env_t *, int, val_t *result, val_t *args) } static -int fun_is_equipped(env_t *, int, val_t *result, val_t *args) +int fun_is_equipped(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { dumb_ptr<map_session_data> chr = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; int stackable; @@ -810,33 +811,33 @@ int fun_is_equipped(env_t *, int, val_t *result, val_t *args) } static -int fun_is_married(env_t *, int, val_t *result, val_t *args) +int fun_is_married(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = (ENTITY_TYPE(0) == BL::PC && ARGPC(0)->status.partner_id); return 0; } static -int fun_is_dead(env_t *, int, val_t *result, val_t *args) +int fun_is_dead(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = (ENTITY_TYPE(0) == BL::PC && pc_isdead(ARGPC(0))); return 0; } static -int fun_is_pc(env_t *, int, val_t *result, val_t *args) +int fun_is_pc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = (ENTITY_TYPE(0) == BL::PC); return 0; } static -int fun_partner(env_t *, int, val_t *result, val_t *args) +int fun_partner(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (ENTITY_TYPE(0) == BL::PC && ARGPC(0)->status.partner_id) { RESULTENTITY = - map_nick2sd(map_charid2nick(ARGPC(0)->status.partner_id)).operator->(); + map_nick2sd(map_charid2nick(ARGPC(0)->status.partner_id)); return 0; } else @@ -844,14 +845,14 @@ int fun_partner(env_t *, int, val_t *result, val_t *args) } static -int fun_awayfrom(env_t *, int, val_t *result, val_t *args) +int fun_awayfrom(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { location_t *loc = &ARGLOCATION(0); int dx = dirx[ARGDIR(1)]; int dy = diry[ARGDIR(1)]; int distance = ARGINT(2); while (distance-- - && !bool(read_gat(loc->m, loc->x + dx, loc->y + dy) + && !bool(read_gatp(loc->m, loc->x + dx, loc->y + dy) & MapCell::UNWALKABLE)) { loc->x += dx; @@ -863,28 +864,28 @@ int fun_awayfrom(env_t *, int, val_t *result, val_t *args) } static -int fun_failed(env_t *, int, val_t *result, val_t *args) +int fun_failed(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = ARG_TYPE(0) == TYPE::FAIL; return 0; } static -int fun_npc(env_t *, int, val_t *result, val_t *args) +int fun_npc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { - RESULTENTITY = npc_name2id(ARGSTR(0)).operator->(); + RESULTENTITY = npc_name2id(ARGSTR(0).c_str()); return RESULTENTITY == NULL; } static -int fun_pc(env_t *, int, val_t *result, val_t *args) +int fun_pc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { - RESULTENTITY = map_nick2sd(ARGSTR(0)).operator->(); + RESULTENTITY = map_nick2sd(ARGSTR(0).c_str()); return RESULTENTITY == NULL; } static -int fun_distance(env_t *, int, val_t *result, val_t *args) +int fun_distance(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (ARGLOCATION(0).m != ARGLOCATION(1).m) RESULTINT = 0x7fffffff; @@ -895,7 +896,7 @@ int fun_distance(env_t *, int, val_t *result, val_t *args) } static -int fun_rdistance(env_t *, int, val_t *result, val_t *args) +int fun_rdistance(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (ARGLOCATION(0).m != ARGLOCATION(1).m) RESULTINT = 0x7fffffff; @@ -903,15 +904,15 @@ int fun_rdistance(env_t *, int, val_t *result, val_t *args) { int dx = ARGLOCATION(0).x - ARGLOCATION(1).x; int dy = ARGLOCATION(0).y - ARGLOCATION(1).y; - RESULTINT = (int)(sqrt((dx * dx) + (dy * dy))); + RESULTINT = static_cast<int>(sqrt((dx * dx) + (dy * dy))); } return 0; } static -int fun_anchor(env_t *env, int, val_t *result, val_t *args) +int fun_anchor(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args) { - teleport_anchor_t *anchor = magic_find_anchor(ARGSTR(0)); + dumb_ptr<teleport_anchor_t> anchor = magic_find_anchor(ARGSTR(0).str()); if (!anchor) return 1; @@ -929,7 +930,7 @@ int fun_anchor(env_t *env, int, val_t *result, val_t *args) } static -int fun_line_of_sight(env_t *, int, val_t *result, val_t *args) +int fun_line_of_sight(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { block_list e1, e2; @@ -941,7 +942,7 @@ int fun_line_of_sight(env_t *, int, val_t *result, val_t *args) return 0; } -void magic_random_location(location_t *dest, area_t *area) +void magic_random_location(location_t *dest, dumb_ptr<area_t> area) { switch (area->ty) { @@ -958,8 +959,9 @@ void magic_random_location(location_t *dest, area_t *area) case AREA::RECT: case AREA::BAR: { - int m, x, y, w, h; - magic_area_rect(&m, &x, &y, &w, &h, area); + map_local *m; + int x, y, w, h; + magic_area_rect(&m, &x, &y, &w, &h, *area); if (w <= 1) w = 1; @@ -984,27 +986,27 @@ void magic_random_location(location_t *dest, area_t *area) } static -int fun_pick_location(env_t *, int, val_t *result, val_t *args) +int fun_pick_location(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { magic_random_location(&result->v.v_location, ARGAREA(0)); return 0; } static -int fun_read_script_int(env_t *, int, val_t *result, val_t *args) +int fun_read_script_int(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { dumb_ptr<block_list> subject_p = ARGENTITY(0); - char *var_name = ARGSTR(1); + dumb_string var_name = ARGSTR(1); if (subject_p->bl_type != BL::PC) return 1; - RESULTINT = pc_readglobalreg(subject_p->as_player(), var_name); + RESULTINT = pc_readglobalreg(subject_p->as_player(), var_name.c_str()); return 0; } static -int fun_rbox(env_t *, int, val_t *result, val_t *args) +int fun_rbox(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { location_t loc = ARGLOCATION(0); int radius = ARGINT(1); @@ -1020,7 +1022,7 @@ int fun_rbox(env_t *, int, val_t *result, val_t *args) } static -int fun_running_status_update(env_t *, int, val_t *result, val_t *args) +int fun_running_status_update(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { if (ENTITY_TYPE(0) != BL::PC && ENTITY_TYPE(0) != BL::MOB) return 1; @@ -1031,66 +1033,67 @@ int fun_running_status_update(env_t *, int, val_t *result, val_t *args) } static -int fun_status_option(env_t *, int, val_t *result, val_t *args) +int fun_status_option(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = (bool((ARGPC(0))->status.option & static_cast<Option>(ARGINT(0)))); return 0; } static -int fun_element(env_t *, int, val_t *result, val_t *args) +int fun_element(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = static_cast<int>(battle_get_element(ARGENTITY(0)).element); return 0; } static -int fun_element_level(env_t *, int, val_t *result, val_t *args) +int fun_element_level(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { RESULTINT = battle_get_element(ARGENTITY(0)).level; return 0; } static -int fun_index(env_t *, int, val_t *result, val_t *args) +int fun_index(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { - RESULTINT = ARGSPELL(0)->index; + RESULTINT = ARGSPELL(0)->index_; return 0; } static -int fun_is_exterior(env_t *, int, val_t *result, val_t *args) +int fun_is_exterior(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { - RESULTINT = map[ARGLOCATION(0).m].name[4] == '1'; +#warning "Evil assumptions!" + RESULTINT = ARGLOCATION(0).m->name[4] == '1'; return 0; } static -int fun_contains_string(env_t *, int, val_t *result, val_t *args) +int fun_contains_string(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { - RESULTINT = NULL != strstr(ARGSTR(0), ARGSTR(1)); + RESULTINT = NULL != strstr(ARGSTR(0).c_str(), ARGSTR(1).c_str()); return 0; } static -int fun_strstr(env_t *, int, val_t *result, val_t *args) +int fun_strstr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { - char *offset = strstr(ARGSTR(0), ARGSTR(1)); - RESULTINT = offset - ARGSTR(0); + const char *offset = strstr(ARGSTR(0).c_str(), ARGSTR(1).c_str()); + RESULTINT = offset - ARGSTR(0).c_str(); return offset == NULL; } static -int fun_strlen(env_t *, int, val_t *result, val_t *args) +int fun_strlen(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { - RESULTINT = strlen(ARGSTR(0)); + RESULTINT = strlen(ARGSTR(0).c_str()); return 0; } static -int fun_substr(env_t *, int, val_t *result, val_t *args) +int fun_substr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { - const char *src = ARGSTR(0); + const char *src = ARGSTR(0).c_str(); const int slen = strlen(src); int offset = ARGINT(1); int len = ARGINT(2); @@ -1106,30 +1109,33 @@ int fun_substr(env_t *, int, val_t *result, val_t *args) if (offset + len > slen) len = slen - offset; - RESULTSTR = (char *) calloc(1, 1 + len); - memcpy(RESULTSTR, src + offset, len); + const char *begin = src + offset; + const char *end = begin + len; + RESULTSTR = dumb_string::copy(begin, end); return 0; } static -int fun_sqrt(env_t *, int, val_t *result, val_t *args) +int fun_sqrt(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { - RESULTINT = (int) sqrt(ARGINT(0)); + RESULTINT = static_cast<int>(sqrt(ARGINT(0))); return 0; } static -int fun_map_level(env_t *, int, val_t *result, val_t *args) +int fun_map_level(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { - RESULTINT = map[ARGLOCATION(0).m].name[4] - '0'; +#warning "Evil assumptions!" + RESULTINT = ARGLOCATION(0).m->name[4] - '0'; return 0; } static -int fun_map_nr(env_t *, int, val_t *result, val_t *args) +int fun_map_nr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { - const char *mapname = map[ARGLOCATION(0).m].name; +#warning "Evil assumptions!" + const char *mapname = ARGLOCATION(0).m->name; RESULTINT = ((mapname[0] - '0') * 100) + ((mapname[1] - '0') * 10) + ((mapname[2] - '0')); @@ -1137,7 +1143,7 @@ int fun_map_nr(env_t *, int, val_t *result, val_t *args) } static -int fun_dir_towards(env_t *, int, val_t *result, val_t *args) +int fun_dir_towards(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { int dx; int dy; @@ -1203,7 +1209,7 @@ int fun_dir_towards(env_t *, int, val_t *result, val_t *args) } static -int fun_extract_healer_xp(env_t *, int, val_t *result, val_t *args) +int fun_extract_healer_xp(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) { dumb_ptr<map_session_data> sd = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; @@ -1215,7 +1221,8 @@ int fun_extract_healer_xp(env_t *, int, val_t *result, val_t *args) } static -fun_t functions[] = { +fun_t functions[] = +{ {"+", "..", '.', fun_add}, {"-", "ii", 'i', fun_sub}, {"*", "ii", 'i', fun_mul}, @@ -1297,16 +1304,16 @@ fun_t functions[] = { static int functions_are_sorted = 0; -static +static __attribute__((deprecated)) int compare_fun(const void *lhs, const void *rhs) { - return strcmp(((const fun_t *) lhs)->name, ((const fun_t *) rhs)->name); + return strcmp(static_cast<const fun_t *>(lhs)->name, static_cast<const fun_t *>(rhs)->name); } -fun_t *magic_get_fun(const char *name, int *index) +fun_t *magic_get_fun(const std::string& name, int *index) { static -int functions_nr; + int functions_nr; fun_t *result; fun_t key; @@ -1322,9 +1329,9 @@ int functions_nr; functions_are_sorted = 1; } - key.name = name; - result = (fun_t *) bsearch(&key, functions, functions_nr, sizeof(fun_t), - compare_fun); + key.name = name.c_str(); + result = static_cast<fun_t *>(bsearch(&key, functions, functions_nr, sizeof(fun_t), + compare_fun)); if (result && index) *index = result - functions; @@ -1332,9 +1339,9 @@ int functions_nr; return result; } +// 1 on failure static -int // 1 on failure -eval_location(env_t *env, location_t *dest, e_location_t *expr) +int eval_location(dumb_ptr<env_t> env, location_t *dest, e_location_t *expr) { val_t m, x, y; magic_eval(env, &m, expr->m); @@ -1344,9 +1351,9 @@ eval_location(env_t *env, location_t *dest, e_location_t *expr) if (CHECK_TYPE(&m, TYPE::STRING) && CHECK_TYPE(&x, TYPE::INT) && CHECK_TYPE(&y, TYPE::INT)) { - int map_id = map_mapname2mapid(m.v.v_string); + map_local *map_id = map_mapname2mapid(m.v.v_string.c_str()); magic_clear_var(&m); - if (map_id < 0) + if (!map_id) return 1; dest->m = map_id; dest->x = x.v.v_int; @@ -1363,9 +1370,10 @@ eval_location(env_t *env, location_t *dest, e_location_t *expr) } static -area_t *eval_area(env_t *env, e_area_t *expr) +dumb_ptr<area_t> eval_area(dumb_ptr<env_t> env, e_area_t& expr_) { - area_t *area = (area_t *)malloc(sizeof(area_t)); + e_area_t *expr = &expr_; // temporary hack to reduce diff + auto area = dumb_ptr<area_t>::make(); area->ty = expr->ty; switch (expr->ty) @@ -1374,7 +1382,7 @@ area_t *eval_area(env_t *env, e_area_t *expr) area->size = 1; if (eval_location(env, &area->a.a_loc, &expr->a.a_loc)) { - free(area); + area.delete_(); return NULL; } else @@ -1385,7 +1393,7 @@ area_t *eval_area(env_t *env, e_area_t *expr) int i, fail = 0; for (i = 0; i < 2; i++) { - area->a.a_union[i] = eval_area(env, expr->a.a_union[i]); + area->a.a_union[i] = eval_area(env, *expr->a.a_union[i]); if (!area->a.a_union[i]) fail = 1; } @@ -1397,7 +1405,7 @@ area_t *eval_area(env_t *env, e_area_t *expr) if (area->a.a_union[i]) free_area(area->a.a_union[i]); } - free(area); + area.delete_(); return NULL; } area->size = area->a.a_union[0]->size + area->a.a_union[1]->size; @@ -1425,7 +1433,7 @@ area_t *eval_area(env_t *env, e_area_t *expr) } else { - free(area); + area.delete_(); magic_clear_var(&width); magic_clear_var(&height); return NULL; @@ -1458,7 +1466,7 @@ area_t *eval_area(env_t *env, e_area_t *expr) } else { - free(area); + area.delete_(); magic_clear_var(&width); magic_clear_var(&depth); magic_clear_var(&dir); @@ -1469,7 +1477,7 @@ area_t *eval_area(env_t *env, e_area_t *expr) default: FPRINTF(stderr, "INTERNAL ERROR: Unknown area type %d\n", area->ty); - free(area); + area.delete_(); return NULL; } } @@ -1514,13 +1522,13 @@ int magic_signature_check(const char *opname, const char *funname, const char *s if (ty == TYPE::ENTITY) { /* Dereference entities in preparation for calling function */ - arg->v.v_entity = map_id2bl(arg->v.v_int).operator->(); + arg->v.v_entity = map_id2bl(arg->v.v_int); if (!arg->v.v_entity) ty = arg->ty = TYPE::FAIL; } else if (ty == TYPE::INVOCATION) { - arg->v.v_invocation = map_id2bl(arg->v.v_int)->as_spell().operator->(); + arg->v.v_invocation = map_id2bl(arg->v.v_int)->as_spell(); if (!arg->v.v_entity) ty = arg->ty = TYPE::FAIL; } @@ -1584,11 +1592,8 @@ int magic_signature_check(const char *opname, const char *funname, const char *s return 0; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -void magic_eval(env_t *env, val_t *dest, expr_t *expr) +void magic_eval(dumb_ptr<env_t> env, val_t *dest, dumb_ptr<expr_t> expr) { -#pragma GCC diagnostic pop switch (expr->ty) { case EXPR::VAL: @@ -1603,7 +1608,7 @@ void magic_eval(env_t *env, val_t *dest, expr_t *expr) break; case EXPR::AREA: - if ((dest->v.v_area = eval_area(env, &expr->e.e_area))) + if ((dest->v.v_area = eval_area(env, expr->e.e_area))) dest->ty = TYPE::AREA; else dest->ty = TYPE::FAIL; @@ -1619,8 +1624,8 @@ void magic_eval(env_t *env, val_t *dest, expr_t *expr) for (i = 0; i < args_nr; ++i) magic_eval(env, &arguments[i], expr->e.e_funapp.args[i]); if (magic_signature_check("function", f->name, f->signature, args_nr, arguments, - expr->e.e_funapp.line_nr, expr->e.e_funapp.column) - || f->fun(env, args_nr, dest, arguments)) + expr->e.e_funapp.line_nr, expr->e.e_funapp.column) + || f->fun(env, dest, const_array<val_t>(arguments, args_nr))) dest->ty = TYPE::FAIL; else { @@ -1645,7 +1650,7 @@ void magic_eval(env_t *env, val_t *dest, expr_t *expr) case EXPR::ID: { - val_t v = VAR(expr->e.e_id); + val_t v = env->VAR(expr->e.e_id); magic_copy_var(dest, &v); break; } @@ -1664,11 +1669,7 @@ void magic_eval(env_t *env, val_t *dest, expr_t *expr) dest->ty = TYPE::UNDEF; else { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" - env_t *env = t->env; -#pragma GCC diagnostic pop - val_t val = VAR(id); + val_t val = t->env->VAR(id); magic_copy_var(dest, &val); } } @@ -1676,7 +1677,7 @@ void magic_eval(env_t *env, val_t *dest, expr_t *expr) { FPRINTF(stderr, "[magic] Attempt to access field %s on non-spell\n", - env->base_env->var_name[id]); + env->base_env->varv[id].name); dest->ty = TYPE::FAIL; } break; @@ -1690,7 +1691,7 @@ void magic_eval(env_t *env, val_t *dest, expr_t *expr) } } -int magic_eval_int(env_t *env, expr_t *expr) +int magic_eval_int(dumb_ptr<env_t> env, dumb_ptr<expr_t> expr) { val_t result; magic_eval(env, &result, expr); @@ -1703,22 +1704,22 @@ int magic_eval_int(env_t *env, expr_t *expr) return result.v.v_int; } -char *magic_eval_str(env_t *env, expr_t *expr) +std::string magic_eval_str(dumb_ptr<env_t> env, dumb_ptr<expr_t> expr) { val_t result; magic_eval(env, &result, expr); if (result.ty == TYPE::FAIL || result.ty == TYPE::UNDEF) - return strdup("?"); + return "?"; stringify(&result, 0); - return result.v.v_string; + return result.v.v_string.str(); } -expr_t *magic_new_expr(EXPR ty) +dumb_ptr<expr_t> magic_new_expr(EXPR ty) { - expr_t *expr = (expr_t *) malloc(sizeof(expr_t)); + auto expr = dumb_ptr<expr_t>::make(); expr->ty = ty; return expr; } diff --git a/src/map/magic-expr.hpp b/src/map/magic-expr.hpp index 419c833..7f3e1e1 100644 --- a/src/map/magic-expr.hpp +++ b/src/map/magic-expr.hpp @@ -21,14 +21,14 @@ typedef struct fun const char *name; const char *signature; char ret_ty; - int(*fun)(env_t *env, int args_nr, val_t *result, val_t *args); + int (*fun)(dumb_ptr<env_t> env, val_t *result, const_array<val_t> arga); } fun_t; typedef struct op { const char *name; const char *signature; - int(*op)(env_t *env, int args_nr, val_t *args); + int (*op)(dumb_ptr<env_t> env, const_array<val_t> arga); } op_t; /** @@ -36,40 +36,40 @@ typedef struct op * @param name The name to look up * @return A function of that name, or NULL, and a function index */ -fun_t *magic_get_fun(const char *name, int *index); +fun_t *magic_get_fun(const std::string& name, int *index); /** * Retrieves an operation by name * @param name The name to look up * @return An operation of that name, or NULL, and a function index */ -op_t *magic_get_op(char *name, int *index); +op_t *magic_get_op(const std::string& name, int *index); /** * Evaluates an expression and stores the result in `dest' */ -void magic_eval(env_t *env, val_t *dest, expr_t *expr); +void magic_eval(dumb_ptr<env_t> env, val_t *dest, dumb_ptr<expr_t> expr); /** * Evaluates an expression and coerces the result into an integer */ -int magic_eval_int(env_t *env, expr_t *expr); +int magic_eval_int(dumb_ptr<env_t> env, dumb_ptr<expr_t> expr); /** * Evaluates an expression and coerces the result into a string */ -char *magic_eval_str(env_t *env, expr_t *expr); +std::string magic_eval_str(dumb_ptr<env_t> env, dumb_ptr<expr_t> expr); -expr_t *magic_new_expr(EXPR ty); +dumb_ptr<expr_t> magic_new_expr(EXPR ty); void magic_clear_var(val_t *v); void magic_copy_var(val_t *dest, val_t *src); -void magic_random_location(location_t *dest, area_t *area); +void magic_random_location(location_t *dest, dumb_ptr<area_t> area); // ret -1: not a string, ret 1: no such item, ret 0: OK -int magic_find_item(val_t *args, int index, struct item *item, int *stackable); +int magic_find_item(const_array<val_t> args, int index, struct item *item, int *stackable); #define GET_ARG_ITEM(index, dest, stackable) \ switch (magic_find_item(args, index, &dest, &stackable)) \ @@ -79,6 +79,6 @@ int magic_find_item(val_t *args, int index, struct item *item, int *stackable); default: break; \ } -int magic_location_in_area(int m, int x, int y, area_t *area); +int magic_location_in_area(map_local *m, int x, int y, dumb_ptr<area_t> area); #endif // MAGIC_EXPR_HPP diff --git a/src/map/magic-interpreter-aux.hpp b/src/map/magic-interpreter-aux.hpp index 4bb0a82..2ff597f 100644 --- a/src/map/magic-interpreter-aux.hpp +++ b/src/map/magic-interpreter-aux.hpp @@ -9,10 +9,4 @@ bool CHECK_TYPE(T *v, TYPE t) return v->ty == t; } -// FIXME: macro capture! -#define VAR(i) \ - ((!env->vars || env->vars[i].ty == TYPE::UNDEF) \ - ? env->base_env->vars[i] \ - : env->vars[i]) - #endif // MAGIC_INTERPRETER_AUX_HPP diff --git a/src/map/magic-interpreter-base.cpp b/src/map/magic-interpreter-base.cpp index 775e7e4..e6c1f37 100644 --- a/src/map/magic-interpreter-base.cpp +++ b/src/map/magic-interpreter-base.cpp @@ -17,6 +17,7 @@ void set_int_p(val_t *v, int i, TYPE t) v->v.v_int = i; } +#warning "This code should die" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-macros" @@ -26,7 +27,7 @@ void set_int_p(val_t *v, int i, TYPE t) #define SETTER(tty, dyn_ty, field) (val_t *v, tty x) { v->ty = dyn_ty; v->v.field = x; } static -void set_string SETTER(char *, TYPE::STRING, v_string) +void set_string SETTER(dumb_string, TYPE::STRING, v_string) static void set_entity(val_t *v, dumb_ptr<block_list> e) @@ -43,9 +44,9 @@ void set_invocation(val_t *v, dumb_ptr<invocation> i) } static -void set_spell SETTER(spell_t *, TYPE::SPELL, v_spell) +void set_spell SETTER(dumb_ptr<spell_t>, TYPE::SPELL, v_spell) -#define setenv(f, v, x) f(&(env->vars[v]), x) +#define setenv(f, v, x) f(&(env->varu[v]), x) #define set_env_int(v, x) setenv(set_int, v, x) #define set_env_dir(v, x) setenv(set_dir, v, x) @@ -61,100 +62,45 @@ void set_spell SETTER(spell_t *, TYPE::SPELL, v_spell) magic_conf_t magic_conf; /* Global magic conf */ env_t magic_default_env = { &magic_conf, NULL }; -static -int spells_sorted = 0; - -const char *magic_find_invocation(const char *spellname) +const char *magic_find_invocation(const std::string& spellname) { - int i; - - for (i = 0; i < abs(magic_conf.spells_nr); i++) - if (!strcmp(magic_conf.spells[i]->name, spellname)) - return magic_conf.spells[i]->invocation; + auto it = magic_conf.spells_by_name.find(spellname); + if (it != magic_conf.spells_by_name.end()) + return it->second->invocation.c_str(); return NULL; } -static -int spell_compare(const void *lhs, const void *rhs) -{ - return strcmp((*((const spell_t *const*) lhs))->invocation, - (*((const spell_t *const*) rhs))->invocation); -} - -spell_t *magic_find_spell(char *invocation) +dumb_ptr<spell_t> magic_find_spell(const std::string& invocation) { - spell_t key; - spell_t *keyp = &key; - spell_t **retval; + auto it = magic_conf.spells_by_invocation.find(invocation); + if (it != magic_conf.spells_by_invocation.end()) + return it->second; - if (!spells_sorted) - { - qsort(magic_conf.spells, magic_conf.spells_nr, sizeof(spell_t *), - spell_compare); - spells_sorted = 1; - } - - key.invocation = invocation; - - retval = - ((spell_t **) - bsearch(&keyp, magic_conf.spells, magic_conf.spells_nr, - sizeof(spell_t *), spell_compare)); - - if (!retval) - return NULL; - else - return *retval; + return NULL; } /* -------------------------------------------------------------------------------- */ /* Spell anchors */ /* -------------------------------------------------------------------------------- */ -static -int compare_teleport_anchor(const void *lhs, const void *rhs) -{ - return strcmp((*((const teleport_anchor_t *const*) lhs))->invocation, - (*((const teleport_anchor_t *const*) rhs))->invocation); -} - -const char *magic_find_anchor_invocation(const char *anchor_name) +const char *magic_find_anchor_invocation(const std::string& anchor_name) { - int i; + auto it = magic_conf.anchors_by_name.find(anchor_name); - for (i = 0; i < abs(magic_conf.anchors_nr); i++) - if (!strcmp(magic_conf.anchors[i]->name, anchor_name)) - return magic_conf.anchors[i]->invocation; + if (it != magic_conf.anchors_by_name.end()) + return it->second->invocation.c_str(); return NULL; } -teleport_anchor_t *magic_find_anchor(char *name) +dumb_ptr<teleport_anchor_t> magic_find_anchor(const std::string& name) { - teleport_anchor_t key; - teleport_anchor_t *keyp = &key; - teleport_anchor_t **retval; - - if (magic_conf.anchors_nr > 0) - { /* unsorted */ - qsort(magic_conf.anchors, magic_conf.anchors_nr, - sizeof(teleport_anchor_t *), compare_teleport_anchor); - magic_conf.anchors_nr = -magic_conf.anchors_nr; - } - - key.invocation = name; - - retval = (teleport_anchor_t **) bsearch(&keyp, - magic_conf.anchors, - -magic_conf.anchors_nr, - sizeof(teleport_anchor_t *), - compare_teleport_anchor); + auto it = magic_conf.anchors_by_invocation.find(name); + if (it != magic_conf.anchors_by_invocation.end()) + return it->second; - if (!retval) - return NULL; - else - return *retval; + return NULL; } /* -------------------------------------------------------------------------------- */ @@ -162,63 +108,59 @@ teleport_anchor_t *magic_find_anchor(char *name) /* -------------------------------------------------------------------------------- */ static -env_t *alloc_env(magic_conf_t *conf) +dumb_ptr<env_t> alloc_env(magic_conf_t *conf) { - env_t *env; - CREATE(env, env_t, 1); - CREATE(env->vars, val_t, conf->vars_nr); + auto env = dumb_ptr<env_t>::make(); + env->varu = make_unique<val_t[]>(conf->varv.size()); env->base_env = conf; return env; } static -env_t *clone_env(env_t *src) +dumb_ptr<env_t> clone_env(dumb_ptr<env_t> src) { - env_t *retval = alloc_env(src->base_env); - int i; + dumb_ptr<env_t> retval = alloc_env(src->base_env); - for (i = 0; i < src->base_env->vars_nr; i++) - magic_copy_var(&retval->vars[i], &src->vars[i]); + for (int i = 0; i < src->base_env->varv.size(); i++) + magic_copy_var(&retval->varu[i], &src->varu[i]); return retval; } -void magic_free_env(env_t *env) +void magic_free_env(dumb_ptr<env_t> env) { - int i; - for (i = 0; i < env->base_env->vars_nr; i++) - magic_clear_var(&env->vars[i]); - free(env); + for (int i = 0; i < env->base_env->varv.size(); i++) + magic_clear_var(&env->varu[i]); + // handled by std::unique_ptr now. Was a memory leak before. + // delete[] env->vars; + env.delete_(); } -env_t *spell_create_env(magic_conf_t *conf, spell_t *spell, - dumb_ptr<map_session_data> caster, int spellpower, char *param) +dumb_ptr<env_t> spell_create_env(magic_conf_t *conf, dumb_ptr<spell_t> spell, + dumb_ptr<map_session_data> caster, int spellpower, const_string param) { - env_t *env = alloc_env(conf); + dumb_ptr<env_t> env = alloc_env(conf); switch (spell->spellarg_ty) { case SPELLARG::STRING: - set_env_string(spell->arg, param); + set_env_string(spell->arg, dumb_string::copyc(param)); break; case SPELLARG::PC: { - dumb_ptr<map_session_data> subject = map_nick2sd(param); + dumb_ptr<map_session_data> subject = map_nick2sd(std::string(param.begin(), param.end()).c_str()); if (!subject) subject = caster; set_env_entity(spell->arg, subject); - free(param); break; } case SPELLARG::NONE: - free(param); break; default: - free(param); FPRINTF(stderr, "Unexpected spellarg type %d\n", spell->spellarg_ty); } @@ -231,24 +173,23 @@ env_t *spell_create_env(magic_conf_t *conf, spell_t *spell, } static -void free_components(component_t ** component_holder) +void free_components(dumb_ptr<component_t> *component_holder) { if (*component_holder == NULL) return; free_components(&(*component_holder)->next); - free(*component_holder); + (*component_holder).delete_(); *component_holder = NULL; } -void magic_add_component(component_t ** component_holder, int id, int count) +void magic_add_component(dumb_ptr<component_t> *component_holder, int id, int count) { if (count <= 0) return; if (*component_holder == NULL) { - component_t *component = - (component_t *) malloc(sizeof(component_t)); + auto component = dumb_ptr<component_t>::make(); component->next = NULL; component->item_id = id; component->count = count; @@ -256,7 +197,7 @@ void magic_add_component(component_t ** component_holder, int id, int count) } else { - component_t *component = *component_holder; + dumb_ptr<component_t> component = *component_holder; if (component->item_id == id) { component->count += count; @@ -269,30 +210,28 @@ void magic_add_component(component_t ** component_holder, int id, int count) } static -void copy_components(component_t ** component_holder, component_t *component) +void copy_components(dumb_ptr<component_t> *component_holder, dumb_ptr<component_t> component) { if (component == NULL) return; - magic_add_component(component_holder, component->item_id, - component->count); + magic_add_component(component_holder, component->item_id, component->count); copy_components(component_holder, component->next); } typedef struct spellguard_check { - component_t *catalysts, *components; + dumb_ptr<component_t> catalysts, components; int mana; interval_t casttime; } spellguard_check_t; static -int check_prerequisites(dumb_ptr<map_session_data> caster, component_t *component) +int check_prerequisites(dumb_ptr<map_session_data> caster, dumb_ptr<component_t> component) { while (component) { - if (pc_count_all_items(caster, component->item_id) - < component->count) + if (pc_count_all_items(caster, component->item_id) < component->count) return 0; /* insufficient */ component = component->next; @@ -302,7 +241,7 @@ int check_prerequisites(dumb_ptr<map_session_data> caster, component_t *componen } static -void consume_components(dumb_ptr<map_session_data> caster, component_t *component) +void consume_components(dumb_ptr<map_session_data> caster, dumb_ptr<component_t> component) { while (component) { @@ -313,7 +252,7 @@ void consume_components(dumb_ptr<map_session_data> caster, component_t *componen static int spellguard_can_satisfy(spellguard_check_t *check, dumb_ptr<map_session_data> caster, - env_t *env, int *near_miss) + dumb_ptr<env_t> env, int *near_miss) { tick_t tick = gettick(); @@ -330,8 +269,8 @@ int spellguard_can_satisfy(spellguard_check_t *check, dumb_ptr<map_session_data> { interval_t casttime = check->casttime; - if (VAR(VAR_MIN_CASTTIME).ty == TYPE::INT) - casttime = max(casttime, static_cast<interval_t>(VAR(VAR_MIN_CASTTIME).v.v_int)); + if (env->VAR(VAR_MIN_CASTTIME).ty == TYPE::INT) + casttime = max(casttime, static_cast<interval_t>(env->VAR(VAR_MIN_CASTTIME).v.v_int)); caster->cast_tick = tick + casttime; /* Make sure not to cast too frequently */ @@ -344,9 +283,10 @@ int spellguard_can_satisfy(spellguard_check_t *check, dumb_ptr<map_session_data> static effect_set_t *spellguard_check_sub(spellguard_check_t *check, - spellguard_t *guard, - dumb_ptr<map_session_data> caster, env_t *env, - int *near_miss) + dumb_ptr<spellguard_t> guard, + dumb_ptr<map_session_data> caster, + dumb_ptr<env_t> env, + int *near_miss) { if (guard == NULL) return NULL; @@ -413,9 +353,9 @@ effect_set_t *spellguard_check_sub(spellguard_check_t *check, } static -effect_set_t *check_spellguard(spellguard_t *guard, - dumb_ptr<map_session_data> caster, env_t *env, - int *near_miss) +effect_set_t *check_spellguard(dumb_ptr<spellguard_t> guard, + dumb_ptr<map_session_data> caster, dumb_ptr<env_t> env, + int *near_miss) { spellguard_check_t check; effect_set_t *retval; @@ -436,18 +376,16 @@ effect_set_t *check_spellguard(spellguard_t *guard, /* Public API */ /* -------------------------------------------------------------------------------- */ -effect_set_t *spell_trigger(spell_t *spell, dumb_ptr<map_session_data> caster, - env_t *env, int *near_miss) +effect_set_t *spell_trigger(dumb_ptr<spell_t> spell, dumb_ptr<map_session_data> caster, + dumb_ptr<env_t> env, int *near_miss) { - int i; - spellguard_t *guard = spell->spellguard; + dumb_ptr<spellguard_t> guard = spell->spellguard; if (near_miss) *near_miss = 0; - for (i = 0; i < spell->letdefs_nr; i++) - magic_eval(env, - &env->vars[spell->letdefs[i].id], spell->letdefs[i].expr); + for (letdef_t& ld : spell->letdefv) + magic_eval(env, &env->varu[ld.id], ld.expr); return check_spellguard(guard, caster, env, near_miss); } @@ -455,11 +393,11 @@ effect_set_t *spell_trigger(spell_t *spell, dumb_ptr<map_session_data> caster, static void spell_set_location(dumb_ptr<invocation> invocation, dumb_ptr<block_list> entity) { - magic_clear_var(&invocation->env->vars[VAR_LOCATION]); - invocation->env->vars[VAR_LOCATION].ty = TYPE::LOCATION; - invocation->env->vars[VAR_LOCATION].v.v_location.m = entity->bl_m; - invocation->env->vars[VAR_LOCATION].v.v_location.x = entity->bl_x; - invocation->env->vars[VAR_LOCATION].v.v_location.y = entity->bl_y; + magic_clear_var(&invocation->env->varu[VAR_LOCATION]); + invocation->env->varu[VAR_LOCATION].ty = TYPE::LOCATION; + invocation->env->varu[VAR_LOCATION].v.v_location.m = entity->bl_m; + invocation->env->varu[VAR_LOCATION].v.v_location.x = entity->bl_x; + invocation->env->varu[VAR_LOCATION].v.v_location.y = entity->bl_y; } void spell_update_location(dumb_ptr<invocation> invocation) @@ -477,7 +415,7 @@ void spell_update_location(dumb_ptr<invocation> invocation) } } -dumb_ptr<invocation> spell_instantiate(effect_set_t *effect_set, env_t *env) +dumb_ptr<invocation> spell_instantiate(effect_set_t *effect_set, dumb_ptr<env_t> env) { dumb_ptr<invocation> retval; retval.new_(); @@ -485,8 +423,8 @@ dumb_ptr<invocation> spell_instantiate(effect_set_t *effect_set, env_t *env) retval->env = env; - retval->caster = VAR(VAR_CASTER).v.v_int; - retval->spell = VAR(VAR_SPELL).v.v_spell; + retval->caster = env->VAR(VAR_CASTER).v.v_int; + retval->spell = env->VAR(VAR_SPELL).v.v_spell; retval->stack_size = 0; retval->current_effect = effect_set->effect; retval->trigger_effect = effect_set->at_trigger; @@ -516,7 +454,7 @@ dumb_ptr<invocation> spell_clone_effect(dumb_ptr<invocation> base) retval->next_invocation = NULL; retval->flags = INVOCATION_FLAG::ZERO; - env_t *env = retval->env = clone_env(base->env); + dumb_ptr<env_t> env = retval->env = clone_env(base->env); retval->spell = base->spell; retval->caster = base->caster; retval->subject = 0; @@ -528,8 +466,7 @@ dumb_ptr<invocation> spell_clone_effect(dumb_ptr<invocation> base) retval->current_effect = base->trigger_effect; retval->trigger_effect = base->trigger_effect; retval->end_effect = NULL; - retval->status_change_refs_nr = 0; - retval->status_change_refs = NULL; + // retval->status_change_refs = NULL; retval->bl_id = 0; retval->bl_prev = NULL; @@ -568,7 +505,7 @@ void spell_bind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invocat invocation->subject = subject->bl_id; } - spell_set_location(invocation, (dumb_ptr<block_list> ) subject); + spell_set_location(invocation, subject); } int spell_unbind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invocation_) diff --git a/src/map/magic-interpreter-lexer.lpp b/src/map/magic-interpreter-lexer.lpp index f593d4a..c0a554b 100644 --- a/src/map/magic-interpreter-lexer.lpp +++ b/src/map/magic-interpreter-lexer.lpp @@ -102,24 +102,25 @@ "WAIT" {FIXLOC; return SLEEP;} \{([^\}]|\\.)*\} { - char *string = strdup(yytext); - magic_frontend_lval.s = string; + magic_frontend_lval.s = dumb_string::copy(yytext); FIXLOC; return SCRIPT_DATA; } \"([^\"]|\\.)*\" { - char *string = strdup(yytext + 1); - char *src = string; - char *dst = string; + dumb_string string = dumb_string::copy(yytext + 1); + const char *src = string.c_str(); + char *dst = &string[0]; while (*src && *src != '"') - if (*src == '\\') { - *dst++ = src[1]; - src += 2; + if (*src == '\\') + { + *dst++ = src[1]; + src += 2; + } + else + *dst++ = *src++; } - else - *dst++ = *src++; *dst = '\0'; /* terminate */ magic_frontend_lval.s = string; FIXLOC; @@ -139,7 +140,7 @@ } [a-zA-Z][-_a-zA-Z0-9]* { - magic_frontend_lval.s = strdup(yytext); + magic_frontend_lval.s = dumb_string::copy(yytext); FIXLOC; return ID; } diff --git a/src/map/magic-interpreter-parser.ypp b/src/map/magic-interpreter-parser.ypp index 2baa854..2cec1f2 100644 --- a/src/map/magic-interpreter-parser.ypp +++ b/src/map/magic-interpreter-parser.ypp @@ -7,8 +7,10 @@ { #include "magic-interpreter-parser.hpp" +#include <cassert> #include <cstdarg> // exception to "no va_list" rule, even after cxxstdio +#include "../common/const_array.hpp" #include "../common/cxxstdio.hpp" #include "itemdb.hpp" @@ -17,22 +19,26 @@ // I still don't get why this is necessary. #define YYLEX_PARAM 0, 0 +#pragma GCC diagnostic warning "-Wall" +#pragma GCC diagnostic warning "-Wextra" +#pragma GCC diagnostic warning "-Wformat" + static -int intern_id(const char *id_name); +size_t intern_id(const_string id_name); static -expr_t *fun_expr(const char *name, int args_nr, expr_t **args, int line, int column); +dumb_ptr<expr_t> fun_expr(const std::string& name, const_array<dumb_ptr<expr_t>> argv, int line, int column); static -expr_t *dot_expr(expr_t *lhs, int id); +dumb_ptr<expr_t> dot_expr(dumb_ptr<expr_t> lhs, int id); static -void BIN_EXPR(expr_t *& x, const char *name, expr_t *arg1, expr_t *arg2, int line, int column) +void BIN_EXPR(dumb_ptr<expr_t> & x, const std::string& name, dumb_ptr<expr_t> arg1, dumb_ptr<expr_t> arg2, int line, int column) { - expr_t *e[2]; + dumb_ptr<expr_t> e[2]; e[0] = arg1; e[1] = arg2; - x = fun_expr(name, 2, e, line, column); + x = fun_expr(name, const_array<dumb_ptr<expr_t>>(e, 2), line, column); } static @@ -41,47 +47,47 @@ int failed_flag = 0; static void magic_frontend_error(const char *msg); -static +static __attribute__((format(printf, 3, 4))) void fail(int line, int column, const char *fmt, ...); static -spell_t *new_spell(spellguard_t *guard); +dumb_ptr<spell_t> new_spell(dumb_ptr<spellguard_t> guard); static -spellguard_t *spellguard_implication(spellguard_t *a, spellguard_t *b); +dumb_ptr<spellguard_t> spellguard_implication(dumb_ptr<spellguard_t> a, dumb_ptr<spellguard_t> b); static -spellguard_t *new_spellguard(SPELLGUARD ty); +dumb_ptr<spellguard_t> new_spellguard(SPELLGUARD ty); static -effect_t *new_effect(EFFECT ty); +dumb_ptr<effect_t> new_effect(EFFECT ty); static -effect_t *set_effect_continuation(effect_t *src, effect_t *continuation); +dumb_ptr<effect_t> set_effect_continuation(dumb_ptr<effect_t> src, dumb_ptr<effect_t> continuation); static -void add_spell(spell_t *spell, int line_nr); +void add_spell(dumb_ptr<spell_t> spell, int line_nr); static -void add_teleport_anchor(teleport_anchor_t *anchor, int line_nr); +void add_teleport_anchor(dumb_ptr<teleport_anchor_t> anchor, int line_nr); static -effect_t *op_effect(char *name, int args_nr, expr_t **args, int line, int column); +dumb_ptr<effect_t> op_effect(const std::string& name, const_array<dumb_ptr<expr_t>> argv, int line, int column); // in magic-interpreter-lexer.cpp int magic_frontend_lex(YYSTYPE *, YYLTYPE *); static -void install_proc(proc_t *proc); +void install_proc(dumb_ptr<proc_t> proc); static -effect_t *call_proc(char *name, int args_nr, expr_t **args, int line_nr, int column); +dumb_ptr<effect_t> call_proc(const_string name, dumb_ptr<std::vector<dumb_ptr<expr_t>>> argvp, int line_nr, int column); static -void bind_constant(char *name, val_t *val, int line_nr); +void bind_constant(const std::string& name, val_t *val, int line_nr); static -val_t *find_constant(char *name); +val_t *find_constant(const std::string& name); } // %code @@ -95,23 +101,29 @@ val_t *find_constant(char *name); SPELL_FLAG spell_flags; SPELLARG spell_arg; FOREACH_FILTER foreach_filter; - char *s; + dumb_string s; int op; - magic_conf_t *magic_conf; + // magic_conf_t *magic_conf; val_t value; - expr_t *expr; + dumb_ptr<expr_t> expr; e_location_t location; e_area_t area; args_rec_t arg_list; - struct { int letdefs_nr; letdef_t *letdefs; } letdefs; - spell_t *spell; + dumb_ptr<std::vector<letdef_t>> letdefvp; + dumb_ptr<spell_t> spell; struct { int id; SPELLARG ty; } spellarg_def; letdef_t vardef; - spellguard_t *spellguard; - component_t *components; - struct {int id, count; } component; - effect_t *effect; - proc_t *proc; + dumb_ptr<spellguard_t> spellguard; + dumb_ptr<component_t> components; + struct { int id, count; } component; + dumb_ptr<effect_t> effect; + dumb_ptr<proc_t> proc; + + // evil hackery + YYSTYPE() { memset(this, '\0', sizeof(*this)); } + ~YYSTYPE() = default; + YYSTYPE(const YYSTYPE& rhs) = default; + YYSTYPE& operator = (const YYSTYPE& rhs) = default; } // %union %expect 7 @@ -193,7 +205,7 @@ val_t *find_constant(char *name); %type <area> area %type <arg_list> arg_list %type <arg_list> arg_list_ne -%type <letdefs> defs +%type <letdefvp> defs %type <spell> spelldef %type <spellarg_def> argopt %type <vardef> def @@ -257,7 +269,7 @@ proc_formals_list : /* empty */ { - CREATE($$, proc_t, 1); + $$ = dumb_ptr<proc_t>::make(); } | proc_formals_list_ne @@ -272,17 +284,16 @@ proc_formals_list_ne : ID { - CREATE($$, proc_t, 1); - $$->args_nr = 1; - $$->args = (int*)malloc(sizeof(int)); - $$->args[0] = intern_id($1); + $$ = dumb_ptr<proc_t>::make(); + $$->argv.push_back(intern_id($1)); + $1.delete_(); } | proc_formals_list_ne ',' ID { $$ = $1; - $$->args = (int *)realloc($$->args, sizeof(int) * (1 + $$->args_nr)); - $$->args[$$->args_nr++] = intern_id($3); + $$->argv.push_back(intern_id($3)); + $3.delete_(); } ; @@ -292,56 +303,59 @@ spellconf_option : ID '=' expr { - int var_id; - if (find_constant($1)) + if (find_constant($1.str())) { - fail(@1.first_line, 0, "Attempt to redefine constant `%s' as global\n", $1); - free($1); + fail(@1.first_line, 0, "Attempt to redefine constant `%s' as global\n", $1.c_str()); } else { - var_id = intern_id($1); - magic_eval(&magic_default_env, &magic_conf.vars[var_id], $3); + int var_id = intern_id($1); + magic_eval(dumb_ptr<env_t>(&magic_default_env), &magic_conf.varv[var_id].val, $3); } + $1.delete_(); } | CONST ID '=' expr { val_t var; - magic_eval(&magic_default_env, &var, $4); - bind_constant($2, &var, @1.first_line); + magic_eval(dumb_ptr<env_t>(&magic_default_env), &var, $4); + bind_constant($2.str(), &var, @1.first_line); + $2.delete_(); } | TELEPORT_ANCHOR ID ':' expr '=' expr { - teleport_anchor_t *anchor; - CREATE(anchor, teleport_anchor_t, 1); - anchor->name = $2; - anchor->invocation = magic_eval_str(&magic_default_env, $4); - anchor->location = $6; + auto anchor = dumb_ptr<teleport_anchor_t>::make(); + anchor->name = $2.str(); + $2.delete_(); + anchor->invocation = magic_eval_str(dumb_ptr<env_t>(&magic_default_env), $4); + anchor->location = $6; - if (!failed_flag) - add_teleport_anchor(anchor, @1.first_line); - else - free(anchor); - failed_flag = 0; + if (!failed_flag) + add_teleport_anchor(anchor, @1.first_line); + else + anchor.delete_(); + failed_flag = 0; } | PROCEDURE ID '(' proc_formals_list ')' '=' effect_list { - proc_t *proc = $4; - proc->name = $2; - proc->body = $7; - if (!failed_flag) - install_proc(proc); - failed_flag = 0; + dumb_ptr<proc_t> proc = $4; + proc->name = $2.str(); + $2.delete_(); + proc->body = $7; + if (!failed_flag) + install_proc(proc); + proc.delete_(); + failed_flag = 0; } | spell_flags SPELL ID argopt ':' expr '=' spelldef { - spell_t *spell = $8; - spell->name = $3; - spell->invocation = magic_eval_str(&magic_default_env, $6); + dumb_ptr<spell_t> spell = $8; + spell->name = $3.str(); + $3.delete_(); + spell->invocation = magic_eval_str(dumb_ptr<env_t>(&magic_default_env), $6); spell->arg = $4.id; spell->spellarg_ty = $4.ty; spell->flags = $1; @@ -394,6 +408,7 @@ argopt | '(' ID ':' arg_ty ')' { $$.id = intern_id($2); + $2.delete_(); $$.ty = $4; } @@ -448,8 +463,8 @@ expr | ID { - val_t *val; - if ((val = find_constant($1))) + val_t *val = find_constant($1.str()); + if (val) { $$ = magic_new_expr(EXPR::VAL); $$->e.e_val = *val; @@ -459,6 +474,7 @@ expr $$ = magic_new_expr(EXPR::ID); $$->e.e_id = intern_id($1); } + $1.delete_(); } | area @@ -560,15 +576,14 @@ expr | expr NEQ expr { BIN_EXPR($$, "=", $1, $3, @1.first_line, @1.first_column); - $$ = fun_expr("not", 1, &$$, @1.first_line, @1.first_column); + $$ = fun_expr("not", const_array<dumb_ptr<expr_t>>(&$$, 1), @1.first_line, @1.first_column); } | ID '(' arg_list ')' { - $$ = fun_expr($1, $3.args_nr, $3.args, @1.first_line, @1.first_column); - if ($3.args) - free($3.args); - free($1); + $$ = fun_expr($1.str(), *$3.argvp, @1.first_line, @1.first_column); + $3.argvp.delete_(); + $1.delete_(); // allocated from m-i-lexer.lpp } | '(' expr ')' @@ -579,6 +594,7 @@ expr | expr '.' ID { $$ = dot_expr($1, intern_id($3)); + $3.delete_(); } ; @@ -588,7 +604,7 @@ arg_list : /* empty */ { - $$.args_nr = 0; + $$.argvp.new_(); } | arg_list_ne @@ -603,15 +619,15 @@ arg_list_ne : expr { - CREATE($$.args, expr_t *, 1); - $$.args_nr = 1; - $$.args[0] = $1; + $$.argvp.new_(); + $$.argvp->push_back($1); } | arg_list_ne ',' expr { - RECREATE($$.args, expr_t *, 1 + $$.args_nr); - $$.args[$$.args_nr++] = $3; + // yikes! Fate is officially banned from ever touching my code again. + $$ = $1; + $$.argvp->push_back($3); } ; @@ -667,8 +683,8 @@ spelldef | LET defs IN spellbody_list { $$ = new_spell($4); - $$->letdefs_nr = $2.letdefs_nr; - $$->letdefs = $2.letdefs; + $$->letdefv = std::move(*$2); + $2.delete_(); $$->spellguard = $4; } @@ -679,16 +695,13 @@ defs : semicolons { - $$.letdefs_nr = 0; - CREATE($$.letdefs, letdef_t, 1); + $$.new_(); } | defs def semicolons { $$ = $1; - $$.letdefs_nr++; - RECREATE($$.letdefs, letdef_t, $$.letdefs_nr); - $$.letdefs[$1.letdefs_nr] = $2; + $$->push_back($2); } ; @@ -698,16 +711,16 @@ def : ID '=' expr { - if (find_constant($1)) + if (find_constant($1.str())) { - fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' as LET-bound variable.\n", $1); - free($1); + fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' as LET-bound variable.\n", $1.c_str()); } else { $$.id = intern_id($1); $$.expr = $3; } + $1.delete_(); } ; @@ -722,7 +735,7 @@ spellbody_list | spellbody '|' spellbody_list { - spellguard_t *sg = new_spellguard(SPELLGUARD::CHOICE); + dumb_ptr<spellguard_t> sg = new_spellguard(SPELLGUARD::CHOICE); sg->next = $1; sg->s.s_alt = $3; $$ = sg; @@ -745,7 +758,7 @@ spellbody | EFFECT_ effect_list maybe_trigger maybe_end { - spellguard_t *sg = new_spellguard(SPELLGUARD::EFFECT); + dumb_ptr<spellguard_t> sg = new_spellguard(SPELLGUARD::EFFECT); sg->s.s_effect.effect = $2; sg->s.s_effect.at_trigger = $3; sg->s.s_effect.at_end = $4; @@ -794,7 +807,7 @@ spellguard | spellguard OR spellguard { - spellguard_t *sg = new_spellguard(SPELLGUARD::CHOICE); + dumb_ptr<spellguard_t> sg = new_spellguard(SPELLGUARD::CHOICE); sg->next = $1; sg->s.s_alt = $3; $$ = sg; @@ -906,15 +919,15 @@ item_name : STRING { - struct item_data *item = itemdb_searchname($1); + struct item_data *item = itemdb_searchname($1.c_str()); if (!item) { - fail(@1.first_line, @1.first_column, "Unknown item `%s'\n", $1); + fail(@1.first_line, @1.first_column, "Unknown item `%s'\n", $1.c_str()); $$ = 0; } else $$ = item->nameid; - free($1); + $1.delete_(); } | INT @@ -989,10 +1002,9 @@ effect | ID '=' expr ';' { - if (find_constant($1)) + if (find_constant($1.str())) { - fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' in assignment.", $1); - free($1); + fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' in assignment.", $1.c_str()); } else { @@ -1000,12 +1012,14 @@ effect $$->e.e_assign.id = intern_id($1); $$->e.e_assign.expr = $3; } + $1.delete_(); } | FOREACH selection ID IN expr DO effect { $$ = new_effect(EFFECT::FOREACH); $$->e.e_foreach.id = intern_id($3); + $3.delete_(); $$->e.e_foreach.area = $5; $$->e.e_foreach.body = $7; $$->e.e_foreach.filter = $2; @@ -1015,6 +1029,7 @@ effect { $$ = new_effect(EFFECT::FOR); $$->e.e_for.id = intern_id($2); + $2.delete_(); $$->e.e_for.start = $4; $$->e.e_for.stop = $6; $$->e.e_for.body = $8; @@ -1044,23 +1059,23 @@ effect | ID '(' arg_list ')' ';' { - $$ = op_effect($1, $3.args_nr, $3.args, @1.first_line, @1.first_column); - free($1); + $$ = op_effect($1.str(), *$3.argvp, @1.first_line, @1.first_column); + $1.delete_(); } | SCRIPT_DATA { $$ = new_effect(EFFECT::SCRIPT); - $$->e.e_script = parse_script($1, @1.first_line); - free($1); + $$->e.e_script = dumb_ptr<const ScriptBuffer>(parse_script($1.c_str(), @1.first_line).release()); + $1.delete_(); if ($$->e.e_script == NULL) fail(@1.first_line, @1.first_column, "Failed to compile script\n"); } | CALL ID '(' arg_list ')' ';' { - $$ = call_proc($2, $4.args_nr, $4.args, @1.first_line, @1.first_column); - free($2); + $$ = call_proc($2, $4.argvp, @1.first_line, @1.first_column); + $2.delete_(); } ; @@ -1083,84 +1098,63 @@ effect_list %% -/* We do incremental realloc here to store our results. Since this happens only once - * during startup for a relatively manageable set of configs, it should be fine. */ - -static -int intern_id(const char *id_name) +size_t intern_id(const_string id_name_) { - int i; - for (i = 0; i < magic_conf.vars_nr; i++) - if (!strcmp(id_name, magic_conf.var_name[i])) - { - free((char*)id_name); + std::string id_name(id_name_.begin(), id_name_.end()); + size_t i; + for (i = 0; i < magic_conf.varv.size(); i++) + if (id_name == magic_conf.varv[i].name) return i; - } + // i = magic_conf.varv.size(); /* Must add new */ - i = magic_conf.vars_nr++; - RECREATE(magic_conf.var_name, const char *, magic_conf.vars_nr); - magic_conf.var_name[i] = id_name; - RECREATE(magic_conf.vars, val_t, magic_conf.vars_nr); - magic_conf.vars[i].ty = TYPE::UNDEF; + magic_conf_t::mcvar new_var {}; + new_var.name = id_name; + new_var.val.ty = TYPE::UNDEF; + magic_conf.varv.push_back(new_var); return i; } -static -void add_spell(spell_t *spell, int line_nr) +void add_spell(dumb_ptr<spell_t> spell, int line_nr) { - int index = magic_conf.spells_nr; - int i; - - for (i = 0; i < index; i++) + auto pair1 = magic_conf.spells_by_name.insert({spell->name, spell}); + if (!pair1.second) { - if (!strcmp(magic_conf.spells[i]->name, spell->name)) - { - fail(line_nr, 0, "Attempt to redefine spell `%s'\n", spell->name); - return; - } - if (!strcmp(magic_conf.spells[i]->invocation, spell->invocation)) - { - fail(line_nr, 0, "Attempt to redefine spell invocation `%s' between spells `%s' and `%s'\n", - spell->invocation, magic_conf.spells[i]->name, spell->name); - return; - } + fail(line_nr, 0, "Attempt to redefine spell `%s'\n", spell->name.c_str()); + return; } - magic_conf.spells_nr++; - RECREATE(magic_conf.spells, spell_t *, magic_conf.spells_nr); - magic_conf.spells[index] = spell; + auto pair2 = magic_conf.spells_by_invocation.insert({spell->invocation, spell}); + if (!pair2.second) + { + fail(line_nr, 0, "Attempt to redefine spell invocation `%s' between spells `%s' and `%s'\n", + spell->invocation.c_str(), pair1.first->second->name.c_str(), spell->name.c_str()); + magic_conf.spells_by_name.erase(pair1.first); + return; + } } -static -void add_teleport_anchor(teleport_anchor_t *anchor, int line_nr) +void add_teleport_anchor(dumb_ptr<teleport_anchor_t> anchor, int line_nr) { - int index = magic_conf.anchors_nr; - int i; - - for (i = 0; i < index; i++) + auto pair1 = magic_conf.anchors_by_name.insert({anchor->name, anchor}); + if (!pair1.second) { - if (!strcmp(magic_conf.anchors[i]->name, anchor->name)) - { - fail(line_nr, 0, "Attempt to redefine teleport anchor `%s'\n", anchor->name); - return; - } - if (!strcmp(magic_conf.anchors[i]->invocation, anchor->invocation)) - { - fail(line_nr, 0, "Attempt to redefine anchor invocation `%s' between anchors `%s' and `%s'\n", - anchor->invocation, magic_conf.anchors[i]->name, anchor->name); - return; - } + fail(line_nr, 0, "Attempt to redefine teleport anchor `%s'\n", anchor->name.c_str()); + return; } - magic_conf.anchors_nr++; - RECREATE(magic_conf.anchors, teleport_anchor_t *, magic_conf.anchors_nr); - magic_conf.anchors[index] = anchor; + auto pair2 = magic_conf.anchors_by_invocation.insert({anchor->name, anchor}); + if (!pair2.second) + { + fail(line_nr, 0, "Attempt to redefine anchor invocation `%s' between anchors `%s' and `%s'\n", + anchor->invocation.c_str(), pair1.first->second->name.c_str(), anchor->name.c_str()); + magic_conf.anchors_by_name.erase(pair1.first); + return; + } } -static __attribute__((format(printf, 3, 4))) void fail(int line, int column, const char *fmt, ...) { va_list ap; @@ -1170,43 +1164,41 @@ void fail(int line, int column, const char *fmt, ...) failed_flag = 1; } -static -expr_t *dot_expr(expr_t *expr, int id) +dumb_ptr<expr_t> dot_expr(dumb_ptr<expr_t> expr, int id) { - expr_t *retval = magic_new_expr(EXPR::SPELLFIELD); + dumb_ptr<expr_t> retval = magic_new_expr(EXPR::SPELLFIELD); retval->e.e_field.id = id; retval->e.e_field.expr = expr; return retval; } -static -expr_t *fun_expr(const char *name, int args_nr, expr_t **args, int line, int column) +dumb_ptr<expr_t> fun_expr(const std::string& name, const_array<dumb_ptr<expr_t>> argv, int line, int column) { int id; - expr_t *expr; + dumb_ptr<expr_t> expr; fun_t *fun = magic_get_fun(name, &id); if (!fun) - fail(line, column, "Unknown function `%s'\n", name); - else if (strlen(fun->signature) != args_nr) + fail(line, column, "Unknown function `%s'\n", name.c_str()); + else if (strlen(fun->signature) != argv.size()) { - fail(line, column, "Incorrect number of arguments to function `%s': Expected %zu, found %d\n", name, strlen(fun->signature), args_nr); + fail(line, column, "Incorrect number of arguments to function `%s': Expected %zu, found %zu\n", + name.c_str(), strlen(fun->signature), argv.size()); fun = NULL; } if (fun) { - int i; - expr = magic_new_expr(EXPR::FUNAPP); expr->e.e_funapp.line_nr = line; expr->e.e_funapp.column = column; expr->e.e_funapp.id = id; - expr->e.e_funapp.args_nr = args_nr; - for (i = 0; i < args_nr; i++) - expr->e.e_funapp.args[i] = args[i]; + assert (argv.size() < MAX_ARGS); + expr->e.e_funapp.args_nr = argv.size(); + + std::copy(argv.begin(), argv.end(), expr->e.e_funapp.args); } else { @@ -1218,29 +1210,26 @@ expr_t *fun_expr(const char *name, int args_nr, expr_t **args, int line, int col return expr; } -static -spell_t *new_spell(spellguard_t *guard) +dumb_ptr<spell_t> new_spell(dumb_ptr<spellguard_t> guard) { static int spell_counter = 0; - spell_t *retval = (spell_t*)calloc(1, sizeof(spell_t)); - retval->index = ++spell_counter; + auto retval = dumb_ptr<spell_t>::make(); + retval->index_ = ++spell_counter; retval->spellguard = guard; return retval; } -static -spellguard_t *new_spellguard(SPELLGUARD ty) +dumb_ptr<spellguard_t> new_spellguard(SPELLGUARD ty) { - spellguard_t *retval = (spellguard_t *)calloc(1, sizeof(spellguard_t)); + dumb_ptr<spellguard_t> retval = dumb_ptr<spellguard_t>::make(); retval->ty = ty; return retval; } -static -spellguard_t *spellguard_implication(spellguard_t *a, spellguard_t *b) +dumb_ptr<spellguard_t> spellguard_implication(dumb_ptr<spellguard_t> a, dumb_ptr<spellguard_t> b) { - spellguard_t *retval = a; + dumb_ptr<spellguard_t> retval = a; if (a == b) { @@ -1269,18 +1258,16 @@ spellguard_t *spellguard_implication(spellguard_t *a, spellguard_t *b) return retval; } -static -effect_t *new_effect(EFFECT ty) +dumb_ptr<effect_t> new_effect(EFFECT ty) { - effect_t *effect = (effect_t *) calloc(1, sizeof(effect_t)); + auto effect = dumb_ptr<effect_t>::make(); effect->ty = ty; return effect; } -static -effect_t *set_effect_continuation(effect_t *src, effect_t *continuation) +dumb_ptr<effect_t> set_effect_continuation(dumb_ptr<effect_t> src, dumb_ptr<effect_t> continuation) { - effect_t *retval = src; + dumb_ptr<effect_t> retval = src; /* This function is completely analogous to `spellguard_implication' above; read the control flow implications above first before pondering it. */ if (src == continuation) @@ -1301,33 +1288,31 @@ effect_t *set_effect_continuation(effect_t *src, effect_t *continuation) return retval; } -static -effect_t *op_effect(char *name, int args_nr, expr_t **args, int line, int column) +dumb_ptr<effect_t> op_effect(const std::string& name, const_array<dumb_ptr<expr_t>> argv, int line, int column) { int id; - effect_t *effect; + dumb_ptr<effect_t> effect; op_t *op = magic_get_op(name, &id); if (!op) - fail(line, column, "Unknown operation `%s'\n", name); - else if (strlen(op->signature) != args_nr) + fail(line, column, "Unknown operation `%s'\n", name.c_str()); + else if (strlen(op->signature) != argv.size()) { - fail(line, column, "Incorrect number of arguments to operation `%s': Expected %zu, found %d\n", name, strlen(op->signature), args_nr); + fail(line, column, "Incorrect number of arguments to operation `%s': Expected %zu, found %zu\n", + name.c_str(), strlen(op->signature), argv.size()); op = NULL; } if (op) { - int i; - effect = new_effect(EFFECT::OP); effect->e.e_op.line_nr = line; effect->e.e_op.column = column; effect->e.e_op.id = id; - effect->e.e_op.args_nr = args_nr; + assert (argv.size() < MAX_ARGS); + effect->e.e_op.args_nr = argv.size(); - for (i = 0; i < args_nr; i++) - effect->e.e_op.args[i] = args[i]; + std::copy(argv.begin(), argv.end(), effect->e.e_op.args); } else /* failure */ effect = new_effect(EFFECT::SKIP); @@ -1336,99 +1321,55 @@ effect_t *op_effect(char *name, int args_nr, expr_t **args, int line, int column } -proc_t *procs = NULL; -int procs_nr = 0; +std::map<std::string, proc_t> procs; -// I think this is a memory leak, or undefined behavior -static -void install_proc(proc_t *proc) +// I think this was a memory leak (or undefined behavior) +void install_proc(dumb_ptr<proc_t> proc) { - if (!procs) - { - procs = proc; - procs_nr = 1; - } - else - { - RECREATE(procs, proc_t, 1 + procs_nr); - procs[procs_nr++] = *proc; - } + procs.insert({proc->name, std::move(*proc)}); } -static -effect_t *call_proc(char *name, int args_nr, expr_t **args, int line_nr, int column) +dumb_ptr<effect_t> call_proc(const_string name_, dumb_ptr<std::vector<dumb_ptr<expr_t>>> argvp, int line_nr, int column) { - proc_t *p = NULL; - int i; - effect_t *retval; - - for (i = 0; i < procs_nr; i++) - if (!strcmp(procs[i].name, name)) - { - p = &procs[i]; - break; - } - - if (!p) + std::string name(name_.begin(), name_.end()); + auto pi = procs.find(name); + if (pi == procs.end()) { - fail(line_nr, column, "Unknown procedure `%s'\n", name); + fail(line_nr, column, "Unknown procedure `%s'\n", name.c_str()); return new_effect(EFFECT::SKIP); } - if (p->args_nr != args_nr) + proc_t *p = &pi->second; + + if (p->argv.size() != argvp->size()) { - fail(line_nr, column, "Procedure %s/%d invoked with %d parameters\n", name, p->args_nr, args_nr); + fail(line_nr, column, "Procedure %s/%zu invoked with %zu parameters\n", + name.c_str(), p->argv.size(), argvp->size()); return new_effect(EFFECT::SKIP); } - retval = new_effect(EFFECT::CALL); + dumb_ptr<effect_t> retval = new_effect(EFFECT::CALL); retval->e.e_call.body = p->body; - retval->e.e_call.args_nr = args_nr; - retval->e.e_call.formals = p->args; - retval->e.e_call.actuals = args; + retval->e.e_call.formalv = &p->argv; + retval->e.e_call.actualvp = argvp; return retval; } -struct const_def_rec -{ - char *name; - val_t val; -} *const_defs = NULL; - -int const_defs_nr = 0; +std::map<std::string, val_t> const_defm; -static -void bind_constant(char *name, val_t *val, int line_nr) +void bind_constant(const std::string& name, val_t *val, int line_nr) { - if (find_constant(name)) + if (!const_defm.insert({name, *val}).second) { - fail(line_nr, 0, "Redefinition of constant `%s'\n", name); - return; + fail(line_nr, 0, "Redefinition of constant `%s'\n", name.c_str()); } - - if (!const_defs) - const_defs = (struct const_def_rec *)malloc(sizeof(struct const_def_rec)); - else - const_defs = (struct const_def_rec *)realloc(const_defs, - (const_defs_nr + 1) * sizeof(struct const_def_rec)); - - const_defs[const_defs_nr].name = name; - const_defs[const_defs_nr].val = *val; - ++const_defs_nr; } -static -val_t *find_constant(char *name) +val_t *find_constant(const std::string& name) { - int i; - for (i = 0; i < const_defs_nr; i++) - { - if (!strcmp(const_defs[i].name, name)) - { - free(name); - return &const_defs[i].val; - } - } + auto it = const_defm.find(name); + if (it != const_defm.end()) + return &it->second; return NULL; } @@ -1455,20 +1396,6 @@ int magic_init(const char *conffile) { error_flag = 0; - magic_conf.vars_nr = 0; - // can these be left NULL ? I'm afraid to change anything. - magic_conf.var_name = (const char **)malloc(1); - magic_conf.vars = (val_t *)malloc(1); - - magic_conf.obscure_chance = 95; - magic_conf.min_casttime = 100; - - magic_conf.spells_nr = 0; - CREATE(magic_conf.spells, spell_t *, 1); - - magic_conf.anchors_nr = 0; - CREATE(magic_conf.anchors, teleport_anchor_t *, 1); - INTERN_ASSERT("min_casttime", VAR_MIN_CASTTIME); INTERN_ASSERT("obscure_chance", VAR_OBSCURE_CHANCE); INTERN_ASSERT("caster", VAR_CASTER); @@ -1487,23 +1414,14 @@ int magic_init(const char *conffile) } magic_frontend_parse(); - if (magic_conf.vars[VAR_MIN_CASTTIME].ty == TYPE::INT) - magic_conf.min_casttime = magic_conf.vars[VAR_MIN_CASTTIME].v.v_int; - - if (magic_conf.vars[VAR_OBSCURE_CHANCE].ty == TYPE::INT) - magic_conf.obscure_chance = magic_conf.vars[VAR_OBSCURE_CHANCE].v.v_int; + PRINTF("[magic-conf] Magic initialised. %zu spells, %zu teleport anchors.\n", + magic_conf.spells_by_name.size(), magic_conf.anchors_by_name.size()); - PRINTF("[magic-conf] Magic initialised; obscure at %d%%. %d spells, %d teleport anchors.\n", - magic_conf.obscure_chance, magic_conf.spells_nr, magic_conf.anchors_nr); - - if (procs) - free(procs); return error_flag; } extern int magic_frontend_lineno; -static void magic_frontend_error(const char *msg) { FPRINTF(stderr, "[magic-conf] Parse error: %s at line %d\n", msg, magic_frontend_lineno); diff --git a/src/map/magic-interpreter.hpp b/src/map/magic-interpreter.hpp index 432245d..f233f37 100644 --- a/src/map/magic-interpreter.hpp +++ b/src/map/magic-interpreter.hpp @@ -3,27 +3,29 @@ #include "magic-interpreter.t.hpp" +#include <cassert> + #include "magic.hpp" #include "map.hpp" #include "script.hpp" #include "skill.t.hpp" -struct expr; -struct val; -struct location; -struct area; -struct spell; +struct expr_t; +struct val_t; +struct location_t; +struct area_t; +struct spell_t; struct invocation; -typedef struct location +struct location_t { - int m; + map_local *m; int x, y; -} location_t; +}; -typedef struct area +struct area_t { - union a + union au { location_t a_loc; struct @@ -37,29 +39,39 @@ typedef struct area location_t loc; int width, height; } a_rect; - struct area *a_union[2]; + dumb_ptr<area_t> a_union[2]; + + au() { memset(this, '\0', sizeof(*this)); } + ~au() = default; + au(const au&) = default; + au& operator = (const au&) = default; } a; int size; AREA ty; -} area_t; +}; -typedef struct val +struct val_t { union v { int v_int; DIR v_dir; - char *v_string; - // can't be dumb_ptr<block_list> - block_list *v_entity; /* Used ONLY during operation/function invocation; otherwise we use v_int */ - area_t *v_area; + dumb_string v_string; + /* Used ONLY during operation/function invocation; otherwise we use v_int */ + dumb_ptr<block_list> v_entity; + dumb_ptr<area_t> v_area; location_t v_location; - // can't be dumb_ptr<invocation> - invocation *v_invocation; /* Used ONLY during operation/function invocation; otherwise we use v_int */ - struct spell *v_spell; + /* Used ONLY during operation/function invocation; otherwise we use v_int */ + dumb_ptr<invocation> v_invocation; + dumb_ptr<spell_t> v_spell; + + v() { memset(this, '\0', sizeof(*this)); } + ~v() = default; + v(const v&) = default; + v& operator = (const v&) = default; } v; TYPE ty; -} val_t; +}; /* ----------- */ /* Expressions */ @@ -67,12 +79,12 @@ typedef struct val #define MAX_ARGS 7 /* Max. # of args used in builtin primitive functions */ -typedef struct e_location +struct e_location_t { - struct expr *m, *x, *y; -} e_location_t; + dumb_ptr<expr_t> m, x, y; +}; -typedef struct e_area +struct e_area_t { union a0 { @@ -80,21 +92,26 @@ typedef struct e_area struct { e_location_t loc; - struct expr *width, *depth, *dir; + dumb_ptr<expr_t> width, depth, dir; } a_bar; struct { e_location_t loc; - struct expr *width, *height; + dumb_ptr<expr_t> width, height; } a_rect; - struct e_area *a_union[2]; + dumb_ptr<e_area_t> a_union[2]; + + a0() { memset(this, '\0', sizeof(*this)); } + ~a0() = default; + a0(const a0&) = default; + a0& operator = (const a0&) = default; } a; AREA ty; -} e_area_t; +}; -typedef struct expr +struct expr_t { - union e + union eu { val_t e_val; e_location_t e_location; @@ -103,153 +120,165 @@ typedef struct expr { int id, line_nr, column; int args_nr; - struct expr *args[MAX_ARGS]; + dumb_ptr<expr_t> args[MAX_ARGS]; } e_funapp; int e_id; struct { - struct expr *expr; + dumb_ptr<expr_t> expr; int id; } e_field; + + eu() { memset(this, '\0', sizeof(*this)); } + ~eu() = default; + eu(const eu&) = default; + eu& operator = (const eu&) = default; } e; EXPR ty; -} expr_t; +}; -typedef struct effect +struct effect_t { - struct effect *next; + dumb_ptr<effect_t> next; union e0 { struct { int id; - expr_t *expr; + dumb_ptr<expr_t> expr; } e_assign; struct { int id; - expr_t *area; - struct effect *body; + dumb_ptr<expr_t> area; + dumb_ptr<effect_t> body; FOREACH_FILTER filter; } e_foreach; struct { int id; - expr_t *start, *stop; - struct effect *body; + dumb_ptr<expr_t> start, stop; + dumb_ptr<effect_t> body; } e_for; struct { - expr_t *cond; - struct effect *true_branch, *false_branch; + dumb_ptr<expr_t> cond; + dumb_ptr<effect_t> true_branch, false_branch; } e_if; - expr_t *e_sleep; /* sleep time */ - const ScriptCode *e_script; + dumb_ptr<expr_t> e_sleep; /* sleep time */ + dumb_ptr<const ScriptBuffer> e_script; struct { int id; int args_nr; int line_nr, column; - expr_t *args[MAX_ARGS]; + dumb_ptr<expr_t> args[MAX_ARGS]; } e_op; struct { - int args_nr, *formals; - expr_t **actuals; - struct effect *body; + std::vector<int> *formalv; + dumb_ptr<std::vector<dumb_ptr<expr_t>>> actualvp; + dumb_ptr<effect_t> body; } e_call; + + e0() { memset(this, '\0', sizeof(*this)); } + ~e0() = default; + e0(const e0&) = default; + e0& operator = (const e0&) = default; } e; EFFECT ty; -} effect_t; +}; /* ---------- */ /* Components */ /* ---------- */ -typedef struct component +struct component_t { - struct component *next; + dumb_ptr<component_t> next; int item_id; int count; -} component_t; +}; -typedef struct effect_set +struct effect_set_t { - effect_t *effect, *at_trigger, *at_end; -} effect_set_t; + dumb_ptr<effect_t> effect, at_trigger, at_end; +}; -typedef struct spellguard +struct spellguard_t { - struct spellguard *next; - union s + dumb_ptr<spellguard_t> next; + union su { - expr_t *s_condition; - expr_t *s_mana; - expr_t *s_casttime; - component_t *s_components; - component_t *s_catalysts; - struct spellguard *s_alt; /* either `next' or `s.s_alt' */ + dumb_ptr<expr_t> s_condition; + dumb_ptr<expr_t> s_mana; + dumb_ptr<expr_t> s_casttime; + dumb_ptr<component_t> s_components; + dumb_ptr<component_t> s_catalysts; + dumb_ptr<spellguard_t> s_alt; /* either `next' or `s.s_alt' */ effect_set_t s_effect; + su() { memset(this, '\0', sizeof(*this)); } + ~su() = default; + su(const su&) = default; + su& operator = (const su&) = default; } s; SPELLGUARD ty; -} spellguard_t; +}; /* ------ */ /* Spells */ /* ------ */ -typedef struct letdef +struct letdef_t { int id; - expr_t *expr; -} letdef_t; + dumb_ptr<expr_t> expr; +}; -typedef struct spell +struct spell_t { - char *name; - char *invocation; - int index; // Relative location in the definitions file + std::string name; + std::string invocation; + int index_; // Relative location in the definitions file SPELL_FLAG flags; int arg; SPELLARG spellarg_ty; - int letdefs_nr; - letdef_t *letdefs; + std::vector<letdef_t> letdefv; - spellguard_t *spellguard; -} spell_t; + dumb_ptr<spellguard_t> spellguard; +}; /* ------- */ /* Anchors */ /* ------- */ -typedef struct teleport_anchor +struct teleport_anchor_t { - char *name; - char *invocation; - expr_t *location; -} teleport_anchor_t; + std::string name; + std::string invocation; + dumb_ptr<expr_t> location; +}; /* ------------------- */ /* The big config blob */ /* ------------------- */ -typedef struct +struct magic_conf_t { - int vars_nr; - const char **var_name; - val_t *vars; /* Initial assignments, if any, or NULL */ - - int obscure_chance; - int min_casttime; + struct mcvar + { + std::string name; + val_t val; + }; + // This should probably be done by a dedicated "intern pool" class + std::vector<mcvar> varv; - int spells_nr; - spell_t **spells; + std::map<std::string, dumb_ptr<spell_t>> spells_by_name, spells_by_invocation; - int anchors_nr; /* NEGATIVE iff we have sorted the anchors */ - teleport_anchor_t **anchors; -} magic_conf_t; + std::map<std::string, dumb_ptr<teleport_anchor_t>> anchors_by_name, anchors_by_invocation; +}; /* Execution environment */ @@ -266,57 +295,72 @@ typedef struct struct magic_config; -typedef struct env +struct env_t { magic_conf_t *base_env; - val_t *vars; -} env_t; + std::unique_ptr<val_t[]> varu; + + val_t& VAR(size_t i) + { + assert (varu); + if (varu[i].ty == TYPE::UNDEF) + return base_env->varv[i].val; + else + return varu[i]; + } + +}; #define MAX_STACK_SIZE 32 -typedef struct cont_activation_record +struct cont_activation_record_t { - effect_t *return_location; - union c + dumb_ptr<effect_t> return_location; + union cu { struct { int id; TYPE ty; - effect_t *body; - int entities_nr; - int *entities; + dumb_ptr<effect_t> body; + dumb_ptr<std::vector<int>> entities_vp; int index; } c_foreach; struct { int id; - effect_t *body; + dumb_ptr<effect_t> body; int current; int stop; } c_for; struct { - int args_nr, *formals; - val_t *old_actuals; + int args_nr; + int *formalap; + dumb_ptr<val_t[]> old_actualpa; } c_proc; + + cu() { memset(this, '\0', sizeof(*this)); } + ~cu() {} + cu(const cu&) = delete; + cu& operator = (const cu&) = delete; } c; CONT_STACK ty; -} cont_activation_record_t; +}; -typedef struct status_change_ref +struct status_change_ref_t { StatusChange sc_type; int bl_id; -} status_change_ref_t; +}; struct invocation : block_list { dumb_ptr<invocation> next_invocation; /* used for spells directly associated with a caster: they form a singly-linked list */ INVOCATION_FLAG flags; - env_t *env; - spell_t *spell; + dumb_ptr<env_t> env; + dumb_ptr<spell_t> spell; int caster; /* this is the person who originally invoked the spell */ int subject; /* when this person dies, the spell dies with it */ @@ -326,13 +370,12 @@ struct invocation : block_list cont_activation_record_t stack[MAX_STACK_SIZE]; int script_pos; /* Script position; if nonzero, resume the script we were running. */ - effect_t *current_effect; - effect_t *trigger_effect; /* If non-NULL, this is used to spawn a cloned effect based on the same environment */ - effect_t *end_effect; /* If non-NULL, this is executed when the spell terminates naturally, e.g. when all status changes have run out or all delays are over. */ + dumb_ptr<effect_t> current_effect; + dumb_ptr<effect_t> trigger_effect; /* If non-NULL, this is used to spawn a cloned effect based on the same environment */ + dumb_ptr<effect_t> end_effect; /* If non-NULL, this is executed when the spell terminates naturally, e.g. when all status changes have run out or all delays are over. */ /* Status change references: for status change updates, keep track of whom we updated where */ - int status_change_refs_nr; - status_change_ref_t *status_change_refs; + std::vector<status_change_ref_t> status_change_refv; }; @@ -345,25 +388,23 @@ extern env_t magic_default_env; /* Fake default environment */ /** * Adds a component selection to a component holder (which may initially be NULL) */ -void magic_add_component(component_t ** component_holder, int id, int count); +void magic_add_component(dumb_ptr<component_t> *component_holder, int id, int count); -teleport_anchor_t *magic_find_anchor(char *name); +dumb_ptr<teleport_anchor_t> magic_find_anchor(const std::string& name); -/** - * The parameter `param' must have been dynamically allocated; ownership is transferred to the resultant env_t. - */ -env_t *spell_create_env(magic_conf_t *conf, spell_t *spell, - dumb_ptr<map_session_data> caster, int spellpower, char *param); +dumb_ptr<env_t> spell_create_env(magic_conf_t *conf, dumb_ptr<spell_t> spell, + dumb_ptr<map_session_data> caster, int spellpower, const_string param); -void magic_free_env(env_t *env); +void magic_free_env(dumb_ptr<env_t> env); /** * near_miss is set to nonzero iff the spell only failed due to ephemereal issues (spell delay in effect, out of mana, out of components) */ -effect_set_t *spell_trigger(spell_t *spell, dumb_ptr<map_session_data> caster, - env_t *env, int *near_miss); +effect_set_t *spell_trigger(dumb_ptr<spell_t> spell, + dumb_ptr<map_session_data> caster, + dumb_ptr<env_t> env, int *near_miss); -dumb_ptr<invocation> spell_instantiate(effect_set_t *effect, env_t *env); +dumb_ptr<invocation> spell_instantiate(effect_set_t *effect, dumb_ptr<env_t> env); /** * Bind a spell to a subject (this is a no-op for `local' spells). @@ -378,22 +419,26 @@ int spell_unbind(dumb_ptr<map_session_data> subject, dumb_ptr<invocation> invoca */ dumb_ptr<invocation> spell_clone_effect(dumb_ptr<invocation> source); -spell_t *magic_find_spell(char *invocation); +dumb_ptr<spell_t> magic_find_spell(const std::string& invocation); /* The following is used only by the parser: */ -typedef struct args_rec +struct args_rec_t { - int args_nr; - expr_t **args; -} args_rec_t; + dumb_ptr<std::vector<dumb_ptr<expr_t>>> argvp; +}; -typedef struct +struct proc_t { - char *name; - int args_nr; - int *args; - effect_t *body; -} proc_t; + std::string name; + std::vector<int> argv; + dumb_ptr<effect_t> body; + + proc_t() + : name() + , argv() + , body() + {} +}; // must be called after itemdb initialisation int magic_init(const char *); diff --git a/src/map/magic-stmt.cpp b/src/map/magic-stmt.cpp index d7944f1..f24167c 100644 --- a/src/map/magic-stmt.cpp +++ b/src/map/magic-stmt.cpp @@ -71,10 +71,10 @@ void clear_activation_record(cont_activation_record_t *ar) switch (ar->ty) { case CONT_STACK::FOREACH: - free(ar->c.c_foreach.entities); + ar->c.c_foreach.entities_vp.delete_(); break; case CONT_STACK::PROC: - free(ar->c.c_proc.old_actuals); + ar->c.c_proc.old_actualpa.delete_(); break; } } @@ -103,13 +103,7 @@ void clear_stack(dumb_ptr<invocation> invocation_) void spell_free_invocation(dumb_ptr<invocation> invocation_) { - if (invocation_->status_change_refs) - { - free(invocation_->status_change_refs); - /* The following cleanup shouldn't be necessary, but I've added it to help tracking a certain bug */ - invocation_->status_change_refs = NULL; - invocation_->status_change_refs_nr = 0; - } + invocation_->status_change_refv.clear(); if (bool(invocation_->flags & INVOCATION_FLAG::BOUND)) { @@ -200,7 +194,7 @@ void magic_stop_completely(dumb_ptr<map_session_data> c) static void try_to_finish_invocation(dumb_ptr<invocation> invocation) { - if (invocation->status_change_refs_nr == 0 && !invocation->current_effect) + if (invocation->status_change_refv.empty() && !invocation->current_effect) { if (invocation->end_effect) { @@ -225,20 +219,20 @@ int trigger_spell(int subject, int spell) invocation_ = spell_clone_effect(invocation_); spell_bind(map_id_as_player(subject), invocation_); - magic_clear_var(&invocation_->env->vars[VAR_CASTER]); - invocation_->env->vars[VAR_CASTER].ty = TYPE::ENTITY; - invocation_->env->vars[VAR_CASTER].v.v_int = subject; + magic_clear_var(&invocation_->env->varu[VAR_CASTER]); + invocation_->env->varu[VAR_CASTER].ty = TYPE::ENTITY; + invocation_->env->varu[VAR_CASTER].v.v_int = subject; return invocation_->bl_id; } static -void entity_warp(dumb_ptr<block_list> target, int destm, int destx, int desty); +void entity_warp(dumb_ptr<block_list> target, map_local *destm, int destx, int desty); static void char_update(dumb_ptr<map_session_data> character) { - entity_warp((dumb_ptr<block_list> ) character, character->bl_m, character->bl_x, + entity_warp(character, character->bl_m, character->bl_x, character->bl_y); } @@ -276,7 +270,7 @@ void timer_callback_effect_npc_delete(TimerData *, tick_t, int npc_id) } static -dumb_ptr<npc_data> local_spell_effect(int m, int x, int y, int effect, +dumb_ptr<npc_data> local_spell_effect(map_local *m, int x, int y, int effect, interval_t tdelay) { /* 1 minute should be enough for all interesting spell effects, I hope */ @@ -295,7 +289,7 @@ dumb_ptr<npc_data> local_spell_effect(int m, int x, int y, int effect, } static -int op_sfx(env_t *, int, val_t *args) +int op_sfx(dumb_ptr<env_t>, const_array<val_t> args) { interval_t delay = static_cast<interval_t>(ARGINT(2)); @@ -316,10 +310,10 @@ int op_sfx(env_t *, int, val_t *args) } static -int op_instaheal(env_t *env, int, val_t *args) +int op_instaheal(dumb_ptr<env_t> env, const_array<val_t> args) { - dumb_ptr<block_list> caster = (VAR(VAR_CASTER).ty == TYPE::ENTITY) - ? map_id2bl(VAR(VAR_CASTER).v.v_int) : NULL; + dumb_ptr<block_list> caster = (env->VAR(VAR_CASTER).ty == TYPE::ENTITY) + ? map_id2bl(env->VAR(VAR_CASTER).v.v_int) : NULL; dumb_ptr<block_list> subject = ARGENTITY(0); if (!caster) caster = subject; @@ -337,7 +331,7 @@ int op_instaheal(env_t *env, int, val_t *args) } static -int op_itemheal(env_t *env, int args_nr, val_t *args) +int op_itemheal(dumb_ptr<env_t> env, const_array<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); if (subject->bl_type == BL::PC) @@ -346,7 +340,7 @@ int op_itemheal(env_t *env, int args_nr, val_t *args) ARGINT(1), ARGINT(2)); } else - return op_instaheal(env, args_nr, args); + return op_instaheal(env, args); return 0; } @@ -367,7 +361,7 @@ using e::Shroud; #define ARGCHAR(n) (ARGENTITY(n)->is_player()) static -int op_shroud(env_t *, int, val_t *args) +int op_shroud(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<map_session_data> subject = ARGCHAR(0); Shroud arg = static_cast<Shroud>(ARGINT(1)); @@ -386,7 +380,7 @@ int op_shroud(env_t *, int, val_t *args) } static -int op_reveal(env_t *, int, val_t *args) +int op_reveal(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<map_session_data> subject = ARGCHAR(0); @@ -397,7 +391,7 @@ int op_reveal(env_t *, int, val_t *args) } static -int op_message(env_t *, int, val_t *args) +int op_message(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<map_session_data> subject = ARGCHAR(0); @@ -416,13 +410,13 @@ void timer_callback_kill_npc(TimerData *, tick_t, int npc_id) } static -int op_messenger_npc(env_t *, int, val_t *args) +int op_messenger_npc(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<npc_data> npc; location_t *loc = &ARGLOCATION(0); npc = npc_spawn_text(loc->m, loc->x, loc->y, - ARGINT(1), ARGSTR(2), ARGSTR(3)); + ARGINT(1), ARGSTR(2).c_str(), ARGSTR(3).c_str()); Timer(gettick() + static_cast<interval_t>(ARGINT(4)), std::bind(timer_callback_kill_npc, ph::_1, ph::_2, @@ -433,7 +427,7 @@ int op_messenger_npc(env_t *, int, val_t *args) } static -void entity_warp(dumb_ptr<block_list> target, int destm, int destx, int desty) +void entity_warp(dumb_ptr<block_list> target, map_local *destm, int destx, int desty) { if (target->bl_type == BL::PC || target->bl_type == BL::MOB) { @@ -453,7 +447,7 @@ void entity_warp(dumb_ptr<block_list> target, int destm, int destx, int desty) pc_touch_all_relevant_npcs(character); // Note that touching NPCs may have triggered warping and thereby updated x and y: - map_name = map[character->bl_m].name; + map_name = character->bl_m->name; // Warp part #1: update relevant data, interrupt trading etc.: pc_setpos(character, map_name, character->bl_x, character->bl_y, BeingRemoveWhy::GONE); @@ -473,7 +467,7 @@ void entity_warp(dumb_ptr<block_list> target, int destm, int destx, int desty) } static -int op_move(env_t *, int, val_t *args) +int op_move(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); DIR dir = ARGDIR(1); @@ -488,7 +482,7 @@ int op_move(env_t *, int, val_t *args) } static -int op_warp(env_t *, int, val_t *args) +int op_warp(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); location_t *loc = &ARGLOCATION(1); @@ -499,7 +493,7 @@ int op_warp(env_t *, int, val_t *args) } static -int op_banish(env_t *, int, val_t *args) +int op_banish(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); @@ -515,26 +509,22 @@ int op_banish(env_t *, int, val_t *args) } static -void record_status_change(dumb_ptr<invocation> invocation, int bl_id, +void record_status_change(dumb_ptr<invocation> invocation_, int bl_id, StatusChange sc_id) { - int index = invocation->status_change_refs_nr++; - status_change_ref_t *cr; - - RECREATE(invocation->status_change_refs, status_change_ref_t, invocation->status_change_refs_nr); + status_change_ref_t cr {}; + cr.sc_type = sc_id; + cr.bl_id = bl_id; - cr = &invocation->status_change_refs[index]; - - cr->sc_type = sc_id; - cr->bl_id = bl_id; + invocation_->status_change_refv.push_back(cr); } static -int op_status_change(env_t *env, int, val_t *args) +int op_status_change(dumb_ptr<env_t> env, const_array<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); - int invocation_id = VAR(VAR_INVOCATION).ty == TYPE::INVOCATION - ? VAR(VAR_INVOCATION).v.v_int : 0; + int invocation_id = env->VAR(VAR_INVOCATION).ty == TYPE::INVOCATION + ? env->VAR(VAR_INVOCATION).v.v_int : 0; dumb_ptr<invocation> invocation_ = map_id_as_spell(invocation_id); assert (!ARGINT(3)); @@ -551,7 +541,7 @@ int op_status_change(env_t *env, int, val_t *args) } static -int op_stop_status_change(env_t *, int, val_t *args) +int op_stop_status_change(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<block_list> subject = ARGENTITY(0); @@ -562,7 +552,7 @@ int op_stop_status_change(env_t *, int, val_t *args) } static -int op_override_attack(env_t *env, int, val_t *args) +int op_override_attack(dumb_ptr<env_t> env, const_array<val_t> args) { dumb_ptr<block_list> psubject = ARGENTITY(0); int charges = ARGINT(1); @@ -586,7 +576,7 @@ int op_override_attack(env_t *env, int, val_t *args) } subject->attack_spell_override = - trigger_spell(subject->bl_id, VAR(VAR_INVOCATION).v.v_int); + trigger_spell(subject->bl_id, env->VAR(VAR_INVOCATION).v.v_int); subject->attack_spell_charges = charges; if (subject->attack_spell_override) @@ -603,7 +593,7 @@ int op_override_attack(env_t *env, int, val_t *args) } static -int op_create_item(env_t *, int, val_t *args) +int op_create_item(dumb_ptr<env_t>, const_array<val_t> args) { struct item item; dumb_ptr<block_list> entity = ARGENTITY(0); @@ -641,7 +631,7 @@ bool AGGRAVATION_MODE_MAKES_AGGRESSIVE(int n) } static -int op_aggravate(env_t *, int, val_t *args) +int op_aggravate(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<block_list> victim = ARGENTITY(2); int mode = ARGINT(1); @@ -676,9 +666,9 @@ enum class MonsterAttitude }; static -int op_spawn(env_t *, int, val_t *args) +int op_spawn(dumb_ptr<env_t>, const_array<val_t> args) { - area_t *area = ARGAREA(0); + dumb_ptr<area_t> area = ARGAREA(0); dumb_ptr<block_list> owner_e = ARGENTITY(1); int monster_id = ARGINT(2); MonsterAttitude monster_attitude = static_cast<MonsterAttitude>(ARGINT(3)); @@ -699,7 +689,7 @@ int op_spawn(env_t *, int, val_t *args) int mob_id; dumb_ptr<mob_data> mob; - mob_id = mob_once_spawn(owner, map[loc.m].name, loc.x, loc.y, "--ja--", // Is that needed? + mob_id = mob_once_spawn(owner, loc.m->name, loc.x, loc.y, "--ja--", // Is that needed? monster_id, 1, ""); mob = map_id_as_mob(mob_id); @@ -752,22 +742,22 @@ int op_spawn(env_t *, int, val_t *args) } static -const char *get_invocation_name(env_t *env) +const char *get_invocation_name(dumb_ptr<env_t> env) { dumb_ptr<invocation> invocation_; - if (VAR(VAR_INVOCATION).ty != TYPE::INVOCATION) + if (env->VAR(VAR_INVOCATION).ty != TYPE::INVOCATION) return "?"; - invocation_ = map_id_as_spell(VAR(VAR_INVOCATION).v.v_int); + invocation_ = map_id_as_spell(env->VAR(VAR_INVOCATION).v.v_int); if (invocation_) - return invocation_->spell->name; + return invocation_->spell->name.c_str(); else return "??"; } static -int op_injure(env_t *env, int, val_t *args) +int op_injure(dumb_ptr<env_t> env, const_array<val_t> args) { dumb_ptr<block_list> caster = ARGENTITY(0); dumb_ptr<block_list> target = ARGENTITY(1); @@ -777,7 +767,7 @@ int op_injure(env_t *env, int, val_t *args) int mdef = battle_get_mdef(target); if (target->bl_type == BL::PC - && !map[target->bl_m].flag.pvp + && !target->bl_m->flag.pvp && !target->as_player()->special_state.killable && (caster->bl_type != BL::PC || !caster->as_player()->special_state.killer)) return 0; /* Cannot damage other players outside of pvp */ @@ -817,7 +807,7 @@ int op_injure(env_t *env, int, val_t *args) } static -int op_emote(env_t *, int, val_t *args) +int op_emote(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<block_list> victim = ARGENTITY(0); int emotion = ARGINT(1); @@ -827,20 +817,20 @@ int op_emote(env_t *, int, val_t *args) } static -int op_set_script_variable(env_t *, int, val_t *args) +int op_set_script_variable(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; if (!c) return 1; - pc_setglobalreg(c, ARGSTR(1), ARGINT(2)); + pc_setglobalreg(c, ARGSTR(1).c_str(), ARGINT(2)); return 0; } static -int op_set_hair_colour(env_t *, int, val_t *args) +int op_set_hair_colour(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; @@ -853,7 +843,7 @@ int op_set_hair_colour(env_t *, int, val_t *args) } static -int op_set_hair_style(env_t *, int, val_t *args) +int op_set_hair_style(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; @@ -866,15 +856,15 @@ int op_set_hair_style(env_t *, int, val_t *args) } static -int op_drop_item_for (env_t *, int args_nr, val_t *args) +int op_drop_item_for (dumb_ptr<env_t>, const_array<val_t> args) { struct item item; int stackable; location_t *loc = &ARGLOCATION(0); int count = ARGINT(2); interval_t interval = static_cast<interval_t>(ARGINT(3)); - dumb_ptr<map_session_data> c = ((args_nr > 4) && (ENTITY_TYPE(4) == BL::PC)) ? ARGPC(4) : NULL; - interval_t delay = (args_nr > 5) ? static_cast<interval_t>(ARGINT(5)) : interval_t::zero(); + dumb_ptr<map_session_data> c = ((args.size() > 4) && (ENTITY_TYPE(4) == BL::PC)) ? ARGPC(4) : NULL; + interval_t delay = (args.size() > 5) ? static_cast<interval_t>(ARGINT(5)) : interval_t::zero(); interval_t delaytime[3] = { delay, delay, delay }; dumb_ptr<map_session_data> owners[3] = { c, NULL, NULL }; @@ -892,7 +882,7 @@ int op_drop_item_for (env_t *, int args_nr, val_t *args) } static -int op_gain_exp(env_t *, int, val_t *args) +int op_gain_exp(dumb_ptr<env_t>, const_array<val_t> args) { dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL; @@ -905,7 +895,8 @@ int op_gain_exp(env_t *, int, val_t *args) } static -op_t operations[] = { +op_t operations[] = +{ {"sfx", ".ii", op_sfx}, {"instaheal", "eii", op_instaheal}, {"itemheal", "eii", op_itemheal}, @@ -938,13 +929,13 @@ int operations_sorted = 0; static int operation_count; -static +static __attribute__((deprecated)) int compare_operations(const void *lhs, const void *rhs) { - return strcmp(((const op_t *) lhs)->name, ((const op_t *) rhs)->name); + return strcmp(static_cast<const op_t *>(lhs)->name, static_cast<const op_t *>(rhs)->name); } -op_t *magic_get_op(char *name, int *index) +op_t *magic_get_op(const std::string& name, int *index) { op_t key; @@ -962,9 +953,9 @@ op_t *magic_get_op(char *name, int *index) operations_sorted = 1; } - key.name = name; - op_t *op = (op_t *)bsearch(&key, operations, operation_count, sizeof(op_t), - compare_operations); + key.name = name.c_str(); + op_t *op = static_cast<op_t *>(bsearch(&key, operations, operation_count, sizeof(op_t), + compare_operations)); if (op && index) *index = op - operations; @@ -975,24 +966,23 @@ op_t *magic_get_op(char *name, int *index) void spell_effect_report_termination(int invocation_id, int bl_id, StatusChange sc_id, int) { - int i; - int index = -1; dumb_ptr<invocation> invocation_ = map_id_as_spell(invocation_id); if (!invocation_ || invocation_->bl_type != BL::SPELL) return; - for (i = 0; i < invocation_->status_change_refs_nr; i++) + for (status_change_ref_t& cr : invocation_->status_change_refv) { - status_change_ref_t *cr = &invocation_->status_change_refs[i]; - if (cr->sc_type == sc_id && cr->bl_id == bl_id) + if (cr.sc_type == sc_id && cr.bl_id == bl_id) { - index = i; - break; + if (&cr != &invocation_->status_change_refv.back()) + std::swap(cr, invocation_->status_change_refv.back()); + invocation_->status_change_refv.pop_back(); + + try_to_finish_invocation(invocation_); } } - if (index == -1) { dumb_ptr<block_list> entity = map_id2bl(bl_id); if (entity->bl_type == BL::PC) @@ -1002,17 +992,10 @@ void spell_effect_report_termination(int invocation_id, int bl_id, return; } - if (index == invocation_->status_change_refs_nr - 1) - invocation_->status_change_refs_nr--; - else /* Copy last change ref to the one we are deleting */ - invocation_->status_change_refs[index] = - invocation_->status_change_refs[--invocation_->status_change_refs_nr]; - - try_to_finish_invocation(invocation_); } static -effect_t *return_to_stack(dumb_ptr<invocation> invocation_) +dumb_ptr<effect_t> return_to_stack(dumb_ptr<invocation> invocation_) { if (!invocation_->stack_size) return NULL; @@ -1022,20 +1005,18 @@ effect_t *return_to_stack(dumb_ptr<invocation> invocation_) invocation_->stack + (invocation_->stack_size - 1); switch (ar->ty) { - case CONT_STACK::PROC: { - effect_t *ret = ar->return_location; - int i; - - for (i = 0; i < ar->c.c_proc.args_nr; i++) + dumb_ptr<effect_t> ret = ar->return_location; + for (int i = 0; i < ar->c.c_proc.args_nr; i++) { val_t *var = - &invocation_->env->vars[ar->c.c_proc.formals[i]]; + &invocation_->env->varu[ar->c.c_proc.formalap[i]]; magic_clear_var(var); - *var = ar->c.c_proc.old_actuals[i]; + *var = ar->c.c_proc.old_actualpa[i]; } + // pop the stack clear_activation_record(ar); --invocation_->stack_size; @@ -1045,20 +1026,23 @@ effect_t *return_to_stack(dumb_ptr<invocation> invocation_) case CONT_STACK::FOREACH: { int entity_id; - val_t *var = &invocation_->env->vars[ar->c.c_foreach.id]; + val_t *var = &invocation_->env->varu[ar->c.c_foreach.id]; do { - if (ar->c.c_foreach.index >= ar->c.c_foreach.entities_nr) + // This >= is really supposed to be a ==, but + // I have no clue if it's actually safe to change it. + if (ar->c.c_foreach.index >= ar->c.c_foreach.entities_vp->size()) { - effect_t *ret = ar->return_location; + // pop the stack + dumb_ptr<effect_t> ret = ar->return_location; clear_activation_record(ar); --invocation_->stack_size; return ret; } entity_id = - ar->c.c_foreach.entities[ar->c.c_foreach.index++]; + (*ar->c.c_foreach.entities_vp)[ar->c.c_foreach.index++]; } while (!entity_id || !map_id2bl(entity_id)); @@ -1072,15 +1056,16 @@ effect_t *return_to_stack(dumb_ptr<invocation> invocation_) case CONT_STACK::FOR: if (ar->c.c_for.current > ar->c.c_for.stop) { - effect_t *ret = ar->return_location; + dumb_ptr<effect_t> ret = ar->return_location; + // pop the stack clear_activation_record(ar); --invocation_->stack_size; return ret; } - magic_clear_var(&invocation_->env->vars[ar->c.c_for.id]); - invocation_->env->vars[ar->c.c_for.id].ty = TYPE::INT; - invocation_->env->vars[ar->c.c_for.id].v.v_int = + magic_clear_var(&invocation_->env->varu[ar->c.c_for.id]); + invocation_->env->varu[ar->c.c_for.id].ty = TYPE::INT; + invocation_->env->varu[ar->c.c_for.id].v.v_int = ar->c.c_for.current++; return ar->c.c_for.body; @@ -1096,7 +1081,7 @@ effect_t *return_to_stack(dumb_ptr<invocation> invocation_) static cont_activation_record_t *add_stack_entry(dumb_ptr<invocation> invocation_, - CONT_STACK ty, effect_t *return_location) + CONT_STACK ty, dumb_ptr<effect_t> return_location) { cont_activation_record_t *ar = invocation_->stack + invocation_->stack_size++; @@ -1116,20 +1101,9 @@ cont_activation_record_t *add_stack_entry(dumb_ptr<invocation> invocation_, static void find_entities_in_area_c(dumb_ptr<block_list> target, - int *entities_allocd_p, - int *entities_nr_p, - int **entities_p, + std::vector<int> *entities_vp, FOREACH_FILTER filter) { -/* The following macro adds an entity to the result list: */ -#define ADD_ENTITY(e) \ - if (*entities_nr_p == *entities_allocd_p) { \ - /* Need more space */ \ - (*entities_allocd_p) += 32; \ - RECREATE(*entities_p, int, *entities_allocd_p); \ - } \ - (*entities_p)[(*entities_nr_p)++] = e; - switch (target->bl_type) { @@ -1137,7 +1111,7 @@ void find_entities_in_area_c(dumb_ptr<block_list> target, if (filter == FOREACH_FILTER::PC || filter == FOREACH_FILTER::ENTITY || (filter == FOREACH_FILTER::TARGET - && map[target->bl_m].flag.pvp)) + && target->bl_m->flag.pvp)) break; else if (filter == FOREACH_FILTER::SPELL) { /* Check all spells bound to the caster */ @@ -1146,7 +1120,7 @@ void find_entities_in_area_c(dumb_ptr<block_list> target, while (invoc) { - ADD_ENTITY(invoc->bl_id); + entities_vp->push_back(invoc->bl_id); invoc = invoc->next_invocation; } } @@ -1184,42 +1158,45 @@ void find_entities_in_area_c(dumb_ptr<block_list> target, return; } - ADD_ENTITY(target->bl_id); -#undef ADD_ENTITY + entities_vp->push_back(target->bl_id); } static -void find_entities_in_area(area_t *area, int *entities_allocd_p, - int *entities_nr_p, int **entities_p, FOREACH_FILTER filter) +void find_entities_in_area(area_t& area_, + std::vector<int> *entities_vp, + FOREACH_FILTER filter) { + area_t *area = &area_; // temporary hack to "keep diff small". Heh. switch (area->ty) { case AREA::UNION: - find_entities_in_area(area->a.a_union[0], entities_allocd_p, - entities_nr_p, entities_p, filter); - find_entities_in_area(area->a.a_union[1], entities_allocd_p, - entities_nr_p, entities_p, filter); + find_entities_in_area(*area->a.a_union[0], entities_vp, filter); + find_entities_in_area(*area->a.a_union[1], entities_vp, filter); break; default: { - int m, x, y, width, height; - magic_area_rect(&m, &x, &y, &width, &height, area); - map_foreachinarea(std::bind(find_entities_in_area_c, ph::_1, entities_allocd_p, entities_nr_p, entities_p, filter), - m, x, y, x + width, y + height, - BL::NUL /* filter elsewhere */); + map_local *m; + int x, y, width, height; + magic_area_rect(&m, &x, &y, &width, &height, *area); + map_foreachinarea(std::bind(find_entities_in_area_c, ph::_1, entities_vp, filter), + m, + x, y, + x + width, y + height, + BL::NUL /* filter elsewhere */); } } } static -effect_t *run_foreach(dumb_ptr<invocation> invocation, effect_t *foreach, - effect_t *return_location) +dumb_ptr<effect_t> run_foreach(dumb_ptr<invocation> invocation, + dumb_ptr<effect_t> foreach, + dumb_ptr<effect_t> return_location) { val_t area; FOREACH_FILTER filter = foreach->e.e_foreach.filter; int id = foreach->e.e_foreach.id; - effect_t *body = foreach->e.e_foreach.body; + dumb_ptr<effect_t> body = foreach->e.e_foreach.body; magic_eval(invocation->env, &area, foreach->e.e_foreach.area); @@ -1228,32 +1205,28 @@ effect_t *run_foreach(dumb_ptr<invocation> invocation, effect_t *foreach, magic_clear_var(&area); FPRINTF(stderr, "[magic] Error in spell `%s': FOREACH loop over non-area\n", - invocation->spell->name); + invocation->spell->name.c_str()); return return_location; } else { cont_activation_record_t *ar = add_stack_entry(invocation, CONT_STACK::FOREACH, return_location); - int entities_allocd = 64; - int *entities; - int entities_nr = 0; if (!ar) return return_location; - CREATE(entities, int, entities_allocd); - find_entities_in_area(area.v.v_area, &entities_allocd, &entities_nr, - &entities, filter); - RECREATE(entities, int, entities_nr); + std::vector<int> entities_v; + find_entities_in_area(*area.v.v_area, + &entities_v, filter); + entities_v.shrink_to_fit(); // iterator_pair will go away when this gets properly containerized. - random_::shuffle(iterator_pair(entities, entities + entities_nr)); + random_::shuffle(entities_v); ar->c.c_foreach.id = id; ar->c.c_foreach.body = body; ar->c.c_foreach.index = 0; - ar->c.c_foreach.entities_nr = entities_nr; - ar->c.c_foreach.entities = entities; + ar->c.c_foreach.entities_vp.new_(std::move(entities_v)); ar->c.c_foreach.ty = (filter == FOREACH_FILTER::SPELL) ? TYPE::INVOCATION : TYPE::ENTITY; @@ -1264,8 +1237,9 @@ effect_t *run_foreach(dumb_ptr<invocation> invocation, effect_t *foreach, } static -effect_t *run_for (dumb_ptr<invocation> invocation, effect_t *for_, - effect_t *return_location) +dumb_ptr<effect_t> run_for (dumb_ptr<invocation> invocation, + dumb_ptr<effect_t> for_, + dumb_ptr<effect_t> return_location) { cont_activation_record_t *ar; int id = for_->e.e_for.id; @@ -1299,28 +1273,24 @@ effect_t *run_for (dumb_ptr<invocation> invocation, effect_t *for_, } static -effect_t *run_call(dumb_ptr<invocation> invocation, - effect_t *return_location) +dumb_ptr<effect_t> run_call(dumb_ptr<invocation> invocation, + dumb_ptr<effect_t> return_location) { - effect_t *current = invocation->current_effect; + dumb_ptr<effect_t> current = invocation->current_effect; cont_activation_record_t *ar; - int args_nr = current->e.e_call.args_nr; - int *formals = current->e.e_call.formals; - val_t *old_actuals; - CREATE(old_actuals, val_t, args_nr); - int i; + int args_nr = current->e.e_call.formalv->size(); + int *formals = current->e.e_call.formalv->data(); + auto old_actuals = dumb_ptr<val_t[]>::make(args_nr); ar = add_stack_entry(invocation, CONT_STACK::PROC, return_location); ar->c.c_proc.args_nr = args_nr; - ar->c.c_proc.formals = formals; - ar->c.c_proc.old_actuals = old_actuals; - for (i = 0; i < args_nr; i++) + ar->c.c_proc.formalap = formals; + ar->c.c_proc.old_actualpa = old_actuals; + for (int i = 0; i < args_nr; i++) { - val_t *env_val = &invocation->env->vars[formals[i]]; - val_t result; + val_t *env_val = &invocation->env->varu[formals[i]]; magic_copy_var(&old_actuals[i], env_val); - magic_eval(invocation->env, &result, current->e.e_call.actuals[i]); - *env_val = result; + magic_eval(invocation->env, env_val, (*current->e.e_call.actualvp)[i]); } return current->e.e_call.body; @@ -1414,8 +1384,8 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) #endif while (invocation_->current_effect) { - effect_t *e = invocation_->current_effect; - effect_t *next = e->next; + dumb_ptr<effect_t> e = invocation_->current_effect; + dumb_ptr<effect_t> next = e->next; int i; #ifdef DEBUG @@ -1439,7 +1409,7 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) case EFFECT::ASSIGN: magic_eval(invocation_->env, - &invocation_->env->vars[e->e.e_assign.id], + &invocation_->env->varu[e->e.e_assign.id], e->e.e_assign.expr); break; @@ -1473,19 +1443,16 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) dumb_ptr<map_session_data> caster = map_id_as_player(invocation_->caster); if (caster) { - env_t *env = invocation_->env; - argrec_t arg[] = { {"@target", - VAR(VAR_TARGET).ty == - TYPE::ENTITY ? 0 : VAR(VAR_TARGET). - v.v_int} - , - {"@caster", invocation_->caster} - , - {"@caster_name$", caster ? caster->status.name : ""} + dumb_ptr<env_t> env = invocation_->env; + argrec_t arg[] = + { + {"@target", env->VAR(VAR_TARGET).ty == TYPE::ENTITY ? 0 : env->VAR(VAR_TARGET).v.v_int}, + {"@caster", invocation_->caster}, + {"@caster_name$", caster ? caster->status.name : ""}, }; int message_recipient = - VAR(VAR_SCRIPTTARGET).ty == - TYPE::ENTITY ? VAR(VAR_SCRIPTTARGET). + env->VAR(VAR_SCRIPTTARGET).ty == + TYPE::ENTITY ? env->VAR(VAR_SCRIPTTARGET). v.v_int : invocation_->caster; dumb_ptr<map_session_data> recipient = map_id_as_player(message_recipient); @@ -1499,11 +1466,11 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) // We have to do this or otherwise the client won't think that it's // dealing with an NPC - int newpos = run_script_l(e->e.e_script, - invocation_->script_pos, - message_recipient, - invocation_->bl_id, - 3, arg); + int newpos = run_script_l( + ScriptPointer(&*e->e.e_script, invocation_->script_pos), + message_recipient, + invocation_->bl_id, + 3, arg); /* Returns the new script position, or -1 once the script is finished */ if (newpos != -1) { @@ -1536,7 +1503,7 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete) e->e.e_op.args_nr, args, e->e.e_op.line_nr, e->e.e_op.column)) - op->op(invocation_->env, e->e.e_op.args_nr, args); + op->op(invocation_->env, const_array<val_t>(args, e->e.e_op.args_nr)); for (i = 0; i < e->e.e_op.args_nr; i++) magic_clear_var(&args[i]); @@ -1615,9 +1582,9 @@ int spell_attack(int caster_id, int target_id) if (invocation_ && caster->attack_spell_charges > 0) { - magic_clear_var(&invocation_->env->vars[VAR_TARGET]); - invocation_->env->vars[VAR_TARGET].ty = TYPE::ENTITY; - invocation_->env->vars[VAR_TARGET].v.v_int = target_id; + magic_clear_var(&invocation_->env->varu[VAR_TARGET]); + invocation_->env->varu[VAR_TARGET].ty = TYPE::ENTITY; + invocation_->env->varu[VAR_TARGET].v.v_int = target_id; invocation_->current_effect = invocation_->trigger_effect; invocation_->flags &= ~INVOCATION_FLAG::ABORTED; diff --git a/src/map/magic.cpp b/src/map/magic.cpp index f6da29b..e225830 100644 --- a/src/map/magic.cpp +++ b/src/map/magic.cpp @@ -9,83 +9,58 @@ #undef DEBUG +/// Return a pair of strings, {spellname, parameter} +/// Parameter may be empty. static -char *magic_preprocess_message(dumb_ptr<map_session_data> character, char *start, - char *end) +std::pair<std::string, std::string> magic_tokenise(std::string src) { - if (character->state.shroud_active - && character->state.shroud_disappears_on_talk) - magic_unshroud(character); + std::string retval = std::move(src); + const std::string::iterator rvb = retval.begin(), rve = retval.end(); + std::string::iterator seeker = std::find(rvb, rve, ' '); - if (character->state.shroud_active - && character->state.shroud_hides_name_talking) + if (seeker == retval.end()) { - int len = strlen(end); - strcpy(start, "? "); - memmove(start + 2, end, len + 1); - return start + 4; + return {retval, std::string()}; } else - return end + 2; /* step past blank */ -} - -/* Returns a dynamically allocated copy of `src'. - * `*parameter' may point within that copy or be NULL. */ -static -char *magic_tokenise(char *src, char **parameter) -{ - char *retval = strdup(src); - char *seeker = retval; - - while (*seeker && *seeker != ' ') - ++seeker; - - if (!*seeker) - *parameter = NULL; - else { - *seeker = 0; /* Terminate invocation */ + std::string rv1(rvb, seeker); ++seeker; - while (*seeker == ' ') + while (seeker != rve && *seeker == ' ') ++seeker; - *parameter = seeker; + // Note: this very well could be empty + std::string rv2(seeker, rve); + return {rv1, rv2}; } - - return retval; } -int magic_message(dumb_ptr<map_session_data> caster, char *spell_, size_t) +int magic_message(dumb_ptr<map_session_data> caster, const std::string& source_invocation) { if (pc_isdead(caster)) return 0; int power = caster->matk1; - char *invocation_base = spell_ + 8; - char *source_invocation = - 1 + invocation_base + strlen(caster->status.name); - spell_t *spell; - char *parameter; - char *spell_invocation; - - if (!source_invocation) - return 0; - /* Pre-message filter in case some spell alters output */ - source_invocation = - magic_preprocess_message(caster, invocation_base, source_invocation); + // This was the only thing worth saving from magic_preprocess_message. + // May it rest only, and never rise again. + // For more information on how this code worked, travel through time + // and watch all the comments I wrote for myself while trying to figure + // out if it was safe to delete. + if (caster->state.shroud_active && caster->state.shroud_disappears_on_talk) + magic_unshroud(caster); - spell_invocation = magic_tokenise(source_invocation, ¶meter); - parameter = parameter ? strdup(parameter) : strdup(""); + auto pair = magic_tokenise(source_invocation); + std::string spell_invocation = std::move(pair.first); + std::string parameter = std::move(pair.second); - spell = magic_find_spell(spell_invocation); - free(spell_invocation); + dumb_ptr<spell_t> spell = magic_find_spell(spell_invocation); if (spell) { int near_miss; - env_t *env = + dumb_ptr<env_t> env = spell_create_env(&magic_conf, spell, caster, power, parameter); effect_set_t *effects; @@ -118,8 +93,6 @@ int magic_message(dumb_ptr<map_session_data> caster, char *spell_, size_t) return 1; } - else - free(parameter); return 0; /* Not a spell */ } diff --git a/src/map/magic.hpp b/src/map/magic.hpp index cc66eb4..cec5bf4 100644 --- a/src/map/magic.hpp +++ b/src/map/magic.hpp @@ -14,14 +14,14 @@ struct invocation; /* Spell invocation */ * Try to cast magic. * * As an intended side effect, the magic message may be distorted (text only). + * No, it can't. Thank God. * * \param caster Player attempting to cast magic - * \param spell The prospective incantation - * \param spell_len Number of characters in the incantation + * \param source_invocation The prospective incantation * \return 1 or -1 if the input message was magic and was handled by this function, 0 otherwise. -1 is returned when the * message should not be repeated. */ -int magic_message(dumb_ptr<map_session_data> caster, char *spell, size_t spell_len); +int magic_message(dumb_ptr<map_session_data> caster, const std::string& source_invocation); /** * Removes the shroud from a character @@ -51,14 +51,14 @@ void do_init_magic(void); * * Returns NULL if not found */ -const char *magic_find_invocation(const char *spellame); +const char *magic_find_invocation(const std::string& spellame); /** * Identifies the invocation used to denote a teleport location * * Returns NULL if not found */ -const char *magic_find_anchor_invocation(const char *teleport_location); +const char *magic_find_anchor_invocation(const std::string& teleport_location); /** * Execute a spell invocation and sets up timers to finish diff --git a/src/map/map.cpp b/src/map/map.cpp index 96e9f5e..414fcd7 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -41,8 +41,7 @@ DMap<int, dumb_ptr<block_list>> id_db; -static -DMap<std::string, struct map_data *> map_db; +UPMap<std::string, map_abstract> maps_db; static DMap<std::string, dumb_ptr<map_session_data>> nick_db; @@ -63,9 +62,6 @@ dumb_ptr<block_list> object[MAX_FLOORITEM]; static int first_free_object_id = 0, last_object_id = 0; -struct map_data map[MAX_MAP_PER_SERVER]; -int map_num = 0; - static int map_port = 0; @@ -78,11 +74,11 @@ char help_txt[256] = "conf/help.txt"; char wisp_server_name[24] = "Server"; // can be modified in char-server configuration file static -int map_delmap(const char *mapname); +void map_delmap(const std::string& mapname); void SessionDeleter::operator()(SessionData *sd) { - delete static_cast<map_session_data *>(sd); + really_delete1 static_cast<map_session_data *>(sd); } /*========================================== @@ -148,8 +144,6 @@ struct block_list bl_head; */ int map_addblock(dumb_ptr<block_list> bl) { - int m, x, y; - nullpo_ret(bl); if (bl->bl_prev) @@ -159,35 +153,30 @@ int map_addblock(dumb_ptr<block_list> bl) return 0; } - m = bl->bl_m; - x = bl->bl_x; - y = bl->bl_y; - if (m < 0 || m >= map_num || - x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys) + map_local *m = bl->bl_m; + int x = bl->bl_x; + int y = bl->bl_y; + if (!m || + x < 0 || x >= m->xs || y < 0 || y >= m->ys) return 1; if (bl->bl_type == BL::MOB) { - bl->bl_next = - map[m].block_mob[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs]; + bl->bl_next = m->blocks.ref(x / BLOCK_SIZE, y / BLOCK_SIZE).mobs_only; bl->bl_prev = dumb_ptr<block_list>(&bl_head); if (bl->bl_next) bl->bl_next->bl_prev = bl; - map[m].block_mob[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs] = bl; - map[m].block_mob_count[x / BLOCK_SIZE + - (y / BLOCK_SIZE) * map[m].bxs]++; + m->blocks.ref(x / BLOCK_SIZE, y / BLOCK_SIZE).mobs_only = bl; } else { - bl->bl_next = - map[m].block[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs]; + bl->bl_next = m->blocks.ref(x / BLOCK_SIZE, y / BLOCK_SIZE).normal; bl->bl_prev = dumb_ptr<block_list>(&bl_head); if (bl->bl_next) bl->bl_next->bl_prev = bl; - map[m].block[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs] = bl; - map[m].block_count[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs]++; + m->blocks.ref(x / BLOCK_SIZE, y / BLOCK_SIZE).normal = bl; if (bl->bl_type == BL::PC) - map[m].users++; + m->users++; } return 0; @@ -200,7 +189,6 @@ int map_addblock(dumb_ptr<block_list> bl) */ int map_delblock(dumb_ptr<block_list> bl) { - int b; nullpo_ret(bl); // 既にblocklistから抜けている @@ -215,10 +203,8 @@ int map_delblock(dumb_ptr<block_list> bl) return 0; } - b = bl->bl_x / BLOCK_SIZE + (bl->bl_y / BLOCK_SIZE) * map[bl->bl_m].bxs; - if (bl->bl_type == BL::PC) - map[bl->bl_m].users--; + bl->bl_m->users--; if (bl->bl_next) bl->bl_next->bl_prev = bl->bl_prev; @@ -227,15 +213,11 @@ int map_delblock(dumb_ptr<block_list> bl) // リストの頭なので、map[]のblock_listを更新する if (bl->bl_type == BL::MOB) { - map[bl->bl_m].block_mob[b] = bl->bl_next; - if ((map[bl->bl_m].block_mob_count[b]--) < 0) - map[bl->bl_m].block_mob_count[b] = 0; + bl->bl_m->blocks.ref(bl->bl_x / BLOCK_SIZE, bl->bl_y / BLOCK_SIZE).mobs_only = bl->bl_next; } else { - map[bl->bl_m].block[b] = bl->bl_next; - if ((map[bl->bl_m].block_count[b]--) < 0) - map[bl->bl_m].block_count[b] = 0; + bl->bl_m->blocks.ref(bl->bl_x / BLOCK_SIZE, bl->bl_y / BLOCK_SIZE).normal = bl->bl_next; } } else @@ -252,28 +234,25 @@ int map_delblock(dumb_ptr<block_list> bl) * セル上のPCとMOBの数を数える (グランドクロス用) *------------------------------------------ */ -int map_count_oncell(int m, int x, int y) +int map_count_oncell(map_local *m, int x, int y) { int bx, by; dumb_ptr<block_list> bl = NULL; - int i, c; int count = 0; - if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys)) + if (x < 0 || y < 0 || (x >= m->xs) || (y >= m->ys)) return 1; bx = x / BLOCK_SIZE; by = y / BLOCK_SIZE; - bl = map[m].block[bx + by * map[m].bxs]; - c = map[m].block_count[bx + by * map[m].bxs]; - for (i = 0; i < c && bl; i++, bl = bl->bl_next) + bl = m->blocks.ref(bx, by).normal; + for (; bl; bl = bl->bl_next) { if (bl->bl_x == x && bl->bl_y == y && bl->bl_type == BL::PC) count++; } - bl = map[m].block_mob[bx + by * map[m].bxs]; - c = map[m].block_mob_count[bx + by * map[m].bxs]; - for (i = 0; i < c && bl; i++, bl = bl->bl_next) + bl = m->blocks.ref(bx, by).mobs_only; + for (; bl; bl = bl->bl_next) { if (bl->bl_x == x && bl->bl_y == y) count++; @@ -290,33 +269,30 @@ int map_count_oncell(int m, int x, int y) *------------------------------------------ */ void map_foreachinarea(std::function<void(dumb_ptr<block_list>)> func, - int m, + map_local *m, int x0, int y0, int x1, int y1, BL type) { std::vector<dumb_ptr<block_list>> bl_list; - if (m < 0) + if (!m) return; if (x0 < 0) x0 = 0; if (y0 < 0) y0 = 0; - if (x1 >= map[m].xs) - x1 = map[m].xs - 1; - if (y1 >= map[m].ys) - y1 = map[m].ys - 1; + if (x1 >= m->xs) + x1 = m->xs - 1; + if (y1 >= m->ys) + y1 = m->ys - 1; if (type == BL::NUL || type != BL::MOB) for (int by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { for (int bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) { - dumb_ptr<block_list> bl = map[m].block[bx + by * map[m].bxs]; - int c = map[m].block_count[bx + by * map[m].bxs]; - for (int i = 0; i < c && bl; i++, bl = bl->bl_next) + dumb_ptr<block_list> bl = m->blocks.ref(bx, by).normal; + for (; bl; bl = bl->bl_next) { - if (!bl) - continue; if (type != BL::NUL && bl->bl_type != type) continue; if (bl->bl_x >= x0 && bl->bl_x <= x1 @@ -330,12 +306,9 @@ void map_foreachinarea(std::function<void(dumb_ptr<block_list>)> func, { for (int bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) { - dumb_ptr<block_list> bl = map[m].block_mob[bx + by * map[m].bxs]; - int c = map[m].block_mob_count[bx + by * map[m].bxs]; - for (int i = 0; i < c && bl; i++, bl = bl->bl_next) + dumb_ptr<block_list> bl = m->blocks.ref(bx, by).mobs_only; + for (; bl; bl = bl->bl_next) { - if (!bl) - continue; if (bl->bl_x >= x0 && bl->bl_x <= x1 && bl->bl_y >= y0 && bl->bl_y <= y1) bl_list.push_back(bl); @@ -359,7 +332,7 @@ void map_foreachinarea(std::function<void(dumb_ptr<block_list>)> func, *------------------------------------------ */ void map_foreachinmovearea(std::function<void(dumb_ptr<block_list>)> func, - int m, + map_local *m, int x0, int y0, int x1, int y1, int dx, int dy, BL type) @@ -389,32 +362,26 @@ void map_foreachinmovearea(std::function<void(dumb_ptr<block_list>)> func, x0 = 0; if (y0 < 0) y0 = 0; - if (x1 >= map[m].xs) - x1 = map[m].xs - 1; - if (y1 >= map[m].ys) - y1 = map[m].ys - 1; + if (x1 >= m->xs) + x1 = m->xs - 1; + if (y1 >= m->ys) + y1 = m->ys - 1; for (int by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { for (int bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) { - dumb_ptr<block_list> bl = map[m].block[bx + by * map[m].bxs]; - int c = map[m].block_count[bx + by * map[m].bxs]; - for (int i = 0; i < c && bl; i++, bl = bl->bl_next) + dumb_ptr<block_list> bl = m->blocks.ref(bx, by).normal; + for (; bl; bl = bl->bl_next) { - if (!bl) - continue; if (type != BL::NUL && bl->bl_type != type) continue; if (bl->bl_x >= x0 && bl->bl_x <= x1 && bl->bl_y >= y0 && bl->bl_y <= y1) bl_list.push_back(bl); } - bl = map[m].block_mob[bx + by * map[m].bxs]; - c = map[m].block_mob_count[bx + by * map[m].bxs]; - for (int i = 0; i < c && bl; i++, bl = bl->bl_next) + bl = m->blocks.ref(bx, by).mobs_only; + for (; bl; bl = bl->bl_next) { - if (!bl) - continue; if (type != BL::NUL && bl->bl_type != type) continue; if (bl->bl_x >= x0 && bl->bl_x <= x1 @@ -432,20 +399,17 @@ void map_foreachinmovearea(std::function<void(dumb_ptr<block_list>)> func, x0 = 0; if (y0 < 0) y0 = 0; - if (x1 >= map[m].xs) - x1 = map[m].xs - 1; - if (y1 >= map[m].ys) - y1 = map[m].ys - 1; + if (x1 >= m->xs) + x1 = m->xs - 1; + if (y1 >= m->ys) + y1 = m->ys - 1; for (int by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { for (int bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) { - dumb_ptr<block_list> bl = map[m].block[bx + by * map[m].bxs]; - int c = map[m].block_count[bx + by * map[m].bxs]; - for (int i = 0; i < c && bl; i++, bl = bl->bl_next) + dumb_ptr<block_list> bl = m->blocks.ref(bx, by).normal; + for (; bl; bl = bl->bl_next) { - if (!bl) - continue; if (type != BL::NUL && bl->bl_type != type) continue; if (!(bl->bl_x >= x0 && bl->bl_x <= x1 @@ -457,14 +421,13 @@ void map_foreachinmovearea(std::function<void(dumb_ptr<block_list>)> func, || (dy < 0 && bl->bl_y > y1 + dy)) bl_list.push_back(bl); } - bl = map[m].block_mob[bx + by * map[m].bxs]; - c = map[m].block_mob_count[bx + by * map[m].bxs]; - for (int i = 0; i < c && bl; i++, bl = bl->bl_next) + bl = m->blocks.ref(bx, by).mobs_only; + for (; bl; bl = bl->bl_next) { if (type != BL::NUL && bl->bl_type != type) continue; - if (!(bl->bl_x >= x0 && bl->bl_x <= x1 && bl->bl_y >= y0 - && bl->bl_y <= y1)) + if (!(bl->bl_x >= x0 && bl->bl_x <= x1 + && bl->bl_y >= y0 && bl->bl_y <= y1)) continue; if ((dx > 0 && bl->bl_x < x0 + dx) || (dx < 0 && bl->bl_x > x1 + dx) @@ -489,7 +452,7 @@ void map_foreachinmovearea(std::function<void(dumb_ptr<block_list>)> func, // area radius - may be more useful in some instances) // void map_foreachincell(std::function<void(dumb_ptr<block_list>)> func, - int m, + map_local *m, int x, int y, BL type) { @@ -499,12 +462,9 @@ void map_foreachincell(std::function<void(dumb_ptr<block_list>)> func, if (type == BL::NUL || type != BL::MOB) { - dumb_ptr<block_list> bl = map[m].block[bx + by * map[m].bxs]; - int c = map[m].block_count[bx + by * map[m].bxs]; - for (int i = 0; i < c && bl; i++, bl = bl->bl_next) + dumb_ptr<block_list> bl = m->blocks.ref(bx, by).normal; + for (; bl; bl = bl->bl_next) { - if (!bl) - continue; if (type != BL::NUL && bl->bl_type != type) continue; if (bl->bl_x == x && bl->bl_y == y) @@ -514,12 +474,9 @@ void map_foreachincell(std::function<void(dumb_ptr<block_list>)> func, if (type == BL::NUL || type == BL::MOB) { - dumb_ptr<block_list> bl = map[m].block_mob[bx + by * map[m].bxs]; - int c = map[m].block_mob_count[bx + by * map[m].bxs]; - for (int i = 0; i < c && bl; i++, bl = bl->bl_next) + dumb_ptr<block_list> bl = m->blocks.ref(bx, by).mobs_only; + for (; bl; bl = bl->bl_next) { - if (!bl) - continue; if (bl->bl_x == x && bl->bl_y == y) bl_list.push_back(bl); } @@ -670,13 +627,14 @@ void map_clearflooritem_timer(TimerData *tid, tick_t, int id) map_delobject(fitem->bl_id, BL::ITEM); } -std::pair<uint16_t, uint16_t> map_randfreecell(int m, uint16_t x, uint16_t y, uint16_t w, uint16_t h) +std::pair<uint16_t, uint16_t> map_randfreecell(map_local *m, + uint16_t x, uint16_t y, uint16_t w, uint16_t h) { for (int itr : random_::iterator(w * h)) { int dx = itr % w; int dy = itr / w; - if (!bool(read_gat(m, x + dx, y + dy) & MapCell::UNWALKABLE)) + if (!bool(read_gatp(m, x + dx, y + dy) & MapCell::UNWALKABLE)) return {static_cast<uint16_t>(x + dx), static_cast<uint16_t>(y + dy)}; } return {static_cast<uint16_t>(0), static_cast<uint16_t>(0)}; @@ -684,7 +642,7 @@ std::pair<uint16_t, uint16_t> map_randfreecell(int m, uint16_t x, uint16_t y, ui /// Return a randomly selected passable cell within a given range. static -std::pair<uint16_t, uint16_t> map_searchrandfreecell(int m, int x, int y, int range) +std::pair<uint16_t, uint16_t> map_searchrandfreecell(map_local *m, int x, int y, int range) { int whole_range = 2 * range + 1; return map_randfreecell(m, x - range, y - range, whole_range, whole_range); @@ -697,7 +655,7 @@ std::pair<uint16_t, uint16_t> map_searchrandfreecell(int m, int x, int y, int ra *------------------------------------------ */ int map_addflooritem_any(struct item *item_data, int amount, - int m, int x, int y, + map_local *m, int x, int y, dumb_ptr<map_session_data> *owners, interval_t *owner_protection, interval_t lifetime, int dispersal) { @@ -762,7 +720,7 @@ int map_addflooritem_any(struct item *item_data, int amount, } int map_addflooritem(struct item *item_data, int amount, - int m, int x, int y, + map_local *m, int x, int y, dumb_ptr<map_session_data> first_sd, dumb_ptr<map_session_data> second_sd, dumb_ptr<map_session_data> third_sd) @@ -872,8 +830,7 @@ void map_quit(dumb_ptr<map_session_data> sd) else if (sd->state.storage_open) storage_storage_quit(sd); - if (sd->npc_stackbuf && sd->npc_stackbuf != NULL) - free(sd->npc_stackbuf); + sd->npc_stackbuf.clear(); map_delblock(sd); @@ -1062,30 +1019,30 @@ dumb_ptr<block_list> map_id2bl(int id) * map.npcへ追加 (warp等の領域持ちのみ) *------------------------------------------ */ -int map_addnpc(int m, dumb_ptr<npc_data> nd) +int map_addnpc(map_local *m, dumb_ptr<npc_data> nd) { int i; - if (m < 0 || m >= map_num) + if (!m) return -1; - for (i = 0; i < map[m].npc_num && i < MAX_NPC_PER_MAP; i++) - if (map[m].npc[i] == NULL) + for (i = 0; i < m->npc_num && i < MAX_NPC_PER_MAP; i++) + if (m->npc[i] == NULL) break; if (i == MAX_NPC_PER_MAP) { if (battle_config.error_log) - PRINTF("too many NPCs in one map %s\n", map[m].name); + PRINTF("too many NPCs in one map %s\n", m->name); return -1; } - if (i == map[m].npc_num) + if (i == m->npc_num) { - map[m].npc_num++; + m->npc_num++; } nullpo_ret(nd); - map[m].npc[i] = nd; + m->npc[i] = nd; nd->n = i; - id_db.put(nd->bl_id, (dumb_ptr<block_list>)nd); + id_db.put(nd->bl_id, nd); return i; } @@ -1093,23 +1050,26 @@ int map_addnpc(int m, dumb_ptr<npc_data> nd) static void map_removenpc(void) { - int i, m, n = 0; + int n = 0; - for (m = 0; m < map_num; m++) + for (auto& mitp : maps_db) { - for (i = 0; i < map[m].npc_num && i < MAX_NPC_PER_MAP; i++) + if (!mitp.second->gat) + continue; + map_local *m = static_cast<map_local *>(mitp.second.get()); + for (int i = 0; i < m->npc_num && i < MAX_NPC_PER_MAP; i++) { - if (map[m].npc[i] != NULL) + if (m->npc[i] != NULL) { - clif_clearchar(map[m].npc[i], BeingRemoveWhy::QUIT); - map_delblock(map[m].npc[i]); - id_db.put(map[m].npc[i]->bl_id, nullptr); - if (map[m].npc[i]->npc_subtype == NpcSubtype::SCRIPT) + clif_clearchar(m->npc[i], BeingRemoveWhy::QUIT); + map_delblock(m->npc[i]); + id_db.put(m->npc[i]->bl_id, nullptr); + if (m->npc[i]->npc_subtype == NpcSubtype::SCRIPT) { -// free(map[m].npc[i]->u.scr.script); -// free(map[m].npc[i]->u.scr.label_list); +// free(m->npc[i]->u.scr.script); +// free(m->npc[i]->u.scr.label_list); } - map[m].npc[i].delete_(); + m->npc[i].delete_(); n++; } } @@ -1121,12 +1081,12 @@ void map_removenpc(void) * map名からmap番号へ変換 *------------------------------------------ */ -int map_mapname2mapid(const char *name) +map_local *map_mapname2mapid(const char *name) { - struct map_data *md = map_db.get(name); + map_abstract *md = maps_db.get(name); if (md == NULL || md->gat == NULL) - return -1; - return md->m; + return nullptr; + return static_cast<map_local *>(md); } /*========================================== @@ -1135,9 +1095,10 @@ int map_mapname2mapid(const char *name) */ int map_mapname2ipport(const char *name, struct in_addr *ip, int *port) { - struct map_data_other_server *mdos = (struct map_data_other_server *)map_db.get(name); - if (mdos == NULL || mdos->gat) + map_abstract *md = maps_db.get(name); + if (md == NULL || md->gat) return -1; + map_remote *mdos = static_cast<map_remote *>(md); *ip = mdos->ip; *port = mdos->port; return 0; @@ -1219,22 +1180,22 @@ DIR map_calc_dir(dumb_ptr<block_list> src, int x, int y) * (m,x,y)の状態を調べる *------------------------------------------ */ -MapCell map_getcell(int m, int x, int y) +MapCell map_getcell(map_local *m, int x, int y) { - if (x < 0 || x >= map[m].xs - 1 || y < 0 || y >= map[m].ys - 1) + if (x < 0 || x >= m->xs - 1 || y < 0 || y >= m->ys - 1) return MapCell::UNWALKABLE; - return map[m].gat[x + y * map[m].xs]; + return m->gat[x + y * m->xs]; } /*========================================== * (m,x,y)の状態をtにする *------------------------------------------ */ -void map_setcell(int m, int x, int y, MapCell t) +void map_setcell(map_local *m, int x, int y, MapCell t) { - if (x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys) + if (x < 0 || x >= m->xs || y < 0 || y >= m->ys) return; - map[m].gat[x + y * map[m].xs] = t; + m->gat[x + y * m->xs] = t; } /*========================================== @@ -1243,17 +1204,16 @@ void map_setcell(int m, int x, int y, MapCell t) */ int map_setipport(const char *name, struct in_addr ip, int port) { - struct map_data *md = map_db.get(name); + map_abstract *md = maps_db.get(name); if (md == NULL) { - struct map_data_other_server *mdos = NULL; // not exist -> add new data - CREATE(mdos, struct map_data_other_server, 1); + auto mdos = make_unique<map_remote>(); memcpy(mdos->name, name, 24); mdos->gat = NULL; mdos->ip = ip; mdos->port = port; - map_db.put(mdos->name, (struct map_data *)mdos); + maps_db.put(mdos->name, std::move(mdos)); } else { @@ -1270,8 +1230,7 @@ int map_setipport(const char *name, struct in_addr ip, int port) else { // update - struct map_data_other_server *mdos = NULL; - mdos = (struct map_data_other_server *) md; + map_remote *mdos = static_cast<map_remote *>(md); mdos->ip = ip; mdos->port = port; } @@ -1284,7 +1243,7 @@ int map_setipport(const char *name, struct in_addr ip, int port) *------------------------------------------ */ static -bool map_readmap(int m, const_string fn) +bool map_readmap(map_local *m, size_t num, const std::string& fn) { // read & convert fn std::vector<uint8_t> gat_v = grfio_reads(fn); @@ -1292,39 +1251,27 @@ bool map_readmap(int m, const_string fn) return false; size_t s = gat_v.size() - 4; - map[m].m = m; - int xs = map[m].xs = gat_v[0] | gat_v[1] << 8; - int ys = map[m].ys = gat_v[2] | gat_v[3] << 8; - PRINTF("\rLoading Maps [%d/%d]: %-30s (%i, %i)", - m, map_num, std::string(fn.begin(), fn.end()), xs, ys); + int xs = m->xs = gat_v[0] | gat_v[1] << 8; + int ys = m->ys = gat_v[2] | gat_v[3] << 8; + PRINTF("\rLoading Maps [%zu/%zu]: %-30s (%i, %i)", + num, maps_db.size(), + std::string(fn.begin(), fn.end()), xs, ys); fflush(stdout); assert (s == xs * ys); - map[m].gat = make_unique<MapCell[]>(s); - if (map[m].gat == NULL) - { - PRINTF("out of memory : map_readmap gat\n"); - exit(1); - } + m->gat = make_unique<MapCell[]>(s); - map[m].npc_num = 0; - map[m].users = 0; - memset(&map[m].flag, 0, sizeof(map[m].flag)); + m->npc_num = 0; + m->users = 0; + memset(&m->flag, 0, sizeof(m->flag)); if (battle_config.pk_mode) - map[m].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris] + m->flag.pvp = 1; // make all maps pvp for pk_mode [Valaris] MapCell *gat_m = reinterpret_cast<MapCell *>(&gat_v[4]); - std::copy(gat_m, gat_m + s, &map[m].gat[0]); - - map[m].bxs = (xs + BLOCK_SIZE - 1) / BLOCK_SIZE; - map[m].bys = (ys + BLOCK_SIZE - 1) / BLOCK_SIZE; - size_t size = map[m].bxs * map[m].bys; + std::copy(gat_m, gat_m + s, &m->gat[0]); - CREATE(map[m].block, dumb_ptr<block_list>, size); - CREATE(map[m].block_mob, dumb_ptr<block_list>, size); - CREATE(map[m].block_count, int, size); - CREATE(map[m].block_mob_count, int, size); - - map_db.put(map[m].name, &map[m]); + size_t bxs = (xs + BLOCK_SIZE - 1) / BLOCK_SIZE; + size_t bys = (ys + BLOCK_SIZE - 1) / BLOCK_SIZE; + m->blocks.reset(bxs, bys); return true; } @@ -1336,24 +1283,35 @@ bool map_readmap(int m, const_string fn) static int map_readallmap(void) { - int i, maps_removed = 0; + int maps_removed = 0; + int num = 0; - for (i = 0; i < map_num; i++) + for (auto& mit : maps_db) { - assert (strstr(map[i].name, ".gat") != NULL); + assert (strstr(mit.second->name, ".gat") != NULL); { { - if (!map_readmap(i, map[i].name)) + map_local *ml = static_cast<map_local *>(mit.second.get()); + if (!map_readmap(ml, num, mit.first)) { - map_delmap(map[i].name); + // Can't remove while implicitly iterating, + // and I don't feel like explicitly iterating. + //map_delmap(map[i].name); maps_removed++; } + else + num++; } } } - PRINTF("\rMaps Loaded: %d %60s\n", map_num, ""); - PRINTF("\rMaps Removed: %d \n", maps_removed); + PRINTF("\rMaps Loaded: %-65zu\n", maps_db.size()); + if (maps_removed) + { + PRINTF("Cowardly refusing to keep going after removing %d maps.\n", + maps_removed); + exit(1); + } return 0; } @@ -1362,50 +1320,31 @@ int map_readallmap(void) *------------------------------------------ */ static -int map_addmap(const char *mapname) +void map_addmap(const std::string& mapname) { - if (strcasecmp(mapname, "clear") == 0) + if (mapname == "clear") { - map_num = 0; - return 0; + maps_db.clear(); + return; } - if (map_num >= MAX_MAP_PER_SERVER - 1) - { - PRINTF("too many map\n"); - return 1; - } - memcpy(map[map_num].name, mapname, 24); - map_num++; - return 0; + auto newmap = make_unique<map_local>(); + strzcpy(newmap->name, mapname.c_str(), sizeof(newmap->name)); } /*========================================== * 読み込むmapを削除する *------------------------------------------ */ -static -int map_delmap(const char *mapname) +void map_delmap(const std::string& mapname) { - int i; - - if (strcasecmp(mapname, "all") == 0) + if (mapname == "all") { - map_num = 0; - return 0; + maps_db.clear(); + return; } - for (i = 0; i < map_num; i++) - { - if (strcmp(map[i].name, mapname) == 0) - { - PRINTF("Removing map [ %s ] from maplist\n", map[i].name); - memmove(map + i, map + i + 1, - sizeof(map[0]) * (map_num - i - 1)); - map_num--; - } - } - return 0; + maps_db.put(mapname, nullptr); } constexpr int LOGFILE_SECONDS_PER_CHUNK_SHIFT = 10; @@ -1413,7 +1352,7 @@ constexpr int LOGFILE_SECONDS_PER_CHUNK_SHIFT = 10; static FILE *map_logfile = NULL; static -char *map_logfile_name = NULL; +std::string map_logfile_name; static long map_logfile_index; @@ -1454,20 +1393,20 @@ void map_start_logfile(long index) map_logfile_index); map_logfile = fopen(filename_buf.c_str(), "w+"); if (!map_logfile) - perror(map_logfile_name); + perror(map_logfile_name.c_str()); } static -void map_set_logfile(const char *filename) +void map_set_logfile(std::string filename) { struct timeval tv; - map_logfile_name = strdup(filename); + map_logfile_name = std::move(filename); gettimeofday(&tv, NULL); map_start_logfile(tv.tv_sec); - MAP_LOG("log-start v4"); + MAP_LOG("log-start v5"); } void map_log(const_string line) @@ -1523,14 +1462,16 @@ int map_config_read(const char *cfgName) if (h != NULL) { PRINTF("Character server IP address : %s -> %d.%d.%d.%d\n", - w2, (unsigned char) h->h_addr[0], - (unsigned char) h->h_addr[1], - (unsigned char) h->h_addr[2], - (unsigned char) h->h_addr[3]); - SPRINTF(w2, "%d.%d.%d.%d", (unsigned char) h->h_addr[0], - (unsigned char) h->h_addr[1], - (unsigned char) h->h_addr[2], - (unsigned char) h->h_addr[3]); + w2, + static_cast<uint8_t>(h->h_addr[0]), + static_cast<uint8_t>(h->h_addr[1]), + static_cast<uint8_t>(h->h_addr[2]), + static_cast<uint8_t>(h->h_addr[3])); + SPRINTF(w2, "%d.%d.%d.%d", + static_cast<uint8_t>(h->h_addr[0]), + static_cast<uint8_t>(h->h_addr[1]), + static_cast<uint8_t>(h->h_addr[2]), + static_cast<uint8_t>(h->h_addr[3])); } chrif_setip(w2.c_str()); } @@ -1544,14 +1485,15 @@ int map_config_read(const char *cfgName) if (h != NULL) { PRINTF("Map server IP address : %s -> %d.%d.%d.%d\n", w2, - (unsigned char) h->h_addr[0], - (unsigned char) h->h_addr[1], - (unsigned char) h->h_addr[2], - (unsigned char) h->h_addr[3]); - SPRINTF(w2, "%d.%d.%d.%d", (unsigned char) h->h_addr[0], - (unsigned char) h->h_addr[1], - (unsigned char) h->h_addr[2], - (unsigned char) h->h_addr[3]); + static_cast<uint8_t>(h->h_addr[0]), + static_cast<uint8_t>(h->h_addr[1]), + static_cast<uint8_t>(h->h_addr[2]), + static_cast<uint8_t>(h->h_addr[3])); + SPRINTF(w2, "%d.%d.%d.%d", + static_cast<uint8_t>(h->h_addr[0]), + static_cast<uint8_t>(h->h_addr[1]), + static_cast<uint8_t>(h->h_addr[2]), + static_cast<uint8_t>(h->h_addr[3])); } clif_setip(w2.c_str()); } @@ -1595,7 +1537,7 @@ int map_config_read(const char *cfgName) } else if (w1 == "gm_log") { - gm_logfile_name = strdup(w2.c_str()); + gm_logfile_name = std::move(w2); } else if (w1 == "log_file") { @@ -1643,33 +1585,26 @@ void term_func(void) { map_close_logfile(); - int map_id, i; - - for (map_id = 0; map_id < map_num; map_id++) + for (auto& mit : maps_db) { - if (map[map_id].m) - map_foreachinarea(cleanup_sub, map_id, - 0, 0, map[map_id].xs, map[map_id].ys, - BL::NUL); + if (!mit.second->gat) + continue; + map_local *map_id = static_cast<map_local *>(mit.second.get()); + + map_foreachinarea(cleanup_sub, + map_id, + 0, 0, + map_id->xs, map_id->ys, + BL::NUL); } - for (i = 0; i < fd_max; i++) + for (int i = 0; i < fd_max; i++) delete_session(i); map_removenpc(); - for (i = 0; i <= map_num; i++) - { - map[i].gat = nullptr; - if (map[i].block) - free(map[i].block); - if (map[i].block_mob) - free(map[i].block_mob); - if (map[i].block_count) - free(map[i].block_count); - if (map[i].block_mob_count) - free(map[i].block_mob_count); - } + maps_db.clear(); + do_final_script(); do_final_itemdb(); do_final_storage(); diff --git a/src/map/map.hpp b/src/map/map.hpp index cb2513a..c004315 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -8,6 +8,7 @@ #include <functional> #include "../common/db.hpp" +#include "../common/matrix.hpp" #include "../common/socket.hpp" #include "../common/timer.t.hpp" @@ -22,7 +23,6 @@ constexpr int BLOCK_SIZE = 8; #define AREA_SIZE battle_config.area_size constexpr std::chrono::seconds LIFETIME_FLOORITEM = std::chrono::minutes(1); constexpr int DAMAGELOG_SIZE = 30; -constexpr int LOOTITEM_SIZE = 10; constexpr int MAX_SKILL_LEVEL = 100; constexpr int MAX_MOBSKILL = 32; constexpr int MAX_EVENTQUEUE = 2; @@ -40,12 +40,14 @@ struct npc_data; struct mob_data; struct flooritem_data; struct invocation; +struct map_local; struct block_list { dumb_ptr<block_list> bl_next, bl_prev; int bl_id; - short bl_m, bl_x, bl_y; + map_local *bl_m; + short bl_x, bl_y; BL bl_type; // This deletes the copy-ctor also @@ -153,12 +155,14 @@ struct map_session_data : block_list, SessionData struct walkpath_data walkpath; Timer walktimer; int npc_id, areanpc_id, npc_shopid; + // this is important int npc_pos; int npc_menu; int npc_amount; - int npc_stack, npc_stackmax; - const ScriptCode *npc_script, *npc_scriptroot; - struct script_data *npc_stackbuf; + // I have no idea exactly what these are doing ... + // but one should probably be replaced with a ScriptPointer ??? + const ScriptBuffer *npc_script, *npc_scriptroot; + std::vector<struct script_data> npc_stackbuf; char npc_str[256]; struct { @@ -229,10 +233,10 @@ struct map_session_data : block_list, SessionData int die_counter; - int reg_num; - struct script_reg *reg; - int regstr_num; - struct script_regstr *regstr; + // register keys are ints (interned) + DMap<int, int> regm; + // can't be DMap because we want predictable .c_str()s + Map<int, std::string> regstrm; earray<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; short sc_count; @@ -262,13 +266,6 @@ struct map_session_data : block_list, SessionData struct { - char name[24]; - } ignore[80]; - int ignoreAll; - short sg_count; - - struct - { unsigned in_progress:1; } auto_ban_info; @@ -339,16 +336,25 @@ class npc_data_script : public npc_data public: struct { - const ScriptCode *script; + // The bytecode unique to this NPC. + std::unique_ptr<const ScriptBuffer> script; + // Diameter. short xs, ys; + // Tick counter through the timers. + // It is actually updated when frobbing the thing in any way. + // If this is timer_eventv().back().timer, it is expired + // rather than blank. It's probably a bad idea to rely on this. interval_t timer; + // Actual timer that fires the event. Timer timerid; - int timeramount, nexttimer; + // Event to be fired, or .end() if no timer. + std::vector<npc_timerevent_list>::iterator nexttimer; + // When the timer started. Needed to get the true diff, or to stop. tick_t timertick; - struct npc_timerevent_list *timer_event; - int label_list_num; - struct npc_label_list *label_list; - int src_id; + // List of label events to call. + std::vector<npc_timerevent_list> timer_eventv; + // List of (name, offset) label locations in the bytecode + std::vector<npc_label_list> label_listv; } scr; }; @@ -372,7 +378,7 @@ public: class npc_data_message : public npc_data { public: - char *message; + std::string message; }; constexpr int MOB_XP_BONUS_BASE = 1024; @@ -384,9 +390,13 @@ struct mob_data : block_list short mob_class; DIR dir; MobMode mode; - short m, x0, y0, xs, ys; + struct + { + map_local *m; + short x0, y0, xs, ys; + interval_t delay1, delay2; + } spawn; char name[24]; - interval_t spawndelay1, spawndelay2; struct { MS state; @@ -416,8 +426,7 @@ struct mob_data : block_list int id; int dmg; } dmglog[DAMAGELOG_SIZE]; - struct item *lootitem; - short lootitem_count; + std::vector<struct item> lootitemv; earray<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data; short sc_count; @@ -426,7 +435,6 @@ struct mob_data : block_list Opt3 opt3; Option option; short min_chase; - short sg_count; Timer deletetimer; Timer skilltimer; @@ -444,18 +452,28 @@ struct mob_data : block_list short size; }; -struct map_data +struct BlockLists { + dumb_ptr<block_list> normal, mobs_only; +}; + +struct map_abstract +{ + // shouldn't this be 16? + // but beware of hard-coded memcpys char name[24]; - char alias[24]; // [MouseJstr] - // if NULL, actually a map_data_other_server + // gat is NULL for map_remote and non-NULL or map_local std::unique_ptr<MapCell[]> gat; - dumb_ptr<block_list> *block; - dumb_ptr<block_list> *block_mob; - int *block_count, *block_mob_count; - int m; + + virtual ~map_abstract() {}; +}; +extern +UPMap<std::string, map_abstract> maps_db; + +struct map_local : map_abstract +{ + Matrix<BlockLists> blocks; short xs, ys; - short bxs, bys; int npc_num; int users; struct @@ -494,27 +512,18 @@ struct map_data int drop_per; } drop_list[MAX_DROP_PER_MAP]; }; -struct map_data_other_server + +struct map_remote : map_abstract { - char name[24]; - unsigned char *gat; // NULL固定にして判断 struct in_addr ip; unsigned int port; }; -extern struct map_data map[]; -extern int map_num; - inline -MapCell read_gatp(struct map_data *m, int x, int y) +MapCell read_gatp(map_local *m, int x, int y) { return m->gat[x + y * m->xs]; } -inline -MapCell read_gat(int m, int x, int y) -{ - return read_gatp(&map[m], x, y); -} struct flooritem_data : block_list { @@ -552,21 +561,21 @@ public: int map_addblock(dumb_ptr<block_list>); int map_delblock(dumb_ptr<block_list>); void map_foreachinarea(std::function<void(dumb_ptr<block_list>)>, - int, + map_local *, int, int, int, int, BL); // -- moonsoul (added map_foreachincell) void map_foreachincell(std::function<void(dumb_ptr<block_list>)>, - int, + map_local *, int, int, BL); void map_foreachinmovearea(std::function<void(dumb_ptr<block_list>)>, - int, + map_local *, int, int, int, int, int, int, BL); //block関連に追加 -int map_count_oncell(int m, int x, int y); +int map_count_oncell(map_local *m, int x, int y); // 一時的object関連 int map_addobject(dumb_ptr<block_list>); int map_delobject(int, BL type); @@ -576,15 +585,15 @@ void map_foreachobject(std::function<void(dumb_ptr<block_list>)>, // void map_quit(dumb_ptr<map_session_data>); // npc -int map_addnpc(int, dumb_ptr<npc_data>); +int map_addnpc(map_local *, dumb_ptr<npc_data>); void map_log(const_string line); #define MAP_LOG(format, ...) \ map_log(static_cast<const std::string&>(STRPRINTF(format, ## __VA_ARGS__))) #define MAP_LOG_PC(sd, fmt, ...) \ - MAP_LOG("PC%d %d:%d,%d " fmt, \ - sd->status.char_id, sd->bl_m, sd->bl_x, sd->bl_y, ## __VA_ARGS__) + MAP_LOG("PC%d %s:%d,%d " fmt, \ + sd->status.char_id, sd->bl_m->name, sd->bl_x, sd->bl_y, ## __VA_ARGS__) // 床アイテム関連 void map_clearflooritem_timer(TimerData *, tick_t, int); @@ -593,10 +602,12 @@ void map_clearflooritem(int id) { map_clearflooritem_timer(nullptr, tick_t(), id); } -int map_addflooritem_any(struct item *, int amount, int m, int x, int y, +int map_addflooritem_any(struct item *, int amount, + map_local *m, int x, int y, dumb_ptr<map_session_data> *owners, interval_t *owner_protection, interval_t lifetime, int dispersal); -int map_addflooritem(struct item *, int, int, int, int, +int map_addflooritem(struct item *, int, + map_local *, int, int, dumb_ptr<map_session_data>, dumb_ptr<map_session_data>, dumb_ptr<map_session_data>); @@ -672,7 +683,7 @@ dumb_ptr<invocation> map_id_is_spell(int id) } -int map_mapname2mapid(const char *); +map_local *map_mapname2mapid(const char *); int map_mapname2ipport(const char *, struct in_addr *, int *); int map_setipport(const char *name, struct in_addr ip, int port); void map_addiddb(dumb_ptr<block_list>); @@ -690,17 +701,15 @@ dumb_ptr<map_session_data> map_get_prev_session( dumb_ptr<map_session_data> current); // gat関連 -MapCell map_getcell(int, int, int); -void map_setcell(int, int, int, MapCell); +MapCell map_getcell(map_local *, int, int); +void map_setcell(map_local *, int, int, MapCell); // その他 bool map_check_dir(DIR s_dir, DIR t_dir); DIR map_calc_dir(dumb_ptr<block_list> src, int x, int y); -// path.cより -int path_search(struct walkpath_data *, int, int, int, int, int, int); - -std::pair<uint16_t, uint16_t> map_randfreecell(int m, uint16_t x, uint16_t y, uint16_t w, uint16_t h); +std::pair<uint16_t, uint16_t> map_randfreecell(map_local *m, + uint16_t x, uint16_t y, uint16_t w, uint16_t h); inline dumb_ptr<map_session_data> block_list::as_player() { return dumb_ptr<map_session_data>(static_cast<map_session_data *>(this)) ; } inline dumb_ptr<npc_data> block_list::as_npc() { return dumb_ptr<npc_data>(static_cast<npc_data *>(this)) ; } diff --git a/src/map/mob.cpp b/src/map/mob.cpp index 828bca5..e4520d0 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -20,6 +20,7 @@ #include "map.hpp" #include "npc.hpp" #include "party.hpp" +#include "path.hpp" #include "pc.hpp" #include "skill.hpp" @@ -289,12 +290,11 @@ int mob_gen_exp(struct mob_db *mob) bool(mob->mode & MobMode::AGGRESSIVE) ? 10.0 / 9.0 : 1.0; - int xp = - (int) floor(effective_hp * - pow(sqrt(attack_factor) + sqrt(dodge_factor) + - sqrt(persuit_factor) + 55, - 3) * aggression_factor / 2000000.0 * - (double) battle_config.base_exp_rate / 100.); + int xp = floor(effective_hp * pow(sqrt(attack_factor) + + sqrt(dodge_factor) + + sqrt(persuit_factor) + 55, 3) + * aggression_factor / 2000000.0 + * static_cast<double>(battle_config.base_exp_rate) / 100.); if (xp < 1) xp = 1; PRINTF("Exp for mob '%s' generated: %d\n", mob->name, xp); @@ -371,14 +371,15 @@ int mob_once_spawn(dumb_ptr<map_session_data> sd, const char *mapname, const char *event) { dumb_ptr<mob_data> md = NULL; - int m, count, r = mob_class; + map_local *m; + int count, r = mob_class; if (sd && strcmp(mapname, "this") == 0) m = sd->bl_m; else m = map_mapname2mapid(mapname); - if (m < 0 || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000) // 値が異常なら召喚を止める + if (m == nullptr || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000) // 値が異常なら召喚を止める return 0; if (sd) @@ -396,11 +397,7 @@ int mob_once_spawn(dumb_ptr<map_session_data> sd, const char *mapname, for (count = 0; count < amount; count++) { md.new_(); - if (bool(mob_db[mob_class].mode & MobMode::LOOTER)) - md->lootitem = - (struct item *) calloc(LOOTITEM_SIZE, sizeof(struct item)); - else - md->lootitem = NULL; + md->lootitemv.clear(); mob_spawn_dataset(md, mobname, mob_class); md->bl_m = m; @@ -409,13 +406,13 @@ int mob_once_spawn(dumb_ptr<map_session_data> sd, const char *mapname, if (r < 0 && battle_config.dead_branch_active == 1) //移動してアクティブで反撃する md->mode = MobMode::war; - md->m = m; - md->x0 = x; - md->y0 = y; - md->xs = 0; - md->ys = 0; - md->spawndelay1 = static_cast<interval_t>(-1); // Only once is a flag. - md->spawndelay2 = static_cast<interval_t>(-1); // Only once is a flag. + md->spawn.m = m; + md->spawn.x0 = x; + md->spawn.y0 = y; + md->spawn.xs = 0; + md->spawn.ys = 0; + md->spawn.delay1 = static_cast<interval_t>(-1); // Only once is a flag. + md->spawn.delay2 = static_cast<interval_t>(-1); // Only once is a flag. memcpy(md->npc_event, event, sizeof(md->npc_event)); @@ -436,7 +433,7 @@ int mob_once_spawn_area(dumb_ptr<map_session_data> sd, const char *mapname, const char *event) { int x, y, i, max, lx = -1, ly = -1, id = 0; - int m; + map_local *m; if (strcmp(mapname, "this") == 0) m = sd->bl_m; @@ -447,7 +444,7 @@ int mob_once_spawn_area(dumb_ptr<map_session_data> sd, const char *mapname, if (max > 1000) max = 1000; - if (m < 0 || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000) // A summon is stopped if a value is unusual + if (m == nullptr || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000) // A summon is stopped if a value is unusual return 0; for (i = 0; i < amount; i++) @@ -618,9 +615,11 @@ int mob_walk(dumb_ptr<mob_data> md, tick_t tick, unsigned char data) md->state.state = MS::WALK; map_foreachinmovearea(std::bind(clif_moboutsight, ph::_1, md), - md->bl_m, x - AREA_SIZE, y - AREA_SIZE, + md->bl_m, + x - AREA_SIZE, y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE, - dx, dy, BL::PC); + dx, dy, + BL::PC); x += dx; y += dy; @@ -635,9 +634,11 @@ int mob_walk(dumb_ptr<mob_data> md, tick_t tick, unsigned char data) map_addblock(md); map_foreachinmovearea(std::bind(clif_mobinsight, ph::_1, md), - md->bl_m, x - AREA_SIZE, y - AREA_SIZE, + md->bl_m, + x - AREA_SIZE, y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE, - -dx, -dy, BL::PC); + -dx, -dy, + BL::PC); md->state.state = MS::IDLE; } interval_t i = calc_next_walk_step(md); @@ -789,10 +790,12 @@ int mob_attack(dumb_ptr<mob_data> md, tick_t tick) // If you are reading this, please note: // it is highly platform-specific that this even works at all. int radius = battle_config.mob_splash_radius; - if (radius >= 0 && tbl->bl_type == BL::PC && !map[tbl->bl_m].flag.town) + if (radius >= 0 && tbl->bl_type == BL::PC && !tbl->bl_m->flag.town) map_foreachinarea(std::bind(mob_ancillary_attack, ph::_1, md, tbl, tick), - tbl->bl_m, tbl->bl_x - radius, tbl->bl_y - radius, - tbl->bl_x + radius, tbl->bl_y + radius, BL::PC); + tbl->bl_m, + tbl->bl_x - radius, tbl->bl_y - radius, + tbl->bl_x + radius, tbl->bl_y + radius, + BL::PC); md->attackabletime = tick + battle_get_adelay(md); @@ -1016,22 +1019,18 @@ int mob_setdelayspawn(int id) return -1; // Processing of MOB which is not revitalized - if (md->spawndelay1 == static_cast<interval_t>(-1) - && md->spawndelay2 == static_cast<interval_t>(-1) + if (md->spawn.delay1 == static_cast<interval_t>(-1) + && md->spawn.delay2 == static_cast<interval_t>(-1) && md->n == 0) { map_deliddb(md); - if (md->lootitem) - { - free(md->lootitem); - md->lootitem = NULL; - } + md->lootitemv.clear(); MapBlockLock::freeblock(md); return 0; } - tick_t spawntime1 = md->last_spawntime + md->spawndelay1; - tick_t spawntime2 = md->last_deadtime + md->spawndelay2; + tick_t spawntime1 = md->last_spawntime + md->spawn.delay1; + tick_t spawntime2 = md->last_deadtime + md->spawn.delay2; tick_t spawntime3 = gettick() + std::chrono::seconds(5); tick_t spawntime = std::max({spawntime1, spawntime2, spawntime3}); @@ -1071,22 +1070,22 @@ int mob_spawn(int id) map_delblock(md); } - md->bl_m = md->m; + md->bl_m = md->spawn.m; { int i = 0; do { - if (md->x0 == 0 && md->y0 == 0) + if (md->spawn.x0 == 0 && md->spawn.y0 == 0) { - x = random_::in(1, map[md->bl_m].xs - 2); - y = random_::in(1, map[md->bl_m].ys - 2); + x = random_::in(1, md->bl_m->xs - 2); + y = random_::in(1, md->bl_m->ys - 2); } else { // TODO: move this logic earlier - possibly all the way // into the data files - x = md->x0 - md->xs / 2 + random_::in(0, md->xs); - y = md->y0 - md->ys / 2 + random_::in(0, md->ys); + x = md->spawn.x0 - md->spawn.xs / 2 + random_::in(0, md->spawn.xs); + y = md->spawn.y0 - md->spawn.ys / 2 + random_::in(0, md->spawn.ys); } i++; } @@ -1131,7 +1130,6 @@ int mob_spawn(int id) md->attackabletime = tick; md->canmove_tick = tick; - md->sg_count = 0; // md->deletetimer = nullptr; // md->skilltimer = nullptr; @@ -1141,9 +1139,7 @@ int mob_spawn(int id) md->skilllv = 0; memset(md->dmglog, 0, sizeof(md->dmglog)); - if (md->lootitem) - memset(md->lootitem, 0, sizeof(*md->lootitem)); - md->lootitem_count = 0; + md->lootitemv.clear(); for (StatusChange i : erange(StatusChange(), StatusChange::MAX_STATUSCHANGE)) { @@ -1470,10 +1466,6 @@ void mob_ai_sub_hard_lootsearch(dumb_ptr<block_list> bl, dumb_ptr<mob_data> md, if (!md->target_id && bool(mode & MobMode::LOOTER)) { - if (!md->lootitem - || (battle_config.monster_loot_type == 1 - && md->lootitem_count >= LOOTITEM_SIZE)) - return; if (bl->bl_m == md->bl_m && (dist = distance(md->bl_x, md->bl_y, bl->bl_x, bl->bl_y)) < 9) { @@ -1560,7 +1552,7 @@ int mob_ai_sub_hard_slavemob(dumb_ptr<mob_data> md, tick_t tick) // Since the master was in near immediately before, teleport is carried out and it pursues. if (old_dist < 10 && md->master_dist > 18) { - mob_warp(md, -1, mmd->bl_x, mmd->bl_y, BeingRemoveWhy::WARPED); + mob_warp(md, nullptr, mmd->bl_x, mmd->bl_y, BeingRemoveWhy::WARPED); md->state.master_check = 1; return 0; } @@ -1779,8 +1771,10 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) if (!asd->invincible_timer && !pc_isinvisible(asd)) { map_foreachinarea(std::bind(mob_ai_sub_hard_linksearch, ph::_1, md, asd), - md->bl_m, md->bl_x - 13, md->bl_y - 13, - md->bl_x + 13, md->bl_y + 13, BL::MOB); + md->bl_m, + md->bl_x - 13, md->bl_y - 13, + md->bl_x + 13, md->bl_y + 13, + BL::MOB); } } } @@ -1829,15 +1823,18 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) if (md->state.special_mob_ai) { map_foreachinarea(std::bind(mob_ai_sub_hard_activesearch, ph::_1, md, &i), - md->bl_m, md->bl_x - AREA_SIZE * 2, md->bl_y - AREA_SIZE * 2, + md->bl_m, + md->bl_x - AREA_SIZE * 2, md->bl_y - AREA_SIZE * 2, md->bl_x + AREA_SIZE * 2, md->bl_y + AREA_SIZE * 2, BL::NUL); } else { map_foreachinarea(std::bind(mob_ai_sub_hard_activesearch, ph::_1, md, &i), - md->bl_m, md->bl_x - AREA_SIZE * 2, md->bl_y - AREA_SIZE * 2, - md->bl_x + AREA_SIZE * 2, md->bl_y + AREA_SIZE * 2, BL::PC); + md->bl_m, + md->bl_x - AREA_SIZE * 2, md->bl_y - AREA_SIZE * 2, + md->bl_x + AREA_SIZE * 2, md->bl_y + AREA_SIZE * 2, + BL::PC); } } @@ -1848,8 +1845,10 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) { i = 0; map_foreachinarea(std::bind(mob_ai_sub_hard_lootsearch, ph::_1, md, &i), - md->bl_m, md->bl_x - AREA_SIZE * 2, md->bl_y - AREA_SIZE * 2, - md->bl_x + AREA_SIZE * 2, md->bl_y + AREA_SIZE * 2, BL::ITEM); + md->bl_m, + md->bl_x - AREA_SIZE * 2, md->bl_y - AREA_SIZE * 2, + md->bl_x + AREA_SIZE * 2, md->bl_y + AREA_SIZE * 2, + BL::ITEM); } // It will attack, if the candidate for an attack is. @@ -1955,7 +1954,8 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) if (tbl == NULL || tbl->bl_type != BL::ITEM || tbl->bl_m != md->bl_m || (dist = distance(md->bl_x, md->bl_y, tbl->bl_x, - tbl->bl_y)) >= md->min_chase || !md->lootitem) + tbl->bl_y)) >= md->min_chase + || !bool(mob_db[md->mob_class].mode & MobMode::LOOTER)) { // 遠すぎるかアイテムがなくなった mob_unlocktarget(md, tick); @@ -1991,23 +1991,7 @@ void mob_ai_sub_hard(dumb_ptr<block_list> bl, tick_t tick) if (md->state.state == MS::WALK) mob_stop_walking(md, 1); // 歩行中なら停止 fitem = tbl->as_item(); - if (md->lootitem_count < LOOTITEM_SIZE) - memcpy(&md->lootitem[md->lootitem_count++], - &fitem->item_data, sizeof(md->lootitem[0])); - else if (battle_config.monster_loot_type == 1 - && md->lootitem_count >= LOOTITEM_SIZE) - { - mob_unlocktarget(md, tick); - return; - } - else - { - for (i = 0; i < LOOTITEM_SIZE - 1; i++) - memcpy(&md->lootitem[i], &md->lootitem[i + 1], - sizeof(md->lootitem[0])); - memcpy(&md->lootitem[LOOTITEM_SIZE - 1], - &fitem->item_data, sizeof(md->lootitem[0])); - } + md->lootitemv.push_back(fitem->item_data); map_clearflooritem(tbl->bl_id); mob_unlocktarget(md, tick); } @@ -2064,8 +2048,10 @@ void mob_ai_sub_foreachclient(dumb_ptr<map_session_data> sd, tick_t tick) nullpo_retv(sd); map_foreachinarea(std::bind(mob_ai_sub_hard, ph::_1, tick), - sd->bl_m, sd->bl_x - AREA_SIZE * 2, sd->bl_y - AREA_SIZE * 2, - sd->bl_x + AREA_SIZE * 2, sd->bl_y + AREA_SIZE * 2, BL::MOB); + sd->bl_m, + sd->bl_x - AREA_SIZE * 2, sd->bl_y - AREA_SIZE * 2, + sd->bl_x + AREA_SIZE * 2, sd->bl_y + AREA_SIZE * 2, + BL::MOB); } /*========================================== @@ -2108,7 +2094,7 @@ void mob_ai_sub_lazy(dumb_ptr<block_list> bl, tick_t tick) && mob_can_move(md)) { - if (map[md->bl_m].users > 0) + if (md->bl_m->users > 0) { // Since PC is in the same map, somewhat better negligent processing is carried out. @@ -2118,7 +2104,7 @@ void mob_ai_sub_lazy(dumb_ptr<block_list> bl, tick_t tick) // MOB which is not not the summons MOB but BOSS, either sometimes reboils. else if (random_::chance(MOB_LAZYWARPPERC) - && md->x0 <= 0 + && md->spawn.x0 <= 0 && md->master_id != 0 && !bool(mob_db[md->mob_class].mode & MobMode::BOSS)) mob_spawn(md->bl_id); @@ -2130,10 +2116,10 @@ void mob_ai_sub_lazy(dumb_ptr<block_list> bl, tick_t tick) // MOB which is not BOSS which is not Summons MOB, either -- a case -- sometimes -- leaping if (random_::chance(MOB_LAZYWARPPERC) - && md->x0 <= 0 + && md->spawn.x0 <= 0 && md->master_id != 0 && !bool(mob_db[md->mob_class].mode & MobMode::BOSS)) - mob_warp(md, -1, -1, -1, BeingRemoveWhy::NEGATIVE1); + mob_warp(md, nullptr, -1, -1, BeingRemoveWhy::NEGATIVE1); } md->next_walktime = tick + std::chrono::seconds(5) + std::chrono::milliseconds(random_::to(10 * 1000)); @@ -2159,14 +2145,16 @@ void mob_ai_lazy(TimerData *, tick_t tick) */ struct delay_item_drop { - int m, x, y; + map_local *m; + int x, y; int nameid, amount; dumb_ptr<map_session_data> first_sd, second_sd, third_sd; }; struct delay_item_drop2 { - int m, x, y; + map_local *m; + int x, y; struct item item_data; dumb_ptr<map_session_data> first_sd, second_sd, third_sd; }; @@ -2176,39 +2164,33 @@ struct delay_item_drop2 *------------------------------------------ */ static -void mob_delay_item_drop(TimerData *, tick_t, struct delay_item_drop *ditem) +void mob_delay_item_drop(TimerData *, tick_t, struct delay_item_drop ditem) { - struct item temp_item; + struct item temp_item {}; PickupFail flag; - nullpo_retv(ditem); - - memset(&temp_item, 0, sizeof(temp_item)); - temp_item.nameid = ditem->nameid; - temp_item.amount = ditem->amount; + temp_item.nameid = ditem.nameid; + temp_item.amount = ditem.amount; temp_item.identify = !itemdb_isequip3(temp_item.nameid); if (battle_config.item_auto_get == 1) { - if (ditem->first_sd + if (ditem.first_sd && (flag = - pc_additem(ditem->first_sd, &temp_item, ditem->amount)) + pc_additem(ditem.first_sd, &temp_item, ditem.amount)) != PickupFail::OKAY) { - clif_additem(ditem->first_sd, 0, 0, flag); + clif_additem(ditem.first_sd, 0, 0, flag); map_addflooritem(&temp_item, 1, - ditem->m, ditem->x, ditem->y, - ditem->first_sd, ditem->second_sd, ditem->third_sd); + ditem.m, ditem.x, ditem.y, + ditem.first_sd, ditem.second_sd, ditem.third_sd); } - free(ditem); return; } map_addflooritem(&temp_item, 1, - ditem->m, ditem->x, ditem->y, - ditem->first_sd, ditem->second_sd, ditem->third_sd); - - free(ditem); + ditem.m, ditem.x, ditem.y, + ditem.first_sd, ditem.second_sd, ditem.third_sd); } /*========================================== @@ -2216,34 +2198,29 @@ void mob_delay_item_drop(TimerData *, tick_t, struct delay_item_drop *ditem) *------------------------------------------ */ static -void mob_delay_item_drop2(TimerData *, tick_t, struct delay_item_drop2 *ditem) +void mob_delay_item_drop2(TimerData *, tick_t, struct delay_item_drop2 ditem) { PickupFail flag; - nullpo_retv(ditem); - if (battle_config.item_auto_get == 1) { - if (ditem->first_sd + if (ditem.first_sd && (flag = - pc_additem(ditem->first_sd, &ditem->item_data, - ditem->item_data.amount)) + pc_additem(ditem.first_sd, &ditem.item_data, + ditem.item_data.amount)) != PickupFail::OKAY) { - clif_additem(ditem->first_sd, 0, 0, flag); - map_addflooritem(&ditem->item_data, ditem->item_data.amount, - ditem->m, ditem->x, ditem->y, - ditem->first_sd, ditem->second_sd, ditem->third_sd); + clif_additem(ditem.first_sd, 0, 0, flag); + map_addflooritem(&ditem.item_data, ditem.item_data.amount, + ditem.m, ditem.x, ditem.y, + ditem.first_sd, ditem.second_sd, ditem.third_sd); } - free(ditem); return; } - map_addflooritem(&ditem->item_data, ditem->item_data.amount, - ditem->m, ditem->x, ditem->y, - ditem->first_sd, ditem->second_sd, ditem->third_sd); - - free(ditem); + map_addflooritem(&ditem.item_data, ditem.item_data.amount, + ditem.m, ditem.x, ditem.y, + ditem.first_sd, ditem.second_sd, ditem.third_sd); } /*========================================== @@ -2313,8 +2290,10 @@ int mob_deleteslave(dumb_ptr<mob_data> md) nullpo_ret(md); map_foreachinarea(std::bind(mob_deleteslave_sub, ph::_1, md->bl_id), - md->bl_m, 0, 0, - map[md->bl_m].xs, map[md->bl_m].ys, BL::MOB); + md->bl_m, + 0, 0, + md->bl_m->xs, md->bl_m->ys, + BL::MOB); return 0; } @@ -2519,7 +2498,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, if (tmpsd[i]->bl_m != md->bl_m || pc_isdead(tmpsd[i])) continue; - tdmg += (double) md->dmglog[i].dmg; + tdmg += md->dmglog[i].dmg; if (mvp_damage < md->dmglog[i].dmg) { third_sd = second_sd; @@ -2530,7 +2509,7 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, } // [MouseJstr] - if ((map[md->bl_m].flag.pvp == 0) || (battle_config.pvp_exp == 1)) + if ((md->bl_m->flag.pvp == 0) || (battle_config.pvp_exp == 1)) { // 経験値の分配 for (int i = 0; i < DAMAGELOG_SIZE; i++) @@ -2541,21 +2520,10 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, struct party *p; if (tmpsd[i] == NULL || tmpsd[i]->bl_m != md->bl_m) continue; -/* jAthena's exp formula - per = ((double)md->dmglog[i].dmg)* (9.+(double)((count > 6)? 6:count))/10./((double)max_hp) * dmg_rate; - temp = ((double)mob_db[md->mob_class].base_exp * (double)battle_config.base_exp_rate / 100. * per); - base_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp; - if (mob_db[md->mob_class].base_exp > 0 && base_exp < 1) base_exp = 1; - if (base_exp < 0) base_exp = 0; - temp = ((double)mob_db[md->mob_class].job_exp * (double)battle_config.job_exp_rate / 100. * per); - job_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp; - if (mob_db[md->mob_class].job_exp > 0 && job_exp < 1) job_exp = 1; - if (job_exp < 0) job_exp = 0; -*/ -//eAthena's exp formula rather than jAthena's -// per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/(double)max_hp; // [Fate] The above is the old formula. We do a more involved computation below. - per = (double) md->dmglog[i].dmg * 256 / (double) max_hp; // 256 = 100% of the score + // [o11c] Look in git history for old code, you idiot! + // 256 = 100% of the score + per = static_cast<double>(md->dmglog[i].dmg) * 256 / static_cast<double>(max_hp); per *= damage_bonus_factor[count > DAMAGE_BONUS_COUNT ? DAMAGE_BONUS_COUNT : count]; // Bonus for party attack if (per > 512) per = 512; // [Fate] Retained from before. The maximum a single individual can get is double the original value. @@ -2626,8 +2594,6 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, { for (int i = 0; i < 8; i++) { - struct delay_item_drop *ditem; - if (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) // Added [Valaris] break; // End @@ -2642,42 +2608,38 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, if (!random_::chance(drop_rate)) continue; - ditem = (struct delay_item_drop *) - calloc(1, sizeof(struct delay_item_drop)); - ditem->nameid = mob_db[md->mob_class].dropitem[i].nameid; - ditem->amount = 1; - ditem->m = md->bl_m; - ditem->x = md->bl_x; - ditem->y = md->bl_y; - ditem->first_sd = mvp_sd; - ditem->second_sd = second_sd; - ditem->third_sd = third_sd; + struct delay_item_drop ditem {}; + ditem.nameid = mob_db[md->mob_class].dropitem[i].nameid; + ditem.amount = 1; + ditem.m = md->bl_m; + ditem.x = md->bl_x; + ditem.y = md->bl_y; + ditem.first_sd = mvp_sd; + ditem.second_sd = second_sd; + ditem.third_sd = third_sd; Timer(tick + std::chrono::milliseconds(500) + static_cast<interval_t>(i), std::bind(mob_delay_item_drop, ph::_1, ph::_2, ditem) ).detach(); } - if (md->lootitem) { - for (int i = 0; i < md->lootitem_count; i++) + int i = 0; + for (struct item lit : md->lootitemv) { - struct delay_item_drop2 *ditem; - - ditem = (struct delay_item_drop2 *) - calloc(1, sizeof(struct delay_item_drop2)); - memcpy(&ditem->item_data, &md->lootitem[i], - sizeof(md->lootitem[0])); - ditem->m = md->bl_m; - ditem->x = md->bl_x; - ditem->y = md->bl_y; - ditem->first_sd = mvp_sd; - ditem->second_sd = second_sd; - ditem->third_sd = third_sd; + struct delay_item_drop2 ditem {}; + ditem.item_data = lit; + ditem.m = md->bl_m; + ditem.x = md->bl_x; + ditem.y = md->bl_y; + ditem.first_sd = mvp_sd; + ditem.second_sd = second_sd; + ditem.third_sd = third_sd; // ? Timer(tick + std::chrono::milliseconds(540) + static_cast<interval_t>(i), std::bind(mob_delay_item_drop2, ph::_1, ph::_2, ditem) ).detach(); + i++; } } } @@ -2748,7 +2710,7 @@ void mob_warpslave_sub(dumb_ptr<block_list> bl, int id, int x, int y) if (md->master_id == id) { - mob_warp(md, -1, x, y, BeingRemoveWhy::QUIT); + mob_warp(md, nullptr, x, y, BeingRemoveWhy::QUIT); } } @@ -2761,8 +2723,10 @@ int mob_warpslave(dumb_ptr<mob_data> md, int x, int y) { //PRINTF("warp slave\n"); map_foreachinarea(std::bind(mob_warpslave_sub, ph::_1, md->bl_id, md->bl_x, md->bl_y), - md->bl_m, x - AREA_SIZE, y - AREA_SIZE, - x + AREA_SIZE, y + AREA_SIZE, BL::MOB); + md->bl_m, + x - AREA_SIZE, y - AREA_SIZE, + x + AREA_SIZE, y + AREA_SIZE, + BL::MOB); return 0; } @@ -2770,7 +2734,7 @@ int mob_warpslave(dumb_ptr<mob_data> md, int x, int y) * mobワープ *------------------------------------------ */ -int mob_warp(dumb_ptr<mob_data> md, int m, int x, int y, BeingRemoveWhy type) +int mob_warp(dumb_ptr<mob_data> md, map_local *m, int x, int y, BeingRemoveWhy type) { int i = 0, xs = 0, ys = 0, bx = x, by = y; @@ -2779,12 +2743,12 @@ int mob_warp(dumb_ptr<mob_data> md, int m, int x, int y, BeingRemoveWhy type) if (md->bl_prev == NULL) return 0; - if (m < 0) + if (m == nullptr) m = md->bl_m; if (type != BeingRemoveWhy::NEGATIVE1) { - if (map[md->bl_m].flag.monster_noteleport) + if (md->bl_m->flag.monster_noteleport) return 0; clif_clearchar(md, type); } @@ -2797,7 +2761,7 @@ int mob_warp(dumb_ptr<mob_data> md, int m, int x, int y, BeingRemoveWhy type) while ((x < 0 || y < 0 - || bool(read_gat(m, x, y) & MapCell::UNWALKABLE)) + || bool(read_gatp(m, x, y) & MapCell::UNWALKABLE)) && (i++) < 1000) { if (xs > 0 && ys > 0 && i < 250) @@ -2809,8 +2773,8 @@ int mob_warp(dumb_ptr<mob_data> md, int m, int x, int y, BeingRemoveWhy type) else { // 完全ランダム探索 - x = random_::in(1, map[m].xs - 2); - y = random_::in(1, map[m].ys - 2); + x = random_::in(1, m->xs - 2); + y = random_::in(1, m->ys - 2); } } md->dir = DIR::S; @@ -2878,8 +2842,10 @@ int mob_countslave(dumb_ptr<mob_data> md) nullpo_ret(md); map_foreachinarea(std::bind(mob_countslave_sub, ph::_1, md->bl_id, &c), - md->bl_m, 0, 0, - map[md->bl_m].xs - 1, map[md->bl_m].ys - 1, BL::MOB); + md->bl_m, + 0, 0, + md->bl_m->xs - 1, md->bl_m->ys - 1, + BL::MOB); return c; } @@ -2890,14 +2856,14 @@ int mob_countslave(dumb_ptr<mob_data> md) int mob_summonslave(dumb_ptr<mob_data> md2, int *value, int amount, int flag) { dumb_ptr<mob_data> md; - int bx, by, m, count = 0, mob_class, k, a = amount; + int bx, by, count = 0, mob_class, k, a = amount; nullpo_ret(md2); nullpo_ret(value); bx = md2->bl_x; by = md2->bl_y; - m = md2->bl_m; + map_local *m = md2->bl_m; if (value[0] <= 1000 || value[0] > 2000) // 値が異常なら召喚を止める return 0; @@ -2917,10 +2883,7 @@ int mob_summonslave(dumb_ptr<mob_data> md2, int *value, int amount, int flag) int x = 0, y = 0, i = 0; md.new_(); if (bool(mob_db[mob_class].mode & MobMode::LOOTER)) - md->lootitem = (struct item *) - calloc(LOOTITEM_SIZE, sizeof(struct item)); - else - md->lootitem = NULL; + md->lootitemv.clear(); while ((x <= 0 || y <= 0 @@ -2943,14 +2906,14 @@ int mob_summonslave(dumb_ptr<mob_data> md2, int *value, int amount, int flag) md->bl_x = x; md->bl_y = y; - md->m = m; - md->x0 = x; - md->y0 = y; - md->xs = 0; - md->ys = 0; + md->spawn.m = m; + md->spawn.x0 = x; + md->spawn.y0 = y; + md->spawn.xs = 0; + md->spawn.ys = 0; md->stats[mob_stat::SPEED] = md2->stats[mob_stat::SPEED]; - md->spawndelay1 = static_cast<interval_t>(-1); // 一度のみフラグ - md->spawndelay2 = static_cast<interval_t>(-1); // 一度のみフラグ + md->spawn.delay1 = static_cast<interval_t>(-1); // 一度のみフラグ + md->spawn.delay2 = static_cast<interval_t>(-1); // 一度のみフラグ memset(md->npc_event, 0, sizeof(md->npc_event)); md->bl_type = BL::MOB; @@ -3005,7 +2968,8 @@ int mob_counttargeted(dumb_ptr<mob_data> md, dumb_ptr<block_list> src, nullpo_ret(md); map_foreachinarea(std::bind(mob_counttargeted_sub, ph::_1, md->bl_id, &c, src, target_lv), - md->bl_m, md->bl_x - AREA_SIZE, md->bl_y - AREA_SIZE, + md->bl_m, + md->bl_x - AREA_SIZE, md->bl_y - AREA_SIZE, md->bl_x + AREA_SIZE, md->bl_y + AREA_SIZE, BL::NUL); return c; @@ -3313,7 +3277,7 @@ int mobskill_use(dumb_ptr<mob_data> md, tick_t tick, flag = (md->hp < max_hp * ms[ii].cond2i / 100); break; case MobSkillCondition::MSC_NOTINTOWN: // Only outside of towns. - flag = !map[md->bl_m].flag.town; + flag = !md->bl_m->flag.town; break; case MobSkillCondition::MSC_SLAVELT: // slave < num flag = (mob_countslave(md) < ms[ii].cond2i); diff --git a/src/map/mob.hpp b/src/map/mob.hpp index 7421fca..1c7cfab 100644 --- a/src/map/mob.hpp +++ b/src/map/mob.hpp @@ -92,7 +92,7 @@ int mob_deleteslave(dumb_ptr<mob_data> md); int mob_counttargeted(dumb_ptr<mob_data> md, dumb_ptr<block_list> src, ATK target_lv); -int mob_warp(dumb_ptr<mob_data> md, int m, int x, int y, BeingRemoveWhy type); +int mob_warp(dumb_ptr<mob_data> md, map_local *m, int x, int y, BeingRemoveWhy type); int mobskill_use(dumb_ptr<mob_data> md, tick_t tick, MobSkillCondition event); int mobskill_event(dumb_ptr<mob_data> md, BF flag); diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 43766e9..b46f3f5 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -5,6 +5,8 @@ #include <cstring> #include <ctime> +#include <list> + #include "../common/cxxstdio.hpp" #include "../common/db.hpp" #include "../common/nullpo.hpp" @@ -22,15 +24,9 @@ #include "../poison.hpp" -struct npc_src_list -{ - struct npc_src_list *next; - struct npc_src_list *prev; - char name[4]; -}; - static -struct npc_src_list *npc_src_first, *npc_src_last; +std::list<std::string> npc_srcs; + static int npc_id = START_NPC_NUM; static @@ -64,27 +60,25 @@ static void npc_enable_sub(dumb_ptr<block_list> bl, dumb_ptr<npc_data> nd) { dumb_ptr<map_session_data> sd; - char *name = (char *) calloc(50, sizeof(char)); + char aname[50] {}; nullpo_retv(bl); - if (bl->bl_type == BL::PC) + assert (bl->bl_type == BL::PC); { sd = bl->as_player(); - if (nd->flag & 1) // 無効化されている + // not if disabled + if (nd->flag & 1) return; - memcpy(name, nd->name, sizeof(nd->name)); + memcpy(aname, nd->name, sizeof(nd->name)); if (sd->areanpc_id == nd->bl_id) - { - free(name); return; - } sd->areanpc_id = nd->bl_id; - npc_event(sd, strcat(name, "::OnTouch"), 0); + strcat(aname, "::OnTouch"); + npc_event(sd, aname, 0); } - free(name); } int npc_enable(const char *name, bool flag) @@ -113,8 +107,10 @@ int npc_enable(const char *name, bool flag) if (flag && (xs > 0 || ys > 0)) map_foreachinarea(std::bind(npc_enable_sub, ph::_1, nd), - nd->bl_m, nd->bl_x - xs, nd->bl_y - ys, - nd->bl_x + xs, nd->bl_y + ys, BL::PC); + nd->bl_m, + nd->bl_x - xs, nd->bl_y - ys, + nd->bl_x + xs, nd->bl_y + ys, + BL::PC); return 0; } @@ -180,7 +176,7 @@ int npc_timer_event(const char *eventname) // Added by RoVeRT return 0; } - run_script(nd->scr.script, ev->pos, nd->bl_id, nd->bl_id); + run_script(ScriptPointer(nd->scr.script.get(), ev->pos), nd->bl_id, nd->bl_id); return 0; } @@ -199,7 +195,7 @@ void npc_event_doall_sub(const std::string& key, struct event_data *ev, if ((p = strchr(p, ':')) && p && strcasecmp(name, p) == 0) { - run_script_l(ev->nd->scr.script, ev->pos, rid, ev->nd->bl_id, argc, + run_script_l(ScriptPointer(ev->nd->scr.script.get(), ev->pos), rid, ev->nd->bl_id, argc, argv); (*c)++; } @@ -227,7 +223,7 @@ void npc_event_do_sub(const std::string& key, struct event_data *ev, if (p && strcasecmp(name, p) == 0) { - run_script_l(ev->nd->scr.script, ev->pos, rid, ev->nd->bl_id, argc, + run_script_l(ScriptPointer(ev->nd->scr.script.get(), ev->pos), rid, ev->nd->bl_id, argc, argv); (*c)++; } @@ -304,75 +300,81 @@ static void npc_timerevent(TimerData *, tick_t tick, int id, interval_t data) { dumb_ptr<npc_data_script> nd = map_id2bl(id)->as_npc()->as_script(); - struct npc_timerevent_list *te; assert (nd != NULL); assert (nd->npc_subtype == NpcSubtype::SCRIPT); - assert (nd->scr.nexttimer >= 0); + assert (nd->scr.nexttimer != nd->scr.timer_eventv.end()); nd->scr.timertick = tick; - te = nd->scr.timer_event + nd->scr.nexttimer; + auto te = nd->scr.nexttimer; // nd->scr.timerid = nullptr; + // er, isn't this the same as nd->scr.timer = te->timer? interval_t t = nd->scr.timer += data; - nd->scr.nexttimer++; - if (nd->scr.timeramount > nd->scr.nexttimer) + assert (t == te->timer); + ++nd->scr.nexttimer; + if (nd->scr.nexttimer != nd->scr.timer_eventv.end()) { - interval_t next = nd->scr.timer_event[nd->scr.nexttimer].timer - t; + interval_t next = nd->scr.nexttimer->timer - t; nd->scr.timerid = Timer(tick + next, std::bind(npc_timerevent, ph::_1, ph::_2, id, next)); } - run_script(nd->scr.script, te->pos, 0, nd->bl_id); + run_script(ScriptPointer(nd->scr.script.get(), te->pos), 0, nd->bl_id); } /*========================================== * タイマーイベント開始 *------------------------------------------ */ -int npc_timerevent_start(dumb_ptr<npc_data_script> nd) +void npc_timerevent_start(dumb_ptr<npc_data_script> nd) { - int j, n; + nullpo_retv(nd); - nullpo_ret(nd); + if (nd->scr.timer_eventv.empty()) + return; + if (nd->scr.nexttimer != nd->scr.timer_eventv.end()) + return; + if (nd->scr.timer == nd->scr.timer_eventv.back().timer) + return; - n = nd->scr.timeramount; - if (nd->scr.nexttimer >= 0 || n == 0) - return 0; + npc_timerevent_list phony {}; + phony.timer = nd->scr.timer; - for (j = 0; j < n; j++) - { - if (nd->scr.timer_event[j].timer > nd->scr.timer) - break; - } - nd->scr.nexttimer = j; + // find the first element such that el.timer > phony.timer; + auto jt = std::upper_bound(nd->scr.timer_eventv.begin(), nd->scr.timer_eventv.end(), phony, + [](const npc_timerevent_list& l, const npc_timerevent_list& r) + { + return l.timer < r.timer; + } + ); + nd->scr.nexttimer = jt; nd->scr.timertick = gettick(); - if (j >= n) - return 0; + if (jt == nd->scr.timer_eventv.end()) + // shouldn't happen? + return; - interval_t next = nd->scr.timer_event[j].timer - nd->scr.timer; + interval_t next = jt->timer - nd->scr.timer; nd->scr.timerid = Timer(gettick() + next, std::bind(npc_timerevent, ph::_1, ph::_2, nd->bl_id, next)); - return 0; } /*========================================== * タイマーイベント終了 *------------------------------------------ */ -int npc_timerevent_stop(dumb_ptr<npc_data_script> nd) +void npc_timerevent_stop(dumb_ptr<npc_data_script> nd) { - nullpo_ret(nd); + nullpo_retv(nd); - if (nd->scr.nexttimer >= 0) + if (nd->scr.nexttimer != nd->scr.timer_eventv.end()) { - nd->scr.nexttimer = -1; + nd->scr.nexttimer = nd->scr.timer_eventv.end(); nd->scr.timer += gettick() - nd->scr.timertick; nd->scr.timerid.cancel(); } - return 0; } /*========================================== @@ -385,7 +387,11 @@ interval_t npc_gettimerevent_tick(dumb_ptr<npc_data_script> nd) interval_t tick = nd->scr.timer; - if (nd->scr.nexttimer >= 0) + // Couldn't we just check the truthiness of the timer? + // Or would that be affected by the (new!) detach logic? + // Of course, you'd be slightly crazy to check the tick when you are + // called with it. + if (nd->scr.nexttimer != nd->scr.timer_eventv.end()) tick += gettick() - nd->scr.timertick; return tick; } @@ -394,19 +400,16 @@ interval_t npc_gettimerevent_tick(dumb_ptr<npc_data_script> nd) * タイマー値の設定 *------------------------------------------ */ -int npc_settimerevent_tick(dumb_ptr<npc_data_script> nd, interval_t newtimer) +void npc_settimerevent_tick(dumb_ptr<npc_data_script> nd, interval_t newtimer) { - int flag; - - nullpo_ret(nd); + nullpo_retv(nd); - flag = nd->scr.nexttimer; + bool flag = nd->scr.nexttimer != nd->scr.timer_eventv.end(); npc_timerevent_stop(nd); nd->scr.timer = newtimer; - if (flag >= 0) + if (flag) npc_timerevent_start(nd); - return 0; } /*========================================== @@ -496,7 +499,7 @@ int npc_event(dumb_ptr<map_session_data> sd, const char *eventname, sd->npc_id = nd->bl_id; sd->npc_pos = - run_script(nd->scr.script, ev->pos, sd->bl_id, nd->bl_id); + run_script(ScriptPointer(nd->scr.script.get(), ev->pos), sd->bl_id, nd->bl_id); return 0; } @@ -512,7 +515,7 @@ void npc_command_sub(const std::string& key, struct event_data *ev, const char * sscanf(&p[11], "%s", temp); if (strcmp(command, temp) == 0) - run_script(ev->nd->scr.script, ev->pos, 0, ev->nd->bl_id); + run_script(ScriptPointer(ev->nd->scr.script.get(), ev->pos), 0, ev->nd->bl_id); } } @@ -528,7 +531,7 @@ int npc_command(dumb_ptr<map_session_data>, const char *npcname, const char *com * 接触型のNPC処理 *------------------------------------------ */ -int npc_touch_areanpc(dumb_ptr<map_session_data> sd, int m, int x, int y) +int npc_touch_areanpc(dumb_ptr<map_session_data> sd, map_local *m, int x, int y) { int i, f = 1; int xs, ys; @@ -538,19 +541,19 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, int m, int x, int y) if (sd->npc_id) return 1; - for (i = 0; i < map[m].npc_num; i++) + for (i = 0; i < m->npc_num; i++) { - if (map[m].npc[i]->flag & 1) + if (m->npc[i]->flag & 1) { // 無効化されている f = 0; continue; } - switch (map[m].npc[i]->npc_subtype) + switch (m->npc[i]->npc_subtype) { case NpcSubtype::WARP: - xs = map[m].npc[i]->as_warp()->warp.xs; - ys = map[m].npc[i]->as_warp()->warp.ys; + xs = m->npc[i]->as_warp()->warp.xs; + ys = m->npc[i]->as_warp()->warp.ys; break; case NpcSubtype::MESSAGE: assert (0 && "I'm pretty sure these are never put on a map"); @@ -558,19 +561,19 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, int m, int x, int y) ys = 0; break; case NpcSubtype::SCRIPT: - xs = map[m].npc[i]->as_script()->scr.xs; - ys = map[m].npc[i]->as_script()->scr.ys; + xs = m->npc[i]->as_script()->scr.xs; + ys = m->npc[i]->as_script()->scr.ys; break; default: continue; } - if (x >= map[m].npc[i]->bl_x - xs / 2 - && x < map[m].npc[i]->bl_x - xs / 2 + xs - && y >= map[m].npc[i]->bl_y - ys / 2 - && y < map[m].npc[i]->bl_y - ys / 2 + ys) + if (x >= m->npc[i]->bl_x - xs / 2 + && x < m->npc[i]->bl_x - xs / 2 + xs + && y >= m->npc[i]->bl_y - ys / 2 + && y < m->npc[i]->bl_y - ys / 2 + ys) break; } - if (i == map[m].npc_num) + if (i == m->npc_num) { if (f) { @@ -579,27 +582,28 @@ int npc_touch_areanpc(dumb_ptr<map_session_data> sd, int m, int x, int y) } return 1; } - switch (map[m].npc[i]->npc_subtype) + switch (m->npc[i]->npc_subtype) { case NpcSubtype::WARP: skill_stop_dancing(sd, 0); - pc_setpos(sd, map[m].npc[i]->as_warp()->warp.name, - map[m].npc[i]->as_warp()->warp.x, map[m].npc[i]->as_warp()->warp.y, BeingRemoveWhy::GONE); + pc_setpos(sd, m->npc[i]->as_warp()->warp.name, + m->npc[i]->as_warp()->warp.x, m->npc[i]->as_warp()->warp.y, BeingRemoveWhy::GONE); break; case NpcSubtype::MESSAGE: assert (0 && "I'm pretty sure these NPCs are never put on a map."); break; case NpcSubtype::SCRIPT: { - char *name = (char *)malloc(50); - - memcpy(name, map[m].npc[i]->name, 50); - if (sd->areanpc_id == map[m].npc[i]->bl_id) - return 1; // TODO fix leak of 'name' - sd->areanpc_id = map[m].npc[i]->bl_id; - if (npc_event(sd, strcat(name, "::OnTouch"), 0) > 0) - npc_click(sd, map[m].npc[i]->bl_id); - free(name); + char aname[50] {}; + memcpy(aname, m->npc[i]->name, sizeof(m->npc[i]->name)); + + if (sd->areanpc_id == m->npc[i]->bl_id) + return 1; + + sd->areanpc_id = m->npc[i]->bl_id; + strcat(aname, "::OnTouch"); + if (npc_event(sd, aname, 0) > 0) + npc_click(sd, m->npc[i]->bl_id); break; } } @@ -670,12 +674,12 @@ int npc_click(dumb_ptr<map_session_data> sd, int id) npc_event_dequeue(sd); break; case NpcSubtype::SCRIPT: - sd->npc_pos = run_script(nd->as_script()->scr.script, 0, sd->bl_id, id); + sd->npc_pos = run_script(ScriptPointer(nd->as_script()->scr.script.get(), 0), sd->bl_id, id); break; case NpcSubtype::MESSAGE: - if (nd->as_message()->message) + if (!nd->as_message()->message.empty()) { - clif_scriptmes(sd, id, nd->as_message()->message); + clif_scriptmes(sd, id, nd->as_message()->message.c_str()); clif_scriptclose(sd, id); } break; @@ -711,7 +715,7 @@ int npc_scriptcont(dumb_ptr<map_session_data> sd, int id) return 0; } - sd->npc_pos = run_script(nd->as_script()->scr.script, sd->npc_pos, sd->bl_id, id); + sd->npc_pos = run_script(ScriptPointer(nd->as_script()->scr.script.get(), sd->npc_pos), sd->bl_id, id); return 0; } @@ -784,7 +788,7 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, if (j == nd->as_shop()->shop_items.size()) return 3; - z += (double) nd->as_shop()->shop_items[j].value * item_list[i * 2]; + z += static_cast<double>(nd->as_shop()->shop_items[j].value) * item_list[i * 2]; itemamount += item_list[i * 2]; switch (pc_checkadditem(sd, item_list[i * 2 + 1], item_list[i * 2])) @@ -804,7 +808,7 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, w += itemdb_weight(item_list[i * 2 + 1]) * item_list[i * 2]; } - if (z > (double) sd->status.zeny) + if (z > static_cast<double>(sd->status.zeny)) return 1; // zeny不足 if (w + sd->weight > sd->max_weight) return 2; // 重量超過 @@ -813,7 +817,7 @@ int npc_buylist(dumb_ptr<map_session_data> sd, int n, if (sd->trade_partner != 0) return 4; // cant buy while trading - pc_payzeny(sd, (int) z); + pc_payzeny(sd, static_cast<int>(z)); for (i = 0; i < n; i++) { @@ -874,13 +878,13 @@ int npc_selllist(dumb_ptr<map_session_data> sd, int n, return 1; if (sd->trade_partner != 0) return 2; // cant sell while trading - z += (double) itemdb_value_sell(nameid) * item_list[i * 2 + 1]; + z += static_cast<double>(itemdb_value_sell(nameid)) * item_list[i * 2 + 1]; itemamount += item_list[i * 2 + 1]; } if (z > MAX_ZENY) z = MAX_ZENY; - pc_getzeny(sd, (int) z); + pc_getzeny(sd, static_cast<int>(z)); for (i = 0; i < n; i++) { int item_id = item_list[i * 2] - 2; @@ -902,16 +906,7 @@ int npc_selllist(dumb_ptr<map_session_data> sd, int n, static void npc_clearsrcfile(void) { - struct npc_src_list *p = npc_src_first; - - while (p) - { - struct npc_src_list *p2 = p; - p = p->next; - free(p2); - } - npc_src_first = NULL; - npc_src_last = NULL; + npc_srcs.clear(); } /*========================================== @@ -920,25 +915,13 @@ void npc_clearsrcfile(void) */ void npc_addsrcfile(const char *name) { - struct npc_src_list *new_src; - size_t len; - if (strcasecmp(name, "clear") == 0) { npc_clearsrcfile(); return; } - len = sizeof(*new_src) + strlen(name); - new_src = (struct npc_src_list *) calloc(1, len); - new_src->next = NULL; - strncpy(new_src->name, name, strlen(name) + 1); - if (npc_src_first == NULL) - npc_src_first = new_src; - if (npc_src_last) - npc_src_last->next = new_src; - - npc_src_last = new_src; + npc_srcs.push_back(name); } /*========================================== @@ -947,23 +930,18 @@ void npc_addsrcfile(const char *name) */ void npc_delsrcfile(const char *name) { - struct npc_src_list *p = npc_src_first, *pp = NULL, **lp = &npc_src_first; - if (strcasecmp(name, "all") == 0) { npc_clearsrcfile(); return; } - for (; p; lp = &p->next, pp = p, p = p->next) + for (auto it = npc_srcs.begin(); it != npc_srcs.end(); ++it) { - if (strcmp(p->name, name) == 0) + if (*it == name) { - *lp = p->next; - if (npc_src_last == p) - npc_src_last = pp; - free(p); - break; + npc_srcs.erase(it); + return; } } } @@ -974,7 +952,7 @@ void npc_delsrcfile(const char *name) */ int npc_parse_warp(const char *w1, const char *, const char *w3, const char *w4) { - int x, y, xs, ys, to_x, to_y, m; + int x, y, xs, ys, to_x, to_y; int i, j; char mapname[24], to_mapname[24]; dumb_ptr<npc_data_warp> nd; @@ -988,7 +966,7 @@ int npc_parse_warp(const char *w1, const char *, const char *w3, const char *w4) return 1; } - m = map_mapname2mapid(mapname); + map_local *m = map_mapname2mapid(mapname); nd.new_(); nd->bl_id = npc_get_new_npc_id(); @@ -1056,7 +1034,6 @@ int npc_parse_shop(char *w1, char *, char *w3, char *w4) char *p; int x, y; DIR dir; - int m; char mapname[24]; dumb_ptr<npc_data_shop> nd; @@ -1070,7 +1047,7 @@ int npc_parse_shop(char *w1, char *, char *w3, char *w4) return 1; } dir = static_cast<DIR>(dir_); - m = map_mapname2mapid(mapname); + map_local *m = map_mapname2mapid(mapname); nd.new_(); p = strchr(w4, ','); @@ -1151,27 +1128,12 @@ int npc_parse_shop(char *w1, char *, char *w3, char *w4) static void npc_convertlabel_db(const std::string& lname, int pos, dumb_ptr<npc_data_script> nd) { - struct npc_label_list *lst; - int num; - nullpo_retv(nd); - lst = nd->scr.label_list; - num = nd->scr.label_list_num; - if (!lst) - { - lst = (struct npc_label_list *) - calloc(1, sizeof(struct npc_label_list)); - num = 0; - } - else - lst = (struct npc_label_list *) - realloc(lst, sizeof(struct npc_label_list) * (num + 1)); - - strzcpy(lst[num].name, lname.c_str(), sizeof(lst[num].name)); - lst[num].pos = pos; - nd->scr.label_list = lst; - nd->scr.label_list_num = num + 1; + struct npc_label_list eln {}; + strzcpy(eln.name, lname.c_str(), sizeof(eln.name)); + eln.pos = pos; + nd->scr.label_listv.push_back(std::move(eln)); } /*========================================== @@ -1184,25 +1146,19 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4, { int x, y; DIR dir = DIR::S; - int m, xs = 0, ys = 0, npc_class = 0; // [Valaris] thanks to fov + map_local *m; + int xs = 0, ys = 0, npc_class = 0; // [Valaris] thanks to fov char mapname[24]; - char *srcbuf = NULL; - const ScriptCode *script = NULL; - int srcsize = 65536; - int startline = 0; - char line[1024]; + std::unique_ptr<const ScriptBuffer> script = NULL; dumb_ptr<npc_data_script> nd; int evflag = 0; char *p; - struct npc_label_list *label_dup = NULL; - int label_dupnum = 0; - int src_id = 0; if (strcmp(w1, "-") == 0) { x = 0; y = 0; - m = -1; + m = nullptr; } else { @@ -1221,61 +1177,48 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4, if (strcmp(w2, "script") == 0) { - // スクリプトの解析 - srcbuf = (char *) calloc(srcsize, sizeof(char)); - if (strchr(first_line, '{')) - { - strcpy(srcbuf, strchr(first_line, '{')); - startline = *lines; - } - else - srcbuf[0] = 0; + // may be empty + std::string srcbuf = strchrnul(first_line, '{'); + // Note: it was a bug that this was missing. I think. + int startline = *lines; + while (1) { - int i; - for (i = strlen(srcbuf) - 1; i >= 0 && isspace(srcbuf[i]); i--); - if (i >= 0 && srcbuf[i] == '}') + size_t i = srcbuf.find_last_not_of(" \t\n\r\f\v"); + if (i != std::string::npos && srcbuf[i] == '}') break; + char line[1024]; if (!fgets(line, 1020, fp)) + // eof break; (*lines)++; if (feof(fp)) break; - if (strlen(srcbuf) + strlen(line) + 1 >= srcsize) - { - srcsize += 65536; - srcbuf = (char *) realloc(srcbuf, srcsize); - memset(srcbuf + srcsize - 65536, '\0', 65536); - } - if (srcbuf[0] != '{') + if (srcbuf.empty()) { - if (strchr(line, '{')) - { - strcpy(srcbuf, strchr(line, '{')); - startline = *lines; - } + // may be a no-op + srcbuf = strchrnul(line, '{'); + // safe to execute more than once + // But will usually only happen once + startline = *lines; } else - strcat(srcbuf, line); + srcbuf += line; } - script = parse_script(srcbuf, startline); + script = parse_script(srcbuf.c_str(), startline); if (script == NULL) - { // script parse error? - free(srcbuf); return 1; - } - } else { - PRINTF("duplicate() is no longer supported!\n"); + assert(0 && "duplicate() is no longer supported!\n"); return 0; - } // end of スクリプト解析 + } nd.new_(); - if (m == -1) + if (m == nullptr) { // スクリプトコピー用のダミーNPC } @@ -1318,7 +1261,7 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4, nd->scr.ys = 0; } - if (npc_class < 0 && m >= 0) + if (npc_class < 0 && m != nullptr) { // イベント型NPC evflag = 1; } @@ -1349,8 +1292,7 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4, nd->flag = 0; nd->npc_class = npc_class; nd->speed = std::chrono::milliseconds(200); - nd->scr.script = script; - nd->scr.src_id = src_id; + nd->scr.script = std::move(script); nd->option = Option::ZERO; nd->opt1 = Opt1::ZERO; nd->opt2 = Opt2::ZERO; @@ -1360,7 +1302,7 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4, npc_script++; nd->bl_type = BL::NPC; nd->npc_subtype = NpcSubtype::SCRIPT; - if (m >= 0) + if (m != nullptr) { nd->n = map_addnpc(m, nd); map_addblock(nd); @@ -1377,37 +1319,13 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4, } npcname_db.put(nd->exname, nd); - //----------------------------------------- - // ラベルデータの準備 - if (srcbuf) - { - // script本体がある場合の処理 - - // ラベルデータのコンバート - for (auto& pair : scriptlabel_db) - npc_convertlabel_db(pair.first, pair.second, nd); + for (auto& pair : scriptlabel_db) + npc_convertlabel_db(pair.first, pair.second, nd); - // もう使わないのでバッファ解放 - free(srcbuf); - - } - else + for (npc_label_list& el : nd->scr.label_listv) { - // duplicate - -// nd->scr.label_list=malloc(sizeof(struct npc_label_list)*label_dupnum); -// memcpy(nd->scr.label_list,label_dup,sizeof(struct npc_label_list)*label_dupnum); - - nd->scr.label_list = label_dup; // ラベルデータ共有 - nd->scr.label_list_num = label_dupnum; - } - - //----------------------------------------- - // イベント用ラベルデータのエクスポート - for (int i = 0; i < nd->scr.label_list_num; i++) - { - char *lname = nd->scr.label_list[i].name; - int pos = nd->scr.label_list[i].pos; + char *lname = el.name; + int pos = el.pos; if ((lname[0] == 'O' || lname[0] == 'o') && (lname[1] == 'N' || lname[1] == 'n')) @@ -1427,42 +1345,31 @@ int npc_parse_script(char *w1, char *w2, char *w3, char *w4, //----------------------------------------- // ラベルデータからタイマーイベント取り込み - for (int i = 0; i < nd->scr.label_list_num; i++) + for (npc_label_list& el : nd->scr.label_listv) { int t_ = 0, n = 0; - char *lname = nd->scr.label_list[i].name; - int pos = nd->scr.label_list[i].pos; + char *lname = el.name; + int pos = el.pos; if (sscanf(lname, "OnTimer%d%n", &t_, &n) == 1 && lname[n] == '\0') { interval_t t = static_cast<interval_t>(t_); - // タイマーイベント - struct npc_timerevent_list *te = nd->scr.timer_event; - int j, k = nd->scr.timeramount; - if (te == NULL) - te = (struct npc_timerevent_list *) calloc(1, - sizeof(struct - npc_timerevent_list)); - else - te = (struct npc_timerevent_list *) realloc(te, - sizeof(struct - npc_timerevent_list) - * (k + 1)); - for (j = 0; j < k; j++) - { - if (te[j].timer > t) - { - memmove(te + j + 1, te + j, - sizeof(struct npc_timerevent_list) * (k - j)); - break; - } - } - te[j].timer = t; - te[j].pos = pos; - nd->scr.timer_event = te; - nd->scr.timeramount = k + 1; + + npc_timerevent_list tel {}; + tel.timer = t; + tel.pos = pos; + + auto it = std::lower_bound(nd->scr.timer_eventv.begin(), nd->scr.timer_eventv.end(), tel, + [](const npc_timerevent_list& l, const npc_timerevent_list& r) + { + return l.timer < r.timer; + } + ); + assert (it == nd->scr.timer_eventv.end() || it->timer != tel.timer); + + nd->scr.timer_eventv.insert(it, std::move(tel)); } } - nd->scr.nexttimer = -1; + nd->scr.nexttimer = nd->scr.timer_eventv.end(); // nd->scr.timerid = nullptr; return 0; @@ -1476,62 +1383,37 @@ static int npc_parse_function(char *, char *, char *w3, char *, char *first_line, FILE * fp, int *lines) { - char *srcbuf = NULL; - const ScriptCode *script; - int srcsize = 65536; - int startline = 0; - char line[1024]; - int i; + std::string srcbuf = strchrnul(first_line, '{'); + int startline = *lines; - // スクリプトの解析 - srcbuf = (char *) calloc(srcsize, sizeof(char)); - if (strchr(first_line, '{')) - { - strcpy(srcbuf, strchr(first_line, '{')); - startline = *lines; - } - else - srcbuf[0] = 0; while (1) { - for (i = strlen(srcbuf) - 1; i >= 0 && isspace(srcbuf[i]); i--); - if (i >= 0 && srcbuf[i] == '}') + size_t i = srcbuf.find_last_not_of(" \t\n\r\f\v"); + if (i != std::string::npos && srcbuf[i] == '}') break; + char line[1024]; if (!fgets(line, 1020, fp)) break; (*lines)++; if (feof(fp)) break; - if (strlen(srcbuf) + strlen(line) + 1 >= srcsize) + if (srcbuf.empty()) { - srcsize += 65536; - srcbuf = (char *) realloc(srcbuf, srcsize); - memset(srcbuf + srcsize - 65536, '\0', 65536); - } - if (srcbuf[0] != '{') - { - if (strchr(line, '{')) - { - strcpy(srcbuf, strchr(line, '{')); - startline = *lines; - } + srcbuf = strchrnul(line, '{'); + startline = *lines; } else - strcat(srcbuf, line); + srcbuf += line; } - script = parse_script(srcbuf, startline); + std::unique_ptr<const ScriptBuffer> script = parse_script(srcbuf.c_str(), startline); if (script == NULL) { // script parse error? - free(srcbuf); return 1; } std::string p = w3; - userfunc_db.put(p, script); - - // もう使わないのでバッファ解放 - free(srcbuf); + userfunc_db.put(p, std::move(script)); return 0; } @@ -1543,7 +1425,7 @@ int npc_parse_function(char *, char *, char *w3, char *, static int npc_parse_mob(const char *w1, const char *, const char *w3, const char *w4) { - int m, x, y, xs, ys, mob_class, num; + int x, y, xs, ys, mob_class, num; int i; char mapname[24]; char eventname[24] = ""; @@ -1562,7 +1444,7 @@ int npc_parse_mob(const char *w1, const char *, const char *w3, const char *w4) interval_t delay1 = std::chrono::milliseconds(delay1_); interval_t delay2 = std::chrono::milliseconds(delay2_); - m = map_mapname2mapid(mapname); + map_local *m = map_mapname2mapid(mapname); if (num > 1 && battle_config.mob_count_rate != 100) { @@ -1589,29 +1471,23 @@ int npc_parse_mob(const char *w1, const char *, const char *w3, const char *w4) md->n = i; md->mob_class = mob_class; md->bl_id = npc_get_new_npc_id(); - md->m = m; - md->x0 = x; - md->y0 = y; - md->xs = xs; - md->ys = ys; - md->spawndelay1 = delay1; - md->spawndelay2 = delay2; + md->spawn.m = m; + md->spawn.x0 = x; + md->spawn.y0 = y; + md->spawn.xs = xs; + md->spawn.ys = ys; + md->spawn.delay1 = delay1; + md->spawn.delay2 = delay2; memset(&md->state, 0, sizeof(md->state)); // md->timer = nullptr; md->target_id = 0; md->attacked_id = 0; - if (bool(mob_db[mob_class].mode & MobMode::LOOTER)) - md->lootitem = - (struct item *) calloc(LOOTITEM_SIZE, sizeof(struct item)); - else - md->lootitem = NULL; + md->lootitemv.clear(); if (strlen(eventname) >= 4) - { memcpy(md->npc_event, eventname, 24); - } else memset(md->npc_event, 0, 24); @@ -1633,7 +1509,6 @@ int npc_parse_mob(const char *w1, const char *, const char *w3, const char *w4) static int npc_parse_mapflag(char *w1, char *, char *w3, char *w4) { - int m; char mapname[24], savemap[16]; int savex, savey; @@ -1642,8 +1517,8 @@ int npc_parse_mapflag(char *w1, char *, char *w3, char *w4) if (sscanf(w1, "%[^,]", mapname) != 1) return 1; - m = map_mapname2mapid(mapname); - if (m < 0) + map_local *m = map_mapname2mapid(mapname); + if (m == nullptr) return 1; //マップフラグ @@ -1651,113 +1526,113 @@ int npc_parse_mapflag(char *w1, char *, char *w3, char *w4) { if (strcmp(w4, "SavePoint") == 0) { - memcpy(map[m].save.map, "SavePoint", 16); - map[m].save.x = -1; - map[m].save.y = -1; + memcpy(m->save.map, "SavePoint", 16); + m->save.x = -1; + m->save.y = -1; } else if (sscanf(w4, "%[^,],%d,%d", savemap, &savex, &savey) == 3) { - memcpy(map[m].save.map, savemap, 16); - map[m].save.x = savex; - map[m].save.y = savey; + memcpy(m->save.map, savemap, 16); + m->save.x = savex; + m->save.y = savey; } - map[m].flag.nosave = 1; + m->flag.nosave = 1; } else if (strcasecmp(w3, "nomemo") == 0) { - map[m].flag.nomemo = 1; + m->flag.nomemo = 1; } else if (strcasecmp(w3, "noteleport") == 0) { - map[m].flag.noteleport = 1; + m->flag.noteleport = 1; } else if (strcasecmp(w3, "nowarp") == 0) { - map[m].flag.nowarp = 1; + m->flag.nowarp = 1; } else if (strcasecmp(w3, "nowarpto") == 0) { - map[m].flag.nowarpto = 1; + m->flag.nowarpto = 1; } else if (strcasecmp(w3, "noreturn") == 0) { - map[m].flag.noreturn = 1; + m->flag.noreturn = 1; } else if (strcasecmp(w3, "monster_noteleport") == 0) { - map[m].flag.monster_noteleport = 1; + m->flag.monster_noteleport = 1; } else if (strcasecmp(w3, "nobranch") == 0) { - map[m].flag.nobranch = 1; + m->flag.nobranch = 1; } else if (strcasecmp(w3, "nopenalty") == 0) { - map[m].flag.nopenalty = 1; + m->flag.nopenalty = 1; } else if (strcasecmp(w3, "pvp") == 0) { - map[m].flag.pvp = 1; + m->flag.pvp = 1; } else if (strcasecmp(w3, "pvp_noparty") == 0) { - map[m].flag.pvp_noparty = 1; + m->flag.pvp_noparty = 1; } else if (strcasecmp(w3, "pvp_nocalcrank") == 0) { - map[m].flag.pvp_nocalcrank = 1; + m->flag.pvp_nocalcrank = 1; } else if (strcasecmp(w3, "nozenypenalty") == 0) { - map[m].flag.nozenypenalty = 1; + m->flag.nozenypenalty = 1; } else if (strcasecmp(w3, "notrade") == 0) { - map[m].flag.notrade = 1; + m->flag.notrade = 1; } else if (battle_config.pk_mode && strcasecmp(w3, "nopvp") == 0) { // nopvp for pk mode [Valaris] - map[m].flag.nopvp = 1; - map[m].flag.pvp = 0; + m->flag.nopvp = 1; + m->flag.pvp = 0; } else if (strcasecmp(w3, "noicewall") == 0) { // noicewall [Valaris] - map[m].flag.noicewall = 1; + m->flag.noicewall = 1; } else if (strcasecmp(w3, "snow") == 0) { // snow [Valaris] - map[m].flag.snow = 1; + m->flag.snow = 1; } else if (strcasecmp(w3, "fog") == 0) { // fog [Valaris] - map[m].flag.fog = 1; + m->flag.fog = 1; } else if (strcasecmp(w3, "sakura") == 0) { // sakura [Valaris] - map[m].flag.sakura = 1; + m->flag.sakura = 1; } else if (strcasecmp(w3, "leaves") == 0) { // leaves [Valaris] - map[m].flag.leaves = 1; + m->flag.leaves = 1; } else if (strcasecmp(w3, "rain") == 0) { // rain [Valaris] - map[m].flag.rain = 1; + m->flag.rain = 1; } else if (strcasecmp(w3, "no_player_drops") == 0) { // no player drops [Jaxad0127] - map[m].flag.no_player_drops = 1; + m->flag.no_player_drops = 1; } else if (strcasecmp(w3, "town") == 0) { // town/safe zone [remoitnane] - map[m].flag.town = 1; + m->flag.town = 1; } return 0; } -dumb_ptr<npc_data> npc_spawn_text(int m, int x, int y, - int npc_class, const char *name, const char *message) +dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y, + int npc_class, const char *name, const char *message) { dumb_ptr<npc_data_message> retval; retval.new_(); @@ -1772,7 +1647,8 @@ dumb_ptr<npc_data> npc_spawn_text(int m, int x, int y, strncpy(retval->exname, name, 23); retval->name[15] = 0; retval->exname[15] = 0; - retval->message = message ? strdup(message) : NULL; + if (message) + retval->message = message; retval->npc_class = npc_class; retval->speed = std::chrono::milliseconds(200); @@ -1792,26 +1668,17 @@ void npc_free_internal(dumb_ptr<npc_data> nd_) if (nd_->npc_subtype == NpcSubtype::SCRIPT) { dumb_ptr<npc_data_script> nd = nd_->as_script(); - if (nd->scr.timer_event) - free(nd->scr.timer_event); - if (nd->scr.src_id == 0) + nd->scr.timer_eventv.clear(); + { - if (nd->scr.script) - { - free(const_cast<ScriptCode *>(nd->scr.script)); - nd->scr.script = NULL; - } - if (nd->scr.label_list) - { - free(nd->scr.label_list); - nd->scr.label_list = NULL; - } + nd->scr.script.reset(); + nd->scr.label_listv.clear(); } } else if (nd_->npc_subtype == NpcSubtype::MESSAGE) { dumb_ptr<npc_data_message> nd = nd_->as_message(); - free(nd->message); + nd->message.clear(); } nd_.delete_(); } @@ -1826,8 +1693,10 @@ void npc_propagate_update(dumb_ptr<npc_data> nd) ys = nd_->scr.ys; } map_foreachinarea(std::bind(npc_enable_sub, ph::_1, nd), - nd->bl_m, nd->bl_x - xs, nd->bl_y - ys, - nd->bl_x + xs, nd->bl_y + ys, BL::PC); + nd->bl_m, + nd->bl_x - xs, nd->bl_y - ys, + nd->bl_x + xs, nd->bl_y + ys, + BL::PC); } void npc_free(dumb_ptr<npc_data> nd) @@ -1845,27 +1714,19 @@ void npc_free(dumb_ptr<npc_data> nd) */ int do_init_npc(void) { - struct npc_src_list *nsl; - FILE *fp; - char line[1024]; - int m, lines; - memset(&ev_tm_b, -1, sizeof(ev_tm_b)); - for (nsl = npc_src_first; nsl; nsl = nsl->next) + for (; !npc_srcs.empty(); npc_srcs.pop_front()) { - if (nsl->prev) - { - free(nsl->prev); - nsl->prev = NULL; - } - fp = fopen_(nsl->name, "r"); + std::string& nsl = npc_srcs.front(); + FILE *fp = fopen_(nsl.c_str(), "r"); if (fp == NULL) { - PRINTF("file not found : %s\n", nsl->name); + PRINTF("file not found : %s\n", nsl); exit(1); } - lines = 0; + int lines = 0; + char line[1024]; while (fgets(line, 1020, fp)) { char w1[1024], w2[1024], w3[1024], w4[1024], mapname[1024]; @@ -1906,8 +1767,8 @@ int do_init_npc(void) if (strcmp(w1, "-") != 0 && strcasecmp(w1, "function") != 0) { sscanf(w1, "%[^,]", mapname); - m = map_mapname2mapid(mapname); - if (strlen(mapname) > 16 || m < 0) + map_local *m = map_mapname2mapid(mapname); + if (strlen(mapname) > 16 || m == nullptr) { // "mapname" is not assigned to this server continue; @@ -1952,7 +1813,7 @@ int do_init_npc(void) } fclose_(fp); PRINTF("\rLoading NPCs [%d]: %-54s", npc_id - START_NPC_NUM, - nsl->name); + nsl); fflush(stdout); } PRINTF("\rNPCs Loaded: %d [Warps:%d Shops:%d Scripts:%d Mobs:%d]\n", diff --git a/src/map/npc.hpp b/src/map/npc.hpp index 5760ca1..539152f 100644 --- a/src/map/npc.hpp +++ b/src/map/npc.hpp @@ -18,7 +18,7 @@ int npc_event_dequeue(dumb_ptr<map_session_data> sd); int npc_event(dumb_ptr<map_session_data> sd, const char *npcname, int); int npc_timer_event(const char *eventname); // Added by RoVeRT int npc_command(dumb_ptr<map_session_data> sd, const char *npcname, const char *command); -int npc_touch_areanpc(dumb_ptr<map_session_data>, int, int, int); +int npc_touch_areanpc(dumb_ptr<map_session_data>, map_local *, int, int); int npc_click(dumb_ptr<map_session_data>, int); int npc_scriptcont(dumb_ptr<map_session_data>, int); int npc_buysellsel(dumb_ptr<map_session_data>, int, int); @@ -36,7 +36,8 @@ int npc_get_new_npc_id(void); * * \param message The message to speak. If message is NULL, the NPC will not do anything at all. */ -dumb_ptr<npc_data> npc_spawn_text(int m, int x, int y, int class_, const char *name, const char *message); // message is strdup'd within +dumb_ptr<npc_data> npc_spawn_text(map_local *m, int x, int y, + int class_, const char *name, const char *message); // message is strdup'd within /** * Uninstalls and frees an NPC @@ -64,10 +65,10 @@ int npc_event_do(const char *name) return npc_event_do_l(name, 0, 0, NULL); } -int npc_timerevent_start(dumb_ptr<npc_data_script> nd); -int npc_timerevent_stop(dumb_ptr<npc_data_script> nd); +void npc_timerevent_start(dumb_ptr<npc_data_script> nd); +void npc_timerevent_stop(dumb_ptr<npc_data_script> nd); interval_t npc_gettimerevent_tick(dumb_ptr<npc_data_script> nd); -int npc_settimerevent_tick(dumb_ptr<npc_data_script> nd, interval_t newtimer); +void npc_settimerevent_tick(dumb_ptr<npc_data_script> nd, interval_t newtimer); int npc_delete(dumb_ptr<npc_data> nd); #endif // NPC_HPP diff --git a/src/map/party.cpp b/src/map/party.cpp index 1f2c78a..451dcfa 100644 --- a/src/map/party.cpp +++ b/src/map/party.cpp @@ -704,7 +704,7 @@ void party_send_hp_check(dumb_ptr<block_list> bl, int party_id, int *flag) } // 経験値公平分配 -int party_exp_share(struct party *p, int mapid, int base_exp, int job_exp) +int party_exp_share(struct party *p, map_local *mapid, int base_exp, int job_exp) { dumb_ptr<map_session_data> sd; int i, c; diff --git a/src/map/party.hpp b/src/map/party.hpp index e2cabb3..4037a04 100644 --- a/src/map/party.hpp +++ b/src/map/party.hpp @@ -42,7 +42,7 @@ int party_recv_message(int party_id, int account_id, const char *mes, int len); int party_send_xy_clear(struct party *p); void party_send_hp_check(dumb_ptr<block_list> bl, int party_id, int *flag); -int party_exp_share(struct party *p, int map, int base_exp, int job_exp); +int party_exp_share(struct party *p, map_local *map, int base_exp, int job_exp); void party_foreachsamemap(std::function<void(dumb_ptr<block_list>)> func, dumb_ptr<map_session_data> sd, int type); diff --git a/src/map/path.cpp b/src/map/path.cpp index 7a8eb37..b938e3b 100644 --- a/src/map/path.cpp +++ b/src/map/path.cpp @@ -1,9 +1,12 @@ +#include "path.hpp" + +#include <cassert> + #include "../common/cxxstdio.hpp" #include "../common/random.hpp" #include "../common/nullpo.hpp" #include "battle.hpp" -#include "map.hpp" #include "../poison.hpp" @@ -182,7 +185,7 @@ int add_path(int *heap, struct tmp_path *tp, int x, int y, int dist, *------------------------------------------ */ static -bool can_place(struct map_data *m, int x, int y) +bool can_place(struct map_local *m, int x, int y) { nullpo_ret(m); @@ -194,7 +197,7 @@ bool can_place(struct map_data *m, int x, int y) *------------------------------------------ */ static -int can_move(struct map_data *m, int x0, int y0, int x1, int y1) +int can_move(struct map_local *m, int x0, int y0, int x1, int y1) { nullpo_ret(m); @@ -217,19 +220,17 @@ int can_move(struct map_data *m, int x0, int y0, int x1, int y1) * path探索 (x0,y0)->(x1,y1) *------------------------------------------ */ -int path_search(struct walkpath_data *wpd, int m, int x0, int y0, int x1, int y1, int flag) +int path_search(struct walkpath_data *wpd, map_local *m, int x0, int y0, int x1, int y1, int flag) { int heap[MAX_HEAP + 1]; struct tmp_path tp[MAX_WALKPATH * MAX_WALKPATH]; int i, rp, x, y; - struct map_data *md; int dx, dy; nullpo_ret(wpd); - if (!map[m].gat) - return -1; - md = &map[m]; + assert (m->gat); + map_local *md = m; if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || bool(read_gatp(md, x1, y1) & MapCell::UNWALKABLE)) return -1; diff --git a/src/map/path.hpp b/src/map/path.hpp new file mode 100644 index 0000000..8dace6f --- /dev/null +++ b/src/map/path.hpp @@ -0,0 +1,8 @@ +#ifndef PATH_HPP +#define PATH_HPP + +#include "map.hpp" + +int path_search(struct walkpath_data *, map_local *, int, int, int, int, int); + +#endif // PATH_HPP diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 23e7f81..f2dcab2 100644 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -21,6 +21,7 @@ #include "mob.hpp" #include "npc.hpp" #include "party.hpp" +#include "path.hpp" #include "script.hpp" #include "skill.hpp" #include "storage.hpp" @@ -216,9 +217,7 @@ earray<EPOS, EQUIP, EQUIP::COUNT> equip_pos //= }}; static -struct GM_Account *gm_accounts = NULL; -static -int GM_num = 0; +std::map<int, uint8_t> gm_accountm; static int pc_checkoverhp(dumb_ptr<map_session_data> sd); @@ -234,17 +233,14 @@ void pc_setdead(dumb_ptr<map_session_data> sd) sd->state.dead_sit = 1; } -int pc_isGM(dumb_ptr<map_session_data> sd) +uint8_t pc_isGM(dumb_ptr<map_session_data> sd) { - int i; - nullpo_ret(sd); - for (i = 0; i < GM_num; i++) - if (gm_accounts[i].account_id == sd->status.account_id) - return gm_accounts[i].level; + auto it = gm_accountm.find(sd->status.account_id); + if (it != gm_accountm.end()) + return it->second; return 0; - } int pc_iskiller(dumb_ptr<map_session_data> src, @@ -265,23 +261,12 @@ int pc_iskiller(dumb_ptr<map_session_data> src, return 0; } -int pc_set_gm_level(int account_id, int level) +void pc_set_gm_level(int account_id, uint8_t level) { - int i; - for (i = 0; i < GM_num; i++) - { - if (account_id == gm_accounts[i].account_id) - { - gm_accounts[i].level = level; - return 0; - } - } - - GM_num++; - RECREATE(gm_accounts, struct GM_Account, GM_num); - gm_accounts[GM_num - 1].account_id = account_id; - gm_accounts[GM_num - 1].level = level; - return 0; + if (level) + gm_accountm[account_id] = level; + else + gm_accountm.erase(account_id); } static @@ -391,8 +376,10 @@ int pc_counttargeted(dumb_ptr<map_session_data> sd, dumb_ptr<block_list> src, { int c = 0; map_foreachinarea(std::bind(pc_counttargeted_sub, ph::_1, sd->bl_id, &c, src, target_lv), - sd->bl_m, sd->bl_x - AREA_SIZE, sd->bl_y - AREA_SIZE, - sd->bl_x + AREA_SIZE, sd->bl_y + AREA_SIZE, BL::NUL); + sd->bl_m, + sd->bl_x - AREA_SIZE, sd->bl_y - AREA_SIZE, + sd->bl_x + AREA_SIZE, sd->bl_y + AREA_SIZE, + BL::NUL); return c; } @@ -430,9 +417,9 @@ int pc_makesavestatus(dumb_ptr<map_session_data> sd) } // セーブ禁止マップだったので指定位置に移動 - if (map[sd->bl_m].flag.nosave) + if (sd->bl_m->flag.nosave) { - struct map_data *m = &map[sd->bl_m]; + map_local *m = sd->bl_m; if (strcmp(m->save.map, "SavePoint") == 0) memcpy(&sd->status.last_point, &sd->status.save_point, sizeof(sd->status.last_point)); @@ -609,7 +596,7 @@ int pc_isequip(dumb_ptr<map_session_data> sd, int n) if (item->elv > 0 && sd->status.base_level < item->elv) return 0; - if (map[sd->bl_m].flag.pvp + if (sd->bl_m->flag.pvp && (item->flag.no_equip == 1 || item->flag.no_equip == 3)) return 0; return 1; @@ -663,7 +650,6 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time, // sd->walktimer = nullptr; // sd->attacktimer = nullptr; // sd->invincible_timer = nullptr; - sd->sg_count = 0; sd->deal_locked = 0; sd->trade_partner = 0; @@ -711,9 +697,6 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time, sd->sc_count = 0; sd->status.option = Option::ZERO; - // init ignore list - memset(sd->ignore, 0, sizeof(sd->ignore)); - // パーティー関係の初期化 sd->party_sended = 0; sd->party_invite = 0; @@ -801,7 +784,7 @@ int pc_authok(int id, int login_id2, TimeT connect_until_time, sd->packet_flood_in = 0; // Obtain IP address (if they are still connected) - if (!getpeername(sd->fd, (struct sockaddr *)&sai, &sa_len)) + if (!getpeername(sd->fd, reinterpret_cast<struct sockaddr *>(&sai), &sa_len)) sd->ip = sai.sin_addr; // message of the limited time of the account @@ -1059,7 +1042,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) { if (sd->status.inventory[index].card[0] != 0x00ff && sd->status.inventory[index].card[0] != 0x00fe - && sd->status.inventory[index].card[0] != (short) 0xff00) + && sd->status.inventory[index].card[0] != static_cast<short>(0xff00)) { int j; for (j = 0; j < sd->inventory_data[index]->slot; j++) @@ -1075,7 +1058,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) if (i == EQUIP::SHIELD && sd->status.inventory[index].equip == EPOS::SHIELD) sd->state.lr_flag = 1; - run_script_l(itemdb_equipscript(c), 0, sd->bl_id, + run_script_l(ScriptPointer(itemdb_equipscript(c), 0), sd->bl_id, 0, 2, arg); sd->state.lr_flag = 0; } @@ -1086,7 +1069,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) { // 防具 if (sd->status.inventory[index].card[0] != 0x00ff && sd->status.inventory[index].card[0] != 0x00fe - && sd->status.inventory[index].card[0] != (short) 0xff00) + && sd->status.inventory[index].card[0] != static_cast<short>(0xff00)) { int j; for (j = 0; j < sd->inventory_data[index]->slot; j++) @@ -1098,7 +1081,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) arg[0].v.i = int(i); arg[1].name = "@itemId"; arg[1].v.i = sd->inventory_data[index]->nameid; - run_script_l(itemdb_equipscript(c), 0, sd->bl_id, + run_script_l(ScriptPointer(itemdb_equipscript(c), 0), sd->bl_id, 0, 2, arg); } } @@ -1161,7 +1144,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) arg[0].v.i = int(i); arg[1].name = "@itemId"; arg[1].v.i = sd->inventory_data[index]->nameid; - run_script_l(sd->inventory_data[index]->equip_script, 0, + run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), sd->bl_id, 0, 2, arg); } sd->state.lr_flag = 0; @@ -1184,7 +1167,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->star += (sd->status.inventory[index].card[1] >> 8); // 星のかけら } sd->attackrange += sd->inventory_data[index]->range; - run_script_l(sd->inventory_data[index]->equip_script, 0, + run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), sd->bl_id, 0, 2, arg); } } @@ -1198,7 +1181,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) sd->watk += sd->inventory_data[index]->atk; refinedef += sd->status.inventory[index].refine * 0; - run_script_l(sd->inventory_data[index]->equip_script, 0, + run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), sd->bl_id, 0, 2, arg); } } @@ -1223,7 +1206,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first) arg[1].name = "@itemId"; arg[1].v.i = sd->inventory_data[index]->nameid; sd->state.lr_flag = 2; - run_script_l(sd->inventory_data[index]->equip_script, 0, sd->bl_id, + run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0), sd->bl_id, 0, 2, arg); sd->state.lr_flag = 0; sd->arrow_atk += sd->inventory_data[index]->atk; @@ -1929,12 +1912,11 @@ int pc_inventoryblank(dumb_ptr<map_session_data> sd) */ int pc_payzeny(dumb_ptr<map_session_data> sd, int zeny) { - double z; - nullpo_ret(sd); - z = (double) sd->status.zeny; - if (sd->status.zeny < zeny || z - (double) zeny > MAX_ZENY) +#warning "Why is this a double?" + double z = sd->status.zeny; + if (sd->status.zeny < zeny || z - zeny > MAX_ZENY) return 1; sd->status.zeny -= zeny; clif_updatestatus(sd, SP::ZENY); @@ -1948,12 +1930,10 @@ int pc_payzeny(dumb_ptr<map_session_data> sd, int zeny) */ int pc_getzeny(dumb_ptr<map_session_data> sd, int zeny) { - double z; - nullpo_ret(sd); - z = (double) sd->status.zeny; - if (z + (double) zeny > MAX_ZENY) + double z = sd->status.zeny; + if (z + zeny > MAX_ZENY) { zeny = 0; sd->status.zeny = MAX_ZENY; @@ -2273,16 +2253,11 @@ int pc_isUseitem(dumb_ptr<map_session_data> sd, int n) if (itemdb_type(nameid) != ItemType::USE) return 0; if (nameid == 601 - && (map[sd->bl_m].flag.noteleport)) + && (sd->bl_m->flag.noteleport)) { return 0; } - if (nameid == 602 && map[sd->bl_m].flag.noreturn) - return 0; - if (nameid == 604 - && (map[sd->bl_m].flag.nobranch)) - return 0; if (item->sex != 2 && sd->status.sex != item->sex) return 0; if (item->elv > 0 && sd->status.base_level < item->elv) @@ -2312,7 +2287,7 @@ int pc_useitem(dumb_ptr<map_session_data> sd, int n) return 1; } - run_script(sd->inventory_data[n]->use_script, 0, sd->bl_id, 0); + run_script(ScriptPointer(sd->inventory_data[n]->use_script.get(), 0), sd->bl_id, 0); clif_useitemack(sd, n, amount - 1, 1); pc_delitem(sd, n, 1, 1); @@ -2355,7 +2330,6 @@ int pc_setpos(dumb_ptr<map_session_data> sd, const char *mapname_org, int x, int BeingRemoveWhy clrtype) { char mapname[24]; - int m = 0; nullpo_ret(sd); @@ -2384,8 +2358,8 @@ int pc_setpos(dumb_ptr<map_session_data> sd, const char *mapname_org, int x, int strcat(mapname, ".gat"); } - m = map_mapname2mapid(mapname); - if (m < 0) + map_local *m = map_mapname2mapid(mapname); + if (!m) { if (sd->mapname[0]) { @@ -2419,10 +2393,10 @@ int pc_setpos(dumb_ptr<map_session_data> sd, const char *mapname_org, int x, int return 1; } - if (x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys) + if (x < 0 || x >= m->xs || y < 0 || y >= m->ys) x = y = 0; if ((x == 0 && y == 0) - || bool(read_gat(m, x, y) & MapCell::UNWALKABLE)) + || bool(read_gatp(m, x, y) & MapCell::UNWALKABLE)) { if (x || y) { @@ -2431,10 +2405,10 @@ int pc_setpos(dumb_ptr<map_session_data> sd, const char *mapname_org, int x, int } do { - x = random_::in(1, map[m].xs - 2); - y = random_::in(1, map[m].ys - 2); + x = random_::in(1, m->xs - 2); + y = random_::in(1, m->ys - 2); } - while (bool(read_gat(m, x, y) & MapCell::UNWALKABLE)); + while (bool(read_gatp(m, x, y) & MapCell::UNWALKABLE)); } if (sd->mapname[0] && sd->bl_prev != NULL) @@ -2442,7 +2416,7 @@ int pc_setpos(dumb_ptr<map_session_data> sd, const char *mapname_org, int x, int clif_clearchar(sd, clrtype); skill_gangsterparadise(sd, 0); map_delblock(sd); - clif_changemap(sd, map[m].name, x, y); // [MouseJstr] + clif_changemap(sd, m->name, x, y); // [MouseJstr] } memcpy(sd->mapname, mapname, 24); @@ -2468,25 +2442,24 @@ int pc_setpos(dumb_ptr<map_session_data> sd, const char *mapname_org, int x, int int pc_randomwarp(dumb_ptr<map_session_data> sd, BeingRemoveWhy type) { int x, y, i = 0; - int m; nullpo_ret(sd); - m = sd->bl_m; + map_local *m = sd->bl_m; - if (map[sd->bl_m].flag.noteleport) // テレポート禁止 + if (sd->bl_m->flag.noteleport) // テレポート禁止 return 0; do { - x = random_::in(1, map[m].xs - 2); - y = random_::in(1, map[m].ys - 2); + x = random_::in(1, m->xs - 2); + y = random_::in(1, m->ys - 2); } - while (bool(read_gat(m, x, y) & MapCell::UNWALKABLE) + while (bool(read_gatp(m, x, y) & MapCell::UNWALKABLE) && (i++) < 1000); if (i < 1000) - pc_setpos(sd, map[m].name, x, y, type); + pc_setpos(sd, m->name, x, y, type); return 0; } @@ -2589,7 +2562,8 @@ void pc_walk(TimerData *, tick_t tick, int id, unsigned char data) // sd->walktimer = dummy value that is not nullptr; map_foreachinmovearea(std::bind(clif_pcoutsight, ph::_1, sd), - sd->bl_m, x - AREA_SIZE, y - AREA_SIZE, + sd->bl_m, + x - AREA_SIZE, y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE, dx, dy, BL::NUL); @@ -2605,7 +2579,8 @@ void pc_walk(TimerData *, tick_t tick, int id, unsigned char data) map_addblock(sd); map_foreachinmovearea(std::bind(clif_pcinsight, ph::_1, sd), - sd->bl_m, x - AREA_SIZE, y - AREA_SIZE, + sd->bl_m, + x - AREA_SIZE, y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE, -dx, -dy, BL::NUL); @@ -2618,7 +2593,8 @@ void pc_walk(TimerData *, tick_t tick, int id, unsigned char data) { int p_flag = 0; map_foreachinmovearea(std::bind(party_send_hp_check, ph::_1, sd->status.party_id, &p_flag), - sd->bl_m, x - AREA_SIZE, y - AREA_SIZE, + sd->bl_m, + x - AREA_SIZE, y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE, -dx, -dy, BL::PC); @@ -2772,7 +2748,8 @@ int pc_movepos(dumb_ptr<map_session_data> sd, int dst_x, int dst_y) || sd->bl_y / BLOCK_SIZE != dst_y / BLOCK_SIZE); map_foreachinmovearea(std::bind(clif_pcoutsight, ph::_1, sd), - sd->bl_m, sd->bl_x - AREA_SIZE, sd->bl_y - AREA_SIZE, + sd->bl_m, + sd->bl_x - AREA_SIZE, sd->bl_y - AREA_SIZE, sd->bl_x + AREA_SIZE, sd->bl_y + AREA_SIZE, dx, dy, BL::NUL); @@ -2785,7 +2762,8 @@ int pc_movepos(dumb_ptr<map_session_data> sd, int dst_x, int dst_y) map_addblock(sd); map_foreachinmovearea(std::bind(clif_pcinsight, ph::_1, sd), - sd->bl_m, sd->bl_x - AREA_SIZE, sd->bl_y - AREA_SIZE, + sd->bl_m, + sd->bl_x - AREA_SIZE, sd->bl_y - AREA_SIZE, sd->bl_x + AREA_SIZE, sd->bl_y + AREA_SIZE, -dx, -dy, BL::NUL); @@ -2797,7 +2775,8 @@ int pc_movepos(dumb_ptr<map_session_data> sd, int dst_x, int dst_y) { int flag = 0; map_foreachinmovearea(std::bind(party_send_hp_check, ph::_1, sd->status.party_id, &flag), - sd->bl_m, sd->bl_x - AREA_SIZE, sd->bl_y - AREA_SIZE, + sd->bl_m, + sd->bl_x - AREA_SIZE, sd->bl_y - AREA_SIZE, sd->bl_x + AREA_SIZE, sd->bl_y + AREA_SIZE, -dx, -dy, BL::PC); @@ -3110,7 +3089,7 @@ int pc_gainexp_reason(dumb_ptr<map_session_data> sd, int base_exp, int job_exp, if (sd->bl_prev == NULL || pc_isdead(sd)) return 0; - if ((battle_config.pvp_exp == 0) && map[sd->bl_m].flag.pvp) // [MouseJstr] + if ((battle_config.pvp_exp == 0) && sd->bl_m->flag.pvp) // [MouseJstr] return 0; // no exp on pvp maps earray<const char *, PC_GAINEXP_REASON, PC_GAINEXP_REASON::COUNT> reasons //= @@ -3588,28 +3567,28 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd, if (battle_config.death_penalty_type > 0 && sd->status.base_level >= 20) { // changed penalty options, added death by player if pk_mode [Valaris] - if (!map[sd->bl_m].flag.nopenalty) + if (!sd->bl_m->flag.nopenalty) { if (battle_config.death_penalty_type == 1 && battle_config.death_penalty_base > 0) sd->status.base_exp -= - (double) pc_nextbaseexp(sd) * - (double) battle_config.death_penalty_base / 10000; + static_cast<double>(pc_nextbaseexp(sd)) * + static_cast<double>(battle_config.death_penalty_base) / 10000; if (battle_config.pk_mode && src && src->bl_type == BL::PC) sd->status.base_exp -= - (double) pc_nextbaseexp(sd) * - (double) battle_config.death_penalty_base / 10000; + static_cast<double>(pc_nextbaseexp(sd)) * + static_cast<double>(battle_config.death_penalty_base) / 10000; else if (battle_config.death_penalty_type == 2 && battle_config.death_penalty_base > 0) { if (pc_nextbaseexp(sd) > 0) sd->status.base_exp -= - (double) sd->status.base_exp * - (double) battle_config.death_penalty_base / 10000; + static_cast<double>(sd->status.base_exp) * + static_cast<double>(battle_config.death_penalty_base) / 10000; if (battle_config.pk_mode && src && src->bl_type == BL::PC) sd->status.base_exp -= - (double) sd->status.base_exp * - (double) battle_config.death_penalty_base / 10000; + static_cast<double>(sd->status.base_exp) * + static_cast<double>(battle_config.death_penalty_base) / 10000; } if (sd->status.base_exp < 0) sd->status.base_exp = 0; @@ -3618,23 +3597,23 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd, if (battle_config.death_penalty_type == 1 && battle_config.death_penalty_job > 0) sd->status.job_exp -= - (double) pc_nextjobexp(sd) * - (double) battle_config.death_penalty_job / 10000; + static_cast<double>(pc_nextjobexp(sd)) * + static_cast<double>(battle_config.death_penalty_job) / 10000; if (battle_config.pk_mode && src && src->bl_type == BL::PC) sd->status.job_exp -= - (double) pc_nextjobexp(sd) * - (double) battle_config.death_penalty_job / 10000; + static_cast<double>(pc_nextjobexp(sd)) * + static_cast<double>(battle_config.death_penalty_job) / 10000; else if (battle_config.death_penalty_type == 2 && battle_config.death_penalty_job > 0) { if (pc_nextjobexp(sd) > 0) sd->status.job_exp -= - (double) sd->status.job_exp * - (double) battle_config.death_penalty_job / 10000; + static_cast<double>(sd->status.job_exp) * + static_cast<double>(battle_config.death_penalty_job) / 10000; if (battle_config.pk_mode && src && src->bl_type == BL::PC) sd->status.job_exp -= - (double) sd->status.job_exp * - (double) battle_config.death_penalty_job / 10000; + static_cast<double>(sd->status.job_exp) * + static_cast<double>(battle_config.death_penalty_job) / 10000; } if (sd->status.job_exp < 0) sd->status.job_exp = 0; @@ -3643,10 +3622,10 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd, } // pvp - if (map[sd->bl_m].flag.pvp && !battle_config.pk_mode) + if (sd->bl_m->flag.pvp && !battle_config.pk_mode) { // disable certain pvp functions on pk_mode [Valaris] //ランキング計算 - if (!map[sd->bl_m].flag.pvp_nocalcrank) + if (!sd->bl_m->flag.pvp_nocalcrank) { sd->pvp_point -= 5; if (src && src->bl_type == BL::PC) @@ -4182,56 +4161,33 @@ int pc_setoption(dumb_ptr<map_session_data> sd, Option type) */ int pc_readreg(dumb_ptr<map_session_data> sd, int reg) { - int i; - nullpo_ret(sd); - for (i = 0; i < sd->reg_num; i++) - if (sd->reg[i].index == reg) - return sd->reg[i].data; - - return 0; + return sd->regm.get(reg); } /*========================================== * script用変数の値を設定 *------------------------------------------ */ -int pc_setreg(dumb_ptr<map_session_data> sd, int reg, int val) +void pc_setreg(dumb_ptr<map_session_data> sd, int reg, int val) { - int i; - - nullpo_ret(sd); - - for (i = 0; i < sd->reg_num; i++) - { - if (sd->reg[i].index == reg) - { - sd->reg[i].data = val; - return 0; - } - } - sd->reg_num++; - RECREATE(sd->reg, struct script_reg, sd->reg_num); - sd->reg[i].index = reg; - sd->reg[i].data = val; + nullpo_retv(sd); - return 0; + sd->regm.put(reg, val); } /*========================================== * script用文字列変数の値を読む *------------------------------------------ */ -char *pc_readregstr(dumb_ptr<map_session_data> sd, int reg) +const char *pc_readregstr(dumb_ptr<map_session_data> sd, int reg) { - int i; - nullpo_ret(sd); - for (i = 0; i < sd->regstr_num; i++) - if (sd->regstr[i].index == reg) - return sd->regstr[i].data; + std::string *s = sd->regstrm.search(reg); + if (s) + return s->c_str(); return NULL; } @@ -4240,30 +4196,18 @@ char *pc_readregstr(dumb_ptr<map_session_data> sd, int reg) * script用文字列変数の値を設定 *------------------------------------------ */ -int pc_setregstr(dumb_ptr<map_session_data> sd, int reg, const char *str) +void pc_setregstr(dumb_ptr<map_session_data> sd, int reg, const char *str) { - int i; + nullpo_retv(sd); - nullpo_ret(sd); - if (strlen(str) + 1 > sizeof(sd->regstr[0].data)) + if (!*str) { - PRINTF("pc_setregstr(): String too long!\n"); - return 0; + sd->regstrm.erase(reg); + return; } - for (i = 0; i < sd->regstr_num; i++) - if (sd->regstr[i].index == reg) - { - strcpy(sd->regstr[i].data, str); - return 0; - } - sd->regstr_num++; - RECREATE(sd->regstr, struct script_regstr, sd->regstr_num); - sd->regstr[i].index = reg; - strcpy(sd->regstr[i].data, str); - - return 0; + sd->regstrm.insert(reg, str); } /*========================================== @@ -4478,14 +4422,14 @@ int pc_setaccountreg2(dumb_ptr<map_session_data> sd, const char *reg, int val) *------------------------------------------ */ static -void pc_eventtimer(TimerData *, tick_t, int id, const char *data) +void pc_eventtimer(TimerData *, tick_t, int id, dumb_string data) { dumb_ptr<map_session_data> sd = map_id2sd(id); assert (sd != NULL); - npc_event(sd, data, 0); + npc_event(sd, data.c_str(), 0); - free(const_cast<char *>(data)); + data.delete_(); } /*========================================== @@ -4504,8 +4448,7 @@ int pc_addeventtimer(dumb_ptr<map_session_data> sd, interval_t tick, const char if (i < MAX_EVENTTIMER) { - char *evname = (char *) calloc(24, 1); - strzcpy(evname, name, 24); + dumb_string evname = dumb_string::copyn(name, 24); sd->eventtimer[i] = Timer(gettick() + tick, std::bind(pc_eventtimer, ph::_1, ph::_2, sd->bl_id, evname)); @@ -4862,7 +4805,7 @@ int pc_checkitem(dumb_ptr<map_session_data> sd) } //装備制限チェック if (bool(sd->status.inventory[i].equip) - && map[sd->bl_m].flag.pvp + && sd->bl_m->flag.pvp && (it->flag.no_equip == 1 || it->flag.no_equip == 3)) { //PvP制限 sd->status.inventory[i].equip = EPOS::ZERO; @@ -4932,17 +4875,17 @@ void pc_calc_pvprank_sub(dumb_ptr<block_list> bl, dumb_ptr<map_session_data> sd2 */ int pc_calc_pvprank(dumb_ptr<map_session_data> sd) { - struct map_data *m; - nullpo_ret(sd); - m = &map[sd->bl_m]; + map_local *m = sd->bl_m; nullpo_ret(m); if (!(m->flag.pvp)) return 0; sd->pvp_rank = 1; map_foreachinarea(std::bind(pc_calc_pvprank_sub, ph::_1, sd), - sd->bl_m, 0, 0, m->xs, m->ys, + sd->bl_m, + 0, 0, + m->xs, m->ys, BL::PC); return sd->pvp_rank; } @@ -5392,19 +5335,16 @@ void pc_autosave(TimerData *, tick_t) int pc_read_gm_account(int fd) { - int i = 0; - if (gm_accounts != NULL) - free(gm_accounts); - GM_num = 0; + gm_accountm.clear(); - CREATE(gm_accounts, struct GM_Account, (RFIFOW(fd, 2) - 4) / 5); - for (i = 4; i < RFIFOW(fd, 2); i = i + 5) + // (RFIFOW(fd, 2) - 4) / 5 + for (int i = 4; i < RFIFOW(fd, 2); i += 5) { - gm_accounts[GM_num].account_id = RFIFOL(fd, i); - gm_accounts[GM_num].level = (int) RFIFOB(fd, i + 4); - GM_num++; + int account_id = RFIFOL(fd, i); + uint8_t level = RFIFOB(fd, i + 4); + gm_accountm[account_id] = level; } - return GM_num; + return gm_accountm.size(); } void pc_setstand(dumb_ptr<map_session_data> sd) @@ -5467,7 +5407,7 @@ void pc_invisibility(dumb_ptr<map_session_data> sd, int enabled) { sd->status.option &= ~Option::INVISIBILITY; clif_status_change(sd, StatusChange::CLIF_OPTION_SC_INVISIBILITY, 0); - pc_setpos(sd, map[sd->bl_m].name, sd->bl_x, sd->bl_y, BeingRemoveWhy::WARPED); + pc_setpos(sd, sd->bl_m->name, sd->bl_x, sd->bl_y, BeingRemoveWhy::WARPED); } } diff --git a/src/map/pc.hpp b/src/map/pc.hpp index 4fa0b0c..c319543 100644 --- a/src/map/pc.hpp +++ b/src/map/pc.hpp @@ -42,7 +42,7 @@ bool pc_is90overweight(dumb_ptr<map_session_data> sd) // should do something with the specified player. void pc_touch_all_relevant_npcs(dumb_ptr<map_session_data> sd); -int pc_isGM(dumb_ptr<map_session_data> sd); +uint8_t pc_isGM(dumb_ptr<map_session_data> sd); int pc_iskiller(dumb_ptr<map_session_data> src, dumb_ptr<map_session_data> target); // [MouseJstr] void pc_invisibility(dumb_ptr<map_session_data> sd, int enabled); // [Fate] @@ -119,9 +119,9 @@ int pc_changelook(dumb_ptr<map_session_data>, LOOK, int); int pc_readparam(dumb_ptr<map_session_data>, SP); int pc_setparam(dumb_ptr<map_session_data>, SP, int); int pc_readreg(dumb_ptr<map_session_data>, int); -int pc_setreg(dumb_ptr<map_session_data>, int, int); -char *pc_readregstr(dumb_ptr<map_session_data> sd, int reg); -int pc_setregstr(dumb_ptr<map_session_data> sd, int reg, const char *str); +void pc_setreg(dumb_ptr<map_session_data>, int, int); +const char *pc_readregstr(dumb_ptr<map_session_data> sd, int reg); +void pc_setregstr(dumb_ptr<map_session_data> sd, int reg, const char *str); int pc_readglobalreg(dumb_ptr<map_session_data>, const char *); int pc_setglobalreg(dumb_ptr<map_session_data>, const char *, int); int pc_readaccountreg(dumb_ptr<map_session_data>, const char *); @@ -140,7 +140,7 @@ int pc_marriage(dumb_ptr<map_session_data> sd, dumb_ptr<map_session_data> dstsd); int pc_divorce(dumb_ptr<map_session_data> sd); dumb_ptr<map_session_data> pc_get_partner(dumb_ptr<map_session_data> sd); -int pc_set_gm_level(int account_id, int level); +void pc_set_gm_level(int account_id, uint8_t level); void pc_setstand(dumb_ptr<map_session_data> sd); void pc_cleanup(dumb_ptr<map_session_data> sd); // [Fate] Clean up after a logged-out PC diff --git a/src/map/script.cpp b/src/map/script.cpp index 6d65fd2..7281784 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -12,6 +12,7 @@ #include "../common/cxxstdio.hpp" #include "../common/db.hpp" #include "../common/extract.hpp" +#include "../common/intern-pool.hpp" #include "../common/lock.hpp" #include "../common/random.hpp" #include "../common/socket.hpp" @@ -35,49 +36,33 @@ #include "../poison.hpp" -//#define DEBUG_FUNCIN -//#define DEBUG_DISP -//#define DEBUG_RUN +constexpr bool DEBUG_DISP = false; +constexpr bool DEBUG_RUN = false; -constexpr int SCRIPT_BLOCK_SIZE = 256; -enum -{ LABEL_NEXTLINE = 1, LABEL_START }; -static -ScriptCode *script_buf; -static -int script_pos, script_size; - -static -char *str_buf; -static -int str_pos, str_size; -static struct str_data_t { - ScriptCode type; - int str; + ByteCode type; + std::string strs; int backpatch; - int label; - void(*func)(ScriptState *); + int label_; int val; - int next; -} *str_data; +}; static -int str_num = LABEL_START, str_data_size; +Map<std::string, str_data_t> str_datam; static -int str_hash[16]; +str_data_t LABEL_NEXTLINE_; static DMap<int, int> mapreg_db; static -DMap<int, char *> mapregstr_db; +Map<int, std::string> mapregstr_db; static int mapreg_dirty = -1; char mapreg_txt[256] = "save/mapreg.txt"; constexpr std::chrono::milliseconds MAPREG_AUTOSAVE_INTERVAL = std::chrono::seconds(10); Map<std::string, int> scriptlabel_db; -DMap<std::string, const ScriptCode *> userfunc_db; +UPMap<std::string, const ScriptBuffer> userfunc_db; static const char *pos[11] = @@ -108,14 +93,7 @@ struct Script_Config static int parse_cmd_if = 0; static -int parse_cmd; - -/*========================================== - * ローカルプロトタイプ宣言 (必要な物のみ) - *------------------------------------------ - */ -static -const char *parse_subexpr(const char *, int); +str_data_t *parse_cmdp; static void run_func(ScriptState *st); @@ -127,172 +105,84 @@ void mapreg_setregstr(int num, const char *str); struct BuiltinFunction { - void(*func)(ScriptState *); + void (*func)(ScriptState *); const char *name; const char *arg; }; // defined later extern BuiltinFunction builtin_functions[]; +static +InternPool variable_names; -enum class ScriptCode : uint8_t +enum class ByteCode : uint8_t { // types and specials - NOP, POS, INT, PARAM, FUNC, STR, CONSTSTR, ARG, - NAME, EOL, RETINFO, + NOP, POS, INT, PARAM_, FUNC_, STR, CONSTSTR, ARG, + VARIABLE, EOL, RETINFO, // unary and binary operators LOR, LAND, LE, LT, GE, GT, EQ, NE, - XOR, OR, AND, ADD, SUB, MUL, DIV, MOD, NEG, LNOT, - NOT, R_SHIFT, L_SHIFT -}; + XOR, OR, AND, ADD, SUB, MUL, DIV, MOD, + NEG, LNOT, NOT, R_SHIFT, L_SHIFT, -/*========================================== - * 文字列のハッシュを計算 - *------------------------------------------ - */ -static -int calc_hash(const char *s) -{ - const unsigned char *p = (const unsigned char *)s; - int h = 0; - while (*p) - { - h = (h << 1) + (h >> 3) + (h >> 5) + (h >> 8); - h += *p++; - } - return h & 15; -} + // additions + // needed because FUNC is used for the actual call + FUNC_REF, +}; -/*========================================== - * str_dataの中に名前があるか検索する - *------------------------------------------ - */ -// 既存のであれば番号、無ければ-1 static -int search_str(const char *p) +str_data_t *search_strp(const std::string& p) { - int i; - i = str_hash[calc_hash(p)]; - while (i) - { - if (strcmp(str_buf + str_data[i].str, p) == 0) - { - return i; - } - i = str_data[i].next; - } - return -1; + return str_datam.search(p); } -/*========================================== - * str_dataに名前を登録 - *------------------------------------------ - */ -// 既存のであれば番号、無ければ登録して新規番号 static -int add_str(const char *p) +str_data_t *add_strp(const std::string& p) { - int i; - char *lowcase; - // TODO remove lowcase - lowcase = strdup(p); - for (i = 0; lowcase[i]; i++) - lowcase[i] = tolower(lowcase[i]); - if ((i = search_str(lowcase)) >= 0) - { - free(lowcase); - return i; - } - free(lowcase); + std::string lowcase = p; + for (char& c : lowcase) + c = tolower(c); - i = calc_hash(p); - if (str_hash[i] == 0) - { - str_hash[i] = str_num; - } - else - { - i = str_hash[i]; - for (;;) - { - if (strcmp(str_buf + str_data[i].str, p) == 0) - { - return i; - } - if (str_data[i].next == 0) - break; - i = str_data[i].next; - } - str_data[i].next = str_num; - } - if (str_num >= str_data_size) - { - str_data_size += 128; - RECREATE(str_data, struct str_data_t, str_data_size); - memset(str_data + (str_data_size - 128), '\0', 128); - } - while (str_pos + strlen(p) + 1 >= str_size) - { - str_size += 256; - str_buf = (char *) realloc(str_buf, str_size); - memset(str_buf + (str_size - 256), '\0', 256); - } - strcpy(str_buf + str_pos, p); - str_data[str_num].type = ScriptCode::NOP; - str_data[str_num].str = str_pos; - str_data[str_num].next = 0; - str_data[str_num].func = NULL; - str_data[str_num].backpatch = -1; - str_data[str_num].label = -1; - str_pos += strlen(p) + 1; - return str_num++; -} + if (str_data_t *rv = search_strp(lowcase)) + return rv; -/*========================================== - * スクリプトバッファサイズの確認と拡張 - *------------------------------------------ - */ -static -void check_script_buf(int size) -{ - if (script_pos + size >= script_size) - { - script_size += SCRIPT_BLOCK_SIZE; - script_buf = (ScriptCode *) realloc(script_buf, script_size); - memset(script_buf + script_size - SCRIPT_BLOCK_SIZE, '\0', - SCRIPT_BLOCK_SIZE); - } + // ? + if (str_data_t *rv = search_strp(p)) + return rv; + + str_data_t *datum = str_datam.init(p); + datum->type = ByteCode::NOP; + datum->strs = p; + datum->backpatch = -1; + datum->label_ = -1; + return datum; } /*========================================== * スクリプトバッファに1バイト書き込む *------------------------------------------ */ -static -void add_scriptc(ScriptCode a) +void ScriptBuffer::add_scriptc(ByteCode a) { - check_script_buf(1); - script_buf[script_pos++] = a; + script_buf.push_back(a); } /*========================================== * スクリプトバッファにデータタイプを書き込む *------------------------------------------ */ -static -void add_scriptb(uint8_t a) +void ScriptBuffer::add_scriptb(uint8_t a) { - add_scriptc(static_cast<ScriptCode>(a)); + add_scriptc(static_cast<ByteCode>(a)); } /*========================================== * スクリプトバッファに整数を書き込む *------------------------------------------ */ -static -void add_scripti(unsigned int a) +void ScriptBuffer::add_scripti(uint32_t a) { while (a >= 0x40) { @@ -307,37 +197,43 @@ void add_scripti(unsigned int a) *------------------------------------------ */ // 最大16Mまで -static -void add_scriptl(int l) +void ScriptBuffer::add_scriptl(str_data_t *ld) { - int backpatch = str_data[l].backpatch; + int backpatch = ld->backpatch; - switch (str_data[l].type) + switch (ld->type) { - case ScriptCode::POS: - add_scriptc(ScriptCode::POS); - add_scriptb({uint8_t(str_data[l].label)}); - add_scriptb({uint8_t(str_data[l].label >> 8)}); - add_scriptb({uint8_t(str_data[l].label >> 16)}); + case ByteCode::POS: + add_scriptc(ByteCode::POS); + add_scriptb(static_cast<uint8_t>(ld->label_)); + add_scriptb(static_cast<uint8_t>(ld->label_ >> 8)); + add_scriptb(static_cast<uint8_t>(ld->label_ >> 16)); break; - case ScriptCode::NOP: - // ラベルの可能性があるのでbackpatch用データ埋め込み - add_scriptc(ScriptCode::NAME); - str_data[l].backpatch = script_pos; - add_scriptb({uint8_t(backpatch)}); - add_scriptb({uint8_t(backpatch >> 8)}); - add_scriptb({uint8_t(backpatch >> 16)}); + case ByteCode::NOP: + // need to set backpatch, because it might become a label later + add_scriptc(ByteCode::VARIABLE); + ld->backpatch = script_buf.size(); + add_scriptb(static_cast<uint8_t>(backpatch)); + add_scriptb(static_cast<uint8_t>(backpatch >> 8)); + add_scriptb(static_cast<uint8_t>(backpatch >> 16)); break; - case ScriptCode::INT: - add_scripti(str_data[l].val); + case ByteCode::INT: + add_scripti(ld->val); break; - default: - // もう他の用途と確定してるので数字をそのまま - add_scriptc(ScriptCode::NAME); - add_scriptb({uint8_t(l)}); - add_scriptb({uint8_t(l >> 8)}); - add_scriptb({uint8_t(l >> 16)}); + case ByteCode::FUNC_: + add_scriptc(ByteCode::FUNC_REF); + add_scriptb(static_cast<uint8_t>(ld->val)); + add_scriptb(static_cast<uint8_t>(ld->val >> 8)); + add_scriptb(static_cast<uint8_t>(ld->val >> 16)); + break; + case ByteCode::PARAM_: + add_scriptc(ByteCode::PARAM_); + add_scriptb(static_cast<uint8_t>(ld->val)); + add_scriptb(static_cast<uint8_t>(ld->val >> 8)); + add_scriptb(static_cast<uint8_t>(ld->val >> 16)); break; + default: + abort(); } } @@ -345,21 +241,23 @@ void add_scriptl(int l) * ラベルを解決する *------------------------------------------ */ -static -void set_label(int l, int pos_) +void ScriptBuffer::set_label(str_data_t *ld, int pos_) { - int i, next; + int next; - str_data[l].type = ScriptCode::POS; - str_data[l].label = pos_; - for (i = str_data[l].backpatch; i >= 0 && i != 0x00ffffff;) + ld->type = ByteCode::POS; + ld->label_ = pos_; + for (int i = ld->backpatch; i >= 0 && i != 0x00ffffff; i = next) { - next = (*(int *)(script_buf + i)) & 0x00ffffff; - script_buf[i - 1] = ScriptCode::POS; - script_buf[i] = static_cast<ScriptCode>(pos_); - script_buf[i + 1] = static_cast<ScriptCode>(pos_ >> 8); - script_buf[i + 2] = static_cast<ScriptCode>(pos_ >> 16); - i = next; + next = 0; + // woot! no longer endian-dependent! + next |= static_cast<uint8_t>(script_buf[i + 0]) << 0; + next |= static_cast<uint8_t>(script_buf[i + 1]) << 8; + next |= static_cast<uint8_t>(script_buf[i + 2]) << 16; + script_buf[i - 1] = ByteCode::POS; + script_buf[i] = static_cast<ByteCode>(pos_); + script_buf[i + 1] = static_cast<ByteCode>(pos_ >> 8); + script_buf[i + 2] = static_cast<ByteCode>(pos_ >> 16); } } @@ -474,16 +372,11 @@ void disp_error_message(const char *mes, const char *pos_) * 項の解析 *------------------------------------------ */ -static -const char *parse_simpleexpr(const char *p) +const char *ScriptBuffer::parse_simpleexpr(const char *p) { int i; p = skip_space(p); -#ifdef DEBUG_FUNCIN - if (battle_config.etc_log) - PRINTF("parse_simpleexpr %s\n", p); -#endif if (*p == ';' || *p == ',') { disp_error_message("unexpected expr end", p); @@ -509,7 +402,7 @@ const char *parse_simpleexpr(const char *p) } else if (*p == '"') { - add_scriptc(ScriptCode::STR); + add_scriptc(ByteCode::STR); p++; while (*p && *p != '"') { @@ -532,57 +425,42 @@ const char *parse_simpleexpr(const char *p) } else { - int l; // label , register , function etc - if (skip_word(p) == p) + const char *p2 = skip_word(p); + if (p2 == p) { disp_error_message("unexpected character", p); exit(1); } - char *p2 = const_cast<char *>(skip_word(p)); - char c = *p2; - *p2 = 0; // 名前をadd_strする - l = add_str(p); + str_data_t *ld = add_strp(std::string(p, p2)); - parse_cmd = l; // warn_*_mismatch_paramnumのために必要 - if (l == search_str("if")) // warn_cmd_no_commaのために必要 + parse_cmdp = ld; // warn_*_mismatch_paramnumのために必要 + // why not just check l->str == "if" or std::string(p, p2) == "if"? + if (ld == search_strp("if")) // warn_cmd_no_commaのために必要 parse_cmd_if++; -/* - // 廃止予定のl14/l15,およびプレフィックスlの警告 - if ( strcmp(str_buf+str_data[l].str,"l14")==0 || - strcmp(str_buf+str_data[l].str,"l15")==0 ){ - disp_error_message("l14 and l15 is DEPRECATED. use @menu instead of l15.",p); - }else if (str_buf[str_data[l].str]=='l'){ - disp_error_message("prefix 'l' is DEPRECATED. use prefix '@' instead.",p2); - } -*/ - *p2 = c; p = p2; - if (str_data[l].type != ScriptCode::FUNC && c == '[') + if (ld->type != ByteCode::FUNC_ && *p == '[') { // array(name[i] => getelementofarray(name,i) ) - add_scriptl(search_str("getelementofarray")); - add_scriptc(ScriptCode::ARG); - add_scriptl(l); + add_scriptl(search_strp("getelementofarray")); + add_scriptc(ByteCode::ARG); + add_scriptl(ld); p = parse_subexpr(p + 1, -1); p = skip_space(p); - if ((*p++) != ']') + if (*p != ']') { disp_error_message("unmatch ']'", p); exit(1); } - add_scriptc(ScriptCode::FUNC); + p++; + add_scriptc(ByteCode::FUNC_); } else - add_scriptl(l); + add_scriptl(ld); } -#ifdef DEBUG_FUNCIN - if (battle_config.etc_log) - PRINTF("parse_simpleexpr end %s\n", p); -#endif return p; } @@ -590,15 +468,11 @@ const char *parse_simpleexpr(const char *p) * 式の解析 *------------------------------------------ */ -const char *parse_subexpr(const char *p, int limit) +const char *ScriptBuffer::parse_subexpr(const char *p, int limit) { - ScriptCode op; + ByteCode op; int opl, len; -#ifdef DEBUG_FUNCIN - if (battle_config.etc_log) - PRINTF("parse_subexpr %s\n", p); -#endif p = skip_space(p); if (*p == '-') @@ -606,14 +480,14 @@ const char *parse_subexpr(const char *p, int limit) const char *tmpp = skip_space(p + 1); if (*tmpp == ';' || *tmpp == ',') { - add_scriptl(LABEL_NEXTLINE); + add_scriptl(&LABEL_NEXTLINE_); p++; return p; } } const char *tmpp = p; - if ((op = ScriptCode::NEG, *p == '-') || (op = ScriptCode::LNOT, *p == '!') - || (op = ScriptCode::NOT, *p == '~')) + if ((op = ByteCode::NEG, *p == '-') || (op = ByteCode::LNOT, *p == '!') + || (op = ByteCode::NOT, *p == '~')) { p = parse_subexpr(p + 1, 100); add_scriptc(op); @@ -621,39 +495,40 @@ const char *parse_subexpr(const char *p, int limit) else p = parse_simpleexpr(p); p = skip_space(p); - while (((op = ScriptCode::ADD, opl = 6, len = 1, *p == '+') || - (op = ScriptCode::SUB, opl = 6, len = 1, *p == '-') || - (op = ScriptCode::MUL, opl = 7, len = 1, *p == '*') || - (op = ScriptCode::DIV, opl = 7, len = 1, *p == '/') || - (op = ScriptCode::MOD, opl = 7, len = 1, *p == '%') || - (op = ScriptCode::FUNC, opl = 8, len = 1, *p == '(') || - (op = ScriptCode::LAND, opl = 1, len = 2, *p == '&' && p[1] == '&') || - (op = ScriptCode::AND, opl = 5, len = 1, *p == '&') || - (op = ScriptCode::LOR, opl = 0, len = 2, *p == '|' && p[1] == '|') || - (op = ScriptCode::OR, opl = 4, len = 1, *p == '|') || - (op = ScriptCode::XOR, opl = 3, len = 1, *p == '^') || - (op = ScriptCode::EQ, opl = 2, len = 2, *p == '=' && p[1] == '=') || - (op = ScriptCode::NE, opl = 2, len = 2, *p == '!' && p[1] == '=') || - (op = ScriptCode::R_SHIFT, opl = 5, len = 2, *p == '>' && p[1] == '>') || - (op = ScriptCode::GE, opl = 2, len = 2, *p == '>' && p[1] == '=') || - (op = ScriptCode::GT, opl = 2, len = 1, *p == '>') || - (op = ScriptCode::L_SHIFT, opl = 5, len = 2, *p == '<' && p[1] == '<') || - (op = ScriptCode::LE, opl = 2, len = 2, *p == '<' && p[1] == '=') || - (op = ScriptCode::LT, opl = 2, len = 1, *p == '<')) && opl > limit) + while (((op = ByteCode::ADD, opl = 6, len = 1, *p == '+') || + (op = ByteCode::SUB, opl = 6, len = 1, *p == '-') || + (op = ByteCode::MUL, opl = 7, len = 1, *p == '*') || + (op = ByteCode::DIV, opl = 7, len = 1, *p == '/') || + (op = ByteCode::MOD, opl = 7, len = 1, *p == '%') || + (op = ByteCode::FUNC_, opl = 8, len = 1, *p == '(') || + (op = ByteCode::LAND, opl = 1, len = 2, *p == '&' && p[1] == '&') || + (op = ByteCode::AND, opl = 5, len = 1, *p == '&') || + (op = ByteCode::LOR, opl = 0, len = 2, *p == '|' && p[1] == '|') || + (op = ByteCode::OR, opl = 4, len = 1, *p == '|') || + (op = ByteCode::XOR, opl = 3, len = 1, *p == '^') || + (op = ByteCode::EQ, opl = 2, len = 2, *p == '=' && p[1] == '=') || + (op = ByteCode::NE, opl = 2, len = 2, *p == '!' && p[1] == '=') || + (op = ByteCode::R_SHIFT, opl = 5, len = 2, *p == '>' && p[1] == '>') || + (op = ByteCode::GE, opl = 2, len = 2, *p == '>' && p[1] == '=') || + (op = ByteCode::GT, opl = 2, len = 1, *p == '>') || + (op = ByteCode::L_SHIFT, opl = 5, len = 2, *p == '<' && p[1] == '<') || + (op = ByteCode::LE, opl = 2, len = 2, *p == '<' && p[1] == '=') || + (op = ByteCode::LT, opl = 2, len = 1, *p == '<')) && opl > limit) { p += len; - if (op == ScriptCode::FUNC) + if (op == ByteCode::FUNC_) { - int i = 0, func = parse_cmd; + int i = 0; + str_data_t *funcp = parse_cmdp; const char *plist[128]; - if (str_data[func].type != ScriptCode::FUNC) + if (funcp->type != ByteCode::FUNC_) { disp_error_message("expect function", tmpp); exit(0); } - add_scriptc(ScriptCode::ARG); + add_scriptc(ByteCode::ARG); while (*p && *p != ')' && i < 128) { plist[i] = p; @@ -670,16 +545,17 @@ const char *parse_subexpr(const char *p, int limit) i++; } plist[i] = p; - if (*(p++) != ')') + if (*p != ')') { disp_error_message("func request '(' ')'", p); exit(1); } + p++; - if (str_data[func].type == ScriptCode::FUNC + if (funcp->type == ByteCode::FUNC_ && script_config.warn_func_mismatch_paramnum) { - const char *arg = builtin_functions[str_data[func].val].arg; + const char *arg = builtin_functions[funcp->val].arg; int j = 0; for (j = 0; arg[j]; j++) if (arg[j] == '*') @@ -691,17 +567,13 @@ const char *parse_subexpr(const char *p, int limit) } } } - else // not op == ScriptCode::FUNC + else // not op == ByteCode::FUNC { p = parse_subexpr(p, opl); } add_scriptc(op); p = skip_space(p); } -#ifdef DEBUG_FUNCIN - if (battle_config.etc_log) - PRINTF("parse_subexpr end %s\n", p); -#endif return p; /* return first untreated operator */ } @@ -709,13 +581,8 @@ const char *parse_subexpr(const char *p, int limit) * 式の評価 *------------------------------------------ */ -static -const char *parse_expr(const char *p) +const char *ScriptBuffer::parse_expr(const char *p) { -#ifdef DEBUG_FUNCIN - if (battle_config.etc_log) - PRINTF("parse_expr %s\n", p); -#endif switch (*p) { case ')': @@ -728,10 +595,6 @@ const char *parse_expr(const char *p) exit(1); } p = parse_subexpr(p, -1); -#ifdef DEBUG_FUNCIN - if (battle_config.etc_log) - PRINTF("parse_expr end %s\n", p); -#endif return p; } @@ -739,10 +602,9 @@ const char *parse_expr(const char *p) * 行の解析 *------------------------------------------ */ -static -const char *parse_line(const char *p) +const char *ScriptBuffer::parse_line(const char *p) { - int i = 0, cmd; + int i = 0; const char *plist[128]; p = skip_space(p); @@ -756,14 +618,14 @@ const char *parse_line(const char *p) p = parse_simpleexpr(p); p = skip_space(p); - cmd = parse_cmd; - if (str_data[cmd].type != ScriptCode::FUNC) + str_data_t *cmd = parse_cmdp; + if (cmd->type != ByteCode::FUNC_) { disp_error_message("expect command", p2); // exit(0); } - add_scriptc(ScriptCode::ARG); + add_scriptc(ByteCode::ARG); while (p && *p && *p != ';' && i < 128) { plist[i] = p; @@ -787,12 +649,12 @@ const char *parse_line(const char *p) disp_error_message("need ';'", p); exit(1); } - add_scriptc(ScriptCode::FUNC); + add_scriptc(ByteCode::FUNC_); - if (str_data[cmd].type == ScriptCode::FUNC + if (cmd->type == ByteCode::FUNC_ && script_config.warn_cmd_mismatch_paramnum) { - const char *arg = builtin_functions[str_data[cmd].val].arg; + const char *arg = builtin_functions[cmd->val].arg; int j = 0; for (j = 0; arg[j]; j++) if (arg[j] == '*') @@ -814,13 +676,11 @@ const char *parse_line(const char *p) static void add_builtin_functions(void) { - int i, n; - for (i = 0; builtin_functions[i].func; i++) + for (int i = 0; builtin_functions[i].func; i++) { - n = add_str(builtin_functions[i].name); - str_data[n].type = ScriptCode::FUNC; - str_data[n].val = i; - str_data[n].func = builtin_functions[i].func; + str_data_t *n = add_strp(builtin_functions[i].name); + n->type = ByteCode::FUNC_; + n->val = i; } } @@ -844,34 +704,33 @@ void read_constdb(void) if (line[0] == '/' && line[1] == '/') continue; - char *name = nullptr; + std::string name; int val; int type = 0; // if not provided -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat" - if (sscanf(line.c_str(), "%m[A-Za-z0-9_] %i %i", &name, &val, &type) < 2) - { - free(name); - continue; - } -#pragma GCC diagnostic pop - for (char *p = name; *p; ++p) - *p = tolower(*p); - int n = add_str(name); - free(name); - str_data[n].type = type ? ScriptCode::PARAM : ScriptCode::INT; - str_data[n].val = val; + if (SSCANF(line, "%m[A-Za-z0-9_] %i %i", &name, &val, &type) < 2) + continue; + for (char& c : name) + c = tolower(c); + str_data_t *n = add_strp(name); + n->type = type ? ByteCode::PARAM_ : ByteCode::INT; + n->val = val; } } +std::unique_ptr<const ScriptBuffer> parse_script(const char *src, int line) +{ + auto script_buf = make_unique<ScriptBuffer>(); + script_buf->parse_script(src, line); + return std::move(script_buf); +} + /*========================================== * スクリプトの解析 *------------------------------------------ */ -const ScriptCode *parse_script(const char *src, int line) +void ScriptBuffer::parse_script(const char *src, int line) { const char *p; - int i; static int first = 1; if (first) @@ -880,19 +739,17 @@ const ScriptCode *parse_script(const char *src, int line) read_constdb(); } first = 0; - script_buf = (ScriptCode *) calloc(SCRIPT_BLOCK_SIZE, 1); - script_pos = 0; - script_size = SCRIPT_BLOCK_SIZE; - str_data[LABEL_NEXTLINE].type = ScriptCode::NOP; - str_data[LABEL_NEXTLINE].backpatch = -1; - str_data[LABEL_NEXTLINE].label = -1; - for (i = LABEL_START; i < str_num; i++) - { - if (str_data[i].type == ScriptCode::POS || str_data[i].type == ScriptCode::NAME) + LABEL_NEXTLINE_.type = ByteCode::NOP; + LABEL_NEXTLINE_.backpatch = -1; + LABEL_NEXTLINE_.label_ = -1; + for (auto& pair : str_datam) + { + str_data_t& dit = pair.second; + if (dit.type == ByteCode::POS || dit.type == ByteCode::VARIABLE) { - str_data[i].type = ScriptCode::NOP; - str_data[i].backpatch = -1; - str_data[i].label = -1; + dit.type = ByteCode::NOP; + dit.backpatch = -1; + dit.label_ = -1; } } @@ -908,7 +765,7 @@ const ScriptCode *parse_script(const char *src, int line) if (*p != '{') { disp_error_message("not found '{'", p); - return NULL; + abort(); } for (p++; p && *p && *p != '}';) { @@ -916,20 +773,20 @@ const ScriptCode *parse_script(const char *src, int line) // labelだけ特殊処理 if (*skip_space(skip_word(p)) == ':') { - char *tmpp = const_cast<char *>(skip_word(p)); - char c = *tmpp; - *tmpp = '\0'; - int l = add_str(p); - if (str_data[l].label != -1) + const char *tmpp = skip_word(p); + std::string str(p, tmpp); + str_data_t *ld = add_strp(str); + bool e1 = ld->type != ByteCode::NOP; + bool e2 = ld->type == ByteCode::POS; + bool e3 = ld->label_ != -1; + assert (e1 == e2 && e2 == e3); + if (e3) { - *tmpp = c; disp_error_message("dup label ", p); exit(1); } - set_label(l, script_pos); - std::string str(p, skip_word(p)); - scriptlabel_db.insert(str, script_pos); - *tmpp = c; + set_label(ld, script_buf.size()); + scriptlabel_db.insert(str, script_buf.size()); p = tmpp + 1; continue; } @@ -937,58 +794,63 @@ const ScriptCode *parse_script(const char *src, int line) // 他は全部一緒くた p = parse_line(p); p = skip_space(p); - add_scriptc(ScriptCode::EOL); + add_scriptc(ByteCode::EOL); - set_label(LABEL_NEXTLINE, script_pos); - str_data[LABEL_NEXTLINE].type = ScriptCode::NOP; - str_data[LABEL_NEXTLINE].backpatch = -1; - str_data[LABEL_NEXTLINE].label = -1; + set_label(&LABEL_NEXTLINE_, script_buf.size()); + LABEL_NEXTLINE_.type = ByteCode::NOP; + LABEL_NEXTLINE_.backpatch = -1; + LABEL_NEXTLINE_.label_ = -1; } - add_scriptc(ScriptCode::NOP); + add_scriptc(ByteCode::NOP); - script_size = script_pos; - script_buf = (ScriptCode *) realloc(script_buf, script_pos + 1); - - // 未解決のラベルを解決 - for (i = LABEL_START; i < str_num; i++) + // resolve the unknown labels + for (auto& pair : str_datam) { - if (str_data[i].type == ScriptCode::NOP) + str_data_t& sit = pair.second; + if (sit.type == ByteCode::NOP) { - int j, next; - str_data[i].type = ScriptCode::NAME; - str_data[i].label = i; - for (j = str_data[i].backpatch; j >= 0 && j != 0x00ffffff;) + sit.type = ByteCode::VARIABLE; + sit.label_ = 0; // anything but -1. Shouldn't matter, but helps asserts. + size_t pool_index = variable_names.intern(sit.strs); + for (int next, j = sit.backpatch; j >= 0 && j != 0x00ffffff; j = next) { - next = (*(int *)(script_buf + j)) & 0x00ffffff; - script_buf[j] = static_cast<ScriptCode>(i); - script_buf[j + 1] = static_cast<ScriptCode>(i >> 8); - script_buf[j + 2] = static_cast<ScriptCode>(i >> 16); - j = next; + next = 0; + next |= static_cast<uint8_t>(script_buf[j + 0]) << 0; + next |= static_cast<uint8_t>(script_buf[j + 1]) << 8; + next |= static_cast<uint8_t>(script_buf[j + 2]) << 16; + script_buf[j] = static_cast<ByteCode>(pool_index); + script_buf[j + 1] = static_cast<ByteCode>(pool_index >> 8); + script_buf[j + 2] = static_cast<ByteCode>(pool_index >> 16); } } } -#ifdef DEBUG_DISP - for (i = 0; i < script_pos; i++) + if (!DEBUG_DISP) + return; + for (size_t i = 0; i < script_buf.size(); i++) { if ((i & 15) == 0) - PRINTF("%04x : ", i); + PRINTF("%04zx : ", i); PRINTF("%02x ", script_buf[i]); if ((i & 15) == 15) PRINTF("\n"); } PRINTF("\n"); -#endif - - return script_buf; } // // 実行系 // -enum -{ STOP = 1, END, RERUNLINE, GOTO, RETFUNC }; +enum class ScriptEndState +{ + ZERO, + STOP, + END, + RERUNLINE, + GOTO, + RETFUNC, +}; /*========================================== * ridからsdへの解決 @@ -1013,11 +875,20 @@ static void get_val(ScriptState *st, struct script_data *data) { dumb_ptr<map_session_data> sd = NULL; - if (data->type == ScriptCode::NAME) + + if (data->type == ByteCode::PARAM_) { - char *name = str_buf + str_data[data->u.num & 0x00ffffff].str; - char prefix = *name; - char postfix = name[strlen(name) - 1]; + if ((sd = script_rid2sd(st)) == NULL) + PRINTF("get_val error param SP::%d\n", data->u.num); + data->type = ByteCode::INT; + if (sd) + data->u.num = pc_readparam(sd, static_cast<SP>(data->u.num)); + } + else if (data->type == ByteCode::VARIABLE) + { + const std::string& name = variable_names.outtern(data->u.num & 0x00ffffff); + char prefix = name.front(); + char postfix = name.back(); if (prefix != '$') { @@ -1026,43 +897,29 @@ void get_val(ScriptState *st, struct script_data *data) } if (postfix == '$') { - - data->type = ScriptCode::CONSTSTR; + data->type = ByteCode::CONSTSTR; if (prefix == '@' || prefix == 'l') { if (sd) - data->u.str = pc_readregstr(sd, data->u.num); + data->u.str = dumb_string::fake(pc_readregstr(sd, data->u.num)); } else if (prefix == '$') { - data->u.str = mapregstr_db.get(data->u.num); + std::string *s = mapregstr_db.search(data->u.num); + data->u.str = s ? dumb_string::fake(s->c_str()) : dumb_string(); } else { PRINTF("script: get_val: illegal scope string variable.\n"); - data->u.str = "!!ERROR!!"; + data->u.str = dumb_string::fake("!!ERROR!!"); } - if (data->u.str == NULL) - data->u.str = ""; - + if (!data->u.str) + data->u.str = dumb_string::fake(""); } else { - - data->type = ScriptCode::INT; - if (str_data[data->u.num & 0x00ffffff].type == ScriptCode::INT) - { - // unreachable - data->u.num = str_data[data->u.num & 0x00ffffff].val; - } - else if (str_data[data->u.num & 0x00ffffff].type == ScriptCode::PARAM) - { - if (sd) - data->u.num = - pc_readparam(sd, - SP(str_data[data->u.num & 0x00ffffff].val)); - } - else if (prefix == '@' || prefix == 'l') + data->type = ByteCode::INT; + if (prefix == '@' || prefix == 'l') { if (sd) data->u.num = pc_readreg(sd, data->u.num); @@ -1076,18 +933,18 @@ void get_val(ScriptState *st, struct script_data *data) if (name[1] == '#') { if (sd) - data->u.num = pc_readaccountreg2(sd, name); + data->u.num = pc_readaccountreg2(sd, name.c_str()); } else { if (sd) - data->u.num = pc_readaccountreg(sd, name); + data->u.num = pc_readaccountreg(sd, name.c_str()); } } else { if (sd) - data->u.num = pc_readglobalreg(sd, name); + data->u.num = pc_readglobalreg(sd, name.c_str()); } } } @@ -1101,7 +958,7 @@ static struct script_data get_val2(ScriptState *st, int num) { struct script_data dat; - dat.type = ScriptCode::NAME; + dat.type = ByteCode::VARIABLE; dat.u.num = num; get_val(st, &dat); return dat; @@ -1112,21 +969,30 @@ struct script_data get_val2(ScriptState *st, int num) *------------------------------------------ */ static -void set_reg(dumb_ptr<map_session_data> sd, int num, const char *name, struct script_data vd) +void set_reg(dumb_ptr<map_session_data> sd, ByteCode type, size_t num, struct script_data vd) { - char prefix = *name; - char postfix = name[strlen(name) - 1]; + if (type == ByteCode::PARAM_) + { + int val = vd.u.num; + pc_setparam(sd, static_cast<SP>(num), val); + return; + } + assert (type == ByteCode::VARIABLE); + + const std::string& name = variable_names.outtern(num); + char prefix = name.front(); + char postfix = name.back(); if (postfix == '$') { - const char *str = vd.u.str; + dumb_string str = vd.u.str; if (prefix == '@' || prefix == 'l') { - pc_setregstr(sd, num, str); + pc_setregstr(sd, num, str.c_str()); } else if (prefix == '$') { - mapreg_setregstr(num, str); + mapreg_setregstr(num, str.c_str()); } else { @@ -1137,11 +1003,7 @@ void set_reg(dumb_ptr<map_session_data> sd, int num, const char *name, struct sc { // 数値 int val = vd.u.num; - if (str_data[num & 0x00ffffff].type == ScriptCode::PARAM) - { - pc_setparam(sd, SP(str_data[num & 0x00ffffff].val), val); - } - else if (prefix == '@' || prefix == 'l') + if (prefix == '@' || prefix == 'l') { pc_setreg(sd, num, val); } @@ -1152,31 +1014,31 @@ void set_reg(dumb_ptr<map_session_data> sd, int num, const char *name, struct sc else if (prefix == '#') { if (name[1] == '#') - pc_setaccountreg2(sd, name, val); + pc_setaccountreg2(sd, name.c_str(), val); else - pc_setaccountreg(sd, name, val); + pc_setaccountreg(sd, name.c_str(), val); } else { - pc_setglobalreg(sd, name, val); + pc_setglobalreg(sd, name.c_str(), val); } } } static -void set_reg(dumb_ptr<map_session_data> sd, int num, const char *name, int id) +void set_reg(dumb_ptr<map_session_data> sd, ByteCode type, size_t num, int id) { struct script_data vd; vd.u.num = id; - set_reg(sd, num, name, vd); + set_reg(sd, type, num, vd); } static -void set_reg(dumb_ptr<map_session_data> sd, int num, const char *name, const char *zd) +void set_reg(dumb_ptr<map_session_data> sd, ByteCode type, size_t num, dumb_string zd) { struct script_data vd; vd.u.str = zd; - set_reg(sd, num, name, vd); + set_reg(sd, type, num, vd); } /*========================================== @@ -1184,26 +1046,16 @@ void set_reg(dumb_ptr<map_session_data> sd, int num, const char *name, const cha *------------------------------------------ */ static -const char *conv_str(ScriptState *st, struct script_data *data) +dumb_string conv_str(ScriptState *st, struct script_data *data) { get_val(st, data); - assert (data->type != ScriptCode::RETINFO); - if (data->type == ScriptCode::INT) - { - char *buf; - buf = (char *) calloc(16, 1); - sprintf(buf, "%d", data->u.num); - data->type = ScriptCode::STR; - data->u.str = buf; - } -#if 1 - else if (data->type == ScriptCode::NAME) + assert (data->type != ByteCode::RETINFO); + if (data->type == ByteCode::INT) { - // テンポラリ。本来無いはず - data->type = ScriptCode::CONSTSTR; - data->u.str = str_buf + str_data[data->u.num].str; + std::string buf = STRPRINTF("%d", data->u.num); + data->type = ByteCode::STR; + data->u.str = dumb_string::copys(buf); } -#endif return data->u.str; } @@ -1215,23 +1067,23 @@ static int conv_num(ScriptState *st, struct script_data *data) { get_val(st, data); - assert (data->type != ScriptCode::RETINFO); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + assert (data->type != ByteCode::RETINFO); + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *p = data->u.str; - data->u.num = atoi(p); - if (data->type == ScriptCode::STR) - free(const_cast<char *>(p)); - data->type = ScriptCode::INT; + dumb_string p = data->u.str; + data->u.num = atoi(p.c_str()); + if (data->type == ByteCode::STR) + p.delete_(); + data->type = ByteCode::INT; } return data->u.num; } static -const ScriptCode *conv_script(ScriptState *st, struct script_data *data) +const ScriptBuffer *conv_script(ScriptState *st, struct script_data *data) { get_val(st, data); - assert (data->type == ScriptCode::RETINFO); + assert (data->type == ByteCode::RETINFO); return data->u.script; } @@ -1240,45 +1092,27 @@ const ScriptCode *conv_script(ScriptState *st, struct script_data *data) *------------------------------------------ */ static -void push_val(struct script_stack *stack, ScriptCode type, int val) +void push_val(struct script_stack *stack, ByteCode type, int val) { - assert (type != ScriptCode::RETINFO); - assert (type != ScriptCode::STR); - assert (type != ScriptCode::CONSTSTR); - if (stack->sp >= stack->sp_max) - { - stack->sp_max += 64; - stack->stack_data = (struct script_data *) - realloc(stack->stack_data, sizeof(stack->stack_data[0]) * - stack->sp_max); - memset(stack->stack_data + (stack->sp_max - 64), 0, - 64 * sizeof(*(stack->stack_data))); - } -// if(battle_config.etc_log) -// PRINTF("push (%d,%d)-> %d\n",type,val,stack->sp); - stack->stack_data[stack->sp].type = type; - stack->stack_data[stack->sp].u.num = val; - stack->sp++; + assert (type != ByteCode::RETINFO); + assert (type != ByteCode::STR); + assert (type != ByteCode::CONSTSTR); + + script_data nsd {}; + nsd.type = type; + nsd.u.num = val; + stack->stack_datav.push_back(nsd); } static -void push_script(struct script_stack *stack, ScriptCode type, const ScriptCode *code) +void push_script(struct script_stack *stack, ByteCode type, const ScriptBuffer *code) { - assert (type == ScriptCode::RETINFO); - if (stack->sp >= stack->sp_max) - { - stack->sp_max += 64; - stack->stack_data = (struct script_data *) - realloc(stack->stack_data, sizeof(stack->stack_data[0]) * - stack->sp_max); - memset(stack->stack_data + (stack->sp_max - 64), 0, - 64 * sizeof(*(stack->stack_data))); - } -// if(battle_config.etc_log) -// PRINTF("push (%d,%d)-> %d\n",type,val,stack->sp); - stack->stack_data[stack->sp].type = type; - stack->stack_data[stack->sp].u.script = code; - stack->sp++; + assert (type == ByteCode::RETINFO); + + script_data nsd {}; + nsd.type = type; + nsd.u.script = code; + stack->stack_datav.push_back(nsd); } /*========================================== @@ -1286,23 +1120,14 @@ void push_script(struct script_stack *stack, ScriptCode type, const ScriptCode * *------------------------------------------ */ static -void push_str(struct script_stack *stack, ScriptCode type, const char *str) +void push_str(struct script_stack *stack, ByteCode type, dumb_string str) { - assert (type == ScriptCode::STR || type == ScriptCode::CONSTSTR); - if (stack->sp >= stack->sp_max) - { - stack->sp_max += 64; - stack->stack_data = (struct script_data *) - realloc(stack->stack_data, sizeof(stack->stack_data[0]) * - stack->sp_max); - memset(stack->stack_data + (stack->sp_max - 64), '\0', - 64 * sizeof(*(stack->stack_data))); - } -// if(battle_config.etc_log) -// PRINTF("push (%d,%x)-> %d\n",type,str,stack->sp); - stack->stack_data[stack->sp].type = type; - stack->stack_data[stack->sp].u.str = str; - stack->sp++; + assert (type == ByteCode::STR || type == ByteCode::CONSTSTR); + + script_data nsd {}; + nsd.type = type; + nsd.u.str = str; + stack->stack_datav.push_back(nsd); } /*========================================== @@ -1312,19 +1137,10 @@ void push_str(struct script_stack *stack, ScriptCode type, const char *str) static void push_copy(struct script_stack *stack, int pos_) { - switch (stack->stack_data[pos_].type) - { - case ScriptCode::CONSTSTR: - push_str(stack, ScriptCode::CONSTSTR, stack->stack_data[pos_].u.str); - break; - case ScriptCode::STR: - push_str(stack, ScriptCode::STR, strdup(stack->stack_data[pos_].u.str)); - break; - default: - push_val(stack, stack->stack_data[pos_].type, - stack->stack_data[pos_].u.num); - break; - } + script_data csd = stack->stack_datav[pos_]; + if (csd.type == ByteCode::STR) + csd.u.str = csd.u.str.dup(); + stack->stack_datav.push_back(csd); } /*========================================== @@ -1334,22 +1150,18 @@ void push_copy(struct script_stack *stack, int pos_) static void pop_stack(struct script_stack *stack, int start, int end) { - int i; - for (i = start; i < end; i++) + for (int i = start; i < end; i++) { - if (stack->stack_data[i].type == ScriptCode::STR) - { - free(const_cast<char *>(stack->stack_data[i].u.str)); - } - } - if (stack->sp > end) - { - memmove(&stack->stack_data[start], &stack->stack_data[end], - sizeof(stack->stack_data[0]) * (stack->sp - end)); + if (stack->stack_datav[i].type == ByteCode::STR) + stack->stack_datav[i].u.str.delete_(); } - stack->sp -= end - start; + auto it = stack->stack_datav.begin(); + stack->stack_datav.erase(it + start, it + end); } +#define AARGO2(n) (st->stack->stack_datav[st->start + (n)]) +#define HARGO2(n) (st->end > st->start + (n)) + // // 埋め込み関数 // @@ -1360,9 +1172,8 @@ void pop_stack(struct script_stack *stack, int start, int end) static void builtin_mes(ScriptState *st) { - conv_str(st, &(st->stack->stack_data[st->start + 2])); - clif_scriptmes(script_rid2sd(st), st->oid, - st->stack->stack_data[st->start + 2].u.str); + dumb_string mes = conv_str(st, &AARGO2(2)); + clif_scriptmes(script_rid2sd(st), st->oid, mes.c_str()); } /*========================================== @@ -1372,15 +1183,15 @@ void builtin_mes(ScriptState *st) static void builtin_goto(ScriptState *st) { - if (st->stack->stack_data[st->start + 2].type != ScriptCode::POS) + if (AARGO2(2).type != ByteCode::POS) { PRINTF("script: goto: not label !\n"); - st->state = END; + st->state = ScriptEndState::END; return; } - st->pos = conv_num(st, &(st->stack->stack_data[st->start + 2])); - st->state = GOTO; + st->scriptp.pos = conv_num(st, &AARGO2(2)); + st->state = ScriptEndState::GOTO; } /*========================================== @@ -1390,10 +1201,10 @@ void builtin_goto(ScriptState *st) static void builtin_callfunc(ScriptState *st) { - const ScriptCode *scr; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string str = conv_str(st, &AARGO2(2)); + const ScriptBuffer *scr = userfunc_db.get(str.str()); - if ((scr = userfunc_db.get(str))) + if (scr) { int j = 0; assert (st->start + 3 == st->end); @@ -1402,20 +1213,19 @@ void builtin_callfunc(ScriptState *st) push_copy(st->stack, i); #endif - push_val(st->stack, ScriptCode::INT, j); // 引数の数をプッシュ - push_val(st->stack, ScriptCode::INT, st->defsp); // 現在の基準スタックポインタをプッシュ - push_val(st->stack, ScriptCode::INT, st->pos); // 現在のスクリプト位置をプッシュ - push_script(st->stack, ScriptCode::RETINFO, st->script); // 現在のスクリプトをプッシュ + push_val(st->stack, ByteCode::INT, j); // 引数の数をプッシュ + push_val(st->stack, ByteCode::INT, st->defsp); // 現在の基準スタックポインタをプッシュ + push_val(st->stack, ByteCode::INT, st->scriptp.pos); // 現在のスクリプト位置をプッシュ + push_script(st->stack, ByteCode::RETINFO, st->scriptp.code); // 現在のスクリプトをプッシュ - st->pos = 0; - st->script = scr; + st->scriptp = ScriptPointer(scr, 0); st->defsp = st->start + 4 + j; - st->state = GOTO; + st->state = ScriptEndState::GOTO; } else { PRINTF("script:callfunc: function not found! [%s]\n", str); - st->state = END; + st->state = ScriptEndState::END; } } @@ -1426,7 +1236,7 @@ void builtin_callfunc(ScriptState *st) static void builtin_callsub(ScriptState *st) { - int pos_ = conv_num(st, &(st->stack->stack_data[st->start + 2])); + int pos_ = conv_num(st, &AARGO2(2)); int j = 0; assert (st->start + 3 == st->end); #if 0 @@ -1434,14 +1244,14 @@ void builtin_callsub(ScriptState *st) push_copy(st->stack, i); #endif - push_val(st->stack, ScriptCode::INT, j); // 引数の数をプッシュ - push_val(st->stack, ScriptCode::INT, st->defsp); // 現在の基準スタックポインタをプッシュ - push_val(st->stack, ScriptCode::INT, st->pos); // 現在のスクリプト位置をプッシュ - push_script(st->stack, ScriptCode::RETINFO, st->script); // 現在のスクリプトをプッシュ + push_val(st->stack, ByteCode::INT, j); // 引数の数をプッシュ + push_val(st->stack, ByteCode::INT, st->defsp); // 現在の基準スタックポインタをプッシュ + push_val(st->stack, ByteCode::INT, st->scriptp.pos); // 現在のスクリプト位置をプッシュ + push_script(st->stack, ByteCode::RETINFO, st->scriptp.code); // 現在のスクリプトをプッシュ - st->pos = pos_; + st->scriptp.pos = pos_; st->defsp = st->start + 4 + j; - st->state = GOTO; + st->state = ScriptEndState::GOTO; } /*========================================== @@ -1452,12 +1262,12 @@ static void builtin_return(ScriptState *st) { #if 0 - if (st->end > st->start + 2) + if (HARGO2(2)) { // 戻り値有り push_copy(st->stack, st->start + 2); } #endif - st->state = RETFUNC; + st->state = ScriptEndState::RETFUNC; } /*========================================== @@ -1467,7 +1277,7 @@ void builtin_return(ScriptState *st) static void builtin_next(ScriptState *st) { - st->state = STOP; + st->state = ScriptEndState::STOP; clif_scriptnext(script_rid2sd(st), st->oid); } @@ -1478,14 +1288,14 @@ void builtin_next(ScriptState *st) static void builtin_close(ScriptState *st) { - st->state = END; + st->state = ScriptEndState::END; clif_scriptclose(script_rid2sd(st), st->oid); } static void builtin_close2(ScriptState *st) { - st->state = STOP; + st->state = ScriptEndState::STOP; clif_scriptclose(script_rid2sd(st), st->oid); } @@ -1496,69 +1306,54 @@ void builtin_close2(ScriptState *st) static void builtin_menu(ScriptState *st) { - char *buf; - int i, len = 0; // [fate] len is the total # of bytes we need to transmit the string choices - int menu_choices = 0; - int finished_menu_items = 0; // [fate] set to 1 after we hit the first empty string - - dumb_ptr<map_session_data> sd; - - sd = script_rid2sd(st); - - // We don't need to do this iteration if the player cancels, strictly speaking. - for (i = st->start + 2; i < st->end; i += 2) - { - int choice_len; - conv_str(st, &(st->stack->stack_data[i])); - choice_len = strlen(st->stack->stack_data[i].u.str); - len += choice_len + 1; // count # of bytes we'll need for packet. Only used if menu_or_input = 0. - - if (choice_len && !finished_menu_items) - ++menu_choices; - else - finished_menu_items = 1; - } + dumb_ptr<map_session_data> sd = script_rid2sd(st); if (sd->state.menu_or_input == 0) { - st->state = RERUNLINE; + // First half: show menu. + st->state = ScriptEndState::RERUNLINE; sd->state.menu_or_input = 1; - buf = (char *) calloc(len + 1, 1); - buf[0] = 0; - for (i = st->start + 2; menu_choices > 0; i += 2, --menu_choices) + std::string buf; + for (int i = st->start + 2; i < st->end; i += 2) { - strcat(buf, st->stack->stack_data[i].u.str); - strcat(buf, ":"); + dumb_string choice_str = conv_str(st, &AARGO2(i - st->start)); + if (!choice_str[0]) + break; + buf += choice_str.c_str(); + buf += ':'; } - clif_scriptmenu(script_rid2sd(st), st->oid, buf); - free(buf); - } - else if (sd->npc_menu == 0xff) - { // cansel - sd->state.menu_or_input = 0; - st->state = END; + + clif_scriptmenu(script_rid2sd(st), st->oid, buf.c_str()); } else - { // goto動作 - // ragemu互換のため - pc_setreg(sd, add_str("l15"), sd->npc_menu); - pc_setreg(sd, add_str("@menu"), sd->npc_menu); + { + // Rerun: item is chosen from menu. + if (sd->npc_menu == 0xff) + { + // cancel + sd->state.menu_or_input = 0; + st->state = ScriptEndState::END; + return; + } + + // Actually jump to the label. + // Logic change: menu_choices is the *total* number of labels, + // not just the displayed number that ends with the "". + // (Would it be better to pop the stack before rerunning?) + int menu_choices = (st->end - (st->start + 2)) / 2; + pc_setreg(sd, variable_names.intern("@menu"), sd->npc_menu); sd->state.menu_or_input = 0; if (sd->npc_menu > 0 && sd->npc_menu <= menu_choices) { - if (st->stack-> - stack_data[st->start + sd->npc_menu * 2 + 1].type != ScriptCode::POS) + int arg_index = (sd->npc_menu - 1) * 2 + 1; + if (AARGO2(arg_index + 2).type != ByteCode::POS) { - st->state = END; + st->state = ScriptEndState::END; return; } - st->pos = - conv_num(st, - &(st-> - stack->stack_data[st->start + sd->npc_menu * 2 + - 1])); - st->state = GOTO; + st->scriptp.pos = conv_num(st, &AARGO2(arg_index + 2)); + st->state = ScriptEndState::GOTO; } } } @@ -1570,18 +1365,18 @@ void builtin_menu(ScriptState *st) static void builtin_rand(ScriptState *st) { - if (st->end > st->start + 3) + if (HARGO2(3)) { - int min = conv_num(st, &(st->stack->stack_data[st->start + 2])); - int max = conv_num(st, &(st->stack->stack_data[st->start + 3])); + int min = conv_num(st, &AARGO2(2)); + int max = conv_num(st, &AARGO2(3)); if (min > max) std::swap(max, min); - push_val(st->stack, ScriptCode::INT, random_::in(min, max)); + push_val(st->stack, ByteCode::INT, random_::in(min, max)); } else { - int range = conv_num(st, &(st->stack->stack_data[st->start + 2])); - push_val(st->stack, ScriptCode::INT, range <= 0 ? 0 : random_::to(range)); + int range = conv_num(st, &AARGO2(2)); + push_val(st->stack, ByteCode::INT, range <= 0 ? 0 : random_::to(range)); } } @@ -1594,10 +1389,11 @@ void builtin_pow(ScriptState *st) { int a, b; - a = conv_num(st, &(st->stack->stack_data[st->start + 2])); - b = conv_num(st, &(st->stack->stack_data[st->start + 3])); + a = conv_num(st, &AARGO2(2)); + b = conv_num(st, &AARGO2(3)); - push_val(st->stack, ScriptCode::INT, (int) pow(a * 0.001, b)); +#warning "This is silly" + push_val(st->stack, ByteCode::INT, static_cast<int>(pow(a * 0.001, b))); } @@ -1611,17 +1407,17 @@ void builtin_isat(ScriptState *st) int x, y; dumb_ptr<map_session_data> sd = script_rid2sd(st); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y = conv_num(st, &(st->stack->stack_data[st->start + 4])); + dumb_string str = conv_str(st, &AARGO2(2)); + x = conv_num(st, &AARGO2(3)); + y = conv_num(st, &AARGO2(4)); if (!sd) return; - push_val(st->stack, ScriptCode::INT, - (x == sd->bl_x) - && (y == sd->bl_y) && (!strcmp(str, map[sd->bl_m].name))); - + using namespace operators; + push_val(st->stack, ByteCode::INT, + (x == sd->bl_x) && (y == sd->bl_y) + && (str == sd->bl_m->name)); } /*========================================== @@ -1634,29 +1430,30 @@ void builtin_warp(ScriptState *st) int x, y; dumb_ptr<map_session_data> sd = script_rid2sd(st); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y = conv_num(st, &(st->stack->stack_data[st->start + 4])); - if (strcmp(str, "Random") == 0) + dumb_string str = conv_str(st, &AARGO2(2)); + x = conv_num(st, &AARGO2(3)); + y = conv_num(st, &AARGO2(4)); + using namespace operators; + if (str == "Random") pc_randomwarp(sd, BeingRemoveWhy::WARPED); - else if (strcmp(str, "SavePoint") == 0) + else if (str == "SavePoint") { - if (map[sd->bl_m].flag.noreturn) // 蝶禁止 + if (sd->bl_m->flag.noreturn) // 蝶禁止 return; pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, BeingRemoveWhy::WARPED); } - else if (strcmp(str, "Save") == 0) + else if (str == "Save") { - if (map[sd->bl_m].flag.noreturn) // 蝶禁止 + if (sd->bl_m->flag.noreturn) // 蝶禁止 return; pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, BeingRemoveWhy::WARPED); } else - pc_setpos(sd, str, x, y, BeingRemoveWhy::GONE); + pc_setpos(sd, str.c_str(), x, y, BeingRemoveWhy::GONE); } /*========================================== @@ -1664,35 +1461,40 @@ void builtin_warp(ScriptState *st) *------------------------------------------ */ static -void builtin_areawarp_sub(dumb_ptr<block_list> bl, const char *mapname, int x, int y) +void builtin_areawarp_sub(dumb_ptr<block_list> bl, dumb_string mapname, int x, int y) { dumb_ptr<map_session_data> sd = bl->as_player(); - if (strcmp(mapname, "Random") == 0) + using namespace operators; + if (mapname == "Random") pc_randomwarp(sd, BeingRemoveWhy::WARPED); else - pc_setpos(sd, mapname, x, y, BeingRemoveWhy::GONE); + pc_setpos(sd, mapname.c_str(), x, y, BeingRemoveWhy::GONE); } static void builtin_areawarp(ScriptState *st) { - int x, y, m; + int x, y; int x0, y0, x1, y1; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x0 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y0 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - x1 = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y1 = conv_num(st, &(st->stack->stack_data[st->start + 6])); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 7])); - x = conv_num(st, &(st->stack->stack_data[st->start + 8])); - y = conv_num(st, &(st->stack->stack_data[st->start + 9])); - - if ((m = map_mapname2mapid(mapname)) < 0) + dumb_string mapname = conv_str(st, &AARGO2(2)); + x0 = conv_num(st, &AARGO2(3)); + y0 = conv_num(st, &AARGO2(4)); + x1 = conv_num(st, &AARGO2(5)); + y1 = conv_num(st, &AARGO2(6)); + dumb_string str = conv_str(st, &AARGO2(7)); + x = conv_num(st, &AARGO2(8)); + y = conv_num(st, &AARGO2(9)); + + map_local *m = map_mapname2mapid(mapname.c_str()); + if (m == nullptr) return; map_foreachinarea(std::bind(builtin_areawarp_sub, ph::_1, str, x, y), - m, x0, y0, x1, y1, BL::PC); + m, + x0, y0, + x1, y1, + BL::PC); } /*========================================== @@ -1704,8 +1506,8 @@ void builtin_heal(ScriptState *st) { int hp, sp; - hp = conv_num(st, &(st->stack->stack_data[st->start + 2])); - sp = conv_num(st, &(st->stack->stack_data[st->start + 3])); + hp = conv_num(st, &AARGO2(2)); + sp = conv_num(st, &AARGO2(3)); pc_heal(script_rid2sd(st), hp, sp); } @@ -1718,8 +1520,8 @@ void builtin_itemheal(ScriptState *st) { int hp, sp; - hp = conv_num(st, &(st->stack->stack_data[st->start + 2])); - sp = conv_num(st, &(st->stack->stack_data[st->start + 3])); + hp = conv_num(st, &AARGO2(2)); + sp = conv_num(st, &AARGO2(3)); pc_itemheal(script_rid2sd(st), hp, sp); } @@ -1732,8 +1534,8 @@ void builtin_percentheal(ScriptState *st) { int hp, sp; - hp = conv_num(st, &(st->stack->stack_data[st->start + 2])); - sp = conv_num(st, &(st->stack->stack_data[st->start + 3])); + hp = conv_num(st, &AARGO2(2)); + sp = conv_num(st, &AARGO2(3)); pc_percentheal(script_rid2sd(st), hp, sp); } @@ -1745,57 +1547,42 @@ static void builtin_input(ScriptState *st) { dumb_ptr<map_session_data> sd = NULL; - int num = - (st->end > - st->start + 2) ? st->stack->stack_data[st->start + 2].u.num : 0; - const char *name = - (st->end > - st->start + 2) ? str_buf + str_data[num & 0x00ffffff].str : ""; -// char prefix=*name; - char postfix = name[strlen(name) - 1]; + script_data& scrd = AARGO2(2); + ByteCode type = scrd.type; + assert (type == ByteCode::VARIABLE); + + int num = scrd.u.num; + const std::string& name = variable_names.outtern(num & 0x00ffffff); +// char prefix = name.front(); + char postfix = name.back(); sd = script_rid2sd(st); if (sd->state.menu_or_input) { + // Second time (rerun) sd->state.menu_or_input = 0; if (postfix == '$') { - // 文字列 - if (st->end > st->start + 2) - { // 引数1個 - set_reg(sd, num, name, sd->npc_str); - } - else - { - PRINTF("builtin_input: string discarded !!\n"); - } + set_reg(sd, type, num, dumb_string::fake(sd->npc_str)); } else { - //commented by Lupus (check Value Number Input fix in clif.c) //** Fix by fritz :X keeps people from abusing old input bugs + // wtf? if (sd->npc_amount < 0) //** If input amount is less then 0 { clif_tradecancelled(sd); // added "Deal has been cancelled" message by Valaris builtin_close(st); //** close } - // 数値 - if (st->end > st->start + 2) - { // 引数1個 - set_reg(sd, num, name, sd->npc_amount); - } - else - { - // ragemu互換のため - pc_setreg(sd, add_str("l14"), sd->npc_amount); - } + set_reg(sd, type, num, sd->npc_amount); } } else { - st->state = RERUNLINE; + // First time - send prompt to client, then wait + st->state = ScriptEndState::RERUNLINE; if (postfix == '$') clif_scriptinputstr(sd, st->oid); else @@ -1813,14 +1600,14 @@ void builtin_if (ScriptState *st) { int sel, i; - sel = conv_num(st, &(st->stack->stack_data[st->start + 2])); + sel = conv_num(st, &AARGO2(2)); if (!sel) return; // 関数名をコピー push_copy(st->stack, st->start + 3); // 間に引数マーカを入れて - push_val(st->stack, ScriptCode::ARG, 0); + push_val(st->stack, ByteCode::ARG, 0); // 残りの引数をコピー for (i = st->start + 4; i < st->end; i++) { @@ -1838,16 +1625,20 @@ static void builtin_set(ScriptState *st) { dumb_ptr<map_session_data> sd = NULL; - int num = st->stack->stack_data[st->start + 2].u.num; - char *name = str_buf + str_data[num & 0x00ffffff].str; - char prefix = *name; - char postfix = name[strlen(name) - 1]; - - if (st->stack->stack_data[st->start + 2].type != ScriptCode::NAME) + int num = AARGO2(2).u.num; + if (AARGO2(2).type == ByteCode::PARAM_) { - PRINTF("script: builtin_set: not name\n"); + sd = script_rid2sd(st); + + int val = conv_num(st, &AARGO2(3)); + set_reg(sd, ByteCode::PARAM_, num, val); return; } + const std::string& name = variable_names.outtern(num & 0x00ffffff); + char prefix = name.front(); + char postfix = name.back(); + + assert (AARGO2(2).type == ByteCode::VARIABLE); if (prefix != '$') sd = script_rid2sd(st); @@ -1855,14 +1646,14 @@ void builtin_set(ScriptState *st) if (postfix == '$') { // 文字列 - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 3])); - set_reg(sd, num, name, str); + dumb_string str = conv_str(st, &AARGO2(3)); + set_reg(sd, ByteCode::VARIABLE, num, str); } else { // 数値 - int val = conv_num(st, &(st->stack->stack_data[st->start + 3])); - set_reg(sd, num, name, val); + int val = conv_num(st, &AARGO2(3)); + set_reg(sd, ByteCode::VARIABLE, num, val); } } @@ -1875,11 +1666,11 @@ static void builtin_setarray(ScriptState *st) { dumb_ptr<map_session_data> sd = NULL; - int num = st->stack->stack_data[st->start + 2].u.num; - char *name = str_buf + str_data[num & 0x00ffffff].str; - char prefix = *name; - char postfix = name[strlen(name) - 1]; - int i, j; + assert (AARGO2(2).type == ByteCode::VARIABLE); + int num = AARGO2(2).u.num; + const std::string& name = variable_names.outtern(num & 0x00ffffff); + char prefix = name.front(); + char postfix = name.back(); if (prefix != '$' && prefix != '@') { @@ -1889,12 +1680,12 @@ void builtin_setarray(ScriptState *st) if (prefix != '$') sd = script_rid2sd(st); - for (j = 0, i = st->start + 3; i < st->end && j < 128; i++, j++) + for (int j = 0, i = st->start + 3; i < st->end && j < 128; i++, j++) { if (postfix == '$') - set_reg(sd, num + (j << 24), name, conv_str(st, &(st->stack->stack_data[i]))); + set_reg(sd, ByteCode::VARIABLE, num + (j << 24), conv_str(st, &AARGO2(i - st->start))); else - set_reg(sd, num + (j << 24), name, conv_num(st, &(st->stack->stack_data[i]))); + set_reg(sd, ByteCode::VARIABLE, num + (j << 24), conv_num(st, &AARGO2(i - st->start))); } } @@ -1906,12 +1697,12 @@ static void builtin_cleararray(ScriptState *st) { dumb_ptr<map_session_data> sd = NULL; - int num = st->stack->stack_data[st->start + 2].u.num; - char *name = str_buf + str_data[num & 0x00ffffff].str; - char prefix = *name; - char postfix = name[strlen(name) - 1]; - int sz = conv_num(st, &(st->stack->stack_data[st->start + 4])); - int i; + assert (AARGO2(2).type == ByteCode::VARIABLE); + int num = AARGO2(2).u.num; + const std::string& name = variable_names.outtern(num & 0x00ffffff); + char prefix = name.front(); + char postfix = name.back(); + int sz = conv_num(st, &AARGO2(4)); if (prefix != '$' && prefix != '@') { @@ -1922,11 +1713,11 @@ void builtin_cleararray(ScriptState *st) sd = script_rid2sd(st); if (postfix == '$') - for (i = 0; i < sz; i++) - set_reg(sd, num + (i << 24), name, conv_str(st, &(st->stack->stack_data[st->start + 3]))); + for (int i = 0; i < sz; i++) + set_reg(sd, ByteCode::VARIABLE, num + (i << 24), conv_str(st, &AARGO2(3))); else - for (i = 0; i < sz; i++) - set_reg(sd, num + (i << 24), name, conv_num(st, &(st->stack->stack_data[st->start + 3]))); + for (int i = 0; i < sz; i++) + set_reg(sd, ByteCode::VARIABLE, num + (i << 24), conv_num(st, &AARGO2(3))); } @@ -1941,7 +1732,7 @@ int getarraysize(ScriptState *st, int num, int postfix) for (; i < 128; i++) { struct script_data vd = get_val2(st, num + (i << 24)); - if (postfix == '$' ? bool(*vd.u.str) : bool(vd.u.num)) + if (postfix == '$' ? bool(vd.u.str[0]) : bool(vd.u.num)) c = i; } return c + 1; @@ -1950,10 +1741,11 @@ int getarraysize(ScriptState *st, int num, int postfix) static void builtin_getarraysize(ScriptState *st) { - int num = st->stack->stack_data[st->start + 2].u.num; - char *name = str_buf + str_data[num & 0x00ffffff].str; - char prefix = *name; - char postfix = name[strlen(name) - 1]; + assert (AARGO2(2).type == ByteCode::VARIABLE); + int num = AARGO2(2).u.num; + const std::string& name = variable_names.outtern(num & 0x00ffffff); + char prefix = name.front(); + char postfix = name.back(); if (prefix != '$' && prefix != '@') { @@ -1961,7 +1753,7 @@ void builtin_getarraysize(ScriptState *st) return; } - push_val(st->stack, ScriptCode::INT, getarraysize(st, num, postfix)); + push_val(st->stack, ByteCode::INT, getarraysize(st, num, postfix)); } /*========================================== @@ -1971,25 +1763,25 @@ void builtin_getarraysize(ScriptState *st) static void builtin_getelementofarray(ScriptState *st) { - if (st->stack->stack_data[st->start + 2].type == ScriptCode::NAME) + if (AARGO2(2).type == ByteCode::VARIABLE) { - int i = conv_num(st, &(st->stack->stack_data[st->start + 3])); + int i = conv_num(st, &AARGO2(3)); if (i > 127 || i < 0) { PRINTF("script: getelementofarray (operator[]): param2 illegal number %d\n", i); - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); } else { - push_val(st->stack, ScriptCode::NAME, - (i << 24) | st->stack->stack_data[st->start + 2].u.num); + push_val(st->stack, ByteCode::VARIABLE, + (i << 24) | AARGO2(2).u.num); } } else { PRINTF("script: getelementofarray (operator[]): param1 not name !\n"); - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); } } @@ -2000,8 +1792,8 @@ void builtin_getelementofarray(ScriptState *st) static void builtin_setlook(ScriptState *st) { - LOOK type = LOOK(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - int val = conv_num(st, &(st->stack->stack_data[st->start + 3])); + LOOK type = LOOK(conv_num(st, &AARGO2(2))); + int val = conv_num(st, &AARGO2(3)); pc_changelook(script_rid2sd(st), type, val); @@ -2021,13 +1813,13 @@ void builtin_countitem(ScriptState *st) sd = script_rid2sd(st); - data = &(st->stack->stack_data[st->start + 2]); + data = &AARGO2(2); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - struct item_data *item_data; - if ((item_data = itemdb_searchname(name)) != NULL) + dumb_string name = conv_str(st, data); + struct item_data *item_data = itemdb_searchname(name.c_str()); + if (item_data != NULL) nameid = item_data->nameid; } else @@ -2044,7 +1836,7 @@ void builtin_countitem(ScriptState *st) if (battle_config.error_log) PRINTF("wrong item ID : countitem (%i)\n", nameid); } - push_val(st->stack, ScriptCode::INT, count); + push_val(st->stack, ByteCode::INT, count); } @@ -2061,33 +1853,33 @@ void builtin_checkweight(ScriptState *st) sd = script_rid2sd(st); - data = &(st->stack->stack_data[st->start + 2]); + data = &AARGO2(2); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - struct item_data *item_data = itemdb_searchname(name); + dumb_string name = conv_str(st, data); + struct item_data *item_data = itemdb_searchname(name.c_str()); if (item_data) nameid = item_data->nameid; } else nameid = conv_num(st, data); - amount = conv_num(st, &(st->stack->stack_data[st->start + 3])); + amount = conv_num(st, &AARGO2(3)); if (amount <= 0 || nameid < 500) { //if get wrong item ID or amount<=0, don't count weight of non existing items - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); return; } if (itemdb_weight(nameid) * amount + sd->weight > sd->max_weight) { - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); } else { - push_val(st->stack, ScriptCode::INT, 1); + push_val(st->stack, ByteCode::INT, 1); } } @@ -2106,12 +1898,12 @@ void builtin_getitem(ScriptState *st) sd = script_rid2sd(st); - data = &(st->stack->stack_data[st->start + 2]); + data = &AARGO2(2); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - struct item_data *item_data = itemdb_searchname(name); + dumb_string name = conv_str(st, data); + struct item_data *item_data = itemdb_searchname(name.c_str()); nameid = 727; //Default to iten if (item_data != NULL) nameid = item_data->nameid; @@ -2120,7 +1912,7 @@ void builtin_getitem(ScriptState *st) nameid = conv_num(st, data); if ((amount = - conv_num(st, &(st->stack->stack_data[st->start + 3]))) <= 0) + conv_num(st, &AARGO2(3))) <= 0) { return; //return if amount <=0, skip the useles iteration } @@ -2130,8 +1922,8 @@ void builtin_getitem(ScriptState *st) memset(&item_tmp, 0, sizeof(item_tmp)); item_tmp.nameid = nameid; item_tmp.identify = 1; - if (st->end > st->start + 5) //アイテムを指定したIDに渡す - sd = map_id2sd(conv_num(st, &(st->stack->stack_data[st->start + 5]))); + if (HARGO2(5)) //アイテムを指定したIDに渡す + sd = map_id2sd(conv_num(st, &AARGO2(5))); if (sd == NULL) //アイテムを渡す相手がいなかったらお帰り return; PickupFail flag; @@ -2154,19 +1946,19 @@ static void builtin_makeitem(ScriptState *st) { int nameid, amount, flag = 0; - int x, y, m; + int x, y; struct item item_tmp; dumb_ptr<map_session_data> sd; struct script_data *data; sd = script_rid2sd(st); - data = &(st->stack->stack_data[st->start + 2]); + data = &AARGO2(2); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - struct item_data *item_data = itemdb_searchname(name); + dumb_string name = conv_str(st, data); + struct item_data *item_data = itemdb_searchname(name.c_str()); nameid = 512; //Apple Item ID if (item_data) nameid = item_data->nameid; @@ -2174,15 +1966,17 @@ void builtin_makeitem(ScriptState *st) else nameid = conv_num(st, data); - amount = conv_num(st, &(st->stack->stack_data[st->start + 3])); - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 4])); - x = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y = conv_num(st, &(st->stack->stack_data[st->start + 6])); + amount = conv_num(st, &AARGO2(3)); + dumb_string mapname = conv_str(st, &AARGO2(4)); + x = conv_num(st, &AARGO2(5)); + y = conv_num(st, &AARGO2(6)); - if (sd && strcmp(mapname, "this") == 0) + map_local *m; + using namespace operators; + if (sd && mapname == "this") m = sd->bl_m; else - m = map_mapname2mapid(mapname); + m = map_mapname2mapid(mapname.c_str()); if (nameid > 0) { @@ -2211,12 +2005,12 @@ void builtin_delitem(ScriptState *st) sd = script_rid2sd(st); - data = &(st->stack->stack_data[st->start + 2]); + data = &AARGO2(2); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - struct item_data *item_data = itemdb_searchname(name); + dumb_string name = conv_str(st, data); + struct item_data *item_data = itemdb_searchname(name.c_str()); //nameid=512; if (item_data) nameid = item_data->nameid; @@ -2224,7 +2018,7 @@ void builtin_delitem(ScriptState *st) else nameid = conv_num(st, data); - amount = conv_num(st, &(st->stack->stack_data[st->start + 3])); + amount = conv_num(st, &AARGO2(3)); if (nameid < 500 || amount <= 0) { @@ -2272,19 +2066,19 @@ void builtin_readparam(ScriptState *st) { dumb_ptr<map_session_data> sd; - SP type = SP(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - if (st->end > st->start + 3) - sd = map_nick2sd(conv_str(st, &(st->stack->stack_data[st->start + 3]))); + SP type = SP(conv_num(st, &AARGO2(2))); + if (HARGO2(3)) + sd = map_nick2sd(conv_str(st, &AARGO2(3)).c_str()); else sd = script_rid2sd(st); if (sd == NULL) { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); return; } - push_val(st->stack, ScriptCode::INT, pc_readparam(sd, type)); + push_val(st->stack, ByteCode::INT, pc_readparam(sd, type)); } @@ -2298,24 +2092,24 @@ void builtin_getcharid(ScriptState *st) int num; dumb_ptr<map_session_data> sd; - num = conv_num(st, &(st->stack->stack_data[st->start + 2])); - if (st->end > st->start + 3) - sd = map_nick2sd(conv_str(st, &(st->stack->stack_data[st->start + 3]))); + num = conv_num(st, &AARGO2(2)); + if (HARGO2(3)) + sd = map_nick2sd(conv_str(st, &AARGO2(3)).c_str()); else sd = script_rid2sd(st); if (sd == NULL) { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); return; } if (num == 0) - push_val(st->stack, ScriptCode::INT, sd->status.char_id); + push_val(st->stack, ByteCode::INT, sd->status.char_id); if (num == 1) - push_val(st->stack, ScriptCode::INT, sd->status.party_id); + push_val(st->stack, ByteCode::INT, sd->status.party_id); if (num == 2) - push_val(st->stack, ScriptCode::INT, 0/*guild_id*/); + push_val(st->stack, ByteCode::INT, 0/*guild_id*/); if (num == 3) - push_val(st->stack, ScriptCode::INT, sd->status.account_id); + push_val(st->stack, ByteCode::INT, sd->status.account_id); } /*========================================== @@ -2323,22 +2117,14 @@ void builtin_getcharid(ScriptState *st) *------------------------------------------ */ static -char *builtin_getpartyname_sub(int party_id) +dumb_string builtin_getpartyname_sub(int party_id) { - struct party *p; - - p = NULL; - p = party_search(party_id); + struct party *p = party_search(party_id); - if (p != NULL) - { - char *buf; - buf = (char *) calloc(24, 1); - strcpy(buf, p->name); - return buf; - } + if (p) + return dumb_string::copy(p->name); - return 0; + return dumb_string(); } /*========================================== @@ -2352,27 +2138,24 @@ void builtin_strcharinfo(ScriptState *st) int num; sd = script_rid2sd(st); - num = conv_num(st, &(st->stack->stack_data[st->start + 2])); + num = conv_num(st, &AARGO2(2)); if (num == 0) { - char *buf; - buf = (char *) calloc(24, 1); - strncpy(buf, sd->status.name, 23); - push_str(st->stack, ScriptCode::STR, buf); + dumb_string buf = dumb_string::copy(sd->status.name); + push_str(st->stack, ByteCode::STR, buf); } if (num == 1) { - char *buf; - buf = builtin_getpartyname_sub(sd->status.party_id); - if (buf != 0) - push_str(st->stack, ScriptCode::STR, buf); + dumb_string buf = builtin_getpartyname_sub(sd->status.party_id); + if (buf) + push_str(st->stack, ByteCode::STR, buf); else - push_str(st->stack, ScriptCode::CONSTSTR, ""); + push_str(st->stack, ByteCode::CONSTSTR, dumb_string::fake("")); } if (num == 2) { // was: guild name - push_str(st->stack, ScriptCode::CONSTSTR, ""); + push_str(st->stack, ByteCode::CONSTSTR, dumb_string::fake("")); } } @@ -2411,19 +2194,19 @@ void builtin_getequipid(ScriptState *st) PRINTF("getequipid: sd == NULL\n"); return; } - num = conv_num(st, &(st->stack->stack_data[st->start + 2])); + num = conv_num(st, &AARGO2(2)); i = pc_checkequip(sd, equip[num - 1]); if (i >= 0) { item = sd->inventory_data[i]; if (item) - push_val(st->stack, ScriptCode::INT, item->nameid); + push_val(st->stack, ByteCode::INT, item->nameid); else - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); } else { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); } } @@ -2437,25 +2220,25 @@ void builtin_getequipname(ScriptState *st) int i, num; dumb_ptr<map_session_data> sd; struct item_data *item; - char *buf; - buf = (char *) calloc(64, 1); + std::string buf; + sd = script_rid2sd(st); - num = conv_num(st, &(st->stack->stack_data[st->start + 2])); + num = conv_num(st, &AARGO2(2)); i = pc_checkequip(sd, equip[num - 1]); if (i >= 0) { item = sd->inventory_data[i]; if (item) - sprintf(buf, "%s-[%s]", pos[num - 1], item->jname); + buf = STRPRINTF("%s-[%s]", pos[num - 1], item->jname); else - sprintf(buf, "%s-[%s]", pos[num - 1], pos[10]); + buf = STRPRINTF("%s-[%s]", pos[num - 1], pos[10]); } else { - sprintf(buf, "%s-[%s]", pos[num - 1], pos[10]); + buf = STRPRINTF("%s-[%s]", pos[num - 1], pos[10]); } - push_str(st->stack, ScriptCode::STR, buf); + push_str(st->stack, ByteCode::STR, dumb_string::copys(buf)); } @@ -2466,8 +2249,8 @@ void builtin_getequipname(ScriptState *st) static void builtin_statusup2(ScriptState *st) { - SP type = SP(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - int val = conv_num(st, &(st->stack->stack_data[st->start + 3])); + SP type = SP(conv_num(st, &AARGO2(2))); + int val = conv_num(st, &AARGO2(3)); dumb_ptr<map_session_data> sd = script_rid2sd(st); pc_statusup2(sd, type, val); @@ -2480,8 +2263,8 @@ void builtin_statusup2(ScriptState *st) static void builtin_bonus(ScriptState *st) { - SP type = SP(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - int val = conv_num(st, &(st->stack->stack_data[st->start + 3])); + SP type = SP(conv_num(st, &AARGO2(2))); + int val = conv_num(st, &AARGO2(3)); dumb_ptr<map_session_data> sd = script_rid2sd(st); pc_bonus(sd, type, val); @@ -2494,9 +2277,9 @@ void builtin_bonus(ScriptState *st) static void builtin_bonus2(ScriptState *st) { - SP type = SP(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - int type2 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - int val = conv_num(st, &(st->stack->stack_data[st->start + 4])); + SP type = SP(conv_num(st, &AARGO2(2))); + int type2 = conv_num(st, &AARGO2(3)); + int val = conv_num(st, &AARGO2(4)); dumb_ptr<map_session_data> sd = script_rid2sd(st); pc_bonus2(sd, type, type2, val); @@ -2512,10 +2295,10 @@ void builtin_skill(ScriptState *st) int level, flag = 1; dumb_ptr<map_session_data> sd; - SkillID id = SkillID(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - level = conv_num(st, &(st->stack->stack_data[st->start + 3])); - if (st->end > st->start + 4) - flag = conv_num(st, &(st->stack->stack_data[st->start + 4])); + SkillID id = SkillID(conv_num(st, &AARGO2(2))); + level = conv_num(st, &AARGO2(3)); + if (HARGO2(4)) + flag = conv_num(st, &AARGO2(4)); sd = script_rid2sd(st); pc_skill(sd, id, level, flag); clif_skillinfoblock(sd); @@ -2532,8 +2315,8 @@ void builtin_setskill(ScriptState *st) int level; dumb_ptr<map_session_data> sd; - SkillID id = static_cast<SkillID>(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - level = conv_num(st, &(st->stack->stack_data[st->start + 3])); + SkillID id = static_cast<SkillID>(conv_num(st, &AARGO2(2))); + level = conv_num(st, &AARGO2(3)); sd = script_rid2sd(st); sd->status.skill[id].lv = level; @@ -2547,8 +2330,8 @@ void builtin_setskill(ScriptState *st) static void builtin_getskilllv(ScriptState *st) { - SkillID id = SkillID(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - push_val(st->stack, ScriptCode::INT, pc_checkskill(script_rid2sd(st), id)); + SkillID id = SkillID(conv_num(st, &AARGO2(2))); + push_val(st->stack, ByteCode::INT, pc_checkskill(script_rid2sd(st), id)); } /*========================================== @@ -2558,7 +2341,7 @@ void builtin_getskilllv(ScriptState *st) static void builtin_getgmlevel(ScriptState *st) { - push_val(st->stack, ScriptCode::INT, pc_isGM(script_rid2sd(st))); + push_val(st->stack, ByteCode::INT, pc_isGM(script_rid2sd(st))); } /*========================================== @@ -2568,7 +2351,7 @@ void builtin_getgmlevel(ScriptState *st) static void builtin_end(ScriptState *st) { - st->state = END; + st->state = ScriptEndState::END; } /*========================================== @@ -2583,7 +2366,7 @@ void builtin_getopt2(ScriptState *st) sd = script_rid2sd(st); - push_val(st->stack, ScriptCode::INT, uint16_t(sd->opt2)); + push_val(st->stack, ByteCode::INT, uint16_t(sd->opt2)); } @@ -2597,7 +2380,7 @@ void builtin_setopt2(ScriptState *st) { dumb_ptr<map_session_data> sd; - Opt2 new_opt2 = Opt2(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + Opt2 new_opt2 = Opt2(conv_num(st, &AARGO2(2))); sd = script_rid2sd(st); if (new_opt2 == sd->opt2) return; @@ -2616,10 +2399,10 @@ void builtin_savepoint(ScriptState *st) { int x, y; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y = conv_num(st, &(st->stack->stack_data[st->start + 4])); - pc_setsavepoint(script_rid2sd(st), str, x, y); + dumb_string str = conv_str(st, &AARGO2(2)); + x = conv_num(st, &AARGO2(3)); + y = conv_num(st, &AARGO2(4)); + pc_setsavepoint(script_rid2sd(st), str.c_str(), x, y); } /*========================================== @@ -2636,7 +2419,7 @@ static void builtin_gettimetick(ScriptState *st) /* Asgard Version */ { int type; - type = conv_num(st, &(st->stack->stack_data[st->start + 2])); + type = conv_num(st, &AARGO2(2)); switch (type) { @@ -2644,18 +2427,18 @@ void builtin_gettimetick(ScriptState *st) /* Asgard Version */ case 1: { struct tm t = TimeT::now(); - push_val(st->stack, ScriptCode::INT, + push_val(st->stack, ByteCode::INT, t.tm_hour * 3600 + t.tm_min * 60 + t.tm_sec); break; } /* Seconds since Unix epoch. */ case 2: - push_val(st->stack, ScriptCode::INT, static_cast<time_t>(TimeT::now())); + push_val(st->stack, ByteCode::INT, static_cast<time_t>(TimeT::now())); break; /* System tick(unsigned int, and yes, it will wrap). */ case 0: default: - push_val(st->stack, ScriptCode::INT, gettick().time_since_epoch().count()); + push_val(st->stack, ByteCode::INT, gettick().time_since_epoch().count()); break; } } @@ -2670,58 +2453,40 @@ void builtin_gettimetick(ScriptState *st) /* Asgard Version */ static void builtin_gettime(ScriptState *st) /* Asgard Version */ { - int type = conv_num(st, &(st->stack->stack_data[st->start + 2])); + int type = conv_num(st, &AARGO2(2)); struct tm t = TimeT::now(); switch (type) { case 1: //Sec(0~59) - push_val(st->stack, ScriptCode::INT, t.tm_sec); + push_val(st->stack, ByteCode::INT, t.tm_sec); break; case 2: //Min(0~59) - push_val(st->stack, ScriptCode::INT, t.tm_min); + push_val(st->stack, ByteCode::INT, t.tm_min); break; case 3: //Hour(0~23) - push_val(st->stack, ScriptCode::INT, t.tm_hour); + push_val(st->stack, ByteCode::INT, t.tm_hour); break; case 4: //WeekDay(0~6) - push_val(st->stack, ScriptCode::INT, t.tm_wday); + push_val(st->stack, ByteCode::INT, t.tm_wday); break; case 5: //MonthDay(01~31) - push_val(st->stack, ScriptCode::INT, t.tm_mday); + push_val(st->stack, ByteCode::INT, t.tm_mday); break; case 6: //Month(01~12) - push_val(st->stack, ScriptCode::INT, t.tm_mon + 1); + push_val(st->stack, ByteCode::INT, t.tm_mon + 1); break; case 7: //Year(20xx) - push_val(st->stack, ScriptCode::INT, t.tm_year + 1900); + push_val(st->stack, ByteCode::INT, t.tm_year + 1900); break; default: //(format error) - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); break; } } /*========================================== - * GetTimeStr("TimeFMT", Length); - *------------------------------------------ - */ -static -void builtin_gettimestr(ScriptState *st) -{ - struct tm now = TimeT::now(); - - const char *fmtstr = conv_str(st, &(st->stack->stack_data[st->start + 2])); - int maxlen = conv_num(st, &(st->stack->stack_data[st->start + 3])); - - char *tmpstr = (char *) calloc(maxlen + 1, 1); - strftime(tmpstr, maxlen, fmtstr, &now); - - push_str(st->stack, ScriptCode::STR, tmpstr); -} - -/*========================================== * カプラ倉庫を開く *------------------------------------------ */ @@ -2733,9 +2498,9 @@ void builtin_openstorage(ScriptState *st) dumb_ptr<map_session_data> sd = script_rid2sd(st); // if (sync) { - st->state = STOP; + st->state = ScriptEndState::STOP; sd->npc_flags.storage = 1; -// } else st->state = END; +// } else st->state = ScriptEndState::END; storage_storageopen(sd); } @@ -2750,8 +2515,8 @@ void builtin_getexp(ScriptState *st) dumb_ptr<map_session_data> sd = script_rid2sd(st); int base = 0, job = 0; - base = conv_num(st, &(st->stack->stack_data[st->start + 2])); - job = conv_num(st, &(st->stack->stack_data[st->start + 3])); + base = conv_num(st, &AARGO2(2)); + job = conv_num(st, &AARGO2(3)); if (base < 0 || job < 0) return; if (sd) @@ -2769,16 +2534,16 @@ void builtin_monster(ScriptState *st) int mob_class, amount, x, y; const char *event = ""; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y = conv_num(st, &(st->stack->stack_data[st->start + 4])); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 5])); - mob_class = conv_num(st, &(st->stack->stack_data[st->start + 6])); - amount = conv_num(st, &(st->stack->stack_data[st->start + 7])); - if (st->end > st->start + 8) - event = conv_str(st, &(st->stack->stack_data[st->start + 8])); + dumb_string mapname = conv_str(st, &AARGO2(2)); + x = conv_num(st, &AARGO2(3)); + y = conv_num(st, &AARGO2(4)); + dumb_string str = conv_str(st, &AARGO2(5)); + mob_class = conv_num(st, &AARGO2(6)); + amount = conv_num(st, &AARGO2(7)); + if (HARGO2(8)) + event = conv_str(st, &AARGO2(8)).c_str(); - mob_once_spawn(map_id2sd(st->rid), mapname, x, y, str, mob_class, amount, + mob_once_spawn(map_id2sd(st->rid), mapname.c_str(), x, y, str.c_str(), mob_class, amount, event); } @@ -2792,18 +2557,18 @@ void builtin_areamonster(ScriptState *st) int mob_class, amount, x0, y0, x1, y1; const char *event = ""; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x0 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y0 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - x1 = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y1 = conv_num(st, &(st->stack->stack_data[st->start + 6])); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 7])); - mob_class = conv_num(st, &(st->stack->stack_data[st->start + 8])); - amount = conv_num(st, &(st->stack->stack_data[st->start + 9])); - if (st->end > st->start + 10) - event = conv_str(st, &(st->stack->stack_data[st->start + 10])); - - mob_once_spawn_area(map_id2sd(st->rid), mapname, x0, y0, x1, y1, str, mob_class, + dumb_string mapname = conv_str(st, &AARGO2(2)); + x0 = conv_num(st, &AARGO2(3)); + y0 = conv_num(st, &AARGO2(4)); + x1 = conv_num(st, &AARGO2(5)); + y1 = conv_num(st, &AARGO2(6)); + dumb_string str = conv_str(st, &AARGO2(7)); + mob_class = conv_num(st, &AARGO2(8)); + amount = conv_num(st, &AARGO2(9)); + if (HARGO2(10)) + event = conv_str(st, &AARGO2(10)).c_str(); + + mob_once_spawn_area(map_id2sd(st->rid), mapname.c_str(), x0, y0, x1, y1, str.c_str(), mob_class, amount, event); } @@ -2812,19 +2577,20 @@ void builtin_areamonster(ScriptState *st) *------------------------------------------ */ static -void builtin_killmonster_sub(dumb_ptr<block_list> bl, const char *event, int allflag) +void builtin_killmonster_sub(dumb_ptr<block_list> bl, dumb_string event, int allflag) { dumb_ptr<mob_data> md = bl->as_mob(); if (!allflag) { - if (strcmp(event, md->npc_event) == 0) + using namespace operators; + if (event == md->npc_event) mob_delete(md); return; } else if (allflag) { - if (md->spawndelay1 == static_cast<interval_t>(-1) - && md->spawndelay2 == static_cast<interval_t>(-1)) + if (md->spawn.delay1 == static_cast<interval_t>(-1) + && md->spawn.delay2 == static_cast<interval_t>(-1)) mob_delete(md); return; } @@ -2833,16 +2599,21 @@ void builtin_killmonster_sub(dumb_ptr<block_list> bl, const char *event, int all static void builtin_killmonster(ScriptState *st) { - int m, allflag = 0; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - const char *event = conv_str(st, &(st->stack->stack_data[st->start + 3])); - if (strcmp(event, "All") == 0) + int allflag = 0; + dumb_string mapname = conv_str(st, &AARGO2(2)); + dumb_string event = conv_str(st, &AARGO2(3)); + using namespace operators; + if (event == "All") allflag = 1; - if ((m = map_mapname2mapid(mapname)) < 0) + map_local *m = map_mapname2mapid(mapname.c_str()); + if (m == nullptr) return; map_foreachinarea(std::bind(builtin_killmonster_sub, ph::_1, event, allflag), - m, 0, 0, map[m].xs, map[m].ys, BL::MOB); + m, + 0, 0, + m->xs, m->ys, + BL::MOB); } static @@ -2854,13 +2625,16 @@ void builtin_killmonsterall_sub(dumb_ptr<block_list> bl) static void builtin_killmonsterall(ScriptState *st) { - int m; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string mapname = conv_str(st, &AARGO2(2)); - if ((m = map_mapname2mapid(mapname)) < 0) + map_local *m = map_mapname2mapid(mapname.c_str()); + if (m == nullptr) return; map_foreachinarea(builtin_killmonsterall_sub, - m, 0, 0, map[m].xs, map[m].ys, BL::MOB); + m, + 0, 0, + m->xs, m->ys, + BL::MOB); } /*========================================== @@ -2870,8 +2644,8 @@ void builtin_killmonsterall(ScriptState *st) static void builtin_donpcevent(ScriptState *st) { - const char *event = conv_str(st, &(st->stack->stack_data[st->start + 2])); - npc_event_do(event); + dumb_string event = conv_str(st, &AARGO2(2)); + npc_event_do(event.c_str()); } /*========================================== @@ -2881,9 +2655,9 @@ void builtin_donpcevent(ScriptState *st) static void builtin_addtimer(ScriptState *st) { - interval_t tick = static_cast<interval_t>(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - const char *event = conv_str(st, &(st->stack->stack_data[st->start + 3])); - pc_addeventtimer(script_rid2sd(st), tick, event); + interval_t tick = static_cast<interval_t>(conv_num(st, &AARGO2(2))); + dumb_string event = conv_str(st, &AARGO2(3)); + pc_addeventtimer(script_rid2sd(st), tick, event.c_str()); } /*========================================== @@ -2894,8 +2668,8 @@ static void builtin_initnpctimer(ScriptState *st) { dumb_ptr<npc_data> nd_; - if (st->end > st->start + 2) - nd_ = npc_name2id(conv_str(st, &(st->stack->stack_data[st->start + 2]))); + if (HARGO2(2)) + nd_ = npc_name2id(conv_str(st, &AARGO2(2)).c_str()); else nd_ = map_id_as_npc(st->oid); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); @@ -2913,8 +2687,8 @@ static void builtin_startnpctimer(ScriptState *st) { dumb_ptr<npc_data> nd_; - if (st->end > st->start + 2) - nd_ = npc_name2id(conv_str(st, &(st->stack->stack_data[st->start + 2]))); + if (HARGO2(2)) + nd_ = npc_name2id(conv_str(st, &AARGO2(2)).c_str()); else nd_ = map_id_as_npc(st->oid); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); @@ -2931,8 +2705,8 @@ static void builtin_stopnpctimer(ScriptState *st) { dumb_ptr<npc_data> nd_; - if (st->end > st->start + 2) - nd_ = npc_name2id(conv_str(st, &(st->stack->stack_data[st->start + 2]))); + if (HARGO2(2)) + nd_ = npc_name2id(conv_str(st, &AARGO2(2)).c_str()); else nd_ = map_id_as_npc(st->oid); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); @@ -2949,10 +2723,10 @@ static void builtin_getnpctimer(ScriptState *st) { dumb_ptr<npc_data> nd_; - int type = conv_num(st, &(st->stack->stack_data[st->start + 2])); + int type = conv_num(st, &AARGO2(2)); int val = 0; - if (st->end > st->start + 3) - nd_ = npc_name2id(conv_str(st, &(st->stack->stack_data[st->start + 3]))); + if (HARGO2(3)) + nd_ = npc_name2id(conv_str(st, &AARGO2(3)).c_str()); else nd_ = map_id_as_npc(st->oid); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); @@ -2961,16 +2735,16 @@ void builtin_getnpctimer(ScriptState *st) switch (type) { case 0: - val = (int) npc_gettimerevent_tick(nd).count(); + val = npc_gettimerevent_tick(nd).count(); break; case 1: - val = (nd->scr.nexttimer >= 0); + val = nd->scr.nexttimer != nd->scr.timer_eventv.end(); break; case 2: - val = nd->scr.timeramount; + val = nd->scr.timer_eventv.size(); break; } - push_val(st->stack, ScriptCode::INT, val); + push_val(st->stack, ByteCode::INT, val); } /*========================================== @@ -2981,9 +2755,9 @@ static void builtin_setnpctimer(ScriptState *st) { dumb_ptr<npc_data> nd_; - interval_t tick = static_cast<interval_t>(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - if (st->end > st->start + 3) - nd_ = npc_name2id(conv_str(st, &(st->stack->stack_data[st->start + 3]))); + interval_t tick = static_cast<interval_t>(conv_num(st, &AARGO2(2))); + if (HARGO2(3)) + nd_ = npc_name2id(conv_str(st, &AARGO2(3)).c_str()); else nd_ = map_id_as_npc(st->oid); assert (nd_ && nd_->npc_subtype == NpcSubtype::SCRIPT); @@ -3000,13 +2774,16 @@ static void builtin_announce(ScriptState *st) { int flag; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - flag = conv_num(st, &(st->stack->stack_data[st->start + 3])); + dumb_string str = conv_str(st, &AARGO2(2)); + flag = conv_num(st, &AARGO2(3)); if (flag & 0x0f) { - dumb_ptr<block_list> bl = (flag & 0x08) ? map_id2bl(st->oid) : - (dumb_ptr<block_list>) script_rid2sd(st); + dumb_ptr<block_list> bl; + if (flag & 0x08) + bl = map_id2bl(st->oid); + else + bl = script_rid2sd(st); clif_GMmessage(bl, str, flag); } else @@ -3018,24 +2795,28 @@ void builtin_announce(ScriptState *st) *------------------------------------------ */ static -void builtin_mapannounce_sub(dumb_ptr<block_list> bl, const char *str, int flag) +void builtin_mapannounce_sub(dumb_ptr<block_list> bl, dumb_string str, int flag) { - clif_GMmessage(bl, str, flag | 3); + clif_GMmessage(bl, str.c_str(), flag | 3); } static void builtin_mapannounce(ScriptState *st) { - int flag, m; + int flag; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 3])); - flag = conv_num(st, &(st->stack->stack_data[st->start + 4])); + dumb_string mapname = conv_str(st, &AARGO2(2)); + dumb_string str = conv_str(st, &AARGO2(3)); + flag = conv_num(st, &AARGO2(4)); - if ((m = map_mapname2mapid(mapname)) < 0) + map_local *m = map_mapname2mapid(mapname.c_str()); + if (m == nullptr) return; map_foreachinarea(std::bind(builtin_mapannounce_sub, ph::_1, str, flag & 0x10), - m, 0, 0, map[m].xs, map[m].ys, BL::PC); + m, + 0, 0, + m->xs, m->ys, + BL::PC); } /*========================================== @@ -3045,19 +2826,19 @@ void builtin_mapannounce(ScriptState *st) static void builtin_getusers(ScriptState *st) { - int flag = conv_num(st, &(st->stack->stack_data[st->start + 2])); + int flag = conv_num(st, &AARGO2(2)); dumb_ptr<block_list> bl = map_id2bl((flag & 0x08) ? st->oid : st->rid); int val = 0; switch (flag & 0x07) { case 0: - val = map[bl->bl_m].users; + val = bl->bl_m->users; break; case 1: val = map_getusers(); break; } - push_val(st->stack, ScriptCode::INT, val); + push_val(st->stack, ByteCode::INT, val); } /*========================================== @@ -3067,14 +2848,14 @@ void builtin_getusers(ScriptState *st) static void builtin_getmapusers(ScriptState *st) { - int m; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - if ((m = map_mapname2mapid(str)) < 0) + dumb_string str = conv_str(st, &AARGO2(2)); + map_local *m = map_mapname2mapid(str.c_str()); + if (m == nullptr) { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); return; } - push_val(st->stack, ScriptCode::INT, map[m].users); + push_val(st->stack, ByteCode::INT, m->users); } /*========================================== @@ -3097,26 +2878,30 @@ void builtin_getareausers_living_sub(dumb_ptr<block_list> bl, int *users) static void builtin_getareausers(ScriptState *st) { - int m, x0, y0, x1, y1, users = 0; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x0 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y0 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - x1 = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y1 = conv_num(st, &(st->stack->stack_data[st->start + 6])); + int x0, y0, x1, y1, users = 0; + dumb_string str = conv_str(st, &AARGO2(2)); + x0 = conv_num(st, &AARGO2(3)); + y0 = conv_num(st, &AARGO2(4)); + x1 = conv_num(st, &AARGO2(5)); + y1 = conv_num(st, &AARGO2(6)); int living = 0; - if (st->end > st->start + 7) + if (HARGO2(7)) { - living = conv_num(st, &(st->stack->stack_data[st->start + 7])); + living = conv_num(st, &AARGO2(7)); } - if ((m = map_mapname2mapid(str)) < 0) + map_local *m = map_mapname2mapid(str.c_str()); + if (m == nullptr) { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); return; } map_foreachinarea(std::bind(living ? builtin_getareausers_living_sub: builtin_getareausers_sub, ph::_1, &users), - m, x0, y0, x1, y1, BL::PC); - push_val(st->stack, ScriptCode::INT, users); + m, + x0, y0, + x1, y1, + BL::PC); + push_val(st->stack, ByteCode::INT, users); } /*========================================== @@ -3149,21 +2934,21 @@ void builtin_getareadropitem_sub_anddelete(dumb_ptr<block_list> bl, int item, in static void builtin_getareadropitem(ScriptState *st) { - int m, x0, y0, x1, y1, item, amount = 0, delitems = 0; + int x0, y0, x1, y1, item, amount = 0, delitems = 0; struct script_data *data; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x0 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y0 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - x1 = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y1 = conv_num(st, &(st->stack->stack_data[st->start + 6])); + dumb_string str = conv_str(st, &AARGO2(2)); + x0 = conv_num(st, &AARGO2(3)); + y0 = conv_num(st, &AARGO2(4)); + x1 = conv_num(st, &AARGO2(5)); + y1 = conv_num(st, &AARGO2(6)); - data = &(st->stack->stack_data[st->start + 7]); + data = &AARGO2(7); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - struct item_data *item_data = itemdb_searchname(name); + dumb_string name = conv_str(st, data); + struct item_data *item_data = itemdb_searchname(name.c_str()); item = 512; if (item_data) item = item_data->nameid; @@ -3171,22 +2956,29 @@ void builtin_getareadropitem(ScriptState *st) else item = conv_num(st, data); - if (st->end > st->start + 8) - delitems = conv_num(st, &(st->stack->stack_data[st->start + 8])); + if (HARGO2(8)) + delitems = conv_num(st, &AARGO2(8)); - if ((m = map_mapname2mapid(str)) < 0) + map_local *m = map_mapname2mapid(str.c_str()); + if (m == nullptr) { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); return; } if (delitems) map_foreachinarea(std::bind(builtin_getareadropitem_sub_anddelete, ph::_1, item, &amount), - m, x0, y0, x1, y1, BL::ITEM); + m, + x0, y0, + x1, y1, + BL::ITEM); else map_foreachinarea(std::bind(builtin_getareadropitem_sub, ph::_1, item, &amount), - m, x0, y0, x1, y1, BL::ITEM); + m, + x0, y0, + x1, y1, + BL::ITEM); - push_val(st->stack, ScriptCode::INT, amount); + push_val(st->stack, ByteCode::INT, amount); } /*========================================== @@ -3196,8 +2988,8 @@ void builtin_getareadropitem(ScriptState *st) static void builtin_enablenpc(ScriptState *st) { - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - npc_enable(str, 1); + dumb_string str = conv_str(st, &AARGO2(2)); + npc_enable(str.c_str(), 1); } /*========================================== @@ -3207,8 +2999,8 @@ void builtin_enablenpc(ScriptState *st) static void builtin_disablenpc(ScriptState *st) { - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - npc_enable(str, 0); + dumb_string str = conv_str(st, &AARGO2(2)); + npc_enable(str.c_str(), 0); } /*========================================== @@ -3220,8 +3012,8 @@ void builtin_sc_start(ScriptState *st) { dumb_ptr<block_list> bl; int val1; - StatusChange type = static_cast<StatusChange>(conv_num(st, &(st->stack->stack_data[st->start + 2]))); - interval_t tick = static_cast<interval_t>(conv_num(st, &(st->stack->stack_data[st->start + 3]))); + StatusChange type = static_cast<StatusChange>(conv_num(st, &AARGO2(2))); + interval_t tick = static_cast<interval_t>(conv_num(st, &AARGO2(3))); if (tick < std::chrono::seconds(1)) // work around old behaviour of: // speed potion @@ -3231,9 +3023,9 @@ void builtin_sc_start(ScriptState *st) // which used to use seconds // all others used milliseconds tick *= 1000; - val1 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - if (st->end > st->start + 5) //指定したキャラを状態異常にする - bl = map_id2bl(conv_num(st, &(st->stack->stack_data[st->start + 5]))); + val1 = conv_num(st, &AARGO2(4)); + if (HARGO2(5)) //指定したキャラを状態異常にする + bl = map_id2bl(conv_num(st, &AARGO2(5))); else bl = map_id2bl(st->rid); skill_status_change_start(bl, type, val1, tick); @@ -3247,7 +3039,7 @@ static void builtin_sc_end(ScriptState *st) { dumb_ptr<block_list> bl; - StatusChange type = StatusChange(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + StatusChange type = StatusChange(conv_num(st, &AARGO2(2))); bl = map_id2bl(st->rid); skill_status_change_end(bl, type, nullptr); } @@ -3256,10 +3048,10 @@ static void builtin_sc_check(ScriptState *st) { dumb_ptr<block_list> bl; - StatusChange type = StatusChange(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + StatusChange type = StatusChange(conv_num(st, &AARGO2(2))); bl = map_id2bl(st->rid); - push_val(st->stack, ScriptCode::INT, skill_status_change_active(bl, type)); + push_val(st->stack, ByteCode::INT, skill_status_change_active(bl, type)); } @@ -3270,9 +3062,9 @@ void builtin_sc_check(ScriptState *st) static void builtin_debugmes(ScriptState *st) { - conv_str(st, &(st->stack->stack_data[st->start + 2])); - PRINTF("script debug : %d %d : %s\n", st->rid, st->oid, - st->stack->stack_data[st->start + 2].u.str); + dumb_string mes = conv_str(st, &AARGO2(2)); + PRINTF("script debug : %d %d : %s\n", + st->rid, st->oid, mes); } /*========================================== @@ -3318,8 +3110,8 @@ void builtin_changesex(ScriptState *st) static void builtin_attachrid(ScriptState *st) { - st->rid = conv_num(st, &(st->stack->stack_data[st->start + 2])); - push_val(st->stack, ScriptCode::INT, (map_id2sd(st->rid) != NULL)); + st->rid = conv_num(st, &AARGO2(2)); + push_val(st->stack, ByteCode::INT, (map_id2sd(st->rid) != NULL)); } /*========================================== @@ -3339,9 +3131,9 @@ void builtin_detachrid(ScriptState *st) static void builtin_isloggedin(ScriptState *st) { - push_val(st->stack, ScriptCode::INT, + push_val(st->stack, ByteCode::INT, map_id2sd(conv_num(st, - &(st->stack->stack_data[st->start + 2]))) != NULL); + &AARGO2(2))) != NULL); } /*========================================== @@ -3376,59 +3168,57 @@ enum static void builtin_setmapflag(ScriptState *st) { - int m, i; - - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - i = conv_num(st, &(st->stack->stack_data[st->start + 3])); - m = map_mapname2mapid(str); - if (m >= 0) + dumb_string str = conv_str(st, &AARGO2(2)); + int i = conv_num(st, &AARGO2(3)); + map_local *m = map_mapname2mapid(str.c_str()); + if (m != nullptr) { switch (i) { case MF_NOMEMO: - map[m].flag.nomemo = 1; + m->flag.nomemo = 1; break; case MF_NOTELEPORT: - map[m].flag.noteleport = 1; + m->flag.noteleport = 1; break; case MF_NOBRANCH: - map[m].flag.nobranch = 1; + m->flag.nobranch = 1; break; case MF_NOPENALTY: - map[m].flag.nopenalty = 1; + m->flag.nopenalty = 1; break; case MF_PVP_NOPARTY: - map[m].flag.pvp_noparty = 1; + m->flag.pvp_noparty = 1; break; case MF_NOZENYPENALTY: - map[m].flag.nozenypenalty = 1; + m->flag.nozenypenalty = 1; break; case MF_NOTRADE: - map[m].flag.notrade = 1; + m->flag.notrade = 1; break; case MF_NOWARP: - map[m].flag.nowarp = 1; + m->flag.nowarp = 1; break; case MF_NOPVP: - map[m].flag.nopvp = 1; + m->flag.nopvp = 1; break; case MF_NOICEWALL: // [Valaris] - map[m].flag.noicewall = 1; + m->flag.noicewall = 1; break; case MF_SNOW: // [Valaris] - map[m].flag.snow = 1; + m->flag.snow = 1; break; case MF_FOG: // [Valaris] - map[m].flag.fog = 1; + m->flag.fog = 1; break; case MF_SAKURA: // [Valaris] - map[m].flag.sakura = 1; + m->flag.sakura = 1; break; case MF_LEAVES: // [Valaris] - map[m].flag.leaves = 1; + m->flag.leaves = 1; break; case MF_RAIN: // [Valaris] - map[m].flag.rain = 1; + m->flag.rain = 1; break; } } @@ -3438,137 +3228,133 @@ void builtin_setmapflag(ScriptState *st) static void builtin_removemapflag(ScriptState *st) { - int m, i; - - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - i = conv_num(st, &(st->stack->stack_data[st->start + 3])); - m = map_mapname2mapid(str); - if (m >= 0) + dumb_string str = conv_str(st, &AARGO2(2)); + int i = conv_num(st, &AARGO2(3)); + map_local *m = map_mapname2mapid(str.c_str()); + if (m != nullptr) { switch (i) { case MF_NOMEMO: - map[m].flag.nomemo = 0; + m->flag.nomemo = 0; break; case MF_NOTELEPORT: - map[m].flag.noteleport = 0; + m->flag.noteleport = 0; break; case MF_NOSAVE: - map[m].flag.nosave = 0; + m->flag.nosave = 0; break; case MF_NOBRANCH: - map[m].flag.nobranch = 0; + m->flag.nobranch = 0; break; case MF_NOPENALTY: - map[m].flag.nopenalty = 0; + m->flag.nopenalty = 0; break; case MF_PVP_NOPARTY: - map[m].flag.pvp_noparty = 0; + m->flag.pvp_noparty = 0; break; case MF_NOZENYPENALTY: - map[m].flag.nozenypenalty = 0; + m->flag.nozenypenalty = 0; break; case MF_NOWARP: - map[m].flag.nowarp = 0; + m->flag.nowarp = 0; break; case MF_NOPVP: - map[m].flag.nopvp = 0; + m->flag.nopvp = 0; break; case MF_NOICEWALL: // [Valaris] - map[m].flag.noicewall = 0; + m->flag.noicewall = 0; break; case MF_SNOW: // [Valaris] - map[m].flag.snow = 0; + m->flag.snow = 0; break; case MF_FOG: // [Valaris] - map[m].flag.fog = 0; + m->flag.fog = 0; break; case MF_SAKURA: // [Valaris] - map[m].flag.sakura = 0; + m->flag.sakura = 0; break; case MF_LEAVES: // [Valaris] - map[m].flag.leaves = 0; + m->flag.leaves = 0; break; case MF_RAIN: // [Valaris] - map[m].flag.rain = 0; + m->flag.rain = 0; break; - } } - } static void builtin_getmapflag(ScriptState *st) { - int m, i, r = -1; + int r = -1; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - i = conv_num(st, &(st->stack->stack_data[st->start + 3])); - m = map_mapname2mapid(str); - if (m >= 0) + dumb_string str = conv_str(st, &AARGO2(2)); + int i = conv_num(st, &AARGO2(3)); + map_local *m = map_mapname2mapid(str.c_str()); + if (m != nullptr) { switch (i) { case MF_NOMEMO: - r = map[m].flag.nomemo; + r = m->flag.nomemo; break; case MF_NOTELEPORT: - r = map[m].flag.noteleport; + r = m->flag.noteleport; break; case MF_NOSAVE: - r = map[m].flag.nosave; + r = m->flag.nosave; break; case MF_NOBRANCH: - r = map[m].flag.nobranch; + r = m->flag.nobranch; break; case MF_NOPENALTY: - r = map[m].flag.nopenalty; + r = m->flag.nopenalty; break; case MF_PVP_NOPARTY: - r = map[m].flag.pvp_noparty; + r = m->flag.pvp_noparty; break; case MF_NOZENYPENALTY: - r = map[m].flag.nozenypenalty; + r = m->flag.nozenypenalty; break; case MF_NOWARP: - r = map[m].flag.nowarp; + r = m->flag.nowarp; break; case MF_NOPVP: - r = map[m].flag.nopvp; + r = m->flag.nopvp; break; case MF_NOICEWALL: // [Valaris] - r = map[m].flag.noicewall; + r = m->flag.noicewall; break; case MF_SNOW: // [Valaris] - r = map[m].flag.snow; + r = m->flag.snow; break; case MF_FOG: // [Valaris] - r = map[m].flag.fog; + r = m->flag.fog; break; case MF_SAKURA: // [Valaris] - r = map[m].flag.sakura; + r = m->flag.sakura; break; case MF_LEAVES: // [Valaris] - r = map[m].flag.leaves; + r = m->flag.leaves; break; case MF_RAIN: // [Valaris] - r = map[m].flag.rain; + r = m->flag.rain; break; } } - push_val(st->stack, ScriptCode::INT, r); + push_val(st->stack, ByteCode::INT, r); } static void builtin_pvpon(ScriptState *st) { - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - int m = map_mapname2mapid(str); - if (m >= 0 && !map[m].flag.pvp && !map[m].flag.nopvp) + dumb_string str = conv_str(st, &AARGO2(2)); + map_local *m = map_mapname2mapid(str.c_str()); + if (m != nullptr && !m->flag.pvp && !m->flag.nopvp) { - map[m].flag.pvp = 1; + m->flag.pvp = 1; if (battle_config.pk_mode) // disable ranking functions if pk_mode is on [Valaris] return; @@ -3598,11 +3384,11 @@ void builtin_pvpon(ScriptState *st) static void builtin_pvpoff(ScriptState *st) { - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - int m = map_mapname2mapid(str); - if (m >= 0 && map[m].flag.pvp && map[m].flag.nopvp) + dumb_string str = conv_str(st, &AARGO2(2)); + map_local *m = map_mapname2mapid(str.c_str()); + if (m != nullptr && m->flag.pvp && m->flag.nopvp) { - map[m].flag.pvp = 0; + m->flag.pvp = 0; if (battle_config.pk_mode) // disable ranking options if pk_mode is on [Valaris] return; @@ -3633,7 +3419,7 @@ static void builtin_emotion(ScriptState *st) { int type; - type = conv_num(st, &(st->stack->stack_data[st->start + 2])); + type = conv_num(st, &AARGO2(2)); if (type < 0 || type > 100) return; clif_emotion(map_id2bl(st->oid), type); @@ -3642,73 +3428,82 @@ void builtin_emotion(ScriptState *st) static void builtin_mapwarp(ScriptState *st) // Added by RoVeRT { - int x, y, m; + int x, y; int x0, y0, x1, y1; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string mapname = conv_str(st, &AARGO2(2)); x0 = 0; y0 = 0; - x1 = map[map_mapname2mapid(mapname)].xs; - y1 = map[map_mapname2mapid(mapname)].ys; - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 3])); - x = conv_num(st, &(st->stack->stack_data[st->start + 4])); - y = conv_num(st, &(st->stack->stack_data[st->start + 5])); - - if ((m = map_mapname2mapid(mapname)) < 0) + map_local *m = map_mapname2mapid(mapname.c_str()); + x1 = m->xs; + y1 = m->ys; + dumb_string str = conv_str(st, &AARGO2(3)); + x = conv_num(st, &AARGO2(4)); + y = conv_num(st, &AARGO2(5)); + + if (m == nullptr) return; map_foreachinarea(std::bind(builtin_areawarp_sub, ph::_1, str, x, y), - m, x0, y0, x1, y1, BL::PC); + m, + x0, y0, + x1, y1, + BL::PC); } static void builtin_cmdothernpc(ScriptState *st) // Added by RoVeRT { - const char *npc = conv_str(st, &(st->stack->stack_data[st->start + 2])); - const char *command = conv_str(st, &(st->stack->stack_data[st->start + 3])); + dumb_string npc = conv_str(st, &AARGO2(2)); + dumb_string command = conv_str(st, &AARGO2(3)); - npc_command(map_id2sd(st->rid), npc, command); + npc_command(map_id2sd(st->rid), npc.c_str(), command.c_str()); } static -void builtin_mobcount_sub(dumb_ptr<block_list> bl, const char *event, int *c) +void builtin_mobcount_sub(dumb_ptr<block_list> bl, dumb_string event, int *c) { - if (strcmp(event, bl->as_mob()->npc_event) == 0) + using namespace operators; + if (event == bl->as_mob()->npc_event) (*c)++; } static void builtin_mobcount(ScriptState *st) // Added by RoVeRT { - int m, c = 0; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - const char *event = conv_str(st, &(st->stack->stack_data[st->start + 3])); + int c = 0; + dumb_string mapname = conv_str(st, &AARGO2(2)); + dumb_string event = conv_str(st, &AARGO2(3)); - if ((m = map_mapname2mapid(mapname)) < 0) + map_local *m = map_mapname2mapid(mapname.c_str()); + if (m == nullptr) { - push_val(st->stack, ScriptCode::INT, -1); + push_val(st->stack, ByteCode::INT, -1); return; } map_foreachinarea(std::bind(builtin_mobcount_sub, ph::_1, event, &c), - m, 0, 0, map[m].xs, map[m].ys, BL::MOB); + m, + 0, 0, + m->xs, m->ys, + BL::MOB); - push_val(st->stack, ScriptCode::INT, (c - 1)); + push_val(st->stack, ByteCode::INT, (c - 1)); } static void builtin_marriage(ScriptState *st) { - const char *partner = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string partner = conv_str(st, &AARGO2(2)); dumb_ptr<map_session_data> sd = script_rid2sd(st); - dumb_ptr<map_session_data> p_sd = map_nick2sd(partner); + dumb_ptr<map_session_data> p_sd = map_nick2sd(partner.c_str()); if (sd == NULL || p_sd == NULL || pc_marriage(sd, p_sd) < 0) { - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); return; } - push_val(st->stack, ScriptCode::INT, 1); + push_val(st->stack, ByteCode::INT, 1); } static @@ -3716,17 +3511,17 @@ void builtin_divorce(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - st->state = STOP; // rely on pc_divorce to restart + st->state = ScriptEndState::STOP; // rely on pc_divorce to restart sd->npc_flags.divorce = 1; if (sd == NULL || pc_divorce(sd) < 0) { - push_val(st->stack, ScriptCode::INT, 0); + push_val(st->stack, ByteCode::INT, 0); return; } - push_val(st->stack, ScriptCode::INT, 1); + push_val(st->stack, ByteCode::INT, 1); } /*========================================== @@ -3737,15 +3532,14 @@ static void builtin_getitemname(ScriptState *st) { struct item_data *i_data; - char *item_name; struct script_data *data; - data = &(st->stack->stack_data[st->start + 2]); + data = &AARGO2(2); get_val(st, data); - if (data->type == ScriptCode::STR || data->type == ScriptCode::CONSTSTR) + if (data->type == ByteCode::STR || data->type == ByteCode::CONSTSTR) { - const char *name = conv_str(st, data); - i_data = itemdb_searchname(name); + dumb_string name = conv_str(st, data); + i_data = itemdb_searchname(name.c_str()); } else { @@ -3753,26 +3547,25 @@ void builtin_getitemname(ScriptState *st) i_data = itemdb_search(item_id); } - item_name = (char *) calloc(24, 1); + dumb_string item_name; if (i_data) - strncpy(item_name, i_data->jname, 23); + item_name = dumb_string::copy(i_data->jname); else - strncpy(item_name, "Unknown Item", 23); - - push_str(st->stack, ScriptCode::STR, item_name); + item_name = dumb_string::copy("Unknown Item"); + push_str(st->stack, ByteCode::STR, item_name); } static void builtin_getspellinvocation(ScriptState *st) { - const char *name = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string name = conv_str(st, &AARGO2(2)); - const char *invocation = magic_find_invocation(name); + const char *invocation = magic_find_invocation(name.str()); if (!invocation) invocation = "..."; - push_str(st->stack, ScriptCode::STR, strdup(invocation)); + push_str(st->stack, ByteCode::STR, dumb_string::copy(invocation)); } static @@ -3780,7 +3573,7 @@ void builtin_getpartnerid2(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - push_val(st->stack, ScriptCode::INT, sd->status.partner_id); + push_val(st->stack, ByteCode::INT, sd->status.partner_id); } /*========================================== @@ -3799,30 +3592,30 @@ void builtin_getinventorylist(ScriptState *st) if (sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0) { - pc_setreg(sd, add_str("@inventorylist_id") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_id") + (j << 24), sd->status.inventory[i].nameid); - pc_setreg(sd, add_str("@inventorylist_amount") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_amount") + (j << 24), sd->status.inventory[i].amount); - pc_setreg(sd, add_str("@inventorylist_equip") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_equip") + (j << 24), uint16_t(sd->status.inventory[i].equip)); - pc_setreg(sd, add_str("@inventorylist_refine") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_refine") + (j << 24), sd->status.inventory[i].refine); - pc_setreg(sd, add_str("@inventorylist_identify") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_identify") + (j << 24), sd->status.inventory[i].identify); - pc_setreg(sd, add_str("@inventorylist_attribute") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_attribute") + (j << 24), sd->status.inventory[i].attribute); - pc_setreg(sd, add_str("@inventorylist_card1") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_card1") + (j << 24), sd->status.inventory[i].card[0]); - pc_setreg(sd, add_str("@inventorylist_card2") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_card2") + (j << 24), sd->status.inventory[i].card[1]); - pc_setreg(sd, add_str("@inventorylist_card3") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_card3") + (j << 24), sd->status.inventory[i].card[2]); - pc_setreg(sd, add_str("@inventorylist_card4") + (j << 24), + pc_setreg(sd, variable_names.intern("@inventorylist_card4") + (j << 24), sd->status.inventory[i].card[3]); j++; } } - pc_setreg(sd, add_str("@inventorylist_count"), j); + pc_setreg(sd, variable_names.intern("@inventorylist_count"), j); } static @@ -3842,18 +3635,18 @@ void builtin_getactivatedpoolskilllist(ScriptState *st) if (sd->status.skill[skill_id].lv) { - pc_setreg(sd, add_str("@skilllist_id") + (count << 24), + pc_setreg(sd, variable_names.intern("@skilllist_id") + (count << 24), static_cast<uint16_t>(skill_id)); - pc_setreg(sd, add_str("@skilllist_lv") + (count << 24), + pc_setreg(sd, variable_names.intern("@skilllist_lv") + (count << 24), sd->status.skill[skill_id].lv); - pc_setreg(sd, add_str("@skilllist_flag") + (count << 24), + pc_setreg(sd, variable_names.intern("@skilllist_flag") + (count << 24), static_cast<uint16_t>(sd->status.skill[skill_id].flags)); - pc_setregstr(sd, add_str("@skilllist_name$") + (count << 24), - skill_name(skill_id)); + pc_setregstr(sd, variable_names.intern("@skilllist_name$") + (count << 24), + skill_name(skill_id).c_str()); ++count; } } - pc_setreg(sd, add_str("@skilllist_count"), count); + pc_setreg(sd, variable_names.intern("@skilllist_count"), count); } @@ -3873,25 +3666,25 @@ void builtin_getunactivatedpoolskilllist(ScriptState *st) if (sd->status.skill[skill_id].lv && !bool(sd->status.skill[skill_id].flags & SkillFlags::POOL_ACTIVATED)) { - pc_setreg(sd, add_str("@skilllist_id") + (count << 24), + pc_setreg(sd, variable_names.intern("@skilllist_id") + (count << 24), static_cast<uint16_t>(skill_id)); - pc_setreg(sd, add_str("@skilllist_lv") + (count << 24), + pc_setreg(sd, variable_names.intern("@skilllist_lv") + (count << 24), sd->status.skill[skill_id].lv); - pc_setreg(sd, add_str("@skilllist_flag") + (count << 24), + pc_setreg(sd, variable_names.intern("@skilllist_flag") + (count << 24), static_cast<uint16_t>(sd->status.skill[skill_id].flags)); - pc_setregstr(sd, add_str("@skilllist_name$") + (count << 24), - skill_name(skill_id)); + pc_setregstr(sd, variable_names.intern("@skilllist_name$") + (count << 24), + skill_name(skill_id).c_str()); ++count; } } - pc_setreg(sd, add_str("@skilllist_count"), count); + pc_setreg(sd, variable_names.intern("@skilllist_count"), count); } static void builtin_poolskill(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - SkillID skill_id = SkillID(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + SkillID skill_id = SkillID(conv_num(st, &AARGO2(2))); skill_pool_activate(sd, skill_id); clif_skillinfoblock(sd); @@ -3902,7 +3695,7 @@ static void builtin_unpoolskill(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - SkillID skill_id = SkillID(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + SkillID skill_id = SkillID(conv_num(st, &AARGO2(2))); skill_pool_deactivate(sd, skill_id); clif_skillinfoblock(sd); @@ -3925,18 +3718,18 @@ void builtin_misceffect(ScriptState *st) { int type; int id = 0; - const char *name = NULL; + dumb_string name; dumb_ptr<block_list> bl = NULL; - type = conv_num(st, &(st->stack->stack_data[st->start + 2])); + type = conv_num(st, &AARGO2(2)); - if (st->end > st->start + 3) + if (HARGO2(3)) { - struct script_data *sdata = &(st->stack->stack_data[st->start + 3]); + struct script_data *sdata = &AARGO2(3); get_val(st, sdata); - if (sdata->type == ScriptCode::STR || sdata->type == ScriptCode::CONSTSTR) + if (sdata->type == ByteCode::STR || sdata->type == ByteCode::CONSTSTR) name = conv_str(st, sdata); else id = conv_num(st, sdata); @@ -3944,7 +3737,7 @@ void builtin_misceffect(ScriptState *st) if (name) { - dumb_ptr<map_session_data> sd = map_nick2sd(name); + dumb_ptr<map_session_data> sd = map_nick2sd(name.c_str()); if (sd) bl = sd; } @@ -3978,7 +3771,7 @@ void builtin_specialeffect(ScriptState *st) clif_specialeffect(bl, conv_num(st, - &(st->stack->stack_data[st->start + 2])), + &AARGO2(2)), 0); } @@ -3993,7 +3786,7 @@ void builtin_specialeffect2(ScriptState *st) clif_specialeffect(sd, conv_num(st, - &(st->stack->stack_data[st->start + 2])), + &AARGO2(2)), 0); } @@ -4030,7 +3823,7 @@ void builtin_unequipbyid(ScriptState *st) if (sd == NULL) return; - EQUIP slot_id = EQUIP(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + EQUIP slot_id = EQUIP(conv_num(st, &AARGO2(2))); if (slot_id >= EQUIP() && slot_id < EQUIP::COUNT && sd->equip_index[slot_id] >= 0) @@ -4053,9 +3846,9 @@ void builtin_gmcommand(ScriptState *st) dumb_ptr<map_session_data> sd; sd = script_rid2sd(st); - const char *cmd = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string cmd = conv_str(st, &AARGO2(2)); - is_atcommand(sd->fd, sd, cmd, 99); + is_atcommand(sd->fd, sd, cmd.c_str(), 99); } @@ -4070,28 +3863,28 @@ void builtin_npcwarp(ScriptState *st) int x, y; dumb_ptr<npc_data> nd = NULL; - x = conv_num(st, &(st->stack->stack_data[st->start + 2])); - y = conv_num(st, &(st->stack->stack_data[st->start + 3])); - const char *npc = conv_str(st, &(st->stack->stack_data[st->start + 4])); - nd = npc_name2id(npc); + x = conv_num(st, &AARGO2(2)); + y = conv_num(st, &AARGO2(3)); + dumb_string npc = conv_str(st, &AARGO2(4)); + nd = npc_name2id(npc.c_str()); if (!nd) return; - short m = nd->bl_m; + map_local *m = nd->bl_m; /* Crude sanity checks. */ - if (m < 0 || !nd->bl_prev - || x < 0 || x > map[m].xs -1 - || y < 0 || y > map[m].ys - 1) + if (m == nullptr || !nd->bl_prev + || x < 0 || x > m->xs -1 + || y < 0 || y > m->ys - 1) return; - npc_enable(npc, 0); + npc_enable(npc.c_str(), 0); map_delblock(nd); /* [Freeyorp] */ nd->bl_x = x; nd->bl_y = y; map_addblock(nd); - npc_enable(npc, 1); + npc_enable(npc.c_str(), 1); } @@ -4103,12 +3896,11 @@ void builtin_npcwarp(ScriptState *st) static void builtin_message(ScriptState *st) { - dumb_ptr<map_session_data> pl_sd = NULL; + dumb_string player = conv_str(st, &AARGO2(2)); + dumb_string msg = conv_str(st, &AARGO2(3)); - const char *player = conv_str(st, &(st->stack->stack_data[st->start + 2])); - const char *msg = conv_str(st, &(st->stack->stack_data[st->start + 3])); - - if ((pl_sd = map_nick2sd(player)) == NULL) + dumb_ptr<map_session_data> pl_sd = map_nick2sd(player.c_str()); + if (pl_sd == NULL) return; clif_displaymessage(pl_sd->fd, msg); @@ -4123,19 +3915,14 @@ void builtin_message(ScriptState *st) static void builtin_npctalk(ScriptState *st) { - char message[255]; - dumb_ptr<npc_data> nd = map_id_as_npc(st->oid); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); + dumb_string str = conv_str(st, &AARGO2(2)); if (nd) { - memcpy(message, nd->name, 24); - strcat(message, " : "); - strcat(message, str); - clif_message(nd, message); + std::string message = std::string(nd->name) + " : " + str.c_str(); + clif_message(nd, message.c_str()); } - } /*========================================== @@ -4147,7 +3934,7 @@ void builtin_getlook(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - LOOK type = LOOK(conv_num(st, &(st->stack->stack_data[st->start + 2]))); + LOOK type = LOOK(conv_num(st, &AARGO2(2))); int val = -1; switch (type) { @@ -4179,7 +3966,7 @@ void builtin_getlook(ScriptState *st) break; } - push_val(st->stack, ScriptCode::INT, val); + push_val(st->stack, ByteCode::INT, val); } /*========================================== @@ -4190,27 +3977,27 @@ static void builtin_getsavepoint(ScriptState *st) { int x, y, type; - char *mapname; dumb_ptr<map_session_data> sd; sd = script_rid2sd(st); - type = conv_num(st, &(st->stack->stack_data[st->start + 2])); + type = conv_num(st, &AARGO2(2)); x = sd->status.save_point.x; y = sd->status.save_point.y; switch (type) { case 0: - mapname = (char*)calloc(24, 1); - strncpy(mapname, sd->status.save_point.map, 23); - push_str(st->stack, ScriptCode::STR, mapname); + { + dumb_string mapname = dumb_string::copy(sd->status.save_point.map); + push_str(st->stack, ByteCode::STR, mapname); + } break; case 1: - push_val(st->stack, ScriptCode::INT, x); + push_val(st->stack, ByteCode::INT, x); break; case 2: - push_val(st->stack, ScriptCode::INT, y); + push_val(st->stack, ByteCode::INT, y); break; } } @@ -4220,30 +4007,33 @@ void builtin_getsavepoint(ScriptState *st) *------------------------------------------ */ static -void builtin_areatimer_sub(dumb_ptr<block_list> bl, interval_t tick, const char *event) +void builtin_areatimer_sub(dumb_ptr<block_list> bl, interval_t tick, dumb_string event) { - pc_addeventtimer(bl->as_player(), tick, event); + pc_addeventtimer(bl->as_player(), tick, event.c_str()); } static void builtin_areatimer(ScriptState *st) { - int m; int x0, y0, x1, y1; - const char *mapname = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x0 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y0 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - x1 = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y1 = conv_num(st, &(st->stack->stack_data[st->start + 6])); - interval_t tick = static_cast<interval_t>(conv_num(st, &(st->stack->stack_data[st->start + 7]))); - const char *event = conv_str(st, &(st->stack->stack_data[st->start + 8])); + dumb_string mapname = conv_str(st, &AARGO2(2)); + x0 = conv_num(st, &AARGO2(3)); + y0 = conv_num(st, &AARGO2(4)); + x1 = conv_num(st, &AARGO2(5)); + y1 = conv_num(st, &AARGO2(6)); + interval_t tick = static_cast<interval_t>(conv_num(st, &AARGO2(7))); + dumb_string event = conv_str(st, &AARGO2(8)); - if ((m = map_mapname2mapid(mapname)) < 0) + map_local *m = map_mapname2mapid(mapname.c_str()); + if (m == nullptr) return; map_foreachinarea(std::bind(builtin_areatimer_sub, ph::_1, tick, event), - m, x0, y0, x1, y1, BL::PC); + m, + x0, y0, + x1, y1, + BL::PC); } /*========================================== @@ -4256,20 +4046,20 @@ void builtin_isin(ScriptState *st) int x1, y1, x2, y2; dumb_ptr<map_session_data> sd = script_rid2sd(st); - const char *str = conv_str(st, &(st->stack->stack_data[st->start + 2])); - x1 = conv_num(st, &(st->stack->stack_data[st->start + 3])); - y1 = conv_num(st, &(st->stack->stack_data[st->start + 4])); - x2 = conv_num(st, &(st->stack->stack_data[st->start + 5])); - y2 = conv_num(st, &(st->stack->stack_data[st->start + 6])); + dumb_string str = conv_str(st, &AARGO2(2)); + x1 = conv_num(st, &AARGO2(3)); + y1 = conv_num(st, &AARGO2(4)); + x2 = conv_num(st, &AARGO2(5)); + y2 = conv_num(st, &AARGO2(6)); if (!sd) return; - push_val(st->stack, ScriptCode::INT, + using namespace operators; + push_val(st->stack, ByteCode::INT, (sd->bl_x >= x1 && sd->bl_x <= x2) && (sd->bl_y >= y1 && sd->bl_y <= y2) - && (!strcmp(str, map[sd->bl_m].name))); - + && (str == sd->bl_m->name)); } // Trigger the shop on a (hopefully) nearby shop NPC @@ -4282,7 +4072,7 @@ void builtin_shop(ScriptState *st) if (!sd) return; - nd = npc_name2id(conv_str(st, &(st->stack->stack_data[st->start + 2]))); + nd = npc_name2id(conv_str(st, &AARGO2(2)).c_str()); if (!nd) return; @@ -4299,7 +4089,7 @@ void builtin_isdead(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - push_val(st->stack, ScriptCode::INT, pc_isdead(sd)); + push_val(st->stack, ByteCode::INT, pc_isdead(sd)); } /*======================================== @@ -4309,18 +4099,18 @@ void builtin_isdead(ScriptState *st) static void builtin_fakenpcname(ScriptState *st) { - const char *name = conv_str(st, &(st->stack->stack_data[st->start + 2])); - const char *newname = conv_str(st, &(st->stack->stack_data[st->start + 3])); - int newsprite = conv_num(st, &(st->stack->stack_data[st->start + 4])); - dumb_ptr<npc_data> nd = npc_name2id(name); + dumb_string name = conv_str(st, &AARGO2(2)); + dumb_string newname = conv_str(st, &AARGO2(3)); + int newsprite = conv_num(st, &AARGO2(4)); + dumb_ptr<npc_data> nd = npc_name2id(name.c_str()); if (!nd) return; - strzcpy(nd->name, newname, sizeof(nd->name)); + strzcpy(nd->name, newname.c_str(), sizeof(nd->name)); nd->npc_class = newsprite; // Refresh this npc - npc_enable(name, 0); - npc_enable(name, 1); + npc_enable(name.c_str(), 0); + npc_enable(name.c_str(), 1); } @@ -4333,7 +4123,7 @@ void builtin_getx(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - push_val(st->stack, ScriptCode::INT, sd->bl_x); + push_val(st->stack, ByteCode::INT, sd->bl_x); } /*============================ @@ -4345,7 +4135,7 @@ void builtin_gety(ScriptState *st) { dumb_ptr<map_session_data> sd = script_rid2sd(st); - push_val(st->stack, ScriptCode::INT, sd->bl_y); + push_val(st->stack, ByteCode::INT, sd->bl_y); } /* @@ -4357,7 +4147,7 @@ void builtin_getmap(ScriptState *st) dumb_ptr<map_session_data> sd = script_rid2sd(st); // A map_data lives essentially forever. - push_str(st->stack, ScriptCode::CONSTSTR, map[sd->bl_m].name); + push_str(st->stack, ByteCode::CONSTSTR, dumb_string::fake(sd->bl_m->name)); } // @@ -4368,13 +4158,14 @@ void builtin_getmap(ScriptState *st) *------------------------------------------ */ static -ScriptCode get_com(const ScriptCode *script, int *pos_) +ByteCode get_com(ScriptPointer *script) { - if (static_cast<uint8_t>(script[*pos_]) >= 0x80) + if (static_cast<uint8_t>(script->peek()) >= 0x80) { - return ScriptCode::INT; + // synthetic! Does not advance pos yet. + return ByteCode::INT; } - return script[(*pos_)++]; + return script->pop(); } /*========================================== @@ -4382,18 +4173,19 @@ ScriptCode get_com(const ScriptCode *script, int *pos_) *------------------------------------------ */ static -int get_num(const ScriptCode *scr, int *pos_) +int get_num(ScriptPointer *scr) { - const uint8_t *script = reinterpret_cast<const uint8_t *>(scr); - int i, j; - i = 0; - j = 0; - while (script[*pos_] >= 0xc0) + int i = 0; + int j = 0; + uint8_t val; + do { - i += (script[(*pos_)++] & 0x7f) << j; + val = static_cast<uint8_t>(scr->pop()); + i += (val & 0x7f) << j; j += 6; } - return i + ((script[(*pos_)++] & 0x7f) << j); + while (val >= 0xc0); + return i; } /*========================================== @@ -4403,20 +4195,22 @@ int get_num(const ScriptCode *scr, int *pos_) static int pop_val(ScriptState *st) { - if (st->stack->sp <= 0) + if (st->stack->stack_datav.empty()) return 0; - st->stack->sp--; - get_val(st, &(st->stack->stack_data[st->stack->sp])); - if (st->stack->stack_data[st->stack->sp].type == ScriptCode::INT) - return st->stack->stack_data[st->stack->sp].u.num; - return 0; + script_data& back = st->stack->stack_datav.back(); + get_val(st, &back); + int rv = 0; + if (back.type == ByteCode::INT) + rv = back.u.num; + st->stack->stack_datav.pop_back(); + return rv; } static bool isstr(struct script_data& c) { - return c.type == ScriptCode::STR - || c.type == ScriptCode::CONSTSTR; + return c.type == ByteCode::STR + || c.type == ByteCode::CONSTSTR; } /*========================================== @@ -4426,36 +4220,29 @@ bool isstr(struct script_data& c) static void op_add(ScriptState *st) { - st->stack->sp--; - get_val(st, &(st->stack->stack_data[st->stack->sp])); - get_val(st, &(st->stack->stack_data[st->stack->sp - 1])); + get_val(st, &st->stack->stack_datav.back()); + script_data back = st->stack->stack_datav.back(); + st->stack->stack_datav.pop_back(); + get_val(st, &st->stack->stack_datav.back()); + script_data& back1 = st->stack->stack_datav.back(); + st->stack->stack_datav.pop_back(); - if (isstr(st->stack->stack_data[st->stack->sp]) - || isstr(st->stack->stack_data[st->stack->sp - 1])) + if (!(isstr(back) || isstr(back1))) { - conv_str(st, &(st->stack->stack_data[st->stack->sp])); - conv_str(st, &(st->stack->stack_data[st->stack->sp - 1])); - } - if (st->stack->stack_data[st->stack->sp].type == ScriptCode::INT) - { // ii - st->stack->stack_data[st->stack->sp - 1].u.num += - st->stack->stack_data[st->stack->sp].u.num; + back1.u.num += back.u.num; } else - { // ssの予定 - char *buf; - buf = (char *) - calloc(strlen(st->stack->stack_data[st->stack->sp - 1].u.str) + - strlen(st->stack->stack_data[st->stack->sp].u.str) + 1, - 1); - strcpy(buf, st->stack->stack_data[st->stack->sp - 1].u.str); - strcat(buf, st->stack->stack_data[st->stack->sp].u.str); - if (st->stack->stack_data[st->stack->sp - 1].type == ScriptCode::STR) - free(const_cast<char *>(st->stack->stack_data[st->stack->sp - 1].u.str)); - if (st->stack->stack_data[st->stack->sp].type == ScriptCode::STR) - free(const_cast<char *>(st->stack->stack_data[st->stack->sp].u.str)); - st->stack->stack_data[st->stack->sp - 1].type = ScriptCode::STR; - st->stack->stack_data[st->stack->sp - 1].u.str = buf; + { + dumb_string sb = conv_str(st, &back); + dumb_string sb1 = conv_str(st, &back1); + // ssの予定 + std::string buf = sb1.str() + sb.str(); + if (back1.type == ByteCode::STR) + back1.u.str.delete_(); + if (back.type == ByteCode::STR) + back.u.str.delete_(); + back1.type = ByteCode::STR; + back1.u.str = dumb_string::copys(buf); } } @@ -4464,43 +4251,37 @@ void op_add(ScriptState *st) *------------------------------------------ */ static -void op_2str(ScriptState *st, ScriptCode op, int sp1, int sp2) +void op_2str(ScriptState *st, ByteCode op, dumb_string s1, dumb_string s2) { - const char *s1 = st->stack->stack_data[sp1].u.str; - const char *s2 = st->stack->stack_data[sp2].u.str; int a = 0; + using namespace operators; switch (op) { - case ScriptCode::EQ: - a = (strcmp(s1, s2) == 0); + case ByteCode::EQ: + a = s1 == s2; break; - case ScriptCode::NE: - a = (strcmp(s1, s2) != 0); + case ByteCode::NE: + a = s1 != s2; break; - case ScriptCode::GT: - a = (strcmp(s1, s2) > 0); + case ByteCode::GT: + a = s1 > s2; break; - case ScriptCode::GE: - a = (strcmp(s1, s2) >= 0); + case ByteCode::GE: + a = s1 >= s2; break; - case ScriptCode::LT: - a = (strcmp(s1, s2) < 0); + case ByteCode::LT: + a = s1 < s2; break; - case ScriptCode::LE: - a = (strcmp(s1, s2) <= 0); + case ByteCode::LE: + a = s1 <= s2; break; default: PRINTF("illegal string operater\n"); break; } - push_val(st->stack, ScriptCode::INT, a); - - if (st->stack->stack_data[sp1].type == ScriptCode::STR) - free(const_cast<char *>(s1)); - if (st->stack->stack_data[sp2].type == ScriptCode::STR) - free(const_cast<char *>(s2)); + push_val(st->stack, ByteCode::INT, a); } /*========================================== @@ -4508,63 +4289,63 @@ void op_2str(ScriptState *st, ScriptCode op, int sp1, int sp2) *------------------------------------------ */ static -void op_2num(ScriptState *st, ScriptCode op, int i1, int i2) +void op_2num(ScriptState *st, ByteCode op, int i1, int i2) { switch (op) { - case ScriptCode::SUB: + case ByteCode::SUB: i1 -= i2; break; - case ScriptCode::MUL: + case ByteCode::MUL: i1 *= i2; break; - case ScriptCode::DIV: + case ByteCode::DIV: i1 /= i2; break; - case ScriptCode::MOD: + case ByteCode::MOD: i1 %= i2; break; - case ScriptCode::AND: + case ByteCode::AND: i1 &= i2; break; - case ScriptCode::OR: + case ByteCode::OR: i1 |= i2; break; - case ScriptCode::XOR: + case ByteCode::XOR: i1 ^= i2; break; - case ScriptCode::LAND: + case ByteCode::LAND: i1 = i1 && i2; break; - case ScriptCode::LOR: + case ByteCode::LOR: i1 = i1 || i2; break; - case ScriptCode::EQ: + case ByteCode::EQ: i1 = i1 == i2; break; - case ScriptCode::NE: + case ByteCode::NE: i1 = i1 != i2; break; - case ScriptCode::GT: + case ByteCode::GT: i1 = i1 > i2; break; - case ScriptCode::GE: + case ByteCode::GE: i1 = i1 >= i2; break; - case ScriptCode::LT: + case ByteCode::LT: i1 = i1 < i2; break; - case ScriptCode::LE: + case ByteCode::LE: i1 = i1 <= i2; break; - case ScriptCode::R_SHIFT: + case ByteCode::R_SHIFT: i1 = i1 >> i2; break; - case ScriptCode::L_SHIFT: + case ByteCode::L_SHIFT: i1 = i1 << i2; break; } - push_val(st->stack, ScriptCode::INT, i1); + push_val(st->stack, ByteCode::INT, i1); } /*========================================== @@ -4572,34 +4353,35 @@ void op_2num(ScriptState *st, ScriptCode op, int i1, int i2) *------------------------------------------ */ static -void op_2(ScriptState *st, ScriptCode op) +void op_2(ScriptState *st, ByteCode op) { - int i1, i2; - const char *s1 = NULL, *s2 = NULL; + // pop_val has unfortunate implications here + script_data d2 = st->stack->stack_datav.back(); + st->stack->stack_datav.pop_back(); + get_val(st, &d2); + script_data d1 = st->stack->stack_datav.back(); + st->stack->stack_datav.pop_back(); + get_val(st, &d1); - i2 = pop_val(st); - if (isstr(st->stack->stack_data[st->stack->sp])) - s2 = st->stack->stack_data[st->stack->sp].u.str; - - i1 = pop_val(st); - if (isstr(st->stack->stack_data[st->stack->sp])) - s1 = st->stack->stack_data[st->stack->sp].u.str; - - if (s1 != NULL && s2 != NULL) + if (isstr(d1) && isstr(d2)) { // ss => op_2str - op_2str(st, op, st->stack->sp, st->stack->sp + 1); + op_2str(st, op, d1.u.str, d2.u.str); + if (d1.type == ByteCode::STR) + d1.u.str.delete_(); + if (d2.type == ByteCode::STR) + d2.u.str.delete_(); } - else if (s1 == NULL && s2 == NULL) + else if (!(isstr(d1) || isstr(d2))) { // ii => op_2num - op_2num(st, op, i1, i2); + op_2num(st, op, d1.u.num, d2.u.num); } else { // si,is => error - PRINTF("script: op_2: int&str, str&int not allow."); - push_val(st->stack, ScriptCode::INT, 0); + PRINTF("script: op_2: int&str, str&int not allow.\n"); + push_val(st->stack, ByteCode::INT, 0); } } @@ -4608,23 +4390,23 @@ void op_2(ScriptState *st, ScriptCode op) *------------------------------------------ */ static -void op_1num(ScriptState *st, ScriptCode op) +void op_1num(ScriptState *st, ByteCode op) { int i1; i1 = pop_val(st); switch (op) { - case ScriptCode::NEG: + case ByteCode::NEG: i1 = -i1; break; - case ScriptCode::NOT: + case ByteCode::NOT: i1 = ~i1; break; - case ScriptCode::LNOT: + case ByteCode::LNOT: i1 = !i1; break; } - push_val(st->stack, ScriptCode::INT, i1); + push_val(st->stack, ByteCode::INT, i1); } /*========================================== @@ -4633,102 +4415,94 @@ void op_1num(ScriptState *st, ScriptCode op) */ void run_func(ScriptState *st) { - int i, start_sp, end_sp, func; - - end_sp = st->stack->sp; - for (i = end_sp - 1; i >= 0 && st->stack->stack_data[i].type != ScriptCode::ARG; - i--); - if (i == 0) + size_t end_sp = st->stack->stack_datav.size(); + size_t start_sp = end_sp - 1; + while (st->stack->stack_datav[start_sp].type != ByteCode::ARG) { - if (battle_config.error_log) - PRINTF("function not found\n"); -// st->stack->sp=0; - st->state = END; - return; + start_sp--; + if (start_sp == 0) + { + if (battle_config.error_log) + PRINTF("function not found\n"); + st->state = ScriptEndState::END; + return; + } } - start_sp = i - 1; - st->start = i - 1; + // the func is before the arg + start_sp--; + st->start = start_sp; st->end = end_sp; - func = st->stack->stack_data[st->start].u.num; - if (st->stack->stack_data[st->start].type != ScriptCode::NAME - || str_data[func].type != ScriptCode::FUNC) + size_t func = st->stack->stack_datav[st->start].u.num; + if (st->stack->stack_datav[st->start].type != ByteCode::FUNC_REF) { PRINTF("run_func: not function and command! \n"); -// st->stack->sp=0; - st->state = END; + st->state = ScriptEndState::END; return; } -#ifdef DEBUG_RUN - if (battle_config.etc_log) + + if (DEBUG_RUN && battle_config.etc_log) { - PRINTF("run_func : %s? (%d(%d))\n", str_buf + str_data[func].str, - func, str_data[func].type); + PRINTF("run_func : %s\n", + builtin_functions[func].name); PRINTF("stack dump :"); - for (i = 0; i < end_sp; i++) + for (script_data& d : st->stack->stack_datav) { - switch (st->stack->stack_data[i].type) + // this is not *nearly* complete enough to be useful ... + switch (d.type) { - case ScriptCode::INT: - PRINTF(" int(%d)", st->stack->stack_data[i].u.num); + case ByteCode::INT: + PRINTF(" int(%d)", d.u.num); + break; + case ByteCode::RETINFO: + PRINTF(" retinfo(%p)", static_cast<const void *>(d.u.script)); + break; + case ByteCode::PARAM_: + PRINTF(" param(%d)", d.u.num); break; - case ScriptCode::NAME: - PRINTF(" name(%s)", - str_buf + - str_data[st->stack->stack_data[i].u.num].str); + case ByteCode::VARIABLE: + PRINTF(" name(%s)", variable_names.outtern(d.u.num)); break; - case ScriptCode::ARG: + case ByteCode::ARG: PRINTF(" arg"); break; - case ScriptCode::POS: - PRINTF(" pos(%d)", st->stack->stack_data[i].u.num); + case ByteCode::POS: + PRINTF(" pos(%d)", d.u.num); break; default: - PRINTF(" %d,%d", st->stack->stack_data[i].type, - st->stack->stack_data[i].u.num); + PRINTF(" %d,%d", d.type, d.u.num); } } PRINTF("\n"); } -#endif - if (str_data[func].func) - { - str_data[func].func(st); - } - else - { - if (battle_config.error_log) - PRINTF("run_func : %s? (%d(%d))\n", str_buf + str_data[func].str, - func, str_data[func].type); - push_val(st->stack, ScriptCode::INT, 0); - } + builtin_functions[func].func(st); pop_stack(st->stack, start_sp, end_sp); - if (st->state == RETFUNC) + if (st->state == ScriptEndState::RETFUNC) { // ユーザー定義関数からの復帰 int olddefsp = st->defsp; pop_stack(st->stack, st->defsp, start_sp); // 復帰に邪魔なスタック削除 if (st->defsp < 4 - || st->stack->stack_data[st->defsp - 1].type != ScriptCode::RETINFO) + || st->stack->stack_datav[st->defsp - 1].type != ByteCode::RETINFO) { PRINTF("script:run_func (return) return without callfunc or callsub!\n"); - st->state = END; + st->state = ScriptEndState::END; return; } assert (olddefsp == st->defsp); // pretty sure it hasn't changed yet - st->script = conv_script(st, &(st->stack->stack_data[olddefsp - 1])); // スクリプトを復元 - st->pos = conv_num(st, &(st->stack->stack_data[olddefsp - 2])); // スクリプト位置の復元 - st->defsp = conv_num(st, &(st->stack->stack_data[olddefsp - 3])); // 基準スタックポインタを復元 + st->scriptp.code = conv_script(st, &st->stack->stack_datav[olddefsp - 1]); // スクリプトを復元 + st->scriptp.pos = conv_num(st, &st->stack->stack_datav[olddefsp - 2]); // スクリプト位置の復元 + st->defsp = conv_num(st, &st->stack->stack_datav[olddefsp - 3]); // 基準スタックポインタを復元 // Number of arguments. - i = conv_num(st, &(st->stack->stack_data[olddefsp - 4])); // 引数の数所得 + int i = conv_num(st, &st->stack->stack_datav[olddefsp - 4]); // 引数の数所得 assert (i == 0); pop_stack(st->stack, olddefsp - 4 - i, olddefsp); // 要らなくなったスタック(引数と復帰用データ)削除 - st->state = GOTO; + st->state = ScriptEndState::GOTO; } } @@ -4737,205 +4511,190 @@ void run_func(ScriptState *st) *------------------------------------------ */ static -void run_script_main(const ScriptCode *script, int pos_, int, int, - ScriptState *st, const ScriptCode *rootscript) +void run_script_main(ScriptState *st, const ScriptBuffer *rootscript) { - int rerun_pos; int cmdcount = script_config.check_cmdcount; int gotocount = script_config.check_gotocount; struct script_stack *stack = st->stack; - st->defsp = stack->sp; - st->script = script; + st->defsp = stack->stack_datav.size(); - rerun_pos = st->pos; - for (st->state = 0; st->state == 0;) + int rerun_pos = st->scriptp.pos; + st->state = ScriptEndState::ZERO; + while (st->state == ScriptEndState::ZERO) { - switch (ScriptCode c = get_com(script, &st->pos)) + switch (ByteCode c = get_com(&st->scriptp)) { - case ScriptCode::EOL: - if (stack->sp != st->defsp) + case ByteCode::EOL: + if (stack->stack_datav.size() != st->defsp) { if (battle_config.error_log) - PRINTF("stack.sp (%d) != default (%d)\n", stack->sp, + PRINTF("stack.sp (%zu) != default (%d)\n", + stack->stack_datav.size(), st->defsp); - stack->sp = st->defsp; + stack->stack_datav.resize(st->defsp); } - rerun_pos = st->pos; + rerun_pos = st->scriptp.pos; break; - case ScriptCode::INT: - push_val(stack, ScriptCode::INT, get_num(script, &st->pos)); + case ByteCode::INT: + // synthesized! + push_val(stack, ByteCode::INT, get_num(&st->scriptp)); break; - case ScriptCode::POS: - case ScriptCode::NAME: - push_val(stack, c, (*(const int *)(script + st->pos)) & 0xffffff); - st->pos += 3; + + case ByteCode::POS: + case ByteCode::VARIABLE: + case ByteCode::FUNC_REF: + // Note that these 3 have *very* different meanings, + // despite being encoded similarly. + { + int arg = 0; + arg |= static_cast<uint8_t>(st->scriptp.pop()) << 0; + arg |= static_cast<uint8_t>(st->scriptp.pop()) << 8; + arg |= static_cast<uint8_t>(st->scriptp.pop()) << 16; + push_val(stack, c, arg); + } break; - case ScriptCode::ARG: + case ByteCode::ARG: push_val(stack, c, 0); break; - case ScriptCode::STR: - push_str(stack, ScriptCode::CONSTSTR, reinterpret_cast<const char *>(script + st->pos)); - while (script[st->pos++] != ScriptCode::NOP); + case ByteCode::STR: + // ScriptPointer.pops() leaves it .pos pointing to the \0. + push_str(stack, ByteCode::CONSTSTR, dumb_string::fake(st->scriptp.pops())); break; - case ScriptCode::FUNC: + case ByteCode::FUNC_: run_func(st); - if (st->state == GOTO) + if (st->state == ScriptEndState::GOTO) { - rerun_pos = st->pos; - script = st->script; - st->state = 0; + rerun_pos = st->scriptp.pos; + st->state = ScriptEndState::ZERO; if (gotocount > 0 && (--gotocount) <= 0) { PRINTF("run_script: infinity loop !\n"); - st->state = END; + st->state = ScriptEndState::END; } } break; - case ScriptCode::ADD: + case ByteCode::ADD: op_add(st); break; - case ScriptCode::SUB: - case ScriptCode::MUL: - case ScriptCode::DIV: - case ScriptCode::MOD: - case ScriptCode::EQ: - case ScriptCode::NE: - case ScriptCode::GT: - case ScriptCode::GE: - case ScriptCode::LT: - case ScriptCode::LE: - case ScriptCode::AND: - case ScriptCode::OR: - case ScriptCode::XOR: - case ScriptCode::LAND: - case ScriptCode::LOR: - case ScriptCode::R_SHIFT: - case ScriptCode::L_SHIFT: + case ByteCode::SUB: + case ByteCode::MUL: + case ByteCode::DIV: + case ByteCode::MOD: + case ByteCode::EQ: + case ByteCode::NE: + case ByteCode::GT: + case ByteCode::GE: + case ByteCode::LT: + case ByteCode::LE: + case ByteCode::AND: + case ByteCode::OR: + case ByteCode::XOR: + case ByteCode::LAND: + case ByteCode::LOR: + case ByteCode::R_SHIFT: + case ByteCode::L_SHIFT: op_2(st, c); break; - case ScriptCode::NEG: - case ScriptCode::NOT: - case ScriptCode::LNOT: + case ByteCode::NEG: + case ByteCode::NOT: + case ByteCode::LNOT: op_1num(st, c); break; - case ScriptCode::NOP: - st->state = END; + case ByteCode::NOP: + st->state = ScriptEndState::END; break; default: if (battle_config.error_log) - PRINTF("unknown command : %d @ %d\n", c, pos_); - st->state = END; + PRINTF("unknown command : %d @ %zu\n", + c, st->scriptp.pos); + st->state = ScriptEndState::END; break; } if (cmdcount > 0 && (--cmdcount) <= 0) { PRINTF("run_script: infinity loop !\n"); - st->state = END; + st->state = ScriptEndState::END; } } switch (st->state) { - case STOP: + case ScriptEndState::STOP: break; - case END: + case ScriptEndState::END: { dumb_ptr<map_session_data> sd = map_id2sd(st->rid); - st->pos = -1; + st->scriptp.code = nullptr; + st->scriptp.pos = -1; if (sd && sd->npc_id == st->oid) npc_event_dequeue(sd); } break; - case RERUNLINE: - { - st->pos = rerun_pos; - } + case ScriptEndState::RERUNLINE: + st->scriptp.pos = rerun_pos; break; } - if (st->state != END) + if (st->state != ScriptEndState::END) { // 再開するためにスタック情報を保存 dumb_ptr<map_session_data> sd = map_id2sd(st->rid); - if (sd /* && sd->npc_stackbuf==NULL */ ) + if (sd) { - if (sd->npc_stackbuf) - free(sd->npc_stackbuf); - sd->npc_stackbuf = (struct script_data *) - calloc(sizeof(stack->stack_data[0]) * stack->sp_max, 1); - memcpy(sd->npc_stackbuf, stack->stack_data, - sizeof(stack->stack_data[0]) * stack->sp_max); - sd->npc_stack = stack->sp; - sd->npc_stackmax = stack->sp_max; - sd->npc_script = script; + sd->npc_stackbuf = stack->stack_datav; + sd->npc_script = st->scriptp.code; + // sd->npc_pos is set later ... ??? sd->npc_scriptroot = rootscript; } } - } /*========================================== * スクリプトの実行 *------------------------------------------ */ -int run_script(const ScriptCode *script, int pos_, int rid, int oid) +int run_script(ScriptPointer sp, int rid, int oid) { - return run_script_l(script, pos_, rid, oid, 0, NULL); + return run_script_l(sp, rid, oid, 0, NULL); } -int run_script_l(const ScriptCode *script, int pos_, int rid, int oid, +int run_script_l(ScriptPointer sp, int rid, int oid, int args_nr, argrec_t *args) { struct script_stack stack; ScriptState st; dumb_ptr<map_session_data> sd = map_id2sd(rid); - const ScriptCode *rootscript = script; + const ScriptBuffer *rootscript = sp.code; int i; - if (script == NULL || pos_ < 0) + if (sp.code == NULL || sp.pos >> 24) return -1; - if (sd && sd->npc_stackbuf && sd->npc_scriptroot == rootscript) + if (sd && !sd->npc_stackbuf.empty() && sd->npc_scriptroot == rootscript) { // 前回のスタックを復帰 - script = sd->npc_script; - stack.sp = sd->npc_stack; - stack.sp_max = sd->npc_stackmax; - stack.stack_data = (struct script_data *) - calloc(stack.sp_max, sizeof(stack.stack_data[0])); - memcpy(stack.stack_data, sd->npc_stackbuf, - sizeof(stack.stack_data[0]) * stack.sp_max); - free(sd->npc_stackbuf); - sd->npc_stackbuf = NULL; - } - else - { - // スタック初期化 - stack.sp = 0; - stack.sp_max = 64; - stack.stack_data = (struct script_data *) - calloc(stack.sp_max, sizeof(stack.stack_data[0])); + sp.code = sd->npc_script; + stack.stack_datav = std::move(sd->npc_stackbuf); } st.stack = &stack; - st.pos = pos_; + st.scriptp = sp; st.rid = rid; st.oid = oid; for (i = 0; i < args_nr; i++) { if (args[i].name[strlen(args[i].name) - 1] == '$') - pc_setregstr(sd, add_str(args[i].name), args[i].v.s); + pc_setregstr(sd, variable_names.intern(args[i].name), args[i].v.s); else - pc_setreg(sd, add_str(args[i].name), args[i].v.i); + pc_setreg(sd, variable_names.intern(args[i].name), args[i].v.i); } - run_script_main(script, pos_, rid, oid, &st, rootscript); + run_script_main(&st, rootscript); - free(stack.stack_data); - stack.stack_data = NULL; - return st.pos; + stack.stack_datav.clear(); + return st.scriptp.pos; } /*========================================== @@ -4955,16 +4714,11 @@ void mapreg_setreg(int num, int val) */ void mapreg_setregstr(int num, const char *str) { - char *p = mapregstr_db.get(num); - if (p) - free(p); - if (!str || !*str) - p = NULL; + mapregstr_db.erase(num); else - p = strdup(str); + mapregstr_db.insert(num, str); - mapregstr_db.put(num, p); mapreg_dirty = 1; } @@ -4994,12 +4748,11 @@ void script_load_mapreg(void) record<','>(&buf1), &buf2))) { - int s = add_str(buf1.c_str()); + int s = variable_names.intern(buf1); int key = (index << 24) | s; if (buf1.back() == '$') { - char *p = strdup(buf2.c_str()); - mapregstr_db.put(key, p); + mapregstr_db.insert(key, buf2); } else { @@ -5027,7 +4780,7 @@ static void script_save_mapreg_intsub(int key, int data, FILE *fp) { int num = key & 0x00ffffff, i = key >> 24; - char *name = str_buf + str_data[num].str; + const std::string& name = variable_names.outtern(num); if (name[1] != '@') { if (i == 0) @@ -5038,10 +4791,10 @@ void script_save_mapreg_intsub(int key, int data, FILE *fp) } static -void script_save_mapreg_strsub(int key, char *data, FILE *fp) +void script_save_mapreg_strsub(int key, const std::string& data, FILE *fp) { int num = key & 0x00ffffff, i = key >> 24; - char *name = str_buf + str_data[num].str; + const std::string& name = variable_names.outtern(num); if (name[1] != '@') { if (i == 0) @@ -5084,49 +4837,21 @@ void script_config_read() script_config.check_gotocount = 512; } -/*========================================== - * 終了 - *------------------------------------------ - */ - -static -void mapregstr_db_final(char *data) -{ - free(data); -} - -static -void userfunc_db_final(const ScriptCode *data) -{ - free(const_cast<ScriptCode *>(data)); -} - void do_final_script(void) { if (mapreg_dirty >= 0) script_save_mapreg(); -#if 0 - // labels are allocated just out of this - // (so it's a leak ...) - // this is disabled because it leads to a crash - // due to double-free - if (script_buf) - free(script_buf); -#endif mapreg_db.clear(); for (auto& pair : mapregstr_db) - mapregstr_db_final(pair.second); + pair.second.clear(); mapregstr_db.clear(); scriptlabel_db.clear(); for (auto& pair : userfunc_db) - userfunc_db_final(pair.second); + pair.second.reset(); userfunc_db.clear(); - if (str_data) - free(str_data); - if (str_buf) - free(str_buf); + str_datam.clear(); } /*========================================== @@ -5196,7 +4921,6 @@ BuiltinFunction builtin_functions[] = BUILTIN(savepoint, "Mxy"), BUILTIN(gettimetick, "i"), BUILTIN(gettime, "i"), - BUILTIN(gettimestr, "si"), BUILTIN(openstorage, "*"), BUILTIN(monster, "Mxysmi*"), BUILTIN(areamonster, "Mxyxysmi*"), diff --git a/src/map/script.hpp b/src/map/script.hpp index 4caf58e..171f8a3 100644 --- a/src/map/script.hpp +++ b/src/map/script.hpp @@ -2,43 +2,105 @@ #define SCRIPT_HPP #include <cstdint> +#include <cstring> // for inlined get_str - TODO remove #include <string> +#include <vector> #include "../common/db.hpp" +#include "../common/dumb_ptr.hpp" -enum class ScriptCode : uint8_t; +enum class ByteCode : uint8_t; +struct str_data_t; + +class ScriptBuffer +{ + std::vector<ByteCode> script_buf; +public: + // construction methods used only by script.cpp + void add_scriptc(ByteCode a); + void add_scriptb(uint8_t a); + void add_scripti(uint32_t a); + void add_scriptl(str_data_t *a); + void set_label(str_data_t *ld, int pos_); + const char *parse_simpleexpr(const char *p); + const char *parse_subexpr(const char *p, int limit); + const char *parse_expr(const char *p); + const char *parse_line(const char *p); + void parse_script(const char *src, int line); + + // consumption methods used only by script.cpp + ByteCode operator[](size_t i) const { return script_buf[i]; } + const char *get_str(size_t i) const + { + return reinterpret_cast<const char *>(&script_buf[i]); + } + + // method used elsewhere +}; + +struct ScriptPointer +{ + const ScriptBuffer *code; + size_t pos; + + ScriptPointer() + : code() + , pos() + {} + + ScriptPointer(const ScriptBuffer *c, size_t p) + : code(c) + , pos(p) + {} + + ByteCode peek() const { return (*code)[pos]; } + ByteCode pop() { return (*code)[pos++]; } + const char *pops() + { + const char *rv = code->get_str(pos); + pos += strlen(rv); + return rv; + } +}; struct script_data { - ScriptCode type; - union + ByteCode type; + union uu { int num; - const char *str; - const ScriptCode *script; + dumb_string str; + // Not a ScriptPointer - pos is stored in a separate slot, + // to avoid exploding the struct for everyone. + const ScriptBuffer *script; + + uu() { memset(this, '\0', sizeof(*this)); } + ~uu() = default; + uu(const uu&) = default; + uu& operator = (const uu&) = default; } u; }; struct script_stack { - int sp, sp_max; - struct script_data *stack_data; + std::vector<struct script_data> stack_datav; }; +enum class ScriptEndState; // future improvements coming! class ScriptState { public: struct script_stack *stack; int start, end; - int pos, state; + ScriptEndState state; int rid, oid; - const ScriptCode *script, *new_script; - int defsp, new_pos, new_defsp; + ScriptPointer scriptp, new_scriptp; + int defsp, new_defsp; }; -const ScriptCode *parse_script(const char *, int); +std::unique_ptr<const ScriptBuffer> parse_script(const char *, int); typedef struct argrec { const char *name; @@ -52,13 +114,13 @@ typedef struct argrec _aru(const char *z) : s(z) {} } v; } argrec_t; -int run_script_l(const ScriptCode *, int, int, int, int, argrec_t *args); -int run_script(const ScriptCode *, int, int, int); +int run_script_l(ScriptPointer, int, int, int, argrec_t *args); +int run_script(ScriptPointer, int, int); extern Map<std::string, int> scriptlabel_db; extern -DMap<std::string, const ScriptCode *> userfunc_db; +UPMap<std::string, const ScriptBuffer> userfunc_db; void script_config_read(); void do_init_script(void); diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 4f71f06..4e195be 100644 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -427,8 +427,10 @@ int skill_castend_damage_id(dumb_ptr<block_list> src, dumb_ptr<block_list> bl, skill_area_temp_hp = battle_get_hp(src); map_foreachinarea(std::bind(skill_area_sub, ph::_1, src, skillid, skilllv, tick, flag | BCT_ENEMY | BCT_lo_x01, skill_castend_damage_id), - bl->bl_m, bl->bl_x - 5, bl->bl_y - 5, - bl->bl_x + 5, bl->bl_y + 5, BL::NUL); + bl->bl_m, + bl->bl_x - 5, bl->bl_y - 5, + bl->bl_x + 5, bl->bl_y + 5, + BL::NUL); battle_damage(src, src, md->hp, 0); } } @@ -450,8 +452,10 @@ int skill_castend_damage_id(dumb_ptr<block_list> src, dumb_ptr<block_list> bl, skill_area_temp_id = bl->bl_id; map_foreachinarea(std::bind(skill_area_sub, ph::_1, src, skillid, skilllv, tick, flag | BCT_ENEMY | BCT_lo_x01, skill_castend_damage_id), - bl->bl_m, bl->bl_x - 0, bl->bl_y - 0, - bl->bl_x + 0, bl->bl_y + 0, BL::NUL); + bl->bl_m, + bl->bl_x - 0, bl->bl_y - 0, + bl->bl_x + 0, bl->bl_y + 0, + BL::NUL); } } break; @@ -1342,18 +1346,14 @@ int skill_readdb(void) skill_db[i].stat = scan_stat(split[16]); - char *tmp = strdup(split[17]); - { - // replace "_" by " " - char *s = tmp; - while ((s = strchr(s, '_'))) - *s = ' '; - if ((s = strchr(tmp, '\t')) - || (s = strchr(tmp, ' ')) - || (s = strchr(tmp, '\n'))) - *s = '\000'; - } - skill_lookup_by_id(i).desc = tmp; + std::string tmp = split[17]; + size_t space = tmp.find_first_of(" \t\n"); + if (space != std::string::npos) + tmp.resize(space); + for (char& c : tmp) + if (c == '_') + c = ' '; + skill_lookup_by_id(i).desc = std::move(tmp); } fclose_(fp); PRINTF("read db/skill_db.txt done\n"); @@ -1397,7 +1397,7 @@ skill_name_db& skill_lookup_by_id(SkillID id) skill_name_db& skill_lookup_by_name(const char *name) { for (skill_name_db& ner : skill_names) - if (!strcasecmp(name, ner.name) || !strcasecmp(name, ner.desc)) + if (!strcasecmp(name, ner.name.c_str()) || !strcasecmp(name, ner.desc.c_str())) return ner; return skill_names[num_names - 1]; } diff --git a/src/map/skill.hpp b/src/map/skill.hpp index ec354e2..42caf0b 100644 --- a/src/map/skill.hpp +++ b/src/map/skill.hpp @@ -33,8 +33,8 @@ extern earray<struct skill_db, SkillID, SkillID::MAX_SKILL_DB> skill_db; struct skill_name_db { SkillID id; // skill id - const char *name; // search strings - const char *desc; // description that shows up for search's + std::string name; // search strings + std::string desc; // description that shows up for searches }; // used only by @skillid for iteration - should be depublicized @@ -122,7 +122,7 @@ bool skill_pool_is_activated(dumb_ptr<map_session_data> sd, SkillID skill); int skill_pool_deactivate(dumb_ptr<map_session_data> sd, SkillID skill); // Yield configurable skill name inline -const char *skill_name(SkillID skill) +const std::string& skill_name(SkillID skill) { return skill_lookup_by_id(skill).desc; } diff --git a/src/map/storage.cpp b/src/map/storage.cpp index 463dd7c..5145b80 100644 --- a/src/map/storage.cpp +++ b/src/map/storage.cpp @@ -21,33 +21,6 @@ static Map<int, struct storage> storage_db; -/*========================================== - * 倉庫内アイテムソート - *------------------------------------------ - */ -static -int storage_comp_item(const void *_i1, const void *_i2) -{ - const struct item *i1 = (const struct item *) _i1; - const struct item *i2 = (const struct item *) _i2; - - if (i1->nameid == i2->nameid) - return 0; - else if (!(i1->nameid) || !(i1->amount)) - return 1; - else if (!(i2->nameid) || !(i2->amount)) - return -1; - return i1->nameid - i2->nameid; -} - -static -void sortage_sortitem(struct storage *stor) -{ - nullpo_retv(stor); - qsort(stor->storage_, MAX_STORAGE, sizeof(struct item), - storage_comp_item); -} - void do_init_storage(void) { } @@ -328,14 +301,15 @@ int storage_storage_save(int account_id, int final) //Ack from Char-server indicating the storage was saved. [Skotlex] int storage_storage_saved(int account_id) { - struct storage *stor; + struct storage *stor = account2storage2(account_id); - if ((stor = account2storage2(account_id)) != NULL) - { //Only mark it clean if it's not in use. [Skotlex] + if (stor) + { + //Only mark it clean if it's not in use. [Skotlex] if (stor->dirty && stor->storage_status == 0) { stor->dirty = 0; - sortage_sortitem(stor); + // sortage_sortitem(stor); } return 1; } diff --git a/src/map/tmw.cpp b/src/map/tmw.cpp index 9740ad8..955ea74 100644 --- a/src/map/tmw.cpp +++ b/src/map/tmw.cpp @@ -63,7 +63,7 @@ int tmw_CheckChatSpam(dumb_ptr<map_session_data> sd, const char *message) if (tmw_CheckChatLameness(sd, message)) sd->chat_lines_in += battle_config.chat_lame_penalty; - strncpy((char *) sd->chat_lastmsg, message, battle_config.chat_maxline); + strncpy(sd->chat_lastmsg, message, battle_config.chat_maxline); if (sd->chat_lines_in >= battle_config.chat_spam_flood || sd->chat_total_repeats >= battle_config.chat_spam_flood) diff --git a/src/map/trade.cpp b/src/map/trade.cpp index ff54caa..c0f8c46 100644 --- a/src/map/trade.cpp +++ b/src/map/trade.cpp @@ -108,7 +108,7 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, int index, int amount) struct item_data *id; int trade_i; int trade_weight = 0; - int free = 0; + int free_ = 0; int c; int i; @@ -133,7 +133,7 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, int index, int amount) { if (target_sd->status.inventory[i].nameid == 0 && target_sd->inventory_data[i] == NULL) - free++; + free_++; } for (trade_i = 0; trade_i < 10; trade_i++) { @@ -156,7 +156,7 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, int index, int amount) && id->type != ItemType::_7 && id->type != ItemType::_8) { - free++; + free_++; break; } } @@ -167,7 +167,7 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, int index, int amount) { clif_tradeitemok(sd, index, 0, 1); //fail to add item -- the player was over weighted. } - else if (free <= 0) + else if (free_ <= 0) { clif_tradeitemok(sd, index, 0, 2); //fail to add item -- no free slots at receiver } @@ -210,14 +210,14 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, int index, int amount) && id->type != ItemType::_7 && id->type != ItemType::_8) { - free++; + free_++; break; } } } } // used a slot, but might be cancelled out by stackable checks above - free--; + free_--; } } } |