📄 map.c
字号:
// $Id: map.c,v 1.11 2003/06/29 05:56:44 lemit Exp $
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <netdb.h>
#include "core.h"
#include "timer.h"
#include "db.h"
#include "grfio.h"
#include "map.h"
#include "chrif.h"
#include "clif.h"
#include "intif.h"
#include "npc.h"
#include "pc.h"
#include "mob.h"
#include "chat.h"
#include "itemdb.h"
#include "storage.h"
#include "skill.h"
#include "trade.h"
#include "party.h"
#include "battle.h"
#include "script.h"
#include "guild.h"
#include "pet.h"
#include "atcommand.h"
#ifdef MEMWATCH
#include "memwatch.h"
#endif
// 嬌椡 static偱儘乕僇儖偵廂傔傞
static struct dbt * id_db;
static struct dbt * map_db;
static struct dbt * nick_db;
static struct dbt * charid_db;
static int users;
static struct block_list *object[MAX_FLOORITEM];
static int first_free_object_id,last_object_id;
#define block_free_max 1048576
static void *block_free[block_free_max];
static int block_free_count=0,block_free_lock=0;
#define BL_LIST_MAX 1048576
static struct block_list *bl_list[BL_LIST_MAX];
static int bl_list_count = 0;
struct map_data map[MAX_MAP_PER_SERVER];
int map_num=0;
int autosave_interval=DEFAULT_AUTOSAVE_INTERVAL;
int agit_flag=0;
struct charid2nick {
char nick[24];
int req_id;
};
char motd_txt[256]="conf/motd.txt";
char help_txt[256]="conf/help.txt";
/*==========================================
* 慡map嶪憤寁偱偺愙懕悢愝掕
* (char嶪偐傜憲傜傟偰偔傞)
*------------------------------------------
*/
void map_setusers(int n)
{
users=n;
}
/*==========================================
* 慡map嶪憤寁偱偺愙懕悢庢摼 (/w傊偺墳摎梡)
*------------------------------------------
*/
int map_getusers(void)
{
return users;
}
//
// block嶍彍偺埨慡惈妋曐張棟
//
/*==========================================
* block傪free偡傞偲偒free偺曄傢傝偵屇傇
* 儘僢僋偝傟偰偄傞偲偒偼僶僢僼傽偵偨傔傞
*------------------------------------------
*/
int map_freeblock( void *bl )
{
if(block_free_lock==0)
free(bl);
else{
if( block_free_count>=block_free_max ) {
if(battle_config.error_log)
printf("map_freeblock: *WARNING* too many free block! %d %d\n",
block_free_count,block_free_lock);
}
else
block_free[block_free_count++]=bl;
}
return block_free_lock;
}
/*==========================================
* block偺free傪堦帪揑偵嬛巭偡傞
*------------------------------------------
*/
int map_freeblock_lock(void)
{
return ++block_free_lock;
}
/*==========================================
* block偺free偺儘僢僋傪夝彍偡傞
* 偙偺偲偒丄儘僢僋偑姰慡偵側偔側傞偲
* 僶僢僼傽偵偨傑偭偰偄偨block傪慡晹嶍彍
*------------------------------------------
*/
int map_freeblock_unlock(void)
{
if( (--block_free_lock)==0 ){
int i;
// if(block_free_count>0) {
// if(battle_config.error_log)
// printf("map_freeblock_unlock: free %d object\n",block_free_count);
// }
for(i=0;i<block_free_count;i++)
free(block_free[i]);
block_free_count=0;
}else if(block_free_lock<0){
if(battle_config.error_log)
printf("map_freeblock_unlock: lock count < 0 !\n");
}
return block_free_lock;
}
//
// block壔張棟
//
/*==========================================
* map[]偺block_list偐傜宷偑偭偰偄傞応崌偵
* bl->prev偵bl_head偺傾僪儗僗傪擖傟偰偍偔
*------------------------------------------
*/
static struct block_list bl_head;
/*==========================================
* map[]偺block_list偵捛壛
* mob偼悢偑懡偄偺偱暿儕僗僩
*
* 婛偵link嵪傒偐偺妋擣偑柍偄丅婋尟偐傕
*------------------------------------------
*/
int map_addblock(struct block_list *bl)
{
int m,x,y;
if(bl->prev != NULL){
if(battle_config.error_log)
printf("map_addblock error : bl->prev!=NULL\n");
return 0;
}
m=bl->m;
x=bl->x;
y=bl->y;
if(m<0 || m>=map_num ||
x<0 || x>=map[m].xs ||
y<0 || y>=map[m].ys)
return 1;
if(bl->type==BL_MOB){
bl->next = map[m].block_mob[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs];
bl->prev = &bl_head;
if(bl->next) bl->next->prev = bl;
map[m].block_mob[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs] = bl;
map[m].block_mob_count[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs]++;;
} else {
bl->next = map[m].block[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs];
bl->prev = &bl_head;
if(bl->next) bl->next->prev = bl;
map[m].block[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs] = bl;
map[m].block_count[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs]++;
if(bl->type==BL_PC)
map[m].users++;
}
return 0;
}
/*==========================================
* map[]偺block_list偐傜奜偡
* prev偑NULL偺応崌list偵宷偑偭偰側偄
*------------------------------------------
*/
int map_delblock(struct block_list *bl)
{
// 婛偵blocklist偐傜敳偗偰偄傞
if(bl->prev==NULL){
if(bl->next!=NULL){
// prev偑NULL偱next偑NULL偱側偄偺偼桳偭偰偼側傜側偄
if(battle_config.error_log)
printf("map_delblock error : bl->next!=NULL\n");
}
return 0;
}
if(bl->type==BL_PC)
map[bl->m].users--;
if(bl->next) bl->next->prev = bl->prev;
if(bl->prev==&bl_head){
// 儕僗僩偺摢側偺偱丄map[]偺block_list傪峏怴偡傞
if(bl->type==BL_MOB){
map[bl->m].block_mob[bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map[bl->m].bxs] = bl->next;
if((map[bl->m].block_mob_count[bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map[bl->m].bxs]--) < 0)
map[bl->m].block_mob_count[bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map[bl->m].bxs] = 0;
} else {
map[bl->m].block[bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map[bl->m].bxs] = bl->next;
if((map[bl->m].block_count[bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map[bl->m].bxs]--) < 0)
map[bl->m].block_count[bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map[bl->m].bxs] = 0;
}
} else {
bl->prev->next = bl->next;
}
bl->next = NULL;
bl->prev = NULL;
return 0;
}
/*==========================================
* 廃埻偺PC恖悢傪悢偊傞 (尰嵼枹巊梡)
*------------------------------------------
*/
int map_countnearpc(int m,int x,int y)
{
int bx,by,c=0;
struct block_list *bl;
if(map[m].users==0)
return 0;
for(by=y/BLOCK_SIZE-AREA_SIZE/BLOCK_SIZE-1;by<=y/BLOCK_SIZE+AREA_SIZE/BLOCK_SIZE+1;by++){
if(by<0 || by>=map[m].bys)
continue;
for(bx=x/BLOCK_SIZE-AREA_SIZE/BLOCK_SIZE-1;bx<=x/BLOCK_SIZE+AREA_SIZE/BLOCK_SIZE+1;bx++){
if(bx<0 || bx>=map[m].bxs)
continue;
bl = map[m].block[bx+by*map[m].bxs];
for(;bl;bl=bl->next){
if(bl->type==BL_PC)
c++;
}
}
}
return c;
}
/*==========================================
* map m (x0,y0)-(x1,y1)撪偺慡obj偵懳偟偰
* func傪屇傇
* type!=0 側傜偦偺庬椶偺傒
*------------------------------------------
*/
void map_foreachinarea(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int type,...)
{
int bx,by;
struct block_list *bl;
va_list ap;
int blockcount=bl_list_count,i,c;
va_start(ap,type);
if (x0 < 0) x0 = 0;
if (y0 < 0) y0 = 0;
if (x1 >= map[m].xs) x1 = map[m].xs-1;
if (y1 >= map[m].ys) y1 = map[m].ys-1;
if (type == 0 || type != BL_MOB)
for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) {
for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
bl = map[m].block[bx+by*map[m].bxs];
c = map[m].block_count[bx+by*map[m].bxs];
for(i=0;i<c && bl;i++,bl=bl->next){
if(type && bl->type!=type)
continue;
if(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
bl_list[bl_list_count++]=bl;
}
}
}
if(type==0 || type==BL_MOB)
for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
bl = map[m].block_mob[bx+by*map[m].bxs];
c = map[m].block_mob_count[bx+by*map[m].bxs];
for(i=0;i<c && bl;i++,bl=bl->next){
if(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
bl_list[bl_list_count++]=bl;
}
}
}
if(bl_list_count>=BL_LIST_MAX) {
if(battle_config.error_log)
printf("map_foreachinarea: *WARNING* block count too many!\n");
}
map_freeblock_lock(); // 儊儌儕偐傜偺夝曻傪嬛巭偡傞
for(i=blockcount;i<bl_list_count;i++)
if(bl_list[i]->prev) // 桳岠偐偳偆偐僠僃僢僋
func(bl_list[i],ap);
map_freeblock_unlock(); // 夝曻傪嫋壜偡傞
va_end(ap);
bl_list_count = blockcount;
}
/*==========================================
* 嬮宍(x0,y0)-(x1,y1)偑(dx,dy)堏摦偟偨帪偺
* 椞堟奜偵側傞椞堟(嬮宍偐L帤宍)撪偺obj偵
* 懳偟偰func傪屇傇
*
* dx,dy偼-1,0,1偺傒偲偡傞乮偳傫側抣偱傕偄偄偭傐偄丠乯
*------------------------------------------
*/
void map_foreachinmovearea(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int dx,int dy,int type,...)
{
int bx,by;
struct block_list *bl;
va_list ap;
int blockcount=bl_list_count,i,c;
va_start(ap,type);
if(dx==0 || dy==0){
// 嬮宍椞堟偺応崌
if(dx==0){
if(dy<0){
y0=y1+dy+1;
} else {
y1=y0+dy-1;
}
} else if(dy==0){
if(dx<0){
x0=x1+dx+1;
} else {
x1=x0+dx-1;
}
}
if(x0<0) x0=0;
if(y0<0) y0=0;
if(x1>=map[m].xs) x1=map[m].xs-1;
if(y1>=map[m].ys) y1=map[m].ys-1;
for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
bl = map[m].block[bx+by*map[m].bxs];
c = map[m].block_count[bx+by*map[m].bxs];
for(i=0;i<c && bl;i++,bl=bl->next){
if(type && bl->type!=type)
continue;
if(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
bl_list[bl_list_count++]=bl;
}
bl = map[m].block_mob[bx+by*map[m].bxs];
c = map[m].block_mob_count[bx+by*map[m].bxs];
for(i=0;i<c && bl;i++,bl=bl->next){
if(type && bl->type!=type)
continue;
if(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
bl_list[bl_list_count++]=bl;
}
}
}
}else{
// L帤椞堟偺応崌
if(x0<0) x0=0;
if(y0<0) y0=0;
if(x1>=map[m].xs) x1=map[m].xs-1;
if(y1>=map[m].ys) y1=map[m].ys-1;
for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
bl = map[m].block[bx+by*map[m].bxs];
c = map[m].block_count[bx+by*map[m].bxs];
for(i=0;i<c && bl;i++,bl=bl->next){
if(type && bl->type!=type)
continue;
if(!(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1))
continue;
if(((dx>0 && bl->x<x0+dx) || (dx<0 && bl->x>x1+dx) ||
(dy>0 && bl->y<y0+dy) || (dy<0 && bl->y>y1+dy)) &&
bl_list_count<BL_LIST_MAX)
bl_list[bl_list_count++]=bl;
}
bl = map[m].block_mob[bx+by*map[m].bxs];
c = map[m].block_mob_count[bx+by*map[m].bxs];
for(i=0;i<c && bl;i++,bl=bl->next){
if(type && bl->type!=type)
continue;
if(!(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1))
continue;
if(((dx>0 && bl->x<x0+dx) || (dx<0 && bl->x>x1+dx) ||
(dy>0 && bl->y<y0+dy) || (dy<0 && bl->y>y1+dy)) &&
bl_list_count<BL_LIST_MAX)
bl_list[bl_list_count++]=bl;
}
}
}
}
if(bl_list_count>=BL_LIST_MAX) {
if(battle_config.error_log)
printf("map_foreachinarea: *WARNING* block count too many!\n");
}
map_freeblock_lock(); // 儊儌儕偐傜偺夝曻傪嬛巭偡傞
for(i=blockcount;i<bl_list_count;i++)
if(bl_list[i]->prev) // 桳岠偐偳偆偐僠僃僢僋
func(bl_list[i],ap);
map_freeblock_unlock(); // 夝曻傪嫋壜偡傞
va_end(ap);
bl_list_count = blockcount;
}
/*==========================================
* 彴傾僀僥儉傗僄僼僃僋僩梡偺堦帪obj妱傝摉偰
* object[]傊偺曐懚偲id_db搊榐傑偱
*
* bl->id傕偙偺拞偱愝掕偟偰栤戣柍偄?
*------------------------------------------
*/
int map_addobject(struct block_list *bl)
{
int i;
if(first_free_object_id<2 || first_free_object_id>=MAX_FLOORITEM)
first_free_object_id=2;
for(i=first_free_object_id;i<MAX_FLOORITEM;i++)
if(object[i]==NULL)
break;
if(i>=MAX_FLOORITEM){
if(battle_config.error_log)
printf("no free object id\n");
return 0;
}
first_free_object_id=i;
if(last_object_id<i)
last_object_id=i;
object[i]=bl;
numdb_insert(id_db,i,bl);
return i;
}
/*==========================================
* 堦帪object偺夝曻
* map_delobject偺free偟側偄僶乕僕儑儞
*------------------------------------------
*/
int map_delobjectnofree(int id)
{
if(object[id]==NULL)
return 0;
map_delblock(object[id]);
numdb_erase(id_db,id);
// map_freeblock(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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -