Переглянути джерело

* Corrected Spiral Pierce's hits in the skill_db
* Moved /common/*.o into a obj folder when compiling
* Updated core and map server to jA 1094~1115

git-svn-id: https://svn.code.sf.net/p/rathena/svn/branches/stable@1162 54d463be-8e91-2dee-dedb-b68131a5f0ec

celest 20 роки тому
батько
коміт
fea0900092

+ 20 - 0
Changelog-SVN.txt

@@ -1,5 +1,25 @@
 Date	Added
 
+02/23
+        * Corrected Spiral Pierce's hits in the skill_db [celest]
+        * Moved /common/*.o into a obj folder when compiling [celest]
+        * Updated core and map server to jA 1094~1115 [celest]
+          - Added End_of_exam's Memory Manager for detecting memory problems.
+            To enable remove the // in malloc.c line 11
+               // #define USE_MEMMGR
+          - Added @npctalk and @pettalk
+          - Added support for jA's local zlib
+          - Fixed a bug with path search long
+          - Updated malloc.c to support Memwatch
+          - Added DB data loss detection
+          - Added db/skill_unit_db.txt
+          - Updated skill unit system
+          - Changed Waterball to the new timerskill system
+          ~ For more detailed logs check 'Readme-jap' (knowledge in japanese required,
+            obviously ^^;)
+          Please test if there's any skills that might have suddenly stopped working,
+          thanks ^^;
+
 02/22
 	* Revised New Cards, added missing effects, fixed bugs [Lupus]
 	  ~20 cards to check left 8) But in 22 Feb some new cards have been announced T__T'

Різницю між файлами не показано, бо вона завелика
+ 2920 - 0
Readme-jap


+ 13 - 7
db/skill_cast_db.txt

@@ -16,7 +16,7 @@
 18,2000:1850:1700:1550:1400:1250:1100:950:800:650,0,5000:6000:7000:8000:9000:10000:11000:12000:13000:14000,0	//MG_FIREWALL#ファイアーウォール#
 19,700:1400:2100:2800:3500:4200:4900:5600:6300:7000,1000:1200:1400:1600:1800:2000:2200:2400:2600:2800,0,0	//MG_FIREBOLT#ファイアーボルト#
 20,700:1400:2100:2800:3500:4200:4900:5600:6300:7000,1000:1200:1400:1600:1800:2000:2200:2400:2600:2800,0,0	//MG_LIGHTNINGBOLT#ライトニングボルト#
-21,1000:2000:3000:4000:5000:6000:7000:8000:9000:10000,2000,0,0	//MG_THUNDERSTORM#サンダーストーム#
+21,1000:2000:3000:4000:5000:6000:7000:8000:9000:10000,2000,500,0	//MG_THUNDERSTORM#サンダーストーム#
 
 24,0,0,10000,0		//AL_RUWACH#ルアフ#
 25,0,0,10000,0		//AL_PNEUMA#ニューマ#
@@ -62,17 +62,17 @@
 78,0,3000,600000,0	//PR_LEXAETERNA#レックスエーテルナ#
 79,15000,4000,5000:6000:7000:8000:9000:10000:11000:12000:13000:14000,0	//PR_MAGNUS#マグヌスエクソシズム#
 80,3000:2700:2400:2100:1800:1500:1200:900:600:300,2000,30000,0	//WZ_FIREPILLAR#ファイアーピラー#
-81,700,2000,0,0	//WZ_SIGHTRASHER#サイトラッシャー#
+81,700,2000,500,0	//WZ_SIGHTRASHER#サイトラッシャー#
 
-83,15000,2000:3000:3000:4000:4000:5000:5000:6000:6000:7000,0,3200:3400:3600:3800:4000:4200:4400:4600:4800:5000	//WZ_METEOR#メテオストーム#
+83,15000,2000:3000:3000:4000:4000:5000:5000:6000:6000:7000,500,3200:3400:3600:3800:4000:4200:4400:4600:4800:5000	//WZ_METEOR#メテオストーム#
 84,2500:3000:3500:4000:4500:5000:5500:6000:6500:7000,0,0,0	//WZ_JUPITEL#ユピテルサンダー#
-85,15000:14500:14000:13500:13000:12500:12000:11500:11000:10500,5000,0,5500:6000:6500:7000:7500:8000:8500:9000:9500:10000	//WZ_VERMILION#ロードオブヴァーミリオン#
+85,15000:14500:14000:13500:13000:12500:12000:11500:11000:10500,5000,4100,5500:6000:6500:7000:7500:8000:8500:9000:9500:10000	//WZ_VERMILION#ロードオブヴァーミリオン#
 86,1000:2000:3000:4000:5000,0,0,0	//WZ_WATERBALL#ウォーターボール#
 87,0,0,5000:10000:15000:20000:25000:30000:35000:40000:45000:50000,0	//WZ_ICEWALL#アイスウォール#
 88,5000:4700:4400:4100:3800:3500:3200:2900:2700:2500,1000,0,3000:3500:4000:4500:5000:5500:6000:6500:7000:7500	//WZ_FROSTNOVA#フロストノヴァ#
-89,6000:7000:8000:9000:10000:11000:12000:13000:14000:15000,5000,0,10000:11000:12000:13000:14000:15000:16000:17000:18000:19000	//WZ_STORMGUST#ストームガスト#
+89,6000:7000:8000:9000:10000:11000:12000:13000:14000:15000,5000,4600,10000:11000:12000:13000:14000:15000:16000:17000:18000:19000	//WZ_STORMGUST#ストームガスト#
 90,1000:2000:3000:4000:5000,700,0,0	//WZ_EARTHSPIKE#アーススパイク#
-91,1000:2000:3000:4000:5000,700,0,0	//WZ_HEAVENDRIVE#ヘヴンズドライブ#
+91,1000:2000:3000:4000:5000,700,500,0	//WZ_HEAVENDRIVE#ヘヴンズドライブ#
 92,0,1000,5000:10000:15000:20000:25000,5000:10000:15000:20000:25000	//WZ_QUAGMIRE#クァグマイア#
 
 110,0,0,0,6000:7000:8000:9000:10000:11000	//BS_HAMMERFALL#ハンマーフォール#
@@ -155,7 +155,7 @@
 251,0,700,0,0	//CR_SHIELDBOOMERANG#シールドブーメラン#
 252,0,0,300000,0	//CR_REFLECTSHIELD#リフレクトシールド#
 253,0,0,0,10000:11000:12000:13000:14000:15000:16000:17000:18000:19000	//CR_HOLYCROSS#ホーリークロス#
-254,3000,1500,0,10000:11000:12000:13000:14000:15000:16000:17000:18000:19000	//CR_GRANDCROSS#グランドクロス#
+254,3000,1500,1000,10000:11000:12000:13000:14000:15000:16000:17000:18000:19000	//CR_GRANDCROSS#グランドクロス#
 
 256,3000,0,180000,0	//CR_PROVIDENCE#プロヴィデンス#
 257,0,800,180000,0	//CR_DEFENDER#ディフェンダー#
@@ -218,6 +218,8 @@
 335,3000,0,0,0	//WE_FEMALE#あなたに尽くします#
 336,0,0,10000,0	//WE_CALLPARTNER#あなたに逢いたい#
 
+339,3000,1500,1000,10000:11000:12000:13000:14000:15000:16000:17000:18000:19000	//NPC_DARKGRANDCROSS#闇グランドクロス
+
 355,0,0,40000:60000:80000:100000:120000,0	//LK_AURABLADE#オーラブレード#
 356,0,0,15000:20000:25000:30000:35000:40000:45000:50000:55000:60000,0	//LK_PARRYING#パリイング#
 357,0,0,25000:30000:35000:40000:45000,0	//LK_CONCENTRATION#コンセントレーション#
@@ -270,6 +272,10 @@
 476,1000,1000,75000:90000:105000:120000:135000,0	//ST_FULLSTRIP##
 479,2000,0,120000:240000:360000:480000:600000,0	//CR_FULLPROTECTION##
 
+10006,0,0,300000,0	//GD_LEADERSHIP##
+10007,0,0,300000,0	//GD_GLORYWOUNDS##
+10008,0,0,300000,0	//GD_SOULCOLD##
+10009,0,0,300000,0	//GD_HAWKEYES##
 10010,100,1000,60000,0	//GD_BATTLEORDER##
 10011,100,1000,60000,0	//GD_REGENERATION##
 10012,100,1000,0,0	//GD_RESTORE##

+ 1 - 1
db/skill_db.txt

@@ -454,7 +454,7 @@
 394,8,8,1,0,0,10,9,no,0,0,0,weapon,0	//CG_ARROWVULCAN#アロ?バルカン#
 395,0,0,4,0,1,1,1,yes,0,0,0,magic,0	//CG_MOONLIT#月明りの泉に落ちる花びら#
 396,0,6,16,0,1,1,1,yes,0,0,0,magic,1	//CG_MARIONETTE#?リオネットコントロ?ル#
-397,4,8,1,0,0,5,1,no,0,0,0,weapon,0	//LK_SPIRALPIERCE#スパイラルピア?ス#
+397,4,8,1,0,0,5,5,no,0,0,0,weapon,0	//LK_SPIRALPIERCE#スパイラルピア?ス#
 398,4,6,1,0,0,5,1,no,0,0,0,weapon,0	//LK_HEADCRUSH#ヘッドクラッシュ#
 399,4,6,1,0,0,10,1,no,0,0,0,weapon,0	//LK_JOINTBEAT#ジョイントビ?ト#
 400,8,8,1,8,0,5,1:2:3:4:5,yes,0,0,0,magic,0	//HW_NAPALMVULCAN#ナパ??バルカン#

+ 78 - 0
db/skill_unit_db.txt

@@ -0,0 +1,78 @@
+// id,unit,unit,layout,range,interval,target,flag
+// position -1:特殊, 0:1*1, 1:3*3, 2:5*5,..., 5:11*11
+// target friend:NOENEMY, party:PARTY, 0x20000:BCT_ALL, enemy:ENEMY
+// flag 0x001(UF_DEFNOTENEMY)		defunit_not_enemyの影響を受ける
+//      0x002(UF_NOREITERRATION)	重ね置き不可
+//      0x004(UF_NOFOOTSET)			足元置き不可
+//      0x008(UF_NOOVERLAP)			効果が重複しない
+// 		0x100(UF_DANCE)				ダンススキル
+//		0x200(UF_ENSEMBLE)			合奏スキル
+//
+//    0x89,0x8a,0x8b 表示無し
+//    0x9a 炎属性の詠唱みたいなエフェクト
+//    0x9b 水属性の詠唱みたいなエフェクト
+//    0x9c 風属性の詠唱みたいなエフェクト
+//    0x9d 白い小さなエフェクト
+//  
+//    u1   u2 lay  r intr target  flag
+ 12,0x7e,    ,  0, 0,  -1,all,   0x003	//MG_SAFETYWALL#セイフティウォール
+ 18,0x7f,    , -1, 0,   1,enemy, 0x000	//MG_FIREWALL#ファイアーウォール
+ 21,0x86,    ,  0, 1,1000,enemy, 0x008	//MG_THUNDERSTORM#サンダーストーム
+ 25,0x85,    ,  1, 0,  -1,all,   0x003	//AL_PNEUMA#ニューマ
+ 27,0x81,0x80,  0, 0,  -1,all,   0x002	//AL_WARP#ワープポータル
+ 70,0x83,    , -1, 1,1000,all,   0x000	//PR_SANCTUARY#サンクチュアリ
+ 79,0x84,    , -1, 1,3000,enemy, 0x000	//PR_MAGNUS#マグヌスエクソシズム
+ 80,0x87,0x88,  0, 1,2000,enemy, 0x002	//WZ_FIREPILLAR#ファイアーピラー
+ 83,0x86,    ,  0, 3,1000,enemy, 0x000	//WZ_METEOR#メテオストーム
+ 85,0x86,    ,  0, 6,1000,enemy, 0x008	//WZ_VERMILION#ロードオブヴァーミリオン
+ 87,0x8d,    , -1, 0,  -1,all,   0x000	//WZ_ICEWALL#アイスウォール
+ 88,0x86,    ,  0, 2,1000,enemy, 0x000	//WZ_FROSTNOVA#フロストノヴァ
+ 89,0x86,    ,  0, 5, 450,enemy, 0x000	//WZ_STORMGUST#ストームガスト
+ 91,0x86,    ,  0, 2,1000,enemy, 0x000	//WZ_HEAVENDRIVE#ヘヴンズドライブ
+ 92,0x8e,    ,  2, 0,  -1,enemy, 0x000	//WZ_QUAGMIRE#クァグマイア
+115,0x90,    ,  0, 1,1000,enemy, 0x002	//HT_SKIDTRAP#スキッドトラップ
+116,0x93,    ,  0, 1,1000,enemy, 0x002	//HT_LANDMINE#ランドマイン
+117,0x91,    ,  0, 1,1000,enemy, 0x002	//HT_ANKLESNARE#アンクルスネア
+118,0x94,    ,  0, 1,1000,enemy, 0x002	//HT_SHOCKWAVE#ショックウェーブトラップ
+119,0x95,    ,  0, 2,1000,enemy, 0x002	//HT_SANDMAN#サンドマン
+120,0x96,    ,  0, 1,1000,enemy, 0x002	//HT_FLASHER#フラッシャー
+121,0x97,    ,  0, 1,1000,enemy, 0x002	//HT_FREEZINGTRAP#フリージングトラップ
+122,0x8f,    ,  0, 1,1000,enemy, 0x002	//HT_BLASTMINE#ブラストマイン
+123,0x98,    ,  0, 2,1000,enemy, 0x002	//HT_CLAYMORETRAP#クレイモアトラップ
+125,0x99,    ,  0, 1,1000,all,   0x002	//HT_TALKIEBOX#トーキーボックス
+140,0x92,    , -1, 0,1000,enemy, 0x000	//AS_VENOMDUST#ベナムダスト
+220,0xb0,    ,  0, 0,  -1,all,   0x002	//RG_GRAFFITI#グラフィティ
+229,0xb1,    ,  0, 1,1000,enemy, 0x000	//AM_DEMONSTRATION#デモンストレーション
+254,0x86,    , -1, 0, 300,enemy, 0x000	//CR_GRANDCROSS#グランドクロス
+285,0x9a,    ,  3, 0, -1,all,   0x000	//SA_VOLCANO#ボルケーノ
+286,0x9b,    ,  3, 0, -1,all,   0x000	//SA_DELUGE#デリュージ
+287,0x9c,    ,  3, 0, -1,all,   0x000	//SA_VIOLENTGALE#バイオレントゲイル
+288,0x9d,    ,  3, 0, -1,all,   0x000	//SA_LANDPROTECTOR#ランドプロテクター
+306,0x9e,    ,  4, 0,  -1,all,   0x300	//BD_LULLABY#子守歌
+307,0x9f,    ,  4, 0,  -1,party, 0x300	//BD_RICHMANKIM#ニヨルドの宴
+308,0xa0,    ,  4, 0,  -1,enemy, 0x300	//BD_ETERNALCHAOS#永遠の混沌
+309,0xa1,    ,  4, 0,  -1,party, 0x300	//BD_DRUMBATTLEFIELD#戦太鼓の響き
+310,0xa2,    ,  4, 0,  -1,party, 0x300	//BD_RINGNIBELUNGEN#ニーベルングの指輪
+311,0xa3,    ,  4, 0,  -1,all,   0x300	//BD_ROKISWEIL#ロキの叫び
+312,0xa4,    ,  4, 0,  -1,party, 0x300	//BD_INTOABYSS#深淵の中に
+313,0xa5,    ,  4, 0,  -1,party, 0x300	//BD_SIEGFRIED#不死身のジークフリード
+317,0xa6,    ,  3, 0,  -1,enemy, 0x100	//BA_DISSONANCE#不協和音
+319,0xa7,    ,  3, 0,  -1,friend,0x100	//BA_WHISTLE#口笛
+320,0xa8,    ,  3, 0,  -1,friend,0x100	//BA_ASSASSINCROSS#夕陽のアサシンクロス
+321,0xa9,    ,  3, 0,  -1,friend,0x100	//BA_POEMBRAGI#ブラギの詩
+322,0xaa,    ,  3, 0,  -1,friend,0x100	//BA_APPLEIDUN#イドゥンの林檎
+325,0xab,    ,  3, 0,  -1,enemy, 0x100	//DC_UGLYDANCE#自分勝手なダンス
+327,0xac,    ,  3, 0,  -1,friend,0x100	//DC_HUMMING#ハミング
+328,0xad,    ,  3, 0,  -1,enemy, 0x100,0	//DC_DONTFORGETME#私を忘れないで…
+329,0xae,    ,  3, 0,  -1,friend,0x100,0	//DC_FORTUNEKISS#幸運のキス
+330,0xaf,    ,  3, 0,  -1,party, 0x100,0	//DC_SERVICEFORYOU#サービスフォーユー
+336,0xb2,    ,  0,-1,  -1,all,   0x000,0	//WE_CALLPARTNER#あなたに逢いたい
+339,0x86,    , -1, 0, 300,enemy, 0x000,0	//NPC_DARKGRANDCROSS#闇グランドクロス
+362,0xb4,    ,  0, 3, 300,all,   0x000,0	//HP_BASILICA#バジリカ
+369,0xb3,    ,  3, 0,  -1,all,   0x000,0	//PA_GOSPEL#ゴスペル
+404,0xb6,    , -1, 0,  -1,all,   0x000,0	//PF_FOGWALL#フォグウォール
+405,0xb7,    ,  0, 1,1000,enemy, 0x002,0	//PF_SPIDERWEB#スパイダーウェッブ
+10006,0xc1,  ,  0, 2,  -1,all,   0x000,0	//GD_LEADERSHIP
+10007,0xc2,  ,  0, 2,  -1,all,   0x000,0	//GD_GLORYWOUNDS
+10008,0xc3,  ,  0, 2,  -1,all,   0x000,0	//GD_SOULCOLD
+10009,0xc4,  ,  0, 2,  -1,all,   0x000,0	//GD_HAWKEYES

+ 1 - 1
src/char/Makefile

@@ -1,7 +1,7 @@
 all: char-server
 txt: char-server
 
-COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/lock.o ../common/malloc.o ../common/showmsg.o ../common/strlib.o
+COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/lock.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o
 COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/lock.h ../common/timer.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h
 char-server: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o $(COMMON_OBJ)
 	$(CC) -o ../../$@ $> $(LIB_S)

+ 1 - 1
src/char_sql/Makefile

@@ -1,7 +1,7 @@
 all: char-server_sql
 sql: char-server_sql
 
-COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o ../common/utils.o ../common/strlib.o
+COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o ../common/obj/strlib.o
 COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h
 
 char-server_sql: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o itemdb.o $(COMMON_OBJ)

+ 21 - 13
src/common/Makefile

@@ -1,15 +1,23 @@
-txt sql all: core.o socket.o timer.o grfio.o db.o lock.o nullpo.o malloc.o showmsg.o
-
-core.o: core.c core.h showmsg.h
-socket.o: socket.c socket.h mmo.h showmsg.h
-timer.o: timer.c timer.h showmsg.h
-grfio.o: grfio.c grfio.h showmsg.h
-db.o: db.c db.h showmsg.h
-lock.o: lock.h showmsg.h
-nullpo.o: nullpo.c nullpo.h showmsg.h
-malloc.o: malloc.c malloc.h showmsg.h
-showmsg.o: showmsg.c showmsg.h
-strlib.o: strlib.c strlib.h utils.h
+txt sql all: obj common
+
+obj:
+	mkdir obj
+
+common: obj/core.o obj/socket.o obj/timer.o obj/grfio.o obj/db.o obj/lock.o obj/nullpo.o obj/malloc.o obj/showmsg.o  obj/strlib.o obj/utils.o
+
+obj/%.o: %.c
+	$(COMPILE.c) $(OUTPUT_OPTION) $<
+
+obj/core.o: core.c core.h showmsg.h
+obj/socket.o: socket.c socket.h mmo.h showmsg.h
+obj/timer.o: timer.c timer.h showmsg.h
+obj/grfio.o: grfio.c grfio.h showmsg.h
+obj/db.o: db.c db.h showmsg.h
+obj/lock.o: lock.h showmsg.h
+obj/nullpo.o: nullpo.c nullpo.h showmsg.h
+obj/malloc.o: malloc.c malloc.h showmsg.h
+obj/showmsg.o: showmsg.c showmsg.h
+obj/strlib.o: strlib.c strlib.h utils.h
 
 clean:
-	rm -f *.o
+	rm -f *.o obj

+ 35 - 39
src/common/core.c

@@ -9,10 +9,13 @@
 #include <signal.h>
 #include <string.h>
 #ifdef DUMPSTACK
-#include <execinfo.h>
+	#ifndef _WIN32	// HAVE_EXECINFO_H
+		#include <execinfo.h>
+	#endif
 #endif
 
 #include "../common/mmo.h"
+#include "malloc.h"
 #include "core.h"
 #include "socket.h"
 #include "timer.h"
@@ -92,44 +95,44 @@ static void sig_proc(int sn)
  *	Dumps the stack using glibc's backtrace
  *-----------------------------------------
  */
