map2.c

来自「仙镜游戏源码,仅供学习!请勿用于非法应用!」· C语言 代码 · 共 2,351 行 · 第 1/5 页

C
2,351
字号
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/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"
struct mons_data m_data[99999];
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 int base_exp_table[99]={2,5,20,30  ,85,170  ,220  ,300  ,568  ,630  ,697  ,756  ,900  ,1345  ,1615  ,1975  ,2200  ,2535  ,3000  ,3545  ,
4120  ,4670  ,5250  ,6200  ,7125  ,8020  ,8975  ,9900  ,12000  ,13000  ,14000  ,15000  ,16000  ,20000  ,21200  ,
22400  ,23600  ,24800  ,30000  ,31500  ,33000  ,34500  ,36000  ,42000  ,44000  ,46000  ,48000  ,50000  ,60000  ,
63000  ,66000  ,69000  ,72000  ,84000  ,87500  ,91000  ,94500  ,98000  ,102000  ,106500,111000  ,115500  ,120000,
130000  ,135000  ,140000  ,145000  ,150000  ,200000  ,210000  ,220000  ,230000  ,240000  ,250000  ,260000  ,270000  ,
280000  ,290000  ,350000  ,365000  ,380000  ,395000  ,410000  ,425000  ,440000  ,455000  ,470000  ,485000  ,600000  ,
620000  ,640000  ,660000  ,680000  ,800000  ,830000  ,860000  ,890000 };
const int job_exp_table[50]={0,20  ,90  ,150  ,210  ,270  ,350  ,440  ,540  ,650  ,1000  ,1150  ,1350  ,1600  ,1900  ,2250  ,2650  ,3100  ,3600  ,4150  ,
5500  ,6350  ,7300  ,8350  ,9500  ,10750  ,12100  ,13550  ,15100  ,16750  ,20000  ,22000  ,24500  ,27500  ,31500  ,36000  ,
42000  ,48500  ,55500  ,63000  ,70000  ,80000  ,91000  ,102000  ,114000  ,127000  ,141000  ,156000  ,172000  ,200000};

const unsigned short def_aspd[13][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 */
  };


int char_fd;
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;
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];

struct block_list *object[50000];
int first_free_object_id,last_object_id;

void add_block(struct block_list *bl,int m,int x,int y)
{
  struct block_list *head;
  head = &map_data[m].block[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map_data[m].bxs];
  bl->next = head->next;
  bl->prev = head;
  if(bl->next) bl->next->prev = bl;
  head->next = bl;
}

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 earn_base_exp(int waste1,unsigned int waste2,int fd,int exp_earned)
	{
	struct map_session_data *sd;
	int exp;
	int levels=0;
	int status_points=0;
	int i,j;

	sd=session[fd]->session_data;
	exp=sd->status.base_exp;
	exp+=exp_earned;
	while(exp > base_exp_table[sd->status.base_level + levels - 1])
		{
		exp=exp - base_exp_table[sd->status.base_level + levels - 1];
		levels++;
		}
	if(levels)
		{
		/* This isnt working right */
		for(j=1;j<=levels;j++)
			{
			for(i=1;i < 20;i++)
				{
				if(5*i <= sd->status.base_level + j)
					{
					status_points++;
					}
				}
			status_points+=3;
			}
		/* up to here */
		mmo_map_update_param(fd,SP_STATUSPOINT,sd->status.status_point+status_points);
		mmo_map_update_param(fd,SP_BASELEVEL,sd->status.base_level+levels);
		mmo_map_update_param(fd,SP_NEXTBASEEXP,base_exp_table[sd->status.base_level-1]);
		}
	mmo_map_update_param(fd,SP_BASEEXP,exp);
	return levels;
	}

int earn_job_exp(int waste1,unsigned int waste2,int fd,int exp_earned)
	{
	struct map_session_data *sd;
	int exp;
	int levels=0;

	sd=session[fd]->session_data;
	exp=sd->status.job_exp;
	exp+=exp_earned;
	// If joblevel is 10 and no profesion is selected, no job exp will be earned
	if((sd->status.job_level > 9)&&(sd->status.class == 0))
		return 0;
	while(exp > job_exp_table[sd->status.job_level + levels -  1])
		{
		exp=exp - job_exp_table[sd->status.job_level + levels - 1];
		levels++;
		}
	if(levels)
		{
		if( (levels+sd->status.job_level > 9)&&(sd->status.class == 0) )
			{
			mmo_map_update_param(fd,SP_SKILLPOINT,sd->status.skill_point + levels);
			mmo_map_update_param(fd,SP_JOBLEVEL,10);
			mmo_map_update_param(fd,SP_JOBEXP,0);
			mmo_map_update_param(fd,SP_NEXTJOBEXP,1);
			}
		mmo_map_update_param(fd,SP_SKILLPOINT,sd->status.skill_point + levels);
		mmo_map_update_param(fd,SP_JOBLEVEL,sd->status.job_level+levels);
		mmo_map_update_param(fd,SP_NEXTJOBEXP,base_exp_table[sd->status.job_level-1]);
		}
	mmo_map_update_param(fd,SP_JOBEXP,exp);
	return levels;
	}

