www.pudn.com > ro4fserver.rar > map2.c


#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
 
#include "core.h" 
#include "mmo.h" 
#include "grfio.h" 
#include "npc.h" 
#include "itemdb.h" 
struct mons_data m_data[99999]; 
const int packet_len_table[0x200]={ 
   10,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0, 
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0, 
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0, 
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0, 
 
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0, 
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0, 
    0,  0,  0,  0, 55, 17,  3, 37,  46, -1, 23, -1,  3,108,  3,  2, 
    3, 28, 19, 11,  3, -1,  9,  5,  52, 51, 56, 58, 41,  2,  6,  6, 
 
    7,  3,  2,  2,  2,  5, 16, 12,  10,  7, 29, 23, -1, -1, -1,  0, 
    7, 22, 28,  2,  6, 30, -1, -1,   3, -1, -1,  5,  9, 17, 17,  6, 
   23,  6,  6, -1, -1, -1, -1,  8,   7,  6,  7,  4,  7,  0, -1,  6, 
    8,  8,  3,  3, -1,  6,  6, -1,   7,  6,  2,  5,  6, 44,  5,  3, 
 
    7,  2,  6,  8,  6,  7, -1, -1,  -1, -1,  3,  3,  6,  3,  2, 27, 
    3,  4,  4,  2, -1, -1,  3, -1,   6, 14,  3, -1, 28, 29, -1, -1, 
   30, 30, 26,  2,  6, 26,  3,  3,   8, 19,  5,  2,  3,  2,  2,  2, 
    3,  2,  6,  8, 21,  8,  8,  2,   2, 26,  3, -1,  6, 27, 30, 10, 
 
 
    2,  6,  6, 30, 79, 31, 10, 10,  -1, -1,  4,  6,  6,  2, 11, -1, 
   10, 39,  4, 10, 31, 35, 10, 18,   2, 13, 15, 20, 68,  2,  3, 16, 
    6, 14, -1, -1, 21,  8,  8,  8,   8,  8,  2,  2,  3,  4,  2, -1, 
    6, 86,  6, -1, -1,  7, -1,  6,   3, 16,  4,  4,  4,  6, 24, 26, 
 
   22, 14,  6, 10, 23, 19,  6, 39,   8,  9,  6, 27, -1,  2,  6,  6, 
  110,  6, -1, -1, -1, -1, -1,  6,  -1, 54, 66, 54, 90, 42,  6, 42, 
   -1, -1, -1, -1, -1, 30, -1,  3,  14,  3, 30, 10, 43, 14,186,182, 
   14, 30, 10,  3, -1,  6,106, -1,   4,  5,  4, -1,  6,  7, -1, -1, 
 
    6,  3,106, 10, 10, 34,  0,  6,   8,  4,  4,  4, 29, -1, 10,  6, 
   90, 86, 24,  6, 30,102,  8,  4,   8,  4, 14, 10, -1,  6,  2,  6, 
    3,  3, 35,  5, 11, 26, -1,  4,   4,  6, 10, 12,  6, -1,  4,  4, 
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0, 
 
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0, 
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0, 
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0, 
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0, 
 
}; 
const int base_exp_table[99]={2,5,20,30  ,85,170  ,220  ,300  ,568  ,630  ,697  ,756  ,900  ,1345  ,1615  ,1975  ,2200  ,2535  ,3000  ,3545  , 
4120  ,4670  ,5250  ,6200  ,7125  ,8020  ,8975  ,9900  ,12000  ,13000  ,14000  ,15000  ,16000  ,20000  ,21200  , 
22400  ,23600  ,24800  ,30000  ,31500  ,33000  ,34500  ,36000  ,42000  ,44000  ,46000  ,48000  ,50000  ,60000  , 
63000  ,66000  ,69000  ,72000  ,84000  ,87500  ,91000  ,94500  ,98000  ,102000  ,106500,111000  ,115500  ,120000, 
130000  ,135000  ,140000  ,145000  ,150000  ,200000  ,210000  ,220000  ,230000  ,240000  ,250000  ,260000  ,270000  , 
280000  ,290000  ,350000  ,365000  ,380000  ,395000  ,410000  ,425000  ,440000  ,455000  ,470000  ,485000  ,600000  , 
620000  ,640000  ,660000  ,680000  ,800000  ,830000  ,860000  ,890000 }; 
const int job_exp_table[50]={0,20  ,90  ,150  ,210  ,270  ,350  ,440  ,540  ,650  ,1000  ,1150  ,1350  ,1600  ,1900  ,2250  ,2650  ,3100  ,3600  ,4150  , 
5500  ,6350  ,7300  ,8350  ,9500  ,10750  ,12100  ,13550  ,15100  ,16750  ,20000  ,22000  ,24500  ,27500  ,31500  ,36000  , 
42000  ,48500  ,55500  ,63000  ,70000  ,80000  ,91000  ,102000  ,114000  ,127000  ,141000  ,156000  ,172000  ,200000}; 
 
const unsigned short def_aspd[13][13] = 
  { 
    { 500, 650, 700,2000,2000,2000,2000, 650, 700, 800,2000,2000,2000},     /* Novice */ 
    { 400, 500, 550, 600, 650, 700,2000,2000, 650, 700, 740,2000,2000},     /* Swordman */ 
    { 500, 600,2000,2000,2000,2000,2000, 700,2000,2000,2000,2000,2000},     /* Mage */ 
    { 400, 600,2000,2000,2000,2000, 700,2000,2000,2000,2000,2000,2000},     /* Archer */ 
    { 350,2000,2000,2000,2000,2000,2000, 600, 600,2000,2000,2000,2000},     /* Acolyte */ 
    { 400, 600, 700,2000,2000,2000,2000,2000, 700, 700, 750,2000,2000},     /* Marchant */ 
    { 400, 500, 650,2000,2000,2000, 850,2000,2000, 800,2000,2000,2000},     /* Thief */ 
    { 400, 500, 500, 550, 600, 650,2000,2000, 650, 700, 740,2000,2000},     /* Night */ 
    { 350,2000,2000,2000,2000,2000,2000, 600, 600,2000,2000,2000, 600},     /* Priest */ 
    { 500, 600,2000,2000,2000,2000,2000, 700,2000,2000,2000,2000,2000},     /* Wizard */ 
    { 400, 600, 700,2000,2000,2000,2000,2000, 700, 700, 750,2000,2000},     /* Blacksmith */ 
    { 400, 600,2000,2000,2000,2000, 600,2000,2000,2000,2000,2000,2000},     /* Hunter */ 
    { 400, 500, 650,2000,2000,2000,2000,2000,2000, 800,2000, 500,2000},     /* Assasin */ 
  }; 
 
 
int char_fd; 
char userid[24]; 
char passwd[24]; 
char char_ip_str[16]; 
int char_port; 
char map_ip_str[16]; 
int map_ip; 
int map_port; 
char mapmove_name[24]="-mapmove-"; 
char map[MAX_MAP_PER_SERVER][16]={"prontera.gat",""}; 
struct mmo_map_data map_data[MAX_MAP_PER_SERVER]; 
int users,users_global; 
char npc_txt[256]; 
 
struct block_list *object[50000]; 
int first_free_object_id,last_object_id; 
 
void add_block(struct block_list *bl,int m,int x,int y) 
{ 
  struct block_list *head; 
  head = &map_data[m].block[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map_data[m].bxs]; 
  bl->next = head->next; 
  bl->prev = head; 
  if(bl->next) bl->next->prev = bl; 
  head->next = bl; 
} 
 
void del_block(struct block_list *bl) 
{ 
  if(bl->prev==NULL){ 
    printf("del_block link error\n"); 
    exit(1); 
  } 
  if(bl->next) bl->next->prev = bl->prev; 
  bl->prev->next = bl->next; 
  bl->next = NULL; 
  bl->prev = NULL; 
} 
 
int search_free_object_id(void) 
{ 
  int i; 
  if(first_free_object_id<2 || first_free_object_id>=50000) 
    first_free_object_id=2; 
  for(i=first_free_object_id;i<50000;i++) 
    if(object[i]==NULL) 
      break; 
  if(i==50000){ 
    printf("no free object id\n"); 
    return 0; 
  } 
  first_free_object_id=i; 
  if(last_object_idid) 
    first_free_object_id=id; 
 
  while(last_object_id>2 && object[last_object_id]==NULL) 
    last_object_id--; 
 
  return 0; 
} 
 
int set_pos(unsigned char *p,int x,int y) 
{ 
  *p=x>>2; 
  p[1]=(x<<6) | ((y>>4)&0x3f); 
  p[2]=y<<4; 
  return 0; 
} 
 
int set_2pos(unsigned char *p,int x0,int y0,int x1,int y1) 
{ 
  *p=x0>>2; 
  p[1]=(x0<<6) | ((y0>>4)&0x3f); 
  p[2]=(y0<<4) | ((x1>>6)&0x0f); 
  p[3]=(x1<<2) | ((y1>>8)&0x03); 
  p[4]=y1; 
  return 0; 
} 
int earn_base_exp(int waste1,unsigned int waste2,int fd,int exp_earned) 
	{ 
	struct map_session_data *sd; 
	int exp; 
	int levels=0; 
	int status_points=0; 
	int i,j; 
 
	sd=session[fd]->session_data; 
	exp=sd->status.base_exp; 
	exp+=exp_earned; 
	while(exp > base_exp_table[sd->status.base_level + levels - 1]) 
		{ 
		exp=exp - base_exp_table[sd->status.base_level + levels - 1]; 
		levels++; 
		} 
	if(levels) 
		{ 
		/* This isnt working right */ 
		for(j=1;j<=levels;j++) 
			{ 
			for(i=1;i < 20;i++) 
				{ 
				if(5*i <= sd->status.base_level + j) 
					{ 
					status_points++; 
					} 
				} 
			status_points+=3; 
			} 
		/* up to here */ 
		mmo_map_update_param(fd,SP_STATUSPOINT,sd->status.status_point+status_points); 
		mmo_map_update_param(fd,SP_BASELEVEL,sd->status.base_level+levels); 
		mmo_map_update_param(fd,SP_NEXTBASEEXP,base_exp_table[sd->status.base_level-1]); 
		} 
	mmo_map_update_param(fd,SP_BASEEXP,exp); 
	return levels; 
	} 
 
int earn_job_exp(int waste1,unsigned int waste2,int fd,int exp_earned) 
	{ 
	struct map_session_data *sd; 
	int exp; 
	int levels=0; 
 
	sd=session[fd]->session_data; 
	exp=sd->status.job_exp; 
	exp+=exp_earned; 
	// If joblevel is 10 and no profesion is selected, no job exp will be earned 
	if((sd->status.job_level > 9)&&(sd->status.class == 0)) 
		return 0; 
	while(exp > job_exp_table[sd->status.job_level + levels -  1]) 
		{ 
		exp=exp - job_exp_table[sd->status.job_level + levels - 1]; 
		levels++; 
		} 
	if(levels) 
		{ 
		if( (levels+sd->status.job_level > 9)&&(sd->status.class == 0) ) 
			{ 
			mmo_map_update_param(fd,SP_SKILLPOINT,sd->status.skill_point + levels); 
			mmo_map_update_param(fd,SP_JOBLEVEL,10); 
			mmo_map_update_param(fd,SP_JOBEXP,0); 
			mmo_map_update_param(fd,SP_NEXTJOBEXP,1); 
			} 
		mmo_map_update_param(fd,SP_SKILLPOINT,sd->status.skill_point + levels); 
		mmo_map_update_param(fd,SP_JOBLEVEL,sd->status.job_level+levels); 
		mmo_map_update_param(fd,SP_NEXTJOBEXP,base_exp_table[sd->status.job_level-1]); 
		} 
	mmo_map_update_param(fd,SP_JOBEXP,exp); 
	return levels; 
	} 
 