-#ifdef DUMPSTACK
 static void sig_dump(int sn)
 {
-	FILE *fp;
-	void* array[20];
+	#ifdef DUMPSTACK
+		FILE *fp;
+		void* array[20];
 
-	char **stack;
-	size_t size;		
-	int no = 0;
-	char tmp[256];
+		char **stack;
+		size_t size;		
+		int no = 0;
+		char tmp[256];
 
-	// search for a usable filename
-	do {
-		sprintf(tmp,"save/stackdump_%04d.txt", ++no);
-	} while((fp = fopen(tmp,"r")) && (fclose(fp), no < 9999));
-	// dump the trace into the file
-	if ((fp = fopen (tmp,"w")) != NULL) {
+		// search for a usable filename
+		do {
+			sprintf(tmp,"save/stackdump_%04d.txt", ++no);
+		} while((fp = fopen(tmp,"r")) && (fclose(fp), no < 9999));
+		// dump the trace into the file
+		if ((fp = fopen (tmp,"w")) != NULL) {
 
-		fprintf(fp,"Exception: %s\n", strsignal(sn));
-		fprintf(fp,"Stack trace:\n");
-		size = backtrace (array, 20);
-		stack = backtrace_symbols (array, size);
+			fprintf(fp,"Exception: %s\n", strsignal(sn));
+			fprintf(fp,"Stack trace:\n");
+			size = backtrace (array, 20);
+			stack = backtrace_symbols (array, size);
 
-		for (no = 0; no < size; no++) {
+			for (no = 0; no < size; no++) {
 
-			fprintf(fp, "%s\n", stack[no]);
+				fprintf(fp, "%s\n", stack[no]);
 
-		}
-		fprintf(fp,"End of stack trace\n");
+			}
+			fprintf(fp,"End of stack trace\n");
 
-		fclose(fp);
-		free(stack);
-	}
+			fclose(fp);
+			free(stack);
+		}
+	#endif
 	// When pass the signal to the system's default handler
 	compat_signal(sn, SIG_DFL);
 	raise(sn);
 }
-#endif
 
 int get_svn_revision(char *svnentry) { // Warning: minor syntax checking
 	char line[1024];
@@ -204,28 +207,20 @@ int main(int argc,char **argv)
 	compat_signal(SIGPIPE,SIG_IGN);
 	compat_signal(SIGTERM,sig_proc);
 	compat_signal(SIGINT,sig_proc);
-	
-#ifndef DUMPSTACK
- 	// Signal to create coredumps by system when necessary (crash)
- 	compat_signal(SIGSEGV, SIG_DFL);
-	compat_signal(SIGFPE, SIG_DFL);
-	compat_signal(SIGILL, SIG_DFL);
-	#ifndef _WIN32
-		compat_signal(SIGBUS, SIG_DFL);
-		compat_signal(SIGTRAP, SIG_DFL); 
-	#endif
-#else
+
+	// Signal to create coredumps by system when necessary (crash)
 	compat_signal(SIGSEGV, sig_dump);
 	compat_signal(SIGFPE, sig_dump);
 	compat_signal(SIGILL, sig_dump);
 	#ifndef _WIN32
 		compat_signal(SIGBUS, sig_dump);
-		compat_signal(SIGTRAP, SIG_DFL); 
+		compat_signal(SIGTRAP, SIG_DFL);
 	#endif
-#endif
 
 	display_title();
 
+	do_init_memmgr(argv[0]); // 一番最初に実行する必要がある
+
 	tick_ = time(0);
 
 	do_init(argc,argv);
@@ -234,5 +229,6 @@ int main(int argc,char **argv)
 		do_sendrecv(next);
 		do_parsepacket();
 	}
+
 	return 0;
 }

+ 18 - 2
src/common/db.c

@@ -65,7 +65,7 @@ static unsigned int strdb_hash(struct dbt* table,void* a)
 	return h;
 }
 
-struct dbt* strdb_init(int maxlen)
+struct dbt* strdb_init_(int maxlen,const char *file,int line)
 {
 	int i;
 	struct dbt* table;
@@ -77,6 +77,9 @@ struct dbt* strdb_init(int maxlen)
 	table->maxlen=maxlen;
 	for(i=0;i<HASH_SIZE;i++)
 		table->ht[i]=NULL;
+	table->alloc_file = file;
+	table->alloc_line = line;
+	table->item_count = 0;
 	return table;
 }
 
@@ -98,7 +101,7 @@ static unsigned int numdb_hash(struct dbt* table,void* a)
 	return (unsigned int)a;
 }
 
-struct dbt* numdb_init(void)
+struct dbt* numdb_init_(const char *file,int line)
 {
 	int i;
 	struct dbt* table;
@@ -110,6 +113,9 @@ struct dbt* numdb_init(void)
 	table->maxlen=sizeof(int);
 	for(i=0;i<HASH_SIZE;i++)
 		table->ht[i]=NULL;
+	table->alloc_file = file;
+	table->alloc_line = line;
+	table->item_count = 0;
 	return table;
 }
 
@@ -400,6 +406,7 @@ struct dbn* db_insert(struct dbt *table,void* key,void* data)
 			db_rebalance(p,&table->ht[hash]);
 		}
 	}
+	table->item_count++;
 	return p;
 }
 
@@ -428,12 +435,14 @@ void* db_erase(struct dbt *table,void* key)
 #else
 	aFree(p);
 #endif
+	table->item_count--;
 	return data;
 }
 
 void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...)
 {
 	int i,sp;
+	int count = 0;
 	// red-black treeなので64個stackがあれば2^32個ノードまで大丈夫
 	struct dbn *p,*pn,*stack[64];
 	va_list ap;
@@ -449,6 +458,7 @@ void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...)
 			//	printf("Warning: no data for key %d in db_foreach (db.c) !\n",(int)p->key);
 			//} else {
 			func(p->key, p->data, ap);
+			count++;
 			//}
 			if((pn=p->left)!=NULL){
 				if(p->right){
@@ -466,6 +476,12 @@ void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...)
 			}
 		}
 	}
+	if(count != table->item_count) {
+		printf(
+			"db_foreach : data lost %d of %d item(s) allocated from %s line %d\n",
+			table->item_count - count,count,table->alloc_file,table->alloc_line
+		);
+	}
 	va_end(ap);
 }
 

+ 8 - 2
src/common/db.h

@@ -22,6 +22,9 @@ struct dbt {
 	void (*release)(struct dbn*,int which);
 	int maxlen;
 	struct dbn *ht[HASH_SIZE];
+	int item_count; // vf?
+	const char* alloc_file; // DB?t@C
+	int         alloc_line; // DB?s
 };
 
 #define strdb_search(t,k)   db_search((t),(void*)(k))
