www.pudn.com > ro4fserver.rar > npc.c
#include#include #include #include #include "core.h" #include "mmo.h" #include "npc.h" #include "itemdb.h" #include "script.h" struct mons_data m_data[99999]; static int npc_id=50000; extern char npc_txt[]; extern char map[][16]; extern struct mmo_map_data map_data[]; extern int packet_len_table[]; #define WARP_CLASS 45 #define add_block_npc(m,n) {add_block(&map_data[m].npc[n]->block,m,map_data[m].npc[n]->x,map_data[m].npc[n]->y); \ map_data[m].npc[n]->block.type=BL_NPC;} int mmo_map_npc_say(int fd, unsigned char* buf,unsigned long id, char *string) { WBUFW(buf,0)=0xb4; WBUFW(buf,2)=strlen(string)+9; WBUFL(buf,4)=id; strncpy(WBUFP(buf,8), string,strlen(string)+1); return WBUFW(buf,2); } int send_image(int fd,unsigned char *buf, char *name,int type) { name[15]=0; //So it doesn't copy more than 15 bytes WBUFW(buf,0)=0x0145; strcpy(WBUFP(buf,2),name); WBUFB(buf,18)=type; return 19; } int mmo_map_npc_next(int fd, unsigned char* buf, unsigned long id) { WBUFW(buf,0)=0xb5; WBUFL(buf,2)=id; return 6; } int mmo_map_npc_close(int fd, unsigned char* buf, unsigned long id) { WBUFW(buf,0)=0xb6; WBUFL(buf,2)=id; return 6; } int mmo_map_npc_select(int fd, unsigned char* buf, unsigned long id, char *string) { WBUFW(buf,0)=0xb7; WBUFW(buf,2)=strlen(string)+9; WBUFL(buf,4)=id; strncpy(WBUFP(buf,8), string, strlen(string)+1); return WBUFW(buf,2); } int mmo_map_npc_amount_request(int fd, unsigned char* buf, unsigned long id) { WBUFW(buf,0)=0x142; WBUFL(buf,2)=id; return 6; } int mmo_map_npc_buysell(int fd, unsigned char* buf, unsigned long id) { WBUFW(buf,0)=0xc4; WBUFL(buf,2)=id; return 6; } int mmo_map_npc_buy(int fd, unsigned char* buf, unsigned long id, struct npc_item_list *items, int dc_skill) { int i; WBUFW(buf,0)=0xc6; for(i=0;items[i].nameid;i++){ WBUFL(buf,4+i*11)=items[i].value; WBUFL(buf,8+i*11)=items[i].value; WBUFB(buf,12+i*11)=itemdb_type(items[i].nameid); WBUFW(buf,13+i*11)=items[i].nameid; } WBUFW(buf,2)=i*11+4; return i*11+4; } int mmo_map_npc_sell(int fd, unsigned char* buf, unsigned long id, int oc_skill) { int i,c_item=0; struct map_session_data *sd; sd=session[fd]->session_data; WBUFW(buf,0)=0xc7; for(i=0;i status.inventory[i].nameid) { WBUFW(buf,4+c_item*10)=i+2; WBUFL(buf,6+c_item*10)=itemdb_sellvalue(sd->status.inventory[i].nameid); WBUFL(buf,10+c_item*10)=WBUFL(buf,6+c_item*10); c_item++; } } WBUFW(buf,2)=c_item*10+4; return c_item*10+4; } int npc_click(int fd,int npc_id) { int npc_len,n; struct map_session_data *sd; sd=session[fd]->session_data; for(n=0;n mapno].npc_num;n++) if(map_data[sd->mapno].npc[n]->id==npc_id) break; if(n==map_data[sd->mapno].npc_num || map_data[sd->mapno].npc[n]->block.type!=BL_NPC) return -1; switch(map_data[sd->mapno].npc[n]->block.subtype){ case SCRIPT: sd->npc_pc=0; sd->npc_id=npc_id; sd->npc_n=n; run_script(fd,sd); break; case SHOP: npc_len = mmo_map_npc_buysell(fd, WFIFOP(fd,0),npc_id); WFIFOSET(fd, npc_len); sd->npc_id=npc_id; sd->npc_n=n; break; } #if 0 /*NPC test code*/ if(npc_id==1) { npc_len = mmo_map_npc_say(fd, WFIFOP(fd,0),1,"test"); WFIFOSET(fd, npc_len); mmo_map_npc_next(fd, WFIFOP(fd,0),1); WFIFOSET(fd, 6); } #endif return 0; } int npc_menu_select(int fd,int npc_id,int sel) { struct map_session_data *sd; sd=session[fd]->session_data; sd->local_reg[15]=sel; if(sel==0xff){ sd->npc_pc=0; sd->npc_id=0; sd->npc_n=0; return 0; } run_script(fd,sd); return 0; } int npc_next_click(int fd,int npc_id) { struct map_session_data *sd; sd=session[fd]->session_data; run_script(fd,sd); return 0; } int npc_amount_input(int fd,int npc_id,int val) { struct map_session_data *sd; sd=session[fd]->session_data; sd->local_reg[14]=val; run_script(fd,sd); return 0; } int npc_close_click(int fd,int npc_id) { return 0; } int npc_buysell_selected(int fd,int npc_id,int sell) { int npc_len,n; struct map_session_data *sd; sd=session[fd]->session_data; for(n=0;n mapno].npc_num;n++) if(map_data[sd->mapno].npc[n]->id==npc_id) break; if(n==map_data[sd->mapno].npc_num || map_data[sd->mapno].npc[n]->block.type!=BL_NPC || map_data[sd->mapno].npc[n]->block.subtype!=SHOP || sd->npc_id!=npc_id) return -1; if(sell){ npc_len = mmo_map_npc_sell(fd, WFIFOP(fd,0),npc_id,0); } else { npc_len = mmo_map_npc_buy(fd, WFIFOP(fd,0),npc_id,map_data[sd->mapno].npc[n]->u.shop_item,0); } WFIFOSET(fd, npc_len); return 0; } struct map_session_data* make_rollback_point(struct map_session_data *sd) { struct map_session_data *back; back=malloc(sizeof(*back)); memcpy(back,sd,sizeof(*back)); return back; } int do_rollback(struct map_session_data *sd,struct map_session_data *back) { memcpy(sd,back,sizeof(*back)); free(back); return 0; } int delete_rollback_point(struct map_session_data *back) { free(back); return 0; } int npc_buy_selected(int fd,void *list,int num) { int i,j,n,len,pos; struct item tmp_item; struct map_session_data *sd,*back; int fail=0; sd=session[fd]->session_data; for(n=0;n mapno].npc_num;n++) if(map_data[sd->mapno].npc[n]->id==sd->npc_id) break; if(n==map_data[sd->mapno].npc_num || map_data[sd->mapno].npc[n]->block.type!=BL_NPC || map_data[sd->mapno].npc[n]->block.subtype!=SHOP) return -1; back=make_rollback_point(sd); memset(&tmp_item,0,sizeof(tmp_item)); for(i=pos=0;i mapno].npc[n]->u.shop_item[j].nameid;j++) if(map_data[sd->mapno].npc[n]->u.shop_item[j].nameid==tmp_item.nameid) break; if(map_data[sd->mapno].npc[n]->u.shop_item[j].nameid==0){ fail=1; // 今お話中のNPCで売ってないアイテムが指定されたっぽ session[fd]->eof=1; // プチっ break; } len=mmo_map_item_get(fd,WFIFOP(fd,pos),&tmp_item); if(len<=0){ if(len==-1) fail=3; // 種類数超過。3万個越えも考えられるけど、面倒なので統一 else if(len==-2) fail=2; // 重量オーバ else fail=3; // 謎 break; } pos+=len; sd->status.zeny -= map_data[sd->mapno].npc[n]->u.shop_item[j].value*tmp_item.amount; if(sd->status.zeny < 0){ fail=1; // お金不足 break; } pos+=mmo_map_set_param(fd,WFIFOP(fd,pos),SP_ZENY); } if(fail){ do_rollback(sd,back); } else { WFIFOSET(fd,pos); delete_rollback_point(back); } WFIFOW(fd,0)=0xca; WFIFOB(fd,2)=fail; WFIFOSET(fd,3); return 0; } int npc_sell_selected(int fd,void *list,int num) { int i,len,pos; struct map_session_data *sd,*back; int fail=0; sd=session[fd]->session_data; back=make_rollback_point(sd); for(i=pos=0;i status.zeny+=itemdb_sellvalue(sd->status.inventory[RBUFW(list,i*4)-2].nameid)*RBUFW(list,i*4+2); pos+=mmo_map_set_param(fd,WFIFOP(fd,pos),SP_ZENY); len=mmo_map_item_lost(fd,WFIFOP(fd,pos),RBUFW(list,i*4),RBUFW(list,i*4+2)); if(len<=0){ fail=1; break; } pos+=len; } if(fail){ do_rollback(sd,back); } else { WFIFOSET(fd,pos); delete_rollback_point(back); } WFIFOW(fd,0)=0xcb; WFIFOB(fd,2)=fail; WFIFOSET(fd,3); return 0; } int set_monster_random_point(int m,int n) { int x,y; do { x=rand()%(map_data[m].xs-1); y=rand()%(map_data[m].ys-1); } while(map_data[m].gat[x+y*map_data[m].xs]==1 || map_data[m].gat[x+y*map_data[m].xs]==5); map_data[m].npc[n]->u.mons.to_x=map_data[m].npc[n]->x=x; map_data[m].npc[n]->u.mons.to_y=map_data[m].npc[n]->y=y; return 0; } int mons_walk(int tid,unsigned int tick,int m,int n) { int x,y,dx,dy; struct map_session_data sd; int ret,i; x=map_data[m].npc[n]->x; y=map_data[m].npc[n]->y; dx= map_data[m].npc[n]->u.mons.to_x - x; dy= map_data[m].npc[n]->u.mons.to_y - y; if(dx || dy){ // step if(dx<0) dx=-1; else if(dx>0) dx=1; if(dy<0) dy=-1; else if(dy>0) dy=1; if((x+dx)/BLOCK_SIZE != x/BLOCK_SIZE || (y+dy)/BLOCK_SIZE != y/BLOCK_SIZE){ unsigned char buf[256]; int bx,by; bx=x/BLOCK_SIZE; by=y/BLOCK_SIZE; WBUFW(buf,0)=0x80; WBUFL(buf,2)=map_data[m].npc[n]->id; WBUFB(buf,6)=0; // no effect? if((x+dx)/BLOCK_SIZE != x/BLOCK_SIZE && bx-dx*AREA_SIZE>=0 && bx-dx*AREA_SIZE = map_data[m].bys) continue; mmo_map_sendblock(m,bx-dx*AREA_SIZE,by+i,buf,packet_len_table[0x80],0,0); } } if((y+dy)/BLOCK_SIZE != y/BLOCK_SIZE && by-dy*AREA_SIZE>=0 && by-dy*AREA_SIZE = map_data[m].bxs) continue; mmo_map_sendblock(m,bx+i,by-dy*AREA_SIZE,buf,packet_len_table[0x80],0,0); } } del_block(&map_data[m].npc[n]->block); add_block(&map_data[m].npc[n]->block,m,x+dx,y+dy); memset(buf,0,256); WBUFW(buf,0)=0x7b; WBUFL(buf,2)=map_data[m].npc[n]->id; WBUFW(buf,6)=map_data[m].npc[n]->u.mons.speed; WBUFW(buf,14)=map_data[m].npc[n]->class; WBUFL(buf,22)=tick; set_2pos(WBUFP(buf,50),x,y,map_data[m].npc[n]->u.mons.to_x,map_data[m].npc[n]->u.mons.to_y); WBUFB(buf,55)=0; WBUFB(buf,56)=5; WBUFB(buf,57)=5; bx=(x+dx)/BLOCK_SIZE; by=(y+dy)/BLOCK_SIZE; if((x+dx)/BLOCK_SIZE != x/BLOCK_SIZE && bx+dx*AREA_SIZE>=0 && bx+dx*AREA_SIZE = map_data[m].bys) continue; mmo_map_sendblock(m,bx+dx*AREA_SIZE,by+i,buf,packet_len_table[0x7b],0,0); } } if((y+dy)/BLOCK_SIZE != y/BLOCK_SIZE && by+dy*AREA_SIZE>=0 && by+dy*AREA_SIZE = map_data[m].bxs) continue; mmo_map_sendblock(m,bx+i,by+dy*AREA_SIZE,buf,packet_len_table[0x7b],0,0); } } } map_data[m].npc[n]->x+=dx; map_data[m].npc[n]->y+=dy; dx= map_data[m].npc[n]->u.mons.to_x - map_data[m].npc[n]->x; dy= map_data[m].npc[n]->u.mons.to_y - map_data[m].npc[n]->y; if(dx==0 && dy==0){ map_data[m].npc[n]->u.mons.timer= add_timer(tick+rand()%5000+5000,mons_walk,m,n); } else { map_data[m].npc[n]->u.mons.timer= add_timer(tick+map_data[m].npc[n]->u.mons.speed*((dx&&dy)?14:10)/10,mons_walk,m,n); } return 0; } // search target for(i=0;i<5;i++){ dx=rand()%(12*2+1)-12; dy=rand()%(12*2+1)-12; ret=search_path(&sd,m,map_data[m].npc[n]->x,map_data[m].npc[n]->y,map_data[m].npc[n]->x+dx,map_data[m].npc[n]->y+dy,1); if(ret==0) break; } if(ret==0){ unsigned char buf[256]; memset(buf,0,256); WBUFW(buf,0)=0x7b; WBUFL(buf,2)=map_data[m].npc[n]->id; WBUFW(buf,6)=map_data[m].npc[n]->u.mons.speed; WBUFW(buf,14)=map_data[m].npc[n]->class; WBUFL(buf,22)=tick; set_2pos(WBUFP(buf,50),map_data[m].npc[n]->x,map_data[m].npc[n]->y,map_data[m].npc[n]->x+dx,map_data[m].npc[n]->y+dy); WBUFB(buf,55)=0; WBUFB(buf,56)=5; WBUFB(buf,57)=5; mmo_map_sendarea_mxy(m,map_data[m].npc[n]->x,map_data[m].npc[n]->y,buf,packet_len_table[0x7b]); map_data[m].npc[n]->u.mons.to_x=map_data[m].npc[n]->x+dx; map_data[m].npc[n]->u.mons.to_y=map_data[m].npc[n]->y+dy; map_data[m].npc[n]->u.mons.timer= add_timer(tick+map_data[m].npc[n]->u.mons.speed/2*((dx&&dy)?14:10)/10,mons_walk,m,n); return 0; } map_data[m].npc[n]->u.mons.timer= add_timer(tick+rand()%5000+5000,mons_walk,m,n); return 0; } int read_npcdata(void) { char line_l[1024]; FILE *fl; // parse npc.txt fl=fopen("monster.txt","r"); if(fl==NULL) return -1; while(fgets(line_l,1020,fl)){ char l1[1024],l2[1024],l3[1024],l4[1024]; int move; int base_xp,job_xp,group; if(sscanf(line_l,"%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]",l1,l2,l3,l4)!=4 || sscanf(l1,"%d,%d,%d,%d",&move,&base_xp,&job_xp,&group)!=4) continue; if(strcmp(l2,"monster_info")==0){ int class,num,hp; sscanf(l4,"%d,%d,%d",&class,&hp); m_data[class].base_exp = base_xp; m_data[class].job_exp = job_xp; m_data[class].group = group; m_data[class].health_points = hp; m_data[class].move = move; if (m_data[class].health_points == 0) {m_data[class].health_points = 1000; } printf("monster_info %s read done\n",l3); } } fclose(fl); int i; char line[1024]; FILE *fp; // parse npc.txt fp=fopen(npc_txt,"r"); if(fp==NULL) return -1; while(fgets(line,1020,fp)){ char mapname[256],w1[1024],w2[1024],w3[1024],w4[1024]; int x,y,dir; if(sscanf(line,"%[^\t]\t%[^\t]\t%[^\t]\t%[^\t]",w1,w2,w3,w4)!=4 || sscanf(w1,"%[^,],%d,%d,%d",mapname,&x,&y,&dir)!=4) continue; for(i=0;map[i][0];i++) if(strcmp(map[i],mapname)==0) break; if(map[i][0]==0) continue; if(strcmp(w2,"warp")==0){ int j,k,xs,ys,to_x,to_y; map_data[i].npc[map_data[i].npc_num]=malloc(sizeof(struct npc_data)); map_data[i].npc[map_data[i].npc_num]->m=i; map_data[i].npc[map_data[i].npc_num]->x=x; map_data[i].npc[map_data[i].npc_num]->y=y; memcpy(map_data[i].npc[map_data[i].npc_num]->name,w3,24); map_data[i].npc[map_data[i].npc_num]->class=WARP_CLASS; map_data[i].npc[map_data[i].npc_num]->id=npc_id++; sscanf(w4,"%d,%d,%[^,],%d,%d", &xs,&ys, map_data[i].npc[map_data[i].npc_num]->u.warp.name, &to_x,&to_y); map_data[i].npc[map_data[i].npc_num]->u.warp.x=to_x; map_data[i].npc[map_data[i].npc_num]->u.warp.y=to_y; map_data[i].npc[map_data[i].npc_num]->u.warp.xs=xs; map_data[i].npc[map_data[i].npc_num]->u.warp.ys=ys; for(j=0;j id); map_data[i].npc[map_data[i].npc_num]->block.subtype=WARP; add_block_npc(i,map_data[i].npc_num); map_data[i].npc_num++; } else if(strcmp(w2,"monster")==0){ int j,class,num; sscanf(w4,"%d,%d",&class,&num); for(j=0;j class=class; monster_nums[npc_id] = map_data[i].npc_num; monster_i[npc_id] = i; map_data[i].npc[map_data[i].npc_num]->id=npc_id++; memcpy(map_data[i].npc[map_data[i].npc_num]->name,w3,24); if (m_data[class].move == 1) { map_data[i].npc[map_data[i].npc_num]->u.mons.timer= add_timer(gettick()+rand()%5000+5000,mons_walk,i,map_data[i].npc_num); } map_data[i].npc[map_data[i].npc_num]->u.mons.speed=200; map_data[i].npc[map_data[i].npc_num]->block.subtype=MONS; add_block_npc(i,map_data[i].npc_num); map_data[i].npc_num++; } printf("monster %s read done\n",w3); } else if(strcmp(w2,"shop")==0){ char *p; int max=32,pos=0; struct npc_item_list *item_list; map_data[i].npc[map_data[i].npc_num]=malloc(sizeof(struct npc_data)); map_data[i].npc[map_data[i].npc_num]->m=i; map_data[i].npc[map_data[i].npc_num]->x=x; map_data[i].npc[map_data[i].npc_num]->y=y; map_data[i].npc[map_data[i].npc_num]->dir=dir; memcpy(map_data[i].npc[map_data[i].npc_num]->name,w3,24); map_data[i].npc[map_data[i].npc_num]->class=atoi(w4); map_data[i].npc[map_data[i].npc_num]->id=npc_id++; map_data[i].npc[map_data[i].npc_num]->block.subtype=SHOP; item_list=malloc(sizeof(item_list[0])*(max+1)); p=strchr(w4,','); while(p && pos u.shop_item=item_list; add_block_npc(i,map_data[i].npc_num); printf("shop %s read done\n",w3); map_data[i].npc_num++; } else if(strcmp(w2,"script")==0){ char *buf; int size=65536,j; map_data[i].npc[map_data[i].npc_num]=malloc(sizeof(struct npc_data)); map_data[i].npc[map_data[i].npc_num]->m=i; map_data[i].npc[map_data[i].npc_num]->x=x; map_data[i].npc[map_data[i].npc_num]->y=y; map_data[i].npc[map_data[i].npc_num]->dir=dir; memcpy(map_data[i].npc[map_data[i].npc_num]->name,w3,24); map_data[i].npc[map_data[i].npc_num]->class=atoi(w4); map_data[i].npc[map_data[i].npc_num]->id=npc_id++; map_data[i].npc[map_data[i].npc_num]->block.subtype=SCRIPT; buf=malloc(size); if(strchr(w4,'{')) strcpy(buf,strchr(w4,'{')); else buf[0]=0; while(1){ for(j=strlen(buf)-1;j>=0 && isspace(buf[j]);j--); if(j>=0 && buf[j]=='}') break; fgets(line,1020,fp); if(feof(fp)) break; if(strlen(buf)+strlen(line)>=size){ size+=65536; buf=realloc(buf,size); } if(strchr(buf,'{')==NULL){ if(strchr(line,'{')) strcpy(buf,strchr(line,'{')); } else strcat(buf,line); } map_data[i].npc[map_data[i].npc_num]->u.script=parse_script(buf); add_block_npc(i,map_data[i].npc_num); printf("script %s read done\n",w3); map_data[i].npc_num++; } } fclose(fp); return 0; }