int do_monster_attack(int tid,unsigned int tick,int monsterid,int fd) 
 
	{ 
	struct map_session_data *sd; 
	int damage; 
	int miss; 
	int monster_num; 
	int monster_class; 
	int health[99999]; 
	int playerid; 
	sd=session[fd]->session_data; 
	playerid = sd->account_id; 
	monster_num = monster_nums[monsterid]; 
	monster_class = map_data[sd->mapno].npc[monster_num]->class; 
 
if (m_data[monster_class].health_points == 0) {m_data[monster_class].health_points = 1000; } 
 
 
miss = rand()%7; 
	if (miss == 1) 
		{ 
		WFIFOW(fd,0) = 0x8a; 
		WFIFOL(fd,2) = monsterid; 
		WFIFOL(fd,6) = playerid; 
		WFIFOL(fd,10) = tick; 
		WFIFOL(fd,14) = 250; 
		WFIFOL(fd,18) = 250; 
		WFIFOW(fd,22) = 0; 
		WFIFOW(fd,24) = 0; 
		WFIFOB(fd,26) = 0; 
		WFIFOW(fd,27) = 0; 
	  	mmo_map_sendarea( fd, WFIFOP(fd,0), packet_len_table[0x8a], 0 ); 
		} 
	else 
		{ 
		WFIFOW(fd,0) = 0x8a; 
		WFIFOL(fd,2) = monsterid; 
		WFIFOL(fd,6) = playerid; 
		WFIFOL(fd,10) = tick; 
		WFIFOL(fd,14) = 250; 
		WFIFOL(fd,18) = 250; 
		WFIFOW(fd,22) = rand()%100; 
		WFIFOW(fd,24) = 0; 
		WFIFOB(fd,26) = 0; 
		WFIFOW(fd,27) = 0; 
	 	mmo_map_sendarea( fd, WFIFOP(fd,0), packet_len_table[0x8a], 0 ); 
		} 
 
 
	timer_info_m[monsterid]=add_timer(tick+rand()%500+500,do_monster_attack,monsterid,fd); 
 
 
return 0; 
} 
 
 
int do_attack(int tid,unsigned int tick,int monsterid,int fd) 
 
	{ 
	struct map_session_data *sd; 
	int damage;; 
	int miss; 
	int monster_num; 
	int monster_class; 
	int health[99999]; 
	int playerid; 
	sd=session[fd]->session_data; 
	playerid = sd->account_id; 
	monster_num = monster_nums[monsterid]; 
	monster_class = map_data[sd->mapno].npc[monster_num]->class; 
if(map_data[sd->mapno].npc[monster_num]->u.mons.timer != 0) {delete_timer(map_data[sd->mapno].npc[monster_num]->u.mons.timer); map_data[sd->mapno].npc[monster_num]->u.mons.timer=0; } 
 
 
 
if(health[monsterid] < m_data[monster_class].health_points) { 
	miss = rand()%7; 
	if (miss == 1) 
		{ 
		WFIFOW(fd,0) = 0x8a; 
		WFIFOL(fd,2) = playerid; 
		WFIFOL(fd,6) = monsterid; 
		WFIFOL(fd,10) = tick; 
		WFIFOL(fd,14) = 250; 
		WFIFOL(fd,18) = 250; 
		WFIFOW(fd,22) = 0; 
		WFIFOW(fd,24) = 0; 
		WFIFOB(fd,26) = 0; 
		WFIFOW(fd,27) = 0; 
		mmo_map_sendarea( fd, WFIFOP(fd,0), packet_len_table[0x8a], 0 ); 
		} 
	else 
		{ 
		damage = rand()%100; 
		WFIFOW(fd,0) = 0x8a; 
		WFIFOL(fd,2) = playerid; 
		WFIFOL(fd,6) = monsterid; 
		WFIFOL(fd,10) = tick; 
		WFIFOL(fd,14) = 250; 
		WFIFOL(fd,18) = 250; 
		WFIFOW(fd,22) = damage; 
		WFIFOW(fd,24) = 0; 
		WFIFOB(fd,26) = 0; 
		WFIFOW(fd,27) = 0; 
		mmo_map_sendarea( fd, WFIFOP(fd,0), packet_len_table[0x8a], 0 ); 
		health[monsterid] = health[monsterid] + damage; 
 
	if((timer_info_m[monsterid] != 0) && (timer_info_mp[monsterid] != playerid)) { 
	delete_timer(timer_info_m[monsterid]); 
	timer_info_m[monsterid]=0; 
	timer_info_m[monsterid]=add_timer(tick+rand()%140+140,do_monster_attack,monsterid,fd); 
	timer_info_mp[monsterid] = playerid; 
	} 
	else if(timer_info_mp[monsterid] == playerid) { } 
	else if(timer_info_m[monsterid] == 0) { 
	timer_info_m[monsterid]=add_timer(tick+rand()%140+140,do_monster_attack,monsterid,fd); 
	timer_info_mp[monsterid] = playerid; 
	} 
	} 
	timer_info_a[playerid]=add_timer(tick+rand()%500+500,do_attack,monsterid,fd); 
	 
} 
 
		if (health[monsterid] >= m_data[monster_class].health_points) 
		{ 
		if(timer_info_a[playerid] != 0) {delete_timer(timer_info_a[playerid]);  timer_info_a[playerid]=0;} 
		if(timer_info_m[monsterid] != 0) {delete_timer(timer_info_m[monsterid]);  timer_info_m[monsterid]=0;} 
		WFIFOW(fd,0)=0x80; 
		WFIFOL(fd,2)=monsterid; 
		WFIFOB(fd,6)=1;	// 1=dead 2=player logout 
		mmo_map_sendarea(fd,WFIFOP(fd,0),packet_len_table[0x80], 0 ); 
		health[monsterid] = 0; 
		set_monster_random_point(monster_i[monsterid],monster_num); 
		if (m_data[monster_class].move == 1){ 
		map_data[sd->mapno].npc[monster_num]->u.mons.timer= 
		add_timer(gettick()+rand()%5000+5000,mons_walk,monster_i[monsterid],monster_num); 
		} 
		add_timer(tick+rand()%800+800,earn_base_exp,fd,m_data[monster_class].base_exp); 
		add_timer(tick+rand()%1200+1200,earn_job_exp,fd,m_data[monster_class].job_exp); 
		//earn_job_exp(fd,m_data[monster_class].job_exp); 
 
		} 
return 0; 
} 
 
int set_map(struct map_session_data *sd,char *mapname,int x,int y) 
{ 
  int i; 
  if(sd==NULL) 
    return -1; 
  sd->x = x; 
  sd->y = y; 
  memcpy(sd->mapname,mapname,16); 
  for(i=0;map[i][0];i++) 
    if(strcmp(map[i],mapname)==0) 
      break; 
  if(map[i][0]) 
    sd->mapno=i; 
  else 
    return 1; // must send 0092? 
  if(sd->x <0 || sd->x >= map_data[i].xs) 
    sd->x=0; 
  if(sd->y <0 || sd->y >= map_data[i].ys) 
    sd->y=0; 
  add_block(&sd->block,i,sd->x,sd->y); 
  return 0; 
} 
 
int wait_close(int tid,unsigned int tick,int id,int data) 
{ 
  if(session[id]==NULL) 
    return 0; 
  session[id]->eof=1; 
  return 0; 
} 
 
int parse_tochar(int fd) 
{ 
  struct map_session_data *sd=NULL; 
  int i,j,fdc; 
 
  if(session[fd]->eof){ 
    if(fd==char_fd) 
      char_fd=-1; 
    printf("parse_tochar close %d\n",fd); 
    close(fd); 
    delete_session(fd); 
    return 0; 
  } 
  //printf("parse_tochar : %d %d %d\n",fd,RFIFOREST(fd),RFIFOW(fd,0)); 
  while(RFIFOREST(fd)>=2){ 
    switch(RFIFOW(fd,0)){ 
    case 0x2af9: 
      if(RFIFOREST(fd)<3) 
	return 0; 
      if(RFIFOB(fd,2)){ 
	printf("connect char server error : %d\n",RFIFOB(fd,2)); 
	exit(1); 
      } 
      RFIFOSKIP(fd,3); 
      WFIFOW(fd,0)=0x2afa; 
      for(i=0;map[i][0];i++){ 
	memcpy(WFIFOP(fd,4+i*16),map[i],16); 
      } 
      WFIFOW(fd,2)=4+i*16; 
      WFIFOSET(fd,WFIFOW(fd,2)); 
      break; 
    case 0x2afb: 
      if(RFIFOREST(fd)<3) 
	return 0; 
      if(RFIFOB(fd,2)!=0){ 
	printf("send map error :%d\n",RFIFOB(fd,2)); 
	exit(1); 
      } 
      RFIFOSKIP(fd,3); 
      break; 
    case 0x2afd: 
      if(RFIFOREST(fd)<4 || RFIFOREST(fd)session_data) && sd->account_id==RFIFOL(fd,4)) 
	  break; 
      for(j=i+1;jsession_data) && tmp_sd->account_id==RFIFOL(fd,4)) 
	  break; 
      } 
      if(j!=FD_SETSIZE){ 
	// 他人による2重ログイン落し排除のために、認証成功した後に両方落す 
	WFIFOW(i,0)=0x81; 
	WFIFOB(i,2)=8; 
	WFIFOSET(i,3); 
	WFIFOW(j,0)=0x81; 
	WFIFOB(j,2)=8; 
	WFIFOSET(j,3); 
	add_timer(gettick()+100,wait_close,i,0); 
	add_timer(gettick()+100,wait_close,j,0); 
      } else if(i!=FD_SETSIZE){ 
	fdc=i; 
	memcpy(&sd->status,RFIFOP(fd,12),sizeof(sd->status)); 
	set_map(sd,sd->status.last_point.map , sd->status.last_point.x , sd->status.last_point.y); 
	sd->speed = DEFAULT_WALK_SPEED; 
	sd->sitting=0; 
	sd->dir=0; 
	sd->head_dir=0; 
	WFIFOW(fdc,0)=0x73; 
	WFIFOL(fdc,2)=gettick(); 
	set_pos(WFIFOP(fdc,6),sd->x,sd->y); 
	WFIFOB(fdc,9)=5; 
	WFIFOB(fdc,10)=5; 
	WFIFOSET(fdc,11); 
	sd->state.auth=1; 
      } 
      RFIFOSKIP(fd,RFIFOW(fd,2)); 
      break; 
    case 0x2afe: 
      if(RFIFOREST(fd)<7) 
	return 0; 
      for(i=0;isession_data) && sd->account_id==RFIFOL(fd,4)) 
	  break; 
      if(i!=FD_SETSIZE){ 
	close(i); 
	session[i]->eof=1; 
      } 
      RFIFOSKIP(fd,7); 
      break; 
    case 0x2b00: 
      if(RFIFOREST(fd)<6) 
	return 0; 
      users_global=RFIFOL(fd,2); 
      RFIFOSKIP(fd,6); 
      break; 
    default: 
      printf("parse_tochar3 close %d %d\n",fd,RFIFOW(fd,0)); 
      close(fd); 
      session[fd]->eof=1; 
      return 0; 
    } 
  } 
  return 0; 
} 
 
int mmo_map_sendblock(int m,int bx,int by,char *dat,int len,int srcfd,int wos) 
{ 
  struct block_list *bl; 
  struct map_session_data *dstsd; 
  int fd,c=0; 
 
  if(bx<0 || bx>=map_data[m].bxs || 
     by<0 || by>=map_data[m].bys) 
    return 0; 
  bl=map_data[m].block[bx + by*map_data[m].bxs].next; 
  for(;bl;bl=bl->next){ 
    if(bl->type==BL_PC){ 
      dstsd=(struct map_session_data *)bl; 
      fd=dstsd->fd; 
      if(wos && fd == srcfd) 
	continue; 
      memcpy(WFIFOP(fd,0),dat,len); 
      WFIFOSET(fd,len); 
      c++; 
    } 
  } 
  return c; 
} 
 
// wos = without self  0 - include srcfd  1- exclude srcfd 
int mmo_map_sendarea(int srcfd,char *dat,int len,int wos) 
{ 
  struct map_session_data *srcsd; 
  int bx,by,i,j; 
 
  srcsd=session[srcfd]->session_data; 
  for(by=srcsd->y/BLOCK_SIZE-AREA_SIZE,i=0;i<(AREA_SIZE*2+1);by++,i++){ 
    if(by < 0 || by >= map_data[srcsd->mapno].bys) 
      continue; 
    for(bx=srcsd->x/BLOCK_SIZE-AREA_SIZE,j=0;j<(AREA_SIZE*2+1);bx++,j++){ 
      if(bx < 0 || bx >= map_data[srcsd->mapno].bxs) 
	continue; 
      mmo_map_sendblock(srcsd->mapno,bx,by,dat,len,srcfd,wos); 
    } 
  } 
  return 0; 
} 
 
 
 