@@ -34,9 +37,12 @@ struct dbt {
 #define numdb_erase(t,k)    db_erase ((t),(void*)(k))
 #define numdb_foreach       db_foreach
 #define numdb_final         db_final
+#define strdb_init(a)       strdb_init_(a,__FILE__,__LINE__)
+#define numdb_init()        numdb_init_(__FILE__,__LINE__)
+
+struct dbt* strdb_init_(int maxlen,const char *file,int line);
+struct dbt* numdb_init_(const char *file,int line);
 
-struct dbt* strdb_init(int maxlen);
-struct dbt* numdb_init(void);
 void* db_search(struct dbt *table,void* key);
 void* db_search2(struct dbt *table, const char *key); // [MouseJstr]
 struct dbn* db_insert(struct dbt *table,void* key,void* data);

+ 41 - 14
src/common/grfio.c

@@ -32,21 +32,36 @@
 #include "malloc.h"
 
 #ifdef _WIN32
-	#include <windows.h>
-	#include "../lib/zlib_win32.h"
-	HINSTANCE zlib_dll;
-	#define zlib_inflateInit(strm) zlib_inflateInit_((strm),ZLIB_VERSION, sizeof(z_stream))
-	#define zlib_deflateInit(strm, level) zlib_deflateInit_((strm),(level),ZLIB_VERSION,sizeof(z_stream))
-
-	int (WINAPI* zlib_inflateInit_) (z_streamp strm, const char *version, int stream_size);
-	int (WINAPI* zlib_inflate) (z_streamp strm, int flush);
-	int (WINAPI* zlib_inflateEnd) (z_streamp strm);
-
-	int (WINAPI* zlib_deflateInit_) (z_streamp strm, int level, const char *version, int stream_size);
-	int (WINAPI* zlib_deflate) (z_streamp strm, int flush);
-	int (WINAPI* zlib_deflateEnd) (z_streamp strm);
+	#ifdef LOCALZLIB
+		#include "../lib/zlib/zlib.h"
+		#define zlib_inflateInit inflateInit
+		#define zlib_inflate     inflate
+		#define zlib_inflateEnd  inflateEnd
+		#define zlib_deflateInit deflateInit
+		#define zlib_deflate     deflate
+		#define zlib_deflateEnd  deflateEnd
+	#else
+		#include <windows.h>
+		#include "../lib/zlib_win32.h"
+		HINSTANCE zlib_dll;
+		#define zlib_inflateInit(strm) zlib_inflateInit_((strm),ZLIB_VERSION, sizeof(z_stream))
+		#define zlib_deflateInit(strm, level) zlib_deflateInit_((strm),(level),ZLIB_VERSION,sizeof(z_stream))
+
+		int (WINAPI* zlib_inflateInit_) (z_streamp strm, const char *version, int stream_size);
+		int (WINAPI* zlib_inflate) (z_streamp strm, int flush);
+		int (WINAPI* zlib_inflateEnd) (z_streamp strm);
+
+		int (WINAPI* zlib_deflateInit_) (z_streamp strm, int level, const char *version, int stream_size);
+		int (WINAPI* zlib_deflate) (z_streamp strm, int flush);
+		int (WINAPI* zlib_deflateEnd) (z_streamp strm);
+	#endif
 #else
-	#include <zlib.h>
+	#ifdef LOCALZLIB
+		#include "zlib/zlib.h"
+	#else
+		#include <zlib.h>
+	#endif
+
 	#define zlib_inflateInit inflateInit
 	#define zlib_inflate     inflate
 	#define zlib_inflateEnd  inflateEnd
@@ -966,6 +981,16 @@ void grfio_final(void)
 	}
 	gentry_table = NULL;
 	gentry_entrys = gentry_maxentry = 0;
+
+#ifdef _WIN32
+	#ifndef LOCALZLIB
+		FreeLibrary(zlib_dll);
+		zlib_inflateInit_ = NULL;
+		zlib_inflate      = NULL;
+		zlib_inflateEnd   = NULL;
+	#endif
+#endif
+
 }
 
 /*==========================================
@@ -979,6 +1004,7 @@ void grfio_init(char *fname)
 	int result = 0, result2 = 0, result3 = 0, result4 = 0;
 
 #ifdef _WIN32
+	#ifndef LOCALZLIB
 	if(!zlib_dll) {
 		zlib_dll = LoadLibrary("zlib.dll");
 		(FARPROC)zlib_inflateInit_ = GetProcAddress(zlib_dll,"inflateInit_");
@@ -992,6 +1018,7 @@ void grfio_init(char *fname)
 			exit(1);
 		}
 	}
+	#endif
 #endif
 
 	data_conf = fopen(fname, "r");

+ 481 - 3
src/common/malloc.c

@@ -3,14 +3,25 @@
 #include <string.h>
 #include "malloc.h"
 
-#if !defined(DMALLOC) && !defined(GCOLLECT) && !defined(BCHECK)
+#ifdef MEMWATCH
+#include "memwatch.h"
+#endif
+
+// 独自メモリマネージャを使用する場合、次のコメントを外してください。
+// #define USE_MEMMGR
+
+#if !defined(DMALLOC) && !defined(GCOLLECT) && !defined(BCHECK) && !defined(USE_MEMMGR)
 
 void* aMalloc_( size_t size, const char *file, int line, const char *func )
 {
 	void *ret;
 
 //	printf("%s:%d: in func %s: malloc %d\n",file,line,func,size);
+#ifdef MEMWATCH
+	ret=mwMalloc(size,file,line);
+#else
 	ret=malloc(size);
+#endif
 	if(ret==NULL){
 		printf("%s:%d: in func %s: malloc error out of memory!\n",file,line,func);
 		exit(1);
@@ -23,7 +34,11 @@ void* aCalloc_( size_t num, size_t size, const char *file, int line, const char
 	void *ret;
 
 //	printf("%s:%d: in func %s: calloc %d %d\n",file,line,func,num,size);
+#ifdef MEMWATCH
+	ret=mwCalloc(num,size,file,line);
+#else
 	ret=calloc(num,size);
+#endif
 	if(ret==NULL){
 		printf("%s:%d: in func %s: calloc error out of memory!\n",file,line,func);
 		exit(1);
@@ -37,7 +52,11 @@ void* aRealloc_( void *p, size_t size, const char *file, int line, const char *f
 	void *ret;
 
 //	printf("%s:%d: in func %s: realloc %p %d\n",file,line,func,p,size);
+#ifdef MEMWATCH
+	ret=mwRealloc(p,size,file,line);
+#else
 	ret=realloc(p,size);
+#endif
 	if(ret==NULL){
 		printf("%s:%d: in func %s: realloc error out of memory!\n",file,line,func);
 		exit(1);
@@ -46,10 +65,39 @@ void* aRealloc_( void *p, size_t size, const char *file, int line, const char *f
 	return ret;
 }
 
+void* aStrdup_( const void *p, const char *file, int line, const char *func )
+{
+	void *ret;
+	
+	// printf("%s:%d: in func %s: strdup %p\n",file,line,func,p);
+#ifdef MEMWATCH
+	ret=mwStrdup(p,file,line);
+#else
+	ret=strdup(p);
+#endif
+	if(ret==NULL){
+		printf("%s:%d: in func %s: strdup error out of memory!\n",file,line,func);
+		exit(1);
+
+	}
+	return ret;
+}
+
+void aFree_( void *p, const char *file, int line, const char *func )
+{
+	// printf("%s:%d: in func %s: free %p\n",file,line,func,p);
+#ifdef MEMWATCH
+	mwFree(p,file,line);
+#else
+	free(p);
 #endif
+}
 
+int do_init_memmgr(const char* file) {
+	return 0;
+}
 
-#if defined(GCOLLECT)
+#elif defined(GCOLLECT)
 
 void * _bcallocA(size_t size, size_t cnt) {
 	void *ret = aMallocA(size * cnt);
@@ -62,7 +110,6 @@ void * _bcalloc(size_t size, size_t cnt) {
 	memset(ret, 0, size * cnt);
 	return ret;
 }
-#endif
 
 char * _bstrdup(const char *chr) {
 	int len = strlen(chr);
@@ -70,3 +117,434 @@ char * _bstrdup(const char *chr) {
 	strcpy(ret, chr);
 	return ret;
 }
+
+#elif defined(USE_MEMMGR)
+
+/* USE_MEMMGR */
+
+/*
+ * メモリマネージャ
+ *     malloc , free の処理を効率的に出来るようにしたもの。
+ *     複雑な処理を行っているので、若干重くなるかもしれません。
+ *
+ * データ構造など(説明下手ですいません^^; )
+ *     ・メモリを複数の「ブロック」に分けて、さらにブロックを複数の「ユニット」
+ *       に分けています。ユニットのサイズは、1ブロックの容量を複数個に均等配分
+ *       したものです。たとえば、1ユニット32KBの場合、ブロック1つは32Byteのユ
+ *       ニットが、1024個集まって出来ていたり、64Byteのユニットが 512個集まって
+ *       出来ていたりします。(padding,unit_head を除く)
+ *
+ *     ・ユニット同士はリンクリスト(block_prev,block_next) でつながり、同じサイ
+ *       ズを持つユニット同士もリンクリスト(samesize_prev,samesize_nect) でつな
+ *       がっています。それにより、不要となったメモリの再利用が効率的に行えます。
+ */
+
+/* ブロックに入るデータ量 */
+#define BLOCK_DATA_SIZE	80*1024
+
+/* 一度に確保するブロックの数。 */
+#define BLOCK_ALLOC		32
+
+/* ブロックのアライメント */
+#define BLOCK_ALIGNMENT	64
+
+/* ブロック */
+struct block {
+	int    block_no;		/* ブロック番号 */
+	struct block* block_prev;		/* 前に確保した領域 */
+	struct block* block_next;		/* 次に確保した領域 */
+	int    samesize_no;     /* 同じサイズの番号 */
+	struct block* samesize_prev;	/* 同じサイズの前の領域 */
+	struct block* samesize_next;	/* 同じサイズの次の領域 */
+	int    unit_size;		/* ユニットのバイト数 0=未使用 */
+	int    unit_hash;		/* ユニットのハッシュ */
+	int    unit_count;		/* ユニットの数 */
+	int    unit_used;		/* 使用済みユニット */
+	char   data[BLOCK_DATA_SIZE];
+};
+
+struct unit_head {
+	struct block* block;
+	int    size;
+	const  char* file;
+	int    line;
+};
+
+static struct block* block_first  = NULL;
+static struct block* block_last   = NULL;
+static struct block* block_unused = NULL;
+
+/* ユニットへのハッシュ。80KB/64Byte = 1280個 */
+static struct block* unit_first[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT];		/* 最初 */
+static struct block* unit_unfill[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT];	/* 埋まってない */
+static struct block* unit_last[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT];		/* 最後 */
+
+/* メモリを使い回せない領域用のデータ */
+struct unit_head_large {
+	struct unit_head_large* prev;
+	struct unit_head_large* next;
+	struct unit_head        unit_head;
+};
+static struct unit_head_large *unit_head_large_first = NULL;
+
+static struct block* block_malloc(void);
+static void   block_free(struct block* p);
+static void memmgr_info(void);
+
+void* aMalloc_(size_t size, const char *file, int line, const char *func ) {
+	int i;
+	struct block *block;
+	int size_hash = (size+BLOCK_ALIGNMENT-1) / BLOCK_ALIGNMENT;
+	size = size_hash * BLOCK_ALIGNMENT; /* アライメントの倍数に切り上げ */
+
+	if(size == 0) {
+		return NULL;
+	}
+
+	/* ブロック長を超える領域の確保には、malloc() を用いる */
+	/* その際、unit_head.block に NULL を代入して区別する */
+	if(size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
+#ifdef MEMWATCH
+		struct unit_head_large* p = (struct unit_head_large*)mwMalloc(sizeof(struct unit_head_large) + size,file,line);
+#else
+		struct unit_head_large* p = (struct unit_head_large*)malloc(sizeof(struct unit_head_large) + size);
+#endif
+		if(p != NULL) {
+			p->unit_head.block = NULL;
+			p->unit_head.size  = size;
+			p->unit_head.file  = file;
+			p->unit_head.line  = line;
+			if(unit_head_large_first == NULL) {
+				unit_head_large_first = p;
+				p->next = NULL;
+				p->prev = NULL;
+			} else {
+				unit_head_large_first->prev = p;
+				p->prev = NULL;
+				p->next = unit_head_large_first;
+				unit_head_large_first = p;
+			}
+			return (char *)p + sizeof(struct unit_head_large);
+		} else {
+			printf("MEMMGR::memmgr_alloc failed.\n");
+			exit(1);
+		}
+	}
+
+	/* 同一サイズのブロックが確保されていない時、新たに確保する */
+	if(unit_unfill[size_hash] == NULL) {
+		block = block_malloc();
+		if(unit_first[size_hash] == NULL) {
+			/* 初回確保 */
+			unit_first[size_hash] = block;
+			unit_last[size_hash] = block;
+			block->samesize_no = 0;
+			block->samesize_prev = NULL;
+			block->samesize_next = NULL;
+		} else {
+			/* 連結作業 */
+			unit_last[size_hash]->samesize_next = block;
+			block->samesize_no   = unit_last[size_hash]->samesize_no + 1;
+			block->samesize_prev = unit_last[size_hash];
+			block->samesize_next = NULL;
+			unit_last[size_hash] = block;
+		}
+		unit_unfill[size_hash] = block;
+		block->unit_size  = size + sizeof(struct unit_head);
+		block->unit_count = BLOCK_DATA_SIZE / block->unit_size;
+		block->unit_used  = 0;
+		block->unit_hash  = size_hash;
+		/* 未使用Flagを立てる */
+		for(i=0;i<block->unit_count;i++) {
+			((struct unit_head*)(&block->data[block->unit_size * i]))->block = NULL;
+		}
+	}
+	/* ユニット使用個数加算 */
+	block = unit_unfill[size_hash];
+	block->unit_used++;
+
+	/* ユニット内を全て使い果たした */
+	if(block->unit_count == block->unit_used) {
+		do {
+			unit_unfill[size_hash] = unit_unfill[size_hash]->samesize_next;
+		} while(
+			unit_unfill[size_hash] != NULL &&
+			unit_unfill[size_hash]->unit_count == unit_unfill[size_hash]->unit_used
+		);
+	}
+
+	/* ブロックの中の空きユニット捜索 */
+	for(i=0;i<block->unit_count;i++) {
+		struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]);
+		if(head->block == NULL) {
+			head->block = block;
+			head->size  = size;
+			head->line  = line;
+			head->file  = file;
+			return (char *)head + sizeof(struct unit_head);
+		}
+	}
+	// ここに来てはいけない。
+	printf("MEMMGR::memmgr_malloc() serious error.\n");
+	memmgr_info();
+	exit(1);
+	return NULL;
+};
+
+void* aCalloc_(size_t num, size_t size, const char *file, int line, const char *func ) {
+	void *p = aMalloc_(num * size,file,line,func);
+	memset(p,0,num * size);
+	return p;
+}
+
+void* aRealloc_(void *memblock, size_t size, const char *file, int line, const char *func ) {
+	size_t old_size;
+	if(memblock == NULL) {
+		return aMalloc_(size,file,line,func);
+	}
+
+	old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head)))->size;
+	if(old_size > size) {
+		// サイズ縮小 -> そのまま返す(手抜き)
+		return memblock;
+	}  else {
+		// サイズ拡大
+		void *p = aMalloc_(size,file,line,func);
+		if(p != NULL) {
+			memcpy(p,memblock,old_size);
+		}
+		aFree_(memblock,file,line,func);
+		return p;
+	}
+}
+
+void* aStrdup_(const void* string, const char *file, int line, const char *func ) {
+	if(string == NULL) {
+		return NULL;
+	} else {
+		int  len = strlen(string);
+		char *p  = (char *)aMalloc_(len + 1,file,line,func);
+		memcpy(p,string,len+1);
+		return p;
+	}
+}
+
+void aFree_(void *ptr, const char *file, int line, const char *func ) {
+	struct unit_head *head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head));
+	if(ptr == NULL) {
+		return;
+	} else if(head->block == NULL && head->size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
+		/* malloc() で直に確保された領域 */
+		struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large));
+		if(head_large->prev) {
+			head_large->prev->next = head_large->next;
+		} else {
+			unit_head_large_first  = head_large->next;
+		}
+		if(head_large->next) {
+			head_large->next->prev = head_large->prev;
+		}
+		free(head_large);
+		return;
+	} else {
+		/* ユニット解放 */
+		struct block *block = head->block;
+		if(head->block == NULL) {
+			printf("memmgr: args of aFree is freed pointer %s line %d\n",file,line);
+		} else {
+			head->block = NULL;
+			if(--block->unit_used == 0) {
+				/* ブロックの解放 */
+				if(unit_unfill[block->unit_hash] == block) {
+					/* 空きユニットに指定されている */
+					do {
+						unit_unfill[block->unit_hash] = unit_unfill[block->unit_hash]->samesize_next;
+					} while(
+						unit_unfill[block->unit_hash] != NULL &&
+						unit_unfill[block->unit_hash]->unit_count == unit_unfill[block->unit_hash]->unit_used
+					);
+				}
+				if(block->samesize_prev == NULL && block->samesize_next == NULL) {
+					/* 独立ブロックの解放 */
+					unit_first[block->unit_hash]  = NULL;
+					unit_last[block->unit_hash]   = NULL;
+					unit_unfill[block->unit_hash] = NULL;
+				} else if(block->samesize_prev == NULL) {
+					/* 先頭ブロックの解放 */
+					unit_first[block->unit_hash] = block->samesize_next;
+					(block->samesize_next)->samesize_prev = NULL;
+				} else if(block->samesize_next == NULL) {
+					/* 末端ブロックの解放 */
+					unit_last[block->unit_hash] = block->samesize_prev; 
+					(block->samesize_prev)->samesize_next = NULL;
+				} else {
+					/* 中間ブロックの解放 */
+					(block->samesize_next)->samesize_prev = block->samesize_prev;
+					(block->samesize_prev)->samesize_next = block->samesize_next;
+				}
+				block_free(block);
+			} else {
+				/* 空きユニットの再設定 */
+				if(
+					unit_unfill[block->unit_hash] == NULL ||
+					unit_unfill[block->unit_hash]->samesize_no > block->samesize_no
+				) {
+					unit_unfill[block->unit_hash] = block;
+				}
+			}
+		}
+	}
+}
+
+/* 現在の状況を表示する */
+static void memmgr_info(void) {
+	int i;
+	struct block *p;
+	printf("** Memory Maneger Information **\n");
+	if(block_first == NULL) {
+		printf("Uninitialized.\n");
+		return;
+	}
+	printf(
+		"Blocks: %04u , BlockSize: %06u Byte , Used: %08uKB\n",
+		block_last->block_no+1,sizeof(struct block),
+		(block_last->block_no+1) * sizeof(struct block) / 1024
+	);
+	p = block_first;
+	for(i=0;i<=block_last->block_no;i++) {
+		printf("    Block #%04u : ",p->block_no);
+		if(p->unit_size == 0) {
+			printf("unused.\n");
+		} else {
+			printf(
+				"size: %05u byte. used: %04u/%04u prev:",
+				p->unit_size - sizeof(struct unit_head),p->unit_used,p->unit_count
+			);
+			if(p->samesize_prev == NULL) {
+				printf("NULL");
+			} else {
+				printf("%04u",(p->samesize_prev)->block_no);
+			}
+			printf(" next:");
+			if(p->samesize_next == NULL) {
+				printf("NULL");
+			} else {
+				printf("%04u",(p->samesize_next)->block_no);
+			}
+			printf("\n");
+		}
+		p = p->block_next;
+	}
+}
+
+/* ブロックを確保する */
+static struct block* block_malloc(void) {
+	if(block_unused != NULL) {
+		/* ブロック用の領域は確保済み */
+		struct block* ret = block_unused;
+		do {
+			block_unused = block_unused->block_next;
+		} while(block_unused != NULL && block_unused->unit_size != 0);
+		return ret;
+	} else {
+		/* ブロック用の領域を新たに確保する */
+		int i;
+		int  block_no;
+		struct block* p = (struct block *)calloc(sizeof(struct block),BLOCK_ALLOC);
+		if(p == NULL) {
+			printf("MEMMGR::block_alloc failed.\n");
+			exit(1);
+		}
+		if(block_first == NULL) {
+			/* 初回確保 */
+			block_no     = 0;
+			block_first  = p;
+		} else {
+			block_no      = block_last->block_no + 1;
+			block_last->block_next = p;
+			p->block_prev = block_last;
+		}
+		block_last = &p[BLOCK_ALLOC - 1];
+		/* ブロックを連結させる */
+		for(i=0;i<BLOCK_ALLOC;i++) {
+			if(i != 0) {
+				p[i].block_prev = &p[i-1];
+			}
+			if(i != BLOCK_ALLOC -1) {
+				p[i].block_next = &p[i+1];
+			}
+			p[i].block_no = block_no + i;
+		}
+
+		/* 未使用ブロックへのポインタを更新 */
+		block_unused = &p[1];
+		p->unit_size = 1;
+		return p;
+	}
+}
+
+static void block_free(struct block* p) {
+	/* free() せずに、未使用フラグを付けるだけ */
+	p->unit_size = 0;
+	/* 未使用ポインターを更新する */
+	if(block_unused == NULL) {
+		block_unused = p;
+	} else if(block_unused->block_no > p->block_no) {
+		block_unused = p;
+	}
+}
+
+static char memmer_logfile[128];
+
+static FILE* memmgr_log(void) {
+	FILE *fp = fopen(memmer_logfile,"w");
+	if(!fp) { fp = stdout; }
+	fprintf(fp,"memmgr: memory leaks found\n");
+	return fp;
+}
+
+static void memmer_exit(void) {
+	FILE *fp = NULL;
+	int i;
+	int count = 0;
+	struct block *block = block_first;
+	struct unit_head_large *large = unit_head_large_first;
+	while(block) {
+		if(block->unit_size) {
+			if(!fp) { fp = memmgr_log(); }
+			for(i=0;i<block->unit_count;i++) {
+				struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]);
+				if(head->block != NULL) {
+					fprintf(
+						fp,"%04d : %s line %d size %d\n",++count,
+						head->file,head->line,head->size
+					);
+				}
+			}
+		}
+		block = block->block_next;
+	}
+	while(large) {
+		if(!fp) { fp = memmgr_log(); }
+		fprintf(
+			fp,"%04d : %s line %d size %d\n",++count,
+			large->unit_head.file,
+			large->unit_head.line,large->unit_head.size
+		);
+		large = large->next;
+	}
+	if(!fp) {
+		printf("memmgr: no memory leaks found.\n");
+	} else {
+		printf("memmgr: memory leaks found.\n");
+	}
+}
+
+int do_init_memmgr(const char* file) {
+	sprintf(memmer_logfile,"%s.log",file);
+	atexit(memmer_exit);
+	printf("memmgr: initialised: %s\n",memmer_logfile);
+	return 0;
+}
+
+#endif

