int_party.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include "../common/cbasetypes.h"
  4. #include "../common/mmo.h"
  5. #include "../common/db.h"
  6. #include "../common/malloc.h"
  7. #include "../common/strlib.h"
  8. #include "../common/socket.h"
  9. #include "../common/showmsg.h"
  10. #include "../common/mapindex.h"
  11. #include "../common/sql.h"
  12. #include "char.h"
  13. #include "inter.h"
  14. #include "int_party.h"
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #ifndef TXT_SQL_CONVERT
  19. struct party_data {
  20. struct party party;
  21. unsigned int min_lv, max_lv;
  22. int family; //Is this party a family? if so, this holds the child id.
  23. unsigned char size; //Total size of party.
  24. };
  25. static struct party_data *party_pt;
  26. static DBMap* party_db_; // int party_id -> struct party_data*
  27. int mapif_party_broken(int party_id,int flag);
  28. int party_check_empty(struct party_data *p);
  29. int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id);
  30. int party_check_exp_share(struct party_data *p);
  31. int mapif_party_optionchanged(int fd,struct party *p, int account_id, int flag);
  32. //Updates party's level range and unsets even share if broken.
  33. static int int_party_check_lv(struct party_data *p) {
  34. int i;
  35. unsigned int lv;
  36. p->min_lv = UINT_MAX;
  37. p->max_lv = 0;
  38. for(i=0;i<MAX_PARTY;i++){
  39. /**
  40. * - If not online OR if it's a family party and this is the child (doesn't affect exp range)
  41. **/
  42. if(!p->party.member[i].online || p->party.member[i].char_id == p->family )
  43. continue;
  44. lv=p->party.member[i].lv;
  45. if (lv < p->min_lv) p->min_lv = lv;
  46. if (lv > p->max_lv) p->max_lv = lv;
  47. }
  48. if (p->party.exp && !party_check_exp_share(p)) {
  49. p->party.exp = 0;
  50. mapif_party_optionchanged(0, &p->party, 0, 0);
  51. return 0;
  52. }
  53. return 1;
  54. }
  55. //Calculates the state of a party.
  56. static void int_party_calc_state(struct party_data *p)
  57. {
  58. int i;
  59. unsigned int lv;
  60. p->min_lv = UINT_MAX;
  61. p->max_lv = 0;
  62. p->party.count =
  63. p->size =
  64. p->family = 0;
  65. //Check party size
  66. for(i=0;i<MAX_PARTY;i++){
  67. if (!p->party.member[i].lv) continue;
  68. p->size++;
  69. if(p->party.member[i].online)
  70. p->party.count++;
  71. }
  72. if( p->size == 2 && ( char_child(p->party.member[0].char_id,p->party.member[1].char_id) || char_child(p->party.member[1].char_id,p->party.member[2].char_id) ) ) {
  73. //Child should be able to share with either of their parents [RoM]
  74. if(p->party.member[0].class_&0x2000) //first slot is the child?
  75. p->family = p->party.member[0].char_id;
  76. else
  77. p->family = p->party.member[1].char_id;
  78. } else if( p->size == 3 ) {
  79. //Check Family State.
  80. p->family = char_family(
  81. p->party.member[0].char_id,
  82. p->party.member[1].char_id,
  83. p->party.member[2].char_id
  84. );
  85. }
  86. //max/min levels.
  87. for(i=0;i<MAX_PARTY;i++){
  88. lv=p->party.member[i].lv;
  89. if (!lv) continue;
  90. if(p->party.member[i].online &&
  91. //On families, the kid is not counted towards exp share rules.
  92. p->party.member[i].char_id != p->family)
  93. {
  94. if( lv < p->min_lv ) p->min_lv=lv;
  95. if( p->max_lv < lv ) p->max_lv=lv;
  96. }
  97. }
  98. if (p->party.exp && !party_check_exp_share(p)) {
  99. p->party.exp = 0; //Set off even share.
  100. mapif_party_optionchanged(0, &p->party, 0, 0);
  101. }
  102. return;
  103. }
  104. #endif //TXT_SQL_CONVERT
  105. // Save party to mysql
  106. int inter_party_tosql(struct party *p, int flag, int index)
  107. {
  108. // 'party' ('party_id','name','exp','item','leader_id','leader_char')
  109. char esc_name[NAME_LENGTH*2+1];// escaped party name
  110. int party_id;
  111. if( p == NULL || p->party_id == 0 )
  112. return 0;
  113. party_id = p->party_id;
  114. #ifdef NOISY
  115. ShowInfo("Save party request ("CL_BOLD"%d"CL_RESET" - %s).\n", party_id, p->name);
  116. #endif
  117. Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH));
  118. #ifndef TXT_SQL_CONVERT
  119. if( flag & PS_BREAK )
  120. {// Break the party
  121. // we'll skip name-checking and just reset everyone with the same party id [celest]
  122. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) )
  123. Sql_ShowDebug(sql_handle);
  124. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `party_id`='%d'", party_db, party_id) )
  125. Sql_ShowDebug(sql_handle);
  126. //Remove from memory
  127. idb_remove(party_db_, party_id);
  128. return 1;
  129. }
  130. #endif //TXT_SQL_CONVERT
  131. if( flag & PS_CREATE )
  132. {// Create party
  133. #ifndef TXT_SQL_CONVERT
  134. if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` "
  135. "(`name`, `exp`, `item`, `leader_id`, `leader_char`) "
  136. "VALUES ('%s', '%d', '%d', '%d', '%d')",
  137. party_db, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) )
  138. {
  139. Sql_ShowDebug(sql_handle);
  140. return 0;
  141. }
  142. party_id = p->party_id = (int)Sql_LastInsertId(sql_handle);
  143. #else
  144. //During conversion, you want to specify the id, and allow overwriting
  145. //(in case someone is re-running the process.
  146. if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` "
  147. "(`party_id`, `name`, `exp`, `item`, `leader_id`, `leader_char`) "
  148. "VALUES ('%d', '%s', '%d', '%d', '%d', '%d')",
  149. party_db, p->party_id, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) )
  150. {
  151. Sql_ShowDebug(sql_handle);
  152. return 0;
  153. }
  154. #endif
  155. }
  156. #ifndef TXT_SQL_CONVERT
  157. if( flag & PS_BASIC )
  158. {// Update party info.
  159. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name`='%s', `exp`='%d', `item`='%d' WHERE `party_id`='%d'",
  160. party_db, esc_name, p->exp, p->item, party_id) )
  161. Sql_ShowDebug(sql_handle);
  162. }
  163. if( flag & PS_LEADER )
  164. {// Update leader
  165. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `leader_id`='%d', `leader_char`='%d' WHERE `party_id`='%d'",
  166. party_db, p->member[index].account_id, p->member[index].char_id, party_id) )
  167. Sql_ShowDebug(sql_handle);
  168. }
  169. if( flag & PS_ADDMEMBER )
  170. {// Add one party member.
  171. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `char_id`='%d'",
  172. char_db, party_id, p->member[index].account_id, p->member[index].char_id) )
  173. Sql_ShowDebug(sql_handle);
  174. }
  175. if( flag & PS_DELMEMBER )
  176. {// Remove one party member.
  177. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `char_id`='%d'",
  178. char_db, party_id, p->member[index].account_id, p->member[index].char_id) )
  179. Sql_ShowDebug(sql_handle);
  180. }
  181. #endif //TXT_SQL_CONVERT
  182. if( save_log )
  183. ShowInfo("Party Saved (%d - %s)\n", party_id, p->name);
  184. return 1;
  185. }
  186. #ifndef TXT_SQL_CONVERT
  187. // Read party from mysql
  188. struct party_data *inter_party_fromsql(int party_id)
  189. {
  190. int leader_id = 0;
  191. int leader_char = 0;
  192. struct party_data* p;
  193. struct party_member* m;
  194. char* data;
  195. size_t len;
  196. int i;
  197. #ifdef NOISY
  198. ShowInfo("Load party request ("CL_BOLD"%d"CL_RESET")\n", party_id);
  199. #endif
  200. if( party_id <= 0 )
  201. return NULL;
  202. //Load from memory
  203. p = (struct party_data*)idb_get(party_db_, party_id);
  204. if( p != NULL )
  205. return p;
  206. p = party_pt;
  207. memset(p, 0, sizeof(struct party_data));
  208. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id`, `name`,`exp`,`item`, `leader_id`, `leader_char` FROM `%s` WHERE `party_id`='%d'", party_db, party_id) )
  209. {
  210. Sql_ShowDebug(sql_handle);
  211. return NULL;
  212. }
  213. if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  214. return NULL;
  215. p->party.party_id = party_id;
  216. Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->party.name, data, min(len, NAME_LENGTH));
  217. Sql_GetData(sql_handle, 2, &data, NULL); p->party.exp = (atoi(data) ? 1 : 0);
  218. Sql_GetData(sql_handle, 3, &data, NULL); p->party.item = atoi(data);
  219. Sql_GetData(sql_handle, 4, &data, NULL); leader_id = atoi(data);
  220. Sql_GetData(sql_handle, 5, &data, NULL); leader_char = atoi(data);
  221. Sql_FreeResult(sql_handle);
  222. // Load members
  223. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`name`,`base_level`,`last_map`,`online`,`class` FROM `%s` WHERE `party_id`='%d'", char_db, party_id) )
  224. {
  225. Sql_ShowDebug(sql_handle);
  226. return NULL;
  227. }
  228. for( i = 0; i < MAX_PARTY && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
  229. {
  230. m = &p->party.member[i];
  231. Sql_GetData(sql_handle, 0, &data, NULL); m->account_id = atoi(data);
  232. Sql_GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data);
  233. Sql_GetData(sql_handle, 2, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH));
  234. Sql_GetData(sql_handle, 3, &data, NULL); m->lv = atoi(data);
  235. Sql_GetData(sql_handle, 4, &data, NULL); m->map = mapindex_name2id(data);
  236. Sql_GetData(sql_handle, 5, &data, NULL); m->online = (atoi(data) ? 1 : 0);
  237. Sql_GetData(sql_handle, 6, &data, NULL); m->class_ = atoi(data);
  238. m->leader = (m->account_id == leader_id && m->char_id == leader_char ? 1 : 0);
  239. }
  240. Sql_FreeResult(sql_handle);
  241. if( save_log )
  242. ShowInfo("Party loaded (%d - %s).\n", party_id, p->party.name);
  243. //Add party to memory.
  244. CREATE(p, struct party_data, 1);
  245. memcpy(p, party_pt, sizeof(struct party_data));
  246. //init state
  247. int_party_calc_state(p);
  248. idb_put(party_db_, party_id, p);
  249. return p;
  250. }
  251. int inter_party_sql_init(void)
  252. {
  253. //memory alloc
  254. party_db_ = idb_alloc(DB_OPT_RELEASE_DATA);
  255. party_pt = (struct party_data*)aCalloc(sizeof(struct party_data), 1);
  256. if (!party_pt) {
  257. ShowFatalError("inter_party_sql_init: Out of Memory!\n");
  258. exit(EXIT_FAILURE);
  259. }
  260. /* Uncomment the following if you want to do a party_db cleanup (remove parties with no members) on startup.[Skotlex]
  261. ShowStatus("cleaning party table...\n");
  262. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` LEFT JOIN `%s` ON `%s`.leader_id =`%s`.account_id AND `%s`.leader_char = `%s`.char_id WHERE `%s`.account_id IS NULL",
  263. party_db, party_db, char_db, party_db, char_db, party_db, char_db, char_db) )
  264. Sql_ShowDebug(sql_handle);
  265. */
  266. return 0;
  267. }
  268. void inter_party_sql_final(void)
  269. {
  270. party_db_->destroy(party_db_, NULL);
  271. aFree(party_pt);
  272. return;
  273. }
  274. // Search for the party according to its name
  275. struct party_data* search_partyname(char* str)
  276. {
  277. char esc_name[NAME_LENGTH*2+1];
  278. char* data;
  279. struct party_data* p = NULL;
  280. Sql_EscapeStringLen(sql_handle, esc_name, str, safestrnlen(str, NAME_LENGTH));
  281. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id` FROM `%s` WHERE `name`='%s'", party_db, esc_name) )
  282. Sql_ShowDebug(sql_handle);
  283. else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
  284. {
  285. Sql_GetData(sql_handle, 0, &data, NULL);
  286. p = inter_party_fromsql(atoi(data));
  287. }
  288. Sql_FreeResult(sql_handle);
  289. return p;
  290. }
  291. // Returns whether this party can keep having exp share or not.
  292. int party_check_exp_share(struct party_data *p)
  293. {
  294. return (p->party.count < 2 || p->max_lv - p->min_lv <= party_share_level);
  295. }
  296. // Is there any member in the party?
  297. int party_check_empty(struct party_data *p)
  298. {
  299. int i;
  300. if (p==NULL||p->party.party_id==0) return 1;
  301. for(i=0;i<MAX_PARTY && !p->party.member[i].account_id;i++);
  302. if (i < MAX_PARTY) return 0;
  303. // If there is no member, then break the party
  304. mapif_party_broken(p->party.party_id,0);
  305. inter_party_tosql(&p->party, PS_BREAK, 0);
  306. return 1;
  307. }
  308. //-------------------------------------------------------------------
  309. // map serverへの通信
  310. // パーティ作成可否
  311. int mapif_party_created(int fd,int account_id,int char_id,struct party *p)
  312. {
  313. WFIFOHEAD(fd, 39);
  314. WFIFOW(fd,0)=0x3820;
  315. WFIFOL(fd,2)=account_id;
  316. WFIFOL(fd,6)=char_id;
  317. if(p!=NULL){
  318. WFIFOB(fd,10)=0;
  319. WFIFOL(fd,11)=p->party_id;
  320. memcpy(WFIFOP(fd,15),p->name,NAME_LENGTH);
  321. ShowInfo("int_party: Party created (%d - %s)\n",p->party_id,p->name);
  322. }else{
  323. WFIFOB(fd,10)=1;
  324. WFIFOL(fd,11)=0;
  325. memset(WFIFOP(fd,15),0,NAME_LENGTH);
  326. }
  327. WFIFOSET(fd,39);
  328. return 0;
  329. }
  330. // パーティ情報見つからず
  331. static void mapif_party_noinfo(int fd, int party_id, int char_id)
  332. {
  333. WFIFOHEAD(fd, 12);
  334. WFIFOW(fd,0) = 0x3821;
  335. WFIFOW(fd,2) = 12;
  336. WFIFOL(fd,4) = char_id;
  337. WFIFOL(fd,8) = party_id;
  338. WFIFOSET(fd,12);
  339. ShowWarning("int_party: info not found (party_id=%d char_id=%d)\n", party_id, char_id);
  340. }
  341. // パーティ情報まとめ送り
  342. static void mapif_party_info(int fd, struct party* p, int char_id)
  343. {
  344. unsigned char buf[8 + sizeof(struct party)];
  345. WBUFW(buf,0) = 0x3821;
  346. WBUFW(buf,2) = 8 + sizeof(struct party);
  347. WBUFL(buf,4) = char_id;
  348. memcpy(WBUFP(buf,8), p, sizeof(struct party));
  349. if(fd<0)
  350. mapif_sendall(buf,WBUFW(buf,2));
  351. else
  352. mapif_send(fd,buf,WBUFW(buf,2));
  353. }
  354. // パーティメンバ追加可否
  355. int mapif_party_memberadded(int fd, int party_id, int account_id, int char_id, int flag) {
  356. WFIFOHEAD(fd, 15);
  357. WFIFOW(fd,0) = 0x3822;
  358. WFIFOL(fd,2) = party_id;
  359. WFIFOL(fd,6) = account_id;
  360. WFIFOL(fd,10) = char_id;
  361. WFIFOB(fd,14) = flag;
  362. WFIFOSET(fd,15);
  363. return 0;
  364. }
  365. // パーティ設定変更通知
  366. int mapif_party_optionchanged(int fd,struct party *p,int account_id,int flag)
  367. {
  368. unsigned char buf[16];
  369. WBUFW(buf,0)=0x3823;
  370. WBUFL(buf,2)=p->party_id;
  371. WBUFL(buf,6)=account_id;
  372. WBUFW(buf,10)=p->exp;
  373. WBUFW(buf,12)=p->item;
  374. WBUFB(buf,14)=flag;
  375. if(flag==0)
  376. mapif_sendall(buf,15);
  377. else
  378. mapif_send(fd,buf,15);
  379. return 0;
  380. }
  381. // パーティ脱退通知
  382. int mapif_party_withdraw(int party_id,int account_id, int char_id) {
  383. unsigned char buf[16];
  384. WBUFW(buf,0) = 0x3824;
  385. WBUFL(buf,2) = party_id;
  386. WBUFL(buf,6) = account_id;
  387. WBUFL(buf,10) = char_id;
  388. mapif_sendall(buf, 14);
  389. return 0;
  390. }
  391. // パーティマップ更新通知
  392. int mapif_party_membermoved(struct party *p,int idx)
  393. {
  394. unsigned char buf[20];
  395. WBUFW(buf,0) = 0x3825;
  396. WBUFL(buf,2) = p->party_id;
  397. WBUFL(buf,6) = p->member[idx].account_id;
  398. WBUFL(buf,10) = p->member[idx].char_id;
  399. WBUFW(buf,14) = p->member[idx].map;
  400. WBUFB(buf,16) = p->member[idx].online;
  401. WBUFW(buf,17) = p->member[idx].lv;
  402. mapif_sendall(buf, 19);
  403. return 0;
  404. }
  405. // パーティ解散通知
  406. int mapif_party_broken(int party_id,int flag)
  407. {
  408. unsigned char buf[16];
  409. WBUFW(buf,0)=0x3826;
  410. WBUFL(buf,2)=party_id;
  411. WBUFB(buf,6)=flag;
  412. mapif_sendall(buf,7);
  413. //printf("int_party: broken %d\n",party_id);
  414. return 0;
  415. }
  416. // パーティ内発言
  417. int mapif_party_message(int party_id,int account_id,char *mes,int len, int sfd)
  418. {
  419. unsigned char buf[512];
  420. WBUFW(buf,0)=0x3827;
  421. WBUFW(buf,2)=len+12;
  422. WBUFL(buf,4)=party_id;
  423. WBUFL(buf,8)=account_id;
  424. memcpy(WBUFP(buf,12),mes,len);
  425. mapif_sendallwos(sfd, buf,len+12);
  426. return 0;
  427. }
  428. //-------------------------------------------------------------------
  429. // map serverからの通信
  430. // Create Party
  431. int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct party_member *leader)
  432. {
  433. struct party_data *p;
  434. int i;
  435. if( (p=search_partyname(name))!=NULL){
  436. mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
  437. return 0;
  438. }
  439. // Check Authorised letters/symbols in the name of the character
  440. if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
  441. for (i = 0; i < NAME_LENGTH && name[i]; i++)
  442. if (strchr(char_name_letters, name[i]) == NULL) {
  443. mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
  444. return 0;
  445. }
  446. } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
  447. for (i = 0; i < NAME_LENGTH && name[i]; i++)
  448. if (strchr(char_name_letters, name[i]) != NULL) {
  449. mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
  450. return 0;
  451. }
  452. }
  453. p = (struct party_data*)aCalloc(1, sizeof(struct party_data));
  454. memcpy(p->party.name,name,NAME_LENGTH);
  455. p->party.exp=0;
  456. p->party.item=(item?1:0)|(item2?2:0);
  457. memcpy(&p->party.member[0], leader, sizeof(struct party_member));
  458. p->party.member[0].leader=1;
  459. p->party.member[0].online=1;
  460. p->party.party_id=-1;//New party.
  461. if (inter_party_tosql(&p->party,PS_CREATE|PS_ADDMEMBER,0)) {
  462. //Add party to db
  463. int_party_calc_state(p);
  464. idb_put(party_db_, p->party.party_id, p);
  465. mapif_party_info(fd, &p->party, 0);
  466. mapif_party_created(fd,leader->account_id,leader->char_id,&p->party);
  467. } else { //Failed to create party.
  468. aFree(p);
  469. mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
  470. }
  471. return 0;
  472. }
  473. // パーティ情報要求
  474. static void mapif_parse_PartyInfo(int fd, int party_id, int char_id)
  475. {
  476. struct party_data *p;
  477. p = inter_party_fromsql(party_id);
  478. if (p)
  479. mapif_party_info(fd, &p->party, char_id);
  480. else
  481. mapif_party_noinfo(fd, party_id, char_id);
  482. }
  483. // パーティ追加要求
  484. int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member)
  485. {
  486. struct party_data *p;
  487. int i;
  488. p = inter_party_fromsql(party_id);
  489. if( p == NULL || p->size == MAX_PARTY ) {
  490. mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 1);
  491. return 0;
  492. }
  493. ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == 0 );
  494. if( i == MAX_PARTY )
  495. {// Party full
  496. mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 1);
  497. return 0;
  498. }
  499. memcpy(&p->party.member[i], member, sizeof(struct party_member));
  500. p->party.member[i].leader = 0;
  501. if (p->party.member[i].online) p->party.count++;
  502. p->size++;
  503. if (p->size == 2 || p->size == 3) // Check family state. And also accept either of their Parents. [RoM]
  504. int_party_calc_state(p);
  505. else //Check even share range.
  506. if (member->lv < p->min_lv || member->lv > p->max_lv || p->family) {
  507. if (p->family) p->family = 0; //Family state broken.
  508. int_party_check_lv(p);
  509. }
  510. mapif_party_info(-1, &p->party, 0);
  511. mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 0);
  512. inter_party_tosql(&p->party, PS_ADDMEMBER, i);
  513. return 0;
  514. }
  515. // パーティー設定変更要求
  516. int mapif_parse_PartyChangeOption(int fd,int party_id,int account_id,int exp,int item)
  517. {
  518. struct party_data *p;
  519. int flag = 0;
  520. p = inter_party_fromsql(party_id);
  521. if(!p)
  522. return 0;
  523. p->party.exp=exp;
  524. if( exp && !party_check_exp_share(p) ){
  525. flag|=0x01;
  526. p->party.exp=0;
  527. }
  528. p->party.item = item&0x3; //Filter out invalid values.
  529. mapif_party_optionchanged(fd,&p->party,account_id,flag);
  530. inter_party_tosql(&p->party, PS_BASIC, 0);
  531. return 0;
  532. }
  533. // パーティ脱退要求
  534. int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
  535. {
  536. struct party_data *p;
  537. int i,j=-1;
  538. p = inter_party_fromsql(party_id);
  539. if( p == NULL )
  540. {// Party does not exists?
  541. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) )
  542. Sql_ShowDebug(sql_handle);
  543. return 0;
  544. }
  545. for (i = 0; i < MAX_PARTY; i++) {
  546. if(p->party.member[i].account_id == account_id &&
  547. p->party.member[i].char_id == char_id) {
  548. break;
  549. }
  550. }
  551. if (i >= MAX_PARTY)
  552. return 0; //Member not found?
  553. mapif_party_withdraw(party_id, account_id, char_id);
  554. if (p->party.member[i].leader){
  555. p->party.member[i].account_id = 0;
  556. for (j = 0; j < MAX_PARTY; j++) {
  557. if (!p->party.member[j].account_id)
  558. continue;
  559. mapif_party_withdraw(party_id, p->party.member[j].account_id, p->party.member[j].char_id);
  560. p->party.member[j].account_id = 0;
  561. }
  562. //Party gets deleted on the check_empty call below.
  563. } else {
  564. inter_party_tosql(&p->party,PS_DELMEMBER,i);
  565. j = p->party.member[i].lv;
  566. if(p->party.member[i].online) p->party.count--;
  567. memset(&p->party.member[i], 0, sizeof(struct party_member));
  568. p->size--;
  569. if (j == p->min_lv || j == p->max_lv || p->family)
  570. {
  571. if(p->family) p->family = 0; //Family state broken.
  572. int_party_check_lv(p);
  573. }
  574. }
  575. if (party_check_empty(p) == 0)
  576. mapif_party_info(-1, &p->party, 0);
  577. return 0;
  578. }
  579. // When member goes to other map or levels up.
  580. int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id, unsigned short map, int online, unsigned int lv)
  581. {
  582. struct party_data *p;
  583. int i;
  584. p = inter_party_fromsql(party_id);
  585. if (p == NULL)
  586. return 0;
  587. for(i = 0; i < MAX_PARTY &&
  588. (p->party.member[i].account_id != account_id ||
  589. p->party.member[i].char_id != char_id); i++);
  590. if (i == MAX_PARTY) return 0;
  591. if (p->party.member[i].online != online)
  592. {
  593. p->party.member[i].online = online;
  594. if (online)
  595. p->party.count++;
  596. else
  597. p->party.count--;
  598. // Even share check situations: Family state (always breaks)
  599. // character logging on/off is max/min level (update level range)
  600. // or character logging on/off has a different level (update level range using new level)
  601. if (p->family ||
  602. (p->party.member[i].lv <= p->min_lv || p->party.member[i].lv >= p->max_lv) ||
  603. (p->party.member[i].lv != lv && (lv <= p->min_lv || lv >= p->max_lv))
  604. )
  605. {
  606. p->party.member[i].lv = lv;
  607. int_party_check_lv(p);
  608. }
  609. //Send online/offline update.
  610. mapif_party_membermoved(&p->party, i);
  611. }
  612. if (p->party.member[i].lv != lv) {
  613. if(p->party.member[i].lv == p->min_lv ||
  614. p->party.member[i].lv == p->max_lv)
  615. {
  616. p->party.member[i].lv = lv;
  617. int_party_check_lv(p);
  618. } else
  619. p->party.member[i].lv = lv;
  620. //There is no need to send level update to map servers
  621. //since they do nothing with it.
  622. }
  623. if (p->party.member[i].map != map) {
  624. p->party.member[i].map = map;
  625. mapif_party_membermoved(&p->party, i);
  626. }
  627. return 0;
  628. }
  629. // パーティ解散要求
  630. int mapif_parse_BreakParty(int fd,int party_id)
  631. {
  632. struct party_data *p;
  633. p = inter_party_fromsql(party_id);
  634. if(!p)
  635. return 0;
  636. inter_party_tosql(&p->party,PS_BREAK,0);
  637. mapif_party_broken(fd,party_id);
  638. return 0;
  639. }
  640. // パーティメッセージ送信
  641. int mapif_parse_PartyMessage(int fd,int party_id,int account_id,char *mes,int len)
  642. {
  643. return mapif_party_message(party_id,account_id,mes,len, fd);
  644. }
  645. int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id)
  646. {
  647. struct party_data *p;
  648. int i;
  649. p = inter_party_fromsql(party_id);
  650. if(!p)
  651. return 0;
  652. for (i = 0; i < MAX_PARTY; i++)
  653. {
  654. if(p->party.member[i].leader)
  655. p->party.member[i].leader = 0;
  656. if(p->party.member[i].account_id == account_id &&
  657. p->party.member[i].char_id == char_id)
  658. {
  659. p->party.member[i].leader = 1;
  660. inter_party_tosql(&p->party,PS_LEADER, i);
  661. }
  662. }
  663. return 1;
  664. }
  665. // map server からの通信
  666. // ・1パケットのみ解析すること
  667. // ・パケット長データはinter.cにセットしておくこと
  668. // ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
  669. // ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
  670. int inter_party_parse_frommap(int fd)
  671. {
  672. RFIFOHEAD(fd);
  673. switch(RFIFOW(fd,0)) {
  674. case 0x3020: mapif_parse_CreateParty(fd, (char*)RFIFOP(fd,4), RFIFOB(fd,28), RFIFOB(fd,29), (struct party_member*)RFIFOP(fd,30)); break;
  675. case 0x3021: mapif_parse_PartyInfo(fd, RFIFOL(fd,2), RFIFOL(fd,6)); break;
  676. case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,4), (struct party_member*)RFIFOP(fd,8)); break;
  677. case 0x3023: mapif_parse_PartyChangeOption(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOW(fd,10), RFIFOW(fd,12)); break;
  678. case 0x3024: mapif_parse_PartyLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;
  679. case 0x3025: mapif_parse_PartyChangeMap(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOW(fd,14), RFIFOB(fd,16), RFIFOW(fd,17)); break;
  680. case 0x3026: mapif_parse_BreakParty(fd, RFIFOL(fd,2)); break;
  681. case 0x3027: mapif_parse_PartyMessage(fd, RFIFOL(fd,4), RFIFOL(fd,8), (char*)RFIFOP(fd,12), RFIFOW(fd,2)-12); break;
  682. case 0x3029: mapif_parse_PartyLeaderChange(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;
  683. default:
  684. return 0;
  685. }
  686. return 1;
  687. }
  688. // サーバーから脱退要求(キャラ削除用)
  689. int inter_party_leave(int party_id,int account_id, int char_id)
  690. {
  691. return mapif_parse_PartyLeave(-1,party_id,account_id, char_id);
  692. }
  693. int inter_party_CharOnline(int char_id, int party_id)
  694. {
  695. struct party_data* p;
  696. int i;
  697. if( party_id == -1 )
  698. {// Get party_id from the database
  699. char* data;
  700. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) )
  701. {
  702. Sql_ShowDebug(sql_handle);
  703. return 0;
  704. }
  705. if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  706. return 0; //Eh? No party?
  707. Sql_GetData(sql_handle, 0, &data, NULL);
  708. party_id = atoi(data);
  709. Sql_FreeResult(sql_handle);
  710. }
  711. if (party_id == 0)
  712. return 0; //No party...
  713. p = inter_party_fromsql(party_id);
  714. if(!p) {
  715. ShowError("Character %d's party %d not found!\n", char_id, party_id);
  716. return 0;
  717. }
  718. //Set member online
  719. for(i=0; i<MAX_PARTY; i++) {
  720. if (p->party.member[i].char_id == char_id) {
  721. if (!p->party.member[i].online) {
  722. p->party.member[i].online = 1;
  723. p->party.count++;
  724. if (p->party.member[i].lv < p->min_lv ||
  725. p->party.member[i].lv > p->max_lv)
  726. int_party_check_lv(p);
  727. }
  728. break;
  729. }
  730. }
  731. return 1;
  732. }
  733. int inter_party_CharOffline(int char_id, int party_id) {
  734. struct party_data *p=NULL;
  735. int i;
  736. if( party_id == -1 )
  737. {// Get guild_id from the database
  738. char* data;
  739. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) )
  740. {
  741. Sql_ShowDebug(sql_handle);
  742. return 0;
  743. }
  744. if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  745. return 0; //Eh? No party?
  746. Sql_GetData(sql_handle, 0, &data, NULL);
  747. party_id = atoi(data);
  748. Sql_FreeResult(sql_handle);
  749. }
  750. if (party_id == 0)
  751. return 0; //No party...
  752. //Character has a party, set character offline and check if they were the only member online
  753. if ((p = inter_party_fromsql(party_id)) == NULL)
  754. return 0;
  755. //Set member offline
  756. for(i=0; i< MAX_PARTY; i++) {
  757. if(p->party.member[i].char_id == char_id)
  758. {
  759. p->party.member[i].online = 0;
  760. p->party.count--;
  761. if(p->party.member[i].lv == p->min_lv ||
  762. p->party.member[i].lv == p->max_lv)
  763. int_party_check_lv(p);
  764. break;
  765. }
  766. }
  767. if(!p->party.count)
  768. //Parties don't have any data that needs be saved at this point... so just remove it from memory.
  769. idb_remove(party_db_, party_id);
  770. return 1;
  771. }
  772. #endif //TXT_SQL_CONVERT