party.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  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/timer.h"
  8. #include "../common/socket.h"
  9. #include "../common/nullpo.h"
  10. #include "../common/malloc.h"
  11. #include "../common/showmsg.h"
  12. #include "party.h"
  13. #include "pc.h"
  14. #include "map.h"
  15. #include "battle.h"
  16. #include "intif.h"
  17. #include "clif.h"
  18. #include "log.h"
  19. #include "skill.h"
  20. #include "status.h"
  21. static struct dbt* party_db;
  22. static struct party_data* party_cache = NULL; //party in cache for skipping consecutive lookups. [Skotlex]
  23. int party_share_level = 10;
  24. int party_send_xy_timer(int tid,unsigned int tick,int id,int data);
  25. /*==========================================
  26. * Fills the given party_member structure according to the sd provided.
  27. * Used when creating/adding people to a party. [Skotlex]
  28. *------------------------------------------
  29. */
  30. static void party_fill_member(struct party_member *member, struct map_session_data *sd) {
  31. member->account_id = sd->status.account_id;
  32. member->char_id = sd->status.char_id;
  33. memcpy(member->name,sd->status.name,NAME_LENGTH);
  34. member->class_ = sd->status.class_;
  35. member->map = sd->mapindex;
  36. member->lv = sd->status.base_level;
  37. member->online = 1;
  38. member->leader = 0;
  39. }
  40. /*==========================================
  41. * �I—¹
  42. *------------------------------------------
  43. */
  44. void do_final_party(void)
  45. {
  46. party_db->destroy(party_db,NULL);
  47. }
  48. // �‰Šú‰»
  49. void do_init_party(void)
  50. {
  51. party_db=db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int));
  52. add_timer_func_list(party_send_xy_timer,"party_send_xy_timer");
  53. add_timer_interval(gettick()+battle_config.party_update_interval,party_send_xy_timer,0,0,battle_config.party_update_interval);
  54. }
  55. // ŒŸ�õ
  56. struct party_data *party_search(int party_id)
  57. {
  58. if(!party_id) return NULL;
  59. if (party_cache && party_cache->party.party_id == party_id)
  60. return party_cache;
  61. party_cache = idb_get(party_db,party_id);
  62. return party_cache;
  63. }
  64. int party_searchname_sub(DBKey key,void *data,va_list ap)
  65. {
  66. struct party_data *p=(struct party_data *)data,**dst;
  67. char *str;
  68. str=va_arg(ap,char *);
  69. dst=va_arg(ap,struct party_data **);
  70. if(strncmpi(p->party.name,str,NAME_LENGTH)==0)
  71. *dst=p;
  72. return 0;
  73. }
  74. struct party_data* party_searchname(char *str)
  75. {
  76. struct party_data *p=NULL;
  77. party_db->foreach(party_db,party_searchname_sub,str,&p);
  78. return p;
  79. }
  80. int party_create(struct map_session_data *sd,char *name,int item,int item2)
  81. {
  82. struct party_member leader;
  83. nullpo_retr(0, sd);
  84. if(sd->status.party_id) {
  85. clif_party_created(sd,2);
  86. return 0;
  87. }
  88. party_fill_member(&leader, sd);
  89. leader.leader = 1;
  90. intif_create_party(&leader,name,item,item2);
  91. return 0;
  92. }
  93. int party_created(int account_id,int char_id,int fail,int party_id,char *name)
  94. {
  95. struct map_session_data *sd;
  96. struct party_data *p;
  97. sd=map_id2sd(account_id);
  98. nullpo_retr(0, sd);
  99. if (sd->status.char_id != char_id)
  100. return 0; //unlikely failure...
  101. if(fail){
  102. clif_party_created(sd,1);
  103. return 0;
  104. }
  105. sd->status.party_id=party_id;
  106. if(idb_get(party_db,party_id)!=NULL){
  107. ShowFatalError("party: id already exists!\n");
  108. exit(1);
  109. }
  110. p=(struct party_data *)aCalloc(1,sizeof(struct party_data));
  111. p->party.party_id=party_id;
  112. memcpy(p->party.name, name, NAME_LENGTH);
  113. idb_put(party_db,party_id,p);
  114. clif_party_created(sd,0); //Success message
  115. clif_charnameupdate(sd); //Update other people's display. [Skotlex]
  116. return 1;
  117. }
  118. int party_request_info(int party_id)
  119. {
  120. return intif_request_partyinfo(party_id);
  121. }
  122. int party_check_member(struct party *p)
  123. {
  124. int i, users;
  125. struct map_session_data *sd, **all_sd;
  126. nullpo_retr(0, p);
  127. all_sd = map_getallusers(&users);
  128. for(i=0;i<users;i++)
  129. {
  130. if((sd = all_sd[i]) && sd->status.party_id==p->party_id)
  131. {
  132. int j,f=1;
  133. for(j=0;j<MAX_PARTY;j++){
  134. if(p->member[j].account_id==sd->status.account_id &&
  135. p->member[j].char_id==sd->status.char_id)
  136. {
  137. f=0;
  138. break;
  139. }
  140. }
  141. if(f){
  142. sd->status.party_id=0;
  143. if(battle_config.error_log)
  144. ShowWarning("party: check_member %d[%s] is not member\n",sd->status.account_id,sd->status.name);
  145. }
  146. }
  147. }
  148. return 0;
  149. }
  150. int party_recv_noinfo(int party_id)
  151. {
  152. int i, users;
  153. struct map_session_data *sd, **all_sd;
  154. all_sd = map_getallusers(&users);
  155. for(i=0;i<users;i++){
  156. if((sd = all_sd[i]) && sd->status.party_id==party_id)
  157. sd->status.party_id=0;
  158. }
  159. return 0;
  160. }
  161. static void* create_party(DBKey key, va_list args) {
  162. struct party_data *p;
  163. p=(struct party_data *)aCalloc(1,sizeof(struct party_data));
  164. return p;
  165. }
  166. static void party_check_state(struct party_data *p)
  167. {
  168. int i;
  169. malloc_set(&p->state, 0, sizeof(p->state));
  170. for (i = 0; i < MAX_PARTY; i ++)
  171. {
  172. if (!p->party.member[i].online) continue; //Those not online shouldn't aport to skill usage and all that.
  173. switch (p->party.member[i].class_) {
  174. case JOB_MONK:
  175. case JOB_BABY_MONK:
  176. case JOB_CHAMPION:
  177. p->state.monk = 1;
  178. break;
  179. case JOB_STAR_GLADIATOR:
  180. p->state.sg = 1;
  181. break;
  182. case JOB_SUPER_NOVICE:
  183. case JOB_SUPER_BABY:
  184. p->state.snovice = 1;
  185. break;
  186. case JOB_TAEKWON:
  187. p->state.tk = 1;
  188. break;
  189. }
  190. }
  191. }
  192. int party_recv_info(struct party *sp)
  193. {
  194. struct map_session_data *sd;
  195. struct party_data *p;
  196. int i;
  197. nullpo_retr(0, sp);
  198. p= idb_ensure(party_db, sp->party_id, create_party);
  199. if (!p->party.party_id) //party just received.
  200. party_check_member(sp);
  201. memcpy(&p->party,sp,sizeof(struct party));
  202. malloc_set(&p->state, 0, sizeof(p->state));
  203. malloc_set(&p->data, 0, sizeof(p->data));
  204. for(i=0;i<MAX_PARTY;i++){
  205. if (!p->party.member[i].account_id)
  206. continue;
  207. sd = map_id2sd(p->party.member[i].account_id);
  208. if (sd && sd->status.party_id==p->party.party_id
  209. && sd->status.char_id == p->party.member[i].char_id
  210. && !sd->state.waitingdisconnect)
  211. p->data[i].sd = sd;
  212. }
  213. party_check_state(p);
  214. for(i=0;i<MAX_PARTY;i++){
  215. sd = p->data[i].sd;
  216. if(!sd || sd->state.party_sent)
  217. continue;
  218. clif_party_main_info(p,-1);
  219. clif_party_option(p,sd,0x100);
  220. clif_party_info(p,-1);
  221. sd->state.party_sent=1;
  222. }
  223. return 0;
  224. }
  225. int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
  226. {
  227. struct party_data *p=party_search(sd->status.party_id);
  228. int i,flag=0;
  229. nullpo_retr(0, sd);
  230. if(tsd==NULL || p==NULL)
  231. return 0;
  232. if(!battle_config.invite_request_check) {
  233. if (tsd->guild_invite>0 || tsd->trade_partner) {
  234. clif_party_inviteack(sd,tsd->status.name,0);
  235. return 0;
  236. }
  237. }
  238. if( tsd->status.party_id>0 || tsd->party_invite>0 ){
  239. clif_party_inviteack(sd,tsd->status.name,0);
  240. return 0;
  241. }
  242. for(i=0;i<MAX_PARTY;i++){
  243. if(p->party.member[i].account_id == 0) //Room for a new member.
  244. flag = 1;
  245. /* By default Aegis BLOCKS more than one char from the same account on a party.
  246. * But eA does support it... so this check is left commented.
  247. if(p->party.member[i].account_id==tsd->status.account_id)
  248. {
  249. clif_party_inviteack(sd,tsd->status.name,4);
  250. return 0;
  251. }
  252. */
  253. }
  254. if (!flag) { //Full party.
  255. clif_party_inviteack(sd,tsd->status.name,3);
  256. return 0;
  257. }
  258. tsd->party_invite=sd->status.party_id;
  259. tsd->party_invite_account=sd->status.account_id;
  260. clif_party_invite(sd,tsd);
  261. return 1;
  262. }
  263. int party_reply_invite(struct map_session_data *sd,int account_id,int flag)
  264. {
  265. struct map_session_data *tsd= map_id2sd(account_id);
  266. struct party_member member;
  267. nullpo_retr(0, sd);
  268. if(flag==1){
  269. party_fill_member(&member, sd);
  270. intif_party_addmember(sd->party_invite, &member);
  271. return 0;
  272. }
  273. sd->party_invite=0;
  274. sd->party_invite_account=0;
  275. if(tsd==NULL)
  276. return 0;
  277. clif_party_inviteack(tsd,sd->status.name,1);
  278. return 1;
  279. }
  280. int party_member_added(int party_id,int account_id,int char_id, int flag)
  281. {
  282. struct map_session_data *sd = map_id2sd(account_id),*sd2;
  283. struct party_data *p = party_search(party_id);
  284. if(sd == NULL || sd->status.char_id != char_id){
  285. if (flag == 0) {
  286. if(battle_config.error_log)
  287. ShowError("party: member added error %d is not online\n",account_id);
  288. intif_party_leave(party_id,account_id,char_id);
  289. }
  290. return 0;
  291. }
  292. sd->party_invite=0;
  293. sd->party_invite_account=0;
  294. if (!p) {
  295. if(battle_config.error_log)
  296. ShowError("party_member_added: party %d not found.\n",party_id);
  297. intif_party_leave(party_id,account_id,char_id);
  298. return 0;
  299. }
  300. if(!flag) {
  301. sd->state.party_sent=0;
  302. sd->status.party_id=party_id;
  303. party_check_conflict(sd);
  304. clif_party_join_info(&p->party,sd);
  305. clif_party_hp(sd);
  306. clif_party_xy(sd);
  307. clif_charnameupdate(sd); //Update char name's display [Skotlex]
  308. }
  309. sd2=map_id2sd(sd->party_invite_account);
  310. if (sd2)
  311. clif_party_inviteack(sd2,sd->status.name,flag?2:1);
  312. return 0;
  313. }
  314. int party_removemember(struct map_session_data *sd,int account_id,char *name)
  315. {
  316. struct party_data *p;
  317. int i;
  318. nullpo_retr(0, sd);
  319. if( (p = party_search(sd->status.party_id)) == NULL )
  320. return 0;
  321. for(i=0;i<MAX_PARTY;i++){
  322. if(p->party.member[i].account_id==sd->status.account_id &&
  323. p->party.member[i].char_id==sd->status.char_id) {
  324. if(p->party.member[i].leader)
  325. break;
  326. return 0;
  327. }
  328. }
  329. if (i >= MAX_PARTY) //Request from someone not in party? o.O
  330. return 0;
  331. for(i=0;i<MAX_PARTY;i++){
  332. if(p->party.member[i].account_id==account_id &&
  333. strncmp(p->party.member[i].name,name,NAME_LENGTH)==0)
  334. {
  335. intif_party_leave(p->party.party_id,account_id,p->party.member[i].char_id);
  336. return 1;
  337. }
  338. }
  339. return 0;
  340. }
  341. int party_leave(struct map_session_data *sd)
  342. {
  343. struct party_data *p;
  344. int i;
  345. nullpo_retr(0, sd);
  346. if( (p = party_search(sd->status.party_id)) == NULL )
  347. return 0;
  348. for(i=0;i<MAX_PARTY;i++){
  349. if(p->party.member[i].account_id==sd->status.account_id &&
  350. p->party.member[i].char_id==sd->status.char_id){
  351. intif_party_leave(p->party.party_id,sd->status.account_id,sd->status.char_id);
  352. return 0;
  353. }
  354. }
  355. return 0;
  356. }
  357. int party_member_leaved(int party_id,int account_id,int char_id)
  358. {
  359. struct map_session_data *sd=map_id2sd(account_id);
  360. struct party_data *p=party_search(party_id);
  361. int i;
  362. if (sd && sd->status.char_id != char_id) //Wrong target
  363. sd = NULL;
  364. if(p!=NULL){
  365. for(i=0;i<MAX_PARTY;i++)
  366. if(p->party.member[i].account_id==account_id &&
  367. p->party.member[i].char_id==char_id){
  368. clif_party_leaved(p,sd,account_id,p->party.member[i].name,0x00);
  369. malloc_set(&p->party.member[i], 0, sizeof(p->party.member[0]));
  370. malloc_set(&p->data[i], 0, sizeof(p->data[0]));
  371. p->party.count--;
  372. party_check_state(p);
  373. break;
  374. }
  375. }
  376. if(sd!=NULL && sd->status.party_id==party_id){
  377. sd->status.party_id=0;
  378. sd->state.party_sent=0;
  379. clif_charnameupdate(sd); //Update name display [Skotlex]
  380. }
  381. return 0;
  382. }
  383. int party_broken(int party_id)
  384. {
  385. struct party_data *p;
  386. int i;
  387. if( (p=party_search(party_id))==NULL )
  388. return 0;
  389. for(i=0;i<MAX_PARTY;i++){
  390. if(p->data[i].sd!=NULL){
  391. clif_party_leaved(p,p->data[i].sd,
  392. p->party.member[i].account_id,p->party.member[i].name,0x10);
  393. p->data[i].sd->status.party_id=0;
  394. p->data[i].sd->state.party_sent=0;
  395. }
  396. }
  397. if (party_cache && party_cache->party.party_id == party_id)
  398. party_cache = NULL;
  399. idb_remove(party_db,party_id);
  400. return 0;
  401. }
  402. int party_changeoption(struct map_session_data *sd,int exp,int item)
  403. {
  404. nullpo_retr(0, sd);
  405. if( sd->status.party_id==0)
  406. return 0;
  407. intif_party_changeoption(sd->status.party_id,sd->status.account_id,exp,item);
  408. return 0;
  409. }
  410. int party_optionchanged(int party_id,int account_id,int exp,int item,int flag)
  411. {
  412. struct party_data *p;
  413. struct map_session_data *sd=map_id2sd(account_id);
  414. if( (p=party_search(party_id))==NULL)
  415. return 0;
  416. if(!(flag&0x01) && p->party.exp != exp) {
  417. p->party.exp=exp;
  418. clif_party_option(p,sd,flag); //This packet doesn't updates item info anymore...
  419. }
  420. if(!(flag&0x10) && p->party.item != item) {
  421. p->party.item=item;
  422. clif_party_main_info(p,-1);
  423. }
  424. if(flag&0x01) //Send denied message
  425. clif_party_option(p,sd,flag);
  426. return 0;
  427. }
  428. int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short map,int online,int lv)
  429. {
  430. struct party_data *p;
  431. int i;
  432. if( (p=party_search(party_id))==NULL)
  433. return 0;
  434. for(i=0;i<MAX_PARTY;i++){
  435. struct map_session_data *sd;
  436. struct party_member *m=&p->party.member[i];
  437. if(m->account_id==account_id && m->char_id==char_id){
  438. m->map = map;
  439. m->online=online;
  440. m->lv=lv;
  441. //Check if they still exist on this map server
  442. sd = map_id2sd(m->account_id);
  443. p->data[i].sd = (sd!=NULL && sd->status.party_id==p->party.party_id && sd->status.char_id == m->char_id && !sd->state.waitingdisconnect)?sd:NULL;
  444. break;
  445. }
  446. }
  447. if(i==MAX_PARTY){
  448. if(battle_config.error_log)
  449. ShowError("party: not found member %d/%d on %d[%s]",account_id,char_id,party_id,p->party.name);
  450. return 0;
  451. }
  452. clif_party_info(p,-1);
  453. return 0;
  454. }
  455. int party_send_movemap(struct map_session_data *sd)
  456. {
  457. int i;
  458. struct party_data *p;
  459. nullpo_retr(0, sd);
  460. if( sd->status.party_id==0 )
  461. return 0;
  462. intif_party_changemap(sd,1);
  463. p=party_search(sd->status.party_id);
  464. if (p && sd->fd) {
  465. //Send dots of other party members to this char. [Skotlex]
  466. for(i=0; i < MAX_PARTY; i++) {
  467. if (!p->data[i].sd || p->data[i].sd == sd ||
  468. p->data[i].sd->bl.m != sd->bl.m)
  469. continue;
  470. clif_party_xy_single(sd->fd, p->data[i].sd);
  471. }
  472. }
  473. if( sd->state.party_sent )
  474. return 0;
  475. party_check_conflict(sd);
  476. if(p){
  477. party_check_member(&p->party);
  478. if(sd->status.party_id==p->party.party_id){
  479. clif_party_main_info(p,sd->fd);
  480. clif_party_option(p,sd,0x100);
  481. clif_party_info(p,sd->fd);
  482. sd->state.party_sent=1;
  483. }
  484. }
  485. return 0;
  486. }
  487. int party_send_logout(struct map_session_data *sd)
  488. {
  489. struct party_data *p;
  490. int i;
  491. if(!sd->status.party_id)
  492. return 0;
  493. intif_party_changemap(sd,0);
  494. p=party_search(sd->status.party_id);
  495. if(!p) return 0;
  496. for(i=0;i<MAX_PARTY && p->data[i].sd != sd;i++);
  497. if (i < MAX_PARTY)
  498. malloc_set(&p->data[i], 0, sizeof(p->data[0]));
  499. return 1;
  500. }
  501. int party_send_message(struct map_session_data *sd,char *mes,int len)
  502. {
  503. if(sd->status.party_id==0)
  504. return 0;
  505. intif_party_message(sd->status.party_id,sd->status.account_id,mes,len);
  506. party_recv_message(sd->status.party_id,sd->status.account_id,mes,len);
  507. //Chat Logging support Type 'P'
  508. if(log_config.chat&1 //we log everything then
  509. || (log_config.chat&4 //if Party bit is on
  510. && ( !agit_flag || !(log_config.chat&16) ))) //if WOE ONLY flag is off or AGIT is OFF
  511. log_chat("P", sd->status.party_id, sd->status.char_id, sd->status.account_id, (char*)mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes);
  512. return 0;
  513. }
  514. int party_recv_message(int party_id,int account_id,char *mes,int len)
  515. {
  516. struct party_data *p;
  517. if( (p=party_search(party_id))==NULL)
  518. return 0;
  519. clif_party_message(p,account_id,mes,len);
  520. return 0;
  521. }
  522. int party_check_conflict(struct map_session_data *sd)
  523. {
  524. nullpo_retr(0, sd);
  525. intif_party_checkconflict(sd->status.party_id,sd->status.account_id,sd->status.char_id);
  526. return 0;
  527. }
  528. int party_skill_check(struct map_session_data *sd, int party_id, int skillid, int skilllv)
  529. {
  530. struct party_data *p;
  531. struct map_session_data *p_sd;
  532. int i;
  533. if(!party_id || (p=party_search(party_id))==NULL)
  534. return 0;
  535. switch(skillid) {
  536. case TK_COUNTER: //Increase Triple Attack rate of Monks.
  537. if (!p->state.monk) return 0;
  538. break;
  539. case MO_COMBOFINISH: //Increase Counter rate of Star Gladiators
  540. if (!p->state.sg) return 0;
  541. break;
  542. case AM_TWILIGHT2: //Twilight Pharmacy, requires Super Novice
  543. return p->state.snovice;
  544. case AM_TWILIGHT3: //Twilight Pharmacy, Requires Taekwon
  545. return p->state.tk;
  546. default:
  547. return 0; //Unknown case?
  548. }
  549. for(i=0;i<MAX_PARTY;i++){
  550. if ((p_sd = p->data[i].sd) == NULL)
  551. continue;
  552. if (sd->bl.m != p_sd->bl.m)
  553. continue;
  554. switch(skillid) {
  555. case TK_COUNTER: //Increase Triple Attack rate of Monks.
  556. if((p_sd->class_&MAPID_UPPERMASK) == MAPID_MONK
  557. && pc_checkskill(p_sd,MO_TRIPLEATTACK)) {
  558. sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,MO_TRIPLEATTACK,
  559. 50+50*skilllv, //+100/150/200% rate
  560. 0,0,skill_get_time(SG_FRIEND, 1));
  561. }
  562. break;
  563. case MO_COMBOFINISH: //Increase Counter rate of Star Gladiators
  564. if((p_sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR
  565. && sd->sc.data[SC_READYCOUNTER].timer != -1
  566. && pc_checkskill(p_sd,SG_FRIEND)) {
  567. sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,TK_COUNTER,
  568. 50+50*pc_checkskill(p_sd,SG_FRIEND), //+100/150/200% rate
  569. 0,0,skill_get_time(SG_FRIEND, 1));
  570. }
  571. break;
  572. }
  573. }
  574. return 0;
  575. }
  576. int party_send_xy_timer_sub(DBKey key,void *data,va_list ap)
  577. {
  578. struct party_data *p=(struct party_data *)data;
  579. struct map_session_data *sd;
  580. int i;
  581. nullpo_retr(0, p);
  582. for(i=0;i<MAX_PARTY;i++){
  583. if(!p->data[i].sd) continue;
  584. sd = p->data[i].sd;
  585. if (p->data[i].x != sd->bl.x || p->data[i].y != sd->bl.y)
  586. {
  587. clif_party_xy(sd);
  588. p->data[i].x = sd->bl.x;
  589. p->data[i].y = sd->bl.y;
  590. }
  591. if (battle_config.party_hp_mode &&
  592. p->data[i].hp != sd->battle_status.hp)
  593. {
  594. clif_party_hp(sd);
  595. p->data[i].hp = sd->battle_status.hp;
  596. }
  597. }
  598. return 0;
  599. }
  600. int party_send_xy_timer(int tid,unsigned int tick,int id,int data)
  601. {
  602. party_db->foreach(party_db,party_send_xy_timer_sub,tick);
  603. return 0;
  604. }
  605. int party_send_xy_clear(struct party_data *p)
  606. {
  607. int i;
  608. nullpo_retr(0, p);
  609. for(i=0;i<MAX_PARTY;i++){
  610. if(!p->data[i].sd) continue;
  611. p->data[i].hp = 0;
  612. p->data[i].x = 0;
  613. p->data[i].y = 0;
  614. }
  615. return 0;
  616. }
  617. // exp share and added zeny share [Valaris]
  618. int party_exp_share(struct party_data *p,struct block_list *src,unsigned int base_exp,unsigned int job_exp,int zeny)
  619. {
  620. struct map_session_data* sd[MAX_PARTY];
  621. int i;
  622. unsigned short c;
  623. nullpo_retr(0, p);
  624. for (i = c = 0; i < MAX_PARTY; i++)
  625. if ((sd[c] = p->data[i].sd)!=NULL && sd[c]->bl.m == src->m && !pc_isdead(sd[c])) {
  626. if (battle_config.idle_no_share && (sd[c]->chatID || sd[c]->vender_id || (sd[c]->idletime < (last_tick - battle_config.idle_no_share))))
  627. continue;
  628. c++;
  629. }
  630. if (c < 1)
  631. return 0;
  632. base_exp/=c;
  633. job_exp/=c;
  634. zeny/=c;
  635. if (battle_config.party_even_share_bonus && c > 1) {
  636. unsigned short bonus =100 + battle_config.party_even_share_bonus*(c-1);
  637. if (base_exp) {
  638. if (base_exp/100 > UINT_MAX/bonus)
  639. base_exp= UINT_MAX; //Exp overflow
  640. else if (base_exp > 10000)
  641. base_exp = (base_exp/100)*bonus; //Calculation overflow protection
  642. else
  643. base_exp = base_exp*bonus/100;
  644. }
  645. if (job_exp) {
  646. if (job_exp/100 > UINT_MAX/bonus)
  647. job_exp = UINT_MAX;
  648. else if (job_exp > 10000)
  649. job_exp = (job_exp/100)*bonus;
  650. else
  651. job_exp = job_exp*bonus/100;
  652. }
  653. if (zeny) {
  654. if (zeny/100 > INT_MAX/bonus)
  655. zeny = INT_MAX;
  656. else if (zeny > 10000)
  657. zeny = (zeny/100)*bonus;
  658. else
  659. zeny = zeny*bonus/100;
  660. }
  661. }
  662. for (i = 0; i < c; i++)
  663. {
  664. pc_gainexp(sd[i], src, base_exp, job_exp);
  665. if (zeny) // zeny from mobs [Valaris]
  666. pc_getzeny(sd[i],zeny);
  667. }
  668. return 0;
  669. }
  670. //Does party loot. first holds the id of the player who has time priority to take the item.
  671. int party_share_loot(struct party_data *p, TBL_PC *sd, struct item *item_data, int first)
  672. {
  673. TBL_PC *target=NULL;
  674. int i;
  675. if (p && p->party.item&2 && (first || !(battle_config.party_share_type&1))) {
  676. //item distribution to party members.
  677. if (battle_config.party_share_type&2) { //Round Robin
  678. TBL_PC *psd;
  679. i = p->itemc;
  680. do {
  681. i++;
  682. if (i >= MAX_PARTY)
  683. i = 0; // reset counter to 1st person in party so it'll stop when it reaches "itemc"
  684. if ((psd=p->data[i].sd)==NULL || sd->bl.m != psd->bl.m ||
  685. pc_isdead(psd) || (battle_config.idle_no_share && (
  686. psd->chatID || psd->vender_id || (psd->idletime < (last_tick - battle_config.idle_no_share)))
  687. ))
  688. continue;
  689. if (pc_additem(psd,item_data,item_data->amount))
  690. continue; //Chosen char can't pick up loot.
  691. //Successful pick.
  692. p->itemc = i;
  693. target = psd;
  694. break;
  695. } while (i != p->itemc);
  696. } else { //Random pick
  697. TBL_PC *psd[MAX_PARTY];
  698. int count=0;
  699. //Collect pick candidates
  700. for (i = 0; i < MAX_PARTY; i++) {
  701. if ((psd[count]=p->data[i].sd) && psd[count]->bl.m == sd->bl.m &&
  702. !pc_isdead(psd[count]) && (!battle_config.idle_no_share || (
  703. !psd[count]->chatID && !psd[count]->vender_id &&
  704. (psd[count]->idletime >= (last_tick - battle_config.idle_no_share)))
  705. ))
  706. count++;
  707. }
  708. while (count > 0) { //Pick a random member.
  709. i = rand()%count;
  710. if (pc_additem(psd[i],item_data,item_data->amount))
  711. { //Discard this receiver.
  712. psd[i] = psd[count-1];
  713. count--;
  714. } else { //Successful pick.
  715. target = psd[i];
  716. break;
  717. }
  718. }
  719. }
  720. }
  721. if (!target) { //Give it to the owner.
  722. target = sd;
  723. if ((i=pc_additem(sd,item_data,item_data->amount)))
  724. return i;
  725. }
  726. if(log_config.enable_logs&0x8) //Logs items, taken by (P)layers [Lupus]
  727. log_pick_pc(target, "P", item_data->nameid, item_data->amount, item_data);
  728. //Logs
  729. if(battle_config.party_show_share_picker && target != sd){
  730. char output[80];
  731. sprintf(output, "%s acquired the item.",target->status.name);
  732. clif_disp_onlyself(sd,output,strlen(output));
  733. }
  734. return 0;
  735. }
  736. int party_send_dot_remove(struct map_session_data *sd)
  737. {
  738. if (sd->status.party_id)
  739. clif_party_xy_remove(sd);
  740. return 0;
  741. }
  742. // To use for Taekwon's "Fighting Chant"
  743. // int c = 0;
  744. // party_foreachsamemap(party_sub_count, sd, 0, &c);
  745. int party_sub_count(struct block_list *bl, va_list ap)
  746. {
  747. struct map_session_data *sd = (TBL_PC *)bl;
  748. if (sd->state.autotrade)
  749. return 0;
  750. if (battle_config.idle_no_share && (sd->chatID || sd->vender_id || (sd->idletime < (last_tick - battle_config.idle_no_share))))
  751. return 0;
  752. return 1;
  753. }
  754. int party_foreachsamemap(int (*func)(struct block_list*,va_list),struct map_session_data *sd,int range,...)
  755. {
  756. struct party_data *p;
  757. va_list ap;
  758. int i;
  759. int x0,y0,x1,y1;
  760. struct block_list *list[MAX_PARTY];
  761. int blockcount=0;
  762. int total = 0; //Return value.
  763. nullpo_retr(0,sd);
  764. if((p=party_search(sd->status.party_id))==NULL)
  765. return 0;
  766. x0=sd->bl.x-range;
  767. y0=sd->bl.y-range;
  768. x1=sd->bl.x+range;
  769. y1=sd->bl.y+range;
  770. va_start(ap,range);
  771. for(i=0;i<MAX_PARTY;i++){
  772. struct map_session_data *psd=p->data[i].sd;
  773. if(!psd) continue;
  774. if(psd->bl.m!=sd->bl.m || !psd->bl.prev)
  775. continue;
  776. if(range &&
  777. (psd->bl.x<x0 || psd->bl.y<y0 ||
  778. psd->bl.x>x1 || psd->bl.y>y1 ) )
  779. continue;
  780. list[blockcount++]=&psd->bl;
  781. }
  782. map_freeblock_lock();
  783. for(i=0;i<blockcount;i++)
  784. total += func(list[i],ap);
  785. map_freeblock_unlock();
  786. va_end(ap);
  787. return total;
  788. }