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;j session_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;i session_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;fd session_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;i session_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;i mapno].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(type SP_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;c inventory[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;c inventory[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->amount amount-=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;i session_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;i status.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;i status.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;i status.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;i status.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(c1 1 || 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;i walkpath[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_SIZE mapno].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_SIZE mapno].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_SIZE mapno].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_SIZE mapno].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;w block.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(type SP_LUK || need<=0 || sd->status.status_point status.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;i session_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;fd session_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;y type==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;y type=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; }