int mmo_map_sendarea_mxy(int m,int x,int y,char *dat,int len) 
{ 
  int bx,by,i,j; 
 
  for(by=y/BLOCK_SIZE-AREA_SIZE,i=0;i<(AREA_SIZE*2+1);by++,i++){ 
    if(by < 0 || by >= map_data[m].bys) 
      continue; 
    for(bx=x/BLOCK_SIZE-AREA_SIZE,j=0;j<(AREA_SIZE*2+1);bx++,j++){ 
      if(bx < 0 || bx >= map_data[m].bxs) 
	continue; 
      mmo_map_sendblock(m,bx,by,dat,len,0,0); 
    } 
  } 
  return 0; 
} 
 
int mmo_map_sendall(int srcfd,char *dat,int len,int wos) 
{ 
  struct map_session_data *srcsd,*dstsd; 
  int fd; 
 
  srcsd=session[srcfd]->session_data; 
  for(fd=0;fdsession_data)) 
      continue; 
    if(wos && fd==srcfd) 
      continue; 
    memcpy(WFIFOP(fd,0),dat,len); 
    WFIFOSET(fd,len); 
  } 
  return 0; 
} 
 
int mmo_map_set_frameinitem(int fd,unsigned char *buf,struct flooritem_data *fitem) 
{ 
  if(fitem->item_data.nameid==0) 
    return 0; 
  //009d .l .w .B .w .w .w .B .B 
  WBUFW(buf,0)=0x9d; 
  WBUFL(buf,2)=fitem->id; 
  WBUFW(buf,6)=fitem->item_data.nameid; 
  WBUFB(buf,8)=fitem->item_data.identify; 
  WBUFW(buf,9)=fitem->x; 
  WBUFW(buf,11)=fitem->y; 
  WBUFW(buf,13)=fitem->item_data.amount; 
  WBUFB(buf,15)=fitem->subx; 
  WBUFB(buf,16)=fitem->suby; 
  return 17; 
} 
 
int mmo_map_set_dropitem(int fd,unsigned char *buf,struct flooritem_data *fitem) 
{ 
  if(fitem->item_data.nameid==0) 
    return 0; 
  //009e .l .w .B .w .w .B .B .w 
  WBUFW(buf,0)=0x9e; 
  WBUFL(buf,2)=fitem->id; 
  WBUFW(buf,6)=fitem->item_data.nameid; 
  WBUFB(buf,8)=fitem->item_data.identify; 
  WBUFW(buf,9)=fitem->x; 
  WBUFW(buf,11)=fitem->y; 
  WBUFB(buf,13)=fitem->subx; 
  WBUFB(buf,14)=fitem->suby; 
  WBUFW(buf,15)=fitem->item_data.amount; 
  return 17; 
} 
 
int mmo_map_set_npc(int fd,unsigned char *buf,unsigned long id, unsigned long class, int x, int y,int dir) 
{ 
  WBUFW(buf,0)=0x78; 
  WBUFL(buf,2)=id; 
  WBUFW(buf,6)=200; 
  WBUFW(buf,8)=0; 
  WBUFW(buf,10)=0; 
  WBUFW(buf,12)=0; 
  WBUFW(buf,14)=class; 
  WBUFW(buf,16)=0; 
  WBUFW(buf,18)=0; 
  WBUFW(buf,20)=0; 
  WBUFW(buf,22)=0; 
  WBUFW(buf,24)=0; 
  WBUFW(buf,26)=0; 
  WBUFW(buf,28)=0; 
  WBUFW(buf,30)=0; 
  WBUFW(buf,32)=0; 
  WBUFW(buf,34)=0; 
  WBUFW(buf,36)=0; 
  WBUFW(buf,38)=0; 
  WBUFW(buf,40)=0; 
  WBUFW(buf,42)=0; 
  WBUFB(buf,44)=0; 
  WBUFB(buf,45)=0; 
  set_pos(WBUFP(buf,46),x,y); 
  WBUFB(buf,48)|=dir; 
  WBUFB(buf,49)=0; 
  WBUFB(buf,50)=0; 
  WBUFB(buf,51)=0; 
  return 52; 
} 
 
int mmo_map_set_npc007c(int fd,unsigned char *buf,unsigned long id, unsigned long class, int x, int y) 
{ 
  WBUFW(buf,0)=0x7c; 
  WBUFL(buf,2)=id; 
  WBUFW(buf,6)=200; 
  WBUFW(buf,8)=0; 
  WBUFW(buf,10)=0; 
  WBUFW(buf,12)=0; 
  WBUFW(buf,14)=0; 
  WBUFW(buf,16)=0; 
  WBUFW(buf,18)=0; 
  WBUFW(buf,20)=class; 
  WBUFW(buf,22)=0; 
  WBUFW(buf,24)=0; 
  WBUFW(buf,26)=0; 
  WBUFW(buf,28)=0; 
  WBUFW(buf,30)=0; 
  WBUFW(buf,32)=0; 
  WBUFW(buf,34)=0; 
  set_pos(WBUFP(buf,36),x,y); 
  WBUFB(buf,39)=0; 
  WBUFB(buf,40)=0; 
  return 41; 
} 
 
int mmo_map_set0078(int fd,unsigned char *buf) 
{ 
  struct map_session_data *sd; 
 
  sd=session[fd]->session_data; 
 
  WBUFW(buf,0)=0x78; 
  WBUFL(buf,2)=sd->account_id; 
  WBUFW(buf,6)=sd->speed; 
  WBUFW(buf,8)=0; 
  WBUFW(buf,10)=0; 
  WBUFW(buf,12)=sd->status.option; 
  WBUFW(buf,14)=sd->status.class; 
  WBUFW(buf,16)=sd->status.hair; 
  WBUFW(buf,18)=sd->status.weapon; 
  WBUFW(buf,20)=sd->status.head_bottom; 
  WBUFW(buf,22)=sd->status.sheild; 
  WBUFW(buf,24)=sd->status.head_top; 
  WBUFW(buf,26)=sd->status.head_mid; 
  WBUFW(buf,28)=sd->status.hair_color; 
  WBUFW(buf,30)=sd->status.clothes_color; 
  WBUFW(buf,32)=sd->head_dir; 
  WBUFW(buf,34)=sd->status.guild_id; 
  WBUFW(buf,36)=0; 
  WBUFW(buf,38)=0; 
  WBUFW(buf,40)=sd->status.manner; 
  WBUFW(buf,42)=sd->status.karma; 
  WBUFB(buf,44)=0; 
  WBUFB(buf,45)=sd->sex; 
  set_pos(WBUFP(buf,46),sd->x,sd->y); 
  WBUFB(buf,48)|=sd->dir&0x0f; 
  WBUFB(buf,49)=5; 
  WBUFB(buf,50)=5; 
  WBUFB(buf,51)=sd->sitting; 
  return 0; 
} 
 
int mmo_map_set0079(int fd,unsigned char *buf) 
{ 
  mmo_map_set0078(fd,buf); 
  WBUFW(buf,0)=0x79; 
  return 0; 
} 
 
int mmo_map_set007b(int fd,unsigned char *buf,unsigned long tick,int x0,int y0,int x1,int y1) 
{ 
  struct map_session_data *sd; 
 
  sd=session[fd]->session_data; 
 
  WBUFW(buf,0)=0x7b; 
  WBUFL(buf,2)=sd->account_id; 
  WBUFW(buf,6)=sd->speed; 
  WBUFW(buf,8)=0; 
  WBUFW(buf,10)=0; 
  WBUFW(buf,12)=sd->status.option; 
  WBUFW(buf,14)=sd->status.class; 
  WBUFW(buf,16)=sd->status.hair; 
  WBUFW(buf,18)=sd->status.weapon; 
  WBUFW(buf,20)=sd->status.head_bottom; 
  WBUFL(buf,22)=tick; 
  WBUFW(buf,26)=sd->status.sheild; 
  WBUFW(buf,28)=sd->status.head_top; 
  WBUFW(buf,30)=sd->status.head_mid; 
  WBUFW(buf,32)=sd->status.hair_color; 
  WBUFW(buf,34)=0; 
  WBUFW(buf,36)=sd->head_dir; 
  WBUFW(buf,38)=sd->status.guild_id; 
  WBUFW(buf,40)=0; 
  WBUFW(buf,42)=0; 
  WBUFW(buf,44)=sd->status.manner; 
  WBUFW(buf,46)=sd->status.karma; 
  WBUFB(buf,48)=0; 
  WBUFB(buf,49)=sd->sex; 
  set_2pos(WBUFP(buf,50),x0,y0,x1,y1); 
  WBUFB(buf,55)=0; 
  WBUFB(buf,56)=5; 
  WBUFB(buf,57)=5; 
  return 0; 
} 
 
int mmo_map_send0095(int fd,unsigned long id) 
{ 
  int i; 
  struct map_session_data *sd; 
 
  if(id>=100000){ // PC 
    for(i=0;isession_data) && sd->account_id==id){ 
	WFIFOW(fd,0)=0x95; 
	WFIFOL(fd,2)=id; 
	memcpy(WFIFOP(fd,6),sd->status.name,24); 
	WFIFOSET(fd,30); 
	return 0; 
      } 
    } 
  } else { // NPC 
    sd=session[fd]->session_data; 
    for(i=0;imapno].npc_num;i++){ 
      if(map_data[sd->mapno].npc[i]->id==id){ 
	WFIFOW(fd,0)=0x95; 
	WFIFOL(fd,2)=id; 
	memcpy(WFIFOP(fd,6),map_data[sd->mapno].npc[i]->name,24); 
	WFIFOSET(fd,30); 
	return 0; 
      } 
    } 
  } 
  return -1; 
} 
 
int mmo_map_set_look(int fd,unsigned char *buf,int id,int type,int val) 
{ 
  printf("mmo_map_set_look : %d,%d,%d\n",id,type,val); 
  WBUFW(buf,0)=0xc3; 
  WBUFL(buf,2)=id; 
  WBUFB(buf,6)=type; 
  WBUFB(buf,7)=val; 
  return 8; 
} 
 
int calc_need_status_point(struct map_session_data *sd,int type) 
{ 
  int val; 
 
  if(typeSP_LUK) 
    return -1; 
  val = 
    type==SP_STR ? sd->status.str : 
    type==SP_AGI ? sd->status.agi : 
    type==SP_VIT ? sd->status.vit : 
    type==SP_INT ? sd->status.int_: 
    type==SP_DEX ? sd->status.dex : sd->status.luk; 
  return (val+9)/10+1; 
} 
 