int do_monster_attack(int tid,unsigned int tick,int monsterid,int fd)

	{
	struct map_session_data *sd;
	int damage;
	int miss;
	int monster_num;
	int monster_class;
	int health[99999];
	int playerid;
	sd=session[fd]->session_data;
	playerid = sd->account_id;
	monster_num = monster_nums[monsterid];
	monster_class = map_data[sd->mapno].npc[monster_num]->class;

if (m_data[monster_class].health_points == 0) {m_data[monster_class].health_points = 1000; }


miss = rand()%7;
	if (miss == 1)
		{
		WFIFOW(fd,0) = 0x8a;
		WFIFOL(fd,2) = monsterid;
		WFIFOL(fd,6) = playerid;
		WFIFOL(fd,10) = tick;
		WFIFOL(fd,14) = 250;
		WFIFOL(fd,18) = 250;
		WFIFOW(fd,22) = 0;
		WFIFOW(fd,24) = 0;
		WFIFOB(fd,26) = 0;
		WFIFOW(fd,27) = 0;
	  	mmo_map_sendarea( fd, WFIFOP(fd,0), packet_len_table[0x8a], 0 );
		}
	else
		{
		WFIFOW(fd,0) = 0x8a;
		WFIFOL(fd,2) = monsterid;
		WFIFOL(fd,6) = playerid;
		WFIFOL(fd,10) = tick;
		WFIFOL(fd,14) = 250;
		WFIFOL(fd,18) = 250;
		WFIFOW(fd,22) = rand()%100;
		WFIFOW(fd,24) = 0;
		WFIFOB(fd,26) = 0;
		WFIFOW(fd,27) = 0;
	 	mmo_map_sendarea( fd, WFIFOP(fd,0), packet_len_table[0x8a], 0 );
		}


	timer_info_m[monsterid]=add_timer(tick+rand()%500+500,do_monster_attack,monsterid,fd);


return 0;
}


int do_attack(int tid,unsigned int tick,int monsterid,int fd)

	{
	struct map_session_data *sd;
	int damage;;
	int miss;
	int monster_num;
	int monster_class;
	int health[99999];
	int playerid;
	sd=session[fd]->session_data;
	playerid = sd->account_id;
	monster_num = monster_nums[monsterid];
	monster_class = map_data[sd->mapno].npc[monster_num]->class;
if(map_data[sd->mapno].npc[monster_num]->u.mons.timer != 0) {delete_timer(map_data[sd->mapno].npc[monster_num]->u.mons.timer); map_data[sd->mapno].npc[monster_num]->u.mons.timer=0; }



if(health[monsterid] < m_data[monster_class].health_points) {
	miss = rand()%7;
	if (miss == 1)
		{
		WFIFOW(fd,0) = 0x8a;
		WFIFOL(fd,2) = playerid;
		WFIFOL(fd,6) = monsterid;
		WFIFOL(fd,10) = tick;
		WFIFOL(fd,14) = 250;
		WFIFOL(fd,18) = 250;
		WFIFOW(fd,22) = 0;
		WFIFOW(fd,24) = 0;
		WFIFOB(fd,26) = 0;
		WFIFOW(fd,27) = 0;
		mmo_map_sendarea( fd, WFIFOP(fd,0), packet_len_table[0x8a], 0 );
		}
	else
		{
		damage = rand()%100;
		WFIFOW(fd,0) = 0x8a;
		WFIFOL(fd,2) = playerid;
		WFIFOL(fd,6) = monsterid;
		WFIFOL(fd,10) = tick;
		WFIFOL(fd,14) = 250;
		WFIFOL(fd,18) = 250;
		WFIFOW(fd,22) = damage;
		WFIFOW(fd,24) = 0;
		WFIFOB(fd,26) = 0;
		WFIFOW(fd,27) = 0;
		mmo_map_sendarea( fd, WFIFOP(fd,0), packet_len_table[0x8a], 0 );
		health[monsterid] = health[monsterid] + damage;

	if((timer_info_m[monsterid] != 0) && (timer_info_mp[monsterid] != playerid)) {
	delete_timer(timer_info_m[monsterid]);
	timer_info_m[monsterid]=0;
	timer_info_m[monsterid]=add_timer(tick+rand()%140+140,do_monster_attack,monsterid,fd);
	timer_info_mp[monsterid] = playerid;
	}
	else if(timer_info_mp[monsterid] == playerid) { }
	else if(timer_info_m[monsterid] == 0) {
	timer_info_m[monsterid]=add_timer(tick+rand()%140+140,do_monster_attack,monsterid,fd);
	timer_info_mp[monsterid] = playerid;
	}
	}
	timer_info_a[playerid]=add_timer(tick+rand()%500+500,do_attack,monsterid,fd);
	
}

		if (health[monsterid] >= m_data[monster_class].health_points)
		{
		if(timer_info_a[playerid] != 0) {delete_timer(timer_info_a[playerid]);  timer_info_a[playerid]=0;}
		if(timer_info_m[monsterid] != 0) {delete_timer(timer_info_m[monsterid]);  timer_info_m[monsterid]=0;}
		WFIFOW(fd,0)=0x80;
		WFIFOL(fd,2)=monsterid;
		WFIFOB(fd,6)=1;	// 1=dead 2=player logout
		mmo_map_sendarea(fd,WFIFOP(fd,0),packet_len_table[0x80], 0 );
		health[monsterid] = 0;
		set_monster_random_point(monster_i[monsterid],monster_num);
		if (m_data[monster_class].move == 1){
		map_data[sd->mapno].npc[monster_num]->u.mons.timer=
		add_timer(gettick()+rand()%5000+5000,mons_walk,monster_i[monsterid],monster_num);
		}
		add_timer(tick+rand()%800+800,earn_base_exp,fd,m_data[monster_class].base_exp);
		add_timer(tick+rand()%1200+1200,earn_job_exp,fd,m_data[monster_class].job_exp);
		//earn_job_exp(fd,m_data[monster_class].job_exp);

		}
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;
  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);
  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;

⌨️ 快捷键说明

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