@ -41,6 +41,7 @@
# include "char_creation_helpers.hpp"
# include "char_creation_helpers.hpp"
# include "helper_skills.hpp"
# include "helper_skills.hpp"
# include "helper_inventory.hpp"
using namespace rathena ;
using namespace rathena ;
using namespace rathena : : server_brokk ;
using namespace rathena : : server_brokk ;
@ -54,11 +55,13 @@ AccountDB* login_accounts = nullptr;
BotAccountDB * bot_accounts = nullptr ;
BotAccountDB * bot_accounts = nullptr ;
CharDB * charakters = nullptr ;
CharDB * charakters = nullptr ;
SkillDB * skills = nullptr ;
SkillDB * skills = nullptr ;
InventoryDB * inventory = nullptr ;
// YAML DB Objects of all touched infrastucture
// YAML DB Objects of all touched infrastucture
BotStatPointDatabase bot_statpoint_db ;
BotStatPointDatabase bot_statpoint_db ;
BotJobDatabase bot_job_db ;
BotJobDatabase bot_job_db ;
//BotSkillTreeDatabase bot_skill_tree_db;
//BotSkillTreeDatabase bot_skill_tree_db;
//BotItemDatabase bot_item_db;
// Advanced subnet check [LuzZza]
// Advanced subnet check [LuzZza]
struct s_subnet {
struct s_subnet {
@ -166,7 +169,7 @@ int brokk_mmo_auth_new(const char* userid, const char* pass, const char sex, con
// Check if the bot account already exists
// Check if the bot account already exists
if ( bot_accounts - > load_num ( bot_accounts , & bot_acc , acc . account_id ) ) {
if ( bot_accounts - > load_num ( bot_accounts , & bot_acc , acc . account_id ) ) {
Show Notice ( " Attempt to create an already existing bot account (account: %s, sex: %c) \n " , acc . account_id , sex ) ;
Show Warning ( " Attempt to create an already existing bot account (account: %s, sex: %c) . Skipping... \n " , acc . account_id , sex ) ;
return 1 ; // Account exists
return 1 ; // Account exists
}
}
@ -185,7 +188,7 @@ int brokk_mmo_auth_new(const char* userid, const char* pass, const char sex, con
if ( ! bot_accounts - > create ( bot_accounts , & bot_acc ) )
if ( ! bot_accounts - > create ( bot_accounts , & bot_acc ) )
return 0 ; // Account creation failed
return 0 ; // Account creation failed
Show Notice ( " Bot account creation successful (account %s, id: %d, sex: %c) \n " , acc . userid , acc . account_id , acc . sex ) ;
Show Status ( " Bot account creation successful (account %s, id: %d, sex: %c) \n " , acc . userid , acc . account_id , acc . sex ) ;
// Registration rate limit logic
// Registration rate limit logic
if ( DIFF_TICK ( tick , new_reg_tick ) > 0 ) {
if ( DIFF_TICK ( tick , new_reg_tick ) > 0 ) {
@ -248,8 +251,10 @@ int brokk_mmo_auth_delete_num(uint32 account_id) {
struct mmo_bot_account bot_acc ;
struct mmo_bot_account bot_acc ;
struct mmo_charakter charakter ;
struct mmo_charakter charakter ;
struct bot_skill skill ;
struct bot_skill skill ;
struct bot_inv_item item ;
std : : vector < uint32 > char_ids_to_delete ;
std : : vector < uint32 > char_ids_to_delete ;
std : : vector < bot_skill > skills_to_delete ;
std : : vector < bot_skill > skills_to_delete ;
std : : vector < bot_inv_item > items_to_delete ;
// Check if the account exists
// Check if the account exists
if ( ! login_accounts - > load_num ( login_accounts , & acc , account_id ) ) {
if ( ! login_accounts - > load_num ( login_accounts , & acc , account_id ) ) {
@ -289,17 +294,15 @@ int brokk_mmo_auth_delete_num(uint32 account_id) {
}
}
}
}
iter_chars - > destroy ( iter_chars ) ; // Destroy the iterator after use
iter_chars - > destroy ( iter_chars ) ; // Destroy the iterator after use
ShowDebug ( " DelMarco \n " ) ;
// Second pass: Delete the collected charakters
// Second pass: Delete the collected charakters
for ( const auto & char_id : char_ids_to_delete ) {
for ( const auto & char_id : char_ids_to_delete ) {
ShowDebug ( " DelPolo1 \n " ) ;
ShowInfo ( " Deleting charakter with ID %d. \n " , char_id ) ;
ShowInfo ( " Deleting charakter with ID %d. \n " , char_id ) ;
if ( ! charakters - > remove ( charakters , char_id ) ) {
if ( ! charakters - > remove ( charakters , char_id ) ) {
ShowError ( " Failed to delete charakter (char_id: %s) \n " , char_id ) ;
ShowError ( " Failed to delete charakter (char_id: %s) \n " , char_id ) ;
continue ; // Deletion failed
continue ; // Deletion failed
}
}
ShowDebug ( " DelPolo2 \n " ) ;
// Step 3B: Attempt to delete skills of the char (if any)
// Step 3B: Attempt to delete skills of the char (if any)
// First pass: Collect skill_ids to delete based on config
// First pass: Collect skill_ids to delete based on config
SkillDBIterator * iter_skills = skills - > iterator ( skills , char_id ) ; // Create the iterator
SkillDBIterator * iter_skills = skills - > iterator ( skills , char_id ) ; // Create the iterator
@ -309,19 +312,48 @@ int brokk_mmo_auth_delete_num(uint32 account_id) {
skills_to_delete . push_back ( skill ) ;
skills_to_delete . push_back ( skill ) ;
}
}
iter_skills - > destroy ( iter_skills ) ; // Destroy the iterator after use
iter_skills - > destroy ( iter_skills ) ; // Destroy the iterator after use
ShowDebug ( " DelPolo3 \n " ) ;
// Second pass: Delete the collected skills
// Second pass: Delete the collected skills
for ( const auto & skill_entry : skills_to_delete ) {
int skill_count = 0 ;
for ( const auto & skill_entry : skills_to_delete ) {
//ShowInfo("Deleting skill with ID %d.\n", char_id);
//ShowInfo("Deleting skill with ID %d.\n", char_id);
if ( ! skills - > remove ( skills , char_id , skill_entry . skill_id ) ) {
if ( ! skills - > remove ( skills , char_id , skill_entry . skill_id ) ) {
ShowError ( " Failed to delete skill (skill_id: %s) \n " , skill_entry . skill_id ) ;
ShowError ( " Failed to delete skill (skill_id: %s) \n " , skill_entry . skill_id ) ;
continue ; // Deletion failed
continue ; // Deletion failed
}
}
else {
else {
ShowNotice ( " Deleting of skill %s from char_id %d was successful \n " , convert_skill_id_to_str ( skill_entry . skill_id ) , char_id ) ;
//ShowNotice("Deleting of skill %s from char_id %d was successful\n", convert_skill_id_to_str(skill_entry.skill_id), char_id);
skill_count + + ;
}
}
}
}
ShowDebug ( " DelPolo4 \n " ) ;
ShowNotice ( " Skill cleanup for char_id %d completed. %d skills cleaned. \n " , char_id , skill_count ) ;
ShowDebug ( " Marco \n " ) ; //TODO Prüfn warum hier iterator keine validen items wirft
// Step 3C: Attempt to delete inventory of the char (if any)
// First pass: Collect inv_item_ids to delete based on config
InventoryDBIterator * iter_inventory = inventory - > iterator ( inventory , char_id ) ; // Create the iterator
ShowDebug ( " Polo1 \n " ) ;
while ( iter_inventory - > next ( iter_inventory , char_id , & item ) ) {
ShowDebug ( " Polo iter loop \n " ) ;
std : : string id_str = convert_item_id_to_name ( item . item_id ) ;
ShowDebug ( " Item %s found. Schedule for deletion... \n " , id_str . c_str ( ) ) ;
items_to_delete . push_back ( item ) ;
}
iter_inventory - > destroy ( iter_inventory ) ; // Destroy the iterator after use
ShowDebug ( " Polo2 \n " ) ;
// Second pass: Delete the collected items
for ( const auto & inv_item_entry : items_to_delete ) {
ShowInfo ( " Deleting item with ID %d. \n " , inv_item_entry . inventory_id ) ;
if ( ! inventory - > remove ( inventory , char_id , inv_item_entry . inventory_id ) ) {
ShowError ( " Failed to delete item (item_id: %s) \n " , inv_item_entry . item_id ) ;
continue ; // Deletion failed
}
else {
ShowNotice ( " Deleting of item %s from char_id %d was successful \n " , convert_item_id_to_aegisname ( inv_item_entry . item_id ) , char_id ) ;
}
}
ShowDebug ( " Polo3 \n " ) ;
}
}
ShowNotice ( " Bot account deletion completed (account: %s, id: %d) \n \n " , acc . userid , acc . account_id ) ;
ShowNotice ( " Bot account deletion completed (account: %s, id: %d) \n \n " , acc . userid , acc . account_id ) ;
@ -563,6 +595,18 @@ bool brokk_initialize_dbs()
}
}
}
}
// Inventory database init (inventory table)
if ( inventory = = nullptr ) {
ShowFatalError ( " do_init: inventory engine not found. \n " ) ;
return false ;
}
else {
if ( ! inventory - > init ( inventory ) ) {
ShowFatalError ( " do_init: Failed to initialize inventory engine. \n " ) ;
return false ;
}
}
return true ;
return true ;
}
}
@ -636,7 +680,7 @@ bool brokk_create_character(mmo_charakter& charakter, int& char_id, const bool a
}
}
// Log success
// Log success
Show Notice ( " Character creation successful (name: %s, char_id: %d, sex: %c) \n " , charakter . name , charakter . char_id , charakter . sex ) ;
Show Status ( " Character creation successful (name: %s, char_id: %d, sex: %c) \n " , charakter . name , charakter . char_id , charakter . sex ) ;
// Update registration limit
// Update registration limit
if ( DIFF_TICK ( tick , new_reg_tick ) > 0 ) {
if ( DIFF_TICK ( tick , new_reg_tick ) > 0 ) {
@ -675,6 +719,13 @@ int brokk_teach_skills(bot_skill_bundle& skill_bundle, int& char_id) {
std : : string char_name = existing_char . name ;
std : : string char_name = existing_char . name ;
// TODO Define logic to handle session (on runtinme) added skills
// Those are added into the loaded skill tree on runtime by this function "void clif_addskill(map_session_data *sd, int skill_id)"
// A) There either needs to be a way to dynamicly change/create new skill trees depending on the demand from profiles (could be problematic because client code would be involved
// or
// B) There needs to be a way for brokk to communicate to sindri later, to tell sindri to add skills dynamicly to the skill tree of the logged in char
// Bottom line: Post-Pone decition for first polish iteration
for ( auto & skill : skill_bundle . skills ) {
for ( auto & skill : skill_bundle . skills ) {
// Create entry in the skill database
// Create entry in the skill database
@ -684,7 +735,7 @@ int brokk_teach_skills(bot_skill_bundle& skill_bundle, int& char_id) {
}
}
// Log success single skill
// Log success single skill
ShowNotice ( " Skill %s added to character char_id: %d) \n " , convert_skill_id_to_str ( skill . skill_id ) , skill . char_id ) ;
//ShowNotice("Skill %s added to character char_id: %d)\n", convert_skill_id_to_str(skill.skill_id), skill.char_id);
skill_count + + ;
skill_count + + ;
}
}
@ -694,11 +745,50 @@ int brokk_teach_skills(bot_skill_bundle& skill_bundle, int& char_id) {
return - 1 ; // Success
return - 1 ; // Success
}
}
/**
* Add an item to a charakters bundle in the database .
* @ param item : Pre - configured bot_item object with all necessary fields populated .
* @ return :
* - 1 : success
* 1 : unregistered id ( invalid char_id )
* 2 : Error while writing into inventory table
*/
int brokk_apply_item_loadout ( bot_item_bundle & item_bundle , int & char_id ) {
int item_count = 0 ;
// Check if the character exists
mmo_charakter existing_char ;
if ( ! charakters - > load_num ( charakters , & existing_char , char_id ) ) {
ShowError ( " Attempt to add an item to non-existing character (char_id: %d) \n " , char_id ) ;
return 1 ; // Character does not exist
}
std : : string char_name = existing_char . name ;
for ( auto & item : item_bundle . items ) {
// Create entry in the inventory database
if ( ! inventory - > create ( inventory , & item ) ) {
ShowError ( " Failed to create inventory entry (char_id: %d, item_id: %d) \n " , item . char_id , item . item_id ) ;
return 2 ; // inventory entry creation failed
}
// Log success single item
std : : string aegisname = convert_item_id_to_aegisname ( item . item_id ) ;
ShowNotice ( " Item %s added to character char_id: %d) \n " , aegisname . c_str ( ) , item . char_id ) ;
item_count + + ;
}
// Log success
ShowStatus ( " Successfully added %d Items to characters inventory (name: %s, char_id: %d) \n " , item_count , char_name . c_str ( ) , char_id ) ;
return - 1 ; // Success
}
void BrokkServer : : finalize ( ) {
void BrokkServer : : finalize ( ) {
AccountDB * db = login_accounts ;
AccountDB * db = login_accounts ;
BotAccountDB * bot_db = bot_accounts ;
BotAccountDB * bot_db = bot_accounts ;
CharDB * char_db = charakters ;
CharDB * char_db = charakters ;
SkillDB * skill_db = skills ;
SkillDB * skill_db = skills ;
InventoryDB * inventory_db = inventory ;
//brokk_log(0, "brokk server", 100, "brokk server shutdown");
//brokk_log(0, "brokk server", 100, "brokk server shutdown");
ShowStatus ( " Terminating... \n " ) ;
ShowStatus ( " Terminating... \n " ) ;
@ -728,10 +818,16 @@ void BrokkServer::finalize() {
skill_db = nullptr ;
skill_db = nullptr ;
}
}
if ( inventory_db ) { // destroy inventory engine
inventory_db - > destroy ( inventory_db ) ;
inventory_db = nullptr ;
}
login_accounts = nullptr ; // destroyed in account_engine
login_accounts = nullptr ; // destroyed in account_engine
bot_accounts = nullptr ; // destroyed in bot account_engine
bot_accounts = nullptr ; // destroyed in bot account_engine
charakters = nullptr ; // destroyed in charakter engine
charakters = nullptr ; // destroyed in charakter engine
skills = nullptr ; //destroy in skills engine
skills = nullptr ; //destroy in skills engine
inventory = nullptr ; //destroy in inventory engine
if ( brokk_fd ! = - 1 )
if ( brokk_fd ! = - 1 )
{
{
@ -761,6 +857,7 @@ bool BrokkServer::initialize(int argc, char* argv[]) {
bot_accounts = bot_account_db_sql ( ) ;
bot_accounts = bot_account_db_sql ( ) ;
charakters = char_db_sql ( ) ;
charakters = char_db_sql ( ) ;
skills = skill_db_sql ( ) ;
skills = skill_db_sql ( ) ;
inventory = inventory_db_sql ( ) ;
// Initialize Yaml-DBs
// Initialize Yaml-DBs
bot_read_yaml_dbs ( ) ;
bot_read_yaml_dbs ( ) ;
@ -790,7 +887,6 @@ bool BrokkServer::initialize(int argc, char* argv[]) {
/*
/*
//Demo-Skill tree
//Demo-Skill tree
//TODO Eintragen in Job-Profil -> welche Skills gelernt werden sollen und Mechanik bauen für plausibles auto-skill erlernen
std : : shared_ptr < bot_skill_tree > tree = bot_skill_tree_db . find ( JOB_MAGE ) ;
std : : shared_ptr < bot_skill_tree > tree = bot_skill_tree_db . find ( JOB_MAGE ) ;
for ( const auto & skill : tree - > skills ) {
for ( const auto & skill : tree - > skills ) {
ShowDebug ( " Skill Found in tree: %s \n " , convert_skill_id_to_str ( skill . first ) ) ;
ShowDebug ( " Skill Found in tree: %s \n " , convert_skill_id_to_str ( skill . first ) ) ;
@ -833,7 +929,7 @@ bool BrokkServer::initialize(int argc, char* argv[]) {
// Close file after done with it
// Close file after done with it
bot_accounts_file . close ( ) ;
bot_accounts_file . close ( ) ;
Show Status ( " Starting to create bot accounts... \n " ) ;
Show Info ( " Starting to create bot accounts... \n " ) ;
// Iterate over each bot entry in the JSON file
// Iterate over each bot entry in the JSON file
for ( const auto & bot : json_bot_accounts ) {
for ( const auto & bot : json_bot_accounts ) {
@ -843,7 +939,7 @@ bool BrokkServer::initialize(int argc, char* argv[]) {
const char sex = bot [ " sex " ] . get < std : : string > ( ) [ 0 ] ; // Extract single char from string
const char sex = bot [ " sex " ] . get < std : : string > ( ) [ 0 ] ; // Extract single char from string
// Debug: Print the entire bot entry
// Debug: Print the entire bot entry
//ShowInfo("Processing bot: %s\n", bot.dump(4).c_str());
ShowInfo ( " Processing bot account: %s ... \n " , userid_str . c_str ( ) ) ;
// Debug: Iterate over the keys in the bot object and print them
// Debug: Iterate over the keys in the bot object and print them
//for (auto it = bot.begin(); it != bot.end(); ++it) {
//for (auto it = bot.begin(); it != bot.end(); ++it) {
@ -873,13 +969,13 @@ bool BrokkServer::initialize(int argc, char* argv[]) {
const auto & json_characters = bot [ " characters " ] ;
const auto & json_characters = bot [ " characters " ] ;
//ShowDebug("StartChar Parsing");
//ShowDebug("StartChar Parsing");
for ( const auto & json_character : json_characters ) { //Iterate every declared character and try to create it
for ( const auto & json_character : json_characters ) { //Iterate every declared character and try to create it
//ShowDebug("char_json:\n%s", character.dump().c_str());
mmo_charakter new_char { } ;
mmo_charakter new_char { } ;
//Step1 Meta-Data about character (allways have to be present/not bound to profile)
//Step1 Meta-Data about character (allways have to be present/not bound to profile)
const std : : string char_name = json_character [ " name " ] ;
const std : : string char_name = json_character [ " name " ] ;
safestrncpy ( new_char . name , char_name . c_str ( ) , NAME_LENGTH ) ;
safestrncpy ( new_char . name , char_name . c_str ( ) , NAME_LENGTH ) ;
ShowInfo ( " Processing bot character %s ... \n " , char_name . c_str ( ) ) ;
std : : string sex_str = json_character [ " sex " ] ;
std : : string sex_str = json_character [ " sex " ] ;
new_char . sex = sex_str [ 0 ] ;
new_char . sex = sex_str [ 0 ] ;
@ -888,21 +984,25 @@ bool BrokkServer::initialize(int argc, char* argv[]) {
new_char . inventory_slots = 100 ;
new_char . inventory_slots = 100 ;
// Decode Job Value
// Decode Job Value
std : : string job_id = json_character [ " start_job " ] ;
std : : string job_id_str = json_character [ " start_job " ] ;
new_char . class_ = convert_jobid_to_number ( job_id . c_str ( ) ) ;
int job_id = convert_jobid_to_number ( job_id_str . c_str ( ) ) ;
new_char . class_ = job_id ;
if ( new_char . class_ = = - 1 ) {
if ( new_char . class_ = = - 1 ) {
job_id = " JOB_NOVICE " ;
job_id _str = " JOB_NOVICE " ;
new_char . class_ = JOB_NOVICE ;
new_char . class_ = JOB_NOVICE ;
}
}
// Step2: build data of character
// Step2: build data of character
new_char . account_id = account_id ;
new_char . account_id = account_id ;
new_char . char_id = - 1 ;
new_char . char_id = - 1 ;
ShowInfo ( " Preparing build data for bot character %s ... \n " , char_name . c_str ( ) ) ;
prepare_character_build_data ( new_char , json_character , bot_job_db ) ;
prepare_character_build_data ( new_char , json_character , bot_job_db ) ;
// Step3: appearance of character
// Step3: appearance of character
ShowInfo ( " Preparing appearance of bot character %s ... \n " , char_name . c_str ( ) ) ;
prepare_character_appearance_data ( new_char , json_character ) ;
prepare_character_appearance_data ( new_char , json_character ) ;
// Step4: location data of character
// Step4: location data of character
ShowInfo ( " Preparing location data for bot character %s ... \n " , char_name . c_str ( ) ) ;
prepare_character_location_data ( new_char , json_character ) ;
prepare_character_location_data ( new_char , json_character ) ;
// All char table related data is collected and can be saved to allow further steps (skills/items/equip)
// All char table related data is collected and can be saved to allow further steps (skills/items/equip)
@ -924,14 +1024,14 @@ bool BrokkServer::initialize(int argc, char* argv[]) {
ShowError ( " Character creation for '%s 'failed: %s \n " , new_char . name , e . what ( ) ) ;
ShowError ( " Character creation for '%s 'failed: %s \n " , new_char . name , e . what ( ) ) ;
continue ;
continue ;
}
}
//TODO Ab hier debuggen warum bei EvaExample bei neuanlage crashed
// Step5: Skills
// Step5: Skills
// Prepare skills inside a skill bundle
// Prepare skills inside a skill bundle
ShowInfo ( " Preparing skill data of bot character %s ... \n " , char_name . c_str ( ) ) ;
bot_skill_bundle skill_bundle { } ;
bot_skill_bundle skill_bundle { } ;
prepare_skill_bundle ( skill_bundle , new_char_id , json_character ) ;
prepare_skill_bundle ( skill_bundle , new_char_id , json_character ) ;
validate_skill_bundle ( skill_bundle , job_id_str . c_str ( ) ) ;
// All skill table related data is collected and can be saved
// All skill table related data is collected and can be saved
try {
try {
@ -945,18 +1045,34 @@ bool BrokkServer::initialize(int argc, char* argv[]) {
continue ;
continue ;
}
}
ShowNotice ( " Skills successfully teached to character (name: %s, char_id: %d, sex: %c) \n " , new_char . name , new_char . char_id , new_char . sex ) ;
// ShowNotice("Skills successfully teached to character (name: %s, char_id: %d, sex: %c)\n", new_char.name, new_char.char_id, new_char.sex);
//Step4: Items
//TODO Testweise folgende ItemIDs einbauen für Debug:
// 1950, 2627 , 4040
//ShowNotice("Items successfully handed out to character (name: %s, char_id: %d, sex: %c)\n", new_char.name, new_char.char_id, new_char.sex);
//Step5: Equipment
// Step6: Items
// Prepare items inside a item bundle
ShowInfo ( " Preparing inventory data for bot character %s ... \n " , char_name . c_str ( ) ) ;
//ShowNotice("Gear/Weapons successfully equiped (name: %s, char_id: %d, sex: %c)\n", new_char.name, new_char.char_id, new_char.sex);
bot_item_bundle item_bundle { } ;
prepare_item_bundle ( item_bundle , new_char_id , json_character ) ;
// All inventory table related data is collected and can be saved
try {
/* Lock-out while in debug
if ( ! brokk_apply_item_loadout ( item_bundle , new_char_id ) ) {
ShowError ( " Failed to create inventory entry for: %s \n " , new_char . name ) ;
continue ;
} */
}
catch ( const std : : exception & e ) {
ShowError ( " skill creation for '%s 'failed: %s \n " , new_char . name , e . what ( ) ) ;
continue ;
}
ShowStatus ( " Items successfully handed out to character (name: %s, char_id: %d, sex: %c) \n " , new_char . name , new_char . char_id , new_char . sex ) ;
ShowStatus ( " Bot-Character creation and administration completed (name: %s, char_id: %d, sex: %c) \n " , new_char . name , new_char . char_id , new_char . sex ) ;
//Step5: Equipment
//ShowInfo("Preparing equipment for bot character %s ...\n", char_name.c_str());
ShowStatus ( " Bot-Character creation and administration completed (name: %s, char_id: %d, sex: %c) \n \n " , new_char . name , new_char . char_id , new_char . sex ) ;
/*****
/*****
* Validating / Applying skill build
* Validating / Applying skill build