int mmo_map_set_param(int fd,unsigned char *buf,int type) 
{ 
  int len=8; 
  struct map_session_data *sd; 
 
  sd=session[fd]->session_data; 
  WBUFW(buf,0)=0xb0; 
  WBUFW(buf,2)=type; 
  switch(type){ 
  case SP_STATUSPOINT: 
    WBUFL(buf,4)=sd->status.status_point; 
    break; 
  case SP_ASPD: 
    WBUFL(buf,4)=(long)((def_aspd[sd->status.class][0])*(float)(((250-(sd->status.agi)-((sd->status.dex)/4.0f)))/250.0f)); 
    break; 
  case SP_ATK1: 
    WBUFW(buf,4) = sd->status.str + (sd->status.str%10)*(sd->status.str%10) + (sd->status.dex/5); 
    break; 
  case SP_MATK1: 
    WBUFL(buf,4)=sd->status.int_ + (sd->status.int_/5)*(sd->status.int_/5); 
    break; 
  case SP_MATK2: 
    WBUFL(buf,4)=sd->status.int_ + (sd->status.int_/7)*(sd->status.int_/7); 
    break; 
  case SP_DEF2: 
    WBUFW(buf,4) = sd->status.vit; 
    break; 
  case SP_MDEF2: 
    WBUFW(buf,4) = sd->status.int_; 
    break; 
  case SP_HIT: 
    WBUFL(buf,4) = sd->status.base_level + sd->status.dex; 
  case SP_FLEE1: 
    WBUFW(buf,4) = sd->status.base_level + sd->status.agi; 
    break; 
  case SP_FLEE2: 
    WBUFW(buf,4) = (sd->status.luk/10)+1; 
    break; 
  case SP_SKILLPOINT: 
    WBUFL(buf,4)=sd->status.skill_point; 
    break; 
  case SP_ZENY: 
    WBUFW(buf,0)=0xb1; 
    WBUFL(buf,4)=sd->status.zeny; 
    break; 
  case SP_BASEEXP:	// This should work 
    WBUFW(buf,0)=0xb1; 
    WBUFL(buf,4)=sd->status.base_exp; 
    break; 
  case SP_JOBEXP:	// This should work 
    WBUFW(buf,0)=0xb1; 
    WBUFL(buf,4)=sd->status.job_exp; 
    break; 
  case SP_NEXTBASEEXP:	// This is temporal 
    WBUFW(buf,0)=0xb1; 
//    WBUFL(buf,4)=sd->status.base_level*sd->status.base_level+1000; 
    WBUFL(buf,4)=base_exp_table[sd->status.base_level-1]; 
    break; 
  case SP_NEXTJOBEXP:	// This is temporal 
    WBUFW(buf,0)=0xb1; 
//    WBUFL(buf,4)=sd->status.job_level*sd->status.job_level+2000; 
    WBUFL(buf,4)=job_exp_table[sd->status.job_level-1]; 
    break; 
  case SP_WEIGHT: 
    WBUFL(buf,4)=sd->weight; 
    break; 
  case SP_MAXWEIGHT: 
    WBUFL(buf,4)=sd->max_weight; 
    break; 
  case SP_BASELEVEL: 
    WBUFL(buf,4)=sd->status.base_level; 
    break; 
  case SP_HP: 
    WBUFL(buf,4)=sd->status.hp; 
    break; 
  case SP_SP:	// Not working good 
    WBUFL(buf,4)=sd->status.hp; 
    break; 
  case SP_MAXHP: 
    WBUFL(buf,4)=sd->status.max_hp; 
    break; 
  case SP_MAXSP: 
    WBUFL(buf,4)=sd->status.max_sp; 
    break; 
  case SP_MANNER: 
    WBUFL(buf,4)=sd->status.manner; 
    break; 
  case SP_KARMA: 
    WBUFL(buf,4)=sd->status.karma; 
    break; 
  case SP_STR: 
    WBUFW(buf,0)=0x141; 
    WBUFL(buf,2)=type; 
    WBUFL(buf,6)=sd->status.str; 
    WBUFL(buf,10)=0; // str bonus 
    len=14; 
    break; 
  case SP_AGI: 
    WBUFW(buf,0)=0x141; 
    WBUFL(buf,2)=type; 
    WBUFL(buf,6)=sd->status.agi; 
    WBUFL(buf,10)=0; // agi bonus 
    len=14; 
    break; 
  case SP_VIT: 
    WBUFW(buf,0)=0x141; 
    WBUFL(buf,2)=type; 
    WBUFL(buf,6)=sd->status.vit; 
    WBUFL(buf,10)=0; // vit bonus 
    len=14; 
    break; 
  case SP_INT: 
    WBUFW(buf,0)=0x141; 
    WBUFL(buf,2)=type; 
    WBUFL(buf,6)=sd->status.int_; 
    WBUFL(buf,10)=0; // int bonus 
    len=14; 
    break; 
  case SP_DEX: 
    WBUFW(buf,0)=0x141; 
    WBUFL(buf,2)=type; 
    WBUFL(buf,6)=sd->status.dex; 
    WBUFL(buf,10)=0; // dex bonus 
    len=14; 
    break; 
  case SP_LUK: 
    WBUFW(buf,0)=0x141; 
    WBUFL(buf,2)=type; 
    WBUFL(buf,6)=sd->status.luk; 
    WBUFL(buf,10)=0; // luk bonus 
    len=14; 
    break; 
  case SP_JOBLEVEL: 
	WBUFL(buf,4)=sd->status.job_level; 
	break; 
  default: 
    len=0; 
    break; 
  } 
  return len; 
} 
 
int mmo_map_update_param(int fd,int type,int val) 
{ 
  struct map_session_data *sd; 
  int len; 
 
  sd=session[fd]->session_data; 
if(val<0) val=0; 
switch(type){ 
	case SP_ZENY: 
	sd->status.zeny=val; 
	break; 
  case SP_STATUSPOINT: 
    sd->status.status_point=val; 
    break; 
  case SP_SKILLPOINT: 
    sd->status.skill_point=val; 
    break; 
  case SP_BASELEVEL: 
    sd->status.base_level=val; 
    break; 
  case SP_STR: 
    sd->status.str=val; 
    break; 
  case SP_AGI: 
    sd->status.agi=val; 
    break; 
  case SP_VIT: 
    sd->status.vit=val; 
    break; 
  case SP_INT: 
    sd->status.int_=val; 
    break; 
  case SP_DEX: 
    sd->status.dex=val; 
    break; 
  case SP_LUK: 
    sd->status.luk=val; 
    break; 
  case SP_HP: 
    sd->status.hp=val; 
    break; 
  case SP_WEIGHT: 
    sd->weight=val; 
    break; 
  case SP_MAXWEIGHT: 
    sd->max_weight=val; 
    break; 
  case SP_MAXHP: 
    sd->status.max_hp=val; 
    break; 
  case SP_SP: 
    sd->status.sp=val; 
    break; 
  case SP_MAXSP: 
    sd->status.max_sp=val; 
    break; 
  case SP_JOBLEVEL: 
    sd->status.job_level=val; 
    break; 
  case SP_KARMA: 
    sd->status.karma=val; 
    break; 
  case SP_MANNER: 
    sd->status.manner=val; 
    break; 
  case SP_BASEEXP: 
    sd->status.base_exp=val; 
    break; 
  case SP_JOBEXP: 
    sd->status.job_exp=val; 
    break; 
  default: 
    break; 
  } 
  len=mmo_map_set_param(fd,WFIFOP(fd,0),type); 
  if(len>0) WFIFOSET(fd,len); 
  return 0; 
} 
 
int mmo_map_item_get(int fd,unsigned char* buf, struct item* item) 
{ 
  struct map_session_data *sd; 
  struct mmo_charstatus *m_cs; 
  struct item *n_item; 
  int c=0,len; 
 
  sd=session[fd]->session_data; 
  m_cs=&sd->status; 
 
  if(!itemdb_isequip(item->nameid)) { 
    for(c=0;cinventory[c]; 
      if(n_item->nameid==item->nameid) { 
	n_item->amount+=item->amount; 
	//printf("already exist item add\n"); 
	break; 
      } 
    } 
  } 
  if(c==MAX_INVENTORY || itemdb_isequip(item->nameid)) { 
    for(c=0;cinventory[c]; 
      if(n_item->nameid) 
	continue; 
      else { 
	memcpy(n_item, item, sizeof(*item)); 
	//printf("equip or new item add\n"); 
 	break; 
      } 
    } 
  } 
  if(c==MAX_INVENTORY) 
    return -1; 
  if(sd->weight + itemdb_weight(item->nameid)*item->amount > sd->max_weight ) 
    return -2; 
 
  sd->weight += itemdb_weight(item->nameid)*item->amount; 
 
  //00a0 .w .w .w .B .B .B .4w .w .B .B 
  n_item=&m_cs->inventory[c]; 
  WBUFW(buf,0)=0xa0; 
  WBUFW(buf,2)=c+2; 
  WBUFW(buf,4)=item->amount; 
  WBUFW(buf,6)=n_item->nameid; 
  WBUFB(buf,8)=n_item->identify; 
  WBUFB(buf,9)=n_item->attribute; 
  WBUFB(buf,10)=n_item->refine; 
  WBUFW(buf,11)=n_item->card[0]; 
  WBUFW(buf,13)=n_item->card[1]; 
  WBUFW(buf,15)=n_item->card[2]; 
  WBUFW(buf,17)=n_item->card[3]; 
  WBUFW(buf,19)=itemdb_equip_point(n_item->nameid,sd); 
  WBUFB(buf,21)=itemdb_type(n_item->nameid); 
  WBUFB(buf,22)=0; 
 
  len=mmo_map_set_param(fd,WBUFP(buf,23),SP_WEIGHT); 
 
  return len+23; 
} 
 
int mmo_map_item_lost(int fd,unsigned char* buf, short index, short amount) 
{ 
  struct map_session_data *sd; 
  struct mmo_charstatus *m_cs; 
  struct item *n_item; 
  int len; 
 
  sd=session[fd]->session_data; 
  m_cs=&sd->status; 
  if(index>=MAX_INVENTORY+2 || index<2) 
    return -1; 
  n_item=&m_cs->inventory[index-2]; 
  if(!n_item->nameid) 
    return -1; 
  if(n_item->amountamount-=amount; 
  if(n_item->amount==0) 
    n_item->nameid=0; 
 
  sd->weight-=itemdb_weight(n_item->nameid)*amount; 
  len=mmo_map_set_param(fd,WBUFP(buf,0),SP_WEIGHT); 
  WBUFW(buf,len+0)=0xaf; 
  WBUFW(buf,len+2)=index; 
  WBUFW(buf,len+4)=amount; 
 
  return len+6; 
} 
 
int mmo_map_getblockchar(int fd,int m,int bx,int by) 
{ 
  struct block_list *bl; 
  int c=0; 
 
  if(bx<0 || bx>=map_data[m].bxs || 
     by<0 || by>=map_data[m].bys) 
    return 0; 
  //printf("getblockchar (%d,%d,%d)\n",m,bx,by); 
  bl=map_data[m].block[bx + by*map_data[m].bxs].next; 
  for(;bl;bl=bl->next){ 
    if(bl->type==BL_PC){ 
      struct map_session_data *srcsd; 
      srcsd=(struct map_session_data *)bl; 
      if(fd == srcsd->fd) 
	continue; 
      //printf("send 0078 pc%08x\n",srcsd->account_id); 
      mmo_map_set0078(srcsd->fd,WFIFOP(fd,0)); 
      WFIFOSET(fd,packet_len_table[0x78]); 
      c++; 
    } else if(bl->type==BL_NPC){ 
      struct npc_data *nd; 
      nd=(struct npc_data*)bl; 
      //printf("send 0078 npc%08x\n",nd->id); 
      mmo_map_set_npc(fd,WFIFOP(fd,0),nd->id,nd->class,nd->x,nd->y,nd->dir); 
      WFIFOSET(fd,packet_len_table[0x78]); 
    } else if(bl->type==BL_ITEM){ 
      struct flooritem_data *fid; 
      int len; 
 
      fid=(struct flooritem_data*)bl; 
      len=mmo_map_set_frameinitem(fd,WFIFOP(fd,0),fid); 
      if(len>0) 
	WFIFOSET(fd,len); 
    } 
  } 
  return c; 
} 
 
int mmo_map_clrblockchar(int fd,int m,int bx,int by) 
{ 
  struct block_list *bl; 
  int c=0; 
 
  if(bx<0 || bx>=map_data[m].bxs || 
     by<0 || by>=map_data[m].bys) 
    return 0; 
  bl=map_data[m].block[bx + by*map_data[m].bxs].next; 
  for(;bl;bl=bl->next){ 
    if(bl->type==BL_PC){ 
      struct map_session_data *srcsd; 
      srcsd=(struct map_session_data *)bl; 
      if(fd == srcsd->fd) 
	continue; 
      WFIFOW(fd,0)=0x80; 
      WFIFOL(fd,2)=srcsd->account_id; 
      WFIFOB(fd,6)=0; // no effect? 
      WFIFOSET(fd,packet_len_table[0x80]); 
      c++; 
    } else if(bl->type==BL_NPC){ 
      struct npc_data *nd; 
      nd=(struct npc_data*)bl; 
      WFIFOW(fd,0)=0x80; 
      WFIFOL(fd,2)=nd->id; 
      WFIFOB(fd,6)=0; // no effect? 
      WFIFOSET(fd,packet_len_table[0x80]); 
    } 
  } 
  return c; 
} 
 
int mmo_map_set_skilleffectarea(int fd,unsigned char *buf,unsigned long dst_id,unsigned long src_id,unsigned long type, int x, int y) 
{ 
  WBUFW(buf,0)=0x11f; 
  WBUFL(buf,2)=dst_id; 
  WBUFL(buf,6)=src_id; 
  WBUFW(buf,10)=x; 
  WBUFW(buf,12)=y; 
  WBUFB(buf,14)=type; 
  WBUFB(buf,15)=1; 
 
  return 16; 
} 
 
int mmo_map_getareachar(int fd) 
{ 
  int i,j,bx,by; 
  struct map_session_data *srcsd; 
 
  srcsd=session[fd]->session_data; 
  for(by=srcsd->y/BLOCK_SIZE-AREA_SIZE,i=0;i<(AREA_SIZE*2+1);by++,i++){ 
    if(by < 0 || by >= map_data[srcsd->mapno].bys) 
      continue; 
    for(bx=srcsd->x/BLOCK_SIZE-AREA_SIZE,j=0;j<(AREA_SIZE*2+1);bx++,j++){ 
      if(bx < 0 || bx >= map_data[srcsd->mapno].bxs) 
	continue; 
      mmo_map_getblockchar(fd,srcsd->mapno,bx,by); 
    } 
  } 
 
#if 0 
  // --- skill effect test code --- 
  if(strcmp(srcsd->mapname,"prontera.gat")) 
    return 0; 
  for(i=0;i<256;i++){ 
    len=mmo_map_set_skilleffectarea(fd,WFIFOP(fd,0),49999-i, srcsd->account_id, i, 159-(i/32*2), 191-(i%32*2)); 
    if(len>0) WFIFOSET(fd,len); 
  } 
 
#endif 
#if 0 
  // --- NPC test code --- 
  if(strcmp(srcsd->mapname,"prontera.gat")) 
    return 0; 
  len=mmo_map_set_npc(fd,WFIFOP(fd,0),1, 0x70, 156, 195); 
  WFIFOSET(fd,len); 
  for(i=45;i<126;i++){ 
    if(i==0x68 || i==0x6f) 
      continue; 
    mmo_map_set_npc(fd,WFIFOP(fd,0),i-45+20, i, 159-((i-45)/20*2), 191-((i-45)%20*2)); 
    WFIFOSET(fd,packet_len_table[0x78]); 
  } 
  mmo_map_set_npc(fd,WFIFOP(fd,0),i-45+20, 0x2bc, 159-((i-45)/20*2), 191-((i-45)%20*2)); 
  WFIFOSET(fd,packet_len_table[0x78]); 
  i++; 
  mmo_map_set_npc(fd,WFIFOP(fd,0),i-45+20, 1039, 159-((i-45)/20*2), 191-((i-45)%20*2)); // Baphomet 
  WFIFOSET(fd,packet_len_table[0x78]); 
#endif 
  return 0; 
} 
 
int mmo_map_sendwis(int fd) 
{ 
  int i; 
  struct map_session_data *srcsd,*dstsd; 
 
  if(!session[fd] || !(srcsd=session[fd]->session_data)) 
    return -1; 
  for(i=0;isession_data)) 
      continue; 
    if(strcmp(dstsd->status.name,RFIFOP(fd,4))==0){ 
      WFIFOW(i,0)=0x97; 
      WFIFOW(i,2)=RFIFOW(fd,2); 
      memcpy(WFIFOP(i,4),srcsd->status.name,24); 
      memcpy(WFIFOP(i,28),RFIFOP(fd,28),RFIFOW(fd,2)-28); 
      WFIFOSET(i,RFIFOW(fd,2)); 
      break; 
    } 
  } 
  WFIFOW(fd,0)=0x98; 
  WFIFOB(fd,2)= i==FD_SETSIZE; 
  WFIFOSET(fd,3); 
  return 0; 
} 
 
