map2.c

来自「CS反恐精英1.6的部分C源代码。」· C语言 代码 · 共 2,313 行 · 第 1/5 页

C
2,313
字号
// 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.
//
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <arpa/inet.h>

#include "core.h"
#include "mmo.h"
#include "grfio.h"
#include "npc.h"
#include "itemdb.h"
#include "skill_db.h"
#include "save.h"
#include "map2.h"
#include "party.h"
#include "guild.h"
// ADDED on 04/09/2003 --------------
#include "pet.h"
// ----------------------------------

const int packet_len_table[0x200]={
   10,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,

    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0, 55, 17,  3, 37,  46, -1, 23, -1,  3,108,  3,  2,
    3, 28, 19, 11,  3, -1,  9,  5,  52, 51, 56, 58, 41,  2,  6,  6,

    7,  3,  2,  2,  2,  5, 16, 12,  10,  7, 29, 23, -1, -1, -1,  0,
    7, 22, 28,  2,  6, 30, -1, -1,   3, -1, -1,  5,  9, 17, 17,  6,
   23,  6,  6, -1, -1, -1, -1,  8,   7,  6,  7,  4,  7,  0, -1,  6,
    8,  8,  3,  3, -1,  6,  6, -1,   7,  6,  2,  5,  6, 44,  5,  3,

    7,  2,  6,  8,  6,  7, -1, -1,  -1, -1,  3,  3,  6,  3,  2, 27,
    3,  4,  4,  2, -1, -1,  3, -1,   6, 14,  3, -1, 28, 29, -1, -1,
   30, 30, 26,  2,  6, 26,  3,  3,   8, 19,  5,  2,  3,  2,  2,  2,
    3,  2,  6,  8, 21,  8,  8,  2,   2, 26,  3, -1,  6, 27, 30, 10,


    2,  6,  6, 30, 79, 31, 10, 10,  -1, -1,  4,  6,  6,  2, 11, -1,
   10, 39,  4, 10, 31, 35, 10, 18,   2, 13, 15, 20, 68,  2,  3, 16,
    6, 14, -1, -1, 21,  8,  8,  8,   8,  8,  2,  2,  3,  4,  2, -1,
    6, 86,  6, -1, -1,  7, -1,  6,   3, 16,  4,  4,  4,  6, 24, 26,

   22, 14,  6, 10, 23, 19,  6, 39,   8,  9,  6, 27, -1,  2,  6,  6,
  110,  6, -1, -1, -1, -1, -1,  6,  -1, 54, 66, 54, 90, 42,  6, 42,
   -1, -1, -1, -1, -1, 30, -1,  3,  14,  3, 30, 10, 43, 14,186,182,
   14, 30, 10,  3, -1,  6,106, -1,   4,  5,  4, -1,  6,  7, -1, -1,

    6,  3,106, 10, 10, 34,  0,  6,   8,  4,  4,  4, 29, -1, 10,  6,
   90, 86, 24,  6, 30,102,  8,  4,   8,  4, 14, 10, -1,  6,  2,  6,
    3,  3, 35,  5, 11, 26, -1,  4,   4,  6, 10, 12,  6, -1,  4,  4,
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,

    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,

};

const unsigned short def_aspd[14][13] =
  {
    { 500, 650, 700,2000,2000,2000,2000, 650, 700, 800,2000,2000,2000},     /* Novice */
    { 400, 500, 550, 600, 650, 700,2000,2000, 650, 700, 740,2000,2000},     /* Swordman */
    { 500, 600,2000,2000,2000,2000,2000, 700,2000,2000,2000,2000,2000},     /* Mage */
    { 400, 600,2000,2000,2000,2000, 700,2000,2000,2000,2000,2000,2000},     /* Archer */
    { 350,2000,2000,2000,2000,2000,2000, 600, 600,2000,2000,2000,2000},     /* Acolyte */
    { 400, 600, 700,2000,2000,2000,2000,2000, 700, 700, 750,2000,2000},     /* Marchant */
    { 400, 500, 650,2000,2000,2000, 850,2000,2000, 800,2000,2000,2000},     /* Thief */
    { 400, 500, 500, 550, 600, 650,2000,2000, 650, 700, 740,2000,2000},     /* Night */
    { 350,2000,2000,2000,2000,2000,2000, 600, 600,2000,2000,2000, 600},     /* Priest */
    { 500, 600,2000,2000,2000,2000,2000, 700,2000,2000,2000,2000,2000},     /* Wizard */
    { 400, 600, 700,2000,2000,2000,2000,2000, 700, 700, 750,2000,2000},     /* Blacksmith */
    { 400, 600,2000,2000,2000,2000, 600,2000,2000,2000,2000,2000,2000},     /* Hunter */
    { 400, 500, 650,2000,2000,2000,2000,2000,2000, 800,2000, 500,2000},     /* Assasin */
    { 400, 600,2000,2000,2000,2000, 600,2000,2000,2000,2000,2000,2000},     /* kami */
};

