map2.c
来自「CS反恐精英1.6的部分C源代码。」· C语言 代码 · 共 2,313 行 · 第 1/5 页
C
2,313 行
if(len>0) WFIFOSET(fd,len);
// ASPD
len=mmo_map_set_param(fd,WFIFOP(fd,0),SP_ASPD);
if(len>0) WFIFOSET(fd,len);
// skill
//skill information and aquisition
len=mmo_map_all_skill(fd,WFIFOP(fd,0),sd->status.skill_point,0);
if(len>0) WFIFOSET(fd,len);
return 0;
}
/*reworking jobchange function (experimental)*/
int mmo_map_jobchange(int fd,int class)
{
int len;
struct map_session_data *sd;
sd=session[fd]->session_data;
//Fred JobLevel Reset ;)
sd->status.job_level=1;
WFIFOW(fd,0) = 0xb0;
WFIFOW(fd,2) = 0x37;
WFIFOL(fd,4) = 1;
WFIFOSET(fd,8);
//Hud Skill Point Reset
mmo_map_update_param(fd,SP_SKILLPOINT,-(sd->status.skill_point));
sd->status.class=class;
//the argument you see changes (3~)丂sd->account_id(apply ID)LOOK_BASE乮substance乯,sd->status.class(type)
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);
mmo_map_calc_status(fd,0,0);
len = mmo_map_all_skill(fd,WFIFOP(fd,0),sd->status.skill_point,0);
if(len>0) WFIFOSET(fd,len);
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) possible cell searching among them. random drops?
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 (150)
int calc_cost(struct mmo_tmp_path *p,int x1,int y1)
{
int xd,yd;
xd=x1-p->x;
if(xd<0) xd=-xd;
yd=y1-p->y;
if(yd<0) yd=-yd;
return (xd+yd)*10+p->dist;
}
int add_path(struct mmo_tmp_path *path,int *wp,int x,int y,int dist,int dir,int before,int x1,int y1)
{
int i;
for(i=0;i<*wp;i++)
if(path[i].x==x && path[i].y==y){
if(path[i].dist>dist){
path[i].dist=dist;
path[i].dir=dir;
path[i].before=before;
path[i].cost=calc_cost(&path[i],x1,y1);
path[i].flag=0;
}
return 0;
}
//printf("add_path %d %d,%d,%d,%d,%d\n",*wp,x,y,dist,dir,before);
path[*wp].x=x;
path[*wp].y=y;
path[*wp].dist=dist;
path[*wp].dir=dir;
path[*wp].before=before;
path[*wp].cost=calc_cost(&path[*wp],x1,y1);
path[*wp].flag=0;
*wp=*wp+1;
return 0;
}
int can_move(struct mmo_map_data *m,int x0,int y0,int x1,int y1)
{
int c;
if(x0-x1<-1 || x0-x1>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;
}
//FRED11
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];
if( (x0>0) && (y0>0)&& (x1>0) &&(y1>0) ) {
// easy
dx = (x1-x0<0) ? -1 : 1;
dy = (y1-y0<0) ? -1 : 1;
for(x=x0,y=y0,i=0;(x!=x1 || y!=y1) && (i<64);){
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
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=calc_cost(&tmp_path[wp],x1,y1);
tmp_path[wp++].flag=0;
while(1){
int min_cost,min_pos,max_dist;
for(i=0,min_cost=65536,max_dist=-1,min_pos=-1;i<wp;i++){
if(tmp_path[i].flag==0 && (tmp_path[i].cost<min_cost ||
(tmp_path[i].cost==min_cost && tmp_path[i].dist>max_dist))){
min_pos=i;
min_cost=tmp_path[i].cost;
max_dist=tmp_path[i].dist;
}
}
if(min_pos<0)
return -1;
rp=min_pos;
x=tmp_path[rp].x;
y=tmp_path[rp].y;
if(x==x1 && y==y1){
int len,j;
for(len=0,i=rp;len<100 && i!=0;i=tmp_path[i].before,len++);
if(len==100 || len>=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<len;i++)
//printf("%d",sd->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,x1,y1);
if(can_move(m,x,y,x+1,y ))
add_path(tmp_path,&wp,x+1,y ,tmp_path[rp].dist+10,6,rp,x1,y1);
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,x1,y1);
if(can_move(m,x,y,x ,y+1))
add_path(tmp_path,&wp,x ,y+1,tmp_path[rp].dist+10,0,rp,x1,y1);
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,x1,y1);
if(can_move(m,x,y,x-1,y ))
add_path(tmp_path,&wp,x-1,y ,tmp_path[rp].dist+10,2,rp,x1,y1);
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,x1,y1);
if(can_move(m,x,y,x ,y-1))
add_path(tmp_path,&wp,x ,y-1,tmp_path[rp].dist+10,4,rp,x1,y1);
if(wp>=MAX_TMP_PATH-5)
return -1;
tmp_path[rp].flag=1;
}
return -1;
}
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)
{
int m,j;
m=sd->mapno;
//changing maps while escaping
for(j=0;j<map_data[m].npc_num;j++){
if(map_data[m].npc[j]->block.subtype==MONS){//if monster
if(map_data[m].npc[j]->u.mons.target_id == sd->account_id){
mmo_mons_attack_no(m,j,sd->account_id,gettick());
}
}
}
del_block(&sd->block);
// pet processing
if(sd->status.pet.activity == 1)
{
// changing maps on the same server
WFIFOW(id,0) = 0x80;
WFIFOL(id,2) = sd->status.pet.pet_id_as_npc;
WFIFOB(id,6) = 0;
WFIFOSET(id,7);
del_block(&map_data[sd->mapno].npc[sd->status.pet.pet_npc_id_on_map[sd->mapno]]->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 );
current_attack_m=0;
map_data[sd->mapno].users--;
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};
// ADDED on 04/09/2003 ------------------
char buf[256];
// --------------------------------------
//printf("walk_char %d %08x %d\n",id,tick,data);
if(session[id]==NULL || (sd=session[id]->session_data)==NULL)
return 0;
if(sd->walktimer != tid){
//printf("walk_char %d != %d\n",sd->walktimer,tid);
return 0;
}
if(sd->walkpath_pos>=sd->walkpath_len || sd->walkpath_pos!=data || sd->walktimer<0){
sd->walktimer=-1;
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<map_data[sd->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<map_data[sd->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>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?