int mmo_map_all_nonequip(int fd,unsigned char *buf) 
{ 
  int i,c; 
  struct map_session_data *sd; 
  struct item *n_item; 
 
  sd=session[fd]->session_data; 
  WBUFW(buf,0)=0xa3; 
  for(i=c=0;istatus.inventory[i]; 
    if(n_item->nameid==0 || itemdb_isequip(n_item->nameid)) 
      continue; 
    WBUFW(buf,4+c*10)=i+2; 
    WBUFW(buf,4+c*10+2)=n_item->nameid; 
    WBUFB(buf,4+c*10+4)=itemdb_type(n_item->nameid); 
    WBUFB(buf,4+c*10+5)=n_item->identify; 
    WBUFW(buf,4+c*10+6)=n_item->amount; 
    WBUFB(buf,4+c*10+8)=0; 
    WBUFB(buf,4+c*10+9)=0;	// 装備中の矢の場合 0x80? 
    c++; 
  } 
  if(c==0) 
    return 0; 
  WBUFW(buf,2)=4+c*10; 
  return 4+c*10; 
} 
 
int mmo_map_all_equip(int fd,unsigned char *buf) 
{ 
  int i,c; 
  struct map_session_data *sd; 
  struct item *n_item; 
 
  sd=session[fd]->session_data; 
  WBUFW(buf,0)=0xa4; 
  for(i=c=0;istatus.inventory[i]; 
    if(n_item->nameid==0 || !itemdb_isequip(n_item->nameid)) 
      continue; 
    WBUFW(buf,4+c*20)=i+2; 
    WBUFW(buf,4+c*20+2)=n_item->nameid; 
    WBUFB(buf,4+c*20+4)=itemdb_type(n_item->nameid); 
    WBUFB(buf,4+c*20+5)=n_item->identify; 
    WBUFW(buf,4+c*20+6)=itemdb_equip_point(n_item->nameid,sd); 
    WBUFW(buf,4+c*20+8)=n_item->equip; 
    WBUFB(buf,4+c*20+10)=n_item->attribute; 
    WBUFB(buf,4+c*20+11)=n_item->refine; 
    WBUFW(buf,4+c*20+12)=n_item->card[0]; 
    WBUFW(buf,4+c*20+14)=n_item->card[1]; 
    WBUFW(buf,4+c*20+16)=n_item->card[2]; 
    WBUFW(buf,4+c*20+18)=n_item->card[3]; 
    c++; 
  } 
  if(c==0) 
    return 0; 
  WBUFW(buf,2)=4+c*20; 
  return 4+c*20; 
} 
 
int mmo_map_all_skill(int fd,unsigned char *buf) 
{ 
  int i,c; 
  struct map_session_data *sd; 
  struct skill *n_skill; 
 
  sd=session[fd]->session_data; 
  WBUFW(buf,0)=0x10f; 
  for(i=c=0;istatus.skill[i]; 
    if(n_skill->id==0) 
      continue; 
    WBUFW(buf,4+c*37)=n_skill->id;	//id 
    WBUFW(buf,4+c*37+2)=0;	//target type 0-passive 1-enemy 2-place 4-immidiatery 16-ally 
    WBUFW(buf,4+c*37+4)=0;	//??? 
    WBUFW(buf,4+c*37+6)=n_skill->lv;	//lv 
    WBUFW(buf,4+c*37+8)=10;	//sp 
    WBUFW(buf,4+c*37+10)=16;	//range 
    memcpy(WBUFP(buf,4+c*37+12),"",24);	//name 
    WBUFB(buf,4+c*37+36)=1;	//up 
    c++; 
  } 
  if(c==0) 
    return 0; 
  WBUFW(buf,2)=4+c*37; 
  return 4+c*37; 
} 
 
int mmo_map_set00bd(int fd,unsigned char *buf) 
{ 
  struct map_session_data *sd; 
 
  sd=session[fd]->session_data; 
 
  //R 00bd .w .B .B .B .B .B .B .B .B .B .B .B .B .w .w .w .w .w .w .w .w .w .w .w .w ?.w 
  memset(buf,0,packet_len_table[0xbd]); 
  WBUFW(buf,0)=0xbd; 
  WBUFW(buf,2)=sd->status.status_point; 
  WBUFB(buf,4)=sd->status.str; 
  WBUFB(buf,5)=calc_need_status_point(sd,SP_STR); 
  WBUFB(buf,6)=sd->status.agi; 
  WBUFB(buf,7)=calc_need_status_point(sd,SP_AGI); 
  WBUFB(buf,8)=sd->status.vit; 
  WBUFB(buf,9)=calc_need_status_point(sd,SP_VIT); 
  WBUFB(buf,10)=sd->status.int_; 
  WBUFB(buf,11)=calc_need_status_point(sd,SP_INT); 
  WBUFB(buf,12)=sd->status.dex; 
  WBUFB(buf,13)=calc_need_status_point(sd,SP_DEX); 
  WBUFB(buf,14)=sd->status.luk; 
  WBUFB(buf,15)=calc_need_status_point(sd,SP_LUK); 
  WBUFW(buf,16) = sd->status.str + (sd->status.str%10)*(sd->status.str%10) + (sd->status.dex/5); 
  WBUFW(buf,18) = 0; // attack bouns 
  WBUFW(buf,20) = sd->status.int_ + (sd->status.int_/5)*(sd->status.int_/5); 
  WBUFW(buf,22) = sd->status.int_ + (sd->status.int_/7)*(sd->status.int_/7); 
  WBUFW(buf,24) = 0; // def 
  WBUFW(buf,26) = sd->status.vit; 
  WBUFW(buf,28) = 0; // mdef 
  WBUFW(buf,30) = sd->status.int_; 
  WBUFW(buf,32) = sd->status.base_level + sd->status.dex; 
  WBUFW(buf,34) = sd->status.base_level + sd->status.agi; 
  WBUFW(buf,36) = (sd->status.luk/10)+1; 
  WBUFW(buf,38) = 1+(sd->status.luk/3); 
  WBUFW(buf,40) = sd->status.karma; 
  WBUFW(buf,42) = sd->status.manner; 
 
  return packet_len_table[0xbd]; 
} 
 
int mmo_send_selfdata(int fd,struct map_session_data *sd) 
{ 
  int len,i; 
 
  sd->max_weight=10000; 
  sd->weight=0; 
  for(i=0;istatus.inventory[i]; 
    if(n_item->nameid==0) 
      continue; 
    sd->weight+=itemdb_weight(n_item->nameid)*n_item->amount; 
  } 
 
  // each connection 
  // skill 
  len=mmo_map_all_skill(fd,WFIFOP(fd,0)); 
  if(len>0) WFIFOSET(fd,len); 
  // equip check&modify 
  // party&guild 
 
  // each load end 
  // next exp , weight , skill point 
  len=mmo_map_set_param(fd,WFIFOP(fd,0),SP_MAXWEIGHT); 
  if(len>0) WFIFOSET(fd,len); 
  len=mmo_map_set_param(fd,WFIFOP(fd,0),SP_WEIGHT); 
  if(len>0) WFIFOSET(fd,len); 
  // item 
  len=mmo_map_all_nonequip(fd,WFIFOP(fd,0)); 
  if(len>0) WFIFOSET(fd,len); 
  len=mmo_map_all_equip(fd,WFIFOP(fd,0)); 
  if(len>0) WFIFOSET(fd,len); 
  // status 
  len=mmo_map_set00bd(fd,WFIFOP(fd,0)); 
  if(len>0) WFIFOSET(fd,len); 
  // ASPD 
  len=mmo_map_set_param(fd,WFIFOP(fd,0),SP_ASPD); 
  if(len>0) WFIFOSET(fd,len); 
 
  return 0; 
} 
 
int mmo_map_jobchange(int fd,int class) 
{ 
  int len; 
  struct map_session_data *sd; 
 
  sd=session[fd]->session_data; 
 
  sd->status.class=class; 
  len=mmo_map_set_look(fd,WFIFOP(fd,0),sd->account_id,LOOK_BASE,sd->status.class); 
  if(len>0) mmo_map_sendarea(fd,WFIFOP(fd,0),len,0); 
 
  return 0; 
} 
 