int count=0;
int rank;
int char_fd;
int current_attack_m = 0;
char userid[24];
char passwd[24];
char char_ip_str[16];
int char_port;
char map_ip_str[16];
int map_ip;
int map_port;
int map_port_fd;
char mapmove_name[24]="-mapmove-";
char map[MAX_MAP_PER_SERVER][16]={"prontera.gat",""};
struct mmo_map_data map_data[MAX_MAP_PER_SERVER];
int users,users_global;
char *npc_txt[256];
int npc_txt_num=0;
struct skill_db skill_db[MAX_SKILL];//skill database information
struct mmo_chat *last_chat;
struct block_list *object[50000];
int first_free_object_id,last_object_id;
struct mons_data mons_data[4000];
long ExpData[101];//Lvup experience value data
long SkillExpData[3][101];//skill lv up experience data
int PVP_flag=0;
int check_connect_timer;
int send_users_tochar_timer;
int clear_flooritem_timer;
int loop_monstersearch_timer;
int heal_hp_timer;
int heal_sp_timer;
int map_number;


//macro declaration
#define NOM_ATTACK(atk1,atk2,def) ((atk1+rand()%atk2)-def);//normal attack
#define CRI_ATTACK(atk1,atk2,s_lv,s_type)	(atk1+atk2+s_lv*s_type);//critical attack
#define KAT_ATTACK(damage)	((damage/5)+1);//second katar attack
#define SKILL_ATTACK(matk1,matk2) (matk2+rand()%matk1);//skill attack
#define SKILL_HEAL(int_,blvl,lvl) ((blvl + int_)/8)*(12 * lvl);//( [ BLv + Int ] / 8 ) * ( 12 * SLv ) formula by Trihan 
//#define SKILL_HEAL(int_) (rand()%2000+int_);//heal amount
#define SKILL_BASH(atk1,atk2,lvl) ( (  (atk1+rand()%atk2) * (100+(30*lvl))/100 ) - 0  );//skilllvlbonus =  100% 130 160 depend on skill lvl
// Find char, By SilentAvenger 16/6/03
int find_char(char* cname)
{
	int i;
	for(i=0;i<FD_SETSIZE;i++)
	{
		if(session[i]!=NULL && session[i]->session_data!=NULL)
		{
			struct map_session_data *sd=NULL;
			sd = session[i]->session_data;
			if(strcmp(sd->status.name,cname)==0) return i;
		}
	}
	return -1;
}

// BugFix by -AL- 15/06/2003
void add_block(struct block_list *bl,int m,int x,int y)
{
  struct block_list * head;
  int blocknumber;

  if(!bl){
    printf("[Error] add_block : block_list is NULL\n");
    return;
  }
  if((m<0)||(m>(MAX_MAP_PER_SERVER-1))){
    printf("[Error] add_block : wrong map number (%d)\n",m);
    return;
  }
  if((x<0)||(y<0)){
    printf("[Error] add_block : x(%d) or y(%d) is negativ\n",x,y);
    return;
  }

  //printf("[Debug] add_block : add (%d,%d,%d)\n",m,x,y);
  
  blocknumber=x/BLOCK_SIZE+(y/BLOCK_SIZE)*map_data[m].bxs;
  head = &map_data[m].block[blocknumber];
  if (!head){
    printf("[Error] add_block : block %d doesn't exist in map %d\n",blocknumber,m);
    return;
  }
  
  bl->next = head->next;
  bl->prev = head;
  if(bl->next) bl->next->prev = bl;
  head->next = bl;
  return;
}


