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