int mmo_map_make_flooritem(struct item *item_data,int amount,int m,int x,int y) 
{ 
  int i,j,c,free_cell,r; 
  int id; 
  struct flooritem_data *fitem; 
  unsigned char buf[64]; 
  int len; 
 
  if((id=search_free_object_id())==0) 
    return 0; 
 
  // (x-1,y-1)-(x+1,y+1)の中で侵入可能セル探して、ランダムにその中に落す 
  for(free_cell=0,i=-1;i<=1;i++){ 
    if(i+y<0 || i+y>=map_data[m].ys) 
      continue; 
    for(j=-1;j<=1;j++){ 
      if(j+x<0 || j+x>=map_data[m].xs) 
	continue; 
      if((c=map_data[m].gat[j+x+(i+y)*map_data[m].xs])==1 || c==5) 
	continue; 
      free_cell++; 
    } 
  } 
  if(free_cell==0) 
    return 0; 
  r=rand(); 
  free_cell=r%free_cell; 
  r=r>>4; 
  for(i=-1;i<=1;i++){ 
    if(i+y<0 || i+y>=map_data[m].ys) 
      continue; 
    for(j=-1;j<=1;j++){ 
      if(j+x<0 || j+x>=map_data[m].xs) 
	continue; 
      if((c=map_data[m].gat[j+x+(i+y)*map_data[m].xs])==1 || c==5) 
	continue; 
      if(free_cell==0){ 
	x+=j; 
	y+=i; 
	i=3; 
	break; 
      } 
      free_cell--; 
    } 
  } 
 
  fitem=malloc(sizeof(*fitem)); 
  object[id]=&fitem->block; 
  fitem->id=id; 
  fitem->m=m; 
  fitem->x=x; 
  fitem->y=y; 
  memcpy(&fitem->item_data,item_data,sizeof(*item_data)); 
  fitem->item_data.amount=amount; 
  fitem->subx=(r&3)*3+3; 
  fitem->suby=((r>>2)&3)*3+3; 
  fitem->drop_tick=gettick(); 
  //printf("(%d,%d)+(%d,%d)\n",fitem->x,fitem->y,fitem->subx,fitem->suby); 
 
  fitem->block.type=BL_ITEM; 
  add_block(&fitem->block,fitem->m,fitem->x,fitem->y); 
 
  len=mmo_map_set_dropitem(0,buf,fitem); 
  if(len>0) 
    mmo_map_sendarea_mxy(m,x,y,buf,len); 
 
  return id; 
} 
 
int mmo_map_dropitem(int fd,int index,int amount) 
{ 
  int len; 
  struct map_session_data *sd; 
  struct item item_data_tmp; 
 
  if(index<2 || index>=MAX_INVENTORY+2) 
    return -1; 
  sd=session[fd]->session_data; 
  memcpy(&item_data_tmp,&sd->status.inventory[index-2],sizeof(item_data_tmp)); 
  len=mmo_map_item_lost(fd,WFIFOP(fd,0),index,amount); 
  if(len<=0) 
    return -1; 
  WFIFOSET(fd,len); 
  mmo_map_make_flooritem(&item_data_tmp,amount,sd->mapno,sd->x,sd->y); 
  return 0; 
} 
 
int mmo_map_takeitem(int fd,int item_id) 
{ 
  int len; 
  struct map_session_data *sd; 
  struct flooritem_data *fitem; 
 
  if(item_id<2 || item_id>=50000 || object[item_id]==NULL || object[item_id]->type!=BL_ITEM) 
    return -1; 
 
  sd=session[fd]->session_data; 
  fitem=(struct flooritem_data*)object[item_id]; 
 
  len=mmo_map_item_get(fd,WFIFOP(fd,0),&fitem->item_data); 
  if(len>0){ 
    WFIFOSET(fd,len); 
 
    WFIFOW(fd,0)=0x8a;	// take motion 
    WFIFOL(fd,2)=sd->account_id; 
    WFIFOL(fd,6)=item_id; 
    WFIFOL(fd,10)=gettick(); 
    WFIFOB(fd,26)=1; 
    mmo_map_sendarea(fd,WFIFOP(fd,0),packet_len_table[0x8a],0); 
 
    WFIFOW(fd,0)=0xa1;	// delete floor item 
    WFIFOL(fd,2)=item_id; 
    mmo_map_sendarea(fd,WFIFOP(fd,0),packet_len_table[0xa1],0); 
 
    delete_object(item_id); 
  } 
 
  return 0; 
} 
 
int clear_flooritem(int tid,unsigned int tick,int id,int data) 
{ 
  int i; 
  struct flooritem_data *fitem; 
  unsigned char buf[64]; 
 
  for(i=2;i<=last_object_id;i++){ 
    if(object[i]==NULL || object[i]->type!=BL_ITEM) 
      continue; 
    fitem=(struct flooritem_data *)object[i]; 
    if(tick-fitem->drop_tick < LIFETIME_FLOORITEM*1000) 
      continue; 
 
    WBUFW(buf,0)=0xa1;	// delete floor item 
    WBUFL(buf,2)=i; 
    mmo_map_sendarea_mxy(fitem->m,fitem->x,fitem->y,buf,packet_len_table[0xa1]); 
 
    delete_object(i); 
  } 
  return 0; 
} 
 
#define MAX_TMP_PATH (33*33) 
struct mmo_tmp_path { int x,y,dist,dir,before,cost; }; 
 
int add_path(struct mmo_tmp_path *path,int *wp,int x,int y,int dist,int dir,int before) 
{ 
  int i,c1,c2; 
  for(i=0;i<*wp;i++) 
    if(path[i].x==x && path[i].y==y){ 
      if(path[i].dist>=dist){ 
	if(path[i].dist==dist){ 
	  c1=path[i].cost; 
	  c2=path[before].cost+((dir&1)?i:0); 
	  if(c11 || y0-y1<-1 || y0-y1>1) 
    return 0; 
  if(x1<0 || y1<0 || x1>=m->xs || y1>=m->ys) 
    return 0; 
  if((c=m->gat[x0+y0*m->xs])==1 || c==5) 
    return 0; 
  if((c=m->gat[x1+y1*m->xs])==1 || c==5) 
    return 0; 
  if(x0==x1 || y0==y1) 
    return 1; 
  if(((c=m->gat[x0+y1*m->xs])==1 || c==5) || 
     ((c=m->gat[x1+y0*m->xs])==1 || c==5)) 
    return 0; 
  return 1; 
} 
 
int search_path(struct map_session_data *sd,int mapno,int x0,int y0,int x1,int y1,int easy_only) 
{ 
  struct mmo_tmp_path tmp_path[MAX_TMP_PATH]; 
  int rp,wp,i; 
  int x,y,dx,dy; 
  struct mmo_map_data *m; 
 
  //printf("search_path %s (%d,%d)-(%d,%d)\n",map[mapno],x0,y0,x1,y1); 
  if(!map[mapno][0]) 
    return -1; 
  m=&map_data[mapno]; 
  // easy 
  dx = (x1-x0<0) ? -1 : 1; 
  dy = (y1-y0<0) ? -1 : 1; 
  for(x=x0,y=y0,i=0;x!=x1 || y!=y1;){ 
    if(x!=x1 && y!=y1){ 
      if(!can_move(m,x,y,x+dx,y+dy)) 
	break; 
      x+=dx; 
      y+=dy; 
      sd->walkpath[i++]=(dx<0) ? ((dy>0)? 1 : 3) : ((dy<0)? 5 : 7); 
    } else if(x!=x1){ 
      if(!can_move(m,x,y,x+dx,y   )) 
	break; 
      x+=dx; 
      sd->walkpath[i++]=(dx<0) ? 2 : 6; 
    } else { // y!=y1 
      if(!can_move(m,x,y,x   ,y+dy)) 
	break; 
      y+=dy; 
      sd->walkpath[i++]=(dy>0) ? 0 : 4; 
    } 
    if(x==x1 && y==y1){ 
      sd->walkpath_len=i; 
      sd->walkpath_pos=0; 
      return 0; 
    } 
  } 
  if(easy_only) 
    return -1; 
 
  // difficult 
  rp=wp=0; 
  tmp_path[wp].x=x0; 
  tmp_path[wp].y=y0; 
  tmp_path[wp].dist=0; 
  tmp_path[wp].dir=0; 
  tmp_path[wp++].before=0; 
  tmp_path[wp++].cost=0; 
  while(rp=sizeof(sd->walkpath)) 
	return -1; 
      sd->walkpath_len=len; 
      sd->walkpath_pos=0; 
      for(i=rp,j=len-1;i!=0;i=tmp_path[i].before,j--) 
	sd->walkpath[j]=tmp_path[i].dir; 
      //printf("search path ok (%d,%d)-(%d,%d) ",x0,y0,x1,y1); 
      //for(i=0;iwalkpath[i]); 
      //printf("\n"); 
      return 0; 
    } 
    if(can_move(m,x,y,x+1,y-1)) 
      add_path(tmp_path,&wp,x+1,y-1,tmp_path[rp].dist+14,5,rp); 
    if(can_move(m,x,y,x+1,y  )) 
      add_path(tmp_path,&wp,x+1,y  ,tmp_path[rp].dist+10,6,rp); 
    if(can_move(m,x,y,x+1,y+1)) 
      add_path(tmp_path,&wp,x+1,y+1,tmp_path[rp].dist+14,7,rp); 
    if(can_move(m,x,y,x  ,y+1)) 
      add_path(tmp_path,&wp,x  ,y+1,tmp_path[rp].dist+10,0,rp); 
    if(can_move(m,x,y,x-1,y+1)) 
      add_path(tmp_path,&wp,x-1,y+1,tmp_path[rp].dist+14,1,rp); 
    if(can_move(m,x,y,x-1,y  )) 
      add_path(tmp_path,&wp,x-1,y  ,tmp_path[rp].dist+10,2,rp); 
    if(can_move(m,x,y,x-1,y-1)) 
      add_path(tmp_path,&wp,x-1,y-1,tmp_path[rp].dist+14,3,rp); 
    if(can_move(m,x,y,x  ,y-1)) 
      add_path(tmp_path,&wp,x  ,y-1,tmp_path[rp].dist+10,4,rp); 
    if(wp>=MAX_TMP_PATH-8) 
      return -1; 
    rp++; 
  } 
  return -1; 
} 
 
int calc_next_walk_step(int fd) 
{ 
  struct map_session_data *sd; 
 
  if(session[fd]==NULL || (sd=session[fd]->session_data)==NULL) 
    return -1; 
  if(sd->walkpath_pos>=sd->walkpath_len) 
    return -1; 
  if(sd->walkpath[sd->walkpath_pos]&1) 
    return sd->speed*14/10; 
  return sd->speed; 
} 
 
int mmo_map_changemap(int id,struct map_session_data *sd,char *mapname,int x,int y,int type) 
{ 
  del_block(&sd->block); 
  WFIFOW(id,0)=0x80; 
  WFIFOL(id,2)=sd->account_id; 
  WFIFOB(id,6)=type; 
  mmo_map_sendarea(id,WFIFOP(id,0),packet_len_table[0x80], 1 ); 
 
  set_map(sd,mapname,x,y); 
  WFIFOW(id,0)=0x91; // in same server move 
  memcpy(WFIFOP(id,2),mapname,16); 
  WFIFOW(id,18)=x; 
  WFIFOW(id,20)=y; 
  WFIFOSET(id,22); 
  return 0; 
} 
 
int walk_char(int tid,unsigned int tick,int id,int data) 
{ 
  struct map_session_data *sd; 
  int i,m,nx,ny,dx,dy; 
  static int dirx[8]={0,-1,-1,-1,0,1,1,1}; 
  static int diry[8]={1,1,0,-1,-1,-1,0,1}; 
 
  //printf("walk_char %d %08x %d\n",id,tick,data); 
  if(session[id]==NULL || (sd=session[id]->session_data)==NULL) 
    return 0; 
  if(sd->walkpath_pos>=sd->walkpath_len || sd->walkpath_pos!=data || sd->walktimer<0){ 
    sd->walktimer=0; 
    return 0; 
  } 
  dx=dirx[(int)sd->walkpath[sd->walkpath_pos]]; 
  dy=diry[(int)sd->walkpath[sd->walkpath_pos]]; 
  nx=sd->x+dx; 
  ny=sd->y+dy; 
  if(nx/BLOCK_SIZE != sd->x/BLOCK_SIZE || ny/BLOCK_SIZE != sd->y/BLOCK_SIZE){ 
    unsigned char buf[256]; 
    int bx,by; 
    bx=sd->x/BLOCK_SIZE; 
    by=sd->y/BLOCK_SIZE; 
    WBUFW(buf,0)=0x80; 
    WBUFL(buf,2)=sd->account_id; 
    WBUFB(buf,6)=0;	// no effect? 
    if(nx/BLOCK_SIZE != sd->x/BLOCK_SIZE && bx-dx*AREA_SIZE>=0 && bx-dx*AREA_SIZEmapno].bxs){ 
      for(i=-AREA_SIZE;i<=AREA_SIZE;i++){ 
	if(by+i < 0 || by+i >= map_data[sd->mapno].bys) 
	  continue; 
	mmo_map_sendblock(sd->mapno,bx-dx*AREA_SIZE,by+i,buf,packet_len_table[0x80],id,1); 
	mmo_map_clrblockchar(id,sd->mapno,bx-dx*AREA_SIZE,by+i); 
      } 
    } 
    if(ny/BLOCK_SIZE != sd->y/BLOCK_SIZE && by-dy*AREA_SIZE>=0 && by-dy*AREA_SIZEmapno].bys){ 
      for(i=-AREA_SIZE;i<=AREA_SIZE;i++){ 
	if(bx+i < 0 || bx+i >= map_data[sd->mapno].bxs) 
	  continue; 
	mmo_map_sendblock(sd->mapno,bx+i,by-dy*AREA_SIZE,buf,packet_len_table[0x80],id,1); 
	mmo_map_clrblockchar(id,sd->mapno,bx+i,by-dy*AREA_SIZE); 
      } 
    } 
    del_block(&sd->block); 
    add_block(&sd->block,sd->mapno,nx,ny); 
    mmo_map_set007b(id,buf,tick,sd->x,sd->y,sd->to_x,sd->to_y); 
    bx=nx/BLOCK_SIZE; 
    by=ny/BLOCK_SIZE; 
    if(nx/BLOCK_SIZE != sd->x/BLOCK_SIZE && bx+dx*AREA_SIZE>=0 && bx+dx*AREA_SIZEmapno].bxs){ 
      for(i=-AREA_SIZE;i<=AREA_SIZE;i++){ 
	if(by+i < 0 || by+i >= map_data[sd->mapno].bys) 
	  continue; 
	mmo_map_sendblock(sd->mapno,bx+dx*AREA_SIZE,by+i,buf,packet_len_table[0x7b],id,1); 
	mmo_map_getblockchar(id,sd->mapno,bx+dx*AREA_SIZE,by+i); 
      } 
    } 
    if(ny/BLOCK_SIZE != sd->y/BLOCK_SIZE && by+dy*AREA_SIZE>=0 && by+dy*AREA_SIZEmapno].bys){ 
      for(i=-AREA_SIZE;i<=AREA_SIZE;i++){ 
	if(bx+i < 0 || bx+i >= map_data[sd->mapno].bxs) 
	  continue; 
	mmo_map_sendblock(sd->mapno,bx+i,by+dy*AREA_SIZE,buf,packet_len_table[0x7b],id,1); 
	mmo_map_getblockchar(id,sd->mapno,bx+i,by+dy*AREA_SIZE); 
      } 
    } 
  } 
  sd->x+=dx; 
  sd->y+=dy; 
  //printf("walk_char %d (%d,%d) %d/%d %d\n",id,sd->x,sd->y,sd->walkpath_pos,sd->walkpath_len,sd->walkpath[sd->walkpath_pos]); 
  sd->walkpath_pos++; 
  if(sd->walkpath_pos>=sd->walkpath_len){ 
    sd->walkpath_pos=0; 
    sd->walkpath_len=0; 
    sd->walktimer=-1; 
  } 
  m=sd->mapno; 
  if(!map[m][0]) 
    return -1; 
  if(map_data[m].gat[sd->x+map_data[m].xs*sd->y]&0x80){ 
    int w; 
    sd->walkpath_pos=0; 
    sd->walkpath_len=0; 
    sd->walktimer=-1; 
    for(w=0;wblock.subtype!=WARP) 
	continue; 
      xs=map_data[m].npc[w]->u.warp.xs; 
      ys=map_data[m].npc[w]->u.warp.ys; 
      if(sd->x >= map_data[m].npc[w]->x-xs/2 && sd->x x-xs/2+xs && 
         sd->y >= map_data[m].npc[w]->y-ys/2 && sd->y y-ys/2+ys){ 
	mmo_map_changemap(id,sd,map_data[m].npc[w]->u.warp.name,map_data[m].npc[w]->u.warp.x,map_data[m].npc[w]->u.warp.y,0); 
	break; 
      } 
    } 
  } 
  if(sd->walkpath_pos>=sd->walkpath_len) 
    return 0; 
  if((i=calc_next_walk_step(id))>0){ 
    sd->walktimer=add_timer(tick+i,walk_char,id,sd->walkpath_pos); 
    //printf("walktimer=%d\n",sd->walktimer); 
  } 
  return 0; 
} 
 
