Fimbulwinter Project  Pre-Alpha
An Ragnarok Online Emulator
CharServer/CharDB.hpp
00001 /*==================================================================*
00002 *     ___ _           _           _          _       _                          *
00003 *    / __(_)_ __ ___ | |__  _   _| |_      _(_)_ __ | |_ ___ _ __       *
00004 *   / _\ | | '_ ` _ \| '_ \| | | | \ \ /\ / / | '_ \| __/ _ \ '__|      *
00005 *  / /   | | | | | | | |_) | |_| | |\ V  V /| | | | | ||  __/ |         *
00006 *  \/    |_|_| |_| |_|_.__/ \__,_|_| \_/\_/ |_|_| |_|\__\___|_|         *
00007 *                                                                                                                                       *
00008 * ------------------------------------------------------------------*
00009 *                                                        Emulator                                       *
00010 * ------------------------------------------------------------------*
00011 *                     Licenced under GNU GPL v3                     *
00012 * ----------------------------------------------------------------- *
00013 *                     CharServer Database Modules                       *
00014 * ==================================================================*/
00015 #pragma once
00016 
00017 #include <ragnarok.hpp>
00018 #include <packets.hpp>
00019 #include <soci/soci.h>
00020 #include <database_helper.h>
00021 
00022 using namespace soci;
00023 
00024 struct CharSessionData;
00025 
00034 class CharDB
00035 {
00036 public:
00037         CharDB(soci::session *db)
00038         {
00039                 db_ = db;
00040         }
00041 
00043         int get_char_count(int accid) 
00044         {
00045                 soci::statement s =     (db_->prepare << "SELECT `char_id` FROM `char` WHERE `account_id`=:id LIMIT 1", use(accid));
00046         
00047                 s.execute(false);
00048 
00049                 return (int)s.get_affected_rows();
00050         }
00051 
00053         int load_chars_to_buf(int account_id, struct CHARACTER_INFO *charinfo, CharSessionData *csd) // Load the characters into a Buffer
00054         {
00055                 CharData c;
00056                 string lastmap;
00057                 string name;
00058 
00059                 soci::statement s = (db_->prepare << "SELECT "
00060                         "`account_id`, `char_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`,"
00061                         "`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`,"
00062                         "`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`,"
00063                         "`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`,"
00064                         "`robe`"
00065                         " FROM `char` WHERE `account_id`=:acc AND `char_num` < :max LIMIT 1",
00066                         use(account_id), use(MAX_CHARS),
00067                         into(c.account_id),
00068                         into(c.char_id),
00069                         into(c.slot),
00070                         into(name),
00071                         into(c.class_),
00072                         into(c.base_level),
00073                         into(c.job_level),
00074                         into(c.base_exp),
00075                         into(c.job_exp),
00076                         into(c.zeny),
00077                         into(c.str),
00078                         into(c.agi),
00079                         into(c.vit),
00080                         into(c.int_),
00081                         into(c.dex),
00082                         into(c.luk),
00083                         into(c.max_hp),
00084                         into(c.hp),
00085                         into(c.max_sp),
00086                         into(c.sp),
00087                         into(c.status_point),
00088                         into(c.skill_point),
00089                         into(c.option),
00090                         into(c.karma),
00091                         into(c.manner),
00092                         into(c.hair),
00093                         into(c.hair_color),
00094                         into(c.clothes_color),
00095                         into(c.weapon),
00096                         into(c.shield),
00097                         into(c.head_top),
00098                         into(c.head_mid),
00099                         into(c.head_bottom),
00100                         into(lastmap),
00101                         into(c.rename),
00102                         into(c.delete_date),
00103                         into(c.robe));
00104 
00105                 s.execute(false);
00106                 int i = 0, j = 0;
00107                 while(s.fetch())
00108                 {
00109                         c.last_point.map = CharServer::maps.get_map_id(lastmap);
00110                         strncpy(c.name, name.c_str(), NAME_LENGTH);
00111 
00112                         csd->found_char[i++] = c.char_id;
00113                         CharServer::char_to_buf(charinfo++, &c);
00114                         j++;
00115                 }
00116 
00117                 for(; i < MAX_CHARS; i++)
00118                         csd->found_char[i] = -1;
00119 
00120                 return j;
00121         }
00122 
00124         void load_char(int id, CharData &c, bool full) // Load the character
00125         {
00126                 string lastmap;
00127                 string name;
00128 
00129                 soci::statement s = (db_->prepare << "SELECT "
00130                         "`account_id`, `char_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`,"
00131                         "`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`,"
00132                         "`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`,"
00133                         "`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`,"
00134                         "`robe`"
00135                         " FROM `char` WHERE `char_id`=:ch LIMIT 1",
00136                         use(id),
00137                         into(c.account_id),
00138                         into(c.char_id),
00139                         into(c.slot),
00140                         into(name),
00141                         into(c.class_),
00142                         into(c.base_level),
00143                         into(c.job_level),
00144                         into(c.base_exp),
00145                         into(c.job_exp),
00146                         into(c.zeny),
00147                         into(c.str),
00148                         into(c.agi),
00149                         into(c.vit),
00150                         into(c.int_),
00151                         into(c.dex),
00152                         into(c.luk),
00153                         into(c.max_hp),
00154                         into(c.hp),
00155                         into(c.max_sp),
00156                         into(c.sp),
00157                         into(c.status_point),
00158                         into(c.skill_point),
00159                         into(c.option),
00160                         into(c.karma),
00161                         into(c.manner),
00162                         into(c.hair),
00163                         into(c.hair_color),
00164                         into(c.clothes_color),
00165                         into(c.weapon),
00166                         into(c.shield),
00167                         into(c.head_top),
00168                         into(c.head_mid),
00169                         into(c.head_bottom),
00170                         into(lastmap),
00171                         into(c.rename),
00172                         into(c.delete_date),
00173                         into(c.robe));
00174 
00175                 s.execute(true);
00176                 s.fetch();
00177 
00178                 c.last_point.map = CharServer::maps.get_map_id(lastmap);
00179                 strncpy(c.name, name.c_str(), NAME_LENGTH);
00180 
00181                 if (full)
00182                 {
00183                         s = (db_->prepare << "SELECT `last_x`, `last_y`, `save_map`, `save_x`, `save_y`"
00184                                 " FROM `char` WHERE `char_id`=:ch LIMIT 1",
00185                                 use(id),
00186                                 into(c.last_point.x),
00187                                 into(c.last_point.y),
00188                                 into(lastmap),
00189                                 into(c.save_point.x),
00190                                 into(c.save_point.y));
00191 
00192                         s.execute(true);
00193                         s.fetch();
00194 
00195                         c.save_point.map = CharServer::maps.get_map_id(lastmap);
00196                 }
00197         }
00198 
00200         int save(CharData &c, bool nw) // Save the character into the database.
00201         {
00202                 if (nw)
00203                 {
00204                         *db_ << "INSERT INTO `char` (`account_id`, `char_num`, `name`, `zeny`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`,"
00205                         "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES ("
00206                         ":q, :w, :e, :r,  :t, :y, :u, :o, :p, :a, :b, :c,:d, :e,:f, :g, :h, :i, :j, :l, :m, :n)",
00207                         use(c.account_id), use(c.slot), use(string(c.name)), use(0 /* TODO: Start Zeny */), use(c.str), use(c.agi), use(c.vit), use(c.int_), use(c.dex), use(c.luk),
00208                         use((40 * (100 + c.vit)/100)), use((40 * (100 + c.vit)/100 )),  use((11 * (100 + c.int_)/100)), use((11 * (100 + c.int_)/100)), use(c.hair), use(c.hair_color),
00209                         use(string("prontera") /* TODO: StartMap mapindex_id2name(start_point.map) */), use(150 /* start_point.x */), use(150 /* start_point.y */), use(string("prontera") /* c.mapindex_id2name(start_point.map) */), use(150 /* start_point.x */), use(150 /* start_point.y */);
00210 
00211                         return database_helper::get_last_insert_id(db_);
00212                 }
00213                 else
00214                 {
00215                         return c.char_id;
00216                 }
00217         }
00218 
00220         bool delete_char(int cid) // Delete a Character.
00221         {
00222                 // TODO: Divorce, De-addopt, leave party, delete pets, delete homunculus, mercenary data, friend list, saved hotkeys, invetory, memo areas, char registry, skills, sc's and leave or break guild
00223                 
00224                 statement s = (db_->prepare << "DELETE FROM `char` WHERE `char_id`=:d LIMIT 1", use(cid));
00225                 s.execute(false);
00226 
00227                 return true;
00228         }
00229 
00231         void load_acc_reg( int account_id, int char_id, struct AccountReg &reg, int type) 
00232         {
00233                 struct GlobalReg *r;
00234                 string str;
00235                 string value;
00236                 int i;
00237                 soci::statement s(*db_);
00238 
00239                 memset(&reg, 0, sizeof(AccountReg));
00240                 reg.account_id = account_id;
00241                 reg.char_id = char_id;
00242 
00243                 switch (type)
00244                 {
00245                 case 3: //char reg
00246                         s = (db_->prepare << "SELECT `str`, `value` FROM `global_reg_value` WHERE `type`=3 AND `char_id`=:c",
00247                                 use(char_id),
00248                                 into(str),
00249                                 into(value));
00250                         break;
00251                 case 2: //account reg
00252                         s = (db_->prepare << "SELECT `str`, `value` FROM `global_reg_value` WHERE `type`=2 AND `account_id`=:a",
00253                                 use(account_id),
00254                                 into(str),
00255                                 into(value));
00256                         break;
00257                 case 1: //account2 reg
00258                         ShowError("inter_accreg_fromsql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n");
00259                         return;
00260                 default:
00261                         ShowError("inter_accreg_fromsql: Invalid type %d\n", type);
00262                         return;
00263                 }
00264 
00265                 s.execute(false);
00266 
00267                 for (i = 0; i < MAX_REG_NUM && s.fetch(); i++)
00268                 {
00269                         r = &reg.reg[i];
00270 
00271                         memcpy(r->str, str.c_str(), min(str.size(), sizeof(r->str)));
00272                         memcpy(r->value, value.c_str(), min(str.size(), sizeof(r->value)));
00273                 }
00274 
00275                 reg.reg_num = i;
00276         }
00277 
00278 private:
00279         soci::session *db_;
00280 };
 All Classes Functions