+ 6 - 2
src/common/malloc.h

@@ -59,15 +59,19 @@
 	void* aMalloc_( size_t size, const char *file, int line, const char *func );
 	void* aCalloc_( size_t num, size_t size, const char *file, int line, const char *func );
 	void* aRealloc_( void *p, size_t size, const char *file, int line, const char *func );
+	void  aFree_( void *p, const char *file, int line, const char *func );
+	void* aStrdup_( const void *p, const char *file, int line, const char *func );
 
 #	define aMalloc(n) aMalloc_(n,ALC_MARK)
 #	define aMallocA(n) aMalloc_(n,ALC_MARK)
 #	define aCalloc(m,n) aCalloc_(m,n,ALC_MARK)
 #	define aCallocA(m,n) aCalloc_(m,n,ALC_MARK)
 #	define aRealloc(p,n) aRealloc_(p,n,ALC_MARK)
-#	define aFree(ptr) free(ptr)
-#	define aStrdup(ptr) strdup(ptr)
+#	define aStrdup(p) aStrdup_(p,ALC_MARK)
+#	define aFree(p) do { aFree_(p,ALC_MARK); if(p != NULL) { p = NULL; } } while(0)
 
 #endif
 
+int do_init_memmgr(const char* file);
+
 #endif

+ 1 - 1
src/ladmin/Makefile

@@ -2,7 +2,7 @@ all: ladmin
 txt: ladmin
 sql: ladmin
 
-COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o ../common/strlib.o
+COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o
 COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h
 
 ladmin: ladmin.o md5calc.o $(COMMON_OBJ)

+ 1 - 1
src/login/Makefile

@@ -1,7 +1,7 @@
 all: login-server
 txt: login-server
 
-COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/lock.o ../common/malloc.o ../common/showmsg.o ../common/strlib.o
+COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/lock.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o
 COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/lock.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h
 
 login-server: login.o md5calc.o $(COMMON_OBJ)

+ 1 - 1
src/login_sql/Makefile

@@ -2,7 +2,7 @@ all: login-server_sql
 sql: login-server_sql
 
 shared_libs=all
-COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o ../common/strlib.o
+COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o
 COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h
 
 login-server_sql: login.o md5calc.o $(COMMON_OBJ)

+ 52 - 50
src/map/Makefile

@@ -10,7 +10,9 @@ txtobj:
 sqlobj:
 	mkdir sqlobj
 
-COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/grfio.o ../common/db.o ../common/lock.o ../common/nullpo.o ../common/malloc.o ../common/showmsg.o ../common/utils.o ../common/strlib.o
+COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/grfio.o ../common/obj/db.o ../common/obj/lock.o ../common/obj/nullpo.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o ../common/obj/strlib.o
+
+COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/grfio.h ../common/db.h ../common/lock.h ../common/nullpo.h ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h
 LIBS = -lz -lm
 
 map-server: txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/status.o txtobj/npc.o txtobj/npc_chat.o txtobj/chat.o txtobj/path.o txtobj/itemdb.o txtobj/mob.o txtobj/script.o txtobj/storage.o txtobj/skill.o txtobj/atcommand.o txtobj/charcommand.o txtobj/battle.o txtobj/intif.o txtobj/trade.o txtobj/party.o txtobj/vending.o txtobj/guild.o txtobj/pet.o txtobj/log.o $(COMMON_OBJ)
@@ -25,56 +27,56 @@ txtobj/%.o: %.c
 sqlobj/%.o: %.c
 	$(COMPILE.c) $(OUTPUT_OPTION) $<
 
-txtobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h ../common/core.h ../common/timer.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h
-txtobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-txtobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/showmsg.h
-txtobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h
-txtobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h
-txtobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-txtobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-txtobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h
-txtobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h
-txtobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h
-txtobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h ../common/timer.h ../common/socket.h ../common/mmo.h ../common/showmsg.h
-txtobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h ../common/timer.h ../common/socket.h ../common/db.h ../common/mmo.h ../common/lock.h ../common/showmsg.h
-txtobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h ../common/mmo.h ../common/db.h ../common/showmsg.h
-txtobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-txtobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-txtobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-txtobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h ../common/socket.h ../common/mmo.h ../common/showmsg.h
-txtobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h ../common/mmo.h ../common/showmsg.h
-txtobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-txtobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h ../common/mmo.h ../common/showmsg.h
-txtobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-txtobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-txtobj/log.o: log.c log.h map.h ../common/nullpo.h
-txtobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
+txtobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h $(COMMON_H)
+txtobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h $(COMMON_H)
+txtobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h $(COMMON_H)
+txtobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h $(COMMON_H)
+txtobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h $(COMMON_H)
+txtobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H)
+txtobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H)
+txtobj/chat.o: chat.c map.h clif.h pc.h chat.h $(COMMON_H)
+txtobj/path.o: path.c map.h battle.h $(COMMON_H)
+txtobj/itemdb.o: itemdb.c map.h battle.h itemdb.h $(COMMON_H)
+txtobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h $(COMMON_H)
+txtobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h $(COMMON_H)
+txtobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h $(COMMON_H)
+txtobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h $(COMMON_H)
+txtobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H)
+txtobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h $(COMMON_H)
+txtobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h $(COMMON_H)
+txtobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h $(COMMON_H)
+txtobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h $(COMMON_H)
+txtobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h $(COMMON_H)
+txtobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h $(COMMON_H)
+txtobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h $(COMMON_H)
+txtobj/log.o: log.c log.h map.h $(COMMON_H)
+txtobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H)
 
-sqlobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h log.h ../common/core.h ../common/timer.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h
-sqlobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-sqlobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/showmsg.h
-sqlobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h log.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h
-sqlobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h
-sqlobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-sqlobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-sqlobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h
-sqlobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h
-sqlobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h
-sqlobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h  log.h ../common/timer.h ../common/socket.h ../common/mmo.h ../common/showmsg.h
-sqlobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h ../common/timer.h ../common/socket.h ../common/db.h ../common/mmo.h ../common/lock.h ../common/showmsg.h
-sqlobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h ../common/mmo.h ../common/db.h ../common/showmsg.h
-sqlobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h log.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-sqlobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-sqlobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-sqlobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h ../common/socket.h ../common/mmo.h ../common/showmsg.h
-sqlobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h log.h ../common/mmo.h ../common/showmsg.h
-sqlobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-sqlobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h log.h ../common/mmo.h ../common/showmsg.h
-sqlobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-sqlobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
-sqlobj/mail.o: mail.c mail.h ../common/showmsg.h ../common/strlib.h ../common/utils.h
-sqlobj/log.o: log.c log.h map.h ../common/nullpo.h
-sqlobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
+sqlobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h log.h $(COMMON_H)
+sqlobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h $(COMMON_H)
+sqlobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h $(COMMON_H)
+sqlobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h log.h $(COMMON_H)
+sqlobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h $(COMMON_H)
+sqlobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H)
+sqlobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H)
+sqlobj/chat.o: chat.c map.h clif.h pc.h chat.h $(COMMON_H)
+sqlobj/path.o: path.c map.h battle.h $(COMMON_H)
+sqlobj/itemdb.o: itemdb.c map.h battle.h itemdb.h $(COMMON_H)
+sqlobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h  log.h $(COMMON_H)
+sqlobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h $(COMMON_H)
+sqlobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h $(COMMON_H)
+sqlobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h log.h $(COMMON_H)
+sqlobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H)
+sqlobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h $(COMMON_H)
+sqlobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h $(COMMON_H)
+sqlobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h log.h $(COMMON_H)
+sqlobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h $(COMMON_H)
+sqlobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h log.h $(COMMON_H)
+sqlobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h $(COMMON_H)
+sqlobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h $(COMMON_H)
+sqlobj/mail.o: mail.c mail.h $(COMMON_H)
+sqlobj/log.o: log.c log.h map.h $(COMMON_H)
+sqlobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H)
 
 clean:
 	rm -rf *.o ../../map-server ../../map-server_sql sqlobj txtobj

+ 50 - 2
src/map/atcommand.c

@@ -9,6 +9,7 @@
 #include "../common/timer.h"
 #include "../common/nullpo.h"
 #include "../common/mmo.h"
+#include "../common/db.h"
 
 #include "log.h"
 #include "clif.h"
@@ -210,6 +211,8 @@ ACMD_FUNC(gmotd); // Added by MC Cameri, created by davidsiaw
 ACMD_FUNC(misceffect); // by MC Cameri
 ACMD_FUNC(mobsearch);
 ACMD_FUNC(cleanmap);
+ACMD_FUNC(npctalk);
+ACMD_FUNC(pettalk);
 ACMD_FUNC(autoloot);  // by Upa-Kun
 
 #ifndef TXT_ONLY
@@ -484,6 +487,8 @@ static AtCommandInfo atcommand_info[] = {
 	{ AtCommand_MiscEffect,			"@misceffect",		50, atcommand_misceffect }, // by MC Cameri
 	{ AtCommand_MobSearch,			"@mobsearch",		 0, atcommand_mobsearch },
 	{ AtCommand_CleanMap,			"@cleanmap",		 0, atcommand_cleanmap },
+	{ AtCommand_NpcTalk,			"@npctalk",			 0,	atcommand_npctalk },
+	{ AtCommand_PetTalk,			"@pettalk",			 0,	atcommand_pettalk },
 
 #ifndef TXT_ONLY // sql-only commands
 	{ AtCommand_CheckMail,			"@checkmail",		 1, atcommand_listmail }, // [Valaris]
@@ -1743,8 +1748,8 @@ int atcommand_whozeny(
 		clif_displaymessage(fd, output);
 	}
 
-	free(zeny);
-	free(counted);
+	aFree(zeny);
+	aFree(counted);
 
 	return 0;
 }
@@ -7789,6 +7794,49 @@ atcommand_cleanmap(
 	return 0;
 }
 
+/*==========================================
+ * NPC/PET‚ɘb‚³‚¹‚é
+ *------------------------------------------
+ */
+int
+atcommand_npctalk(
+	const int fd, struct map_session_data* sd,
+	const char* command, const char* message)
+{
+	char name[100],mes[100];
+	struct npc_data *nd;
+
+	if (sscanf(message, "%s %99[^\n]", name, mes) < 2)
+		return -1;
+
+	if (!(nd = npc_name2id(name)))
+		return -1;
+	
+	clif_message(&nd->bl, mes);
+	return 0;
+}
+int
+atcommand_pettalk(
+	const int fd, struct map_session_data* sd,
+	const char* command, const char* message)
+{
+	char mes[100],temp[100];
+	struct pet_data *pd;
+
+	nullpo_retr(-1, sd);
+
+	if(!sd->status.pet_id || !(pd=sd->pd))
+		return -1;
+
+	if (sscanf(message, "%99[^\n]", mes) < 1)
+		return -1;
+
+	snprintf(temp, sizeof temp ,"%s : %s",sd->pet.name,mes);
+	clif_message(&pd->bl, temp);
+
+	return 0;
+}
+
 /*==========================================
  *
  *------------------------------------------

+ 2 - 0
src/map/atcommand.h

@@ -196,6 +196,8 @@ enum AtCommandType {
 	AtCommand_MiscEffect, // by MC Cameri
 	AtCommand_MobSearch,
 	AtCommand_CleanMap,
+	AtCommand_NpcTalk,
+	AtCommand_PetTalk,
 
 	// SQL-only commands start
 #ifndef TXT_ONLY

+ 9 - 7
src/map/battle.c

@@ -59,15 +59,17 @@ int battle_counttargeted(struct block_list *bl,struct block_list *src,int target
 
 // ダメージの遅延
 struct battle_delay_damage_ {
-	struct block_list *src,*target;
+	struct block_list *src;
+	int target;
 	int damage;
 	int flag;
 };
 int battle_delay_damage_sub(int tid,unsigned int tick,int id,int data)
 {
 	struct battle_delay_damage_ *dat=(struct battle_delay_damage_ *)data;
-	if( dat && map_id2bl(id)==dat->src && dat->target->prev!=NULL)
-		battle_damage(dat->src,dat->target,dat->damage,dat->flag);
+	struct block_list *target=map_id2bl(dat->target);
+	if( dat && map_id2bl(id)==dat->src && target && target->prev!=NULL)
+		battle_damage(dat->src,target,dat->damage,dat->flag);
 	aFree(dat);
 	return 0;
 }
@@ -80,7 +82,7 @@ int battle_delay_damage(unsigned int tick,struct block_list *src,struct block_li
 
 
 	dat->src=src;
-	dat->target=target;
+	dat->target=target->id;
 	dat->damage=damage;
 	dat->flag=flag;
 	add_timer(tick,battle_delay_damage_sub,src->id,(int)dat);
@@ -256,7 +258,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 			flag&BF_SHORT && skill_num != NPC_GUIDEDATTACK) {
 			// セーフティウォール
 			struct skill_unit *unit;
-			unit = map_find_skill_unit_oncell(bl->m,bl->x,bl->y,MG_SAFETYWALL);
+			unit = (struct skill_unit *)sc_data[SC_SAFETYWALL].val2;
 			if (unit) {
 				if (unit->group && (--unit->group->val2)<=0)
 					skill_delunit(unit);
@@ -3501,7 +3503,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 		if(sd && sd->splash_range > 0 && (wd.damage > 0 || wd.damage2 > 0) )
 			skill_castend_damage_id(src,target,0,-1,tick,0);
 		map_freeblock_lock();
-		battle_damage(src,target,(wd.damage+wd.damage2),0);
+		battle_delay_damage(tick+wd.amotion,src,target,(wd.damage+wd.damage2),0);
 		if(target->prev != NULL &&
 			(target->type != BL_PC || (target->type == BL_PC && !pc_isdead((struct map_session_data *)target) ) ) ) {
 			if(wd.damage > 0 || wd.damage2 > 0) {
@@ -3652,7 +3654,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 		}
 
 		if(rdamage > 0)
-			battle_damage(target,src,rdamage,0);
+			battle_delay_damage(tick+wd.amotion,src,target,rdamage,0);
 		if(t_sc_data && t_sc_data[SC_AUTOCOUNTER].timer != -1 && t_sc_data[SC_AUTOCOUNTER].val4 > 0) {
 			if(t_sc_data[SC_AUTOCOUNTER].val3 == src->id)
 				battle_weapon_attack(target,src,tick,0x8000|t_sc_data[SC_AUTOCOUNTER].val1);

+ 11 - 0
src/map/chrif.c

@@ -1011,6 +1011,8 @@ int chrif_disconnect(int fd) {
 		ShowWarning(tmp_output);
 		clif_foreachclient(chrif_disconnect_sub);
 		chrif_connected = 0;
+		// 他のmap 鯖のデータを消す
+		map_eraseallipport();
 	}
 	close(fd);
 	return 0;
@@ -1146,6 +1148,15 @@ int check_connect_char_server(int tid, unsigned int tick, int id, int data) {
 	if (chrif_isconnect()) displayed = 0;
 	return 0;
 }
+/*==========================================
+ * 終了
+ *------------------------------------------
+ */
+int do_final_chrif(void)
+{
+	delete_session(char_fd);
+	return 0;
+}
 
 /*==========================================
  *

+ 1 - 0
src/map/chrif.h

@@ -31,6 +31,7 @@ int chrif_changesex(int id, int sex);
 int chrif_chardisconnect(struct map_session_data *sd);
 int check_connect_char_server(int tid, unsigned int tick, int id, int data);
 
+int do_final_chrif(void);
 int do_init_chrif(void);
 
 int chrif_flush_fifo(void);

+ 8 - 2
src/map/guild.c

@@ -477,8 +477,11 @@ int guild_recv_info(struct guild *sg)
 	// ƒCƒxƒ“ƒg‚Ì”­�¶
 	if( (ev=numdb_search(guild_infoevent_db,sg->guild_id))!=NULL ){
 		numdb_erase(guild_infoevent_db,sg->guild_id);
-		for(;ev;ev2=ev->next,aFree(ev),ev=ev2){
+		while(ev){
 			npc_event_do(ev->name);
+			ev2=ev->next;
+			aFree(ev);
+			ev=ev2;
 		}
 	}
 
@@ -1400,8 +1403,11 @@ int guild_castledataloadack(int castle_id,int index,int value)
 	}
 	if( (ev=numdb_search(guild_castleinfoevent_db,code))!=NULL ){
 		numdb_erase(guild_castleinfoevent_db,code);
-		for(;ev;ev2=ev->next,aFree(ev),ev=ev2){
+		while(ev){
 			npc_event_do(ev->name);
+			ev2=ev->next;
+			aFree(ev);
+			ev=ev2;
 		}
 	}
 	return 1;

+ 12 - 6
src/map/itemdb.c

@@ -379,8 +379,10 @@ static int itemdb_readdb(void)
 			id->equip_script = parse_script((unsigned char *) p,lines);
 		}
 		fclose(fp);
-		sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,filename[i]);
-		ShowStatus(tmp_output);
+		if (ln > 0) {
+			sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,filename[i]);
+			ShowStatus(tmp_output);
+		}
 		ln=0;	// reset to 0
 	}
 	return 0;
@@ -456,8 +458,10 @@ static int itemdb_read_randomitem()
 			ln++;
 		}
 		fclose(fp);
-		sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",*pc,fn);
-		ShowStatus(tmp_output);
+		if (*pc > 0) {
+			sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",*pc,fn);
+			ShowStatus(tmp_output);
+		}
 	}
 
 	return 0;
@@ -699,8 +703,10 @@ static int itemdb_read_noequip(void)
 
 	}
 	fclose(fp);
-	sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/item_noequip.txt");
-	ShowStatus(tmp_output);
+	if (ln > 0) {
+		sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/item_noequip.txt");
+		ShowStatus(tmp_output);
+	}	
 	return 0;
 }
 

+ 122 - 30
src/map/map.c

@@ -403,12 +403,13 @@ int map_count_oncell(int m, int x, int y) {
 /*
  * ォサォ・セェホ��ェヒフクェトェアェソォケォュォ・讚ヒォテォネェ��ケ
  */
-struct skill_unit *map_find_skill_unit_oncell(int m,int x,int y,int skill_id)
+struct skill_unit *map_find_skill_unit_oncell(struct block_list *target,int x,int y,int skill_id,struct skill_unit *out_unit)
 {
-	int bx,by;
+	int m,bx,by;
 	struct block_list *bl;
 	int i,c;
 	struct skill_unit *unit;
+	m = target->m;
 
 	if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys))
 		return NULL;
@@ -421,7 +422,10 @@ struct skill_unit *map_find_skill_unit_oncell(int m,int x,int y,int skill_id)
 		if (bl->x != x || bl->y != y || bl->type != BL_SKILL)
 			continue;
 		unit = (struct skill_unit *) bl;