int mmo_map_status_up(int fd,int type) 
{ 
  struct map_session_data *sd; 
  int need,len,val=0; 
 
  sd=session[fd]->session_data; 
 
  need=calc_need_status_point(sd,type); 
  if(typeSP_LUK || need<=0 || sd->status.status_pointstatus.status_point-=need; 
  len=mmo_map_set_param(fd,WFIFOP(fd,0),SP_STATUSPOINT); 
  if(len>0) WFIFOSET(fd,len); 
  switch(type){ 
  case SP_STR: 
    val=++sd->status.str; 
    break; 
  case SP_AGI: 
    val=++sd->status.agi; 
    break; 
  case SP_VIT: 
    val=++sd->status.vit; 
    break; 
  case SP_INT: 
    val=++sd->status.int_; 
    break; 
  case SP_DEX: 
    val=++sd->status.dex; 
    break; 
  case SP_LUK: 
	val=++sd->status.luk; 
	break; 
} 
  len=mmo_map_set_param(fd,WFIFOP(fd,0),type); 
  if(len>0) WFIFOSET(fd,len); 
  if(need!=calc_need_status_point(sd,type)){ 
    WFIFOW(fd,0)=0xbe; 
    WFIFOW(fd,2)=type-SP_STR+SP_USTR; 
    WFIFOB(fd,4)=calc_need_status_point(sd,type); 
    WFIFOSET(fd,5); 
  } 
  WFIFOW(fd,0)=0xbc; 
  WFIFOW(fd,2)=type; 
  WFIFOB(fd,4)=0x01; 
  WFIFOB(fd,5)=val; 
  WFIFOSET(fd,6); 
  return 0; 
} 
 
void write_log(char *mes) 
{ 
  FILE *log; 
  log=fopen("mes.log","a"); 
  if(log){ 
    fprintf(log,"%s\n",mes); 
    fclose(log); 
  } 
} 
 
int parse_map(int fd) 
{ 
  int i,x,y,len; 
int target_id; 
int player_id; 
 
  struct map_session_data *sd; 
  unsigned long tick; 
  if(char_fd<0) 
    session[fd]->eof=1; 
  sd=session[fd]->session_data; 
  if(session[fd]->eof){ 
    if(fd==char_fd) 
      char_fd=-1; 
    if(sd && sd->state.auth){ 
      del_block(&sd->block); 
      WFIFOW(fd,0)=0x80; 
      WFIFOL(fd,2)=sd->account_id; 
      WFIFOB(fd,6)=2;	//logout? 
      mmo_map_sendarea(fd,WFIFOP(fd,0),packet_len_table[0x80], 1 ); 
 
      if(char_fd>0){ 
	memcpy(sd->status.last_point.map,sd->mapname,16); 
	sd->status.last_point.x = sd->x; 
	sd->status.last_point.y = sd->y; 
 
	WFIFOW(char_fd,0)=0x2b01; 
	WFIFOW(char_fd,2)=sizeof(sd->status)+12; 
	WFIFOL(char_fd,4)=sd->account_id; 
	WFIFOL(char_fd,8)=sd->char_id; 
	memcpy(WFIFOP(char_fd,12),&sd->status,sizeof(sd->status)); 
	WFIFOSET(char_fd,WFIFOW(char_fd,2)); 
      } 
    } 
    close(fd); 
    delete_session(fd); 
    return 0; 
  } 
  printf("parse_map : %d %d %x\n",fd,RFIFOREST(fd),RFIFOW(fd,0)); 
  tick=gettick(); 
  if(RFIFOREST(fd)>=2){ 
    if(RFIFOW(fd,0)>=0x200 || packet_len_table[RFIFOW(fd,0)]==0 || 
       ((!sd || (sd && sd->state.auth==0)) && RFIFOW(fd,0)!=0x72)){ 
      close(fd); 
      session[fd]->eof=1; 
      return 0; 
    } 
    len=packet_len_table[RFIFOW(fd,0)]; 
    if(len==-1){ 
      if(RFIFOREST(fd)<4) 
	return 0; 
      len=RFIFOW(fd,2); 
    } 
    if(RFIFOREST(fd)session_data=malloc(sizeof(*sd)); 
	memset(sd,0,sizeof(*sd)); 
      } 
      WFIFOW(char_fd,0)=0x2afc; 
      sd->account_id=WFIFOL(char_fd,2)=RFIFOL(fd,2); 
      sd->char_id=WFIFOL(char_fd,6)=RFIFOL(fd,6); 
      sd->login_id1=WFIFOL(char_fd,10)=RFIFOL(fd,10); 
      sd->client_tick=RFIFOL(fd,14); 
      sd->sex=RFIFOB(fd,18); 
      sd->state.auth=0; 
      sd->fd=fd; 
      sd->block.type=BL_PC; 
      WFIFOSET(char_fd,14); 
 
      WFIFOL(fd,0)=RFIFOL(fd,2); 
      WFIFOSET(fd,4); 
      break; 
 
    case 0x7e: // tick send 
      sd->client_tick=RFIFOL(fd,2); 
      WFIFOL(fd,0)=0x7f; 
      sd->server_tick=WFIFOL(fd,2)=tick; 
      WFIFOSET(fd,6); 
      break; 
 
 
    case 0x7d: // load end ack 
      mmo_send_selfdata(fd,sd); 
      mmo_map_getareachar(fd); 
      mmo_map_set0079(fd,WFIFOP(fd,0)); 
      mmo_map_sendarea(fd,WFIFOP(fd,0),packet_len_table[0x79], 1 ); 
      break; 
    case 0x85: // walk to (x,y) 
    	player_id = sd->account_id; 
    	if(timer_info_a[player_id] != 0) {delete_timer(timer_info_a[player_id]);  timer_info_a[player_id]=0;} 
      x=RFIFOB(fd,2)*4+(RFIFOB(fd,3)>>6); 
      y=((RFIFOB(fd,3)&0x3f)<<4)+(RFIFOB(fd,4)>>4); 
      if(search_path(sd,sd->mapno,sd->x,sd->y,x,y,0)==0){ 
	sd->to_x=x; 
	sd->to_y=y; 
	WFIFOW(fd,0)=0x87; 
	WFIFOL(fd,2)=tick; 
	set_2pos(WFIFOP(fd,6),sd->x,sd->y,x,y); 
	WFIFOB(fd,11)=0; 
	WFIFOSET(fd,12); 
	mmo_map_set007b(fd,WFIFOP(fd,0),tick,sd->x,sd->y,x,y); 
	mmo_map_sendarea(fd,WFIFOP(fd,0),packet_len_table[0x7b],1); 
	if(sd->walktimer>0) 
	  delete_timer(sd->walktimer); 
	if((i=calc_next_walk_step(fd))>0){ 
	  sd->walktimer=add_timer(tick+i/2,walk_char,fd,0); 
	  //printf("walktimer=%d\n",sd->walktimer); 
	} 
      } 
      break; 
    case 0x0118: /* stop attack */ 
	target_id = RFIFOL(fd,2); 
	player_id = sd->account_id; 
	if(timer_info_a[player_id] != 0) {delete_timer(timer_info_a[player_id]);  timer_info_a[player_id]=0;} 
 
	break; 
    case 0x0089: /* attack or sitting request */ 
       switch(RFIFOB(fd,6)) { 
 
      case 0x0007:  /* start attack */ 
	if (sd->sitting != 2) { 
	target_id = RFIFOL(fd,2); 
	player_id = sd->account_id; 
 
	if(timer_info_a[player_id] != 0) { 
	delete_timer(timer_info_a[player_id]); 
	timer_info_a[player_id]=0; 
	//timer_info_a[player_id]=add_timer(tick+rand()%4+4,do_attack,target_id,fd); 
	do_attack(0,tick,target_id,fd); 
	} 
	else { 
	do_attack(0,tick,target_id,fd); 
	} 
 
	} 
	break; 
 
 
      case 0x0002: /* sit down */ 
	WFIFOW(fd,0) = 0x8a; 
	WFIFOL(fd,2) = sd->account_id; 
	WFIFOB(fd,26) = 2; 
	mmo_map_sendarea( fd, WFIFOP(fd,0), packet_len_table[0x8a], 0 ); 
	sd->sitting=2;	// 1にするとloginした人からは死体に見える (笑 
	break; 
      case 0x0003: /* stand up */ 
	WFIFOW(fd,0) = 0x8a; 
	WFIFOL(fd,2) = sd->account_id; 
	WFIFOB(fd,26) = 3; 
	mmo_map_sendarea( fd, WFIFOP(fd,0), packet_len_table[0x8a], 0 ); 
	sd->sitting=0; 
	break; 
      } 
      break; 
    case 0x8c: // global message 
      write_log(RFIFOP(fd,4)); 
      WFIFOW(fd,0)=0x8d; 
      WFIFOW(fd,2)=RFIFOW(fd,2)+4; 
      WFIFOL(fd,4)=sd->account_id; 
      memcpy(WFIFOP(fd,8),RFIFOP(fd,4),RFIFOW(fd,2)-4); 
      mmo_map_sendarea(fd,WFIFOP(fd,0),WFIFOW(fd,2),1); 
      memcpy(WFIFOP(fd,0),RFIFOP(fd,0),RFIFOW(fd,2)); 
      WFIFOW(fd,0)=0x8e; 
      WFIFOSET(fd,WFIFOW(fd,2)); 
      break; 
    case 0x94: // get char name req 
      mmo_map_send0095(fd,RFIFOL(fd,2)); 
      break; 
    case 0x96: // wis 
      sprintf(WFIFOP(fd,0),"wis to %s %s",RFIFOP(fd,4),RFIFOP(fd,28)); 
      write_log(WFIFOP(fd,0)); 
      if(strcmp(RFIFOP(fd,4),mapmove_name)==0){ 
	char mapname[32]; 
	int x,y; 
	if(sscanf(RFIFOP(fd,28),"%s%d%d",mapname,&x,&y)!=3) 
	  break; 
	for(i=0;map[i][0];i++) 
	  if(strcmp(map[i],mapname)==0){ 
	    mmo_map_changemap(fd,sd,mapname,x,y,2); 
	    break; 
	  } 
	if(map[i][0]==0){ 
	  WFIFOW(fd,0)=0x98; 
	  WFIFOB(fd,2)=2; 
	  WFIFOSET(fd,3); 
	} 
      } else 
	mmo_map_sendwis(fd); 
      break; 
    case 0x99: // GM message 
      write_log(RFIFOP(fd,4)); 
      memcpy(WFIFOP(fd,0),RFIFOP(fd,0),RFIFOW(fd,2)); 
      WFIFOW(fd,0)=0x9a; 
      mmo_map_sendall(fd, WFIFOP(fd,0), WFIFOW(fd,2), 0 ); 
      break; 
    case 0x9b: // change dir 
      WFIFOW(fd,0)=0x9c; 
      WFIFOL(fd,2)=sd->account_id; 
      WFIFOW(fd,6)=RFIFOW(fd,2); 
      WFIFOB(fd,8)=RFIFOW(fd,4); 
      mmo_map_sendarea(fd,WFIFOP(fd,0),9,1); 
 
      sd->head_dir=RFIFOW(fd,2); 
      sd->dir=RFIFOB(fd,4); 
      break; 
    case 0xb2: 
      switch(RFIFOB(fd,2)) { 
      case 0x00: // restart 
	break; 
      case 0x01: // char sel 
	WFIFOW(fd,0)=0xb3; 
	WFIFOB(fd,2)=1; 
	WFIFOSET(fd,3); 
	break; 
      } 
      break; 
 
    case 0xbf: // emotion 
      WFIFOW(fd,0)=0xc0; 
      WFIFOL(fd,2)=sd->account_id; 
      WFIFOB(fd,6)=RFIFOB(fd,2); 
      mmo_map_sendarea(fd,WFIFOP(fd,0),7,0); 
      break; 
    case 0xc1: // how many connections 
      WFIFOW(fd,0)=0xc2; 
      WFIFOL(fd,2)=users_global; 
      WFIFOSET(fd,6); 
      break; 
    case 0x18a: // quit game 
      WFIFOW(fd,0)=0x18b; 
      WFIFOW(fd,2)=0; 
      WFIFOSET(fd,4); 
      break; 
 
    case 0xbb: // status up 
      mmo_map_status_up(fd,RFIFOW(fd,2)); 
      break; 
 
    case 0x90: // NPC clicked 
      npc_click(fd,RFIFOL(fd,2)); 
      break; 
 
      // for script NPC 
    case 0xb8: // NPC select menu 
      npc_menu_select(fd,RFIFOL(fd,2),RFIFOB(fd,6)); 
      break; 
    case 0xb9: // NPC next clicked 
      npc_next_click(fd,RFIFOL(fd,2)); 
      break; 
    case 0x143: // NPC amount input 
      npc_amount_input(fd,RFIFOL(fd,2),RFIFOL(fd,6)); 
      break; 
    case 0x146: // NPC close clicked 
      npc_close_click(fd,RFIFOL(fd,2)); 
      break; 
 
      // for shop NPC 
    case 0xc5: // NPC buy or sell selected 
      npc_buysell_selected(fd,RFIFOL(fd,2),RFIFOB(fd,6)); 
      break; 
    case 0xc8: // NPC buy list send 
      npc_buy_selected(fd,RFIFOP(fd,4),(RFIFOW(fd,2)-4)/4); 
      break; 
    case 0xc9: // NPC sell list send 
      npc_sell_selected(fd,RFIFOP(fd,4),(RFIFOW(fd,2)-4)/4); 
      break; 
    default: 
      break; 
 
      // floor item 
    case 0xa2: // drop item 
      mmo_map_dropitem(fd,RFIFOW(fd,2),RFIFOW(fd,4)); 
      break; 
    case 0x9f: // take item 
      mmo_map_takeitem(fd,RFIFOL(fd,2)); 
      break; 
case 0xa9: 
	if(itemdb_type(sd->status.inventory[RFIFOW(fd,2)-2].nameid)!=4 && itemdb_type(sd->status.inventory[RFIFOW(fd,2)-2].nameid)!=5) 
	{ 
	WFIFOW(fd,0)=0xaa; 
	WFIFOW(fd,2)=RFIFOW(fd,2); 
	WFIFOW(fd,4)=RFIFOW(fd,4); 
	WFIFOB(fd,6)=0; 
	WFIFOSET(fd,7); 
	break; 
	} 
	sd->status.inventory[RFIFOW(fd,2)-2].equip=RFIFOW(fd,4); 
	WFIFOW(fd,0)=0xaa; 
	WFIFOW(fd,2)=RFIFOW(fd,2); 
	WFIFOW(fd,4)=RFIFOW(fd,4); 
	WFIFOB(fd,6)=1; 
	WFIFOSET(fd,7); 
	break; 
case 0xab: 
	WFIFOW(fd,0)=0xac; 
	WFIFOW(fd,2)=RFIFOW(fd,2); 
	WFIFOW(fd,4)=sd->status.inventory[RFIFOW(fd,2)-2].equip; 
	WFIFOB(fd,6)=1; 
	WFIFOSET(fd,7); 
	sd->status.inventory[RFIFOW(fd,2)-2].equip=0; 
	break; 
} 
RFIFOSKIP(fd,len); 
} 
return 0; 
 
} 
 
