script.c

来自「CS反恐精英1.6的部分C源代码。」· C语言 代码 · 共 1,080 行 · 第 1/2 页

C
1,080
字号
      } else {
	printf("parse_script : unknown command %s\n",p);
	free((void *)script_buf);
	return NULL;
      }
    }
    p=skip_space(p);
    if(*p!=';'){
      printf("not found ';' : %s\n",p);
      free((void *)script_buf);
      return NULL;
    }
    p=skip_space(p+1);
  }
  p=skip_space(p);
  if(*p!='}'){
    printf("not found '}' : %s\n",p);
    free((void *)script_buf);
    return NULL;
  }
  add_scriptc(C_CLOSE);	// for safety
#ifdef DEBUG_PARSER_OUTPUT
  for(i=0;i<script_pos;i++){
    if((i&15)==0) printf("%04x : ",i);
    printf("%02x ",script_buf[i]);
    if((i&15)==15) printf("\n");
  }
  printf("\n");
  //  exit(1);
#endif
  script_buf=realloc(script_buf,script_pos);
  return script_buf;
}

int unget_com_data=-1;

int get_com(unsigned char *script,int *pos)
{
  int i,j;
  if(unget_com_data>=0){
    i=unget_com_data;
    unget_com_data=-1;
    return i;
  }
  if(script[*pos]>=0x80){
    return C_INT;
  }
  i=0; j=0;
  while(script[*pos]>=0x40){
    i=script[(*pos)++]<<j;
    j+=6;
  }
  return i+(script[(*pos)++]<<j);
}

void unget_com(int c)
{
  if(unget_com_data!=-1){
    printf("unget_com can back one data\n");
  }
  unget_com_data=c;
}

int mmo_map_cutin(int fd,unsigned char* buf,char *img_name,int type)
{
  WBUFW(buf,0)=0x145;
  memcpy(WBUFP(buf,2),img_name,16);
  WBUFB(buf,18)=type;
  return 19;
}

int mmo_map_countitem(struct map_session_data *sd,int nameid)
{
  int i,count;

  for(i=count=0;i<MAX_INVENTORY;i++){
    if(sd->status.inventory[i].nameid==nameid)
      count+=sd->status.inventory[i].amount;
  }
  return count;
}

int mmo_map_readparam(struct map_session_data *sd,int i)
{
  switch(i){
  case SP_SKILLPOINT:
    return sd->status.skill_point;
  case SP_STATUSPOINT:
    return sd->status.status_point;
  case SP_ZENY:
    return sd->status.zeny;
  case SP_BASELEVEL:
    return sd->status.base_level;
  case SP_JOBLEVEL:
    return sd->status.job_level;
  case SP_SCRIPT_FLAG:
	return sd->local_reg[14];
  case SP_GETJOB:
	return sd->status.class;
  case SP_CHECKSTORAGE:
        if(sd->status.skill[0].lv > 5)
        return 1;
  case SP_CHECKCART:
        if(sd->status.skill[38].lv > 0)
        return 1;
  case SP_CHECKFALCON:
	if (sd->status.skill[126].lv > 0)
	return 1;
  case SP_CHECKPECOPECO:
	if (sd->status.skill[62].lv > 0)
	return 1;
  default:
    return 0;
  }
}

int get_num(struct map_session_data *sd,unsigned char *script,int *pos)
{
  int i,j,c;
  switch(c=get_com(script,pos)){
  case C_PARAM:
    i=get_num(sd,script,pos);
    return mmo_map_readparam(sd,i);
  case C_LOCAL:
  case C_GLOBAL:
    i=get_num(sd,script,pos);
    if(c==C_LOCAL){
      if(i>=0 && i<LOCAL_REG_NUM)
	return sd->local_reg[i];
    } else {
      if(i>=0 && i<GLOBAL_REG_NUM)
	return sd->status.global_reg[i];
    }
    return 0;
  case C_INT:
    i=0; j=0;
    while(script[*pos]>=0xc0){
      i+=(script[(*pos)++]&0x7f)<<j;
      j+=6;
    }
    return i+((script[(*pos)++]&0x7f)<<j);
  default:
    printf("get_num : unknown command %d\n",c);
    return 0;
  }
  return 0;
}