void del_block(struct block_list *bl)
{
  if(bl->prev==NULL){
    printf("del_block link error\n");
    exit(1);
  }
  if(bl->next) bl->next->prev = bl->prev;
  bl->prev->next = bl->next;
  bl->next = NULL;
  bl->prev = NULL;
}

int search_free_object_id(void)
{
  int i;
  if(first_free_object_id<2 || first_free_object_id>=50000)
    first_free_object_id=2;
  for(i=first_free_object_id;i<50000;i++)
    if(object[i]==NULL)
      break;
  if(i==50000){
    printf("no free object id\n");
    return 0;
  }
  first_free_object_id=i;
  if(last_object_id<i)
    last_object_id=i;
  return i;
}

int delete_object(int id)
{
  if(object[id]==NULL)
    return 0;

  del_block(object[id]);
  free(object[id]);
  object[id]=NULL;

  if(first_free_object_id>id)
    first_free_object_id=id;

  while(last_object_id>2 && object[last_object_id]==NULL)
    last_object_id--;

  return 0;
}

int set_pos(unsigned char *p,int x,int y)
{
  *p=x>>2;
  p[1]=(x<<6) | ((y>>4)&0x3f);
  p[2]=y<<4;
  return 0;
}

int set_2pos(unsigned char *p,int x0,int y0,int x1,int y1)
{
  *p=x0>>2;
  p[1]=(x0<<6) | ((y0>>4)&0x3f);
  p[2]=(y0<<4) | ((x1>>6)&0x0f);
  p[3]=(x1<<2) | ((y1>>8)&0x03);
  p[4]=y1;
  return 0;
}

int set_map(struct map_session_data *sd,char *mapname,int x,int y)
{
  int i;
  if(sd==NULL)
    return -1;
  sd->x = x;
  sd->y = y;
  memcpy(sd->mapname,mapname,16);
  for(i=0;map[i][0];i++)
    if(strcmp(map[i],mapname)==0)
      break;
	if(map[i][0]){
    sd->mapno=i;
//	printf("mapno %d \n",i);
	}
  else
    return 1; // must send 0092?
  if(sd->x <0 || sd->x >= map_data[i].xs)
    sd->x=0;
  if(sd->y <0 || sd->y >= map_data[i].ys)
    sd->y=0;
  add_block(&sd->block,i,sd->x,sd->y);
  map_data[i].users++;
  return 0;
}

int wait_close(int tid,unsigned int tick,int id,int data)
{
  if(session[id]==NULL)
    return 0;
  session[id]->eof=1;
  return 0;
}

