charsave.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <limits.h>
  7. #include "../common/core.h"
  8. #include "../common/socket.h"
  9. #include "../common/timer.h"
  10. #include "../common/nullpo.h"
  11. #include "../common/mmo.h"
  12. #include "../common/strlib.h"
  13. #include "../common/showmsg.h"
  14. #include "../common/malloc.h"
  15. #include "charsave.h"
  16. #include "map.h"
  17. #ifndef TXT_ONLY
  18. struct mmo_charstatus *charsave_loadchar(int charid){
  19. int i,j, friends;
  20. struct mmo_charstatus *c;
  21. char *str_p;
  22. friends = 0;
  23. c = (struct mmo_charstatus *)aCalloc(1,sizeof(struct mmo_charstatus));
  24. if(charid <= 0){
  25. ShowError("charsave_loadchar() charid <= 0! (%d)", charid);
  26. aFree(c);
  27. return NULL;
  28. }
  29. //Tested, Mysql 4.1.9+ has no problems with the long query, the buf is 65k big and the sql server needs for it 0.00009 secs on an athlon xp 2400+ WinXP (1GB Mem) .. [Sirius]
  30. sprintf(tmp_sql, "SELECT `char_id`,`account_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`, `str`,`agi`,`vit`,`int`,`dex`,`luk`, `max_hp`,`hp`,`max_sp`,`sp`,`status_point`,`skill_point`, `option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`hair`,`hair_color`, `clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`, `last_map`,`last_x`,`last_y`,`save_map`,`save_x`,`save_y`, `partner_id`, `father`, `mother`, `child`, `fame` FROM `char` WHERE `char_id` = '%d'", charid);
  31. if(mysql_query(&charsql_handle, tmp_sql)){
  32. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  33. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  34. aFree(c);
  35. return NULL;
  36. }
  37. charsql_res = mysql_store_result(&charsql_handle);
  38. if(mysql_num_rows(charsql_res) <= 0){
  39. ShowWarning("charsave_loadchar() -> CHARACTER NOT FOUND! (id: %d)\n", charid);
  40. mysql_free_result(charsql_res);
  41. aFree(c);
  42. return NULL;
  43. }
  44. //fetch data
  45. charsql_row = mysql_fetch_row(charsql_res);
  46. //fill with data
  47. c->char_id = charid;
  48. c->account_id = atoi(charsql_row[1]);
  49. c->char_num = atoi(charsql_row[2]);
  50. strcpy(c->name, charsql_row[3]);
  51. c->class_ = atoi(charsql_row[4]);
  52. c->base_level = atoi(charsql_row[5]);
  53. c->job_level = atoi(charsql_row[6]);
  54. c->base_exp = atoi(charsql_row[7]);
  55. c->job_exp = atoi(charsql_row[8]);
  56. c->zeny = atoi(charsql_row[9]);
  57. c->str = atoi(charsql_row[10]);
  58. c->agi = atoi(charsql_row[11]);
  59. c->vit = atoi(charsql_row[12]);
  60. c->int_ = atoi(charsql_row[13]);
  61. c->dex = atoi(charsql_row[14]);
  62. c->luk = atoi(charsql_row[15]);
  63. c->max_hp = atoi(charsql_row[16]);
  64. c->hp = atoi(charsql_row[17]);
  65. c->max_sp = atoi(charsql_row[18]);
  66. c->sp = atoi(charsql_row[19]);
  67. c->status_point = atoi(charsql_row[20]) > USHRT_MAX? USHRT_MAX : atoi(charsql_row[20]);
  68. c->skill_point = atoi(charsql_row[21]) > USHRT_MAX? USHRT_MAX : atoi(charsql_row[21]);
  69. c->option = atoi(charsql_row[22]);
  70. c->karma = atoi(charsql_row[23]);
  71. c->manner = atoi(charsql_row[24]);
  72. c->party_id = atoi(charsql_row[25]);
  73. c->guild_id = atoi(charsql_row[26]);
  74. c->pet_id = atoi(charsql_row[27]);
  75. c->hair = atoi(charsql_row[28]);
  76. c->hair_color = atoi(charsql_row[29]);
  77. c->clothes_color = atoi(charsql_row[30]);
  78. c->weapon = atoi(charsql_row[31]);
  79. c->shield = atoi(charsql_row[32]);
  80. c->head_top = atoi(charsql_row[33]);
  81. c->head_mid = atoi(charsql_row[34]);
  82. c->head_bottom = atoi(charsql_row[35]);
  83. c->last_point.map = mapindex_name2id(charsql_row[36]);
  84. c->last_point.x = atoi(charsql_row[37]);
  85. c->last_point.y = atoi(charsql_row[38]);
  86. c->save_point.map = mapindex_name2id(charsql_row[39]);
  87. c->save_point.x = atoi(charsql_row[40]);
  88. c->save_point.y = atoi(charsql_row[41]);
  89. c->partner_id = atoi(charsql_row[42]);
  90. c->father = atoi(charsql_row[43]);
  91. c->mother = atoi(charsql_row[44]);
  92. c->child = atoi(charsql_row[45]);
  93. c->fame = atoi(charsql_row[46]);
  94. mysql_free_result(charsql_res);
  95. //Check for '0' Savepoint / LastPoint
  96. if (c->last_point.x == 0 || c->last_point.y == 0 || c->last_point.map == 0){
  97. c->last_point.map = mapindex_name2id(MAP_PRONTERA);
  98. c->last_point.x = 100;
  99. c->last_point.y = 100;
  100. }
  101. if (c->save_point.x == 0 || c->save_point.y == 0 || c->save_point.map == 0){
  102. c->save_point.map = mapindex_name2id(MAP_PRONTERA);
  103. c->save_point.x = 100;
  104. c->save_point.y = 100;
  105. }
  106. //read the memo points
  107. sprintf(tmp_sql, "SELECT `memo_id`, `char_id`, `map`, `x`, `y` FROM `memo` WHERE `char_id` = '%d' ORDER BY `memo_id`", charid);
  108. if(mysql_query(&charsql_handle, tmp_sql)){
  109. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  110. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  111. aFree(c);
  112. return NULL;
  113. }
  114. charsql_res = mysql_store_result(&charsql_handle);
  115. if(charsql_res){
  116. for(i = 0; (charsql_row = mysql_fetch_row(charsql_res)); i++){
  117. c->memo_point[i].map = mapindex_name2id(charsql_row[2]);
  118. c->memo_point[i].x = atoi(charsql_row[3]);
  119. c->memo_point[i].y = atoi(charsql_row[4]);
  120. }
  121. mysql_free_result(charsql_res);
  122. }
  123. //read inventory...
  124. str_p = tmp_sql;
  125. str_p += sprintf(str_p, "SELECT `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`");
  126. for (i = 0; i < MAX_SLOTS; i++)
  127. str_p += sprintf(str_p, ", `card%d`", i);
  128. str_p += sprintf(str_p, " FROM `inventory` WHERE `char_id` = '%d'", charid);
  129. if(mysql_query(&charsql_handle, tmp_sql)){
  130. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  131. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  132. aFree(c);
  133. return NULL;
  134. }
  135. charsql_res = mysql_store_result(&charsql_handle);
  136. if(charsql_res){
  137. for(i = 0; (charsql_row = mysql_fetch_row(charsql_res)); i++){
  138. //c->inventory[i].id = atoi(charsql_row[0]);
  139. c->inventory[i].nameid = atoi(charsql_row[0]);
  140. c->inventory[i].amount = atoi(charsql_row[1]);
  141. c->inventory[i].equip = atoi(charsql_row[2]);
  142. c->inventory[i].identify = atoi(charsql_row[3]);
  143. c->inventory[i].refine = atoi(charsql_row[4]);
  144. c->inventory[i].attribute = atoi(charsql_row[5]);
  145. for (j = 0; j < MAX_SLOTS; j++)
  146. c->inventory[i].card[j] = atoi(charsql_row[6+j]);
  147. }
  148. mysql_free_result(charsql_res);
  149. }
  150. //cart inventory ..
  151. str_p = tmp_sql;
  152. str_p += sprintf(str_p, "SELECT `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`");
  153. for (i = 0; i < MAX_SLOTS; i++)
  154. str_p += sprintf(str_p, ", `card%d`", i);
  155. str_p += sprintf(str_p, " FROM `cart_inventory` WHERE `char_id` = '%d'", charid);
  156. if(mysql_query(&charsql_handle, tmp_sql)){
  157. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  158. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  159. aFree(c);
  160. return NULL;
  161. }
  162. charsql_res = mysql_store_result(&charsql_handle);
  163. if(charsql_res){
  164. for(i = 0; (charsql_row = mysql_fetch_row(charsql_res)); i++){
  165. //c->cart[i].id = atoi(charsql_row[0]);
  166. c->cart[i].nameid = atoi(charsql_row[0]);
  167. c->cart[i].amount = atoi(charsql_row[1]);
  168. c->cart[i].equip = atoi(charsql_row[2]);
  169. c->cart[i].identify = atoi(charsql_row[3]);
  170. c->cart[i].refine = atoi(charsql_row[4]);
  171. c->cart[i].attribute = atoi(charsql_row[5]);
  172. for (j = 0; j < MAX_SLOTS; j++)
  173. c->cart[i].card[j] = atoi(charsql_row[6+j]);
  174. }
  175. mysql_free_result(charsql_res);
  176. }
  177. //Skills...
  178. sprintf(tmp_sql, "SELECT `char_id`, `id`, `lv` FROM `skill` WHERE `char_id` = '%d'", charid);
  179. if(mysql_query(&charsql_handle, tmp_sql)){
  180. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  181. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  182. aFree(c);
  183. return NULL;
  184. }
  185. charsql_res = mysql_store_result(&charsql_handle);
  186. if(charsql_res){
  187. while((charsql_row = mysql_fetch_row(charsql_res))){
  188. i = atoi(charsql_row[1]);
  189. c->skill[i].id = i;
  190. c->skill[i].lv = atoi(charsql_row[2]);
  191. }
  192. mysql_free_result(charsql_res);
  193. }
  194. /* Reg values are handled by the char server.
  195. //Global REG
  196. sprintf(tmp_sql, "SELECT `char_id`, `str`, `value` FROM `global_reg_value` WHERE `type` = '3' AND `char_id` = '%d'", charid);
  197. if(mysql_query(&charsql_handle, tmp_sql)){
  198. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  199. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  200. aFree(c);
  201. return NULL;
  202. }
  203. charsql_res = mysql_store_result(&charsql_handle);
  204. if(charsql_res){
  205. for(i = 0; (charsql_row = mysql_fetch_row(charsql_res)); i++){
  206. strcpy(c->global_reg[i].str, charsql_row[1]);
  207. strcpy(c->global_reg[i].value, charsql_row[2]);
  208. }
  209. mysql_free_result(charsql_res);
  210. c->global_reg_num = i;
  211. }
  212. */
  213. //Shamelessly stolen from its_sparky (ie: thanks) and then assimilated by [Skotlex]
  214. //Friend list
  215. sprintf(tmp_sql, "SELECT f.friend_account, f.friend_id, c.name FROM friends f LEFT JOIN `char` c ON f.friend_account=c.account_id AND f.friend_id=c.char_id WHERE f.char_id='%d'", charid);
  216. if(mysql_query(&charsql_handle, tmp_sql)){
  217. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  218. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  219. sql_res = NULL; //To avoid trying to read data.
  220. }
  221. else
  222. sql_res = mysql_store_result(&charsql_handle);
  223. if(sql_res)
  224. {
  225. for(i = 0; (sql_row = mysql_fetch_row(sql_res)) && i<MAX_FRIENDS; i++)
  226. {
  227. if (sql_row[2] != NULL)
  228. {
  229. c->friends[i].account_id = atoi(sql_row[0]);
  230. c->friends[i].char_id = atoi(sql_row[1]);
  231. strncpy(c->friends[i].name, sql_row[2], NAME_LENGTH-1); //The -1 is to avoid losing the ending \0 [Skotlex]
  232. }
  233. }
  234. mysql_free_result(sql_res);
  235. }
  236. ShowInfo("charsql_loadchar(): loading of '%d' (%s) complete.\n", charid, c->name);
  237. return c;
  238. }
  239. int charsave_savechar(int charid, struct mmo_charstatus *c){
  240. int i,j;
  241. char *str_p;
  242. // char tmp_str[64];
  243. // char tmp_str2[512];
  244. //First save the 'char'
  245. sprintf(tmp_sql ,"UPDATE `char` SET `class`='%d', `base_level`='%d', `job_level`='%d',"
  246. "`base_exp`='%d', `job_exp`='%d', `zeny`='%d',"
  247. "`max_hp`='%d',`hp`='%d',`max_sp`='%d',`sp`='%d',`status_point`='%d',`skill_point`='%d',"
  248. "`str`='%d',`agi`='%d',`vit`='%d',`int`='%d',`dex`='%d',`luk`='%d',"
  249. "`option`='%d',`karma`='%d',`manner`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',"
  250. "`hair`='%d',`hair_color`='%d',`clothes_color`='%d',`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d',"
  251. "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d',"
  252. "`partner_id`='%d', `father`='%d', `mother`='%d', `child`='%d', `fame`='%d'"
  253. "WHERE `account_id`='%d' AND `char_id` = '%d'",
  254. c->class_, c->base_level, c->job_level,
  255. c->base_exp, c->job_exp, c->zeny,
  256. c->max_hp, c->hp, c->max_sp, c->sp, c->status_point, c->skill_point,
  257. c->str, c->agi, c->vit, c->int_, c->dex, c->luk,
  258. c->option, c->karma, c->manner, c->party_id, c->guild_id, c->pet_id,
  259. c->hair, c->hair_color, c->clothes_color,
  260. c->weapon, c->shield, c->head_top, c->head_mid, c->head_bottom,
  261. mapindex_id2name(c->last_point.map), c->last_point.x, c->last_point.y,
  262. mapindex_id2name(c->save_point.map), c->save_point.x, c->save_point.y, c->partner_id, c->father, c->mother,
  263. c->child, c->fame, c->account_id, c->char_id
  264. );
  265. if(mysql_query(&charsql_handle, tmp_sql)){
  266. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  267. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  268. }
  269. //Save the inventory
  270. sprintf(tmp_sql, "DELETE FROM `inventory` WHERE `char_id` = '%d'", charid);
  271. if(mysql_query(&charsql_handle, tmp_sql)){
  272. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  273. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  274. }
  275. for(i = 0; i < MAX_INVENTORY; i++){
  276. if(c->inventory[i].nameid > 0){
  277. str_p = tmp_sql;
  278. str_p += sprintf(str_p, "INSERT INTO `inventory` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`");
  279. for (j = 0; j < MAX_SLOTS; j++)
  280. str_p += sprintf(str_p, ", `card%d`", j);
  281. str_p += sprintf(str_p, ") VALUES ('%d', '%d', '%d', '%d', '%d', '%d', '%d'",
  282. charid, c->inventory[i].nameid, c->inventory[i].amount, c->inventory[i].equip,
  283. c->inventory[i].identify, c->inventory[i].refine, c->inventory[i].attribute);
  284. for (j = 0; j < MAX_SLOTS; j++)
  285. str_p += sprintf(str_p, ", '%d'", c->inventory[i].card[j]);
  286. strcat(tmp_sql,")");
  287. if(mysql_query(&charsql_handle, tmp_sql)){
  288. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  289. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  290. }
  291. }
  292. }
  293. //Save the cart
  294. sprintf(tmp_sql, "DELETE FROM `cart_inventory` WHERE `char_id` = '%d'", charid);
  295. if(mysql_query(&charsql_handle, tmp_sql)){
  296. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  297. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  298. }
  299. for(i = 0; i < MAX_CART; i++){
  300. if(c->cart[i].nameid > 0){
  301. str_p = tmp_sql;
  302. str_p += sprintf(str_p, "INSERT INTO `cart_inventory` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`");
  303. for (j = 0; j < MAX_SLOTS; j++)
  304. str_p += sprintf(str_p, ", `card%d`", j);
  305. str_p += sprintf(str_p, ") VALUES ('%d', '%d', '%d', '%d', '%d', '%d', '%d'",
  306. charid, c->cart[i].nameid, c->cart[i].amount, c->cart[i].equip,
  307. c->cart[i].identify, c->cart[i].refine, c->cart[i].attribute);
  308. for (j = 0; j < MAX_SLOTS; j++)
  309. str_p += sprintf(str_p, ", '%d'", c->cart[i].card[j]);
  310. strcat(tmp_sql,")");
  311. if(mysql_query(&charsql_handle, tmp_sql)){
  312. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  313. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  314. }
  315. }
  316. }
  317. //Save memo points
  318. sprintf(tmp_sql, "DELETE FROM `memo` WHERE `char_id` = '%d'", charid);
  319. if(mysql_query(&charsql_handle, tmp_sql)){
  320. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  321. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  322. }
  323. for(i = 0; i < MAX_MEMOPOINTS; i++){
  324. if(c->memo_point[i].map && c->memo_point[i].x > 0 && c->memo_point[i].y > 0){
  325. sprintf(tmp_sql, "INSERT INTO `memo` ( `char_id`, `map`, `x`, `y` ) VALUES ('%d', '%s', '%d', '%d')", charid, mapindex_id2name(c->memo_point[i].map), c->memo_point[i].x, c->memo_point[i].y);
  326. if(mysql_query(&charsql_handle, tmp_sql)){
  327. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  328. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  329. }
  330. }
  331. }
  332. //Save skills
  333. sprintf(tmp_sql, "DELETE FROM `skill` WHERE `char_id` = '%d'", charid);
  334. if(mysql_query(&charsql_handle, tmp_sql)){
  335. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  336. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  337. }
  338. for(i = 0; i < MAX_SKILL; i++){
  339. if(c->skill[i].id > 0){
  340. sprintf(tmp_sql, "INSERT INTO `skill` (`char_id`, `id`, `lv`) VALUES ('%d', '%d', '%d')", charid, c->skill[i].id, c->skill[i].lv);
  341. if(mysql_query(&charsql_handle, tmp_sql)){
  342. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  343. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  344. }
  345. }
  346. }
  347. /* Reg values are handled by the char server.
  348. //global_reg_value saving
  349. sprintf(tmp_sql, "DELETE FROM `global_reg_value` WHERE `type`=3 AND `char_id` = '%d'", charid);
  350. if(mysql_query(&charsql_handle, tmp_sql)){
  351. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  352. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  353. }
  354. for(i = 0; i < c->global_reg_num; i++){
  355. if(c->global_reg[i].str){
  356. if(c->global_reg[i].value){
  357. //jstrescapecpy(tmp_str, c->global_reg[i].str);
  358. sprintf(tmp_sql, "INSERT INTO `global_reg_value` (`char_id`, `str`, `value`) VALUES ('%d', '%s', '%s')", charid, jstrescapecpy(tmp_str,c->global_reg[i].str), jstrescapecpy(tmp_str2,c->global_reg[i].value));
  359. if(mysql_query(&charsql_handle, tmp_sql)){
  360. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  361. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  362. }
  363. }
  364. }
  365. }
  366. */
  367. //friendlist saving
  368. sprintf(tmp_sql, "DELETE FROM `friends` WHERE `char_id` = '%d'", charid);
  369. if(mysql_query(&charsql_handle, tmp_sql)){
  370. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  371. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  372. }
  373. for(i = 0; i < MAX_FRIENDS; i++){
  374. if(c->friends[i].char_id > 0){
  375. sprintf(tmp_sql, "INSERT INTO `friends` (`char_id`, `friend_account`, `friend_id`) VALUES ('%d','%d','%d')", charid, c->friends[i].account_id, c->friends[i].char_id);
  376. if(mysql_query(&charsql_handle, tmp_sql)){
  377. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  378. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  379. }
  380. }
  381. }
  382. ShowInfo("charsql_savechar(): saving of '%d' (%s) complete.\n", charid, c->name);
  383. return 0;
  384. }
  385. int charsave_load_scdata(int account_id, int char_id)
  386. { //Loads character's sc_data
  387. struct map_session_data *sd;
  388. sd = map_id2sd(account_id);
  389. if (!sd)
  390. {
  391. ShowError("charsave_load_scdata: Player of AID %d not found!\n", account_id);
  392. return -1;
  393. }
  394. if (sd->status.char_id != char_id)
  395. {
  396. ShowError("charsave_load_scdata: Receiving data for account %d, char id does not matches (%d != %d)!\n", account_id, sd->status.char_id, char_id);
  397. return -1;
  398. }
  399. sprintf(tmp_sql, "SELECT `type`, `tick`, `val1`, `val2`, `val3`, `val4` FROM `sc_data`"
  400. "WHERE `account_id`='%d' AND `char_id`='%d'", account_id, char_id);
  401. if(mysql_query(&charsql_handle, tmp_sql)){
  402. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  403. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  404. return -1;
  405. }
  406. sql_res = mysql_store_result(&charsql_handle);
  407. if(sql_res)
  408. {
  409. while ((sql_row = mysql_fetch_row(sql_res)))
  410. {
  411. if (atoi(sql_row[1]) < 1)
  412. { //Protection against invalid tick values. [Skotlex]
  413. ShowWarning("charsave_load_scdata: Received invalid duration (%d ms) for status change %d (character %s)\n", atoi(sql_row[1]), sd->status.name);
  414. continue;
  415. }
  416. status_change_start(&sd->bl, atoi(sql_row[0]), 10000, atoi(sql_row[2]), atoi(sql_row[3]),
  417. atoi(sql_row[4]), atoi(sql_row[5]), atoi(sql_row[1]), 15);
  418. }
  419. }
  420. //Once loaded, sc_data must be disposed.
  421. sprintf(tmp_sql, "DELETE FROM `sc_data` WHERE `account_id`='%d' AND `char_id`='%d'", account_id, char_id);
  422. if(mysql_query(&charsql_handle, tmp_sql)){
  423. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  424. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  425. }
  426. return 0;
  427. }
  428. void charsave_save_scdata(int account_id, int char_id, struct status_change* sc_data, int max_sc)
  429. { //Saves character's sc_data.
  430. int i,count =0;
  431. struct TimerData *timer;
  432. unsigned int tick = gettick();
  433. char *p = tmp_sql;
  434. p += sprintf(p, "INSERT INTO `sc_data` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ");
  435. for(i = 0; i < max_sc; i++)
  436. {
  437. if (sc_data->data[i].timer == -1)
  438. continue;
  439. timer = get_timer(sc_data->data[i].timer);
  440. if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0)
  441. continue;
  442. p += sprintf(p, " ('%d','%d','%hu','%d','%d','%d','%d','%d'),", account_id, char_id,
  443. i, DIFF_TICK(timer->tick,tick), sc_data->data[i].val1, sc_data->data[i].val2, sc_data->data[i].val3, sc_data->data[i].val4);
  444. count++;
  445. }
  446. if (count > 0)
  447. {
  448. *--p = '\0'; //Remove the trailing comma.
  449. if(mysql_query(&charsql_handle, tmp_sql)){
  450. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  451. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  452. }
  453. }
  454. ShowInfo("charsql_save_scdata(): saved %d status changes of '%d:%d'.\n", count, account_id, char_id);
  455. return;
  456. }
  457. #endif