script.c

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

C
1,080
字号
//
// PvPGN YARE MOD V1.0 (Yeat Another Ragnarok Emulator) - (Server)
// Copyright (c) Project-YARE & PvPGN 2003
// www.project-yare.com
// forum.project-yare.net
// www.pvpgn.org
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "mmo.h"
#include "core.h"
#include "npc.h"
#include "script.h"
#include "itemdb.h"
#include "map2.h"
#include "save.h"

#define SCRIPT_BLOCK_SIZE 256
//#define DEBUG_PARSER_OUTPUT
#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;}

extern int packet_len_table[];
extern struct mmo_map_data map_data[];

enum {
  C_NOP,C_POS,C_INT,C_LOCAL,C_GLOBAL,C_PARAM,

  C_LOR,C_LAND,C_LE,C_LT,C_GE,C_GT,C_EQ,C_NE,	//operator
  C_XOR,C_OR,C_AND,C_ADD,C_SUB,C_MUL,C_DIV,C_MOD,C_NEG,C_LNOT,C_NOT,
  C_COUNTITEM,C_READPARAM,	// function

  C_MES,C_NEXT,C_CLOSE,C_MENU,C_MENU_GOTO,C_GOTO,C_JOBCHANGE,C_INPUT,C_IF,	//command
  C_SET,C_SETLOOK,C_WARP,C_GETITEM,C_DELITEM,C_CUTIN,C_VIEWPOINT,C_MONSTER,C_SAVE,
  C_STORAGE,C_GIVESPECIAL,C_FULLHEAL
};

struct {
  unsigned char *str;
  int com;
  unsigned char *arg;
} com_tbl[]={
  {"mes",C_MES,"s"},
  {"next",C_NEXT,""},
  {"close",C_CLOSE,""},
  {"menu",C_MENU,"m"},
  {"goto",C_GOTO,"l"},
  {"jobchange",C_JOBCHANGE,"i"},
  {"input",C_INPUT,""},
  {"warp",C_WARP,"sii"},
  {"setlook",C_SETLOOK,"ii"},
  {"set",C_SET,"Ie"},
  {"if",C_IF,"eg"},
  {"getitem",C_GETITEM,"ii"},
  {"delitem",C_DELITEM,"ii"},
  {"cutin",C_CUTIN,"si"},
  {"viewpoint",C_VIEWPOINT,"iiiii"},
  {"monster",C_MONSTER,"sii"},
  {"save",C_SAVE,"sii"},
  {"open_storage",C_STORAGE,""},
  {"give_special",C_GIVESPECIAL,"i"},
  {"full_heal",C_FULLHEAL,""},
  {NULL,0,NULL}
};
struct {
  unsigned char *str;
  int type;
  int val;
} alias_tbl[]={
  {"Job_Novice",C_INT,0},
  {"Job_Swordman",C_INT,1},
  {"Job_Mage",C_INT,2},
  {"Job_Archer",C_INT,3},
  {"Job_Acolyte",C_INT,4},
  {"Job_Merchant",C_INT,5},
  {"Job_Thief",C_INT,6},
  {"Job_Knight",C_INT,7},
  {"Job_Priest",C_INT,8},
  {"Job_Wizard",C_INT,9},
  {"Job_Blacksmith",C_INT,10},
  {"Job_Hunter",C_INT,11},
  {"Job_Assassin",C_INT,12},
  {"Job_Kami",C_INT,100},
  {"S_FLAG",C_LOCAL,0},
  {"Script_flag_num",C_PARAM,SP_SCRIPT_FLAG},
  {"SkillPoint",C_PARAM,SP_SKILLPOINT},
  {"StatusPoint",C_PARAM,SP_STATUSPOINT},
  {"Zeny",C_PARAM,SP_ZENY},
  {"BaseLevel",C_PARAM,SP_BASELEVEL},
  {"JobLevel",C_PARAM,SP_JOBLEVEL},
  {"GetJob",C_PARAM,SP_GETJOB},
  {"CheckCart",C_PARAM,SP_CHECKCART},
  {"CheckStorage",C_PARAM,SP_CHECKSTORAGE},
  {"CheckFalcon",C_PARAM,SP_CHECKFALCON},
  {"CheckPecoPeco",C_PARAM,SP_CHECKPECOPECO},
  {NULL,0}
};

