summaryrefslogtreecommitdiff
path: root/src/map/party.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/party.c')
-rw-r--r--src/map/party.c1288
1 files changed, 644 insertions, 644 deletions
diff --git a/src/map/party.c b/src/map/party.c
index d433fa3b8..7d8cdafe2 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -1,644 +1,644 @@
-// $Id: party.c,v 1.2 2004/09/22 02:59:47 Akitasha Exp $
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "party.h"
-#include "db.h"
-#include "timer.h"
-#include "socket.h"
-#include "nullpo.h"
-#include "malloc.h"
-#include "pc.h"
-#include "map.h"
-#include "battle.h"
-#include "intif.h"
-#include "clif.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-#define PARTY_SEND_XYHP_INVERVAL 1000 // 座標やHP送信の間隔
-
-static struct dbt* party_db;
-
-int party_send_xyhp_timer(int tid,unsigned int tick,int id,int data);
-/*==========================================
- * 終了
- *------------------------------------------
- */
-static int party_db_final(void *key,void *data,va_list ap)
-{
- free(data);
- return 0;
-}
-void do_final_party(void)
-{
- if(party_db)
- numdb_final(party_db,party_db_final);
-}
-// 初期化
-void do_init_party(void)
-{
- party_db=numdb_init();
- add_timer_func_list(party_send_xyhp_timer,"party_send_xyhp_timer");
- add_timer_interval(gettick()+PARTY_SEND_XYHP_INVERVAL,party_send_xyhp_timer,0,0,PARTY_SEND_XYHP_INVERVAL);
-}
-
-// 検索
-struct party *party_search(int party_id)
-{
- return numdb_search(party_db,party_id);
-}
-int party_searchname_sub(void *key,void *data,va_list ap)
-{
- struct party *p=(struct party *)data,**dst;
- char *str;
- str=va_arg(ap,char *);
- dst=va_arg(ap,struct party **);
- if(strcmpi(p->name,str)==0)
- *dst=p;
- return 0;
-}
-// パーティ名検索
-struct party* party_searchname(char *str)
-{
- struct party *p=NULL;
- numdb_foreach(party_db,party_searchname_sub,str,&p);
- return p;
-}
-// 作成要求
-int party_create(struct map_session_data *sd,char *name)
-{
- nullpo_retr(0, sd);
-
- if(sd->status.party_id==0)
- intif_create_party(sd,name);
- else
- clif_party_created(sd,2);
- return 0;
-}
-
-// 作成可否
-int party_created(int account_id,int fail,int party_id,char *name)
-{
- struct map_session_data *sd;
- sd=map_id2sd(account_id);
-
- nullpo_retr(0, sd);
-
- if(fail==0){
- struct party *p;
- sd->status.party_id=party_id;
- if((p=numdb_search(party_db,party_id))!=NULL){
- printf("party: id already exists!\n");
- exit(1);
- }
- p=(struct party *)aCalloc(1,sizeof(struct party));
- p->party_id=party_id;
- memcpy(p->name,name,24);
- numdb_insert(party_db,party_id,p);
- clif_party_created(sd,0);
- }else{
- clif_party_created(sd,1);
- }
- return 0;
-}
-
-// 情報要求
-int party_request_info(int party_id)
-{
- return intif_request_partyinfo(party_id);
-}
-
-// 所属キャラの確認
-int party_check_member(struct party *p)
-{
- int i;
- struct map_session_data *sd;
-
- nullpo_retr(0, p);
-
- for(i=0;i<fd_max;i++){
- if(session[i] && (sd=session[i]->session_data) && sd->state.auth){
- if(sd->status.party_id==p->party_id){
- int j,f=1;
- for(j=0;j<MAX_PARTY;j++){ // パーティにデータがあるか確認
- if( p->member[j].account_id==sd->status.account_id){
- if( strcmp(p->member[j].name,sd->status.name)==0 )
- f=0; // データがある
- else
- p->member[j].sd=NULL; // 同垢別キャラだった
- }
- }
- if(f){
- sd->status.party_id=0;
- if(battle_config.error_log)
- printf("party: check_member %d[%s] is not member\n",sd->status.account_id,sd->status.name);
- }
- }
- }
- }
- return 0;
-}
-
-// 情報所得失敗(そのIDのキャラを全部未所属にする)
-int party_recv_noinfo(int party_id)
-{
- int i;
- struct map_session_data *sd;
- for(i=0;i<fd_max;i++){
- if(session[i] && (sd=session[i]->session_data) && sd->state.auth){
- if(sd->status.party_id==party_id)
- sd->status.party_id=0;
- }
- }
- return 0;
-}
-// 情報所得
-int party_recv_info(struct party *sp)
-{
- struct party *p;
- int i;
-
- nullpo_retr(0, sp);
-
- if((p=numdb_search(party_db,sp->party_id))==NULL){
- p=(struct party *)aCalloc(1,sizeof(struct party));
- numdb_insert(party_db,sp->party_id,p);
-
- // 最初のロードなのでユーザーのチェックを行う
- party_check_member(sp);
- }
- memcpy(p,sp,sizeof(struct party));
-
- for(i=0;i<MAX_PARTY;i++){ // sdの設定
- struct map_session_data *sd = map_id2sd(p->member[i].account_id);
- p->member[i].sd=(sd!=NULL && sd->status.party_id==p->party_id)?sd:NULL;
- }
-
- clif_party_info(p,-1);
-
- for(i=0;i<MAX_PARTY;i++){ // 設定情報の送信
-// struct map_session_data *sd = map_id2sd(p->member[i].account_id);
- struct map_session_data *sd = p->member[i].sd;
- if(sd!=NULL && sd->party_sended==0){
- clif_party_option(p,sd,0x100);
- sd->party_sended=1;
- }
- }
-
- return 0;
-}
-
-// パーティへの勧誘
-int party_invite(struct map_session_data *sd,int account_id)
-{
- struct map_session_data *tsd= map_id2sd(account_id);
- struct party *p=party_search(sd->status.party_id);
- int i;
-
- nullpo_retr(0, sd);
-
- if(tsd==NULL || p==NULL)
- return 0;
- if(!battle_config.invite_request_check) {
- if (tsd->guild_invite>0 || tsd->trade_partner) { // 相手が取引中かどうか
- clif_party_inviteack(sd,tsd->status.name,0);
- return 0;
- }
- }
- if( tsd->status.party_id>0 || tsd->party_invite>0 ){ // 相手の所属確認
- clif_party_inviteack(sd,tsd->status.name,0);
- return 0;
- }
- for(i=0;i<MAX_PARTY;i++){ // 同アカウント確認
- if(p->member[i].account_id==account_id){
- clif_party_inviteack(sd,tsd->status.name,0);
- return 0;
- }
- }
-
- tsd->party_invite=sd->status.party_id;
- tsd->party_invite_account=sd->status.account_id;
-
- clif_party_invite(sd,tsd);
- return 0;
-}
-// パーティ勧誘への返答
-int party_reply_invite(struct map_session_data *sd,int account_id,int flag)
-{
- struct map_session_data *tsd= map_id2sd(account_id);
-
- nullpo_retr(0, sd);
-
- if(flag==1){ // 承諾
- //inter鯖へ追加要求
- intif_party_addmember( sd->party_invite, sd->status.account_id );
- return 0;
- }
- else { // 拒否
- sd->party_invite=0;
- sd->party_invite_account=0;
- if(tsd==NULL)
- return 0;
- clif_party_inviteack(tsd,sd->status.name,1);
- }
- return 0;
-}
-// パーティが追加された
-int party_member_added(int party_id,int account_id,int flag)
-{
- struct map_session_data *sd= map_id2sd(account_id),*sd2;
- if(sd==NULL && flag==0){
- if(battle_config.error_log)
- printf("party: member added error %d is not online\n",account_id);
- intif_party_leave(party_id,account_id); // キャラ側に登録できなかったため脱退要求を出す
- return 0;
- }
- sd2=map_id2sd(sd->party_invite_account);
- sd->party_invite=0;
- sd->party_invite_account=0;
-
- if(flag==1){ // 失敗
- if( sd2!=NULL )
- clif_party_inviteack(sd2,sd->status.name,0);
- return 0;
- }
-
- // 成功
- sd->party_sended=0;
- sd->status.party_id=party_id;
-
- if( sd2!=NULL)
- clif_party_inviteack(sd2,sd->status.name,2);
-
- // いちおう競合確認
- party_check_conflict(sd);
-
- return 0;
-}
-// パーティ除名要求
-int party_removemember(struct map_session_data *sd,int account_id,char *name)
-{
- struct party *p;
- int i;
-
- nullpo_retr(0, sd);
-
- if( (p = party_search(sd->status.party_id)) == NULL )
- return 0;
-
- for(i=0;i<MAX_PARTY;i++){ // リーダーかどうかチェック
- if(p->member[i].account_id==sd->status.account_id)
- if(p->member[i].leader==0)
- return 0;
- }
-
- for(i=0;i<MAX_PARTY;i++){ // 所属しているか調べる
- if(p->member[i].account_id==account_id){
- intif_party_leave(p->party_id,account_id);
- return 0;
- }
- }
- return 0;
-}
-
-// パーティ脱退要求
-int party_leave(struct map_session_data *sd)
-{
- struct party *p;
- int i;
-
- nullpo_retr(0, sd);
-
- if( (p = party_search(sd->status.party_id)) == NULL )
- return 0;
-
- for(i=0;i<MAX_PARTY;i++){ // 所属しているか
- if(p->member[i].account_id==sd->status.account_id){
- intif_party_leave(p->party_id,sd->status.account_id);
- return 0;
- }
- }
- return 0;
-}
-// パーティメンバが脱退した
-int party_member_leaved(int party_id,int account_id,char *name)
-{
- struct map_session_data *sd=map_id2sd(account_id);
- struct party *p=party_search(party_id);
- if(p!=NULL){
- int i;
- for(i=0;i<MAX_PARTY;i++)
- if(p->member[i].account_id==account_id){
- clif_party_leaved(p,sd,account_id,name,0x00);
- p->member[i].account_id=0;
- p->member[i].sd=NULL;
- }
- }
- if(sd!=NULL && sd->status.party_id==party_id){
- sd->status.party_id=0;
- sd->party_sended=0;
- }
- return 0;
-}
-// パーティ解散通知
-int party_broken(int party_id)
-{
- struct party *p;
- int i;
- if( (p=party_search(party_id))==NULL )
- return 0;
-
- for(i=0;i<MAX_PARTY;i++){
- if(p->member[i].sd!=NULL){
- clif_party_leaved(p,p->member[i].sd,
- p->member[i].account_id,p->member[i].name,0x10);
- p->member[i].sd->status.party_id=0;
- p->member[i].sd->party_sended=0;
- }
- }
- numdb_erase(party_db,party_id);
- return 0;
-}
-// パーティの設定変更要求
-int party_changeoption(struct map_session_data *sd,int exp,int item)
-{
- struct party *p;
-
- nullpo_retr(0, sd);
-
- if( sd->status.party_id==0 || (p=party_search(sd->status.party_id))==NULL )
- return 0;
- intif_party_changeoption(sd->status.party_id,sd->status.account_id,exp,item);
- return 0;
-}
-// パーティの設定変更通知
-int party_optionchanged(int party_id,int account_id,int exp,int item,int flag)
-{
- struct party *p;
- struct map_session_data *sd=map_id2sd(account_id);
- if( (p=party_search(party_id))==NULL)
- return 0;
-
- if(!(flag&0x01)) p->exp=exp;
- if(!(flag&0x10)) p->item=item;
- clif_party_option(p,sd,flag);
- return 0;
-}
-
-// パーティメンバの移動通知
-int party_recv_movemap(int party_id,int account_id,char *map,int online,int lv)
-{
- struct party *p;
- int i;
- if( (p=party_search(party_id))==NULL)
- return 0;
- for(i=0;i<MAX_PARTY;i++){
- struct party_member *m=&p->member[i];
- if( m == NULL ){
- printf("party_recv_movemap nullpo?\n");
- return 0;
- }
- if(m->account_id==account_id){
- memcpy(m->map,map,16);
- m->online=online;
- m->lv=lv;
- break;
- }
- }
- if(i==MAX_PARTY){
- if(battle_config.error_log)
- printf("party: not found member %d on %d[%s]",account_id,party_id,p->name);
- return 0;
- }
-
- for(i=0;i<MAX_PARTY;i++){ // sd再設定
- struct map_session_data *sd= map_id2sd(p->member[i].account_id);
- p->member[i].sd=(sd!=NULL && sd->status.party_id==p->party_id)?sd:NULL;
- }
-
- party_send_xy_clear(p); // 座標再通知要請
-
- clif_party_info(p,-1);
- return 0;
-}
-
-// パーティメンバの移動
-int party_send_movemap(struct map_session_data *sd)
-{
- struct party *p;
-
- nullpo_retr(0, sd);
-
- if( sd->status.party_id==0 )
- return 0;
- intif_party_changemap(sd,1);
-
- if( sd->party_sended!=0 ) // もうパーティデータは送信済み
- return 0;
-
- // 競合確認
- party_check_conflict(sd);
-
- // あるならパーティ情報送信
- if( (p=party_search(sd->status.party_id))!=NULL ){
- party_check_member(p); // 所属を確認する
- if(sd->status.party_id==p->party_id){
- clif_party_info(p,sd->fd);
- clif_party_option(p,sd,0x100);
- sd->party_sended=1;
- }
- }
-
- return 0;
-}
-// パーティメンバのログアウト
-int party_send_logout(struct map_session_data *sd)
-{
- struct party *p;
-
- nullpo_retr(0, sd);
-
- if( sd->status.party_id>0 )
- intif_party_changemap(sd,0);
-
- // sdが無効になるのでパーティ情報から削除
- if( (p=party_search(sd->status.party_id))!=NULL ){
- int i;
- for(i=0;i<MAX_PARTY;i++)
- if(p->member[i].sd==sd)
- p->member[i].sd=NULL;
- }
-
- return 0;
-}
-// パーティメッセージ送信
-int party_send_message(struct map_session_data *sd,char *mes,int len)
-{
- if(sd->status.party_id==0)
- return 0;
- intif_party_message(sd->status.party_id,sd->status.account_id,mes,len);
- return 0;
-}
-
-// パーティメッセージ受信
-int party_recv_message(int party_id,int account_id,char *mes,int len)
-{
- struct party *p;
- if( (p=party_search(party_id))==NULL)
- return 0;
- clif_party_message(p,account_id,mes,len);
- return 0;
-}
-// パーティ競合確認
-int party_check_conflict(struct map_session_data *sd)
-{
- nullpo_retr(0, sd);
-
- intif_party_checkconflict(sd->status.party_id,sd->status.account_id,sd->status.name);
- return 0;
-}
-
-
-// 位置やHP通知用
-int party_send_xyhp_timer_sub(void *key,void *data,va_list ap)
-{
- struct party *p=(struct party *)data;
- int i;
-
- nullpo_retr(0, p);
-
- for(i=0;i<MAX_PARTY;i++){
- struct map_session_data *sd;
- if((sd=p->member[i].sd)!=NULL){
- // 座標通知
- if(sd->party_x!=sd->bl.x || sd->party_y!=sd->bl.y){
- clif_party_xy(p,sd);
- sd->party_x=sd->bl.x;
- sd->party_y=sd->bl.y;
- }
- // HP通知
- if(sd->party_hp!=sd->status.hp){
- clif_party_hp(p,sd);
- sd->party_hp=sd->status.hp;
- }
-
- }
- }
- return 0;
-}
-// 位置やHP通知
-int party_send_xyhp_timer(int tid,unsigned int tick,int id,int data)
-{
- numdb_foreach(party_db,party_send_xyhp_timer_sub,tick);
- return 0;
-}
-
-// 位置通知クリア
-int party_send_xy_clear(struct party *p)
-{
- int i;
-
- nullpo_retr(0, p);
-
- for(i=0;i<MAX_PARTY;i++){
- struct map_session_data *sd;
- if((sd=p->member[i].sd)!=NULL){
- sd->party_x=-1;
- sd->party_y=-1;
- sd->party_hp=-1;
- }
- }
- return 0;
-}
-// HP通知の必要性検査用(map_foreachinmoveareaから呼ばれる)
-int party_send_hp_check(struct block_list *bl,va_list ap)
-{
- int party_id;
- int *flag;
- struct map_session_data *sd;
-
- nullpo_retr(0, bl);
- nullpo_retr(0, ap);
- nullpo_retr(0, sd=(struct map_session_data *)bl);
-
- party_id=va_arg(ap,int);
- flag=va_arg(ap,int *);
-
- if(sd->status.party_id==party_id){
- *flag=1;
- sd->party_hp=-1;
- }
- return 0;
-}
-
-// 経験値公平分配
-int party_exp_share(struct party *p,int map,int base_exp,int job_exp)
-{
- struct map_session_data *sd;
- int i,c;
-
- nullpo_retr(0, p);
-
- for(i=c=0;i<MAX_PARTY;i++)
- if((sd=p->member[i].sd)!=NULL && sd->bl.m==map)
- c++;
- if(c==0)
- return 0;
- for(i=0;i<MAX_PARTY;i++)
- if((sd=p->member[i].sd)!=NULL && sd->bl.m==map)
- pc_gainexp(sd,base_exp/c+1,job_exp/c+1);
- return 0;
-}
-
-// 同じマップのパーティメンバー全体に処理をかける
-// type==0 同じマップ
-// !=0 画面内
-void party_foreachsamemap(int (*func)(struct block_list*,va_list),
- struct map_session_data *sd,int type,...)
-{
- struct party *p;
- va_list ap;
- int i;
- int x0,y0,x1,y1;
- struct block_list *list[MAX_PARTY];
- int blockcount=0;
-
- nullpo_retv(sd);
-
- if((p=party_search(sd->status.party_id))==NULL)
- return;
-
- x0=sd->bl.x-AREA_SIZE;
- y0=sd->bl.y-AREA_SIZE;
- x1=sd->bl.x+AREA_SIZE;
- y1=sd->bl.y+AREA_SIZE;
-
- va_start(ap,type);
-
- for(i=0;i<MAX_PARTY;i++){
- struct party_member *m=&p->member[i];
- if(m->sd!=NULL){
- if(sd->bl.m!=m->sd->bl.m)
- continue;
- if(type!=0 &&
- (m->sd->bl.x<x0 || m->sd->bl.y<y0 ||
- m->sd->bl.x>x1 || m->sd->bl.y>y1 ) )
- continue;
- list[blockcount++]=&m->sd->bl;
- }
- }
-
- map_freeblock_lock(); // メモリからの解放を禁止する
-
- for(i=0;i<blockcount;i++)
- if(list[i]->prev) // 有効かどうかチェック
- func(list[i],ap);
-
- map_freeblock_unlock(); // 解放を許可する
-
- va_end(ap);
-}
+// $Id: party.c,v 1.2 2004/09/22 02:59:47 Akitasha Exp $
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "party.h"
+#include "db.h"
+#include "timer.h"
+#include "socket.h"
+#include "nullpo.h"
+#include "malloc.h"
+#include "pc.h"
+#include "map.h"
+#include "battle.h"
+#include "intif.h"
+#include "clif.h"
+
+#ifdef MEMWATCH
+#include "memwatch.h"
+#endif
+
+#define PARTY_SEND_XYHP_INVERVAL 1000 // 座標やHP送信の間隔
+
+static struct dbt* party_db;
+
+int party_send_xyhp_timer(int tid,unsigned int tick,int id,int data);
+/*==========================================
+ * 終了
+ *------------------------------------------
+ */
+static int party_db_final(void *key,void *data,va_list ap)
+{
+ free(data);
+ return 0;
+}
+void do_final_party(void)
+{
+ if(party_db)
+ numdb_final(party_db,party_db_final);
+}
+// 初期化
+void do_init_party(void)
+{
+ party_db=numdb_init();
+ add_timer_func_list(party_send_xyhp_timer,"party_send_xyhp_timer");
+ add_timer_interval(gettick()+PARTY_SEND_XYHP_INVERVAL,party_send_xyhp_timer,0,0,PARTY_SEND_XYHP_INVERVAL);
+}
+
+// 検索
+struct party *party_search(int party_id)
+{
+ return numdb_search(party_db,party_id);
+}
+int party_searchname_sub(void *key,void *data,va_list ap)
+{
+ struct party *p=(struct party *)data,**dst;
+ char *str;
+ str=va_arg(ap,char *);
+ dst=va_arg(ap,struct party **);
+ if(strcmpi(p->name,str)==0)
+ *dst=p;
+ return 0;
+}
+// パーティ名検索
+struct party* party_searchname(char *str)
+{
+ struct party *p=NULL;
+ numdb_foreach(party_db,party_searchname_sub,str,&p);
+ return p;
+}
+// 作成要求
+int party_create(struct map_session_data *sd,char *name)
+{
+ nullpo_retr(0, sd);
+
+ if(sd->status.party_id==0)
+ intif_create_party(sd,name);
+ else
+ clif_party_created(sd,2);
+ return 0;
+}
+
+// 作成可否
+int party_created(int account_id,int fail,int party_id,char *name)
+{
+ struct map_session_data *sd;
+ sd=map_id2sd(account_id);
+
+ nullpo_retr(0, sd);
+
+ if(fail==0){
+ struct party *p;
+ sd->status.party_id=party_id;
+ if((p=numdb_search(party_db,party_id))!=NULL){
+ printf("party: id already exists!\n");
+ exit(1);
+ }
+ p=(struct party *)aCalloc(1,sizeof(struct party));
+ p->party_id=party_id;
+ memcpy(p->name,name,24);
+ numdb_insert(party_db,party_id,p);
+ clif_party_created(sd,0);
+ }else{
+ clif_party_created(sd,1);
+ }
+ return 0;
+}
+
+// 情報要求
+int party_request_info(int party_id)
+{
+ return intif_request_partyinfo(party_id);
+}
+
+// 所属キャラの確認
+int party_check_member(struct party *p)
+{
+ int i;
+ struct map_session_data *sd;
+
+ nullpo_retr(0, p);
+
+ for(i=0;i<fd_max;i++){
+ if(session[i] && (sd=session[i]->session_data) && sd->state.auth){
+ if(sd->status.party_id==p->party_id){
+ int j,f=1;
+ for(j=0;j<MAX_PARTY;j++){ // パーティにデータがあるか確認
+ if( p->member[j].account_id==sd->status.account_id){
+ if( strcmp(p->member[j].name,sd->status.name)==0 )
+ f=0; // データがある
+ else
+ p->member[j].sd=NULL; // 同垢別キャラだった
+ }
+ }
+ if(f){
+ sd->status.party_id=0;
+ if(battle_config.error_log)
+ printf("party: check_member %d[%s] is not member\n",sd->status.account_id,sd->status.name);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+// 情報所得失敗(そのIDのキャラを全部未所属にする)
+int party_recv_noinfo(int party_id)
+{
+ int i;
+ struct map_session_data *sd;
+ for(i=0;i<fd_max;i++){
+ if(session[i] && (sd=session[i]->session_data) && sd->state.auth){
+ if(sd->status.party_id==party_id)
+ sd->status.party_id=0;
+ }
+ }
+ return 0;
+}
+// 情報所得
+int party_recv_info(struct party *sp)
+{
+ struct party *p;
+ int i;
+
+ nullpo_retr(0, sp);
+
+ if((p=numdb_search(party_db,sp->party_id))==NULL){
+ p=(struct party *)aCalloc(1,sizeof(struct party));
+ numdb_insert(party_db,sp->party_id,p);
+
+ // 最初のロードなのでユーザーのチェックを行う
+ party_check_member(sp);
+ }
+ memcpy(p,sp,sizeof(struct party));
+
+ for(i=0;i<MAX_PARTY;i++){ // sdの設定
+ struct map_session_data *sd = map_id2sd(p->member[i].account_id);
+ p->member[i].sd=(sd!=NULL && sd->status.party_id==p->party_id)?sd:NULL;
+ }
+
+ clif_party_info(p,-1);
+
+ for(i=0;i<MAX_PARTY;i++){ // 設定情報の送信
+// struct map_session_data *sd = map_id2sd(p->member[i].account_id);
+ struct map_session_data *sd = p->member[i].sd;
+ if(sd!=NULL && sd->party_sended==0){
+ clif_party_option(p,sd,0x100);
+ sd->party_sended=1;
+ }
+ }
+
+ return 0;
+}
+
+// パーティへの勧誘
+int party_invite(struct map_session_data *sd,int account_id)
+{
+ struct map_session_data *tsd= map_id2sd(account_id);
+ struct party *p=party_search(sd->status.party_id);
+ int i;
+
+ nullpo_retr(0, sd);
+
+ if(tsd==NULL || p==NULL)
+ return 0;
+ if(!battle_config.invite_request_check) {
+ if (tsd->guild_invite>0 || tsd->trade_partner) { // 相手が取引中かどうか
+ clif_party_inviteack(sd,tsd->status.name,0);
+ return 0;
+ }
+ }
+ if( tsd->status.party_id>0 || tsd->party_invite>0 ){ // 相手の所属確認
+ clif_party_inviteack(sd,tsd->status.name,0);
+ return 0;
+ }
+ for(i=0;i<MAX_PARTY;i++){ // 同アカウント確認
+ if(p->member[i].account_id==account_id){
+ clif_party_inviteack(sd,tsd->status.name,0);
+ return 0;
+ }
+ }
+
+ tsd->party_invite=sd->status.party_id;
+ tsd->party_invite_account=sd->status.account_id;
+
+ clif_party_invite(sd,tsd);
+ return 0;
+}
+// パーティ勧誘への返答
+int party_reply_invite(struct map_session_data *sd,int account_id,int flag)
+{
+ struct map_session_data *tsd= map_id2sd(account_id);
+
+ nullpo_retr(0, sd);
+
+ if(flag==1){ // 承諾
+ //inter鯖へ追加要求
+ intif_party_addmember( sd->party_invite, sd->status.account_id );
+ return 0;
+ }
+ else { // 拒否
+ sd->party_invite=0;
+ sd->party_invite_account=0;
+ if(tsd==NULL)
+ return 0;
+ clif_party_inviteack(tsd,sd->status.name,1);
+ }
+ return 0;
+}
+// パーティが追加された
+int party_member_added(int party_id,int account_id,int flag)
+{
+ struct map_session_data *sd= map_id2sd(account_id),*sd2;
+ if(sd==NULL && flag==0){
+ if(battle_config.error_log)
+ printf("party: member added error %d is not online\n",account_id);
+ intif_party_leave(party_id,account_id); // キャラ側に登録できなかったため脱退要求を出す
+ return 0;
+ }
+ sd2=map_id2sd(sd->party_invite_account);
+ sd->party_invite=0;
+ sd->party_invite_account=0;
+
+ if(flag==1){ // 失敗
+ if( sd2!=NULL )
+ clif_party_inviteack(sd2,sd->status.name,0);
+ return 0;
+ }
+
+ // 成功
+ sd->party_sended=0;
+ sd->status.party_id=party_id;
+
+ if( sd2!=NULL)
+ clif_party_inviteack(sd2,sd->status.name,2);
+
+ // いちおう競合確認
+ party_check_conflict(sd);
+
+ return 0;
+}
+// パーティ除名要求
+int party_removemember(struct map_session_data *sd,int account_id,char *name)
+{
+ struct party *p;
+ int i;
+
+ nullpo_retr(0, sd);
+
+ if( (p = party_search(sd->status.party_id)) == NULL )
+ return 0;
+
+ for(i=0;i<MAX_PARTY;i++){ // リーダーかどうかチェック
+ if(p->member[i].account_id==sd->status.account_id)
+ if(p->member[i].leader==0)
+ return 0;
+ }
+
+ for(i=0;i<MAX_PARTY;i++){ // 所属しているか調べる
+ if(p->member[i].account_id==account_id){
+ intif_party_leave(p->party_id,account_id);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+// パーティ脱退要求
+int party_leave(struct map_session_data *sd)
+{
+ struct party *p;
+ int i;
+
+ nullpo_retr(0, sd);
+
+ if( (p = party_search(sd->status.party_id)) == NULL )
+ return 0;
+
+ for(i=0;i<MAX_PARTY;i++){ // 所属しているか
+ if(p->member[i].account_id==sd->status.account_id){
+ intif_party_leave(p->party_id,sd->status.account_id);
+ return 0;
+ }
+ }
+ return 0;
+}
+// パーティメンバが脱退した
+int party_member_leaved(int party_id,int account_id,char *name)
+{
+ struct map_session_data *sd=map_id2sd(account_id);
+ struct party *p=party_search(party_id);
+ if(p!=NULL){
+ int i;
+ for(i=0;i<MAX_PARTY;i++)
+ if(p->member[i].account_id==account_id){
+ clif_party_leaved(p,sd,account_id,name,0x00);
+ p->member[i].account_id=0;
+ p->member[i].sd=NULL;
+ }
+ }
+ if(sd!=NULL && sd->status.party_id==party_id){
+ sd->status.party_id=0;
+ sd->party_sended=0;
+ }
+ return 0;
+}
+// パーティ解散通知
+int party_broken(int party_id)
+{
+ struct party *p;
+ int i;
+ if( (p=party_search(party_id))==NULL )
+ return 0;
+
+ for(i=0;i<MAX_PARTY;i++){
+ if(p->member[i].sd!=NULL){
+ clif_party_leaved(p,p->member[i].sd,
+ p->member[i].account_id,p->member[i].name,0x10);
+ p->member[i].sd->status.party_id=0;
+ p->member[i].sd->party_sended=0;
+ }
+ }
+ numdb_erase(party_db,party_id);
+ return 0;
+}
+// パーティの設定変更要求
+int party_changeoption(struct map_session_data *sd,int exp,int item)
+{
+ struct party *p;
+
+ nullpo_retr(0, sd);
+
+ if( sd->status.party_id==0 || (p=party_search(sd->status.party_id))==NULL )
+ return 0;
+ intif_party_changeoption(sd->status.party_id,sd->status.account_id,exp,item);
+ return 0;
+}
+// パーティの設定変更通知
+int party_optionchanged(int party_id,int account_id,int exp,int item,int flag)
+{
+ struct party *p;
+ struct map_session_data *sd=map_id2sd(account_id);
+ if( (p=party_search(party_id))==NULL)
+ return 0;
+
+ if(!(flag&0x01)) p->exp=exp;
+ if(!(flag&0x10)) p->item=item;
+ clif_party_option(p,sd,flag);
+ return 0;
+}
+
+// パーティメンバの移動通知
+int party_recv_movemap(int party_id,int account_id,char *map,int online,int lv)
+{
+ struct party *p;
+ int i;
+ if( (p=party_search(party_id))==NULL)
+ return 0;
+ for(i=0;i<MAX_PARTY;i++){
+ struct party_member *m=&p->member[i];
+ if( m == NULL ){
+ printf("party_recv_movemap nullpo?\n");
+ return 0;
+ }
+ if(m->account_id==account_id){
+ memcpy(m->map,map,16);
+ m->online=online;
+ m->lv=lv;
+ break;
+ }
+ }
+ if(i==MAX_PARTY){
+ if(battle_config.error_log)
+ printf("party: not found member %d on %d[%s]",account_id,party_id,p->name);
+ return 0;
+ }
+
+ for(i=0;i<MAX_PARTY;i++){ // sd再設定
+ struct map_session_data *sd= map_id2sd(p->member[i].account_id);
+ p->member[i].sd=(sd!=NULL && sd->status.party_id==p->party_id)?sd:NULL;
+ }
+
+ party_send_xy_clear(p); // 座標再通知要請
+
+ clif_party_info(p,-1);
+ return 0;
+}
+
+// パーティメンバの移動
+int party_send_movemap(struct map_session_data *sd)
+{
+ struct party *p;
+
+ nullpo_retr(0, sd);
+
+ if( sd->status.party_id==0 )
+ return 0;
+ intif_party_changemap(sd,1);
+
+ if( sd->party_sended!=0 ) // もうパーティデータは送信済み
+ return 0;
+
+ // 競合確認
+ party_check_conflict(sd);
+
+ // あるならパーティ情報送信
+ if( (p=party_search(sd->status.party_id))!=NULL ){
+ party_check_member(p); // 所属を確認する
+ if(sd->status.party_id==p->party_id){
+ clif_party_info(p,sd->fd);
+ clif_party_option(p,sd,0x100);
+ sd->party_sended=1;
+ }
+ }
+
+ return 0;
+}
+// パーティメンバのログアウト
+int party_send_logout(struct map_session_data *sd)
+{
+ struct party *p;
+
+ nullpo_retr(0, sd);
+
+ if( sd->status.party_id>0 )
+ intif_party_changemap(sd,0);
+
+ // sdが無効になるのでパーティ情報から削除
+ if( (p=party_search(sd->status.party_id))!=NULL ){
+ int i;
+ for(i=0;i<MAX_PARTY;i++)
+ if(p->member[i].sd==sd)
+ p->member[i].sd=NULL;
+ }
+
+ return 0;
+}
+// パーティメッセージ送信
+int party_send_message(struct map_session_data *sd,char *mes,int len)
+{
+ if(sd->status.party_id==0)
+ return 0;
+ intif_party_message(sd->status.party_id,sd->status.account_id,mes,len);
+ return 0;
+}
+
+// パーティメッセージ受信
+int party_recv_message(int party_id,int account_id,char *mes,int len)
+{
+ struct party *p;
+ if( (p=party_search(party_id))==NULL)
+ return 0;
+ clif_party_message(p,account_id,mes,len);
+ return 0;
+}
+// パーティ競合確認
+int party_check_conflict(struct map_session_data *sd)
+{
+ nullpo_retr(0, sd);
+
+ intif_party_checkconflict(sd->status.party_id,sd->status.account_id,sd->status.name);
+ return 0;
+}
+
+
+// 位置やHP通知用
+int party_send_xyhp_timer_sub(void *key,void *data,va_list ap)
+{
+ struct party *p=(struct party *)data;
+ int i;
+
+ nullpo_retr(0, p);
+
+ for(i=0;i<MAX_PARTY;i++){
+ struct map_session_data *sd;
+ if((sd=p->member[i].sd)!=NULL){
+ // 座標通知
+ if(sd->party_x!=sd->bl.x || sd->party_y!=sd->bl.y){
+ clif_party_xy(p,sd);
+ sd->party_x=sd->bl.x;
+ sd->party_y=sd->bl.y;
+ }
+ // HP通知
+ if(sd->party_hp!=sd->status.hp){
+ clif_party_hp(p,sd);
+ sd->party_hp=sd->status.hp;
+ }
+
+ }
+ }
+ return 0;
+}
+// 位置やHP通知
+int party_send_xyhp_timer(int tid,unsigned int tick,int id,int data)
+{
+ numdb_foreach(party_db,party_send_xyhp_timer_sub,tick);
+ return 0;
+}
+
+// 位置通知クリア
+int party_send_xy_clear(struct party *p)
+{
+ int i;
+
+ nullpo_retr(0, p);
+
+ for(i=0;i<MAX_PARTY;i++){
+ struct map_session_data *sd;
+ if((sd=p->member[i].sd)!=NULL){
+ sd->party_x=-1;
+ sd->party_y=-1;
+ sd->party_hp=-1;
+ }
+ }
+ return 0;
+}
+// HP通知の必要性検査用(map_foreachinmoveareaから呼ばれる)
+int party_send_hp_check(struct block_list *bl,va_list ap)
+{
+ int party_id;
+ int *flag;
+ struct map_session_data *sd;
+
+ nullpo_retr(0, bl);
+ nullpo_retr(0, ap);
+ nullpo_retr(0, sd=(struct map_session_data *)bl);
+
+ party_id=va_arg(ap,int);
+ flag=va_arg(ap,int *);
+
+ if(sd->status.party_id==party_id){
+ *flag=1;
+ sd->party_hp=-1;
+ }
+ return 0;
+}
+
+// 経験値公平分配
+int party_exp_share(struct party *p,int map,int base_exp,int job_exp)
+{
+ struct map_session_data *sd;
+ int i,c;
+
+ nullpo_retr(0, p);
+
+ for(i=c=0;i<MAX_PARTY;i++)
+ if((sd=p->member[i].sd)!=NULL && sd->bl.m==map)
+ c++;
+ if(c==0)
+ return 0;
+ for(i=0;i<MAX_PARTY;i++)
+ if((sd=p->member[i].sd)!=NULL && sd->bl.m==map)
+ pc_gainexp(sd,base_exp/c+1,job_exp/c+1);
+ return 0;
+}
+
+// 同じマップのパーティメンバー全体に処理をかける
+// type==0 同じマップ
+// !=0 画面内
+void party_foreachsamemap(int (*func)(struct block_list*,va_list),
+ struct map_session_data *sd,int type,...)
+{
+ struct party *p;
+ va_list ap;
+ int i;
+ int x0,y0,x1,y1;
+ struct block_list *list[MAX_PARTY];
+ int blockcount=0;
+
+ nullpo_retv(sd);
+
+ if((p=party_search(sd->status.party_id))==NULL)
+ return;
+
+ x0=sd->bl.x-AREA_SIZE;
+ y0=sd->bl.y-AREA_SIZE;
+ x1=sd->bl.x+AREA_SIZE;
+ y1=sd->bl.y+AREA_SIZE;
+
+ va_start(ap,type);
+
+ for(i=0;i<MAX_PARTY;i++){
+ struct party_member *m=&p->member[i];
+ if(m->sd!=NULL){
+ if(sd->bl.m!=m->sd->bl.m)
+ continue;
+ if(type!=0 &&
+ (m->sd->bl.x<x0 || m->sd->bl.y<y0 ||
+ m->sd->bl.x>x1 || m->sd->bl.y>y1 ) )
+ continue;
+ list[blockcount++]=&m->sd->bl;
+ }
+ }
+
+ map_freeblock_lock(); // メモリからの解放を禁止する
+
+ for(i=0;i<blockcount;i++)
+ if(list[i]->prev) // 有効かどうかチェック
+ func(list[i],ap);
+
+ map_freeblock_unlock(); // 解放を許可する
+
+ va_end(ap);
+}