-		if (unit->alive && unit->group->skill_id == skill_id)
+		if (unit==out_unit || !unit->alive ||
+				!unit->group || unit->group->skill_id!=skill_id)
+			continue;
+		if (battle_check_target(&unit->bl,target,unit->group->target_flag)>0)
 			return unit;
 	}
 	return NULL;
@@ -1622,7 +1626,7 @@ struct map_session_data * map_nick2sd(char *nick) {
 struct block_list * map_id2bl(int id)
 {
 	struct block_list *bl=NULL;
-	if(id<sizeof(objects)/sizeof(objects[0]))
+	if(id >= 0 && id < sizeof(objects)/sizeof(objects[0]))
 		bl = objects[id];
 	else
 		bl = (struct block_list*)numdb_search(id_db,id);
@@ -1826,7 +1830,7 @@ int map_getcell(int m,int x,int y,cell_t cellchk)
 
 int map_getcellp(struct map_data* m,int x,int y,cell_t cellchk)
 {
-	int j;
+	int type;
 	nullpo_ret(m);
 
 	if(x<0 || x>=m->xs-1 || y<0 || y>=m->ys-1)
@@ -1834,24 +1838,28 @@ int map_getcellp(struct map_data* m,int x,int y,cell_t cellchk)
 		if(cellchk==CELL_CHKNOPASS) return 1;
 		return 0;
 	}
-	j=x+y*m->xs;
+	type = m->gat[x+y*m->xs];
+	if (cellchk<0x10)
+		type &= CELL_MASK;
 
 	switch(cellchk)
 	{
 		case CELL_CHKPASS:
-			return (m->gat[j] != 1 && m->gat[j] != 5);
+			return (type!=1 && type!=5);
 		case CELL_CHKNOPASS:
-			return (m->gat[j] == 1 || m->gat[j] == 5);
+			return (type==1 || type==5);
 		case CELL_CHKWALL:
-			return (m->gat[j] == 1);
-		case CELL_CHKNPC:
-			return (m->gat[j]&0x80);
+			return (type==1);
 		case CELL_CHKWATER:
-			return (m->gat[j] == 3);
+			return (type==3);
 		case CELL_CHKGROUND:
-			return (m->gat[j] == 5);
+			return (type==5);
 		case CELL_GETTYPE:
-			return m->gat[j];
+			return type;
+		case CELL_CHKNPC:
+			return (type&CELL_NPC);
+		case CELL_CHKBASILICA:
+			return (type&CELL_BASILICA);
 		default:
 			return 0;
 	}
@@ -1868,10 +1876,20 @@ void map_setcell(int m,int x,int y,int cell)
 		return;
 	j=x+y*map[m].xs;
 
-	if (cell == CELL_SETNPC)
-		map[m].gat[j] |= 0x80;
-	else
-		map[m].gat[j] = cell;
+	switch (cell) {
+		case CELL_SETNPC:
+			map[m].gat[j] |= CELL_NPC;
+			break;
+		case CELL_SETBASILICA:
+			map[m].gat[j] |= CELL_BASILICA;
+			break;
+		case CELL_CLRBASILICA:
+			map[m].gat[j] &= ~CELL_BASILICA;
+			break;
+		default:
+			map[m].gat[j] = (map[m].gat[j]&~CELL_MASK) + cell;
+			break;
+	}
 }
 
 /*==========================================
@@ -1889,15 +1907,39 @@ int map_setipport(char *name,unsigned long ip,int port) {
 		mdos->gat  = NULL;
 		mdos->ip   = ip;
 		mdos->port = port;
+		mdos->map  = NULL;
 		strdb_insert(map_db,mdos->name,mdos);
+	} else if(md->gat){
+		if(ip!=clif_getip() || port!=clif_getport()){
+			// 読み込んでいたけど、担当外になったマップ
+			mdos=(struct map_data_other_server *)aCalloc(1,sizeof(struct map_data_other_server));
+			memcpy(mdos->name,name,24);
+			mdos->gat  = NULL;
+			mdos->ip   = ip;
+			mdos->port = port;
+			mdos->map  = md;
+			strdb_insert(map_db,mdos->name,mdos);
+			// printf("from char server : %s -> %08lx:%d\n",name,ip,port);
+		} else {
+			// 読み込んでいて、担当になったマップ(何もしない)
+			;
+		}
 	} 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;
+		mdos=(struct map_data_other_server *)md;
+		if(ip == clif_getip() && port == clif_getport()) {
+			// 自分の担当になったマップ
+			if(mdos->map == NULL) {
+				// 読み込んでいないので終了する
+				printf("map_setipport : %s is not loaded.\n",name);
+				exit(1);
+			} else {
+				// 読み込んでいるので置き換える
+				md = mdos->map;
+				free(mdos);
+				strdb_insert(map_db,md->name,md);
 			}
-		} else { // update
-			mdos=(struct map_data_other_server *)md;
+		} else {
+			// 他の鯖の担当マップなので置き換えるだけ
 			mdos->ip   = ip;
 			mdos->port = port;
 		}
@@ -1905,6 +1947,56 @@ int map_setipport(char *name,unsigned long ip,int port) {
 	return 0;
 }
 
+/*==========================================
+ * 他鯖管理のマップを全て削除
+ *------------------------------------------
+ */
+int map_eraseallipport_sub(void *key,void *data,va_list va) {
+	struct map_data_other_server *mdos = (struct map_data_other_server*)data;
+	if(mdos->gat == NULL && mdos->map == NULL) {
+		strdb_erase(map_db,key);
+		free(mdos);
+	}
+	return 0;
+}
+
+int map_eraseallipport(void) {
+	strdb_foreach(map_db,map_eraseallipport_sub);
+	return 1;
+}
+
+/*==========================================
+ * 他鯖管理のマップをdbから削除
+ *------------------------------------------
+ */
+int map_eraseipport(char *name,unsigned long ip,int port)
+{
+	struct map_data *md;
+	struct map_data_other_server *mdos;
+//	unsigned char *p=(unsigned char *)&ip;
+
+	md=strdb_search(map_db,name);
+	if(md){
+		if(md->gat) // local -> check data
+			return 0;
+		else {
+			mdos=(struct map_data_other_server *)md;
+			if(mdos->ip==ip && mdos->port == port) {
+				if(mdos->map) {
+					// このマップ鯖でも読み込んでいるので移動できる
+					return 1; // 呼び出し元で chrif_sendmap() をする
+				} else {
+					strdb_erase(map_db,name);
+					free(mdos);
+				}
+//				if(battle_config.etc_log)
+//					printf("erase map %s %d.%d.%d.%d:%d\n",name,p[0],p[1],p[2],p[3],port);
+			}
+		}
+	}
+	return 0;
+}
+
 // 初期化周り
 /*==========================================
  * 水場高さ設定
@@ -2043,7 +2135,7 @@ static void map_cache_close(void)
 		fwrite(map_cache.map,map_cache.head.nmaps,sizeof(struct map_cache_info),map_cache.fp);
 	}
 	fclose(map_cache.fp);
-	free(map_cache.map);
+	aFree(map_cache.map);
 	map_cache.fp = NULL;
 	return;
 }
@@ -2085,16 +2177,16 @@ int map_cache_read(struct map_data *m)
 				if(fread(buf,1,size_compress,map_cache.fp) != size_compress) {
 					// なぜかファイル後半が欠けてるので読み直し
 					printf("fread error\n");
-					m->xs = 0; m->ys = 0; m->gat = NULL;
-					free(m->gat); free(buf);
+					free(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL;
+					free(buf);
 					return 0;
 				}
 				dest_len = m->xs * m->ys;
 				decode_zip(m->gat,&dest_len,buf,size_compress);
 				if(dest_len != map_cache.map[i].xs * map_cache.map[i].ys) {
 					// 正常に解凍が出来てない
-					m->xs = 0; m->ys = 0; m->gat = NULL;
-					free(m->gat); free(buf);
+					free(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL;
+					free(buf);
 					return 0;
 				}
 				free(buf);
@@ -3069,7 +3161,7 @@ void do_final(void) {
     strdb_final(nick_db, nick_db_final);
     numdb_final(charid_db, charid_db_final);
 
-
+	do_final_chrif(); // この内部でキャラを全て切断する
 	do_final_script();
 	do_final_itemdb();
 	do_final_storage();

+ 25 - 14
src/map/map.h

@@ -20,7 +20,7 @@
 #define MAX_STATUSCHANGE 210
 #define MAX_SKILLUNITGROUP 32
 #define MAX_MOBSKILLUNITGROUP 8
-#define MAX_SKILLUNITGROUPTICKSET 128
+#define MAX_SKILLUNITGROUPTICKSET 32
 #define MAX_SKILLTIMERSKILL 32
 #define MAX_MOBSKILLTIMERSKILL 10
 #define MAX_MOBSKILL 32
@@ -85,13 +85,13 @@ struct skill_unit_group {
 	int src_id;
 	int party_id;
 	int guild_id;
-	int map,range;
+	int map;
 	int target_flag;
 	unsigned int tick;
 	int limit,interval;
 
 	int skill_id,skill_lv;
-	int val1,val2;
+	int val1,val2,val3;
 	char *valstr;
 	int unit_id;
 	int group_id;
@@ -582,6 +582,7 @@ struct map_data_other_server {
 	unsigned char *gat;	// NULL固定にして判断
 	unsigned long ip;
 	unsigned int port;
+	struct map_data* map;
 };
 
 struct flooritem_data {
@@ -646,20 +647,29 @@ enum {
 	LOOK_BASE,LOOK_HAIR,LOOK_WEAPON,LOOK_HEAD_BOTTOM,LOOK_HEAD_TOP,LOOK_HEAD_MID,LOOK_HAIR_COLOR,LOOK_CLOTHES_COLOR,LOOK_SHIELD,LOOK_SHOES
 };
 
+// CELL
+#define CELL_MASK		0x0f
+#define CELL_NPC		0x80	// NPCセル
+#define CELL_BASILICA	0x40	// BASILICAセル
 /*
- * map_getcell()ェヌ゙ナ鯑ェオェ��ユォ鬮ー
+ * map_getcell()で使用されるフラグ
  */
 typedef enum { 
-	CELL_CHKWALL=1,		// ロ�(ォサォ�ソォ、ォラ1)
-	CELL_CHKWATER=3,	// 筰洄(ォサォ�ソォ、ォラ3)
-	CELL_CHKGROUND=5,	// �リ�。寬レェ(ォサォ�ソォ、ォラ5)
-	CELL_CHKNPC=0x80,	// ォソォテォチォソォ、ォラェホNPC(ォサォ�ソォ、ォラ0x80ォユォ鬮ー)
-	CELL_CHKPASS,		// �ホヲハヲメ�(ォサォ�ソォ、ォラ1,5�鞣)
-	CELL_CHKNOPASS,		// �ホヲワ�ヲ(ォサォ�ソォ、ォラ1,5)
-	CELL_GETTYPE		// ォサォ�ソォ、ォラェ��ケ
+	CELL_CHKWALL=0,		// 壁(セルタイプ1)
+	CELL_CHKWATER,		// 水場(セルタイプ3)
+	CELL_CHKGROUND,		// 地面障害物(セルタイプ5)
+	CELL_CHKPASS,		// 通過可能(セルタイプ1,5以外)
+	CELL_CHKNOPASS,		// 通過不可(セルタイプ1,5)
+	CELL_GETTYPE,		// セルタイプを返す
+	CELL_CHKNPC=0x10,	// タッチタイプのNPC(セルタイプ0x80フラグ)
+	CELL_CHKBASILICA,	// バジリカ(セルタイプ0x40フラグ)
 } cell_t;
-// map_setcell()ェヌ゙ナ鯑ェオェ��ユォ鬮ー
-#define CELL_SETNPC	0x80	// ォソォテォチォソォ、ォラェホNPCェ�サォテォネ
+// map_setcell()で使用されるフラグ
+enum {
+	CELL_SETNPC=0x10,	// タッチタイプのNPCをセット
+	CELL_SETBASILICA,	// バジリカをセット
+	CELL_CLRBASILICA,	// バジリカをクリア
+};
 
 struct chat_data {
 	struct block_list bl;
@@ -718,7 +728,7 @@ void map_foreachinpath(int (*func)(struct block_list*,va_list),int m,int x0,int
 int map_countnearpc(int,int,int);
 //block関連に追加
 int map_count_oncell(int m,int x,int y);
-struct skill_unit *map_find_skill_unit_oncell(int m,int x,int y,int skill_id);
+struct skill_unit *map_find_skill_unit_oncell(struct block_list *,int x,int y,int skill_id,struct skill_unit *);
 // 一時的object関連
 int map_addobject(struct block_list *);
 int map_delobject(int);
@@ -747,6 +757,7 @@ int map_mapname2mapid(char*);
 int map_mapname2ipport(char*,int*,int*);
 int map_setipport(char *name,unsigned long ip,int port);
 int map_eraseipport(char *name,unsigned long ip,int port);
+int map_eraseallipport(void);
 void map_addiddb(struct block_list *);
 void map_deliddb(struct block_list *bl);
 int map_foreachiddb(int (*)(void*,void*,va_list),...);

+ 37 - 61
src/map/mob.c

@@ -496,10 +496,16 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data)
 		dx = dirx[md->dir];
 		dy = diry[md->dir];
 
-		if(map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKNOPASS)) {
+		if (map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKBASILICA) && !(status_get_mode(&md->bl)&0x20)) {
+			mob_stop_walking(md,1);
+			return 0;
+		}
+
+		if (map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKNOPASS)) {
 			mob_walktoxy_sub(md);
 			return 0;
 		}
+
 		if (skill_check_basilica (&md->bl,x+dx,y+dy) ||
 			skill_check_moonlit (&md->bl,x+dx,y+dy)) {
 			mob_walktoxy_sub(md);
@@ -515,18 +521,18 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data)
 		if(md->min_chase>13)
 			md->min_chase--;
 