int npc_id = 50000;
static unsigned char * script_buf;
static int script_pos,script_size;
int menu_goto[32];
char *str_buf;
int str_pos,str_size;
static struct {
  int str;
  int backpatch;
  int label;
  int next;
} *str_data;
int str_num=1,str_data_size;
int str_hash[16];
struct mons_data mons_data[4000];

int calc_hash(unsigned char *p)
{
  int h=0;
  while(*p){
    h=(h<<1)+(h>>3)+(h>>5)+(h>>8);
    h+=*p++;
  }
  return h&15;
}

// 贷赂のであˇE腥止妗⑻丹堡ˇˇ1
int search_str(unsigned char *p)
{
  int i;
  i=str_hash[calc_hash(p)];
  while(i){
    if(strcmp(str_buf+str_data[i].str,p)==0){
      return i;
    }
    i=str_data[i].next;
  }
  return -1;
}
// 贷赂のであˇE腥止妗⑻丹堡ˇ信邢郡筏瓶返ˇ止
int add_str(unsigned char *p)
{
  int i;
  i=calc_hash(p);
  if(str_hash[i]==0){
    str_hash[i]=str_num;
  } else {
    i=str_hash[i];
    for(;;){
      if(strcmp(str_buf+str_data[i].str,p)==0){
	return i;
      }
      if(str_data[i].next==0)
	break;
      i=str_data[i].next;
    }
    str_data[i].next=str_num;
  }
  if(str_num>=str_data_size){
    str_data_size+=128;
    str_data=realloc(str_data,sizeof(str_data[0])*str_data_size);
  }
  while(str_pos+strlen(p)+1>=str_size){
    str_size+=256;
    str_buf=realloc(str_buf,str_size);
  }
  strcpy(str_buf+str_pos,p);
  str_data[str_num].str=str_pos;
  str_data[str_num].next=0;
  str_data[str_num].backpatch=-1;
  str_data[str_num].label=-1;
  str_pos+=strlen(p)+1;
  return str_num++;
}

void check_script_buf(int size)
{
  if(script_pos+size>=script_size){
    script_size+=SCRIPT_BLOCK_SIZE;
    script_buf=realloc(script_buf,script_size);
    if(script_buf==NULL){
      printf("check_script_buf : error \n");
      exit(1);
    }
  }
}
void add_scriptb(int a)
{
  check_script_buf(1);
  script_buf[script_pos++]=a;
}

void add_scriptc(int a)
{
  while(a>=0x40){
    add_scriptb((a&0x3f)|0x40);
    a=(a-0x40)>>6;
  }
  add_scriptb(a&0x3f);
}

void add_scripti(int a)
{
  while(a>=0x40){
    add_scriptb(a|0xc0);
    a=(a-0x40)>>6;
  }
  add_scriptb(a|0x80);
}

void add_scriptl(int l)
{
  //printf("%d(%s) @ %d\n",l,str_buf+str_data[l].str,script_pos);
  check_script_buf(5);
  if(str_data[l].label<0){
    script_buf[script_pos++]=C_POS;
    script_buf[script_pos++]=str_data[l].backpatch;
    script_buf[script_pos++]=str_data[l].backpatch>>8;
    script_buf[script_pos++]=str_data[l].backpatch>>16;
    script_buf[script_pos++]=str_data[l].backpatch>>24;
    str_data[l].backpatch=script_pos-4;
  } else {
    script_buf[script_pos++]=C_POS;
    script_buf[script_pos++]=str_data[l].label;
    script_buf[script_pos++]=str_data[l].label>>8;
    script_buf[script_pos++]=str_data[l].label>>16;
    script_buf[script_pos++]=str_data[l].label>>24;
  }
}

void set_label(int l,int pos)
{
  int i,n;
  //printf("%d(%s) - %d\n",l,str_buf+str_data[l].str,pos);
  str_data[l].label=pos;
  for(i=str_data[l].backpatch;i>=0;){
    n=*(int*)(script_buf+i);
    script_buf[i]=pos;
    script_buf[i+1]=pos>>8;
    script_buf[i+2]=pos>>16;
    script_buf[i+3]=pos>>24;
    i=n;
  }
}

