mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 14:41:28 +00:00
[Bots] Save Bot Toggle Archer Setting between Loads. (#2612)
* [Bots] Save Bot Toggle Archer Setting between Loads. * [Bots] Save Bot Toggle Archer Setting between Loads. * Typo
This commit is contained in:
parent
7abc084cd1
commit
7e0fe93039
@ -68,6 +68,7 @@ public:
|
|||||||
uint8_t stop_melee_level;
|
uint8_t stop_melee_level;
|
||||||
int32_t expansion_bitmask;
|
int32_t expansion_bitmask;
|
||||||
uint8_t enforce_spell_settings;
|
uint8_t enforce_spell_settings;
|
||||||
|
uint8_t archery_setting;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string PrimaryKey()
|
static std::string PrimaryKey()
|
||||||
@ -127,6 +128,7 @@ public:
|
|||||||
"stop_melee_level",
|
"stop_melee_level",
|
||||||
"expansion_bitmask",
|
"expansion_bitmask",
|
||||||
"enforce_spell_settings",
|
"enforce_spell_settings",
|
||||||
|
"archery_setting",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,6 +184,7 @@ public:
|
|||||||
"stop_melee_level",
|
"stop_melee_level",
|
||||||
"expansion_bitmask",
|
"expansion_bitmask",
|
||||||
"enforce_spell_settings",
|
"enforce_spell_settings",
|
||||||
|
"archery_setting",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,6 +274,7 @@ public:
|
|||||||
e.stop_melee_level = 255;
|
e.stop_melee_level = 255;
|
||||||
e.expansion_bitmask = -1;
|
e.expansion_bitmask = -1;
|
||||||
e.enforce_spell_settings = 0;
|
e.enforce_spell_settings = 0;
|
||||||
|
e.archery_setting = 0;
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@ -355,6 +359,7 @@ public:
|
|||||||
e.stop_melee_level = static_cast<uint8_t>(strtoul(row[46], nullptr, 10));
|
e.stop_melee_level = static_cast<uint8_t>(strtoul(row[46], nullptr, 10));
|
||||||
e.expansion_bitmask = static_cast<int32_t>(atoi(row[47]));
|
e.expansion_bitmask = static_cast<int32_t>(atoi(row[47]));
|
||||||
e.enforce_spell_settings = static_cast<uint8_t>(strtoul(row[48], nullptr, 10));
|
e.enforce_spell_settings = static_cast<uint8_t>(strtoul(row[48], nullptr, 10));
|
||||||
|
e.archery_setting = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@ -436,6 +441,7 @@ public:
|
|||||||
v.push_back(columns[46] + " = " + std::to_string(e.stop_melee_level));
|
v.push_back(columns[46] + " = " + std::to_string(e.stop_melee_level));
|
||||||
v.push_back(columns[47] + " = " + std::to_string(e.expansion_bitmask));
|
v.push_back(columns[47] + " = " + std::to_string(e.expansion_bitmask));
|
||||||
v.push_back(columns[48] + " = " + std::to_string(e.enforce_spell_settings));
|
v.push_back(columns[48] + " = " + std::to_string(e.enforce_spell_settings));
|
||||||
|
v.push_back(columns[49] + " = " + std::to_string(e.archery_setting));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@ -506,6 +512,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.stop_melee_level));
|
v.push_back(std::to_string(e.stop_melee_level));
|
||||||
v.push_back(std::to_string(e.expansion_bitmask));
|
v.push_back(std::to_string(e.expansion_bitmask));
|
||||||
v.push_back(std::to_string(e.enforce_spell_settings));
|
v.push_back(std::to_string(e.enforce_spell_settings));
|
||||||
|
v.push_back(std::to_string(e.archery_setting));
|
||||||
|
|
||||||
auto results = db.QueryDatabase(
|
auto results = db.QueryDatabase(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@ -584,6 +591,7 @@ public:
|
|||||||
v.push_back(std::to_string(e.stop_melee_level));
|
v.push_back(std::to_string(e.stop_melee_level));
|
||||||
v.push_back(std::to_string(e.expansion_bitmask));
|
v.push_back(std::to_string(e.expansion_bitmask));
|
||||||
v.push_back(std::to_string(e.enforce_spell_settings));
|
v.push_back(std::to_string(e.enforce_spell_settings));
|
||||||
|
v.push_back(std::to_string(e.archery_setting));
|
||||||
|
|
||||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||||
}
|
}
|
||||||
@ -666,6 +674,7 @@ public:
|
|||||||
e.stop_melee_level = static_cast<uint8_t>(strtoul(row[46], nullptr, 10));
|
e.stop_melee_level = static_cast<uint8_t>(strtoul(row[46], nullptr, 10));
|
||||||
e.expansion_bitmask = static_cast<int32_t>(atoi(row[47]));
|
e.expansion_bitmask = static_cast<int32_t>(atoi(row[47]));
|
||||||
e.enforce_spell_settings = static_cast<uint8_t>(strtoul(row[48], nullptr, 10));
|
e.enforce_spell_settings = static_cast<uint8_t>(strtoul(row[48], nullptr, 10));
|
||||||
|
e.archery_setting = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
@ -739,6 +748,7 @@ public:
|
|||||||
e.stop_melee_level = static_cast<uint8_t>(strtoul(row[46], nullptr, 10));
|
e.stop_melee_level = static_cast<uint8_t>(strtoul(row[46], nullptr, 10));
|
||||||
e.expansion_bitmask = static_cast<int32_t>(atoi(row[47]));
|
e.expansion_bitmask = static_cast<int32_t>(atoi(row[47]));
|
||||||
e.enforce_spell_settings = static_cast<uint8_t>(strtoul(row[48], nullptr, 10));
|
e.enforce_spell_settings = static_cast<uint8_t>(strtoul(row[48], nullptr, 10));
|
||||||
|
e.archery_setting = static_cast<uint8_t>(strtoul(row[49], nullptr, 10));
|
||||||
|
|
||||||
all_entries.push_back(e);
|
all_entries.push_back(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@
|
|||||||
#define CURRENT_BINARY_DATABASE_VERSION 9212
|
#define CURRENT_BINARY_DATABASE_VERSION 9212
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9034
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9035
|
||||||
#else
|
#else
|
||||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
|
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -33,6 +33,7 @@
|
|||||||
9032|2022_11_07_bot_expansion_bitmask.sql|SHOW COLUMNS FROM `bot_data` LIKE 'expansion_bitmask'|empty|
|
9032|2022_11_07_bot_expansion_bitmask.sql|SHOW COLUMNS FROM `bot_data` LIKE 'expansion_bitmask'|empty|
|
||||||
9033|2022_11_19_bot_spell_settings.sql|SHOW TABLES LIKE 'bot_spell_settings'|empty|
|
9033|2022_11_19_bot_spell_settings.sql|SHOW TABLES LIKE 'bot_spell_settings'|empty|
|
||||||
9034|2022_12_02_bot_spell_settings.sql|SHOW COLUMNS FROM `bot_data` LIKE 'enforce_spell_settings'|empty|
|
9034|2022_12_02_bot_spell_settings.sql|SHOW COLUMNS FROM `bot_data` LIKE 'enforce_spell_settings'|empty|
|
||||||
|
9035|2022_12_04_bot_archery.sql|SHOW COLUMNS FROM `bot_data` LIKE 'archery_setting'|empty|
|
||||||
|
|
||||||
# Upgrade conditions:
|
# Upgrade conditions:
|
||||||
# This won't be needed after this system is implemented, but it is used database that are not
|
# This won't be needed after this system is implemented, but it is used database that are not
|
||||||
|
|||||||
2
utils/sql/git/bots/required/2022_12_04_bot_archery.sql
Normal file
2
utils/sql/git/bots/required/2022_12_04_bot_archery.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE `bot_data`
|
||||||
|
ADD COLUMN `archery_setting` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0' AFTER `enforce_spell_settings`;
|
||||||
24
zone/bot.cpp
24
zone/bot.cpp
@ -72,7 +72,6 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm
|
|||||||
SetBotID(0);
|
SetBotID(0);
|
||||||
SetBotSpellID(0);
|
SetBotSpellID(0);
|
||||||
SetSpawnStatus(false);
|
SetSpawnStatus(false);
|
||||||
SetBotArcher(false);
|
|
||||||
SetBotCharmer(false);
|
SetBotCharmer(false);
|
||||||
SetPetChooser(false);
|
SetPetChooser(false);
|
||||||
SetRangerAutoWeaponSelect(false);
|
SetRangerAutoWeaponSelect(false);
|
||||||
@ -167,7 +166,6 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
|||||||
SetBotID(botID);
|
SetBotID(botID);
|
||||||
SetBotSpellID(botSpellsID);
|
SetBotSpellID(botSpellsID);
|
||||||
SetSpawnStatus(false);
|
SetSpawnStatus(false);
|
||||||
SetBotArcher(false);
|
|
||||||
SetBotCharmer(false);
|
SetBotCharmer(false);
|
||||||
SetPetChooser(false);
|
SetPetChooser(false);
|
||||||
SetRangerAutoWeaponSelect(false);
|
SetRangerAutoWeaponSelect(false);
|
||||||
@ -3164,12 +3162,12 @@ void Bot::AI_Process()
|
|||||||
|
|
||||||
if (atArcheryRange && !IsBotArcher()) {
|
if (atArcheryRange && !IsBotArcher()) {
|
||||||
|
|
||||||
SetBotArcher(true);
|
SetBotArcherySetting(true);
|
||||||
changeWeapons = true;
|
changeWeapons = true;
|
||||||
}
|
}
|
||||||
else if (!atArcheryRange && IsBotArcher()) {
|
else if (!atArcheryRange && IsBotArcher()) {
|
||||||
|
|
||||||
SetBotArcher(false);
|
SetBotArcherySetting(false);
|
||||||
changeWeapons = true;
|
changeWeapons = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10867,6 +10865,24 @@ std::string Bot::GetHPString(int8 min_hp, int8 max_hp)
|
|||||||
return hp_string;
|
return hp_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bot::SetBotArcherySetting(bool bot_archer_setting, bool save)
|
||||||
|
{
|
||||||
|
m_bot_archery_setting = bot_archer_setting;
|
||||||
|
if (save) {
|
||||||
|
if (!database.botdb.SaveBotArcherSetting(GetBotID(), bot_archer_setting)) {
|
||||||
|
if (GetBotOwner() && GetBotOwner()->IsClient()) {
|
||||||
|
GetBotOwner()->CastToClient()->Message(
|
||||||
|
Chat::White,
|
||||||
|
fmt::format(
|
||||||
|
"Failed to save archery settings for {}.",
|
||||||
|
GetCleanName()
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8 Bot::spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND] = { 0 };
|
uint8 Bot::spell_casting_chances[SPELL_TYPE_COUNT][PLAYER_CLASS_COUNT][EQ::constants::STANCE_TYPE_COUNT][cntHSND] = { 0 };
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -468,7 +468,7 @@ public:
|
|||||||
virtual bool GetSpawnStatus() { return _spawnStatus; }
|
virtual bool GetSpawnStatus() { return _spawnStatus; }
|
||||||
uint8 GetPetChooserID() { return _petChooserID; }
|
uint8 GetPetChooserID() { return _petChooserID; }
|
||||||
bool IsPetChooser() { return _petChooser; }
|
bool IsPetChooser() { return _petChooser; }
|
||||||
bool IsBotArcher() { return _botArcher; }
|
bool IsBotArcher() { return m_bot_archery_setting; }
|
||||||
bool IsBotCharmer() { return _botCharmer; }
|
bool IsBotCharmer() { return _botCharmer; }
|
||||||
virtual bool IsBot() const { return true; }
|
virtual bool IsBot() const { return true; }
|
||||||
bool GetRangerAutoWeaponSelect() { return _rangerAutoWeaponSelect; }
|
bool GetRangerAutoWeaponSelect() { return _rangerAutoWeaponSelect; }
|
||||||
@ -586,7 +586,7 @@ public:
|
|||||||
void SetBotSpellID(uint32 newSpellID);
|
void SetBotSpellID(uint32 newSpellID);
|
||||||
virtual void SetSpawnStatus(bool spawnStatus) { _spawnStatus = spawnStatus; }
|
virtual void SetSpawnStatus(bool spawnStatus) { _spawnStatus = spawnStatus; }
|
||||||
void SetPetChooserID(uint8 id) { _petChooserID = id; }
|
void SetPetChooserID(uint8 id) { _petChooserID = id; }
|
||||||
void SetBotArcher(bool a) { _botArcher = a; }
|
void SetBotArcherySetting(bool bot_archer_setting, bool save = false);
|
||||||
void SetBotCharmer(bool c) { _botCharmer = c; }
|
void SetBotCharmer(bool c) { _botCharmer = c; }
|
||||||
void SetPetChooser(bool p) { _petChooser = p; }
|
void SetPetChooser(bool p) { _petChooser = p; }
|
||||||
void SetBotOwner(Mob* botOwner) { this->_botOwner = botOwner; }
|
void SetBotOwner(Mob* botOwner) { this->_botOwner = botOwner; }
|
||||||
@ -753,7 +753,7 @@ private:
|
|||||||
bool _spawnStatus;
|
bool _spawnStatus;
|
||||||
Mob* _botOwner;
|
Mob* _botOwner;
|
||||||
bool _botOrderAttack;
|
bool _botOrderAttack;
|
||||||
bool _botArcher;
|
bool m_bot_archery_setting;
|
||||||
bool _botCharmer;
|
bool _botCharmer;
|
||||||
bool _petChooser;
|
bool _petChooser;
|
||||||
uint8 _petChooserID;
|
uint8 _petChooserID;
|
||||||
|
|||||||
@ -6942,8 +6942,9 @@ void bot_subcommand_bot_tattoo(Client *c, const Seperator *sep)
|
|||||||
|
|
||||||
void bot_subcommand_bot_toggle_archer(Client *c, const Seperator *sep)
|
void bot_subcommand_bot_toggle_archer(Client *c, const Seperator *sep)
|
||||||
{
|
{
|
||||||
if (helper_command_alias_fail(c, "bot_subcommand_bot_toggle_archer", sep->arg[0], "bottogglearcher"))
|
if (helper_command_alias_fail(c, "bot_subcommand_bot_toggle_archer", sep->arg[0], "bottogglearcher")) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (helper_is_help_or_usage(sep->arg[1])) {
|
if (helper_is_help_or_usage(sep->arg[1])) {
|
||||||
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname] ([actionable_name]))", sep->arg[0]);
|
c->Message(Chat::White, "usage: %s ([option: on | off]) ([actionable: target | byname] ([actionable_name]))", sep->arg[0]);
|
||||||
return;
|
return;
|
||||||
@ -6966,21 +6967,26 @@ void bot_subcommand_bot_toggle_archer(Client *c, const Seperator *sep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::list<Bot*> sbl;
|
std::list<Bot*> sbl;
|
||||||
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None)
|
if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto bot_iter : sbl) {
|
for (auto bot_iter : sbl) {
|
||||||
if (!bot_iter)
|
if (!bot_iter) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (toggle_archer)
|
if (toggle_archer) {
|
||||||
bot_iter->SetBotArcher(!bot_iter->IsBotArcher());
|
bot_iter->SetBotArcherySetting(!bot_iter->IsBotArcher(), true);
|
||||||
else
|
}
|
||||||
bot_iter->SetBotArcher(archer_state);
|
else {
|
||||||
|
bot_iter->SetBotArcherySetting(archer_state, true);
|
||||||
|
}
|
||||||
bot_iter->ChangeBotArcherWeapons(bot_iter->IsBotArcher());
|
bot_iter->ChangeBotArcherWeapons(bot_iter->IsBotArcher());
|
||||||
|
|
||||||
if (bot_iter->GetClass() == RANGER && bot_iter->GetLevel() >= 61)
|
if (bot_iter->GetClass() == RANGER && bot_iter->GetLevel() >= 61) {
|
||||||
bot_iter->SetRangerAutoWeaponSelect(bot_iter->IsBotArcher());
|
bot_iter->SetRangerAutoWeaponSelect(bot_iter->IsBotArcher());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9368,11 +9374,9 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep)
|
|||||||
c->PushItemOnCursor(*inst, true);
|
c->PushItemOnCursor(*inst, true);
|
||||||
if (
|
if (
|
||||||
slot_id == EQ::invslot::slotRange ||
|
slot_id == EQ::invslot::slotRange ||
|
||||||
slot_id == EQ::invslot::slotAmmo ||
|
slot_id == EQ::invslot::slotAmmo
|
||||||
slot_id == EQ::invslot::slotPrimary ||
|
|
||||||
slot_id == EQ::invslot::slotSecondary
|
|
||||||
) {
|
) {
|
||||||
my_bot->SetBotArcher(false);
|
my_bot->SetBotArcherySetting(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
my_bot->RemoveBotItemBySlot(slot_id, &error_message);
|
my_bot->RemoveBotItemBySlot(slot_id, &error_message);
|
||||||
|
|||||||
@ -410,7 +410,8 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot)
|
|||||||
" `follow_distance`," // 26
|
" `follow_distance`," // 26
|
||||||
" `stop_melee_level`," // 27
|
" `stop_melee_level`," // 27
|
||||||
" `expansion_bitmask`," // 28
|
" `expansion_bitmask`," // 28
|
||||||
" `enforce_spell_settings`" // 29
|
" `enforce_spell_settings`," // 29
|
||||||
|
" `archery_setting`" // 30
|
||||||
" FROM `bot_data`"
|
" FROM `bot_data`"
|
||||||
" WHERE `bot_id` = {}"
|
" WHERE `bot_id` = {}"
|
||||||
" LIMIT 1",
|
" LIMIT 1",
|
||||||
@ -511,6 +512,8 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot)
|
|||||||
loaded_bot->SetExpansionBitmask(eb, false);
|
loaded_bot->SetExpansionBitmask(eb, false);
|
||||||
|
|
||||||
loaded_bot->SetBotEnforceSpellSetting((std::stoi(row[29]) > 0 ? true : false));
|
loaded_bot->SetBotEnforceSpellSetting((std::stoi(row[29]) > 0 ? true : false));
|
||||||
|
|
||||||
|
loaded_bot->SetBotArcherySetting((std::stoi(row[30]) > 0 ? true : false));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -3302,6 +3305,27 @@ bool BotDatabase::SaveEnforceSpellSetting(const uint32 bot_id, const bool enforc
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BotDatabase::SaveBotArcherSetting(const uint32 bot_id, const bool bot_archer_setting)
|
||||||
|
{
|
||||||
|
if (!bot_id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
query = fmt::format(
|
||||||
|
"UPDATE `bot_data`"
|
||||||
|
"SET `archery_setting` = {} "
|
||||||
|
"WHERE `bot_id` = {}",
|
||||||
|
(bot_archer_setting ? 1 : 0),
|
||||||
|
bot_id
|
||||||
|
);
|
||||||
|
auto results = database.QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* fail::Bot functions */
|
/* fail::Bot functions */
|
||||||
const char* BotDatabase::fail::LoadBotsList() { return "Failed to bots list"; }
|
const char* BotDatabase::fail::LoadBotsList() { return "Failed to bots list"; }
|
||||||
const char* BotDatabase::fail::LoadOwnerID() { return "Failed to load owner ID"; }
|
const char* BotDatabase::fail::LoadOwnerID() { return "Failed to load owner ID"; }
|
||||||
|
|||||||
@ -144,6 +144,8 @@ public:
|
|||||||
|
|
||||||
bool SaveStopMeleeLevel(const uint32 owner_id, const uint32 bot_id, const uint8 sml_value);
|
bool SaveStopMeleeLevel(const uint32 owner_id, const uint32 bot_id, const uint8 sml_value);
|
||||||
|
|
||||||
|
bool SaveBotArcherSetting(const uint32 bot_id, const bool bot_archer_setting);
|
||||||
|
|
||||||
bool LoadOwnerOptions(Client *owner);
|
bool LoadOwnerOptions(Client *owner);
|
||||||
bool SaveOwnerOption(const uint32 owner_id, size_t type, const bool flag);
|
bool SaveOwnerOption(const uint32 owner_id, size_t type, const bool flag);
|
||||||
bool SaveOwnerOption(const uint32 owner_id, const std::pair<size_t, size_t> type, const std::pair<bool, bool> flag);
|
bool SaveOwnerOption(const uint32 owner_id, const std::pair<size_t, size_t> type, const std::pair<bool, bool> flag);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user