PageRenderTime 65ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/src/char/int_homun.c

https://gitlab.com/gumiko/hercules
C | 367 lines | 276 code | 46 blank | 45 comment | 46 complexity | 8a6e7540e8be36b82aaac44c9e07ccda MD5 | raw file
  1. /**
  2. * This file is part of Hercules.
  3. * http://herc.ws - http://github.com/HerculesWS/Hercules
  4. *
  5. * Copyright (C) 2012-2016 Hercules Dev Team
  6. * Copyright (C) Athena Dev Teams
  7. *
  8. * Hercules is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #define HERCULES_CORE
  22. #include "int_homun.h"
  23. #include "char/char.h"
  24. #include "char/inter.h"
  25. #include "char/mapif.h"
  26. #include "common/memmgr.h"
  27. #include "common/mmo.h"
  28. #include "common/nullpo.h"
  29. #include "common/showmsg.h"
  30. #include "common/socket.h"
  31. #include "common/sql.h"
  32. #include "common/strlib.h"
  33. #include "common/utils.h"
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. struct inter_homunculus_interface inter_homunculus_s;
  37. struct inter_homunculus_interface *inter_homunculus;
  38. int inter_homunculus_sql_init(void)
  39. {
  40. return 0;
  41. }
  42. void inter_homunculus_sql_final(void)
  43. {
  44. return;
  45. }
  46. void mapif_homunculus_created(int fd, int account_id, const struct s_homunculus *sh, unsigned char flag)
  47. {
  48. nullpo_retv(sh);
  49. WFIFOHEAD(fd, sizeof(struct s_homunculus)+9);
  50. WFIFOW(fd,0) = 0x3890;
  51. WFIFOW(fd,2) = sizeof(struct s_homunculus)+9;
  52. WFIFOL(fd,4) = account_id;
  53. WFIFOB(fd,8)= flag;
  54. memcpy(WFIFOP(fd,9),sh,sizeof(struct s_homunculus));
  55. WFIFOSET(fd, WFIFOW(fd,2));
  56. }
  57. void mapif_homunculus_deleted(int fd, int flag)
  58. {
  59. WFIFOHEAD(fd, 3);
  60. WFIFOW(fd, 0) = 0x3893;
  61. WFIFOB(fd,2) = flag; //Flag 1 = success
  62. WFIFOSET(fd, 3);
  63. }
  64. void mapif_homunculus_loaded(int fd, int account_id, struct s_homunculus *hd)
  65. {
  66. WFIFOHEAD(fd, sizeof(struct s_homunculus)+9);
  67. WFIFOW(fd,0) = 0x3891;
  68. WFIFOW(fd,2) = sizeof(struct s_homunculus)+9;
  69. WFIFOL(fd,4) = account_id;
  70. if( hd != NULL )
  71. {
  72. WFIFOB(fd,8) = 1; // success
  73. memcpy(WFIFOP(fd,9), hd, sizeof(struct s_homunculus));
  74. }
  75. else
  76. {
  77. WFIFOB(fd,8) = 0; // not found.
  78. memset(WFIFOP(fd,9), 0, sizeof(struct s_homunculus));
  79. }
  80. WFIFOSET(fd, sizeof(struct s_homunculus)+9);
  81. }
  82. void mapif_homunculus_saved(int fd, int account_id, bool flag)
  83. {
  84. WFIFOHEAD(fd, 7);
  85. WFIFOW(fd,0) = 0x3892;
  86. WFIFOL(fd,2) = account_id;
  87. WFIFOB(fd,6) = flag; // 1:success, 0:failure
  88. WFIFOSET(fd, 7);
  89. }
  90. void mapif_homunculus_renamed(int fd, int account_id, int char_id, unsigned char flag, const char *name)
  91. {
  92. nullpo_retv(name);
  93. WFIFOHEAD(fd, NAME_LENGTH+12);
  94. WFIFOW(fd, 0) = 0x3894;
  95. WFIFOL(fd, 2) = account_id;
  96. WFIFOL(fd, 6) = char_id;
  97. WFIFOB(fd,10) = flag;
  98. safestrncpy(WFIFOP(fd,11), name, NAME_LENGTH);
  99. WFIFOSET(fd, NAME_LENGTH+12);
  100. }
  101. /**
  102. * Creates a new homunculus with the given data.
  103. *
  104. * @remark
  105. * The homunculus ID is expected to be 0, and will be filled with the newly
  106. * assigned ID.
  107. *
  108. * @param[in,out] hd The new homunculus' data.
  109. * @retval false in case of errors.
  110. */
  111. bool mapif_homunculus_create(struct s_homunculus *hd)
  112. {
  113. char esc_name[NAME_LENGTH*2+1];
  114. nullpo_retr(false, hd);
  115. Assert_retr(false, hd->hom_id == 0);
  116. SQL->EscapeStringLen(inter->sql_handle, esc_name, hd->name, strnlen(hd->name, NAME_LENGTH));
  117. if (SQL_ERROR == SQL->Query(inter->sql_handle, "INSERT INTO `%s` "
  118. "(`char_id`, `class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`, `rename_flag`, `vaporize`) "
  119. "VALUES ('%d', '%d', '%d', '%s', '%d', '%u', '%u', '%d', '%d', %d, '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
  120. homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk,
  121. hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize)) {
  122. Sql_ShowDebug(inter->sql_handle);
  123. return false;
  124. }
  125. hd->hom_id = (int)SQL->LastInsertId(inter->sql_handle);
  126. return true;
  127. }
  128. /**
  129. * Saves an existing homunculus.
  130. *
  131. * @param hd The homunculus' data.
  132. * @retval false in case of errors.
  133. */
  134. bool mapif_homunculus_save(const struct s_homunculus *hd)
  135. {
  136. bool flag = true;
  137. char esc_name[NAME_LENGTH*2+1];
  138. nullpo_retr(false, hd);
  139. Assert_retr(false, hd->hom_id > 0);
  140. SQL->EscapeStringLen(inter->sql_handle, esc_name, hd->name, strnlen(hd->name, NAME_LENGTH));
  141. if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `char_id`='%d', `class`='%d',`prev_class`='%d',`name`='%s',`level`='%d',`exp`='%u',`intimacy`='%u',`hunger`='%d', `str`='%d', `agi`='%d', `vit`='%d', `int`='%d', `dex`='%d', `luk`='%d', `hp`='%d',`max_hp`='%d',`sp`='%d',`max_sp`='%d',`skill_point`='%d', `rename_flag`='%d', `vaporize`='%d' WHERE `homun_id`='%d'",
  142. homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk,
  143. hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize, hd->hom_id)) {
  144. Sql_ShowDebug(inter->sql_handle);
  145. flag = false;
  146. } else {
  147. int i;
  148. struct SqlStmt *stmt = SQL->StmtMalloc(inter->sql_handle);
  149. if (SQL_ERROR == SQL->StmtPrepare(stmt, "REPLACE INTO `%s` (`homun_id`, `id`, `lv`) VALUES (%d, ?, ?)", skill_homunculus_db, hd->hom_id)) {
  150. SqlStmt_ShowDebug(stmt);
  151. flag = false;
  152. } else {
  153. for (i = 0; i < MAX_HOMUNSKILL; ++i) {
  154. if (hd->hskill[i].id > 0 && hd->hskill[i].lv != 0) {
  155. SQL->StmtBindParam(stmt, 0, SQLDT_USHORT, &hd->hskill[i].id, 0);
  156. SQL->StmtBindParam(stmt, 1, SQLDT_USHORT, &hd->hskill[i].lv, 0);
  157. if (SQL_ERROR == SQL->StmtExecute(stmt)) {
  158. SqlStmt_ShowDebug(stmt);
  159. flag = false;
  160. break;
  161. }
  162. }
  163. }
  164. }
  165. SQL->StmtFree(stmt);
  166. }
  167. return flag;
  168. }
  169. // Load an homunculus
  170. bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd)
  171. {
  172. char* data;
  173. size_t len;
  174. nullpo_ret(hd);
  175. memset(hd, 0, sizeof(*hd));
  176. if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `homun_id`,`char_id`,`class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `%s` WHERE `homun_id`='%d'", homunculus_db, homun_id) )
  177. {
  178. Sql_ShowDebug(inter->sql_handle);
  179. return false;
  180. }
  181. if (!SQL->NumRows(inter->sql_handle)) {
  182. //No homunculus found.
  183. SQL->FreeResult(inter->sql_handle);
  184. return false;
  185. }
  186. if( SQL_SUCCESS != SQL->NextRow(inter->sql_handle) )
  187. {
  188. Sql_ShowDebug(inter->sql_handle);
  189. SQL->FreeResult(inter->sql_handle);
  190. return false;
  191. }
  192. hd->hom_id = homun_id;
  193. SQL->GetData(inter->sql_handle, 1, &data, NULL); hd->char_id = atoi(data);
  194. SQL->GetData(inter->sql_handle, 2, &data, NULL); hd->class_ = atoi(data);
  195. SQL->GetData(inter->sql_handle, 3, &data, NULL); hd->prev_class = atoi(data);
  196. SQL->GetData(inter->sql_handle, 4, &data, &len); safestrncpy(hd->name, data, sizeof(hd->name));
  197. SQL->GetData(inter->sql_handle, 5, &data, NULL); hd->level = atoi(data);
  198. SQL->GetData(inter->sql_handle, 6, &data, NULL); hd->exp = atoi(data);
  199. SQL->GetData(inter->sql_handle, 7, &data, NULL); hd->intimacy = (unsigned int)strtoul(data, NULL, 10);
  200. SQL->GetData(inter->sql_handle, 8, &data, NULL); hd->hunger = atoi(data);
  201. SQL->GetData(inter->sql_handle, 9, &data, NULL); hd->str = atoi(data);
  202. SQL->GetData(inter->sql_handle, 10, &data, NULL); hd->agi = atoi(data);
  203. SQL->GetData(inter->sql_handle, 11, &data, NULL); hd->vit = atoi(data);
  204. SQL->GetData(inter->sql_handle, 12, &data, NULL); hd->int_ = atoi(data);
  205. SQL->GetData(inter->sql_handle, 13, &data, NULL); hd->dex = atoi(data);
  206. SQL->GetData(inter->sql_handle, 14, &data, NULL); hd->luk = atoi(data);
  207. SQL->GetData(inter->sql_handle, 15, &data, NULL); hd->hp = atoi(data);
  208. SQL->GetData(inter->sql_handle, 16, &data, NULL); hd->max_hp = atoi(data);
  209. SQL->GetData(inter->sql_handle, 17, &data, NULL); hd->sp = atoi(data);
  210. SQL->GetData(inter->sql_handle, 18, &data, NULL); hd->max_sp = atoi(data);
  211. SQL->GetData(inter->sql_handle, 19, &data, NULL); hd->skillpts = atoi(data);
  212. SQL->GetData(inter->sql_handle, 20, &data, NULL); hd->rename_flag = atoi(data);
  213. SQL->GetData(inter->sql_handle, 21, &data, NULL); hd->vaporize = atoi(data);
  214. SQL->FreeResult(inter->sql_handle);
  215. hd->intimacy = cap_value(hd->intimacy, 0, 100000);
  216. hd->hunger = cap_value(hd->hunger, 0, 100);
  217. // Load Homunculus Skill
  218. if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `homun_id`=%d", skill_homunculus_db, homun_id)) {
  219. Sql_ShowDebug(inter->sql_handle);
  220. return false;
  221. }
  222. while (SQL_SUCCESS == SQL->NextRow(inter->sql_handle)) {
  223. int idx;
  224. // id
  225. SQL->GetData(inter->sql_handle, 0, &data, NULL);
  226. idx = atoi(data);
  227. if (idx < HM_SKILLBASE || idx >= HM_SKILLBASE + MAX_HOMUNSKILL)
  228. continue;// invalid skill id
  229. idx -= HM_SKILLBASE;
  230. hd->hskill[idx].id = (unsigned short)atoi(data);
  231. // lv
  232. SQL->GetData(inter->sql_handle, 1, &data, NULL);
  233. hd->hskill[idx].lv = (unsigned char)atoi(data);
  234. }
  235. SQL->FreeResult(inter->sql_handle);
  236. if (chr->show_save_log)
  237. ShowInfo("Homunculus loaded (%d - %s).\n", hd->hom_id, hd->name);
  238. return true;
  239. }
  240. bool mapif_homunculus_delete(int homun_id)
  241. {
  242. if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%d'", homunculus_db, homun_id)
  243. || SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%d'", skill_homunculus_db, homun_id)
  244. ) {
  245. Sql_ShowDebug(inter->sql_handle);
  246. return false;
  247. }
  248. return true;
  249. }
  250. bool mapif_homunculus_rename(const char *name)
  251. {
  252. int i;
  253. nullpo_ret(name);
  254. // Check Authorized letters/symbols in the name of the homun
  255. if( char_name_option == 1 )
  256. {// only letters/symbols in char_name_letters are authorized
  257. for( i = 0; i < NAME_LENGTH && name[i]; i++ )
  258. if( strchr(char_name_letters, name[i]) == NULL )
  259. return false;
  260. } else
  261. if( char_name_option == 2 )
  262. {// letters/symbols in char_name_letters are forbidden
  263. for( i = 0; i < NAME_LENGTH && name[i]; i++ )
  264. if( strchr(char_name_letters, name[i]) != NULL )
  265. return false;
  266. }
  267. return true;
  268. }
  269. void mapif_parse_homunculus_create(int fd, int len, int account_id, const struct s_homunculus *phd)
  270. {
  271. struct s_homunculus shd;
  272. bool result;
  273. memcpy(&shd, phd, sizeof(shd));
  274. result = mapif->homunculus_create(&shd);
  275. mapif->homunculus_created(fd, account_id, &shd, result);
  276. }
  277. void mapif_parse_homunculus_delete(int fd, int homun_id)
  278. {
  279. bool result = mapif->homunculus_delete(homun_id);
  280. mapif->homunculus_deleted(fd, result);
  281. }
  282. void mapif_parse_homunculus_load(int fd, int account_id, int homun_id)
  283. {
  284. struct s_homunculus hd;
  285. bool result = mapif->homunculus_load(homun_id, &hd);
  286. mapif->homunculus_loaded(fd, account_id, ( result ? &hd : NULL ));
  287. }
  288. void mapif_parse_homunculus_save(int fd, int len, int account_id, const struct s_homunculus *phd)
  289. {
  290. bool result = mapif->homunculus_save(phd);
  291. mapif->homunculus_saved(fd, account_id, result);
  292. }
  293. void mapif_parse_homunculus_rename(int fd, int account_id, int char_id, const char *name)
  294. {
  295. bool result = mapif->homunculus_rename(name);
  296. mapif->homunculus_renamed(fd, account_id, char_id, result, name);
  297. }
  298. /*==========================================
  299. * Inter Packets
  300. *------------------------------------------*/
  301. int inter_homunculus_parse_frommap(int fd)
  302. {
  303. unsigned short cmd = RFIFOW(fd,0);
  304. switch (cmd) {
  305. case 0x3090: mapif->parse_homunculus_create(fd, RFIFOW(fd,2), RFIFOL(fd,4), RFIFOP(fd,8)); break;
  306. case 0x3091: mapif->parse_homunculus_load (fd, RFIFOL(fd,2), RFIFOL(fd,6)); break;
  307. case 0x3092: mapif->parse_homunculus_save (fd, RFIFOW(fd,2), RFIFOL(fd,4), RFIFOP(fd,8)); break;
  308. case 0x3093: mapif->parse_homunculus_delete(fd, RFIFOL(fd,2)); break;
  309. case 0x3094: mapif->parse_homunculus_rename(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOP(fd,10)); break;
  310. default:
  311. return 0;
  312. }
  313. return 1;
  314. }
  315. void inter_homunculus_defaults(void)
  316. {
  317. inter_homunculus = &inter_homunculus_s;
  318. inter_homunculus->sql_init = inter_homunculus_sql_init;
  319. inter_homunculus->sql_final = inter_homunculus_sql_final;
  320. inter_homunculus->parse_frommap = inter_homunculus_parse_frommap;
  321. }