int get_expr(struct map_session_data *sd,unsigned char *script,int *pos)
{
  int stack[32],sp,c;

  for(sp=0;sp>=0 && (c=get_com(script,pos))!=C_NOP;){
    switch(c){
    case C_INT:
    case C_PARAM:
    case C_LOCAL:
    case C_GLOBAL:
      unget_com(c);
      stack[sp++]=get_num(sd,script,pos);
      break;

    case C_ADD:
      sp--;
      stack[sp-1]+=stack[sp];
      break;
    case C_SUB:
      sp--;
      stack[sp-1]-=stack[sp];
      break;
    case C_MUL:
      sp--;
      stack[sp-1]*=stack[sp];
      break;
    case C_DIV:
      sp--;
      if(stack[sp]==0)
	stack[sp]=1;
      stack[sp-1]/=stack[sp];
      break;
    case C_MOD:
      sp--;
      if(stack[sp]==0)
	stack[sp]=1;
      stack[sp-1]%=stack[sp];
      break;
    case C_NEG:
      stack[sp-1]=-stack[sp-1];
      break;

    case C_EQ:
      sp--;
      stack[sp-1]=stack[sp-1] == stack[sp];
      break;
    case C_NE:
      sp--;
      stack[sp-1]=stack[sp-1] != stack[sp];
      break;
    case C_GT:
      sp--;
      stack[sp-1]=stack[sp-1] > stack[sp];
      break;
    case C_GE:
      sp--;
      stack[sp-1]=stack[sp-1] >= stack[sp];
      break;
    case C_LT:
      sp--;
      stack[sp-1]=stack[sp-1] < stack[sp];
      break;
    case C_LE:
      sp--;
      stack[sp-1]=stack[sp-1] <= stack[sp];
      break;

    case C_LAND:
      sp--;
      stack[sp-1]=stack[sp-1] && stack[sp];
      break;
    case C_LOR:
      sp--;
      stack[sp-1]=stack[sp-1] || stack[sp];
      break;
    case C_LNOT:
      stack[sp-1]=!stack[sp-1];
      break;

    case C_AND:
      sp--;
      stack[sp-1]=stack[sp-1] & stack[sp];
      break;
    case C_OR:
      sp--;
      stack[sp-1]=stack[sp-1] | stack[sp];
      break;
    case C_XOR:
      sp--;
      stack[sp-1]=stack[sp-1] ^ stack[sp];
      break;
    case C_NOT:
      stack[sp-1]=~stack[sp-1];
      break;

    case C_COUNTITEM:
      stack[sp-1]=mmo_map_countitem(sd,stack[sp-1]);
      break;
    case C_READPARAM:
      stack[sp-1]=mmo_map_readparam(sd,stack[sp-1]);
      break;

    default:
      printf("get_expr : unknown command %d\n",c);
      return 0;
    }
  }
  if(sp!=1){
    if(sp<=0)
      printf("get_expr : stack empty???\n");
    else
      printf("get_expr : too many data???\n");
    return 0;
  }
  return stack[sp-1];
}

