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 + -
显示快捷键?