summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcelest <celest@54d463be-8e91-2dee-dedb-b68131a5f0ec>2005-02-22 16:08:24 +0000
committercelest <celest@54d463be-8e91-2dee-dedb-b68131a5f0ec>2005-02-22 16:08:24 +0000
commitf65bf4bd28cd9240c889bfd2a1f4650d91760a2d (patch)
tree6730a4d5ca802cc2c4cdb128dca07f1e95cac0fb /src
parent6b0b62a5b2a9d85f60afe4fe048403101bd8f39d (diff)
downloadhercules-f65bf4bd28cd9240c889bfd2a1f4650d91760a2d.tar.gz
hercules-f65bf4bd28cd9240c889bfd2a1f4650d91760a2d.tar.bz2
hercules-f65bf4bd28cd9240c889bfd2a1f4650d91760a2d.tar.xz
hercules-f65bf4bd28cd9240c889bfd2a1f4650d91760a2d.zip
* 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://rathena.svn.sourceforge.net/svnroot/rathena/branches/stable@1162 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src')
-rw-r--r--src/char/Makefile2
-rw-r--r--src/char_sql/Makefile2
-rw-r--r--src/common/Makefile34
-rw-r--r--src/common/core.c74
-rw-r--r--src/common/db.c20
-rw-r--r--src/common/db.h10
-rw-r--r--src/common/grfio.c55
-rw-r--r--src/common/malloc.c484
-rw-r--r--src/common/malloc.h8
-rw-r--r--src/ladmin/Makefile2
-rw-r--r--src/login/Makefile2
-rw-r--r--src/login_sql/Makefile2
-rw-r--r--src/map/Makefile102
-rw-r--r--src/map/atcommand.c52
-rw-r--r--src/map/atcommand.h2
-rw-r--r--src/map/battle.c16
-rw-r--r--src/map/chrif.c11
-rw-r--r--src/map/chrif.h1
-rw-r--r--src/map/guild.c10
-rw-r--r--src/map/itemdb.c18
-rw-r--r--src/map/map.c152
-rw-r--r--src/map/map.h39
-rw-r--r--src/map/mob.c98
-rw-r--r--src/map/path.c2
-rw-r--r--src/map/pc.c93
-rw-r--r--src/map/skill.c2820
-rw-r--r--src/map/skill.h36
-rw-r--r--src/map/status.c31
-rw-r--r--src/map/status.h2
-rw-r--r--src/txt-converter/char/Makefile2
-rw-r--r--src/txt-converter/login/Makefile2
31 files changed, 2181 insertions, 2003 deletions
diff --git a/src/char/Makefile b/src/char/Makefile
index 3c09db92c..aee0e69e2 100644
--- a/src/char/Makefile
+++ b/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)
diff --git a/src/char_sql/Makefile b/src/char_sql/Makefile
index e206dd211..1741b5ab6 100644
--- a/src/char_sql/Makefile
+++ b/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)
diff --git a/src/common/Makefile b/src/common/Makefile
index eaa7205d2..c387c2e01 100644
--- a/src/common/Makefile
+++ b/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
diff --git a/src/common/core.c b/src/common/core.c
index fbd607080..016ade08d 100644
--- a/src/common/core.c
+++ b/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;
}
diff --git a/src/common/db.c b/src/common/db.c
index 12d54176c..9f2c75a68 100644
--- a/src/common/db.c
+++ b/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);
}
diff --git a/src/common/db.h b/src/common/db.h
index ea9aceab0..c31f5bfaa 100644
--- a/src/common/db.h
+++ b/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);
diff --git a/src/common/grfio.c b/src/common/grfio.c
index 0c628d163..224ea909e 100644
--- a/src/common/grfio.c
+++ b/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");
diff --git a/src/common/malloc.c b/src/common/malloc.c
index 089a9db18..40c9f34bf 100644
--- a/src/common/malloc.c
+++ b/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
diff --git a/src/common/malloc.h b/src/common/malloc.h
index d90665487..45451c9e0 100644
--- a/src/common/malloc.h
+++ b/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
diff --git a/src/ladmin/Makefile b/src/ladmin/Makefile
index ebe67a349..20722350b 100644
--- a/src/ladmin/Makefile
+++ b/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)
diff --git a/src/login/Makefile b/src/login/Makefile
index 482503969..01810b1d1 100644
--- a/src/login/Makefile
+++ b/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)
diff --git a/src/login_sql/Makefile b/src/login_sql/Makefile
index 18b023fe6..20b01c66d 100644
--- a/src/login_sql/Makefile
+++ b/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)
diff --git a/src/map/Makefile b/src/map/Makefile
index 884e8b902..b413c8a62 100644
--- a/src/map/Makefile
+++ b/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
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 12e6c2306..3169c75ab 100644
--- a/src/map/atcommand.c
+++ b/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;
}
@@ -7790,6 +7795,49 @@ atcommand_cleanmap(
}
/*==========================================
+ * NPC/PETに話させる
+ *------------------------------------------
+ */
+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;
+}
+
+/*==========================================
*
*------------------------------------------
*/
diff --git a/src/map/atcommand.h b/src/map/atcommand.h
index cb260db19..ea6849476 100644
--- a/src/map/atcommand.h
+++ b/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
diff --git a/src/map/battle.c b/src/map/battle.c
index 707362f7f..605fd30e0 100644
--- a/src/map/battle.c
+++ b/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);
diff --git a/src/map/chrif.c b/src/map/chrif.c
index a04c483d5..bbc6a51e5 100644
--- a/src/map/chrif.c
+++ b/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;
+}
/*==========================================
*
diff --git a/src/map/chrif.h b/src/map/chrif.h
index 7f55d23d6..03ff83f6a 100644
--- a/src/map/chrif.h
+++ b/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);
diff --git a/src/map/guild.c b/src/map/guild.c
index d0d7f14dd..ea9c3795f 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -477,8 +477,11 @@ int guild_recv_info(struct guild *sg)
// イベントの発生
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;
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 41e2e2a75..82149946d 100644
--- a/src/map/itemdb.c
+++ b/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;
}
diff --git a/src/map/map.c b/src/map/map.c
index ee597789c..d402ac06c 100644
--- a/src/map/map.c
+++ b/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();
diff --git a/src/map/map.h b/src/map/map.h
index 2963a316e..96cbc9fb3 100644
--- a/src/map/map.h
+++ b/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),...);
diff --git a/src/map/mob.c b/src/map/mob.c
index 74a1c5889..9b2f91da1 100644
--- a/src/map/mob.c
+++ b/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);
diff --git a/src/map/path.c b/src/map/path.c
index dae7fc59a..92ea4941e 100644
--- a/src/map/path.c
+++ b/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;
diff --git a/src/map/pc.c b/src/map/pc.c
index 416e05f97..0a5ef8a67 100644
--- a/src/map/pc.c
+++ b/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;
diff --git a/src/map/skill.c b/src/map/skill.c
index 9ae3e2ba4..3d3411b16 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -556,6 +556,12 @@ int skill_get_mhp( int id ,int lv ){ skill_get (skill_db[id].mhp[lv-1], id, lv);
int skill_get_castnodex( int id ,int lv ){ skill_get (skill_db[id].castnodex[lv-1], id, lv); }
int skill_get_delaynodex( int id ,int lv ){ skill_get (skill_db[id].delaynodex[lv-1], id, lv); }
int skill_get_nocast ( int id ){ skill_get (skill_db[id].nocast, id, 1); }
+int skill_get_unit_id ( int id, int flag ){ skill_get (skill_db[id].unit_id[flag], id, 1); }
+int skill_get_unit_layout_type( int id ,int lv ){ skill_get (skill_db[id].unit_layout_type[lv-1], id, lv); }
+int skill_get_unit_interval( int id ){ skill_get (skill_db[id].unit_interval, id, 1); }
+int skill_get_unit_range( int id ){ skill_get (skill_db[id].unit_range, id, 1); }
+int skill_get_unit_target( int id ){ skill_get (skill_db[id].unit_target, id, 1); }
+int skill_get_unit_flag( int id ){ skill_get (skill_db[id].unit_flag, id, 1); }
int skill_tree_get_max(int id, int b_class){
struct pc_base_job s_class = pc_calc_base_job(b_class);
@@ -577,6 +583,9 @@ int skill_clear_element_field(struct block_list *bl);
int skill_landprotector(struct block_list *bl, va_list ap );
int skill_trap_splash(struct block_list *bl, va_list ap );
int skill_count_target(struct block_list *bl, va_list ap );
+struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl,struct skill_unit_group *sg,int tick);
+int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int tick);
+int skill_unit_effect(struct block_list *bl,va_list ap);
// [MouseJstr] - skill ok to cast? and when?
int skillnotok(int skillid, struct map_session_data *sd)
@@ -635,96 +644,53 @@ static int distance(int x0,int y0,int x1,int y1)
return dx>dy ? dx : dy;
}
-/* スキルユニットIDを返す(これもデ?タベ?スに入れたいな) */
-int skill_get_unit_id(int id,int flag)
+/* スキルユニットの配置情報を返す */
+struct skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT];
+int firewall_unit_pos;
+int icewall_unit_pos;
+
+struct skill_unit_layout *skill_get_unit_layout(int skillid,int skilllv,struct block_list *src,int x,int y)
{
+
+ int pos = skill_get_unit_layout_type(skillid,skilllv);
+ int dir;
- switch(id){
- case MG_SAFETYWALL: return 0x7e; /* セイフティウォ?ル */
- case MG_FIREWALL: return 0x7f; /* ファイア?ウォ?ル */
- case AL_WARP: return (flag==0)?0x81:0x80; /* ワ?プポ?タル */
- case PR_BENEDICTIO: return 0x82; /* 聖?降福 */
- case PR_SANCTUARY: return 0x83; /* サンクチュアリ */
- case PR_MAGNUS: return 0x84; /* マグヌスエクソシズム */
- case AL_PNEUMA: return 0x85; /* ニュ?マ */
- case MG_THUNDERSTORM: return 0x86; /* サンダ?スト?ム */
- case WZ_HEAVENDRIVE: return 0x86; /* ヘヴンズドライブ */
- case WZ_SIGHTRASHER: return 0x86; /* サイトラッシャ? */
- case WZ_METEOR: return 0x86; /* メテオスト?ム */
- case WZ_VERMILION: return 0x86; /* ロ?ドオブヴァ?ミリオン */
- //case WZ_FROSTNOVA: return 0x86; /* フロストノヴァ */
- case WZ_STORMGUST: return 0x86; /* スト?ムガスト(とりあえずLoVと同じで?理) */
- case CR_GRANDCROSS: return 0x86; /* グランドクロス */
- case NPC_DARKGRANDCROSS: return 0x86; /*闇グランドクロス*/
- case WZ_FIREPILLAR: return (flag==0)?0x87:0x88; /* ファイア?ピラ? */
- case HT_TALKIEBOX: return 0x99; /* ト?キ?ボックス */
- case WZ_ICEWALL: return 0x8d; /* アイスウォ?ル */
- case WZ_QUAGMIRE: return 0x8e; /* クァグマイア */
- case HT_BLASTMINE: return 0x8f; /* ブラストマイン */
- case HT_SKIDTRAP: return 0x90; /* スキッドトラップ */
- case HT_ANKLESNARE: return 0x91; /* アンクルスネア */
- case AS_VENOMDUST: return 0x92; /* ベノムダスト */
- case HT_LANDMINE: return 0x93; /* ランドマイン */
- case HT_SHOCKWAVE: return 0x94; /* ショックウェ?ブトラップ */
- case HT_SANDMAN: return 0x95; /* サンドマン */
- case HT_FLASHER: return 0x96; /* フラッシャ? */
- case HT_FREEZINGTRAP: return 0x97; /* フリ?ジングトラップ */
- case HT_CLAYMORETRAP: return 0x98; /* クレイモア?トラップ */
- case SA_VOLCANO: return 0x9a; /* ボルケ?ノ */
- case SA_DELUGE: return 0x9b; /* デリュ?ジ */
- case SA_VIOLENTGALE: return 0x9c; /* バイオレントゲイル */
- case SA_LANDPROTECTOR: return 0x9d; /* ランドプロテクタ? */
- case BD_LULLABY: return 0x9e; /* 子守歌 */
- case BD_RICHMANKIM: return 0x9f; /* ニヨルドの宴 */
- case BD_ETERNALCHAOS: return 0xa0; /* 永遠の混沌 */
- case BD_DRUMBATTLEFIELD:return 0xa1; /* ?太鼓の響き */
- case BD_RINGNIBELUNGEN: return 0xa2; /* ニ?ベルングの指輪 */
- case BD_ROKISWEIL: return 0xa3; /* ロキの叫び */
- case BD_INTOABYSS: return 0xa4; /* 深淵の中に */
- case BD_SIEGFRIED: return 0xa5; /* 不死身のジ?クフリ?ド */
- case BA_DISSONANCE: return 0xa6; /* 不協和音 */
- case BA_WHISTLE: return 0xa7; /* 口笛 */
- case BA_ASSASSINCROSS: return 0xa8; /* 夕陽のアサシンクロス */
- case BA_POEMBRAGI: return 0xa9; /* ブラギの詩 */
- case BA_APPLEIDUN: return 0xaa; /* イドゥンの林檎 */
- case DC_UGLYDANCE: return 0xab; /* 自分勝手なダンス */
- case DC_HUMMING: return 0xac; /* ハミング */
- case DC_DONTFORGETME: return 0xad; /* 私を忘れないで… */
- case DC_FORTUNEKISS: return 0xae; /* 幸運のキス */
- case DC_SERVICEFORYOU: return 0xaf; /* サ?ビスフォ?ユ? */
- case RG_GRAFFITI: return 0xb0; /* グラフィティ */
- case AM_DEMONSTRATION: return 0xb1; /* デモンストレ?ション */
- case WE_CALLPARTNER: return 0xb2; /* あなたに逢いたい */
- case PA_GOSPEL: return 0xb3; /* ゴスペル */
- case HP_BASILICA: return 0xb4; /* バジリカ */
-// case CG_MOONLIT: return 0xb5;
- case PF_FOGWALL: return 0xb6; /* フォグウォ?ル */
- case PF_SPIDERWEB: return 0xb7; /* スパイダ?ウェッブ */
- // temporary unit ID's [Celest]
- case GD_LEADERSHIP: return 0xc1;
- case GD_GLORYWOUNDS: return 0xc2;
- case GD_SOULCOLD: return 0xc3;
- case GD_HAWKEYES: return 0xc4;
- }
- return 0;
- /*
- 0x89,0x8a,0x8b 表示無し
- 0x9a 炎?性の詠唱みたいなエフェクト
- 0x9b 水?性の詠唱みたいなエフェクト
- 0x9c 風?性の詠唱みたいなエフェクト
- 0x9d 白い小さなエフェクト
- 0xb1 Alchemist Demonstration
- 0xb2 = Pink Warp Portal
- 0xb3 = Gospel For Paladin
- 0xb4 = Basilica
- 0xb5 = Empty
- 0xb6 = Fog Wall for Professor
- 0xb7 = Spider Web for Professor
- 0xb8 = Empty
- 0xb9 =
- */
+ if (pos!=-1)
+ return &skill_unit_layout[pos];
+
+ if (src->x==x && src->y==y)
+ dir = 2;
+ else
+ dir = map_calc_dir(src,x,y);
+
+ if (skillid==MG_FIREWALL)
+ return &skill_unit_layout[firewall_unit_pos+dir];
+ else if (skillid==WZ_ICEWALL)
+ return &skill_unit_layout[icewall_unit_pos+dir];
+
+ printf("unknown unit layout for skill %d, %d\n",skillid,skilllv);
+ return &skill_unit_layout[0];
}
+// case GD_LEADERSHIP: return 0xc1;
+// case GD_GLORYWOUNDS: return 0xc2;
+// case GD_SOULCOLD: return 0xc3;
+// case GD_HAWKEYES: return 0xc4;
+// 0x89,0x8a,0x8b 表示無し
+// 0x9a 炎?性の詠唱みたいなエフェクト
+// 0x9b 水?性の詠唱みたいなエフェクト
+// 0x9c 風?性の詠唱みたいなエフェクト
+// 0x9d 白い小さなエフェクト
+// 0xb1 Alchemist Demonstration
+// 0xb2 = Pink Warp Portal
+// 0xb3 = Gospel For Paladin
+// 0xb4 = Basilica
+// 0xb5 = Empty
+// 0xb6 = Fog Wall for Professor
+// 0xb7 = Spider Web for Professor
+// 0xb8 = Empty
+// 0xb9 =
+
/*==========================================
* スキル追加?果
*------------------------------------------
@@ -1162,16 +1128,16 @@ int skill_blown( struct block_list *src, struct block_list *target,int count)
nullpo_retr(0, target);
if(target->type==BL_PC){
- nullpo_retr(0, sd=(struct map_session_data *)target);
+ sd=(struct map_session_data *)target;
}else if(target->type==BL_MOB){
- nullpo_retr(0, md=(struct mob_data *)target);
+ md=(struct mob_data *)target;
}else if(target->type==BL_PET){
- nullpo_retr(0, pd=(struct pet_data *)target);
+ pd=(struct pet_data *)target;
}else if(target->type==BL_SKILL){
- nullpo_retr(0, su=(struct skill_unit *)target);
+ su=(struct skill_unit *)target;
}else return 0;
- if(!(count&0x10000 && (sd||md||pd||su))){ /* 指定なしなら位置?係から方向を求める */
+ if(!(count&0x10000)){ /* 指定なしなら位置関係から方向を求める */
dx=target->x-src->x; dx=(dx>0)?1:((dx<0)?-1: 0);
dy=target->y-src->y; dy=(dy>0)?1:((dy<0)?-1: 0);
}
@@ -1228,18 +1194,13 @@ int skill_blown( struct block_list *src, struct block_list *target,int count)
if(su){
skill_unit_move_unit_group(su->group,target->m,dx,dy);
}else{
-// struct status_change *sc_data=status_get_sc_data(target);
- if(moveblock) map_delblock(target);
- target->x=nx;
- target->y=ny;
- if(moveblock) map_addblock(target);
-/*ダンス中にエフェクトは移動しないらしい
- if(sc_data && sc_data[SC_DANCING].timer!=-1){ //?象がダンス中なのでエフェクトも移動
- struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[SC_DANCING].val2;
- if(sg)
- skill_unit_move_unit_group(sg,target->m,dx,dy);
- }
-*/
+ int tick = gettick();
+ skill_unit_move(target,tick,0);
+ if(moveblock) map_delblock(target);
+ target->x=nx;
+ target->y=ny;
+ if(moveblock) map_addblock(target);
+ skill_unit_move(target,tick,1);
}
if(sd) { /* ?面?に入ってきたので表示 */
@@ -1258,8 +1219,6 @@ int skill_blown( struct block_list *src, struct block_list *target,int count)
pd->state.state = prev_state;
}
- skill_unit_move(target,gettick(),(count&0xffff)+7); /* スキルユニットの判定 */
-
return 0;
}
@@ -1480,9 +1439,6 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
//武器スキル?ここまで
switch(skillid){
- case WZ_SIGHTRASHER:
- clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, 5);
- break;
case AS_SPLASHER:
clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, -1, 5);
break;
@@ -1495,11 +1451,9 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
default:
clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, (skillid==0)? 5:type );
}
- if(dmg.blewcount > 0 && !map[src->m].flag.gvg) { /* 吹き飛ばし?理とそのパケット */
- if(skillid == WZ_SIGHTRASHER)
- skill_blown(src,bl,dmg.blewcount);
- else
- skill_blown(dsrc,bl,dmg.blewcount);
+ /* 吹き飛ばし処理とそのパケット */
+ if (dmg.blewcount > 0 && bl->type!=BL_SKILL && !map[src->m].flag.gvg) {
+ skill_blown(dsrc,bl,dmg.blewcount);
if(bl->type == BL_MOB)
clif_fixmobpos((struct mob_data *)bl);
else if(bl->type == BL_PET)
@@ -1510,8 +1464,12 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
map_freeblock_lock();
/* ?際にダメ?ジ?理を行う */
- if(skillid || flag)
- battle_damage(src,bl,damage,0);
+ if (skillid || flag) {
+ if (attack_type&BF_WEAPON)
+ battle_delay_damage(tick+dmg.amotion,src,bl,damage,0);
+ else
+ battle_damage(src,bl,damage,0);
+ }
if(skillid == RG_INTIMIDATE && damage > 0 && !(status_get_mode(bl)&0x20) && !map[src->m].flag.gvg ) {
int s_lv = status_get_lv(src),t_lv = status_get_lv(bl);
int rate = 50 + skilllv * 5;
@@ -1594,8 +1552,12 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
battle_heal(NULL,bl,0,-sp,0);
}
- if((skillid || flag) && rdamage > 0)
- battle_damage(bl,src,rdamage,0);
+ if ((skillid || flag) && rdamage>0) {
+ if (attack_type&BF_WEAPON)
+ battle_delay_damage(tick+dmg.amotion,bl,src,rdamage,0);
+ else
+ battle_damage(bl,src,rdamage,0);
+ }
if(attack_type&BF_WEAPON && sc_data && sc_data[SC_AUTOCOUNTER].timer != -1 && sc_data[SC_AUTOCOUNTER].val4 > 0) {
if(sc_data[SC_AUTOCOUNTER].val3 == dsrc->id)
@@ -1647,9 +1609,8 @@ int skill_area_sub( struct block_list *bl,va_list ap )
static int skill_check_unit_range_sub( struct block_list *bl,va_list ap )
{
struct skill_unit *unit;
- int *c,x,y,range,sx[4],sy[4];
- int t_range,tx[4],ty[4];
- int i,r_flag,skillid;
+ int *c;
+ int skillid,unit_id;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
@@ -1662,57 +1623,46 @@ static int skill_check_unit_range_sub( struct block_list *bl,va_list ap )
if(!unit->alive)
return 0;
- x = va_arg(ap,int);
- y = va_arg(ap,int);
- range = va_arg(ap,int);
skillid = va_arg(ap,int);
+ unit_id = unit->group->unit_id;
- if(skillid == MG_SAFETYWALL || skillid == AL_PNEUMA) {
- if(unit->group->unit_id != 0x7e && unit->group->unit_id != 0x85)
+ if (skillid==MG_SAFETYWALL || skillid==AL_PNEUMA) {
+ if(unit_id != 0x7e && unit_id != 0x85)
return 0;
- }
- else if(skillid == AL_WARP) {
- if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92)
+ } else if (skillid==AL_WARP) {
+ if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92)
return 0;
- }
- else if((skillid >= HT_SKIDTRAP && skillid <= HT_CLAYMORETRAP) || skillid == HT_TALKIEBOX) {
- if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92)
+ } else if ((skillid>=HT_SKIDTRAP && skillid<=HT_CLAYMORETRAP) || skillid==HT_TALKIEBOX) {
+ if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92)
return 0;
- }
- else if(skillid == WZ_FIREPILLAR) {
- if(unit->group->unit_id != 0x87)
+ } else if (skillid==WZ_FIREPILLAR) {
+ if (unit_id!=0x87)
return 0;
- }
- else return 0;
- t_range=(unit->range!=0)? unit->range:unit->group->range;
- tx[0] = tx[3] = unit->bl.x - t_range;
- tx[1] = tx[2] = unit->bl.x + t_range;
- ty[0] = ty[1] = unit->bl.y - t_range;
- ty[2] = ty[3] = unit->bl.y + t_range;
- sx[0] = sx[3] = x - range;
- sx[1] = sx[2] = x + range;
- sy[0] = sy[1] = y - range;
- sy[2] = sy[3] = y + range;
- for(i=r_flag=0;i<4;i++) {
- if(sx[i] >= tx[0] && sx[i] <= tx[1] && sy[i] >= ty[0] && sy[i] <= ty[2]) {
- r_flag = 1;
- break;
- }
- if(tx[i] >= sx[0] && tx[i] <= sx[1] && ty[i] >= sy[0] && ty[i] <= sy[2]) {
- r_flag = 1;
- break;
- }
- }
- if(r_flag) (*c)++;
+ } else if (skillid==HP_BASILICA) {
+ if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92 && unit_id!=0x83)
+ return 0;
+ } else
+ return 0;
+
+ (*c)++;
return 0;
}
-int skill_check_unit_range(int m,int x,int y,int range,int skillid)
+int skill_check_unit_range(int m,int x,int y,int skillid,int skilllv)
{
int c = 0;
+ int range = skill_get_unit_range(skillid);
+ int layout_type = skill_get_unit_layout_type(skillid,skilllv);
+ if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) {
+ printf("skill_check_unit_range: unsupported layout type %d for skill %d\n",layout_type,skillid);
+ return 0;
+ }
- map_foreachinarea(skill_check_unit_range_sub,m,x-10,y-10,x+10,y+10,BL_SKILL,&c,x,y,range,skillid);
+ // とりあえず正方形のユニットレイアウトのみ対応
+ range += layout_type;
+ map_foreachinarea(skill_check_unit_range_sub,m,
+ x-range,y-range,x+range,y+range,BL_SKILL,&c,skillid);
return c;
}
@@ -1720,6 +1670,8 @@ int skill_check_unit_range(int m,int x,int y,int range,int skillid)
static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap )
{
int *c;
+ int skillid;
+
nullpo_retr(0, bl);
nullpo_retr(0, ap);
@@ -1731,16 +1683,29 @@ static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap )
if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))
return 0;
+ skillid = va_arg(ap,int);
+ if (skillid==HP_BASILICA && bl->type==BL_PC)
+ return 0;
+
(*c)++;
return 0;
}
-int skill_check_unit_range2(int m,int x,int y,int range)
+int skill_check_unit_range2(int m,int x,int y,int skillid, int skilllv)
{
int c = 0;
+ int range = skill_get_unit_range(skillid);
+ int layout_type = skill_get_unit_layout_type(skillid,skilllv);
+ if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) {
+ printf("skill_check_unit_range2: unsupported layout type %d for skill %d\n",layout_type,skillid);
+ return 0;
+ }
- map_foreachinarea(skill_check_unit_range2_sub,m,x-range,y-range,x+range,y+range,0,&c);
+ // とりあえず正方形のユニットレイアウトのみ対応
+ range += layout_type;
+ map_foreachinarea(skill_check_unit_range2_sub,m,
+ x-range,y-range,x+range,y+range,0,&c,skillid);
return c;
}
@@ -1758,6 +1723,27 @@ int skill_area_sub_count(struct block_list *src,struct block_list *target,int sk
return 0;
}
+int skill_count_water(struct block_list *src,int range)
+{
+ int i,x,y,cnt = 0,size = range*2+1;
+ struct skill_unit *unit;
+
+ for (i=0;i<size*size;i++) {
+ x = src->x+(i%size-range);
+ y = src->y+(i/size-range);
+ if (map_getcell(src->m,x,y,CELL_CHKWATER)) {
+ cnt++;
+ continue;
+ }
+ unit = map_find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL);
+ if (unit) {
+ cnt++;
+ skill_delunit(unit);
+ }
+ }
+ return cnt;
+}
+
/*==========================================
*
*------------------------------------------
@@ -1877,6 +1863,14 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data )
src->x+range,src->y+range,0,src,skl->skill_id,skl->skill_lv,tick);
break;
+ case WZ_WATERBALL:
+ if (skl->type>1) {
+ skl->timer = 0; // skill_addtimerskillで使用されないように
+ skill_addtimerskill(src,tick+150,target->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag);
+ skl->timer = -1;
+ }
+ skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
+ break;
default:
skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
break;
@@ -2047,7 +2041,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
if(sd && pc_isdead(sd))
return 1;
- if((skillid == WZ_SIGHTRASHER || skillid == CR_GRANDCROSS || skillid == NPC_DARKGRANDCROSS) && src != bl)
+ if((skillid == CR_GRANDCROSS || skillid == NPC_DARKGRANDCROSS) && src != bl)
bl = src;
if(bl->prev == NULL)
return 1;
@@ -2445,8 +2439,17 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
case WZ_WATERBALL: /* ウォ?タ?ボ?ル */
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
- if(skilllv>1)
- status_change_start(src,SC_WATERBALL,skilllv,bl->id,0,0,0,0);
+ if (skilllv>1) {
+ int cnt,range;
+ range = skilllv>5?2:skilllv/2;
+ if (sd)
+ cnt = skill_count_water(src,range)-1;
+ else
+ cnt = skill_get_num(skillid,skilllv)-1;
+ if (cnt>0)
+ skill_addtimerskill(src,tick+150,bl->id,0,0,
+ skillid,skilllv,cnt,flag);
+ }
break;
case PR_BENEDICTIO: /* 聖?降福 */
@@ -2457,6 +2460,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
/* 魔法系範?攻?スキル */
case MG_NAPALMBEAT: /* ナパ?ムビ?ト */
case MG_FIREBALL: /* ファイヤ?ボ?ル */
+ case WZ_SIGHTRASHER: /* サイトラッシャー */
if(flag&1){
/* 個別にダメ?ジを?える */
if(bl->id!=skill_area_temp[1]){
@@ -2469,27 +2473,46 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
skill_area_temp[0]| 0x0500);
}
}else{
- int ar=(skillid==MG_NAPALMBEAT)?1:2;
+ int ar;
+ skill_area_temp[0]=0;
skill_area_temp[1]=bl->id;
- if(skillid==MG_NAPALMBEAT){ /* ナパ?ムでは先に?える */
- skill_area_temp[0]=0;
- map_foreachinarea(skill_area_sub,
- bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
- src,skillid,skilllv,tick, flag|BCT_ENEMY ,
- skill_area_sub_count);
- }else{
- skill_area_temp[0]=0;
- skill_area_temp[2]=bl->x;
- skill_area_temp[3]=bl->y;
+ switch (skillid) {
+ case MG_NAPALMBEAT:
+ ar = 1;
+ /* ナパームビートは分散ダメージなので敵の数を数える */
+ map_foreachinarea(skill_area_sub,
+ bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0,
+ src,skillid,skilllv,tick,flag|BCT_ENEMY,
+ skill_area_sub_count);
+ break;
+ case MG_FIREBALL:
+ ar = 2;
+ skill_area_temp[2]=bl->x;
+ skill_area_temp[3]=bl->y;
+ /* ターゲットに攻撃を加える(スキルエフェクト表示) */
+ skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
+ skill_area_temp[0]);
+ break;
+ case WZ_SIGHTRASHER:
+ default:
+ ar = 3;
+ bl = src;
+ status_change_end(src,SC_SIGHT,-1);
+ break;
}
- /* まずタ?ゲットに攻?を加える */
- skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
- skill_area_temp[0] );
- /* その後タ?ゲット以外の範??の敵全?に?理を行う */
+ if (skillid==WZ_SIGHTRASHER) {
+ /* スキルエフェクト表示 */
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ } else {
+ /* ターゲットに攻撃を加える(スキルエフェクト表示) */
+ skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
+ skill_area_temp[0]);
+ }
+ /* ターゲット以外の範囲内の敵全体に処理を行う */
map_foreachinarea(skill_area_sub,
- bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0,
- src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
- skill_castend_damage_id);
+ bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0,
+ src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
+ skill_castend_damage_id);
}
break;
@@ -2528,12 +2551,6 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
map_foreachinarea(skill_attack_area,src->m,src->x-5,bl->y-5,bl->x+5,bl->y+5,0,BF_MAGIC,src,src,skillid,skilllv,tick,flag,BCT_ENEMY);
break;
- case WZ_SIGHTRASHER:
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0);
- status_change_end(src,SC_SIGHT,-1);
- break;
-
/* その他 */
case HT_BLITZBEAT: /* ブリッツビ?ト */
if(flag&1){
@@ -4688,7 +4705,6 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
nullpo_retr(0, sd=(struct map_session_data *)src);
}
if( skillid != WZ_METEOR &&
- skillid != WZ_SIGHTRASHER &&
skillid != AM_CANNIBALIZE &&
skillid != AM_SPHEREMINE)
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
@@ -4739,7 +4755,6 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
case AL_PNEUMA: /* ニュ?マ */
case WZ_ICEWALL: /* アイスウォ?ル */
case WZ_FIREPILLAR: /* ファイアピラ? */
- case WZ_SIGHTRASHER:
case WZ_QUAGMIRE: /* クァグマイア */
case WZ_VERMILION: /* ロ?ドオブヴァ?ミリオン */
//case WZ_FROSTNOVA: /* フロストノヴァ */
@@ -5007,349 +5022,137 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma
struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag)
{
struct skill_unit_group *group;
- int i,count=1,limit=10000,val1=0,val2=0;
- int target=BCT_ENEMY,interval=1000,range=0;
- int dir=0,aoe_diameter=0; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills
+ int i,limit,val1=0,val2=0,val3=0;
+ int count=0;
+ int target,interval,range,unit_flag;
+ struct skill_unit_layout *layout;
struct status_change *sc_data;
nullpo_retr(0, src);
+ limit = skill_get_time(skillid,skilllv);
+ range = skill_get_unit_range(skillid);
+ interval = skill_get_unit_interval(skillid);
+ target = skill_get_unit_target(skillid);
+ unit_flag = skill_get_unit_flag(skillid);
+ layout = skill_get_unit_layout(skillid,skilllv,src,x,y);
+
+ if (unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy)
+ target = BCT_NOENEMY;
+
sc_data = status_get_sc_data(src); // for firewall and fogwall - celest
switch(skillid){ /* 設定 */
case MG_SAFETYWALL: /* セイフティウォ?ル */
- limit=skill_get_time(skillid,skilllv);
val2=skilllv+1;
- interval = -1;
- target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL;
break;
-
case MG_FIREWALL: /* ファイヤ?ウォ?ル */
- if(src->x == x && src->y == y)
- dir = 2;
- else
- dir=map_calc_dir(src,x,y);
- if(dir&1) count=5;
- else count=3;
- limit=skill_get_time(skillid,skilllv);
- if(sc_data) {
- if (sc_data[SC_VIOLENTGALE].timer!=-1) limit = limit*3/2;
- }
- // check for sc_data first - Celest
- // if (((struct map_session_data *)src)->sc_data[SC_VIOLENTGALE].timer!=-1)
- // limit *= 1.5;
+ if(sc_data && sc_data[SC_VIOLENTGALE].timer!=-1)
+ limit = limit*3/2;
val2=4+skilllv;
- interval=1;
- break;
-
- case AL_PNEUMA: /* ニュ?マ */
- limit=skill_get_time(skillid,skilllv);
- interval = -1;
- target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL;
- count = 9;
break;
case AL_WARP: /* ワ?プポ?タル */
- target=BCT_ALL;
val1=skilllv+6;
if(flag==0)
limit=2000;
- else
- limit=skill_get_time(skillid,skilllv);
break;
case PR_SANCTUARY: /* サンクチュアリ */
- count=21;
- limit=skill_get_time(skillid,skilllv);
val1=(skilllv+3)*2;
val2=(skilllv>6)?777:skilllv*100;
- target=BCT_ALL;
- range=1;
- break;
-
- case PR_MAGNUS: /* マグヌスエクソシズム */
- count=33;
- limit=skill_get_time(skillid,skilllv);
- interval=3000;
+ interval += 500;
break;
case WZ_FIREPILLAR: /* ファイア?ピラ? */
- if(flag==0)
- limit=skill_get_time(skillid,skilllv);
- else
+ if(flag!=0)
limit=1000;
- interval=2000;
val1=skilllv+2;
- if(skilllv < 6)
- range=1;
- else
+ if(skilllv >= 6)
range=2;
break;
- case MG_THUNDERSTORM: /* サンダ?スト?ム */
- limit=500;
- range=1;
- break;
-
- //case WZ_FROSTNOVA: /* フロストノヴァ */
- // limit=500;
- // range=5;
- // break;
-
- case WZ_HEAVENDRIVE: /* ヘヴンズドライブ */
- limit=500;
- range=2;
- break;
-
- case WZ_METEOR: /* メテオスト?ム */
- limit=500;
- range=3;
- break;
-
- case WZ_SIGHTRASHER:
- limit=500;
- count=41;
- break;
-
- case WZ_VERMILION: /* ロ?ドオブヴァ?ミリオン */
- limit=4100;
- interval=1000;
- range=6;
- break;
-
- case WZ_ICEWALL: /* アイスウォ?ル */
- limit=skill_get_time(skillid,skilllv);
- count=5;
- break;
-
- case WZ_STORMGUST: /* スト?ムガスト */
- limit=4600;
- interval=450;
- range=5;
- break;
-
- case WZ_QUAGMIRE: /* クァグマイア */
- limit=skill_get_time(skillid,skilllv);
- interval=200;
- count=25;
- break;
-
case HT_SANDMAN: /* サンドマン */
case HT_CLAYMORETRAP: /* クレイモア?トラップ */
- limit=skill_get_time(skillid,skilllv);
- // longer trap times in WOE [celest]
- if (map[src->m].flag.gvg) limit *= 4;
- range=2;
- break;
case HT_SKIDTRAP: /* スキッドトラップ */
case HT_LANDMINE: /* ランドマイン */
case HT_ANKLESNARE: /* アンクルスネア */
- case PF_SPIDERWEB: /* スパイダ?ウェッブ */
case HT_FLASHER: /* フラッシャ? */
case HT_FREEZINGTRAP: /* フリ?ジングトラップ */
case HT_BLASTMINE: /* ブラストマイン */
- limit=skill_get_time(skillid,skilllv);
// longer trap times in WOE [celest]
- if (skillid != PF_SPIDERWEB && map[src->m].flag.gvg)
- limit *= 4;
- range=1;
- break;
-
- case HT_TALKIEBOX: /* ト?キ?ボックス */
- limit=skill_get_time(skillid,skilllv);
- range=1;
- target=BCT_ALL;
+ if (map[src->m].flag.gvg) limit *= 4;
break;
-
case HT_SHOCKWAVE: /* ショックウェ?ブトラップ */
- limit=skill_get_time(skillid,skilllv);
- range=1;
val1=skilllv*15+10;
break;
- case AS_VENOMDUST: /* ベノムダスト */
- limit=skill_get_time(skillid,skilllv);
- interval=1000;
- count=5;
- break;
-
- case CR_GRANDCROSS: /* グランドクロス */
- case NPC_DARKGRANDCROSS: /*闇グランドクロス*/
- count=29;
- limit=1000;
- interval=300;
- break;
-
- case SA_VOLCANO: /* ボルケ?ノ */
- case SA_DELUGE: /* デリュ?ジ */
- case SA_VIOLENTGALE: /* バイオレントゲイル */
- limit=skill_get_time(skillid,skilllv);
- //count=skilllv<=2?25:(skilllv<=4?49:81);
- count=49;
- target=BCT_ALL;
- break;
-
case SA_LANDPROTECTOR: /* グランドクロス */
- limit=skill_get_time(skillid,skilllv); // changed to get duration from cast_db (moonsoul)
- val1=skilllv*15+10;
- aoe_diameter=skilllv+skilllv%2+5;
- target=BCT_ALL;
- count=aoe_diameter*aoe_diameter; // -- this will not function if changed to ^2 (moonsoul)
- break;
-
- case BD_LULLABY: /* 子守唄 */
- case BD_ETERNALCHAOS: /* エタ?ナルカオス */
- case BD_ROKISWEIL: /* ロキの叫び */
- count=81;
- limit=skill_get_time(skillid,skilllv);
- range=5;
- target=(skillid==BD_ETERNALCHAOS ? BCT_ENEMY : BCT_ALL);
- break;
- case BD_RICHMANKIM:
- case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */
- case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */
- case BD_INTOABYSS: /* 深淵の中に */
- case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */
- count=81;
- limit=skill_get_time(skillid,skilllv);
- range=5;
- target=BCT_PARTY;
+ {
+ int aoe_diameter; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills
+ val1=skilllv*15+10;
+ aoe_diameter=skilllv+skilllv%2+5;
+ count=aoe_diameter*aoe_diameter; // -- this will not function if changed to ^2 (moonsoul)
+ }
break;
case BA_WHISTLE: /* 口笛 */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=3;
- target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1;
val2 = ((status_get_agi(src)/10)&0xffff)<<16;
val2 |= (status_get_luk(src)/10)&0xffff;
break;
case DC_HUMMING: /* ハミング */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=3;
- target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
val2 = status_get_dex(src)/10;
break;
-
- case BA_DISSONANCE: /* 不協和音 */
- case DC_UGLYDANCE: /* 自分勝手なダンス */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=3;
- target=BCT_ENEMY;
- break;
-
case DC_DONTFORGETME: /* 私を忘れないで… */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=3;
- target=BCT_ENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
val2 = ((status_get_str(src)/20)&0xffff)<<16;
val2 |= (status_get_agi(src)/10)&0xffff;
break;
case BA_POEMBRAGI: /* ブラギの詩 */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=3;
- target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON);
val2 = ((status_get_dex(src)/10)&0xffff)<<16;
val2 |= (status_get_int(src)/5)&0xffff;
break;
case BA_APPLEIDUN: /* イドゥンの林檎 */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=3;
- target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = ((pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON))&0xffff)<<16;
- else
- val1 = 0;
- val1 |= (status_get_vit(src))&0xffff;
- val2 = 0;//回復用タイムカウンタ(6秒?に1?加)
+ val2 |= (status_get_vit(src))&0xffff;
+ val3 = 0;//回復用タイムカウンタ(6秒?に1?加)
break;
case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=3;
- target=BCT_PARTY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
val2 = status_get_int(src)/10;
break;
case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=3;
- target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1;
val2 = status_get_agi(src)/20;
break;
case DC_FORTUNEKISS: /* 幸運のキス */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=3;
- target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
val2 = status_get_luk(src)/10;
break;
- case AM_DEMONSTRATION: /* デモンストレ?ション */
- limit=skill_get_time(skillid,skilllv);
- interval=1000;
- range=1;
- target=BCT_ENEMY;
- break;
-
- case WE_CALLPARTNER: /* あなたに逢いたい */
- limit=skill_get_time(skillid,skilllv);
- range=-1;
- break;
-
case HP_BASILICA: /* バジリカ */
- limit=skill_get_time(skillid,skilllv);
- target=BCT_ALL;
- range=3;
//Fix to prevent the priest from walking while Basilica is up.
battle_stopwalking(src,1);
- //status_change_start(src,SC_ANKLE,skilllv,0,0,0,limit,0);
- //sd->canmove_tick = gettick() + limit; // added later [celest]
- break;
-
- case PA_GOSPEL: /* ゴスペル */
- count=49;
- target=BCT_PARTY;
- limit=skill_get_time(skillid,skilllv);
break;
-/* case CG_MOONLIT:
- range=1;
- target=BCT_ALL;
- limit=skill_get_time(skillid,skilllv);
- break;*/
-
case PF_FOGWALL: /* フォグウォ?ル */
- count=15;
- limit=skill_get_time(skillid,skilllv);
- if(sc_data) {
- if (sc_data[SC_DELUGE].timer!=-1) limit *= 2;
- }
+ if(sc_data && sc_data[SC_DELUGE].timer!=-1) limit *= 2;
break;
case RG_GRAFFITI: /* Graffiti */
count=1; // Leave this at 1 [Valaris]
- limit=600000; // Time length [Valaris]
break;
case GD_LEADERSHIP:
@@ -5360,20 +5163,16 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,
target=BCT_ALL;
limit=300000;
break;
-
- default:
- if(battle_config.error_log)
- printf ("skill_unitsetting: Unknown skill id = %d\n",skillid);
- return 0;
}
- nullpo_retr(NULL, group=skill_initunitgroup(src,count,skillid,skilllv,skill_get_unit_id(skillid,flag&1)));
+ nullpo_retr(NULL, group=skill_initunitgroup(src,(count > 0 ? count : layout->count),
+ skillid,skilllv,skill_get_unit_id(skillid,flag&1)));
group->limit=limit;
group->val1=val1;
group->val2=val2;
+ group->val3=val3;
group->target_flag=target;
group->interval=interval;
- group->range=range;
if(skillid==HT_TALKIEBOX ||
skillid==RG_GRAFFITI){
group->valstr=aCallocA(80, 1);
@@ -5383,200 +5182,20 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,
}
memcpy(group->valstr,talkie_mes,80);
}
- for(i=0;i<count;i++){
+ for(i=0;i<layout->count;i++){
struct skill_unit *unit;
- int ux=x,uy=y,val1=skilllv,val2=0,limit=group->limit,alive=1;
- int range=group->range;
- switch(skillid){ /* 設定 */
- case AL_PNEUMA: /* ニュ?マ */
- {
- static const int dx[9]={-1, 0, 1,-1, 0, 1,-1, 0, 1};
- static const int dy[9]={-1,-1,-1, 0, 0, 0, 1, 1, 1};
- ux+=dx[i];
- uy+=dy[i];
- }
- break;
+ int ux,uy,val1=skilllv,val2=0,limit=group->limit,alive=1;
+ ux = x + layout->dx[i];
+ uy = y + layout->dy[i];
+ switch (skillid) {
case MG_FIREWALL: /* ファイヤ?ウォ?ル */
- {
- if(dir&1){ /* 斜め配置 */
- static const int dx[][5]={
- { 1,1,0,0,-1 }, { -1,-1,0,0,1 },
- },dy[][5]={
- { 1,0,0,-1,-1 }, { 1,0,0,-1,-1 },
- };
- ux+=dx[(dir>>1)&1][i];
- uy+=dy[(dir>>1)&1][i];
- }else{ /* 上下配置 */
- if(dir%4==0) /* 上下 */
- ux+=i-1;
- else /* 左右 */
- uy+=i-1;
- }
- val2=group->val2;
- }
- break;
-
- case PR_SANCTUARY: /* サンクチュアリ */
- {
- static const int dx[]={
- -1,0,1, -2,-1,0,1,2, -2,-1,0,1,2, -2,-1,0,1,2, -1,0,1 };
- static const int dy[]={
- -2,-2,-2, -1,-1,-1,-1,-1, 0,0,0,0,0, 1,1,1,1,1, 2,2,2, };
- ux+=dx[i];
- uy+=dy[i];
- }
- break;
-
- case PR_MAGNUS: /* マグヌスエクソシズム */
- {
- static const int dx[]={ -1,0,1, -1,0,1, -3,-2,-1,0,1,2,3,
- -3,-2,-1,0,1,2,3, -3,-2,-1,0,1,2,3, -1,0,1, -1,0,1, };
- static const int dy[]={
- -3,-3,-3, -2,-2,-2, -1,-1,-1,-1,-1,-1,-1,
- 0,0,0,0,0,0,0, 1,1,1,1,1,1,1, 2,2,2, 3,3,3 };
- ux+=dx[i];
- uy+=dy[i];
- }
+ val2=group->val2;
break;
-
- case WZ_SIGHTRASHER:
- {
- static const int dx[]={
- -5, 0, 5, -4, 0, 4, -3, 0, 3, -2, 0, 2, -1, 0, 1, -5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, -1, 0, 1, -2, 0, 2, -3, 0, 3, -4, 0, 4, -5, 0, 5 };
- static const int dy[]={
- -5,-5,-5, -4,-4,-4, -3,-3,-3, -2,-2,-2, -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 };
- ux+=dx[i];
- uy+=dy[i];
- }
- break;
-
case WZ_ICEWALL: /* アイスウォ?ル */
- {
- static const int dirx[8]={0,-1,-1,-1,0,1,1,1};
- static const int diry[8]={1,1,0,-1,-1,-1,0,1};
if(skilllv <= 1)
val1 = 500;
else
val1 = 200 + 200*skilllv;
- if(src->x == x && src->y == y)
- dir = 2;
- else
- dir=map_calc_dir(src,x,y);
- ux+=(2-i)*diry[dir];
- uy+=(i-2)*dirx[dir];
- }
- break;
-
- case WZ_QUAGMIRE: /* クァグマイア */
- ux+=(i%5-2);
- uy+=(i/5-2);
- if(i==12)
- range=2;
- else
- range=-1;
-
- break;
-
- case AS_VENOMDUST: /* ベノムダスト */
- {
- static const int dx[]={-1,0,0,0,1};
- static const int dy[]={0,-1,0,1,0};
- ux+=dx[i];
- uy+=dy[i];
- }
- break;
-
- case CR_GRANDCROSS: /* グランドクロス */
- case NPC_DARKGRANDCROSS: /*闇グランドクロス*/
- {
- static const int dx[]={
- 0, 0, -1,0,1, -2,-1,0,1,2, -4,-3,-2,-1,0,1,2,3,4, -2,-1,0,1,2, -1,0,1, 0, 0, };
- static const int dy[]={
- -4, -3, -2,-2,-2, -1,-1,-1,-1,-1, 0,0,0,0,0,0,0,0,0, 1,1,1,1,1, 2,2,2, 3, 4, };
- ux+=dx[i];
- uy+=dy[i];
- }
- break;
- case SA_VOLCANO: /* ボルケ?ノ */
- case SA_DELUGE: /* デリュ?ジ */
- case SA_VIOLENTGALE: /* バイオレントゲイル */
- {
- int u_range=0,central=0;
- if(skilllv<=2){
- u_range=2;
- central=12;
- }else if(skilllv<=4){
- u_range=3;
- central=24;
- }else if(skilllv>=5){
- u_range=4;
- central=40;
- }
- ux+=(i%(u_range*2+1)-u_range);
- uy+=(i/(u_range*2+1)-u_range);
-
- if(i==central)
- range=u_range;//中央のユニットの?果範?は全範?
- else
- range=-1;//中央以外のユニットは飾り
- }
- break;
- case SA_LANDPROTECTOR: /* ランドプロテクタ? */
- {
- int u_range=0;
-
- if(skilllv<=2) u_range=3;
- else if(skilllv<=4) u_range=4;
- else if(skilllv>=5) u_range=5;
-
- ux+=(i%(u_range*2+1)-u_range);
- uy+=(i/(u_range*2+1)-u_range);
-
- range=0;
- }
- break;
-
- /* ダンスなど */
- case BD_LULLABY: /* 子守歌 */
- case BD_RICHMANKIM: /* ニヨルドの宴 */
- case BD_ETERNALCHAOS: /* 永遠の混沌 */
- case BD_DRUMBATTLEFIELD:/* ?太鼓の響き */
- case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */
- case BD_ROKISWEIL: /* ロキの叫び */
- case BD_INTOABYSS: /* 深淵の中に */
- case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */
- ux+=(i%9-4);
- uy+=(i/9-4);
- if(i==40)
- range=4; /* 中心の場合は範?を4にオ?バ?ライド */
- else
- range=-1; /* 中心じゃない場合は範?を-1にオ?バ?ライド */
- break;
- case BA_DISSONANCE: /* 不協和音 */
- case BA_WHISTLE: /* 口笛 */
- case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
- case BA_POEMBRAGI: /* ブラギの詩 */
- case BA_APPLEIDUN: /* イドゥンの林檎 */
- case DC_UGLYDANCE: /* 自分勝手なダンス */
- case DC_HUMMING: /* ハミング */
- case DC_DONTFORGETME: /* 私を忘れないで… */
- case DC_FORTUNEKISS: /* 幸運のキス */
- case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */
-// case CG_MOONLIT:
- ux+=(i%7-3);
- uy+=(i/7-3);
- if(i==40)
- range=4; /* 中心の場合は範?を4にオ?バ?ライド */
- else
- range=-1; /* 中心じゃない場合は範?を-1にオ?バ?ライド */
- break;
- case PA_GOSPEL: /* ゴスペル */
- ux+=(i%7-3);
- uy+=(i/7-3);
- break;
- case PF_FOGWALL: /* フォグウォ?ル */
- ux+=(i%5-2);
- uy+=(i/5-1);
break;
case RG_GRAFFITI: /* Graffiti [Valaris] */
ux+=(i%5-2);
@@ -5603,7 +5222,7 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,
unit->val2=val2;
unit->limit=limit;
unit->range=range;
-
+
// [celest]
if (sc_data) {
// attach the unit's id to the caster
@@ -5642,6 +5261,10 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,
break;
}
}
+ if (range==0)
+ map_foreachinarea(skill_unit_effect,unit->bl.m
+ ,unit->bl.x,unit->bl.y,unit->bl.x,unit->bl.y
+ ,0,&unit->bl,gettick(),1);
}
}
return group;
@@ -5655,123 +5278,284 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
{
struct skill_unit_group *sg;
struct block_list *ss;
- struct skill_unit_group_tickset *ts;
- struct map_session_data *srcsd=NULL;
- int diff,goflag,splash_count=0;
+ struct skill_unit *unit2;
struct status_change *sc_data;
+ int type;
nullpo_retr(0, src);
nullpo_retr(0, bl);
- sc_data = status_get_sc_data(bl);
-
- if( bl->prev==NULL || !src->alive || (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl) ) )
+
+ if(bl->prev==NULL || !src->alive ||
+ (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)))
return 0;
nullpo_retr(0, sg=src->group);
nullpo_retr(0, ss=map_id2bl(sg->src_id));
+
+ sc_data = status_get_sc_data(bl);
+ type = SkillStatusChangeTable[sg->skill_id];
- if(ss->type == BL_PC)
- nullpo_retr(0, srcsd=(struct map_session_data *)ss);
- if(srcsd && srcsd->chatID)
+ if (battle_check_target(&src->bl,bl,sg->target_flag)<=0)
return 0;
- if( bl->type != BL_PC && bl->type != BL_MOB )
+ // 対象がLP上に居る場合は無効
+ if (map_find_skill_unit_oncell(bl,bl->x,bl->y,SA_LANDPROTECTOR,NULL))
return 0;
- nullpo_retr(0, ts = skill_unitgrouptickset_search(bl, sg));
- diff=DIFF_TICK(tick,ts->tick);
- goflag=(diff>sg->interval || diff<0);
- if (sg->skill_id == CR_GRANDCROSS && !battle_config.gx_allhit) // 重なっていたら3HITしない
- goflag = (diff>sg->interval*map_count_oncell(bl->m,bl->x,bl->y) || diff<0);
- //?象がLP上に居る場合は無?
- map_foreachinarea(skill_landprotector,bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,0,&goflag);
+ switch (sg->unit_id) {
+ case 0x85: /* ニューマ */
+ case 0x7e: /* セイフティウォール */
+ if (sc_data && sc_data[type].timer == -1)
+ status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
+ break;
- if(!goflag)
- return 0;
- ts->tick=tick;
+ case 0x80: /* ワープポータル(発動後) */
+ if(bl->type==BL_PC){
+ struct map_session_data *sd = (struct map_session_data *)bl;
+ if(sd && src->bl.m == bl->m && src->bl.x == bl->x && src->bl.y == bl->y &&
+ src->bl.x == sd->to_x && src->bl.y == sd->to_y) {
+ if( battle_config.chat_warpportal || !sd->chatID ){
+ pc_setpos(sd,sg->valstr,sg->val2>>16,sg->val2&0xffff,3);
+ if(sg->src_id == bl->id || (strcmp(map[src->bl.m].name,sg->valstr) == 0 &&
+ src->bl.x == (sg->val2>>16) && src->bl.y == (sg->val2&0xffff) ))
+ skill_delunitgroup(sg);
+ if (--sg->val1<=0)
+ skill_delunitgroup(sg);
+ }
+ }
+ } else if(bl->type==BL_MOB && battle_config.mob_warpportal){
+ int m = map_mapname2mapid(sg->valstr);
+ mob_warp((struct mob_data *)bl,m,sg->val2>>16,sg->val2&0xffff,3);
+ }
+ break;
- switch(sg->unit_id){
- case 0x83: /* サンクチュアリ */
- {
- int race=status_get_race(bl);
- int damage_flag = (battle_check_undead(race,status_get_elem_type(bl)) || race == 6)? 1:0;
+ case 0x8e: /* クァグマイア */
+ if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ break;
+ if(sc_data && sc_data[type].timer==-1)
+ status_change_start(bl,type,sg->skill_lv,(int)src,0,0,
+ skill_get_time2(sg->skill_id,sg->skill_lv),0);
+ break;
- if( status_get_hp(bl)>=status_get_max_hp(bl) && !damage_flag)
+ case 0x9a: /* ボルケ?ノ */
+ case 0x9b: /* デリュ?ジ */
+ case 0x9c: /* バイオレントゲイル */
+ if (sc_data && sc_data[type].timer!=-1) {
+ unit2 = (struct skill_unit *)sc_data[type].val4;
+ if (unit2 && unit2->group &&
+ (unit2==src || DIFF_TICK(sg->tick,unit2->group->tick)<=0))
break;
-
- if((sg->val1--)<=0){
- skill_delunitgroup(sg);
- return 0;
- }
- if(!damage_flag) {
- int heal=sg->val2;
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage)
- heal=0; /* ?金蟲カ?ド(ヒ?ル量0) */
- clif_skill_nodamage(&src->bl,bl,AL_HEAL,heal,1);
- battle_heal(NULL,bl,heal,0,0);
- }
- else {
- // reduce healing count if this was meant for damaging [celest]
- sg->val1 /= 2;
- skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
- }
}
+ status_change_start(bl,type,sg->skill_lv,(int)src,0,0,
+ skill_get_time2(sg->skill_id,sg->skill_lv),0);
break;
- case 0x84: /* マグヌスエクソシズム */
- {
- int race=status_get_race(bl);
- int damage_flag = (battle_check_undead(race,status_get_elem_type(bl)) || race == 6)? 1:0;
+ case 0x9e: /* 子守唄 */
+ case 0x9f: /* ニヨルドの宴 */
+ case 0xa0: /* 永遠の混沌 */
+ case 0xa1: /* ?太鼓の響き */
+ case 0xa2: /* ニ?ベルングの指輪 */
+ case 0xa3: /* ロキの叫び */
+ case 0xa4: /* 深淵の中に */
+ case 0xa5: /* 不死身のジ?クフリ?ド */
+ case 0xa6: /* 不協和音 */
+ case 0xa7: /* 口笛 */
+ case 0xa8: /* 夕陽のアサシンクロス */
+ case 0xa9: /* ブラギの詩 */
+ case 0xaa: /* イドゥンの林檎 */
+ case 0xab: /* 自分勝手なダンス */
+ case 0xac: /* ハミング */
+ case 0xad: /* 私を忘れないで… */
+ case 0xae: /* 幸運のキス */
+ case 0xaf: /* サ?ビスフォ?ユ? */
+ case 0xb4:
+ if (sg->src_id==bl->id)
+ break;
+ if (sc_data && sc_data[type].timer!=-1) {
+ unit2 = (struct skill_unit *)sc_data[type].val4;
+ if (unit2 && unit2->group &&
+ (unit2 == src || DIFF_TICK(sg->tick,unit2->group->tick)<=0))
+ break;
+ }
+ status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
+ (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
+ break;
- if(!damage_flag)
- return 0;
- skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
+ case 0xb6: /* フォグウォ?ル */
+ if (sc_data && sc_data[type].timer!=-1) {
+ unit2 = (struct skill_unit *)sc_data[type].val4;
+ if (unit2 && unit2->group &&
+ (unit2 == src || DIFF_TICK(sg->tick,unit2->group->tick)<=0))
+ break;
}
+ status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
+ (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
+ skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick);
break;
- case 0x85: /* ニュ?マ */
+ // New guild skills [Celest]
+ case 0xc1: // GD_LEADERSHIP
{
- struct skill_unit *unit2;
- int type=SC_PNEUMA;
- if(sc_data) {
- if (sc_data[type].timer==-1)
- status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
- else if((unit2 = (struct skill_unit *)sc_data[type].val2) && unit2 != src){
- if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick) > 0)
- status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
- ts->tick-=sg->interval;
+ struct map_session_data *sd, *tsd;
+ tsd=(struct map_session_data *)ss;
+ if (tsd && (sd=(struct map_session_data *)bl) &&
+ sd->status.guild_id == tsd->status.guild_id &&
+ sd != tsd) {
+ sd->state.leadership_flag = (int)src;
+ status_calc_pc (sd, 0);
}
- }
}
break;
- case 0x7e: /* セイフティウォ?ル */
- if (sc_data) {
- status_change_start(bl,SC_SAFETYWALL,sg->skill_lv,(int)src,0,0,0,0);
- ts->tick-=sg->interval;
+ case 0xc2: // GD_GLORYWOUNDS
+ {
+ struct map_session_data *sd, *tsd;
+ tsd=(struct map_session_data *)ss;
+ if (tsd && (sd=(struct map_session_data *)bl) &&
+ sd->status.guild_id == tsd->status.guild_id &&
+ sd != tsd) {
+ sd->state.glorywounds_flag = (int)src;
+ status_calc_pc (sd, 0);
+ }
+ }
+ break;
+ case 0xc3: // GD_SOULCOLD
+ {
+ struct map_session_data *sd, *tsd;
+ tsd=(struct map_session_data *)ss;
+ if (tsd && (sd=(struct map_session_data *)bl) &&
+ sd->status.guild_id == tsd->status.guild_id &&
+ sd != tsd) {
+ sd->state.soulcold_flag = (int)src;
+ status_calc_pc (sd, 0);
+ }
+ }
+ break;
+ case 0xc4: // GD_HAWKEYES
+ {
+ struct map_session_data *sd, *tsd;
+ tsd=(struct map_session_data *)ss;
+ if (tsd && (sd=(struct map_session_data *)bl) &&
+ sd->status.guild_id == tsd->status.guild_id &&
+ sd != tsd) {
+ sd->state.hawkeyes_flag = (int)src;
+ status_calc_pc (sd, 0);
+ }
}
break;
- case 0x86: /* ロ?ドオブヴァ?ミリオン(&スト?ムガスト &グランドクロス) */
- skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
+ case 0xb2: /* あなたを_?いたいです */
+ case 0xb3: /* ゴスペル */
+ //case 0xb6: /* フォグウォ?ル */ - moved [celest]
+ //とりあえず何もしない
break;
+ /* default:
+ if(battle_config.error_log)
+ printf("skill_unit_onplace: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
+ break;*/
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * スキルユニットの発動イベント(タイマー発動)
+ *------------------------------------------
+ */
+int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsigned int tick)
+{
+ struct skill_unit_group *sg;
+ struct block_list *ss;
+ int splash_count=0;
+ struct status_change *sc_data;
+ struct skill_unit_group_tickset *ts;
+ int type;
+ int diff=0;
+
+ nullpo_retr(0, src);
+ nullpo_retr(0, bl);
+
+ if (bl->type!=BL_PC && bl->type!=BL_MOB)
+ return 0;
+
+ if (bl->prev==NULL || !src->alive ||
+ (bl->type==BL_PC && pc_isdead((struct map_session_data *)bl)))
+ return 0;
+
+ nullpo_retr(0, sg=src->group);
+ nullpo_retr(0, ss=map_id2bl(sg->src_id));
+ sc_data = status_get_sc_data(bl);
+ type = SkillStatusChangeTable[sg->skill_id];
+
+ // 対象がLP上に居る場合は無効
+ if (map_find_skill_unit_oncell(bl,bl->x,bl->y,SA_LANDPROTECTOR,NULL))
+ return 0;
+
+ // 前に影響を受けてからintervalの間は影響を受けない
+ nullpo_retr(0,ts = skill_unitgrouptickset_search(bl,sg,tick));
+ diff = DIFF_TICK(tick,ts->tick);
+ if (sg->skill_id == PR_SANCTUARY)
+ diff += 500; // 新規に回復したユニットだけカウントするための仕掛け
+ if (diff < 0)
+ return 0;
+ ts->tick = tick+sg->interval;
+ // GXは重なっていたら3HITしない
+ if (sg->skill_id==CR_GRANDCROSS && !battle_config.gx_allhit)
+ ts->tick += sg->interval*(map_count_oncell(bl->m,bl->x,bl->y)-1);
+
+ switch (sg->unit_id) {
+ case 0x83: /* サンクチュアリ */
+ {
+ int race=status_get_race(bl);
- case 0x7f: /* ファイヤ?ウォ?ル */
- if( (src->val2--)>0)
- skill_attack(BF_MAGIC,ss,&src->bl,bl,
- sg->skill_id,sg->skill_lv,tick,0);
- if( src->val2<=0 )
+ if (battle_check_undead(race,status_get_elem_type(bl)) || race==6) {
+ if (skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0)) {
+ // reduce healing count if this was meant for damaging [celest]
+ // sg->val1 /= 2;
+ sg->val1--; // チャットキャンセルに対応
+ }
+ } else {
+ int heal = sg->val2;
+ if (status_get_hp(bl)>=status_get_max_hp(bl))
+ break;
+ if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage)
+ heal=0; /* 黄金蟲カード(ヒール量0) */
+ clif_skill_nodamage(&src->bl,bl,AL_HEAL,heal,1);
+ battle_heal(NULL,bl,heal,0,0);
+ if (diff>=500)
+ sg->val1--; // 新規に入ったユニットだけカウント
+ }
+ if (sg->val1<=0)
+ skill_delunitgroup(sg);
+ break;
+ }
+
+ case 0x84: /* マグヌスエクソシズム */
+ {
+ int race = status_get_race(bl);
+ if (!battle_check_undead(race,status_get_elem_type(bl)) && race!=6)
+ return 0;
+ skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
+ src->val2++;
+ break;
+ }
+
+ case 0x7f: /* ファイヤーウォール */
+ skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
+ if (--src->val2<=0)
skill_delunit(src);
break;
-
- case 0x87: /* ファイア?ピラ?(?動前) */
+ case 0x86: /* ロードオブヴァーミリオン(TS,MS,FN,SG,HD,GX,闇GX) */
+ skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
+ break;
+ case 0x87: /* ファイアーピラー(発動前) */
skill_delunit(src);
skill_unitsetting(ss,sg->skill_id,sg->skill_lv,src->bl.x,src->bl.y,1);
break;
- case 0x88: /* ファイア?ピラ?(?動後) */
- if(DIFF_TICK(tick,sg->tick) < 150)
- //skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
- map_foreachinarea(skill_attack_area,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,BF_MAGIC,ss,&src->bl,sg->skill_id,sg->skill_lv,tick,0,BCT_ENEMY); // area damage [Celest]
+ case 0x88: /* ファイアーピラー(発動後) */
+ map_foreachinarea(skill_attack_area,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
+ BF_MAGIC,ss,&src->bl,sg->skill_id,sg->skill_lv,tick,0,BCT_ENEMY); // area damage [Celest]
+ //skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
case 0x90: /* スキッドトラップ */
@@ -5784,7 +5568,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
clif_changelook(&src->bl,LOOK_BASE,sg->unit_id);
sg->limit=DIFF_TICK(tick,sg->tick)+1500;
}
- break;
+ break;
case 0x93: /* ランドマイン */
skill_attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
@@ -5813,22 +5597,22 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
break;
case 0x91: /* アンクルスネア */
- {
- struct status_change *sc_data=status_get_sc_data(bl);
- if(sg->val2==0 && sc_data && sc_data[SC_ANKLE].timer==-1){
- int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE);
- int sec = skill_get_time2(sg->skill_id,sg->skill_lv) - status_get_agi(bl)*100;
- if(status_get_mode(bl)&0x20)
- sec = sec/5;
- if (sec < 3000) // minimum time of 3 seconds [celest]
- sec = 3000;
- battle_stopwalking(bl,1);
- status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0);
-
+ if(sg->val2==0 && sc_data && sc_data[SC_ANKLE].timer==-1){
+ int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE);
+ int sec = skill_get_time2(sg->skill_id,sg->skill_lv) - status_get_agi(bl)*100;
+ if(status_get_mode(bl)&0x20)
+ sec = sec/5;
+ if (sec < 3000) // minimum time of 3 seconds [celest]
+ sec = 3000;
+ battle_stopwalking(bl,1);
+ status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0);
+
+ skill_unit_move(bl,tick,0);
if(moveblock) map_delblock(bl);
bl->x = src->bl.x;
bl->y = src->bl.y;
if(moveblock) map_addblock(bl);
+ skill_unit_move(bl,tick,1);
if(bl->type == BL_MOB)
clif_fixmobpos((struct mob_data *)bl);
else if(bl->type == BL_PET)
@@ -5836,156 +5620,26 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
else
clif_fixpos(bl);
clif_01ac(&src->bl);
- sg->limit=DIFF_TICK(tick,sg->tick) + sec;
+ sg->limit=DIFF_TICK(tick,sg->tick) + sec;
sg->val2=bl->id;
- }
- }
- break;
-
- case 0x80: /* ワ?プポ?タル(?動後) */
- if(bl->type==BL_PC){
- struct map_session_data *sd = (struct map_session_data *)bl;
- if(sd && src->bl.m == bl->m && src->bl.x == bl->x && src->bl.y == bl->y && src->bl.x == sd->to_x && src->bl.y == sd->to_y) {
- if( battle_config.chat_warpportal || !sd->chatID ){
- if((sg->val1--)>0){
- pc_setpos(sd,sg->valstr,sg->val2>>16,sg->val2&0xffff,3);
- if(sg->src_id == bl->id ||( strcmp(map[src->bl.m].name,sg->valstr) == 0 && src->bl.x == (sg->val2>>16) && src->bl.y == (sg->val2&0xffff) ))
- skill_delunitgroup(sg);
- }else
- skill_delunitgroup(sg);
- }
- }
- }else if(bl->type==BL_MOB && battle_config.mob_warpportal){
- int m=map_mapname2mapid(sg->valstr);
- struct mob_data *md;
- md=(struct mob_data *)bl;
- mob_warp((struct mob_data *)bl,m,sg->val2>>16,sg->val2&0xffff,3);
+ sg->interval = -1;
+ src->range = 0;
}
break;
- case 0x8e: /* クァグマイア */
- {
- struct status_change *sc_data=status_get_sc_data(bl);
- int type=SkillStatusChangeTable[sg->skill_id];
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
- break;
- if(sc_data && sc_data[type].timer==-1)
- status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
- }
- break;
case 0x92: /* ベノムダスト */
- {
- struct status_change *sc_data=status_get_sc_data(bl);
- int type=SkillStatusChangeTable[sg->skill_id];
- if(sc_data && sc_data[type].timer==-1 )
- status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
- }
+ if(sc_data && sc_data[type].timer==-1 )
+ status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
break;
- case 0x9a: /* ボルケ?ノ */
- case 0x9b: /* デリュ?ジ */
- case 0x9c: /* バイオレントゲイル */
- {
- struct skill_unit *unit2;
- struct status_change *sc_data=status_get_sc_data(bl);
- int type=SkillStatusChangeTable[sg->skill_id];
- if(sc_data) {
- if (sc_data[type].timer==-1)
- status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
- else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){
- if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 )
- status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0);
- ts->tick-=sg->interval;
- }
- }
- } break;
-
- case 0x9e: /* 子守唄 */
- case 0x9f: /* ニヨルドの宴 */
- case 0xa0: /* 永遠の混沌 */
- case 0xa1: /* ?太鼓の響き */
- case 0xa2: /* ニ?ベルングの指輪 */
- case 0xa3: /* ロキの叫び */
- case 0xa4: /* 深淵の中に */
- case 0xa5: /* 不死身のジ?クフリ?ド */
- case 0xa6: /* 不協和音 */
- case 0xa7: /* 口笛 */
- case 0xa8: /* 夕陽のアサシンクロス */
- case 0xa9: /* ブラギの詩 */
- case 0xab: /* 自分勝手なダンス */
- case 0xac: /* ハミング */
- case 0xad: /* 私を忘れないで… */
- case 0xae: /* 幸運のキス */
- case 0xaf: /* サ?ビスフォ?ユ? */
- case 0xb4:
-// case 0xb6: /* フォグウォ?ル */
- {
- struct skill_unit *unit2;
- struct status_change *sc_data=status_get_sc_data(bl);
- int type=SkillStatusChangeTable[sg->skill_id];
- if(sg->src_id == bl->id)
- break;
- if(sc_data) {
- if (sc_data[type].timer==-1)
- status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
- (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
- else if( (unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){
- if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 )
- status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
- (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
- ts->tick-=sg->interval;
- }
- }
- } break;
-
- case 0xaa: /* イドゥンの林檎 */
- {
- struct skill_unit *unit2;
- struct status_change *sc_data=status_get_sc_data(bl);
- int type=SkillStatusChangeTable[sg->skill_id];
- if(sg->src_id == bl->id)
- break;
- if(sc_data) {
- if (sc_data[type].timer==-1)
- status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff,
- (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
- else if((unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){
- if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 )
- status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff,
- (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
- ts->tick-=sg->interval;
- }
- }
- } break;
-
- case 0xb6: /* フォグウォ?ル */
- {
- struct skill_unit *unit2;
- struct status_change *sc_data=status_get_sc_data(bl);
- int type=SkillStatusChangeTable[sg->skill_id];
- if(sc_data) {
- if (sc_data[type].timer==-1) {
- status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
- (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
- skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick);
- }
- else if( (unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){
- if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 ) {
- status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
- (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0);
- skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick);
- }
-// ts->tick-=sg->interval;
- }
- }
- } break;
case 0xb1: /* デモンストレ?ション */
skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
if(bl->type == BL_PC && rand()%100 < sg->skill_lv && battle_config.equipment_breaking)
pc_breakweapon((struct map_session_data *)bl);
break;
- case 0x99: /* ト?キ?ボックス */
- if(sg->src_id == bl->id) //自分が踏んでも?動しない
+
+ case 0x99: /* トーキーボックス */
+ if(sg->src_id == bl->id) //自分が踏んでも発動しない
break;
if(sg->val2==0){
clif_talkiebox(&src->bl,sg->valstr);
@@ -5994,76 +5648,41 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
sg->limit=DIFF_TICK(tick,sg->tick)+5000;
sg->val2=-1; //踏んだ
}
- break;
- case 0xb2: /* あなたを_?いたいです */
- case 0xb3: /* ゴスペル */
- //case 0xb6: /* フォグウォ?ル */ - moved [celest]
- //とりあえず何もしない
- break;
+ break;
+
+ //case 0xb4: /* バジリカ */
+ /*if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0 &&
+ !(status_get_mode(bl)&0x20))
+ skill_blown(&src->bl,bl,1);
+ if (sg->src_id==bl->id)
+ break;
+ if (battle_check_target(&src->bl,bl,BCT_NOENEMY)>0) {
+ type = SkillStatusChangeTable[sg->skill_id];
+ status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2,
+ (int)src,sg->interval+100,0);
+ }
+ break;*/
case 0xb7: /* スパイダ?ウェッブ */
if(sg->val2==0){
int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE);
skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick);
+ skill_unit_move(bl,tick,0);
if(moveblock) map_delblock(bl);
- bl->x = (&src->bl)->x;
- bl->y = (&src->bl)->y;
+ bl->x = src->bl.x;
+ bl->y = src->bl.y;
if(moveblock) map_addblock(bl);
- if(bl->type == BL_MOB)
- clif_fixmobpos((struct mob_data *)bl);
- else if(bl->type == BL_PET)
- clif_fixpetpos((struct pet_data *)bl);
- else
- clif_fixpos(bl);
- clif_01ac(&src->bl);
- sg->limit=DIFF_TICK(tick,sg->tick) + skill_get_time2(sg->skill_id,sg->skill_lv);
+ skill_unit_move(bl,tick,1);
+ if(bl->type == BL_MOB)
+ clif_fixmobpos((struct mob_data *)bl);
+ else if(bl->type == BL_PET)
+ clif_fixpetpos((struct pet_data *)bl);
+ else
+ clif_fixpos(bl);
+ sg->limit = DIFF_TICK(tick,sg->tick)+skill_get_time2(sg->skill_id,sg->skill_lv);
sg->val2=bl->id;
- }
- break;
-
- // New guild skills [Celest]
- case 0xc1: // GD_LEADERSHIP
- {
- struct map_session_data *sd;
- if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
- sd->status.guild_id == srcsd->status.guild_id &&
- sd != srcsd) {
- sd->state.leadership_flag = (int)src;
- status_calc_pc (sd, 0);
- }
- }
- break;
- case 0xc2: // GD_GLORYWOUNDS
- {
- struct map_session_data *sd;
- if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
- sd->status.guild_id == srcsd->status.guild_id &&
- sd != srcsd) {
- sd->state.glorywounds_flag = (int)src;
- status_calc_pc (sd, 0);
- }
- }
- break;
- case 0xc3: // GD_SOULCOLD
- {
- struct map_session_data *sd;
- if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
- sd->status.guild_id == srcsd->status.guild_id &&
- sd != srcsd) {
- sd->state.soulcold_flag = (int)src;
- status_calc_pc (sd, 0);
- }
- }
- break;
- case 0xc4: // GD_HAWKEYES
- {
- struct map_session_data *sd;
- if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) &&
- sd->status.guild_id == srcsd->status.guild_id &&
- sd != srcsd) {
- sd->state.hawkeyes_flag = (int)src;
- status_calc_pc (sd, 0);
- }
+ sg->interval = -1;
+ src->range = 0;
}
break;
@@ -6072,6 +5691,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
printf("skill_unit_onplace: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
break;*/
}
+
if(bl->type==BL_MOB && ss!=bl) /* スキル使用?件のMOBスキル */
{
if(battle_config.mob_changetarget_byskill == 1)
@@ -6095,77 +5715,41 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int tick)
{
struct skill_unit_group *sg;
+ struct status_change *sc_data;
+ int type;
nullpo_retr(0, src);
nullpo_retr(0, bl);
nullpo_retr(0, sg=src->group);
+ sc_data = status_get_sc_data(bl);
+ type = SkillStatusChangeTable[sg->skill_id];
- if( bl->prev==NULL || !src->alive )
- return 0;
-
- if( bl->type!=BL_PC && bl->type!=BL_MOB )
+ if (bl->prev==NULL || !src->alive ||
+ (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)))
return 0;
switch(sg->unit_id){
- case 0x7e: /* セイフティウォ?ル */
- case 0x85: /* ニュ?マ */
+ case 0x7e: /* セイフティウォール */
+ case 0x85: /* ニューマ */
case 0x8e: /* クァグマイア */
- {
- struct status_change *sc_data=status_get_sc_data(bl);
- int type=
- (sg->unit_id==0x85)?SC_PNEUMA:
- ((sg->unit_id==0x7e)?SC_SAFETYWALL:
- SC_QUAGMIRE);
- if((type != SC_QUAGMIRE || bl->type != BL_MOB) &&
- sc_data && sc_data[type].timer!=-1 && ((struct skill_unit *)sc_data[type].val2)==src){
- status_change_end(bl,type,-1);
- }
- } break;
-
- case 0x91: /* アンクルスネア */
- {
- struct block_list *target=map_id2bl(sg->val2);
- if( target && target==bl ){
- status_change_end(bl,SC_ANKLE,-1);
- sg->limit=DIFF_TICK(tick,sg->tick)+1000;
- }
+ case 0x9a: /* ボルケーノ */
+ case 0x9b: /* デリュージ */
+ case 0x9c: /* バイオレントゲイル */
+ if (type==SC_QUAGMIRE && bl->type==BL_MOB)
+ break;
+ if (sc_data && sc_data[type].timer!=-1 && sc_data[type].val2==(int)src) {
+ status_change_end(bl,type,-1);
}
break;
-// case 0xb5:
- case 0xb8:
- {
- struct block_list *target=map_id2bl(sg->val2);
- if( target==bl )
- status_change_end(bl,SC_SPIDERWEB,-1);
+ case 0x91: /* アンクルスネア */
+ {
+ struct block_list *target = map_id2bl(sg->val2);
+ if(target && target == bl){
+ status_change_end(bl,SC_ANKLE,-1);
sg->limit=DIFF_TICK(tick,sg->tick)+1000;
}
break;
- case 0xb6:
- {
- struct block_list *target=map_id2bl(sg->val2);
- struct status_change *sc_data=status_get_sc_data(bl);
- if( target==bl ) {
- status_change_end(bl,SC_FOGWALL,-1);
- if (sc_data && sc_data[SC_BLIND].timer!=-1)
- sc_data[SC_BLIND].timer = add_timer(
- gettick() + 30000, status_change_timer, bl->id, 0);
- }
- //sg->limit=DIFF_TICK(tick,sg->tick)+1000;
- }
- break;
- case 0x9a: /* ボルケ?ノ */
- case 0x9b: /* デリュ?ジ */
- case 0x9c: /* バイオレントゲイル */
- {
- struct status_change *sc_data=status_get_sc_data(bl);
- struct skill_unit *su;
- int type=SkillStatusChangeTable[sg->skill_id];
- if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val2)) && su == src ){
- status_change_end(bl,type,-1);
- }
- }
- break;
-
+ }
case 0x9e: /* 子守唄 */
case 0x9f: /* ニヨルドの宴 */
case 0xa0: /* 永遠の混沌 */
@@ -6185,24 +5769,32 @@ int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int t
case 0xae: /* 幸運のキス */
case 0xaf: /* サ?ビスフォ?ユ? */
case 0xb4:
- {
- struct status_change *sc_data=status_get_sc_data(bl);
- struct skill_unit *su;
- int type=SkillStatusChangeTable[sg->skill_id];
- if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val4)) && su == src ){
- status_change_end(bl,type,-1);
- }
+ if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)src) {
+ status_change_end(bl,type,-1);
}
break;
+
+ case 0xb6:
+ {
+ struct block_list *target = map_id2bl(sg->val2);
+ if(target && target==bl) {
+ status_change_end(bl,SC_FOGWALL,-1);
+ if (sc_data && sc_data[SC_BLIND].timer!=-1)
+ sc_data[SC_BLIND].timer = add_timer(
+ gettick() + 30000, status_change_timer, bl->id, 0);
+ }
+ break;
+ }
+
case 0xb7: /* スパイダ?ウェッブ */
{
- struct block_list *target=map_id2bl(sg->val2);
- if( target && target==bl )
+ struct block_list *target = map_id2bl(sg->val2);
+ if (target && target==bl)
status_change_end(bl,SC_SPIDERWEB,-1);
- sg->limit=DIFF_TICK(tick,sg->tick)+1000;
+ sg->limit = DIFF_TICK(tick,sg->tick)+1000;
+ break;
}
- break;
- // New guild skills [Celest]
+ // New guild skills [Celest]
case 0xc1: // GD_LEADERSHIP
{
struct map_session_data *sd;
@@ -6231,73 +5823,53 @@ int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int t
sd->state.hawkeyes_flag = 0;
}
break;
-
/* default:
if(battle_config.error_log)
printf("skill_unit_onout: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
break;*/
}
- skill_unitgrouptickset_delete(bl,sg);
+
return 0;
}
+
/*==========================================
- * スキルユニットの削除イベント
+ * スキルユニット効果発動/離脱処理(foreachinarea)
+ * bl: ユニット(BL_PC/BL_MOB)
*------------------------------------------
*/
-int skill_unit_ondelete(struct skill_unit *src,struct block_list *bl,unsigned int tick)
+int skill_unit_effect(struct block_list *bl,va_list ap)
{
- struct skill_unit_group *sg;
+ struct skill_unit *unit;
+ struct skill_unit_group *group;
+ int flag;
+ unsigned int tick;
- nullpo_retr(0, src);
nullpo_retr(0, bl);
- nullpo_retr(0, sg = src->group);
+ nullpo_retr(0, ap);
+ nullpo_retr(0, unit=va_arg(ap,struct skill_unit*));
+ tick = va_arg(ap,unsigned int);
+ flag = va_arg(ap,unsigned int);
- if( bl->prev==NULL || !src->alive )
+ if (bl->type!=BL_PC && bl->type!=BL_MOB)
return 0;
- if( bl->type!=BL_PC && bl->type!=BL_MOB )
+ if (!unit->alive || bl->prev==NULL)
return 0;
- switch(sg->unit_id){
- case 0x85: /* ニュ?マ */
- case 0x7e: /* セイフティウォ?ル */
- case 0x8e: /* クァグマイヤ */
- case 0x9a: /* ボルケ?ノ */
- case 0x9b: /* デリュ?ジ */
- case 0x9c: /* バイオレントゲイル */
- case 0x9e: /* 子守唄 */
- case 0x9f: /* ニヨルドの宴 */
- case 0xa0: /* 永遠の混沌 */
- case 0xa1: /* ?太鼓の響き */
- case 0xa2: /* ニ?ベルングの指輪 */
- case 0xa3: /* ロキの叫び */
- case 0xa4: /* 深淵の中に */
- case 0xa5: /* 不死身のジ?クフリ?ド */
- case 0xa6: /* 不協和音 */
- case 0xa7: /* 口笛 */
- case 0xa8: /* 夕陽のアサシンクロス */
- case 0xa9: /* ブラギの詩 */
- case 0xaa: /* イドゥンの林檎 */
- case 0xab: /* 自分勝手なダンス */
- case 0xac: /* ハミング */
- case 0xad: /* 私を忘れないで… */
- case 0xae: /* 幸運のキス */
- case 0xaf: /* サ?ビスフォ?ユ? */
- case 0xb4:
- case 0xc1:
- case 0xc2:
- case 0xc3:
- case 0xc4:
- return skill_unit_onout(src,bl,tick);
+ nullpo_retr(0, group=unit->group);
-/* default:
- if(battle_config.error_log)
- printf("skill_unit_ondelete: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
- break;*/
+ if (flag)
+ skill_unit_onplace(unit,bl,tick);
+ else {
+ skill_unit_onout(unit,bl,tick);
+ unit = map_find_skill_unit_oncell(bl,bl->x,bl->y,group->skill_id,unit);
+ if (unit)
+ skill_unit_onplace(unit,bl,tick);
}
- skill_unitgrouptickset_delete(bl,sg);
+
return 0;
}
+
/*==========================================
* スキルユニットの限界イベント
*------------------------------------------
@@ -6435,10 +6007,7 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data )
return 0;
}
- if(battle_config.pc_skill_reiteration == 0) {
- range = -1;
- switch(sd->skillid) {
- case MG_SAFETYWALL:
+ /*case MG_SAFETYWALL:
case WZ_FIREPILLAR:
case HT_SKIDTRAP:
case HT_LANDMINE:
@@ -6451,28 +6020,23 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data )
case HT_CLAYMORETRAP:
case HT_TALKIEBOX:
case AL_WARP:
- case PF_SPIDERWEB: /* スパイダ?ウェッブ */
- case RG_GRAFFITI: /* グラフィティ */
+ case PF_SPIDERWEB:
+ case RG_GRAFFITI:
range = 0;
break;
case AL_PNEUMA:
range = 1;
- break;
- }
- if(range >= 0) {
- if(skill_check_unit_range(sd->bl.m,sd->skillx,sd->skilly,range,sd->skillid) > 0) {
- clif_skill_fail(sd,sd->skillid,0,0);
- sd->canact_tick = tick;
- sd->canmove_tick = tick;
- sd->skillitem = sd->skillitemlv = -1;
- return 0;
- }
- }
+ break;*/
+ if (!battle_config.pc_skill_reiteration &&
+ skill_get_unit_flag(sd->skillid)&UF_NOREITERATION &&
+ skill_check_unit_range(sd->bl.m,sd->skillx,sd->skilly,sd->skillid,sd->skilllv)) {
+ clif_skill_fail(sd,sd->skillid,0,0);
+ sd->canact_tick = tick;
+ sd->canmove_tick = tick;
+ sd->skillitem = sd->skillitemlv = -1;
+ return 0;
}
- if(battle_config.pc_skill_nofootset) {
- range = -1;
- switch(sd->skillid) {
- case WZ_FIREPILLAR:
+ /*case WZ_FIREPILLAR:
case HT_SKIDTRAP:
case HT_LANDMINE:
case HT_ANKLESNARE:
@@ -6483,25 +6047,22 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data )
case HT_BLASTMINE:
case HT_CLAYMORETRAP:
case HT_TALKIEBOX:
- case PF_SPIDERWEB: /* スパイダ?ウェッブ */
+ case PF_SPIDERWEB:
case WZ_ICEWALL:
range = 2;
break;
case AL_WARP:
range = 0;
- break;
- }
- if(range >= 0) {
- if(skill_check_unit_range2(sd->bl.m,sd->skillx,sd->skilly,range) > 0) {
- clif_skill_fail(sd,sd->skillid,0,0);
- sd->canact_tick = tick;
- sd->canmove_tick = tick;
- sd->skillitem = sd->skillitemlv = -1;
- return 0;
- }
- }
+ break;*/
+ if (battle_config.pc_skill_nofootset &&
+ skill_get_unit_flag(sd->skillid)&UF_NOFOOTSET &&
+ skill_check_unit_range2(sd->bl.m,sd->skillx,sd->skilly,sd->skillid,sd->skilllv)) {
+ clif_skill_fail(sd,sd->skillid,0,0);
+ sd->canact_tick = tick;
+ sd->canmove_tick = tick;
+ sd->skillitem = sd->skillitemlv = -1;
+ return 0;
}
-
if(battle_config.pc_land_skill_limit) {
maxcount = skill_get_maxcount(sd->skillid);
if(maxcount > 0) {
@@ -7523,22 +7084,22 @@ int skill_use_id( struct map_session_data *sd, int target_id,
return 0;
}
break;
- // removed on 12/14's patch [celest]
- //case AS_SPLASHER: /* ベナムスプラッシャ? */
- /* {
- struct status_change *t_sc_data = status_get_sc_data(bl);
- if(t_sc_data && t_sc_data[SC_POISON].timer==-1){
- clif_skill_fail(sd,skill_num,0,10);
- return 0;
- }
- }
- break;*/
case PF_MEMORIZE: /* メモライズ */
casttime = 12000;
break;
case HW_MAGICPOWER:
casttime = 700;
break;
+ case HP_BASILICA: /* バジリカ */
+ if (skill_check_unit_range(sd->bl.m,sd->bl.x,sd->bl.y,sd->skillid,sd->skilllv)) {
+ clif_skill_fail(sd,sd->skillid,0,0);
+ return 0;
+ }
+ if (skill_check_unit_range2(sd->bl.m,sd->bl.x,sd->bl.y,sd->skillid,sd->skilllv)) {
+ clif_skill_fail(sd,sd->skillid,0,0);
+ return 0;
+ }
+ break;
case GD_BATTLEORDER:
case GD_REGENERATION:
case GD_RESTORE:
@@ -7991,13 +7552,14 @@ int skill_devotion3(struct block_list *bl,int target)
int n,r=0;
nullpo_retr(1, bl);
+ md = (struct map_session_data *)bl;
- if( (md = (struct map_session_data *)bl) == NULL || (sd = map_id2sd(target)) == NULL )
+ if ((sd = map_id2sd(target))==NULL)
return 1;
else
r = distance(bl->x,bl->y,sd->bl.x,sd->bl.y);
- if(pc_checkskill(sd,CR_DEVOTION)+6 < r){ // 許容範?を超えてた
+ if(pc_checkskill(md,CR_DEVOTION)+6 < r){ // 許容範?を超えてた
for(n=0;n<5;n++)
if(md->dev.val1[n]==target)
md->dev.val2[n]=0; // 離れた時は、?を切るだけ
@@ -8249,12 +7811,28 @@ int skill_abra_dataset(int skilllv)
//NPCスキルはダメ
if(skill >= NPC_PIERCINGATT && skill <= NPC_SUMMONMONSTER) return 0;
//演奏スキルはダメ
- if(skill_is_danceskill(skill)) return 0;
+ if (skill_get_unit_flag(skill)&UF_DANCE) return 0;
return skill;
}
/*==========================================
+ * バジリカのセルを設定する
+ *------------------------------------------
+ */
+void skill_basilica_cell(struct skill_unit *unit,int flag)
+{
+ int i,x,y,range = skill_get_unit_range(HP_BASILICA);
+ int size = range*2+1;
+
+ for (i=0;i<size*size;i++) {
+ x = unit->bl.x+(i%size-range);
+ y = unit->bl.y+(i/size-range);
+ map_setcell(unit->bl.m,x,y,flag);
+ }
+}
+
+/*==========================================
*
*------------------------------------------
*/
@@ -8293,16 +7871,20 @@ int skill_clear_element_field(struct block_list *bl)
{
struct mob_data *md=NULL;
struct map_session_data *sd=NULL;
- int i,skillid;
+ int i,max,skillid;
nullpo_retr(0, bl);
- if(bl->type==BL_MOB)
- md=(struct mob_data *)bl;
- if(bl->type==BL_PC)
- sd=(struct map_session_data *)bl;
+ if (bl->type==BL_MOB) {
+ max = MAX_MOBSKILLUNITGROUP;
+ md = (struct mob_data *)bl;
+ } else if(bl->type==BL_PC) {
+ max = MAX_SKILLUNITGROUP;
+ sd = (struct map_session_data *)bl;
+ } else
+ return 0;
- for(i=0;i<MAX_MOBSKILLUNITGROUP;i++){
+ for (i=0;i<max;i++) {
if(sd){
skillid=sd->skillunit[i].skill_id;
if(skillid==SA_DELUGE||skillid==SA_VOLCANO||skillid==SA_VIOLENTGALE||skillid==SA_LANDPROTECTOR)
@@ -8372,7 +7954,8 @@ int skill_idun_heal(struct block_list *bl, va_list ap )
* 指定範??でsrcに?して有?なタ?ゲットのblの?を?える(foreachinarea)
*------------------------------------------
*/
-int skill_count_target(struct block_list *bl, va_list ap ){
+int skill_count_target(struct block_list *bl, va_list ap)
+{
struct block_list *src;
int *c;
@@ -8528,48 +8111,6 @@ int skill_type_cloaking(struct block_list *bl)
*/
/*==========================================
- * 演奏/ダンススキルかどうか判定
- * 引? スキルID
- * ?り ダンスじゃない=0 合奏=2 それ以外のダンス=1
- *------------------------------------------
- */
-int skill_is_danceskill(int id)
-{
- int i;
- switch(id){
- case BD_LULLABY: /* 子守歌 */
- case BD_RICHMANKIM: /* ニヨルドの宴 */
- case BD_ETERNALCHAOS: /* 永遠の混沌 */
- case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */
- case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */
- case BD_ROKISWEIL: /* ロキの叫び */
- case BD_INTOABYSS: /* 深淵の中に */
- case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */
- case BD_RAGNAROK: /* 神?の?昏 */
- case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
- i=2;
- break;
- case BA_DISSONANCE: /* 不協和音 */
- case BA_FROSTJOKE: /* 寒いジョ?ク */
- case BA_WHISTLE: /* 口笛 */
- case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
- case BA_POEMBRAGI: /* ブラギの詩 */
- case BA_APPLEIDUN: /* イドゥンの林檎 */
- case DC_UGLYDANCE: /* 自分勝手なダンス */
- case DC_SCREAM: /* スクリ?ム */
- case DC_HUMMING: /* ハミング */
- case DC_DONTFORGETME: /* 私を忘れないで… */
- case DC_FORTUNEKISS: /* 幸運のキス */
- case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */
- i=1;
- break;
- default:
- i=0;
- }
- return i;
-}
-
-/*==========================================
* 演奏/ダンスをやめる
* flag 1で合奏中なら相方にユニットを任せる
*
@@ -8650,10 +8191,13 @@ struct skill_unit *skill_initunit(struct skill_unit_group *group,int idx,int x,i
map_addblock(&unit->bl);
clif_skill_setunit(unit);
+
+// if (group->skill_id==HP_BASILICA)
+// skill_basilica_cell(unit,CELL_SETBASILICA);
+
return unit;
}
-int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap );
/*==========================================
* スキルユニット削除
*------------------------------------------
@@ -8661,7 +8205,6 @@ int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap );
int skill_delunit(struct skill_unit *unit)
{
struct skill_unit_group *group;
- int range;
nullpo_retr(0, unit);
if(!unit->alive)
@@ -8671,11 +8214,15 @@ int skill_delunit(struct skill_unit *unit)
/* onlimitイベント呼び出し */
skill_unit_onlimit( unit,gettick() );
- /* ondeleteイベント呼び出し */
- range=group->range;
- map_foreachinarea( skill_unit_timer_sub_ondelete, unit->bl.m,
- unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0,
- &unit->bl,gettick() );
+ /* onoutイベント呼び出し */
+ if (!unit->range) {
+ map_foreachinarea(skill_unit_effect,unit->bl.m,
+ unit->bl.x,unit->bl.y,unit->bl.x,unit->bl.y,0,
+ &unit->bl,gettick(),0);
+ }
+
+// if (group->skill_id==HP_BASILICA)
+// skill_basilica_cell(unit,CELL_CLRBASILICA);
clif_skill_delunit(unit);
@@ -8691,7 +8238,7 @@ int skill_delunit(struct skill_unit *unit)
* スキルユニットグル?プ初期化
*------------------------------------------
*/
-static int skill_unit_group_newid=10;
+static int skill_unit_group_newid = MAX_SKILL_DB;
struct skill_unit_group *skill_initunitgroup(struct block_list *src,
int count,int skillid,int skilllv,int unit_id)
{
@@ -8743,7 +8290,7 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src,
group->guild_id=status_get_guild_id(src);
group->group_id=skill_unit_group_newid++;
if(skill_unit_group_newid<=0)
- skill_unit_group_newid=10;
+ skill_unit_group_newid = MAX_SKILL_DB;
group->unit=(struct skill_unit *)aCalloc(count,sizeof(struct skill_unit));
group->unit_count=count;
group->val1=group->val2=0;
@@ -8751,39 +8298,23 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src,
group->skill_lv=skilllv;
group->unit_id=unit_id;
group->map=src->m;
- group->range=0;
group->limit=10000;
group->interval=1000;
group->tick=gettick();
group->valstr=NULL;
- if( skill_is_danceskill(skillid) ){
+ if (skill_get_unit_flag(skillid)&UF_DANCE) {
struct map_session_data *sd = NULL;
if(src->type==BL_PC && (sd=(struct map_session_data *)src) ){
sd->skillid_dance=skillid;
sd->skilllv_dance=skilllv;
}
status_change_start(src,SC_DANCING,skillid,(int)group,0,0,skill_get_time(skillid,skilllv)+1000,0);
- switch(skillid){ //合奏スキルは相方をダンス?態にする
- case BD_LULLABY: /* 子守歌 */
- case BD_RICHMANKIM: /* ニヨルドの宴 */
- case BD_ETERNALCHAOS: /* 永遠の混沌 */
- case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */
- case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */
- case BD_ROKISWEIL: /* ロキの叫び */
- case BD_INTOABYSS: /* 深淵の中に */
- case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */
- case BD_RAGNAROK: /* 神?の?昏 */
- case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
- {
- int range=1;
- int c=0;
- if(sd){
- map_foreachinarea(skill_check_condition_use_sub,sd->bl.m,
- sd->bl.x-range,sd->bl.y-range,
- sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c);
- }
- }
+ //合奏スキルは相方をダンス状態にする
+ if (sd && skill_get_unit_flag(skillid)&UF_ENSEMBLE) {
+ int c=0;
+ map_foreachinarea(skill_check_condition_use_sub,sd->bl.m,
+ sd->bl.x-1,sd->bl.y-1,sd->bl.x+1,sd->bl.y+1,BL_PC,&sd->bl,&c);
}
}
return group;
@@ -8803,7 +8334,8 @@ int skill_delunitgroup(struct skill_unit_group *group)
return 0;
src=map_id2bl(group->src_id);
- if( skill_is_danceskill(group->skill_id) ){ //ダンススキルはダンス?態を解除する
+ //ダンススキルはダンス状態を解除する
+ if (skill_get_unit_flag(group->skill_id)&UF_DANCE) {
if(src)
status_change_end(src,SC_DANCING,-1);
}
@@ -8841,13 +8373,14 @@ int skill_clear_unitgroup(struct block_list *src)
if(src->type==BL_PC){
group=((struct map_session_data *)src)->skillunit;
maxsug=MAX_SKILLUNITGROUP;
- }else if(src->type==BL_MOB){
+ } else if(src->type==BL_MOB){
group=((struct mob_data *)src)->skillunit;
maxsug=MAX_MOBSKILLUNITGROUP;
- }else if(src->type==BL_PET){ // [Valaris]
+ } else if(src->type==BL_PET){ // [Valaris]
group=((struct pet_data *)src)->skillunit;
maxsug=MAX_MOBSKILLUNITGROUP;
- }
+ } else
+ return 0;
if(group){
int i;
for(i=0;i<maxsug;i++)
@@ -8857,31 +8390,19 @@ int skill_clear_unitgroup(struct block_list *src)
return 0;
}
-/*
- * 珞ヌォケォュォェェヘヌェュェキェゾェホヤムツ
- */
-int skill_unit_overlap_type(int skill_id)
-{
- switch (skill_id) {
- case WZ_STORMGUST:
- case WZ_VERMILION:
- return 1; // ェノェチェ鬪ォ鰥ーェォェ鬮タォ?ォクェ磑ェアェ
- default:
- return 0; // ?ローェォェ鬮タォ?ォクェ磑ェアェ
- }
-}
-
/*==========================================
* スキルユニットグル?プの被影響tick?索
*------------------------------------------
*/
struct skill_unit_group_tickset *skill_unitgrouptickset_search(
- struct block_list *bl, struct skill_unit_group *sg)
+ struct block_list *bl,struct skill_unit_group *group,int tick)
{
int i,j=-1,k,s,id;
struct skill_unit_group_tickset *set;
nullpo_retr(0, bl);
+ if (group->interval==-1)
+ return NULL;
if (bl->type == BL_PC)
set = ((struct map_session_data *)bl)->skillunittick;
@@ -8890,16 +8411,16 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search(
else
return 0;
- if (skill_unit_overlap_type(sg->skill_id))
- id = s = sg->skill_id;
+ if (skill_get_unit_flag(group->skill_id)&UF_NOOVERLAP)
+ id = s = group->skill_id;
else
- id = s = sg->group_id;
+ id = s = group->group_id;
for (i=0; i<MAX_SKILLUNITGROUPTICKSET; i++) {
k = (i+s) % MAX_SKILLUNITGROUPTICKSET;
if (set[k].id == id)
return &set[k];
- else if (j == -1 && set[k].id == 0)
+ else if (j==-1 && (DIFF_TICK(tick,set[k].tick)>0 || set[k].id==0))
j=k;
}
@@ -8908,101 +8429,41 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search(
sprintf (tmp_output, "skill_unitgrouptickset_search: tickset is full\n");
ShowWarning (tmp_output);
}
- for (i = 0; i<MAX_SKILLUNITGROUPTICKSET; i++)
- set[k].id = 0;
j = id % MAX_SKILLUNITGROUPTICKSET;
}
set[j].id = id;
+ set[j].tick = tick;
return &set[j];
}
/*==========================================
- * スキルユニットグル?プの被影響tick削除
- *------------------------------------------
- */
-int skill_unitgrouptickset_delete(
- struct block_list *bl, struct skill_unit_group *sg)
-{
- int i, k, s, id;
- struct skill_unit_group_tickset *set=NULL;
-
- nullpo_retr(0, bl);
- if (bl->type == BL_PC)
- set=((struct map_session_data *)bl)->skillunittick;
- else if (bl->type == BL_MOB)
- set=((struct mob_data *)bl)->skillunittick;
- else
- return 0;
-
- if (skill_unit_overlap_type(sg->skill_id))
- id = s = sg->skill_id;
- else
- id = s = sg->group_id;
-
- for(i=0; i<MAX_SKILLUNITGROUPTICKSET; i++) {
- k = (i+s) % MAX_SKILLUNITGROUPTICKSET;
- if (set[k].id == id) {
- set[k].id = 0;
- break;
- }
- }
-// if (i == MAX_SKILLUNITGROUPTICKSET && battle_config.error_log) {
-// printf("skill_unitgrouptickset_delete: tickset not found\n");
-// }
-
- return 0;
-}
-
-/*==========================================
* スキルユニットタイマ??動?理用(foreachinarea)
*------------------------------------------
*/
int skill_unit_timer_sub_onplace( struct block_list *bl, va_list ap )
{
- struct block_list *src;
- struct skill_unit *su;
+ struct skill_unit *unit;
+ struct skill_unit_group *group;
unsigned int tick;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
- src=va_arg(ap,struct block_list*);
+ unit = va_arg(ap,struct skill_unit *);
+ tick = va_arg(ap,unsigned int);
- tick=va_arg(ap,unsigned int);
- su = (struct skill_unit *)src;
-
- if( su && su->alive ) {
- struct skill_unit_group *sg;
- sg = su->group;
- if(sg && battle_check_target(src,bl,sg->target_flag )>0)
- skill_unit_onplace( su, bl, tick );
- }
- return 0;
-}
+ if (bl->type!=BL_PC && bl->type!=BL_MOB)
+ return 0;
+ if (!unit->alive || bl->prev==NULL)
+ return 0;
-/*==========================================
- * スキルユニットタイマ?削除?理用(foreachinarea)
- *------------------------------------------
- */
-int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap )
-{
- struct block_list *src;
- struct skill_unit *su;
- unsigned int tick;
+ nullpo_retr(0, group=unit->group);
- nullpo_retr(0, bl);
- nullpo_retr(0, ap);
- src=va_arg(ap,struct block_list*);
+ if (battle_check_target(&unit->bl,bl,group->target_flag)<=0)
+ return 0;
- tick=va_arg(ap,unsigned int);
- su = (struct skill_unit *)src;
+ skill_unit_onplace_timer(unit,bl,tick);
- if( su && su->alive ){
- struct skill_unit_group *sg;
- sg = su->group;
- if( sg && battle_check_target(src,bl,sg->target_flag )>0 )
- skill_unit_ondelete( su, bl, tick );
- }
return 0;
}
@@ -9020,28 +8481,37 @@ int skill_unit_timer_sub( struct block_list *bl, va_list ap )
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, unit=(struct skill_unit *)bl);
- nullpo_retr(0, group=unit->group);
tick=va_arg(ap,unsigned int);
if(!unit->alive)
return 0;
- range=(unit->range!=0)?unit->range:group->range;
+ nullpo_retr(0, group=unit->group);
+ range = unit->range;
- /* onplaceイベント呼び出し */
- if(unit->alive && unit->range>=0){
- map_foreachinarea( skill_unit_timer_sub_onplace, bl->m,
- bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,
- bl,tick);
- if(group->unit_id == 0xaa && DIFF_TICK(tick,group->tick)>=6000*group->val2){
- map_foreachinarea( skill_idun_heal, bl->m,
- bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,unit);
- group->val2++;
+ /* onplace_timerイベント呼び出し */
+ if (range>=0 && group->interval!=-1) {
+ map_foreachinarea(skill_unit_timer_sub_onplace, bl->m,
+ bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,bl,tick);
+ if (!unit->alive)
+ return 0;
+ // マグヌスは発動したユニットは削除する
+ if (group->skill_id==PR_MAGNUS && unit->val2) {
+ skill_delunit(unit);
+ return 0;
}
}
+ // イドゥンの林檎による回復
+ if (group->unit_id==0xaa && DIFF_TICK(tick,group->tick)>=6000*group->val3) {
+ struct block_list *src = map_id2bl(group->src_id);
+ int range = skill_get_unit_layout_type(group->skill_id,group->skill_lv);
+ nullpo_retr(0, src);
+ map_foreachinarea(skill_idun_heal,src->m,
+ src->x-range,src->y-range,src->x+range,src->y+range,0,unit);
+ group->val3++;
+ }
/* 時間切れ削除 */
- if(unit->alive &&
- (DIFF_TICK(tick,group->tick)>=group->limit || DIFF_TICK(tick,group->tick)>=unit->limit) ){
+ if((DIFF_TICK(tick,group->tick)>=group->limit || DIFF_TICK(tick,group->tick)>=unit->limit)){
switch(group->unit_id){
case 0x8f: /* ブラストマイン */
group->unit_id = 0x8c;
@@ -9117,92 +8587,33 @@ int skill_unit_timer( int tid,unsigned int tick,int id,int data)
* スキルユニット移動時?理用(foreachinarea)
*------------------------------------------
*/
-int skill_unit_out_all_sub( struct block_list *bl, va_list ap )
-{
- struct skill_unit *unit;
- struct skill_unit_group *group;
- struct block_list *src;
- int range;
- unsigned int tick;
-
- nullpo_retr(0, bl);
- nullpo_retr(0, ap);
- nullpo_retr(0, src=va_arg(ap,struct block_list*));
- nullpo_retr(0, unit=(struct skill_unit *)bl);
- nullpo_retr(0, group=unit->group);
-
- tick=va_arg(ap,unsigned int);
-
- if(!unit->alive || src->prev==NULL)
- return 0;
-
- range=(unit->range!=0)?unit->range:group->range;
-
- if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 )
- return 0;
-
- if( src->x >= bl->x-range && src->x <= bl->x+range &&
- src->y >= bl->y-range && src->y <= bl->y+range )
- skill_unit_onout( unit, src, tick );
-
- return 0;
-}
-
-
-/*==========================================
- * スキルユニット移動時?理
- *------------------------------------------
- */
-int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range)
-{
- nullpo_retr(0, bl);
-
- if( bl->prev==NULL )
- return 0;
-
- if(range<7)
- range=7;
- map_foreachinarea( skill_unit_out_all_sub,
- bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL,
- bl,tick );
-
- return 0;
-}
-
-/*==========================================
- * スキルユニット移動時?理用(foreachinarea)
- *------------------------------------------
- */
int skill_unit_move_sub( struct block_list *bl, va_list ap )
{
- struct skill_unit *unit;
+ struct skill_unit *unit = (struct skill_unit *)bl;
struct skill_unit_group *group;
- struct block_list *src;
- int range;
- unsigned int tick;
+ struct block_list *target;
+ unsigned int tick,flag;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
- nullpo_retr(0, unit=(struct skill_unit *)bl);
- nullpo_retr(0, src=va_arg(ap,struct block_list*));
-
- tick=va_arg(ap,unsigned int);
+ nullpo_retr(0, target=va_arg(ap,struct block_list*));
+ tick = va_arg(ap,unsigned int);
+ flag = va_arg(ap,int);
- if(!unit->alive || src->prev==NULL)
+ if (target->type!=BL_PC && target->type!=BL_MOB)
return 0;
- if((group=unit->group) == NULL)
+ nullpo_retr(0, group=unit->group);
+ if (group->interval!=-1)
return 0;
- range=(unit->range!=0)?unit->range:group->range;
- if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 )
+ if (!unit->alive || target->prev==NULL)
return 0;
- if( src->x >= bl->x-range && src->x <= bl->x+range &&
- src->y >= bl->y-range && src->y <= bl->y+range )
- skill_unit_onplace( unit, src, tick );
+ if (flag)
+ skill_unit_onplace(unit,target,tick);
else
- skill_unit_onout( unit, src, tick );
+ skill_unit_onout(unit,target,tick);
return 0;
}
@@ -9211,54 +8622,16 @@ int skill_unit_move_sub( struct block_list *bl, va_list ap )
* スキルユニット移動時?理
*------------------------------------------
*/
-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)
{
nullpo_retr(0, bl);
- if( bl->prev==NULL )
+ if(bl->prev==NULL )
return 0;
- if(range<7)
- range=7;
- map_foreachinarea( skill_unit_move_sub,
- bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL,
- bl,tick );
-
- return 0;
-}
+ map_foreachinarea(skill_unit_move_sub,
+ bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,bl,tick,flag);
-/*==========================================
- * スキルユニット自?の移動時?理(foreachinarea)
- *------------------------------------------
- */
-int skill_unit_move_unit_group_sub( struct block_list *bl, va_list ap )
-{
- struct skill_unit *unit;
- struct skill_unit_group *group;
- struct block_list *src;
- int range;
- unsigned int tick;
-
- nullpo_retr(0, bl);
- nullpo_retr(0, ap);
- nullpo_retr(0, src=va_arg(ap,struct block_list*));
- nullpo_retr(0, unit=(struct skill_unit *)src);
- nullpo_retr(0, group=unit->group);
-
- tick=va_arg(ap,unsigned int);
-
- if(!unit->alive || bl->prev==NULL)
- return 0;
-
- range=(unit->range!=0)?unit->range:group->range;
-
- if( range<0 || battle_check_target(src,bl,group->target_flag )<=0 )
- return 0;
- if( bl->x >= src->x-range && bl->x <= src->x+range &&
- bl->y >= src->y-range && bl->y <= src->y+range )
- skill_unit_onplace( unit, bl, tick );
- else
- skill_unit_onout( unit, bl, tick );
return 0;
}
@@ -9269,115 +8642,97 @@ int skill_unit_move_unit_group_sub( struct block_list *bl, va_list ap )
*/
int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int dy)
{
+ int i,j;
+ int tick = gettick();
+ int *m_flag;
+ struct skill_unit *unit1;
+ struct skill_unit *unit2;
+
nullpo_retr(0, group);
+ if (group->unit_count<=0)
+ return 0;
+ if (group->unit==NULL)
+ return 0;
- if( group->unit_count<=0)
+ // 移動可能なスキルはダンス系と、ブラストマイン、クレイモアートラップのみ
+ if (!(skill_get_unit_flag(group->skill_id)&UF_DANCE) &&
+ group->skill_id!=HT_CLAYMORETRAP && group->skill_id!=HT_BLASTMINE)
return 0;
- if(group->unit!=NULL){
- if(!battle_config.unit_movement_type){
- int i;
- for(i=0;i<group->unit_count;i++){
- struct skill_unit *unit=&group->unit[i];
- if(unit->alive && !(m==unit->bl.m && dx==0 && dy==0)){
- int range=unit->range;
- map_delblock(&unit->bl);
- unit->bl.m = m;
- unit->bl.x += dx;
- unit->bl.y += dy;
- map_addblock(&unit->bl);
- clif_skill_setunit(unit);
- if(range>0){
- if(range<7)
- range=7;
- map_foreachinarea( skill_unit_move_unit_group_sub, unit->bl.m,
- unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0,
- &unit->bl,gettick() );
- }
- }
+ m_flag = malloc(sizeof(int)*group->unit_count);
+ memset(m_flag,0,sizeof(int)*group->unit_count);// 移動フラグ
+ // 先にフラグを全部決める
+ // m_flag
+ // 0: 単純移動
+ // 1: ユニットを移動する(現位置からユニットがなくなる)
+ // 2: 残留&新位置が移動先となる(移動先にユニットが存在しない)
+ // 3: 残留
+ for(i=0;i<group->unit_count;i++){
+ unit1=&group->unit[i];
+ if (!unit1->alive || unit1->bl.m!=m)
+ continue;
+ for(j=0;j<group->unit_count;j++){
+ unit2=&group->unit[j];
+ if (!unit2->alive)
+ continue;
+ if (unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){
+ // 移動先にユニットがかぶっている
+ m_flag[i] |= 0x1;
}
- }else{
- int i,j, *r_flag, *s_flag, *m_flag;
- struct skill_unit *unit1;
- struct skill_unit *unit2;
- r_flag = (int *) aMallocA(sizeof(int) * group->unit_count);
- s_flag = (int *) aMallocA(sizeof(int) * group->unit_count);
- m_flag = (int *) aMallocA(sizeof(int) * group->unit_count);
- memset(r_flag,0, sizeof(int) * group->unit_count);// ?承フラグ
- memset(s_flag,0, sizeof(int) * group->unit_count);// ?承フラグ
- memset(m_flag,0, sizeof(int) * group->unit_count);// ?承フラグ
-
- //先にフラグを全部決める
- for(i=0;i<group->unit_count;i++){
- int move_check=0;// かぶりフラグ
- unit1=&group->unit[i];
- for(j=0;j<group->unit_count;j++){
- unit2=&group->unit[j];
- if(unit1->bl.m==m && unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){
- //移動先にユニットがかぶってたら
- s_flag[i]=1;// 移動前のユニットナンバ?の?承フラグon
- r_flag[j]=1;// かぶるユニットナンバ?の?留フラグon
- move_check=1;//ユニットがかぶった。
- break;
- }
- }
- if(!move_check)// ユニットがかぶってなかったら
- m_flag[i]=1;// 移動前ユニットナンバ?の移動フラグon
- }
-
- //フラグに基づいてユニット移動
- for(i=0;i<group->unit_count;i++){
- unit1=&group->unit[i];
- if(m_flag[i]){// 移動フラグがonで
- if(!r_flag[i]){// ?留フラグがoffなら
- //?純移動(rangeも?承の必要無し)
- int range=unit1->range;
- map_delblock(&unit1->bl);
- unit1->bl.m = m;
- unit1->bl.x += dx;
- unit1->bl.y += dy;
- map_addblock(&unit1->bl);
- clif_skill_setunit(unit1);
- if(range > 0){
- if(range < 7)
- range = 7;
- map_foreachinarea( skill_unit_move_unit_group_sub, unit1->bl.m,
- unit1->bl.x-range,unit1->bl.y-range,unit1->bl.x+range,unit1->bl.y+range,0,
- &unit1->bl,gettick() );
- }
- }else{// ?留フラグがonなら
- //空ユニットになるので、?承可能なユニットを探す
- for(j=0;j<group->unit_count;j++){
- unit2=&group->unit[j];
- if(s_flag[j] && !r_flag[j]){
- // ?承移動(range?承付き)
- int range=unit1->range;
- map_delblock(&unit2->bl);
- unit2->bl.m = m;
- unit2->bl.x = unit1->bl.x + dx;
- unit2->bl.y = unit1->bl.y + dy;
- unit2->range = unit1->range;
- map_addblock(&unit2->bl);
- clif_skill_setunit(unit2);
- if(range > 0){
- if(range < 7)
- range = 7;
- map_foreachinarea( skill_unit_move_unit_group_sub, unit2->bl.m,
- unit2->bl.x-range,unit2->bl.y-range,unit2->bl.x+range,unit2->bl.y+range,0,
- &unit2->bl,gettick() );
- }
- s_flag[j]=0;// ?承完了したのでoff
- break;
- }
- }
- }
+ if (unit1->bl.x-dx==unit2->bl.x && unit1->bl.y-dy==unit2->bl.y){
+ // ユニットがこの場所にやってくる
+ m_flag[i] |= 0x2;
+ }
+ }
+ }
+ // フラグに基づいてユニット移動
+ // フラグが1のunitを探し、フラグが2のunitの移動先に移す
+ j = 0;
+ for (i=0;i<group->unit_count;i++) {
+ unit1=&group->unit[i];
+ if (!unit1->alive)
+ continue;
+ if (!(m_flag[i]&0x2)) {
+ // ユニットがなくなる場所でスキルユニット影響を消す
+ map_foreachinarea(skill_unit_effect,unit1->bl.m,
+ unit1->bl.x,unit1->bl.y,unit1->bl.x,unit1->bl.y,0,
+ &unit1->bl,tick,0);
+ }
+ if (m_flag[i]==0) {
+ // 単純移動
+ map_delblock(&unit1->bl);
+ unit1->bl.m = m;
+ unit1->bl.x += dx;
+ unit1->bl.y += dy;
+ map_addblock(&unit1->bl);
+ clif_skill_setunit(unit1);
+ } else if (m_flag[i]==1) {
+ // フラグが2のものを探してそのユニットの移動先に移動
+ for(;j<group->unit_count;j++) {
+ if (m_flag[j]==2) {
+ // 継承移動
+ unit2 = &group->unit[j];
+ if (!unit2->alive)
+ continue;
+ map_delblock(&unit1->bl);
+ unit1->bl.m = m;
+ unit1->bl.x = unit2->bl.x+dx;
+ unit1->bl.y = unit2->bl.y+dy;
+ map_addblock(&unit1->bl);
+ clif_skill_setunit(unit1);
+ j++;
+ break;
}
}
- aFree(r_flag);
- aFree(s_flag);
- aFree(m_flag);
+ }
+ if (!(m_flag[i]&0x2)) {
+ // 移動後の場所でスキルユニットを発動
+ map_foreachinarea(skill_unit_effect,unit1->bl.m,
+ unit1->bl.x,unit1->bl.y,unit1->bl.x,unit1->bl.y,0,
+ &unit1->bl,tick,1);
}
}
+ free(m_flag);
return 0;
}
@@ -9505,25 +8860,29 @@ int skill_produce_mix( struct map_session_data *sd,
if(!equip) {
// Corrected rates [DracoRPG] --------------------------//
if(skill_produce_db[idx].req_skill==AM_PHARMACY) {
+ make_per = pc_checkskill(sd,AM_LEARNINGPOTION)*100
+ + pc_checkskill(sd,AM_PHARMACY)*300 + sd->status.job_level*20
+ + sd->status.dex*10+sd->status.int_*5;
+
if(nameid >= 501 && nameid <= 505) // Normal potions
- make_per = 2000 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_POTIONPITCHER)*100;
- if(nameid >= 605 && nameid <= 606) // Anodyne & Aloevera (not sure of the formula, I put the same base value as normal pots but without the Aid Potion bonus since they are not throwable pots ^^)
- make_per = 2000 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300;
+ make_per += 2000 + pc_checkskill(sd,AM_POTIONPITCHER)*100;
+ else if(nameid >= 605 && nameid <= 606) // Anodyne & Aloevera (not sure of the formula, I put the same base value as normal pots but without the Aid Potion bonus since they are not throwable pots ^^)
+ make_per += 2000;
else if(nameid >= 545 && nameid <= 547) // Concentrated potions
- make_per = sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300;
+ ;
else if(nameid == 970) // Alcohol
- make_per = 1000 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300;
+ make_per += 1000;
else if(nameid == 7135) // Bottle Grenade
- make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_DEMONSTRATION)*100;
+ make_per += 500 + pc_checkskill(sd,AM_DEMONSTRATION)*100;
else if(nameid == 7136) // Acid Bottle
- make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_ACIDTERROR)*100;
+ make_per += 500 + pc_checkskill(sd,AM_ACIDTERROR)*100;
else if(nameid == 7137) // Plant Bottle
- make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CANNIBALIZE)*100;
+ make_per += 500 + pc_checkskill(sd,AM_CANNIBALIZE)*100;
else if(nameid == 7138) // Marine Sphere Bottle
- make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_SPHEREMINE)*100;
+ make_per += 500 + pc_checkskill(sd,AM_SPHEREMINE)*100;
else if(nameid == 7139) // Glistening Coat
- make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CP_WEAPON)*100 +
- pc_checkskill(sd,AM_CP_SHIELD)*100 + pc_checkskill(sd,AM_CP_ARMOR)*100 + pc_checkskill(sd,AM_CP_HELM)*100;
+ make_per += 500 + pc_checkskill(sd,AM_CP_WEAPON)*100 + pc_checkskill(sd,AM_CP_SHIELD)*100 +
+ pc_checkskill(sd,AM_CP_ARMOR)*100 + pc_checkskill(sd,AM_CP_HELM)*100;
else
make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300;
} else if (skill_produce_db[idx].req_skill == ASC_CDP) {
@@ -9604,8 +8963,7 @@ int skill_produce_mix( struct map_session_data *sd,
clif_additem(sd,0,0,flag);
map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
}
- }
- else {
+ } else {
if(log_config.produce > 0)
log_produce(sd,nameid,slot1,slot2,slot3,0);
@@ -9675,6 +9033,213 @@ int skill_arrow_create( struct map_session_data *sd,int nameid)
* 初期化系
*/
+/*----------------------------------------------------------------------------
+ * 初期化系
+ */
+
+/*
+ * 文字列処理
+ * ',' で区切って val に戻す
+ */
+int skill_split_str(char *str,char **val,int num)
+{
+ int i;
+
+ for (i=0; i<num && str; i++){
+ val[i] = str;
+ str = strchr(str,',');
+ if (str)
+ *str++=0;
+ }
+ return i;
+}
+/*
+ * 文字列処理
+ * ':' で区切ってatoiしてvalに戻す
+ */
+int skill_split_atoi(char *str,int *val)
+{
+ int i, max = 0;
+
+ for (i=0; i<MAX_SKILL_LEVEL; i++) {
+ if (str) {
+ val[i] = max = atoi(str);
+ str = strchr(str,':');
+ if (str)
+ *str++=0;
+ } else {
+ val[i] = max;
+ }
+ }
+ return i;
+}
+
+/*
+ * スキルユニットの配置情報作成
+ */
+void skill_init_unit_layout()
+{
+ int i,j,size,pos = 0;
+
+ memset(skill_unit_layout,0,sizeof(skill_unit_layout));
+ // 矩形のユニット配置を作成する
+ for (i=0; i<=MAX_SQUARE_LAYOUT; i++) {
+ size = i*2+1;
+ skill_unit_layout[i].count = size*size;
+ for (j=0; j<size*size; j++) {
+ skill_unit_layout[i].dx[j] = (j%size-i);
+ skill_unit_layout[i].dy[j] = (j/size-i);
+ }
+ }
+ pos = i;
+ // 矩形以外のユニット配置を作成する
+ for (i=0;i<MAX_SKILL_DB;i++) {
+ if (!skill_db[i].unit_id[0] || skill_db[i].unit_layout_type[0] != -1)
+ continue;
+ switch (i) {
+ case MG_FIREWALL:
+ case WZ_ICEWALL:
+ // ファイアーウォール、アイスウォールは方向で変わるので別処理
+ break;
+ case PR_SANCTUARY:
+ {
+ static const int dx[] = {
+ -1, 0, 1,-2,-1, 0, 1, 2,-2,-1,
+ 0, 1, 2,-2,-1, 0, 1, 2,-1, 0, 1};
+ static const int dy[]={
+ -2,-2,-2,-1,-1,-1,-1,-1, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2};
+ skill_unit_layout[pos].count = 21;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ break;
+ }
+ case PR_MAGNUS:
+ {
+ static const int dx[] = {
+ -1, 0, 1,-1, 0, 1,-3,-2,-1, 0,
+ 1, 2, 3,-3,-2,-1, 0, 1, 2, 3,
+ -3,-2,-1, 0, 1, 2, 3,-1, 0, 1,-1, 0, 1};
+ static const int dy[] = {
+ -3,-3,-3,-2,-2,-2,-1,-1,-1,-1,
+ -1,-1,-1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3};
+ skill_unit_layout[pos].count = 33;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ break;
+ }
+ case AS_VENOMDUST:
+ {
+ static const int dx[] = {-1, 0, 0, 0, 1};
+ static const int dy[] = { 0,-1, 0, 1, 0};
+ skill_unit_layout[pos].count = 5;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ break;
+ }
+ case CR_GRANDCROSS:
+ case NPC_DARKGRANDCROSS:
+ {
+ static const int dx[] = {
+ 0, 0,-1, 0, 1,-2,-1, 0, 1, 2,
+ -4,-3,-2,-1, 0, 1, 2, 3, 4,-2,
+ -1, 0, 1, 2,-1, 0, 1, 0, 0};
+ static const int dy[] = {
+ -4,-3,-2,-2,-2,-1,-1,-1,-1,-1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 2, 2, 2, 3, 4};
+ skill_unit_layout[pos].count = 29;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ break;
+ }
+ case PF_FOGWALL:
+ {
+ static const int dx[] = {
+ -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2};
+ static const int dy[] = {
+ -1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};
+ skill_unit_layout[pos].count = 15;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ break;
+ }
+ default:
+ printf("unknown unit layout at skill %d\n",i);
+ break;
+ }
+ if (!skill_unit_layout[pos].count)
+ continue;
+ for (j=0;j<MAX_SKILL_LEVEL;j++)
+ skill_db[i].unit_layout_type[j] = pos;
+ pos++;
+ }
+ // ファイヤーウォール
+ firewall_unit_pos = pos;
+ for (i=0;i<8;i++) {
+ if (i&1) { /* 斜め配置 */
+ skill_unit_layout[pos].count = 5;
+ if (i&0x2) {
+ int dx[] = {-1,-1, 0, 0, 1};
+ int dy[] = { 1, 0, 0,-1,-1};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ } else {
+ int dx[] = { 1, 1 ,0, 0,-1};
+ int dy[] = { 1, 0, 0,-1,-1};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ } else { /* 縦横配置 */
+ skill_unit_layout[pos].count = 3;
+ if (i%4==0) { /* 上下 */
+ int dx[] = {-1, 0, 1};
+ int dy[] = { 0, 0, 0};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ } else { /* 左右 */
+ int dx[] = { 0, 0, 0};
+ int dy[] = {-1, 0, 1};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ }
+ pos++;
+ }
+ // アイスウォール
+ icewall_unit_pos = pos;
+ for (i=0;i<8;i++) {
+ skill_unit_layout[pos].count = 5;
+ if (i&1) { /* 斜め配置 */
+ if (i&0x2) {
+ int dx[] = {-2,-1, 0, 1, 2};
+ int dy[] = { 2,-1, 0,-1,-2};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ } else {
+ int dx[] = { 2, 1 ,0,-1,-2};
+ int dy[] = { 2, 1, 0,-1,-2};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ } else { /* 縦横配置 */
+ if (i%4==0) { /* 上下 */
+ int dx[] = {-2,-1, 0, 1, 2};
+ int dy[] = { 0, 0, 0, 0, 0};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ } else { /* 左右 */
+ int dx[] = { 0, 0, 0, 0, 0};
+ int dy[] = {-2,-1, 0, 1, 2};
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ }
+ pos++;
+ }
+}
+
/*==========================================
* スキル?係ファイル?み?み
* skill_db.txt スキルデ?タ
@@ -9699,14 +9264,10 @@ int skill_readdb(void)
return 1;
}
while(fgets(line,1020,fp)){
- char *split[50], *split2[MAX_SKILL_LEVEL];
+ char *split[50];
if(line[0]=='/' && line[1]=='/')
continue;
- for(j=0,p=line;j<14 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
+ j = skill_split_str(line,split,14);
if(split[13]==NULL || j<14)
continue;
@@ -9717,28 +9278,13 @@ int skill_readdb(void)
continue;
/* printf("skill id=%d\n",i); */
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].range[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+ skill_split_atoi(split[1],skill_db[i].range);
skill_db[i].hit=atoi(split[2]);
skill_db[i].inf=atoi(split[3]);
skill_db[i].pl=atoi(split[4]);
skill_db[i].nk=atoi(split[5]);
skill_db[i].max=atoi(split[6]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[7];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].num[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+ skill_split_atoi(split[1],skill_db[i].num);
if(strcmpi(split[8],"yes") == 0)
skill_db[i].castcancel=1;
@@ -9755,14 +9301,7 @@ int skill_readdb(void)
skill_db[i].skill_type=BF_MISC;
else
skill_db[i].skill_type=0;
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[13];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].blewcount[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+ skill_split_atoi(split[13],skill_db[i].blewcount);
}
fclose(fp);
sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_db.txt");
@@ -9774,14 +9313,10 @@ int skill_readdb(void)
return 1;
}
while(fgets(line,1020,fp)){
- char *split[51], *split2[MAX_SKILL_LEVEL];
+ char *split[50];
if(line[0]=='/' && line[1]=='/')
continue;
- for(j=0,p=line;j<30 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
+ j = skill_split_str(line,split,30);
if(split[29]==NULL || j<30)
continue;
@@ -9791,74 +9326,26 @@ int skill_readdb(void)
else if(i<=0 || i>MAX_SKILL_DB)
continue;
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].hp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].mhp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].sp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].hp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[5];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].sp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[6];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].zeny[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[7];j<32 && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<32 && split2[k];k++) {
- l = atoi(split2[k]);
- if(l == 99) {
+ skill_split_atoi(split[1],skill_db[i].hp);
+ skill_split_atoi(split[2],skill_db[i].mhp);
+ skill_split_atoi(split[3],skill_db[i].sp);
+ skill_split_atoi(split[4],skill_db[i].hp_rate);
+ skill_split_atoi(split[5],skill_db[i].sp_rate);
+ skill_split_atoi(split[6],skill_db[i].zeny);
+
+ p = split[7];
+ for(j=0;j<32;j++){
+ l = atoi(p);
+ if (l==99) {
skill_db[i].weapon = 0xffffffff;
break;
}
else
skill_db[i].weapon |= 1<<l;
+ p=strchr(p,':');
+ if(!p)
+ break;
+ p++;
}
if( strcmpi(split[8],"hiding")==0 ) skill_db[i].state=ST_HIDING;
@@ -9875,14 +9362,7 @@ int skill_readdb(void)
else if( strcmpi(split[8],"water")==0 ) skill_db[i].state=ST_WATER;
else skill_db[i].state=ST_NONE;
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[9];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].spiritball[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+ skill_split_atoi(split[9],skill_db[i].spiritball);
skill_db[i].itemid[0]=atoi(split[10]);
skill_db[i].amount[0]=atoi(split[11]);
skill_db[i].itemid[1]=atoi(split[12]);
@@ -9915,15 +9395,11 @@ int skill_readdb(void)
return 1;
}
while(fgets(line,1020,fp)){
- char *split[50], *split2[MAX_SKILL_LEVEL];
+ char *split[50];
memset(split,0,sizeof(split)); // [Valaris] thanks to fov
if(line[0]=='/' && line[1]=='/')
continue;
- for(j=0,p=line;j<5 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
+ j = skill_split_str(line,split,5);
if(split[4]==NULL || j<5)
continue;
@@ -9933,45 +9409,55 @@ int skill_readdb(void)
else if(i<=0 || i>MAX_SKILL_DB)
continue;
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].cast[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].delay[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+ skill_split_atoi(split[1],skill_db[i].cast);
+ skill_split_atoi(split[2],skill_db[i].delay);
+ skill_split_atoi(split[3],skill_db[i].upkeep_time);
+ skill_split_atoi(split[4],skill_db[i].upkeep_time2);
+ }
+ fclose(fp);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_cast_db.txt");
+ ShowStatus(tmp_output);
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].upkeep_time[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+ /* スキルユニットデータベース */
+ fp = fopen("db/skill_unit_db.txt","r");
+ if (fp==NULL) {
+ printf("can't read db/skill_unit_db.txt\n");
+ return 1;
+ }
+ while (fgets(line,1020,fp)) {
+ char *split[50];
+ if (line[0]=='/' && line[1]=='/')
+ continue;
+ j = skill_split_str(line,split,8);
+ if (split[7]==NULL || j<8)
+ continue;
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].upkeep_time2[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+ i=atoi(split[0]);
+ if (i>=10000 && i<10015) // for guild skills [Celest]
+ i -= 9500;
+ else if(i<=0 || i>MAX_SKILL_DB)
+ continue;
+ skill_db[i].unit_id[0] = strtol(split[1],NULL,16);
+ skill_db[i].unit_id[1] = strtol(split[2],NULL,16);
+ skill_split_atoi(split[3],skill_db[i].unit_layout_type);
+ skill_db[i].unit_range = atoi(split[4]);
+ skill_db[i].unit_interval = atoi(split[5]);
+
+ if( strcmpi(split[6],"noenemy")==0 ) skill_db[i].unit_target=BCT_NOENEMY;
+ else if( strcmpi(split[6],"friend")==0 ) skill_db[i].unit_target=BCT_NOENEMY;
+ else if( strcmpi(split[6],"party")==0 ) skill_db[i].unit_target=BCT_PARTY;
+ else if( strcmpi(split[6],"all")==0 ) skill_db[i].unit_target=BCT_ALL;
+ else if( strcmpi(split[6],"enemy")==0 ) skill_db[i].unit_target=BCT_ENEMY;
+ else if( strcmpi(split[6],"self")==0 ) skill_db[i].unit_target=BCT_SELF;
+ else skill_db[i].unit_target = strtol(split[6],NULL,16);
+
+ skill_db[i].unit_flag = strtol(split[7],NULL,16);
+ k++;
}
fclose(fp);
- sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_cast_db.txt");
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_unit_db.txt");
ShowStatus(tmp_output);
+ skill_init_unit_layout();
/* 製造系スキルデ?タベ?ス */
memset(skill_produce_db,0,sizeof(skill_produce_db));
@@ -9990,16 +9476,11 @@ int skill_readdb(void)
if(line[0]=='/' && line[1]=='/')
continue;
memset(split,0,sizeof(split));
- for(j=0,p=line;j<3 + MAX_PRODUCE_RESOURCE * 2 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
+ j = skill_split_str(line,split,(3 + MAX_PRODUCE_RESOURCE * 2));
if(split[0]==0) //fixed by Lupus
continue;
i=atoi(split[0]);
- if(i<=0)
- continue;
+ if(i<=0) continue;
skill_produce_db[k].nameid=i;
skill_produce_db[k].itemlv=atoi(split[1]);
@@ -10031,11 +9512,7 @@ int skill_readdb(void)
if(line[0]=='/' && line[1]=='/')
continue;
memset(split,0,sizeof(split));
- for(j=0,p=line;j<13 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
+ j = skill_split_str(line,split,13);
if(split[0]==0) //fixed by Lupus
continue;
i=atoi(split[0]);
@@ -10068,11 +9545,7 @@ int skill_readdb(void)
if(line[0]=='/' && line[1]=='/')
continue;
memset(split,0,sizeof(split));
- for(j=0,p=line;j<13 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
+ j = skill_split_str(line,split,13);
if(split[0]==0) //fixed by Lupus
continue;
i=atoi(split[0]);
@@ -10096,15 +9569,11 @@ int skill_readdb(void)
return 1;
}
while(fgets(line,1020,fp)){
- char *split[50], *split2[MAX_SKILL_LEVEL];
+ char *split[50];
if(line[0]=='/' && line[1]=='/')
continue;
memset(split,0,sizeof(split));
- for(j=0,p=line;j<3 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
+ j = skill_split_str(line,split,3);
if(split[0]==0) //fixed by Lupus
continue;
i=atoi(split[0]);
@@ -10113,25 +9582,10 @@ int skill_readdb(void)
else if(i<=0 || i>MAX_SKILL_DB)
continue;
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].castnodex[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
-
+ skill_split_atoi(split[1],skill_db[i].castnodex);
if (!split[2])
continue;
- memset(split2,0,sizeof(split2));
- for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){
- split2[j]=p;
- p=strchr(p,':');
- if(p) *p++=0;
- }
- for(k=0;k<MAX_SKILL_LEVEL;k++)
- skill_db[i].delaynodex[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+ skill_split_atoi(split[2],skill_db[i].delaynodex);
}
fclose(fp);
sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_castnodex_db.txt");
@@ -10148,11 +9602,7 @@ int skill_readdb(void)
if(line[0]=='/' && line[1]=='/')
continue;
memset(split,0,sizeof(split));
- for(j=0,p=line;j<2 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
+ j = skill_split_str(line,split,2);
if(split[0]==0) //fixed by Lupus
continue;
i=atoi(split[0]);
diff --git a/src/map/skill.h b/src/map/skill.h
index dc789aa4a..72653e9a9 100644
--- a/src/map/skill.h
+++ b/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);
diff --git a/src/map/status.c b/src/map/status.c
index 0d35572d0..5275be42a 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -31,14 +31,17 @@ int SkillStatusChangeTable[]={ /* status.hのenumのSC_***とあわせること */
-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) {
diff --git a/src/map/status.h b/src/map/status.h
index d788c7b50..fbeee7300 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -111,7 +111,7 @@ enum { // struct map_session_data の status_changeの番?テ?ブル
//-- 137-139
SC_SAFETYWALL = 140,
SC_PNEUMA = 141,
- SC_WATERBALL = 142,
+//-- 142
SC_ANKLE = 143,
SC_DANCING = 144,
SC_KEEPING = 145,
diff --git a/src/txt-converter/char/Makefile b/src/txt-converter/char/Makefile
index a4cca87fd..6b85a04db 100644
--- a/src/txt-converter/char/Makefile
+++ b/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)
diff --git a/src/txt-converter/login/Makefile b/src/txt-converter/login/Makefile
index 56b97e772..7158931d0 100644
--- a/src/txt-converter/login/Makefile
+++ b/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