📄 script.c
字号:
*------------------------------------------
*/
unsigned char* parse_script(unsigned char *src,int line)
{
unsigned char *p,*tmpp;
int i;
static int first=1;
if(first){
add_buildin_func();
read_constdb();
}
first=0;
script_buf=calloc(SCRIPT_BLOCK_SIZE, 1);
if(script_buf==NULL){
printf("out of memory : parse_script\n");
exit(1);
}
script_pos=0;
script_size=SCRIPT_BLOCK_SIZE;
str_data[LABEL_NEXTLINE].type=C_NOP;
str_data[LABEL_NEXTLINE].backpatch=-1;
str_data[LABEL_NEXTLINE].label=-1;
for(i=LABEL_START;i<str_num;i++){
if(str_data[i].type==C_POS || str_data[i].type==C_NAME){
str_data[i].type=C_NOP;
str_data[i].backpatch=-1;
str_data[i].label=-1;
}
}
// 奜晹梡label db偺弶婜壔
if(scriptlabel_db!=NULL)
strdb_final(scriptlabel_db,scriptlabel_final);
scriptlabel_db=strdb_init(50);
// for error message
startptr = src;
startline = line;
p=src;
p=skip_space(p);
if(*p!='{'){
disp_error_message("not found '{'",p);
return NULL;
}
for(p++;p && *p && *p!='}';){
p=skip_space(p);
// label偩偗摿庩張棟
tmpp=skip_space(skip_word(p));
if(*tmpp==':'){
int l,c;
c=*skip_word(p);
*skip_word(p)=0;
l=add_str(p);
if(str_data[l].label!=-1){
*skip_word(p)=c;
disp_error_message("dup label ",p);
exit(1);
}
set_label(l,script_pos);
strdb_insert(scriptlabel_db,p,script_pos); // 奜晹梡label db搊榐
*skip_word(p)=c;
p=tmpp+1;
continue;
}
// 懠偼慡晹堦弿偔偨
p=parse_line(p);
p=skip_space(p);
add_scriptc(C_EOL);
set_label(LABEL_NEXTLINE,script_pos);
str_data[LABEL_NEXTLINE].type=C_NOP;
str_data[LABEL_NEXTLINE].backpatch=-1;
str_data[LABEL_NEXTLINE].label=-1;
}
add_scriptc(C_NOP);
script_size = script_pos;
script_buf=realloc(script_buf,script_pos);
if(script_buf==NULL){
printf("out of momory : parse_script realloc\n");
exit(1);
}
// 枹夝寛偺儔儀儖傪夝寛
for(i=LABEL_START;i<str_num;i++){
if(str_data[i].type==C_NOP){
int j,next;
str_data[i].type=C_NAME;
str_data[i].label=i;
for(j=str_data[i].backpatch;j>=0 && j!=0x00ffffff;){
next=(*(int*)(script_buf+j)) & 0x00ffffff;
script_buf[j]=i;
script_buf[j+1]=i>>8;
script_buf[j+2]=i>>16;
j=next;
}
}
}
#ifdef DEBUG_DISP
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");
#endif
return script_buf;
}
//
// 幚峴宯
//
enum {STOP=1,END,RERUNLINE,GOTO};
/*==========================================
* rid偐傜sd傊偺夝寛
*------------------------------------------
*/
struct map_session_data *script_rid2sd(struct script_state *st)
{
struct map_session_data *sd=map_id2sd(st->rid);
if(!sd){
printf("script_rid2sd: fatal error ! player not attached!\n");
}
return sd;
}
/*==========================================
* 曄悢偺撉傒庢傝
*------------------------------------------
*/
int get_val(struct script_state*st,struct script_data* data)
{
struct map_session_data *sd=NULL;
if(data->type==C_NAME){
char *name=str_buf+str_data[data->u.num&0x00ffffff].str;
char prefix=*name;
char postfix=name[strlen(name)-1];
if(prefix!='$')
sd=script_rid2sd(st);
if(postfix=='$'){
data->type=C_CONSTSTR;
if( prefix=='@' || prefix=='l' ){
data->u.str = pc_readregstr(sd,data->u.num);
}else if(prefix=='$'){
data->u.str = (char *)numdb_search(mapregstr_db,data->u.num);
}else{
printf("script: get_val: illeagal scope string variable.\n");
data->u.str = "!!ERROR!!";
}
if( data->u.str == NULL )
data->u.str ="";
}else{
data->type=C_INT;
if(str_data[data->u.num&0x00ffffff].type==C_INT){
data->u.num = str_data[data->u.num&0x00ffffff].val;
}else if(str_data[data->u.num&0x00ffffff].type==C_PARAM){
data->u.num = pc_readparam(sd,str_data[data->u.num&0x00ffffff].val);
}else if(prefix=='@' || prefix=='l'){
data->u.num = pc_readreg(sd,data->u.num);
}else if(prefix=='$'){
data->u.num = (int)numdb_search(mapreg_db,data->u.num);
}else if(prefix=='#'){
if( name[1]=='#')
data->u.num = pc_readaccountreg2(sd,name);
else
data->u.num = pc_readaccountreg(sd,name);
}else{
data->u.num = pc_readglobalreg(sd,name);
}
}
}
return 0;
}
/*==========================================
* 曄悢偺撉傒庢傝2
*------------------------------------------
*/
void* get_val2(struct script_state*st,int num)
{
struct script_data dat;
dat.type=C_NAME;
dat.u.num=num;
get_val(st,&dat);
if( dat.type==C_INT ) return (void*)dat.u.num;
else return (void*)dat.u.str;
}
/*==========================================
* 曄悢愝掕梡
*------------------------------------------
*/
static int set_reg(struct map_session_data *sd,int num,char *name,void *v)
{
char prefix=*name;
char postfix=name[strlen(name)-1];
if( postfix=='$' ){
char *str=(char*)v;
if( prefix=='@' || prefix=='l'){
pc_setregstr(sd,num,str);
}else if(prefix=='$') {
mapreg_setregstr(num,str);
}else{
printf("script: set_reg: illeagal scope string variable !");
}
}else{
// 悢抣
int val = (int)v;
if(str_data[num&0x00ffffff].type==C_PARAM){
pc_setparam(sd,str_data[num&0x00ffffff].val,val);
}else if(prefix=='@' || prefix=='l') {
pc_setreg(sd,num,val);
}else if(prefix=='$') {
mapreg_setreg(num,val);
}else if(prefix=='#') {
if( name[1]=='#' )
pc_setaccountreg2(sd,name,val);
else
pc_setaccountreg(sd,name,val);
}else{
pc_setglobalreg(sd,name,val);
}
}
return 0;
}
/*==========================================
* 暥帤楍傊偺曄姺
*------------------------------------------
*/
char* conv_str(struct script_state *st,struct script_data *data)
{
get_val(st,data);
if(data->type==C_INT){
char *buf;
buf=calloc(16, 1);
if(buf==NULL){
printf("out of memory : conv_str\n");
exit(1);
}
sprintf(buf,"%d",data->u.num);
data->type=C_STR;
data->u.str=buf;
#if 1
} else if(data->type==C_NAME){
// 僥儞億儔儕丅杮棃柍偄偼偢
data->type=C_CONSTSTR;
data->u.str=str_buf+str_data[data->u.num].str;
#endif
}
return data->u.str;
}
/*==========================================
* 悢抣傊曄姺
*------------------------------------------
*/
int conv_num(struct script_state *st,struct script_data *data)
{
char *p;
get_val(st,data);
if(data->type==C_STR || data->type==C_CONSTSTR){
p=data->u.str;
data->u.num = atoi(p);
if(data->type==C_STR)
free(p);
data->type=C_INT;
}
return data->u.num;
}
/*==========================================
* 僗僞僢僋傊悢抣傪僾僢僔儏
*------------------------------------------
*/
void push_val(struct script_stack *stack,int type,int val)
{
if(stack->sp >= stack->sp_max){
stack->sp_max += 64;
stack->stack_data = realloc(stack->stack_data,
sizeof(stack->stack_data[0]) * stack->sp_max);
if(stack->stack_data==NULL){
printf("push_val:stack over flow\n");
exit(1);
}
memset(stack->stack_data + (stack->sp_max - 64), 0,
64 * sizeof(*(stack->stack_data)));
}
// if(battle_config.etc_log)
// printf("push (%d,%d)-> %d\n",type,val,stack->sp);
stack->stack_data[stack->sp].type=type;
stack->stack_data[stack->sp].u.num=val;
stack->sp++;
}
/*==========================================
* 僗僞僢僋傊暥帤楍傪僾僢僔儏
*------------------------------------------
*/
void push_str(struct script_stack *stack,int type,unsigned char *str)
{
if(stack->sp>=stack->sp_max){
stack->sp_max += 64;
stack->stack_data = realloc(stack->stack_data,
sizeof(stack->stack_data[0]) * stack->sp_max);
if(stack->stack_data==NULL){
printf("push_val:stack over flow\n");
exit(1);
}
memset(stack->stack_data + (stack->sp_max - 64), '\0',
64 * sizeof(*(stack->stack_data)));
}
// if(battle_config.etc_log)
// printf("push (%d,%x)-> %d\n",type,str,stack->sp);
stack->stack_data[stack->sp].type=type;
stack->stack_data[stack->sp].u.str=str;
stack->sp++;
}
/*==========================================
* 僗僞僢僋傊暋惢傪僾僢僔儏
*------------------------------------------
*/
void push_copy(struct script_stack *stack,int pos)
{
switch(stack->stack_data[pos].type){
case C_CONSTSTR:
push_str(stack,C_CONSTSTR,stack->stack_data[pos].u.str);
break;
case C_STR:
push_str(stack,C_STR,strdup(stack->stack_data[pos].u.str));
break;
default:
push_val(stack,stack->stack_data[pos].type,stack->stack_data[pos].u.num);
break;
}
}
/*==========================================
* 僗僞僢僋偐傜億僢僾
*------------------------------------------
*/
void pop_stack(struct script_stack* stack,int start,int end)
{
int i;
for(i=start;i<end;i++){
if(stack->stack_data[i].type==C_STR){
free(stack->stack_data[i].u.str);
}
}
if(stack->sp>end){
memmove(&stack->stack_data[start],&stack->stack_data[end],sizeof(stack->stack_data[0])*(stack->sp-end));
}
stack->sp-=end-start;
}
//
// 杽傔崬傒娭悢
//
/*==========================================
*
*------------------------------------------
*/
int buildin_mes(struct script_state *st)
{
conv_str(st,& (st->stack->stack_data[st->start+2]));
clif_scriptmes(script_rid2sd(st),st->oid,st->stack->stack_data[st->start+2].u.str);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_goto(struct script_state *st)
{
int pos;
if( st->stack->stack_data[st->start+2].type!=C_POS ){
printf("script: goto: not label !\n");
st->state=END;
return 0;
}
pos=conv_num(st,& (st->stack->stack_data[st->start+2]));
st->pos=pos;
st->state=GOTO;
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_next(struct script_state *st)
{
st->state=STOP;
clif_scriptnext(script_rid2sd(st),st->oid);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_close(struct script_state *st)
{
st->state=END;
clif_scriptclose(script_rid2sd(st),st->oid);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_menu(struct script_state *st)
{
char *buf;
int len,i;
struct map_session_data *sd;
sd=script_rid2sd(st);
if(sd->state.menu_or_input==0){
st->state=RERUNLINE;
sd->state.menu_or_input=1;
for(i=st->start+2,len=16;i<st->end;i+=2){
conv_str(st,& (st->stack->stack_data[i]));
len+=strlen(st->stack->stack_data[i].u.str)+1;
}
buf=calloc(len, 1);
if(buf==NULL){
printf("out of memory : buildin_menu\n");
exit(1);
}
buf[0]=0;
for(i=st->start+2,len=0;i<st->end;i+=2){
strcat(buf,st->stack->stack_data[i].u.str);
strcat(buf,":");
}
clif_scriptmenu(script_rid2sd(st),st->oid,buf);
free(buf);
} else if(sd->npc_menu==0xff){ // cansel
sd->state.menu_or_input=0;
st->state=END;
} else { // goto摦嶌
// ragemu屳姺偺偨傔
pc_setreg(sd,add_str("l15"),sd->npc_menu);
pc_setreg(sd,add_str("@menu"),sd->npc_menu);
sd->state.menu_or_input=0;
if(sd->npc_menu>0 && sd->npc_menu<(st->end-st->start)/2){
int pos;
if( st->stack->stack_data[st->start+sd->npc_menu*2+1].type!=C_POS ){
printf("script: menu: not label !\n");
st->state=END;
return 0;
}
pos=conv_num(st,& (st->stack->stack_data[st->start+sd->npc_menu*2+1]));
st->pos=pos;
st->state=GOTO;
}
}
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_rand(struct script_state *st)
{
int range,min,max;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -