📄 npc.c
字号:
// $Id: npc.c,v 1.12 2003/07/01 00:29:54 lemit Exp $
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include "map.h"
#include "npc.h"
#include "clif.h"
#include "pc.h"
#include "itemdb.h"
#include "script.h"
#include "mob.h"
#include "db.h"
#include "timer.h"
#include "pet.h"
#include "battle.h"
#include "skill.h"
#ifdef MEMWATCH
#include "memwatch.h"
#endif
struct npc_src_list {
struct npc_src_list * next;
char name[4];
} ;
static struct npc_src_list *npc_src_first,*npc_src_last;
static int npc_id=START_NPC_NUM;
static int npc_warp,npc_shop,npc_script,npc_mob;
int npc_get_new_npc_id(void){ return npc_id++; }
static struct dbt *ev_db;
static struct dbt *npcname_db;
struct event_data {
struct npc_data *nd;
int pos;
};
static struct tm ev_tm_b; // 帪寁僀儀儞僩梡
/*==========================================
* NPC偺柍岠壔/桳岠壔
*------------------------------------------
*/
int npc_enable(const char *name,int flag)
{
struct npc_data *nd=strdb_search(npcname_db,name);
if (nd==NULL)
return 0;
if (flag) { // 桳岠壔
nd->flag&=~1;
clif_spawnnpc(nd);
}else{ // 柍岠壔
nd->flag|=1;
clif_clearchar(&nd->bl,0);
}
return 0;
}
/*==========================================
* NPC傪柤慜偱扵偡
*------------------------------------------
*/
struct npc_data* npc_name2id(const char *name)
{
return strdb_search(npcname_db,name);
}
/*==========================================
* 僀儀儞僩僉儏乕偺僀儀儞僩張棟
*------------------------------------------
*/
int npc_event_dequeue(struct map_session_data *sd)
{
sd->npc_id=0;
if (sd->eventqueue[0][0]) { // 僉儏乕偺僀儀儞僩張棟
char *name=calloc(50, 1);
int i;
if (name==NULL) {
printf("run_script: out of memory !\n");
exit(1);
}
memcpy(name,sd->eventqueue[0],50);
for(i=MAX_EVENTQUEUE-2;i>=0;i--)
memcpy(sd->eventqueue[i],sd->eventqueue[i+1],50);
add_timer(gettick()+100,npc_event_timer,sd->bl.id,(int)name);
}
return 0;
}
/*==========================================
* 僀儀儞僩偺抶墑幚峴
*------------------------------------------
*/
int npc_event_timer(int tid,unsigned int tick,int id,int data)
{
struct map_session_data *sd=map_id2sd(id);
if (sd==NULL)
return 0;
npc_event(sd,(const char *)data);
free((void*)data);
return 0;
}
/*==========================================
* 慡偰偺NPC偺On*僀儀儞僩幚峴
*------------------------------------------
*/
int npc_event_doall_sub(void *key,void *data,va_list ap)
{
char *p=(char *)key;
struct event_data *ev=(struct event_data *)data;
int *c=va_arg(ap,int *);
const char *name=va_arg(ap,const char *);
if( (p=strchr(p,':')) && p && strcasecmp(name,p)==0 ){
run_script(ev->nd->u.scr.script,ev->pos,0,ev->nd->bl.id);
(*c)++;
}
return 0;
}
int npc_event_doall(const char *name)
{
int c=0;
char buf[64]="::";
strcpy(buf+2,name);
strdb_foreach(ev_db,npc_event_doall_sub,&c,buf);
return c;
}
int npc_event_do_sub(void *key,void *data,va_list ap)
{
char *p=(char *)key;
struct event_data *ev=(struct event_data *)data;
int *c=va_arg(ap,int *);
const char *name=va_arg(ap,const char *);
if (p && strcasecmp(name,p)==0 ) {
run_script(ev->nd->u.scr.script,ev->pos,0,ev->nd->bl.id);
(*c)++;
}
return 0;
}
int npc_event_do(const char *name)
{
int c=0;
if (*name==':' && name[1]==':') {
return npc_event_doall(name+2);
}
strdb_foreach(ev_db,npc_event_do_sub,&c,name);
return c;
}
/*==========================================
* 帪寁僀儀儞僩幚峴
*------------------------------------------
*/
int npc_event_do_clock(int tid,unsigned int tick,int id,int data)
{
time_t timer;
struct tm *t;
char buf[64];
int c=0;
time(&timer);
t=localtime(&timer);
if (t->tm_min != ev_tm_b.tm_min ) {
sprintf(buf,"OnMinute%02d",t->tm_min);
c+=npc_event_doall(buf);
sprintf(buf,"OnClock%02d%02d",t->tm_hour,t->tm_min);
c+=npc_event_doall(buf);
}
if (t->tm_hour!= ev_tm_b.tm_hour) {
sprintf(buf,"OnHour%02d",t->tm_hour);
c+=npc_event_doall(buf);
}
if (t->tm_mday!= ev_tm_b.tm_mday) {
sprintf(buf,"OnDay%02d%02d",t->tm_mon+1,t->tm_mday);
c+=npc_event_doall(buf);
}
memcpy(&ev_tm_b,t,sizeof(ev_tm_b));
return c;
}
/*==========================================
* OnInit僀儀儞僩幚峴(&帪寁僀儀儞僩奐巒)
*------------------------------------------
*/
int npc_event_do_oninit(void)
{
int c = npc_event_doall("OnInit");
printf("npc: OnInit Event done. (%d npc)\n",c);
add_timer_interval(gettick()+100,
npc_event_do_clock,0,0,1000);
return 0;
}
/*==========================================
* 僞僀儅乕僀儀儞僩幚峴
*------------------------------------------
*/
int npc_timerevent(int tid,unsigned int tick,int id,int data)
{
int next,t;
struct npc_data* nd=(struct npc_data *)map_id2bl(id);
struct npc_timerevent_list *te;
if( nd==NULL || nd->u.scr.nexttimer<0 ){
printf("npc_timerevent: ??\n");
return 0;
}
nd->u.scr.timertick=tick;
te=nd->u.scr.timer_event+ nd->u.scr.nexttimer;
nd->u.scr.timerid = -1;
t = nd->u.scr.timer+=data;
nd->u.scr.nexttimer++;
if( nd->u.scr.timeramount>nd->u.scr.nexttimer ){
next= nd->u.scr.timer_event[ nd->u.scr.nexttimer ].timer - t;
nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,id,next);
}
run_script(nd->u.scr.script,te->pos,0,nd->bl.id);
return 0;
}
/*==========================================
* 僞僀儅乕僀儀儞僩奐巒
*------------------------------------------
*/
int npc_timerevent_start(struct npc_data *nd)
{
int j,n=nd->u.scr.timeramount, next;
if( nd->u.scr.nexttimer>=0 || n==0 )
return 0;
for(j=0;j<n;j++){
if( nd->u.scr.timer_event[j].timer > nd->u.scr.timer )
break;
}
nd->u.scr.nexttimer=j;
nd->u.scr.timertick=gettick();
if(j>=n)
return 0;
next = nd->u.scr.timer_event[j].timer - nd->u.scr.timer;
nd->u.scr.timerid = add_timer(gettick()+next,npc_timerevent,nd->bl.id,next);
return 0;
}
/*==========================================
* 僞僀儅乕僀儀儞僩廔椆
*------------------------------------------
*/
int npc_timerevent_stop(struct npc_data *nd)
{
if( nd->u.scr.nexttimer>=0 ){
nd->u.scr.nexttimer = -1;
nd->u.scr.timer += (int)(gettick() - nd->u.scr.timertick);
if(nd->u.scr.timerid!=-1)
delete_timer(nd->u.scr.timerid,npc_timerevent);
nd->u.scr.timerid = -1;
}
return 0;
}
/*==========================================
* 僞僀儅乕抣偺強摼
*------------------------------------------
*/
int npc_gettimerevent_tick(struct npc_data *nd)
{
int tick=nd->u.scr.timer;
if( nd->u.scr.nexttimer>=0 )
tick += (int)(gettick() - nd->u.scr.timertick);
return tick;
}
/*==========================================
* 僞僀儅乕抣偺愝掕
*------------------------------------------
*/
int npc_settimerevent_tick(struct npc_data *nd,int newtimer)
{
int flag= nd->u.scr.nexttimer;
npc_timerevent_stop(nd);
nd->u.scr.timer=newtimer;
if(flag>=0)
npc_timerevent_start(nd);
return 0;
}
/*==========================================
* 僀儀儞僩宆偺NPC張棟
*------------------------------------------
*/
int npc_event(struct map_session_data *sd,const char *eventname)
{
struct event_data *ev=strdb_search(ev_db,eventname);
struct npc_data *nd;
int xs,ys;
if (sd == NULL) return 0;
if (ev==NULL || (nd=ev->nd)==NULL) {
if (battle_config.error_log)
printf("npc_event: event not found [%s]\n",eventname);
return 0;
}
xs=nd->u.scr.xs;
ys=nd->u.scr.ys;
if (xs>=0 && ys>=0 ) {
if (nd->bl.m != sd->bl.m )
return 0;
if ( xs>0 && (sd->bl.x<nd->bl.x-xs/2 || nd->bl.x+xs/2<sd->bl.x) )
return 0;
if ( ys>0 && (sd->bl.y<nd->bl.y-ys/2 || nd->bl.y+ys/2<sd->bl.y) )
return 0;
}
if ( sd->npc_id!=0) {
// if (battle_config.error_log)
// printf("npc_event: npc_id != 0\n");
int i;
for(i=0;i<MAX_EVENTQUEUE;i++)
if (!sd->eventqueue[i][0])
break;
if (i==MAX_EVENTQUEUE) {
if (battle_config.error_log)
printf("npc_event: event queue is full !\n");
}else{
// if (battle_config.etc_log)
// printf("npc_event: enqueue\n");
memcpy(sd->eventqueue[i],eventname,50);
}
return 1;
}
if (nd->flag&1) { // 柍岠壔偝傟偰偄傞
npc_event_dequeue(sd);
return 0;
}
sd->npc_id=nd->bl.id;
sd->npc_pos=run_script(nd->u.scr.script,ev->pos,sd->bl.id,nd->bl.id);
return 0;
}
/*==========================================
* 愙怗宆偺NPC張棟
*------------------------------------------
*/
int npc_touch_areanpc(struct map_session_data *sd,int m,int x,int y)
{
int i,f=1;
int xs,ys;
for(i=0;i<map[m].npc_num;i++) {
if (map[m].npc[i]->flag&1) { // 柍岠壔偝傟偰偄傞
f=0;
continue;
}
switch(map[m].npc[i]->bl.subtype) {
case WARP:
xs=map[m].npc[i]->u.warp.xs;
ys=map[m].npc[i]->u.warp.ys;
break;
case SCRIPT:
xs=map[m].npc[i]->u.scr.xs;
ys=map[m].npc[i]->u.scr.ys;
break;
default:
continue;
}
if (x >= map[m].npc[i]->bl.x-xs/2 && x < map[m].npc[i]->bl.x-xs/2+xs &&
y >= map[m].npc[i]->bl.y-ys/2 && y < map[m].npc[i]->bl.y-ys/2+ys)
break;
}
if (i==map[m].npc_num) {
if (f) {
if (battle_config.error_log)
printf("npc_touch_areanpc : some bug \n");
}
return 1;
}
switch(map[m].npc[i]->bl.subtype) {
case WARP:
pc_setpos(sd,map[m].npc[i]->u.warp.name,map[m].npc[i]->u.warp.x,map[m].npc[i]->u.warp.y,0);
break;
case SCRIPT:
npc_click(sd,map[m].npc[i]->bl.id);
break;
}
return 0;
}
/*==========================================
* 嬤偔偐偳偆偐偺敾掕
*------------------------------------------
*/
int npc_checknear(struct map_session_data *sd,int id)
{
struct npc_data *nd;
nd=(struct npc_data *)map_id2bl(id);
if (nd==NULL || nd->bl.type!=BL_NPC) {
if (battle_config.error_log)
printf("no such npc : %d\n",id);
return 1;
}
if (nd->class<0) // 僀儀儞僩宯偼忢偵OK
return 1;
// 僄儕傾敾掕
if (nd->bl.m!=sd->bl.m ||
nd->bl.x<sd->bl.x-AREA_SIZE-1 || nd->bl.x>sd->bl.x+AREA_SIZE+1 ||
nd->bl.y<sd->bl.y-AREA_SIZE-1 || nd->bl.y>sd->bl.y+AREA_SIZE+1)
return 1;
return 0;
}
/*==========================================
* 僋儕僢僋帪偺NPC張棟
*------------------------------------------
*/
int npc_click(struct map_session_data *sd,int id)
{
struct npc_data *nd;
if (sd->npc_id != 0) {
if (battle_config.error_log)
printf("npc_click: npc_id != 0\n");
return 1;
}
if (npc_checknear(sd,id))
return 1;
nd=(struct npc_data *)map_id2bl(id);
if (nd->flag&1) // 柍岠壔偝傟偰偄傞
return 1;
sd->npc_id=id;
switch(nd->bl.subtype) {
case SHOP:
clif_npcbuysell(sd,id);
npc_event_dequeue(sd);
break;
case SCRIPT:
sd->npc_pos=run_script(nd->u.scr.script,0,sd->bl.id,id);
break;
}
return 0;
}
/*==========================================
*
*------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -