npc.c
来自「CS反恐精英1.6的部分C源代码。」· C语言 代码 · 共 872 行 · 第 1/2 页
C
872 行
//
// 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.
//
// npc.c - NPC scripting language file.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "core.h"
#include "mmo.h"
#include "npc.h"
#include "itemdb.h"
#include "script.h"
#include "map2.h"
// ADDED on 04/09/2003 -------
#include "pet.h"
// ---------------------------
static int npc_id=50000;
extern char *npc_txt[];
extern int npc_txt_num;
extern char map[][16];
extern struct mmo_map_data map_data[];
extern int packet_len_table[];
extern struct mons_data mons_data[];
#define WARP_CLASS 45
#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;}
int mmo_map_npc_say(int fd, unsigned char* buf,unsigned long id, char *string)
{
WBUFW(buf,0)=0xb4;
WBUFW(buf,2)=strlen(string)+9;
WBUFL(buf,4)=id;
strncpy(WBUFP(buf,8), string,strlen(string)+1);
return WBUFW(buf,2);
}
int mmo_map_npc_next(int fd, unsigned char* buf, unsigned long id)
{
WBUFW(buf,0)=0xb5;
WBUFL(buf,2)=id;
return 6;
}
int mmo_map_npc_close(int fd, unsigned char* buf, unsigned long id)
{
WBUFW(buf,0)=0xb6;
WBUFL(buf,2)=id;
return 6;
}
int mmo_map_npc_select(int fd, unsigned char* buf, unsigned long id, char *string)
{
WBUFW(buf,0)=0xb7;
WBUFW(buf,2)=strlen(string)+9;
WBUFL(buf,4)=id;
strncpy(WBUFP(buf,8), string, strlen(string)+1);
return WBUFW(buf,2);
}
int mmo_map_npc_amount_request(int fd, unsigned char* buf, unsigned long id)
{
WBUFW(buf,0)=0x142;
WBUFL(buf,2)=id;
return 6;
}
int mmo_map_npc_buysell(int fd, unsigned char* buf, unsigned long id)
{
WBUFW(buf,0)=0xc4;
WBUFL(buf,2)=id;
return 6;
}
int mmo_map_npc_buy(int fd, unsigned char* buf, unsigned long id, struct npc_item_list *items, int dc_skill)
{
int i;
WBUFW(buf,0)=0xc6;
for(i=0;items[i].nameid;i++){
WBUFL(buf,4+i*11)=items[i].value;
WBUFL(buf,8+i*11)=items[i].value;
WBUFB(buf,12+i*11)=itemdb_type(items[i].nameid);
WBUFW(buf,13+i*11)=items[i].nameid;
}
WBUFW(buf,2)=i*11+4;
return i*11+4;
}
int mmo_map_npc_sell(int fd, unsigned char* buf, unsigned long id, int oc_skill)
{
int i,c_item=0;
struct map_session_data *sd;
sd=session[fd]->session_data;
WBUFW(buf,0)=0xc7;
for(i=0;i<MAX_INVENTORY;i++) {
if(sd->status.inventory[i].nameid) {
WBUFW(buf,4+c_item*10)=i+2;
WBUFL(buf,6+c_item*10)=itemdb_sellvalue(sd->status.inventory[i].nameid);
WBUFL(buf,10+c_item*10)=WBUFL(buf,6+c_item*10);
c_item++;
}
}
WBUFW(buf,2)=c_item*10+4;
return c_item*10+4;
}
int npc_click(int fd,int npc_id)
{
int npc_len,n;
struct map_session_data *sd;
sd=session[fd]->session_data;
// ADDED on 06/14/2003 by SilentAvenger ---------
if(!sd->status.talking_to_npc)
{
sd->status.talking_to_npc=1;
// ----------------------------------------------
for(n=0;n<map_data[sd->mapno].npc_num;n++)
if(map_data[sd->mapno].npc[n]->id==npc_id)
break;
if(n==map_data[sd->mapno].npc_num ||
map_data[sd->mapno].npc[n]->block.type!=BL_NPC)
return -1;
switch(map_data[sd->mapno].npc[n]->block.subtype){
case SCRIPT:
sd->npc_pc=0;
sd->npc_id=npc_id;
sd->npc_n=n;
run_script(fd,sd);
break;
case SHOP:
sd->status.talking_to_npc=0;
npc_len = mmo_map_npc_buysell(fd, WFIFOP(fd,0),npc_id);
WFIFOSET(fd, npc_len);
sd->npc_id=npc_id;
sd->npc_n=n;
break;
}
#if 0
/*NPC test code*/
if(npc_id==1) {
npc_len = mmo_map_npc_say(fd, WFIFOP(fd,0),1,"test");
WFIFOSET(fd, npc_len);
mmo_map_npc_next(fd, WFIFOP(fd,0),1);
WFIFOSET(fd, 6);
}
#endif
// ADDED on 06/14/2003 by SilentAvenger ---------
}
// ----------------------------------------------
return 0;
}
int npc_menu_select(int fd,int npc_id,int sel)
{
struct map_session_data *sd;
sd=session[fd]->session_data;
sd->local_reg[15]=sel;
if(sel==0xff){
sd->npc_pc=0;
sd->npc_id=0;
sd->npc_n=0;
// ADDED on 06/14/2003 by SilentAvenger ---------
sd->status.talking_to_npc=0;
// ----------------------------------------------
return 0;
}
run_script(fd,sd);
return 0;
}
int npc_next_click(int fd,int npc_id)
{
struct map_session_data *sd;
sd=session[fd]->session_data;
run_script(fd,sd);
return 0;
}
int npc_amount_input(int fd,int npc_id,int val)
{
struct map_session_data *sd;
sd=session[fd]->session_data;
sd->local_reg[14]=val;
run_script(fd,sd);
return 0;
}
int npc_close_click(int fd,int npc_id)
{
// ADDED on 06/14/2003 by SilentAvenger ---------
struct map_session_data *sd;
sd=session[fd]->session_data;
sd->status.talking_to_npc=0;
// ----------------------------------------------
return 0;
}
int npc_buysell_selected(int fd,int npc_id,int sell)
{
int npc_len,n;
struct map_session_data *sd;
sd=session[fd]->session_data;
for(n=0;n<map_data[sd->mapno].npc_num;n++)
if(map_data[sd->mapno].npc[n]->id==npc_id)
break;
if(n==map_data[sd->mapno].npc_num ||
map_data[sd->mapno].npc[n]->block.type!=BL_NPC ||
map_data[sd->mapno].npc[n]->block.subtype!=SHOP ||
sd->npc_id!=npc_id)
return -1;
if(sell){
npc_len = mmo_map_npc_sell(fd, WFIFOP(fd,0),npc_id,0);
} else {
npc_len = mmo_map_npc_buy(fd, WFIFOP(fd,0),npc_id,map_data[sd->mapno].npc[n]->u.shop_item,0);
}
WFIFOSET(fd, npc_len);
return 0;
}
struct map_session_data* make_rollback_point(struct map_session_data *sd)
{
struct map_session_data *back;
back=malloc(sizeof(*back));
memcpy(back,sd,sizeof(*back));
return back;
}
int do_rollback(struct map_session_data *sd,struct map_session_data *back)
{
memcpy(sd,back,sizeof(*back));
free(back);
return 0;
}
int delete_rollback_point(struct map_session_data *back)
{
free(back);
return 0;
}
int npc_buy_selected(int fd,void *list,int num)
{
int i,j,n,len,pos;
struct item tmp_item;
struct map_session_data *sd,*back;
int fail=0;
sd=session[fd]->session_data;
for(n=0;n<map_data[sd->mapno].npc_num;n++)
if(map_data[sd->mapno].npc[n]->id==sd->npc_id)
break;
if(n==map_data[sd->mapno].npc_num ||
map_data[sd->mapno].npc[n]->block.type!=BL_NPC ||
map_data[sd->mapno].npc[n]->block.subtype!=SHOP)
return -1;
back=make_rollback_point(sd);
memset(&tmp_item,0,sizeof(tmp_item));
for(i=pos=0;i<num;i++){
tmp_item.amount=RBUFW(list,i*4); // amount
tmp_item.nameid=RBUFW(list,i*4+2); // nameid
tmp_item.identify=1;
for(j=0;map_data[sd->mapno].npc[n]->u.shop_item[j].nameid;j++)
if(map_data[sd->mapno].npc[n]->u.shop_item[j].nameid==tmp_item.nameid)
break;
if(map_data[sd->mapno].npc[n]->u.shop_item[j].nameid==0){
fail=1; // 海お厦面のNPCで卿ってないアイテムが回年されたっぽ
session[fd]->eof=1; // プチっ
break;
}
len=mmo_map_item_get(fd,WFIFOP(fd,pos),&tmp_item);
if(len<=0){
if(len==-1)
fail=3; // 硷梧眶亩册。3它改臂えも雇えられるけど、烫泡なので琵办
else if(len==-2)
fail=2; // 脚翁オ〖バ
else
fail=3; // 奇
break;
}
pos+=len;
sd->status.zeny -= map_data[sd->mapno].npc[n]->u.shop_item[j].value*tmp_item.amount;
if(sd->status.zeny < 0){
fail=1; // お垛稍颅
break;
}
pos+=mmo_map_set_param(fd,WFIFOP(fd,pos),SP_ZENY);
}
if(fail){
do_rollback(sd,back);
} else {
WFIFOSET(fd,pos);
delete_rollback_point(back);
}
WFIFOW(fd,0)=0xca;
WFIFOB(fd,2)=fail;
WFIFOSET(fd,3);
return 0;
}
int npc_sell_selected(int fd,void *list,int num)
{
int i,len,pos;
struct map_session_data *sd,*back;
int fail=0;
sd=session[fd]->session_data;
back=make_rollback_point(sd);
for(i=pos=0;i<num;i++){
sd->status.zeny+=itemdb_sellvalue(sd->status.inventory[RBUFW(list,i*4)-2].nameid)*RBUFW(list,i*4+2);
pos+=mmo_map_set_param(fd,WFIFOP(fd,pos),SP_ZENY);
len=mmo_map_item_lost(fd,WFIFOP(fd,pos),RBUFW(list,i*4),RBUFW(list,i*4+2));
if(len<=0){
fail=1;
break;
}
pos+=len;
}
if(fail){
do_rollback(sd,back);
} else {
WFIFOSET(fd,pos);
delete_rollback_point(back);
}
WFIFOW(fd,0)=0xcb;
WFIFOB(fd,2)=fail;
WFIFOSET(fd,3);
return 0;
}
int set_monster_random_point(int m,int n)
{
int x,y;
do {
x=rand()%(map_data[m].xs-2)+1;
y=rand()%(map_data[m].ys-2)+1;
} while(map_data[m].gat[x+y*map_data[m].xs]==1 || map_data[m].gat[x+y*map_data[m].xs]==5);
map_data[m].npc[n]->u.mons.to_x=map_data[m].npc[n]->x=x;
map_data[m].npc[n]->u.mons.to_y=map_data[m].npc[n]->y=y;
map_data[m].npc[n]->dir=0;
return 0;
}
//斧た誊弄にみえないところへ浓をとばす
int set_monster_no_point(int m,int n)
{
int x,y;
x=-1;
y=-1;
map_data[m].npc[n]->u.mons.to_x=map_data[m].npc[n]->x=x;
map_data[m].npc[n]->u.mons.to_y=map_data[m].npc[n]->y=y;
map_data[m].npc[n]->dir=0;
return 0;
}
//モンスタ〖が殊く簇眶
int mons_walk(int tid,unsigned int tick,int m,int n)
{
int x,y,dx,dy;
struct map_session_data sd;
int ret,i;
if(mons_data[map_data[m].npc[n]->class].aggressive==2 ||
mons_data[map_data[m].npc[n]->class].aggressive==3 ||
mons_data[map_data[m].npc[n]->class].aggressive==4 )
return 0;
// fix point monster
if(map_data[m].npc[n]->u.mons.speed<=0){
map_data[m].npc[n]->u.mons.timer=
add_timer(tick+rand()%5000+5000,mons_walk,m,n);
return 0;
}
x=map_data[m].npc[n]->x;
y=map_data[m].npc[n]->y;
dx= map_data[m].npc[n]->u.mons.to_x - x;
dy= map_data[m].npc[n]->u.mons.to_y - y;
// printf("%d,%d,%d (%d,%d) (%d,%d)\n",m,n,map_data[m].npc[n]->id,map_data[m].npc[n]->x,map_data[m].npc[n]->y,dx,dy);
if(dx || dy){
// step
if(dx<0) dx=-1;
else if(dx>0) dx=1;
if(dy<0) dy=-1;
else if(dy>0) dy=1;
if((x+dx)/BLOCK_SIZE != x/BLOCK_SIZE || (y+dy)/BLOCK_SIZE != y/BLOCK_SIZE){
unsigned char buf[256];
int bx,by;
bx=x/BLOCK_SIZE;
by=y/BLOCK_SIZE;
WBUFW(buf,0)=0x80;
WBUFL(buf,2)=map_data[m].npc[n]->id;
WBUFB(buf,6)=0; // no effect?
if((x+dx)/BLOCK_SIZE != x/BLOCK_SIZE && bx-dx*AREA_SIZE>=0 && bx-dx*AREA_SIZE<map_data[m].bxs){ // x
for(i=-AREA_SIZE;i<=AREA_SIZE;i++){ // x
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?