+		skill_unit_move(&md->bl,tick,0);
 		if(moveblock) map_delblock(&md->bl);
 		md->bl.x = x;
 		md->bl.y = y;
 		if(moveblock) map_addblock(&md->bl);
+		skill_unit_move(&md->bl,tick,1);
 
 		map_foreachinmovearea(clif_mobinsight,md->bl.m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,-dx,-dy,BL_PC,md);
 		md->state.state=MS_IDLE;
 
 		if(md->option&4)
 			skill_check_cloaking(&md->bl);
-
-		skill_unit_move(&md->bl,tick,1);	// スキルユニットの検査
 	}
 	if((i=calc_next_walk_step(md))>0){
 		i = i>>1;
@@ -712,7 +718,7 @@ int mob_changestate(struct mob_data *md,int state,int type)
 		md->last_deadtime=gettick();
 		// Since it died, all aggressors' attack to this mob is stopped.
 		clif_foreachclient(mob_stopattacked,md->bl.id);
-		skill_unit_out_all(&md->bl,gettick(),1);
+		skill_unit_move(&md->bl,gettick(),0);
 		status_change_clear(&md->bl,2);	// ステータス異常を解除する
 		skill_clear_unitgroup(&md->bl);	// 全てのスキルユニットグループを削除する
 		skill_cleartimerskill(&md->bl);
@@ -789,11 +795,21 @@ static int mob_timer(int tid,unsigned int tick,int id,int data)
 static int mob_walktoxy_sub(struct mob_data *md)
 {
 	struct walkpath_data wpd;
+	int x,y;
+	static int dirx[8]={0,-1,-1,-1,0,1,1,1};
+	static int diry[8]={1,1,0,-1,-1,-1,0,1};
 
 	nullpo_retr(0, md);
 
 	if(path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,md->to_x,md->to_y,md->state.walk_easy))
 		return 1;
+	x = md->bl.x+dirx[wpd.path[0]];
+	y = md->bl.y+diry[wpd.path[0]];
+	if (map_getcell(md->bl.m,x,y,CELL_CHKBASILICA) && !(status_get_mode(&md->bl)&0x20)) {
+		md->state.change_walk_target=0;
+		return 1;
+	}
+
 	memcpy(&md->walkpath,&wpd,sizeof(wpd));
 
 	md->state.change_walk_target=0;
@@ -909,7 +925,7 @@ int mob_spawn(int id)
 	md->last_spawntime=tick;
 	if( md->bl.prev!=NULL ){
 //		clif_clearchar_area(&md->bl,3);
-		skill_unit_out_all(&md->bl,gettick(),1);
+//		skill_unit_move(&md->bl,tick,0);
 		map_delblock(&md->bl);
 	}
 	else
@@ -939,8 +955,6 @@ int mob_spawn(int id)
 	md->dir=0;
 	md->target_dir=0;
 
-	map_addblock(&md->bl);
-
 	memset(&md->state,0,sizeof(md->state));
 	md->attacked_id = 0;
 	md->target_id = 0;
@@ -1003,6 +1017,9 @@ int mob_spawn(int id)
 		md->hp = status_get_max_hp(&md->bl);
 	}
 
+	map_addblock(&md->bl);
+	skill_unit_move(&md->bl,tick,1);
+
 	clif_spawnmob(md);
 
 	return 0;
@@ -2876,6 +2893,7 @@ int mob_warpslave(struct mob_data *md,int x, int y)
 int mob_warp(struct mob_data *md,int m,int x,int y,int type)
 {
 	int i=0,xs=0,ys=0,bx=x,by=y;
+	int tick = gettick();
 
 	nullpo_retr(0, md);
 
@@ -2889,7 +2907,7 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type)
 			return 0;
 		clif_clearchar_area(&md->bl,type);
 	}
-	skill_unit_out_all(&md->bl,gettick(),1);
+	skill_unit_move(&md->bl,tick,0);
 	map_delblock(&md->bl);
 
 	if(bx>0 && by>0){	// 位置指定の場合周囲9セルを探索
@@ -2928,6 +2946,7 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type)
 	}
 
 	map_addblock(&md->bl);
+	skill_unit_move(&md->bl,tick,1);
 	if(type>0)
 	{
 		clif_spawnmob(md);
@@ -3241,59 +3260,16 @@ int mobskill_castend_pos( int tid, unsigned int tick, int id,int data )
 			return 0;
 	}
 
-	if(battle_config.monster_skill_reiteration == 0) {
-		range = -1;
-		switch(md->skillid) {
-			case MG_SAFETYWALL:
-			case WZ_FIREPILLAR:
-			case HT_SKIDTRAP:
-			case HT_LANDMINE:
-			case HT_ANKLESNARE:
-			case HT_SHOCKWAVE:
-			case HT_SANDMAN:
-			case HT_FLASHER:
-			case HT_FREEZINGTRAP:
-			case HT_BLASTMINE:
-			case HT_CLAYMORETRAP:
-			case PF_SPIDERWEB:		/* スパイダーウェッブ */
-				range = 0;
-				break;
-			case AL_PNEUMA:
-			case AL_WARP:
-				range = 1;
-				break;
-		}
-		if(range >= 0) {
-			if(skill_check_unit_range(md->bl.m,md->skillx,md->skilly,range,md->skillid) > 0)
-				return 0;
-		}
-	}
-	if(battle_config.monster_skill_nofootset) {
-		range = -1;
-		switch(md->skillid) {
-			case WZ_FIREPILLAR:
-			case HT_SKIDTRAP:
-			case HT_LANDMINE:
-			case HT_ANKLESNARE:
-			case HT_SHOCKWAVE:
-			case HT_SANDMAN:
-			case HT_FLASHER:
-			case HT_FREEZINGTRAP:
-			case HT_BLASTMINE:
-			case HT_CLAYMORETRAP:
-			case AM_DEMONSTRATION:
-			case PF_SPIDERWEB:		/* スパイダーウェッブ */
-				range = 1;
-				break;
-			case AL_WARP:
-				range = 0;
-				break;
-		}
-		if(range >= 0) {
-			if(skill_check_unit_range2(md->bl.m,md->skillx,md->skilly,range) > 0)
-				return 0;
-		}
-	}
+	if (!battle_config.monster_skill_reiteration &&
+			skill_get_unit_flag(md->skillid)&UF_NOREITERATION &&
+			skill_check_unit_range(md->bl.m,md->skillx,md->skilly,md->skillid,md->skilllv))
+		return 0;
+
+	if(battle_config.monster_skill_nofootset &&
+			skill_get_unit_flag(md->skillid)&UF_NOFOOTSET &&
+			skill_check_unit_range2(md->bl.m,md->skillx,md->skilly,md->skillid,md->skilllv))
+		return 0;
+
 
 	if(battle_config.monster_land_skill_limit) {
 		maxcount = skill_get_maxcount(md->skillid);

+ 1 - 1
src/map/path.c

@@ -273,7 +273,7 @@ int path_search_long(int m,int x0,int y0,int x1,int y1)
 	else
 		weight = abs(y1 - y0);
 
-	while (x0 != x1 && y0 != y1) {
+	while (x0 != x1 || y0 != y1) {
 		if (map_getcellp(md,x0,y0,CELL_CHKWALL))
 			return 0;
 		wx += dx;

+ 65 - 28
src/map/pc.c

@@ -140,6 +140,7 @@ static int pc_invincible_timer(int tid,unsigned int tick,int id,int data) {
 		return 0;
 	}
 	sd->invincible_timer=-1;
+	skill_unit_move(&sd->bl,tick,1);
 
 	return 0;
 }
@@ -160,6 +161,7 @@ int pc_delinvincibletimer(struct map_session_data *sd) {
 		delete_timer(sd->invincible_timer,pc_invincible_timer);
 		sd->invincible_timer = -1;
 	}
+	skill_unit_move(&sd->bl,gettick(),1);
 	return 0;
 }
 
@@ -2244,7 +2246,12 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount)
 		i = pc_search_inventory(sd,0);
 		if(i >= 0) {
 			memcpy(&sd->status.inventory[i],item_data,sizeof(sd->status.inventory[0]));
-			sd->status.inventory[i].amount=amount;
+			if(itemdb_isequip2(data)){
+				sd->status.inventory[i].amount=1;
+				amount=1;
+			} else {
+				sd->status.inventory[i].amount=amount;
+			}
 			sd->inventory_data[i]=data;
 			clif_additem(sd,i,amount,0);
 		}