int run_script(int fd,struct map_session_data *sd)
{
  int stop,end,len;
  int j;
  int temp_map;
  int pos,c,i;
  int i1,i2;
  unsigned char *script,*s1;
  struct item tmp_item;
  struct mmo_charstatus *p;   
  p=&sd->status;

  pos=sd->npc_pc;
  script=map_data[sd->mapno].npc[sd->npc_n]->u.script;
  if(script==NULL){
    sd->npc_pc=0;
    sd->npc_id=0;
    sd->npc_n=0;
    return 0;
  }

  for(stop=0,end=0;!stop && !end;){
    switch(get_com(script,&pos)){
    case C_MES:
      len=mmo_map_npc_say(fd,WFIFOP(fd,0),sd->npc_id,script+pos);
      if(len>0) WFIFOSET(fd,len);
      pos+=strlen(script+pos)+1;
      break;
    case C_NEXT:
      len=mmo_map_npc_next(fd,WFIFOP(fd,0),sd->npc_id);
      if(len>0) WFIFOSET(fd,len);
      stop=1;
      break;
    case C_CLOSE:
      len=mmo_map_npc_close(fd,WFIFOP(fd,0),sd->npc_id);
      if(len>0) WFIFOSET(fd,len);
      end=1;
      break;
    case C_MENU:
      len=mmo_map_npc_select(fd,WFIFOP(fd,0),sd->npc_id,script+pos);
      if(len>0) WFIFOSET(fd,len);
      pos+=strlen(script+pos)+1;
      stop=1;
      break;
    case C_MENU_GOTO:
      for(i=1,c=C_POS;i<sd->local_reg[15] && (c=get_com(script,&pos))==C_POS;i++)
	pos+=4;
      if(c!=C_POS || (c=get_com(script,&pos))!=C_POS){
	end=1;
	break;
      }
      pos=*(int*)(script+pos);
      break;
    case C_JOBCHANGE:
      mmo_map_jobchange(fd,get_num(sd,script,&pos));
      break;
    case C_GOTO:
      if(get_com(script,&pos)!=C_POS){
	end=1;
	break;
      }
      pos=*(int*)(script+pos);
      break;
    case C_INPUT:
      len=mmo_map_npc_amount_request(fd,WFIFOP(fd,0),sd->npc_id);
      if(len>0) WFIFOSET(fd,len);
      stop=1;
      break;
    case C_SETLOOK:
		//傾僀僥儉僫儞僶乕
      i1=get_num(sd,script,&pos);
      i2=get_num(sd,script,&pos);
      len=mmo_map_set_look(fd,WFIFOP(fd,0),sd->account_id,itemdb_stype(i1),itemdb_view_point(i1));
      if(len>0) mmo_map_sendarea(fd,WFIFOP(fd,0),len,0);
      break;
    case C_WARP:
      s1=script+pos;
      pos+=strlen(script+pos)+1;
      i1=get_num(sd,script,&pos);
      i2=get_num(sd,script,&pos);
      sd->status.talking_to_npc=0;
      mmo_map_changemap(fd,sd,s1,i1,i2,2);
      break;
    case C_SET:
      c=get_com(script,&pos);
      i1=get_num(sd,script,&pos);
      i2=get_expr(sd,script,&pos);
      switch(c){
      case C_PARAM:
	mmo_map_update_param(fd,i1,i2);
	break;
      case C_LOCAL:
	sd->local_reg[i1]=i2;
	break;
      case C_GLOBAL:
	sd->status.global_reg[i1]=i2;
	break;
      }
      break;
    case C_IF:
      i1=get_expr(sd,script,&pos);
      if(get_com(script,&pos)!=C_POS){
	end=1;
	break;
      }
      if(i1)
	pos=*(int*)(script+pos);
      else
	pos+=4;
      break;

    case C_GETITEM:
      i1=get_num(sd,script,&pos);
      i2=get_num(sd,script,&pos);
      memset(&tmp_item,0,sizeof(tmp_item));
      tmp_item.nameid=i1;
      tmp_item.amount=i2;
      tmp_item.identify=1;
      len=mmo_map_item_get(fd,WFIFOP(fd,0),&tmp_item);
      if(len>0) WFIFOSET(fd,len);
      break;
    case C_DELITEM:
      i1=get_num(sd,script,&pos);
      i2=get_num(sd,script,&pos);
      for(i=0;i<100;i++){
	if(sd->status.inventory[i].nameid==i1){
	  if(sd->status.inventory[i].amount>=i2){
	    len=mmo_map_item_lost(fd,WFIFOP(fd,0),i+2,i2);
	    if(len>0){
	      WFIFOSET(fd,len);
	      i2=0;
	    }
	  } else {
	    len=mmo_map_item_lost(fd,WFIFOP(fd,0),i+2,sd->status.inventory[i].amount);
	    if(len>0){
	      WFIFOSET(fd,len);
	      i2-=sd->status.inventory[i].amount;
	    }
	  }
	  break;
	}
      }
      if(i2>0)
	sd->local_reg[13]++;
      break;
    case C_CUTIN:
      s1=script+pos;
      pos+=strlen(script+pos)+1;
      i1=get_num(sd,script,&pos);
      len=mmo_map_cutin(fd,WFIFOP(fd,0),s1,i1);
      if(len>0) WFIFOSET(fd,len);
      break;
	case C_MONSTER:
		temp_map = sd->mapno;
		s1=script+pos;
		pos+=strlen(script+pos)+1;
		i1=get_num(sd,script,&pos);
		i2=get_num(sd,script,&pos);
		for(j=0;j <i2;j++)
		{
		map_data[temp_map].npc[map_data[temp_map].npc_num]=malloc(sizeof(struct npc_data));
	    map_data[temp_map].npc[map_data[temp_map].npc_num]->u.mons.speed=200;
		map_data[temp_map].npc[map_data[temp_map].npc_num]->class=i1;
		map_data[temp_map].npc[map_data[temp_map].npc_num]->id=npc_id++;
		map_data[temp_map].npc[map_data[temp_map].npc_num]->block.subtype=MONS;
		map_data[temp_map].npc[map_data[temp_map].npc_num]->u.mons.hp=10;
		map_data[temp_map].npc[map_data[temp_map].npc_num]->u.mons.script = 1;
		memcpy(map_data[temp_map].npc[map_data[temp_map].npc_num]->name,s1,24);
		respawn_mons2(temp_map,map_data[temp_map].npc_num);
		map_data[temp_map].npc_num++;
		}
		break;
    case C_VIEWPOINT:
      WFIFOW(fd,0)=0x144;
      WFIFOL(fd,2)=sd->npc_id;
      WFIFOL(fd,6)=get_num(sd,script,&pos);	// type
      WFIFOL(fd,10)=get_num(sd,script,&pos);	// x
      WFIFOL(fd,14)=get_num(sd,script,&pos);	// y
      WFIFOB(fd,18)=get_num(sd,script,&pos);	// point id
      WFIFOL(fd,19)=get_num(sd,script,&pos);	// color
      WFIFOSET(fd,23);
      break;
/*** Lemming ***/
	case C_SAVE:
      s1=script+pos;
      pos+=strlen(script+pos)+1;
      i1=get_num(sd,script,&pos);
      i2=get_num(sd,script,&pos);
      strcpy(sd->status.save_point.map,s1);
	sd->status.save_point.x = i1;
	sd->status.save_point.y = i2;
	mmo_char_save(sd);
        //printf("Save Command Done -> Map: %s,%d,%d\n",sd->status.save_point,sd->status.save_point.x,sd->status.save_point.y);
	break;
/*** hud give_special code     
     give_special 1 = give cart to target     
     give_special 2 = give falcon to target 
     give_special 3 = give pecopeco to target
					***/
    case C_GIVESPECIAL:
     i1=get_num(sd,script,&pos);
     if (i1 == 1) { // if give_special 1 -- give target a cart
                        WFIFOW(fd,0)=0x0119;
                        WFIFOL(fd,2)=sd->account_id;
                        WFIFOW(fd,6)=0x00; 
                        WFIFOW(fd,8)=0x00; 
                        WFIFOW(fd,10)=0x08;
                        mmo_map_sendarea( fd, WFIFOP(fd,0), packet_len_table[0x0119], 0 );
                        sd->status.option=0x00|0x00|0x08;
     }
     if (i1 == 2) { // if give_special 2 -- give target a falcon
                        WFIFOW(fd,0)=0x0119;
                        WFIFOL(fd,2)=sd->account_id;
                        WFIFOW(fd,6)=0x00; 
                        WFIFOW(fd,8)=0x00; 
                        WFIFOW(fd,10)=0x10;
                        mmo_map_sendarea( fd, WFIFOP(fd,0), packet_len_table[0x0119], 0 );
                        sd->status.option=0x00|0x00|0x10;
     }
     if (i1 == 3) { // if give_special 3 -- give target a pecopeco
                        WFIFOW(fd,0)=0x0119;
                        WFIFOL(fd,2)=sd->account_id;
                        WFIFOW(fd,6)=0x00;
                        WFIFOW(fd,8)=0x00;
                        WFIFOW(fd,10)=0x20;
                        mmo_map_sendarea( fd, WFIFOP(fd,0), packet_len_table[0x0119], 0 );
                        sd->status.option=0x00|0x00|0x20;
     }
    break;

    case C_FULLHEAL:
    p->hp = p->max_hp;
    p->sp = p->max_sp;
    WFIFOW(fd,0) = 0xb0;
    WFIFOW(fd,2) = 0005;
    WFIFOL(fd,4) = p->hp;
    WFIFOSET(fd,8);

    WFIFOW(fd,0) = 0xb0; 
    WFIFOW(fd,2) = 0007;   
    WFIFOL(fd,4) = p->sp;
    WFIFOSET(fd,8);
    break;

/*** Lemming ***/
    case C_STORAGE:
    mmo_open_storage(fd);
    break;

    default:
      {
	FILE *log=fopen("map.log","a");
	if(log){
	  int i;
	  fprintf(log,"run_script error %04x : ",pos);
	  for(i=-5;i<=5;i++)
	    fprintf(log,"%02x%c",script[pos+i],(i==-1) ? '[':((i==0) ? ']':' '));
	  fprintf(log,"\n");
	  fclose(log);
	}
      }
      end=1;
      break;
    }
  }
  if(end){
    sd->npc_pc=0;
    sd->npc_id=0;
    sd->npc_n=0;
  } else {
    sd->npc_pc=pos;
  }
  return 0;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?