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