@@ -2480,7 +2487,12 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
 		for(i=0;i<MAX_CART;i++){
 			if(sd->status.cart[i].nameid==0){
 				memcpy(&sd->status.cart[i],item_data,sizeof(sd->status.cart[0]));
-				sd->status.cart[i].amount=amount;
+				if(itemdb_isequip2(data)){
+					sd->status.inventory[i].amount=1;
+					amount=1;
+				} else {
+					sd->status.inventory[i].amount=amount;
+				}
 				sd->cart_num++;
 				clif_cart_additem(sd,i,amount,0);
 				break;
@@ -2877,6 +2889,13 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
 			status_change_end(&sd->bl,SC_BLADESTOP,-1);
 		if(sd->sc_data[SC_DANCING].timer!=-1) // clear dance effect when warping [Valaris]
 			skill_stop_dancing(&sd->bl,0);
+		if (sd->sc_data[SC_BASILICA].timer!=-1) {
+			int i;
+			for (i=0;i<MAX_SKILLUNITGROUP;i++)
+				if (sd->skillunit[i].skill_id==HP_BASILICA)
+					skill_delunitgroup(&sd->skillunit[i]);
+			status_change_end(&sd->bl,SC_BASILICA,-1);
+		}
 	}
 
 	if(sd->status.option&2)
@@ -2910,7 +2929,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
 			int ip,port;
 			if(map_mapname2ipport(mapname,&ip,&port)==0){
 				skill_stop_dancing(&sd->bl,1);
-				skill_unit_out_all(&sd->bl,gettick(),1);
+				skill_unit_move(&sd->bl,gettick(),0);
 				clif_clearchar_area(&sd->bl,clrtype&0xffff);
 				skill_gangsterparadise(sd,0);
 				map_delblock(&sd->bl);
@@ -2966,7 +2985,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
 	}
 
 	if(sd->mapname[0] && sd->bl.prev != NULL){
-		skill_unit_out_all(&sd->bl,gettick(),1);
+		skill_unit_move(&sd->bl,gettick(),0);
 		clif_clearchar_area(&sd->bl,clrtype&0xffff);
 		skill_gangsterparadise(sd,0);
 		map_delblock(&sd->bl);
@@ -3199,10 +3218,12 @@ static int pc_walk(int tid,unsigned int tick,int id,int data)
 		x += dx;
 		y += dy;
 
+		skill_unit_move(&sd->bl,tick,0);
 		if(moveblock) map_delblock(&sd->bl);
 		sd->bl.x = x;
 		sd->bl.y = y;
 		if(moveblock) map_addblock(&sd->bl);
+		skill_unit_move(&sd->bl,tick,1);
 
 	#if 0
 		if (sd->status.guild_id > 0) {
@@ -3250,20 +3271,15 @@ static int pc_walk(int tid,unsigned int tick,int id,int data)
 			if (sd->sc_data[SC_DEVOTION].val1)
 				skill_devotion2(&sd->bl,sd->sc_data[SC_DEVOTION].val1);
 
-			if (sd->sc_data[SC_BASILICA].timer != -1) { // Basilica cancels if caster moves [celest]
-				struct skill_unit *su;
-				if ((su = (struct skill_unit *)sd->sc_data[SC_BASILICA].val4)) {
-					struct skill_unit_group *sg;
-					if ((sg = su->group) && sg->src_id == sd->bl.id) {
-						status_change_end(&sd->bl,SC_BASILICA,-1);
-						skill_delunitgroup (sg);
-					}
-				}
+			if (sd->sc_data[SC_BASILICA].timer!=-1) { // Basilica cancels if caster moves [celest]
+				int i;
+				for (i=0;i<MAX_SKILLUNITGROUP;i++)
+					if (sd->skillunit[i].skill_id==HP_BASILICA)
+						skill_delunitgroup(&sd->skillunit[i]);
+				status_change_end(&sd->bl,SC_BASILICA,-1);
 			}
 		}
 
-		skill_unit_move(&sd->bl,tick,1);	// スキルユニットの?査
-
 		if(map_getcell(sd->bl.m,x,y,CELL_CHKNPC))
 			npc_touch_areanpc(sd,sd->bl.m,x,y);
 		else
@@ -3420,7 +3436,8 @@ int pc_randomwalk(struct map_session_data *sd,int tick)
 int pc_movepos(struct map_session_data *sd,int dst_x,int dst_y)
 {
 	int moveblock;
-	int dx,dy,dist;
+	int dx,dy;
+	int tick = gettick();
 
 	struct walkpath_data wpd;
 
@@ -3433,16 +3450,17 @@ int pc_movepos(struct map_session_data *sd,int dst_x,int dst_y)
 
 	dx = dst_x - sd->bl.x;
 	dy = dst_y - sd->bl.y;
-	dist = distance(sd->bl.x,sd->bl.y,dst_x,dst_y);
 
 	moveblock = ( sd->bl.x/BLOCK_SIZE != dst_x/BLOCK_SIZE || sd->bl.y/BLOCK_SIZE != dst_y/BLOCK_SIZE);
 
 	map_foreachinmovearea(clif_pcoutsight,sd->bl.m,sd->bl.x-AREA_SIZE,sd->bl.y-AREA_SIZE,sd->bl.x+AREA_SIZE,sd->bl.y+AREA_SIZE,dx,dy,0,sd);
 
+	skill_unit_move(&sd->bl,tick,0);
 	if(moveblock) map_delblock(&sd->bl);
 	sd->bl.x = dst_x;
 	sd->bl.y = dst_y;
 	if(moveblock) map_addblock(&sd->bl);
+	skill_unit_move(&sd->bl,tick,1);
 
 	map_foreachinmovearea(clif_pcinsight,sd->bl.m,sd->bl.x-AREA_SIZE,sd->bl.y-AREA_SIZE,sd->bl.x+AREA_SIZE,sd->bl.y+AREA_SIZE,-dx,-dy,0,sd);
 
@@ -3459,8 +3477,6 @@ int pc_movepos(struct map_session_data *sd,int dst_x,int dst_y)
 	if(sd->status.option&4)	// クロ?キングの消滅?査
 		skill_check_cloaking(&sd->bl);
 
-	skill_unit_move(&sd->bl,gettick(),dist+7);	// スキルユニットの?査
-
 	if(map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNPC))
 		npc_touch_areanpc(sd,sd->bl.m,sd->bl.x,sd->bl.y);
 	else
@@ -3781,7 +3797,7 @@ int pc_attack(struct map_session_data *sd,int target_id,int type)
 		return 0;
 	}
 
-	if(!battle_check_target(&sd->bl,bl,BCT_ENEMY))
+	if(battle_check_target(&sd->bl,bl,BCT_ENEMY) <= 0)
 		return 1;
 	if(sd->attacktimer != -1)
 		pc_stopattack(sd);
@@ -4612,7 +4628,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
 	skill_castcancel(&sd->bl,0);	// 詠唱の中止
 	clif_clearchar_area(&sd->bl,1);
 	pc_setdead(sd);
-	skill_unit_out_all(&sd->bl,gettick(),1);
+	skill_unit_move(&sd->bl,gettick(),0);
 	if(sd->sc_data[SC_BLADESTOP].timer!=-1)//白刃は事前に解除
 		status_change_end(&sd->bl,SC_BLADESTOP,-1);
 	pc_setglobalreg(sd,"PC_DIE_COUNTER",++sd->die_counter); //死にカウンタ?書き?み
@@ -4967,7 +4983,21 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
 		sd->status.status_point = val;
 		break;
 	case SP_ZENY:
-		sd->status.zeny = val;
+		if(val <= MAX_ZENY) {
+			// MAX_ZENY 以下なら代入
+			sd->status.zeny = val;
+		} else {
+			if(sd->status.zeny > val) {
+				// Zeny が減少しているなら代入
+				sd->status.zeny = val;
+			} else if(sd->status.zeny <= MAX_ZENY) {
+				// Zeny が増加していて、現在の値がMAX_ZENY 以下ならMAX_ZENY
+				sd->status.zeny = MAX_ZENY;
+			} else {
+				// Zeny が増加していて、現在の値がMAX_ZENY より下なら増加分を無視
+				;
+			}
+		}
 		break;
 	case SP_BASEEXP:
 		if(pc_nextbaseexp(sd) > 0) {
@@ -5761,6 +5791,7 @@ int pc_setaccountreg2(struct map_session_data *sd,char *reg,int val)
 int pc_eventtimer(int tid,unsigned int tick,int id,int data)
 {
 	struct map_session_data *sd=map_id2sd(id);
+	char *p = (char *)data;
 	int i;
 	if(sd==NULL)
 		return 0;
@@ -5768,11 +5799,11 @@ int pc_eventtimer(int tid,unsigned int tick,int id,int data)
 	for(i=0;i<MAX_EVENTTIMER;i++){
 		if( sd->eventtimer[i]==tid ){
 			sd->eventtimer[i]=-1;
-			npc_event(sd,(const char *)data,0);
+			npc_event(sd,p,0);
 			break;
 		}
 	}
-	aFree((void *)data);
+	aFree(p);
 	if(i==MAX_EVENTTIMER) {
 		if(battle_config.error_log)
 			printf("pc_eventtimer: no such event timer\n");
@@ -5795,8 +5826,9 @@ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name)
 		if( sd->eventtimer[i]==-1 )
 			break;
 	if(i<MAX_EVENTTIMER){
-		char *evname=(char *)aMallocA((strlen(name)+1)*sizeof(char));
-		memcpy(evname,name,(strlen(name)+1));
+		char *evname=strdup(name);
+		//char *evname=(char *)aMallocA((strlen(name)+1)*sizeof(char));
+		//memcpy(evname,name,(strlen(name)+1));
 		sd->eventtimer[i]=add_timer(gettick()+tick,
 			pc_eventtimer,sd->bl.id,(int)evname);
 		sd->eventcount++;
@@ -5819,12 +5851,15 @@ int pc_deleventtimer(struct map_session_data *sd,const char *name)
 		return 0;
 
 	for(i=0;i<MAX_EVENTTIMER;i++)
-		if( sd->eventtimer[i]!=-1 && strcmp(
-			(char *)(get_timer(sd->eventtimer[i])->data), name)==0 ){
+		if( sd->eventtimer[i]!=-1 ) {
+			char *p = (char *)(get_timer(sd->eventtimer[i])->data);
+			if(strcmp(p, name)==0) {
 				delete_timer(sd->eventtimer[i],pc_eventtimer);
 				sd->eventtimer[i]=-1;
 				sd->eventcount--;
+				free(p);
 				break;
+			}
 		}
 
 	return 0;
@@ -5865,8 +5900,10 @@ int pc_cleareventtimer(struct map_session_data *sd)
 
 	for(i=0;i<MAX_EVENTTIMER;i++)
 		if( sd->eventtimer[i]!=-1 ){
+			char *p = (char *)(get_timer(sd->eventtimer[i])->data);
 			delete_timer(sd->eventtimer[i],pc_eventtimer);
 			sd->eventtimer[i]=-1;
+			free(p);
 		}
 
 	return 0;

Різницю між файлами не показано, бо вона завелика
+ 242 - 623
src/map/skill.c


+ 28 - 8
src/map/skill.h

@@ -25,6 +25,12 @@ struct skill_db {
 	int castnodex[MAX_SKILL_LEVEL];
 	int delaynodex[MAX_SKILL_LEVEL];
 	int nocast;
+	int unit_id[2];
+	int unit_layout_type[MAX_SKILL_LEVEL];
+	int unit_range;
+	int unit_interval;
+	int unit_target;
+	int unit_flag;
 };
 extern struct skill_db skill_db[MAX_SKILL_DB];
 
@@ -35,6 +41,24 @@ struct skill_name_db {
 };
 extern const struct skill_name_db skill_names[];
 
+#define MAX_SKILL_UNIT_LAYOUT	50
+#define MAX_SQUARE_LAYOUT		5	// 11*11のユニット配置が最大
+#define MAX_SKILL_UNIT_COUNT ((MAX_SQUARE_LAYOUT*2+1)*(MAX_SQUARE_LAYOUT*2+1))
+struct skill_unit_layout {
+	int count;
+	int dx[MAX_SKILL_UNIT_COUNT];
+	int dy[MAX_SKILL_UNIT_COUNT];
+};
+
+enum {
+	UF_DEFNOTENEMY		= 0x0001,	// defnotenemy 設定でBCT_NOENEMYに切り替え
+	UF_NOREITERATION	= 0x0002,	// 重複置き禁止 
+	UF_NOFOOTSET		= 0x0004,	// 足元置き禁止
+	UF_NOOVERLAP		= 0x0008,	// ユニット効果が重複しない
+	UF_DANCE			= 0x0100,	// ダンススキル
+	UF_ENSEMBLE			= 0x0200,	// 合奏スキル
+};
+
 // アイテム作成デ?タベ?ス
 struct skill_produce_db {
 	int nameid, trigger;
@@ -87,6 +111,7 @@ int skill_get_unit_id(int id,int flag);
 int	skill_get_inf2( int id );
 int	skill_get_maxcount( int id );
 int	skill_get_blewcount( int id ,int lv );
+int	skill_get_unit_flag( int id );
 int	skill_tree_get_max( int id, int b_class );	// Celest
 
 // スキルの使用
@@ -110,10 +135,6 @@ int skill_delunit(struct skill_unit *unit);
 struct skill_unit_group *skill_initunitgroup(struct block_list *src,
 	int count,int skillid,int skilllv,int unit_id);
 int skill_delunitgroup(struct skill_unit_group *group);
-
-struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl,struct skill_unit_group *sg);
-int skill_unitgrouptickset_delete(struct block_list *bl,struct skill_unit_group *sg);
-
 int skill_clear_unitgroup(struct block_list *src);
 
 int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl,
@@ -121,12 +142,12 @@ int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl,
 
 int skill_castfix( struct block_list *bl, int time );
 int skill_delayfix( struct block_list *bl, int time );
-int skill_check_unit_range(int m,int x,int y,int range,int skillid);
-int skill_check_unit_range2(int m,int x,int y,int range);
+int skill_check_unit_range(int m,int x,int y,int skillid, int skilllv);
+int skill_check_unit_range2(int m,int x,int y,int skillid, int skilllv);
 // -- moonsoul	(added skill_check_unit_cell)
 int skill_check_unit_cell(int skillid,int m,int x,int y,int unit_id);
 int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range);
-int skill_unit_move( struct block_list *bl,unsigned int tick,int range);
+int skill_unit_move(struct block_list *bl,unsigned int tick,int flag);
 int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int dy);
 
 struct skill_unit_group *skill_check_dancing( struct block_list *src );
@@ -151,7 +172,6 @@ void skill_devotion_end(struct map_session_data *md,struct map_session_data *sd,
 // その他
 int skill_check_cloaking(struct block_list *bl);
 int skill_type_cloaking(struct block_list *bl);
-int skill_is_danceskill(int id);
 
 // ステ?タス異常
 int skill_encchant_eremental_end(struct block_list *bl, int type);

+ 5 - 26
src/map/status.c

@@ -31,14 +31,17 @@ int SkillStatusChangeTable[]={	/* status.h
 	-1, 1,-1,
 /* 10- */
 	SC_SIGHT,			/* サイト */
-	-1,-1,-1,-1,
+	-1,
+	SC_SAFETYWALL,		/* セーフティーウォール */
+	-1,-1,-1,
 	SC_FREEZE,			/* フロストダイバ? */
 	SC_STONE,			/* スト?ンカ?ス */
 	-1,-1,-1,
 /* 20- */
 	-1,-1,-1,-1,
 	SC_RUWACH,			/* ルアフ */
-	-1,-1,-1,-1,
+	SC_PNEUMA,			/* ニューマ */
+	-1,-1,-1,
 	SC_INCREASEAGI,		/* 速度?加 */
 /* 30- */
 	SC_DECREASEAGI,		/* 速度減少 */
@@ -3585,15 +3588,6 @@ int status_change_start(struct block_list *bl,int type,int val1,int val2,int val
 		case SC_ANKLE:
 			break;
 
-		/* ウォ?タ?ボ?ル */
-		case SC_WATERBALL:
-			tick=150;
-			if(val1>5) //レベルが5以上の場合は25?に制限(1?目はすでに打ってるので-1)
-				val3=5*5-1;
-			else
-				val3= (val1|1)*(val1|1)-1;
-			break;
-
 		/* スキルじゃない/時間に?係しない */
 		case SC_RIDING:
 			calc_flag = 1;
@@ -4361,21 +4355,6 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
 		}
 		break;
 
-	case SC_WATERBALL:	/* ウォ?タ?ボ?ル */
-		{
-			struct block_list *target=map_id2bl(sc_data[type].val2);
-			if (!target || !target->prev)
-				break;	// target has been killed in previous hits, no need to raise an alarm ^^;
-			// nullpo_retb(target);
-			// nullpo_retb(target->prev);
-			skill_attack(BF_MAGIC,bl,bl,target,WZ_WATERBALL,sc_data[type].val1,tick,0);
-			if((--sc_data[type].val3)>0) {
-				sc_data[type].timer=add_timer( 150+tick,status_change_timer, bl->id, data );
-				return 0;
-			}
-		}
-		break;
-
 	case SC_ENDURE:	/* インデュア */
 	case SC_AUTOBERSERK: // Celest
 		if(sd && sd->special_state.infinite_endure) {

+ 1 - 1
src/map/status.h

@@ -111,7 +111,7 @@ enum {	// struct map_session_data 
 //-- 137-139
 	SC_SAFETYWALL		= 140,
 	SC_PNEUMA			= 141,
-	SC_WATERBALL		= 142,
+//-- 142
 	SC_ANKLE			= 143,
 	SC_DANCING			= 144,
 	SC_KEEPING			= 145,

+ 1 - 1
src/txt-converter/char/Makefile

@@ -1,7 +1,7 @@
 all: char-converter
 sql: char-converter
 
-COMMON_OBJ = ../../common/core.o ../../common/socket.o ../../common/timer.o ../../common/grfio.o ../../common/db.o ../../common/lock.o ../../common/nullpo.o ../../common/malloc.o ../../common/showmsg.o ../../common/strlib.o
+COMMON_OBJ = ../../common/obj/core.o ../../common/obj/socket.o ../../common/obj/timer.o ../../common/obj/grfio.o ../../common/obj/db.o ../../common/obj/lock.o ../../common/obj/nullpo.o ../../common/obj/malloc.o ../../common/obj/showmsg.o ../../common/obj/strlib.o
 
 char-converter: char-converter.o $(COMMON_OBJ)
 	$(CC) -o ../../../$@ $^ $(LIB_S)

+ 1 - 1
src/txt-converter/login/Makefile

@@ -1,7 +1,7 @@
 all: login-converter
 sql: login-converter
 
-COMMON_OBJ = ../../common/core.o ../../common/socket.o ../../common/timer.o ../../common/grfio.o ../../common/db.o ../../common/lock.o ../../common/nullpo.o ../../common/malloc.o ../../common/showmsg.o ../../common/strlib.o
+COMMON_OBJ = ../../common/obj/core.o ../../common/obj/socket.o ../../common/obj/timer.o ../../common/obj/grfio.o ../../common/obj/db.o ../../common/obj/lock.o ../../common/obj/nullpo.o ../../common/obj/malloc.o ../../common/obj/showmsg.o ../../common/obj/strlib.o
 
 COMMON_H = ../../common/core.h ../../common/socket.h ../../common/timer.h ../../common/mmo.h ../../common/version.h ../../common/db.h ../../common/malloc.h ../../common/strlib.h
 

Деякі файли не було показано, через те що забагато файлів було змінено