int send_users_tochar(int tid,unsigned int tick,int id,int data) 
{ 
  int users=0,i; 
  struct map_session_data *sd; 
 
  for(i=0;isession_data) && sd->state.auth) 
      users++; 
  } 
  if(char_fd>0 && session[char_fd]){ 
    WFIFOW(char_fd,0)=0x2aff; 
    WFIFOL(char_fd,2)=users; 
    WFIFOSET(char_fd,6); 
  } 
  return 0; 
} 
 
int check_connect_char_server(int tid,unsigned int tick,int id,int data) 
{ 
  if(char_fd<=0 || session[char_fd]==NULL){ 
    char_fd=make_connection(inet_addr(char_ip_str),char_port); 
    session[char_fd]->func_parse=parse_tochar; 
    WFIFOW(char_fd,0)=0x2af8; 
    memcpy(WFIFOP(char_fd,2),userid,24); 
    memcpy(WFIFOP(char_fd,26),passwd,24); 
    WFIFOL(char_fd,50)=0; 
    WFIFOL(char_fd,54)=map_ip; 
    WFIFOL(char_fd,58)=map_port; 
    WFIFOSET(char_fd,60); 
  } 
  return 0; 
} 
 
void mmo_map_allclose(void) 
{ 
  int fd; 
  struct map_session_data *sd; 
 
  for(fd=0;fdsession_data) && sd->state.auth){ 
      if(char_fd>0 && session[char_fd]){ 
	memcpy(sd->status.last_point.map,sd->mapname,16); 
	sd->status.last_point.x = sd->x; 
	sd->status.last_point.y = sd->y; 
 
	WFIFOW(char_fd,0)=0x2b01; 
	WFIFOW(char_fd,2)=sizeof(sd->status)+12; 
	WFIFOL(char_fd,4)=sd->account_id; 
	WFIFOL(char_fd,8)=sd->char_id; 
	memcpy(WFIFOP(char_fd,12),&sd->status,sizeof(sd->status)); 
	write(char_fd,WFIFOP(char_fd,0),WFIFOW(char_fd,2)); 
      } 
    } 
    close(fd); 
    delete_session(fd); 
  } 
  if(char_fd>0){ 
    close(char_fd); 
    delete_session(char_fd); 
    char_fd=-1; 
  } 
  script_close(); 
  return; 
} 
 
int read_mapdata(void) 
{ 
  int i; 
 
  // read&convert *.gat files 
  for(i=0;map[i][0];i++){ 
    char fn[256]; 
    unsigned char *gat; 
    int s; 
 
    if(strstr(map[i],".gat")==NULL) 
      continue; 
    sprintf(fn,"data\\%s",map[i]); 
    gat=grfio_read(fn); 
    if(gat){ 
      int x,y,xs,ys; 
      struct gat_1cell {float high[4]; int type;} *p; 
 
      xs=map_data[i].xs=*(int*)(gat+6); 
      ys=map_data[i].ys=*(int*)(gat+10); 
      map_data[i].gat=malloc(s=map_data[i].xs*map_data[i].ys); 
      map_data[i].npc_num=0; 
      for(y=0;ytype==0){ 
	    map_data[i].gat[x+y*xs]=(p->high[0]<0 || p->high[1]<0 || p->high[2]<0 || p->high[3]<0) ? 3 : 0; 
	  } else { 
	    map_data[i].gat[x+y*xs]=p->type; 
	  } 
	  p++; 
	} 
      } 
      free(gat); 
      map_data[i].bxs=(xs+BLOCK_SIZE-1)/BLOCK_SIZE; 
      map_data[i].bys=(ys+BLOCK_SIZE-1)/BLOCK_SIZE; 
      map_data[i].block=malloc(map_data[i].bxs*map_data[i].bys*sizeof(struct block_list)); 
      for(y=0;ytype=TIMER_INTERVAL; 
  timer_data[i]->interval=10*1000; 
 
  i=add_timer(gettick()+10,send_users_tochar,0,0); 
  timer_data[i]->type=TIMER_INTERVAL; 
  timer_data[i]->interval=5*1000; 
 
  i=add_timer(gettick()+10,clear_flooritem,0,0); 
  timer_data[i]->type=TIMER_INTERVAL; 
  timer_data[i]->interval=1000; 
 
  return 0; 
}