unsigned char *skip_space(unsigned char *p)
{
  while(1){
    while(isspace(*p))
      p++;
    if(p[0]=='/' && p[1]=='/'){
      while(*p && *p!='\n')
	p++;
    } else
      break;
  }
  return p;
}
unsigned char *skip_word(unsigned char *p)
{
  while(isalnum(*p)||*p=='_'|| *p>=0x81)
    if(*p>=0x81 && p[1]){
      p+=2;
    } else
      p++;
  return p;
}
int comcmp(unsigned char *str,unsigned char *com)
{
  while(*com && tolower(*str)==tolower(*com)){
    str++;
    com++;
  }
  return isalnum(*str)|| *str=='_' || *com;
}

unsigned char* parse_int(unsigned char *p)
{
  int i;

  //printf("parse_int : %s\n",p);
  p=skip_space(p);
  if(isdigit(*p) || *p=='-'){
    i=strtoul(p,(char**)&p,0);
    add_scripti(i);
  } else if((*p=='g' || *p=='l') && isdigit(p[1])){
    add_scriptc(*p=='g' ? C_GLOBAL : C_LOCAL);
    i=strtoul(p+1,(char**)&p,0);
    add_scripti(i);
  } else {
    for(i=0;alias_tbl[i].str;i++)
      if(comcmp(p,alias_tbl[i].str)==0)
	break;
    if(alias_tbl[i].str==NULL){
      printf("unknown constant %s\n",p);
      exit(1);
    }
    if(alias_tbl[i].type!=C_INT)
      add_scriptc(alias_tbl[i].type);
    add_scripti(alias_tbl[i].val);
    p=skip_word(p);
  }
  return p;
}

unsigned char* parse_subexpr(unsigned char*,int);

unsigned char* parse_simpleexpr(unsigned char *p)
{
  int func;

  if(*p=='('){
    p=parse_subexpr(p+1,-1);
    p=skip_space(p);
    if(*p++!=')'){
      printf("unmatch ')' : %s\n",p);
      exit(1);
    }
  } else if((func=C_COUNTITEM,comcmp(p,"countitem")==0)||
	    (func=C_READPARAM,comcmp(p,"readparam")==0)){
    p=skip_word(p);
    p=skip_space(p);
    if(*p!='('){
      printf("func reqest '(' ')' : %s\n",p);
      exit(1);
    }
    p=parse_subexpr(p+1,-1);
    p=skip_space(p);
    if(*p++!=')'){
      printf("func reqest '(' ')' : %s\n",p-1);
      exit(1);
    }
    add_scriptc(func);
  } else
    p=parse_int(p);
  return p;
}

unsigned char* parse_subexpr(unsigned char *p,int limit)
{
  int op,opl,len;

  p=skip_space(p);
  if((op=C_NEG,*p=='-') || (op=C_LNOT,*p=='!') || (op=C_NOT,*p=='~')){
    p=parse_subexpr(p+1,100);
    add_scriptc(op);
  }
  p=skip_space(p);
  p=parse_simpleexpr(p);
  p=skip_space(p);
  while(((op=C_ADD,opl=6,len=1,*p=='+') ||
	 (op=C_SUB,opl=6,len=1,*p=='-') ||
	 (op=C_MUL,opl=7,len=1,*p=='*') ||
	 (op=C_DIV,opl=7,len=1,*p=='/') ||
	 (op=C_MOD,opl=7,len=1,*p=='%') ||
	 (op=C_LAND,opl=1,len=2,*p=='&' && p[1]=='&') ||
	 (op=C_AND,opl=5,len=1,*p=='&') ||
	 (op=C_LOR,opl=0,len=2,*p=='|' && p[1]=='|') ||
	 (op=C_OR,opl=4,len=1,*p=='|') ||
	 (op=C_XOR,opl=3,len=1,*p=='^') ||
	 (op=C_EQ,opl=2,len=2,*p=='=' && p[1]=='=') ||
	 (op=C_NE,opl=2,len=2,*p=='!' && p[1]=='=') ||
	 (op=C_GE,opl=2,len=2,*p=='>' && p[1]=='=') ||
	 (op=C_GT,opl=2,len=1,*p=='>') ||
	 (op=C_LE,opl=2,len=2,*p=='<' && p[1]=='=') ||
	 (op=C_LT,opl=2,len=1,*p=='<')) && opl>limit){
    p+=len;
    p=parse_subexpr(p,opl);
    add_scriptc(op);
    p=skip_space(p);
  }
  return p;  /* return first untreated operator */
}