int parse_tochar(int fd)
{
  struct map_session_data *sd=NULL;
  int i,j,fdc;

  if(session[fd]->eof){
    if(fd==char_fd)
      char_fd=-1;
    printf("parse_tochar close %d\n",fd);
    close(fd);
    delete_session(fd);
    return 0;
  }
  //printf("parse_tochar : %d %d %d\n",fd,RFIFOREST(fd),RFIFOW(fd,0));
  while(RFIFOREST(fd)>=2){
    switch(RFIFOW(fd,0)){
    case 0x2af9:
      if(RFIFOREST(fd)<3)
	return 0;
      if(RFIFOB(fd,2)){
	printf("connect char server error : %d\n",RFIFOB(fd,2));
	exit(1);
      }
      RFIFOSKIP(fd,3);
      WFIFOW(fd,0)=0x2afa;
      for(i=0;map[i][0];i++){
	memcpy(WFIFOP(fd,4+i*16),map[i],16);
      }
      WFIFOW(fd,2)=4+i*16;
      WFIFOSET(fd,WFIFOW(fd,2));
      break;
    case 0x2afb:
      if(RFIFOREST(fd)<3)
	return 0;
      if(RFIFOB(fd,2)!=0){
	printf("send map error :%d\n",RFIFOB(fd,2));
	exit(1);
      }
      RFIFOSKIP(fd,3);
      break;
    case 0x2afd:
      if(RFIFOREST(fd)<4 || RFIFOREST(fd)<RFIFOW(fd,2))
	return 0;
      for(i=0;i<FD_SETSIZE;i++)
	if(session[i] && (sd=session[i]->session_data) && sd->account_id==RFIFOL(fd,4))
	  break;
      for(j=i+1;j<FD_SETSIZE;j++){
	struct map_session_data *tmp_sd;
	if(session[j] && (tmp_sd=session[j]->session_data) && tmp_sd->account_id==RFIFOL(fd,4))
	  break;
      }
      if(j!=FD_SETSIZE){
	//after certification, both players are dropped on a double login
	//printf("Output 1 : %d / Output 2 : %d",session[i]->wdata_size,session[i]->wdata);

/* Testing fix by removing packets to null connections... and just raw closing the socket.. (hud) */
	if ((i<FD_SETSIZE) && session[i] && session[i]->session_data)
	{
	  WFIFOW(i,0)=0x81;
	  WFIFOB(i,2)=8;
	  WFIFOSET(i,3);
	  add_timer(gettick()+100,wait_close,i,0);
	}
	if ((j<FD_SETSIZE) && session[j] && session[j]->session_data)
	{
	  WFIFOW(j,0)=0x81;
	  WFIFOB(j,2)=8;
	  WFIFOSET(j,3);
	  add_timer(gettick()+100,wait_close,j,0);
	}
      } else if(i!=FD_SETSIZE){
	fdc=i;
	memcpy(&sd->status,RFIFOP(fd,12),sizeof(sd->status));
	set_map(sd,sd->status.last_point.map , sd->status.last_point.x , sd->status.last_point.y);
	sd->speed = DEFAULT_WALK_SPEED;
	sd->sitting=0;
	sd->dir=0;
	sd->head_dir=0;
	WFIFOW(fdc,0)=0x73;
	WFIFOL(fdc,2)=gettick();
	set_pos(WFIFOP(fdc,6),sd->x,sd->y);
	WFIFOB(fdc,9)=5;
	WFIFOB(fdc,10)=5;
	WFIFOSET(fdc,11);
	sd->state.auth=1;

	// ADDED on 04/09/2003 -------------
	//pet_init(sd);
	sd->status.pet.pet_id_as_npc = -1;
	//printf("PET_ID=%d, ACTIVITY=%d\n",sd->status.pet.pet_id_as_npc,sd->status.pet.activity);
	// ---------------------------------
      }
      RFIFOSKIP(fd,RFIFOW(fd,2));
      break;
    case 0x2afe:
      if(RFIFOREST(fd)<7)
	return 0;
      for(i=0;i<FD_SETSIZE;i++)
	if(session[i] && (sd=session[i]->session_data) && sd->account_id==RFIFOL(fd,4))
	  break;
      if(i!=FD_SETSIZE){
	close(i);
	session[i]->eof=1;
      }
      RFIFOSKIP(fd,7);
      break;
    case 0x2b00:
      if(RFIFOREST(fd)<6)
	return 0;
      users_global=RFIFOL(fd,2);
      RFIFOSKIP(fd,6);
      break;
    case 0x2b03:
      if(RFIFOREST(fd)<7)
	return 0;
      for(i=0;i<FD_SETSIZE;i++)
	if(session[i] && (sd=session[i]->session_data) && sd->account_id==RFIFOL(fd,2))
	  break;
      if(i!=FD_SETSIZE){
		WFIFOW(i,0)=0xb3;
		WFIFOB(i,2)=1;
		WFIFOSET(i,3);
      }
      RFIFOSKIP(fd,7);
      break;

    default:
      printf("parse_tochar3 close %d %d\n",fd,RFIFOW(fd,0));
      close(fd);
      session[fd]->eof=1;
      return 0;
    }
  }
  return 0;
}

int mmo_map_sendblock(int m,int bx,int by,char *dat,int len,int srcfd,int wos)
{
  struct block_list *bl;
  struct map_session_data *srcsd,*dstsd;
  int fd,c=0;

  if(bx<0 || bx>=map_data[m].bxs ||
     by<0 || by>=map_data[m].bys)
    return 0;
  bl=map_data[m].block[bx + by*map_data[m].bxs].next;
  if(session[srcfd])
    srcsd=session[srcfd]->session_data;
  else
    srcsd=NULL;
  for(;bl;bl=bl->next){
    if(bl->type==BL_PC){
      dstsd=(struct map_session_data *)bl;
      fd=dstsd->fd;
      if(wos && fd == srcfd)
	continue;
      if(wos==2 && dstsd->chatID)
	continue;
      if(wos==3 && srcsd && srcsd->chatID==dstsd->chatID)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?