diff options
Diffstat (limited to 'src/map/map.c')
-rw-r--r-- | src/map/map.c | 2215 |
1 files changed, 0 insertions, 2215 deletions
diff --git a/src/map/map.c b/src/map/map.c deleted file mode 100644 index d840486..0000000 --- a/src/map/map.c +++ /dev/null @@ -1,2215 +0,0 @@ -// $Id: map.c,v 1.6 2004/09/25 17:37:01 MouseJstr Exp $ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#ifdef LCCWIN32 -#include <winsock.h> -#else -#include <netdb.h> -#endif - -#include "../common/core.h" -#include "../common/timer.h" -#include "../common/db.h" -#include "../common/grfio.h" -#include "../common/mt_rand.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 "atcommand.h" -#include "../common/nullpo.h" -#include "../common/socket.h" -#include "magic.h" - -#ifdef MEMWATCH -#include "memwatch.h" -#endif - -// 極力 staticでローカルに収める -static struct dbt *id_db = NULL; -static struct dbt *map_db = NULL; -static struct dbt *nick_db = NULL; -static struct dbt *charid_db = NULL; - -static int users = 0; -static struct block_list *object[MAX_FLOORITEM]; -static int first_free_object_id = 0, last_object_id = 0; - -#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 map_port = 0; - -int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; -int save_settings = 0xFFFF; -int agit_flag = 0; -int night_flag = 0; // 0=day, 1=night [Yor] - -struct charid2nick -{ - char nick[24]; - int req_id; -}; - -char motd_txt[256] = "conf/motd.txt"; -char help_txt[256] = "conf/help.txt"; - -char wisp_server_name[24] = "Server"; // can be modified in char-server configuration file - -/*========================================== - * 全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); - bl = NULL; - } - 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[i] = NULL; - } - 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; - - nullpo_retr (0, bl); - - 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) -{ - int b; - nullpo_retr (0, 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; - } - - b = bl->x / BLOCK_SIZE + (bl->y / BLOCK_SIZE) * map[bl->m].bxs; - - 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[b] = bl->next; - if ((map[bl->m].block_mob_count[b]--) < 0) - map[bl->m].block_mob_count[b] = 0; - } - else - { - map[bl->m].block[b] = bl->next; - if ((map[bl->m].block_count[b]--) < 0) - map[bl->m].block_count[b] = 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 = NULL; - - 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; -} - -/*========================================== - * セル上のPCとMOBの数を数える (グランドクロス用) - *------------------------------------------ - */ -int map_count_oncell (int m, int x, int y) -{ - int bx, by; - struct block_list *bl = NULL; - int i, c; - int count = 0; - - if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys)) - return 1; - bx = x / BLOCK_SIZE; - by = y / BLOCK_SIZE; - - 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 (bl->x == x && bl->y == y && bl->type == BL_PC) - count++; - } - 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 == x && bl->y == y) - count++; - } - if (!count) - count = 1; - return count; -} - -/*========================================== - * 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 = NULL; - va_list ap = NULL; - int blockcount = bl_list_count, i, c; - - if (m < 0) - return; - 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 (bl && type && bl->type != type) - continue; - if (bl && 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 && 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 = NULL; - va_list ap = NULL; - 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 (bl && type && bl->type != type) - continue; - if (bl && 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 (bl && type && bl->type != type) - continue; - if (bl && 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 (bl && type && bl->type != type) - continue; - if ((bl) - && !(bl->x >= x0 && bl->x <= x1 && bl->y >= y0 - && bl->y <= y1)) - continue; - if ((bl) - && ((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 (bl && type && bl->type != type) - continue; - if ((bl) - && !(bl->x >= x0 && bl->x <= x1 && bl->y >= y0 - && bl->y <= y1)) - continue; - if ((bl) - && ((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; -} - -// -- moonsoul (added map_foreachincell which is a rework of map_foreachinarea but -// which only checks the exact single x/y passed to it rather than an -// area radius - may be more useful in some instances) -// -void map_foreachincell (int (*func) (struct block_list *, va_list), int m, - int x, int y, int type, ...) -{ - int bx, by; - struct block_list *bl = NULL; - va_list ap = NULL; - int blockcount = bl_list_count, i, c; - - va_start (ap, type); - - by = y / BLOCK_SIZE; - bx = x / BLOCK_SIZE; - - if (type == 0 || type != BL_MOB) - { - 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 && bl->type != type) - continue; - if (bl && bl->x == x && bl->y == y && bl_list_count < BL_LIST_MAX) - bl_list[bl_list_count++] = bl; - } - } - - if (type == 0 || type == BL_MOB) - { - 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 && bl->x == x && bl->y == y && 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_foreachincell: *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 (bl == NULL) - { - printf ("map_addobject nullpo?\n"); - return 0; - } - 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, int type) -{ - if (object[id] == NULL) - return 0; - - if (object[id]->type != type) - { - fprintf (stderr, "Incorrect type: expected %d, got %d\n", type, - object[id]->type); - *((char *) 0) = 0; // break for backtrace - } - - 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) - last_object_id--; - - return 0; -} - -/*========================================== - * 一時objectの解放 - * block_listからの削除、id_dbからの削除 - * object dataのfree、object[]へのNULL代入 - * - * addとの対称性が無いのが気になる - *------------------------------------------ - */ -int map_delobject (int id, int type) -{ - struct block_list *obj = object[id]; - - if (obj == NULL) - return 0; - - map_delobjectnofree (id, type); - if (obj->type == BL_PC) // [Fate] Not sure where else to put this... I'm not sure where delobject for PCs is called from - pc_cleanup ((struct map_session_data *) obj); - - map_freeblock (obj); - - return 0; -} - -/*========================================== - * 全一時obj相手にfuncを呼ぶ - * - *------------------------------------------ - */ -void map_foreachobject (int (*func) (struct block_list *, va_list), int type, - ...) -{ - int i; - int blockcount = bl_list_count; - va_list ap = NULL; - - va_start (ap, type); - - for (i = 2; i <= last_object_id; i++) - { - if (object[i]) - { - if (type && object[i]->type != type) - continue; - if (bl_list_count >= BL_LIST_MAX) - { - if (battle_config.error_log) - printf ("map_foreachobject: too many block !\n"); - } - else - bl_list[bl_list_count++] = object[i]; - } - } - - map_freeblock_lock (); - - for (i = blockcount; i < bl_list_count; i++) - if (bl_list[i]->prev || bl_list[i]->next) - func (bl_list[i], ap); - - map_freeblock_unlock (); - - va_end (ap); - bl_list_count = blockcount; -} - -/*========================================== - * 床アイテムを消す - * - * data==0の時はtimerで消えた時 - * data!=0の時は拾う等で消えた時として動作 - * - * 後者は、map_clearflooritem(id)へ - * map.h内で#defineしてある - *------------------------------------------ - */ -void map_clearflooritem_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data) -{ - struct flooritem_data *fitem = NULL; - - fitem = (struct flooritem_data *) object[id]; - if (fitem == NULL || fitem->bl.type != BL_ITEM - || (!data && fitem->cleartimer != tid)) - { - if (battle_config.error_log) - printf ("map_clearflooritem_timer : error\n"); - return; - } - if (data) - delete_timer (fitem->cleartimer, map_clearflooritem_timer); - clif_clearflooritem (fitem, 0); - map_delobject (fitem->bl.id, BL_ITEM); -} - -/*========================================== - * (m,x,y)の周囲rangeマス内の空き(=侵入可能)cellの - * 内から適当なマス目の座標をx+(y<<16)で返す - * - * 現状range=1でアイテムドロップ用途のみ - *------------------------------------------ - */ -int map_searchrandfreecell (int m, int x, int y, int range) -{ - int free_cell, i, j, c; - - for (free_cell = 0, i = -range; i <= range; i++) - { - if (i + y < 0 || i + y >= map[m].ys) - continue; - for (j = -range; j <= range; j++) - { - if (j + x < 0 || j + x >= map[m].xs) - continue; - if ((c = read_gat (m, j + x, i + y)) == 1 || c == 5) - continue; - free_cell++; - } - } - if (free_cell == 0) - return -1; - free_cell = MRAND (free_cell); - for (i = -range; i <= range; i++) - { - if (i + y < 0 || i + y >= map[m].ys) - continue; - for (j = -range; j <= range; j++) - { - if (j + x < 0 || j + x >= map[m].xs) - continue; - if ((c = read_gat (m, j + x, i + y)) == 1 || c == 5) - continue; - if (free_cell == 0) - { - x += j; - y += i; - i = range + 1; - break; - } - free_cell--; - } - } - - return x + (y << 16); -} - -/*========================================== - * (m,x,y)を中心に3x3以内に床アイテム設置 - * - * item_dataはamount以外をcopyする - *------------------------------------------ - */ -int map_addflooritem_any (struct item *item_data, int amount, int m, int x, - int y, struct map_session_data **owners, - int *owner_protection, int lifetime, int dispersal) -{ - int xy, r; - unsigned int tick; - struct flooritem_data *fitem = NULL; - - nullpo_retr (0, item_data); - - if ((xy = map_searchrandfreecell (m, x, y, dispersal)) < 0) - return 0; - r = mt_random (); - - CREATE (fitem, struct flooritem_data, 1); - fitem->bl.type = BL_ITEM; - fitem->bl.prev = fitem->bl.next = NULL; - fitem->bl.m = m; - fitem->bl.x = xy & 0xffff; - fitem->bl.y = (xy >> 16) & 0xffff; - fitem->first_get_id = 0; - fitem->first_get_tick = 0; - fitem->second_get_id = 0; - fitem->second_get_tick = 0; - fitem->third_get_id = 0; - fitem->third_get_tick = 0; - - fitem->bl.id = map_addobject (&fitem->bl); - if (fitem->bl.id == 0) - { - free (fitem); - return 0; - } - - tick = gettick (); - - if (owners[0]) - fitem->first_get_id = owners[0]->bl.id; - fitem->first_get_tick = tick + owner_protection[0]; - - if (owners[1]) - fitem->second_get_id = owners[1]->bl.id; - fitem->second_get_tick = tick + owner_protection[1]; - - if (owners[2]) - fitem->third_get_id = owners[2]->bl.id; - fitem->third_get_tick = tick + owner_protection[2]; - - memcpy (&fitem->item_data, item_data, sizeof (*item_data)); - fitem->item_data.amount = amount; - fitem->subx = (r & 3) * 3 + 3; - fitem->suby = ((r >> 2) & 3) * 3 + 3; - fitem->cleartimer = - add_timer (gettick () + lifetime, map_clearflooritem_timer, - fitem->bl.id, 0); - - map_addblock (&fitem->bl); - clif_dropflooritem (fitem); - - return fitem->bl.id; -} - -int map_addflooritem (struct item *item_data, int amount, int m, int x, int y, - struct map_session_data *first_sd, - struct map_session_data *second_sd, - struct map_session_data *third_sd, int type) -{ - struct map_session_data *owners[3] = { first_sd, second_sd, third_sd }; - int owner_protection[3]; - - if (type) - { - owner_protection[0] = battle_config.mvp_item_first_get_time; - owner_protection[1] = - owner_protection[0] + battle_config.mvp_item_second_get_time; - owner_protection[2] = - owner_protection[1] + battle_config.mvp_item_third_get_time; - } - else - { - owner_protection[0] = battle_config.item_first_get_time; - owner_protection[1] = - owner_protection[0] + battle_config.item_second_get_time; - owner_protection[2] = - owner_protection[1] + battle_config.item_third_get_time; - } - - return map_addflooritem_any (item_data, amount, m, x, y, - owners, owner_protection, - battle_config.flooritem_lifetime, 1); -} - -/* int xy,r; */ -/* unsigned int tick; */ -/* struct flooritem_data *fitem=NULL; */ - -/* nullpo_retr(0, item_data); */ - -/* if((xy=map_searchrandfreecell(m,x,y,1))<0) */ -/* return 0; */ -/* r=rand(); */ - -/* fitem = (struct flooritem_data *)aCalloc(1,sizeof(*fitem)); */ -/* fitem->bl.type=BL_ITEM; */ -/* fitem->bl.prev = fitem->bl.next = NULL; */ -/* fitem->bl.m=m; */ -/* fitem->bl.x=xy&0xffff; */ -/* fitem->bl.y=(xy>>16)&0xffff; */ -/* fitem->first_get_id = 0; */ -/* fitem->first_get_tick = 0; */ -/* fitem->second_get_id = 0; */ -/* fitem->second_get_tick = 0; */ -/* fitem->third_get_id = 0; */ -/* fitem->third_get_tick = 0; */ - -/* fitem->bl.id = map_addobject(&fitem->bl); */ -/* if(fitem->bl.id==0){ */ -/* free(fitem); */ -/* return 0; */ -/* } */ - -/* tick = gettick(); */ -/* if(first_sd) { */ -/* fitem->first_get_id = first_sd->bl.id; */ -/* if(type) */ -/* fitem->first_get_tick = tick + battle_config.mvp_item_first_get_time; */ -/* else */ -/* fitem->first_get_tick = tick + battle_config.item_first_get_time; */ -/* } */ -/* if(second_sd) { */ -/* fitem->second_get_id = second_sd->bl.id; */ -/* if(type) */ -/* fitem->second_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time; */ -/* else */ -/* fitem->second_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time; */ -/* } */ -/* if(third_sd) { */ -/* fitem->third_get_id = third_sd->bl.id; */ -/* if(type) */ -/* fitem->third_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time + battle_config.mvp_item_third_get_time; */ -/* else */ -/* fitem->third_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time + battle_config.item_third_get_time; */ -/* } */ - -/* memcpy(&fitem->item_data,item_data,sizeof(*item_data)); */ -/* fitem->item_data.amount=amount; */ -/* fitem->subx=(r&3)*3+3; */ -/* fitem->suby=((r>>2)&3)*3+3; */ -/* fitem->cleartimer=add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0); */ - -/* map_addblock(&fitem->bl); */ -/* clif_dropflooritem(fitem); */ - -/* return fitem->bl.id; */ -/* } */ - -/*========================================== - * charid_dbへ追加(返信待ちがあれば返信) - *------------------------------------------ - */ -void map_addchariddb (int charid, char *name) -{ - struct charid2nick *p = (struct charid2nick *)numdb_search (charid_db, charid); - if (p == NULL) - { // データベースにない - CREATE (p, struct charid2nick, 1); - p->req_id = 0; - } - else - numdb_erase (charid_db, charid); - - int req = p->req_id; - memcpy (p->nick, name, 24); - p->req_id = 0; - numdb_insert (charid_db, charid, p); - if (req) - { // 返信待ちがあれば返信 - struct map_session_data *sd = map_id2sd (req); - if (sd != NULL) - clif_solved_charname (sd, charid); - } -} - -/*========================================== - * charid_dbへ追加(返信要求のみ) - *------------------------------------------ - */ -int map_reqchariddb (struct map_session_data *sd, int charid) -{ - nullpo_retr (0, sd); - - struct charid2nick *p = (struct charid2nick *)numdb_search (charid_db, charid); - if (p != NULL) // データベースにすでにある - return 0; - CREATE (p, struct charid2nick, 1); - p->req_id = sd->bl.id; - numdb_insert (charid_db, charid, p); - return 0; -} - -/*========================================== - * id_dbへblを追加 - *------------------------------------------ - */ -void map_addiddb (struct block_list *bl) -{ - nullpo_retv (bl); - - numdb_insert (id_db, bl->id, bl); -} - -/*========================================== - * id_dbからblを削除 - *------------------------------------------ - */ -void map_deliddb (struct block_list *bl) -{ - nullpo_retv (bl); - - numdb_erase (id_db, bl->id); -} - -/*========================================== - * nick_dbへsdを追加 - *------------------------------------------ - */ -void map_addnickdb (struct map_session_data *sd) -{ - nullpo_retv (sd); - - strdb_insert (nick_db, sd->status.name, sd); -} - -/*========================================== - * PCのquit処理 map.c内分 - * - * quit処理の主体が違うような気もしてきた - *------------------------------------------ - */ -int map_quit (struct map_session_data *sd) -{ - nullpo_retr (0, sd); - - if (sd->chatID) // チャットから出る - chat_leavechat (sd); - - if (sd->trade_partner) // 取引を中断する - trade_tradecancel (sd); - - if (sd->party_invite > 0) // パーティ勧誘を拒否する - party_reply_invite (sd, sd->party_invite_account, 0); - - if (sd->guild_invite > 0) // ギルド勧誘を拒否する - guild_reply_invite (sd, sd->guild_invite, 0); - if (sd->guild_alliance > 0) // ギルド同盟勧誘を拒否する - guild_reply_reqalliance (sd, sd->guild_alliance_account, 0); - - party_send_logout (sd); // パーティのログアウトメッセージ送信 - - guild_send_memberinfoshort (sd, 0); // ギルドのログアウトメッセージ送信 - - pc_cleareventtimer (sd); // イベントタイマを破棄する - - skill_castcancel (&sd->bl, 0); // 詠唱を中断する - skill_stop_dancing (&sd->bl, 1); // ダンス/演奏中断 - - if (sd->sc_data && sd->sc_data[SC_BERSERK].timer != -1) //バーサーク中の終了はHPを100に - sd->status.hp = 100; - - skill_status_change_clear (&sd->bl, 1); // ステータス異常を解除する - skill_clear_unitgroup (&sd->bl); // スキルユニットグループの削除 - skill_cleartimerskill (&sd->bl); - pc_stop_walking (sd, 0); - pc_stopattack (sd); - pc_delinvincibletimer (sd); - pc_delspiritball (sd, sd->spiritball, 1); - skill_gangsterparadise (sd, 0); - - pc_calcstatus (sd, 4); - - clif_clearchar_area (&sd->bl, 2); - - if (pc_isdead (sd)) - pc_setrestartvalue (sd, 2); - pc_makesavestatus (sd); - //クローンスキルで覚えたスキルは消す - - //The storage closing routines will save the char if needed. [Skotlex] - if (!sd->state.storage_flag) - chrif_save (sd); - else if (sd->state.storage_flag == 1) - storage_storage_quit (sd); - else if (sd->state.storage_flag == 2) - storage_guild_storage_quit (sd, 1); - - if (sd->npc_stackbuf && sd->npc_stackbuf != NULL) - free (sd->npc_stackbuf); - - map_delblock (&sd->bl); - - numdb_erase (id_db, sd->bl.id); - strdb_erase (nick_db, sd->status.name); - numdb_erase (charid_db, sd->status.char_id); - - return 0; -} - -/*========================================== - * id番号のPCを探す。居なければNULL - *------------------------------------------ - */ -struct map_session_data *map_id2sd (int id) -{ -// remove search from db, because: -// 1 - all players, npc, items and mob are in this db (to search, it's not speed, and search in session is more sure) -// 2 - DB seems not always correct. Sometimes, when a player disconnects, its id (account value) is not removed and structure -// point to a memory area that is not more a session_data and value are incorrect (or out of available memory) -> crash -// replaced by searching in all session. -// by searching in session, we are sure that fd, session, and account exist. -/* - struct block_list *bl; - - bl=numdb_search(id_db,id); - if(bl && bl->type==BL_PC) - return (struct map_session_data*)bl; - return NULL; -*/ - int i; - struct map_session_data *sd = NULL; - - for (i = 0; i < fd_max; i++) - if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->bl.id == id) - return sd; - - return NULL; -} - -/*========================================== - * char_id番号の名前を探す - *------------------------------------------ - */ -char *map_charid2nick (int id) -{ - struct charid2nick *p = (struct charid2nick *)numdb_search (charid_db, id); - - if (p == NULL) - return NULL; - if (p->req_id != 0) - return NULL; - return p->nick; -} - -/*========================================*/ -/* [Fate] Operations to iterate over active map sessions */ - -static struct map_session_data *map_get_session (int i) -{ - struct map_session_data *d; - - if (i >= 0 && i < fd_max - && session[i] && (d = (struct map_session_data *)session[i]->session_data) && d->state.auth) - return d; - - return NULL; -} - -static struct map_session_data *map_get_session_forward (int start) -{ - int i; - for (i = start; i < fd_max; i++) - { - struct map_session_data *d = map_get_session (i); - if (d) - return d; - } - - return NULL; -} - -static struct map_session_data *map_get_session_backward (int start) -{ - int i; - for (i = start; i >= 0; i--) - { - struct map_session_data *d = map_get_session (i); - if (d) - return d; - } - - return NULL; -} - -struct map_session_data *map_get_first_session (void) -{ - return map_get_session_forward (0); -} - -struct map_session_data *map_get_next_session (struct map_session_data *d) -{ - return map_get_session_forward (d->fd + 1); -} - -struct map_session_data *map_get_last_session (void) -{ - return map_get_session_backward (fd_max); -} - -struct map_session_data *map_get_prev_session (struct map_session_data *d) -{ - return map_get_session_backward (d->fd - 1); -} - -/*========================================== - * Search session data from a nick name - * (without sensitive case if necessary) - * return map_session_data pointer or NULL - *------------------------------------------ - */ -struct map_session_data *map_nick2sd (char *nick) -{ - int i, quantity = 0, nicklen; - struct map_session_data *sd = NULL; - struct map_session_data *pl_sd = NULL; - - if (nick == NULL) - return NULL; - - nicklen = strlen (nick); - - for (i = 0; i < fd_max; i++) - { - if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data) - && pl_sd->state.auth) - { - // Without case sensitive check (increase the number of similar character names found) - if (strncasecmp (pl_sd->status.name, nick, nicklen) == 0) - { - // Strict comparison (if found, we finish the function immediatly with correct value) - if (strcmp (pl_sd->status.name, nick) == 0) - return pl_sd; - quantity++; - sd = pl_sd; - } - } - } - // Here, the exact character name is not found - // We return the found index of a similar account ONLY if there is 1 similar character - if (quantity == 1) - return sd; - - // Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found - return NULL; -} - -/*========================================== - * id番号の物を探す - * 一時objectの場合は配列を引くのみ - *------------------------------------------ - */ -struct block_list *map_id2bl (int id) -{ - struct block_list *bl = NULL; - if (id < sizeof (object) / sizeof (object[0])) - bl = object[id]; - else - bl = (struct block_list *)numdb_search (id_db, id); - - return bl; -} - -/*========================================== - * id_db内の全てにfuncを実行 - *------------------------------------------ - */ -int map_foreachiddb (db_func_t func, ...) -{ - va_list ap = NULL; - - va_start (ap, func); - numdb_foreach (id_db, func, ap); - va_end (ap); - return 0; -} - -/*========================================== - * map.npcへ追加 (warp等の領域持ちのみ) - *------------------------------------------ - */ -int map_addnpc (int m, struct npc_data *nd) -{ - int i; - if (m < 0 || m >= map_num) - return -1; - for (i = 0; i < map[m].npc_num && i < MAX_NPC_PER_MAP; i++) - if (map[m].npc[i] == NULL) - break; - if (i == MAX_NPC_PER_MAP) - { - if (battle_config.error_log) - printf ("too many NPCs in one map %s\n", map[m].name); - return -1; - } - if (i == map[m].npc_num) - { - map[m].npc_num++; - } - - nullpo_retr (0, nd); - - map[m].npc[i] = nd; - nd->n = i; - numdb_insert (id_db, nd->bl.id, nd); - - return i; -} - -void map_removenpc (void) -{ - int i, m, n = 0; - - for (m = 0; m < map_num; m++) - { - for (i = 0; i < map[m].npc_num && i < MAX_NPC_PER_MAP; i++) - { - if (map[m].npc[i] != NULL) - { - clif_clearchar_area (&map[m].npc[i]->bl, 2); - map_delblock (&map[m].npc[i]->bl); - numdb_erase (id_db, map[m].npc[i]->bl.id); - if (map[m].npc[i]->bl.subtype == SCRIPT) - { -// free(map[m].npc[i]->u.scr.script); -// free(map[m].npc[i]->u.scr.label_list); - } - free (map[m].npc[i]); - map[m].npc[i] = NULL; - n++; - } - } - } - printf ("%d NPCs removed.\n", n); -} - -/*========================================== - * map名からmap番号へ変換 - *------------------------------------------ - */ -int map_mapname2mapid (char *name) -{ - struct map_data *md = (struct map_data *)strdb_search (map_db, name); - if (md == NULL || md->gat == NULL) - return -1; - return md->m; -} - -/*========================================== - * 他鯖map名からip,port変換 - *------------------------------------------ - */ -int map_mapname2ipport (char *name, int *ip, int *port) -{ - struct map_data_other_server *mdos = (struct map_data_other_server *)strdb_search (map_db, name); - if (mdos == NULL || mdos->gat) - return -1; - *ip = mdos->ip; - *port = mdos->port; - return 0; -} - -/*========================================== - * - *------------------------------------------ - */ -int map_check_dir (int s_dir, int t_dir) -{ - if (s_dir == t_dir) - return 0; - switch (s_dir) - { - case 0: - if (t_dir == 7 || t_dir == 1 || t_dir == 0) - return 0; - break; - case 1: - if (t_dir == 0 || t_dir == 2 || t_dir == 1) - return 0; - break; - case 2: - if (t_dir == 1 || t_dir == 3 || t_dir == 2) - return 0; - break; - case 3: - if (t_dir == 2 || t_dir == 4 || t_dir == 3) - return 0; - break; - case 4: - if (t_dir == 3 || t_dir == 5 || t_dir == 4) - return 0; - break; - case 5: - if (t_dir == 4 || t_dir == 6 || t_dir == 5) - return 0; - break; - case 6: - if (t_dir == 5 || t_dir == 7 || t_dir == 6) - return 0; - break; - case 7: - if (t_dir == 6 || t_dir == 0 || t_dir == 7) - return 0; - break; - } - return 1; -} - -/*========================================== - * 彼我の方向を計算 - *------------------------------------------ - */ -int map_calc_dir (struct block_list *src, int x, int y) -{ - int dir = 0; - int dx, dy; - - nullpo_retr (0, src); - - dx = x - src->x; - dy = y - src->y; - if (dx == 0 && dy == 0) - { // 彼我の場所一致 - dir = 0; // 上 - } - else if (dx >= 0 && dy >= 0) - { // 方向的に右上 - dir = 7; // 右上 - if (dx * 3 - 1 < dy) - dir = 0; // 上 - if (dx > dy * 3) - dir = 6; // 右 - } - else if (dx >= 0 && dy <= 0) - { // 方向的に右下 - dir = 5; // 右下 - if (dx * 3 - 1 < -dy) - dir = 4; // 下 - if (dx > -dy * 3) - dir = 6; // 右 - } - else if (dx <= 0 && dy <= 0) - { // 方向的に左下 - dir = 3; // 左下 - if (dx * 3 + 1 > dy) - dir = 4; // 下 - if (dx < dy * 3) - dir = 2; // 左 - } - else - { // 方向的に左上 - dir = 1; // 左上 - if (-dx * 3 - 1 < dy) - dir = 0; // 上 - if (-dx > dy * 3) - dir = 2; // 左 - } - return dir; -} - -// gat系 -/*========================================== - * (m,x,y)の状態を調べる - *------------------------------------------ - */ -int map_getcell (int m, int x, int y) -{ - if (x < 0 || x >= map[m].xs - 1 || y < 0 || y >= map[m].ys - 1) - return 1; - return map[m].gat[x + y * map[m].xs]; -} - -/*========================================== - * (m,x,y)の状態をtにする - *------------------------------------------ - */ -int map_setcell (int m, int x, int y, int t) -{ - if (x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys) - return t; - return map[m].gat[x + y * map[m].xs] = t; -} - -/*========================================== - * 他鯖管理のマップをdbに追加 - *------------------------------------------ - */ -int map_setipport (char *name, unsigned long ip, int port) -{ - struct map_data_other_server *mdos = NULL; - - struct map_data *md = (struct map_data *)strdb_search (map_db, name); - if (md == NULL) - { // not exist -> add new data - CREATE (mdos, struct map_data_other_server, 1); - memcpy (mdos->name, name, 24); - mdos->gat = NULL; - mdos->ip = ip; - mdos->port = port; - strdb_insert (map_db, mdos->name, mdos); - } - else - { - if (md->gat) - { // local -> check data - if (ip != clif_getip () || port != clif_getport ()) - { - printf ("from char server : %s -> %08lx:%d\n", name, ip, - port); - return 1; - } - } - else - { // update - mdos = (struct map_data_other_server *) md; - mdos->ip = ip; - mdos->port = port; - } - } - return 0; -} - -// 初期化周り -/*========================================== - * 水場高さ設定 - *------------------------------------------ - */ -static struct Waterlist -{ - char mapname[24]; - int waterheight; -} *waterlist = NULL; - -#define NO_WATER 1000000 - -static int map_waterheight (char *mapname) -{ - if (waterlist) - { - int i; - for (i = 0; waterlist[i].mapname[0] && i < MAX_MAP_PER_SERVER; i++) - if (strcmp (waterlist[i].mapname, mapname) == 0) - return waterlist[i].waterheight; - } - return NO_WATER; -} - -static void map_readwater (char *watertxt) -{ - char line[1024], w1[1024]; - FILE *fp = NULL; - int n = 0; - - fp = fopen_ (watertxt, "r"); - if (fp == NULL) - { - printf ("file not found: %s\n", watertxt); - return; - } - if (waterlist == NULL) - { - CREATE (waterlist, struct Waterlist, MAX_MAP_PER_SERVER); - } - while (fgets (line, 1020, fp) && n < MAX_MAP_PER_SERVER) - { - int wh, count; - if (line[0] == '/' && line[1] == '/') - continue; - if ((count = sscanf (line, "%s%d", w1, &wh)) < 1) - { - continue; - } - strcpy (waterlist[n].mapname, w1); - if (count >= 2) - waterlist[n].waterheight = wh; - else - waterlist[n].waterheight = 3; - n++; - } - fclose_ (fp); -} - -/*========================================== - * マップ1枚読み込み - *------------------------------------------ - */ -static int map_readmap (int m, char *fn, char *alias) -{ - int s; - int x, y, xs, ys; - struct gat_1cell - { - char type; - } *p; - int wh; - size_t size; - - // read & convert fn - uint8_t *gat = (uint8_t *)grfio_read (fn); - if (gat == NULL) - return -1; - - printf ("\rLoading Maps [%d/%d]: %-50s ", m, map_num, fn); - fflush (stdout); - - map[m].m = m; - xs = map[m].xs = *(short *) (gat); - ys = map[m].ys = *(short *) (gat + 2); - printf ("\n%i %i\n", xs, ys); - map[m].gat = (uint8_t *)calloc (s = map[m].xs * map[m].ys, 1); - if (map[m].gat == NULL) - { - printf ("out of memory : map_readmap gat\n"); - exit (1); - } - - map[m].npc_num = 0; - map[m].users = 0; - memset (&map[m].flag, 0, sizeof (map[m].flag)); - if (battle_config.pk_mode) - map[m].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris] - wh = map_waterheight (map[m].name); - for (y = 0; y < ys; y++) - { - p = (struct gat_1cell *) (gat + y * xs + 4); - for (x = 0; x < xs; x++) - { - /*if(wh!=NO_WATER && p->type==0){ - * // 水場判定 - * map[m].gat[x+y*xs]=(p->high[0]>wh || p->high[1]>wh || p->high[2]>wh || p->high[3]>wh) ? 3 : 0; - * } else { */ - map[m].gat[x + y * xs] = p->type; - //} - p++; - } - } - free (gat); - - map[m].bxs = (xs + BLOCK_SIZE - 1) / BLOCK_SIZE; - map[m].bys = (ys + BLOCK_SIZE - 1) / BLOCK_SIZE; - size = map[m].bxs * map[m].bys; - - CREATE (map[m].block, struct block_list *, size); - - CREATE (map[m].block_mob, struct block_list *, size); - - CREATE (map[m].block_count, int, size); - - CREATE (map[m].block_mob_count, int, size); - - strdb_insert (map_db, map[m].name, &map[m]); - -// printf("%s read done\n",fn); - - return 0; -} - -/*========================================== - * 全てのmapデータを読み込む - *------------------------------------------ - */ -int map_readallmap (void) -{ - int i, maps_removed = 0; - char fn[256] = ""; - - // 先に全部のャbプの存在を確認 - for (i = 0; i < map_num; i++) - { - if (strstr (map[i].name, ".gat") == NULL) - continue; - sprintf (fn, "data\\%s", map[i].name); - // TODO - remove this, it is the last call to grfio_size, which is deprecated - if (!grfio_size (fn)) - { - map_delmap (map[i].name); - maps_removed++; - } - } - for (i = 0; i < map_num; i++) - { - if (strstr (map[i].name, ".gat") != NULL) - { - char *p = strstr (map[i].name, ">"); // [MouseJstr] - if (p != NULL) - { - char alias[64]; - *p = '\0'; - strcpy (alias, map[i].name); - strcpy (map[i].name, p + 1); - sprintf (fn, "data\\%s", map[i].name); - if (map_readmap (i, fn, alias) == -1) - { - map_delmap (map[i].name); - maps_removed++; - } - } - else - { - sprintf (fn, "data\\%s", map[i].name); - if (map_readmap (i, fn, NULL) == -1) - { - map_delmap (map[i].name); - maps_removed++; - } - } - } - } - - free (waterlist); - printf ("\rMaps Loaded: %d %60s\n", map_num, ""); - printf ("\rMaps Removed: %d \n", maps_removed); - return 0; -} - -/*========================================== - * 読み込むmapを追加する - *------------------------------------------ - */ -int map_addmap (char *mapname) -{ - if (strcasecmp (mapname, "clear") == 0) - { - map_num = 0; - return 0; - } - - if (map_num >= MAX_MAP_PER_SERVER - 1) - { - printf ("too many map\n"); - return 1; - } - memcpy (map[map_num].name, mapname, 24); - map_num++; - return 0; -} - -/*========================================== - * 読み込むmapを削除する - *------------------------------------------ - */ -int map_delmap (char *mapname) -{ - int i; - - if (strcasecmp (mapname, "all") == 0) - { - map_num = 0; - return 0; - } - - for (i = 0; i < map_num; i++) - { - if (strcmp (map[i].name, mapname) == 0) - { - printf ("Removing map [ %s ] from maplist\n", map[i].name); - memmove (map + i, map + i + 1, - sizeof (map[0]) * (map_num - i - 1)); - map_num--; - } - } - return 0; -} - -extern char *gm_logfile_name; - -#define LOGFILE_SECONDS_PER_CHUNK_SHIFT 10 - -FILE *map_logfile = NULL; -char *map_logfile_name = NULL; -static long map_logfile_index; - -static void map_close_logfile (void) -{ - if (map_logfile) - { - char *filenameop_buf = (char*)malloc (strlen (map_logfile_name) + 50); - sprintf (filenameop_buf, "gzip -f %s.%ld", map_logfile_name, - map_logfile_index); - - fclose (map_logfile); - - if (!system (filenameop_buf)) - perror (filenameop_buf); - - free (filenameop_buf); - } -} - -static void map_start_logfile (long suffix) -{ - char *filename_buf = (char*)malloc (strlen (map_logfile_name) + 50); - map_logfile_index = suffix >> LOGFILE_SECONDS_PER_CHUNK_SHIFT; - - sprintf (filename_buf, "%s.%ld", map_logfile_name, map_logfile_index); - map_logfile = fopen (filename_buf, "w+"); - if (!map_logfile) - perror (map_logfile_name); - - free (filename_buf); -} - -static void map_set_logfile (char *filename) -{ - struct timeval tv; - - map_logfile_name = strdup (filename); - gettimeofday (&tv, NULL); - - map_start_logfile (tv.tv_sec); - - MAP_LOG ("log-start v3"); -} - -void map_write_log (char *format, ...) -{ - struct timeval tv; - va_list args; - va_start (args, format); - - gettimeofday (&tv, NULL); - - if ((tv.tv_sec >> LOGFILE_SECONDS_PER_CHUNK_SHIFT) != map_logfile_index) - { - map_close_logfile (); - map_start_logfile (tv.tv_sec); - } - - fprintf (map_logfile, "%ld.%06ld ", (long) tv.tv_sec, (long) tv.tv_usec); - vfprintf (map_logfile, format, args); - fputc ('\n', map_logfile); -} - -/*========================================== - * 設定ファイルを読み込む - *------------------------------------------ - */ -int map_config_read (char *cfgName) -{ - char line[1024], w1[1024], w2[1024]; - FILE *fp; - struct hostent *h = NULL; - - fp = fopen_ (cfgName, "r"); - if (fp == NULL) - { - printf ("Map configuration file not found at: %s\n", cfgName); - exit (1); - } - while (fgets (line, sizeof (line) - 1, fp)) - { - if (line[0] == '/' && line[1] == '/') - continue; - if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) == 2) - { - if (strcasecmp (w1, "userid") == 0) - { - chrif_setuserid (w2); - } - else if (strcasecmp (w1, "passwd") == 0) - { - chrif_setpasswd (w2); - } - else if (strcasecmp (w1, "char_ip") == 0) - { - h = gethostbyname (w2); - if (h != NULL) - { - printf - ("Character server IP address : %s -> %d.%d.%d.%d\n", - w2, (unsigned char) h->h_addr[0], - (unsigned char) h->h_addr[1], - (unsigned char) h->h_addr[2], - (unsigned char) h->h_addr[3]); - sprintf (w2, "%d.%d.%d.%d", (unsigned char) h->h_addr[0], - (unsigned char) h->h_addr[1], - (unsigned char) h->h_addr[2], - (unsigned char) h->h_addr[3]); - } - chrif_setip (w2); - } - else if (strcasecmp (w1, "char_port") == 0) - { - chrif_setport (atoi (w2)); - } - else if (strcasecmp (w1, "map_ip") == 0) - { - h = gethostbyname (w2); - if (h != NULL) - { - printf ("Map server IP address : %s -> %d.%d.%d.%d\n", w2, - (unsigned char) h->h_addr[0], - (unsigned char) h->h_addr[1], - (unsigned char) h->h_addr[2], - (unsigned char) h->h_addr[3]); - sprintf (w2, "%d.%d.%d.%d", (unsigned char) h->h_addr[0], - (unsigned char) h->h_addr[1], - (unsigned char) h->h_addr[2], - (unsigned char) h->h_addr[3]); - } - clif_setip (w2); - } - else if (strcasecmp (w1, "map_port") == 0) - { - clif_setport (atoi (w2)); - map_port = (atoi (w2)); - } - else if (strcasecmp (w1, "water_height") == 0) - { - map_readwater (w2); - } - else if (strcasecmp (w1, "map") == 0) - { - map_addmap (w2); - } - else if (strcasecmp (w1, "delmap") == 0) - { - map_delmap (w2); - } - else if (strcasecmp (w1, "npc") == 0) - { - npc_addsrcfile (w2); - } - else if (strcasecmp (w1, "delnpc") == 0) - { - npc_delsrcfile (w2); - } - else if (strcasecmp (w1, "autosave_time") == 0) - { - autosave_interval = atoi (w2) * 1000; - if (autosave_interval <= 0) - autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; - } - else if (strcasecmp (w1, "motd_txt") == 0) - { - strcpy (motd_txt, w2); - } - else if (strcasecmp (w1, "help_txt") == 0) - { - strcpy (help_txt, w2); - } - else if (strcasecmp (w1, "mapreg_txt") == 0) - { - strcpy (mapreg_txt, w2); - } - else if (strcasecmp (w1, "gm_log") == 0) - { - gm_logfile_name = strdup (w2); - } - else if (strcasecmp (w1, "log_file") == 0) - { - map_set_logfile (w2); - } - else if (strcasecmp (w1, "import") == 0) - { - map_config_read (w2); - } - } - } - fclose_ (fp); - - return 0; -} - -static int cleanup_sub (struct block_list *bl, va_list ap) -{ - nullpo_retr (0, bl); - - switch (bl->type) - { - case BL_PC: - map_delblock (bl); // There is something better... - break; - case BL_NPC: - npc_delete ((struct npc_data *) bl); - break; - case BL_MOB: - mob_delete ((struct mob_data *) bl); - break; - case BL_ITEM: - map_clearflooritem (bl->id); - break; - case BL_SKILL: - skill_delunit ((struct skill_unit *) bl); - break; - case BL_SPELL: - spell_free_invocation ((struct invocation *) bl); - break; - } - - return 0; -} - -/*========================================== - * map鯖終了時処理 - *------------------------------------------ - */ -void term_func (void) -{ - map_close_logfile (); - - int map_id, i; - - for (map_id = 0; map_id < map_num; map_id++) - { - if (map[map_id].m) - map_foreachinarea (cleanup_sub, map_id, 0, 0, map[map_id].xs, - map[map_id].ys, 0, 0); - } - - for (i = 0; i < fd_max; i++) - delete_session (i); - - map_removenpc (); - - numdb_final (id_db, NULL); - strdb_final (map_db, NULL); - strdb_final (nick_db, NULL); - numdb_final (charid_db, NULL); - - for (i = 0; i <= map_num; i++) - { - if (map[i].gat) - free (map[i].gat); - if (map[i].block) - free (map[i].block); - if (map[i].block_mob) - free (map[i].block_mob); - if (map[i].block_count) - free (map[i].block_count); - if (map[i].block_mob_count) - free (map[i].block_mob_count); - } - do_final_script (); - do_final_itemdb (); - do_final_storage (); - do_final_guild (); -} - -/// --help was passed -// FIXME this should produce output -void map_helpscreen (void) -{ - exit (1); -} - -int compare_item (struct item *a, struct item *b) -{ - return ((a->nameid == b->nameid) && - (a->identify == b->identify) && - (a->refine == b->refine) && - (a->attribute == b->attribute) && - (a->card[0] == b->card[0]) && - (a->card[1] == b->card[1]) && - (a->card[2] == b->card[2]) && (a->card[3] == b->card[3])); -} - -/*====================================================== - * Map-Server Init and Command-line Arguments [Valaris] - *------------------------------------------------------ - */ -int do_init (int argc, char *argv[]) -{ - int i; - - unsigned char *MAP_CONF_NAME = "conf/map_athena.conf"; - unsigned char *BATTLE_CONF_FILENAME = "conf/battle_athena.conf"; - unsigned char *ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf"; - unsigned char *SCRIPT_CONF_NAME = "conf/script_athena.conf"; - unsigned char *MSG_CONF_NAME = "conf/msg_athena.conf"; - - for (i = 1; i < argc; i++) - { - - if (strcmp (argv[i], "--help") == 0 || strcmp (argv[i], "--h") == 0 - || strcmp (argv[i], "--?") == 0 || strcmp (argv[i], "/?") == 0) - map_helpscreen (); - else if (strcmp (argv[i], "--map_config") == 0) - MAP_CONF_NAME = argv[i + 1]; - else if (strcmp (argv[i], "--battle_config") == 0) - BATTLE_CONF_FILENAME = argv[i + 1]; - else if (strcmp (argv[i], "--atcommand_config") == 0) - ATCOMMAND_CONF_FILENAME = argv[i + 1]; - else if (strcmp (argv[i], "--script_config") == 0) - SCRIPT_CONF_NAME = argv[i + 1]; - else if (strcmp (argv[i], "--msg_config") == 0) - MSG_CONF_NAME = argv[i + 1]; - } - - map_config_read (MAP_CONF_NAME); - battle_config_read (BATTLE_CONF_FILENAME); - atcommand_config_read (ATCOMMAND_CONF_FILENAME); - script_config_read (SCRIPT_CONF_NAME); - msg_config_read (MSG_CONF_NAME); - - id_db = numdb_init (); - map_db = strdb_init (16); - nick_db = strdb_init (24); - charid_db = numdb_init (); - - map_readallmap (); - -// add_timer_func_list (map_clearflooritem_timer, "map_clearflooritem_timer"); - - do_init_chrif (); - do_init_clif (); - do_init_itemdb (); - do_init_mob (); // npcの初期化時内でmob_spawnして、mob_dbを参照するのでinit_npcより先 - do_init_script (); - do_init_npc (); - do_init_pc (); - do_init_party (); - do_init_guild (); - do_init_storage (); - do_init_skill (); - do_init_magic (); - - npc_event_do_oninit (); // npcのOnInitイベント実行 - - if (battle_config.pk_mode == 1) - printf ("The server is running in \033[1;31mPK Mode\033[0m.\n"); - - printf - ("The map-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n", - map_port); - - return 0; -} - -int map_scriptcont (struct map_session_data *sd, int id) -{ - struct block_list *bl = map_id2bl (id); - - if (!bl) - return 0; - - switch (bl->type) - { - case BL_NPC: - return npc_scriptcont (sd, id); - case BL_SPELL: - spell_execute_script ((struct invocation *) bl); - break; - } - - return 0; -} |