unsigned char* parse_expr(unsigned char *p)
{
  p=parse_subexpr(p,-1);
  add_scriptc(C_NOP);
  return p;
}

unsigned char* parse_arg(int com,unsigned char *p)
{
  int argc,c,i;
  unsigned char *tmp,bak;

  for(argc=0;com_tbl[com].arg[argc];argc++){
    p=skip_space(p);
    if(argc && *p==',')
      p++;
    p=skip_space(p);
    switch(com_tbl[com].arg[argc]){
    case 's':
      if(*p!='"'){
	printf("parse_arg : string must start \"\n");
	exit(1);
      }
      p++;
      while(*p && *p!='"'){
	if(p[-1]<=0x7e && *p=='\\')
	  p++;
	add_scriptb(*p++);
      }
      p++;
      add_scriptb(0);
      break;
    case 'm':
      for(c=0;;c++){
	if(*p!='"'){
	  printf("parse_arg : menu must start \"\n");
	  exit(1);
	}
	p++;
	while(*p && *p!='"'){
	  if(p[-1]<=0x7e && *p=='\\')
	    p++;
	  add_scriptb(*p++);
	}
	add_scriptb(':');
	p++;
	p=skip_space(p);
	if(*p!=','){
	  printf("parse_arg : not found ','\n");
	  exit(1);
	}
	p=skip_space(p+1);
	tmp=skip_word(p);
	bak=*tmp;
	*tmp=0;
	menu_goto[c]=add_str(p);
	*tmp=bak;
	p=skip_space(tmp);
	if(*p==','){
	  p=skip_space(p+1);
	} else {
	  c++;
	  break;
	}
      }
      add_scriptb(0);
      add_scriptc(C_MENU_GOTO);
      for(i=0;i<c;i++)
	add_scriptl(menu_goto[i]);
      add_scriptc(C_NOP);
      break;
    case 'l':
      tmp=skip_word(p);
      bak=*tmp;
      *tmp=0;
      add_scriptl(add_str(p));
      *tmp=bak;
      p=skip_space(tmp);
      break;
    case 'i':
      p=parse_int(p);
      break;
    case 'I':
      p=parse_int(p);
      break;
    case 'e':
      p=parse_expr(p);
      break;
    case 'g':
      p=skip_space(p);
      if(comcmp(p,"goto")){
	printf("if statement is 'if <cmp> goto <label>;' : %s\n",p);
	exit(1);
      }
      p=skip_space(p+4);

      // parse label
      tmp=skip_word(p);
      bak=*tmp;
      *tmp=0;
      add_scriptl(add_str(p));
      *tmp=bak;
      p=skip_space(tmp);

      break;
    default:
      printf("unknown arg type : '%c' @ %s\n",com_tbl[com].arg[argc],com_tbl[com].str);
      exit(1);
    }
  }
  return p;
}

unsigned char* parse_script(unsigned char *src)
{
  unsigned char *p,*tmp;
  int i;

  str_num=1;
  for(i=0;i<16;i++)
    str_hash[i]=0;

  script_buf=malloc(SCRIPT_BLOCK_SIZE);
  script_pos=0;
  script_size=SCRIPT_BLOCK_SIZE;

  p=src;
  p=skip_space(p);
  if(*p!='{'){
    printf("not found '{' : %c\n",*p);
    free((void *)script_buf);
    return NULL;
  }
  for(p++;*p && *p!='}';){
    p=skip_space(p);
    for(i=0;com_tbl[i].str;i++){
      if(comcmp(p,com_tbl[i].str)==0)
	break;
    }
    if(com_tbl[i].str){
      add_scriptc(com_tbl[i].com);
      p=skip_word(p);
      p=parse_arg(i,p);
    } else {
      tmp=skip_space(skip_word(p));
      if(*tmp==':'){
	int l;
	*skip_word(p)=0;
	l=add_str(p);
	set_label(l,script_pos);
	p=tmp+1;
	continue;

⌨️ 快捷键说明

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