|
Fimbulwinter Project
Pre-Alpha
An Ragnarok Online Emulator
|
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 ®, int type) 00232 { 00233 struct GlobalReg *r; 00234 string str; 00235 string value; 00236 int i; 00237 soci::statement s(*db_); 00238 00239 memset(®, 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[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 };
1.7.6.1