summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/GNUmakefile75
-rw-r--r--src/map/Makefile103
-rw-r--r--src/map/Makefile.win3215
-rw-r--r--src/map/atcommand.c4043
-rw-r--r--src/map/atcommand.h72
-rw-r--r--src/map/battle.c2751
-rw-r--r--src/map/battle.h97
-rw-r--r--src/map/charcommand.c626
-rw-r--r--src/map/charcommand.h9
-rw-r--r--src/map/chat.c16
-rw-r--r--src/map/chrif.c259
-rw-r--r--src/map/chrif.h8
-rw-r--r--src/map/clif.c3552
-rw-r--r--src/map/clif.h33
-rw-r--r--src/map/guild.c313
-rw-r--r--src/map/guild.h4
-rw-r--r--src/map/intif.c169
-rw-r--r--src/map/intif.h6
-rw-r--r--src/map/itemdb.c339
-rw-r--r--src/map/itemdb.h3
-rw-r--r--src/map/log.c397
-rw-r--r--src/map/log.h13
-rw-r--r--src/map/mail.c259
-rw-r--r--src/map/map.c2012
-rw-r--r--src/map/map.h196
-rw-r--r--src/map/mob.c1798
-rw-r--r--src/map/mob.h32
-rw-r--r--src/map/npc.c1028
-rw-r--r--src/map/npc.h16
-rw-r--r--src/map/npc_chat.c502
-rw-r--r--src/map/party.c56
-rw-r--r--src/map/party.h2
-rw-r--r--src/map/path.c86
-rw-r--r--src/map/pc.c3294
-rw-r--r--src/map/pc.h51
-rw-r--r--src/map/pet.c305
-rw-r--r--src/map/pet.h8
-rw-r--r--src/map/script.c1506
-rw-r--r--src/map/script.h24
-rw-r--r--src/map/skill.c8690
-rw-r--r--src/map/skill.h270
-rw-r--r--src/map/status.c5159
-rw-r--r--src/map/status.h271
-rw-r--r--src/map/storage.c207
-rw-r--r--src/map/storage.h2
-rw-r--r--src/map/trade.c395
-rw-r--r--src/map/vending.c21
47 files changed, 23933 insertions, 15160 deletions
diff --git a/src/map/GNUmakefile b/src/map/GNUmakefile
deleted file mode 100644
index 03f520f37..000000000
--- a/src/map/GNUmakefile
+++ /dev/null
@@ -1,75 +0,0 @@
-all: txt sql
-
-txt: txtobj map-server
-
-sql: sqlobj map-server_sql
-
-txtobj:
- mkdir 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
-LIBS = -lz -lm
-
-map-server: txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/npc.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 $(COMMON_OBJ)
- $(CC) -o ../../$@ $^ $(LIBS)
-
-map-server_sql: sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/npc.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/charcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/mail.o sqlobj/log.o $(COMMON_OBJ)
- $(CC) -o ../../$@ $^ $(LIB_S)
-
-txtobj/%.o: %.c
- $(COMPILE.c) -DTXT_ONLY $(OUTPUT_OPTION) $<
-
-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/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/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 ../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/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/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/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/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
-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
-
-clean:
- rm -rf *.o ../../map-server ../../map-server_sql sqlobj txtobj
diff --git a/src/map/Makefile b/src/map/Makefile
index 4786887ae..b413c8a62 100644
--- a/src/map/Makefile
+++ b/src/map/Makefile
@@ -10,13 +10,15 @@ 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_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/npc.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 $(COMMON_OBJ)
- $(CC) -o ../../$@ $> $(LIBS)
+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)
+ $(CC) -o ../../$@ $> $(LIBS) $(LIB_S)
-map-server_sql: sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/npc.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/charcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/mail.o sqlobj/log.o $(COMMON_OBJ)
+map-server_sql: sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/status.o sqlobj/npc.o sqlobj/npc_chat.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/charcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/mail.o sqlobj/log.o $(COMMON_OBJ)
$(CC) -o ../../$@ $> $(LIB_S)
txtobj/%.o: %.c
@@ -25,51 +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/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/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 ../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/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/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/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
-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/Makefile.win32 b/src/map/Makefile.win32
index ed4b4e95a..2fa1861ac 100644
--- a/src/map/Makefile.win32
+++ b/src/map/Makefile.win32
@@ -15,25 +15,28 @@ txtobj:
sqlobj:
mkdir sqlobj
-ZLIBDIR = C:/eathena/zlib122
-PACKETDEF = -DPACKETVER=5 -DNEW_006b -D__WIN32
+ZLIBDIR = ../zlib
+PACKETDEF = -DPACKETVER=6 -DNEW_006b -D__WIN32 -DLOCALZLIB
# OPT = /MDd /D_DEBUG
OPT =
LINKOPT = /debug /SUBSYSTEM:CONSOLE
# OPT = /O2
CFLAGS = $(OPT) /nologo /I../common /I$(ZLIBDIR) $(PACKETDEF) /D_WIN32
-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_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/utils.o
+
LIBS = "WSOCK32.LIB"
# "WSOCK32.LIB" "USER32.LIB" "ADVAPI32.LIB" "MSVCRT.LIB" "OLDNAMES.LIB" "KERNEL32.LIB"
-TXTOBJS = txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/npc.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/battle.o txtobj/intif.o txtobj/trade.o txtobj/party.o txtobj/vending.o txtobj/guild.o txtobj/pet.o $(COMMON_OBJ) $(ZLIBDIR)/inflate.o $(ZLIBDIR)/adler32.o $(ZLIBDIR)/crc32.o $(ZLIBDIR)/inftrees.o $(ZLIBDIR)/zutil.o $(ZLIBDIR)/inffast.o
+TXTOBJS = 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) $(ZLIBDIR)/inflate.o $(ZLIBDIR)/deflate.o $(ZLIBDIR)/trees.o $(ZLIBDIR)/adler32.o $(ZLIBDIR)/compress.o $(ZLIBDIR)/crc32.o $(ZLIBDIR)/inftrees.o $(ZLIBDIR)/zutil.o $(ZLIBDIR)/inffast.o
+
+SQLOBJS = sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/status.o sqlobj/npc.o sqlobj/npc_chat.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/charcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/log.o $(COMMON_OBJ) $(ZLIBDIR)/inflate.o $(ZLIBDIR)/adler32.o $(ZLIBDIR)/crc32.o $(ZLIBDIR)/inftrees.o $(ZLIBDIR)/zutil.o $(ZLIBDIR)/inffast.o
map-server: $(TXTOBJS)
link $(LINKOPT) /out:../../$@.exe $(TXTOBJS) $(LIBS)
-map-server_sql: sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/npc.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/mail.o $(COMMON_OBJ)
+map-server_sql: $(SQLOBJS)
link $(LINKOPT) /out:../../$@.exe $> $(LIBS)
txtobj/%.o: %.c
@@ -86,7 +89,7 @@ sqlobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h ../common/db.
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
+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
clean:
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 34bf0150d..79e3ec675 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -8,6 +8,9 @@
#include "../common/socket.h"
#include "../common/timer.h"
#include "../common/nullpo.h"
+#include "../common/mmo.h"
+#include "../common/db.h"
+#include "../common/core.h"
#include "log.h"
#include "clif.h"
@@ -16,6 +19,7 @@
#include "itemdb.h"
#include "map.h"
#include "pc.h"
+#include "status.h"
#include "skill.h"
#include "mob.h"
#include "pet.h"
@@ -26,7 +30,6 @@
#include "script.h"
#include "npc.h"
#include "trade.h"
-#include "core.h"
#ifndef TXT_ONLY
#include "mail.h"
@@ -36,201 +39,233 @@
static char command_symbol = '@'; // first char of the commands (by [Yor])
-static char msg_table[1000][1024]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others)
-
-#define ATCOMMAND_FUNC(x) int atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message)
-ATCOMMAND_FUNC(broadcast);
-ATCOMMAND_FUNC(localbroadcast);
-ATCOMMAND_FUNC(rurap);
-ATCOMMAND_FUNC(rura);
-ATCOMMAND_FUNC(where);
-ATCOMMAND_FUNC(jumpto);
-ATCOMMAND_FUNC(jump);
-ATCOMMAND_FUNC(who);
-ATCOMMAND_FUNC(who2);
-ATCOMMAND_FUNC(who3);
-ATCOMMAND_FUNC(whomap);
-ATCOMMAND_FUNC(whomap2);
-ATCOMMAND_FUNC(whomap3);
-ATCOMMAND_FUNC(whogm); // by Yor
-ATCOMMAND_FUNC(whozeny); // [Valaris]
-ATCOMMAND_FUNC(happyhappyjoyjoy); // [Valaris]
-ATCOMMAND_FUNC(save);
-ATCOMMAND_FUNC(load);
-ATCOMMAND_FUNC(speed);
-ATCOMMAND_FUNC(storage);
-ATCOMMAND_FUNC(guildstorage);
-ATCOMMAND_FUNC(option);
-ATCOMMAND_FUNC(hide);
-ATCOMMAND_FUNC(jobchange);
-ATCOMMAND_FUNC(die);
-ATCOMMAND_FUNC(kill);
-ATCOMMAND_FUNC(alive);
-ATCOMMAND_FUNC(kami);
-ATCOMMAND_FUNC(heal);
-ATCOMMAND_FUNC(item);
-ATCOMMAND_FUNC(item2);
-ATCOMMAND_FUNC(itemreset);
-ATCOMMAND_FUNC(itemcheck);
-ATCOMMAND_FUNC(baselevelup);
-ATCOMMAND_FUNC(joblevelup);
-ATCOMMAND_FUNC(help);
-ATCOMMAND_FUNC(gm);
-ATCOMMAND_FUNC(pvpoff);
-ATCOMMAND_FUNC(pvpon);
-ATCOMMAND_FUNC(gvgoff);
-ATCOMMAND_FUNC(gvgon);
-ATCOMMAND_FUNC(model);
-ATCOMMAND_FUNC(go);
-ATCOMMAND_FUNC(monster);
-ATCOMMAND_FUNC(monstersmall);
-ATCOMMAND_FUNC(monsterbig);
-ATCOMMAND_FUNC(spawn);
-ATCOMMAND_FUNC(killmonster);
-ATCOMMAND_FUNC(killmonster2);
-ATCOMMAND_FUNC(refine);
-ATCOMMAND_FUNC(produce);
-ATCOMMAND_FUNC(memo);
-ATCOMMAND_FUNC(gat);
-ATCOMMAND_FUNC(packet);
-ATCOMMAND_FUNC(statuspoint);
-ATCOMMAND_FUNC(skillpoint);
-ATCOMMAND_FUNC(zeny);
-ATCOMMAND_FUNC(param);
-ATCOMMAND_FUNC(guildlevelup);
-ATCOMMAND_FUNC(makeegg);
-ATCOMMAND_FUNC(hatch);
-ATCOMMAND_FUNC(petfriendly);
-ATCOMMAND_FUNC(pethungry);
-ATCOMMAND_FUNC(petrename);
-ATCOMMAND_FUNC(recall);
-ATCOMMAND_FUNC(recallall);
-ATCOMMAND_FUNC(revive);
-ATCOMMAND_FUNC(character_stats_all);
-ATCOMMAND_FUNC(character_save);
-ATCOMMAND_FUNC(night);
-ATCOMMAND_FUNC(day);
-ATCOMMAND_FUNC(doom);
-ATCOMMAND_FUNC(doommap);
-ATCOMMAND_FUNC(raise);
-ATCOMMAND_FUNC(raisemap);
-ATCOMMAND_FUNC(character_baselevel);
-ATCOMMAND_FUNC(character_joblevel);
-ATCOMMAND_FUNC(kick);
-ATCOMMAND_FUNC(kickall);
-ATCOMMAND_FUNC(allskill);
-ATCOMMAND_FUNC(questskill);
-ATCOMMAND_FUNC(charquestskill);
-ATCOMMAND_FUNC(lostskill);
-ATCOMMAND_FUNC(charlostskill);
-ATCOMMAND_FUNC(spiritball);
-ATCOMMAND_FUNC(party);
-ATCOMMAND_FUNC(guild);
-ATCOMMAND_FUNC(charskreset);
-ATCOMMAND_FUNC(charstreset);
-ATCOMMAND_FUNC(charreset);
-ATCOMMAND_FUNC(charstpoint);
-ATCOMMAND_FUNC(charmodel);
-ATCOMMAND_FUNC(charskpoint);
-ATCOMMAND_FUNC(charzeny);
-ATCOMMAND_FUNC(agitstart);
-ATCOMMAND_FUNC(agitend);
-ATCOMMAND_FUNC(reloaditemdb);
-ATCOMMAND_FUNC(reloadmobdb);
-ATCOMMAND_FUNC(reloadskilldb);
-#ifndef TXT_ONLY
-ATCOMMAND_FUNC(rehash);// by Fr3DBr
-#else /* TXT_ONLY */
-ATCOMMAND_FUNC(reloadscript);
-#endif /* TXT_ONLY */
-ATCOMMAND_FUNC(reloadgmdb); // by Yor
-ATCOMMAND_FUNC(mapexit);
-ATCOMMAND_FUNC(idsearch);
-ATCOMMAND_FUNC(mapinfo);
-ATCOMMAND_FUNC(dye); //** by fritz
-ATCOMMAND_FUNC(hair_style); //** by fritz
-ATCOMMAND_FUNC(hair_color); //** by fritz
-ATCOMMAND_FUNC(stat_all); //** by fritz
-ATCOMMAND_FUNC(char_change_sex); // by Yor
-ATCOMMAND_FUNC(char_block); // by Yor
-ATCOMMAND_FUNC(char_ban); // by Yor
-ATCOMMAND_FUNC(char_unblock); // by Yor
-ATCOMMAND_FUNC(char_unban); // by Yor
-ATCOMMAND_FUNC(mount_peco); // by Valaris
-ATCOMMAND_FUNC(char_mount_peco); // by Yor
-ATCOMMAND_FUNC(guildspy); // [Syrus22]
-ATCOMMAND_FUNC(partyspy); // [Syrus22]
-ATCOMMAND_FUNC(repairall); // [Valaris]
-ATCOMMAND_FUNC(guildrecall); // by Yor
-ATCOMMAND_FUNC(partyrecall); // by Yor
-//ATCOMMAND_FUNC(nuke); // [Valaris]
-ATCOMMAND_FUNC(enablenpc);
-ATCOMMAND_FUNC(disablenpc);
-ATCOMMAND_FUNC(servertime); // by Yor
-ATCOMMAND_FUNC(chardelitem); // by Yor
-ATCOMMAND_FUNC(jail); // by Yor
-ATCOMMAND_FUNC(unjail); // by Yor
-ATCOMMAND_FUNC(disguise); // [Valaris]
-ATCOMMAND_FUNC(undisguise); // by Yor
-ATCOMMAND_FUNC(chardisguise); // Kalaspuff
-ATCOMMAND_FUNC(charundisguise); // Kalaspuff
-ATCOMMAND_FUNC(email); // by Yor
-ATCOMMAND_FUNC(effect);//by Apple
-ATCOMMAND_FUNC(character_item_list); // by Yor
-ATCOMMAND_FUNC(character_storage_list); // by Yor
-ATCOMMAND_FUNC(character_cart_list); // by Yor
-ATCOMMAND_FUNC(addwarp); // by MouseJstr
-ATCOMMAND_FUNC(follow); // by MouseJstr
-ATCOMMAND_FUNC(skillon); // by MouseJstr
-ATCOMMAND_FUNC(skilloff); // by MouseJstr
-ATCOMMAND_FUNC(killer); // by MouseJstr
-ATCOMMAND_FUNC(npcmove); // by MouseJstr
-ATCOMMAND_FUNC(killable); // by MouseJstr
-ATCOMMAND_FUNC(charkillable); // by MouseJstr
-ATCOMMAND_FUNC(chareffect); // by MouseJstr
-ATCOMMAND_FUNC(chardye); // by MouseJstr
-ATCOMMAND_FUNC(charhairstyle); // by MouseJstr
-ATCOMMAND_FUNC(charhaircolor); // by MouseJstr
-ATCOMMAND_FUNC(dropall); // by MouseJstr
-ATCOMMAND_FUNC(chardropall); // by MouseJstr
-ATCOMMAND_FUNC(storeall); // by MouseJstr
-ATCOMMAND_FUNC(charstoreall); // by MouseJstr
-ATCOMMAND_FUNC(skillid); // by MouseJstr
-ATCOMMAND_FUNC(useskill); // by MouseJstr
-ATCOMMAND_FUNC(summon);
-ATCOMMAND_FUNC(rain);
-ATCOMMAND_FUNC(snow);
-ATCOMMAND_FUNC(sakura);
-ATCOMMAND_FUNC(fog);
-ATCOMMAND_FUNC(leaves);
-ATCOMMAND_FUNC(adjgmlvl); // by MouseJstr
-ATCOMMAND_FUNC(adjcmdlvl); // by MouseJstr
-ATCOMMAND_FUNC(trade); // by MouseJstr
-ATCOMMAND_FUNC(send); // by davidsiaw
-ATCOMMAND_FUNC(setbattleflag); // by MouseJstr
-ATCOMMAND_FUNC(unmute); // [Valaris]
-ATCOMMAND_FUNC(uptime); // by MC Cameri
-ATCOMMAND_FUNC(changesex); // by MC Cameri
-ATCOMMAND_FUNC(mute); // celest
-ATCOMMAND_FUNC(refresh); // by MC Cameri
-ATCOMMAND_FUNC(petid); // by MC Cameri
-ATCOMMAND_FUNC(identify); // by MC Cameri
-ATCOMMAND_FUNC(gmotd); // Added by MC Cameri, created by davidsiaw
-ATCOMMAND_FUNC(misceffect); // by MC Cameri
+#define MAX_MSG 1000
+char *msg_table[MAX_MSG]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others)
+
+#define ACMD_FUNC(x) int atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message)
+ACMD_FUNC(broadcast);
+ACMD_FUNC(localbroadcast);
+ACMD_FUNC(rura);
+ACMD_FUNC(where);
+ACMD_FUNC(jumpto);
+ACMD_FUNC(jump);
+ACMD_FUNC(who);
+ACMD_FUNC(who2);
+ACMD_FUNC(who3);
+ACMD_FUNC(whomap);
+ACMD_FUNC(whomap2);
+ACMD_FUNC(whomap3);
+ACMD_FUNC(whogm); // by Yor
+ACMD_FUNC(whozeny); // [Valaris]
+ACMD_FUNC(happyhappyjoyjoy); // [Valaris]
+ACMD_FUNC(save);
+ACMD_FUNC(load);
+ACMD_FUNC(speed);
+ACMD_FUNC(storage);
+ACMD_FUNC(guildstorage);
+ACMD_FUNC(option);
+ACMD_FUNC(hide);
+ACMD_FUNC(jobchange);
+ACMD_FUNC(die);
+ACMD_FUNC(kill);
+ACMD_FUNC(alive);
+ACMD_FUNC(kami);
+ACMD_FUNC(heal);
+ACMD_FUNC(item);
+ACMD_FUNC(item2);
+ACMD_FUNC(itemreset);
+ACMD_FUNC(itemcheck);
+ACMD_FUNC(baselevelup);
+ACMD_FUNC(joblevelup);
+ACMD_FUNC(help);
+ACMD_FUNC(gm);
+ACMD_FUNC(pvpoff);
+ACMD_FUNC(pvpon);
+ACMD_FUNC(gvgoff);
+ACMD_FUNC(gvgon);
+ACMD_FUNC(model);
+ACMD_FUNC(go);
+ACMD_FUNC(monster);
+ACMD_FUNC(monstersmall);
+ACMD_FUNC(monsterbig);
+ACMD_FUNC(spawn);
+ACMD_FUNC(killmonster);
+ACMD_FUNC(killmonster2);
+ACMD_FUNC(refine);
+ACMD_FUNC(produce);
+ACMD_FUNC(memo);
+ACMD_FUNC(gat);
+ACMD_FUNC(packet);
+ACMD_FUNC(statuspoint);
+ACMD_FUNC(skillpoint);
+ACMD_FUNC(zeny);
+ACMD_FUNC(param);
+ACMD_FUNC(guildlevelup);
+ACMD_FUNC(makeegg);
+ACMD_FUNC(hatch);
+ACMD_FUNC(petfriendly);
+ACMD_FUNC(pethungry);
+ACMD_FUNC(petrename);
+ACMD_FUNC(recall);
+ACMD_FUNC(recallall);
+ACMD_FUNC(revive);
+ACMD_FUNC(character_stats_all);
+ACMD_FUNC(character_save);
+ACMD_FUNC(night);
+ACMD_FUNC(day);
+ACMD_FUNC(doom);
+ACMD_FUNC(doommap);
+ACMD_FUNC(raise);
+ACMD_FUNC(raisemap);
+ACMD_FUNC(character_baselevel);
+ACMD_FUNC(character_joblevel);
+ACMD_FUNC(kick);
+ACMD_FUNC(kickall);
+ACMD_FUNC(allskill);
+ACMD_FUNC(questskill);
+ACMD_FUNC(charquestskill);
+ACMD_FUNC(lostskill);
+ACMD_FUNC(charlostskill);
+ACMD_FUNC(spiritball);
+ACMD_FUNC(party);
+ACMD_FUNC(guild);
+ACMD_FUNC(charskreset);
+ACMD_FUNC(charstreset);
+ACMD_FUNC(charreset);
+ACMD_FUNC(charstpoint);
+ACMD_FUNC(charmodel);
+ACMD_FUNC(charskpoint);
+ACMD_FUNC(agitstart);
+ACMD_FUNC(agitend);
+ACMD_FUNC(reloaditemdb);
+ACMD_FUNC(reloadmobdb);
+ACMD_FUNC(reloadskilldb);
+ACMD_FUNC(reloadscript);
+ACMD_FUNC(reloadgmdb); // by Yor
+ACMD_FUNC(reloadatcommand);
+ACMD_FUNC(reloadbattleconf);
+ACMD_FUNC(reloadstatusdb);
+ACMD_FUNC(reloadpcdb);
+ACMD_FUNC(mapexit);
+ACMD_FUNC(idsearch);
+ACMD_FUNC(mapinfo);
+ACMD_FUNC(dye); //** by fritz
+ACMD_FUNC(hair_style); //** by fritz
+ACMD_FUNC(hair_color); //** by fritz
+ACMD_FUNC(stat_all); //** by fritz
+ACMD_FUNC(char_change_sex); // by Yor
+ACMD_FUNC(char_block); // by Yor
+ACMD_FUNC(char_ban); // by Yor
+ACMD_FUNC(char_unblock); // by Yor
+ACMD_FUNC(char_unban); // by Yor
+ACMD_FUNC(mount_peco); // by Valaris
+ACMD_FUNC(char_mount_peco); // by Yor
+ACMD_FUNC(guildspy); // [Syrus22]
+ACMD_FUNC(partyspy); // [Syrus22]
+ACMD_FUNC(repairall); // [Valaris]
+ACMD_FUNC(guildrecall); // by Yor
+ACMD_FUNC(partyrecall); // by Yor
+ACMD_FUNC(nuke); // [Valaris]
+ACMD_FUNC(enablenpc);
+ACMD_FUNC(hidenpc);
+ACMD_FUNC(disablenpc);
+ACMD_FUNC(servertime); // by Yor
+ACMD_FUNC(chardelitem); // by Yor
+ACMD_FUNC(jail); // by Yor
+ACMD_FUNC(unjail); // by Yor
+ACMD_FUNC(disguise); // [Valaris]
+ACMD_FUNC(undisguise); // by Yor
+ACMD_FUNC(chardisguise); // Kalaspuff
+ACMD_FUNC(charundisguise); // Kalaspuff
+ACMD_FUNC(email); // by Yor
+ACMD_FUNC(effect);//by Apple
+ACMD_FUNC(character_cart_list); // by Yor
+ACMD_FUNC(addwarp); // by MouseJstr
+ACMD_FUNC(follow); // by MouseJstr
+ACMD_FUNC(skillon); // by MouseJstr
+ACMD_FUNC(skilloff); // by MouseJstr
+ACMD_FUNC(killer); // by MouseJstr
+ACMD_FUNC(npcmove); // by MouseJstr
+ACMD_FUNC(killable); // by MouseJstr
+ACMD_FUNC(charkillable); // by MouseJstr
+ACMD_FUNC(dropall); // by MouseJstr
+ACMD_FUNC(chardropall); // by MouseJstr
+ACMD_FUNC(storeall); // by MouseJstr
+ACMD_FUNC(charstoreall); // by MouseJstr
+ACMD_FUNC(skillid); // by MouseJstr
+ACMD_FUNC(useskill); // by MouseJstr
+ACMD_FUNC(summon);
+ACMD_FUNC(rain);
+ACMD_FUNC(snow);
+ACMD_FUNC(sakura);
+ACMD_FUNC(fog);
+ACMD_FUNC(leaves);
+ACMD_FUNC(adjgmlvl); // by MouseJstr
+ACMD_FUNC(adjcmdlvl); // by MouseJstr
+ACMD_FUNC(trade); // by MouseJstr
+ACMD_FUNC(send); // by davidsiaw
+ACMD_FUNC(setbattleflag); // by MouseJstr
+ACMD_FUNC(unmute); // [Valaris]
+ACMD_FUNC(clearweather); // Dexity
+ACMD_FUNC(uptime); // by MC Cameri
+ACMD_FUNC(changesex); // by MC Cameri
+ACMD_FUNC(mute); // celest
+ACMD_FUNC(refresh); // by MC Cameri
+ACMD_FUNC(petid); // by MC Cameri
+ACMD_FUNC(identify); // by MC Cameri
+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(users);
+ACMD_FUNC(autoloot); // by Upa-Kun
#ifndef TXT_ONLY
-ATCOMMAND_FUNC(checkmail); // [Valaris]
-ATCOMMAND_FUNC(listmail); // [Valaris]
-ATCOMMAND_FUNC(listnewmail); // [Valaris]
-ATCOMMAND_FUNC(readmail); // [Valaris]
-ATCOMMAND_FUNC(sendmail); // [Valaris]
-ATCOMMAND_FUNC(sendprioritymail); // [Valaris]
-ATCOMMAND_FUNC(deletemail); // [Valaris]
-ATCOMMAND_FUNC(sound); // [Valaris]
-ATCOMMAND_FUNC(refreshonline); // [Valaris]
+ACMD_FUNC(checkmail); // [Valaris]
+ACMD_FUNC(listmail); // [Valaris]
+ACMD_FUNC(listnewmail); // [Valaris]
+ACMD_FUNC(readmail); // [Valaris]
+ACMD_FUNC(sendmail); // [Valaris]
+ACMD_FUNC(sendprioritymail); // [Valaris]
+ACMD_FUNC(deletemail); // [Valaris]
+//ACMD_FUNC(sound); // [Valaris]
+ACMD_FUNC(refreshonline); // [Valaris]
#endif /* TXT_ONLY */
-ATCOMMAND_FUNC(skilltree); // by MouseJstr
+ACMD_FUNC(skilltree); // by MouseJstr
+
+ACMD_FUNC(marry); // by MouseJstr
+ACMD_FUNC(divorce); // by MouseJstr
+ACMD_FUNC(rings); // by MouseJstr
+
+ACMD_FUNC(grind); // by MouseJstr
+ACMD_FUNC(grind2); // by MouseJstr
+
+#ifdef DMALLOC
+ACMD_FUNC(dmstart); // by MouseJstr
+ACMD_FUNC(dmtick); // by MouseJstr
+#endif
+
+ACMD_FUNC(jumptoid); // by Dino9021
+ACMD_FUNC(jumptoid2); // by Dino9021
+ACMD_FUNC(recallid); // by Dino9021
+ACMD_FUNC(recallid2); // by Dino9021
+ACMD_FUNC(kickid); // by Dino9021
+ACMD_FUNC(kickid2); // by Dino9021
+ACMD_FUNC(reviveid); // by Dino9021
+ACMD_FUNC(reviveid2); // by Dino9021
+ACMD_FUNC(killid); // by Dino9021
+ACMD_FUNC(killid2); // by Dino9021
+ACMD_FUNC(charkillableid); // by Dino9021
+ACMD_FUNC(charkillableid2); // by Dino9021
+ACMD_FUNC(sound);
+ACMD_FUNC(undisguiseall);
+ACMD_FUNC(disguiseall);
+ACMD_FUNC(changelook);
+ACMD_FUNC(mobinfo); //by Lupus
+ACMD_FUNC(adopt); // by Veider
/*==========================================
*AtCommandInfo atcommand_info[]構造体の定義
@@ -240,8 +275,6 @@ ATCOMMAND_FUNC(skilltree); // by MouseJstr
// First char of commands is configured in atcommand_athena.conf. Leave @ in this list for default value.
// to set default level, read atcommand_athena.conf first please.
static AtCommandInfo atcommand_info[] = {
- { AtCommand_RuraP, "@rura+", 60, atcommand_rurap },
- { AtCommand_RuraP, "@charwarp", 60, atcommand_rurap },
{ AtCommand_Rura, "@rura", 40, atcommand_rura },
{ AtCommand_Warp, "@warp", 40, atcommand_rura },
{ AtCommand_Where, "@where", 1, atcommand_where },
@@ -359,16 +392,15 @@ static AtCommandInfo atcommand_info[] = {
{ AtCommand_ReloadItemDB, "@reloaditemdb", 99, atcommand_reloaditemdb }, // admin command
{ AtCommand_ReloadMobDB, "@reloadmobdb", 99, atcommand_reloadmobdb }, // admin command
{ AtCommand_ReloadSkillDB, "@reloadskilldb", 99, atcommand_reloadskilldb }, // admin command
-#ifndef TXT_ONLY
- { AtCommand_Rehash, "@rehash", 99, atcommand_rehash }, // admin command
-#else /* TXT_ONLY */
{ AtCommand_ReloadScript, "@reloadscript", 99, atcommand_reloadscript }, // admin command
-#endif /* TXT_ONLY */
{ AtCommand_ReloadGMDB, "@reloadgmdb", 99, atcommand_reloadgmdb }, // admin command
+ { AtCommand_ReloadAtcommand, "@reloadatcommand", 99, atcommand_reloadatcommand },
+ { AtCommand_ReloadBattleConf, "@reloadbattleconf",99, atcommand_reloadbattleconf },
+ { AtCommand_ReloadStatusDB, "@reloadstatusdb", 99, atcommand_reloadstatusdb },
+ { AtCommand_ReloadPcDB, "@reloadpcdb", 99, atcommand_reloadpcdb },
{ AtCommand_CharModel, "@charmodel", 50, atcommand_charmodel },
{ AtCommand_CharSKPoint, "@charskpoint", 60, atcommand_charskpoint },
{ AtCommand_CharSTPoint, "@charstpoint", 60, atcommand_charstpoint },
- { AtCommand_CharZeny, "@charzeny", 60, atcommand_charzeny },
{ AtCommand_MapInfo, "@mapinfo", 99, atcommand_mapinfo },
{ AtCommand_Dye, "@dye", 40, atcommand_dye }, // by fritz
{ AtCommand_Dye, "@ccolor", 40, atcommand_dye }, // by fritz
@@ -380,7 +412,7 @@ static AtCommandInfo atcommand_info[] = {
{ AtCommand_StatAll, "@statsall", 60, atcommand_stat_all },
{ AtCommand_StatAll, "@allstats", 60, atcommand_stat_all }, // by fritz
{ AtCommand_StatAll, "@allstat", 60, atcommand_stat_all }, // by fritz
- { AtCommand_CharChangeSex, "@charchangesex", 60, atcommand_char_change_sex }, // by Yor
+// { AtCommand_CharChangeSex, "@charchangesex", 60, atcommand_char_change_sex }, // by Yor
{ AtCommand_CharBlock, "@block", 60, atcommand_char_block }, // by Yor
{ AtCommand_CharBlock, "@charblock", 60, atcommand_char_block }, // by Yor
{ AtCommand_CharBan, "@ban", 60, atcommand_char_ban }, // by Yor
@@ -400,8 +432,9 @@ static AtCommandInfo atcommand_info[] = {
{ AtCommand_RepairAll, "@repairall", 60, atcommand_repairall }, // [Valaris]
{ AtCommand_GuildRecall, "@guildrecall", 60, atcommand_guildrecall }, // by Yor
{ AtCommand_PartyRecall, "@partyrecall", 60, atcommand_partyrecall }, // by Yor
-// { AtCommand_Nuke, "@nuke", 60, atcommand_nuke }, // [Valaris]
+ { AtCommand_Nuke, "@nuke", 60, atcommand_nuke }, // [Valaris]
{ AtCommand_Enablenpc, "@enablenpc", 80, atcommand_enablenpc }, // []
+ { AtCommand_Hidenpc, "@hidenpc", 80, atcommand_hidenpc }, // []
{ AtCommand_Disablenpc, "@disablenpc", 80, atcommand_disablenpc }, // []
{ AtCommand_ServerTime, "@time", 0, atcommand_servertime }, // by Yor
{ AtCommand_ServerTime, "@date", 0, atcommand_servertime }, // by Yor
@@ -419,8 +452,8 @@ static AtCommandInfo atcommand_info[] = {
{ AtCommand_CharUnDisguise, "@charundisguise", 60, atcommand_charundisguise }, // Kalaspuff
{ AtCommand_EMail, "@email", 0, atcommand_email }, // by Yor
{ AtCommand_Effect, "@effect", 40, atcommand_effect }, // by Apple
- { AtCommand_Char_Item_List, "@charitemlist", 40, atcommand_character_item_list }, // by Yor
- { AtCommand_Char_Storage_List, "@charstoragelist", 40, atcommand_character_storage_list }, // by Yor
+// { AtCommand_Char_Item_List, "@charitemlist", 40, atcommand_character_item_list }, // by Yor, now #itemlist
+// { AtCommand_Char_Storage_List, "@charstoragelist", 40, atcommand_character_storage_list }, // by Yor, now #storagelist
{ AtCommand_Char_Cart_List, "@charcartlist", 40, atcommand_character_cart_list }, // by Yor
{ AtCommand_Follow, "@follow", 10, atcommand_follow }, // by MouseJstr
{ AtCommand_AddWarp, "@addwarp", 20, atcommand_addwarp }, // by MouseJstr
@@ -430,12 +463,6 @@ static AtCommandInfo atcommand_info[] = {
{ AtCommand_NpcMove, "@npcmove", 20, atcommand_npcmove }, // by MouseJstr
{ AtCommand_Killable, "@killable", 40, atcommand_killable }, // by MouseJstr
{ AtCommand_CharKillable, "@charkillable", 40, atcommand_charkillable }, // by MouseJstr
- { AtCommand_Chareffect, "@chareffect", 40, atcommand_chareffect }, // MouseJstr
-/*
- { AtCommand_Chardye, "@chardye", 40, atcommand_chardye }, // MouseJstr
- { AtCommand_Charhairstyle, "@charhairstyle", 40, atcommand_charhairstyle }, // MouseJstr
- { AtCommand_Charhaircolor, "@charhaircolor", 40, atcommand_charhaircolor }, // MouseJstr
-*/
{ AtCommand_Dropall, "@dropall", 40, atcommand_dropall }, // MouseJstr
{ AtCommand_Chardropall, "@chardropall", 40, atcommand_chardropall }, // MouseJstr
{ AtCommand_Storeall, "@storeall", 40, atcommand_storeall }, // MouseJstr
@@ -459,8 +486,9 @@ static AtCommandInfo atcommand_info[] = {
{ AtCommand_Send, "@send", 60, atcommand_send },
{ AtCommand_SetBattleFlag, "@setbattleflag", 60, atcommand_setbattleflag },
{ AtCommand_UnMute, "@unmute", 60, atcommand_unmute }, // [Valaris]
+ { AtCommand_Clearweather, "@clearweather", 99, atcommand_clearweather }, // Dexity
{ AtCommand_UpTime, "@uptime", 0, atcommand_uptime }, // by MC Cameri
- { AtCommand_ChangeSex, "@changesex", 1, atcommand_changesex }, // by MC Cameri
+// { AtCommand_ChangeSex, "@changesex", 1, atcommand_changesex }, // by MC Cameri
{ AtCommand_Mute, "@mute", 99, atcommand_mute }, // [celest]
{ AtCommand_Mute, "@red", 99, atcommand_mute }, // [celest]
{ AtCommand_WhoZeny, "@whozeny", 20, atcommand_whozeny }, // [Valaris]
@@ -470,6 +498,12 @@ static AtCommandInfo atcommand_info[] = {
{ AtCommand_Identify, "@identify", 40, atcommand_identify }, // by MC Cameri
{ AtCommand_Gmotd, "@gmotd", 0, atcommand_gmotd }, // Added by MC Cameri, created by davidsiaw
{ 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 },
+ { AtCommand_Users, "@users", 0, atcommand_users },
+ { AtCommand_ResetState, "/reset", 40, NULL },
#ifndef TXT_ONLY // sql-only commands
{ AtCommand_CheckMail, "@checkmail", 1, atcommand_listmail }, // [Valaris]
@@ -483,17 +517,60 @@ static AtCommandInfo atcommand_info[] = {
#endif /* TXT_ONLY */
{ AtCommand_SkillTree, "@skilltree", 40, atcommand_skilltree }, // [MouseJstr]
+ { AtCommand_Marry, "@marry", 40, atcommand_marry }, // [MouseJstr]
+ { AtCommand_Divorce, "@divorce", 40, atcommand_divorce }, // [MouseJstr]
+ { AtCommand_Rings, "@rings", 40, atcommand_rings }, // [MouseJstr]
+ { AtCommand_Grind, "@grind", 99, atcommand_grind }, // [MouseJstr]
+ { AtCommand_Grind2, "@grind2", 99, atcommand_grind2 }, // [MouseJstr]
+
+#ifdef DMALLOC
+ { AtCommand_DMStart, "@dmstart", 99, atcommand_dmstart }, // [MouseJstr]
+ { AtCommand_DMTick, "@dmtick", 99, atcommand_dmtick }, // [MouseJstr]
+#endif
+ { AtCommand_JumpToId, "@jumptoid", 20, atcommand_jumptoid }, // [Dino9021]
+ { AtCommand_JumpToId, "@warptoid", 20, atcommand_jumptoid }, // [Dino9021]
+ { AtCommand_JumpToId, "@gotoid", 20, atcommand_jumptoid }, // [Dino9021]
+ { AtCommand_JumpToId2, "@jumptoid2", 20, atcommand_jumptoid2 }, // [Dino9021]
+ { AtCommand_JumpToId2, "@warptoid2", 20, atcommand_jumptoid2 }, // [Dino9021]
+ { AtCommand_JumpToId2, "@gotoid2", 20, atcommand_jumptoid2 }, // [Dino9021]
+ { AtCommand_RecallId, "@recallid", 60, atcommand_recallid }, // [Dino9021]
+ { AtCommand_RecallId2, "@recallid2", 60, atcommand_recallid2 }, // [Dino9021]
+ { AtCommand_KickId, "@kickid", 99, atcommand_kickid }, // [Dino9021]
+ { AtCommand_KickId2, "@kickid2", 99, atcommand_kickid2 }, // [Dino9021]
+ { AtCommand_ReviveId, "@reviveid", 60, atcommand_reviveid }, // [Dino9021]
+ { AtCommand_ReviveId2, "@reviveid2", 60, atcommand_reviveid2 }, // [Dino9021]
+ { AtCommand_KillId, "@killid", 60, atcommand_killid }, // [Dino9021]
+ { AtCommand_KillId2, "@killid2", 60, atcommand_killid2 }, // [Dino9021]
+ { AtCommand_CharKillableId, "@charkillableid", 40, atcommand_charkillableid }, // [Dino9021]
+ { AtCommand_CharKillableId2, "@charkillableid2", 40, atcommand_charkillableid2 }, // [Dino9021]
+ { AtCommand_Sound, "@sound", 40, atcommand_sound },
+ { AtCommand_UndisguiseAll, "@undisguiseall", 99, atcommand_undisguiseall },
+ { AtCommand_DisguiseAll, "@disguiseall", 99, atcommand_disguiseall },
+ { AtCommand_ChangeLook, "@changelook", 99, atcommand_changelook },
+ { AtCommand_AutoLoot, "@autoloot", 10, atcommand_autoloot }, // Upa-Kun
+ { AtCommand_MobInfo, "@mobinfo", 1, atcommand_mobinfo }, // [Lupus]
+ { AtCommand_MobInfo, "@monsterinfo", 1, atcommand_mobinfo }, // [Lupus]
+ { AtCommand_MobInfo, "@mi", 1, atcommand_mobinfo }, // [Lupus]
+ { AtCommand_Adopt, "@adopt", 40, atcommand_adopt }, // [Veider]
+
// add new commands before this line
{ AtCommand_Unknown, NULL, 1, NULL }
};
+/*=========================================
+ * Generic variables
+ *-----------------------------------------
+ */
+char atcmd_output[200];
+char atcmd_player_name[100];
+
/*====================================================
* This function return the name of the job (by [Yor])
*----------------------------------------------------
*/
-char * job_name(int class) {
- switch (class) {
+char * job_name(int class_) {
+ switch (class_) {
case 0: return "Novice";
case 1: return "Swordsman";
case 2: return "Mage";
@@ -597,7 +674,7 @@ int lowtohigh_compare (const void * a, const void * b)
// Return the message string of the specified number by [Yor]
//-----------------------------------------------------------
char * msg_txt(int msg_number) {
- if (msg_number >= 0 && msg_number < (int)(sizeof(msg_table) / sizeof(msg_table[0])) &&
+ if (msg_number >= 0 && msg_number < MAX_MSG &&
msg_table[msg_number] != NULL && msg_table[msg_number][0] != '\0')
return msg_table[msg_number];
@@ -607,9 +684,9 @@ char * msg_txt(int msg_number) {
//------------------------------------------------------------
// E-mail check: return 0 (not correct) or 1 (valid). by [Yor]
//------------------------------------------------------------
-int e_mail_check(unsigned char *email) {
+int e_mail_check(char *email) {
char ch;
- unsigned char* last_arobas;
+ char* last_arobas;
// athena limits
if (strlen(email) < 3 || strlen(email) > 39)
@@ -670,6 +747,11 @@ is_atcommand(const int fd, struct map_session_data* sd, const char* message, int
nullpo_retr(AtCommand_None, sd);
+ if (!battle_config.allow_atcommand_when_mute &&
+ sd->sc_count && sd->sc_data[SC_NOCHAT].timer != -1) {
+ return AtCommand_Unknown;
+ }
+
if (!message || !*message)
return AtCommand_None;
@@ -683,13 +765,12 @@ is_atcommand(const int fd, struct map_session_data* sd, const char* message, int
if (!*str)
return AtCommand_None;
- type = atcommand(gmlvl > 0 ? gmlvl : pc_isGM(sd), str, &info);
+ type = atcommand(sd, gmlvl > 0 ? gmlvl : pc_isGM(sd), str, &info);
if (type != AtCommand_None) {
char command[100];
- char output[200];
const char* p = str;
memset(command, '\0', sizeof(command));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
while (*p && !isspace(*p))
p++;
if (p - str >= sizeof(command)) // too long
@@ -699,20 +780,16 @@ is_atcommand(const int fd, struct map_session_data* sd, const char* message, int
p++;
if (type == AtCommand_Unknown || info.proc == NULL) {
- sprintf(output, msg_table[153], command); // %s is Unknown Command.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[153], command); // %s is Unknown Command.
+ clif_displaymessage(fd, atcmd_output);
} else {
if (info.proc(fd, sd, command, p) != 0) {
// Command can not be executed
- sprintf(output, msg_table[154], command); // %s failed.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[154], command); // %s failed.
+ clif_displaymessage(fd, atcmd_output);
}
}
- // ToDo: Fix Logs :)
- //if((log_config.gm) && (info.level >= log_config.gm))
- // log_atcommand(sd, message);
-
return info.type;
}
@@ -723,7 +800,7 @@ is_atcommand(const int fd, struct map_session_data* sd, const char* message, int
*
*------------------------------------------
*/
-AtCommandType atcommand(const int level, const char* message, struct AtCommandInfo* info) {
+AtCommandType atcommand(struct map_session_data* sd, const int level, const char* message, struct AtCommandInfo* info) {
char* p = (char *)message; // it's 'char' and not 'const char' to have possibility to modify the first character if necessary
if (!info)
@@ -756,6 +833,8 @@ AtCommandType atcommand(const int level, const char* message, struct AtCommandIn
return AtCommand_None;
else
return AtCommand_Unknown;
+ } else if((log_config.gm) && (atcommand_info[i].level >= log_config.gm)) {
+ log_atcommand(sd, message);
}
memcpy(info, &atcommand_info[i], sizeof atcommand_info[i]);
} else {
@@ -770,49 +849,73 @@ AtCommandType atcommand(const int level, const char* message, struct AtCommandIn
*------------------------------------------
*/
static int atkillmonster_sub(struct block_list *bl, va_list ap) {
- int flag = va_arg(ap, int);
-
- nullpo_retr(0, bl);
+ struct mob_data *md;
+ int flag;
+
+ nullpo_retr(0, ap);
+ nullpo_retr(0, md=(struct mob_data *)bl);
+ flag = va_arg(ap, int);
if (flag)
- mob_damage(NULL, (struct mob_data *)bl, ((struct mob_data *)bl)->hp, 2);
+ mob_damage(NULL, md, md->hp, 2);
else
- mob_delete((struct mob_data *)bl);
-
+ mob_delete(md);
+
return 0;
}
-
-#ifndef TXT_ONLY
-static int atkillnpc_sub(struct block_list *bl, va_list ap)
+/*==========================================
+ * Mob search
+ *------------------------------------------
+ */
+static int atmobsearch_sub(struct block_list *bl,va_list ap)
{
- int flag = va_arg(ap,int);
+ int mob_id,fd;
+ static int number=0;
+ struct mob_data *md;
- nullpo_retr(0, bl);
+ nullpo_retr(0, bl);
- npc_delete((struct npc_data *)bl);
+ if(!ap){
+ number=0;
+ return 0;
+ }
+ mob_id = va_arg(ap,int);
+ fd = va_arg(ap,int);
- flag = 0;
+ md = (struct mob_data *)bl;
- return 0;
+ if(md && fd && (mob_id==-1 || (md->class_==mob_id))){
+ snprintf(atcmd_output, sizeof atcmd_output, "%2d[%3d:%3d] %s",
+ ++number,bl->x, bl->y,md->name);
+ clif_displaymessage(fd, atcmd_output);
+ }
+ return 0;
}
-
-void rehash( const int fd, struct map_session_data* sd )
+/*==========================================
+ * cleanmap
+ *------------------------------------------
+ */
+static int atcommand_cleanmap_sub(struct block_list *bl,va_list ap)
{
- int map_id = 0;
+ struct flooritem_data *fitem;
- int LOADED_MAPS = map_num;
-
- for (map_id = 0; map_id < LOADED_MAPS;map_id++) {
+ nullpo_retr(0, bl);
- if (map_id > LOADED_MAPS)
- break;
+ fitem = (struct flooritem_data *)bl;
+ if(fitem==NULL || fitem->bl.type!=BL_ITEM){
+ if(battle_config.error_log)
+ printf("map_clearflooritem_timer : error\n");
+ return 1;
+ }
+ delete_timer(fitem->cleartimer,map_clearflooritem_timer);
+ if(fitem->item_data.card[0] == (short)0xff00)
+ intif_delete_petdata(*((long *)(&fitem->item_data.card[1])));
+ clif_clearflooritem(fitem,0);
+ map_delobject(fitem->bl.id);
- map_foreachinarea(atkillmonster_sub, map_id, 0, 0, map[map_id].xs, map[map_id].ys, BL_MOB, 0);
- map_foreachinarea(atkillnpc_sub, map_id, 0, 0, map[map_id].xs, map[map_id].ys, BL_NPC, 0);
- }
+ return 0;
}
-#endif /* not TXT_ONLY */
/*==========================================
* Read Message Data
*------------------------------------------
@@ -821,12 +924,15 @@ int msg_config_read(const char *cfgName) {
int msg_number;
char line[1024], w1[1024], w2[1024];
FILE *fp;
+ static int called = 1;
if ((fp = fopen(cfgName, "r")) == NULL) {
printf("Messages file not found: %s\n", cfgName);
return 1;
}
+ if ((--called) == 0)
+ memset(&msg_table[0], 0, sizeof(msg_table[0]) * MAX_MSG);
while(fgets(line, sizeof(line)-1, fp)) {
if (line[0] == '/' && line[1] == '/')
continue;
@@ -835,9 +941,13 @@ int msg_config_read(const char *cfgName) {
msg_config_read(w2);
} else {
msg_number = atoi(w1);
- if (msg_number >= 0 && msg_number < (int)(sizeof(msg_table) / sizeof(msg_table[0])))
- strcpy(msg_table[msg_number], w2);
+ if (msg_number >= 0 && msg_number < MAX_MSG) {
+ if (msg_table[msg_number] != NULL)
+ aFree(msg_table[msg_number]);
+ msg_table[msg_number] = (char *)aCalloc(strlen(w2) + 1, sizeof (char));
+ strcpy(msg_table[msg_number],w2);
// printf("message #%d: '%s'.\n", msg_number, msg_table[msg_number]);
+ }
}
}
}
@@ -847,6 +957,17 @@ int msg_config_read(const char *cfgName) {
}
/*==========================================
+ * Cleanup Message Data
+ *------------------------------------------
+ */
+void do_final_msg () {
+ int i;
+ for (i = 0; i < MAX_MSG; i++)
+ aFree(msg_table[i]);
+ return;
+}
+
+/*==========================================
*
*------------------------------------------
*/
@@ -932,73 +1053,7 @@ int atcommand_send(
case 4:
WBUFW(buf,0)=0x190;
}
-
-
- }
- return 0;
-}
-
-/*==========================================
- * @rura+
- *------------------------------------------
- */
-int atcommand_rurap(
- const int fd, struct map_session_data* sd,
- const char* command, const char* message)
-{
- char map_name[100];
- char character[100];
- int x = 0, y = 0;
- struct map_session_data *pl_sd;
- int m;
-
- memset(map_name, '\0', sizeof(map_name));
- memset(character, '\0', sizeof(character));
-
- if (!message || !*message || sscanf(message, "%99s %d %d %99[^\n]", map_name, &x, &y, character) < 4) {
- clif_displaymessage(fd, "Usage: @charwarp/@rura+ <mapname> <x> <y> <char name>");
- return -1;
- }
-
- if (x <= 0)
- x = rand() % 399 + 1;
- if (y <= 0)
- y = rand() % 399 + 1;
- if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat)
- strcat(map_name, ".gat");
-
- if ((pl_sd = map_nick2sd(character)) != NULL) {
- if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can rura+ only lower or same GM level
- if (x > 0 && x < 400 && y > 0 && y < 400) {
- m = map_mapname2mapid(map_name);
- if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp someone to this map.");
- return -1;
- }
- if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp this player from its actual map.");
- return -1;
- }
- if (pc_setpos(pl_sd, map_name, x, y, 3) == 0) {
- clif_displaymessage(pl_sd->fd, msg_table[0]); // Warped.
- clif_displaymessage(fd, msg_table[15]); // Player warped (message sends to player too).
- } else {
- clif_displaymessage(fd, msg_table[1]); // Map not found.
- return -1;
- }
- } else {
- clif_displaymessage(fd, msg_table[2]); // Coordinates out of range.
- return -1;
- }
- } else {
- clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
- return -1;
- }
- } else {
- clif_displaymessage(fd, msg_table[3]); // Character not found.
- return -1;
}
-
return 0;
}
@@ -1015,6 +1070,8 @@ int atcommand_rura(
int x = 0, y = 0;
int m;
+ nullpo_retr(-1, sd);
+
memset(map_name, '\0', sizeof(map_name));
if (!message || !*message || sscanf(message, "%99s %d %d", map_name, &x, &y) < 1) {
@@ -1033,11 +1090,11 @@ int atcommand_rura(
if (x > 0 && x < 400 && y > 0 && y < 400) {
m = map_mapname2mapid(map_name);
if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp you to this map.");
+ clif_displaymessage(fd, msg_table[247]);
return -1;
}
if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp you from your actual map.");
+ clif_displaymessage(fd, msg_table[248]);
return -1;
}
if (pc_setpos(sd, map_name, x, y, 3) == 0)
@@ -1062,30 +1119,28 @@ int atcommand_where(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
- char output[200];
struct map_session_data *pl_sd = NULL;
nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
- memset(character, '\0', sizeof character);
- if (sscanf(message, "%99[^\n]", character) < 1)
+ memset(atcmd_player_name, '\0', sizeof atcmd_player_name);
+ if (sscanf(message, "%99[^\n]", atcmd_player_name) < 1)
return -1;
- if(strncmp(sd->status.name,character,24)==0)
+ if(strncmp(sd->status.name,atcmd_player_name,24)==0)
return -1;
- if ((pl_sd = map_nick2sd(character)) == NULL) {
- snprintf(output, sizeof output, "%s %d %d",
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) == NULL) {
+ snprintf(atcmd_output, sizeof atcmd_output, "%s %d %d",
sd->mapname, sd->bl.x, sd->bl.y);
- clif_displaymessage(fd, output);
+ clif_displaymessage(fd, atcmd_output);
return -1;
}
- snprintf(output, sizeof output, "%s %s %d %d",
- character, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
- clif_displaymessage(fd, output);
-
+ snprintf(atcmd_output, sizeof atcmd_output, "%s %s %d %d",
+ atcmd_player_name, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
+ clif_displaymessage(fd, atcmd_output);
+
return 0;
}
@@ -1097,35 +1152,33 @@ int atcommand_jumpto(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
- char output[200];
struct map_session_data *pl_sd = NULL;
nullpo_retr(-1, sd);
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @jumpto/@warpto/@goto <char name>).");
return -1;
}
-
- memset(character, '\0', sizeof character);
- if (sscanf(message, "%99[^\n]", character) < 1)
+
+ memset(atcmd_player_name, '\0', sizeof atcmd_player_name);
+ if (sscanf(message, "%99[^\n]", atcmd_player_name) < 1)
return -1;
- if(strncmp(sd->status.name,character,24)==0) //Yourself mate? Tsk tsk tsk.
+ if(strncmp(sd->status.name,atcmd_player_name,24)==0) //Yourself mate? Tsk tsk tsk.
return -1;
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp you to the map of this player.");
+ clif_displaymessage(fd, msg_table[247]);
return -1;
}
if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp you from your actual map.");
+ clif_displaymessage(fd, msg_table[248]);
return -1;
}
pc_setpos(sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y, 3);
- sprintf(output, msg_table[4], character); // Jump to %s
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[4], atcmd_player_name); // Jump to %s
+ clif_displaymessage(fd, atcmd_output);
} else {
clif_displaymessage(fd, msg_table[3]); // Character not found.
return -1;
@@ -1142,10 +1195,11 @@ int atcommand_jump(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char output[200];
int x = 0, y = 0;
- memset(output, '\0', sizeof(output));
+ nullpo_retr(-1, sd);
+
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
sscanf(message, "%d %d", &x, &y);
@@ -1154,17 +1208,13 @@ int atcommand_jump(
if (y <= 0)
y = rand() % 399 + 1;
if (x > 0 && x < 400 && y > 0 && y < 400) {
- if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp you to your actual map.");
- return -1;
- }
- if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp you from your actual map.");
+ if (sd->bl.m >= 0 && (map[sd->bl.m].flag.nowarp || map[sd->bl.m].flag.nowarpto) && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
+ clif_displaymessage(fd, msg_table[248]);
return -1;
}
pc_setpos(sd, sd->mapname, x, y, 3);
- sprintf(output, msg_table[5], x, y); // Jump to %d %d
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[5], x, y); // Jump to %d %d
+ clif_displaymessage(fd, atcmd_output);
} else {
clif_displaymessage(fd, msg_table[2]); // Coordinates out of range.
return -1;
@@ -1181,14 +1231,15 @@ int atcommand_who(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char output[200];
struct map_session_data *pl_sd;
int i, j, count;
int pl_GM_level, GM_level;
char match_text[100];
char player_name[24];
- memset(output, '\0', sizeof(output));
+ nullpo_retr(-1, sd);
+
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(match_text, '\0', sizeof(match_text));
memset(player_name, '\0', sizeof(player_name));
@@ -1200,7 +1251,7 @@ int atcommand_who(
count = 0;
GM_level = pc_isGM(sd);
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
pl_GM_level = pc_isGM(pl_sd);
if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
memcpy(player_name, pl_sd->status.name, 24);
@@ -1208,10 +1259,10 @@ int atcommand_who(
player_name[j] = tolower(player_name[j]);
if (strstr(player_name, match_text) != NULL) { // search with no case sensitive
if (pl_GM_level > 0)
- sprintf(output, "Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.name, pl_GM_level, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
+ sprintf(atcmd_output, "(CID:%d/AID:%d) Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.char_id, pl_sd->status.account_id, pl_sd->status.name, pl_GM_level, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
else
- sprintf(output, "Name: %s | Location: %s %d %d", pl_sd->status.name, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "(CID:%d/AID:%d) Name: %s | Location: %s %d %d", pl_sd->status.char_id, pl_sd->status.account_id, pl_sd->status.name, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
+ clif_displaymessage(fd, atcmd_output);
count++;
}
}
@@ -1223,8 +1274,8 @@ int atcommand_who(
else if (count == 1)
clif_displaymessage(fd, msg_table[29]); // 1 player found.
else {
- sprintf(output, msg_table[30], count); // %d players found.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[30], count); // %d players found.
+ clif_displaymessage(fd, atcmd_output);
}
return 0;
@@ -1238,14 +1289,15 @@ int atcommand_who2(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char output[200];
struct map_session_data *pl_sd;
int i, j, count;
int pl_GM_level, GM_level;
char match_text[100];
char player_name[24];
- memset(output, '\0', sizeof(output));
+ nullpo_retr(-1, sd);
+
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(match_text, '\0', sizeof(match_text));
memset(player_name, '\0', sizeof(player_name));
@@ -1257,7 +1309,7 @@ int atcommand_who2(
count = 0;
GM_level = pc_isGM(sd);
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
pl_GM_level = pc_isGM(pl_sd);
if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
memcpy(player_name, pl_sd->status.name, 24);
@@ -1265,10 +1317,10 @@ int atcommand_who2(
player_name[j] = tolower(player_name[j]);
if (strstr(player_name, match_text) != NULL) { // search with no case sensitive
if (pl_GM_level > 0)
- sprintf(output, "Name: %s (GM:%d) | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_GM_level, pl_sd->status.base_level, job_name(pl_sd->status.class), pl_sd->status.job_level);
+ sprintf(atcmd_output, "Name: %s (GM:%d) | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_GM_level, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level);
else
- sprintf(output, "Name: %s | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_sd->status.base_level, job_name(pl_sd->status.class), pl_sd->status.job_level);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Name: %s | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level);
+ clif_displaymessage(fd, atcmd_output);
count++;
}
}
@@ -1280,8 +1332,8 @@ int atcommand_who2(
else if (count == 1)
clif_displaymessage(fd, msg_table[29]); // 1 player found.
else {
- sprintf(output, msg_table[30], count); // %d players found.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[30], count); // %d players found.
+ clif_displaymessage(fd, atcmd_output);
}
return 0;
@@ -1297,7 +1349,6 @@ int atcommand_who3(
{
char temp0[100];
char temp1[100];
- char output[200];
struct map_session_data *pl_sd;
int i, j, count;
int pl_GM_level, GM_level;
@@ -1306,9 +1357,11 @@ int atcommand_who3(
struct guild *g;
struct party *p;
+ nullpo_retr(-1, sd);
+
memset(temp0, '\0', sizeof(temp0));
memset(temp1, '\0', sizeof(temp1));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(match_text, '\0', sizeof(match_text));
memset(player_name, '\0', sizeof(player_name));
@@ -1320,7 +1373,7 @@ int atcommand_who3(
count = 0;
GM_level = pc_isGM(sd);
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
pl_GM_level = pc_isGM(pl_sd);
if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
memcpy(player_name, pl_sd->status.name, 24);
@@ -1338,10 +1391,10 @@ int atcommand_who3(
else
sprintf(temp0, "%s", p->name);
if (pl_GM_level > 0)
- sprintf(output, "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'", pl_sd->status.name, pl_GM_level, temp0, temp1);
+ sprintf(atcmd_output, "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'", pl_sd->status.name, pl_GM_level, temp0, temp1);
else
- sprintf(output, "Name: %s | Party: '%s' | Guild: '%s'", pl_sd->status.name, temp0, temp1);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Name: %s | Party: '%s' | Guild: '%s'", pl_sd->status.name, temp0, temp1);
+ clif_displaymessage(fd, atcmd_output);
count++;
}
}
@@ -1353,8 +1406,8 @@ int atcommand_who3(
else if (count == 1)
clif_displaymessage(fd, msg_table[29]); // 1 player found.
else {
- sprintf(output, msg_table[30], count); // %d players found.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[30], count); // %d players found.
+ clif_displaymessage(fd, atcmd_output);
}
return 0;
@@ -1368,14 +1421,13 @@ int atcommand_whomap(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char output[200];
struct map_session_data *pl_sd;
int i, count;
int pl_GM_level, GM_level;
int map_id;
char map_name[100];
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(map_name, '\0', sizeof(map_name));
if (!message || !*message)
@@ -1391,15 +1443,15 @@ int atcommand_whomap(
count = 0;
GM_level = pc_isGM(sd);
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
pl_GM_level = pc_isGM(pl_sd);
if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
if (pl_sd->bl.m == map_id) {
if (pl_GM_level > 0)
- sprintf(output, "Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.name, pl_GM_level, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
+ sprintf(atcmd_output, "Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.name, pl_GM_level, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
else
- sprintf(output, "Name: %s | Location: %s %d %d", pl_sd->status.name, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Name: %s | Location: %s %d %d", pl_sd->status.name, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
+ clif_displaymessage(fd, atcmd_output);
count++;
}
}
@@ -1407,13 +1459,13 @@ int atcommand_whomap(
}
if (count == 0)
- sprintf(output, msg_table[54], map[map_id].name); // No player found in map '%s'.
+ sprintf(atcmd_output, msg_table[54], map[map_id].name); // No player found in map '%s'.
else if (count == 1)
- sprintf(output, msg_table[55], map[map_id].name); // 1 player found in map '%s'.
+ sprintf(atcmd_output, msg_table[55], map[map_id].name); // 1 player found in map '%s'.
else {
- sprintf(output, msg_table[56], count, map[map_id].name); // %d players found in map '%s'.
+ sprintf(atcmd_output, msg_table[56], count, map[map_id].name); // %d players found in map '%s'.
}
- clif_displaymessage(fd, output);
+ clif_displaymessage(fd, atcmd_output);
return 0;
}
@@ -1426,14 +1478,15 @@ int atcommand_whomap2(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char output[200];
struct map_session_data *pl_sd;
int i, count;
int pl_GM_level, GM_level;
int map_id = 0;
char map_name[100];
- memset(output, '\0', sizeof(output));
+ nullpo_retr(-1, sd);
+
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(map_name, '\0', sizeof(map_name));
if (!message || !*message)
@@ -1449,15 +1502,15 @@ int atcommand_whomap2(
count = 0;
GM_level = pc_isGM(sd);
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
pl_GM_level = pc_isGM(pl_sd);
if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
if (pl_sd->bl.m == map_id) {
if (pl_GM_level > 0)
- sprintf(output, "Name: %s (GM:%d) | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_GM_level, pl_sd->status.base_level, job_name(pl_sd->status.class), pl_sd->status.job_level);
+ sprintf(atcmd_output, "Name: %s (GM:%d) | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_GM_level, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level);
else
- sprintf(output, "Name: %s | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_sd->status.base_level, job_name(pl_sd->status.class), pl_sd->status.job_level);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Name: %s | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level);
+ clif_displaymessage(fd, atcmd_output);
count++;
}
}
@@ -1465,13 +1518,13 @@ int atcommand_whomap2(
}
if (count == 0)
- sprintf(output, msg_table[54], map[map_id].name); // No player found in map '%s'.
+ sprintf(atcmd_output, msg_table[54], map[map_id].name); // No player found in map '%s'.
else if (count == 1)
- sprintf(output, msg_table[55], map[map_id].name); // 1 player found in map '%s'.
+ sprintf(atcmd_output, msg_table[55], map[map_id].name); // 1 player found in map '%s'.
else {
- sprintf(output, msg_table[56], count, map[map_id].name); // %d players found in map '%s'.
+ sprintf(atcmd_output, msg_table[56], count, map[map_id].name); // %d players found in map '%s'.
}
- clif_displaymessage(fd, output);
+ clif_displaymessage(fd, atcmd_output);
return 0;
}
@@ -1486,7 +1539,6 @@ int atcommand_whomap3(
{
char temp0[100];
char temp1[100];
- char output[200];
struct map_session_data *pl_sd;
int i, count;
int pl_GM_level, GM_level;
@@ -1495,9 +1547,11 @@ int atcommand_whomap3(
struct guild *g;
struct party *p;
+ nullpo_retr(-1, sd);
+
memset(temp0, '\0', sizeof(temp0));
memset(temp1, '\0', sizeof(temp1));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(map_name, '\0', sizeof(map_name));
if (!message || !*message)
@@ -1513,7 +1567,7 @@ int atcommand_whomap3(
count = 0;
GM_level = pc_isGM(sd);
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
pl_GM_level = pc_isGM(pl_sd);
if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
if (pl_sd->bl.m == map_id) {
@@ -1528,10 +1582,10 @@ int atcommand_whomap3(
else
sprintf(temp0, "%s", p->name);
if (pl_GM_level > 0)
- sprintf(output, "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'", pl_sd->status.name, pl_GM_level, temp0, temp1);
+ sprintf(atcmd_output, "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'", pl_sd->status.name, pl_GM_level, temp0, temp1);
else
- sprintf(output, "Name: %s | Party: '%s' | Guild: '%s'", pl_sd->status.name, temp0, temp1);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Name: %s | Party: '%s' | Guild: '%s'", pl_sd->status.name, temp0, temp1);
+ clif_displaymessage(fd, atcmd_output);
count++;
}
}
@@ -1539,13 +1593,13 @@ int atcommand_whomap3(
}
if (count == 0)
- sprintf(output, msg_table[54], map[map_id].name); // No player found in map '%s'.
+ sprintf(atcmd_output, msg_table[54], map[map_id].name); // No player found in map '%s'.
else if (count == 1)
- sprintf(output, msg_table[55], map[map_id].name); // 1 player found in map '%s'.
+ sprintf(atcmd_output, msg_table[55], map[map_id].name); // 1 player found in map '%s'.
else {
- sprintf(output, msg_table[56], count, map[map_id].name); // %d players found in map '%s'.
+ sprintf(atcmd_output, msg_table[56], count, map[map_id].name); // %d players found in map '%s'.
}
- clif_displaymessage(fd, output);
+ clif_displaymessage(fd, atcmd_output);
return 0;
}
@@ -1560,7 +1614,6 @@ int atcommand_whogm(
{
char temp0[100];
char temp1[100];
- char output[200];
struct map_session_data *pl_sd;
int i, j, count;
int pl_GM_level, GM_level;
@@ -1569,9 +1622,11 @@ int atcommand_whogm(
struct guild *g;
struct party *p;
+ nullpo_retr(-1, sd);
+
memset(temp0, '\0', sizeof(temp0));
memset(temp1, '\0', sizeof(temp1));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(match_text, '\0', sizeof(match_text));
memset(player_name, '\0', sizeof(player_name));
@@ -1583,7 +1638,7 @@ int atcommand_whogm(
count = 0;
GM_level = pc_isGM(sd);
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
pl_GM_level = pc_isGM(pl_sd);
if (pl_GM_level > 0) {
if (!((battle_config.hide_GM_session || (pl_sd->status.option & OPTION_HIDE)) && (pl_GM_level > GM_level))) { // you can look only lower or same level
@@ -1591,10 +1646,10 @@ int atcommand_whogm(
for (j = 0; player_name[j]; j++)
player_name[j] = tolower(player_name[j]);
if (strstr(player_name, match_text) != NULL) { // search with no case sensitive
- sprintf(output, "Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.name, pl_GM_level, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
- clif_displaymessage(fd, output);
- sprintf(output, " BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.base_level, job_name(pl_sd->status.class), pl_sd->status.job_level);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.name, pl_GM_level, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, " BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level);
+ clif_displaymessage(fd, atcmd_output);
g = guild_search(pl_sd->status.guild_id);
if (g == NULL)
sprintf(temp1, "None");
@@ -1605,8 +1660,8 @@ int atcommand_whogm(
sprintf(temp0, "None");
else
sprintf(temp0, "%s", p->name);
- sprintf(output, " Party: '%s' | Guild: '%s'", temp0, temp1);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, " Party: '%s' | Guild: '%s'", temp0, temp1);
+ clif_displaymessage(fd, atcmd_output);
count++;
}
}
@@ -1619,8 +1674,8 @@ int atcommand_whogm(
else if (count == 1)
clif_displaymessage(fd, msg_table[151]); // 1 GM found.
else {
- sprintf(output, msg_table[152], count); // %d GMs found.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[152], count); // %d GMs found.
+ clif_displaymessage(fd, atcmd_output);
}
return 0;
@@ -1630,15 +1685,18 @@ int atcommand_whozeny(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char output[200];
struct map_session_data *pl_sd;
int i, j, count,c;
char match_text[100];
char player_name[24];
- int zeny[clif_countusers()];
- int counted[clif_countusers()];
+ //int zeny[clif_countusers()];
+ //int counted[clif_countusers()];
+ int *zeny = (int *)aCallocA(clif_countusers(), sizeof(int));
+ int *counted = (int *)aCallocA(clif_countusers(), sizeof(int));
+
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(match_text, '\0', sizeof(match_text));
memset(player_name, '\0', sizeof(player_name));
@@ -1649,7 +1707,7 @@ int atcommand_whozeny(
count = 0;
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
memcpy(player_name, pl_sd->status.name, 24);
for (j = 0; player_name[j]; j++)
player_name[j] = tolower(player_name[j]);
@@ -1668,10 +1726,10 @@ int atcommand_whozeny(
for (i = 0; i < fd_max; i++) {
if(!zeny[c])
continue;
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && zeny[c] && counted[i]==0) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && zeny[c] && counted[i]==0) {
if(pl_sd->status.zeny==zeny[c]) {
- sprintf(output, "Name: %s | Zeny: %d", pl_sd->status.name, pl_sd->status.zeny);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Name: %s | Zeny: %d", pl_sd->status.name, pl_sd->status.zeny);
+ clif_displaymessage(fd, atcmd_output);
zeny[c]=0;
counted[i]=1;
}
@@ -1684,10 +1742,13 @@ int atcommand_whozeny(
else if (count == 1)
clif_displaymessage(fd, msg_table[29]); // 1 player found.
else {
- sprintf(output, msg_table[30], count); // %d players found.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[30], count); // %d players found.
+ clif_displaymessage(fd, atcmd_output);
}
+ aFree(zeny);
+ aFree(counted);
+
return 0;
}
@@ -1697,14 +1758,15 @@ int atcommand_happyhappyjoyjoy(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
-
struct map_session_data *pl_sd;
int i,e;
+ nullpo_retr(-1, sd);
+
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
e=rand()%40;
- if(e==34)
+ if(e==34)
e = 0;
clif_emotion(&pl_sd->bl,e);
}
@@ -1721,6 +1783,8 @@ int atcommand_save(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
+
pc_setsavepoint(sd, sd->mapname, sd->bl.x, sd->bl.y);
if (sd->status.pet_id > 0 && sd->pd)
intif_save_petdata(sd->status.account_id, &sd->pet);
@@ -1742,13 +1806,15 @@ int atcommand_load(
{
int m;
+ nullpo_retr(-1, sd);
+
m = map_mapname2mapid(sd->status.save_point.map);
if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp you to your save map.");
+ clif_displaymessage(fd, msg_table[249]);
return -1;
}
if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp you from your actual map.");
+ clif_displaymessage(fd, msg_table[248]);
return -1;
}
@@ -1766,14 +1832,15 @@ int atcommand_speed(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char output[200];
int speed;
- memset(output, '\0', sizeof(output));
+ nullpo_retr(-1, sd);
+
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message) {
- sprintf(output, "Please, enter a speed value (usage: @speed <%d-%d>).", MIN_WALK_SPEED, MAX_WALK_SPEED);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Please, enter a speed value (usage: @speed <%d-%d>).", MIN_WALK_SPEED, MAX_WALK_SPEED);
+ clif_displaymessage(fd, atcmd_output);
return -1;
}
@@ -1785,8 +1852,8 @@ int atcommand_speed(
clif_updatestatus(sd, SP_SPEED);
clif_displaymessage(fd, msg_table[8]); // Speed changed.
} else {
- sprintf(output, "Please, enter a valid speed value (usage: @speed <%d-%d>).", MIN_WALK_SPEED, MAX_WALK_SPEED);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Please, enter a valid speed value (usage: @speed <%d-%d>).", MIN_WALK_SPEED, MAX_WALK_SPEED);
+ clif_displaymessage(fd, atcmd_output);
return -1;
}
@@ -1801,11 +1868,25 @@ int atcommand_storage(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ struct storage *stor; //changes from Freya/Yor
+ nullpo_retr(-1, sd);
+
+ if (sd->state.storage_flag == 1) {
+ clif_displaymessage(fd, msg_table[250]);
+ return -1;
+ }
+
+ if ((stor = account2storage2(sd->status.account_id)) != NULL && stor->storage_status == 1) {
+ clif_displaymessage(fd, msg_table[250]);
+ return -1;
+ }
+
storage_storageopen(sd);
return 0;
}
+
/*==========================================
*
*------------------------------------------
@@ -1814,8 +1895,23 @@ int atcommand_guildstorage(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- if (sd->status.guild_id > 0)
+ struct storage *stor; //changes from Freya/Yor
+ nullpo_retr(-1, sd);
+
+ if (sd->status.guild_id > 0) {
+ if (sd->state.storage_flag == 1) {
+ clif_displaymessage(fd, msg_table[251]);
+ return -1;
+ }
+ if ((stor = account2storage2(sd->status.account_id)) != NULL && stor->storage_status == 1) {
+ clif_displaymessage(fd, msg_table[251]);
+ return -1;
+ }
storage_guild_storageopen(sd);
+ } else {
+ clif_displaymessage(fd, msg_table[252]);
+ return -1;
+ }
return 0;
}
@@ -1829,6 +1925,7 @@ int atcommand_option(
const char* command, const char* message)
{
int param1 = 0, param2 = 0, param3 = 0;
+ nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%d %d %d", &param1, &param2, &param3) < 1 || param1 < 0 || param2 < 0 || param3 < 0) {
clif_displaymessage(fd, "Please, enter at least a option (usage: @option <param1:0+> <param2:0+> <param3:0+>).");
@@ -1844,30 +1941,30 @@ int atcommand_option(
}
sd->status.option = param3;
// fix pecopeco display
- if (sd->status.class == 13 || sd->status.class == 21 || sd->status.class == 4014 || sd->status.class == 4022) {
+ if (sd->status.class_ == 13 || sd->status.class_ == 21 || sd->status.class_ == 4014 || sd->status.class_ == 4022) {
if (!pc_isriding(sd)) { // sd have the new value...
- if (sd->status.class == 13)
- sd->status.class = sd->view_class = 7;
- else if (sd->status.class == 21)
- sd->status.class = sd->view_class = 14;
- else if (sd->status.class == 4014)
- sd->status.class = sd->view_class = 4008;
- else if (sd->status.class == 4022)
- sd->status.class = sd->view_class = 4015;
+ if (sd->status.class_ == 13)
+ sd->status.class_ = sd->view_class = 7;
+ else if (sd->status.class_ == 21)
+ sd->status.class_ = sd->view_class = 14;
+ else if (sd->status.class_ == 4014)
+ sd->status.class_ = sd->view_class = 4008;
+ else if (sd->status.class_ == 4022)
+ sd->status.class_ = sd->view_class = 4015;
}
} else {
if (pc_isriding(sd)) { // sd have the new value...
if (sd->disguise > 0) { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris] (code added by [Yor])
sd->status.option &= ~0x0020;
} else {
- if (sd->status.class == 7)
- sd->status.class = sd->view_class = 13;
- else if (sd->status.class == 14)
- sd->status.class = sd->view_class = 21;
- else if (sd->status.class == 4008)
- sd->status.class = sd->view_class = 4014;
- else if (sd->status.class == 4015)
- sd->status.class = sd->view_class = 4022;
+ if (sd->status.class_ == 7)
+ sd->status.class_ = sd->view_class = 13;
+ else if (sd->status.class_ == 14)
+ sd->status.class_ = sd->view_class = 21;
+ else if (sd->status.class_ == 4008)
+ sd->status.class_ = sd->view_class = 4014;
+ else if (sd->status.class_ == 4015)
+ sd->status.class_ = sd->view_class = 4022;
else
sd->status.option &= ~0x0020;
}
@@ -1875,7 +1972,7 @@ int atcommand_option(
}
clif_changeoption(&sd->bl);
- pc_calcstatus(sd, 0);
+ status_calc_pc(sd, 0);
clif_displaymessage(fd, msg_table[9]); // Options changed.
return 0;
@@ -1889,6 +1986,7 @@ int atcommand_hide(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
if (sd->status.option & OPTION_HIDE) {
sd->status.option &= ~OPTION_HIDE;
clif_displaymessage(fd, msg_table[10]); // Invisible: Off
@@ -1909,32 +2007,116 @@ int atcommand_jobchange(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- int job = 0, upper = -1;
+ int job = 0, upper = 0;
+ nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%d %d", &job, &upper) < 1) {
- clif_displaymessage(fd, "Please, enter job ID (usage: @job/@jobchange <job ID>).");
- return -1;
+
+ int i, found = 0;
+ const struct { char name[16]; int id; } jobs[] = {
+ { "novice", 0 },
+ { "swordsman", 1 },
+ { "mage", 2 },
+ { "archer", 3 },
+ { "acolyte", 4 },
+ { "merchant", 5 },
+ { "thief", 6 },
+ { "knight", 7 },
+ { "priest", 8 },
+ { "priestess", 8 },
+ { "wizard", 9 },
+ { "blacksmith", 10 },
+ { "hunter", 11 },
+ { "assassin", 12 },
+ { "crusader", 14 },
+ { "monk", 15 },
+ { "sage", 16 },
+ { "rogue", 17 },
+ { "alchemist", 18 },
+ { "bard", 19 },
+ { "dancer", 20 },
+ { "super novice", 23 },
+ { "supernovice", 23 },
+ { "high novice", 4001 },
+ { "swordsman high", 4002 },
+ { "mage high", 4003 },
+ { "archer high", 4004 },
+ { "acolyte high", 4005 },
+ { "merchant high", 4006 },
+ { "thief high", 4007 },
+ { "lord knight", 4008 },
+ { "high priest", 4009 },
+ { "high priestess", 4009 },
+ { "high wizard", 4010 },
+ { "whitesmith", 4011 },
+ { "sniper", 4012 },
+ { "assassin cross", 4013 },
+ { "paladin", 4015 },
+ { "champion", 4016 },
+ { "professor", 4017 },
+ { "stalker", 4018 },
+ { "creator", 4019 },
+ { "clown", 4020 },
+ { "gypsy", 4021 },
+ { "baby novice", 4023 },
+ { "baby swordsman", 4024 },
+ { "baby mage", 4025 },
+ { "baby archer", 4026 },
+ { "baby acolyte", 4027 },
+ { "baby merchant", 4028 },
+ { "baby thief", 4029 },
+ { "baby knight", 4030 },
+ { "baby priest", 4031 },
+ { "baby priestess", 4031 },
+ { "baby wizard", 4032 },
+ { "baby blacksmith",4033 },
+ { "baby hunter", 4034 },
+ { "baby assassin", 4035 },
+ { "baby crusader", 4037 },
+ { "baby monk", 4038 },
+ { "baby sage", 4039 },
+ { "baby rogue", 4040 },
+ { "baby alchemist", 4041 },
+ { "baby bard", 4042 },
+ { "baby dancer", 4043 },
+ { "super baby", 4045 },
+ };
+
+ for (i=0; i < (int)(sizeof(jobs) / sizeof(jobs[0])); i++) {
+ if (strncmpi(message, jobs[i].name, 16) == 0) {
+ job = jobs[i].id;
+ upper = 0;
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ clif_displaymessage(fd, "Please, enter job ID (usage: @job/@jobchange <job ID>).");
+ return -1;
+ }
}
if (job == 37 ||job == 45)
return 0;
if ((job >= 0 && job < MAX_PC_CLASS)) {
+ int j;
// fix pecopeco display
if ((job != 13 && job != 21 && job != 4014 && job != 4022)) {
if (pc_isriding(sd)) {
- if (sd->status.class == 13)
- sd->status.class = sd->view_class = 7;
- if (sd->status.class == 21)
- sd->status.class = sd->view_class = 14;
- if (sd->status.class == 4014)
- sd->status.class = sd->view_class = 4008;
- if (sd->status.class == 4022)
- sd->status.class = sd->view_class = 4015;
+ if (sd->status.class_ == 13)
+ sd->status.class_ = sd->view_class = 7;
+ if (sd->status.class_ == 21)
+ sd->status.class_ = sd->view_class = 14;
+ if (sd->status.class_ == 4014)
+ sd->status.class_ = sd->view_class = 4008;
+ if (sd->status.class_ == 4022)
+ sd->status.class_ = sd->view_class = 4015;
sd->status.option &= ~0x0020;
clif_changeoption(&sd->bl);
- pc_calcstatus(sd, 0);
+ status_calc_pc(sd, 0);
}
} else {
if (!pc_isriding(sd)) {
@@ -1948,7 +2130,10 @@ int atcommand_jobchange(
job = 4015;
}
}
-
+ for (j=0; j < MAX_INVENTORY; j++) {
+ if(sd->status.inventory[j].nameid>0 && sd->status.inventory[j].equip!=0)
+ pc_unequipitem(sd, j, 3);
+ }
if (pc_jobchange(sd, job, upper) == 0)
clif_displaymessage(fd, msg_table[12]); // Your job has been changed.
else {
@@ -1971,6 +2156,7 @@ int atcommand_die(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
clif_specialeffect(&sd->bl,450,1);
pc_damage(NULL, sd, sd->status.hp + 1);
clif_displaymessage(fd, msg_table[13]); // A pity! You've died.
@@ -1986,17 +2172,17 @@ int atcommand_kill(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
struct map_session_data *pl_sd;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @kill <char name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kill only lower or same level
pc_damage(NULL, pl_sd, pl_sd->status.hp + 1);
clif_displaymessage(fd, msg_table[14]); // Character killed.
@@ -2020,6 +2206,7 @@ int atcommand_alive(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
if (pc_isdead(sd)) {
sd->status.hp = sd->status.max_hp;
sd->status.sp = sd->status.max_sp;
@@ -2032,9 +2219,8 @@ int atcommand_alive(
clif_resurrection(&sd->bl, 1);
clif_displaymessage(fd, msg_table[16]); // You've been revived! It's a miracle!
return 0;
- }
+ }
return -1;
-
}
/*==========================================
@@ -2045,17 +2231,17 @@ int atcommand_kami(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char output[200];
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message) {
clif_displaymessage(fd, "Please, enter a message (usage: @kami <message>).");
return -1;
}
- sscanf(message, "%199[^\n]", output);
- intif_GMmessage(output, strlen(output) + 1, (*(command + 5) == 'b') ? 0x10 : 0);
+ sscanf(message, "%199[^\n]", atcmd_output);
+ intif_GMmessage(atcmd_output, strlen(atcmd_output) + 1, (*(command + 5) == 'b') ? 0x10 : 0);
return 0;
}
@@ -2069,6 +2255,7 @@ int atcommand_heal(
const char* command, const char* message)
{
int hp = 0, sp = 0; // [Valaris] thanks to fov
+ nullpo_retr(-1, sd);
sscanf(message, "%d %d", &hp, &sp);
@@ -2120,6 +2307,7 @@ int atcommand_item(
struct item item_tmp;
struct item_data *item_data;
int get_count, i, pet_id;
+ nullpo_retr(-1, sd);
memset(item_name, '\0', sizeof(item_name));
@@ -2147,10 +2335,10 @@ int atcommand_item(
for (i = 0; i < number; i += get_count) {
// if pet egg
if (pet_id >= 0) {
- sd->catch_target_class = pet_db[pet_id].class;
+ sd->catch_target_class = pet_db[pet_id].class_;
intif_create_pet(sd->status.account_id, sd->status.char_id,
- pet_db[pet_id].class, mob_db[pet_db[pet_id].class].lv,
- pet_db[pet_id].EggID, 0, pet_db[pet_id].intimate,
+ (short)pet_db[pet_id].class_, (short)mob_db[pet_db[pet_id].class_].lv,
+ (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate,
100, 0, 1, pet_db[pet_id].jname);
// if not pet egg
} else {
@@ -2186,6 +2374,7 @@ int atcommand_item2(
int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
int flag;
int loop, get_count, i;
+ nullpo_retr(-1, sd);
memset(item_name, '\0', sizeof(item_name));
@@ -2253,6 +2442,7 @@ int atcommand_itemreset(
const char* command, const char* message)
{
int i;
+ nullpo_retr(-1, sd);
for (i = 0; i < MAX_INVENTORY; i++) {
if (sd->status.inventory[i].amount && sd->status.inventory[i].equip == 0)
@@ -2271,6 +2461,7 @@ int atcommand_itemcheck(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
pc_checkitem(sd);
return 0;
@@ -2285,6 +2476,7 @@ int atcommand_baselevelup(
const char* command, const char* message)
{
int level, i;
+ nullpo_retr(-1, sd);
if (!message || !*message || (level = atoi(message)) == 0) {
clif_displaymessage(fd, "Please, enter a level adjustement (usage: @lvup/@blevel/@baselvlup <number of levels>).");
@@ -2296,7 +2488,7 @@ int atcommand_baselevelup(
clif_displaymessage(fd, msg_table[47]); // Base level can't go any higher.
return -1;
} // End Addition
- if (level > battle_config.maximum_level || level > (battle_config.maximum_level - sd->status.base_level)) // fix positiv overflow
+ if ((unsigned int)level > battle_config.maximum_level || (unsigned int)level > (battle_config.maximum_level - sd->status.base_level)) // fix positiv overflow
level = battle_config.maximum_level - sd->status.base_level;
for (i = 1; i <= level; i++)
sd->status.status_point += (sd->status.base_level + i + 14) / 5;
@@ -2304,7 +2496,7 @@ int atcommand_baselevelup(
clif_updatestatus(sd, SP_BASELEVEL);
clif_updatestatus(sd, SP_NEXTBASEEXP);
clif_updatestatus(sd, SP_STATUSPOINT);
- pc_calcstatus(sd, 0);
+ status_calc_pc(sd, 0);
pc_heal(sd, sd->status.max_hp, sd->status.max_sp);
clif_misceffect(&sd->bl, 0);
clif_displaymessage(fd, msg_table[21]); // Base level raised.
@@ -2313,7 +2505,7 @@ int atcommand_baselevelup(
clif_displaymessage(fd, msg_table[158]); // Base level can't go any lower.
return -1;
}
- if (level < -battle_config.maximum_level || level < (1 - sd->status.base_level)) // fix negativ overflow
+ if (level < -(int)battle_config.maximum_level || level < (1 - (int)sd->status.base_level)) // fix negativ overflow
level = 1 - sd->status.base_level;
if (sd->status.status_point > 0) {
for (i = 0; i > level; i--)
@@ -2325,7 +2517,7 @@ int atcommand_baselevelup(
sd->status.base_level += level;
clif_updatestatus(sd, SP_BASELEVEL);
clif_updatestatus(sd, SP_NEXTBASEEXP);
- pc_calcstatus(sd, 0);
+ status_calc_pc(sd, 0);
clif_displaymessage(fd, msg_table[22]); // Base level lowered.
}
@@ -2340,16 +2532,23 @@ int atcommand_joblevelup(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- int up_level = 50, level;
+ unsigned int up_level = 50;
+ int level;
+ struct pc_base_job s_class;
+ nullpo_retr(-1, sd);
+ s_class = pc_calc_base_job(sd->status.class_);
if (!message || !*message || (level = atoi(message)) == 0) {
clif_displaymessage(fd, "Please, enter a level adjustement (usage: @joblvup/@jlevel/@joblvlup <number of levels>).");
return -1;
}
- if (sd->status.class == 0 || sd->status.class == 4001)
+ if (s_class.job == 0)
up_level -= 40;
- else if ((sd->status.class > 4007 && sd->status.class < 4024) || sd->status.class == 23)
+ // super novices can go up to 99 [celest]
+ else if (s_class.job == 23)
+ up_level += 49;
+ else if (sd->status.class_ > 4007 && sd->status.class_ < 4023)
up_level += 20;
if (level > 0) {
@@ -2357,14 +2556,14 @@ int atcommand_joblevelup(
clif_displaymessage(fd, msg_table[23]); // Job level can't go any higher.
return -1;
}
- if (level > up_level || level > (up_level - sd->status.job_level)) // fix positiv overflow
+ if ((unsigned int)level > up_level || (unsigned int)level > (up_level - sd->status.job_level)) // fix positiv overflow
level = up_level - sd->status.job_level;
sd->status.job_level += level;
clif_updatestatus(sd, SP_JOBLEVEL);
clif_updatestatus(sd, SP_NEXTJOBEXP);
sd->status.skill_point += level;
clif_updatestatus(sd, SP_SKILLPOINT);
- pc_calcstatus(sd, 0);
+ status_calc_pc(sd, 0);
clif_misceffect(&sd->bl, 1);
clif_displaymessage(fd, msg_table[24]); // Job level raised.
} else {
@@ -2372,7 +2571,7 @@ int atcommand_joblevelup(
clif_displaymessage(fd, msg_table[159]); // Job level can't go any lower.
return -1;
}
- if (level < -up_level || level < (1 - sd->status.job_level)) // fix negativ overflow
+ if (level < -(int)up_level || level < (1 - (int)sd->status.job_level)) // fix negativ overflow
level = 1 - sd->status.job_level;
sd->status.job_level += level;
clif_updatestatus(sd, SP_JOBLEVEL);
@@ -2383,7 +2582,7 @@ int atcommand_joblevelup(
sd->status.skill_point = 0;
clif_updatestatus(sd, SP_SKILLPOINT);
} // to add: remove status points from skills
- pc_calcstatus(sd, 0);
+ status_calc_pc(sd, 0);
clif_displaymessage(fd, msg_table[25]); // Job level lowered.
}
@@ -2401,6 +2600,7 @@ int atcommand_help(
char buf[2048], w1[2048], w2[2048];
int i, gm_level;
FILE* fp;
+ nullpo_retr(-1, sd);
memset(buf, '\0', sizeof(buf));
@@ -2439,6 +2639,7 @@ int atcommand_gm(
const char* command, const char* message)
{
char password[100];
+ nullpo_retr(-1, sd);
memset(password, '\0', sizeof(password));
@@ -2466,6 +2667,7 @@ int atcommand_pvpoff(
{
struct map_session_data *pl_sd;
int i;
+ nullpo_retr(-1, sd);
if (battle_config.pk_mode) { //disable command if server is in PK mode [Valaris]
clif_displaymessage(fd, msg_table[52]); // This option cannot be used in PK Mode.
@@ -2476,7 +2678,7 @@ int atcommand_pvpoff(
map[sd->bl.m].flag.pvp = 0;
clif_send0199(sd->bl.m, 0);
for (i = 0; i < fd_max; i++) { //人数分ループ
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
if (sd->bl.m == pl_sd->bl.m) {
clif_pvpset(pl_sd, 0, 0, 2);
if (pl_sd->pvp_timer != -1) {
@@ -2505,6 +2707,7 @@ int atcommand_pvpon(
{
struct map_session_data *pl_sd;
int i;
+ nullpo_retr(-1, sd);
if (battle_config.pk_mode) { //disable command if server is in PK mode [Valaris]
clif_displaymessage(fd, msg_table[52]); // This option cannot be used in PK Mode.
@@ -2515,7 +2718,7 @@ int atcommand_pvpon(
map[sd->bl.m].flag.pvp = 1;
clif_send0199(sd->bl.m, 1);
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
if (sd->bl.m == pl_sd->bl.m && pl_sd->pvp_timer == -1) {
pl_sd->pvp_timer = add_timer(gettick() + 200,
pc_calc_pvprank_timer, pl_sd->bl.id, 0);
@@ -2542,6 +2745,7 @@ int atcommand_gvgoff(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
if (map[sd->bl.m].flag.gvg) {
map[sd->bl.m].flag.gvg = 0;
clif_send0199(sd->bl.m, 0);
@@ -2562,6 +2766,7 @@ int atcommand_gvgon(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
if (!map[sd->bl.m].flag.gvg) {
map[sd->bl.m].flag.gvg = 1;
clif_send0199(sd->bl.m, 3);
@@ -2583,14 +2788,14 @@ int atcommand_model(
const char* command, const char* message)
{
int hair_style = 0, hair_color = 0, cloth_color = 0;
- char output[200];
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%d %d %d", &hair_style, &hair_color, &cloth_color) < 1) {
- sprintf(output, "Please, enter at least a value (usage: @model <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d>).",
+ sprintf(atcmd_output, "Please, enter at least a value (usage: @model <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d>).",
MIN_HAIR_STYLE, MAX_HAIR_STYLE, MIN_HAIR_COLOR, MAX_HAIR_COLOR, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
- clif_displaymessage(fd, output);
+ clif_displaymessage(fd, atcmd_output);
return -1;
}
@@ -2598,7 +2803,7 @@ int atcommand_model(
hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR &&
cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) {
//服の色変更
- if (cloth_color != 0 && sd->status.sex == 1 && (sd->status.class == 12 || sd->status.class == 17)) {
+ if (cloth_color != 0 && sd->status.sex == 1 && (sd->status.class_ == 12 || sd->status.class_ == 17)) {
//服の色未実装職の判定
clif_displaymessage(fd, msg_table[35]); // You can't use this command with this class.
return -1;
@@ -2623,24 +2828,19 @@ int atcommand_model(
int atcommand_dye(const int fd, struct map_session_data* sd, const char* command, const char* message)
{
int cloth_color = 0;
- char output[200];
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%d", &cloth_color) < 1) {
- sprintf(output, "Please, enter a clothes color (usage: @dye/@ccolor <clothes color: %d-%d>).", MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Please, enter a clothes color (usage: @dye/@ccolor <clothes color: %d-%d>).", MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
+ clif_displaymessage(fd, atcmd_output);
return -1;
}
if (cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) {
- if (cloth_color != 0 && sd->status.sex == 1 && (sd->status.class == 12 || sd->status.class == 17)) {
- clif_displaymessage(fd, msg_table[35]); // You can't use this command with this class.
- return -1;
- } else {
- pc_changelook(sd, LOOK_CLOTHES_COLOR, cloth_color);
- clif_displaymessage(fd, msg_table[36]); // Appearence changed.
- }
+ pc_changelook(sd, LOOK_CLOTHES_COLOR, cloth_color);
+ clif_displaymessage(fd, msg_table[36]); // Appearence changed.
} else {
clif_displaymessage(fd, msg_table[37]); // An invalid number was specified.
return -1;
@@ -2650,35 +2850,24 @@ int atcommand_dye(const int fd, struct map_session_data* sd, const char* command
}
/*==========================================
- * @chardye by [MouseJstr]
- *------------------------------------------
- */
-int
-atcommand_chardye(const int fd, struct map_session_data* sd,
- const char* command, const char* message)
-{
- return 0;
-}
-
-/*==========================================
* @hairstyle && @hstyle
*------------------------------------------
*/
int atcommand_hair_style(const int fd, struct map_session_data* sd, const char* command, const char* message)
{
int hair_style = 0;
- char output[200];
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%d", &hair_style) < 1) {
- sprintf(output, "Please, enter a hair style (usage: @hairstyle/@hstyle <hair ID: %d-%d>).", MIN_HAIR_STYLE, MAX_HAIR_STYLE);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Please, enter a hair style (usage: @hairstyle/@hstyle <hair ID: %d-%d>).", MIN_HAIR_STYLE, MAX_HAIR_STYLE);
+ clif_displaymessage(fd, atcmd_output);
return -1;
}
if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE) {
- if (hair_style != 0 && sd->status.sex == 1 && (sd->status.class == 12 || sd->status.class == 17)) {
+ if (hair_style != 0 && sd->status.sex == 1 && (sd->status.class_ == 12 || sd->status.class_ == 17)) {
clif_displaymessage(fd, msg_table[35]); // You can't use this command with this class.
return -1;
} else {
@@ -2701,7 +2890,8 @@ int
atcommand_charhairstyle(const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- return 0;
+ nullpo_retr(-1, sd);
+ return 0;
}
/*==========================================
@@ -2711,18 +2901,18 @@ atcommand_charhairstyle(const int fd, struct map_session_data* sd,
int atcommand_hair_color(const int fd, struct map_session_data* sd, const char* command, const char* message)
{
int hair_color = 0;
- char output[200];
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%d", &hair_color) < 1) {
- sprintf(output, "Please, enter a hair color (usage: @haircolor/@hcolor <hair color: %d-%d>).", MIN_HAIR_COLOR, MAX_HAIR_COLOR);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Please, enter a hair color (usage: @haircolor/@hcolor <hair color: %d-%d>).", MIN_HAIR_COLOR, MAX_HAIR_COLOR);
+ clif_displaymessage(fd, atcmd_output);
return -1;
}
if (hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR) {
- if (hair_color != 0 && sd->status.sex == 1 && (sd->status.class == 12 || sd->status.class == 17)) {
+ if (hair_color != 0 && sd->status.sex == 1 && (sd->status.class_ == 12 || sd->status.class_ == 17)) {
clif_displaymessage(fd, msg_table[35]); // You can't use this command with this class.
return -1;
} else {
@@ -2738,17 +2928,6 @@ int atcommand_hair_color(const int fd, struct map_session_data* sd, const char*
}
/*==========================================
- * @charhaircolor by [MouseJstr]
- *------------------------------------------
- */
-int
-atcommand_charhaircolor(const int fd, struct map_session_data* sd,
- const char* command, const char* message)
-{
- return 0;
-}
-
-/*==========================================
* @go [city_number/city_name]: improved by [yor] to add city names and help
*------------------------------------------
*/
@@ -2759,15 +2938,9 @@ int atcommand_go(
int i;
int town;
char map_name[100];
- char output[200];
int m;
- if(map[sd->bl.m].flag.nogo) {
- clif_displaymessage(sd->fd,"You can not use @go on this map.");
- return 0;
- }
-
- struct { char map[16]; int x, y; } data[] = {
+ const struct { char map[16]; int x, y; } data[] = {
{ "prontera.gat", 156, 191 }, // 0=Prontera
{ "morocc.gat", 156, 93 }, // 1=Morroc
{ "geffen.gat", 119, 59 }, // 2=Geffen
@@ -2785,10 +2958,19 @@ int atcommand_go(
{ "louyang.gat", 217, 40 }, // 14=Lou Yang
{ "new_1-1.gat", 53, 111 }, // 15=Start point
{ "sec_pri.gat", 23, 61 }, // 16=Prison
+ { "jawaii.gat", 249, 127 }, // 17=Jawaii
+ { "ayothaya.gat", 151, 117 }, // 18=Ayothaya
};
+ nullpo_retr(-1, sd);
+
+ if(map[sd->bl.m].flag.nogo) {
+ clif_displaymessage(sd->fd,"You can not use @go on this map.");
+ return 0;
+ }
+
memset(map_name, '\0', sizeof(map_name));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
// get the number
town = atoi(message);
@@ -2803,7 +2985,8 @@ int atcommand_go(
clif_displaymessage(fd, " 0=Prontera 7=Lutie 14=Lou Yang");
clif_displaymessage(fd, " 1=Morroc 8=Comodo 15=Start point");
clif_displaymessage(fd, " 2=Geffen 9=Yuno 16=Prison");
- clif_displaymessage(fd, " 3=Payon 10=Amatsu");
+ clif_displaymessage(fd, " 3=Payon 10=Amatsu 17=Jawaii");
+ clif_displaymessage(fd, " 18=Ayothaya");
return -1;
} else {
// get possible name of the city and add .gat if not in the name
@@ -2858,17 +3041,23 @@ int atcommand_go(
strncmp(map_name, "prison.gat", 3) == 0 || // name of the position (3 first characters)
strncmp(map_name, "jails.gat", 3) == 0) { // name of the position
town = 16;
+ } else if (strncmp(map_name, "jawaii.gat", 3) == 0 || // 3 first characters
+ strncmp(map_name, "jawai.gat", 3) == 0) { // writing error (3 first characters)
+ town = 17;
+ } else if (strncmp(map_name, "ayothaya.gat", 4) == 0 || // 3 first characters
+ strncmp(map_name, "ayotaya.gat", 4) == 0) { // writing error (3 first characters)
+ town = 18;
}
if (town >= -3 && town <= -1) {
if (sd->status.memo_point[-town-1].map[0]) {
m = map_mapname2mapid(sd->status.memo_point[-town-1].map);
if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp you to this memo map.");
+ clif_displaymessage(fd, msg_table[247]);
return -1;
}
if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp you from your actual map.");
+ clif_displaymessage(fd, msg_table[248]);
return -1;
}
if (pc_setpos(sd, sd->status.memo_point[-town-1].map, sd->status.memo_point[-town-1].x, sd->status.memo_point[-town-1].y, 3) == 0) {
@@ -2878,21 +3067,21 @@ int atcommand_go(
return -1;
}
} else {
- sprintf(output, msg_table[164], -town-1); // Your memo point #%d doesn't exist.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[164], -town-1); // Your memo point #%d doesn't exist.
+ clif_displaymessage(fd, atcmd_output);
return -1;
}
} else if (town >= 0 && town < (int)(sizeof(data) / sizeof(data[0]))) {
- m = map_mapname2mapid(data[town].map);
+ m = map_mapname2mapid((char *)data[town].map);
if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp you to this destination map.");
+ clif_displaymessage(fd, msg_table[247]);
return -1;
}
if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to warp you from your actual map.");
+ clif_displaymessage(fd, msg_table[248]);
return -1;
}
- if (pc_setpos(sd, data[town].map, data[town].x, data[town].y, 3) == 0) {
+ if (pc_setpos(sd, (char *)data[town].map, data[town].x, data[town].y, 3) == 0) {
clif_displaymessage(fd, msg_table[0]); // Warped.
} else {
clif_displaymessage(fd, msg_table[1]); // Map not found.
@@ -2917,17 +3106,17 @@ int atcommand_monster(
{
char name[100];
char monster[100];
- char output[200];
int mob_id;
int number = 0;
int x = 0, y = 0;
int count;
int i, j, k;
int mx, my, range;
+ nullpo_retr(-1, sd);
memset(name, '\0', sizeof(name));
memset(monster, '\0', sizeof(monster));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message ||
(sscanf(message, "\"%[^\"]\" %99s %d %d %d", name, monster, &number, &x, &y) < 2 &&
@@ -2964,7 +3153,7 @@ int atcommand_monster(
printf("%s monster='%s' name='%s' id=%d count=%d (%d,%d)\n", command, monster, name, mob_id, number, x, y);
count = 0;
- range = sqrt(number) / 2;
+ range = (int)sqrt(number) / 2;
range = range * 2 + 5; // calculation of an odd number (+ 4 area around)
for (i = 0; i < number; i++) {
j = 0;
@@ -2987,8 +3176,8 @@ int atcommand_monster(
if (number == count)
clif_displaymessage(fd, msg_table[39]); // All monster summoned!
else {
- sprintf(output, msg_table[240], count); // %d monster(s) summoned!
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[240], count); // %d monster(s) summoned!
+ clif_displaymessage(fd, atcmd_output);
}
else {
clif_displaymessage(fd, msg_table[40]); // Invalid monster ID or name.
@@ -3007,7 +3196,6 @@ int atcommand_spawn(
const char* command, const char* message) {
char name[100];
char monster[100];
- char output[200];
int mob_id;
int number = 0;
int x = 0, y = 0;
@@ -3015,9 +3203,10 @@ int atcommand_spawn(
int i, j, k;
int mx, my, range;
+ nullpo_retr(-1, sd);
memset(name, '\0', sizeof(name));
memset(monster, '\0', sizeof(monster));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message ||
(sscanf(message, "\"%[^\"]\" %99s %d %d %d", name, monster, &number, &x, &y) < 2 &&
@@ -3055,7 +3244,7 @@ int atcommand_spawn(
printf("%s monster='%s' name='%s' id=%d count=%d (%d,%d)\n", command, monster, name, mob_id, number, x, y);
count = 0;
- range = sqrt(number) / 2;
+ range = (int)sqrt(number) / 2;
range = range * 2 + 5; // calculation of an odd number (+ 4 area around)
for (i = 0; i < number; i++) {
j = 0;
@@ -3078,8 +3267,8 @@ int atcommand_spawn(
if (number == count)
clif_displaymessage(fd, msg_table[39]); // All monster summoned!
else {
- sprintf(output, msg_table[240], count); // %d monster(s) summoned!
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[240], count); // %d monster(s) summoned!
+ clif_displaymessage(fd, atcmd_output);
}
else {
clif_displaymessage(fd, msg_table[40]); // Invalid monster ID or name.
@@ -3254,6 +3443,8 @@ void atcommand_killmonster_sub(
int map_id;
char map_name[100];
+ if (!sd) return;
+
memset(map_name, '\0', sizeof(map_name));
if (!message || !*message || sscanf(message, "%99s", map_name) < 1)
@@ -3280,6 +3471,7 @@ int atcommand_killmonster(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ if (!sd) return 0;
atcommand_killmonster_sub(fd, sd, message, 1);
return 0;
@@ -3293,6 +3485,7 @@ int atcommand_killmonster2(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ if (!sd) return 0;
atcommand_killmonster_sub(fd, sd, message, 0);
return 0;
@@ -3308,9 +3501,9 @@ int atcommand_refine(
{
int i, position = 0, refine = 0, current_position, final_refine;
int count;
- char output[200];
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%d %d", &position, &refine) < 2) {
clif_displaymessage(fd, "Please, enter a position and a amount (usage: @refine <equip position> <+/- amount>).");
@@ -3337,7 +3530,7 @@ int atcommand_refine(
if (sd->status.inventory[i].refine != final_refine) {
sd->status.inventory[i].refine = final_refine;
current_position = sd->status.inventory[i].equip;
- pc_unequipitem(sd, i, 0, BF_NORMAL);
+ pc_unequipitem(sd, i, 3);
clif_refine(fd, sd, 0, i, sd->status.inventory[i].refine);
clif_delitem(sd, i, 1);
clif_additem(sd, i, 1, 0);
@@ -3353,8 +3546,8 @@ int atcommand_refine(
else if (count == 1)
clif_displaymessage(fd, msg_table[167]); // 1 item has been refined!
else {
- sprintf(output, msg_table[168], count); // %d items have been refined!
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[168], count); // %d items have been refined!
+ clif_displaymessage(fd, atcmd_output);
}
return 0;
@@ -3373,9 +3566,9 @@ int atcommand_produce(
int flag = 0;
struct item_data *item_data;
struct item tmp_item;
- char output[200];
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(item_name, '\0', sizeof(item_name));
if (!message || !*message || sscanf(message, "%99s %d %d", item_name, &attribute, &star) < 1) {
@@ -3412,10 +3605,10 @@ int atcommand_produce(
if (battle_config.error_log)
printf("@produce NOT WEAPON [%d]\n", item_id);
if (item_id != 0 && itemdb_exists(item_id))
- sprintf(output, msg_table[169], item_id, item_data->name); // This item (%d: '%s') is not an equipment.
+ sprintf(atcmd_output, msg_table[169], item_id, item_data->name); // This item (%d: '%s') is not an equipment.
else
- sprintf(output, msg_table[170]); // This item is not an equipment.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[170]); // This item is not an equipment.
+ clif_displaymessage(fd, atcmd_output);
return -1;
}
@@ -3428,17 +3621,18 @@ int atcommand_produce(
*/
void atcommand_memo_sub(struct map_session_data* sd) {
int i;
- char output[200];
- memset(output, '\0', sizeof(output));
+ if (!sd) return;
+
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
clif_displaymessage(sd->fd, "Your actual memo positions are (except respawn point):");
for (i = MIN_PORTAL_MEMO; i <= MAX_PORTAL_MEMO; i++) {
if (sd->status.memo_point[i].map[0])
- sprintf(output, "%d - %s (%d,%d)", i, sd->status.memo_point[i].map, sd->status.memo_point[i].x, sd->status.memo_point[i].y);
+ sprintf(atcmd_output, "%d - %s (%d,%d)", i, sd->status.memo_point[i].map, sd->status.memo_point[i].x, sd->status.memo_point[i].y);
else
- sprintf(output, msg_table[171], i); // %d - void
- clif_displaymessage(sd->fd, output);
+ sprintf(atcmd_output, msg_table[171], i); // %d - void
+ clif_displaymessage(sd->fd, atcmd_output);
}
return;
@@ -3453,21 +3647,21 @@ int atcommand_memo(
const char* command, const char* message)
{
int position = 0;
- char output[200];
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%d", &position) < 1)
atcommand_memo_sub(sd);
else {
if (position >= MIN_PORTAL_MEMO && position <= MAX_PORTAL_MEMO) {
if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
- clif_displaymessage(fd, "You are not authorised to memo this map.");
+ clif_displaymessage(fd, msg_table[253]);
return -1;
}
if (sd->status.memo_point[position].map[0]) {
- sprintf(output, msg_table[172], position, sd->status.memo_point[position].map, sd->status.memo_point[position].x, sd->status.memo_point[position].y); // You replace previous memo position %d - %s (%d,%d).
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[172], position, sd->status.memo_point[position].map, sd->status.memo_point[position].x, sd->status.memo_point[position].y); // You replace previous memo position %d - %s (%d,%d).
+ clif_displaymessage(fd, atcmd_output);
}
memcpy(sd->status.memo_point[position].map, map[sd->bl.m].name, 24);
sd->status.memo_point[position].x = sd->bl.x;
@@ -3477,8 +3671,8 @@ int atcommand_memo(
clif_displaymessage(fd, msg_table[173]); // Note: you don't have the 'Warp' skill level to use it.
atcommand_memo_sub(sd);
} else {
- sprintf(output, "Please, enter a valid position (usage: @memo <memo_position:%d-%d>).", MIN_PORTAL_MEMO, MAX_PORTAL_MEMO);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Please, enter a valid position (usage: @memo <memo_position:%d-%d>).", MIN_PORTAL_MEMO, MAX_PORTAL_MEMO);
+ clif_displaymessage(fd, atcmd_output);
atcommand_memo_sub(sd);
return -1;
}
@@ -3495,20 +3689,21 @@ int atcommand_gat(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char output[200];
int y;
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
for (y = 2; y >= -2; y--) {
- sprintf(output, "%s (x= %d, y= %d) %02X %02X %02X %02X %02X",
- map[sd->bl.m].name, sd->bl.x - 2, sd->bl.y + y,
- map_getcell(sd->bl.m, sd->bl.x - 2, sd->bl.y + y),
- map_getcell(sd->bl.m, sd->bl.x - 1, sd->bl.y + y),
- map_getcell(sd->bl.m, sd->bl.x, sd->bl.y + y),
- map_getcell(sd->bl.m, sd->bl.x + 1, sd->bl.y + y),
- map_getcell(sd->bl.m, sd->bl.x + 2, sd->bl.y + y));
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "%s (x= %d, y= %d) %02X %02X %02X %02X %02X",
+ map[sd->bl.m].name, sd->bl.x - 2, sd->bl.y + y,
+ map_getcell(sd->bl.m, sd->bl.x - 2, sd->bl.y + y, CELL_GETTYPE),
+ map_getcell(sd->bl.m, sd->bl.x - 1, sd->bl.y + y, CELL_GETTYPE),
+ map_getcell(sd->bl.m, sd->bl.x, sd->bl.y + y, CELL_GETTYPE),
+ map_getcell(sd->bl.m, sd->bl.x + 1, sd->bl.y + y, CELL_GETTYPE),
+ map_getcell(sd->bl.m, sd->bl.x + 2, sd->bl.y + y, CELL_GETTYPE));
+
+ clif_displaymessage(fd, atcmd_output);
}
return 0;
@@ -3523,6 +3718,7 @@ int atcommand_packet(
const char* command, const char* message)
{
int x = 0, y = 0;
+ nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%d %d", &x, &y) < 2) {
clif_displaymessage(fd, "Please, enter a status type/flag (usage: @packet <status type> <flag>).");
@@ -3579,6 +3775,7 @@ int atcommand_skillpoint(
const char* command, const char* message)
{
int point, new_skill_point;
+ nullpo_retr(-1, sd);
if (!message || !*message || (point = atoi(message)) == 0) {
clif_displaymessage(fd, "Please, enter a number (usage: @skpoint <number of points>).");
@@ -3615,6 +3812,7 @@ int atcommand_zeny(
const char* command, const char* message)
{
int zeny, new_zeny;
+ nullpo_retr(-1, sd);
if (!message || !*message || (zeny = atoi(message)) == 0) {
clif_displaymessage(fd, "Please, enter an amount (usage: @zeny <amount>).");
@@ -3656,13 +3854,13 @@ int atcommand_param(
&sd->status.str, &sd->status.agi, &sd->status.vit,
&sd->status.int_, &sd->status.dex, &sd->status.luk
};
- char output[200];
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) {
- sprintf(output, "Please, enter a valid value (usage: @str,@agi,@vit,@int,@dex,@luk <+/-adjustement>).");
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Please, enter a valid value (usage: @str,@agi,@vit,@int,@dex,@luk <+/-adjustement>).");
+ clif_displaymessage(fd, atcmd_output);
return -1;
}
@@ -3674,22 +3872,22 @@ int atcommand_param(
}
}
if (index < 0 || index > MAX_STATUS_TYPE) { // normaly impossible...
- sprintf(output, "Please, enter a valid value (usage: @str,@agi,@vit,@int,@dex,@luk <+/-adjustement>).");
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Please, enter a valid value (usage: @str,@agi,@vit,@int,@dex,@luk <+/-adjustement>).");
+ clif_displaymessage(fd, atcmd_output);
return -1;
}
new_value = (int)*status[index] + value;
- if (value > 0 && (value > battle_config.max_parameter || new_value > battle_config.max_parameter)) // fix positiv overflow
+ if (value > 0 && ((unsigned int)value > battle_config.max_parameter || (unsigned int)new_value > battle_config.max_parameter)) // fix positiv overflow
new_value = battle_config.max_parameter;
- else if (value < 0 && (value < -battle_config.max_parameter || new_value < 1)) // fix negativ overflow
+ else if (value < 0 && (value < -(int)battle_config.max_parameter || new_value < 1)) // fix negativ overflow
new_value = 1;
if (new_value != (int)*status[index]) {
*status[index] = new_value;
clif_updatestatus(sd, SP_STR + index);
clif_updatestatus(sd, SP_USTR + index);
- pc_calcstatus(sd, 0);
+ status_calc_pc(sd, 0);
clif_displaymessage(fd, msg_table[42]); // Stat changed.
} else {
if (value < 0)
@@ -3716,6 +3914,7 @@ int atcommand_stat_all(
&sd->status.str, &sd->status.agi, &sd->status.vit,
&sd->status.int_, &sd->status.dex, &sd->status.luk
};
+ nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0)
value = battle_config.max_parameter;
@@ -3724,16 +3923,16 @@ int atcommand_stat_all(
for (index = 0; index < (int)(sizeof(status) / sizeof(status[0])); index++) {
new_value = (int)*status[index] + value;
- if (value > 0 && (value > battle_config.max_parameter || new_value > battle_config.max_parameter)) // fix positiv overflow
+ if (value > 0 && ((unsigned int)value > battle_config.max_parameter || (unsigned int)new_value > battle_config.max_parameter)) // fix positiv overflow
new_value = battle_config.max_parameter;
- else if (value < 0 && (value < -battle_config.max_parameter || new_value < 1)) // fix negativ overflow
+ else if (value < 0 && (value < -(int)battle_config.max_parameter || new_value < 1)) // fix negativ overflow
new_value = 1;
if (new_value != (int)*status[index]) {
*status[index] = new_value;
clif_updatestatus(sd, SP_STR + index);
clif_updatestatus(sd, SP_USTR + index);
- pc_calcstatus(sd, 0);
+ status_calc_pc(sd, 0);
count++;
}
}
@@ -3762,6 +3961,7 @@ int atcommand_guildlevelup(
int level = 0;
short added_level;
struct guild *guild_info;
+ nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%d", &level) < 1 || level == 0) {
clif_displaymessage(fd, "Please, enter a valid level (usage: @guildlvup/@guildlvlup <# of levels>).");
@@ -3804,6 +4004,7 @@ int atcommand_makeegg(
{
struct item_data *item_data;
int id, pet_id;
+ nullpo_retr(-1, sd);
if (!message || !*message) {
clif_displaymessage(fd, "Please, enter a monter/egg name/id (usage: @makeegg <pet_id>).");
@@ -3819,11 +4020,11 @@ int atcommand_makeegg(
if (pet_id < 0)
pet_id = search_petDB_index(id, PET_EGG);
if (pet_id >= 0) {
- sd->catch_target_class = pet_db[pet_id].class;
+ sd->catch_target_class = pet_db[pet_id].class_;
intif_create_pet(
sd->status.account_id, sd->status.char_id,
- pet_db[pet_id].class, mob_db[pet_db[pet_id].class].lv,
- pet_db[pet_id].EggID, 0, pet_db[pet_id].intimate,
+ (short)pet_db[pet_id].class_, (short)mob_db[pet_db[pet_id].class_].lv,
+ (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate,
100, 0, 1, pet_db[pet_id].jname);
} else {
clif_displaymessage(fd, msg_table[180]); // The monter/egg name/id doesn't exist.
@@ -3841,6 +4042,7 @@ int atcommand_hatch(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
if (sd->status.pet_id <= 0)
clif_sendegg(sd);
else {
@@ -3861,6 +4063,7 @@ int atcommand_petfriendly(
{
int friendly;
int t;
+ nullpo_retr(-1, sd);
if (!message || !*message || (friendly = atoi(message)) < 0) {
clif_displaymessage(fd, "Please, enter a valid value (usage: @petfriendly <0-1000>).");
@@ -3877,9 +4080,9 @@ int atcommand_petfriendly(
if ((sd->pet.intimate > 0 && t <= 0) ||
(sd->pet.intimate <= 0 && t > 0)) {
if (sd->bl.prev != NULL)
- pc_calcstatus(sd, 0);
+ status_calc_pc(sd, 0);
else
- pc_calcstatus(sd, 2);
+ status_calc_pc(sd, 2);
}
}
clif_displaymessage(fd, msg_table[182]); // Pet friendly value changed!
@@ -3908,6 +4111,7 @@ int atcommand_pethungry(
const char* command, const char* message)
{
int hungry;
+ nullpo_retr(-1, sd);
if (!message || !*message || (hungry = atoi(message)) < 0) {
clif_displaymessage(fd, "Please, enter a valid number (usage: @pethungry <0-100>).");
@@ -3944,6 +4148,7 @@ int atcommand_petrename(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
if (sd->status.pet_id > 0 && sd->pd) {
if (sd->pet.rename_flag != 0) {
sd->pet.rename_flag = 0;
@@ -3971,24 +4176,22 @@ atcommand_recall(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
- char output[200];
struct map_session_data *pl_sd = NULL;
-
+
nullpo_retr(-1, sd);
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @recall <char name>).");
return -1;
}
-
- memset(character, '\0', sizeof character);
- if(sscanf(message, "%99[^\n]", character) < 1)
+
+ memset(atcmd_player_name, '\0', sizeof atcmd_player_name);
+ if(sscanf(message, "%99[^\n]", atcmd_player_name) < 1)
return -1;
- if(strncmp(sd->status.name,character,24)==0)
+ if(strncmp(sd->status.name,atcmd_player_name,24)==0)
return -1;
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can recall only lower or same level
if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
clif_displaymessage(fd, "You are not authorised to warp somenone to your actual map.");
@@ -3999,8 +4202,8 @@ atcommand_recall(
return -1;
}
pc_setpos(pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2);
- sprintf(output, msg_table[46], character); // %s recalled!
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[46], atcmd_player_name); // %s recalled!
+ clif_displaymessage(fd, atcmd_output);
} else {
clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
return -1;
@@ -4021,23 +4224,23 @@ int atcommand_revive(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
struct map_session_data *pl_sd;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @revive <char name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
- if (pc_isdead(sd)) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
+ if (pc_isdead(pl_sd)) {
pl_sd->status.hp = pl_sd->status.max_hp;
clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1);
pc_setstand(pl_sd);
if (battle_config.pc_invincible_time > 0)
- pc_setinvincibletimer(sd, battle_config.pc_invincible_time);
+ pc_setinvincibletimer(pl_sd, battle_config.pc_invincible_time);
clif_updatestatus(pl_sd, SP_HP);
clif_updatestatus(pl_sd, SP_SP);
clif_resurrection(&pl_sd->bl, 1);
@@ -4061,24 +4264,24 @@ int atcommand_char_change_sex(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @charchangesex <name>).");
return -1;
}
// check player name
- if (strlen(character) < 4) {
+ if (strlen(atcmd_player_name) < 4) {
clif_displaymessage(fd, msg_table[86]); // Sorry, but a player name have at least 4 characters.
return -1;
- } else if (strlen(character) > 23) {
+ } else if (strlen(atcmd_player_name) > 23) {
clif_displaymessage(fd, msg_table[87]); // Sorry, but a player name have 23 characters maximum.
return -1;
} else {
- chrif_char_ask_name(sd->status.account_id, character, 5, 0, 0, 0, 0, 0, 0); // type: 5 - changesex
+ chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 5, 0, 0, 0, 0, 0, 0); // type: 5 - changesex
clif_displaymessage(fd, msg_table[88]); // Character name sends to char-server to ask it.
}
@@ -4094,24 +4297,24 @@ int atcommand_char_block(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @charblock/@block <name>).");
return -1;
}
// check player name
- if (strlen(character) < 4) {
+ if (strlen(atcmd_player_name) < 4) {
clif_displaymessage(fd, msg_table[86]); // Sorry, but a player name have at least 4 characters.
return -1;
- } else if (strlen(character) > 23) {
+ } else if (strlen(atcmd_player_name) > 23) {
clif_displaymessage(fd, msg_table[87]); // Sorry, but a player name have 23 characters maximum.
return -1;
} else {
- chrif_char_ask_name(sd->status.account_id, character, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block
+ chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block
clif_displaymessage(fd, msg_table[88]); // Character name sends to char-server to ask it.
}
@@ -4138,22 +4341,21 @@ int atcommand_char_ban(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char modif[100], character[100];
char * modif_p;
int year, month, day, hour, minute, second, value;
+ nullpo_retr(-1, sd);
- memset(modif, '\0', sizeof(modif));
- memset(character, '\0', sizeof(character));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%s %99[^\n]", modif, character) < 2) {
+ if (!message || !*message || sscanf(message, "%s %99[^\n]", atcmd_output, atcmd_player_name) < 2) {
clif_displaymessage(fd, "Please, enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <name>).");
return -1;
}
- modif[sizeof(modif)-1] = '\0';
- character[sizeof(character)-1] = '\0';
+ atcmd_output[sizeof(atcmd_output)-1] = '\0';
- modif_p = modif;
+ modif_p = atcmd_output;
year = month = day = hour = minute = second = 0;
while (modif_p[0] != '\0') {
value = atoi(modif_p);
@@ -4193,14 +4395,14 @@ int atcommand_char_ban(
}
// check player name
- if (strlen(character) < 4) {
+ if (strlen(atcmd_player_name) < 4) {
clif_displaymessage(fd, msg_table[86]); // Sorry, but a player name have at least 4 characters.
return -1;
- } else if (strlen(character) > 23) {
+ } else if (strlen(atcmd_player_name) > 23) {
clif_displaymessage(fd, msg_table[87]); // Sorry, but a player name have 23 characters maximum.
return -1;
} else {
- chrif_char_ask_name(sd->status.account_id, character, 2, year, month, day, hour, minute, second); // type: 2 - ban
+ chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 2, year, month, day, hour, minute, second); // type: 2 - ban
clif_displaymessage(fd, msg_table[88]); // Character name sends to char-server to ask it.
}
@@ -4215,25 +4417,25 @@ int atcommand_char_unblock(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @charunblock <player_name>).");
return -1;
}
// check player name
- if (strlen(character) < 4) {
+ if (strlen(atcmd_player_name) < 4) {
clif_displaymessage(fd, msg_table[86]); // Sorry, but a player name have at least 4 characters.
return -1;
- } else if (strlen(character) > 23) {
+ } else if (strlen(atcmd_player_name) > 23) {
clif_displaymessage(fd, msg_table[87]); // Sorry, but a player name have 23 characters maximum.
return -1;
} else {
// send answer to login server via char-server
- chrif_char_ask_name(sd->status.account_id, character, 3, 0, 0, 0, 0, 0, 0); // type: 3 - unblock
+ chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 3, 0, 0, 0, 0, 0, 0); // type: 3 - unblock
clif_displaymessage(fd, msg_table[88]); // Character name sends to char-server to ask it.
}
@@ -4248,25 +4450,25 @@ int atcommand_char_unban(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @charunban <player_name>).");
return -1;
}
// check player name
- if (strlen(character) < 4) {
+ if (strlen(atcmd_player_name) < 4) {
clif_displaymessage(fd, msg_table[86]); // Sorry, but a player name have at least 4 characters.
return -1;
- } else if (strlen(character) > 23) {
+ } else if (strlen(atcmd_player_name) > 23) {
clif_displaymessage(fd, msg_table[87]); // Sorry, but a player name have 23 characters maximum.
return -1;
} else {
// send answer to login server via char-server
- chrif_char_ask_name(sd->status.account_id, character, 4, 0, 0, 0, 0, 0, 0); // type: 4 - unban
+ chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 4, 0, 0, 0, 0, 0, 0); // type: 4 - unban
clif_displaymessage(fd, msg_table[88]); // Character name sends to char-server to ask it.
}
@@ -4283,11 +4485,12 @@ int atcommand_night(
{
struct map_session_data *pl_sd;
int i;
+ nullpo_retr(-1, sd);
if (night_flag != 1) {
night_flag = 1; // 0=day, 1=night [Yor]
for(i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && !map[sd->bl.m].flag.indoors) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && !map[sd->bl.m].flag.indoors) {
//pl_sd->opt2 |= STATE_BLIND;
//clif_changeoption(&pl_sd->bl);
if (battle_config.night_darkness_level > 0)
@@ -4318,13 +4521,18 @@ int atcommand_day(
{
struct map_session_data *pl_sd;
int i;
+ nullpo_retr(-1, sd);
if (night_flag != 0) {
night_flag = 0; // 0=day, 1=night [Yor]
for(i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
- pl_sd->opt2 &= ~STATE_BLIND;
- clif_changeoption(&pl_sd->bl);
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
+ if (battle_config.night_darkness_level > 0)
+ clif_refresh (pl_sd);
+ else {
+ pl_sd->opt2 &= ~STATE_BLIND;
+ clif_changeoption(&pl_sd->bl);
+ }
clif_displaymessage(pl_sd->fd, msg_table[60]); // Day has arrived.
}
}
@@ -4346,9 +4554,10 @@ int atcommand_doom(
{
struct map_session_data *pl_sd;
int i;
+ nullpo_retr(-1, sd);
clif_specialeffect(&sd->bl,450,2);
for(i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && i != fd &&
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && i != fd &&
pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can doom only lower or same gm level
pc_damage(NULL, pl_sd, pl_sd->status.hp + 1);
clif_displaymessage(pl_sd->fd, msg_table[61]); // The holy messenger has given judgement.
@@ -4369,9 +4578,10 @@ int atcommand_doommap(
{
struct map_session_data *pl_sd;
int i;
+ nullpo_retr(-1, sd);
clif_specialeffect(&sd->bl,450,3);
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && i != fd && sd->bl.m == pl_sd->bl.m &&
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && i != fd && sd->bl.m == pl_sd->bl.m &&
pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can doom only lower or same gm level
pc_damage(NULL, pl_sd, pl_sd->status.hp + 1);
// clif_specialeffect(&pl_sd->bl,450,1);
@@ -4412,10 +4622,11 @@ int atcommand_raise(
const char* command, const char* message)
{
int i;
+ nullpo_retr(-1, sd);
for (i = 0; i < fd_max; i++) {
if (session[i])
- atcommand_raise_sub(session[i]->session_data);
+ atcommand_raise_sub((struct map_session_data *) session[i]->session_data);
}
clif_displaymessage(fd, msg_table[64]); // Mercy has been granted.
@@ -4433,8 +4644,10 @@ int atcommand_raisemap(
struct map_session_data *pl_sd;
int i;
+ nullpo_retr(-1, sd);
+
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && sd->bl.m == pl_sd->bl.m)
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && sd->bl.m == pl_sd->bl.m)
atcommand_raise_sub(pl_sd);
}
clif_displaymessage(fd, msg_table[64]); // Mercy has been granted.
@@ -4451,17 +4664,17 @@ int atcommand_character_baselevel(
const char* command, const char* message)
{
struct map_session_data *pl_sd;
- char character[100];
int level = 0, i;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%d %99[^\n]", &level, character) < 2 || level == 0) {
+ if (!message || !*message || sscanf(message, "%d %99[^\n]", &level, atcmd_player_name) < 2 || level == 0) {
clif_displaymessage(fd, "Please, enter a level adjustement and a player name (usage: @charbaselvl <#> <nickname>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can change base level only lower or same gm level
if (level > 0) {
@@ -4469,7 +4682,7 @@ int atcommand_character_baselevel(
clif_displaymessage(fd, msg_table[91]); // Character's base level can't go any higher.
return 0;
} // End Addition
- if (level > battle_config.maximum_level || level > (battle_config.maximum_level - pl_sd->status.base_level)) // fix positiv overflow
+ if ((unsigned int)level > battle_config.maximum_level || (unsigned int)level > (battle_config.maximum_level - pl_sd->status.base_level)) // fix positiv overflow
level = battle_config.maximum_level - pl_sd->status.base_level;
for (i = 1; i <= level; i++)
pl_sd->status.status_point += (pl_sd->status.base_level + i + 14) / 5;
@@ -4477,7 +4690,7 @@ int atcommand_character_baselevel(
clif_updatestatus(pl_sd, SP_BASELEVEL);
clif_updatestatus(pl_sd, SP_NEXTBASEEXP);
clif_updatestatus(pl_sd, SP_STATUSPOINT);
- pc_calcstatus(pl_sd, 0);
+ status_calc_pc(pl_sd, 0);
pc_heal(pl_sd, pl_sd->status.max_hp, pl_sd->status.max_sp);
clif_misceffect(&pl_sd->bl, 0);
clif_displaymessage(fd, msg_table[65]); // Character's base level raised.
@@ -4486,7 +4699,7 @@ int atcommand_character_baselevel(
clif_displaymessage(fd, msg_table[193]); // Character's base level can't go any lower.
return -1;
}
- if (level < -battle_config.maximum_level || level < (1 - pl_sd->status.base_level)) // fix negativ overflow
+ if (level < -(int)battle_config.maximum_level || level < (1 - (int)pl_sd->status.base_level)) // fix negativ overflow
level = 1 - pl_sd->status.base_level;
if (pl_sd->status.status_point > 0) {
for (i = 0; i > level; i--)
@@ -4498,7 +4711,7 @@ int atcommand_character_baselevel(
pl_sd->status.base_level += level;
clif_updatestatus(pl_sd, SP_BASELEVEL);
clif_updatestatus(pl_sd, SP_NEXTBASEEXP);
- pc_calcstatus(pl_sd, 0);
+ status_calc_pc(pl_sd, 0);
clif_displaymessage(fd, msg_table[66]); // Character's base level lowered.
}
} else {
@@ -4522,25 +4735,28 @@ int atcommand_character_joblevel(
const char* command, const char* message)
{
struct map_session_data *pl_sd;
- char character[100];
- int max_level = 50, level = 0;
+ unsigned int max_level = 50;
+ int level = 0;
//転生や養子の場合の元の職業を算出する
struct pc_base_job pl_s_class;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%d %99[^\n]", &level, character) < 2 || level == 0) {
+ if (!message || !*message || sscanf(message, "%d %99[^\n]", &level, atcmd_player_name) < 2 || level == 0) {
clif_displaymessage(fd, "Please, enter a level adjustement and a player name (usage: @charjlvl <#> <nickname>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
- pl_s_class = pc_calc_base_job(pl_sd->status.class);
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
+ pl_s_class = pc_calc_base_job(pl_sd->status.class_);
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can change job level only lower or same gm level
if (pl_s_class.job == 0)
max_level -= 40;
- if ((pl_s_class.job == 23) || (pl_s_class.upper == 1 && pl_s_class.type == 2)) //スパノビと転生職はJobレベルの最高が70
- // To-do: super novices has max level 99 - celest
+ // super novices can go up to 99 [celest]
+ else if (pl_s_class.job == 23)
+ max_level += 49;
+ else if (pl_sd->status.class_ > 4007 && pl_sd->status.class_ < 4023)
max_level += 20;
if (level > 0) {
@@ -4555,7 +4771,7 @@ int atcommand_character_joblevel(
clif_updatestatus(pl_sd, SP_NEXTJOBEXP);
pl_sd->status.skill_point += level;
clif_updatestatus(pl_sd, SP_SKILLPOINT);
- pc_calcstatus(pl_sd, 0);
+ status_calc_pc(pl_sd, 0);
clif_misceffect(&pl_sd->bl, 1);
clif_displaymessage(fd, msg_table[68]); // character's job level raised.
} else {
@@ -4574,7 +4790,7 @@ int atcommand_character_joblevel(
pl_sd->status.skill_point = 0;
clif_updatestatus(pl_sd, SP_SKILLPOINT);
} // to add: remove status points from skills
- pc_calcstatus(pl_sd, 0);
+ status_calc_pc(pl_sd, 0);
clif_displaymessage(fd, msg_table[69]); // Character's job level lowered.
}
} else {
@@ -4598,16 +4814,16 @@ int atcommand_kick(
const char* command, const char* message)
{
struct map_session_data *pl_sd;
- char character[100];
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @kick <charname>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_isGM(sd) >= pc_isGM(pl_sd)) // you can kick only lower or same gm level
clif_GM_kick(sd, pl_sd, 1);
else {
@@ -4632,9 +4848,10 @@ int atcommand_kickall(
{
struct map_session_data *pl_sd;
int i;
+ nullpo_retr(-1, sd);
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth &&
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth &&
pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kick only lower or same gm level
if (sd->status.account_id != pl_sd->status.account_id)
clif_GM_kick(sd, pl_sd, 0);
@@ -4654,6 +4871,7 @@ int atcommand_allskill(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
pc_allskillup(sd); // all skills
sd->status.skill_point = 0; // 0 skill points
clif_updatestatus(sd, SP_SKILLPOINT); // update
@@ -4671,6 +4889,7 @@ int atcommand_questskill(
const char* command, const char* message)
{
int skill_id;
+ nullpo_retr(-1, sd);
if (!message || !*message || (skill_id = atoi(message)) < 0) {
clif_displaymessage(fd, "Please, enter a quest skill number (usage: @questskill <#:0+>).");
@@ -4706,20 +4925,20 @@ int atcommand_charquestskill(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
struct map_session_data *pl_sd;
int skill_id = 0;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%d %99[^\n]", &skill_id, character) < 2 || skill_id < 0) {
+ if (!message || !*message || sscanf(message, "%d %99[^\n]", &skill_id, atcmd_player_name) < 2 || skill_id < 0) {
clif_displaymessage(fd, "Please, enter a quest skill number and a player name (usage: @charquestskill <#:0+> <char_name>).");
return -1;
}
if (skill_id >= 0 && skill_id < MAX_SKILL_DB) {
if (skill_get_inf2(skill_id) & 0x01) {
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_checkskill(pl_sd, skill_id) == 0) {
pc_skill(pl_sd, skill_id, 1, 0);
clif_displaymessage(fd, msg_table[199]); // This player has learned the skill.
@@ -4752,6 +4971,7 @@ int atcommand_lostskill(
const char* command, const char* message)
{
int skill_id;
+ nullpo_retr(-1, sd);
if (!message || !*message || (skill_id = atoi(message)) < 0) {
clif_displaymessage(fd, "Please, enter a quest skill number (usage: @lostskill <#:0+>).");
@@ -4789,20 +5009,20 @@ int atcommand_charlostskill(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
struct map_session_data *pl_sd;
int skill_id = 0;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%d %99[^\n]", &skill_id, character) < 2 || skill_id < 0) {
+ if (!message || !*message || sscanf(message, "%d %99[^\n]", &skill_id, atcmd_player_name) < 2 || skill_id < 0) {
clif_displaymessage(fd, "Please, enter a quest skill number and a player name (usage: @charlostskill <#:0+> <char_name>).");
return -1;
}
if (skill_id >= 0 && skill_id < MAX_SKILL) {
if (skill_get_inf2(skill_id) & 0x01) {
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_checkskill(pl_sd, skill_id) > 0) {
pl_sd->status.skill[skill_id].lv = 0;
pl_sd->status.skill[skill_id].flag = 0;
@@ -4837,6 +5057,7 @@ int atcommand_spiritball(
const char* command, const char* message)
{
int number;
+ nullpo_retr(-1, sd);
if (!message || !*message || (number = atoi(message)) < 0) {
clif_displaymessage(fd, "Please, enter a spirit ball number (usage: @spiritball <number: 0-1000>).");
@@ -4877,6 +5098,7 @@ int atcommand_party(
const char* command, const char* message)
{
char party[100];
+ nullpo_retr(-1, sd);
memset(party, '\0', sizeof(party));
@@ -4885,7 +5107,7 @@ int atcommand_party(
return -1;
}
- party_create(sd, party);
+ party_create(sd, party, 0, 0);
return 0;
}
@@ -4900,6 +5122,7 @@ int atcommand_guild(
{
char guild[100];
int prev;
+ nullpo_retr(-1, sd);
memset(guild, '\0', sizeof(guild));
@@ -4924,6 +5147,7 @@ int atcommand_agitstart(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
if (agit_flag == 1) {
clif_displaymessage(fd, msg_table[73]); // Already it has started siege warfare.
return -1;
@@ -4944,6 +5168,7 @@ int atcommand_agitend(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
if (agit_flag == 0) {
clif_displaymessage(fd, msg_table[75]); // Siege warfare hasn't started yet.
return -1;
@@ -4966,14 +5191,17 @@ int atcommand_mapexit(
{
struct map_session_data *pl_sd;
int i;
+ nullpo_retr(-1, sd);
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
if (sd->status.account_id != pl_sd->status.account_id)
clif_GM_kick(sd, pl_sd, 0);
}
}
clif_GM_kick(sd, sd, 0);
+
+ flush_fifos();
runflag = 0;
@@ -4989,30 +5217,30 @@ int atcommand_idsearch(
const char* command, const char* message)
{
char item_name[100];
- char output[200];
- int i, match;
+ unsigned int i, match;
struct item_data *item;
+ nullpo_retr(-1, sd);
memset(item_name, '\0', sizeof(item_name));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%99s", item_name) < 0) {
clif_displaymessage(fd, "Please, enter a part of item name (usage: @idsearch <part_of_item_name>).");
return -1;
}
- sprintf(output, msg_table[77], item_name); // The reference result of '%s' (name: id):
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[77], item_name); // The reference result of '%s' (name: id):
+ clif_displaymessage(fd, atcmd_output);
match = 0;
for(i = 0; i < 20000; i++) {
if ((item = itemdb_exists(i)) != NULL && strstr(item->jname, item_name) != NULL) {
match++;
- sprintf(output, msg_table[78], item->jname, item->nameid); // %s: %d
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[78], item->jname, item->nameid); // %s: %d
+ clif_displaymessage(fd, atcmd_output);
}
}
- sprintf(output, msg_table[79], match); // It is %d affair above.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[79], match); // It is %d affair above.
+ clif_displaymessage(fd, atcmd_output);
return 0;
}
@@ -5025,23 +5253,22 @@ int atcommand_charskreset(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
- char output[200];
struct map_session_data *pl_sd;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @charskreset <charname>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can reset skill points only lower or same gm level
pc_resetskill(pl_sd);
- sprintf(output, msg_table[206], character); // '%s' skill points reseted!
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[206], atcmd_player_name); // '%s' skill points reseted!
+ clif_displaymessage(fd, atcmd_output);
} else {
clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
return -1;
@@ -5062,23 +5289,22 @@ int atcommand_charstreset(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
- char output[200];
struct map_session_data *pl_sd;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @charstreset <charname>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can reset stats points only lower or same gm level
pc_resetstate(pl_sd);
- sprintf(output, msg_table[207], character); // '%s' stats points reseted!
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[207], atcmd_player_name); // '%s' stats points reseted!
+ clif_displaymessage(fd, atcmd_output);
} else {
clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
return -1;
@@ -5101,27 +5327,26 @@ int atcommand_charmodel(
{
int hair_style = 0, hair_color = 0, cloth_color = 0;
struct map_session_data *pl_sd;
- char character[100];
- char output[200];
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
- if (!message || !*message || sscanf(message, "%d %d %d %99[^\n]", &hair_style, &hair_color, &cloth_color, character) < 4 || hair_style < 0 || hair_color < 0 || cloth_color < 0) {
- sprintf(output, "Please, enter a valid model and a player name (usage: @charmodel <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d> <name>).",
+ if (!message || !*message || sscanf(message, "%d %d %d %99[^\n]", &hair_style, &hair_color, &cloth_color, atcmd_player_name) < 4 || hair_style < 0 || hair_color < 0 || cloth_color < 0) {
+ sprintf(atcmd_output, "Please, enter a valid model and a player name (usage: @charmodel <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d> <name>).",
MIN_HAIR_STYLE, MAX_HAIR_STYLE, MIN_HAIR_COLOR, MAX_HAIR_COLOR, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
- clif_displaymessage(fd, output);
+ clif_displaymessage(fd, atcmd_output);
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE &&
hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR &&
cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) {
if (cloth_color != 0 &&
pl_sd->status.sex == 1 &&
- (pl_sd->status.class == 12 || pl_sd->status.class == 17)) {
+ (pl_sd->status.class_ == 12 || pl_sd->status.class_ == 17)) {
clif_displaymessage(fd, msg_table[35]); // You can't use this command with this class.
return -1;
} else {
@@ -5151,18 +5376,18 @@ int atcommand_charskpoint(
const char* command, const char* message)
{
struct map_session_data *pl_sd;
- char character[100];
int new_skill_point;
int point = 0;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%d %99[^\n]", &point, character) < 2 || point == 0) {
+ if (!message || !*message || sscanf(message, "%d %99[^\n]", &point, atcmd_player_name) < 2 || point == 0) {
clif_displaymessage(fd, "Please, enter a number and a player name (usage: @charskpoint <amount> <name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
new_skill_point = (int)pl_sd->status.skill_point + point;
if (point > 0 && (point > 0x7FFF || new_skill_point > 0x7FFF)) // fix positiv overflow
new_skill_point = 0x7FFF;
@@ -5196,18 +5421,18 @@ int atcommand_charstpoint(
const char* command, const char* message)
{
struct map_session_data *pl_sd;
- char character[100];
int new_status_point;
int point = 0;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%d %99[^\n]", &point, character) < 2 || point == 0) {
+ if (!message || !*message || sscanf(message, "%d %99[^\n]", &point, atcmd_player_name) < 2 || point == 0) {
clif_displaymessage(fd, "Please, enter a number and a player name (usage: @charstpoint <amount> <name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
new_status_point = (int)pl_sd->status.status_point + point;
if (point > 0 && (point > 0x7FFF || new_status_point > 0x7FFF)) // fix positiv overflow
new_status_point = 0x7FFF;
@@ -5233,50 +5458,6 @@ int atcommand_charstpoint(
}
/*==========================================
- * Character Zeny Point (Rewritten by [Yor])
- *------------------------------------------
- */
-int atcommand_charzeny(
- const int fd, struct map_session_data* sd,
- const char* command, const char* message)
-{
- struct map_session_data *pl_sd;
- char character[100];
- int zeny = 0, new_zeny;
-
- memset(character, '\0', sizeof(character));
-
- if (!message || !*message || sscanf(message, "%d %99[^\n]", &zeny, character) < 2 || zeny == 0) {
- clif_displaymessage(fd, "Please, enter a number and a player name (usage: @charzeny <zeny> <name>).");
- return -1;
- }
-
- if ((pl_sd = map_nick2sd(character)) != NULL) {
- new_zeny = pl_sd->status.zeny + zeny;
- if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY)) // fix positiv overflow
- new_zeny = MAX_ZENY;
- else if (zeny < 0 && (zeny < -MAX_ZENY || new_zeny < 0)) // fix negativ overflow
- new_zeny = 0;
- if (new_zeny != pl_sd->status.zeny) {
- pl_sd->status.zeny = new_zeny;
- clif_updatestatus(pl_sd, SP_ZENY);
- clif_displaymessage(fd, msg_table[211]); // Character's number of zenys changed!
- } else {
- if (zeny < 0)
- clif_displaymessage(fd, msg_table[41]); // Impossible to decrease the number/value.
- else
- clif_displaymessage(fd, msg_table[149]); // Impossible to increase the number/value.
- return -1;
- }
- } else {
- clif_displaymessage(fd, msg_table[3]); // Character not found.
- return -1;
- }
-
- return 0;
-}
-
-/*==========================================
* Recall All Characters Online To Your Location
*------------------------------------------
*/
@@ -5287,9 +5468,9 @@ int atcommand_recallall(
struct map_session_data *pl_sd;
int i;
int count;
- char output[200];
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
clif_displaymessage(fd, "You are not authorised to warp somenone to your actual map.");
@@ -5298,7 +5479,7 @@ int atcommand_recallall(
count = 0;
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && sd->status.account_id != pl_sd->status.account_id &&
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && sd->status.account_id != pl_sd->status.account_id &&
pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can recall only lower or same level
if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd))
count++;
@@ -5309,8 +5490,8 @@ int atcommand_recallall(
clif_displaymessage(fd, msg_table[92]); // All characters recalled!
if (count) {
- sprintf(output, "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", count);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", count);
+ clif_displaymessage(fd, atcmd_output);
}
return 0;
@@ -5327,12 +5508,12 @@ int atcommand_guildrecall(
struct map_session_data *pl_sd;
int i;
char guild_name[100];
- char output[200];
struct guild *g;
int count;
+ nullpo_retr(-1, sd);
memset(guild_name, '\0', sizeof(guild_name));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%99[^\n]", guild_name) < 1) {
clif_displaymessage(fd, "Please, enter a guild name/id (usage: @guildrecall <guild_name/id>).");
@@ -5348,7 +5529,7 @@ int atcommand_guildrecall(
(g = guild_search(atoi(message))) != NULL) {
count = 0;
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth &&
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth &&
sd->status.account_id != pl_sd->status.account_id &&
pl_sd->status.guild_id == g->guild_id) {
if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd))
@@ -5357,11 +5538,11 @@ int atcommand_guildrecall(
pc_setpos(pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2);
}
}
- sprintf(output, msg_table[93], g->name); // All online characters of the %s guild are near you.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[93], g->name); // All online characters of the %s guild are near you.
+ clif_displaymessage(fd, atcmd_output);
if (count) {
- sprintf(output, "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", count);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", count);
+ clif_displaymessage(fd, atcmd_output);
}
} else {
clif_displaymessage(fd, msg_table[94]); // Incorrect name/ID, or no one from the guild is online.
@@ -5382,12 +5563,12 @@ int atcommand_partyrecall(
int i;
struct map_session_data *pl_sd;
char party_name[100];
- char output[200];
struct party *p;
int count;
+ nullpo_retr(-1, sd);
memset(party_name, '\0', sizeof(party_name));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%99[^\n]", party_name) < 1) {
clif_displaymessage(fd, "Please, enter a party name/id (usage: @partyrecall <party_name/id>).");
@@ -5403,7 +5584,7 @@ int atcommand_partyrecall(
(p = party_search(atoi(message))) != NULL) {
count = 0;
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth &&
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth &&
sd->status.account_id != pl_sd->status.account_id &&
pl_sd->status.party_id == p->party_id) {
if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd))
@@ -5412,11 +5593,11 @@ int atcommand_partyrecall(
pc_setpos(pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2);
}
}
- sprintf(output, msg_table[95], p->name); // All online characters of the %s party are near you.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[95], p->name); // All online characters of the %s party are near you.
+ clif_displaymessage(fd, atcmd_output);
if (count) {
- sprintf(output, "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", count);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.", count);
+ clif_displaymessage(fd, atcmd_output);
}
} else {
clif_displaymessage(fd, msg_table[96]); // Incorrect name or ID, or no one from the party is online.
@@ -5434,6 +5615,7 @@ int atcommand_reloaditemdb(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
itemdb_reload();
clif_displaymessage(fd, msg_table[97]); // Item database reloaded.
@@ -5448,7 +5630,9 @@ int atcommand_reloadmobdb(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
mob_reload();
+ read_petdb();
clif_displaymessage(fd, msg_table[98]); // Monster database reloaded.
return 0;
@@ -5462,6 +5646,7 @@ int atcommand_reloadskilldb(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
skill_reload();
clif_displaymessage(fd, msg_table[99]); // Skill database reloaded.
@@ -5469,28 +5654,92 @@ int atcommand_reloadskilldb(
}
/*==========================================
+ * @reloadatcommand
+ * atcommand_athena.conf のリロード
+ *------------------------------------------
+ */
+int
+atcommand_reloadatcommand(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ atcommand_config_read(ATCOMMAND_CONF_FILENAME);
+ clif_displaymessage(fd, msg_table[254]);
+ return 0;
+}
+/*==========================================
+ * @reloadbattleconf
+ * battle_athena.conf のリロード
+ *------------------------------------------
+ */
+int
+atcommand_reloadbattleconf(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ battle_config_read(BATTLE_CONF_FILENAME);
+ clif_displaymessage(fd, msg_table[255]);
+ return 0;
+}
+/*==========================================
+ * @reloadstatusdb
+ * job_db1.txt job_db2.txt job_db2-2.txt
+ * refine_db.txt size_fix.txt
+ * のリロード
+ *------------------------------------------
+ */
+int
+atcommand_reloadstatusdb(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ status_readdb();
+ clif_displaymessage(fd, msg_table[256]);
+ return 0;
+}
+/*==========================================
+ * @reloadpcdb
+ * exp.txt skill_tree.txt attr_fix.txt
+ * のリロード
+ *------------------------------------------
+ */
+int
+atcommand_reloadpcdb(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ pc_readdb();
+ clif_displaymessage(fd, msg_table[257]);
+ return 0;
+}
+
+/*==========================================
*
*------------------------------------------
*/
-#ifndef TXT_ONLY
-int atcommand_rehash(
-#else /* TXT_ONLY */
+void rehash(void)
+{
+ int map_id;
+
+ for (map_id = 0; map_id < map_num; map_id++) {
+ map_foreachinarea(cleanup_sub, map_id, 0, 0, map[map_id].xs, map[map_id].ys, BL_MOB);
+ map_foreachinarea(cleanup_sub, map_id, 0, 0, map[map_id].xs, map[map_id].ys, BL_NPC);
+ }
+}
int atcommand_reloadscript(
-#endif /* TXT_ONLY */
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
-#ifndef TXT_ONLY
- atcommand_broadcast( fd, sd, "@broadcast", "eAthena SQL Server is Rehashing..." );
+ nullpo_retr(-1, sd);
+ atcommand_broadcast( fd, sd, "@broadcast", "eAthena Server is Rehashing..." );
atcommand_broadcast( fd, sd, "@broadcast", "You will feel a bit of lag at this point !" );
-
- rehash( fd, sd );
+
+ rehash();
atcommand_broadcast( fd, sd, "@broadcast", "Reloading NPCs..." );
-#endif /* not TXT_ONLY */
- do_init_npc();
+ //do_init_npc();
do_init_script();
-
+ npc_reload();
npc_event_do_oninit();
clif_displaymessage(fd, msg_table[100]); // Scripts reloaded.
@@ -5506,6 +5755,7 @@ int atcommand_reloadgmdb( // by [Yor]
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
chrif_reloadGMdb();
clif_displaymessage(fd, msg_table[101]); // Login-server asked to reload GM accounts and their level.
@@ -5529,71 +5779,71 @@ int atcommand_mapinfo(
struct map_session_data *pl_sd;
struct npc_data *nd = NULL;
struct chat_data *cd = NULL;
- char output[200], map_name[100];
char direction[12];
int m_id, i, chat_num, list = 0;
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
- memset(map_name, '\0', sizeof(map_name));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
memset(direction, '\0', sizeof(direction));
- sscanf(message, "%d %99[^\n]", &list, map_name);
+ sscanf(message, "%d %99[^\n]", &list, atcmd_player_name);
if (list < 0 || list > 3) {
clif_displaymessage(fd, "Please, enter at least a valid list number (usage: @mapinfo <0-3> [map]).");
return -1;
}
- if (map_name[0] == '\0')
- strcpy(map_name, sd->mapname);
- if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat)
- strcat(map_name, ".gat");
+ if (atcmd_player_name[0] == '\0')
+ strcpy(atcmd_player_name, sd->mapname);
+ if (strstr(atcmd_player_name, ".gat") == NULL && strstr(atcmd_player_name, ".afm") == NULL && strlen(atcmd_player_name) < 13) // 16 - 4 (.gat)
+ strcat(atcmd_player_name, ".gat");
- if ((m_id = map_mapname2mapid(map_name)) < 0) {
+ if ((m_id = map_mapname2mapid(atcmd_player_name)) < 0) {
clif_displaymessage(fd, msg_table[1]); // Map not found.
return -1;
}
clif_displaymessage(fd, "------ Map Info ------");
- sprintf(output, "Map Name: %s", map_name);
- clif_displaymessage(fd, output);
- sprintf(output, "Players In Map: %d", map[m_id].users);
- clif_displaymessage(fd, output);
- sprintf(output, "NPCs In Map: %d", map[m_id].npc_num);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Map Name: %s", atcmd_player_name);
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, "Players In Map: %d", map[m_id].users);
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, "NPCs In Map: %d", map[m_id].npc_num);
+ clif_displaymessage(fd, atcmd_output);
chat_num = 0;
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth &&
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth &&
(cd = (struct chat_data*)map_id2bl(pl_sd->chatID))) {
chat_num++;
}
}
- sprintf(output, "Chats In Map: %d", chat_num);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "Chats In Map: %d", chat_num);
+ clif_displaymessage(fd, atcmd_output);
clif_displaymessage(fd, "------ Map Flags ------");
- sprintf(output, "Player vs Player: %s | No Guild: %s | No Party: %s",
+ sprintf(atcmd_output, "Player vs Player: %s | No Guild: %s | No Party: %s",
(map[m_id].flag.pvp) ? "True" : "False",
(map[m_id].flag.pvp_noguild) ? "True" : "False",
(map[m_id].flag.pvp_noparty) ? "True" : "False");
- clif_displaymessage(fd, output);
- sprintf(output, "Guild vs Guild: %s | No Party: %s", (map[m_id].flag.gvg) ? "True" : "False", (map[m_id].flag.gvg_noparty) ? "True" : "False");
- clif_displaymessage(fd, output);
- sprintf(output, "No Dead Branch: %s", (map[m_id].flag.nobranch) ? "True" : "False");
- clif_displaymessage(fd, output);
- sprintf(output, "No Memo: %s", (map[m_id].flag.nomemo) ? "True" : "False");
- clif_displaymessage(fd, output);
- sprintf(output, "No Penalty: %s", (map[m_id].flag.nopenalty) ? "True" : "False");
- clif_displaymessage(fd, output);
- sprintf(output, "No Return: %s", (map[m_id].flag.noreturn) ? "True" : "False");
- clif_displaymessage(fd, output);
- sprintf(output, "No Save: %s", (map[m_id].flag.nosave) ? "True" : "False");
- clif_displaymessage(fd, output);
- sprintf(output, "No Teleport: %s", (map[m_id].flag.noteleport) ? "True" : "False");
- clif_displaymessage(fd, output);
- sprintf(output, "No Monster Teleport: %s", (map[m_id].flag.monster_noteleport) ? "True" : "False");
- clif_displaymessage(fd, output);
- sprintf(output, "No Zeny Penalty: %s", (map[m_id].flag.nozenypenalty) ? "True" : "False");
- clif_displaymessage(fd, output);
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, "Guild vs Guild: %s | No Party: %s", (map[m_id].flag.gvg) ? "True" : "False", (map[m_id].flag.gvg_noparty) ? "True" : "False");
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, "No Dead Branch: %s", (map[m_id].flag.nobranch) ? "True" : "False");
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, "No Memo: %s", (map[m_id].flag.nomemo) ? "True" : "False");
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, "No Penalty: %s", (map[m_id].flag.nopenalty) ? "True" : "False");
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, "No Return: %s", (map[m_id].flag.noreturn) ? "True" : "False");
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, "No Save: %s", (map[m_id].flag.nosave) ? "True" : "False");
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, "No Teleport: %s", (map[m_id].flag.noteleport) ? "True" : "False");
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, "No Monster Teleport: %s", (map[m_id].flag.monster_noteleport) ? "True" : "False");
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, "No Zeny Penalty: %s", (map[m_id].flag.nozenypenalty) ? "True" : "False");
+ clif_displaymessage(fd, atcmd_output);
switch (list) {
case 0:
@@ -5602,10 +5852,10 @@ int atcommand_mapinfo(
case 1:
clif_displaymessage(fd, "----- Players in Map -----");
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && strcmp(pl_sd->mapname, map_name) == 0) {
- sprintf(output, "Player '%s' (session #%d) | Location: %d,%d",
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && strcmp(pl_sd->mapname, atcmd_player_name) == 0) {
+ sprintf(atcmd_output, "Player '%s' (session #%d) | Location: %d,%d",
pl_sd->status.name, i, pl_sd->bl.x, pl_sd->bl.y);
- clif_displaymessage(fd, output);
+ clif_displaymessage(fd, atcmd_output);
}
}
break;
@@ -5625,24 +5875,24 @@ int atcommand_mapinfo(
case 9: strcpy(direction, "North"); break;
default: strcpy(direction, "Unknown"); break;
}
- sprintf(output, "NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d",
- ++i, nd->name, direction, nd->class, nd->bl.x, nd->bl.y);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d",
+ ++i, nd->name, direction, nd->class_, nd->bl.x, nd->bl.y);
+ clif_displaymessage(fd, atcmd_output);
}
break;
case 3:
clif_displaymessage(fd, "----- Chats in Map -----");
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth &&
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth &&
(cd = (struct chat_data*)map_id2bl(pl_sd->chatID)) &&
- strcmp(pl_sd->mapname, map_name) == 0 &&
+ strcmp(pl_sd->mapname, atcmd_player_name) == 0 &&
cd->usersd[0] == pl_sd) {
- sprintf(output, "Chat %d: %s | Player: %s | Location: %d %d",
+ sprintf(atcmd_output, "Chat %d: %s | Player: %s | Location: %d %d",
i, cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y);
- clif_displaymessage(fd, output);
- sprintf(output, " Users: %d/%d | Password: %s | Public: %s",
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, " Users: %d/%d | Password: %s | Public: %s",
cd->users, cd->limit, cd->pass, (cd->pub) ? "Yes" : "No");
- clif_displaymessage(fd, output);
+ clif_displaymessage(fd, atcmd_output);
}
}
break;
@@ -5663,21 +5913,22 @@ int atcommand_mount_peco(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
if (sd->disguise > 0) { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
clif_displaymessage(fd, msg_table[212]); // Cannot mount a Peco while in disguise.
return -1;
}
if (!pc_isriding(sd)) { // if actually no peco
- if (sd->status.class == 7 || sd->status.class == 14 || sd->status.class == 4008 || sd->status.class == 4015) {
- if (sd->status.class == 7)
- sd->status.class = sd->view_class = 13;
- else if (sd->status.class == 14)
- sd->status.class = sd->view_class = 21;
- else if (sd->status.class == 4008)
- sd->status.class = sd->view_class = 4014;
- else if (sd->status.class == 4015)
- sd->status.class = sd->view_class = 4022;
+ if (sd->status.class_ == 7 || sd->status.class_ == 14 || sd->status.class_ == 4008 || sd->status.class_ == 4015) {
+ if (sd->status.class_ == 7)
+ sd->status.class_ = sd->view_class = 13;
+ else if (sd->status.class_ == 14)
+ sd->status.class_ = sd->view_class = 21;
+ else if (sd->status.class_ == 4008)
+ sd->status.class_ = sd->view_class = 4014;
+ else if (sd->status.class_ == 4015)
+ sd->status.class_ = sd->view_class = 4022;
pc_setoption(sd, sd->status.option | 0x0020);
clif_displaymessage(fd, msg_table[102]); // Mounted Peco.
} else {
@@ -5685,14 +5936,14 @@ int atcommand_mount_peco(
return -1;
}
} else {
- if (sd->status.class == 13)
- sd->status.class = sd->view_class = 7;
- else if (sd->status.class == 21)
- sd->status.class = sd->view_class = 14;
- else if (sd->status.class == 4014)
- sd->status.class = sd->view_class = 4008;
- else if (sd->status.class == 4022)
- sd->status.class = sd->view_class = 4015;
+ if (sd->status.class_ == 13)
+ sd->status.class_ = sd->view_class = 7;
+ else if (sd->status.class_ == 21)
+ sd->status.class_ = sd->view_class = 14;
+ else if (sd->status.class_ == 4014)
+ sd->status.class_ = sd->view_class = 4008;
+ else if (sd->status.class_ == 4022)
+ sd->status.class_ = sd->view_class = 4015;
pc_setoption(sd, sd->status.option & ~0x0020);
clif_displaymessage(fd, msg_table[214]); // Unmounted Peco.
}
@@ -5708,32 +5959,32 @@ int atcommand_char_mount_peco(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
struct map_session_data *pl_sd;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @charmountpeco <char_name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pl_sd->disguise > 0) { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
clif_displaymessage(fd, msg_table[215]); // This player cannot mount a Peco while in disguise.
return -1;
}
if (!pc_isriding(pl_sd)) { // if actually no peco
- if (pl_sd->status.class == 7 || pl_sd->status.class == 14 || pl_sd->status.class == 4008 || pl_sd->status.class == 4015) {
- if (pl_sd->status.class == 7)
- pl_sd->status.class = pl_sd->view_class = 13;
- else if (pl_sd->status.class == 14)
- pl_sd->status.class = pl_sd->view_class = 21;
- else if (pl_sd->status.class == 4008)
- pl_sd->status.class = pl_sd->view_class = 4014;
- else if (pl_sd->status.class == 4015)
- pl_sd->status.class = pl_sd->view_class = 4022;
+ if (pl_sd->status.class_ == 7 || pl_sd->status.class_ == 14 || pl_sd->status.class_ == 4008 || pl_sd->status.class_ == 4015) {
+ if (pl_sd->status.class_ == 7)
+ pl_sd->status.class_ = pl_sd->view_class = 13;
+ else if (pl_sd->status.class_ == 14)
+ pl_sd->status.class_ = pl_sd->view_class = 21;
+ else if (pl_sd->status.class_ == 4008)
+ pl_sd->status.class_ = pl_sd->view_class = 4014;
+ else if (pl_sd->status.class_ == 4015)
+ pl_sd->status.class_ = pl_sd->view_class = 4022;
pc_setoption(pl_sd, pl_sd->status.option | 0x0020);
clif_displaymessage(fd, msg_table[216]); // Now, this player mounts a peco.
} else {
@@ -5741,14 +5992,14 @@ int atcommand_char_mount_peco(
return -1;
}
} else {
- if (pl_sd->status.class == 13)
- pl_sd->status.class = pl_sd->view_class = 7;
- else if (pl_sd->status.class == 21)
- pl_sd->status.class = pl_sd->view_class = 14;
- else if (pl_sd->status.class == 4014)
- pl_sd->status.class = pl_sd->view_class = 4008;
- else if (pl_sd->status.class == 4022)
- pl_sd->status.class = pl_sd->view_class = 4015;
+ if (pl_sd->status.class_ == 13)
+ pl_sd->status.class_ = pl_sd->view_class = 7;
+ else if (pl_sd->status.class_ == 21)
+ pl_sd->status.class_ = pl_sd->view_class = 14;
+ else if (pl_sd->status.class_ == 4014)
+ pl_sd->status.class_ = pl_sd->view_class = 4008;
+ else if (pl_sd->status.class_ == 4022)
+ pl_sd->status.class_ = pl_sd->view_class = 4015;
pc_setoption(pl_sd, pl_sd->status.option & ~0x0020);
clif_displaymessage(fd, msg_table[218]); // Now, this player has not more peco.
}
@@ -5769,11 +6020,11 @@ int atcommand_guildspy(
const char* command, const char* message)
{
char guild_name[100];
- char output[200];
struct guild *g;
+ nullpo_retr(-1, sd);
memset(guild_name, '\0', sizeof(guild_name));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%99[^\n]", guild_name) < 1) {
clif_displaymessage(fd, "Please, enter a guild name/id (usage: @guildspy <guild_name/id>).");
@@ -5784,12 +6035,12 @@ int atcommand_guildspy(
(g = guild_search(atoi(message))) != NULL) {
if (sd->guildspy == g->guild_id) {
sd->guildspy = 0;
- sprintf(output, msg_table[103], g->name); // No longer spying on the %s guild.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[103], g->name); // No longer spying on the %s guild.
+ clif_displaymessage(fd, atcmd_output);
} else {
sd->guildspy = g->guild_id;
- sprintf(output, msg_table[104], g->name); // Spying on the %s guild.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[104], g->name); // Spying on the %s guild.
+ clif_displaymessage(fd, atcmd_output);
}
} else {
clif_displaymessage(fd, msg_table[94]); // Incorrect name/ID, or no one from the guild is online.
@@ -5808,11 +6059,11 @@ int atcommand_partyspy(
const char* command, const char* message)
{
char party_name[100];
- char output[200];
struct party *p;
+ nullpo_retr(-1, sd);
memset(party_name, '\0', sizeof(party_name));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%99[^\n]", party_name) < 1) {
clif_displaymessage(fd, "Please, enter a party name/id (usage: @partyspy <party_name/id>).");
@@ -5823,12 +6074,12 @@ int atcommand_partyspy(
(p = party_search(atoi(message))) != NULL) {
if (sd->partyspy == p->party_id) {
sd->partyspy = 0;
- sprintf(output, msg_table[105], p->name); // No longer spying on the %s party.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[105], p->name); // No longer spying on the %s party.
+ clif_displaymessage(fd, atcmd_output);
} else {
sd->partyspy = p->party_id;
- sprintf(output, msg_table[106], p->name); // Spying on the %s party.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[106], p->name); // Spying on the %s party.
+ clif_displaymessage(fd, atcmd_output);
}
} else {
clif_displaymessage(fd, msg_table[96]); // Incorrect name or ID, or no one from the party is online.
@@ -5847,6 +6098,7 @@ int atcommand_repairall(
const char* command, const char* message)
{
int count, i;
+ nullpo_retr(-1, sd);
count = 0;
for (i = 0; i < MAX_INVENTORY; i++) {
@@ -5869,22 +6121,22 @@ int atcommand_repairall(
return 0;
}
-/* Removed @nuke for now in favor of alchemist marine sphere skill [Valaris]
+// Removed @nuke for now in favor of alchemist marine sphere skill [Valaris]
int atcommand_nuke(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
struct map_session_data *pl_sd;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @nuke <char name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kill only lower or same GM level
skill_castend_damage_id(&pl_sd->bl, &pl_sd->bl, NPC_SELFDESTRUCTION, 99, gettick(), 0);
clif_displaymessage(fd, msg_table[109]); // Player has been nuked!
@@ -5899,7 +6151,7 @@ int atcommand_nuke(
return 0;
}
-*/
+
/*==========================================
*
@@ -5909,11 +6161,12 @@ int atcommand_enablenpc(const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
char NPCname[100];
+ nullpo_retr(-1, sd);
memset(NPCname, '\0', sizeof(NPCname));
if (!message || !*message || sscanf(message, "%99[^\n]", NPCname) < 1) {
- clif_displaymessage(fd, "Please, enter a NPC name (usage: @npcon <NPC_name>).");
+ clif_displaymessage(fd, "Please, enter a NPC name (usage: @enablenpc <NPC_name>).");
return -1;
}
@@ -5932,10 +6185,11 @@ int atcommand_enablenpc(const int fd, struct map_session_data* sd,
*
*------------------------------------------
*/
-int atcommand_disablenpc(const int fd, struct map_session_data* sd,
+int atcommand_hidenpc(const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
char NPCname[100];
+ nullpo_retr(-1, sd);
memset(NPCname, '\0', sizeof(NPCname));
@@ -5955,6 +6209,31 @@ int atcommand_disablenpc(const int fd, struct map_session_data* sd,
return 0;
}
+int atcommand_disablenpc(const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct npc_data *nd;
+ char NPCname[100];
+ nullpo_retr(-1, sd);
+
+ memset(NPCname, '\0', sizeof(NPCname));
+
+ if (!message || !*message || sscanf(message, "%99[^\n]", NPCname) < 1) {
+ clif_displaymessage(fd, "Please, enter a NPC name (usage: @npcoff <NPC_name>).");
+ return -1;
+ }
+
+ if ((nd = npc_name2id(NPCname)) != NULL) {
+ npc_unload(nd);
+ clif_displaymessage(fd, msg_table[112]); // Npc Disabled.
+ } else {
+ clif_displaymessage(fd, msg_table[111]); // This NPC doesn't exist.
+ return -1;
+ }
+
+ return 0;
+}
+
/*==========================================
* time in txt for time command (by [Yor])
*------------------------------------------
@@ -6010,6 +6289,7 @@ int atcommand_servertime(const int fd, struct map_session_data* sd,
time_t time_server; // variable for number of seconds (used with time() function)
struct tm *datetime; // variable for time in structure ->tm_mday, ->tm_sec, ...
char temp[256];
+ nullpo_retr(-1, sd);
memset(temp, '\0', sizeof(temp));
@@ -6082,17 +6362,16 @@ int atcommand_chardelitem(const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
struct map_session_data *pl_sd;
- char character[100];
char item_name[100];
int i, number = 0, item_id, item_position, count;
- char output[200];
struct item_data *item_data;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
memset(item_name, '\0', sizeof(item_name));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
- if (!message || !*message || sscanf(message, "%s %d %99[^\n]", item_name, &number, character) < 3 || number < 1) {
+ if (!message || !*message || sscanf(message, "%s %d %99[^\n]", item_name, &number, atcmd_player_name) < 3 || number < 1) {
clif_displaymessage(fd, "Please, enter an item name/id, a quantity and a player name (usage: @chardelitem <item_name_or_ID> <quantity> <player>).");
return -1;
}
@@ -6103,7 +6382,7 @@ int atcommand_chardelitem(const int fd, struct map_session_data* sd,
item_id = item_data->nameid;
if (item_id > 500) {
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kill only lower or same level
item_position = pc_search_inventory(pl_sd, item_id);
if (item_position >= 0) {
@@ -6113,13 +6392,13 @@ int atcommand_chardelitem(const int fd, struct map_session_data* sd,
count++;
item_position = pc_search_inventory(pl_sd, item_id); // for next loop
}
- sprintf(output, msg_table[113], count); // %d item(s) removed by a GM.
- clif_displaymessage(pl_sd->fd, output);
+ sprintf(atcmd_output, msg_table[113], count); // %d item(s) removed by a GM.
+ clif_displaymessage(pl_sd->fd, atcmd_output);
if (number == count)
- sprintf(output, msg_table[114], count); // %d item(s) removed from the player.
+ sprintf(atcmd_output, msg_table[114], count); // %d item(s) removed from the player.
else
- sprintf(output, msg_table[115], count, count, number); // %d item(s) removed. Player had only %d on %d items.
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, msg_table[115], count, count, number); // %d item(s) removed. Player had only %d on %d items.
+ clif_displaymessage(fd, atcmd_output);
} else {
clif_displaymessage(fd, msg_table[116]); // Character does not have the item.
return -1;
@@ -6149,18 +6428,18 @@ int atcommand_jail(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
struct map_session_data *pl_sd;
int x, y;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @jail <char_name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can jail only lower or same GM
switch(rand() % 2) {
case 0:
@@ -6201,23 +6480,22 @@ int atcommand_unjail(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
struct map_session_data *pl_sd;
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @unjail/@discharge <char_name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can jail only lower or same GM
if (pl_sd->bl.m != map_mapname2mapid("sec_pri.gat")) {
clif_displaymessage(fd, msg_table[119]); // This player is not in jails.
return -1;
- } else if (pc_setpos(pl_sd, "prontera.gat", 156, 191, 3) == 0) {
- pc_setsavepoint(pl_sd, "prontera.gat", 156, 191); // Save char respawn point in Prontera
+ } else if (pc_setpos(pl_sd, "prontera.gat", 0, 0, 3) == 0) { //old coords: 156,191
+ pc_setsavepoint(pl_sd, "prontera.gat", 0, 0); // Save char respawn point in Prontera
clif_displaymessage(pl_sd->fd, msg_table[120]); // GM has discharge you.
clif_displaymessage(fd, msg_table[121]); // Player warped to Prontera.
} else {
@@ -6245,6 +6523,7 @@ int atcommand_disguise(
const char* command, const char* message)
{
int mob_id = 0;
+ nullpo_retr(-1, sd);
if (!message || !*message) {
clif_displaymessage(fd, "Please, enter a Monster/NPC name/id (usage: @disguise <monster_name_or_monster_ID>).");
@@ -6257,7 +6536,7 @@ int atcommand_disguise(
if ((mob_id >= 46 && mob_id <= 125) || (mob_id >= 700 && mob_id <= 718) || // NPC
(mob_id >= 721 && mob_id <= 755) || (mob_id >= 757 && mob_id <= 811) || // NPC
(mob_id >= 813 && mob_id <= 834) || // NPC
- (mob_id > 1000 && mob_id < 1521)) { // monsters
+ (mob_id > 1000 && mob_id < 1582)) { // monsters
if (pc_isriding(sd)) { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
clif_displaymessage(fd, msg_table[227]); // Cannot wear disguise while riding a Peco.
return -1;
@@ -6275,6 +6554,50 @@ int atcommand_disguise(
}
/*==========================================
+ * DisguiseAll
+ *------------------------------------------
+ */
+
+int atcommand_disguiseall(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ int mob_id=0, i=0;
+ struct map_session_data *pl_sd;
+ nullpo_retr(-1, sd);
+
+ if (!message || !*message) {
+ clif_displaymessage(fd, "Please, enter a Monster/NPC name/id (usage: @disguiseall <monster_name_or_monster_ID>).");
+ return -1;
+ }
+
+ if ((mob_id = mobdb_searchname(message)) == 0) // check name first (to avoid possible name begining by a number)
+ mob_id = atoi(message);
+
+ if ((mob_id >= 46 && mob_id <= 125) || (mob_id >= 700 && mob_id <= 718) || // NPC
+ (mob_id >= 721 && mob_id <= 755) || (mob_id >= 757 && mob_id <= 811) || // NPC
+ (mob_id >= 813 && mob_id <= 834) || // NPC
+ (mob_id > 1000 && mob_id < 1582)) { // monsters
+ for(i=0; i < fd_max; i++) {
+ if(session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
+ if(pc_isriding(pl_sd)) { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
+ clif_displaymessage(fd, msg_table[227]); // Cannot wear disguise while riding a Peco.
+ } else {
+ pl_sd->disguiseflag = 1; // set to override items with disguise script [Valaris]
+ pl_sd->disguise = mob_id;
+ pc_setpos(pl_sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y, 3);
+ }
+ }
+ }
+ clif_displaymessage(fd, msg_table[122]); // Disguise applied.
+ } else {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*==========================================
* @undisguise by [Yor]
*------------------------------------------
*/
@@ -6282,6 +6605,7 @@ int atcommand_undisguise(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
if (sd->disguise) {
clif_clearchar(&sd->bl, 9);
sd->disguise = 0;
@@ -6296,6 +6620,30 @@ int atcommand_undisguise(
}
/*==========================================
+ * UndisguiseAll
+ *------------------------------------------
+ */
+int atcommand_undisguiseall(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct map_session_data *pl_sd;
+ int i;
+ nullpo_retr(-1, sd);
+
+ for(i=0; i < fd_max; i++) {
+ if(session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && pl_sd->disguise) {
+ clif_clearchar(&pl_sd->bl, 9);
+ pl_sd->disguise = 0;
+ pc_setpos(pl_sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y, 3);
+ }
+ }
+ clif_displaymessage(fd, msg_table[124]); // Undisguise applied.
+
+ return 0;
+}
+
+/*==========================================
* @broadcast by [Valaris]
*------------------------------------------
*/
@@ -6303,17 +6651,17 @@ int atcommand_broadcast(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char output[200];
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message) {
clif_displaymessage(fd, "Please, enter a message (usage: @broadcast <message>).");
return -1;
}
- sprintf(output, "%s : %s", sd->status.name, message);
- intif_GMmessage(output, strlen(output) + 1, 0);
+ sprintf(atcmd_output, "%s : %s", sd->status.name, message);
+ intif_GMmessage(atcmd_output, strlen(atcmd_output) + 1, 0);
return 0;
}
@@ -6326,18 +6674,18 @@ int atcommand_localbroadcast(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char output[200];
+ nullpo_retr(-1, sd);
- memset(output, '\0', sizeof(output));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message) {
clif_displaymessage(fd, "Please, enter a message (usage: @localbroadcast <message>).");
return -1;
}
- sprintf(output, "%s : %s", sd->status.name, message);
+ sprintf(atcmd_output, "%s : %s", sd->status.name, message);
- clif_GMmessage(&sd->bl, output, strlen(output) + 1, 1); // 1: ALL_SAMEMAP
+ clif_GMmessage(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 1); // 1: ALL_SAMEMAP
return 0;
}
@@ -6351,14 +6699,14 @@ int atcommand_chardisguise(
const char* command, const char* message)
{
int mob_id;
- char character[100];
char mob_name[100];
struct map_session_data* pl_sd;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
memset(mob_name, '\0', sizeof(mob_name));
- if (!message || !*message || sscanf(message, "%s %99[^\n]", mob_name, character) < 2) {
+ if (!message || !*message || sscanf(message, "%s %99[^\n]", mob_name, atcmd_player_name) < 2) {
clif_displaymessage(fd, "Please, enter a Monster/NPC name/id and a player name (usage: @chardisguise <monster_name_or_monster_ID> <char name>).");
return -1;
}
@@ -6366,7 +6714,7 @@ int atcommand_chardisguise(
if ((mob_id = mobdb_searchname(mob_name)) == 0) // check name first (to avoid possible name begining by a number)
mob_id = atoi(mob_name);
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can disguise only lower or same level
if ((mob_id >= 46 && mob_id <= 125) || (mob_id >= 700 && mob_id <= 718) || // NPC
(mob_id >= 721 && mob_id <= 755) || (mob_id >= 757 && mob_id <= 811) || // NPC
@@ -6404,17 +6752,17 @@ int atcommand_charundisguise(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
struct map_session_data* pl_sd;
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @charundisguise <char name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can undisguise only lower or same level
if (pl_sd->disguise) {
clif_clearchar(&pl_sd->bl, 9);
@@ -6447,6 +6795,7 @@ int atcommand_email(
{
char actual_email[100];
char new_email[100];
+ nullpo_retr(-1, sd);
memset(actual_email, '\0', sizeof(actual_email));
memset(new_email, '\0', sizeof(new_email));
@@ -6486,6 +6835,7 @@ int atcommand_effect(
{
struct map_session_data *pl_sd;
int type = 0, flag = 0, i;
+ nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%d %d", &type,&flag) < 2) {
clif_displaymessage(fd, "Please, enter at least a option (usage: @effect <type+>).");
@@ -6497,7 +6847,7 @@ int atcommand_effect(
}
else{
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
clif_specialeffect(&pl_sd->bl, type, flag);
clif_displaymessage(pl_sd->fd, msg_table[229]); // Your effect has changed.
}
@@ -6508,203 +6858,6 @@ int atcommand_effect(
}
/*==========================================
- * @charitemlist <character>: Displays the list of a player's items.
- *------------------------------------------
- */
-int
-atcommand_character_item_list(
- const int fd, struct map_session_data* sd,
- const char* command, const char* message)
-{
- struct map_session_data *pl_sd;
- struct item_data *item_data, *item_temp;
- int i, j, equip, count, counter, counter2;
- char character[100], output[200], equipstr[100], outputtmp[200];
-
- memset(character, '\0', sizeof(character));
- memset(output, '\0', sizeof(output));
- memset(equipstr, '\0', sizeof(equipstr));
- memset(outputtmp, '\0', sizeof(outputtmp));
-
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
- clif_displaymessage(fd, "Please, enter a player name (usage: @charitemlist <char name>).");
- return -1;
- }
-
- if ((pl_sd = map_nick2sd(character)) != NULL) {
- if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can look items only lower or same level
- counter = 0;
- count = 0;
- for (i = 0; i < MAX_INVENTORY; i++) {
- if (pl_sd->status.inventory[i].nameid > 0 && (item_data = itemdb_search(pl_sd->status.inventory[i].nameid)) != NULL) {
- counter = counter + pl_sd->status.inventory[i].amount;
- count++;
- if (count == 1) {
- sprintf(output, "------ Items list of '%s' ------", pl_sd->status.name);
- clif_displaymessage(fd, output);
- }
- if ((equip = pl_sd->status.inventory[i].equip)) {
- strcpy(equipstr, "| equiped: ");
- if (equip & 4)
- strcat(equipstr, "robe/gargment, ");
- if (equip & 8)
- strcat(equipstr, "left accessory, ");
- if (equip & 16)
- strcat(equipstr, "body/armor, ");
- if ((equip & 34) == 2)
- strcat(equipstr, "right hand, ");
- if ((equip & 34) == 32)
- strcat(equipstr, "left hand, ");
- if ((equip & 34) == 34)
- strcat(equipstr, "both hands, ");
- if (equip & 64)
- strcat(equipstr, "feet, ");
- if (equip & 128)
- strcat(equipstr, "right accessory, ");
- if ((equip & 769) == 1)
- strcat(equipstr, "lower head, ");
- if ((equip & 769) == 256)
- strcat(equipstr, "top head, ");
- if ((equip & 769) == 257)
- strcat(equipstr, "lower/top head, ");
- if ((equip & 769) == 512)
- strcat(equipstr, "mid head, ");
- if ((equip & 769) == 512)
- strcat(equipstr, "lower/mid head, ");
- if ((equip & 769) == 769)
- strcat(equipstr, "lower/mid/top head, ");
- // remove final ', '
- equipstr[strlen(equipstr) - 2] = '\0';
- } else
- memset(equipstr, '\0', sizeof(equipstr));
- if (sd->status.inventory[i].refine)
- sprintf(output, "%d %s %+d (%s %+d, id: %d) %s", pl_sd->status.inventory[i].amount, item_data->name, pl_sd->status.inventory[i].refine, item_data->jname, pl_sd->status.inventory[i].refine, pl_sd->status.inventory[i].nameid, equipstr);
- else
- sprintf(output, "%d %s (%s, id: %d) %s", pl_sd->status.inventory[i].amount, item_data->name, item_data->jname, pl_sd->status.inventory[i].nameid, equipstr);
- clif_displaymessage(fd, output);
- memset(output, '\0', sizeof(output));
- counter2 = 0;
- for (j = 0; j < item_data->slot; j++) {
- if (pl_sd->status.inventory[i].card[j]) {
- if ((item_temp = itemdb_search(pl_sd->status.inventory[i].card[j])) != NULL) {
- if (output[0] == '\0')
- sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
- else
- sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
- strcat(output, outputtmp);
- }
- }
- }
- if (output[0] != '\0') {
- output[strlen(output) - 2] = ')';
- output[strlen(output) - 1] = '\0';
- clif_displaymessage(fd, output);
- }
- }
- }
- if (count == 0)
- clif_displaymessage(fd, "No item found on this player.");
- else {
- sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count);
- clif_displaymessage(fd, output);
- }
- } else {
- clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
- return -1;
- }
- } else {
- clif_displaymessage(fd, msg_table[3]); // Character not found.
- return -1;
- }
-
- return 0;
-}
-
-/*==========================================
- * @charstoragelist <character>: Displays the items list of a player's storage.
- *------------------------------------------
- */
-int
-atcommand_character_storage_list(
- const int fd, struct map_session_data* sd,
- const char* command, const char* message)
-{
- struct storage *stor;
- struct map_session_data *pl_sd;
- struct item_data *item_data, *item_temp;
- int i, j, count, counter, counter2;
- char character[100], output[200], outputtmp[200];
-
- memset(character, '\0', sizeof(character));
- memset(output, '\0', sizeof(output));
- memset(outputtmp, '\0', sizeof(outputtmp));
-
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
- clif_displaymessage(fd, "Please, enter a player name (usage: @charitemlist <char name>).");
- return -1;
- }
-
- if ((pl_sd = map_nick2sd(character)) != NULL) {
- if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can look items only lower or same level
- if((stor = account2storage2(pl_sd->status.account_id)) != NULL) {
- counter = 0;
- count = 0;
- for (i = 0; i < MAX_STORAGE; i++) {
- if (stor->storage[i].nameid > 0 && (item_data = itemdb_search(stor->storage[i].nameid)) != NULL) {
- counter = counter + stor->storage[i].amount;
- count++;
- if (count == 1) {
- sprintf(output, "------ Storage items list of '%s' ------", pl_sd->status.name);
- clif_displaymessage(fd, output);
- }
- if (stor->storage[i].refine)
- sprintf(output, "%d %s %+d (%s %+d, id: %d)", stor->storage[i].amount, item_data->name, stor->storage[i].refine, item_data->jname, stor->storage[i].refine, stor->storage[i].nameid);
- else
- sprintf(output, "%d %s (%s, id: %d)", stor->storage[i].amount, item_data->name, item_data->jname, stor->storage[i].nameid);
- clif_displaymessage(fd, output);
- memset(output, '\0', sizeof(output));
- counter2 = 0;
- for (j = 0; j < item_data->slot; j++) {
- if (stor->storage[i].card[j]) {
- if ((item_temp = itemdb_search(stor->storage[i].card[j])) != NULL) {
- if (output[0] == '\0')
- sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
- else
- sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
- strcat(output, outputtmp);
- }
- }
- }
- if (output[0] != '\0') {
- output[strlen(output) - 2] = ')';
- output[strlen(output) - 1] = '\0';
- clif_displaymessage(fd, output);
- }
- }
- }
- if (count == 0)
- clif_displaymessage(fd, "No item found in the storage of this player.");
- else {
- sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count);
- clif_displaymessage(fd, output);
- }
- } else {
- clif_displaymessage(fd, "This player has no storage.");
- return 0;
- }
- } else {
- clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
- return -1;
- }
- } else {
- clif_displaymessage(fd, msg_table[3]); // Character not found.
- return -1;
- }
-
- return 0;
-}
-
-/*==========================================
* @charcartlist <character>: Displays the items list of a player's cart.
*------------------------------------------
*/
@@ -6713,21 +6866,22 @@ atcommand_character_cart_list(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ char outputtmp[200];
struct map_session_data *pl_sd;
struct item_data *item_data, *item_temp;
int i, j, count, counter, counter2;
- char character[100], output[200], outputtmp[200];
+ nullpo_retr(-1, sd);
- memset(character, '\0', sizeof(character));
- memset(output, '\0', sizeof(output));
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(outputtmp, '\0', sizeof(outputtmp));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
clif_displaymessage(fd, "Please, enter a player name (usage: @charitemlist <char name>).");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can look items only lower or same level
counter = 0;
count = 0;
@@ -6736,39 +6890,39 @@ atcommand_character_cart_list(
counter = counter + pl_sd->status.cart[i].amount;
count++;
if (count == 1) {
- sprintf(output, "------ Cart items list of '%s' ------", pl_sd->status.name);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "------ Cart items list of '%s' ------", pl_sd->status.name);
+ clif_displaymessage(fd, atcmd_output);
}
if (pl_sd->status.cart[i].refine)
- sprintf(output, "%d %s %+d (%s %+d, id: %d)", pl_sd->status.cart[i].amount, item_data->name, pl_sd->status.cart[i].refine, item_data->jname, pl_sd->status.cart[i].refine, pl_sd->status.cart[i].nameid);
+ sprintf(atcmd_output, "%d %s %+d (%s %+d, id: %d)", pl_sd->status.cart[i].amount, item_data->name, pl_sd->status.cart[i].refine, item_data->jname, pl_sd->status.cart[i].refine, pl_sd->status.cart[i].nameid);
else
- sprintf(output, "%d %s (%s, id: %d)", pl_sd->status.cart[i].amount, item_data->name, item_data->jname, pl_sd->status.cart[i].nameid);
- clif_displaymessage(fd, output);
- memset(output, '\0', sizeof(output));
+ sprintf(atcmd_output, "%d %s (%s, id: %d)", pl_sd->status.cart[i].amount, item_data->name, item_data->jname, pl_sd->status.cart[i].nameid);
+ clif_displaymessage(fd, atcmd_output);
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
counter2 = 0;
for (j = 0; j < item_data->slot; j++) {
if (pl_sd->status.cart[i].card[j]) {
- if ((item_temp = itemdb_search(pl_sd->status.cart[i].card[j])) != NULL) {
- if (output[0] == '\0')
+ if ( (item_temp = itemdb_search(pl_sd->status.cart[i].card[j])) != NULL) {
+ if (atcmd_output[0] == '\0')
sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
else
sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
- strcat(output, outputtmp);
+ strcat(atcmd_output, outputtmp);
}
}
}
- if (output[0] != '\0') {
- output[strlen(output) - 2] = ')';
- output[strlen(output) - 1] = '\0';
- clif_displaymessage(fd, output);
+ if (atcmd_output[0] != '\0') {
+ atcmd_output[strlen(atcmd_output) - 2] = ')';
+ atcmd_output[strlen(atcmd_output) - 1] = '\0';
+ clif_displaymessage(fd, atcmd_output);
}
}
}
if (count == 0)
clif_displaymessage(fd, "No item found in the cart of this player.");
else {
- sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "%d item(s) found in %d kind(s) of items.", counter, count);
+ clif_displaymessage(fd, atcmd_output);
}
} else {
clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
@@ -6792,6 +6946,7 @@ atcommand_killer(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
sd->special_state.killer = !sd->special_state.killer;
if(sd->special_state.killer)
@@ -6812,6 +6967,7 @@ atcommand_killable(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
sd->special_state.killable = !sd->special_state.killable;
if(sd->special_state.killable)
@@ -6833,6 +6989,7 @@ atcommand_charkillable(
const char* command, const char* message)
{
struct map_session_data *pl_sd = NULL;
+ nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
@@ -6861,6 +7018,7 @@ atcommand_skillon(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
map[sd->bl.m].flag.noskill = 0;
clif_displaymessage(fd, msg_table[244]);
return 0;
@@ -6876,6 +7034,7 @@ atcommand_skilloff(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
+ nullpo_retr(-1, sd);
map[sd->bl.m].flag.noskill = 1;
clif_displaymessage(fd, msg_table[243]);
return 0;
@@ -6891,31 +7050,29 @@ int
atcommand_npcmove(const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char character[100];
int x = 0, y = 0;
struct npc_data *nd = 0;
-
- if( sd == NULL )
- return -1;
+ nullpo_retr(-1, sd);
+
if (!message || !*message)
return -1;
- memset(character, '\0', sizeof character);
+ memset(atcmd_player_name, '\0', sizeof atcmd_player_name);
- if (sscanf(message, "%d %d %99[^\n]", &x, &y, character) < 4)
+ if (sscanf(message, "%d %d %99[^\n]", &x, &y, atcmd_player_name) < 3) {
+ clif_displaymessage(fd, "Usage: @npcmove <X> <Y> <npc_name>");
return -1;
+ }
- nd=npc_name2id(character);
- if (nd==NULL)
- return -1;
+ nullpo_retr(-1, (nd = npc_name2id(atcmd_player_name)));
- npc_enable(character, 0);
- nd->bl.x = x;
- nd->bl.y = y;
- npc_enable(character, 1);
+ npc_enable(atcmd_player_name, 0);
+ nd->bl.x = x;
+ nd->bl.y = y;
+ npc_enable(atcmd_player_name, 1);
- return 0;
+ return 0;
}
/*==========================================
@@ -6929,24 +7086,24 @@ atcommand_addwarp(const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
char w1[64], w3[64], w4[64];
- char map[30], output[200];
int x,y,ret;
+ nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
- if (sscanf(message, "%99s %d %d[^\n]", map, &x, &y ) < 3)
+ if (sscanf(message, "%99s %d %d[^\n]", atcmd_player_name, &x, &y ) < 3)
return -1;
sprintf(w1,"%s,%d,%d", sd->mapname, sd->bl.x, sd->bl.y);
- sprintf(w3,"%s%d%d%d%d", map,sd->bl.x, sd->bl.y, x, y);
- sprintf(w4,"1,1,%s.gat,%d,%d", map, x, y);
+ sprintf(w3,"%s%d%d%d%d", atcmd_player_name,sd->bl.x, sd->bl.y, x, y);
+ sprintf(w4,"1,1,%s.gat,%d,%d", atcmd_player_name, x, y);
ret = npc_parse_warp(w1, "warp", w3, w4);
- sprintf(output, "New warp NPC => %s",w3);
+ sprintf(atcmd_output, "New warp NPC => %s",w3);
- clif_displaymessage(fd, output);
+ clif_displaymessage(fd, atcmd_output);
return ret;
}
@@ -6962,6 +7119,7 @@ atcommand_follow(const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
struct map_session_data *pl_sd = NULL;
+ nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
@@ -6974,33 +7132,6 @@ atcommand_follow(const int fd, struct map_session_data* sd,
/*==========================================
- * @chareffect by [MouseJstr]
- *
- * Create a effect localized on another character
- *------------------------------------------
- */
-int
-atcommand_chareffect(const int fd, struct map_session_data* sd,
- const char* command, const char* message)
-{
- struct map_session_data *pl_sd = NULL;
- char target[255];
- int type = 0;
-
- if (!message || !*message || sscanf(message, "%d %s", &type, target) != 2) {
- clif_displaymessage(fd, "usage: @chareffect <type+> <target>.");
- return -1;
- }
-
- if((pl_sd=map_nick2sd((char *) target)) == NULL)
- return -1;
-
- clif_specialeffect(&pl_sd->bl, type, 0);
- clif_displaymessage(fd, msg_table[229]); // Your effect has changed.
-
- return 0;
-}
-/*==========================================
* @dropall by [MouseJstr]
*
* Drop all your possession on the ground
@@ -7011,10 +7142,11 @@ atcommand_dropall(const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
int i;
+ nullpo_retr(-1, sd);
for (i = 0; i < MAX_INVENTORY; i++) {
if (sd->status.inventory[i].amount) {
if(sd->status.inventory[i].equip != 0)
- pc_unequipitem(sd, i, 0, BF_NORMAL);
+ pc_unequipitem(sd, i, 3);
pc_dropitem(sd, i, sd->status.inventory[i].amount);
}
}
@@ -7022,7 +7154,7 @@ atcommand_dropall(const int fd, struct map_session_data* sd,
}
/*==========================================
* @chardropall by [MouseJstr]
- *
+ *
* Throw all the characters possessions on the ground. Normally
* done in response to them being disrespectful of a GM
*------------------------------------------
@@ -7033,6 +7165,7 @@ atcommand_chardropall(const int fd, struct map_session_data* sd,
{
int i;
struct map_session_data *pl_sd = NULL;
+ nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
@@ -7041,7 +7174,7 @@ atcommand_chardropall(const int fd, struct map_session_data* sd,
for (i = 0; i < MAX_INVENTORY; i++) {
if (pl_sd->status.inventory[i].amount) {
if(pl_sd->status.inventory[i].equip != 0)
- pc_unequipitem(pl_sd, i, 0, BF_NORMAL);
+ pc_unequipitem(pl_sd, i, 3);
pc_dropitem(pl_sd, i, pl_sd->status.inventory[i].amount);
}
}
@@ -7064,6 +7197,7 @@ atcommand_storeall(const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
int i;
+ nullpo_retr(-1, sd);
if (storage_storageopen(sd) == 1) {
clif_displaymessage(fd, "run this command again..");
return 0;
@@ -7071,7 +7205,7 @@ atcommand_storeall(const int fd, struct map_session_data* sd,
for (i = 0; i < MAX_INVENTORY; i++) {
if (sd->status.inventory[i].amount) {
if(sd->status.inventory[i].equip != 0)
- pc_unequipitem(sd, i, 0, BF_NORMAL);
+ pc_unequipitem(sd, i, 3);
storage_storageadd(sd, i, sd->status.inventory[i].amount);
}
}
@@ -7092,10 +7226,11 @@ atcommand_charstoreall(const int fd, struct map_session_data* sd,
{
int i;
struct map_session_data *pl_sd = NULL;
+ nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
- if((pl_sd=map_nick2sd((char *) message)) == NULL)
+ if((pl_sd=map_nick2sd((char *) message)) == NULL)
return -1;
if (storage_storageopen(pl_sd) == 1) {
@@ -7106,7 +7241,7 @@ atcommand_charstoreall(const int fd, struct map_session_data* sd,
for (i = 0; i < MAX_INVENTORY; i++) {
if (pl_sd->status.inventory[i].amount) {
if(pl_sd->status.inventory[i].equip != 0)
- pc_unequipitem(pl_sd, i, 0, BF_NORMAL);
+ pc_unequipitem(pl_sd, i, 3);
storage_storageadd(pl_sd, i, sd->status.inventory[i].amount);
}
}
@@ -7131,15 +7266,15 @@ atcommand_skillid(const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
int skillen = 0, idx = 0;
+ nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
skillen = strlen(message);
while (skill_names[idx].id != 0) {
if ((strnicmp(skill_names[idx].name, message, skillen) == 0) ||
(strnicmp(skill_names[idx].desc, message, skillen) == 0)) {
- char output[255];
- sprintf(output, "skill %d: %s", skill_names[idx].id, skill_names[idx].desc);
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "skill %d: %s", skill_names[idx].id, skill_names[idx].desc);
+ clif_displaymessage(fd, atcmd_output);
}
idx++;
}
@@ -7161,10 +7296,11 @@ atcommand_useskill(const int fd, struct map_session_data* sd,
int skilllv;
int inf;
char target[255];
+ nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
- if(sscanf(message, "%d %d %s", &skillnum, &skilllv, target) != 3) {
+ if(sscanf(message, "%d %d %99[^\n]", &skillnum, &skilllv, target) != 3) {
clif_displaymessage(fd, "Usage: @useskill <skillnum> <skillv> <target>");
return -1;
}
@@ -7197,7 +7333,8 @@ atcommand_skilltree(const int fd, struct map_session_data* sd,
int meets = 1, j, c=0, s=0;
struct pc_base_job s_class;
char target[255], *tbl;
- char output[255];
+ struct skill_tree_entry *ent;
+ nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
@@ -7206,10 +7343,10 @@ atcommand_skilltree(const int fd, struct map_session_data* sd,
clif_displaymessage(fd, "Usage: @skilltree <skillnum> <target>");
return -1;
}
- if((pl_sd=map_nick2sd(target)) == NULL)
+ if((pl_sd=map_nick2sd(target)) == NULL)
return -1;
- s_class = pc_calc_base_job(pl_sd->status.class);
+ s_class = pc_calc_base_job(pl_sd->status.class_);
c = s_class.job;
s = s_class.upper;
@@ -7217,52 +7354,295 @@ atcommand_skilltree(const int fd, struct map_session_data* sd,
tbl = job_name(c);
- sprintf(output, "Player is using %s %s skill tree (%d basic points)",
- s_class.upper ? "upper" : "lower",
+ sprintf(atcmd_output, "Player is using %s %s skill tree (%d basic points)",
+ s_class.upper ? "upper" : "lower",
tbl, pc_checkskill(pl_sd, 1));
- clif_displaymessage(fd, output);
+ clif_displaymessage(fd, atcmd_output);
- for (j = 0; j < MAX_SKILL; j++) {
+ for (j = 0; skill_tree[s][c][j].id != 0; j++) {
if (skill_tree[s][c][j].id == skillnum) {
skillidx = j;
break;
}
}
-
+
if (skillidx == -1) {
- sprintf(output, "I do not believe the player can use that skill");
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "I do not believe the player can use that skill");
+ clif_displaymessage(fd, atcmd_output);
return 0;
}
- struct skill_tree_entry *ent = &skill_tree[s][c][skillidx];
+ ent = &skill_tree[s][c][skillidx];
- for(j=0;j<5;j++)
+ for(j=0;j<5;j++)
if( ent->need[j].id &&
- pc_checkskill(sd,ent->need[j].id) < ent->need[j].lv)
+ pc_checkskill(sd,ent->need[j].id) < ent->need[j].lv)
{
int idx = 0;
char *desc;
- while (skill_names[idx].id != 0 && skill_names[idx].id != ent->need[j].id)
+ while (skill_names[idx].id != 0 && skill_names[idx].id != ent->need[j].id)
idx++;
if (skill_names[idx].id == 0)
desc = "Unknown skill";
else
desc = skill_names[idx].desc;
- sprintf(output, "player requires level %d of skill %s",
+ sprintf(atcmd_output, "player requires level %d of skill %s",
ent->need[j].lv, desc);
- clif_displaymessage(fd, output);
+ clif_displaymessage(fd, atcmd_output);
meets = 0;
}
if (meets == 1) {
- sprintf(output, "I believe the player meets all the requirements for that skill");
- clif_displaymessage(fd, output);
+ sprintf(atcmd_output, "I believe the player meets all the requirements for that skill");
+ clif_displaymessage(fd, atcmd_output);
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * @marry by [MouseJstr], fixed by Lupus
+ *
+ * Marry two players
+ *------------------------------------------
+ */
+int
+atcommand_marry(const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct map_session_data *pl_sd1 = NULL;
+ struct map_session_data *pl_sd2 = NULL;
+ char player1[255], player2[255];
+
+ nullpo_retr(-1, sd);
+
+ if (!message || !*message || sscanf(message, "%[^,],%[^\r\n]", player1, player2) != 2) {
+ clif_displaymessage(fd, "Usage: @marry <player1>,<player2>.");
+ return -1;
+ }
+
+ if((pl_sd1=map_nick2sd((char *) player1)) == NULL) {
+ sprintf(player2, "Cannot find player '%s' online", player1);
+ clif_displaymessage(fd, player2);
+ return -1;
+ }
+
+ if((pl_sd2=map_nick2sd((char *) player2)) == NULL) {
+ sprintf(player1, "Cannot find player '%s' online", player2);
+ clif_displaymessage(fd, player1);
+ return -1;
+ }
+
+ if (pc_marriage(pl_sd1, pl_sd2) == 0) {
+ clif_displaymessage(fd, "They are married.. wish them well");
+ clif_wedding_effect(&sd->bl); //wedding effect and music [Lupus]
+ return 0;
+ }
+ return -1;
+}
+
+/*==========================================
+ * @divorce by [MouseJstr], fixed by [Lupus]
+ *
+ * divorce two players
+ *------------------------------------------
+ */
+int
+atcommand_divorce(const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct map_session_data *pl_sd = NULL;
+
+ nullpo_retr(-1, sd);
+
+ if (!message || !*message || sscanf(message, "%[^\r\n]", atcmd_player_name) != 1) {
+ clif_displaymessage(fd, "Usage: @divorce <player>.");
+ return -1;
+ }
+
+ if((pl_sd=map_nick2sd((char *) atcmd_player_name)) != NULL) {
+ if (pc_divorce(pl_sd) != 0) {
+ sprintf(atcmd_output, "The divorce has failed.. Cannot find player '%s' or his(her) partner online.", atcmd_player_name);
+ clif_displaymessage(fd, atcmd_output);
+ return -1;
+ } else {
+ sprintf(atcmd_output, "'%s' and his(her) partner are now divorced.", atcmd_player_name);
+ clif_displaymessage(fd, atcmd_output);
+ return 0;
+ }
}
-
+ sprintf(atcmd_output, "Cannot find player '%s' online", atcmd_player_name);
+ clif_displaymessage(fd, atcmd_output);
+ return -1;
+}
+
+/*==========================================
+ * @rings by [MouseJstr]
+ *
+ * Give two players rings
+ *------------------------------------------
+ */
+int
+atcommand_rings(const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct item item_tmp;
+ int flag;
+
+ memset(&item_tmp, 0, sizeof(item_tmp));
+
+ item_tmp.nameid = 2634;
+ item_tmp.identify = 1;
+
+ if ((flag = pc_additem((struct map_session_data*)sd, &item_tmp, 1)))
+ clif_additem((struct map_session_data*)sd, 0, 0, flag);
+
+ item_tmp.nameid = 2635;
+ item_tmp.identify = 1;
+ if ((flag = pc_additem((struct map_session_data*)sd, &item_tmp, 1)))
+ clif_additem((struct map_session_data*)sd, 0, 0, flag);
+
+ clif_displaymessage(fd, "You have rings! Give them to the lovers.");
+
+ return 0;
+}
+
+#ifdef DMALLOC
+unsigned long dmark_;
+int
+atcommand_dmstart(const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ dmark_ = dmalloc_mark();
+
+ clif_displaymessage(fd, "debug mark set");
+
return 0;
}
+int
+atcommand_dmtick(const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ dmalloc_log_changed ( dmark_, 1, 0, 1 ) ;
+ dmark_ = dmalloc_mark();
+ clif_displaymessage(fd, "malloc changes logged");
+
+ return 0;
+}
+#endif
+
+/*==========================================
+ * @grind by [MouseJstr]
+ *------------------------------------------
+ */
+int
+atcommand_grind(const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct map_session_data *pl_sd = NULL;
+ int skillnum;
+ int inf;
+ char target[255];
+ nullpo_retr(-1, sd);
+
+ if (!message || !*message)
+ return -1;
+ if(sscanf(message, "%s", target) != 1) {
+ clif_displaymessage(fd, "Usage: @grind <target>");
+ return -1;
+ }
+ if((pl_sd=map_nick2sd(target)) == NULL)
+ return -1;
+
+ for (skillnum = 1; skillnum < 500; skillnum++) {
+ sd->status.sp = sd->status.max_sp;
+ atcommand_alive(fd, sd, command, message);
+
+ inf = skill_get_inf(skillnum);
+
+ if ((inf == 2) || (inf == 1))
+ skill_use_pos(sd, pl_sd->bl.x+5, pl_sd->bl.y+5, skillnum, 1);
+ else
+ skill_use_id(sd, pl_sd->bl.id, skillnum, 1);
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * @grind2 by [MouseJstr]
+ *------------------------------------------
+ */
+int
+atcommand_grind2(const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ int i, x, y, id;
+
+ for (i = 1000; i <2000; i++) {
+ x = sd->bl.x + (rand() % 10 - 5);
+ y = sd->bl.y + (rand() % 10 - 5);
+ id = mob_once_spawn(sd, "this", x, y, "--ja--", i, 1, "");
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * @changelook by [Celest]
+ *------------------------------------------
+ */
+int
+atcommand_changelook(const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ int i, j = 0, k = 0;
+ int pos[6] = { LOOK_HEAD_TOP,LOOK_HEAD_MID,LOOK_HEAD_BOTTOM,LOOK_WEAPON,LOOK_SHIELD,LOOK_SHOES };
+
+ if((i = sscanf(message, "%d %d", &j, &k)) < 1) {
+ clif_displaymessage(fd, "Usage: @changelook [<position>] <view id> -- [] = optional");
+ clif_displaymessage(fd, "Position: 1-Top 2-Middle 3-Bottom 4-Weapon 5-Shield");
+ return -1;
+ } else if (i == 2) {
+ if (j < 1) j = 1;
+ else if (j > 6) j = 6; // 6 = Shoes - for beta clients only perhaps
+ j = pos[j - 1];
+ } else if (i == 1) { // position not defined, use HEAD_TOP as default
+ k = j; // swap
+ j = LOOK_HEAD_TOP;
+ }
+
+ clif_changelook(&sd->bl,j,k);
+
+ return 0;
+}
+
+/*==========================================
+ *Turns on/off AutoLoot for a specific player
+ *------------------------------------------
+ *by Upa-Kun
+ */
+int
+atcommand_autoloot(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ nullpo_retr(-1, sd);
+ if (sd->autoloot)
+ {
+ sd->autoloot = 0;
+ clif_displaymessage(fd, "Autoloot is now off.");
+ }
+ else
+ {
+ sd->autoloot = 1;
+ clif_displaymessage(fd, "Autoloot is now on.");
+ }
+ return 0;
+}
+
+
/*==========================================
* It is made to rain.
*------------------------------------------
@@ -7273,13 +7653,16 @@ atcommand_rain(
const char* command, const char* message)
{
int effno = 0;
- effno = 161;
nullpo_retr(-1, sd);
- if (effno < 0 || map[sd->bl.m].flag.rain)
- return -1;
-
- map[sd->bl.m].flag.rain=1;
- clif_specialeffect(&sd->bl,effno,2);
+ effno = 161;
+ if (map[sd->bl.m].flag.rain) {
+ map[sd->bl.m].flag.rain=0;
+ clif_displaymessage(fd, "The rain has stopped.");
+ } else {
+ map[sd->bl.m].flag.rain=1;
+ clif_specialeffect(&sd->bl,effno,2);
+ clif_displaymessage(fd, "It is made to rain.");
+ }
return 0;
}
/*==========================================
@@ -7294,11 +7677,15 @@ atcommand_snow(
int effno = 0;
effno = 162;
nullpo_retr(-1, sd);
- if (effno < 0 || map[sd->bl.m].flag.snow)
- return -1;
+ if (map[sd->bl.m].flag.snow) {
+ map[sd->bl.m].flag.snow=0;
+ clif_displaymessage(fd, "Snow has stopped falling.");
+ } else {
+ map[sd->bl.m].flag.snow=1;
+ clif_specialeffect(&sd->bl,effno,2);
+ clif_displaymessage(fd, "It is made to snow.");
+ }
- map[sd->bl.m].flag.snow=1;
- clif_specialeffect(&sd->bl,effno,2);
return 0;
}
@@ -7314,11 +7701,14 @@ atcommand_sakura(
int effno = 0;
effno = 163;
nullpo_retr(-1, sd);
- if (effno < 0 || map[sd->bl.m].flag.sakura)
- return -1;
-
- map[sd->bl.m].flag.sakura=1;
- clif_specialeffect(&sd->bl,effno,2);
+ if (map[sd->bl.m].flag.sakura) {
+ map[sd->bl.m].flag.sakura=0;
+ clif_displaymessage(fd, "Cherry tree leaves is made to fall.");
+ } else {
+ map[sd->bl.m].flag.sakura=1;
+ clif_specialeffect(&sd->bl,effno,2);
+ clif_displaymessage(fd, "Cherry tree leaves is made to fall.");
+ }
return 0;
}
@@ -7334,11 +7724,14 @@ atcommand_fog(
int effno = 0;
effno = 233;
nullpo_retr(-1, sd);
- if (effno < 0 || map[sd->bl.m].flag.fog)
- return -1;
-
- map[sd->bl.m].flag.fog=1;
- clif_specialeffect(&sd->bl,effno,2);
+ if (map[sd->bl.m].flag.fog) {
+ map[sd->bl.m].flag.fog=0;
+ clif_displaymessage(fd, "The fog has gone.");
+ } else {
+ map[sd->bl.m].flag.fog=1;
+ clif_specialeffect(&sd->bl,effno,2);
+ clif_displaymessage(fd, "Fog hangs over.");
+ }
return 0;
}
@@ -7355,15 +7748,211 @@ atcommand_leaves(
int effno = 0;
effno = 333;
nullpo_retr(-1, sd);
- if (effno < 0 || map[sd->bl.m].flag.leaves)
+ if (map[sd->bl.m].flag.leaves) {
+ map[sd->bl.m].flag.leaves=0;
+ clif_displaymessage(fd, "Leaves no longer fall.");
+ } else {
+ map[sd->bl.m].flag.leaves=1;
+ clif_specialeffect(&sd->bl,effno,2);
+ clif_displaymessage(fd, "Fallen leaves fall.");
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * Clearing Weather Effects by Dexity
+ *------------------------------------------
+ */
+int
+atcommand_clearweather(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ //int effno = 0;
+ nullpo_retr(-1, sd);
+ map[sd->bl.m].flag.rain=0;
+ map[sd->bl.m].flag.snow=0;
+ map[sd->bl.m].flag.sakura=0;
+ map[sd->bl.m].flag.fog=0;
+ map[sd->bl.m].flag.leaves=0;
+ //clif_specialeffect(&sd->bl,effno,2); // not required. [celest]
+ return 0;
+}
+
+/*===============================================================
+ * Sound Command - plays a sound for everyone! [Codemaster]
+ *---------------------------------------------------------------
+ */
+int
+atcommand_sound(
+ const int fd, struct map_session_data *sd,
+ const char *command, const char *message)
+{
+ char sound_file[100];
+
+ if(!message || !*message || sscanf(message, "%99[^\n]", sound_file) < 1) {
+ clif_displaymessage(fd, "Please, enter a sound filename. (usage: @sound <filename>)");
+ return -1;
+ }
+
+ memset(sound_file, '\0', sizeof(sound_file));
+ if(sscanf(message, "%99[^\n]", sound_file) < 1)
+ return -1;
+
+ if(strstr(sound_file, ".wav") == NULL)
+ strcat(sound_file, ".wav");
+
+ clif_soundeffectall(&sd->bl, sound_file,0);
+
+ return 0;
+}
+
+/*==========================================
+ * MOB Search
+ *------------------------------------------
+ */
+int
+atcommand_mobsearch(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ char mob_name[100];
+ int mob_id,map_id = 0;
+
+ nullpo_retr(-1, sd);
+
+ if (sscanf(message, "%99[^\n]", mob_name) < 0)
+ return -1;
+
+ if ((mob_id = atoi(mob_name)) == 0)
+ mob_id = mobdb_searchname(mob_name);
+ if(mob_id !=-1 && (mob_id <= 1000 || mob_id >= 2000)){
+ snprintf(atcmd_output, sizeof atcmd_output, "Invalid mob id %s!",mob_name);
+ clif_displaymessage(fd, atcmd_output);
+ return 0;
+ }
+ if(mob_id == atoi(mob_name) && mob_db[mob_id].jname)
+ strcpy(mob_name,mob_db[mob_id].jname); // --ja--
+// strcpy(mob_name,mob_db[mob_id].name); // --en--
+
+ map_id = sd->bl.m;
+
+ snprintf(atcmd_output, sizeof atcmd_output, "Mob Search... %s %s",
+ mob_name, sd->mapname);
+ clif_displaymessage(fd, atcmd_output);
+
+ map_foreachinarea(atmobsearch_sub, map_id, 0, 0,
+ map[map_id].xs, map[map_id].ys, BL_MOB, mob_id, fd);
+
+ atmobsearch_sub(&sd->bl,0); // 番号リセット
+
+ return 0;
+}
+/*==========================================
+ * ドロップアイテムの掃除
+ *------------------------------------------
+ */
+int
+atcommand_cleanmap(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ int i=0;
+ map_foreachinarea(atcommand_cleanmap_sub,sd->bl.m,
+ sd->bl.x-AREA_SIZE*2,sd->bl.y-AREA_SIZE*2,
+ sd->bl.x+AREA_SIZE*2,sd->bl.y+AREA_SIZE*2,
+ BL_ITEM,sd,&i);
+ clif_displaymessage(fd, "All dropped items have been cleaned up.");
+ return 0;
+}
+
+/*==========================================
+ * 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;
- map[sd->bl.m].flag.leaves=1;
- clif_specialeffect(&sd->bl,effno,2);
+ 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;
}
+
/*==========================================
- *
+ * @users
+ * サーバー内の人数マップを表示させる
+ * 手抜きのため汚くなっているのは仕様です。
+ *------------------------------------------
+ */
+
+static struct dbt *users_db;
+static int users_all;
+
+static int atcommand_users_sub1(struct map_session_data* sd,va_list va) {
+ int users = (int)strdb_search(users_db,sd->mapname) + 1;
+ users_all++;
+ strdb_insert(users_db,sd->mapname,(void *)users);
+ return 0;
+}
+
+static int atcommand_users_sub2(void* key,void* val,va_list va) {
+ char buf[256];
+ struct map_session_data* sd = va_arg(va,struct map_session_data*);
+ sprintf(buf,"%s : %d (%d%%)",(char *)key,(int)val,(int)val * 100 / users_all);
+ clif_displaymessage(sd->fd,buf);
+ return 0;
+}
+
+int
+atcommand_users(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ char buf[256];
+ users_all = 0;
+ users_db = strdb_init(24);
+ clif_foreachclient(atcommand_users_sub1);
+ strdb_foreach(users_db,atcommand_users_sub2,sd);
+ sprintf(buf,"all : %d",users_all);
+ clif_displaymessage(fd,buf);
+ strdb_final(users_db,NULL);
+ return 0;
+}
+
+/*==========================================
+ *
*------------------------------------------
*/
int
@@ -7378,14 +7967,14 @@ atcommand_summon(
int id = 0;
struct mob_data *md;
unsigned int tick=gettick();
-
+
nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
if (sscanf(message, "%99s", name) < 1)
return -1;
-
+
if ((mob_id = atoi(name)) == 0)
mob_id = mobdb_searchname(name);
if(mob_id == 0)
@@ -7398,7 +7987,7 @@ atcommand_summon(
if((md=(struct mob_data *)map_id2bl(id))){
md->master_id=sd->bl.id;
md->state.special_mob_ai=1;
- md->mode=mob_db[md->class].mode|0x04;
+ md->mode=mob_db[md->class_].mode|0x04;
md->deletetimer=add_timer(tick+60000,mob_timer_delete,id,0);
clif_misceffect2(&md->bl,344);
}
@@ -7424,9 +8013,10 @@ atcommand_adjcmdlvl(
{
int i, newlev;
char cmd[100];
+ nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%d %s", &newlev, cmd) != 2) {
- clif_displaymessage(fd, "usage: @adjcmdlvl <lvl> <command>.");
+ clif_displaymessage(fd, "Usage: @adjcmdlvl <lvl> <command>.");
return -1;
}
@@ -7458,13 +8048,14 @@ atcommand_adjgmlvl(
int newlev;
char user[100];
struct map_session_data *pl_sd;
+ nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%d %[^\r\n]", &newlev, user) != 2) {
- clif_displaymessage(fd, "usage: @adjgmlvl <lvl> <user>.");
+ clif_displaymessage(fd, "Usage: @adjgmlvl <lvl> <user>.");
return -1;
}
- if((pl_sd=map_nick2sd((char *) user)) == NULL)
+ if((pl_sd=map_nick2sd((char *) user)) == NULL)
return -1;
pc_set_gm_level(pl_sd->status.account_id, newlev);
@@ -7478,7 +8069,7 @@ atcommand_adjgmlvl(
*
* Open a trade window with a remote player
*
- * If I have to jump to a remote player one more time, I am
+ * If I have to jump to a remote player one more time, I am
* gonna scream!
*------------------------------------------
*/
@@ -7488,6 +8079,7 @@ atcommand_trade(
const char* command, const char* message)
{
struct map_session_data *pl_sd = NULL;
+ nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
@@ -7509,13 +8101,14 @@ atcommand_setbattleflag(
const char* command, const char* message)
{
char flag[128], value[128];
+ nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%s %s", flag, value) != 2) {
- clif_displaymessage(fd, "usage: @setbattleflag <flag> <value>.");
+ clif_displaymessage(fd, "Usage: @setbattleflag <flag> <value>.");
return -1;
}
- if (battle_set_value(flag, value) == 0)
+ if (battle_set_value(flag, value) == 0)
clif_displaymessage(fd, "unknown battle_config flag");
else
clif_displaymessage(fd, "battle_config set as requested");
@@ -7533,13 +8126,14 @@ int atcommand_unmute(
const char* command, const char* message)
{
struct map_session_data *pl_sd = NULL;
+ nullpo_retr(-1, sd);
if (!message || !*message)
return -1;
if((pl_sd=map_nick2sd((char *) message)) != NULL) {
if(pl_sd->sc_data[SC_NOCHAT].timer!=-1) {
pl_sd->status.manner = 0; // have to set to 0 first [celest]
- skill_status_change_end(&pl_sd->bl,SC_NOCHAT,-1);
+ status_change_end(&pl_sd->bl,SC_NOCHAT,-1);
clif_displaymessage(sd->fd,"Player unmuted");
}
else
@@ -7558,9 +8152,9 @@ atcommand_uptime(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- char output[200];
long seconds = 0, day = 24*60*60, hour = 60*60,
minute = 60, days = 0, hours = 0, minutes = 0;
+ nullpo_retr(-1, sd);
seconds = (gettick()-ticks)/CLOCKS_PER_SEC;
days = seconds/day;
@@ -7569,9 +8163,11 @@ atcommand_uptime(
seconds -= (seconds/hour>0)?(seconds/hour)*hour:0;
minutes = seconds/minute;
seconds -= (seconds/minute>0)?(seconds/minute)*minute:0;
-
- snprintf(output, sizeof(output), msg_table[245], days, hours, minutes, seconds);
- clif_displaymessage(fd,output);
+
+ snprintf(atcmd_output, sizeof(atcmd_output), msg_table[245], days, hours, minutes, seconds);
+
+ clif_displaymessage(fd,atcmd_output);
+
return 0;
}
@@ -7586,7 +8182,8 @@ atcommand_changesex(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- chrif_changesex(sd->status.account_id, ((sd->status.sex+1)%2));
+ nullpo_retr(-1, sd);
+ chrif_char_ask_name(sd->status.account_id,sd->status.name, 5,0,0,0,0,0,0);
return 0;
}
@@ -7599,18 +8196,18 @@ int atcommand_mute(
const char* command, const char* message)
{
struct map_session_data *pl_sd = NULL;
- char character[100];
int manner;
+ nullpo_retr(-1, sd);
- if (!message || !*message || sscanf(message, "%d %99[^\n]", &manner, character) < 1) {
- clif_displaymessage(fd, "usage: @mute <time> <character name>.");
+ if (!message || !*message || sscanf(message, "%d %99[^\n]", &manner, atcmd_player_name) < 1) {
+ clif_displaymessage(fd, "Usage: @mute <time> <character name>.");
return -1;
}
- if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) {
pl_sd->status.manner -= manner;
if(pl_sd->status.manner < 0)
- skill_status_change_start(&pl_sd->bl,SC_NOCHAT,0,0,0,0,0,0);
+ status_change_start(&pl_sd->bl,SC_NOCHAT,0,0,0,0,0,0);
}
else {
clif_displaymessage(fd, msg_table[3]); // Character not found.
@@ -7628,9 +8225,9 @@ int atcommand_refresh(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
-
nullpo_retr(-1, sd);
- pc_setpos(sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
+ //pc_setpos(sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
+ clif_refresh(sd);
return 0;
}
@@ -7647,7 +8244,7 @@ atcommand_petid(const int fd, struct map_session_data* sd,
char temp0[100];
char temp1[100];
int cnt = 0, i = 0;
-
+
nullpo_retr(-1, sd);
if (!message || !*message)
@@ -7663,7 +8260,7 @@ atcommand_petid(const int fd, struct map_session_data* sd,
strcpy(temp0,pet_db[i].jname);
strcpy(temp0, estr_lower(temp1));
if (strstr(temp1, searchtext) || strstr(temp0, searchtext) ) {
- snprintf(temp0, sizeof(temp0), "ID: %i -- Name: %s", pet_db[i].class,
+ snprintf(temp0, sizeof(temp0), "ID: %i -- Name: %s", pet_db[i].class_,
pet_db[i].jname);
if (cnt >= 100) { // Only if there are custom pets
clif_displaymessage(fd, "Be more specific, can't send more than"
@@ -7690,15 +8287,17 @@ atcommand_identify(
const int fd, struct map_session_data* sd,
const char* command, const char* message)
{
- nullpo_retr(-1, sd);
int i,num;
+
+ nullpo_retr(-1, sd);
+
for(i=num=0;i<MAX_INVENTORY;i++){
if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify!=1){
num++;
}
}
if (num > 0) {
- clif_item_identify_list(sd);
+ clif_item_identify_list(sd);
} else {
clif_displaymessage(fd,"There are no items to appraise.");
}
@@ -7706,7 +8305,7 @@ atcommand_identify(
}
/*==========================================
- * @gmotd (Global MOTD)
+ * @gmotd (Global MOTD)
* by davidsiaw :P
*------------------------------------------
*/
@@ -7717,6 +8316,7 @@ atcommand_gmotd(
{
char buf[256];
FILE *fp;
+ nullpo_retr(-1, sd);
if( (fp = fopen(motd_txt, "r"))!=NULL){
while (fgets(buf, 250, fp) != NULL){
int i;
@@ -7744,10 +8344,632 @@ int atcommand_misceffect(
if (sscanf(message, "%d", &effect) < 1)
return -1;
clif_misceffect(&sd->bl,effect);
-
+
return 0;
}
+int charid2sessionid(int charid)
+{
+ int i;
+ int session_id=0;
+ struct map_session_data *pl_sd = NULL;
+
+ for(i=0;i<fd_max;i++){
+ if(session[i] && (pl_sd= (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth){
+ if (pl_sd->status.char_id==charid) { session_id = i; break; }
+ }
+ }
+
+ return session_id;
+}
+
+int accountid2sessionid(int accountid)
+{
+ int i;
+ int session_id=0;
+ struct map_session_data *pl_sd = NULL;
+
+ for(i=0;i<fd_max;i++){
+ if(session[i] && (pl_sd= (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth){
+ if (pl_sd->status.account_id==accountid) { session_id = i; break; }
+ }
+ }
+
+ return session_id;
+}
+
+
+/*==========================================
+ * Jump to a player by PID number
+ * Original by Dino9021
+ * Added in by nsstrunks
+ *------------------------------------------
+ */
+
+int atcommand_jumptoid(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ int cid=0;
+ int session_id=0;
+ struct map_session_data *pl_sd;
+
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
+
+ if (!message || (cid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
+ clif_displaymessage(fd, "Please, enter a player CID (usage: @jumptoid/@warptoid/@gotoid <char id>).");
+ return -1;
+ }
+
+ cid=atoi(message);
+
+ if ((session_id=charid2sessionid(cid))!=0)
+ {
+ if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) {
+ if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
+ clif_displaymessage(fd, msg_table[247]);
+ return -1;
+ }
+ if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
+ clif_displaymessage(fd, msg_table[248]);
+ return -1;
+ }
+ pc_setpos(sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y, 3);
+ sprintf(atcmd_output, msg_table[4], pl_sd->status.name); // Jump to %s
+ clif_displaymessage(fd, atcmd_output);
+ } else {
+ clif_displaymessage(fd, msg_table[154]); // Character not found.
+ return -1;
+ }
+ }
+ else
+ {
+ clif_displaymessage(fd,msg_table[3]);
+ }
+ //printf("Session_id = %d, cid = %d\n",session_id,cid);
+
+ return 0;
+}
+
+/*==========================================
+ * Jump to a player by PID number
+ * Original by Dino9021
+ * Added in by nsstrunks
+ *------------------------------------------
+ */
+
+int atcommand_jumptoid2(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ int aid=0;
+ int session_id=0;
+ struct map_session_data *pl_sd;
+
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
+
+ if (!message || (aid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
+ clif_displaymessage(fd, "Please, enter a player AID (usage: @jumptoid/@warptoid/@gotoid <account id>).");
+ return -1;
+ }
+
+ aid=atoi(message);
+
+ if ((session_id=accountid2sessionid(aid))!=0)
+ {
+ if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) {
+ if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
+ clif_displaymessage(fd, msg_table[247]);
+ return -1;
+ }
+ if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
+ clif_displaymessage(fd, msg_table[248]);
+ return -1;
+ }
+ pc_setpos(sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y, 3);
+ sprintf(atcmd_output, msg_table[4], pl_sd->status.name); // Jump to %s
+ clif_displaymessage(fd, atcmd_output);
+ } else {
+ clif_displaymessage(fd, msg_table[154]); // Character not found.
+ return -1;
+ }
+ }
+ else
+ {
+ clif_displaymessage(fd,msg_table[3]);
+ }
+ //printf("Session_id = %d, aid = %d\n",session_id,aid);
+
+ return 0;
+}
+
+/*==========================================
+ * Recall a player by PID number
+ * Original by Dino9021
+ * Added in by nsstrunks
+ *------------------------------------------
+ */
+int atcommand_recallid(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ int cid=0;
+ int session_id=0;
+ struct map_session_data *pl_sd;
+
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
+
+ if (!message || (cid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
+ clif_displaymessage(fd, "Please, enter a player CID (usage: @recallid <char id>).");
+ return -1;
+ }
+
+ cid=atoi(message);
+
+ if ((session_id=charid2sessionid(cid))!=0)
+ {
+ if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) {
+ if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can recall only lower or same level
+ if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
+ clif_displaymessage(fd, msg_table[247]);
+ return -1;
+ }
+ if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
+ clif_displaymessage(fd, msg_table[248]);
+ return -1;
+ }
+ pc_setpos(pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2);
+ sprintf(atcmd_output, msg_table[46], pl_sd->status.name); // Jump to %s
+ clif_displaymessage(fd, atcmd_output);
+ } else {
+ clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[154]); // Character not found.
+ return -1;
+ }
+ }
+ else
+ {
+ clif_displaymessage(fd,msg_table[3]);
+ }
+ //printf("Session_id = %d, cid = %d\n",session_id,cid);
+
+ return 0;
+}
+
+/*==========================================
+ * Recall a player by PID number
+ * Original by Dino9021
+ * Added in by nsstrunks
+ *------------------------------------------
+ */
+int atcommand_recallid2(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ int aid=0;
+ int session_id=0;
+ struct map_session_data *pl_sd;
+
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
+
+ if (!message || (aid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
+ clif_displaymessage(fd, "Please, enter a player AID (usage: @recallid2 <account id>).");
+ return -1;
+ }
+
+ aid=atoi(message);
+
+ if ((session_id=accountid2sessionid(aid))!=0)
+ {
+ if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) {
+ if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can recall only lower or same level
+ if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
+ clif_displaymessage(fd, msg_table[247]);
+ return -1;
+ }
+ if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
+ clif_displaymessage(fd, msg_table[248]);
+ return -1;
+ }
+ pc_setpos(pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2);
+ sprintf(atcmd_output, msg_table[46], pl_sd->status.name); // Jump to %s
+ clif_displaymessage(fd, atcmd_output);
+ } else {
+ clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[154]); // Character not found.
+ return -1;
+ }
+ }
+ else
+ {
+ clif_displaymessage(fd,msg_table[3]);
+ }
+ //printf("Session_id = %d, aid = %d\n",session_id,aid);
+
+ return 0;
+}
+
+/*==========================================
+ * Kick a player by PID number
+ * Original by Dino9021
+ * Added in by nsstrunks
+ *------------------------------------------
+ */
+int atcommand_kickid(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct map_session_data *pl_sd;
+ int cid=0;
+ int session_id=0;
+
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+
+ if (!message || (cid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
+ clif_displaymessage(fd, "Please, enter a player CID (usage: @kickid <char id>).");
+ return -1;
+ }
+
+ cid=atoi(message);
+
+ if ((session_id=charid2sessionid(cid))!=0)
+ {
+ if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) {
+ if (pc_isGM(sd) >= pc_isGM(pl_sd)) // you can kick only lower or same gm level
+ clif_GM_kick(sd, pl_sd, 1);
+ else {
+ clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[3]); // Character not found.
+ return -1;
+ }
+
+ }
+ else
+ {
+ clif_displaymessage(fd,msg_table[3]);
+ }
+ //printf("Session_id = %d, cid = %d\n",session_id,cid);
+
+ return 0;
+}
+
+/*==========================================
+ * Kick a player by PID number
+ * Original by Dino9021
+ * Added in by nsstrunks
+ *------------------------------------------
+ */
+int atcommand_kickid2(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct map_session_data *pl_sd;
+ int aid=0;
+ int session_id=0;
+
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+
+ if (!message || (aid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
+ clif_displaymessage(fd, "Please, enter a player AID (usage: @kickid2 <account id>).");
+ return -1;
+ }
+
+ aid=atoi(message);
+
+ if ((session_id=accountid2sessionid(aid))!=0)
+ {
+ if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) {
+ if (pc_isGM(sd) >= pc_isGM(pl_sd)) // you can kick only lower or same gm level
+ clif_GM_kick(sd, pl_sd, 1);
+ else {
+ clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[3]); // Character not found.
+ return -1;
+ }
+
+ }
+ else
+ {
+ clif_displaymessage(fd,msg_table[3]);
+ }
+ //printf("Session_id = %d, aid = %d\n",session_id,aid);
+
+ return 0;
+}
+
+/*==========================================
+ * Revive a player by PID number
+ * Original by Dino9021
+ * Added in by nsstrunks
+ *------------------------------------------
+ */
+int atcommand_reviveid(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ int cid=0;
+ int session_id=0;
+ struct map_session_data *pl_sd;
+
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+
+ if (!message || (cid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
+ clif_displaymessage(fd, "Please, enter a player CID (usage: @reviveid <char id>).");
+ return -1;
+ }
+
+ cid=atoi(message);
+
+ if ((session_id=charid2sessionid(cid))!=0)
+ {
+ if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) {
+ pl_sd->status.hp = pl_sd->status.max_hp;
+ pc_setstand(pl_sd);
+ if (battle_config.pc_invincible_time > 0)
+ pc_setinvincibletimer(sd, battle_config.pc_invincible_time);
+ clif_updatestatus(pl_sd, SP_HP);
+ clif_updatestatus(pl_sd, SP_SP);
+ clif_resurrection(&pl_sd->bl, 1);
+ clif_displaymessage(fd, msg_table[51]); // Character revived.
+ } else {
+ clif_displaymessage(fd, msg_table[3]); // Character not found.
+ return -1;
+ }
+
+ }
+ else
+ {
+ clif_displaymessage(fd,msg_table[3]);
+ }
+ //printf("Session_id = %d, cid = %d\n",session_id,cid);
+
+
+ return 0;
+}
+
+/*==========================================
+ * Revive a player by PID number
+ * Original by Dino9021
+ * Added in by nsstrunks
+ *------------------------------------------
+ */
+int atcommand_reviveid2(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ int aid=0;
+ int session_id=0;
+ struct map_session_data *pl_sd;
+
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+
+ if (!message || (aid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
+ clif_displaymessage(fd, "Please, enter a player AID (usage: @reviveid2 <account id>).");
+ return -1;
+ }
+
+ aid=atoi(message);
+
+ if ((session_id=accountid2sessionid(aid))!=0)
+ {
+ if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) {
+ pl_sd->status.hp = pl_sd->status.max_hp;
+ pc_setstand(pl_sd);
+ if (battle_config.pc_invincible_time > 0)
+ pc_setinvincibletimer(sd, battle_config.pc_invincible_time);
+ clif_updatestatus(pl_sd, SP_HP);
+ clif_updatestatus(pl_sd, SP_SP);
+ clif_resurrection(&pl_sd->bl, 1);
+ clif_displaymessage(fd, msg_table[51]); // Character revived.
+ } else {
+ clif_displaymessage(fd, msg_table[3]); // Character not found.
+ return -1;
+ }
+
+ }
+ else
+ {
+ clif_displaymessage(fd,msg_table[3]);
+ }
+ //printf("Session_id = %d, aid = %d\n",session_id,aid);
+
+
+ return 0;
+}
+
+/*==========================================
+ * Kill a player by PID number
+ * Original by Dino9021
+ * Added in by nsstrunks
+ *------------------------------------------
+ */
+int atcommand_killid(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ int cid=0;
+ int session_id=0;
+ struct map_session_data *pl_sd;
+
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+
+ if (!message || (cid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
+ clif_displaymessage(fd, "Please, enter a player CID (usage: @killid <char id>).");
+ return -1;
+ }
+
+ cid=atoi(message);
+
+ if ((session_id=charid2sessionid(cid))!=0)
+ {
+ if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) {
+ if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kill only lower or same level
+ pc_damage(NULL, pl_sd, pl_sd->status.hp + 1);
+ clif_displaymessage(fd, msg_table[14]); // Character killed.
+ } else {
+ clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[3]); // Character not found.
+ return -1;
+ }
+
+ }
+ else
+ {
+ clif_displaymessage(fd,msg_table[3]);
+ }
+ //printf("Session_id = %d, cid = %d\n",session_id,cid);
+
+ return 0;
+}
+
+/*==========================================
+ * Kill a player by PID number
+ * Original by Dino9021
+ * Added in by nsstrunks
+ *------------------------------------------
+ */
+int atcommand_killid2(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ int aid=0;
+ int session_id=0;
+ struct map_session_data *pl_sd;
+
+ memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
+
+ if (!message || (aid = atoi(message)) == 0 || !*message || sscanf(message, "%99[^\n]", atcmd_player_name) < 1) {
+ clif_displaymessage(fd, "Please, enter a player AID (usage: @killid2 <account id>).");
+ return -1;
+ }
+
+ aid=atoi(message);
+
+ if ((session_id=accountid2sessionid(aid))!=0)
+ {
+ if ((pl_sd = (struct map_session_data *) session[session_id]->session_data) != NULL) {
+ if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kill only lower or same level
+ pc_damage(NULL, pl_sd, pl_sd->status.hp + 1);
+ clif_displaymessage(fd, msg_table[14]); // Character killed.
+ } else {
+ clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[3]); // Character not found.
+ return -1;
+ }
+
+ }
+ else
+ {
+ clif_displaymessage(fd,msg_table[3]);
+ }
+ //printf("Session_id = %d, aid = %d\n",session_id,aid);
+
+ return 0;
+}
+
+/*==========================================
+ * Make a player killable, by PID
+ * Original by Dino9021
+ * Added in by nsstrunks
+ *------------------------------------------
+ */
+int
+atcommand_charkillableid(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct map_session_data *pl_sd = NULL;
+ int cid=0;
+ int session_id=0;
+
+ if (!message || (cid = atoi(message)) == 0 || !*message)
+ return -1;
+
+ cid=atoi(message);
+
+ if ((session_id=charid2sessionid(cid))!=0)
+ {
+ if((pl_sd= (struct map_session_data *) session[session_id]->session_data) == NULL)
+ return -1;
+
+ pl_sd->special_state.killable = !pl_sd->special_state.killable;
+
+ if(pl_sd->special_state.killable)
+ clif_displaymessage(fd, "The player is now killable");
+ else
+ clif_displaymessage(fd, "The player is no longer killable");
+ }
+ else
+ {
+ clif_displaymessage(fd,msg_table[3]);
+ }
+ //printf("Session_id = %d, cid = %d\n",session_id,cid);
+ return 0;
+}
+
+
+/*==========================================
+ * Make a player killable, by PID
+ * Original by Dino9021
+ * Added in by nsstrunks
+ *------------------------------------------
+ */
+int
+atcommand_charkillableid2(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct map_session_data *pl_sd = NULL;
+ int aid=0;
+ int session_id=0;
+
+ if (!message || (aid = atoi(message)) == 0 || !*message)
+ return -1;
+
+ aid=atoi(message);
+
+ if ((session_id=accountid2sessionid(aid))!=0)
+ {
+ if((pl_sd= (struct map_session_data *) session[session_id]->session_data) == NULL)
+ return -1;
+
+ pl_sd->special_state.killable = !pl_sd->special_state.killable;
+
+ if(pl_sd->special_state.killable)
+ clif_displaymessage(fd, "The player is now killable");
+ else
+ clif_displaymessage(fd, "The player is no longer killable");
+ }
+ else
+ {
+ clif_displaymessage(fd,msg_table[3]);
+ }
+ //printf("Session_id = %d, aid = %d\n",session_id,aid);
+ return 0;
+}
+
#ifndef TXT_ONLY /* Begin SQL-Only commands */
/*==========================================
@@ -7767,7 +8989,7 @@ int atcommand_listmail(
mail_check(sd,3);
else if(strlen(command)==9)
mail_check(sd,2);
- else
+ else
mail_check(sd,1);
return 0;
}
@@ -7818,7 +9040,7 @@ int atcommand_sendmail(
if(strlen(command)==17)
mail_send(sd,name,text,1);
- else
+ else
mail_send(sd,name,text,0);
return 0;
@@ -7837,8 +9059,171 @@ int atcommand_refreshonline(
nullpo_retr(-1, sd);
char_online_check();
-
+
return 0;
}
#endif /* end sql only */
+
+/*==========================================
+ * Show Monster DB Info v 1.0
+ * originally by [Lupus] eAthena
+ *------------------------------------------
+ */
+int atcommand_mobinfo(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ unsigned char msize[3][7] = {"Small", "Medium", "Large"};
+ unsigned char mrace[12][11] = {"Formless", "Undead", "Beast", "Plant", "Insect", "Fish", "Demon", "Demi-Human", "Angel", "Dragon", "Boss", "Non-Boss"};
+ unsigned char melement[11][8] = {"None", "Neutral", "Water", "Earth", "Fire", "Wind", "Poison", "Holy", "Dark", "Ghost", "Undead"};
+ char atcmd_output2[200];
+ struct item_data *item_data;
+ struct mob_db *mob;
+ int mob_id;
+ int i, j;
+
+ memset(atcmd_output, '\0', sizeof(atcmd_output));
+ memset(atcmd_output2, '\0', sizeof(atcmd_output2));
+
+ if (!message || !*message) {
+ clif_displaymessage(fd, "Please, enter a Monster/NPC name/id (usage: @mobinfo <monster_name_or_monster_ID>).");
+ return -1;
+ }
+
+ // If monster identifier/name argument is a name
+ if ((mob_id = mobdb_searchname(message)) == 0) // check name first (to avoid possible name begining by a number)
+ mob_id = mobdb_checkid(atoi(message));
+
+ if (mob_id == 0) {
+ clif_displaymessage(fd, msg_table[40]); // Invalid monster ID or name.
+ return -1;
+ }
+
+ mob = &mob_db[mob_id];
+
+ // stats
+ if (mob->mexp)
+ sprintf(atcmd_output, "Monster (MVP): '%s'/'%s' (%d)", mob->name, mob->jname, mob_id);
+ else
+ sprintf(atcmd_output, "Monster: '%s'/'%s' (%d)", mob->name, mob->jname, mob_id);
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, " Level:%d HP:%d SP:%d Base EXP:%d Job EXP:%d", mob->lv, mob->max_hp, mob->max_sp, mob->base_exp, mob->job_exp);
+ clif_displaymessage(fd, atcmd_output);
+ sprintf(atcmd_output, " DEF:%d MDEF:%d STR:%d AGI:%d VIT:%d INT:%d DEX:%d LUK:%d", mob->def, mob->mdef, mob->str, mob->agi, mob->vit, mob->int_, mob->dex, mob->luk);
+ clif_displaymessage(fd, atcmd_output);
+ if (mob->element < 20) {
+ //Element - None, Level 0
+ i = 0;
+ j = 0;
+ } else {
+ i = mob->element % 20 + 1;
+ j = mob->element / 20;
+ }
+ sprintf(atcmd_output, " ATK:%d~%d Range:%d~%d~%d Size:%s Race: %s Element: %s (Lv:%d)", mob->atk1, mob->atk2, mob->range, mob->range2 , mob->range3, msize[mob->size], mrace[mob->race], melement[i], j);
+ clif_displaymessage(fd, atcmd_output);
+ // drops
+ clif_displaymessage(fd, " Drops:");
+ strcpy(atcmd_output, " ");
+ j = 0;
+ for (i = 0; i < 10; i++) {
+ if (mob->dropitem[i].nameid <= 0 || (item_data = itemdb_search(mob->dropitem[i].nameid)) == NULL)
+ continue;
+ if (mob->dropitem[i].p > 0) {
+ sprintf(atcmd_output2, " - %s %02.02f%%", item_data->name, (float)mob->dropitem[i].p / 100);
+ strcat(atcmd_output, atcmd_output2);
+ if (++j % 3 == 0) {
+ clif_displaymessage(fd, atcmd_output);
+ strcpy(atcmd_output, " ");
+ }
+ }
+ }
+ if (j == 0)
+ clif_displaymessage(fd, "This monster has no drop.");
+ else if (j % 3 != 0)
+ clif_displaymessage(fd, atcmd_output);
+ // mvp
+ if (mob->mexp) {
+ sprintf(atcmd_output, " MVP Bonus EXP:%d %02.02f%%", mob->mexp, (float)mob->mexpper / 100);
+ clif_displaymessage(fd, atcmd_output);
+ strcpy(atcmd_output, " MVP Items:");
+ j = 0;
+ for (i = 0; i < 3; i++) {
+ if (mob->mvpitem[i].nameid <= 0 || (item_data = itemdb_search(mob->mvpitem[i].nameid)) == NULL)
+ continue;
+ if (mob->mvpitem[i].p > 0) {
+ j++;
+ if (j == 1)
+ sprintf(atcmd_output2, " %s %02.02f%%", item_data->name, (float)mob->mvpitem[i].p / 100);
+ else
+ sprintf(atcmd_output2, " - %s %02.02f%%", item_data->name, (float)mob->mvpitem[i].p / 100);
+ strcat(atcmd_output, atcmd_output2);
+ }
+ }
+ if (j == 0)
+ clif_displaymessage(fd, "This monster has no MVP drop.");
+ else
+ clif_displaymessage(fd, atcmd_output);
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * @adopt by [Veider]
+ *
+ * adopt a novice
+ *------------------------------------------
+ */
+int
+atcommand_adopt(const int fd, struct map_session_data* sd,
+const char* command, const char* message)
+{
+ struct map_session_data *pl_sd1 = NULL;
+ struct map_session_data *pl_sd2 = NULL;
+ struct map_session_data *pl_sd3 = NULL;
+ char player1[255], player2[255], player3[255];
+
+ nullpo_retr(-1, sd);
+
+ if (!message || !*message)
+ return -1;
+
+ if (sscanf(message, "%[^,],%[^,],%[^\r\n]", player1, player2, player3) != 3) {
+ clif_displaymessage(fd, "usage: @adopt <player1> <player2> <player3>.");
+ return -1;
+ }
+
+ printf("Adopting: --%s--%s--%s--\n",player1,player2,player3);
+
+ if((pl_sd1=map_nick2sd((char *) player1)) == NULL) {
+ sprintf(player2, "Cannot find player %s online", player1);
+ clif_displaymessage(fd, player2);
+ return -1;
+ }
+
+ if((pl_sd2=map_nick2sd((char *) player2)) == NULL) {
+ sprintf(player1, "Cannot find player %s online", player2);
+ clif_displaymessage(fd, player1);
+ return -1;
+ }
+
+ if((pl_sd3=map_nick2sd((char *) player3)) == NULL) {
+ sprintf(player1, "Cannot find player %s online", player3);
+ clif_displaymessage(fd, player1);
+ return -1;
+ }
+
+ if((pl_sd1->status.base_level < 70) || (pl_sd2->status.base_level < 70)){
+ clif_displaymessage(fd, "They are too young to be parents!");
+ return -1;
+ }
+
+ if (pc_adoption(pl_sd1, pl_sd2, pl_sd3) == 0) {
+ clif_displaymessage(fd, "They are family.. wish them luck");
+ return 0;
+ }
+ else
+ return -1;
+}
+
diff --git a/src/map/atcommand.h b/src/map/atcommand.h
index 3d84cd5b9..1160dccb7 100644
--- a/src/map/atcommand.h
+++ b/src/map/atcommand.h
@@ -112,20 +112,20 @@ enum AtCommandType {
AtCommand_CharSkReset,
AtCommand_CharStReset,
//by chbrules
- AtCommand_CharModel,
+ AtCommand_CharModel,
AtCommand_CharSKPoint,
- AtCommand_CharSTPoint,
- AtCommand_CharZeny,
+ AtCommand_CharSTPoint,
+// AtCommand_CharZeny, //now #zeny
AtCommand_RecallAll,
AtCommand_ReloadItemDB,
AtCommand_ReloadMobDB,
AtCommand_ReloadSkillDB,
-#ifndef TXT_ONLY
- AtCommand_Rehash,
-#else /* TXT_ONLY */
AtCommand_ReloadScript,
-#endif /* TXT_ONLY */
AtCommand_ReloadGMDB,
+ AtCommand_ReloadAtcommand,
+ AtCommand_ReloadBattleConf,
+ AtCommand_ReloadStatusDB,
+ AtCommand_ReloadPcDB,
AtCommand_MapInfo,
AtCommand_Dye,
AtCommand_Hstyle,
@@ -143,8 +143,9 @@ enum AtCommandType {
AtCommand_RepairAll, // [Valaris]
AtCommand_GuildRecall, // by Yor
AtCommand_PartyRecall, // by Yor
-// AtCommand_Nuke, // [Valaris]
+ AtCommand_Nuke, // [Valaris]
AtCommand_Enablenpc,
+ AtCommand_Hidenpc,
AtCommand_Disablenpc,
AtCommand_ServerTime, // by Yor
AtCommand_CharDelItem, // by Yor
@@ -157,8 +158,8 @@ enum AtCommandType {
AtCommand_EMail, // by Yor
AtCommand_Hatch,
AtCommand_Effect, // by Apple
- AtCommand_Char_Item_List, // by Yor
- AtCommand_Char_Storage_List, // by Yor
+// AtCommand_Char_Item_List, // by Yor, now #itemlist
+// AtCommand_Char_Storage_List, // by Yor, now #storagelist
AtCommand_Char_Cart_List, // by Yor
AtCommand_AddWarp, // by MouseJstr
AtCommand_Follow, // by MouseJstr
@@ -168,10 +169,7 @@ enum AtCommandType {
AtCommand_NpcMove, // by MouseJstr
AtCommand_Killable, // by MouseJstr
AtCommand_CharKillable, // by MouseJstr
- AtCommand_Chareffect, // by MouseJstr
- AtCommand_Chardye, // by MouseJstr
- AtCommand_Charhairstyle, // by MouseJstr
- AtCommand_Charhaircolor, // by MouseJstr
+// AtCommand_Chareffect, // by MouseJstr, now #effect
AtCommand_Dropall, // by MouseJstr
AtCommand_Chardropall, // by MouseJstr
AtCommand_Storeall, // by MouseJstr
@@ -190,6 +188,7 @@ enum AtCommandType {
AtCommand_Send,
AtCommand_SetBattleFlag,
AtCommand_UnMute,
+ AtCommand_Clearweather, // by Dexity
AtCommand_UpTime, // by MC Cameri
AtCommand_ChangeSex, // by MC Cameri
AtCommand_Mute, // [celest]
@@ -200,9 +199,14 @@ enum AtCommandType {
AtCommand_Identify, // by MC Cameri
AtCommand_Gmotd, // Added by MC Cameri, created by davidsiaw
AtCommand_MiscEffect, // by MC Cameri
+ AtCommand_MobSearch,
+ AtCommand_CleanMap,
+ AtCommand_NpcTalk,
+ AtCommand_PetTalk,
+ AtCommand_Users,
// SQL-only commands start
-#ifndef TXT_ONLY
+#ifndef TXT_ONLY
AtCommand_CheckMail, // [Valaris]
AtCommand_ListMail, // [Valaris]
AtCommand_ListNewMail, // [Valaris]
@@ -210,12 +214,40 @@ enum AtCommandType {
AtCommand_SendMail, // [Valaris]
AtCommand_DeleteMail, // [Valaris]
AtCommand_SendPriorityMail, // [Valaris]
- AtCommand_Sound, // [Valaris]
+// AtCommand_Sound, // [Valaris]
AtCommand_RefreshOnline, // [Valaris]
// SQL-only commands end
#endif
AtCommand_SkillTree, // by MouseJstr
-
+ AtCommand_Marry, // by MouseJstr
+ AtCommand_Divorce, // by MouseJstr
+ AtCommand_Rings, // by MouseJstr
+ AtCommand_Grind, // by MouseJstr
+ AtCommand_Grind2, // by MouseJstr
+
+ AtCommand_DMStart, // by MouseJstr
+ AtCommand_DMTick, // by MouseJstr
+
+ AtCommand_JumpToId, // by Dino9021
+ AtCommand_JumpToId2, // by Dino9021
+ AtCommand_RecallId, // by Dino9021
+ AtCommand_RecallId2, // by Dino9021
+ AtCommand_KickId, // by Dino9021
+ AtCommand_KickId2, // by Dino9021
+ AtCommand_ReviveId, // by Dino9021
+ AtCommand_ReviveId2, // by Dino9021
+ AtCommand_KillId, // by Dino9021
+ AtCommand_KillId2, // by Dino9021
+ AtCommand_CharKillableId, // by Dino9021
+ AtCommand_CharKillableId2, // by Dino9021
+ AtCommand_Sound,
+ AtCommand_UndisguiseAll,
+ AtCommand_DisguiseAll,
+ AtCommand_ChangeLook,
+ AtCommand_AutoLoot, //by Upa-Kun
+ AtCommand_MobInfo, //by Lupus
+ AtCommand_Adopt, // by Veider
+
// end
AtCommand_Unknown,
AtCommand_MAX
@@ -235,6 +267,7 @@ AtCommandType
is_atcommand(const int fd, struct map_session_data* sd, const char* message, int gmlvl);
AtCommandType atcommand(
+ struct map_session_data *sd,
const int level, const char* message, AtCommandInfo* info);
int get_atcommand_level(const AtCommandType type);
@@ -248,11 +281,12 @@ int atcommand_recall(const int fd, struct map_session_data* sd, const char* comm
int atcommand_config_read(const char *cfgName);
int msg_config_read(const char *cfgName);
+void do_final_msg();
char *estr_lower(char *str);
-char * job_name(int class);
-int e_mail_check(unsigned char *email);
+char * job_name(int class_);
+int e_mail_check(char *email);
#endif
diff --git a/src/map/battle.c b/src/map/battle.c
index 00ca5a9e0..077e5fc9b 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -12,6 +12,7 @@
#include "map.h"
#include "pc.h"
+#include "status.h"
#include "skill.h"
#include "mob.h"
#include "itemdb.h"
@@ -55,1259 +56,21 @@ int battle_counttargeted(struct block_list *bl,struct block_list *src,int target
return mob_counttargeted((struct mob_data *)bl,src,target_lv);
return 0;
}
-/*==========================================
- * 対象のClassを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_class(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return ((struct mob_data *)bl)->class;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data *)bl)->status.class;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- return ((struct pet_data *)bl)->class;
- else
- return 0;
-}
-/*==========================================
- * 対象の方向を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_dir(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return ((struct mob_data *)bl)->dir;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data *)bl)->dir;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- return ((struct pet_data *)bl)->dir;
- else
- return 0;
-}
-/*==========================================
- * 対象のレベルを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_lv(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return ((struct mob_data *)bl)->level;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data *)bl)->status.base_level;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- return ((struct pet_data *)bl)->msd->pet.level;
- else
- return 0;
-}
-/*==========================================
- * 対象の射程を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_range(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return mob_db[((struct mob_data *)bl)->class].range;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data *)bl)->attackrange;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- return mob_db[((struct pet_data *)bl)->class].range;
- else
- return 0;
-}
-/*==========================================
- * 対象のHPを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_hp(struct block_list *bl)
-{
- nullpo_retr(1, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return ((struct mob_data *)bl)->hp;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data *)bl)->status.hp;
- else
- return 1;
-}
-/*==========================================
- * 対象のMHPを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_max_hp(struct block_list *bl)
-{
- nullpo_retr(1, bl);
- if(bl->type==BL_PC && ((struct map_session_data *)bl))
- return ((struct map_session_data *)bl)->status.max_hp;
- else {
- struct status_change *sc_data=battle_get_sc_data(bl);
- int max_hp=1;
- if(bl->type==BL_MOB && ((struct mob_data*)bl)) {
- max_hp = mob_db[((struct mob_data*)bl)->class].max_hp;
- if(battle_config.mobs_level_up) // mobs leveling up increase [Valaris]
- max_hp+=(((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv)*battle_get_vit(bl);
- if(mob_db[((struct mob_data*)bl)->class].mexp > 0) {
- if(battle_config.mvp_hp_rate != 100)
- max_hp = (max_hp * battle_config.mvp_hp_rate)/100;
- }
- else {
- if(battle_config.monster_hp_rate != 100)
- max_hp = (max_hp * battle_config.monster_hp_rate)/100;
- }
- }
- else if(bl->type==BL_PET && ((struct pet_data*)bl)) {
- max_hp = mob_db[((struct pet_data*)bl)->class].max_hp;
- if(mob_db[((struct pet_data*)bl)->class].mexp > 0) {
- if(battle_config.mvp_hp_rate != 100)
- max_hp = (max_hp * battle_config.mvp_hp_rate)/100;
- }
- else {
- if(battle_config.monster_hp_rate != 100)
- max_hp = (max_hp * battle_config.monster_hp_rate)/100;
- }
- }
- if(sc_data) {
- if(sc_data[SC_APPLEIDUN].timer!=-1)
- max_hp += ((5+sc_data[SC_APPLEIDUN].val1*2+((sc_data[SC_APPLEIDUN].val2+1)>>1)
- +sc_data[SC_APPLEIDUN].val3/10) * max_hp)/100;
- }
- if(max_hp < 1) max_hp = 1;
- return max_hp;
- }
- return 1;
-}
-/*==========================================
- * 対象のStrを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_str(struct block_list *bl)
-{
- int str=0;
- struct status_change *sc_data;
-
- nullpo_retr(0, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_MOB && ((struct mob_data *)bl)) {
- str = mob_db[((struct mob_data *)bl)->class].str;
- if(battle_config.mobs_level_up) // mobs leveling up increase [Valaris]
- str+=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv;
- }
- else if(bl->type==BL_PC && ((struct map_session_data *)bl))
- return ((struct map_session_data *)bl)->paramc[0];
- else if(bl->type==BL_PET && ((struct pet_data *)bl))
- str = mob_db[((struct pet_data *)bl)->class].str;
-
- if(sc_data) {
- if(sc_data[SC_LOUD].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1 && bl->type != BL_PC)
- str += 4;
- if( sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC){ // ブレッシング
- int race=battle_get_race(bl);
- if(battle_check_undead(race,battle_get_elem_type(bl)) || race==6 ) str >>= 1; // 悪 魔/不死
- else str += sc_data[SC_BLESSING].val1; // その他
- }
- if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // トゥルーサイト
- str += 5;
- }
- if(str < 0) str = 0;
- return str;
-}
-/*==========================================
- * 対象のAgiを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-
-int battle_get_agi(struct block_list *bl)
-{
- int agi=0;
- struct status_change *sc_data;
-
- nullpo_retr(0, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl) {
- agi=mob_db[((struct mob_data *)bl)->class].agi;
- if(battle_config.mobs_level_up) // increase of mobs leveling up [Valaris]
- agi+=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv;
- }
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- agi=((struct map_session_data *)bl)->paramc[1];
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- agi=mob_db[((struct pet_data *)bl)->class].agi;
-
- if(sc_data) {
- if( sc_data[SC_INCREASEAGI].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1 &&
- bl->type != BL_PC) // 速度増加(PCはpc.cで)
- agi += 2+sc_data[SC_INCREASEAGI].val1;
-
- if(sc_data[SC_CONCENTRATE].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1 && bl->type != BL_PC)
- agi += agi*(2+sc_data[SC_CONCENTRATE].val1)/100;
-
- if(sc_data[SC_DECREASEAGI].timer!=-1) // 速度減少
- agi -= 2+sc_data[SC_DECREASEAGI].val1;
-
- if(sc_data[SC_QUAGMIRE].timer!=-1 ) { // クァグマイア
- //agi >>= 1;
- int agib = agi*(sc_data[SC_QUAGMIRE].val1*10)/100;
- agi -= agib > 50 ? 50 : agib;
- }
- if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // トゥルーサイト
- agi += 5;
- }
- if(agi < 0) agi = 0;
- return agi;
-}
-/*==========================================
- * 対象のVitを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_vit(struct block_list *bl)
-{
- int vit=0;
- struct status_change *sc_data;
-
- nullpo_retr(0, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl) {
- vit=mob_db[((struct mob_data *)bl)->class].vit;
- if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris]
- vit+=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv;
- }
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- vit=((struct map_session_data *)bl)->paramc[2];
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- vit=mob_db[((struct pet_data *)bl)->class].vit;
- if(sc_data) {
- if(sc_data[SC_STRIPARMOR].timer != -1 && bl->type!=BL_PC)
- vit = vit*60/100;
- if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // トゥルーサイト
- vit += 5;
- }
-
- if(vit < 0) vit = 0;
- return vit;
-}
-/*==========================================
- * 対象のIntを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_int(struct block_list *bl)
-{
- int int_=0;
- struct status_change *sc_data;
-
- nullpo_retr(0, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl){
- int_=mob_db[((struct mob_data *)bl)->class].int_;
- if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris]
- int_+=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv;
- }
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- int_=((struct map_session_data *)bl)->paramc[3];
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- int_=mob_db[((struct pet_data *)bl)->class].int_;
-
- if(sc_data) {
- if( sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC){ // ブレッシング
- int race=battle_get_race(bl);
- if(battle_check_undead(race,battle_get_elem_type(bl)) || race==6 ) int_ >>= 1; // 悪 魔/不死
- else int_ += sc_data[SC_BLESSING].val1; // その他
- }
- if( sc_data[SC_STRIPHELM].timer != -1 && bl->type != BL_PC)
- int_ = int_*60/100;
- if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // トゥルーサイト
- int_ += 5;
- }
- if(int_ < 0) int_ = 0;
- return int_;
-}
-/*==========================================
- * 対象のDexを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_dex(struct block_list *bl)
-{
- int dex=0;
- struct status_change *sc_data;
-
- nullpo_retr(0, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl) {
- dex=mob_db[((struct mob_data *)bl)->class].dex;
- if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris]
- dex+=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv;
- }
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- dex=((struct map_session_data *)bl)->paramc[4];
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- dex=mob_db[((struct pet_data *)bl)->class].dex;
-
- if(sc_data) {
- if(sc_data[SC_CONCENTRATE].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1 && bl->type != BL_PC)
- dex += dex*(2+sc_data[SC_CONCENTRATE].val1)/100;
-
- if( sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC){ // ブレッシング
- int race=battle_get_race(bl);
- if(battle_check_undead(race,battle_get_elem_type(bl)) || race==6 ) dex >>= 1; // 悪 魔/不死
- else dex += sc_data[SC_BLESSING].val1; // その他
- }
-
- if(sc_data[SC_QUAGMIRE].timer!=-1 ) { // クァグマイア
- // dex >>= 1;
- int dexb = dex*(sc_data[SC_QUAGMIRE].val1*10)/100;
- dex -= dexb > 50 ? 50 : dexb;
- }
- if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // トゥルーサイト
- dex += 5;
- }
- if(dex < 0) dex = 0;
- return dex;
-}
-/*==========================================
- * 対象のLukを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_luk(struct block_list *bl)
-{
- int luk=0;
- struct status_change *sc_data;
-
- nullpo_retr(0, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl) {
- luk=mob_db[((struct mob_data *)bl)->class].luk;
- if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris]
- luk+=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv;
- }
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- luk=((struct map_session_data *)bl)->paramc[5];
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- luk=mob_db[((struct pet_data *)bl)->class].luk;
-
- if(sc_data) {
- if(sc_data[SC_GLORIA].timer!=-1 && bl->type != BL_PC) // グロリア(PCはpc.cで)
- luk += 30;
- if(sc_data[SC_CURSE].timer!=-1 ) // 呪い
- luk=0;
- if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // トゥルーサイト
- luk += 5;
- }
- if(luk < 0) luk = 0;
- return luk;
-}
-
-/*==========================================
- * 対象のFleeを返す(汎用)
- * 戻りは整数で1以上
- *------------------------------------------
- */
-int battle_get_flee(struct block_list *bl)
-{
- int flee=1;
- struct status_change *sc_data;
-
- nullpo_retr(1, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl)
- flee=((struct map_session_data *)bl)->flee;
- else
- flee=battle_get_agi(bl) + battle_get_lv(bl);
-
- if(sc_data) {
- if(sc_data[SC_WHISTLE].timer!=-1 && bl->type != BL_PC)
- flee += flee*(sc_data[SC_WHISTLE].val1+sc_data[SC_WHISTLE].val2
- +(sc_data[SC_WHISTLE].val3>>16))/100;
- if(sc_data[SC_BLIND].timer!=-1 && bl->type != BL_PC)
- flee -= flee*25/100;
- if(sc_data[SC_WINDWALK].timer!=-1 && bl->type != BL_PC) // ウィンドウォーク
- flee += flee*(sc_data[SC_WINDWALK].val2)/100;
- if(sc_data[SC_SPIDERWEB].timer!=-1 && bl->type != BL_PC) //スパイダーウェブ
- flee -= flee*50/100;
- }
- if(flee < 1) flee = 1;
- return flee;
-}
-/*==========================================
- * 対象のHitを返す(汎用)
- * 戻りは整数で1以上
- *------------------------------------------
- */
-int battle_get_hit(struct block_list *bl)
-{
- int hit=1;
- struct status_change *sc_data;
-
- nullpo_retr(1, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl)
- hit=((struct map_session_data *)bl)->hit;
- else
- hit=battle_get_dex(bl) + battle_get_lv(bl);
-
- if(sc_data) {
- if(sc_data[SC_HUMMING].timer!=-1 && bl->type != BL_PC) //
- hit += hit*(sc_data[SC_HUMMING].val1*2+sc_data[SC_HUMMING].val2
- +sc_data[SC_HUMMING].val3)/100;
- if(sc_data[SC_BLIND].timer!=-1 && bl->type != BL_PC) // 呪い
- hit -= hit*25/100;
- if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) // トゥルーサイト
- hit += 3*(sc_data[SC_TRUESIGHT].val1);
- if(sc_data[SC_CONCENTRATION].timer!=-1 && bl->type != BL_PC) //コンセントレーション
- hit += (hit*(10*(sc_data[SC_CONCENTRATION].val1)))/100;
- }
- if(hit < 1) hit = 1;
- return hit;
-}
-/*==========================================
- * 対象の完全回避を返す(汎用)
- * 戻りは整数で1以上
- *------------------------------------------
- */
-int battle_get_flee2(struct block_list *bl)
-{
- int flee2=1;
- struct status_change *sc_data;
-
- nullpo_retr(1, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl){
- flee2 = battle_get_luk(bl) + 10;
- flee2 += ((struct map_session_data *)bl)->flee2 - (((struct map_session_data *)bl)->paramc[5] + 10);
- }
- else
- flee2=battle_get_luk(bl)+1;
-
- if(sc_data) {
- if(sc_data[SC_WHISTLE].timer!=-1 && bl->type != BL_PC)
- flee2 += (sc_data[SC_WHISTLE].val1+sc_data[SC_WHISTLE].val2
- +(sc_data[SC_WHISTLE].val3&0xffff))*10;
- }
- if(flee2 < 1) flee2 = 1;
- return flee2;
-}
-/*==========================================
- * 対象のクリティカルを返す(汎用)
- * 戻りは整数で1以上
- *------------------------------------------
- */
-int battle_get_critical(struct block_list *bl)
-{
- int critical=1;
- struct status_change *sc_data;
-
- nullpo_retr(1, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl){
- critical = battle_get_luk(bl)*3 + 10;
- critical += ((struct map_session_data *)bl)->critical - ((((struct map_session_data *)bl)->paramc[5]*3) + 10);
- }
- else
- critical=battle_get_luk(bl)*3 + 1;
-
- if(sc_data) {
- if(sc_data[SC_FORTUNE].timer!=-1 && bl->type != BL_PC)
- critical += (10+sc_data[SC_FORTUNE].val1+sc_data[SC_FORTUNE].val2
- +sc_data[SC_FORTUNE].val3)*10;
- if(sc_data[SC_EXPLOSIONSPIRITS].timer!=-1 && bl->type != BL_PC)
- critical += sc_data[SC_EXPLOSIONSPIRITS].val2;
- if(sc_data[SC_TRUESIGHT].timer!=-1 && bl->type != BL_PC) //トゥルーサイト
- critical += critical*sc_data[SC_TRUESIGHT].val1/100;
- }
- if(critical < 1) critical = 1;
- return critical;
-}
-/*==========================================
- * base_atkの取得
- * 戻りは整数で1以上
- *------------------------------------------
- */
-int battle_get_baseatk(struct block_list *bl)
-{
- struct status_change *sc_data;
- int batk=1;
-
- nullpo_retr(1, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl)
- batk = ((struct map_session_data *)bl)->base_atk; //設定されているbase_atk
- else { //それ以外なら
- int str,dstr;
- str = battle_get_str(bl); //STR
- dstr = str/10;
- batk = dstr*dstr + str; //base_atkを計算する
- }
- if(sc_data) { //状態異常あり
- if(sc_data[SC_PROVOKE].timer!=-1 && bl->type != BL_PC) //PCでプロボック(SM_PROVOKE)状態
- batk = batk*(100+2*sc_data[SC_PROVOKE].val1)/100; //base_atk増加
- if(sc_data[SC_CURSE].timer!=-1 ) //呪われていたら
- batk -= batk*25/100; //base_atkが25%減少
- if(sc_data[SC_CONCENTRATION].timer!=-1 && bl->type != BL_PC) //コンセントレーション
- batk += batk*(5*sc_data[SC_CONCENTRATION].val1)/100;
- if(sc_data[SC_EDP].timer != -1) // [Celest]
- batk += batk*(50+50*sc_data[SC_EDP].val1)/100;
- }
- if(batk < 1) batk = 1; //base_atkは最低でも1
- return batk;
-}
-/*==========================================
- * 対象のAtkを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_atk(struct block_list *bl)
-{
- struct status_change *sc_data;
- int atk=0;
-
- nullpo_retr(0, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl)
- atk = ((struct map_session_data*)bl)->watk;
- else if(bl->type==BL_MOB && (struct mob_data *)bl)
- atk = mob_db[((struct mob_data*)bl)->class].atk1;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- atk = mob_db[((struct pet_data*)bl)->class].atk1;
-
- if(sc_data) {
- if(sc_data[SC_PROVOKE].timer!=-1 && bl->type != BL_PC)
- atk = atk*(100+2*sc_data[SC_PROVOKE].val1)/100;
- if(sc_data[SC_CURSE].timer!=-1 )
- atk -= atk*25/100;
- if(sc_data[SC_CONCENTRATION].timer!=-1 && bl->type != BL_PC) //コンセントレーション
- atk += atk*(5*sc_data[SC_CONCENTRATION].val1)/100;
- }
- if(atk < 0) atk = 0;
- return atk;
-}
-/*==========================================
- * 対象の左手Atkを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_atk_(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl){
- int atk=((struct map_session_data*)bl)->watk_;
-
- if(((struct map_session_data *)bl)->sc_data[SC_CURSE].timer!=-1 )
- atk -= atk*25/100;
- return atk;
- }
- else
- return 0;
-}
-/*==========================================
- * 対象のAtk2を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_atk2(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data*)bl)->watk2;
- else {
- struct status_change *sc_data=battle_get_sc_data(bl);
- int atk2=0;
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- atk2 = mob_db[((struct mob_data*)bl)->class].atk2;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- atk2 = mob_db[((struct pet_data*)bl)->class].atk2;
- if(sc_data) {
- if( sc_data[SC_IMPOSITIO].timer!=-1)
- atk2 += sc_data[SC_IMPOSITIO].val1*5;
- if( sc_data[SC_PROVOKE].timer!=-1 )
- atk2 = atk2*(100+2*sc_data[SC_PROVOKE].val1)/100;
- if( sc_data[SC_CURSE].timer!=-1 )
- atk2 -= atk2*25/100;
- if(sc_data[SC_DRUMBATTLE].timer!=-1)
- atk2 += sc_data[SC_DRUMBATTLE].val2;
- if(sc_data[SC_NIBELUNGEN].timer!=-1 && (battle_get_element(bl)/10) >= 8 )
- atk2 += sc_data[SC_NIBELUNGEN].val2;
- if(sc_data[SC_STRIPWEAPON].timer!=-1)
- atk2 = atk2*90/100;
- if(sc_data[SC_CONCENTRATION].timer!=-1) //コンセントレーション
- atk2 += atk2*(5*sc_data[SC_CONCENTRATION].val1)/100;
- }
- if(atk2 < 0) atk2 = 0;
- return atk2;
- }
- return 0;
-}
-/*==========================================
- * 対象の左手Atk2を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_atk_2(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data*)bl)->watk_2;
- else
- return 0;
-}
-/*==========================================
- * 対象のMAtk1を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_matk1(struct block_list *bl)
-{
- struct status_change *sc_data;
- nullpo_retr(0, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_MOB){
- int matk,int_=battle_get_int(bl);
- matk = int_+(int_/5)*(int_/5);
-
- if(sc_data)
- if(sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC)
- matk = matk*(100+2*sc_data[SC_MINDBREAKER].val1)/100;
- return matk;
- }
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data *)bl)->matk1;
- else if(bl->type==BL_PET){
- int matk,int_=battle_get_int(bl);
- matk = int_+(int_/5)*(int_/5);
-
- if(sc_data)
- if(sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC)
- matk = matk*(100+2*sc_data[SC_MINDBREAKER].val1)/100;
- return matk;
- }
- else
- return 0;
-}
-/*==========================================
- * 対象のMAtk2を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_matk2(struct block_list *bl)
-{
- struct status_change *sc_data=battle_get_sc_data(bl);
- nullpo_retr(0, bl);
- if(bl->type==BL_MOB){
- int matk,int_=battle_get_int(bl);
- matk = int_+(int_/7)*(int_/7);
-
- if(sc_data)
- if(sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC)
- matk = matk*(100+2*sc_data[SC_MINDBREAKER].val1)/100;
- return matk;
- }
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data *)bl)->matk2;
- else if(bl->type==BL_PET){
- int matk,int_=battle_get_int(bl);
- matk = int_+(int_/7)*(int_/7);
- if(sc_data)
- if(sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC)
- matk = matk*(100+2*sc_data[SC_MINDBREAKER].val1)/100;
- return matk;
- }
- else
- return 0;
-}
-/*==========================================
- * 対象のDefを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_def(struct block_list *bl)
-{
- struct status_change *sc_data;
- int def=0,skilltimer=-1,skillid=0;
-
- nullpo_retr(0, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl){
- def = ((struct map_session_data *)bl)->def;
- skilltimer = ((struct map_session_data *)bl)->skilltimer;
- skillid = ((struct map_session_data *)bl)->skillid;
- }
- else if(bl->type==BL_MOB && (struct mob_data *)bl) {
- def = mob_db[((struct mob_data *)bl)->class].def;
- skilltimer = ((struct mob_data *)bl)->skilltimer;
- skillid = ((struct mob_data *)bl)->skillid;
- }
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- def = mob_db[((struct pet_data *)bl)->class].def;
-
- if(def < 1000000) {
- if(sc_data) {
- //キーピング時はDEF100
- if( sc_data[SC_KEEPING].timer!=-1)
- def = 100;
- //プロボック時は減算
- if( sc_data[SC_PROVOKE].timer!=-1 && bl->type != BL_PC)
- def = (def*(100 - 6*sc_data[SC_PROVOKE].val1)+50)/100;
- //戦太鼓の響き時は加算
- if( sc_data[SC_DRUMBATTLE].timer!=-1 && bl->type != BL_PC)
- def += sc_data[SC_DRUMBATTLE].val3;
- //毒にかかっている時は減算
- if(sc_data[SC_POISON].timer!=-1 && bl->type != BL_PC)
- def = def*75/100;
- //ストリップシールド時は減算
- if(sc_data[SC_STRIPSHIELD].timer!=-1 && bl->type != BL_PC)
- def = def*85/100;
- //シグナムクルシス時は減算
- if(sc_data[SC_SIGNUMCRUCIS].timer!=-1 && bl->type != BL_PC)
- def = def * (100 - sc_data[SC_SIGNUMCRUCIS].val2)/100;
- //永遠の混沌時はDEF0になる
- if(sc_data[SC_ETERNALCHAOS].timer!=-1 && bl->type != BL_PC)
- def = 0;
- //凍結、石化時は右シフト
- if(sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0))
- def >>= 1;
- //コンセントレーション時は減算
- if( sc_data[SC_CONCENTRATION].timer!=-1 && bl->type != BL_PC)
- def = (def*(100 - 5*sc_data[SC_CONCENTRATION].val1))/100;
- }
- //詠唱中は詠唱時減算率に基づいて減算
- if(skilltimer != -1) {
- int def_rate = skill_get_castdef(skillid);
- if(def_rate != 0)
- def = (def * (100 - def_rate))/100;
- }
- }
- if(def < 0) def = 0;
- return def;
-}
-/*==========================================
- * 対象のMDefを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_mdef(struct block_list *bl)
-{
- struct status_change *sc_data;
- int mdef=0;
-
- nullpo_retr(0, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl)
- mdef = ((struct map_session_data *)bl)->mdef;
- else if(bl->type==BL_MOB && (struct mob_data *)bl)
- mdef = mob_db[((struct mob_data *)bl)->class].mdef;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- mdef = mob_db[((struct pet_data *)bl)->class].mdef;
-
- if(mdef < 1000000) {
- if(sc_data) {
- //バリアー状態時はMDEF100
- if(sc_data[SC_BARRIER].timer != -1)
- mdef = 100;
- //凍結、石化時は1.25倍
- if(sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0))
- mdef = mdef*125/100;
- if( sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC)
- mdef -= (mdef*6*sc_data[SC_MINDBREAKER].val1)/100;
- }
- }
- if(mdef < 0) mdef = 0;
- return mdef;
-}
-/*==========================================
- * 対象のDef2を返す(汎用)
- * 戻りは整数で1以上
- *------------------------------------------
- */
-int battle_get_def2(struct block_list *bl)
-{
- struct status_change *sc_data;
- int def2=1;
-
- nullpo_retr(1, bl);
- sc_data=battle_get_sc_data(bl);
- if(bl->type==BL_PC)
- def2 = ((struct map_session_data *)bl)->def2;
- else if(bl->type==BL_MOB)
- def2 = mob_db[((struct mob_data *)bl)->class].vit;
- else if(bl->type==BL_PET)
- def2 = mob_db[((struct pet_data *)bl)->class].vit;
-
- if(sc_data) {
- if( sc_data[SC_ANGELUS].timer!=-1 && bl->type != BL_PC)
- def2 = def2*(110+5*sc_data[SC_ANGELUS].val1)/100;
- if( sc_data[SC_PROVOKE].timer!=-1 && bl->type != BL_PC)
- def2 = (def2*(100 - 6*sc_data[SC_PROVOKE].val1)+50)/100;
- if(sc_data[SC_POISON].timer!=-1 && bl->type != BL_PC)
- def2 = def2*75/100;
- //コンセントレーション時は減算
- if( sc_data[SC_CONCENTRATION].timer!=-1 && bl->type != BL_PC)
- def2 = def2*(100 - 5*sc_data[SC_CONCENTRATION].val1)/100;
- }
- if(def2 < 1) def2 = 1;
- return def2;
-}
-/*==========================================
- * 対象のMDef2を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_mdef2(struct block_list *bl)
-{
- int mdef2=0;
- struct status_change *sc_data=battle_get_sc_data(bl);
-
- nullpo_retr(0, bl);
- if(bl->type==BL_MOB)
- mdef2 = mob_db[((struct mob_data *)bl)->class].int_ + (mob_db[((struct mob_data *)bl)->class].vit>>1);
- else if(bl->type==BL_PC)
- mdef2 = ((struct map_session_data *)bl)->mdef2 + (((struct map_session_data *)bl)->paramc[2]>>1);
- else if(bl->type==BL_PET)
- mdef2 = mob_db[((struct pet_data *)bl)->class].int_ + (mob_db[((struct pet_data *)bl)->class].vit>>1);
- if(sc_data) {
- if( sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC)
- mdef2 -= (mdef2*6*sc_data[SC_MINDBREAKER].val1)/100;
- }
- if(mdef2 < 0) mdef2 = 0;
- return mdef2;
-}
-/*==========================================
- * 対象のSpeed(移動速度)を返す(汎用)
- * 戻りは整数で1以上
- * Speedは小さいほうが移動速度が速い
- *------------------------------------------
- */
-int battle_get_speed(struct block_list *bl)
-{
- nullpo_retr(1000, bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data *)bl)->speed;
- else {
- struct status_change *sc_data=battle_get_sc_data(bl);
- int speed = 1000;
- if(bl->type==BL_MOB && (struct mob_data *)bl) {
- speed = ((struct mob_data *)bl)->speed;
- if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris]
- speed-=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class].lv;
- }
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- speed = ((struct pet_data *)bl)->msd->petDB->speed;
-
- if(sc_data) {
- //速度増加時は25%減算
- if(sc_data[SC_INCREASEAGI].timer!=-1 && sc_data[SC_DONTFORGETME].timer == -1)
- speed -= speed*25/100;
- //速度減少時は25%加算
- if(sc_data[SC_DECREASEAGI].timer!=-1)
- speed = speed*125/100;
- //クァグマイア時は50%加算
- if(sc_data[SC_QUAGMIRE].timer!=-1)
- speed = speed*3/2;
- //私を忘れないで…時は加算
- if(sc_data[SC_DONTFORGETME].timer!=-1)
- speed = speed*(100+sc_data[SC_DONTFORGETME].val1*2 + sc_data[SC_DONTFORGETME].val2 + (sc_data[SC_DONTFORGETME].val3&0xffff))/100;
- //金剛時は25%加算
- if(sc_data[SC_STEELBODY].timer!=-1)
- speed = speed*125/100;
- //ディフェンダー時は加算
- if(sc_data[SC_DEFENDER].timer!=-1)
- speed = (speed * (155 - sc_data[SC_DEFENDER].val1*5)) / 100;
- //踊り状態は4倍遅い
- if(sc_data[SC_DANCING].timer!=-1 )
- speed*=4;
- //呪い時は450加算
- if(sc_data[SC_CURSE].timer!=-1)
- speed = speed + 450;
- //ウィンドウォーク時はLv*2%減算
- if(sc_data[SC_WINDWALK].timer!=-1)
- speed -= (speed*(sc_data[SC_WINDWALK].val1*2))/100;
- if(sc_data[SC_SLOWDOWN].timer!=-1)
- speed = speed*150/100;
- }
- if(speed < 1) speed = 1;
- return speed;
- }
-
- return 1000;
-}
-/*==========================================
- * 対象のaDelay(攻撃時ディレイ)を返す(汎用)
- * aDelayは小さいほうが攻撃速度が速い
- *------------------------------------------
- */
-int battle_get_adelay(struct block_list *bl)
-{
- nullpo_retr(4000, bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl)
- return (((struct map_session_data *)bl)->aspd<<1);
- else {
- struct status_change *sc_data=battle_get_sc_data(bl);
- int adelay=4000,aspd_rate = 100,i;
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- adelay = mob_db[((struct mob_data *)bl)->class].adelay;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- adelay = mob_db[((struct pet_data *)bl)->class].adelay;
-
- if(sc_data) {
- //ツーハンドクイッケン使用時でクァグマイアでも私を忘れないで…でもない時は3割減算
- if(sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
- aspd_rate -= 30;
- //アドレナリンラッシュ使用時でツーハンドクイッケンでもクァグマイアでも私を忘れないで…でもない時は
- if(sc_data[SC_ADRENALINE].timer != -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 &&
- sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) { // アドレナリンラッシュ
- //使用者とパーティメンバーで格差が出る設定でなければ3割減算
- if(sc_data[SC_ADRENALINE].val2 || !battle_config.party_skill_penaly)
- aspd_rate -= 30;
- //そうでなければ2.5割減算
- else
- aspd_rate -= 25;
- }
- //スピアクィッケン時は減算
- if(sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 &&
- sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // スピアクィッケン
- aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2;
- //夕日のアサシンクロス時は減算
- if(sc_data[SC_ASSNCROS].timer!=-1 && // 夕陽のアサシンクロス
- sc_data[SC_TWOHANDQUICKEN].timer==-1 && sc_data[SC_ADRENALINE].timer==-1 && sc_data[SC_SPEARSQUICKEN].timer==-1 &&
- sc_data[SC_DONTFORGETME].timer == -1)
- aspd_rate -= 5+sc_data[SC_ASSNCROS].val1+sc_data[SC_ASSNCROS].val2+sc_data[SC_ASSNCROS].val3;
- //私を忘れないで…時は加算
- if(sc_data[SC_DONTFORGETME].timer!=-1) // 私を忘れないで
- aspd_rate += sc_data[SC_DONTFORGETME].val1*3 + sc_data[SC_DONTFORGETME].val2 + (sc_data[SC_DONTFORGETME].val3>>16);
- //金剛時25%加算
- if(sc_data[SC_STEELBODY].timer!=-1) // 金剛
- aspd_rate += 25;
- //増速ポーション使用時は減算
- if( sc_data[i=SC_SPEEDPOTION2].timer!=-1 || sc_data[i=SC_SPEEDPOTION1].timer!=-1 || sc_data[i=SC_SPEEDPOTION0].timer!=-1)
- aspd_rate -= sc_data[i].val2;
- //ディフェンダー時は加算
- if(sc_data[SC_DEFENDER].timer != -1)
- adelay += (1100 - sc_data[SC_DEFENDER].val1*100);
- }
- if(aspd_rate != 100)
- adelay = adelay*aspd_rate/100;
- if(adelay < battle_config.monster_max_aspd<<1) adelay = battle_config.monster_max_aspd<<1;
- return adelay;
- }
- return 4000;
-}
-int battle_get_amotion(struct block_list *bl)
-{
- nullpo_retr(2000, bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data *)bl)->amotion;
- else {
- struct status_change *sc_data=battle_get_sc_data(bl);
- int amotion=2000,aspd_rate = 100,i;
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- amotion = mob_db[((struct mob_data *)bl)->class].amotion;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- amotion = mob_db[((struct pet_data *)bl)->class].amotion;
-
- if(sc_data) {
- if(sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
- aspd_rate -= 30;
- if(sc_data[SC_ADRENALINE].timer != -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 &&
- sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) { // アドレナリンラッシュ
- if(sc_data[SC_ADRENALINE].val2 || !battle_config.party_skill_penaly)
- aspd_rate -= 30;
- else
- aspd_rate -= 25;
- }
- if(sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 &&
- sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // スピアクィッケン
- aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2;
- if(sc_data[SC_ASSNCROS].timer!=-1 && // 夕陽のアサシンクロス
- sc_data[SC_TWOHANDQUICKEN].timer==-1 && sc_data[SC_ADRENALINE].timer==-1 && sc_data[SC_SPEARSQUICKEN].timer==-1 &&
- sc_data[SC_DONTFORGETME].timer == -1)
- aspd_rate -= 5+sc_data[SC_ASSNCROS].val1+sc_data[SC_ASSNCROS].val2+sc_data[SC_ASSNCROS].val3;
- if(sc_data[SC_DONTFORGETME].timer!=-1) // 私を忘れないで
- aspd_rate += sc_data[SC_DONTFORGETME].val1*3 + sc_data[SC_DONTFORGETME].val2 + (sc_data[SC_DONTFORGETME].val3>>16);
- if(sc_data[SC_STEELBODY].timer!=-1) // 金剛
- aspd_rate += 25;
- if( sc_data[i=SC_SPEEDPOTION2].timer!=-1 || sc_data[i=SC_SPEEDPOTION1].timer!=-1 || sc_data[i=SC_SPEEDPOTION0].timer!=-1)
- aspd_rate -= sc_data[i].val2;
- if(sc_data[SC_DEFENDER].timer != -1)
- amotion += (550 - sc_data[SC_DEFENDER].val1*50);
- }
- if(aspd_rate != 100)
- amotion = amotion*aspd_rate/100;
- if(amotion < battle_config.monster_max_aspd) amotion = battle_config.monster_max_aspd;
- return amotion;
- }
- return 2000;
-}
-int battle_get_dmotion(struct block_list *bl)
-{
- int ret;
- struct status_change *sc_data;
-
- nullpo_retr(0, bl);
- sc_data = battle_get_sc_data(bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl){
- ret=mob_db[((struct mob_data *)bl)->class].dmotion;
- if(battle_config.monster_damage_delay_rate != 100)
- ret = ret*battle_config.monster_damage_delay_rate/400;
- }
- else if(bl->type==BL_PC && (struct map_session_data *)bl){
- ret=((struct map_session_data *)bl)->dmotion;
- if(battle_config.pc_damage_delay_rate != 100)
- ret = ret*battle_config.pc_damage_delay_rate/400;
- }
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- ret=mob_db[((struct pet_data *)bl)->class].dmotion;
- else
- return 2000;
-
- if((sc_data && (sc_data[SC_ENDURE].timer!=-1 || sc_data[SC_BERSERK].timer!=-1)) ||
- (bl->type == BL_PC && ((struct map_session_data *)bl)->special_state.infinite_endure))
- ret=0;
-
- return ret;
-}
-int battle_get_element(struct block_list *bl)
-{
- int ret = 20;
- struct status_change *sc_data;
-
- nullpo_retr(ret, bl);
- sc_data = battle_get_sc_data(bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl) // 10の位=Lv*2、1の位=属性
- ret=((struct mob_data *)bl)->def_ele;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- ret=20+((struct map_session_data *)bl)->def_ele; // 防御属性Lv1
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- ret = mob_db[((struct pet_data *)bl)->class].element;
-
- if(sc_data) {
- if( sc_data[SC_BENEDICTIO].timer!=-1 ) // 聖体降福
- ret=26;
- if( sc_data[SC_FREEZE].timer!=-1 ) // 凍結
- ret=21;
- if( sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0)
- ret=22;
- }
-
- return ret;
-}
-int battle_get_attack_element(struct block_list *bl)
-{
- int ret = 0;
- struct status_change *sc_data=battle_get_sc_data(bl);
-
- nullpo_retr(0, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- ret=0;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- ret=((struct map_session_data *)bl)->atk_ele;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- ret=0;
-
- if(sc_data) {
- if( sc_data[SC_FROSTWEAPON].timer!=-1) // フロストウェポン
- ret=1;
- if( sc_data[SC_SEISMICWEAPON].timer!=-1) // サイズミックウェポン
- ret=2;
- if( sc_data[SC_FLAMELAUNCHER].timer!=-1) // フレームランチャー
- ret=3;
- if( sc_data[SC_LIGHTNINGLOADER].timer!=-1) // ライトニングローダー
- ret=4;
- if( sc_data[SC_ENCPOISON].timer!=-1) // エンチャントポイズン
- ret=5;
- if( sc_data[SC_ASPERSIO].timer!=-1) // アスペルシオ
- ret=6;
- }
-
- return ret;
-}
-int battle_get_attack_element2(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl) {
- int ret = ((struct map_session_data *)bl)->atk_ele_;
- struct status_change *sc_data = ((struct map_session_data *)bl)->sc_data;
-
- if(sc_data) {
- if( sc_data[SC_FROSTWEAPON].timer!=-1) // フロストウェポン
- ret=1;
- if( sc_data[SC_SEISMICWEAPON].timer!=-1) // サイズミックウェポン
- ret=2;
- if( sc_data[SC_FLAMELAUNCHER].timer!=-1) // フレームランチャー
- ret=3;
- if( sc_data[SC_LIGHTNINGLOADER].timer!=-1) // ライトニングローダー
- ret=4;
- if( sc_data[SC_ENCPOISON].timer!=-1) // エンチャントポイズン
- ret=5;
- if( sc_data[SC_ASPERSIO].timer!=-1) // アスペルシオ
- ret=6;
- }
- return ret;
- }
- return 0;
-}
-int battle_get_party_id(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data *)bl)->status.party_id;
- else if(bl->type==BL_MOB && (struct mob_data *)bl){
- struct mob_data *md=(struct mob_data *)bl;
- if( md->master_id>0 )
- return -md->master_id;
- return -md->bl.id;
- }
- else if(bl->type==BL_SKILL && (struct skill_unit *)bl)
- return ((struct skill_unit *)bl)->group->party_id;
- else
- return 0;
-}
-int battle_get_guild_id(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data *)bl)->status.guild_id;
- else if(bl->type==BL_MOB && (struct mob_data *)bl)
- return ((struct mob_data *)bl)->class;
- else if(bl->type==BL_SKILL && (struct skill_unit *)bl)
- return ((struct skill_unit *)bl)->group->guild_id;
- else
- return 0;
-}
-int battle_get_race(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return mob_db[((struct mob_data *)bl)->class].race;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return 7;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- return mob_db[((struct pet_data *)bl)->class].race;
- else
- return 0;
-}
-int battle_get_size(struct block_list *bl)
-{
- nullpo_retr(1, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return mob_db[((struct mob_data *)bl)->class].size;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return 1;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- return mob_db[((struct pet_data *)bl)->class].size;
- else
- return 1;
-}
-int battle_get_mode(struct block_list *bl)
-{
- nullpo_retr(0x01, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return mob_db[((struct mob_data *)bl)->class].mode;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- return mob_db[((struct pet_data *)bl)->class].mode;
- else
- return 0x01; // とりあえず動くということで1
-}
-
-int battle_get_mexp(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return mob_db[((struct mob_data *)bl)->class].mexp;
- else if(bl->type==BL_PET && (struct pet_data *)bl)
- return mob_db[((struct pet_data *)bl)->class].mexp;
- else
- return 0;
-}
-
-// StatusChange系の所得
-struct status_change *battle_get_sc_data(struct block_list *bl)
-{
- nullpo_retr(NULL, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return ((struct mob_data*)bl)->sc_data;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data*)bl)->sc_data;
- return NULL;
-}
-short *battle_get_sc_count(struct block_list *bl)
-{
- nullpo_retr(NULL, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return &((struct mob_data*)bl)->sc_count;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return &((struct map_session_data*)bl)->sc_count;
- return NULL;
-}
-short *battle_get_opt1(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return &((struct mob_data*)bl)->opt1;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return &((struct map_session_data*)bl)->opt1;
- else if(bl->type==BL_NPC && (struct npc_data *)bl)
- return &((struct npc_data*)bl)->opt1;
- return 0;
-}
-short *battle_get_opt2(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return &((struct mob_data*)bl)->opt2;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return &((struct map_session_data*)bl)->opt2;
- else if(bl->type==BL_NPC && (struct npc_data *)bl)
- return &((struct npc_data*)bl)->opt2;
- return 0;
-}
-short *battle_get_opt3(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return &((struct mob_data*)bl)->opt3;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return &((struct map_session_data*)bl)->opt3;
- else if(bl->type==BL_NPC && (struct npc_data *)bl)
- return &((struct npc_data*)bl)->opt3;
- return 0;
-}
-short *battle_get_option(struct block_list *bl)
-{
- nullpo_retr(0, bl);
- if(bl->type==BL_MOB && (struct mob_data *)bl)
- return &((struct mob_data*)bl)->option;
- else if(bl->type==BL_PC && (struct map_session_data *)bl)
- return &((struct map_session_data*)bl)->status.option;
- else if(bl->type==BL_NPC && (struct npc_data *)bl)
- return &((struct npc_data*)bl)->option;
- return 0;
-}
-
-//-------------------------------------------------------------------
// ダメージの遅延
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);
- free(dat);
+ 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;
}
int battle_delay_damage(unsigned int tick,struct block_list *src,struct block_list *target,int damage,int flag)
@@ -1319,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);
@@ -1330,7 +93,7 @@ int battle_delay_damage(unsigned int tick,struct block_list *src,struct block_li
int battle_damage(struct block_list *bl,struct block_list *target,int damage,int flag)
{
struct map_session_data *sd=NULL;
- struct status_change *sc_data=battle_get_sc_data(target);
+ struct status_change *sc_data=status_get_sc_data(target);
short *sc_count;
int i;
@@ -1353,14 +116,14 @@ int battle_damage(struct block_list *bl,struct block_list *target,int damage,int
if(damage<0)
return battle_heal(bl,target,-damage,0,flag);
- if(!flag && (sc_count=battle_get_sc_count(target))!=NULL && *sc_count>0){
+ if(!flag && (sc_count=status_get_sc_count(target))!=NULL && *sc_count>0){
// 凍結、石化、睡眠を消去
if(sc_data[SC_FREEZE].timer!=-1)
- skill_status_change_end(target,SC_FREEZE,-1);
+ status_change_end(target,SC_FREEZE,-1);
if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0)
- skill_status_change_end(target,SC_STONE,-1);
+ status_change_end(target,SC_STONE,-1);
if(sc_data[SC_SLEEP].timer!=-1)
- skill_status_change_end(target,SC_SLEEP,-1);
+ status_change_end(target,SC_SLEEP,-1);
}
if(target->type==BL_MOB){ // MOB
@@ -1479,29 +242,35 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
struct mob_data *md=NULL;
struct status_change *sc_data,*sc;
short *sc_count;
- int class;
+ int class_;
nullpo_retr(0, bl);
- class = battle_get_class(bl);
+ class_ = status_get_class(bl);
if(bl->type==BL_MOB) md=(struct mob_data *)bl;
else sd=(struct map_session_data *)bl;
- sc_data=battle_get_sc_data(bl);
- sc_count=battle_get_sc_count(bl);
+ sc_data=status_get_sc_data(bl);
+ sc_count=status_get_sc_count(bl);
if(sc_count!=NULL && *sc_count>0){
-
- if(sc_data[SC_SAFETYWALL].timer!=-1 && damage>0 && flag&BF_WEAPON && flag&BF_SHORT && skill_num != NPC_GUIDEDATTACK){
+ if (sc_data[SC_SAFETYWALL].timer!=-1 && damage>0 && flag&BF_WEAPON &&
+ flag&BF_SHORT && skill_num != NPC_GUIDEDATTACK) {
// セーフティウォール
- struct skill_unit *unit=(struct skill_unit*)sc_data[SC_SAFETYWALL].val2;
- if( unit && unit->alive && (--unit->group->val2)<=0 )
- skill_delunit(unit);
- skill_unit_move(bl,gettick(),1); // 重ね掛けチェック
- damage=0;
+ struct skill_unit *unit;
+ unit = (struct skill_unit *)sc_data[SC_SAFETYWALL].val2;
+ if (unit) {
+ if (unit->group && (--unit->group->val2)<=0)
+ skill_delunit(unit);
+ damage=0;
+ } else {
+ status_change_end(bl,SC_SAFETYWALL,-1);
+ }
}
- if(sc_data[SC_PNEUMA].timer!=-1 && damage>0 && ((flag&BF_WEAPON && flag&BF_LONG && skill_num != NPC_GUIDEDATTACK) ||
- (flag&BF_MISC && (skill_num == HT_BLITZBEAT || skill_num == SN_FALCONASSAULT)))){ // [DracoRPG]
+ if(sc_data[SC_PNEUMA].timer!=-1 && damage>0 &&
+ ((flag&BF_WEAPON && flag&BF_LONG && skill_num != NPC_GUIDEDATTACK) ||
+ (flag&BF_MISC && (skill_num == HT_BLITZBEAT || skill_num == SN_FALCONASSAULT)) ||
+ (flag&BF_MAGIC && skill_num == ASC_BREAKER))){ // [DracoRPG]
// ニューマ
damage=0;
}
@@ -1514,29 +283,35 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
if(sc_data[SC_AETERNA].timer!=-1 && damage>0){ // レックスエーテルナ
damage<<=1;
- skill_status_change_end( bl,SC_AETERNA,-1 );
+ status_change_end( bl,SC_AETERNA,-1 );
}
//属性場のダメージ増加
if(sc_data[SC_VOLCANO].timer!=-1){ // ボルケーノ
if(flag&BF_SKILL && skill_get_pl(skill_num)==3)
- damage += damage*sc_data[SC_VOLCANO].val4/100;
- else if(!flag&BF_SKILL && battle_get_attack_element(bl)==3)
- damage += damage*sc_data[SC_VOLCANO].val4/100;
+ //damage += damage*sc_data[SC_VOLCANO].val4/100;
+ damage += damage * enchant_eff[sc_data[SC_VOLCANO].val1-1] /100;
+ else if(!flag&BF_SKILL && status_get_attack_element(bl)==3)
+ //damage += damage*sc_data[SC_VOLCANO].val4/100;
+ damage += damage * enchant_eff[sc_data[SC_VOLCANO].val1-1] /100;
}
if(sc_data[SC_VIOLENTGALE].timer!=-1){ // バイオレントゲイル
if(flag&BF_SKILL && skill_get_pl(skill_num)==4)
- damage += damage*sc_data[SC_VIOLENTGALE].val4/100;
- else if(!flag&BF_SKILL && battle_get_attack_element(bl)==4)
- damage += damage*sc_data[SC_VIOLENTGALE].val4/100;
+ //damage += damage*sc_data[SC_VIOLENTGALE].val4/100;
+ damage += damage * enchant_eff[sc_data[SC_VIOLENTGALE].val1-1] /100;
+ else if(!flag&BF_SKILL && status_get_attack_element(bl)==4)
+ //damage += damage*sc_data[SC_VIOLENTGALE].val4/100;
+ damage += damage * enchant_eff[sc_data[SC_VIOLENTGALE].val1-1] /100;
}
if(sc_data[SC_DELUGE].timer!=-1){ // デリュージ
if(flag&BF_SKILL && skill_get_pl(skill_num)==1)
- damage += damage*sc_data[SC_DELUGE].val4/100;
- else if(!flag&BF_SKILL && battle_get_attack_element(bl)==1)
- damage += damage*sc_data[SC_DELUGE].val4/100;
+ //damage += damage*sc_data[SC_DELUGE].val4/100;
+ damage += damage * enchant_eff[sc_data[SC_DELUGE].val1-1] /100;
+ else if(!flag&BF_SKILL && status_get_attack_element(bl)==1)
+ //damage += damage*sc_data[SC_DELUGE].val4/100;
+ damage += damage * enchant_eff[sc_data[SC_DELUGE].val1-1] /100;
}
if(sc_data[SC_ENERGYCOAT].timer!=-1 && damage>0 && flag&BF_WEAPON){ // エナジーコート
@@ -1549,7 +324,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
clif_updatestatus(sd,SP_SP);
}
if(sd->status.sp<=0)
- skill_status_change_end( bl,SC_ENERGYCOAT,-1 );
+ status_change_end( bl,SC_ENERGYCOAT,-1 );
}
else
damage -= damage * (sc_data[SC_ENERGYCOAT].val1 * 6) / 100;
@@ -1563,7 +338,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
else damage=-sc->val2;
}
if((--sc->val3)<=0 || (sc->val2<=0) || skill_num == AL_HOLYLIGHT)
- skill_status_change_end(bl, SC_KYRIE, -1);
+ status_change_end(bl, SC_KYRIE, -1);
}
if(sc_data[SC_BASILICA].timer!=-1 && damage > 0){
@@ -1577,12 +352,21 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
if(sc_data[SC_AUTOGUARD].timer != -1 && damage > 0 && flag&BF_WEAPON) {
if(rand()%100 < sc_data[SC_AUTOGUARD].val2) {
+ int delay;
+
damage = 0;
clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sc_data[SC_AUTOGUARD].val1,1);
+ // different delay depending on skill level [celest]
+ if (sc_data[SC_AUTOGUARD].val1 <= 5)
+ delay = 300;
+ else if (sc_data[SC_AUTOGUARD].val1 > 5 && sc_data[SC_AUTOGUARD].val1 <= 9)
+ delay = 200;
+ else
+ delay = 100;
if(sd)
- sd->canmove_tick = gettick() + 300;
+ sd->canmove_tick = gettick() + delay;
else if(md)
- md->canmove_tick = gettick() + 300;
+ md->canmove_tick = gettick() + delay;
}
}
// -- moonsoul (chance to block attacks with new Lord Knight skill parrying)
@@ -1595,39 +379,43 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
}
// リジェクトソード
if(sc_data[SC_REJECTSWORD].timer!=-1 && damage > 0 && flag&BF_WEAPON &&
- ((src->type==BL_PC && ((struct map_session_data *)src)->status.weapon == (1 || 2 || 3)) || src->type==BL_MOB )){
+ // Fixed the condition check [Aalye]
+ (src->type==BL_MOB || (src->type==BL_PC && (((struct map_session_data *)src)->status.weapon == 1 ||
+ ((struct map_session_data *)src)->status.weapon == 2 ||
+ ((struct map_session_data *)src)->status.weapon == 3)))){
if(rand()%100 < (15*sc_data[SC_REJECTSWORD].val1)){ //反射確率は15*Lv
damage = damage*50/100;
+ clif_damage(bl,src,gettick(),0,0,damage,0,0,0);
battle_damage(bl,src,damage,0);
//ダメージを与えたのは良いんだが、ここからどうして表示するんだかわかんねぇ
//エフェクトもこれでいいのかわかんねぇ
clif_skill_nodamage(bl,bl,ST_REJECTSWORD,sc_data[SC_REJECTSWORD].val1,1);
if((--sc_data[SC_REJECTSWORD].val2)<=0)
- skill_status_change_end(bl, SC_REJECTSWORD, -1);
+ status_change_end(bl, SC_REJECTSWORD, -1);
}
}
if(sc_data[SC_SPIDERWEB].timer!=-1 && damage > 0) // [Celest]
if ((flag&BF_SKILL && skill_get_pl(skill_num)==3) ||
- (!flag&BF_SKILL && battle_get_attack_element(src)==3)) {
+ (!flag&BF_SKILL && status_get_attack_element(src)==3)) {
damage<<=1;
- skill_status_change_end(bl, SC_SPIDERWEB, -1);
+ status_change_end(bl, SC_SPIDERWEB, -1);
}
-
+
if(sc_data[SC_FOGWALL].timer != -1 && flag&BF_MAGIC)
- if(rand()%100 < sc_data[SC_FOGWALL].val2)
+ if(rand()%100 < 75)
damage = 0;
}
- if(class == 1288 || class == 1287 || class == 1286 || class == 1285) {
-// if(class == 1288) {
- if(class == 1288 && flag&BF_SKILL)
+ if(class_ == 1288 || class_ == 1287 || class_ == 1286 || class_ == 1285) {
+// if(class_ == 1288) {
+ if(class_ == 1288 && (flag&BF_SKILL || skill_num == ASC_BREAKER || skill_num == PA_SACRIFICE))
damage=0;
if(src->type == BL_PC) {
struct guild *g=guild_search(((struct map_session_data *)src)->status.guild_id);
struct guild_castle *gc=guild_mapname2gc(map[bl->m].name);
if(!((struct map_session_data *)src)->status.guild_id)
damage=0;
- if(gc && agit_flag==0 && class != 1288) // guardians cannot be damaged during non-woe [Valaris]
+ if(gc && agit_flag==0 && class_ != 1288) // guardians cannot be damaged during non-woe [Valaris]
damage=0; // end woe check [Valaris]
if(g == NULL)
damage=0;//ギルド未加入ならダメージ無し
@@ -1636,12 +424,18 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
else if(g && guild_checkskill(g,GD_APPROVAL) <= 0)
damage=0;//正規ギルド承認がないとダメージ無し
else if (battle_config.guild_max_castles != 0 && guild_checkcastles(g)>=battle_config.guild_max_castles)
- damage = 0; // [MouseJstr]
+ damage = 0; // [MouseJstr]
+ else if (g && gc && guild_check_alliance(gc->guild_id, g->guild_id, 0) == 1)
+ return 0;
}
else damage = 0;
}
if(map[bl->m].flag.gvg && damage > 0) { //GvG
+ if(bl->type == BL_MOB){ //defenseがあればダメージが減るらしい?
+ struct guild_castle *gc=guild_mapname2gc(map[bl->m].name);
+ if (gc) damage -= damage*(gc->defense/100)*(battle_config.castle_defense_rate/100);
+ }
if(flag&BF_WEAPON) {
if(flag&BF_SHORT)
damage=damage*battle_config.gvg_short_damage_rate/100;
@@ -1671,20 +465,47 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
}
/*==========================================
+ * HP/SP吸収の計算
+ *------------------------------------------
+ */
+int battle_calc_drain(int damage, int rate, int per, int val)
+{
+ int diff = 0;
+
+ if (damage <= 0 || rate <= 0)
+ return 0;
+
+ if (per && rand()%100 < rate) {
+ diff = (damage * per) / 100;
+ if (diff == 0) {
+ if (per > 0)
+ diff = 1;
+ else
+ diff = -1;
+ }
+ }
+
+ if (val && rand()%100 < rate) {
+ diff += val;
+ }
+ return diff;
+}
+
+/*==========================================
* 修練ダメージ
*------------------------------------------
*/
int battle_addmastery(struct map_session_data *sd,struct block_list *target,int dmg,int type)
{
int damage,skill;
- int race=battle_get_race(target);
+ int race=status_get_race(target);
int weapon;
damage = 0;
nullpo_retr(0, sd);
// デーモンベイン(+3 〜 +30) vs 不死 or 悪魔 (死人は含めない?)
- if((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 && (battle_check_undead(race,battle_get_elem_type(target)) || race==6) )
+ if((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 && (battle_check_undead(race,status_get_elem_type(target)) || race==6) )
damage += (skill*(int)(3+(sd->status.base_level+1)*0.05)); // submitted by orn
//damage += (skill * 3);
@@ -1698,7 +519,7 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int
weapon = sd->weapontype2;
switch(weapon)
{
- case 0x01: // 短剣 (Updated By AppleGirl)
+ case 0x01: // 短剣 Knife
case 0x02: // 1HS
{
// 剣修練(+4 〜 +40) 片手剣 短剣含む
@@ -1716,16 +537,6 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int
break;
}
case 0x04: // 1HL
- {
- // 槍修練(+4 〜 +40,+5 〜 +50) 槍
- if((skill = pc_checkskill(sd,KN_SPEARMASTERY)) > 0) {
- if(!pc_isriding(sd))
- damage += (skill * 4); // ペコに乗ってない
- else
- damage += (skill * 5); // ペコに乗ってる
- }
- break;
- }
case 0x05: // 2HL
{
// 槍修練(+4 〜 +40,+5 〜 +50) 槍
@@ -1737,13 +548,7 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int
}
break;
}
- case 0x06: // 片手斧
- {
- if((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0) {
- damage += (skill * 3);
- }
- break;
- }
+ case 0x06: // 片手斧
case 0x07: // Axe by Tato
{
if((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0) {
@@ -1765,7 +570,7 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int
break;
case 0x0b: // 弓
break;
- case 0x00: // 素手
+ case 0x00: // 素手 Bare Hands
case 0x0c: // Knuckles
{
// 鉄拳(+3 〜 +30) 素手,ナックル
@@ -1819,14 +624,16 @@ static struct Damage battle_calc_pet_weapon_attack(
struct mob_data *tmd=NULL;
int hitrate,flee,cri = 0,atkmin,atkmax;
int luk,target_count = 1;
- int def1 = battle_get_def(target);
- int def2 = battle_get_def2(target);
- int t_vit = battle_get_vit(target);
+ int def1 = status_get_def(target);
+ int def2 = status_get_def2(target);
+ int t_vit = status_get_vit(target);
struct Damage wd;
int damage,damage2=0,type,div_,blewcount=skill_get_blewcount(skill_num,skill_lv);
int flag,dmg_lv=0;
int t_mode=0,t_race=0,t_size=1,s_race=0,s_ele=0;
struct status_change *t_sc_data;
+ int div_flag=0; // 0: total damage is to be divided by div_
+ // 1: damage is distributed,and has to be multiplied by div_ [celest]
//return前の処理があるので情報出力部のみ変更
if( target == NULL || pd == NULL ){ //srcは内容に直接触れていないのでスルーしてみる
@@ -1835,8 +642,8 @@ static struct Damage battle_calc_pet_weapon_attack(
return wd;
}
- s_race=battle_get_race(src);
- s_ele=battle_get_attack_element(src);
+ s_race=status_get_race(src);
+ s_ele=status_get_attack_element(src);
// ターゲット
if(target->type == BL_MOB)
@@ -1845,61 +652,70 @@ static struct Damage battle_calc_pet_weapon_attack(
memset(&wd,0,sizeof(wd));
return wd;
}
- t_race=battle_get_race( target );
- t_size=battle_get_size( target );
- t_mode=battle_get_mode( target );
- t_sc_data=battle_get_sc_data( target );
+ t_race=status_get_race( target );
+ t_size=status_get_size( target );
+ t_mode=status_get_mode( target );
+ t_sc_data=status_get_sc_data( target );
flag=BF_SHORT|BF_WEAPON|BF_NORMAL; // 攻撃の種類の設定
// 回避率計算、回避判定は後で
- flee = battle_get_flee(target);
- if(battle_config.agi_penaly_type > 0 || battle_config.vit_penaly_type > 0)
- target_count += battle_counttargeted(target,src,battle_config.agi_penaly_count_lv);
- if(battle_config.agi_penaly_type > 0) {
- if(target_count >= battle_config.agi_penaly_count) {
- if(battle_config.agi_penaly_type == 1)
- flee = (flee * (100 - (target_count - (battle_config.agi_penaly_count - 1))*battle_config.agi_penaly_num))/100;
- else if(battle_config.agi_penaly_type == 2)
- flee -= (target_count - (battle_config.agi_penaly_count - 1))*battle_config.agi_penaly_num;
+ flee = status_get_flee(target);
+ if(battle_config.agi_penalty_type > 0 || battle_config.vit_penalty_type > 0)
+ target_count += battle_counttargeted(target,src,battle_config.agi_penalty_count_lv);
+ if(battle_config.agi_penalty_type > 0) {
+ if(target_count >= battle_config.agi_penalty_count) {
+ if(battle_config.agi_penalty_type == 1)
+ flee = (flee * (100 - (target_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
+ else if(battle_config.agi_penalty_type == 2)
+ flee -= (target_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num;
if(flee < 1) flee = 1;
}
}
- hitrate=battle_get_hit(src) - flee + 80;
+ hitrate=status_get_hit(src) - flee + 80;
type=0; // normal
- div_ = 1; // single attack
+ if (skill_num > 0) {
+ div_ = skill_get_num(skill_num,skill_lv);
+ if (div_ < 1) div_ = 1; //Avoid the rare case where the db says div_ is 0 and below
+ }
+ else div_ = 1; // single attack
- luk=battle_get_luk(src);
+ luk=status_get_luk(src);
if(battle_config.pet_str)
- damage = battle_get_baseatk(src);
+ damage = status_get_baseatk(src);
else
damage = 0;
if(skill_num==HW_MAGICCRASHER){ /* マジッククラッシャーはMATKで殴る */
- atkmin = battle_get_matk1(src);
- atkmax = battle_get_matk2(src);
+ atkmin = status_get_matk1(src);
+ atkmax = status_get_matk2(src);
}else{
- atkmin = battle_get_atk(src);
- atkmax = battle_get_atk2(src);
+ atkmin = status_get_atk(src);
+ atkmax = status_get_atk2(src);
}
- if(mob_db[pd->class].range>3 )
+ if(mob_db[pd->class_].range>3 )
flag=(flag&~BF_RANGEMASK)|BF_LONG;
if(atkmin > atkmax) atkmin = atkmax;
- cri = battle_get_critical(src);
- cri -= battle_get_luk(target) * 2; // luk/5*10 => target_luk*2 not target_luk*3
+ cri = status_get_critical(src);
+ cri -= status_get_luk(target) * 2; // luk/5*10 => target_luk*2 not target_luk*3
if(battle_config.enemy_critical_rate != 100) {
cri = cri*battle_config.enemy_critical_rate/100;
if(cri < 1)
cri = 1;
}
- if(t_sc_data != NULL && t_sc_data[SC_SLEEP].timer!=-1 )
- cri <<=1;
+ if(t_sc_data) {
+ if (t_sc_data[SC_SLEEP].timer!=-1)
+ cri <<=1;
+ if(t_sc_data[SC_JOINTBEAT].timer != -1 &&
+ t_sc_data[SC_JOINTBEAT].val2 == 6) // Always take crits with Neck broken by Joint Beat [DracoRPG]
+ cri = 1000;
+ }
- if(skill_num == 0 && skill_lv >= 0 && battle_config.enemy_critical && (rand() % 1000) < cri)
+ if(skill_num == 0 && battle_config.enemy_critical && (rand() % 1000) < cri)
{
damage += atkmax;
type = 0x0a;
@@ -1930,14 +746,14 @@ static struct Damage battle_calc_pet_weapon_attack(
hitrate = (hitrate*(100+5*skill_lv))/100;
break;
case SM_MAGNUM: // マグナムブレイク
- damage = damage*(5*skill_lv +(wflag)?65:115 )/100;
+ damage = damage*(wflag > 1 ? 5*skill_lv+115 : 30*skill_lv+100)/100;
+ hitrate = (hitrate*(100+10*skill_lv))/100;
break;
case MC_MAMMONITE: // メマーナイト
damage = damage*(100+ 50*skill_lv)/100;
break;
case AC_DOUBLE: // ダブルストレイフィング
damage = damage*(180+ 20*skill_lv)/100;
- div_=2;
flag=(flag&~BF_RANGEMASK)|BF_LONG;
break;
case AC_SHOWER: // アローシャワー
@@ -1952,7 +768,7 @@ static struct Damage battle_calc_pet_weapon_attack(
damage = damage*(100+ 10*skill_lv)/100;
hitrate = hitrate*(100+5*skill_lv)/100;
div_=t_size+1;
- damage*=div_;
+ div_flag = 1;
break;
case KN_SPEARSTAB: // スピアスタブ
damage = damage*(100+ 15*skill_lv)/100;
@@ -1970,14 +786,13 @@ static struct Damage battle_calc_pet_weapon_attack(
if(skill_lv>9 && wflag==2) damage2+=damage/4;
if(skill_lv>9 && wflag==3) damage2+=damage/2;
damage +=damage2;
- blewcount=0;
break;
case KN_BOWLINGBASH: // ボウリングバッシュ
damage = damage*(100+ 50*skill_lv)/100;
blewcount=0;
break;
case AS_GRIMTOOTH:
- damage = damage*(100+ 20*skill_lv)/100;
+ damage = damage*(100+ 20*skill_lv)/100;
break;
case AS_POISONREACT: // celest
s_ele = 0;
@@ -1985,7 +800,6 @@ static struct Damage battle_calc_pet_weapon_attack(
break;
case AS_SONICBLOW: // ソニックブロウ
damage = damage*(300+ 50*skill_lv)/100;
- div_=8;
break;
case TF_SPRINKLESAND: // 砂まき
damage = damage*125/100;
@@ -1995,8 +809,7 @@ static struct Damage battle_calc_pet_weapon_attack(
break;
// 以下MOB
case NPC_COMBOATTACK: // 多段攻撃
- div_=skill_get_num(skill_num,skill_lv);
- damage *= div_;
+ div_flag = 1;
break;
case NPC_RANDOMATTACK: // ランダムATK攻撃
damage = damage*(50+rand()%150)/100;
@@ -2009,6 +822,7 @@ static struct Damage battle_calc_pet_weapon_attack(
case NPC_POISONATTACK:
case NPC_HOLYATTACK:
case NPC_DARKNESSATTACK:
+ case NPC_UNDEADATTACK:
case NPC_TELEKINESISATTACK:
div_= pd->skillduration; // [Valaris]
break;
@@ -2043,27 +857,27 @@ static struct Damage battle_calc_pet_weapon_attack(
break;
case CR_HOLYCROSS: // ホーリークロス
damage = damage*(100+ 35*skill_lv)/100;
- div_=2;
break;
case CR_GRANDCROSS:
hitrate= 1000000;
break;
case AM_DEMONSTRATION: // デモンストレーション
+ hitrate= 1000000;
damage = damage*(100+ 20*skill_lv)/100;
damage2 = damage2*(100+ 20*skill_lv)/100;
break;
case AM_ACIDTERROR: // アシッドテラー
+ hitrate = 1000000;
damage = damage*(100+ 40*skill_lv)/100;
damage2 = damage2*(100+ 40*skill_lv)/100;
break;
case MO_FINGEROFFENSIVE: //指弾
damage = damage * (125 + 25 * skill_lv) / 100;
- div_ = 1;
flag=(flag&~BF_RANGEMASK)|BF_LONG; //orn
break;
case MO_INVESTIGATE: // 発 勁
if(def1 < 1000000)
- damage = damage*(100+ 75*skill_lv)/100 * (def1 + def2)/100;
+ damage = damage*(100+ 75*skill_lv)/100 * (def1 + def2)/50;
hitrate = 1000000;
s_ele = 0;
break;
@@ -2074,32 +888,30 @@ static struct Damage battle_calc_pet_weapon_attack(
break;
case MO_CHAINCOMBO: // 連打掌
damage = damage*(150+ 50*skill_lv)/100;
- div_=4;
break;
case MO_COMBOFINISH: // 猛龍拳
damage = damage*(240+ 60*skill_lv)/100;
break;
case DC_THROWARROW: // 矢撃ち
- damage = damage*(100+ 50 * skill_lv)/100;
+ damage = damage*(60+ 40 * skill_lv)/100;
flag=(flag&~BF_RANGEMASK)|BF_LONG;
break;
case BA_MUSICALSTRIKE: // ミュージカルストライク
- damage = damage*(100+ 50 * skill_lv)/100;
+ damage = damage*(60+ 40 * skill_lv)/100;
flag=(flag&~BF_RANGEMASK)|BF_LONG;
break;
case CH_TIGERFIST: // 伏虎拳
- damage = damage*(100+ 60*skill_lv)/100;
+ damage = damage*(40+ 100*skill_lv)/100;
break;
case CH_CHAINCRUSH: // 連柱崩撃
- damage = damage*(100+ 60*skill_lv)/100;
- div_=skill_get_num(skill_num,skill_lv);
+ damage = damage*(400+ 100*skill_lv)/100;
break;
case CH_PALMSTRIKE: // 猛虎硬派山
- damage = damage*(50+ 100*skill_lv)/100;
+ damage = damage*(200+ 100*skill_lv)/100;
break;
case LK_SPIRALPIERCE: /* スパイラルピアース */
damage = damage*(100+ 50*skill_lv)/100; //増加量が分からないので適当に
- div_=5;
+ flag=(flag&~BF_RANGEMASK)|BF_LONG;
if(target->type == BL_PC)
((struct map_session_data *)target)->canmove_tick = gettick() + 1000;
else if(target->type == BL_MOB)
@@ -2119,31 +931,35 @@ static struct Damage battle_calc_pet_weapon_attack(
break;
case CG_ARROWVULCAN: /* アローバルカン */
damage = damage*(200+100*skill_lv)/100;
- div_=9;
break;
case AS_SPLASHER: /* ベナムスプラッシャー */
damage = damage*(200+20*skill_lv)/100;
+ hitrate = 1000000;
break;
}
+ if (div_flag && div_ > 1) { // [Skotlex]
+ damage *= div_;
+ damage2 *= div_;
+ }
}
if( skill_num!=NPC_CRITICALSLASH ){
// 対 象の防御力によるダメージの減少
// ディバインプロテクション(ここでいいのかな?)
- if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && def1 < 1000000 ) { //DEF, VIT無視
+ if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && skill_num != AM_ACIDTERROR && def1 < 1000000 ) { //DEF, VIT無視
int t_def;
- target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penaly_count_lv);
- if(battle_config.vit_penaly_type > 0) {
- if(target_count >= battle_config.vit_penaly_count) {
- if(battle_config.vit_penaly_type == 1) {
- def1 = (def1 * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100;
- def2 = (def2 * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100;
- t_vit = (t_vit * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100;
+ target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penalty_count_lv);
+ if(battle_config.vit_penalty_type > 0) {
+ if(target_count >= battle_config.vit_penalty_count) {
+ if(battle_config.vit_penalty_type == 1) {
+ def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
+ def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
+ t_vit = (t_vit * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
}
- else if(battle_config.vit_penaly_type == 2) {
- def1 -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num;
- def2 -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num;
- t_vit -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num;
+ else if(battle_config.vit_penalty_type == 2) {
+ def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
+ def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
+ t_vit -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
}
if(def1 < 0) def1 = 0;
if(def2 < 1) def2 = 1;
@@ -2168,10 +984,10 @@ static struct Damage battle_calc_pet_weapon_attack(
// 回避修正
if( hitrate < 1000000 && t_sc_data ) { // 必中攻撃
if(t_sc_data[SC_FOGWALL].timer != -1 && flag&BF_LONG)
- hitrate -= 50;
+ hitrate -= 75;
if (t_sc_data[SC_SLEEP].timer!=-1 || // 睡眠は必中
t_sc_data[SC_STAN].timer!=-1 || // スタンは必中
- t_sc_data[SC_FREEZE].timer!=-1 ||
+ t_sc_data[SC_FREEZE].timer!=-1 ||
(t_sc_data[SC_STONE].timer!=-1 && t_sc_data[SC_STONE].val2==0)) // 凍結は必中
hitrate = 1000000;
}
@@ -2184,13 +1000,13 @@ static struct Damage battle_calc_pet_weapon_attack(
dmg_lv = ATK_DEF;
}
-
+
if(t_sc_data) {
int cardfix=100;
if(t_sc_data[SC_DEFENDER].timer != -1 && flag&BF_LONG)
cardfix=cardfix*(100-t_sc_data[SC_DEFENDER].val2)/100;
if(t_sc_data[SC_FOGWALL].timer != -1 && flag&BF_LONG)
- cardfix=cardfix*(100-t_sc_data[SC_FOGWALL].val2)/100;
+ cardfix=cardfix*50/100;
if(cardfix != 100)
damage=damage*cardfix/100;
}
@@ -2198,22 +1014,22 @@ static struct Damage battle_calc_pet_weapon_attack(
// 属 性の適用
if(skill_num != 0 || s_ele != 0 || !battle_config.pet_attack_attr_none)
- damage=battle_attr_fix(damage, s_ele, battle_get_element(target) );
+ damage=battle_attr_fix(damage, s_ele, status_get_element(target) );
if(skill_num==PA_PRESSURE) /* プレッシャー 必中? */
damage = 500+300*skill_lv;
// インベナム修正
if(skill_num==TF_POISON){
- damage = battle_attr_fix(damage + 15*skill_lv, s_ele, battle_get_element(target) );
+ damage = battle_attr_fix(damage + 15*skill_lv, s_ele, status_get_element(target) );
}
if(skill_num==MC_CARTREVOLUTION){
- damage = battle_attr_fix(damage, 0, battle_get_element(target) );
+ damage = battle_attr_fix(damage, 0, status_get_element(target) );
}
// 完全回避の判定
if(battle_config.enemy_perfect_flee) {
- if(skill_num == 0 && skill_lv >= 0 && tmd!=NULL && rand()%1000 < battle_get_flee2(target) ){
+ if(skill_num == 0 && tmd!=NULL && rand()%1000 < status_get_flee2(target) ){
damage=0;
type=0x0b;
dmg_lv = ATK_LUCKY;
@@ -2231,10 +1047,10 @@ static struct Damage battle_calc_pet_weapon_attack(
wd.damage2=0;
wd.type=type;
wd.div_=div_;
- wd.amotion=battle_get_amotion(src);
+ wd.amotion=status_get_amotion(src);
if(skill_num == KN_AUTOCOUNTER)
wd.amotion >>= 1;
- wd.dmotion=battle_get_dmotion(target);
+ wd.dmotion=status_get_dmotion(target);
wd.blewcount=blewcount;
wd.flag=flag;
wd.dmg_lv=dmg_lv;
@@ -2249,16 +1065,18 @@ static struct Damage battle_calc_mob_weapon_attack(
struct mob_data* md=(struct mob_data *)src,*tmd=NULL;
int hitrate,flee,cri = 0,atkmin,atkmax;
int luk,target_count = 1;
- int def1 = battle_get_def(target);
- int def2 = battle_get_def2(target);
- int t_vit = battle_get_vit(target);
+ int def1 = status_get_def(target);
+ int def2 = status_get_def2(target);
+ int t_vit = status_get_vit(target);
struct Damage wd;
int damage,damage2=0,type,div_,blewcount=skill_get_blewcount(skill_num,skill_lv);
int flag,skill,ac_flag = 0,dmg_lv = 0;
- int t_mode=0,t_race=0,t_size=1,s_race=0,s_ele=0;
+ int t_mode=0,t_race=0,t_size=1,s_race=0,s_ele=0,s_size=0,s_race2=0;
struct status_change *sc_data,*t_sc_data;
short *sc_count;
short *option, *opt1, *opt2;
+ int div_flag=0; // 0: total damage is to be divided by div_
+ // 1: damage is distributed,and has to be multiplied by div_ [celest]
//return前の処理があるので情報出力部のみ変更
if( src == NULL || target == NULL || md == NULL ){
@@ -2267,35 +1085,37 @@ static struct Damage battle_calc_mob_weapon_attack(
return wd;
}
- s_race=battle_get_race(src);
- s_ele=battle_get_attack_element(src);
- sc_data=battle_get_sc_data(src);
- sc_count=battle_get_sc_count(src);
- option=battle_get_option(src);
- opt1=battle_get_opt1(src);
- opt2=battle_get_opt2(src);
+ s_race = status_get_race(src);
+ s_ele = status_get_attack_element(src);
+ s_size = status_get_size(src);
+ sc_data = status_get_sc_data(src);
+ sc_count = status_get_sc_count(src);
+ option = status_get_option(src);
+ opt1 = status_get_opt1(src);
+ opt2 = status_get_opt2(src);
+ s_race2 = status_get_race2(src);
// ターゲット
- if(target->type==BL_PC)
- tsd=(struct map_session_data *)target;
- else if(target->type==BL_MOB)
- tmd=(struct mob_data *)target;
- t_race=battle_get_race( target );
- t_size=battle_get_size( target );
- t_mode=battle_get_mode( target );
- t_sc_data=battle_get_sc_data( target );
-
- if((skill_num == 0 || (target->type == BL_PC && battle_config.pc_auto_counter_type&2) ||
- (target->type == BL_MOB && battle_config.monster_auto_counter_type&2)) && skill_lv >= 0) {
+ if(target->type == BL_PC)
+ tsd = (struct map_session_data *)target;
+ else if(target->type == BL_MOB)
+ tmd = (struct mob_data *)target;
+ t_race = status_get_race( target );
+ t_size = status_get_size( target );
+ t_mode = status_get_mode( target );
+ t_sc_data = status_get_sc_data( target );
+
+ if(skill_num == 0 || (target->type == BL_PC && battle_config.pc_auto_counter_type&2) ||
+ (target->type == BL_MOB && battle_config.monster_auto_counter_type&2)) {
if(skill_num != CR_GRANDCROSS && t_sc_data && t_sc_data[SC_AUTOCOUNTER].timer != -1) {
- int dir = map_calc_dir(src,target->x,target->y),t_dir = battle_get_dir(target);
+ int dir = map_calc_dir(src,target->x,target->y),t_dir = status_get_dir(target);
int dist = distance(src->x,src->y,target->x,target->y);
if(dist <= 0 || map_check_dir(dir,t_dir) ) {
memset(&wd,0,sizeof(wd));
t_sc_data[SC_AUTOCOUNTER].val3 = 0;
t_sc_data[SC_AUTOCOUNTER].val4 = 1;
if(sc_data && sc_data[SC_AUTOCOUNTER].timer == -1) {
- int range = battle_get_range(target);
+ int range = status_get_range(target);
if((target->type == BL_PC && ((struct map_session_data *)target)->status.weapon != 11 && dist <= range+1) ||
(target->type == BL_MOB && range <= 3 && dist <= range+1) )
t_sc_data[SC_AUTOCOUNTER].val3 = src->id;
@@ -2312,37 +1132,40 @@ static struct Damage battle_calc_mob_weapon_attack(
flag=BF_SHORT|BF_WEAPON|BF_NORMAL; // 攻撃の種類の設定
// 回避率計算、回避判定は後で
- flee = battle_get_flee(target);
- if(battle_config.agi_penaly_type > 0 || battle_config.vit_penaly_type > 0)
- target_count += battle_counttargeted(target,src,battle_config.agi_penaly_count_lv);
- if(battle_config.agi_penaly_type > 0) {
- if(target_count >= battle_config.agi_penaly_count) {
- if(battle_config.agi_penaly_type == 1)
- flee = (flee * (100 - (target_count - (battle_config.agi_penaly_count - 1))*battle_config.agi_penaly_num))/100;
- else if(battle_config.agi_penaly_type == 2)
- flee -= (target_count - (battle_config.agi_penaly_count - 1))*battle_config.agi_penaly_num;
+ flee = status_get_flee(target);
+ if(battle_config.agi_penalty_type > 0 || battle_config.vit_penalty_type > 0)
+ target_count += battle_counttargeted(target,src,battle_config.agi_penalty_count_lv);
+ if(battle_config.agi_penalty_type > 0) {
+ if(target_count >= battle_config.agi_penalty_count) {
+ if(battle_config.agi_penalty_type == 1)
+ flee = (flee * (100 - (target_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
+ else if(battle_config.agi_penalty_type == 2)
+ flee -= (target_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num;
if(flee < 1) flee = 1;
}
}
- hitrate=battle_get_hit(src) - flee + 80;
+ hitrate=status_get_hit(src) - flee + 80;
type=0; // normal
- div_ = 1; // single attack
+ if (skill_num > 0) {
+ div_ = skill_get_num(skill_num,skill_lv);
+ if (div_ < 1) div_ = 1; //Avoid the rare case where the db says div_ is 0 and below
+ } else div_ = 1; // single attack
- luk=battle_get_luk(src);
+ luk=status_get_luk(src);
if(battle_config.enemy_str)
- damage = battle_get_baseatk(src);
+ damage = status_get_baseatk(src);
else
damage = 0;
if(skill_num==HW_MAGICCRASHER){ /* マジッククラッシャーはMATKで殴る */
- atkmin = battle_get_matk1(src);
- atkmax = battle_get_matk2(src);
+ atkmin = status_get_matk1(src);
+ atkmax = status_get_matk2(src);
}else{
- atkmin = battle_get_atk(src);
- atkmax = battle_get_atk2(src);
+ atkmin = status_get_atk(src);
+ atkmax = status_get_atk2(src);
}
- if(mob_db[md->class].range>3 )
+ if(mob_db[md->class_].range>3 )
flag=(flag&~BF_RANGEMASK)|BF_LONG;
if(atkmin > atkmax) atkmin = atkmax;
@@ -2351,15 +1174,20 @@ static struct Damage battle_calc_mob_weapon_attack(
atkmin=atkmax;
}
- cri = battle_get_critical(src);
- cri -= battle_get_luk(target) * 3;
+ cri = status_get_critical(src);
+ cri -= status_get_luk(target) * 3;
if(battle_config.enemy_critical_rate != 100) {
cri = cri*battle_config.enemy_critical_rate/100;
if(cri < 1)
cri = 1;
}
- if(t_sc_data != NULL && t_sc_data[SC_SLEEP].timer!=-1 ) // 睡眠中はクリティカルが倍に
- cri <<=1;
+ if(t_sc_data) {
+ if (t_sc_data[SC_SLEEP].timer!=-1 ) // 睡眠中はクリティカルが倍に
+ cri <<=1;
+ if(t_sc_data[SC_JOINTBEAT].timer != -1 &&
+ t_sc_data[SC_JOINTBEAT].val2 == 6) // Always take crits with Neck broken by Joint Beat [DracoRPG]
+ cri = 1000;
+ }
if(ac_flag) cri = 1000;
@@ -2395,9 +1223,9 @@ static struct Damage battle_calc_mob_weapon_attack(
// ソニックブロー
if(sc_data){ //状態異常中のダメージ追加
if(sc_data[SC_OVERTHRUST].timer!=-1) // オーバートラスト
- damage += damage*(5*sc_data[SC_OVERTHRUST].val1)/100;
+ damage += damage*(5*sc_data[SC_OVERTHRUST].val1)/100;
if(sc_data[SC_TRUESIGHT].timer!=-1) // トゥルーサイト
- damage += damage*(2*sc_data[SC_TRUESIGHT].val1)/100;
+ damage += damage*(2*sc_data[SC_TRUESIGHT].val1)/100;
if(sc_data[SC_BERSERK].timer!=-1) // バーサーク
damage += damage*2;
if(sc_data && sc_data[SC_AURABLADE].timer!=-1) //[DracoRPG]
@@ -2416,14 +1244,14 @@ static struct Damage battle_calc_mob_weapon_attack(
hitrate = (hitrate*(100+5*skill_lv))/100;
break;
case SM_MAGNUM: // マグナムブレイク
- damage = damage*(5*skill_lv +(wflag)?65:115 )/100;
+ damage = damage*(wflag > 1 ? 5*skill_lv+115 : 30*skill_lv+100)/100;
+ hitrate = (hitrate*(100+10*skill_lv))/100;
break;
case MC_MAMMONITE: // メマーナイト
damage = damage*(100+ 50*skill_lv)/100;
break;
case AC_DOUBLE: // ダブルストレイフィング
damage = damage*(180+ 20*skill_lv)/100;
- div_=2;
flag=(flag&~BF_RANGEMASK)|BF_LONG;
break;
case AC_SHOWER: // アローシャワー
@@ -2436,9 +1264,9 @@ static struct Damage battle_calc_mob_weapon_attack(
break;
case KN_PIERCE: // ピアース
damage = damage*(100+ 10*skill_lv)/100;
- hitrate=hitrate*(100+5*skill_lv)/100;
- div_=t_size+1;
- damage*=div_;
+ hitrate = hitrate*(100+5*skill_lv)/100;
+ div_ = t_size+1;
+ div_flag = 1;
break;
case KN_SPEARSTAB: // スピアスタブ
damage = damage*(100+ 15*skill_lv)/100;
@@ -2456,7 +1284,6 @@ static struct Damage battle_calc_mob_weapon_attack(
if(skill_lv>9 && wflag==2) damage2+=damage/4;
if(skill_lv>9 && wflag==3) damage2+=damage/2;
damage +=damage2;
- blewcount=0;
break;
case KN_BOWLINGBASH: // ボウリングバッシュ
damage = damage*(100+ 50*skill_lv)/100;
@@ -2470,7 +1297,7 @@ static struct Damage battle_calc_mob_weapon_attack(
flag=(flag&~BF_SKILLMASK)|BF_NORMAL;
break;
case AS_GRIMTOOTH:
- damage = damage*(100+ 20*skill_lv)/100;
+ damage = damage*(100+ 20*skill_lv)/100;
break;
case AS_POISONREACT: // celest
s_ele = 0;
@@ -2478,7 +1305,6 @@ static struct Damage battle_calc_mob_weapon_attack(
break;
case AS_SONICBLOW: // ソニックブロウ
damage = damage*(300+ 50*skill_lv)/100;
- div_=8;
break;
case TF_SPRINKLESAND: // 砂まき
damage = damage*125/100;
@@ -2488,8 +1314,7 @@ static struct Damage battle_calc_mob_weapon_attack(
break;
// 以下MOB
case NPC_COMBOATTACK: // 多段攻撃
- div_=skill_get_num(skill_num,skill_lv);
- damage *= div_;
+ div_flag = 1;
break;
case NPC_RANDOMATTACK: // ランダムATK攻撃
damage = damage*(50+rand()%150)/100;
@@ -2502,6 +1327,7 @@ static struct Damage battle_calc_mob_weapon_attack(
case NPC_POISONATTACK:
case NPC_HOLYATTACK:
case NPC_DARKNESSATTACK:
+ case NPC_UNDEADATTACK:
case NPC_TELEKINESISATTACK:
damage = damage*(100+25*(skill_lv-1))/100;
break;
@@ -2536,27 +1362,27 @@ static struct Damage battle_calc_mob_weapon_attack(
break;
case CR_HOLYCROSS: // ホーリークロス
damage = damage*(100+ 35*skill_lv)/100;
- div_=2;
break;
case CR_GRANDCROSS:
hitrate= 1000000;
break;
case AM_DEMONSTRATION: // デモンストレーション
+ hitrate = 1000000;
damage = damage*(100+ 20*skill_lv)/100;
damage2 = damage2*(100+ 20*skill_lv)/100;
break;
case AM_ACIDTERROR: // アシッドテラー
+ hitrate = 1000000;
damage = damage*(100+ 40*skill_lv)/100;
damage2 = damage2*(100+ 40*skill_lv)/100;
break;
case MO_FINGEROFFENSIVE: //指弾
damage = damage * (125 + 25 * skill_lv) / 100;
- div_ = 1;
flag=(flag&~BF_RANGEMASK)|BF_LONG; //orn
break;
case MO_INVESTIGATE: // 発 勁
if(def1 < 1000000)
- damage = damage*(100+ 75*skill_lv)/100 * (def1 + def2)/100;
+ damage = damage*(100+ 75*skill_lv)/100 * (def1 + def2)/50;
hitrate = 1000000;
s_ele = 0;
break;
@@ -2567,32 +1393,30 @@ static struct Damage battle_calc_mob_weapon_attack(
break;
case MO_CHAINCOMBO: // 連打掌
damage = damage*(150+ 50*skill_lv)/100;
- div_=4;
break;
case BA_MUSICALSTRIKE: // ミュージカルストライク
- damage = damage*(100+ 50 * skill_lv)/100;
+ damage = damage*(60+ 40 * skill_lv)/100;
flag=(flag&~BF_RANGEMASK)|BF_LONG;
break;
case DC_THROWARROW: // 矢撃ち
- damage = damage*(100+ 50 * skill_lv)/100;
+ damage = damage*(60+ 40 * skill_lv)/100;
flag=(flag&~BF_RANGEMASK)|BF_LONG;
break;
case MO_COMBOFINISH: // 猛龍拳
damage = damage*(240+ 60*skill_lv)/100;
break;
case CH_TIGERFIST: // 伏虎拳
- damage = damage*(100+ 20*skill_lv)/100;
+ damage = damage*(40+ 100*skill_lv)/100;
break;
case CH_CHAINCRUSH: // 連柱崩撃
- damage = damage*(100+ 60*skill_lv)/100;
- div_=skill_get_num(skill_num,skill_lv);
+ damage = damage*(400+ 100*skill_lv)/100;
break;
case CH_PALMSTRIKE: // 猛虎硬派山
- damage = damage*(50+ 100*skill_lv)/100;
+ damage = damage*(200+ 100*skill_lv)/100;
break;
case LK_SPIRALPIERCE: /* スパイラルピアース */
damage = damage*(100+ 50*skill_lv)/100; //増加量が分からないので適当に
- div_=5;
+ flag=(flag&~BF_RANGEMASK)|BF_LONG;
if(tsd)
tsd->canmove_tick = gettick() + 1000;
else if(tmd)
@@ -2612,31 +1436,35 @@ static struct Damage battle_calc_mob_weapon_attack(
break;
case CG_ARROWVULCAN: /* アローバルカン */
damage = damage*(200+100*skill_lv)/100;
- div_=9;
break;
case AS_SPLASHER: /* ベナムスプラッシャー */
damage = damage*(200+20*skill_lv)/100;
+ hitrate = 1000000;
break;
}
+ if (div_flag && div_ > 1) { // [Skotlex]
+ damage *= div_;
+ damage2 *= div_;
+ }
}
if( skill_num!=NPC_CRITICALSLASH ){
// 対 象の防御力によるダメージの減少
// ディバインプロテクション(ここでいいのかな?)
- if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && def1 < 1000000) { //DEF, VIT無視
+ if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && skill_num != AM_ACIDTERROR && def1 < 1000000) { //DEF, VIT無視
int t_def;
- target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penaly_count_lv);
- if(battle_config.vit_penaly_type > 0) {
- if(target_count >= battle_config.vit_penaly_count) {
- if(battle_config.vit_penaly_type == 1) {
- def1 = (def1 * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100;
- def2 = (def2 * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100;
- t_vit = (t_vit * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100;
+ target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penalty_count_lv);
+ if(battle_config.vit_penalty_type > 0) {
+ if(target_count >= battle_config.vit_penalty_count) {
+ if(battle_config.vit_penalty_type == 1) {
+ def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
+ def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
+ t_vit = (t_vit * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
}
- else if(battle_config.vit_penaly_type == 2) {
- def1 -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num;
- def2 -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num;
- t_vit -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num;
+ else if(battle_config.vit_penalty_type == 2) {
+ def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
+ def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
+ t_vit -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
}
if(def1 < 0) def1 = 0;
if(def2 < 1) def2 = 1;
@@ -2644,7 +1472,7 @@ static struct Damage battle_calc_mob_weapon_attack(
}
}
t_def = def2*8/10;
- if(battle_check_undead(s_race,battle_get_elem_type(src)) || s_race==6)
+ if(battle_check_undead(s_race,status_get_elem_type(src)) || s_race==6)
if(tsd && (skill=pc_checkskill(tsd,AL_DP)) > 0 )
t_def += skill* (int) (3 + (tsd->status.base_level+1)*0.04); // submitted by orn
//t_def += skill*3;
@@ -2666,10 +1494,10 @@ static struct Damage battle_calc_mob_weapon_attack(
// 回避修正
if( hitrate < 1000000 && t_sc_data ) { // 必中攻撃
if(t_sc_data[SC_FOGWALL].timer != -1 && flag&BF_LONG)
- hitrate -= 50;
+ hitrate -= 75;
if (t_sc_data[SC_SLEEP].timer!=-1 || // 睡眠は必中
t_sc_data[SC_STAN].timer!=-1 || // スタンは必中
- t_sc_data[SC_FREEZE].timer!=-1 ||
+ t_sc_data[SC_FREEZE].timer!=-1 ||
(t_sc_data[SC_STONE].timer!=-1 && t_sc_data[SC_STONE].val2==0)) // 凍結は必中
hitrate = 1000000;
}
@@ -2686,16 +1514,24 @@ static struct Damage battle_calc_mob_weapon_attack(
int cardfix=100,i;
cardfix=cardfix*(100-tsd->subele[s_ele])/100; // 属 性によるダメージ耐性
cardfix=cardfix*(100-tsd->subrace[s_race])/100; // 種族によるダメージ耐性
- if(mob_db[md->class].mode & 0x20)
+ cardfix=cardfix*(100-tsd->subsize[s_size])/100;
+ cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; // 種族によるダメージ耐性
+ if(mob_db[md->class_].mode & 0x20)
cardfix=cardfix*(100-tsd->subrace[10])/100;
else
cardfix=cardfix*(100-tsd->subrace[11])/100;
for(i=0;i<tsd->add_def_class_count;i++) {
- if(tsd->add_def_classid[i] == md->class) {
+ if(tsd->add_def_classid[i] == md->class_) {
cardfix=cardfix*(100-tsd->add_def_classrate[i])/100;
break;
}
}
+ for(i=0;i<tsd->add_damage_class_count2;i++) {
+ if(tsd->add_damage_classid2[i] == md->class_) {
+ cardfix=cardfix*(100+tsd->add_damage_classrate2[i])/100;
+ break;
+ }
+ }
if(flag&BF_LONG)
cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
if(flag&BF_SHORT)
@@ -2707,7 +1543,7 @@ static struct Damage battle_calc_mob_weapon_attack(
if(t_sc_data[SC_DEFENDER].timer != -1 && flag&BF_LONG)
cardfix=cardfix*(100-t_sc_data[SC_DEFENDER].val2)/100;
if(t_sc_data[SC_FOGWALL].timer != -1 && flag&BF_LONG)
- cardfix=cardfix*(100-t_sc_data[SC_FOGWALL].val2)/100;
+ cardfix=cardfix*50/100;
if(cardfix != 100)
damage=damage*cardfix/100;
}
@@ -2721,11 +1557,11 @@ static struct Damage battle_calc_mob_weapon_attack(
if(damage < 0) damage = 0;
// 属 性の適用
- if (!((battle_config.mob_ghostring_fix == 1) &&
- (battle_get_element(target) == 8) &&
- (target->type==BL_PC))) // [MouseJstr]
- if(skill_num != 0 || s_ele != 0 || !battle_config.mob_attack_attr_none)
- damage=battle_attr_fix(damage, s_ele, battle_get_element(target) );
+ if (!((battle_config.mob_ghostring_fix == 1) &&
+ (status_get_elem_type(target) == 8) &&
+ (target->type==BL_PC))) // [MouseJstr]
+ if(skill_num != 0 || s_ele != 0 || !battle_config.mob_attack_attr_none)
+ damage=battle_attr_fix(damage, s_ele, status_get_element(target) );
//if(sc_data && sc_data[SC_AURABLADE].timer!=-1) /* オーラブレード 必中 */
// damage += sc_data[SC_AURABLADE].val1 * 10;
@@ -2734,21 +1570,21 @@ static struct Damage battle_calc_mob_weapon_attack(
// インベナム修正
if(skill_num==TF_POISON){
- damage = battle_attr_fix(damage + 15*skill_lv, s_ele, battle_get_element(target) );
+ damage = battle_attr_fix(damage + 15*skill_lv, s_ele, status_get_element(target) );
}
if(skill_num==MC_CARTREVOLUTION){
- damage = battle_attr_fix(damage, 0, battle_get_element(target) );
+ damage = battle_attr_fix(damage, 0, status_get_element(target) );
}
// 完全回避の判定
- if(skill_num == 0 && skill_lv >= 0 && tsd!=NULL && rand()%1000 < battle_get_flee2(target) ){
+ if(skill_num == 0 && tsd!=NULL && rand()%1000 < status_get_flee2(target) ){
damage=0;
type=0x0b;
dmg_lv = ATK_LUCKY;
}
if(battle_config.enemy_perfect_flee) {
- if(skill_num == 0 && skill_lv >= 0 && tmd!=NULL && rand()%1000 < battle_get_flee2(target) ){
+ if(skill_num == 0 && tmd!=NULL && rand()%1000 < status_get_flee2(target) ){
damage=0;
type=0x0b;
dmg_lv = ATK_LUCKY;
@@ -2769,10 +1605,10 @@ static struct Damage battle_calc_mob_weapon_attack(
wd.damage2=0;
wd.type=type;
wd.div_=div_;
- wd.amotion=battle_get_amotion(src);
+ wd.amotion=status_get_amotion(src);
if(skill_num == KN_AUTOCOUNTER)
wd.amotion >>= 1;
- wd.dmotion=battle_get_dmotion(target);
+ wd.dmotion=status_get_dmotion(target);
wd.blewcount=blewcount;
wd.flag=flag;
wd.dmg_lv=dmg_lv;
@@ -2791,14 +1627,14 @@ static struct Damage battle_calc_pc_weapon_attack(
int hitrate,flee,cri = 0,atkmin,atkmax;
int dex,luk,target_count = 1;
int no_cardfix=0;
- int def1 = battle_get_def(target);
- int def2 = battle_get_def2(target);
-// int mdef1, mdef2;
- int t_vit = battle_get_vit(target);
+ int def1 = status_get_def(target);
+ int def2 = status_get_def2(target);
+ int t_vit = status_get_vit(target);
struct Damage wd;
int damage,damage2,damage3=0,damage4=0,type,div_,blewcount=skill_get_blewcount(skill_num,skill_lv);
int flag,skill,dmg_lv = 0;
- int t_mode=0,t_race=0,t_size=1,s_race=7,s_ele=0;
+ int t_mode=0,t_race=0,t_size=1,s_race=7,s_ele=0,s_size=1;
+ int t_race2=0;
struct status_change *sc_data,*t_sc_data;
short *sc_count;
short *option, *opt1, *opt2;
@@ -2806,6 +1642,8 @@ static struct Damage battle_calc_pc_weapon_attack(
int watk,watk_,cardfix,t_ele;
int da=0,i,t_class,ac_flag = 0;
int idef_flag=0,idef_flag_=0;
+ int div_flag=0; // 0: total damage is to be divided by div_
+ // 1: damage is distributed,and has to be multiplied by div_ [celest]
//return前の処理があるので情報出力部のみ変更
if( src == NULL || target == NULL || sd == NULL ){
@@ -2816,14 +1654,16 @@ static struct Damage battle_calc_pc_weapon_attack(
// アタッカー
- s_race=battle_get_race(src); //種族
- s_ele=battle_get_attack_element(src); //属性
- s_ele_=battle_get_attack_element2(src); //左手属性
- sc_data=battle_get_sc_data(src); //ステータス異常
- sc_count=battle_get_sc_count(src); //ステータス異常の数
- option=battle_get_option(src); //鷹とかペコとかカートとか
- opt1=battle_get_opt1(src); //石化、凍結、スタン、睡眠、暗闇
- opt2=battle_get_opt2(src); //毒、呪い、沈黙、暗闇?
+ s_race=status_get_race(src); //種族
+ s_ele=status_get_attack_element(src); //属性
+ s_ele_=status_get_attack_element2(src); //左手属性
+ s_size=status_get_size(src);
+ sc_data=status_get_sc_data(src); //ステータス異常
+ sc_count=status_get_sc_count(src); //ステータス異常の数
+ option=status_get_option(src); //鷹とかペコとかカートとか
+ opt1=status_get_opt1(src); //石化、凍結、スタン、睡眠、暗闇
+ opt2=status_get_opt2(src); //毒、呪い、沈黙、暗闇?
+ t_race2=status_get_race2(target);
if(skill_num != CR_GRANDCROSS) //グランドクロスでないなら
sd->state.attack_type = BF_WEAPON; //攻撃タイプは武器攻撃
@@ -2833,24 +1673,24 @@ static struct Damage battle_calc_pc_weapon_attack(
tsd=(struct map_session_data *)target; //tsdに代入(tmdはNULL)
else if(target->type==BL_MOB) //対象がMobなら
tmd=(struct mob_data *)target; //tmdに代入(tsdはNULL)
- t_race=battle_get_race( target ); //対象の種族
- t_ele=battle_get_elem_type(target); //対象の属性
- t_size=battle_get_size( target ); //対象のサイズ
- t_mode=battle_get_mode( target ); //対象のMode
- t_sc_data=battle_get_sc_data( target ); //対象のステータス異常
+ t_race=status_get_race( target ); //対象の種族
+ t_ele=status_get_elem_type(target); //対象の属性
+ t_size=status_get_size( target ); //対象のサイズ
+ t_mode=status_get_mode( target ); //対象のMode
+ t_sc_data=status_get_sc_data( target ); //対象のステータス異常
//オートカウンター処理ここから
- if((skill_num == 0 || (target->type == BL_PC && battle_config.pc_auto_counter_type&2) ||
- (target->type == BL_MOB && battle_config.monster_auto_counter_type&2)) && skill_lv >= 0) {
+ if(skill_num == 0 || (target->type == BL_PC && battle_config.pc_auto_counter_type&2) ||
+ (target->type == BL_MOB && battle_config.monster_auto_counter_type&2)) {
if(skill_num != CR_GRANDCROSS && t_sc_data && t_sc_data[SC_AUTOCOUNTER].timer != -1) { //グランドクロスでなく、対象がオートカウンター状態の場合
- int dir = map_calc_dir(src,target->x,target->y),t_dir = battle_get_dir(target);
+ int dir = map_calc_dir(src,target->x,target->y),t_dir = status_get_dir(target);
int dist = distance(src->x,src->y,target->x,target->y);
if(dist <= 0 || map_check_dir(dir,t_dir) ) { //対象との距離が0以下、または対象の正面?
memset(&wd,0,sizeof(wd));
t_sc_data[SC_AUTOCOUNTER].val3 = 0;
t_sc_data[SC_AUTOCOUNTER].val4 = 1;
if(sc_data && sc_data[SC_AUTOCOUNTER].timer == -1) { //自分がオートカウンター状態
- int range = battle_get_range(target);
+ int range = status_get_range(target);
if((target->type == BL_PC && ((struct map_session_data *)target)->status.weapon != 11 && dist <= range+1) || //対象がPCで武器が弓矢でなく射程内
(target->type == BL_MOB && range <= 3 && dist <= range+1) ) //または対象がMobで射程が3以下で射程内
t_sc_data[SC_AUTOCOUNTER].val3 = src->id;
@@ -2869,32 +1709,35 @@ static struct Damage battle_calc_pc_weapon_attack(
flag=BF_SHORT|BF_WEAPON|BF_NORMAL; // 攻撃の種類の設定
// 回避率計算、回避判定は後で
- flee = battle_get_flee(target);
- if(battle_config.agi_penaly_type > 0 || battle_config.vit_penaly_type > 0) //AGI、VITペナルティ設定が有効
- target_count += battle_counttargeted(target,src,battle_config.agi_penaly_count_lv); //対象の数を算出
- if(battle_config.agi_penaly_type > 0) {
- if(target_count >= battle_config.agi_penaly_count) { //ペナルティ設定より対象が多い
- if(battle_config.agi_penaly_type == 1) //回避率がagi_penaly_num%ずつ減少
- flee = (flee * (100 - (target_count - (battle_config.agi_penaly_count - 1))*battle_config.agi_penaly_num))/100;
- else if(battle_config.agi_penaly_type == 2) //回避率がagi_penaly_num分減少
- flee -= (target_count - (battle_config.agi_penaly_count - 1))*battle_config.agi_penaly_num;
+ flee = status_get_flee(target);
+ if(battle_config.agi_penalty_type > 0 || battle_config.vit_penalty_type > 0) //AGI、VITペナルティ設定が有効
+ target_count += battle_counttargeted(target,src,battle_config.agi_penalty_count_lv); //対象の数を算出
+ if(battle_config.agi_penalty_type > 0) {
+ if(target_count >= battle_config.agi_penalty_count) { //ペナルティ設定より対象が多い
+ if(battle_config.agi_penalty_type == 1) //回避率がagi_penalty_num%ずつ減少
+ flee = (flee * (100 - (target_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
+ else if(battle_config.agi_penalty_type == 2) //回避率がagi_penalty_num分減少
+ flee -= (target_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num;
if(flee < 1) flee = 1; //回避率は最低でも1
}
}
- hitrate=battle_get_hit(src) - flee + 80; //命中率計算
+ hitrate=status_get_hit(src) - flee + 80; //命中率計算
type=0; // normal
- div_ = 1; // single attack
+ if (skill_num > 0) {
+ div_=skill_get_num(skill_num,skill_lv);
+ if (div_ < 1) div_ = 1; //Avoid the rare case where the db says div_ is 0 and below
+ } else div_ = 1; // single attack
- dex=battle_get_dex(src); //DEX
- luk=battle_get_luk(src); //LUK
- watk = battle_get_atk(src); //ATK
- watk_ = battle_get_atk_(src); //ATK左手
+ dex=status_get_dex(src); //DEX
+ luk=status_get_luk(src); //LUK
+ watk = status_get_atk(src); //ATK
+ watk_ = status_get_atk_(src); //ATK左手
if(skill_num==HW_MAGICCRASHER){ /* マジッククラッシャーはMATKで殴る */
- damage = damage2 = battle_get_matk1(src); //damega,damega2初登場、base_atkの取得
+ damage = damage2 = status_get_matk1(src); //damega,damega2初登場、base_atkの取得
}else{
- damage = damage2 = battle_get_baseatk(&sd->bl); //damega,damega2初登場、base_atkの取得
+ damage = damage2 = status_get_baseatk(&sd->bl); //damega,damega2初登場、base_atkの取得
}
atkmin = atkmin_ = dex; //最低ATKはDEXで初期化?
sd->state.arrow_atk = 0; //arrow_atk初期化
@@ -2942,11 +1785,12 @@ static struct Damage battle_calc_pc_weapon_attack(
}
//三段掌
- if(skill_num == 0 && skill_lv >= 0 && (skill = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0 && sd->status.weapon <= 16 && !sd->state.arrow_atk) {
+ //if(skill_num == 0 && skill_lv >= 0 && (skill = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0 && sd->status.weapon <= 16 && !sd->state.arrow_atk) {
+ if(skill_num == 0 && (skill = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0 && sd->status.weapon <= 16) { // triple blow works with bows ^^ [celest]
da = (rand()%100 < (30 - skill)) ? 2:0;
}
- if(sd->double_rate > 0 && da == 0 && skill_num == 0 && skill_lv >= 0)
+ if(sd->double_rate > 0 && da == 0 && skill_num == 0)
da = (rand()%100 < sd->double_rate) ? 1:0;
// 過剰精錬ボーナス
@@ -2957,16 +1801,22 @@ static struct Damage battle_calc_pc_weapon_attack(
if(da == 0){ //ダブルアタックが発動していない
// クリティカル計算
- cri = battle_get_critical(src);
+ cri = status_get_critical(src);
+ cri += sd->critaddrace[t_race];
if(sd->state.arrow_atk)
cri += sd->arrow_cri;
if(sd->status.weapon == 16)
// カタールの場合、クリティカルを倍に
cri <<=1;
- cri -= battle_get_luk(target) * 3;
- if(t_sc_data != NULL && t_sc_data[SC_SLEEP].timer!=-1 ) // 睡眠中はクリティカルが倍に
- cri <<=1;
+ cri -= status_get_luk(target) * 3;
+ if(t_sc_data) {
+ if (t_sc_data[SC_SLEEP].timer!=-1 ) // 睡眠中はクリティカルが倍に
+ cri <<=1;
+ if(t_sc_data[SC_JOINTBEAT].timer != -1 &&
+ t_sc_data[SC_JOINTBEAT].val2 == 6) // Always take crits with Neck broken by Joint Beat [DracoRPG]
+ cri = 1000;
+ }
if(ac_flag) cri = 1000;
if(skill_num == KN_AUTOCOUNTER) {
@@ -2975,25 +1825,29 @@ static struct Damage battle_calc_pc_weapon_attack(
else
cri <<= 1;
}
-
- if(skill_num == SN_SHARPSHOOTING && rand()%100 < 50)
+ if(skill_num == SN_SHARPSHOOTING)
cri += 200;
}
if(tsd && tsd->critical_def)
cri = cri * (100-tsd->critical_def) / 100;
- if(da == 0 && (skill_num==0 || skill_num == KN_AUTOCOUNTER || skill_num == SN_SHARPSHOOTING) && skill_lv >= 0 && //ダブルアタックが発動していない
+ if(da == 0 && (skill_num==0 || skill_num == KN_AUTOCOUNTER || skill_num == SN_SHARPSHOOTING) && //ダブルアタックが発動していない
(rand() % 1000) < cri) // 判定(スキルの場合は無視)
{
damage += atkmax;
damage2 += atkmax_;
- if(sd->atk_rate != 100) {
- damage = (damage * sd->atk_rate)/100;
- damage2 = (damage2 * sd->atk_rate)/100;
+ if(sd->atk_rate != 100 || sd->weapon_atk_rate != 0) {
+ if (sd->status.weapon < 16) {
+ damage = (damage * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100;
+ damage2 = (damage2 * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100;
+ }
}
if(sd->state.arrow_atk)
damage += sd->arrow_atk;
+
+ damage += damage * sd->crit_atk_rate / 100;
+
type = 0x0a;
/* if(def1 < 1000000) {
@@ -3038,9 +1892,11 @@ static struct Damage battle_calc_pc_weapon_attack(
damage2 += atkmin_ + rand() % (atkmax_-atkmin_ + 1);
else
damage2 += atkmin_ ;
- if(sd->atk_rate != 100) {
- damage = (damage * sd->atk_rate)/100;
- damage2 = (damage2 * sd->atk_rate)/100;
+ if(sd->atk_rate != 100 || sd->weapon_atk_rate != 0) {
+ if (sd->status.weapon < 16) {
+ damage = (damage * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100;
+ damage2 = (damage2 * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100;
+ }
}
if(sd->state.arrow_atk) {
@@ -3119,8 +1975,10 @@ static struct Damage battle_calc_pc_weapon_attack(
hitrate = (hitrate*(100+5*skill_lv))/100;
break;
case SM_MAGNUM: // マグナムブレイク
- damage = damage*(5*skill_lv +(wflag)?65:115 )/100;
- damage2 = damage2*(5*skill_lv +(wflag)?65:115 )/100;
+ // 20*skill level+100? i think this will do for now [based on jRO info]
+ damage = damage*(wflag > 1 ? 5*skill_lv+115 : 30*skill_lv+100)/100;
+ damage2 = damage2*(wflag > 1 ? 5*skill_lv+115 : 30*skill_lv+100)/100;
+ hitrate = (hitrate*(100+10*skill_lv))/100;
break;
case MC_MAMMONITE: // メマーナイト
damage = damage*(100+ 50*skill_lv)/100;
@@ -3134,7 +1992,6 @@ static struct Damage battle_calc_pc_weapon_attack(
}
damage = damage*(180+ 20*skill_lv)/100;
damage2 = damage2*(180+ 20*skill_lv)/100;
- div_=2;
if(sd->arrow_ele > 0) {
s_ele = sd->arrow_ele;
s_ele_ = sd->arrow_ele;
@@ -3177,12 +2034,12 @@ static struct Damage battle_calc_pc_weapon_attack(
damage2 = damage2*(100+ 10*skill_lv)/100;
hitrate=hitrate*(100+5*skill_lv)/100;
div_=t_size+1;
- damage*=div_;
- damage2*=div_;
+ div_flag=1;
break;
case KN_SPEARSTAB: // スピアスタブ
damage = damage*(100+ 15*skill_lv)/100;
damage2 = damage2*(100+ 15*skill_lv)/100;
+ blewcount=0;
break;
case KN_SPEARBOOMERANG: // スピアブーメラン
damage = damage*(100+ 50*skill_lv)/100;
@@ -3206,7 +2063,6 @@ static struct Damage battle_calc_pc_weapon_attack(
if(skill_lv>9 && wflag==2) damage4+=damage2/4;
if(skill_lv>9 && wflag==3) damage4+=damage2/2;
damage2 +=damage4;
- blewcount=0;
break;
case KN_BOWLINGBASH: // ボウリングバッシュ
damage = damage*(100+ 50*skill_lv)/100;
@@ -3233,7 +2089,6 @@ static struct Damage battle_calc_pc_weapon_attack(
hitrate+=30; // hitrate +30, thanks to midas
damage = damage*(300+ 50*skill_lv)/100;
damage2 = damage2*(300+ 50*skill_lv)/100;
- div_=8;
break;
case TF_SPRINKLESAND: // 砂まき
damage = damage*125/100;
@@ -3241,8 +2096,10 @@ static struct Damage battle_calc_pc_weapon_attack(
break;
case MC_CARTREVOLUTION: // カートレボリューション
if(sd->cart_max_weight > 0 && sd->cart_weight > 0) {
- damage = (damage*(150 + pc_checkskill(sd,BS_WEAPONRESEARCH) + (sd->cart_weight*100/sd->cart_max_weight) ) )/100;
- damage2 = (damage2*(150 + pc_checkskill(sd,BS_WEAPONRESEARCH) + (sd->cart_weight*100/sd->cart_max_weight) ) )/100;
+ damage = ( damage*(150 + sd->cart_weight/800) )/100; //fixed CARTREV damage [Lupus] // should be 800, not 80... weight is *10 ^_- [celest]
+ damage2 = ( damage2*(150 + sd->cart_weight/800) )/100;
+ //damage = (damage*(150 + pc_checkskill(sd,BS_WEAPONRESEARCH) + (sd->cart_weight*100/sd->cart_max_weight) ) )/100;
+ //damage2 = (damage2*(150 + pc_checkskill(sd,BS_WEAPONRESEARCH) + (sd->cart_weight*100/sd->cart_max_weight) ) )/100;
}
else {
damage = (damage*150)/100;
@@ -3251,9 +2108,7 @@ static struct Damage battle_calc_pc_weapon_attack(
break;
// 以下MOB
case NPC_COMBOATTACK: // 多段攻撃
- div_=skill_get_num(skill_num,skill_lv);
- damage *= div_;
- damage2 *= div_;
+ div_flag=1;
break;
case NPC_RANDOMATTACK: // ランダムATK攻撃
damage = damage*(50+rand()%150)/100;
@@ -3267,6 +2122,7 @@ static struct Damage battle_calc_pc_weapon_attack(
case NPC_POISONATTACK:
case NPC_HOLYATTACK:
case NPC_DARKNESSATTACK:
+ case NPC_UNDEADATTACK:
case NPC_TELEKINESISATTACK:
damage = damage*(100+25*skill_lv)/100;
damage2 = damage2*(100+25*skill_lv)/100;
@@ -3313,7 +2169,6 @@ static struct Damage battle_calc_pc_weapon_attack(
case CR_HOLYCROSS: // ホーリークロス
damage = damage*(100+ 35*skill_lv)/100;
damage2 = damage2*(100+ 35*skill_lv)/100;
- div_=2;
break;
case CR_GRANDCROSS:
hitrate= 1000000;
@@ -3324,28 +2179,30 @@ static struct Damage battle_calc_pc_weapon_attack(
case AM_DEMONSTRATION: // デモンストレーション
damage = damage*(100+ 20*skill_lv)/100;
damage2 = damage2*(100+ 20*skill_lv)/100;
+ no_cardfix = 1;
break;
case AM_ACIDTERROR: // アシッドテラー
+ hitrate = 1000000;
damage = damage*(100+ 40*skill_lv)/100;
damage2 = damage2*(100+ 40*skill_lv)/100;
+ s_ele = 0;
+ s_ele_ = 0;
+ no_cardfix = 1;
break;
case MO_FINGEROFFENSIVE: //指弾
+ damage = damage * (125 + 25 * skill_lv) / 100;
+ damage2 = damage2 * (125 + 25 * skill_lv) / 100;
if(battle_config.finger_offensive_type == 0) {
- damage = damage * (125 + 25 * skill_lv) / 100 * sd->spiritball_old;
- damage2 = damage2 * (125 + 25 * skill_lv) / 100 * sd->spiritball_old;
div_ = sd->spiritball_old;
+ div_flag = 1;
}
- else {
- damage = damage * (125 + 25 * skill_lv) / 100;
- damage2 = damage2 * (125 + 25 * skill_lv) / 100;
- div_ = 1;
- }
+ else div_ = 1;
flag=(flag&~BF_RANGEMASK)|BF_LONG; //orn
break;
case MO_INVESTIGATE: // 発 勁
if(def1 < 1000000) {
- damage = damage*(100+ 75*skill_lv)/100 * (def1 + def2)/100;
- damage2 = damage2*(100+ 75*skill_lv)/100 * (def1 + def2)/100;
+ damage = damage*(100+ 75*skill_lv)/100 * (def1 + def2)/50;
+ damage2 = damage2*(100+ 75*skill_lv)/100 * (def1 + def2)/50;
}
hitrate = 1000000;
s_ele = 0;
@@ -3363,26 +2220,19 @@ static struct Damage battle_calc_pc_weapon_attack(
case MO_CHAINCOMBO: // 連打掌
damage = damage*(150+ 50*skill_lv)/100;
damage2 = damage2*(150+ 50*skill_lv)/100;
- div_=4;
break;
case MO_COMBOFINISH: // 猛龍拳
damage = damage*(240+ 60*skill_lv)/100;
damage2 = damage2*(240+ 60*skill_lv)/100;
break;
case BA_MUSICALSTRIKE: // ミュージカルストライク
- if(!sd->state.arrow_atk && sd->arrow_atk > 0) {
- int arr = rand()%(sd->arrow_atk+1);
- damage += arr;
- damage2 += arr;
- }
- damage = damage*(100+ 50 * skill_lv)/100;
- damage2 = damage2*(100+ 50 * skill_lv)/100;
+ damage = damage*(60+ 40 * skill_lv)/100;
+ damage2 = damage2*(60+ 40 * skill_lv)/100;
if(sd->arrow_ele > 0) {
s_ele = sd->arrow_ele;
s_ele_ = sd->arrow_ele;
}
flag=(flag&~BF_RANGEMASK)|BF_LONG;
- sd->state.arrow_atk = 1;
break;
case DC_THROWARROW: // 矢撃ち
if(!sd->state.arrow_atk && sd->arrow_atk > 0) {
@@ -3400,22 +2250,21 @@ static struct Damage battle_calc_pc_weapon_attack(
sd->state.arrow_atk = 1;
break;
case CH_TIGERFIST: // 伏虎拳
- damage = damage*(100+ 20*skill_lv)/100;
- damage2 = damage2*(100+ 20*skill_lv)/100;
+ damage = damage*(40+ 100*skill_lv)/100;
+ damage2 = damage*(40+ 100*skill_lv)/100;
break;
case CH_CHAINCRUSH: // 連柱崩撃
- damage = damage*(100+ 60*skill_lv)/100;
- damage2 = damage2*(100+ 60*skill_lv)/100;
- div_=skill_get_num(skill_num,skill_lv);
+ damage = damage*(400+ 100*skill_lv)/100;
+ damage2 = damage*(400+ 100*skill_lv)/100;
break;
case CH_PALMSTRIKE: // 猛虎硬派山
- damage = damage*(50+ 100*skill_lv)/100;
- damage2 = damage2*(50+ 100*skill_lv)/100;
+ damage = damage*(200+ 100*skill_lv)/100;
+ damage2 = damage*(200+ 100*skill_lv)/100;
break;
case LK_SPIRALPIERCE: /* スパイラルピアース */
damage = damage*(100+ 50*skill_lv)/100; //増加量が分からないので適当に
damage2 = damage2*(100+ 50*skill_lv)/100; //増加量が分からないので適当に
- div_=5;
+ flag=(flag&~BF_RANGEMASK)|BF_LONG;
if(tsd)
tsd->canmove_tick = gettick() + 1000;
else if(tmd)
@@ -3441,35 +2290,33 @@ static struct Damage battle_calc_pc_weapon_attack(
case CG_ARROWVULCAN: /* アローバルカン */
damage = damage*(200+100*skill_lv)/100;
damage2 = damage2*(200+100*skill_lv)/100;
- div_=9;
+ if(sd->arrow_ele > 0) {
+ s_ele = sd->arrow_ele;
+ s_ele_ = sd->arrow_ele;
+ }
+ flag=(flag&~BF_RANGEMASK)|BF_LONG;
break;
case AS_SPLASHER: /* ベナムスプラッシャー */
damage = damage*(200+20*skill_lv+20*pc_checkskill(sd,AS_POISONREACT))/100;
damage2 = damage2*(200+20*skill_lv+20*pc_checkskill(sd,AS_POISONREACT))/100;
- break;
- case PA_SACRIFICE:
- if(sd){
- int hp, mhp, damage3;
- hp = battle_get_hp(src);
- mhp = battle_get_max_hp(src);
- damage3 = mhp*9/100;
- damage = damage*damage3*(90+10*skill_lv)/10000;
- damage2 = damage2*damage3*(90+10*skill_lv)/10000;
- }
+ no_cardfix = 1;
+ hitrate = 1000000;
break;
case ASC_BREAKER: // -- moonsoul (special damage for ASC_BREAKER skill)
if(sd){
- int damage3;
- int mdef1=battle_get_mdef(target);
- int mdef2=battle_get_mdef2(target);
- int imdef_flag=0;
-
- damage = ((damage * 5) + (skill_lv * battle_get_int(src) * 5) + rand()%500 + 500) /2;
- damage2 = ((damage2 * 5) + (skill_lv * battle_get_int(src) * 5) + rand()%500 + 500) /2;
- damage3 = damage;
- hitrate = 1000000;
-
- if(sd->ignore_mdef_ele & (1<<t_ele) || sd->ignore_mdef_race & (1<<t_race))
+ // calculate physical part of damage
+#ifndef TWILIGHT
+ damage = damage * skill_lv;
+ damage2 = damage2 * skill_lv;
+#else /* TWILIGHT */
+ damage = damage * skill_lv * 0.5; //Halved by Krel
+ damage2 = damage2 * skill_lv * 0.5; //Halved by Krel
+ // element modifier added right after this
+
+ // calculate magic part of damage
+ damage3 = skill_lv * status_get_int(src) * 5 * 0.5; //Krel
+ // ignores magic defense now [Celest]
+ /*if(sd->ignore_mdef_ele & (1<<t_ele) || sd->ignore_mdef_race & (1<<t_race))
imdef_flag = 1;
if(t_mode & 0x20) {
if(sd->ignore_mdef_race & (1<<10))
@@ -3487,14 +2334,23 @@ static struct Damage battle_calc_pc_weapon_attack(
damage3 = (damage3*(100-mdef1))/100 - mdef2;
}
}
-
+
if(damage3<1)
damage3=1;
- damage3=battle_attr_fix(damage2,s_ele_, battle_get_element(target) );
+ damage3=battle_attr_fix(damage2,s_ele_, status_get_element(target) );*/
+
+#endif /* TWILIGHT */
+ flag=(flag&~BF_RANGEMASK)|BF_LONG;
}
break;
}
+ if (div_flag && div_ > 1) { // [Skotlex]
+ damage *= div_;
+ damage2 *= div_;
+ }
+ if (sd && skill_num > 0 && sd->skillatk[0] == skill_num)
+ damage += damage*sd->skillatk[1]/100;
}
if(da == 2) { //三段掌が発動しているか
type = 0x08;
@@ -3505,20 +2361,20 @@ static struct Damage battle_calc_pc_weapon_attack(
if( skill_num!=NPC_CRITICALSLASH ){
// 対 象の防御力によるダメージの減少
// ディバインプロテクション(ここでいいのかな?)
- if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && def1 < 1000000) { //DEF, VIT無視
+ if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && skill_num != AM_ACIDTERROR && def1 < 1000000) { //DEF, VIT無視
int t_def;
- target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penaly_count_lv);
- if(battle_config.vit_penaly_type > 0) {
- if(target_count >= battle_config.vit_penaly_count) {
- if(battle_config.vit_penaly_type == 1) {
- def1 = (def1 * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100;
- def2 = (def2 * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100;
- t_vit = (t_vit * (100 - (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num))/100;
+ target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penalty_count_lv);
+ if(battle_config.vit_penalty_type > 0) {
+ if(target_count >= battle_config.vit_penalty_count) {
+ if(battle_config.vit_penalty_type == 1) {
+ def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
+ def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
+ t_vit = (t_vit * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
}
- else if(battle_config.vit_penaly_type == 2) {
- def1 -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num;
- def2 -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num;
- t_vit -= (target_count - (battle_config.vit_penaly_count - 1))*battle_config.vit_penaly_num;
+ else if(battle_config.vit_penalty_type == 2) {
+ def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
+ def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
+ t_vit -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
}
if(def1 < 0) def1 = 0;
if(def2 < 1) def2 = 1;
@@ -3527,6 +2383,19 @@ static struct Damage battle_calc_pc_weapon_attack(
}
t_def = def2*8/10;
vitbonusmax = (t_vit/20)*(t_vit/20)-1;
+ if (tmd) {
+ if(t_mode & 0x20) {
+ if(sd->ignore_def_mob & 2)
+ idef_flag = 1;
+ if(sd->ignore_def_mob_ & 2)
+ idef_flag_ = 1;
+ } else {
+ if(sd->ignore_def_mob & 1)
+ idef_flag = 1;
+ if(sd->ignore_def_mob_ & 1)
+ idef_flag_ = 1;
+ }
+ }
if(sd->ignore_def_ele & (1<<t_ele) || sd->ignore_def_race & (1<<t_race))
idef_flag = 1;
if(sd->ignore_def_ele_ & (1<<t_ele) || sd->ignore_def_race_ & (1<<t_race))
@@ -3567,24 +2436,39 @@ static struct Damage battle_calc_pc_weapon_attack(
// 状態異常中のダメージ追加でクリティカルにも有効なスキル
if (sc_data) {
// エンチャントデッドリーポイズン
- if(sc_data[SC_EDP].timer != -1) {
+ if(!no_cardfix && sc_data[SC_EDP].timer != -1 && skill_num != ASC_BREAKER && skill_num != ASC_METEORASSAULT) {
damage += damage * (150 + sc_data[SC_EDP].val1 * 50) / 100;
- damage2 += damage2 * (150 + sc_data[SC_EDP].val1 * 50) / 100;
no_cardfix = 1;
}
+ // sacrifice works on boss monsters, and does 9% damage to self [Celest]
+ if (!skill_num && /*!(t_mode&0x20) &&*/ sc_data[SC_SACRIFICE].timer != -1) {
+ int mhp = status_get_max_hp(src);
+ int dmg = mhp * 9/100;
+ pc_heal(sd, -dmg, 0);
+ damage = dmg * (90 + sc_data[SC_SACRIFICE].val1 * 10) / 100;
+ damage2 = 0;
+ hitrate = 1000000;
+ s_ele = 0;
+ s_ele_ = 0;
+ skill_num = PA_SACRIFICE;
+ //clif_skill_nodamage(src,target,skill_num,skill_lv,1); // this doesn't show effect either.. hmm =/
+ sc_data[SC_SACRIFICE].val2 --;
+ if (sc_data[SC_SACRIFICE].val2 == 0)
+ status_change_end(src, SC_SACRIFICE,-1);
+ }
}
// 精錬ダメージの追加
if( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST) { //DEF, VIT無視
- damage += battle_get_atk2(src);
- damage2 += battle_get_atk_2(src);
+ damage += status_get_atk2(src);
+ damage2 += status_get_atk_2(src);
}
if(skill_num == CR_SHIELDBOOMERANG) {
if(sd->equip_index[8] >= 0) {
int index = sd->equip_index[8];
if(sd->inventory_data[index] && sd->inventory_data[index]->type == 5) {
damage += sd->inventory_data[index]->weight/10;
- damage += sd->status.inventory[index].refine * pc_getrefinebonus(0,1);
+ damage += sd->status.inventory[index].refine * status_getrefinebonus(0,1);
}
}
}
@@ -3593,7 +2477,7 @@ static struct Damage battle_calc_pc_weapon_attack(
int index = sd->equip_index[9];
if(sd->inventory_data[index] && sd->inventory_data[index]->type == 4) {
damage += (int)(double)(sd->inventory_data[index]->weight*(0.8*skill_lv*4/10));
- damage += sd->status.inventory[index].refine * pc_getrefinebonus(0,1);
+ damage += sd->status.inventory[index].refine * status_getrefinebonus(0,1);
}
}
}
@@ -3617,10 +2501,10 @@ static struct Damage battle_calc_pc_weapon_attack(
// 回避修正
if( hitrate < 1000000 && t_sc_data ) { // 必中攻撃
if(t_sc_data[SC_FOGWALL].timer != -1 && flag&BF_LONG)
- hitrate -= 50;
+ hitrate -= 75;
if (t_sc_data[SC_SLEEP].timer!=-1 || // 睡眠は必中
t_sc_data[SC_STAN].timer!=-1 || // スタンは必中
- t_sc_data[SC_FREEZE].timer!=-1 ||
+ t_sc_data[SC_FREEZE].timer!=-1 ||
(t_sc_data[SC_STONE].timer!=-1 && t_sc_data[SC_STONE].val2==0)) // 凍結は必中
hitrate = 1000000;
}
@@ -3653,17 +2537,20 @@ static struct Damage battle_calc_pc_weapon_attack(
cardfix=cardfix*(100+sd->addrace[t_race])/100; // 種族によるダメージ修正
cardfix=cardfix*(100+sd->addele[t_ele])/100; // 属性によるダメージ修正
cardfix=cardfix*(100+sd->addsize[t_size])/100; // サイズによるダメージ修正
+ cardfix=cardfix*(100+sd->addrace2[t_race2])/100;
}
else {
cardfix=cardfix*(100+sd->addrace[t_race]+sd->addrace_[t_race])/100; // 種族によるダメージ修正(左手による追加あり)
cardfix=cardfix*(100+sd->addele[t_ele]+sd->addele_[t_ele])/100; // 属性によるダメージ修正(左手による追加あり)
cardfix=cardfix*(100+sd->addsize[t_size]+sd->addsize_[t_size])/100; // サイズによるダメージ修正(左手による追加あり)
+ cardfix=cardfix*(100+sd->addrace2[t_race2]+sd->addrace2_[t_race2])/100;
}
}
else { //弓矢
cardfix=cardfix*(100+sd->addrace[t_race]+sd->arrow_addrace[t_race])/100; // 種族によるダメージ修正(弓矢による追加あり)
cardfix=cardfix*(100+sd->addele[t_ele]+sd->arrow_addele[t_ele])/100; // 属性によるダメージ修正(弓矢による追加あり)
cardfix=cardfix*(100+sd->addsize[t_size]+sd->arrow_addsize[t_size])/100; // サイズによるダメージ修正(弓矢による追加あり)
+ cardfix=cardfix*(100+sd->addrace2[t_race2])/100;
}
if(t_mode & 0x20) { //ボス
if(!sd->state.arrow_atk) { //弓矢攻撃以外なら
@@ -3686,7 +2573,7 @@ static struct Damage battle_calc_pc_weapon_attack(
cardfix=cardfix*(100+sd->addrace[11]+sd->arrow_addrace[11])/100; //ボス以外モンスターに追加ダメージ(弓矢による追加あり)
}
//特定Class用補正処理(少女の日記→ボンゴン用?)
- t_class = battle_get_class(target);
+ t_class = status_get_class(target);
for(i=0;i<sd->add_damage_class_count;i++) {
if(sd->add_damage_classid[i] == t_class) {
cardfix=cardfix*(100+sd->add_damage_classrate[i])/100;
@@ -3703,6 +2590,7 @@ static struct Damage battle_calc_pc_weapon_attack(
cardfix=cardfix*(100+sd->addrace_[t_race])/100; // 種族によるダメージ修正左手
cardfix=cardfix*(100+sd->addele_[t_ele])/100; // 属 性によるダメージ修正左手
cardfix=cardfix*(100+sd->addsize_[t_size])/100; // サイズによるダメージ修正左手
+ cardfix=cardfix*(100+sd->addrace2_[t_race2])/100;
if(t_mode & 0x20) //ボス
cardfix=cardfix*(100+sd->addrace_[10])/100; //ボスモンスターに追加ダメージ左手
else
@@ -3716,27 +2604,24 @@ static struct Damage battle_calc_pc_weapon_attack(
}
}
if(!no_cardfix)
-
damage2=damage2*cardfix/100;
+
//カード補正による左手ダメージ増加
//カードによるダメージ増加処理(左手)ここまで
-// -- moonsoul (cardfix for magic damage portion of ASC_BREAKER)
- if(skill_num == ASC_BREAKER)
- damage3 = damage3 * cardfix / 100;
-
//カードによるダメージ減衰処理ここから
if(tsd){ //対象がPCの場合
cardfix=100;
cardfix=cardfix*(100-tsd->subrace[s_race])/100; // 種族によるダメージ耐性
cardfix=cardfix*(100-tsd->subele[s_ele])/100; // 属性によるダメージ耐性
- if(battle_get_mode(src) & 0x20)
+ cardfix=cardfix*(100-tsd->subsize[s_size])/100;
+ if(status_get_mode(src) & 0x20)
cardfix=cardfix*(100-tsd->subrace[10])/100; //ボスからの攻撃はダメージ減少
else
cardfix=cardfix*(100-tsd->subrace[11])/100; //ボス以外からの攻撃はダメージ減少
//特定Class用補正処理左手(少女の日記→ボンゴン用?)
for(i=0;i<tsd->add_def_class_count;i++) {
- if(tsd->add_def_classid[i] == sd->status.class) {
+ if(tsd->add_def_classid[i] == sd->status.class_) {
cardfix=cardfix*(100-tsd->add_def_classrate[i])/100;
break;
}
@@ -3756,29 +2641,29 @@ static struct Damage battle_calc_pc_weapon_attack(
if(t_sc_data[SC_DEFENDER].timer != -1 && flag&BF_LONG) //ディフェンダー状態で遠距離攻撃
cardfix=cardfix*(100-t_sc_data[SC_DEFENDER].val2)/100; //ディフェンダーによる減衰
if(t_sc_data[SC_FOGWALL].timer != -1 && flag&BF_LONG)
- cardfix=cardfix*(100-t_sc_data[SC_FOGWALL].val2)/100;
+ cardfix=cardfix*50/100;
if(cardfix != 100) {
damage=damage*cardfix/100; //ディフェンダー補正によるダメージ減少
damage2=damage2*cardfix/100; //ディフェンダー補正による左手ダメージ減少
}
if(t_sc_data[SC_ASSUMPTIO].timer != -1){ //アスムプティオ
if(!map[target->m].flag.pvp){
- damage=damage/3;
- damage2=damage2/3;
- }else{
- damage=damage/2;
- damage2=damage2/2;
+ damage=damage/3;
+ damage2=damage2/3;
+ }else{
+ damage=damage/2;
+ damage2=damage2/2;
+ }
}
}
- }
//対象にステータス異常がある場合のダメージ減算処理ここまで
if(damage < 0) damage = 0;
if(damage2 < 0) damage2 = 0;
// 属 性の適用
- damage=battle_attr_fix(damage,s_ele, battle_get_element(target) );
- damage2=battle_attr_fix(damage2,s_ele_, battle_get_element(target) );
+ damage=battle_attr_fix(damage,s_ele, status_get_element(target) );
+ damage2=battle_attr_fix(damage2,s_ele_, status_get_element(target) );
// 星のかけら、気球の適用
damage += sd->star;
@@ -3797,16 +2682,16 @@ static struct Damage battle_calc_pc_weapon_attack(
// >二刀流の左右ダメージ計算誰かやってくれぇぇぇぇえええ!
// >map_session_data に左手ダメージ(atk,atk2)追加して
- // >pc_calcstatus()でやるべきかな?
+ // >status_calc_pc()でやるべきかな?
// map_session_data に左手武器(atk,atk2,ele,star,atkmods)追加して
- // pc_calcstatus()でデータを入力しています
+ // status_calc_pc()でデータを入力しています
//左手のみ武器装備
if(sd->weapontype1 == 0 && sd->weapontype2 > 0) {
damage = damage2;
damage2 = 0;
}
-
+
// 右手、左手修練の適用
if(sd->status.weapon > 16) {// 二刀流か?
int dmg = damage, dmg2 = damage2;
@@ -3838,14 +2723,14 @@ static struct Damage battle_calc_pc_weapon_attack(
// インベナム修正
if(skill_num==TF_POISON){
- damage = battle_attr_fix(damage + 15*skill_lv, s_ele, battle_get_element(target) );
+ damage = battle_attr_fix(damage + 15*skill_lv, s_ele, status_get_element(target) );
}
if(skill_num==MC_CARTREVOLUTION){
- damage = battle_attr_fix(damage, 0, battle_get_element(target) );
+ damage = battle_attr_fix(damage, 0, status_get_element(target) );
}
// 完全回避の判定
- if(skill_num == 0 && skill_lv >= 0 && tsd!=NULL && div_ < 255 && rand()%1000 < battle_get_flee2(target) ){
+ if(skill_num == 0 && tsd!=NULL && div_ < 255 && rand()%1000 < status_get_flee2(target) ){
damage=damage2=0;
type=0x0b;
dmg_lv = ATK_LUCKY;
@@ -3853,7 +2738,7 @@ static struct Damage battle_calc_pc_weapon_attack(
// 対象が完全回避をする設定がONなら
if(battle_config.enemy_perfect_flee) {
- if(skill_num == 0 && skill_lv >= 0 && tmd!=NULL && div_ < 255 && rand()%1000 < battle_get_flee2(target) ) {
+ if(skill_num == 0 && tmd!=NULL && div_ < 255 && rand()%1000 < status_get_flee2(target) ) {
damage=damage2=0;
type=0x0b;
dmg_lv = ATK_LUCKY;
@@ -3921,21 +2806,14 @@ static struct Damage battle_calc_pc_weapon_attack(
}
}
-
-// -- moonsoul (final combination of phys, mag damage for ASC_BREAKER)
- if(skill_num == ASC_BREAKER) {
- damage += damage3;
- damage2 += damage3;
- }
-
wd.damage=damage;
wd.damage2=damage2;
wd.type=type;
wd.div_=div_;
- wd.amotion=battle_get_amotion(src);
+ wd.amotion=status_get_amotion(src);
if(skill_num == KN_AUTOCOUNTER)
wd.amotion >>= 1;
- wd.dmotion=battle_get_dmotion(target);
+ wd.dmotion=status_get_dmotion(target);
wd.blewcount=blewcount;
wd.flag=flag;
wd.dmg_lv=dmg_lv;
@@ -3972,32 +2850,45 @@ struct Damage battle_calc_weapon_attack(
memset(&wd,0,sizeof(wd));
if(battle_config.equipment_breaking && src->type==BL_PC && (wd.damage > 0 || wd.damage2 > 0)) {
- struct map_session_data *sd=(struct map_session_data *)src;
- int breakrate=1;
- if(sd->status.weapon && sd->status.weapon!=11) {
- if(target->type == BL_PC && sd->sc_data[SC_MELTDOWN].timer!=-1){
- breakrate+=100*sd->sc_data[SC_MELTDOWN].val1;
- if(rand()%10000 < breakrate*battle_config.equipment_break_rate/100 || breakrate >= 10000)
- pc_breakweapon((struct map_session_data *)target);
+ struct map_session_data *sd = (struct map_session_data *)src;
+ // weapon = 0, armor = 1
+ int breakrate = 1; //0.01% default self weapon breaking chance [DracoRPG]
+ int breakrate_[2] = {0,0}; //enemy breaking chance [celest]
+ int breaktime = 5000;
+
+ breakrate_[0] += sd->break_weapon_rate;
+ breakrate_[1] += sd->break_armor_rate;
+
+ if (sd->sc_count) {
+ if (sd->sc_data[SC_MELTDOWN].timer!=-1) {
+ breakrate_[0] += 100*sd->sc_data[SC_MELTDOWN].val1;
+ breakrate_[1] = 70*sd->sc_data[SC_MELTDOWN].val1;
+ breaktime = skill_get_time2(WS_MELTDOWN,1);
}
if(sd->sc_data[SC_OVERTHRUST].timer!=-1)
- breakrate+=20*sd->sc_data[SC_OVERTHRUST].val1;
- if(wd.type==0x0a)
- breakrate*=2;
- if(rand()%10000 < breakrate*battle_config.equipment_break_rate/100 || breakrate >= 10000) {
- if(pc_breakweapon(sd)==1)
+ breakrate += 10;
+ }
+
+ if(sd->status.weapon && sd->status.weapon != 11) {
+ if(rand() % 10000 < breakrate * battle_config.equipment_break_rate / 100 || breakrate >= 10000)
+ if (pc_breakweapon(sd) == 1)
wd = battle_calc_pc_weapon_attack(src,target,skill_num,skill_lv,wflag);
- }
}
- }
-
- if (battle_config.equipment_breaking && target->type == BL_PC && (wd.damage > 0 || wd.damage2 > 0)) {
- int breakrate=1;
- if(src->type==BL_PC && ((struct map_session_data *)src)->sc_data[SC_MELTDOWN].timer!=-1) breakrate+=70*((struct map_session_data *)src)->sc_data[SC_MELTDOWN].val1;
- if (wd.type==0x0a)
- breakrate*=2;
- if (rand()%10000 < breakrate*battle_config.equipment_break_rate/100 || breakrate >= 10000) {
- pc_breakarmor((struct map_session_data *)target);
+ if(rand() % 10000 < breakrate_[0] * battle_config.equipment_break_rate / 100 || breakrate_[0] >= 10000) {
+ if (target->type == BL_PC) {
+ struct map_session_data *tsd = (struct map_session_data *)target;
+ if(tsd->status.weapon != 11)
+ pc_breakweapon(tsd);
+ } else
+ status_change_start(target,SC_STRIPWEAPON,1,75,0,0,breaktime,0);
+ }
+ if(rand() % 10000 < breakrate_[1] * battle_config.equipment_break_rate/100 || breakrate_[1] >= 10000) {
+ if (target->type == BL_PC) {
+ struct map_session_data *tsd = (struct map_session_data *)target;
+ if(tsd->status.weapon != 11)
+ pc_breakarmor(tsd);
+ } else
+ status_change_start(target,SC_STRIPSHIELD,1,75,0,0,breaktime,0);
}
}
@@ -4011,13 +2902,14 @@ struct Damage battle_calc_weapon_attack(
struct Damage battle_calc_magic_attack(
struct block_list *bl,struct block_list *target,int skill_num,int skill_lv,int flag)
{
- int mdef1=battle_get_mdef(target);
- int mdef2=battle_get_mdef2(target);
+ int mdef1=status_get_mdef(target);
+ int mdef2=status_get_mdef2(target);
int matk1,matk2,damage=0,div_=1,blewcount=skill_get_blewcount(skill_num,skill_lv),rdamage = 0;
struct Damage md;
int aflag;
int normalmagic_flag=1;
- int ele=0,race=7,t_ele=0,t_race=7,t_mode = 0,cardfix,t_class,i;
+ int matk_flag = 1;
+ int ele=0,race=7,size=1,race2=7,t_ele=0,t_race=7,t_mode = 0,cardfix,t_class,i;
struct map_session_data *sd=NULL,*tsd=NULL;
struct mob_data *tmd = NULL;
@@ -4034,13 +2926,15 @@ struct Damage battle_calc_magic_attack(
return md;
}
- matk1=battle_get_matk1(bl);
- matk2=battle_get_matk2(bl);
+ matk1=status_get_matk1(bl);
+ matk2=status_get_matk2(bl);
ele = skill_get_pl(skill_num);
- race = battle_get_race(bl);
- t_ele = battle_get_elem_type(target);
- t_race = battle_get_race(target);
- t_mode = battle_get_mode(target);
+ race = status_get_race(bl);
+ size = status_get_size(bl);
+ race2 = status_get_race2(bl);
+ t_ele = status_get_elem_type(target);
+ t_race = status_get_race(target);
+ t_mode = status_get_mode(target);
#define MATK_FIX( a,b ) { matk1=matk1*(a)/(b); matk2=matk2*(a)/(b); }
@@ -4078,10 +2972,10 @@ struct Damage battle_calc_magic_attack(
case PR_TURNUNDEAD: // 攻撃リザレクションとターンアンデッド
if(target->type != BL_PC && battle_check_undead(t_race,t_ele)){
int hp, mhp, thres;
- hp = battle_get_hp(target);
- mhp = battle_get_max_hp(target);
- thres = (skill_lv * 20) + battle_get_luk(bl)+
- battle_get_int(bl) + battle_get_lv(bl)+
+ hp = status_get_hp(target);
+ mhp = status_get_max_hp(target);
+ thres = (skill_lv * 20) + status_get_luk(bl)+
+ status_get_int(bl) + status_get_lv(bl)+
((200 - hp * 200 / mhp));
if(thres > 700) thres = 700;
// if(battle_config.battle_log)
@@ -4089,7 +2983,7 @@ struct Damage battle_calc_magic_attack(
if(rand()%1000 < thres && !(t_mode&0x20)) // 成功
damage = hp;
else // 失敗
- damage = battle_get_lv(bl) + battle_get_int(bl) + skill_lv * 10;
+ damage = status_get_lv(bl) + status_get_int(bl) + skill_lv * 10;
}
normalmagic_flag=0;
break;
@@ -4157,7 +3051,7 @@ struct Damage battle_calc_magic_attack(
break;
case WZ_STORMGUST: // ストームガスト
MATK_FIX( skill_lv*40+100 ,100 );
- blewcount|=0x10000;
+// blewcount|=0x10000;
break;
case AL_HOLYLIGHT: // ホーリーライト
MATK_FIX( 125,100 );
@@ -4174,15 +3068,30 @@ struct Damage battle_calc_magic_attack(
printf("battle_calc_magic_attack(): napalmvulcan enemy count=0 !\n");
}
break;
+ case PF_SOULBURN: // Celest
+ if (target->type != BL_PC || skill_lv < 5) {
+ memset(&md,0,sizeof(md));
+ return md;
+ } else if (target->type == BL_PC) {
+ damage = ((struct map_session_data *)target)->status.sp * 2;
+ matk_flag = 0; // don't consider matk and matk2
+ }
+ break;
+ case ASC_BREAKER:
+ damage = rand()%500 + 500 + skill_lv * status_get_int(bl) * 5;
+ matk_flag = 0; // don't consider matk and matk2
+ break;
}
}
if(normalmagic_flag){ // 一般魔法ダメージ計算
int imdef_flag=0;
- if(matk1>matk2)
- damage= matk2+rand()%(matk1-matk2+1);
- else
- damage= matk2;
+ if (matk_flag) {
+ if(matk1>matk2)
+ damage= matk2+rand()%(matk1-matk2+1);
+ else
+ damage= matk2;
+ }
if(sd) {
if(sd->ignore_mdef_ele & (1<<t_ele) || sd->ignore_mdef_race & (1<<t_race))
imdef_flag = 1;
@@ -4216,7 +3125,7 @@ struct Damage battle_calc_magic_attack(
cardfix=cardfix*(100+sd->magic_addrace[10])/100;
else
cardfix=cardfix*(100+sd->magic_addrace[11])/100;
- t_class = battle_get_class(target);
+ t_class = status_get_class(target);
for(i=0;i<sd->add_magic_damage_class_count;i++) {
if(sd->add_magic_damage_classid[i] == t_class) {
cardfix=cardfix*(100+sd->add_magic_damage_classrate[i])/100;
@@ -4224,15 +3133,19 @@ struct Damage battle_calc_magic_attack(
}
}
damage=damage*cardfix/100;
+ if (skill_num > 0 && sd->skillatk[0] == skill_num)
+ damage += damage*sd->skillatk[1]/100;
}
if( tsd ){
- int s_class = battle_get_class(bl);
+ int s_class = status_get_class(bl);
cardfix=100;
cardfix=cardfix*(100-tsd->subele[ele])/100; // 属 性によるダメージ耐性
cardfix=cardfix*(100-tsd->subrace[race])/100; // 種族によるダメージ耐性
+ cardfix=cardfix*(100-tsd->subsize[size])/100;
cardfix=cardfix*(100-tsd->magic_subrace[race])/100;
- if(battle_get_mode(bl) & 0x20)
+ cardfix=cardfix*(100-tsd->subrace2[race2])/100; // 種族によるダメージ耐性
+ if(status_get_mode(bl) & 0x20)
cardfix=cardfix*(100-tsd->magic_subrace[10])/100;
else
cardfix=cardfix*(100-tsd->magic_subrace[11])/100;
@@ -4247,13 +3160,13 @@ struct Damage battle_calc_magic_attack(
}
if(damage < 0) damage = 0;
- damage=battle_attr_fix(damage, ele, battle_get_element(target) ); // 属 性修正
+ damage=battle_attr_fix(damage, ele, status_get_element(target) ); // 属 性修正
if(skill_num == CR_GRANDCROSS) { // グランドクロス
struct Damage wd;
wd=battle_calc_weapon_attack(bl,target,skill_num,skill_lv,flag);
damage = (damage + wd.damage) * (100 + 40*skill_lv)/100;
- if(battle_config.gx_dupele) damage=battle_attr_fix(damage, ele, battle_get_element(target) ); //属性2回かかる
+ if(battle_config.gx_dupele) damage=battle_attr_fix(damage, ele, status_get_element(target) ); //属性2回かかる
if(bl==target) damage=damage/2; //反動は半分
}
@@ -4287,8 +3200,8 @@ struct Damage battle_calc_magic_attack(
md.damage=damage;
md.div_=div_;
- md.amotion=battle_get_amotion(bl);
- md.dmotion=battle_get_dmotion(target);
+ md.amotion=status_get_amotion(bl);
+ md.dmotion=status_get_dmotion(target);
md.damage2=0;
md.type=0;
md.blewcount=blewcount;
@@ -4304,16 +3217,16 @@ struct Damage battle_calc_magic_attack(
struct Damage battle_calc_misc_attack(
struct block_list *bl,struct block_list *target,int skill_num,int skill_lv,int flag)
{
- int int_=battle_get_int(bl);
-// int luk=battle_get_luk(bl);
- int dex=battle_get_dex(bl);
- int skill,ele,race,cardfix;
+ int int_=status_get_int(bl);
+// int luk=status_get_luk(bl);
+ int dex=status_get_dex(bl);
+ int skill,ele,race,size,cardfix,race2;
struct map_session_data *sd=NULL,*tsd=NULL;
int damage=0,div_=1,blewcount=skill_get_blewcount(skill_num,skill_lv);
struct Damage md;
int damagefix=1;
- int aflag=BF_MISC|BF_LONG|BF_SKILL;
+ int aflag=BF_MISC|BF_SHORT|BF_SKILL;
//return前の処理があるので情報出力部のみ変更
if( bl == NULL || target == NULL ){
@@ -4355,11 +3268,13 @@ struct Damage battle_calc_misc_attack(
damage=(dex/10+int_/2+skill*3+40)*2;
if(flag > 1)
damage /= flag;
+ aflag |= (flag&~BF_RANGEMASK)|BF_LONG;
break;
case TF_THROWSTONE: // 石投げ
damage=50;
damagefix=0;
+ aflag |= (flag&~BF_RANGEMASK)|BF_LONG;
break;
case BA_DISSONANCE: // 不協和音
@@ -4367,7 +3282,7 @@ struct Damage battle_calc_misc_attack(
break;
case NPC_SELFDESTRUCTION: // 自爆
- damage=battle_get_hp(bl)-(bl==target?1:0);
+ damage=status_get_hp(bl)-(bl==target?1:0);
damagefix=0;
break;
@@ -4378,8 +3293,8 @@ struct Damage battle_calc_misc_attack(
case NPC_DARKBREATH:
{
- struct status_change *sc_data = battle_get_sc_data(target);
- int hitrate=battle_get_hit(bl) - battle_get_flee(target) + 80;
+ struct status_change *sc_data = status_get_sc_data(target);
+ int hitrate=status_get_hit(bl) - status_get_flee(target) + 80;
hitrate = ( (hitrate>95)?95: ((hitrate<5)?5:hitrate) );
if(sc_data && (sc_data[SC_SLEEP].timer!=-1 || sc_data[SC_STAN].timer!=-1 ||
sc_data[SC_FREEZE].timer!=-1 || (sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0) ) )
@@ -4391,13 +3306,25 @@ struct Damage battle_calc_misc_attack(
}
break;
case SN_FALCONASSAULT: /* ファルコンアサルト */
- skill = pc_checkskill(sd,HT_STEELCROW); // Celest
- damage=((150+50*skill_lv)*(dex/10+int_/2+skill*3+40)*2)/100;
+#ifdef TWILIGHT
+ if( sd==NULL || (skill = pc_checkskill(sd,HT_BLITZBEAT)) <= 0)
+ skill=0;
+ damage=(100+50*skill_lv+(dex/10+int_/2+skill*3+40)*2) * 2;
+#else
+ if( sd==NULL || (skill = pc_checkskill(sd,HT_STEELCROW)) <= 0)
+ skill=0;
+ damage=((150+50*skill_lv)*(dex/10+int_/2+skill*3+40)*2)/100; // [Celest]
+#endif
+ if(flag > 1)
+ damage /= flag;
+ aflag |= (flag&~BF_RANGEMASK)|BF_LONG;
break;
}
ele = skill_get_pl(skill_num);
- race = battle_get_race(bl);
+ race = status_get_race(bl);
+ size = status_get_size(bl);
+ race2 = status_get_race(bl);
if(damagefix){
if(damage<1 && skill_num != NPC_DARKBREATH)
@@ -4407,27 +3334,35 @@ struct Damage battle_calc_misc_attack(
cardfix=100;
cardfix=cardfix*(100-tsd->subele[ele])/100; // 属性によるダメージ耐性
cardfix=cardfix*(100-tsd->subrace[race])/100; // 種族によるダメージ耐性
+ cardfix=cardfix*(100-tsd->subsize[size])/100;
cardfix=cardfix*(100-tsd->misc_def_rate)/100;
+ cardfix=cardfix*(100-tsd->subrace2[race2])/100;
damage=damage*cardfix/100;
}
+ if (sd && skill_num > 0 && sd->skillatk[0] == skill_num)
+ damage += damage*sd->skillatk[1]/100;
+
if(damage < 0) damage = 0;
- damage=battle_attr_fix(damage, ele, battle_get_element(target) ); // 属性修正
+ damage=battle_attr_fix(damage, ele, status_get_element(target) ); // 属性修正
}
div_=skill_get_num( skill_num,skill_lv );
if(div_>1)
damage*=div_;
- if(damage > 0 && (damage < div_ || (battle_get_def(target) >= 1000000 && battle_get_mdef(target) >= 1000000) ) ) {
+ if(damage > 0 && (damage < div_ || (status_get_def(target) >= 1000000 && status_get_mdef(target) >= 1000000) ) ) {
damage = div_;
}
+ if(status_get_mode(target)&0x40 && damage>0)
+ damage = 1;
+
damage=battle_calc_damage(bl,target,damage,div_,skill_num,skill_lv,aflag); // 最終修正
md.damage=damage;
md.div_=div_;
- md.amotion=battle_get_amotion(bl);
- md.dmotion=battle_get_dmotion(target);
+ md.amotion=status_get_amotion(bl);
+ md.dmotion=status_get_dmotion(target);
md.damage2=0;
md.type=0;
md.blewcount=blewcount;
@@ -4453,6 +3388,7 @@ struct Damage battle_calc_attack( int attack_type,
default:
if(battle_config.error_log)
printf("battle_calc_attack: unknwon attack type ! %d\n",attack_type);
+ memset(&d,0,sizeof(d));
break;
}
return d;
@@ -4465,7 +3401,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
unsigned int tick,int flag)
{
struct map_session_data *sd=NULL;
- struct status_change *sc_data = battle_get_sc_data(src),*t_sc_data=battle_get_sc_data(target);
+ struct status_change *sc_data = status_get_sc_data(src),*t_sc_data=status_get_sc_data(target);
short *opt1;
int race = 7, ele = 0;
int damage,rdamage = 0;
@@ -4484,7 +3420,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
if(target->type == BL_PC && pc_isdead((struct map_session_data *)target))
return 0;
- opt1=battle_get_opt1(src);
+ opt1=status_get_opt1(src);
if(opt1 && *opt1 > 0) {
battle_stopattack(src);
return 0;
@@ -4495,11 +3431,11 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
}
if(battle_check_target(src,target,BCT_ENEMY) <= 0 &&
- !battle_check_range(src,target,0))
+ !battle_check_range(src,target,0))
return 0; // 攻撃対象外
- race = battle_get_race(target);
- ele = battle_get_elem_type(target);
+ race = status_get_race(target);
+ ele = status_get_elem_type(target);
if(battle_check_target(src,target,BCT_ENEMY) > 0 &&
battle_check_range(src,target,0)){
// 攻撃対象となりうるので攻撃
@@ -4549,17 +3485,17 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
}
}
if(rdamage > 0)
- clif_damage(src,src,tick, wd.amotion,0,rdamage,1,4,0);
+ clif_damage(src,src,tick,wd.amotion,wd.dmotion,rdamage,1,4,0);
}
if (wd.div_ == 255 && sd) { //三段掌
- int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src);
+ int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src);
int skilllv;
- if(wd.damage+wd.damage2 < battle_get_hp(target)) {
+ if(wd.damage+wd.damage2 < status_get_hp(target)) {
if((skilllv = pc_checkskill(sd, MO_CHAINCOMBO)) > 0)
delay += 300 * battle_config.combo_delay_rate /100; //追加ディレイをconfにより調整
- skill_status_change_start(src,SC_COMBO,MO_TRIPLEATTACK,skilllv,0,0,delay,0);
+ status_change_start(src,SC_COMBO,MO_TRIPLEATTACK,skilllv,0,0,delay,0);
}
sd->attackabletime = sd->canmove_tick = tick + delay;
clif_combo_delay(src,delay);
@@ -4576,23 +3512,23 @@ 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) {
skill_additional_effect(src,target,0,0,BF_WEAPON,tick);
if(sd) {
if(sd->weapon_coma_ele[ele] > 0 && rand()%10000 < sd->weapon_coma_ele[ele])
- battle_damage(src,target,battle_get_max_hp(target),1);
+ battle_damage(src,target,status_get_max_hp(target),1);
if(sd->weapon_coma_race[race] > 0 && rand()%10000 < sd->weapon_coma_race[race])
- battle_damage(src,target,battle_get_max_hp(target),1);
- if(battle_get_mode(target) & 0x20) {
+ battle_damage(src,target,status_get_max_hp(target),1);
+ if(status_get_mode(target) & 0x20) {
if(sd->weapon_coma_race[10] > 0 && rand()%10000 < sd->weapon_coma_race[10])
- battle_damage(src,target,battle_get_max_hp(target),1);
+ battle_damage(src,target,status_get_max_hp(target),1);
}
else {
if(sd->weapon_coma_race[11] > 0 && rand()%10000 < sd->weapon_coma_race[11])
- battle_damage(src,target,battle_get_max_hp(target),1);
+ battle_damage(src,target,status_get_max_hp(target),1);
}
}
}
@@ -4643,69 +3579,96 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
}
}
if(sd) {
- if(sd->autospell_id > 0 && sd->autospell_lv > 0 && rand()%100 < sd->autospell_rate) {
- int skilllv=sd->autospell_lv,i,f=0,sp;
+ if(sd->autospell_id > 0 && rand()%100 < sd->autospell_rate) {
+ int skilllv = sd->autospell_lv, i;
i = rand()%100;
if(i >= 50) skilllv -= 2;
else if(i >= 15) skilllv--;
if(skilllv < 1) skilllv = 1;
- sp = skill_get_sp(sd->autospell_id,skilllv)*2/3;
- if(sd->status.sp >= sp) {
- if((i=skill_get_inf(sd->autospell_id) == 2) || i == 32)
- f = skill_castend_pos2(src,target->x,target->y,sd->autospell_id,skilllv,tick,flag);
- else {
- switch( skill_get_nk(sd->autospell_id) ) {
- case 0: case 2:
- f = skill_castend_damage_id(src,target,sd->autospell_id,skilllv,tick,flag);
- break;
- case 1:/* 支援系 */
- if((sd->autospell_id==AL_HEAL || (sd->autospell_id==ALL_RESURRECTION && target->type != BL_PC)) && battle_check_undead(race,ele))
- f = skill_castend_damage_id(src,target,sd->autospell_id,skilllv,tick,flag);
- else
- f = skill_castend_nodamage_id(src,target,sd->autospell_id,skilllv,tick,flag);
- break;
- }
+
+ if((i=skill_get_inf(sd->autospell_id) == 2) || i == 32)
+ skill_castend_pos2(src,target->x,target->y,sd->autospell_id,skilllv,tick,flag);
+ else {
+ switch( skill_get_nk(sd->autospell_id) ) {
+ case 0: case 2:
+ skill_castend_damage_id(src,target,sd->autospell_id,skilllv,tick,flag);
+ break;
+ case 1:/* 支援系 */
+ if((sd->autospell_id==AL_HEAL || (sd->autospell_id==ALL_RESURRECTION && target->type != BL_PC)) && battle_check_undead(race,ele))
+ skill_castend_damage_id(src,target,sd->autospell_id,skilllv,tick,flag);
+ else
+ skill_castend_nodamage_id(src,target,sd->autospell_id,skilllv,tick,flag);
+ break;
}
- if(!f) pc_heal(sd,0,-sp);
- }
+ }
}
- if(wd.flag&BF_WEAPON && src != target && (wd.damage > 0 || wd.damage2 > 0)) {
+ if (wd.flag&BF_WEAPON && src != target && (wd.damage > 0 || wd.damage2 > 0)) {
int hp = 0,sp = 0;
- if(sd->hp_drain_rate && sd->hp_drain_per > 0 && wd.damage > 0 && rand()%100 < sd->hp_drain_rate) {
- hp += (wd.damage * sd->hp_drain_per)/100;
- if(sd->hp_drain_rate > 0 && hp < 1) hp = 1;
- else if(sd->hp_drain_rate < 0 && hp > -1) hp = -1;
- }
- if(sd->hp_drain_rate_ && sd->hp_drain_per_ > 0 && wd.damage2 > 0 && rand()%100 < sd->hp_drain_rate_) {
- hp += (wd.damage2 * sd->hp_drain_per_)/100;
- if(sd->hp_drain_rate_ > 0 && hp < 1) hp = 1;
- else if(sd->hp_drain_rate_ < 0 && hp > -1) hp = -1;
- }
- if(sd->sp_drain_rate && sd->sp_drain_per > 0 && wd.damage > 0 && rand()%100 < sd->sp_drain_rate) {
- sp += (wd.damage * sd->sp_drain_per)/100;
- if(sd->sp_drain_rate > 0 && sp < 1) sp = 1;
- else if(sd->sp_drain_rate < 0 && sp > -1) sp = -1;
+ if (!battle_config.left_cardfix_to_right) { // 二刀流左手カードの吸収系効果を右手に追加しない場合
+ hp += battle_calc_drain(wd.damage, sd->hp_drain_rate, sd->hp_drain_per, sd->hp_drain_value);
+ hp += battle_calc_drain(wd.damage2, sd->hp_drain_rate_, sd->hp_drain_per_, sd->hp_drain_value_);
+ sp += battle_calc_drain(wd.damage, sd->sp_drain_rate, sd->sp_drain_per, sd->sp_drain_value);
+ sp += battle_calc_drain(wd.damage2, sd->sp_drain_rate_, sd->sp_drain_per_, sd->sp_drain_value_);
+ } else { // 二刀流左手カードの吸収系効果を右手に追加する場合
+ int hp_drain_rate = sd->hp_drain_rate + sd->hp_drain_rate_;
+ int hp_drain_per = sd->hp_drain_per + sd->hp_drain_per_;
+ int hp_drain_value = sd->hp_drain_value + sd->hp_drain_value_;
+ int sp_drain_rate = sd->sp_drain_rate + sd->sp_drain_rate_;
+ int sp_drain_per = sd->sp_drain_per + sd->sp_drain_per_;
+ int sp_drain_value = sd->sp_drain_value + sd->sp_drain_value_;
+ hp += battle_calc_drain(wd.damage, hp_drain_rate, hp_drain_per, hp_drain_value);
+ sp += battle_calc_drain(wd.damage, sp_drain_rate, sp_drain_per, sp_drain_value);
}
- if(sd->sp_drain_rate_ && sd->sp_drain_per_ > 0 && wd.damage2 > 0 && rand()%100 < sd->sp_drain_rate_) {
- sp += (wd.damage2 * sd->sp_drain_per_)/100;
- if(sd->sp_drain_rate_ > 0 && sp < 1) sp = 1;
- else if(sd->sp_drain_rate_ < 0 && sp > -1) sp = -1;
- }
- if(hp || sp) pc_heal(sd,hp,sp);
+
+ if (hp || sp) pc_heal(sd, hp, sp);
+ if (sd->sp_drain_type && target->type == BL_PC)
+ battle_heal(NULL,target,0,-sp,0);
+ }
+ }
+ if (target->type == BL_PC) {
+ struct map_session_data *tsd = (struct map_session_data *)target;
+ if(tsd && ((sd && !sd->state.arrow_atk) || (status_get_range(src)<=2)) &&
+ tsd->autospell2_id > 0 && rand()%100 < tsd->autospell2_rate) {
+ struct block_list *tbl;
+ int skilllv = tsd->autospell_lv, i;
+ i = rand()%100;
+ if(i >= 50) skilllv -= 2;
+ else if(i >= 15) skilllv--;
+ if(skilllv < 1) skilllv = 1;
+
+ if (tsd->autospell2_type == 0) tbl = target;
+ else tbl = src;
+ if((i=skill_get_inf(tsd->autospell2_id) == 2) || i == 32)
+ skill_castend_pos2(target,tbl->x,tbl->y,tsd->autospell2_id,skilllv,tick,flag);
+ else {
+ switch( skill_get_nk(tsd->autospell2_id) ) {
+ case 0: case 2:
+ skill_castend_damage_id(target,tbl,tsd->autospell2_id,skilllv,tick,flag);
+ break;
+ case 1:/* 支援系 */
+ if((tsd->autospell2_id==AL_HEAL || (tsd->autospell2_id==ALL_RESURRECTION && tbl->type != BL_PC)) &&
+ battle_check_undead(status_get_race(tbl),status_get_elem_type(tbl)))
+ skill_castend_damage_id(target,tbl,tsd->autospell2_id,skilllv,tick,flag);
+ else
+ skill_castend_nodamage_id(target,tbl,tsd->autospell2_id,skilllv,tick,flag);
+ break;
+ }
+ }
}
}
if(rdamage > 0)
- battle_damage(target,src,rdamage,0);
+ battle_delay_damage(tick+wd.amotion,target,src,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);
- skill_status_change_end(target,SC_AUTOCOUNTER,-1);
+ status_change_end(target,SC_AUTOCOUNTER,-1);
}
if(t_sc_data && t_sc_data[SC_POISONREACT].timer != -1 && t_sc_data[SC_POISONREACT].val4 > 0) { // poison react [Celest]
if(t_sc_data[SC_POISONREACT].val3 == src->id) {
struct map_session_data *tsd = (struct map_session_data *)target;
- if ((src->type == BL_MOB && battle_get_elem_type(src)==5) || (src->type == BL_PC && battle_get_attack_element(src)==5)) {
+ if ((src->type == BL_MOB && status_get_elem_type(src)==5) || (src->type == BL_PC && status_get_attack_element(src)==5)) {
t_sc_data[SC_POISONREACT].val2 = 0;
battle_weapon_attack(target,src,tick,flag|AS_POISONREACT);
} else {
@@ -4713,19 +3676,18 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
--t_sc_data[SC_POISONREACT].val2;
}
if (t_sc_data[SC_POISONREACT].val2<=0)
- skill_status_change_end(target,SC_POISONREACT,-1);
- }
- }
- if(t_sc_data && t_sc_data[SC_BLADESTOP_WAIT].timer != -1){
- if (!(src->type == BL_MOB && mob_db[((struct mob_data *)src)->class].mode&0x20)) {
- int lv = t_sc_data[SC_BLADESTOP_WAIT].val1;
- skill_status_change_end(target,SC_BLADESTOP_WAIT,-1);
- skill_status_change_start(src,SC_BLADESTOP,lv,1,(int)src,(int)target,skill_get_time2(MO_BLADESTOP,lv),0);
- skill_status_change_start(target,SC_BLADESTOP,lv,2,(int)target,(int)src,skill_get_time2(MO_BLADESTOP,lv),0);
+ status_change_end(target,SC_POISONREACT,-1);
}
}
+ if (t_sc_data && t_sc_data[SC_BLADESTOP_WAIT].timer != -1 &&
+ !(status_get_mode(src)&0x20)) { // ボスには無効
+ int lv = t_sc_data[SC_BLADESTOP_WAIT].val1;
+ status_change_end(target,SC_BLADESTOP_WAIT,-1);
+ status_change_start(src,SC_BLADESTOP,lv,1,(int)src,(int)target,skill_get_time2(MO_BLADESTOP,lv),0);
+ status_change_start(target,SC_BLADESTOP,lv,2,(int)target,(int)src,skill_get_time2(MO_BLADESTOP,lv),0);
+ }
if(t_sc_data && t_sc_data[SC_SPLASHER].timer!=-1) //殴ったので対象のベナムスプラッシャー状態を解除
- skill_status_change_end(target,SC_SPLASHER,-1);
+ status_change_end(target,SC_SPLASHER,-1);
map_freeblock_unlock();
}
@@ -4789,8 +3751,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
return -1;
// Celest
- sc_data = battle_get_sc_data(src);
- tsc_data = battle_get_sc_data(target);
+ sc_data = status_get_sc_data(src);
+ tsc_data = status_get_sc_data(target);
if ((sc_data && sc_data[SC_BASILICA].timer != -1) ||
(tsc_data && tsc_data[SC_BASILICA].timer != -1))
return -1;
@@ -4810,15 +3772,22 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
// スキルユニットの場合、親を求める
if( src->type==BL_SKILL) {
- int inf2 = skill_get_inf2(((struct skill_unit *)src)->group->skill_id);
- if( (ss=map_id2bl( ((struct skill_unit *)src)->group->src_id))==NULL )
+ struct skill_unit *su = (struct skill_unit *)src;
+ int skillid, inf2;
+
+ nullpo_retr (-1, su);
+ nullpo_retr (-1, su->group);
+ skillid = su->group->skill_id;
+ inf2 = skill_get_inf2(skillid);
+ if( (ss=map_id2bl( su->group->src_id))==NULL )
return -1;
if(ss->prev == NULL)
return -1;
- if(inf2&0x80 &&
- (map[src->m].flag.pvp || pc_iskiller((struct map_session_data *)src, (struct map_session_data *)target)) && // [MouseJstr]
- !(target->type == BL_PC && pc_isinvisible((struct map_session_data *)target)))
- return 0;
+ if(inf2&0x80 &&
+ (map[src->m].flag.pvp ||
+ (skillid >= 115 && skillid <= 125 && map[src->m].flag.gvg)) &&
+ !(target->type == BL_PC && pc_isinvisible((struct map_session_data *)target)))
+ return 0;
if(ss == target) {
if(inf2&0x100)
return 0;
@@ -4826,10 +3795,33 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
return -1;
}
}
- // Mobでmaster_idがあってspecial_mob_aiなら、召喚主を求める
+
if( src->type==BL_MOB ){
struct mob_data *md=(struct mob_data *)src;
- if(md && md->master_id>0){
+ nullpo_retr (-1, md);
+
+ if(target->type == BL_PC) {
+ struct map_session_data *sd = (struct map_session_data *)target;
+ nullpo_retr (-1, sd);
+
+ if(md->class_ >= 1285 && md->class_ <= 1287){
+ struct guild_castle *gc = guild_mapname2gc (map[target->m].name);
+ if(gc && agit_flag==0) // Guardians will not attack during non-woe time [Valaris]
+ return 1; // end addition [Valaris]
+ if(gc && sd->status.guild_id > 0) {
+ struct guild *g=guild_search(sd->status.guild_id); // don't attack guild members [Valaris]
+ if(g && g->guild_id == gc->guild_id)
+ return 1;
+ if(g && guild_isallied(g,gc))
+ return 1;
+ }
+ }
+ // option to have monsters ignore GMs [Valaris]
+ if (battle_config.monsters_ignore_gm > 0 && pc_isGM(sd) >= battle_config.monsters_ignore_gm)
+ return 1;
+ }
+ // Mobでmaster_idがあってspecial_mob_aiなら、召喚主を求める
+ if(md->master_id>0){
if(md->master_id==target->id) // 主なら肯定
return 1;
if(md->state.special_mob_ai){
@@ -4869,11 +3861,11 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if(ss->type == BL_PET && target->type==BL_MOB)
return 0;
- s_p=battle_get_party_id(ss);
- s_g=battle_get_guild_id(ss);
+ s_p=status_get_party_id(ss);
+ s_g=status_get_guild_id(ss);
- t_p=battle_get_party_id(target);
- t_g=battle_get_guild_id(target);
+ t_p=status_get_party_id(target);
+ t_g=status_get_guild_id(target);
if(flag&0x10000) {
if(s_p && t_p && s_p == t_p) // 同じパーティなら肯定(味方)
@@ -4896,7 +3888,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if(su && su->group->target_flag==BCT_NOENEMY)
return 1;
else if (battle_config.pk_mode &&
- (((struct map_session_data*)ss)->status.class==0 || ((struct map_session_data*)target)->status.class==0 ||
+ (((struct map_session_data*)ss)->status.class_==0 || ((struct map_session_data*)target)->status.class_==0 ||
((struct map_session_data*)ss)->status.base_level < battle_config.pk_min_level ||
((struct map_session_data*)target)->status.base_level < battle_config.pk_min_level))
return 1; // prevent novice engagement in pk_mode [Valaris]
@@ -4939,7 +3931,6 @@ int battle_check_range(struct block_list *src,struct block_list *bl,int range)
{
int dx,dy;
- struct walkpath_data wpd;
int arange;
nullpo_retr(0, src);
@@ -4962,16 +3953,7 @@ int battle_check_range(struct block_list *src,struct block_list *bl,int range)
// return 1;
// 障害物判定
- wpd.path_len=0;
- wpd.path_pos=0;
- wpd.path_half=0;
- if(path_search(&wpd,src->m,src->x,src->y,bl->x,bl->y,0x10001)!=-1)
- return 1;
-
- dx=(dx>0)?1:((dx<0)?-1:0);
- dy=(dy>0)?1:((dy<0)?-1:0);
- return (path_search(&wpd,src->m,src->x+dx,src->y+dy,
- bl->x-dx,bl->y-dy,0x10001)!=-1)?1:0;
+ return path_search_long(NULL,src->m,src->x,src->y,bl->x,bl->y);
}
/*==========================================
@@ -4989,7 +3971,7 @@ int battle_config_switch(const char *str) {
static const struct {
char str[128];
- int *val;
+ void *val;
} battle_data[] = {
{ "warp_point_debug", &battle_config.warp_point_debug },
{ "enemy_critical", &battle_config.enemy_critical },
@@ -5045,7 +4027,6 @@ static const struct {
{ "player_skillup_limit", &battle_config.skillup_limit },
{ "weapon_produce_rate", &battle_config.wp_rate },
{ "potion_produce_rate", &battle_config.pp_rate },
- { "deadly_potion_produce_rate", &battle_config.cdp_rate },
{ "monster_active_enable", &battle_config.monster_active_enable },
{ "monster_damage_delay_rate", &battle_config.monster_damage_delay_rate},
{ "monster_loot_type", &battle_config.monster_loot_type },
@@ -5082,6 +4063,11 @@ static const struct {
{ "natural_heal_skill_interval", &battle_config.natural_heal_skill_interval},
{ "natural_heal_weight_rate", &battle_config.natural_heal_weight_rate },
{ "item_name_override_grffile", &battle_config.item_name_override_grffile},
+ { "item_equip_override_grffile", &battle_config.item_equip_override_grffile}, // [Celest]
+ { "item_slots_override_grffile", &battle_config.item_slots_override_grffile}, // [Celest]
+ { "indoors_override_grffile", &battle_config.indoors_override_grffile}, // [Celest]
+ { "skill_sp_override_grffile", &battle_config.skill_sp_override_grffile}, // [Celest]
+ { "cardillust_read_grffile", &battle_config.cardillust_read_grffile}, // [Celest]
{ "arrow_decrement", &battle_config.arrow_decrement },
{ "max_aspd", &battle_config.max_aspd },
{ "max_hp", &battle_config.max_hp },
@@ -5099,14 +4085,14 @@ static const struct {
{ "undead_detect_type", &battle_config.undead_detect_type },
{ "player_auto_counter_type", &battle_config.pc_auto_counter_type },
{ "monster_auto_counter_type", &battle_config.monster_auto_counter_type},
- { "agi_penaly_type", &battle_config.agi_penaly_type },
- { "agi_penaly_count", &battle_config.agi_penaly_count },
- { "agi_penaly_num", &battle_config.agi_penaly_num },
- { "agi_penaly_count_lv", &battle_config.agi_penaly_count_lv },
- { "vit_penaly_type", &battle_config.vit_penaly_type },
- { "vit_penaly_count", &battle_config.vit_penaly_count },
- { "vit_penaly_num", &battle_config.vit_penaly_num },
- { "vit_penaly_count_lv", &battle_config.vit_penaly_count_lv },
+ { "agi_penalty_type", &battle_config.agi_penalty_type },
+ { "agi_penalty_count", &battle_config.agi_penalty_count },
+ { "agi_penalty_num", &battle_config.agi_penalty_num },
+ { "agi_penalty_count_lv", &battle_config.agi_penalty_count_lv },
+ { "vit_penalty_type", &battle_config.vit_penalty_type },
+ { "vit_penalty_count", &battle_config.vit_penalty_count },
+ { "vit_penalty_num", &battle_config.vit_penalty_num },
+ { "vit_penalty_count_lv", &battle_config.vit_penalty_count_lv },
{ "player_defense_type", &battle_config.player_defense_type },
{ "monster_defense_type", &battle_config.monster_defense_type },
{ "pet_defense_type", &battle_config.pet_defense_type },
@@ -5127,7 +4113,7 @@ static const struct {
{ "monster_attack_direction_change", &battle_config.monster_attack_direction_change },
{ "player_land_skill_limit", &battle_config.pc_land_skill_limit },
{ "monster_land_skill_limit", &battle_config.monster_land_skill_limit},
- { "party_skill_penaly", &battle_config.party_skill_penaly },
+ { "party_skill_penalty", &battle_config.party_skill_penalty },
{ "monster_class_change_full_recover", &battle_config.monster_class_change_full_recover },
{ "produce_item_name_input", &battle_config.produce_item_name_input },
{ "produce_potion_name_input", &battle_config.produce_potion_name_input},
@@ -5140,7 +4126,6 @@ static const struct {
{ "dead_branch_active", &battle_config.dead_branch_active },
{ "vending_max_value", &battle_config.vending_max_value },
{ "show_steal_in_same_party", &battle_config.show_steal_in_same_party },
- { "enable_upper_class", &battle_config.enable_upper_class },
{ "pet_attack_attr_none", &battle_config.pet_attack_attr_none },
{ "mob_attack_attr_none", &battle_config.mob_attack_attr_none },
{ "mob_ghostring_fix", &battle_config.mob_ghostring_fix },
@@ -5156,8 +4141,15 @@ static const struct {
{ "invite_request_check", &battle_config.invite_request_check },
{ "skill_removetrap_type", &battle_config.skill_removetrap_type },
{ "disp_experience", &battle_config.disp_experience },
- { "castle_defense_rate", &battle_config.castle_defense_rate },
- { "riding_weight", &battle_config.riding_weight },
+ { "castle_defense_rate", &battle_config.castle_defense_rate },
+ { "hp_rate", &battle_config.hp_rate },
+ { "sp_rate", &battle_config.sp_rate },
+ { "gm_can_drop_lv", &battle_config.gm_can_drop_lv },
+ { "disp_hpmeter", &battle_config.disp_hpmeter },
+ { "bone_drop", &battle_config.bone_drop },
+ { "monster_damage_delay", &battle_config.monster_damage_delay },
+
+// eAthena additions
{ "item_rate_common", &battle_config.item_rate_common }, // Added by RoVeRT
{ "item_rate_equip", &battle_config.item_rate_equip },
{ "item_rate_card", &battle_config.item_rate_card }, // End Addition
@@ -5198,16 +4190,23 @@ static const struct {
{ "max_cloth_color", &battle_config.max_cloth_color }, // added by [MouseJstr]
{ "castrate_dex_scale", &battle_config.castrate_dex_scale }, // added by [MouseJstr]
{ "area_size", &battle_config.area_size }, // added by [MouseJstr]
- { "muting_players", &battle_config.muting_players}, // added by [Apple]
+ { "muting_players", &battle_config.muting_players}, // added by [Apple]
{ "zeny_from_mobs", &battle_config.zeny_from_mobs}, // [Valaris]
{ "mobs_level_up", &battle_config.mobs_level_up}, // [Valaris]
{ "pk_min_level", &battle_config.pk_min_level}, // [celest]
{ "skill_steal_type", &battle_config.skill_steal_type}, // [celest]
{ "skill_steal_rate", &battle_config.skill_steal_rate}, // [celest]
{ "night_darkness_level", &battle_config.night_darkness_level}, // [celest]
+ { "motd_type", &battle_config.motd_type}, // [celest]
+ { "allow_atcommand_when_mute", &battle_config.allow_atcommand_when_mute}, // [celest]
+ { "finding_ore_rate", &battle_config.finding_ore_rate}, // [celest]
+ { "exp_calc_type", &battle_config.exp_calc_type}, // [celest]
+ { "min_skill_delay_limit", &battle_config.min_skill_delay_limit}, // [celest]
+ { "require_glory_guild", &battle_config.require_glory_guild}, // [celest]
+ { "idle_no_share", &battle_config.idle_no_share}, // [celest], for a feature by [MouseJstr]
//SQL-only options start
-#ifndef TXT_ONLY
+#ifndef TXT_ONLY
{ "mail_system", &battle_config.mail_system }, // added by [Valaris]
//SQL-only options end
#endif
@@ -5217,7 +4216,7 @@ int battle_set_value(char *w1, char *w2) {
int i;
for(i = 0; i < sizeof(battle_data) / (sizeof(battle_data[0])); i++)
if (strcmpi(w1, battle_data[i].str) == 0) {
- *battle_data[i].val = battle_config_switch(w2);
+ *((unsigned int *) battle_data[i].val) = battle_config_switch(w2);
return 1;
}
return 0;
@@ -5276,7 +4275,6 @@ void battle_set_defaults() {
battle_config.skillup_limit = 0;
battle_config.wp_rate=100;
battle_config.pp_rate=100;
- battle_config.cdp_rate=100;
battle_config.monster_active_enable=1;
battle_config.monster_damage_delay_rate=100;
battle_config.monster_loot_type=0;
@@ -5313,6 +4311,11 @@ void battle_set_defaults() {
battle_config.natural_heal_skill_interval=10000;
battle_config.natural_heal_weight_rate=50;
battle_config.item_name_override_grffile=1;
+ battle_config.item_equip_override_grffile=0; // [Celest]
+ battle_config.item_slots_override_grffile=0; // [Celest]
+ battle_config.indoors_override_grffile=0; // [Celest]
+ battle_config.skill_sp_override_grffile=0; // [Celest]
+ battle_config.cardillust_read_grffile=0; // [Celest]
battle_config.arrow_decrement=1;
battle_config.max_aspd = 199;
battle_config.max_hp = 32500;
@@ -5330,14 +4333,14 @@ void battle_set_defaults() {
battle_config.undead_detect_type = 0;
battle_config.pc_auto_counter_type = 1;
battle_config.monster_auto_counter_type = 1;
- battle_config.agi_penaly_type = 0;
- battle_config.agi_penaly_count = 3;
- battle_config.agi_penaly_num = 0;
- battle_config.agi_penaly_count_lv = ATK_FLEE;
- battle_config.vit_penaly_type = 0;
- battle_config.vit_penaly_count = 3;
- battle_config.vit_penaly_num = 0;
- battle_config.vit_penaly_count_lv = ATK_DEF;
+ battle_config.agi_penalty_type = 0;
+ battle_config.agi_penalty_count = 3;
+ battle_config.agi_penalty_num = 0;
+ battle_config.agi_penalty_count_lv = ATK_FLEE;
+ battle_config.vit_penalty_type = 0;
+ battle_config.vit_penalty_count = 3;
+ battle_config.vit_penalty_num = 0;
+ battle_config.vit_penalty_count_lv = ATK_DEF;
battle_config.player_defense_type = 0;
battle_config.monster_defense_type = 0;
battle_config.pet_defense_type = 0;
@@ -5349,17 +4352,16 @@ void battle_set_defaults() {
battle_config.pc_cloak_check_type = 0;
battle_config.monster_cloak_check_type = 0;
battle_config.gvg_short_damage_rate = 100;
- battle_config.gvg_long_damage_rate = 100;
- battle_config.gvg_magic_damage_rate = 100;
- battle_config.gvg_misc_damage_rate = 100;
+ battle_config.gvg_long_damage_rate = 60;
+ battle_config.gvg_magic_damage_rate = 50;
+ battle_config.gvg_misc_damage_rate = 60;
battle_config.gvg_eliminate_time = 7000;
battle_config.mob_changetarget_byskill = 0;
battle_config.pc_attack_direction_change = 1;
battle_config.monster_attack_direction_change = 1;
- battle_config.pc_undead_nofreeze = 0;
battle_config.pc_land_skill_limit = 1;
battle_config.monster_land_skill_limit = 1;
- battle_config.party_skill_penaly = 1;
+ battle_config.party_skill_penalty = 1;
battle_config.monster_class_change_full_recover = 0;
battle_config.produce_item_name_input = 1;
battle_config.produce_potion_name_input = 1;
@@ -5372,7 +4374,6 @@ void battle_set_defaults() {
battle_config.dead_branch_active = 0;
battle_config.vending_max_value = 10000000;
battle_config.show_steal_in_same_party = 0;
- battle_config.enable_upper_class = 0;
battle_config.pet_attack_attr_none = 0;
battle_config.pc_attack_attr_none = 0;
battle_config.mob_attack_attr_none = 1;
@@ -5388,6 +4389,15 @@ void battle_set_defaults() {
battle_config.invite_request_check = 1;
battle_config.skill_removetrap_type = 0;
battle_config.disp_experience = 0;
+ battle_config.castle_defense_rate = 100;
+ battle_config.hp_rate = 100;
+ battle_config.sp_rate = 100;
+ battle_config.gm_can_drop_lv = 0;
+ battle_config.disp_hpmeter = 0;
+ battle_config.bone_drop = 0;
+ battle_config.monster_damage_delay = 1;
+
+// eAthena additions
battle_config.item_rate_common = 100;
battle_config.item_rate_equip = 100;
battle_config.item_rate_card = 100;
@@ -5421,7 +4431,7 @@ void battle_set_defaults() {
battle_config.ban_spoof_namer = 5; // added by [Yor] (default: 5 minutes)
battle_config.hack_info_GM_level = 60; // added by [Yor] (default: 60, GM level)
battle_config.any_warp_GM_min_level = 20; // added by [Yor]
- battle_config.packet_ver_flag = 511; // added by [Yor]
+ battle_config.packet_ver_flag = 255; // added by [Yor]
battle_config.min_hair_style = 0;
battle_config.max_hair_style = 20;
battle_config.min_hair_color = 0;
@@ -5434,13 +4444,18 @@ void battle_set_defaults() {
battle_config.skill_steal_type = 1;
battle_config.skill_steal_rate = 100;
battle_config.night_darkness_level = 9;
-
+ battle_config.motd_type = 0;
+ battle_config.allow_atcommand_when_mute = 0;
+ battle_config.finding_ore_rate = 100;
battle_config.castrate_dex_scale = 150;
-
battle_config.area_size = 14;
+ battle_config.exp_calc_type = 1;
+ battle_config.min_skill_delay_limit = 100;
+ battle_config.require_glory_guild = 0;
+ battle_config.idle_no_share = 0;
//SQL-only options start
-#ifndef TXT_ONLY
+#ifndef TXT_ONLY
battle_config.mail_system = 0;
//SQL-only options end
#endif
@@ -5477,6 +4492,10 @@ void battle_validate_conf() {
battle_config.max_aspd = 10;
if(battle_config.max_aspd > 1000)
battle_config.max_aspd = 1000;
+ if(battle_config.hp_rate < 0)
+ battle_config.hp_rate = 1;
+ if(battle_config.sp_rate < 0)
+ battle_config.sp_rate = 1;
if(battle_config.max_hp > 1000000)
battle_config.max_hp = 1000000;
if(battle_config.max_hp < 100)
@@ -5495,10 +4514,10 @@ void battle_validate_conf() {
battle_config.max_cart_weight = 100;
battle_config.max_cart_weight *= 10;
- if(battle_config.agi_penaly_count < 2)
- battle_config.agi_penaly_count = 2;
- if(battle_config.vit_penaly_count < 2)
- battle_config.vit_penaly_count = 2;
+ if(battle_config.agi_penalty_count < 2)
+ battle_config.agi_penalty_count = 2;
+ if(battle_config.vit_penalty_count < 2)
+ battle_config.vit_penalty_count = 2;
if(battle_config.guild_exp_limit > 99)
battle_config.guild_exp_limit = 99;
@@ -5530,11 +4549,11 @@ void battle_validate_conf() {
battle_config.night_at_start = 0;
else if (battle_config.night_at_start > 1) // added by [Yor]
battle_config.night_at_start = 1;
- if (battle_config.day_duration < 0) // added by [Yor]
- battle_config.day_duration = 0;
- if (battle_config.night_duration < 0) // added by [Yor]
- battle_config.night_duration = 0;
-
+ if (battle_config.day_duration != 0 && battle_config.day_duration < 60000) // added by [Yor]
+ battle_config.day_duration = 60000;
+ if (battle_config.night_duration != 0 && battle_config.night_duration < 60000) // added by [Yor]
+ battle_config.night_duration = 60000;
+
if (battle_config.ban_spoof_namer < 0) // added by [Yor]
battle_config.ban_spoof_namer = 0;
else if (battle_config.ban_spoof_namer > 32767)
@@ -5551,33 +4570,43 @@ void battle_validate_conf() {
battle_config.any_warp_GM_min_level = 100;
// at least 1 client must be accepted
- if ((battle_config.packet_ver_flag & 511) == 0) // added by [Yor]
- battle_config.packet_ver_flag = 511; // accept all clients
-
+ if ((battle_config.packet_ver_flag & 255) == 0) // added by [Yor]
+ battle_config.packet_ver_flag = 255; // accept all clients
+
if (battle_config.night_darkness_level > 10) // Celest
battle_config.night_darkness_level = 10;
+ if (battle_config.motd_type < 0)
+ battle_config.motd_type = 0;
+ else if (battle_config.motd_type > 1)
+ battle_config.motd_type = 1;
+
+ if (battle_config.finding_ore_rate < 0)
+ battle_config.finding_ore_rate = 0;
+
if (battle_config.vending_max_value > 10000000 || battle_config.vending_max_value<=0) // Lupus & Kobra_k88
battle_config.vending_max_value = 10000000;
+ if (battle_config.min_skill_delay_limit < 10)
+ battle_config.min_skill_delay_limit = 10; // minimum delay of 10ms
}
/*==========================================
* 設定ファイルを読み込む
*------------------------------------------
*/
-int battle_config_read(const char *cfgName)
+int battle_config_read(const char *cfgName)
{
char line[1024], w1[1024], w2[1024];
FILE *fp;
static int count = 0;
- if ((count++) == 0)
+ if ((count++) == 0)
battle_set_defaults();
fp = fopen(cfgName,"r");
if (fp == NULL) {
- printf("file not found: %s\n", cfgName);
+ printf("File not found: %s\n", cfgName);
return 1;
}
while(fgets(line,1020,fp)){
diff --git a/src/map/battle.h b/src/map/battle.h
index f6f0345ca..393cc58b4 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -63,50 +63,6 @@ int battle_weapon_attack( struct block_list *bl,struct block_list *target,
// 各種パラメータを得る
int battle_counttargeted(struct block_list *bl,struct block_list *src,int target_lv);
-int battle_get_class(struct block_list *bl);
-int battle_get_dir(struct block_list *bl);
-int battle_get_lv(struct block_list *bl);
-int battle_get_range(struct block_list *bl);
-int battle_get_hp(struct block_list *bl);
-int battle_get_max_hp(struct block_list *bl);
-int battle_get_str(struct block_list *bl);
-int battle_get_agi(struct block_list *bl);
-int battle_get_vit(struct block_list *bl);
-int battle_get_int(struct block_list *bl);
-int battle_get_dex(struct block_list *bl);
-int battle_get_luk(struct block_list *bl);
-int battle_get_hit(struct block_list *bl);
-int battle_get_flee(struct block_list *bl);
-int battle_get_def(struct block_list *bl);
-int battle_get_mdef(struct block_list *bl);
-int battle_get_flee2(struct block_list *bl);
-int battle_get_def2(struct block_list *bl);
-int battle_get_mdef2(struct block_list *bl);
-int battle_get_baseatk(struct block_list *bl);
-int battle_get_atk(struct block_list *bl);
-int battle_get_atk2(struct block_list *bl);
-int battle_get_speed(struct block_list *bl);
-int battle_get_adelay(struct block_list *bl);
-int battle_get_amotion(struct block_list *bl);
-int battle_get_dmotion(struct block_list *bl);
-int battle_get_element(struct block_list *bl);
-int battle_get_attack_element(struct block_list *bl);
-int battle_get_attack_element2(struct block_list *bl); //左手武器属性取得
-#define battle_get_elem_type(bl) (battle_get_element(bl)%10)
-#define battle_get_elem_level(bl) (battle_get_element(bl)/10/2)
-int battle_get_party_id(struct block_list *bl);
-int battle_get_guild_id(struct block_list *bl);
-int battle_get_race(struct block_list *bl);
-int battle_get_size(struct block_list *bl);
-int battle_get_mode(struct block_list *bl);
-int battle_get_mexp(struct block_list *bl);
-
-struct status_change *battle_get_sc_data(struct block_list *bl);
-short *battle_get_sc_count(struct block_list *bl);
-short *battle_get_opt1(struct block_list *bl);
-short *battle_get_opt2(struct block_list *bl);
-short *battle_get_opt3(struct block_list *bl);
-short *battle_get_option(struct block_list *bl);
enum {
BCT_NOENEMY =0x00000,
@@ -115,6 +71,7 @@ enum {
BCT_NOPARTY =0x50000,
BCT_ALL =0x20000,
BCT_NOONE =0x60000,
+ BCT_SELF =0x60000,
};
int battle_check_undead(int race,int element);
@@ -174,7 +131,6 @@ extern struct Battle_Config {
int skillup_limit;
int wp_rate;
int pp_rate;
- int cdp_rate;
int monster_active_enable;
int monster_damage_delay_rate;
int monster_loot_type;
@@ -212,12 +168,17 @@ extern struct Battle_Config {
int natural_heal_skill_interval;
int natural_heal_weight_rate;
int item_name_override_grffile;
+ int indoors_override_grffile; // [Celest]
+ int skill_sp_override_grffile; // [Celest]
+ int cardillust_read_grffile;
+ int item_equip_override_grffile;
+ int item_slots_override_grffile;
int arrow_decrement;
int max_aspd;
int max_hp;
int max_sp;
int max_lv;
- int max_parameter;
+ unsigned int max_parameter;
int max_cart_weight;
int pc_skill_log;
int mob_skill_log;
@@ -229,12 +190,12 @@ extern struct Battle_Config {
int undead_detect_type;
int pc_auto_counter_type;
int monster_auto_counter_type;
- int agi_penaly_type;
- int agi_penaly_count;
- int agi_penaly_num;
- int vit_penaly_type;
- int vit_penaly_count;
- int vit_penaly_num;
+ int agi_penalty_type;
+ int agi_penalty_count;
+ int agi_penalty_num;
+ int vit_penalty_type;
+ int vit_penalty_count;
+ int vit_penalty_num;
int player_defense_type;
int monster_defense_type;
int pet_defense_type;
@@ -253,10 +214,9 @@ extern struct Battle_Config {
int mob_changetarget_byskill;
int pc_attack_direction_change;
int monster_attack_direction_change;
- int pc_undead_nofreeze;
int pc_land_skill_limit;
int monster_land_skill_limit;
- int party_skill_penaly;
+ int party_skill_penalty;
int monster_class_change_full_recover;
int produce_item_name_input;
int produce_potion_name_input;
@@ -271,7 +231,6 @@ extern struct Battle_Config {
// int pet_lootitem; // removed [Valaris]
// int pet_weight; // removed [Valaris]
int show_steal_in_same_party;
- int enable_upper_class;
int pet_attack_attr_none;
int mob_attack_attr_none;
int mob_ghostring_fix;
@@ -287,7 +246,7 @@ extern struct Battle_Config {
int prevent_logout; // Added by RoVeRT
int alchemist_summon_reward; // [Valaris]
- int maximum_level;
+ unsigned int maximum_level;
int drops_by_luk;
int monsters_ignore_gm;
int equipment_breaking;
@@ -297,8 +256,8 @@ extern struct Battle_Config {
int pk_mode;
int show_mob_hp; // end additions [Valaris]
- int agi_penaly_count_lv;
- int vit_penaly_count_lv;
+ int agi_penalty_count_lv;
+ int vit_penalty_count_lv;
int gx_allhit;
int gx_cardfix;
@@ -312,18 +271,25 @@ extern struct Battle_Config {
int skill_removetrap_type;
int disp_experience;
int castle_defense_rate;
- int riding_weight;
int backstab_bow_penalty;
+ int hp_rate;
+ int sp_rate;
+ int gm_can_drop_lv;
+ int disp_hpmeter;
+ int bone_drop;
+ int monster_damage_delay;
+// eAthena additions
int night_at_start; // added by [Yor]
int day_duration; // added by [Yor]
int night_duration; // added by [Yor]
int ban_spoof_namer; // added by [Yor]
+ int ban_hack_trade; // added by [Yor]
int hack_info_GM_level; // added by [Yor]
int any_warp_GM_min_level; // added by [Yor]
int packet_ver_flag; // added by [Yor]
- int muting_players; // added by [Apple]
-
+ int muting_players; // added by [PoW]
+
int min_hair_style; // added by [MouseJstr]
int max_hair_style; // added by [MouseJstr]
int min_hair_color; // added by [MouseJstr]
@@ -336,10 +302,17 @@ extern struct Battle_Config {
int zeny_from_mobs; // [Valaris]
int mobs_level_up; // [Valaris]
- int pk_min_level; // [celest]
+ unsigned int pk_min_level; // [celest]
int skill_steal_type; // [celest]
int skill_steal_rate; // [celest]
int night_darkness_level; // [celest]
+ int motd_type; // [celest]
+ int allow_atcommand_when_mute; // [celest]
+ int finding_ore_rate; // orn
+ int exp_calc_type;
+ int min_skill_delay_limit;
+ int require_glory_guild;
+ int idle_no_share;
#ifndef TXT_ONLY /* SQL-only options */
int mail_system; // [Valaris]
diff --git a/src/map/charcommand.c b/src/map/charcommand.c
index de05e20ae..9b700dc47 100644
--- a/src/map/charcommand.c
+++ b/src/map/charcommand.c
@@ -15,6 +15,7 @@
#include "itemdb.h"
#include "map.h"
#include "pc.h"
+#include "status.h"
#include "skill.h"
#include "mob.h"
#include "pet.h"
@@ -27,10 +28,11 @@
#include "npc.h"
#include "trade.h"
#include "core.h"
+#include "showmsg.h"
static char command_symbol = '#';
-static char msg_table[1000][1024]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others)
+extern char *msg_table[1000]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others)
#define CCMD_FUNC(x) int charcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message)
@@ -42,6 +44,15 @@ CCMD_FUNC(option);
CCMD_FUNC(save);
CCMD_FUNC(stats_all);
CCMD_FUNC(reset);
+CCMD_FUNC(spiritball);
+CCMD_FUNC(itemlist);
+CCMD_FUNC(effect);
+CCMD_FUNC(storagelist);
+CCMD_FUNC(item);
+CCMD_FUNC(warp);
+CCMD_FUNC(zeny);
+CCMD_FUNC(showexp);
+CCMD_FUNC(showdelay);
#ifdef TXT_ONLY
/* TXT_ONLY */
@@ -70,6 +81,18 @@ static CharCommandInfo charcommand_info[] = {
{ CharCommandReset, "#reset", 60, charcommand_reset },
{ CharCommandSave, "#save", 60, charcommand_save },
{ CharCommandStatsAll, "#statsall", 40, charcommand_stats_all },
+ { CharCommandSpiritball, "#spiritball", 40, charcommand_spiritball },
+ { CharCommandItemList, "#itemlist", 40, charcommand_itemlist },
+ { CharCommandEffect, "#effect", 40, charcommand_effect },
+ { CharCommandStorageList, "#storagelist", 40, charcommand_storagelist },
+ { CharCommandItem, "#item", 60, charcommand_item },
+ { CharCommandWarp, "#warp", 60, charcommand_warp },
+ { CharCommandWarp, "#rura", 60, charcommand_warp },
+ { CharCommandWarp, "#rura+", 60, charcommand_warp },
+ { CharCommandZeny, "#zeny", 60, charcommand_zeny },
+ { CharCommandShowExp, "#showexp", 0, charcommand_showexp},
+ { CharCommandShowDelay, "#showdelay", 0, charcommand_showdelay},
+
#ifdef TXT_ONLY
/* TXT_ONLY */
@@ -248,8 +271,8 @@ int charcommand_config_read(const char *cfgName) {
charcommand_config_read(w2);
else if (strcmpi(w1, "command_symbol") == 0 && w2[0] > 31 &&
w2[0] != '/' && // symbol of standard ragnarok GM commands
- w2[0] != '%' && // symbol of party chat speaking
- w2[0] != '@') // symbol for @commands
+ w2[0] != '%' // symbol of party chat speaking
+ )
command_symbol = w2[0];
}
fclose(fp);
@@ -285,23 +308,24 @@ int charcommand_jobchange(
}
if ((pl_sd = map_nick2sd(character)) != NULL) {
+ int j;
if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can change job only to lower or same level
if ((job >= 0 && job < MAX_PC_CLASS)) {
// fix pecopeco display
if ((job != 13 && job != 21 && job != 4014 && job != 4022)) {
if (pc_isriding(sd)) {
- if (pl_sd->status.class == 13)
- pl_sd->status.class = pl_sd->view_class = 7;
- if (pl_sd->status.class == 21)
- pl_sd->status.class = pl_sd->view_class = 14;
- if (pl_sd->status.class == 4014)
- pl_sd->status.class = pl_sd->view_class = 4008;
- if (pl_sd->status.class == 4022)
- pl_sd->status.class = pl_sd->view_class = 4015;
+ if (pl_sd->status.class_ == 13)
+ pl_sd->status.class_ = pl_sd->view_class = 7;
+ if (pl_sd->status.class_ == 21)
+ pl_sd->status.class_ = pl_sd->view_class = 14;
+ if (pl_sd->status.class_ == 4014)
+ pl_sd->status.class_ = pl_sd->view_class = 4008;
+ if (pl_sd->status.class_ == 4022)
+ pl_sd->status.class_ = pl_sd->view_class = 4015;
pl_sd->status.option &= ~0x0020;
clif_changeoption(&pl_sd->bl);
- pc_calcstatus(pl_sd, 0);
+ status_calc_pc(pl_sd, 0);
}
} else {
if (!pc_isriding(sd)) {
@@ -315,7 +339,10 @@ int charcommand_jobchange(
job = 4015;
}
}
-
+ for (j=0; j < MAX_INVENTORY; j++) {
+ if(pl_sd->status.inventory[j].nameid>0 && pl_sd->status.inventory[j].equip!=0)
+ pc_unequipitem(pl_sd, j, 3);
+ }
if (pc_jobchange(pl_sd, job, upper) == 0)
clif_displaymessage(fd, msg_table[48]); // Character's job changed.
else {
@@ -412,9 +439,9 @@ int charcommand_petfriendly(
if ((pl_sd->pet.intimate > 0 && t <= 0) ||
(pl_sd->pet.intimate <= 0 && t > 0)) {
if (pl_sd->bl.prev != NULL)
- pc_calcstatus(pl_sd, 0);
+ status_calc_pc(pl_sd, 0);
else
- pc_calcstatus(pl_sd, 2);
+ status_calc_pc(pl_sd, 2);
}
}
clif_displaymessage(pl_sd->fd, msg_table[182]); // Pet friendly value changed!
@@ -481,7 +508,7 @@ int charcommand_stats(
{ "Zeny - %d", pl_sd->status.zeny },
{ NULL, 0 }
};
- sprintf(job_jobname, "Job - %s %s", job_name(pl_sd->status.class), "(level %d)");
+ sprintf(job_jobname, "Job - %s %s", job_name(pl_sd->status.class_), "(level %d)");
sprintf(output, msg_table[53], pl_sd->status.name); // '%s' stats:
clif_displaymessage(fd, output);
for (i = 0; output_table[i].format != NULL; i++) {
@@ -561,37 +588,37 @@ int charcommand_option(
pl_sd->opt2 = opt2;
pl_sd->status.option = opt3;
// fix pecopeco display
- if (pl_sd->status.class == 13 || pl_sd->status.class == 21 || pl_sd->status.class == 4014 || pl_sd->status.class == 4022) {
+ if (pl_sd->status.class_ == 13 || pl_sd->status.class_ == 21 || pl_sd->status.class_ == 4014 || pl_sd->status.class_ == 4022) {
if (!pc_isriding(pl_sd)) { // pl_sd have the new value...
- if (pl_sd->status.class == 13)
- pl_sd->status.class = pl_sd->view_class = 7;
- else if (pl_sd->status.class == 21)
- pl_sd->status.class = pl_sd->view_class = 14;
- else if (pl_sd->status.class == 4014)
- pl_sd->status.class = pl_sd->view_class = 4008;
- else if (pl_sd->status.class == 4022)
- pl_sd->status.class = pl_sd->view_class = 4015;
+ if (pl_sd->status.class_ == 13)
+ pl_sd->status.class_ = pl_sd->view_class = 7;
+ else if (pl_sd->status.class_ == 21)
+ pl_sd->status.class_ = pl_sd->view_class = 14;
+ else if (pl_sd->status.class_ == 4014)
+ pl_sd->status.class_ = pl_sd->view_class = 4008;
+ else if (pl_sd->status.class_ == 4022)
+ pl_sd->status.class_ = pl_sd->view_class = 4015;
}
} else {
if (pc_isriding(pl_sd)) { // pl_sd have the new value...
if (pl_sd->disguise > 0) { // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris] (code added by [Yor])
pl_sd->status.option &= ~0x0020;
} else {
- if (pl_sd->status.class == 7)
- pl_sd->status.class = pl_sd->view_class = 13;
- else if (pl_sd->status.class == 14)
- pl_sd->status.class = pl_sd->view_class = 21;
- else if (pl_sd->status.class == 4008)
- pl_sd->status.class = pl_sd->view_class = 4014;
- else if (pl_sd->status.class == 4015)
- pl_sd->status.class = pl_sd->view_class = 4022;
+ if (pl_sd->status.class_ == 7)
+ pl_sd->status.class_ = pl_sd->view_class = 13;
+ else if (pl_sd->status.class_ == 14)
+ pl_sd->status.class_ = pl_sd->view_class = 21;
+ else if (pl_sd->status.class_ == 4008)
+ pl_sd->status.class_ = pl_sd->view_class = 4014;
+ else if (pl_sd->status.class_ == 4015)
+ pl_sd->status.class_ = pl_sd->view_class = 4022;
else
pl_sd->status.option &= ~0x0020;
}
}
}
clif_changeoption(&pl_sd->bl);
- pc_calcstatus(pl_sd, 0);
+ status_calc_pc(pl_sd, 0);
clif_displaymessage(fd, msg_table[58]); // Character's options changed.
} else {
clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
@@ -673,14 +700,14 @@ int charcommand_stats_all(const int fd, struct map_session_data* sd, const char*
count = 0;
for(i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
if (pc_isGM(pl_sd) > 0)
sprintf(gmlevel, "| GM Lvl: %d", pc_isGM(pl_sd));
else
sprintf(gmlevel, " ");
- sprintf(output, "Name: %s | BLvl: %d | Job: %s (Lvl: %d) | HP: %d/%d | SP: %d/%d", pl_sd->status.name, pl_sd->status.base_level, job_name(pl_sd->status.class), pl_sd->status.job_level, pl_sd->status.hp, pl_sd->status.max_hp, pl_sd->status.sp, pl_sd->status.max_sp);
+ sprintf(output, "Name: %s | BLvl: %d | Job: %s (Lvl: %d) | HP: %d/%d | SP: %d/%d", pl_sd->status.name, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level, pl_sd->status.hp, pl_sd->status.max_hp, pl_sd->status.sp, pl_sd->status.max_sp);
clif_displaymessage(fd, output);
sprintf(output, "STR: %d | AGI: %d | VIT: %d | INT: %d | DEX: %d | LUK: %d | Zeny: %d %s", pl_sd->status.str, pl_sd->status.agi, pl_sd->status.vit, pl_sd->status.int_, pl_sd->status.dex, pl_sd->status.luk, pl_sd->status.zeny, gmlevel);
clif_displaymessage(fd, output);
@@ -701,3 +728,530 @@ int charcommand_stats_all(const int fd, struct map_session_data* sd, const char*
return 0;
}
+/*==========================================
+ * CharSpiritBall Function by PalasX
+ *------------------------------------------
+ */
+int charcommand_spiritball(const int fd, struct map_session_data* sd,const char* command, const char* message)
+{
+ struct map_session_data *pl_sd;
+ char character[100];
+ int spirit = 0;
+
+ memset(character, '\0', sizeof(character));
+
+ if(!message || !*message || sscanf(message, "%d %99[^\n]", &spirit, character) < 2 || spirit < 0 || spirit > 1000) {
+ clif_displaymessage(fd, "Usage: @spiritball <number: 0-1000>) <CHARACTER_NAME>.");
+ return -1;
+ }
+
+ if((pl_sd = map_nick2sd(character)) != NULL) {
+ if (spirit >= 0 && spirit <= 0x7FFF) {
+ if (pl_sd->spiritball != spirit || spirit > 999) {
+ if (pl_sd->spiritball > 0)
+ pc_delspiritball(pl_sd, pl_sd->spiritball, 1);
+ pl_sd->spiritball = spirit;
+ clif_spiritball(pl_sd);
+ // no message, player can look the difference
+ if (spirit > 1000)
+ clif_displaymessage(fd, msg_table[204]); // WARNING: more than 1000 spiritballs can CRASH your server and/or client!
+ } else {
+ clif_displaymessage(fd, msg_table[205]); // You already have this number of spiritballs.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[37]); // An invalid number was specified.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[3]); // Character not found.
+ return -1;
+ }
+ return 0;
+}
+
+/*==========================================
+ * #itemlist <character>: Displays the list of a player's items.
+ *------------------------------------------
+ */
+int
+charcommand_itemlist(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct map_session_data *pl_sd;
+ struct item_data *item_data, *item_temp;
+ int i, j, equip, count, counter, counter2;
+ char character[100], output[200], equipstr[100], outputtmp[200];
+ nullpo_retr(-1, sd);
+
+ memset(character, '\0', sizeof(character));
+ memset(output, '\0', sizeof(output));
+ memset(equipstr, '\0', sizeof(equipstr));
+ memset(outputtmp, '\0', sizeof(outputtmp));
+
+ if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ clif_displaymessage(fd, "Please, enter a player name (usage: #itemlist <char name>).");
+ return -1;
+ }
+
+ if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can look items only lower or same level
+ counter = 0;
+ count = 0;
+ for (i = 0; i < MAX_INVENTORY; i++) {
+ if (pl_sd->status.inventory[i].nameid > 0 && (item_data = itemdb_search(pl_sd->status.inventory[i].nameid)) != NULL) {
+ counter = counter + pl_sd->status.inventory[i].amount;
+ count++;
+ if (count == 1) {
+ sprintf(output, "------ Items list of '%s' ------", pl_sd->status.name);
+ clif_displaymessage(fd, output);
+ }
+ if ((equip = pl_sd->status.inventory[i].equip)) {
+ strcpy(equipstr, "| equiped: ");
+ if (equip & 4)
+ strcat(equipstr, "robe/gargment, ");
+ if (equip & 8)
+ strcat(equipstr, "left accessory, ");
+ if (equip & 16)
+ strcat(equipstr, "body/armor, ");
+ if ((equip & 34) == 2)
+ strcat(equipstr, "right hand, ");
+ if ((equip & 34) == 32)
+ strcat(equipstr, "left hand, ");
+ if ((equip & 34) == 34)
+ strcat(equipstr, "both hands, ");
+ if (equip & 64)
+ strcat(equipstr, "feet, ");
+ if (equip & 128)
+ strcat(equipstr, "right accessory, ");
+ if ((equip & 769) == 1)
+ strcat(equipstr, "lower head, ");
+ if ((equip & 769) == 256)
+ strcat(equipstr, "top head, ");
+ if ((equip & 769) == 257)
+ strcat(equipstr, "lower/top head, ");
+ if ((equip & 769) == 512)
+ strcat(equipstr, "mid head, ");
+ if ((equip & 769) == 512)
+ strcat(equipstr, "lower/mid head, ");
+ if ((equip & 769) == 769)
+ strcat(equipstr, "lower/mid/top head, ");
+ // remove final ', '
+ equipstr[strlen(equipstr) - 2] = '\0';
+ } else
+ memset(equipstr, '\0', sizeof(equipstr));
+ if (sd->status.inventory[i].refine)
+ sprintf(output, "%d %s %+d (%s %+d, id: %d) %s", pl_sd->status.inventory[i].amount, item_data->name, pl_sd->status.inventory[i].refine, item_data->jname, pl_sd->status.inventory[i].refine, pl_sd->status.inventory[i].nameid, equipstr);
+ else
+ sprintf(output, "%d %s (%s, id: %d) %s", pl_sd->status.inventory[i].amount, item_data->name, item_data->jname, pl_sd->status.inventory[i].nameid, equipstr);
+ clif_displaymessage(fd, output);
+ memset(output, '\0', sizeof(output));
+ counter2 = 0;
+ for (j = 0; j < item_data->slot; j++) {
+ if (pl_sd->status.inventory[i].card[j]) {
+ if ((item_temp = itemdb_search(pl_sd->status.inventory[i].card[j])) != NULL) {
+ if (output[0] == '\0')
+ sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
+ else
+ sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
+ strcat(output, outputtmp);
+ }
+ }
+ }
+ if (output[0] != '\0') {
+ output[strlen(output) - 2] = ')';
+ output[strlen(output) - 1] = '\0';
+ clif_displaymessage(fd, output);
+ }
+ }
+ }
+ if (count == 0)
+ clif_displaymessage(fd, "No item found on this player.");
+ else {
+ sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count);
+ clif_displaymessage(fd, output);
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[3]); // Character not found.
+ return -1;
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * #effect by [MouseJstr]
+ *
+ * Create a effect localized on another character
+ *------------------------------------------
+ */
+int
+charcommand_effect(const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct map_session_data *pl_sd = NULL;
+ char target[255];
+ int type = 0;
+ nullpo_retr(-1, sd);
+
+ if (!message || !*message || sscanf(message, "%d %s", &type, target) != 2) {
+ clif_displaymessage(fd, "usage: #effect <type+> <target>.");
+ return -1;
+ }
+
+ if((pl_sd=map_nick2sd((char *) target)) == NULL)
+ return -1;
+
+ clif_specialeffect(&pl_sd->bl, type, 0);
+ clif_displaymessage(fd, msg_table[229]); // Your effect has changed.
+
+ return 0;
+}
+
+/*==========================================
+ * #storagelist <character>: Displays the items list of a player's storage.
+ *------------------------------------------
+ */
+int
+charcommand_storagelist(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct storage *stor;
+ struct map_session_data *pl_sd;
+ struct item_data *item_data, *item_temp;
+ int i, j, count, counter, counter2;
+ char character[100], output[200], outputtmp[200];
+ nullpo_retr(-1, sd);
+
+ memset(character, '\0', sizeof(character));
+ memset(output, '\0', sizeof(output));
+ memset(outputtmp, '\0', sizeof(outputtmp));
+
+ if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ clif_displaymessage(fd, "Please, enter a player name (usage: #itemlist <char name>).");
+ return -1;
+ }
+
+ if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can look items only lower or same level
+ if((stor = account2storage2(pl_sd->status.account_id)) != NULL) {
+ counter = 0;
+ count = 0;
+ for (i = 0; i < MAX_STORAGE; i++) {
+ if (stor->storage_[i].nameid > 0 && (item_data = itemdb_search(stor->storage_[i].nameid)) != NULL) {
+ counter = counter + stor->storage_[i].amount;
+ count++;
+ if (count == 1) {
+ sprintf(output, "------ Storage items list of '%s' ------", pl_sd->status.name);
+ clif_displaymessage(fd, output);
+ }
+ if (stor->storage_[i].refine)
+ sprintf(output, "%d %s %+d (%s %+d, id: %d)", stor->storage_[i].amount, item_data->name, stor->storage_[i].refine, item_data->jname, stor->storage_[i].refine, stor->storage_[i].nameid);
+ else
+ sprintf(output, "%d %s (%s, id: %d)", stor->storage_[i].amount, item_data->name, item_data->jname, stor->storage_[i].nameid);
+ clif_displaymessage(fd, output);
+ memset(output, '\0', sizeof(output));
+ counter2 = 0;
+ for (j = 0; j < item_data->slot; j++) {
+ if (stor->storage_[i].card[j]) {
+ if ((item_temp = itemdb_search(stor->storage_[i].card[j])) != NULL) {
+ if (output[0] == '\0')
+ sprintf(outputtmp, " -> (card(s): #%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
+ else
+ sprintf(outputtmp, "#%d %s (%s), ", ++counter2, item_temp->name, item_temp->jname);
+ strcat(output, outputtmp);
+ }
+ }
+ }
+ if (output[0] != '\0') {
+ output[strlen(output) - 2] = ')';
+ output[strlen(output) - 1] = '\0';
+ clif_displaymessage(fd, output);
+ }
+ }
+ }
+ if (count == 0)
+ clif_displaymessage(fd, "No item found in the storage of this player.");
+ else {
+ sprintf(output, "%d item(s) found in %d kind(s) of items.", counter, count);
+ clif_displaymessage(fd, output);
+ }
+ } else {
+ clif_displaymessage(fd, "This player has no storage.");
+ return 0;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[3]); // Character not found.
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+charcommand_giveitem_sub(struct map_session_data *sd,struct item_data *item_data,int number)
+{
+ int flag = 0;
+ int loop = 1, get_count = number,i;
+ struct item item_tmp;
+
+ if(sd && item_data){
+ if (item_data->type == 4 || item_data->type == 5 ||
+ item_data->type == 7 || item_data->type == 8) {
+ loop = number;
+ get_count = 1;
+ }
+ for (i = 0; i < loop; i++) {
+ memset(&item_tmp, 0, sizeof(item_tmp));
+ item_tmp.nameid = item_data->nameid;
+ item_tmp.identify = 1;
+ if ((flag = pc_additem((struct map_session_data*)sd,
+ &item_tmp, get_count)))
+ clif_additem((struct map_session_data*)sd, 0, 0, flag);
+ }
+ }
+}
+/*==========================================
+ * #item command (usage: #item <name/id_of_item> <quantity> <player>)
+ * by MC Cameri
+ *------------------------------------------
+ */
+int charcommand_item(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ char item_name[100];
+ char character[100];
+ struct map_session_data *pl_sd;
+ int number = 0, item_id, flag;
+ struct item item_tmp;
+ struct item_data *item_data;
+ int get_count, i, pet_id;
+ nullpo_retr(-1, sd);
+
+ memset(item_name, '\0', sizeof(item_name));
+
+ if (!message || !*message || sscanf(message, "%99s %d %99[^\n]", item_name, &number, character) < 3) {
+ clif_displaymessage(fd, "Please, enter an item name/id (usage: #item <item name or ID> <quantity> <char name>).");
+ return -1;
+ }
+
+ if (number <= 0)
+ number = 1;
+
+ item_id = 0;
+ if ((item_data = itemdb_searchname(item_name)) != NULL ||
+ (item_data = itemdb_exists(atoi(item_name))) != NULL)
+ item_id = item_data->nameid;
+
+ if (item_id >= 500) {
+ get_count = number;
+ // check pet egg
+ pet_id = search_petDB_index(item_id, PET_EGG);
+ if (item_data->type == 4 || item_data->type == 5 ||
+ item_data->type == 7 || item_data->type == 8) {
+ get_count = 1;
+ }
+ if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can look items only lower or same level
+ for (i = 0; i < number; i += get_count) {
+ // if pet egg
+ if (pet_id >= 0) {
+ pl_sd->catch_target_class = pet_db[pet_id].class_;
+ intif_create_pet(pl_sd->status.account_id, pl_sd->status.char_id,
+ (short)pet_db[pet_id].class_, (short)mob_db[pet_db[pet_id].class_].lv,
+ (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate,
+ 100, 0, 1, pet_db[pet_id].jname);
+ // if not pet egg
+ } else {
+ memset(&item_tmp, 0, sizeof(item_tmp));
+ item_tmp.nameid = item_id;
+ item_tmp.identify = 1;
+ if ((flag = pc_additem(pl_sd, &item_tmp, get_count)))
+ clif_additem(pl_sd, 0, 0, flag);
+ }
+ }
+ clif_displaymessage(fd, msg_table[18]); // Item created.
+ } else {
+ clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
+ return -1;
+ }
+ } else if(/* from jA's @giveitem */strcmpi(character,"all")==0 || strcmpi(character,"everyone")==0){
+ for (i = 0; i < fd_max; i++) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data)){
+ charcommand_giveitem_sub(pl_sd,item_data,number);
+ snprintf(tmp_output, sizeof(tmp_output), "You got %s %d.", item_name,number);
+ clif_displaymessage(pl_sd->fd, tmp_output);
+ }
+ }
+ snprintf(tmp_output, sizeof(tmp_output), "%s received %s %d.","Everyone",item_name,number);
+ clif_displaymessage(fd, tmp_output);
+ } else {
+ clif_displaymessage(fd, msg_table[3]); // Character not found.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[19]); // Invalid item ID or name.
+ return -1;
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * #warp/#rura/#rura+ <mapname> <x> <y> <char name>
+ *------------------------------------------
+ */
+int charcommand_warp(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ char map_name[100];
+ char character[100];
+ int x = 0, y = 0;
+ struct map_session_data *pl_sd;
+ int m;
+
+ nullpo_retr(-1, sd);
+
+ memset(map_name, '\0', sizeof(map_name));
+ memset(character, '\0', sizeof(character));
+
+ if (!message || !*message || sscanf(message, "%99s %d %d %99[^\n]", map_name, &x, &y, character) < 4) {
+ clif_displaymessage(fd, "Usage: #warp/#rura/#rura+ <mapname> <x> <y> <char name>");
+ return -1;
+ }
+
+ if (x <= 0)
+ x = rand() % 399 + 1;
+ if (y <= 0)
+ y = rand() % 399 + 1;
+ if (strstr(map_name, ".gat") == NULL && strstr(map_name, ".afm") == NULL && strlen(map_name) < 13) // 16 - 4 (.gat)
+ strcat(map_name, ".gat");
+
+ if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can rura+ only lower or same GM level
+ if (x > 0 && x < 400 && y > 0 && y < 400) {
+ m = map_mapname2mapid(map_name);
+ if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
+ clif_displaymessage(fd, "You are not authorised to warp someone to this map.");
+ return -1;
+ }
+ if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
+ clif_displaymessage(fd, "You are not authorised to warp this player from its actual map.");
+ return -1;
+ }
+ if (pc_setpos(pl_sd, map_name, x, y, 3) == 0) {
+ clif_displaymessage(pl_sd->fd, msg_table[0]); // Warped.
+ clif_displaymessage(fd, msg_table[15]); // Player warped (message sends to player too).
+ } else {
+ clif_displaymessage(fd, msg_table[1]); // Map not found.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[2]); // Coordinates out of range.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[81]); // Your GM level don't authorise you to do this action on this player.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[3]); // Character not found.
+ return -1;
+ }
+
+ return 0;
+}
+
+/*==========================================
+ * #zeny <charname>
+ *------------------------------------------
+ */
+int charcommand_zeny(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct map_session_data *pl_sd;
+ char character[100];
+ int zeny = 0, new_zeny;
+ nullpo_retr(-1, sd);
+
+ memset(character, '\0', sizeof(character));
+
+ if (!message || !*message || sscanf(message, "%d %99[^\n]", &zeny, character) < 2 || zeny == 0) {
+ clif_displaymessage(fd, "Please, enter a number and a player name (usage: #zeny <zeny> <name>).");
+ return -1;
+ }
+
+ if ((pl_sd = map_nick2sd(character)) != NULL) {
+ new_zeny = pl_sd->status.zeny + zeny;
+ if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY)) // fix positiv overflow
+ new_zeny = MAX_ZENY;
+ else if (zeny < 0 && (zeny < -MAX_ZENY || new_zeny < 0)) // fix negativ overflow
+ new_zeny = 0;
+ if (new_zeny != pl_sd->status.zeny) {
+ pl_sd->status.zeny = new_zeny;
+ clif_updatestatus(pl_sd, SP_ZENY);
+ clif_displaymessage(fd, msg_table[211]); // Character's number of zenys changed!
+ } else {
+ if (zeny < 0)
+ clif_displaymessage(fd, msg_table[41]); // Impossible to decrease the number/value.
+ else
+ clif_displaymessage(fd, msg_table[149]); // Impossible to increase the number/value.
+ return -1;
+ }
+ } else {
+ clif_displaymessage(fd, msg_table[3]); // Character not found.
+ return -1;
+ }
+
+ return 0;
+}
+
+/*===================================
+ * Remove some messages
+ *-----------------------------------
+ */
+int charcommand_showexp(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ if (sd->noexp) {
+ sd->noexp = 0;
+ clif_displaymessage(fd, "Gained exp is now shown");
+ return 0;
+ }
+ else {
+ sd->noexp = 1;
+ clif_displaymessage(fd, "Gained exp is now NOT shown");
+ return 0;
+ }
+}
+
+int charcommand_showdelay(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ if (sd->nodelay) {
+ sd->nodelay = 0;
+ clif_displaymessage(fd, "Skill delay failure is now shown");
+ return 0;
+ }
+ else {
+ sd->nodelay = 1;
+ clif_displaymessage(fd, "Skill delay failure is NOT now shown");
+ return 0;
+ }
+}
+
diff --git a/src/map/charcommand.h b/src/map/charcommand.h
index 11babb816..7c1618cca 100644
--- a/src/map/charcommand.h
+++ b/src/map/charcommand.h
@@ -11,6 +11,15 @@ enum CharCommandType {
CharCommandOption,
CharCommandSave,
CharCommandStatsAll,
+ CharCommandSpiritball,
+ CharCommandItemList,
+ CharCommandEffect,
+ CharCommandStorageList,
+ CharCommandItem, // by MC Cameri
+ CharCommandWarp,
+ CharCommandZeny,
+ CharCommandShowDelay,
+ CharCommandShowExp,
#ifdef TXT_ONLY
/* TXT_ONLY */
diff --git a/src/map/chat.c b/src/map/chat.c
index 75788f03b..3bd29fec3 100644
--- a/src/map/chat.c
+++ b/src/map/chat.c
@@ -29,7 +29,7 @@ int chat_createchat(struct map_session_data *sd,int limit,int pub,char* pass,cha
nullpo_retr(0, sd);
- cd = aCalloc(1,sizeof(struct chat_data));
+ cd = (struct chat_data *) aCalloc(1,sizeof(struct chat_data));
cd->limit = limit;
cd->pub = pub;
@@ -49,7 +49,7 @@ int chat_createchat(struct map_session_data *sd,int limit,int pub,char* pass,cha
cd->bl.id = map_addobject(&cd->bl);
if(cd->bl.id==0){
clif_createchat(sd,1);
- free(cd);
+ aFree(cd);
return 0;
}
pc_setchatid(sd,cd->bl.id);
@@ -78,11 +78,11 @@ int chat_joinchat(struct map_session_data *sd,int chatid,char* pass)
clif_joinchatfail(sd,0);
return 0;
}
- if(cd->pub==0 && strncmp(pass,cd->pass,8)){
+ if(cd->pub==0 && strncmp(pass,(char *) cd->pass,8)){
clif_joinchatfail(sd,1);
return 0;
}
- if(chatid == sd->chatID) //Double Chat fix by Alex14, thx CHaNGeTe
+ if(chatid == (int)sd->chatID) //Double Chat fix by Alex14, thx CHaNGeTe
{
clif_joinchatfail(sd,1);
return 0;
@@ -268,14 +268,14 @@ int chat_createnpcchat(struct npc_data *nd,int limit,int pub,int trigger,char* t
nullpo_retr(1, nd);
- cd = aCalloc(1,sizeof(struct chat_data));
+ cd = (struct chat_data *) aCalloc(1,sizeof(struct chat_data));
cd->limit = cd->trigger = limit;
if(trigger>0)
cd->trigger = trigger;
cd->pub = pub;
cd->users = 0;
- memcpy(cd->pass,"",8);
+ memcpy(cd->pass,"",1);
if(titlelen>=sizeof(cd->title)-1) titlelen=sizeof(cd->title)-1;
memcpy(cd->title,title,titlelen);
cd->title[titlelen]=0;
@@ -286,11 +286,11 @@ int chat_createnpcchat(struct npc_data *nd,int limit,int pub,int trigger,char* t
cd->bl.type = BL_CHAT;
cd->owner_ = (struct block_list *)nd;
cd->owner = &cd->owner_;
- memcpy(cd->npc_event,ev,sizeof(cd->npc_event));
+ memcpy(cd->npc_event,ev,strlen(ev));
cd->bl.id = map_addobject(&cd->bl);
if(cd->bl.id==0){
- free(cd);
+ aFree(cd);
return 0;
}
nd->chat_id=cd->bl.id;
diff --git a/src/map/chrif.c b/src/map/chrif.c
index adb26868d..e250c8a18 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -23,6 +23,7 @@
#include "npc.h"
#include "pc.h"
#include "nullpo.h"
+#include "showmsg.h"
#ifdef MEMWATCH
#include "memwatch.h"
@@ -35,20 +36,22 @@ static const int packet_len_table[0x20] = {
-1,-1,10, 6,11,-1, 0, 0, // 2b10-2b17
};
-int char_fd;
+int chrif_connected;
+int char_fd = -1;
int srvinfo;
static char char_ip_str[16];
static int char_ip;
static int char_port = 6121;
static char userid[24], passwd[24];
-static int chrif_state;
+static int chrif_state = 0;
+static int char_init_done = 0;
// 設定ファイル読み込み関係
/*==========================================
*
*------------------------------------------
*/
-void chrif_setuserid(char *id)
+void chrif_setuserid(char *id)
{
strncpy(userid, id, 24);
}
@@ -57,7 +60,7 @@ void chrif_setuserid(char *id)
*
*------------------------------------------
*/
-void chrif_setpasswd(char *pwd)
+void chrif_setpasswd(char *pwd)
{
strncpy(passwd, pwd, 24);
}
@@ -66,7 +69,7 @@ void chrif_setpasswd(char *pwd)
*
*------------------------------------------
*/
-void chrif_setip(char *ip)
+void chrif_setip(char *ip)
{
strncpy(char_ip_str, ip, 16);
char_ip = inet_addr(char_ip_str);
@@ -76,7 +79,7 @@ void chrif_setip(char *ip)
*
*------------------------------------------
*/
-void chrif_setport(int port)
+void chrif_setport(int port)
{
char_port = port;
}
@@ -85,7 +88,7 @@ void chrif_setport(int port)
*
*------------------------------------------
*/
-int chrif_isconnect(void)
+int chrif_isconnect(void)
{
return chrif_state == 2;
}
@@ -94,11 +97,11 @@ int chrif_isconnect(void)
*
*------------------------------------------
*/
-int chrif_save(struct map_session_data *sd)
+int chrif_save(struct map_session_data *sd)
{
nullpo_retr(-1, sd);
- if (char_fd < 0)
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
return -1;
pc_makesavestatus(sd);
@@ -110,6 +113,8 @@ int chrif_save(struct map_session_data *sd)
memcpy(WFIFOP(char_fd,12), &sd->status, sizeof(sd->status));
WFIFOSET(char_fd, WFIFOW(char_fd,2));
+ storage_storage_save(sd); // to synchronise storage with character [Yor]
+
return 0;
}
@@ -117,7 +122,7 @@ int chrif_save(struct map_session_data *sd)
*
*------------------------------------------
*/
-int chrif_connect(int fd)
+int chrif_connect(int fd)
{
WFIFOW(fd,0) = 0x2af8;
memcpy(WFIFOP(fd,2), userid, 24);
@@ -134,13 +139,13 @@ int chrif_connect(int fd)
* マップ送信
*------------------------------------------
*/
-int chrif_sendmap(int fd)
+int chrif_sendmap(int fd)
{
int i;
WFIFOW(fd,0) = 0x2afa;
for(i = 0; i < map_num; i++)
- if (map[i].alias[0] != '\0') // [MouseJstr] map aliasing
+ if (map[i].alias != '\0') // [MouseJstr] map aliasing
memcpy(WFIFOP(fd,4+i*16), map[i].alias, 16);
else
memcpy(WFIFOP(fd,4+i*16), map[i].name, 16);
@@ -165,7 +170,7 @@ int chrif_recvmap(int fd)
ip = RFIFOL(fd,4);
port = RFIFOW(fd,8);
for(i = 10, j = 0; i < RFIFOW(fd,2); i += 16, j++) {
- map_setipport(RFIFOP(fd,i), ip, port);
+ map_setipport((char*)RFIFOP(fd,i), ip, port);
// if (battle_config.etc_log)
// printf("recv map %d %s\n", j, RFIFOP(fd,i));
}
@@ -179,12 +184,15 @@ int chrif_recvmap(int fd)
* マップ鯖間移動のためのデータ準備要求
*------------------------------------------
*/
-int chrif_changemapserver(struct map_session_data *sd, char *name, int x, int y, int ip, short port)
+int chrif_changemapserver(struct map_session_data *sd, char *name, int x, int y, int ip, short port)
{
int i, s_ip;
nullpo_retr(-1, sd);
+ if( !sd || char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
+ return -1;
+
s_ip = 0;
for(i = 0; i < fd_max; i++)
if (session[i] && session[i]->session_data == sd) {
@@ -213,7 +221,7 @@ int chrif_changemapserver(struct map_session_data *sd, char *name, int x, int y,
* マップ鯖間移動ack
*------------------------------------------
*/
-int chrif_changemapserverack(int fd)
+int chrif_changemapserverack(int fd)
{
struct map_session_data *sd = map_id2sd(RFIFOL(fd,2));
@@ -226,7 +234,7 @@ int chrif_changemapserverack(int fd)
pc_authfail(sd->fd);
return 0;
}
- clif_changemapserver(sd, RFIFOP(fd,18), RFIFOW(fd,34), RFIFOW(fd,36), RFIFOL(fd,38), RFIFOW(fd,42));
+ clif_changemapserver(sd, (char*)RFIFOP(fd,18), RFIFOW(fd,34), RFIFOW(fd,36), RFIFOL(fd,38), RFIFOW(fd,42));
return 0;
}
@@ -235,19 +243,28 @@ int chrif_changemapserverack(int fd)
*
*------------------------------------------
*/
-int chrif_connectack(int fd)
+int chrif_connectack(int fd)
{
if (RFIFOB(fd,2)) {
printf("Connected to char-server failed %d.\n", RFIFOB(fd,2));
exit(1);
}
- printf("Connected to char-server (connection #%d).\n", fd);
+ sprintf(tmp_output,"Successfully connected to Char Server (Connection: '"CL_WHITE"%d"CL_RESET"').\n",fd);
+ ShowStatus(tmp_output);
chrif_state = 1;
+ chrif_connected=1;
chrif_sendmap(fd);
- printf("chrif: OnCharIfInit event done. (%d events)\n", npc_event_doall("OnCharIfInit"));
- printf("chrif: OnInterIfInit event done. (%d events)\n", npc_event_doall("OnInterIfInit"));
+ sprintf(tmp_output,"Event '"CL_WHITE"OnCharIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnCharIfInit"));
+ ShowStatus(tmp_output);
+ sprintf(tmp_output,"Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit"));
+ ShowStatus(tmp_output);
+ if(!char_init_done) {
+ char_init_done = 1;
+ sprintf(tmp_output,"Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce"));
+ ShowStatus(tmp_output);
+ }
// <Agit> Run Event [AgitInit]
// printf("NPC_Event:[OnAgitInit] do (%d) events (Agit Initialize).\n", npc_event_doall("OnAgitInit"));
@@ -259,7 +276,7 @@ int chrif_connectack(int fd)
*
*------------------------------------------
*/
-int chrif_sendmapack(int fd)
+int chrif_sendmapack(int fd)
{
if (RFIFOB(fd,2)) {
printf("chrif : send map list to char server failed %d\n", RFIFOB(fd,2));
@@ -277,13 +294,15 @@ int chrif_sendmapack(int fd)
*
*------------------------------------------
*/
-int chrif_authreq(struct map_session_data *sd)
+int chrif_authreq(struct map_session_data *sd)
{
int i;
nullpo_retr(-1, sd);
- if (!sd || !char_fd || !sd->bl.id || !sd->login_id1)
+ if(!sd || !sd->bl.id || !sd->login_id1)
+ return -1;
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
return -1;
for(i = 0; i < fd_max; i++)
@@ -305,13 +324,15 @@ int chrif_authreq(struct map_session_data *sd)
*
*------------------------------------------
*/
-int chrif_charselectreq(struct map_session_data *sd)
+int chrif_charselectreq(struct map_session_data *sd)
{
int i, s_ip;
nullpo_retr(-1, sd);
- if(!sd || !char_fd || !sd->bl.id || !sd->login_id1)
+ if( !sd || !sd->bl.id || !sd->login_id1 )
+ return -1;
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
return -1;
s_ip = 0;
@@ -335,9 +356,11 @@ int chrif_charselectreq(struct map_session_data *sd)
* キャラ名問い合わせ
*------------------------------------------
*/
-int chrif_searchcharid(int char_id)
+int chrif_searchcharid(int char_id)
{
- if (!char_id)
+ if( !char_id )
+ return -1;
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
return -1;
WFIFOW(char_fd,0) = 0x2b08;
@@ -351,11 +374,14 @@ int chrif_searchcharid(int char_id)
* GMに変化要求
*------------------------------------------
*/
-int chrif_changegm(int id, const char *pass, int len)
+int chrif_changegm(int id, const char *pass, int len)
{
if (battle_config.etc_log)
printf("chrif_changegm: account: %d, password: '%s'.\n", id, pass);
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
+ return -1;
+
WFIFOW(char_fd,0) = 0x2b0a;
WFIFOW(char_fd,2) = len + 8;
WFIFOL(char_fd,4) = id;
@@ -369,11 +395,14 @@ int chrif_changegm(int id, const char *pass, int len)
* Change Email
*------------------------------------------
*/
-int chrif_changeemail(int id, const char *actual_email, const char *new_email)
+int chrif_changeemail(int id, const char *actual_email, const char *new_email)
{
if (battle_config.etc_log)
printf("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n", id, actual_email, new_email);
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
+ return -1;
+
WFIFOW(char_fd,0) = 0x2b0c;
WFIFOL(char_fd,2) = id;
memcpy(WFIFOP(char_fd,6), actual_email, 40);
@@ -394,8 +423,11 @@ int chrif_changeemail(int id, const char *actual_email, const char *new_email)
* 5: changesex
*------------------------------------------
*/
-int chrif_char_ask_name(int id, char * character_name, short operation_type, int year, int month, int day, int hour, int minute, int second)
+int chrif_char_ask_name(int id, char * character_name, short operation_type, int year, int month, int day, int hour, int minute, int second)
{
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
+ return -1;
+
WFIFOW(char_fd, 0) = 0x2b0e;
WFIFOL(char_fd, 2) = id; // account_id of who ask (for answer) -1 if nobody
memcpy(WFIFOP(char_fd,6), character_name, 24);
@@ -419,7 +451,10 @@ int chrif_char_ask_name(int id, char * character_name, short operation_type, int
*------------------------------------------
*/
int chrif_changesex(int id, int sex) {
- WFIFOW(char_fd,0) = 0x3000;
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
+ return -1;
+
+ WFIFOW(char_fd,0) = 0x2b11;
WFIFOW(char_fd,2) = 9;
WFIFOL(char_fd,4) = id;
WFIFOB(char_fd,8) = sex;
@@ -444,7 +479,7 @@ int chrif_changesex(int id, int sex) {
* 3: login-server offline
*------------------------------------------
*/
-int chrif_char_ask_name_answer(int fd)
+int chrif_char_ask_name_answer(int fd)
{
int acc;
struct map_session_data *sd;
@@ -547,7 +582,7 @@ int chrif_char_ask_name_answer(int fd)
* End of GM change (@GM) (modified by Yor)
*------------------------------------------
*/
-int chrif_changedgm(int fd)
+int chrif_changedgm(int fd)
{
int acc, level;
struct map_session_data *sd = NULL;
@@ -573,7 +608,7 @@ int chrif_changedgm(int fd)
* 性別変化終了 (modified by Yor)
*------------------------------------------
*/
-int chrif_changedsex(int fd)
+int chrif_changedsex(int fd)
{
int acc, sex, i;
struct map_session_data *sd;
@@ -586,7 +621,7 @@ int chrif_changedsex(int fd)
sd = map_id2sd(acc);
if (acc > 0) {
if (sd != NULL && sd->status.sex != sex) {
- s_class = pc_calc_base_job(sd->status.class);
+ s_class = pc_calc_base_job(sd->status.class_);
if (sd->status.sex == 0) {
sd->status.sex = 1;
sd->sex = 1;
@@ -597,7 +632,7 @@ int chrif_changedsex(int fd)
// to avoid any problem with equipment and invalid sex, equipment is unequiped.
for (i = 0; i < MAX_INVENTORY; i++) {
if (sd->status.inventory[i].nameid && sd->status.inventory[i].equip)
- pc_unequipitem((struct map_session_data*)sd, i, 0, BF_NORMAL);
+ pc_unequipitem((struct map_session_data*)sd, i, 2);
}
// reset skill of some job
if (s_class.job == 19 || s_class.job == 4020 || s_class.job == 4042 ||
@@ -621,15 +656,15 @@ int chrif_changedsex(int fd)
clif_updatestatus(sd, SP_SKILLPOINT);
// change job if necessary
if (s_class.job == 20 || s_class.job == 4021 || s_class.job == 4043)
- sd->status.class -= 1;
+ sd->status.class_ -= 1;
else if (s_class.job == 19 || s_class.job == 4020 || s_class.job == 4042)
- sd->status.class += 1;
+ sd->status.class_ += 1;
}
// save character
chrif_save(sd);
sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
// do same modify in login-server for the account, but no in char-server (it ask again login_id1 to login, and don't remember it)
- clif_displaymessage(sd->fd, "Your sex has been changed (need disconexion by the server)...");
+ clif_displaymessage(sd->fd, "Your sex has been changed (need disconnection by the server)...");
clif_setwaitclose(sd->fd); // forced to disconnect for the change
}
} else {
@@ -645,11 +680,14 @@ int chrif_changedsex(int fd)
* アカウント変数保存要求
*------------------------------------------
*/
-int chrif_saveaccountreg2(struct map_session_data *sd)
+int chrif_saveaccountreg2(struct map_session_data *sd)
{
int p, j;
nullpo_retr(-1, sd);
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
+ return -1;
+
p = 8;
for(j = 0; j < sd->status.account_reg2_num; j++) {
struct global_reg *reg = &sd->status.account_reg2[j];
@@ -671,7 +709,7 @@ int chrif_saveaccountreg2(struct map_session_data *sd)
* アカウント変数通知
*------------------------------------------
*/
-int chrif_accountreg2(int fd)
+int chrif_accountreg2(int fd)
{
int j, p;
struct map_session_data *sd;
@@ -693,7 +731,7 @@ int chrif_accountreg2(int fd)
* 離婚情報同期要求
*------------------------------------------
*/
-int chrif_divorce(int char_id, int partner_id)
+int chrif_divorce(int char_id, int partner_id)
{
struct map_session_data *sd = NULL;
@@ -719,7 +757,7 @@ int chrif_divorce(int char_id, int partner_id)
* Disconnection of a player (account has been deleted in login-server) by [Yor]
*------------------------------------------
*/
-int chrif_accountdeletion(int fd)
+int chrif_accountdeletion(int fd)
{
int acc;
struct map_session_data *sd;
@@ -731,7 +769,7 @@ int chrif_accountdeletion(int fd)
if (acc > 0) {
if (sd != NULL) {
sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
- clif_displaymessage(sd->fd, "Your account has been deleted (disconnexion)...");
+ clif_displaymessage(sd->fd, "Your account has been deleted (disconnection)...");
clif_setwaitclose(sd->fd); // forced to disconnect for the change
}
} else {
@@ -746,7 +784,7 @@ int chrif_accountdeletion(int fd)
* Disconnection of a player (account has been banned of has a status, from login-server) by [Yor]
*------------------------------------------
*/
-int chrif_accountban(int fd)
+int chrif_accountban(int fd)
{
int acc;
struct map_session_data *sd;
@@ -820,7 +858,7 @@ int chrif_chardisconnect(struct map_session_data *sd)
{
nullpo_retr(-1, sd);
- if(char_fd<=0)
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
return -1;
WFIFOW(char_fd,0)=0x2b18;
@@ -836,10 +874,11 @@ int chrif_chardisconnect(struct map_session_data *sd)
* Receiving GM accounts and their levels from char-server by [Yor]
*------------------------------------------
*/
-int chrif_recvgmaccounts(int fd)
+int chrif_recvgmaccounts(int fd)
{
- printf("From login-server: receiving of %d GM accounts information.\n", pc_read_gm_account(fd));
-
+ sprintf(tmp_output,"From login-server: receiving information of '"CL_WHITE"%d"CL_RESET"' GM accounts.\n", pc_read_gm_account(fd));
+ ShowInfo(tmp_output);
+ memset(tmp_output,'\0',sizeof(tmp_output));
return 0;
}
@@ -847,8 +886,10 @@ int chrif_recvgmaccounts(int fd)
* Request to reload GM accounts and their levels: send to char-server by [Yor]
*------------------------------------------
*/
-int chrif_reloadGMdb(void)
+int chrif_reloadGMdb(void)
{
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
+ return -1;
WFIFOW(char_fd,0) = 0x2af7;
WFIFOSET(char_fd, 2);
@@ -860,12 +901,15 @@ int chrif_reloadGMdb(void)
* Send rates and motd to char server [Wizputer]
*------------------------------------------
*/
- int chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate)
+ int chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate)
{
char buf[256];
FILE *fp;
int i;
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
+ return -1;
+
WFIFOW(char_fd,0) = 0x2b16;
WFIFOW(char_fd,2) = base_rate;
WFIFOW(char_fd,4) = job_rate;
@@ -897,14 +941,62 @@ int chrif_reloadGMdb(void)
*-----------------------------------------
*/
-int chrif_char_offline(struct map_session_data *sd)
+int chrif_char_offline(struct map_session_data *sd)
{
- if (char_fd < 0)
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
return -1;
WFIFOW(char_fd,0) = 0x2b17;
WFIFOL(char_fd,2) = sd->status.char_id;
- WFIFOSET(char_fd,6);
+ WFIFOL(char_fd,6) = sd->status.account_id;
+ WFIFOSET(char_fd,10);
+
+ return 0;
+}
+
+/*=========================================
+ * Tell char-server to reset all chars offline [Wizputer]
+ *-----------------------------------------
+ */
+int chrif_flush_fifo(void) {
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
+ return -1;
+
+ set_nonblocking(char_fd, 0);
+ flush_fifos();
+ set_nonblocking(char_fd, 1);
+
+ return 0;
+}
+
+/*=========================================
+ * Tell char-server to reset all chars offline [Wizputer]
+ *-----------------------------------------
+ */
+int chrif_char_reset_offline(void) {
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
+ return -1;
+
+ WFIFOW(char_fd,0) = 0x2b18;
+ WFIFOSET(char_fd,2);
+
+ return 0;
+}
+
+/*=========================================
+ * Tell char-server charcter is online [Wizputer]
+ *-----------------------------------------
+ */
+
+int chrif_char_online(struct map_session_data *sd)
+{
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() )
+ return -1;
+
+ WFIFOW(char_fd,0) = 0x2b19;
+ WFIFOL(char_fd,2) = sd->status.char_id;
+ WFIFOL(char_fd,6) = sd->status.account_id;
+ WFIFOSET(char_fd,10);
return 0;
}
@@ -913,16 +1005,39 @@ int chrif_char_offline(struct map_session_data *sd)
*
*------------------------------------------
*/
-int chrif_parse(int fd)
+int chrif_disconnect_sub(struct map_session_data* sd,va_list va) {
+ clif_authfail_fd(sd->fd,1);
+ map_quit(sd);
+ return 0;
+}
+
+int chrif_disconnect(int fd) {
+ if(fd == char_fd) {
+ char_fd = 0;
+ sprintf(tmp_output,"Map Server disconnected from Char Server.\n\n");
+ ShowWarning(tmp_output);
+ clif_foreachclient(chrif_disconnect_sub);
+ chrif_connected = 0;
+ // 他のmap 鯖のデータを消す
+ map_eraseallipport();
+ }
+ close(fd);
+ return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_parse(int fd)
{
int packet_len, cmd;
-
// only char-server can have an access to here.
// so, if it isn't the char-server, we disconnect the session (fd != char_fd).
if (fd != char_fd || session[fd]->eof) {
- if (fd == char_fd) {
- printf("Map-server can't connect to char-server (connection #%d).\n", fd);
- char_fd = -1;
+ if (fd == char_fd && chrif_connected == 1) {
+ chrif_disconnect (fd);
+// check_connect_char_server(0, 0, 0, 0);
}
close(fd);
delete_session(fd);
@@ -956,11 +1071,11 @@ int chrif_parse(int fd)
case 0x2afb: chrif_sendmapack(fd); break;
case 0x2afd: pc_authok(RFIFOL(fd,4), RFIFOL(fd,8), (time_t)RFIFOL(fd,12), (struct mmo_charstatus*)RFIFOP(fd,16)); break;
case 0x2afe: pc_authfail(RFIFOL(fd,2)); break;
- case 0x2b00: map_setusers(RFIFOL(fd,2)); break;
+ case 0x2b00: map_setusers(fd); break;
case 0x2b03: clif_charselectok(RFIFOL(fd,2)); break;
case 0x2b04: chrif_recvmap(fd); break;
case 0x2b06: chrif_changemapserverack(fd); break;
- case 0x2b09: map_addchariddb(RFIFOL(fd,2), RFIFOP(fd,6)); break;
+ case 0x2b09: map_addchariddb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break;
case 0x2b0b: chrif_changedgm(fd); break;
case 0x2b0d: chrif_changedsex(fd); break;
case 0x2b0f: chrif_char_ask_name_answer(fd); break;
@@ -991,12 +1106,12 @@ int send_users_tochar(int tid, unsigned int tick, int id, int data) {
int users = 0, i;
struct map_session_data *sd;
- if (char_fd <= 0 || session[char_fd] == NULL)
+ if( char_fd < 1 || session[char_fd] == NULL || !chrif_isconnect() ) // Thanks to Toster
return 0;
WFIFOW(char_fd,0) = 0x2aff;
for (i = 0; i < fd_max; i++) {
- if (session[i] && (sd = session[i]->session_data) && sd->state.auth &&
+ if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd->state.auth &&
!((battle_config.hide_GM_session || (sd->status.option & OPTION_HIDE)) && pc_isGM(sd))) {
WFIFOL(char_fd,6+4*users) = sd->status.char_id;
users++;
@@ -1015,14 +1130,19 @@ int send_users_tochar(int tid, unsigned int tick, int id, int data) {
*------------------------------------------
*/
int check_connect_char_server(int tid, unsigned int tick, int id, int data) {
+ static int displayed = 0;
if (char_fd <= 0 || session[char_fd] == NULL) {
- printf("Attempt to connect to char-server...\n");
+ if (!displayed) {
+ ShowStatus("Attempting to connect to Char Server. Please wait.\n");
+ displayed = 1;
+ }
chrif_state = 0;
char_fd = make_connection(char_ip, char_port);
session[char_fd]->func_parse = chrif_parse;
realloc_fifo(char_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
chrif_connect(char_fd);
+ chrif_connected = chrif_isconnect();
#ifndef TXT_ONLY
srvinfo = 0;
} else {
@@ -1032,7 +1152,16 @@ int check_connect_char_server(int tid, unsigned int tick, int id, int data) {
}
#endif /* not TXT_ONLY */
}
-
+ 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 de20c3086..f2b258ea9 100644
--- a/src/map/chrif.h
+++ b/src/map/chrif.h
@@ -9,6 +9,8 @@ void chrif_setport(int);
int chrif_isconnect(void);
+extern int chrif_connected;
+
int chrif_authreq(struct map_session_data *);
int chrif_save(struct map_session_data*);
int chrif_charselectreq(struct map_session_data *);
@@ -23,9 +25,15 @@ int chrif_saveaccountreg2(struct map_session_data *sd);
int chrif_reloadGMdb(void);
int chrif_ragsrvinfo(int base_rate,int job_rate, int drop_rate);
int chrif_char_offline(struct map_session_data *sd);
+int chrif_char_reset_offline(void);
+int chrif_char_online(struct map_session_data *sd);
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);
+
#endif
diff --git a/src/map/clif.c b/src/map/clif.c
index 9163671a8..c8f190c5a 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -1,6 +1,7 @@
// $Id: clif.c 2200 2004-11-07 11:49:58Z Yor $
#define DUMP_UNKNOWN_PACKET 1
+#define DUMP_ALL_PACKETS 0
#include <stdio.h>
#include <ctype.h>
@@ -24,11 +25,13 @@
#include "../common/malloc.h"
#include "../common/version.h"
#include "../common/nullpo.h"
+#include "../common/showmsg.h"
#include "map.h"
#include "chrif.h"
#include "clif.h"
#include "pc.h"
+#include "status.h"
#include "npc.h"
#include "itemdb.h"
#include "chat.h"
@@ -52,7 +55,16 @@
#define STATE_BLIND 0x10
-static const int packet_len_table[0x220] = {
+struct Clif_Config clif_config;
+struct packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB];
+
+#define USE_PACKET_DB(sd) \
+ clif_config.enable_packet_db && sd->packet_ver == clif_config.packet_db_ver
+
+#define IS_PACKET_DB_VER(cmd) \
+ cmd == clif_config.connect_cmd
+
+static const int packet_len_table[MAX_PACKET_DB] = {
10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -67,12 +79,12 @@ static const int packet_len_table[0x220] = {
3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6,
#endif
//#0x0080
- 7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 23, -1, -1, -1, 0, // 0x8b unknown... size 2 or 23?
+ 7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 2, -1, -1, -1, 0, // 0x8b changed to 2 (was 23)
7, 22, 28, 2, 6, 30, -1, -1, 3, -1, -1, 5, 9, 17, 17, 6,
23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6,
8, 8, 3, 3, -1, 6, 6, -1, 7, 6, 2, 5, 6, 44, 5, 3,
//#0x00C0
- 7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 6, 2, 27,
+ 7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 3, 2, 27, // 0xcd change to 3 (was 6)
3, 4, 4, 2, -1, -1, 3, -1, 6, 14, 3, -1, 28, 29, -1, -1,
30, 30, 26, 2, 6, 26, 3, 3, 8, 19, 5, 2, 3, 2, 2, 2,
3, 2, 6, 8, 21, 8, 8, 2, 2, 26, 3, -1, 6, 27, 30, 10,
@@ -102,13 +114,11 @@ static const int packet_len_table[0x220] = {
30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2, -1, -1,
-1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10,
//#0x200
- 26, -1, 26, 10, 18, 26, 11, 34, 14, 36, 10, 19, 0, -1, 24, 0,
+ 26, -1, 26, 10, 18, 26, 11, 34, 14, 36, 10, 0, 0, -1, 24, 0, // 0x20c change to 0 (was 19)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
};
-// size list for each packet version after packet version 4.
-static int packet_size_table[9][0x220];
-
// local define
enum {
ALL_CLIENT,
@@ -143,6 +153,7 @@ enum {
static char map_ip_str[16];
static in_addr_t map_ip;
+static in_addr_t bind_ip = INADDR_ANY;
static int map_port = 5121;
int map_fd;
char talkie_mes[80];
@@ -151,17 +162,22 @@ char talkie_mes[80];
* map鯖のip設定
*------------------------------------------
*/
-void clif_setip(char *ip)
+void clif_setip(char *ip)
{
memcpy(map_ip_str, ip, 16);
map_ip = inet_addr(map_ip_str);
}
+void clif_setbindip(char *ip)
+{
+ bind_ip = inet_addr(ip);
+}
+
/*==========================================
* map鯖のport設定
*------------------------------------------
*/
-void clif_setport(int port)
+void clif_setport(int port)
{
map_port = port;
}
@@ -170,7 +186,7 @@ void clif_setport(int port)
* map鯖のip読み出し
*------------------------------------------
*/
-in_addr_t clif_getip(void)
+in_addr_t clif_getip(void)
{
return map_ip;
}
@@ -179,7 +195,7 @@ in_addr_t clif_getip(void)
* map鯖のport読み出し
*------------------------------------------
*/
-int clif_getport(void)
+int clif_getport(void)
{
return map_port;
}
@@ -188,13 +204,13 @@ int clif_getport(void)
*
*------------------------------------------
*/
-int clif_countusers(void)
+int clif_countusers(void)
{
int users = 0, i;
struct map_session_data *sd;
for(i = 0; i < fd_max; i++) {
- if (session[i] && (sd = session[i]->session_data) && sd && sd->state.auth &&
+ if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd && sd->state.auth &&
!(battle_config.hide_GM_session && pc_isGM(sd)))
users++;
}
@@ -205,7 +221,7 @@ int clif_countusers(void)
* 全てのclientに対してfunc()実行
*------------------------------------------
*/
-int clif_foreachclient(int (*func)(struct map_session_data*, va_list),...)
+int clif_foreachclient(int (*func)(struct map_session_data*, va_list),...)
{
int i;
va_list ap;
@@ -213,7 +229,7 @@ int clif_foreachclient(int (*func)(struct map_session_data*, va_list),...)
va_start(ap,func);
for(i = 0; i < fd_max; i++) {
- if (session[i] && (sd = session[i]->session_data) && sd && sd->state.auth)
+ if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd && sd->state.auth)
func(sd, ap);
}
va_end(ap);
@@ -224,14 +240,13 @@ int clif_foreachclient(int (*func)(struct map_session_data*, va_list),...)
* clif_sendでAREA*指定時用
*------------------------------------------
*/
-int clif_send_sub(struct block_list *bl, va_list ap)
+int clif_send_sub(struct block_list *bl, va_list ap)
{
- unsigned char *buf;
- int len;
struct block_list *src_bl;
- int type;
struct map_session_data *sd;
-
+ unsigned char *buf;
+ int len, type;
+
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, sd = (struct map_session_data *)bl);
@@ -243,27 +258,30 @@ int clif_send_sub(struct block_list *bl, va_list ap)
switch(type) {
case AREA_WOS:
- if (bl && bl == src_bl)
+ if (bl == src_bl)
return 0;
break;
case AREA_WOC:
- if ((sd && sd->chatID) || (bl && bl == src_bl))
+ if (sd->chatID || bl == src_bl)
return 0;
break;
case AREA_WOSC:
- if ((sd) && sd->chatID && sd->chatID == ((struct map_session_data*)src_bl)->chatID)
- return 0;
+ {
+ struct map_session_data *ssd = (struct map_session_data *)src_bl;
+ if (ssd && sd->chatID && sd->chatID == ssd->chatID)
+ return 0;
+ }
break;
}
- if (sd) {
+ if (session[sd->fd] != NULL) {
if (WFIFOP(sd->fd,0) == buf) {
printf("WARNING: Invalid use of clif_send function\n");
printf(" Packet x%4x use a WFIFO of a player instead of to use a buffer.\n", WBUFW(buf,0));
printf(" Please correct your code.\n");
// don't send to not move the pointer of the packet for next sessions in the loop
} else {
- if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version
+ if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
memcpy(WFIFOP(sd->fd,0), buf, len);
WFIFOSET(sd->fd,len);
}
@@ -279,8 +297,7 @@ int clif_send_sub(struct block_list *bl, va_list ap)
*/
int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) {
int i;
- struct map_session_data *sd;
- struct chat_data *cd;
+ struct map_session_data *sd = NULL;
struct party *p = NULL;
struct guild *g = NULL;
int x0 = 0, x1 = 0, y0 = 0, y1 = 0;
@@ -288,12 +305,15 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) {
if (type != ALL_CLIENT) {
nullpo_retr(0, bl);
}
+ if (bl && bl->type == BL_PC) {
+ nullpo_retr (0, sd=(struct map_session_data*)bl);
+ }
switch(type) {
case ALL_CLIENT: // 全クライアントに送信
for(i = 0; i < fd_max; i++) {
- if (session[i] && (sd = session[i]->session_data) != NULL && sd->state.auth) {
- if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version
+ if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) != NULL && sd->state.auth) {
+ if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
memcpy(WFIFOP(i,0), buf, len);
WFIFOSET(i,len);
}
@@ -302,8 +322,8 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) {
break;
case ALL_SAMEMAP: // 同じマップの全クライアントに送信
for(i = 0; i < fd_max; i++) {
- if (session[i] && (sd = session[i]->session_data) != NULL && sd->state.auth && sd->bl.m == bl->m) {
- if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version
+ if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) != NULL && sd->state.auth && sd->bl.m == bl->m) {
+ if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
memcpy(WFIFOP(i,0), buf, len);
WFIFOSET(i,len);
}
@@ -321,21 +341,24 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) {
break;
case CHAT:
case CHAT_WOS:
- cd = (struct chat_data*)bl;
- if (bl->type == BL_PC) {
- sd = (struct map_session_data*)bl;
- cd = (struct chat_data*)map_id2bl(sd->chatID);
- } else if (bl->type != BL_CHAT)
- break;
- if (cd == NULL)
- break;
- for(i = 0; i < cd->users; i++) {
- if (type == CHAT_WOS && cd->usersd[i] == (struct map_session_data*)bl)
- continue;
- if (packet_size_table[cd->usersd[i]->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version
- if (cd->usersd[i]->fd >=0 && session[cd->usersd[i]->fd]) // Added check to see if session exists [PoW]
- memcpy(WFIFOP(cd->usersd[i]->fd,0), buf, len);
- WFIFOSET(cd->usersd[i]->fd,len);
+ {
+ struct chat_data *cd;
+ if (sd) {
+ cd = (struct chat_data*)map_id2bl(sd->chatID);
+ } else if (bl->type == BL_CHAT) {
+ cd = (struct chat_data*)bl;
+ } else if (bl->type != BL_CHAT)
+ break;
+ if (cd == NULL)
+ break;
+ for(i = 0; i < cd->users; i++) {
+ if (type == CHAT_WOS && cd->usersd[i] == sd)
+ continue;
+ if (packet_db[cd->usersd[i]->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
+ if (cd->usersd[i]->fd >=0 && session[cd->usersd[i]->fd]) // Added check to see if session exists [PoW]
+ memcpy(WFIFOP(cd->usersd[i]->fd,0), buf, len);
+ WFIFOSET(cd->usersd[i]->fd,len);
+ }
}
}
break;
@@ -350,18 +373,18 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) {
case PARTY_WOS: // 自分以外の全パーティーメンバに送信
case PARTY_SAMEMAP: // 同じマップの全パーティーメンバに送信
case PARTY_SAMEMAP_WOS: // 自分以外の同じマップの全パーティーメンバに送信
- if (bl->type == BL_PC) {
- sd = (struct map_session_data *)bl;
+ if (sd) {
if (sd->partyspy > 0) {
p = party_search(sd->partyspy);
- } else {
- if (sd->status.party_id > 0)
- p = party_search(sd->status.party_id);
+ } else if (sd->status.party_id > 0) {
+ p = party_search(sd->status.party_id);
}
}
if (p) {
for(i=0;i<MAX_PARTY;i++){
if ((sd = p->member[i].sd) != NULL) {
+ if ((session[sd->fd] == NULL) || (session[sd->fd]->session_data == NULL))
+ continue;
if (sd->bl.id == bl->id && (type == PARTY_WOS ||
type == PARTY_SAMEMAP_WOS || type == PARTY_AREA_WOS))
continue;
@@ -371,7 +394,7 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) {
(sd->bl.x < x0 || sd->bl.y < y0 ||
sd->bl.x > x1 || sd->bl.y > y1))
continue;
- if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version
+ if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
memcpy(WFIFOP(sd->fd,0), buf, len);
WFIFOSET(sd->fd,len);
}
@@ -381,9 +404,9 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) {
}
}
for (i = 0; i < fd_max; i++){
- if (session[i] && (sd = session[i]->session_data) != NULL && sd->state.auth) {
+ if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) != NULL && sd->state.auth) {
if (sd->partyspy == p->party_id) {
- if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version
+ if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
memcpy(WFIFOP(sd->fd,0), buf, len);
WFIFOSET(sd->fd,len);
}
@@ -393,8 +416,7 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) {
}
break;
case SELF:
- sd = (struct map_session_data *)bl;
- if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version
+ if (sd && packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
memcpy(WFIFOP(sd->fd,0), buf, len);
WFIFOSET(sd->fd,len);
}
@@ -410,13 +432,11 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) {
y1 = bl->y + AREA_SIZE;
case GUILD:
case GUILD_WOS:
- if (bl && bl->type == BL_PC) { // guildspy [Syrus22]
- sd = (struct map_session_data *)bl;
+ if (sd) { // guildspy [Syrus22]
if (sd->guildspy > 0) {
g = guild_search(sd->guildspy);
- } else {
- if (sd->status.guild_id > 0)
- g = guild_search(sd->status.guild_id);
+ } else if (sd->status.guild_id > 0) {
+ g = guild_search(sd->status.guild_id);
}
}
if (g) {
@@ -424,16 +444,18 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) {
if ((sd = g->member[i].sd) != NULL) {
if (type == GUILD_WOS && sd->bl.id == bl->id)
continue;
- if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version
+ if (sd->packet_ver > MAX_PACKET_VER)
+ continue;
+ if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
memcpy(WFIFOP(sd->fd,0), buf, len);
WFIFOSET(sd->fd,len);
}
}
}
for (i = 0; i < fd_max; i++){
- if (session[i] && (sd = session[i]->session_data) != NULL && sd->state.auth) {
+ if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) != NULL && sd->state.auth) {
if (sd->guildspy == g->guild_id) {
- if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version
+ if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
memcpy(WFIFOP(sd->fd,0), buf, len);
WFIFOSET(sd->fd,len);
}
@@ -444,10 +466,8 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) {
break;
case GUILD_SAMEMAP:
case GUILD_SAMEMAP_WOS:
- if (bl->type == BL_PC) {
- sd = (struct map_session_data *)bl;
- if (sd->status.guild_id > 0)
- g = guild_search(sd->status.guild_id);
+ if (sd && sd->status.guild_id > 0) {
+ g = guild_search(sd->status.guild_id);
}
if (g) {
for(i = 0; i < g->max_member; i++) {
@@ -461,7 +481,7 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) {
(sd->bl.x < x0 || sd->bl.y < y0 ||
sd->bl.x > x1 || sd->bl.y > y1))
continue;
- if (packet_size_table[sd->packet_ver-5][RBUFW(buf,0)]) { // packet must exist for the client version
+ if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
memcpy(WFIFOP(sd->fd,0), buf, len);
WFIFOSET(sd->fd,len);
}
@@ -580,7 +600,7 @@ static int clif_set009e(struct flooritem_data *fitem,unsigned char *buf) {
*------------------------------------------
*/
int clif_dropflooritem(struct flooritem_data *fitem) {
- char buf[64];
+ unsigned char buf[64];
nullpo_retr(0, fitem);
@@ -685,7 +705,7 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) {
WBUFW(buf,0) = 0x78;
WBUFL(buf,2) = sd->bl.id;
- WBUFW(buf,6) = battle_get_speed(&sd->bl);
+ WBUFW(buf,6) = status_get_speed(&sd->bl);
WBUFW(buf,8) = sd->opt1;
WBUFW(buf,10) = sd->opt2;
WBUFW(buf,12) = sd->status.option;
@@ -697,7 +717,7 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) {
WBUFB(buf,49) = 5;
WBUFB(buf,50) = 5;
WBUFB(buf,51) = 0;
- WBUFW(buf,52) = ((level = battle_get_lv(&sd->bl)) > battle_config.max_lv) ? battle_config.max_lv : level;
+ WBUFW(buf,52) = ((level = status_get_lv(&sd->bl)) > battle_config.max_lv) ? battle_config.max_lv : level;
return packet_len_table[0x78];
}
@@ -775,7 +795,7 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) {
WBUFB(buf,49) = 5;
WBUFB(buf,50) = 5;
WBUFB(buf,51) = sd->state.dead_sit;
- WBUFW(buf,52) = ((level = battle_get_lv(&sd->bl)) > battle_config.max_lv) ? battle_config.max_lv : level;
+ WBUFW(buf,52) = ((level = status_get_lv(&sd->bl)) > battle_config.max_lv) ? battle_config.max_lv : level;
return packet_len_table[0x1d8];
#endif
@@ -794,7 +814,7 @@ static int clif_set007b(struct map_session_data *sd,unsigned char *buf) {
WBUFW(buf,0)=0x7b;
WBUFL(buf,2)=sd->bl.id;
- WBUFW(buf,6)=battle_get_speed(&sd->bl);
+ WBUFW(buf,6)=status_get_speed(&sd->bl);
WBUFW(buf,8)=sd->opt1;
WBUFW(buf,10)=sd->opt2;
WBUFW(buf,12)=sd->status.option;
@@ -806,7 +826,7 @@ static int clif_set007b(struct map_session_data *sd,unsigned char *buf) {
WBUFB(buf,55)=0;
WBUFB(buf,56)=5;
WBUFB(buf,57)=5;
- WBUFW(buf,58)=((level = battle_get_lv(&sd->bl))>battle_config.max_lv)? battle_config.max_lv:level;
+ WBUFW(buf,58)=((level = status_get_lv(&sd->bl))>battle_config.max_lv)? battle_config.max_lv:level;
return packet_len_table[0x7b];
}
@@ -896,17 +916,17 @@ static int clif_set007b(struct map_session_data *sd,unsigned char *buf) {
* クラスチェンジ typeはMobの場合は1で他は0?
*------------------------------------------
*/
-int clif_class_change(struct block_list *bl,int class,int type)
+int clif_class_change(struct block_list *bl,int class_,int type)
{
- char buf[16];
+ unsigned char buf[16];
nullpo_retr(0, bl);
- if(class >= MAX_PC_CLASS) {
+ if(class_ >= MAX_PC_CLASS) {
WBUFW(buf,0)=0x1b0;
WBUFL(buf,2)=bl->id;
WBUFB(buf,6)=type;
- WBUFL(buf,7)=class;
+ WBUFL(buf,7)=class_;
clif_send(buf,packet_len_table[0x1b0],bl,AREA);
}
@@ -916,9 +936,9 @@ int clif_class_change(struct block_list *bl,int class,int type)
*
*------------------------------------------
*/
-int clif_mob_class_change(struct mob_data *md, int class) {
- char buf[16];
- int view = mob_get_viewclass(class);
+int clif_mob_class_change(struct mob_data *md, int class_) {
+ unsigned char buf[16];
+ int view = mob_get_viewclass(class_);
nullpo_retr(0, md);
@@ -955,9 +975,9 @@ int clif_mob_equip(struct mob_data *md, int nameid) {
* MOB表示1
*------------------------------------------
*/
-static int clif_mob0078(struct mob_data *md, unsigned char *buf)
+static int clif_mob0078(struct mob_data *md, unsigned char *buf)
{
- int level;
+ int level, i;
memset(buf,0,packet_len_table[0x78]);
@@ -965,25 +985,25 @@ static int clif_mob0078(struct mob_data *md, unsigned char *buf)
WBUFW(buf,0)=0x78;
WBUFL(buf,2)=md->bl.id;
- WBUFW(buf,6)=battle_get_speed(&md->bl);
+ WBUFW(buf,6)=status_get_speed(&md->bl);
WBUFW(buf,8)=md->opt1;
WBUFW(buf,10)=md->opt2;
WBUFW(buf,12)=md->option;
- WBUFW(buf,14)=mob_get_viewclass(md->class);
- if((mob_get_viewclass(md->class) <= 23) || (mob_get_viewclass(md->class) == 812) || (mob_get_viewclass(md->class) >= 4001)) {
- WBUFW(buf,12)|=mob_db[md->class].option;
- WBUFW(buf,16)=mob_get_hair(md->class);
- WBUFW(buf,18)=mob_get_weapon(md->class);
- WBUFW(buf,20)=mob_get_head_buttom(md->class);
- WBUFW(buf,22)=mob_get_shield(md->class);
- WBUFW(buf,24)=mob_get_head_top(md->class);
- WBUFW(buf,26)=mob_get_head_mid(md->class);
- WBUFW(buf,28)=mob_get_hair_color(md->class);
- WBUFW(buf,30)=mob_get_clothes_color(md->class); //Add for player monster dye - Valaris
- WBUFB(buf,45)=mob_get_sex(md->class);
- }
-
- if (md->class >= 1285 && md->class <= 1287 && md->guild_id) { // Added guardian emblems [Valaris]
+ WBUFW(buf,14)=mob_get_viewclass(md->class_);
+ if((i=mob_get_viewclass(md->class_)) <= 23 || i == 812 || i >= 4001) {
+ WBUFW(buf,12)|=mob_db[md->class_].option;
+ WBUFW(buf,16)=mob_get_hair(md->class_);
+ WBUFW(buf,18)=mob_get_weapon(md->class_);
+ WBUFW(buf,20)=mob_get_head_buttom(md->class_);
+ WBUFW(buf,22)=mob_get_shield(md->class_);
+ WBUFW(buf,24)=mob_get_head_top(md->class_);
+ WBUFW(buf,26)=mob_get_head_mid(md->class_);
+ WBUFW(buf,28)=mob_get_hair_color(md->class_);
+ WBUFW(buf,30)=mob_get_clothes_color(md->class_); //Add for player monster dye - Valaris
+ WBUFB(buf,45)=mob_get_sex(md->class_);
+ }
+
+ if (md->class_ >= 1285 && md->class_ <= 1287 && md->guild_id) { // Added guardian emblems [Valaris]
struct guild *g;
struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
if (gc && gc->guild_id > 0) {
@@ -999,7 +1019,7 @@ static int clif_mob0078(struct mob_data *md, unsigned char *buf)
WBUFB(buf,48)|=md->dir&0x0f;
WBUFB(buf,49)=5;
WBUFB(buf,50)=5;
- WBUFW(buf,52)=((level = battle_get_lv(&md->bl))>battle_config.max_lv)? battle_config.max_lv:level;
+ WBUFW(buf,52)=((level = status_get_lv(&md->bl))>battle_config.max_lv)? battle_config.max_lv:level;
return packet_len_table[0x78];
}
@@ -1017,27 +1037,27 @@ static int clif_mob007b(struct mob_data *md, unsigned char *buf) {
WBUFW(buf,0)=0x7b;
WBUFL(buf,2)=md->bl.id;
- WBUFW(buf,6)=battle_get_speed(&md->bl);
+ WBUFW(buf,6)=status_get_speed(&md->bl);
WBUFW(buf,8)=md->opt1;
WBUFW(buf,10)=md->opt2;
WBUFW(buf,12)=md->option;
- WBUFW(buf,14)=mob_get_viewclass(md->class);
- if ((mob_get_viewclass(md->class) < 24) || (mob_get_viewclass(md->class) > 4000)) {
- WBUFW(buf,12)|=mob_db[md->class].option;
- WBUFW(buf,16)=mob_get_hair(md->class);
- WBUFW(buf,18)=mob_get_weapon(md->class);
- WBUFW(buf,20)=mob_get_head_buttom(md->class);
+ WBUFW(buf,14)=mob_get_viewclass(md->class_);
+ if ((mob_get_viewclass(md->class_) < 24) || (mob_get_viewclass(md->class_) > 4000)) {
+ WBUFW(buf,12)|=mob_db[md->class_].option;
+ WBUFW(buf,16)=mob_get_hair(md->class_);
+ WBUFW(buf,18)=mob_get_weapon(md->class_);
+ WBUFW(buf,20)=mob_get_head_buttom(md->class_);
WBUFL(buf,22)=gettick();
- WBUFW(buf,26)=mob_get_shield(md->class);
- WBUFW(buf,28)=mob_get_head_top(md->class);
- WBUFW(buf,30)=mob_get_head_mid(md->class);
- WBUFW(buf,32)=mob_get_hair_color(md->class);
- WBUFW(buf,34)=mob_get_clothes_color(md->class); //Add for player monster dye - Valaris
- WBUFB(buf,49)=mob_get_sex(md->class);
+ WBUFW(buf,26)=mob_get_shield(md->class_);
+ WBUFW(buf,28)=mob_get_head_top(md->class_);
+ WBUFW(buf,30)=mob_get_head_mid(md->class_);
+ WBUFW(buf,32)=mob_get_hair_color(md->class_);
+ WBUFW(buf,34)=mob_get_clothes_color(md->class_); //Add for player monster dye - Valaris
+ WBUFB(buf,49)=mob_get_sex(md->class_);
} else
WBUFL(buf,22)=gettick();
- if(md->class >= 1285 && md->class <= 1287 && md->guild_id) { // Added guardian emblems [Valaris]
+ if(md->class_ >= 1285 && md->class_ <= 1287 && md->guild_id) { // Added guardian emblems [Valaris]
struct guild *g;
struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
if(gc && gc->guild_id > 0){
@@ -1052,7 +1072,7 @@ static int clif_mob007b(struct mob_data *md, unsigned char *buf) {
WBUFPOS2(buf,50,md->bl.x,md->bl.y,md->to_x,md->to_y);
WBUFB(buf,56)=5;
WBUFB(buf,57)=5;
- WBUFW(buf,58)=((level = battle_get_lv(&md->bl))>battle_config.max_lv)? battle_config.max_lv:level;
+ WBUFW(buf,58)=((level = status_get_lv(&md->bl))>battle_config.max_lv)? battle_config.max_lv:level;
return packet_len_table[0x7b];
}
@@ -1071,8 +1091,8 @@ static int clif_npc0078(struct npc_data *nd, unsigned char *buf) {
WBUFW(buf,0)=0x78;
WBUFL(buf,2)=nd->bl.id;
WBUFW(buf,6)=nd->speed;
- WBUFW(buf,14)=nd->class;
- if ((nd->class == 722) && (nd->u.scr.guild_id > 0) && ((g=guild_search(nd->u.scr.guild_id)) != NULL)) {
+ WBUFW(buf,14)=nd->class_;
+ if ((nd->class_ == 722) && (nd->u.scr.guild_id > 0) && ((g=guild_search(nd->u.scr.guild_id)) != NULL)) {
WBUFL(buf,22)=g->emblem_id;
WBUFL(buf,26)=g->guild_id;
}
@@ -1095,8 +1115,8 @@ static int clif_npc007b(struct npc_data *nd, unsigned char *buf) {
WBUFW(buf,0)=0x7b;
WBUFL(buf,2)=nd->bl.id;
WBUFW(buf,6)=nd->speed;
- WBUFW(buf,14)=nd->class;
- if ((nd->class == 722) && (nd->u.scr.guild_id > 0) && ((g=guild_search(nd->u.scr.guild_id)) != NULL)) {
+ WBUFW(buf,14)=nd->class_;
+ if ((nd->class_ == 722) && (nd->u.scr.guild_id > 0) && ((g=guild_search(nd->u.scr.guild_id)) != NULL)) {
WBUFL(buf,22)=g->emblem_id;
WBUFL(buf,26)=g->guild_id;
}
@@ -1123,18 +1143,18 @@ static int clif_pet0078(struct pet_data *pd, unsigned char *buf) {
WBUFW(buf,0)=0x78;
WBUFL(buf,2)=pd->bl.id;
WBUFW(buf,6)=pd->speed;
- WBUFW(buf,14)=mob_get_viewclass(pd->class);
- if((mob_get_viewclass(pd->class) < 24) || (mob_get_viewclass(pd->class) > 4000)) {
- WBUFW(buf,12)=mob_db[pd->class].option;
- WBUFW(buf,16)=mob_get_hair(pd->class);
- WBUFW(buf,18)=mob_get_weapon(pd->class);
- WBUFW(buf,20)=mob_get_head_buttom(pd->class);
- WBUFW(buf,22)=mob_get_shield(pd->class);
- WBUFW(buf,24)=mob_get_head_top(pd->class);
- WBUFW(buf,26)=mob_get_head_mid(pd->class);
- WBUFW(buf,28)=mob_get_hair_color(pd->class);
- WBUFW(buf,30)=mob_get_clothes_color(pd->class); //Add for player pet dye - Valaris
- WBUFB(buf,45)=mob_get_sex(pd->class);
+ WBUFW(buf,14)=mob_get_viewclass(pd->class_);
+ if((mob_get_viewclass(pd->class_) < 24) || (mob_get_viewclass(pd->class_) > 4000)) {
+ WBUFW(buf,12)=mob_db[pd->class_].option;
+ WBUFW(buf,16)=mob_get_hair(pd->class_);
+ WBUFW(buf,18)=mob_get_weapon(pd->class_);
+ WBUFW(buf,20)=mob_get_head_buttom(pd->class_);
+ WBUFW(buf,22)=mob_get_shield(pd->class_);
+ WBUFW(buf,24)=mob_get_head_top(pd->class_);
+ WBUFW(buf,26)=mob_get_head_mid(pd->class_);
+ WBUFW(buf,28)=mob_get_hair_color(pd->class_);
+ WBUFW(buf,30)=mob_get_clothes_color(pd->class_); //Add for player pet dye - Valaris
+ WBUFB(buf,45)=mob_get_sex(pd->class_);
} else {
WBUFW(buf,16)=0x14;
if((view = itemdb_viewid(pd->equip)) > 0)
@@ -1146,7 +1166,7 @@ static int clif_pet0078(struct pet_data *pd, unsigned char *buf) {
WBUFB(buf,48)|=pd->dir&0x0f;
WBUFB(buf,49)=0;
WBUFB(buf,50)=0;
- WBUFW(buf,52)=((level = battle_get_lv(&pd->bl))>battle_config.max_lv)? battle_config.max_lv:level;
+ WBUFW(buf,52)=((level = status_get_lv(&pd->bl))>battle_config.max_lv)? battle_config.max_lv:level;
return packet_len_table[0x78];
}
@@ -1165,19 +1185,19 @@ static int clif_pet007b(struct pet_data *pd, unsigned char *buf) {
WBUFW(buf,0)=0x7b;
WBUFL(buf,2)=pd->bl.id;
WBUFW(buf,6)=pd->speed;
- WBUFW(buf,14)=mob_get_viewclass(pd->class);
- if((mob_get_viewclass(pd->class) < 24) || (mob_get_viewclass(pd->class) > 4000)) {
- WBUFW(buf,12)=mob_db[pd->class].option;
- WBUFW(buf,16)=mob_get_hair(pd->class);
- WBUFW(buf,18)=mob_get_weapon(pd->class);
- WBUFW(buf,20)=mob_get_head_buttom(pd->class);
+ WBUFW(buf,14)=mob_get_viewclass(pd->class_);
+ if((mob_get_viewclass(pd->class_) < 24) || (mob_get_viewclass(pd->class_) > 4000)) {
+ WBUFW(buf,12)=mob_db[pd->class_].option;
+ WBUFW(buf,16)=mob_get_hair(pd->class_);
+ WBUFW(buf,18)=mob_get_weapon(pd->class_);
+ WBUFW(buf,20)=mob_get_head_buttom(pd->class_);
WBUFL(buf,22)=gettick();
- WBUFW(buf,26)=mob_get_shield(pd->class);
- WBUFW(buf,28)=mob_get_head_top(pd->class);
- WBUFW(buf,30)=mob_get_head_mid(pd->class);
- WBUFW(buf,32)=mob_get_hair_color(pd->class);
- WBUFW(buf,34)=mob_get_clothes_color(pd->class); //Add for player pet dye - Valaris
- WBUFB(buf,49)=mob_get_sex(pd->class);
+ WBUFW(buf,26)=mob_get_shield(pd->class_);
+ WBUFW(buf,28)=mob_get_head_top(pd->class_);
+ WBUFW(buf,30)=mob_get_head_mid(pd->class_);
+ WBUFW(buf,32)=mob_get_hair_color(pd->class_);
+ WBUFW(buf,34)=mob_get_clothes_color(pd->class_); //Add for player pet dye - Valaris
+ WBUFB(buf,49)=mob_get_sex(pd->class_);
} else {
WBUFW(buf,16)=0x14;
if ((view = itemdb_viewid(pd->equip)) > 0)
@@ -1189,7 +1209,7 @@ static int clif_pet007b(struct pet_data *pd, unsigned char *buf) {
WBUFPOS2(buf,50,pd->bl.x,pd->bl.y,pd->to_x,pd->to_y);
WBUFB(buf,56)=0;
WBUFB(buf,57)=0;
- WBUFW(buf,58)=((level = battle_get_lv(&pd->bl))>battle_config.max_lv)? battle_config.max_lv:level;
+ WBUFW(buf,58)=((level = status_get_lv(&pd->bl))>battle_config.max_lv)? battle_config.max_lv:level;
return packet_len_table[0x7b];
}
@@ -1281,11 +1301,11 @@ int clif_spawnpc(struct map_session_data *sd) {
clif_guild_emblem(sd,g);
} // end addition [Valaris]
- if (sd->status.class==13 || sd->status.class==21 || sd->status.class==4014 || sd->status.class==4022)
+ if (sd->status.class_==13 || sd->status.class_==21 || sd->status.class_==4014 || sd->status.class_==4022)
pc_setoption(sd,sd->status.option|0x0020); // [Valaris]
- if ((pc_isriding(sd) && pc_checkskill(sd,KN_RIDING)>0) && (sd->status.class==7 ||
- sd->status.class==14 || sd->status.class==4008 || sd->status.class==4015))
+ if ((pc_isriding(sd) && pc_checkskill(sd,KN_RIDING)>0) && (sd->status.class_==7 ||
+ sd->status.class_==14 || sd->status.class_==4008 || sd->status.class_==4015))
pc_setriding(sd); // update peco riders for people upgrading athena [Valaris]
@@ -1314,7 +1334,7 @@ int clif_spawnnpc(struct npc_data *nd)
nullpo_retr(0, nd);
- if(nd->class < 0 || nd->flag&1 || nd->class == INVISIBLE_CLASS)
+ if(nd->class_ < 0 || nd->flag&1 || nd->class_ == INVISIBLE_CLASS)
return 0;
memset(buf,0,packet_len_table[0x7c]);
@@ -1322,7 +1342,7 @@ int clif_spawnnpc(struct npc_data *nd)
WBUFW(buf,0)=0x7c;
WBUFL(buf,2)=nd->bl.id;
WBUFW(buf,6)=nd->speed;
- WBUFW(buf,20)=nd->class;
+ WBUFW(buf,20)=nd->class_;
WBUFPOS(buf,36,nd->bl.x,nd->bl.y);
clif_send(buf,packet_len_table[0x7c],&nd->bl,AREA);
@@ -1344,7 +1364,7 @@ int clif_spawnmob(struct mob_data *md)
nullpo_retr(0, md);
- if (mob_get_viewclass(md->class) > 23 ) {
+ if (mob_get_viewclass(md->class_) > 23) {
memset(buf,0,packet_len_table[0x7c]);
WBUFW(buf,0)=0x7c;
@@ -1353,7 +1373,7 @@ int clif_spawnmob(struct mob_data *md)
WBUFW(buf,8)=md->opt1;
WBUFW(buf,10)=md->opt2;
WBUFW(buf,12)=md->option;
- WBUFW(buf,20)=mob_get_viewclass(md->class);
+ WBUFW(buf,20)=mob_get_viewclass(md->class_);
WBUFPOS(buf,36,md->bl.x,md->bl.y);
clif_send(buf,packet_len_table[0x7c],&md->bl,AREA);
}
@@ -1361,8 +1381,8 @@ int clif_spawnmob(struct mob_data *md)
len = clif_mob0078(md,buf);
clif_send(buf,len,&md->bl,AREA);
- if (mob_get_equip(md->class) > 0) // mob equipment [Valaris]
- clif_mob_equip(md,mob_get_equip(md->class));
+ if (mob_get_equip(md->class_) > 0) // mob equipment [Valaris]
+ clif_mob_equip(md,mob_get_equip(md->class_));
if(md->size==2) // tiny/big mobs [Valaris]
clif_specialeffect(&md->bl,423,0);
@@ -1385,13 +1405,13 @@ int clif_spawnpet(struct pet_data *pd)
nullpo_retr(0, pd);
- if (mob_get_viewclass(pd->class) >= MAX_PC_CLASS) {
+ if (mob_get_viewclass(pd->class_) >= MAX_PC_CLASS) {
memset(buf,0,packet_len_table[0x7c]);
WBUFW(buf,0)=0x7c;
WBUFL(buf,2)=pd->bl.id;
WBUFW(buf,6)=pd->speed;
- WBUFW(buf,20)=mob_get_viewclass(pd->class);
+ WBUFW(buf,20)=mob_get_viewclass(pd->class_);
WBUFPOS(buf,36,pd->bl.x,pd->bl.y);
clif_send(buf,packet_len_table[0x7c],&pd->bl,AREA);
@@ -1517,6 +1537,7 @@ static int clif_waitclose(int tid, unsigned int tick, int id, int data) {
if (session[id])
session[id]->eof = 1;
+ close(id);
return 0;
}
@@ -1528,7 +1549,7 @@ void clif_setwaitclose(int fd) {
struct map_session_data *sd;
// if player is not already in the game (double connection probably)
- if ((sd = session[fd]->session_data) == NULL) {
+ if ((sd = (struct map_session_data*)session[fd]->session_data) == NULL) {
// limited timer, just to send information.
add_timer(gettick() + 1000, clif_waitclose, fd, 0);
} else
@@ -1584,7 +1605,7 @@ int clif_changemapserver(struct map_session_data *sd, char *mapname, int x, int
*------------------------------------------
*/
int clif_fixpos(struct block_list *bl) {
- char buf[16];
+ unsigned char buf[16];
nullpo_retr(0, bl);
@@ -1690,7 +1711,7 @@ int clif_scriptmes(struct map_session_data *sd, int npcid, char *mes) {
WFIFOW(fd,0)=0xb4;
WFIFOW(fd,2)=strlen(mes)+9;
WFIFOL(fd,4)=npcid;
- strcpy(WFIFOP(fd,8),mes);
+ strcpy((char*)WFIFOP(fd,8),mes);
WFIFOSET(fd,WFIFOW(fd,2));
return 0;
@@ -1743,7 +1764,7 @@ int clif_scriptmenu(struct map_session_data *sd, int npcid, char *mes) {
WFIFOW(fd,0)=0xb7;
WFIFOW(fd,2)=strlen(mes)+8;
WFIFOL(fd,4)=npcid;
- strcpy(WFIFOP(fd,8),mes);
+ strcpy((char*)WFIFOP(fd,8),mes);
WFIFOSET(fd,WFIFOW(fd,2));
return 0;
@@ -1816,7 +1837,7 @@ int clif_cutin(struct map_session_data *sd, char *image, int type) {
fd=sd->fd;
WFIFOW(fd,0)=0x1b3;
- memcpy(WFIFOP(fd,2),image,64);
+ strncpy((char*)WFIFOP(fd,2),image,64);
WFIFOB(fd,66)=type;
WFIFOSET(fd,packet_len_table[0x1b3]);
@@ -2067,9 +2088,9 @@ int clif_storageitemlist(struct map_session_data *sd,struct storage *stor)
#if PACKETVER < 5
WBUFW(buf,0)=0xa5;
for(i=0,n=0;i<MAX_STORAGE;i++){
- if(stor->storage[i].nameid<=0)
+ if(stor->storage_[i].nameid<=0)
continue;
- nullpo_retr(0, id = itemdb_search(stor->storage[i].nameid));
+ nullpo_retr(0, id = itemdb_search(stor->storage_[i].nameid));
if(itemdb_isequip2(id))
continue;
@@ -2077,10 +2098,10 @@ int clif_storageitemlist(struct map_session_data *sd,struct storage *stor)
if(id->view_id > 0)
WBUFW(buf,n*10+6)=id->view_id;
else
- WBUFW(buf,n*10+6)=stor->storage[i].nameid;
+ WBUFW(buf,n*10+6)=stor->storage_[i].nameid;
WBUFB(buf,n*10+8)=id->type;;
- WBUFB(buf,n*10+9)=stor->storage[i].identify;
- WBUFW(buf,n*10+10)=stor->storage[i].amount;
+ WBUFB(buf,n*10+9)=stor->storage_[i].identify;
+ WBUFW(buf,n*10+10)=stor->storage_[i].amount;
WBUFW(buf,n*10+12)=0;
n++;
}
@@ -2091,9 +2112,9 @@ int clif_storageitemlist(struct map_session_data *sd,struct storage *stor)
#else
WBUFW(buf,0)=0x1f0;
for(i=0,n=0;i<MAX_STORAGE;i++){
- if(stor->storage[i].nameid<=0)
+ if(stor->storage_[i].nameid<=0)
continue;
- nullpo_retr(0, id = itemdb_search(stor->storage[i].nameid));
+ nullpo_retr(0, id = itemdb_search(stor->storage_[i].nameid));
if(itemdb_isequip2(id))
continue;
@@ -2101,15 +2122,15 @@ int clif_storageitemlist(struct map_session_data *sd,struct storage *stor)
if(id->view_id > 0)
WBUFW(buf,n*18+6)=id->view_id;
else
- WBUFW(buf,n*18+6)=stor->storage[i].nameid;
+ WBUFW(buf,n*18+6)=stor->storage_[i].nameid;
WBUFB(buf,n*18+8)=id->type;;
- WBUFB(buf,n*18+9)=stor->storage[i].identify;
- WBUFW(buf,n*18+10)=stor->storage[i].amount;
+ WBUFB(buf,n*18+9)=stor->storage_[i].identify;
+ WBUFW(buf,n*18+10)=stor->storage_[i].amount;
WBUFW(buf,n*18+12)=0;
- WBUFW(buf,n*18+14)=stor->storage[i].card[0];
- WBUFW(buf,n*18+16)=stor->storage[i].card[1];
- WBUFW(buf,n*18+18)=stor->storage[i].card[2];
- WBUFW(buf,n*18+20)=stor->storage[i].card[3];
+ WBUFW(buf,n*18+14)=stor->storage_[i].card[0];
+ WBUFW(buf,n*18+16)=stor->storage_[i].card[1];
+ WBUFW(buf,n*18+18)=stor->storage_[i].card[2];
+ WBUFW(buf,n*18+20)=stor->storage_[i].card[3];
n++;
}
if(n){
@@ -2137,44 +2158,44 @@ int clif_storageequiplist(struct map_session_data *sd,struct storage *stor)
buf = WFIFOP(fd,0);
WBUFW(buf,0)=0xa6;
for(i=0,n=0;i<MAX_STORAGE;i++){
- if(stor->storage[i].nameid<=0)
+ if(stor->storage_[i].nameid<=0)
continue;
- nullpo_retr(0, id = itemdb_search(stor->storage[i].nameid));
+ nullpo_retr(0, id = itemdb_search(stor->storage_[i].nameid));
if(!itemdb_isequip2(id))
continue;
WBUFW(buf,n*20+4)=i+1;
if(id->view_id > 0)
WBUFW(buf,n*20+6)=id->view_id;
else
- WBUFW(buf,n*20+6)=stor->storage[i].nameid;
+ WBUFW(buf,n*20+6)=stor->storage_[i].nameid;
WBUFB(buf,n*20+8)=id->type;
- WBUFB(buf,n*20+9)=stor->storage[i].identify;
+ WBUFB(buf,n*20+9)=stor->storage_[i].identify;
WBUFW(buf,n*20+10)=id->equip;
- WBUFW(buf,n*20+12)=stor->storage[i].equip;
- WBUFB(buf,n*20+14)=stor->storage[i].attribute;
- WBUFB(buf,n*20+15)=stor->storage[i].refine;
- if(stor->storage[i].card[0]==0x00ff || stor->storage[i].card[0]==0x00fe || stor->storage[i].card[0]==(short)0xff00) {
- WBUFW(buf,n*20+16)=stor->storage[i].card[0];
- WBUFW(buf,n*20+18)=stor->storage[i].card[1];
- WBUFW(buf,n*20+20)=stor->storage[i].card[2];
- WBUFW(buf,n*20+22)=stor->storage[i].card[3];
+ WBUFW(buf,n*20+12)=stor->storage_[i].equip;
+ WBUFB(buf,n*20+14)=stor->storage_[i].attribute;
+ WBUFB(buf,n*20+15)=stor->storage_[i].refine;
+ if(stor->storage_[i].card[0]==0x00ff || stor->storage_[i].card[0]==0x00fe || stor->storage_[i].card[0]==(short)0xff00) {
+ WBUFW(buf,n*20+16)=stor->storage_[i].card[0];
+ WBUFW(buf,n*20+18)=stor->storage_[i].card[1];
+ WBUFW(buf,n*20+20)=stor->storage_[i].card[2];
+ WBUFW(buf,n*20+22)=stor->storage_[i].card[3];
} else {
- if(stor->storage[i].card[0] > 0 && (j=itemdb_viewid(stor->storage[i].card[0])) > 0)
+ if(stor->storage_[i].card[0] > 0 && (j=itemdb_viewid(stor->storage_[i].card[0])) > 0)
WBUFW(buf,n*20+16)=j;
else
- WBUFW(buf,n*20+16)=stor->storage[i].card[0];
- if(stor->storage[i].card[1] > 0 && (j=itemdb_viewid(stor->storage[i].card[1])) > 0)
+ WBUFW(buf,n*20+16)=stor->storage_[i].card[0];
+ if(stor->storage_[i].card[1] > 0 && (j=itemdb_viewid(stor->storage_[i].card[1])) > 0)
WBUFW(buf,n*20+18)=j;
else
- WBUFW(buf,n*20+18)=stor->storage[i].card[1];
- if(stor->storage[i].card[2] > 0 && (j=itemdb_viewid(stor->storage[i].card[2])) > 0)
+ WBUFW(buf,n*20+18)=stor->storage_[i].card[1];
+ if(stor->storage_[i].card[2] > 0 && (j=itemdb_viewid(stor->storage_[i].card[2])) > 0)
WBUFW(buf,n*20+20)=j;
else
- WBUFW(buf,n*20+20)=stor->storage[i].card[2];
- if(stor->storage[i].card[3] > 0 && (j=itemdb_viewid(stor->storage[i].card[3])) > 0)
+ WBUFW(buf,n*20+20)=stor->storage_[i].card[2];
+ if(stor->storage_[i].card[3] > 0 && (j=itemdb_viewid(stor->storage_[i].card[3])) > 0)
WBUFW(buf,n*20+22)=j;
else
- WBUFW(buf,n*20+22)=stor->storage[i].card[3];
+ WBUFW(buf,n*20+22)=stor->storage_[i].card[3];
}
n++;
}
@@ -2204,9 +2225,9 @@ int clif_guildstorageitemlist(struct map_session_data *sd,struct guild_storage *
#if PACKETVER < 5
WBUFW(buf,0)=0xa5;
for(i=0,n=0;i<MAX_GUILD_STORAGE;i++){
- if(stor->storage[i].nameid<=0)
+ if(stor->storage_[i].nameid<=0)
continue;
- nullpo_retr(0, id = itemdb_search(stor->storage[i].nameid));
+ nullpo_retr(0, id = itemdb_search(stor->storage_[i].nameid));
if(itemdb_isequip2(id))
continue;
@@ -2214,10 +2235,10 @@ int clif_guildstorageitemlist(struct map_session_data *sd,struct guild_storage *
if(id->view_id > 0)
WBUFW(buf,n*10+6)=id->view_id;
else
- WBUFW(buf,n*10+6)=stor->storage[i].nameid;
+ WBUFW(buf,n*10+6)=stor->storage_[i].nameid;
WBUFB(buf,n*10+8)=id->type;;
- WBUFB(buf,n*10+9)=stor->storage[i].identify;
- WBUFW(buf,n*10+10)=stor->storage[i].amount;
+ WBUFB(buf,n*10+9)=stor->storage_[i].identify;
+ WBUFW(buf,n*10+10)=stor->storage_[i].amount;
WBUFW(buf,n*10+12)=0;
n++;
}
@@ -2228,9 +2249,9 @@ int clif_guildstorageitemlist(struct map_session_data *sd,struct guild_storage *
#else
WBUFW(buf,0)=0x1f0;
for(i=0,n=0;i<MAX_GUILD_STORAGE;i++){
- if(stor->storage[i].nameid<=0)
+ if(stor->storage_[i].nameid<=0)
continue;
- nullpo_retr(0, id = itemdb_search(stor->storage[i].nameid));
+ nullpo_retr(0, id = itemdb_search(stor->storage_[i].nameid));
if(itemdb_isequip2(id))
continue;
@@ -2238,15 +2259,15 @@ int clif_guildstorageitemlist(struct map_session_data *sd,struct guild_storage *
if(id->view_id > 0)
WBUFW(buf,n*18+6)=id->view_id;
else
- WBUFW(buf,n*18+6)=stor->storage[i].nameid;
+ WBUFW(buf,n*18+6)=stor->storage_[i].nameid;
WBUFB(buf,n*18+8)=id->type;;
- WBUFB(buf,n*18+9)=stor->storage[i].identify;
- WBUFW(buf,n*18+10)=stor->storage[i].amount;
+ WBUFB(buf,n*18+9)=stor->storage_[i].identify;
+ WBUFW(buf,n*18+10)=stor->storage_[i].amount;
WBUFW(buf,n*18+12)=0;
- WBUFW(buf,n*18+14)=stor->storage[i].card[0];
- WBUFW(buf,n*18+16)=stor->storage[i].card[1];
- WBUFW(buf,n*18+18)=stor->storage[i].card[2];
- WBUFW(buf,n*18+20)=stor->storage[i].card[3];
+ WBUFW(buf,n*18+14)=stor->storage_[i].card[0];
+ WBUFW(buf,n*18+16)=stor->storage_[i].card[1];
+ WBUFW(buf,n*18+18)=stor->storage_[i].card[2];
+ WBUFW(buf,n*18+20)=stor->storage_[i].card[3];
n++;
}
if(n){
@@ -2274,44 +2295,44 @@ int clif_guildstorageequiplist(struct map_session_data *sd,struct guild_storage
WBUFW(buf,0)=0xa6;
for(i=0,n=0;i<MAX_GUILD_STORAGE;i++){
- if(stor->storage[i].nameid<=0)
+ if(stor->storage_[i].nameid<=0)
continue;
- nullpo_retr(0, id = itemdb_search(stor->storage[i].nameid));
+ nullpo_retr(0, id = itemdb_search(stor->storage_[i].nameid));
if(!itemdb_isequip2(id))
continue;
WBUFW(buf,n*20+4)=i+1;
if(id->view_id > 0)
WBUFW(buf,n*20+6)=id->view_id;
else
- WBUFW(buf,n*20+6)=stor->storage[i].nameid;
+ WBUFW(buf,n*20+6)=stor->storage_[i].nameid;
WBUFB(buf,n*20+8)=id->type;
- WBUFB(buf,n*20+9)=stor->storage[i].identify;
+ WBUFB(buf,n*20+9)=stor->storage_[i].identify;
WBUFW(buf,n*20+10)=id->equip;
- WBUFW(buf,n*20+12)=stor->storage[i].equip;
- WBUFB(buf,n*20+14)=stor->storage[i].attribute;
- WBUFB(buf,n*20+15)=stor->storage[i].refine;
- if(stor->storage[i].card[0]==0x00ff || stor->storage[i].card[0]==0x00fe || stor->storage[i].card[0]==(short)0xff00) {
- WBUFW(buf,n*20+16)=stor->storage[i].card[0];
- WBUFW(buf,n*20+18)=stor->storage[i].card[1];
- WBUFW(buf,n*20+20)=stor->storage[i].card[2];
- WBUFW(buf,n*20+22)=stor->storage[i].card[3];
+ WBUFW(buf,n*20+12)=stor->storage_[i].equip;
+ WBUFB(buf,n*20+14)=stor->storage_[i].attribute;
+ WBUFB(buf,n*20+15)=stor->storage_[i].refine;
+ if(stor->storage_[i].card[0]==0x00ff || stor->storage_[i].card[0]==0x00fe || stor->storage_[i].card[0]==(short)0xff00) {
+ WBUFW(buf,n*20+16)=stor->storage_[i].card[0];
+ WBUFW(buf,n*20+18)=stor->storage_[i].card[1];
+ WBUFW(buf,n*20+20)=stor->storage_[i].card[2];
+ WBUFW(buf,n*20+22)=stor->storage_[i].card[3];
} else {
- if(stor->storage[i].card[0] > 0 && (j=itemdb_viewid(stor->storage[i].card[0])) > 0)
+ if(stor->storage_[i].card[0] > 0 && (j=itemdb_viewid(stor->storage_[i].card[0])) > 0)
WBUFW(buf,n*20+16)=j;
else
- WBUFW(buf,n*20+16)=stor->storage[i].card[0];
- if(stor->storage[i].card[1] > 0 && (j=itemdb_viewid(stor->storage[i].card[1])) > 0)
+ WBUFW(buf,n*20+16)=stor->storage_[i].card[0];
+ if(stor->storage_[i].card[1] > 0 && (j=itemdb_viewid(stor->storage_[i].card[1])) > 0)
WBUFW(buf,n*20+18)=j;
else
- WBUFW(buf,n*20+18)=stor->storage[i].card[1];
- if(stor->storage[i].card[2] > 0 && (j=itemdb_viewid(stor->storage[i].card[2])) > 0)
+ WBUFW(buf,n*20+18)=stor->storage_[i].card[1];
+ if(stor->storage_[i].card[2] > 0 && (j=itemdb_viewid(stor->storage_[i].card[2])) > 0)
WBUFW(buf,n*20+20)=j;
else
- WBUFW(buf,n*20+20)=stor->storage[i].card[2];
- if(stor->storage[i].card[3] > 0 && (j=itemdb_viewid(stor->storage[i].card[3])) > 0)
+ WBUFW(buf,n*20+20)=stor->storage_[i].card[2];
+ if(stor->storage_[i].card[3] > 0 && (j=itemdb_viewid(stor->storage_[i].card[3])) > 0)
WBUFW(buf,n*20+22)=j;
else
- WBUFW(buf,n*20+22)=stor->storage[i].card[3];
+ WBUFW(buf,n*20+22)=stor->storage_[i].card[3];
}
n++;
}
@@ -2384,6 +2405,8 @@ int clif_updatestatus(struct map_session_data *sd,int type)
break;
case SP_HP:
WFIFOL(fd,4)=sd->status.hp;
+ if(battle_config.disp_hpmeter)
+ clif_hpmeter(sd);
break;
case SP_SP:
WFIFOL(fd,4)=sd->status.sp;
@@ -2828,7 +2851,7 @@ int clif_unequipitemack(struct map_session_data *sd,int n,int pos,int ok)
*/
int clif_misceffect(struct block_list* bl,int type)
{
- char buf[32];
+ unsigned char buf[32];
nullpo_retr(0, bl);
@@ -2862,7 +2885,7 @@ int clif_misceffect2(struct block_list *bl, int type) {
*/
int clif_changeoption(struct block_list* bl)
{
- char buf[32];
+ unsigned char buf[32];
short option;
struct status_change *sc_data;
static const int omask[]={ 0x10,0x20 };
@@ -2871,18 +2894,18 @@ int clif_changeoption(struct block_list* bl)
nullpo_retr(0, bl);
- option = *battle_get_option(bl);
- sc_data = battle_get_sc_data(bl);
+ option = *status_get_option(bl);
+ sc_data = status_get_sc_data(bl);
WBUFW(buf,0) = 0x119;
WBUFL(buf,2) = bl->id;
- WBUFW(buf,6) = *battle_get_opt1(bl);
- WBUFW(buf,8) = *battle_get_opt2(bl);
+ WBUFW(buf,6) = *status_get_opt1(bl);
+ WBUFW(buf,8) = *status_get_opt2(bl);
WBUFW(buf,10) = option;
WBUFB(buf,12) = 0; // ??
if(bl->type==BL_PC) { // disguises [Valaris]
- struct map_session_data *sd=((struct map_session_data *)bl);
+ struct map_session_data *sd=(struct map_session_data *)bl;
if(sd && sd->disguise > 23 && sd->disguise < 4001) {
clif_send(buf,packet_len_table[0x119],bl,AREA_WOS);
clif_spawnpc(sd);
@@ -2895,9 +2918,9 @@ int clif_changeoption(struct block_list* bl)
for(i=0;i<sizeof(omask)/sizeof(omask[0]);i++){
if( option&omask[i] ){
if( sc_data[scnum[i]].timer==-1)
- skill_status_change_start(bl,scnum[i],0,0,0,0,0,0);
+ status_change_start(bl,scnum[i],0,0,0,0,0,0);
} else {
- skill_status_change_end(bl,scnum[i],-1);
+ status_change_end(bl,scnum[i],-1);
}
}
@@ -2929,7 +2952,7 @@ int clif_useitemack(struct map_session_data *sd,int index,int amount,int ok)
WFIFOB(fd,6)=ok;
WFIFOSET(fd,packet_len_table[0xa8]);
#else
- char buf[32];
+ unsigned char buf[32];
WBUFW(buf,0)=0x1c8;
WBUFW(buf,2)=index+2;
@@ -2971,19 +2994,19 @@ int clif_createchat(struct map_session_data *sd,int fail)
*/
int clif_dispchat(struct chat_data *cd,int fd)
{
- char buf[128]; // 最大title(60バイト)+17
+ unsigned char buf[128]; // 最大title(60バイト)+17
if(cd==NULL || *cd->owner==NULL)
return 1;
WBUFW(buf,0)=0xd7;
- WBUFW(buf,2)=strlen(cd->title)+17;
+ WBUFW(buf,2)=strlen((const char*)cd->title)+17;
WBUFL(buf,4)=(*cd->owner)->id;
WBUFL(buf,8)=cd->bl.id;
WBUFW(buf,12)=cd->limit;
WBUFW(buf,14)=cd->users;
WBUFB(buf,16)=cd->pub;
- strcpy(WBUFP(buf,17),cd->title);
+ strcpy((char*)WBUFP(buf,17),(const char*)cd->title);
if(fd){
memcpy(WFIFOP(fd,0),buf,WBUFW(buf,2));
WFIFOSET(fd,WBUFW(buf,2));
@@ -3001,19 +3024,19 @@ int clif_dispchat(struct chat_data *cd,int fd)
*/
int clif_changechatstatus(struct chat_data *cd)
{
- char buf[128]; // 最大title(60バイト)+17
+ unsigned char buf[128]; // 最大title(60バイト)+17
if(cd==NULL || cd->usersd[0]==NULL)
return 1;
WBUFW(buf,0)=0xdf;
- WBUFW(buf,2)=strlen(cd->title)+17;
+ WBUFW(buf,2)=strlen((char*)cd->title)+17;
WBUFL(buf,4)=cd->usersd[0]->bl.id;
WBUFL(buf,8)=cd->bl.id;
WBUFW(buf,12)=cd->limit;
WBUFW(buf,14)=cd->users;
WBUFB(buf,16)=cd->pub;
- strcpy(WBUFP(buf,17),cd->title);
+ strcpy((char*)WBUFP(buf,17),(const char*)cd->title);
clif_send(buf,WBUFW(buf,2),&cd->usersd[0]->bl,CHAT);
return 0;
@@ -3025,7 +3048,7 @@ int clif_changechatstatus(struct chat_data *cd)
*/
int clif_clearchat(struct chat_data *cd,int fd)
{
- char buf[32];
+ unsigned char buf[32];
nullpo_retr(0, cd);
@@ -3091,7 +3114,7 @@ int clif_joinchatok(struct map_session_data *sd,struct chat_data* cd)
*/
int clif_addchat(struct chat_data* cd,struct map_session_data *sd)
{
- char buf[32];
+ unsigned char buf[32];
nullpo_retr(0, sd);
nullpo_retr(0, cd);
@@ -3110,7 +3133,7 @@ int clif_addchat(struct chat_data* cd,struct map_session_data *sd)
*/
int clif_changechatowner(struct chat_data* cd,struct map_session_data *sd)
{
- char buf[64];
+ unsigned char buf[64];
nullpo_retr(0, sd);
nullpo_retr(0, cd);
@@ -3133,7 +3156,7 @@ int clif_changechatowner(struct chat_data* cd,struct map_session_data *sd)
*/
int clif_leavechat(struct chat_data* cd,struct map_session_data *sd)
{
- char buf[32];
+ unsigned char buf[32];
nullpo_retr(0, sd);
nullpo_retr(0, cd);
@@ -3160,7 +3183,7 @@ int clif_traderequest(struct map_session_data *sd,char *name)
fd=sd->fd;
WFIFOW(fd,0)=0xe5;
- strcpy(WFIFOP(fd,2),name);
+ strcpy((char*)WFIFOP(fd,2),name);
WFIFOSET(fd,packet_len_table[0xe5]);
return 0;
@@ -3353,35 +3376,35 @@ int clif_storageitemadded(struct map_session_data *sd,struct storage *stor,int i
WFIFOW(fd,0) =0xf4; // Storage item added
WFIFOW(fd,2) =index+1; // index
WFIFOL(fd,4) =amount; // amount
- if((view = itemdb_viewid(stor->storage[index].nameid)) > 0)
+ if((view = itemdb_viewid(stor->storage_[index].nameid)) > 0)
WFIFOW(fd,8) =view;
else
- WFIFOW(fd,8) =stor->storage[index].nameid; // id
- WFIFOB(fd,10)=stor->storage[index].identify; //identify flag
- WFIFOB(fd,11)=stor->storage[index].attribute; // attribute
- WFIFOB(fd,12)=stor->storage[index].refine; //refine
- if(stor->storage[index].card[0]==0x00ff || stor->storage[index].card[0]==0x00fe || stor->storage[index].card[0]==(short)0xff00) {
- WFIFOW(fd,13)=stor->storage[index].card[0]; //card (4w)
- WFIFOW(fd,15)=stor->storage[index].card[1]; //card (4w)
- WFIFOW(fd,17)=stor->storage[index].card[2]; //card (4w)
- WFIFOW(fd,19)=stor->storage[index].card[3]; //card (4w)
+ WFIFOW(fd,8) =stor->storage_[index].nameid; // id
+ WFIFOB(fd,10)=stor->storage_[index].identify; //identify flag
+ WFIFOB(fd,11)=stor->storage_[index].attribute; // attribute
+ WFIFOB(fd,12)=stor->storage_[index].refine; //refine
+ if(stor->storage_[index].card[0]==0x00ff || stor->storage_[index].card[0]==0x00fe || stor->storage_[index].card[0]==(short)0xff00) {
+ WFIFOW(fd,13)=stor->storage_[index].card[0]; //card (4w)
+ WFIFOW(fd,15)=stor->storage_[index].card[1]; //card (4w)
+ WFIFOW(fd,17)=stor->storage_[index].card[2]; //card (4w)
+ WFIFOW(fd,19)=stor->storage_[index].card[3]; //card (4w)
} else {
- if(stor->storage[index].card[0] > 0 && (j=itemdb_viewid(stor->storage[index].card[0])) > 0)
+ if(stor->storage_[index].card[0] > 0 && (j=itemdb_viewid(stor->storage_[index].card[0])) > 0)
WFIFOW(fd,13)= j;
else
- WFIFOW(fd,13)= stor->storage[index].card[0];
- if(stor->storage[index].card[1] > 0 && (j=itemdb_viewid(stor->storage[index].card[1])) > 0)
+ WFIFOW(fd,13)= stor->storage_[index].card[0];
+ if(stor->storage_[index].card[1] > 0 && (j=itemdb_viewid(stor->storage_[index].card[1])) > 0)
WFIFOW(fd,15)= j;
else
- WFIFOW(fd,15)= stor->storage[index].card[1];
- if(stor->storage[index].card[2] > 0 && (j=itemdb_viewid(stor->storage[index].card[2])) > 0)
+ WFIFOW(fd,15)= stor->storage_[index].card[1];
+ if(stor->storage_[index].card[2] > 0 && (j=itemdb_viewid(stor->storage_[index].card[2])) > 0)
WFIFOW(fd,17)= j;
else
- WFIFOW(fd,17)= stor->storage[index].card[2];
- if(stor->storage[index].card[3] > 0 && (j=itemdb_viewid(stor->storage[index].card[3])) > 0)
+ WFIFOW(fd,17)= stor->storage_[index].card[2];
+ if(stor->storage_[index].card[3] > 0 && (j=itemdb_viewid(stor->storage_[index].card[3])) > 0)
WFIFOW(fd,19)= j;
else
- WFIFOW(fd,19)= stor->storage[index].card[3];
+ WFIFOW(fd,19)= stor->storage_[index].card[3];
}
WFIFOSET(fd,packet_len_table[0xf4]);
@@ -3423,35 +3446,35 @@ int clif_guildstorageitemadded(struct map_session_data *sd,struct guild_storage
WFIFOW(fd,0) =0xf4; // Storage item added
WFIFOW(fd,2) =index+1; // index
WFIFOL(fd,4) =amount; // amount
- if((view = itemdb_viewid(stor->storage[index].nameid)) > 0)
+ if((view = itemdb_viewid(stor->storage_[index].nameid)) > 0)
WFIFOW(fd,8) =view;
else
- WFIFOW(fd,8) =stor->storage[index].nameid; // id
- WFIFOB(fd,10)=stor->storage[index].identify; //identify flag
- WFIFOB(fd,11)=stor->storage[index].attribute; // attribute
- WFIFOB(fd,12)=stor->storage[index].refine; //refine
- if(stor->storage[index].card[0]==0x00ff || stor->storage[index].card[0]==0x00fe || stor->storage[index].card[0]==(short)0xff00) {
- WFIFOW(fd,13)=stor->storage[index].card[0]; //card (4w)
- WFIFOW(fd,15)=stor->storage[index].card[1]; //card (4w)
- WFIFOW(fd,17)=stor->storage[index].card[2]; //card (4w)
- WFIFOW(fd,19)=stor->storage[index].card[3]; //card (4w)
+ WFIFOW(fd,8) =stor->storage_[index].nameid; // id
+ WFIFOB(fd,10)=stor->storage_[index].identify; //identify flag
+ WFIFOB(fd,11)=stor->storage_[index].attribute; // attribute
+ WFIFOB(fd,12)=stor->storage_[index].refine; //refine
+ if(stor->storage_[index].card[0]==0x00ff || stor->storage_[index].card[0]==0x00fe || stor->storage_[index].card[0]==(short)0xff00) {
+ WFIFOW(fd,13)=stor->storage_[index].card[0]; //card (4w)
+ WFIFOW(fd,15)=stor->storage_[index].card[1]; //card (4w)
+ WFIFOW(fd,17)=stor->storage_[index].card[2]; //card (4w)
+ WFIFOW(fd,19)=stor->storage_[index].card[3]; //card (4w)
} else {
- if(stor->storage[index].card[0] > 0 && (j=itemdb_viewid(stor->storage[index].card[0])) > 0)
+ if(stor->storage_[index].card[0] > 0 && (j=itemdb_viewid(stor->storage_[index].card[0])) > 0)
WFIFOW(fd,13)= j;
else
- WFIFOW(fd,13)= stor->storage[index].card[0];
- if(stor->storage[index].card[1] > 0 && (j=itemdb_viewid(stor->storage[index].card[1])) > 0)
+ WFIFOW(fd,13)= stor->storage_[index].card[0];
+ if(stor->storage_[index].card[1] > 0 && (j=itemdb_viewid(stor->storage_[index].card[1])) > 0)
WFIFOW(fd,15)= j;
else
- WFIFOW(fd,15)= stor->storage[index].card[1];
- if(stor->storage[index].card[2] > 0 && (j=itemdb_viewid(stor->storage[index].card[2])) > 0)
+ WFIFOW(fd,15)= stor->storage_[index].card[1];
+ if(stor->storage_[index].card[2] > 0 && (j=itemdb_viewid(stor->storage_[index].card[2])) > 0)
WFIFOW(fd,17)= j;
else
- WFIFOW(fd,17)= stor->storage[index].card[2];
- if(stor->storage[index].card[3] > 0 && (j=itemdb_viewid(stor->storage[index].card[3])) > 0)
+ WFIFOW(fd,17)= stor->storage_[index].card[2];
+ if(stor->storage_[index].card[3] > 0 && (j=itemdb_viewid(stor->storage_[index].card[3])) > 0)
WFIFOW(fd,19)= j;
else
- WFIFOW(fd,19)= stor->storage[index].card[3];
+ WFIFOW(fd,19)= stor->storage_[index].card[3];
}
WFIFOSET(fd,packet_len_table[0xf4]);
@@ -3540,23 +3563,24 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds
* NPC表示
*------------------------------------------
*/
+//fixed by Valaris
void clif_getareachar_npc(struct map_session_data* sd,struct npc_data* nd)
{
int len;
-
nullpo_retv(sd);
nullpo_retv(nd);
-
- if(nd->class < 0 || nd->flag&1 || nd->class == INVISIBLE_CLASS)
+ if(nd->class_ < 0 || nd->flag&1 || nd->class_ == INVISIBLE_CLASS)
return;
-
+ if(nd->state.state == MS_WALK){
+ len = clif_npc007b(nd,WFIFOP(sd->fd,0));
+ WFIFOSET(sd->fd,len);
+ } else {
len = clif_npc0078(nd,WFIFOP(sd->fd,0));
WFIFOSET(sd->fd,len);
-
+ }
if(nd->chat_id){
clif_dispchat((struct chat_data*)map_id2bl(nd->chat_id),sd->fd);
}
-
}
/*==========================================
@@ -3573,8 +3597,8 @@ int clif_movemob(struct mob_data *md)
len = clif_mob007b(md,buf);
clif_send(buf,len,&md->bl,AREA);
- if(mob_get_equip(md->class) > 0) // mob equipment [Valaris]
- clif_mob_equip(md,mob_get_equip(md->class));
+ if(mob_get_equip(md->class_) > 0) // mob equipment [Valaris]
+ clif_mob_equip(md,mob_get_equip(md->class_));
if(md->size==2) // tiny/big mobs [Valaris]
clif_specialeffect(&md->bl,423,0);
@@ -3681,12 +3705,13 @@ int clif_damage(struct block_list *src,struct block_list *dst,unsigned int tick,
nullpo_retr(0, src);
nullpo_retr(0, dst);
- sc_data = battle_get_sc_data(dst);
+ sc_data = status_get_sc_data(dst);
if(type != 4 && dst->type == BL_PC && ((struct map_session_data *)dst)->special_state.infinite_endure)
type = 9;
if(sc_data) {
- if(type != 4 && sc_data[SC_ENDURE].timer != -1)
+ if(type != 4 && sc_data[SC_ENDURE].timer != -1 &&
+ (dst->type == BL_PC && !map[dst->m].flag.gvg))
type = 9;
if(sc_data[SC_HALLUCINATION].timer != -1) {
if(damage > 0)
@@ -3721,6 +3746,9 @@ void clif_getareachar_mob(struct map_session_data* sd,struct mob_data* md)
nullpo_retv(sd);
nullpo_retv(md);
+ if (session[sd->fd] == NULL)
+ return;
+
if(md->state.state == MS_WALK){
len = clif_mob007b(md,WFIFOP(sd->fd,0));
WFIFOSET(sd->fd,len);
@@ -3729,14 +3757,14 @@ void clif_getareachar_mob(struct map_session_data* sd,struct mob_data* md)
WFIFOSET(sd->fd,len);
}
- if(mob_get_equip(md->class) > 0) // mob equipment [Valaris]
- clif_mob_equip(md,mob_get_equip(md->class));
+ if(mob_get_equip(md->class_) > 0) // mob equipment [Valaris]
+ clif_mob_equip(md,mob_get_equip(md->class_));
if(md->size==2) // tiny/big mobs [Valaris]
clif_specialeffect(&md->bl,423,0);
else if(md->size==1)
clif_specialeffect(&md->bl,421,0);
-
+
}
@@ -3868,7 +3896,7 @@ int clif_clearchar_skillunit(struct skill_unit *unit,int fd)
WFIFOW(fd, 0)=0x120;
WFIFOL(fd, 2)=unit->bl.id;
WFIFOSET(fd,packet_len_table[0x120]);
- if(unit->group->skill_id == WZ_ICEWALL)
+ if(unit->group && unit->group->skill_id == WZ_ICEWALL)
clif_set0192(fd,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2);
return 0;
@@ -3880,7 +3908,7 @@ int clif_clearchar_skillunit(struct skill_unit *unit,int fd)
*/
int clif_01ac(struct block_list *bl)
{
- char buf[32];
+ unsigned char buf[32];
nullpo_retr(0, bl);
@@ -3904,6 +3932,9 @@ int clif_01ac(struct block_list *bl)
sd=va_arg(ap,struct map_session_data*);
+ if (sd == NULL || session[sd->fd] == NULL)
+ return 0;
+
switch(bl->type){
case BL_PC:
if(sd==(struct map_session_data*)bl)
@@ -3963,7 +3994,7 @@ int clif_pcoutsight(struct block_list *bl,va_list ap)
}
break;
case BL_NPC:
- if( ((struct npc_data *)bl)->class != INVISIBLE_CLASS )
+ if( ((struct npc_data *)bl)->class_ != INVISIBLE_CLASS )
clif_clearchar_id(bl->id,0,sd->fd);
break;
case BL_MOB:
@@ -4033,7 +4064,9 @@ int clif_moboutsight(struct block_list *bl,va_list ap)
nullpo_retr(0, ap);
nullpo_retr(0, md=va_arg(ap,struct mob_data*));
- if(bl->type==BL_PC && (sd = (struct map_session_data*) bl)){
+ if(bl->type==BL_PC
+ && ((sd = (struct map_session_data*) bl) != NULL)
+ && session[sd->fd] != NULL) {
clif_clearchar_id(md->bl.id,0,sd->fd);
}
@@ -4053,7 +4086,9 @@ int clif_mobinsight(struct block_list *bl,va_list ap)
nullpo_retr(0, ap);
md=va_arg(ap,struct mob_data*);
- if(bl->type==BL_PC && (sd = (struct map_session_data *)bl)){
+ if(bl->type==BL_PC
+ && ((sd = (struct map_session_data*) bl) != NULL)
+ && session[sd->fd] != NULL) {
clif_getareachar_mob(sd,md);
}
@@ -4073,7 +4108,9 @@ int clif_petoutsight(struct block_list *bl,va_list ap)
nullpo_retr(0, ap);
nullpo_retr(0, pd=va_arg(ap,struct pet_data*));
- if(bl->type==BL_PC && (sd = (struct map_session_data*) bl)){
+ if(bl->type==BL_PC
+ && ((sd = (struct map_session_data*) bl) != NULL)
+ && session[sd->fd] != NULL) {
clif_clearchar_id(pd->bl.id,0,sd->fd);
}
@@ -4090,7 +4127,9 @@ int clif_npcoutsight(struct block_list *bl,va_list ap)
nullpo_retr(0, ap);
nullpo_retr(0, nd=va_arg(ap,struct npc_data*));
- if(bl->type==BL_PC && (sd = (struct map_session_data*) bl)){
+ if(bl->type==BL_PC
+ && ((sd = (struct map_session_data*) bl) != NULL)
+ && session[sd->fd] != NULL) {
clif_clearchar_id(nd->bl.id,0,sd->fd);
}
@@ -4110,7 +4149,9 @@ int clif_petinsight(struct block_list *bl,va_list ap)
nullpo_retr(0, ap);
pd=va_arg(ap,struct pet_data*);
- if(bl->type==BL_PC && (sd = (struct map_session_data *)bl)){
+ if(bl->type==BL_PC
+ && ((sd = (struct map_session_data*) bl) != NULL)
+ && session[sd->fd] != NULL) {
clif_getareachar_pet(sd,pd);
}
@@ -4127,7 +4168,9 @@ int clif_npcinsight(struct block_list *bl,va_list ap)
nullpo_retr(0, ap);
nd=va_arg(ap,struct npc_data*);
- if(bl->type==BL_PC && (sd = (struct map_session_data *)bl)){
+ if(bl->type==BL_PC
+ && ((sd = (struct map_session_data*) bl) != NULL)
+ && session[sd->fd] != NULL) {
clif_getareachar_npc(sd,nd);
}
@@ -4159,14 +4202,14 @@ int clif_skillinfo(struct map_session_data *sd,int skillid,int type,int range)
if(range < 0) {
range = skill_get_range(id,sd->status.skill[skillid].lv);
if(range < 0)
- range = battle_get_range(&sd->bl) - (range + 1);
+ range = status_get_range(&sd->bl) - (range + 1);
WFIFOW(fd,12)= range;
} else
WFIFOW(fd,12)= range;
memset(WFIFOP(fd,14),0,24);
if(!(skill_get_inf2(id)&0x01) || battle_config.quest_skill_learn == 1 || (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill) )
//WFIFOB(fd,38)= (sd->status.skill[skillid].lv < skill_get_max(id) && sd->status.skill[skillid].flag ==0 )? 1:0;
- WFIFOB(fd,38)= (sd->status.skill[skillid].lv < skill_tree_get_max(id, sd->status.class) && sd->status.skill[skillid].flag ==0 )? 1:0;
+ WFIFOB(fd,38)= (sd->status.skill[skillid].lv < skill_tree_get_max(id, sd->status.class_) && sd->status.skill[skillid].flag ==0 )? 1:0;
else
WFIFOB(fd,38) = 0;
WFIFOSET(fd,packet_len_table[0x147]);
@@ -4196,12 +4239,12 @@ int clif_skillinfoblock(struct map_session_data *sd)
WFIFOW(fd,len+8) = skill_get_sp(id,sd->status.skill[i].lv);
range = skill_get_range(id,sd->status.skill[i].lv);
if(range < 0)
- range = battle_get_range(&sd->bl) - (range + 1);
+ range = status_get_range(&sd->bl) - (range + 1);
WFIFOW(fd,len+10)= range;
memset(WFIFOP(fd,len+12),0,24);
if(!(skill_get_inf2(id)&0x01) || battle_config.quest_skill_learn == 1 || (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill) )
//WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_get_max(id) && sd->status.skill[i].flag ==0 )? 1:0;
- WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_tree_get_max(id, sd->status.class) && sd->status.skill[i].flag ==0 )? 1:0;
+ WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_tree_get_max(id, sd->status.class_) && sd->status.skill[i].flag ==0 )? 1:0;
else
WFIFOB(fd,len+36) = 0;
len+=37;
@@ -4231,10 +4274,10 @@ int clif_skillup(struct map_session_data *sd,int skill_num)
WFIFOW(fd,6) = skill_get_sp(skill_num,sd->status.skill[skill_num].lv);
range = skill_get_range(skill_num,sd->status.skill[skill_num].lv);
if(range < 0)
- range = battle_get_range(&sd->bl) - (range + 1);
+ range = status_get_range(&sd->bl) - (range + 1);
WFIFOW(fd,8) = range;
//WFIFOB(fd,10) = (sd->status.skill[skill_num].lv < skill_get_max(sd->status.skill[skill_num].id)) ? 1 : 0;
- WFIFOB(fd,10) = (sd->status.skill[skill_num].lv < skill_tree_get_max(sd->status.skill[skill_num].id, sd->status.class)) ? 1 : 0;
+ WFIFOB(fd,10) = (sd->status.skill[skill_num].lv < skill_tree_get_max(sd->status.skill[skill_num].id, sd->status.class_)) ? 1 : 0;
WFIFOSET(fd,packet_len_table[0x10e]);
return 0;
@@ -4290,7 +4333,12 @@ int clif_skill_fail(struct map_session_data *sd,int skill_id,int type,int btype)
fd=sd->fd;
- if(type==0x4 && battle_config.display_delay_skill_fail==0){
+ // reset all variables [celest]
+ sd->skillx = sd->skilly = -1;
+ sd->skillid = sd->skilllv = -1;
+ sd->skillitem = sd->skillitemlv = -1;
+
+ if(type==0x4 && (battle_config.display_delay_skill_fail==0 || sd->nodelay)){
return 0;
}
@@ -4318,7 +4366,7 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,
nullpo_retr(0, src);
nullpo_retr(0, dst);
- sc_data = battle_get_sc_data(dst);
+ sc_data = status_get_sc_data(dst);
if(type != 5 && dst->type == BL_PC && ((struct map_session_data *)dst)->special_state.infinite_endure)
type = 9;
@@ -4373,7 +4421,7 @@ int clif_skill_damage2(struct block_list *src,struct block_list *dst,
nullpo_retr(0, src);
nullpo_retr(0, dst);
- sc_data = battle_get_sc_data(dst);
+ sc_data = status_get_sc_data(dst);
if(type != 5 && dst->type == BL_PC && ((struct map_session_data *)dst)->special_state.infinite_endure)
type = 9;
@@ -4542,10 +4590,10 @@ int clif_skill_warppoint(struct map_session_data *sd,int skill_num,
fd=sd->fd;
WFIFOW(fd,0)=0x11c;
WFIFOW(fd,2)=skill_num;
- memcpy(WFIFOP(fd, 4),map1,16);
- memcpy(WFIFOP(fd,20),map2,16);
- memcpy(WFIFOP(fd,36),map3,16);
- memcpy(WFIFOP(fd,52),map4,16);
+ strncpy((char*)WFIFOP(fd, 4),map1,16);
+ strncpy((char*)WFIFOP(fd,20),map2,16);
+ strncpy((char*)WFIFOP(fd,36),map3,16);
+ strncpy((char*)WFIFOP(fd,52),map4,16);
WFIFOSET(fd,packet_len_table[0x11c]);
return 0;
}
@@ -4598,14 +4646,14 @@ int clif_skill_estimation(struct map_session_data *sd,struct block_list *dst)
return 0;
WBUFW(buf, 0)=0x18c;
- WBUFW(buf, 2)=mob_get_viewclass(md->class);
+ WBUFW(buf, 2)=mob_get_viewclass(md->class_);
WBUFW(buf, 4)=md->level;
- WBUFW(buf, 6)=mob_db[md->class].size;
+ WBUFW(buf, 6)=mob_db[md->class_].size;
WBUFL(buf, 8)=md->hp;
- WBUFW(buf,12)=battle_get_def2(&md->bl);
- WBUFW(buf,14)=mob_db[md->class].race;
- WBUFW(buf,16)=battle_get_mdef2(&md->bl) - (mob_db[md->class].vit>>1);
- WBUFW(buf,18)=battle_get_elem_type(&md->bl);
+ WBUFW(buf,12)=status_get_def2(&md->bl);
+ WBUFW(buf,14)=mob_db[md->class_].race;
+ WBUFW(buf,16)=status_get_mdef2(&md->bl) - (mob_db[md->class_].vit>>1);
+ WBUFW(buf,18)=status_get_elem_type(&md->bl);
for(i=0;i<9;i++)
WBUFB(buf,20+i)= battle_attr_fix(100,i+1,md->def_ele);
@@ -4668,8 +4716,11 @@ int clif_status_change(struct block_list *bl,int type,int flag)
* Send message (modified by [Yor])
*------------------------------------------
*/
-int clif_displaymessage(const int fd, char* mes)
+int clif_displaymessage(const int fd, char* mes)
{
+ // invalid pointer?
+ nullpo_retr(-1, mes);
+
//Console [Wizputer]
if (fd == 0)
printf("\033[0;36mConsole: \033[0m\033[1m%s\033[0m\n", mes);
@@ -4691,13 +4742,13 @@ int clif_displaymessage(const int fd, char* mes)
* 天の声を送信する
*------------------------------------------
*/
-int clif_GMmessage(struct block_list *bl, char* mes, int len, int flag)
+int clif_GMmessage(struct block_list *bl, char* mes, int len, int flag)
{
unsigned char *buf;
int lp;
lp = (flag & 0x10) ? 8 : 4;
- buf = (unsigned char*)aCalloc(len + lp, sizeof(unsigned char));
+ buf = (unsigned char*)aCallocA(len + lp, sizeof(unsigned char));
WBUFW(buf,0) = 0x9a;
WBUFW(buf,2) = len + lp;
@@ -4710,12 +4761,33 @@ int clif_GMmessage(struct block_list *bl, char* mes, int len, int flag)
(flag == 3) ? SELF :
ALL_CLIENT);
- if(buf) free(buf);
+ if(buf) aFree(buf);
return 0;
}
/*==========================================
+ * グローバルメッセージ
+ *------------------------------------------
+ */
+void clif_GlobalMessage(struct block_list *bl,char *message)
+{
+ char buf[100];
+ int len,cmd=0x8d;
+
+ if(!bl || !message)
+ return;
+
+ len=strlen(message)+1;
+
+ WBUFW(buf,0)=cmd;
+ WBUFW(buf,2)=len+8;
+ WBUFL(buf,4)=bl->id;
+ strncpy((char *) WBUFP(buf,8),message,len);
+ clif_send((unsigned char *) buf,WBUFW(buf,2),bl,AREA_CHAT_WOC);
+}
+
+/*==========================================
* HPSP回復エフェクトを送信する
*------------------------------------------
*/
@@ -4787,12 +4859,13 @@ int clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type)
WFIFOL(sd->fd,10) = pvpnum;
WFIFOSET(sd->fd,packet_len_table[0x19a]);
} else {
- char buf[32];
+ unsigned char buf[32];
WBUFW(buf,0) = 0x19a;
WBUFL(buf,2) = sd->bl.id;
if(sd->status.option&0x46)
- WBUFL(buf,6) = -1;
+ // WTF? a -1 to an unsigned value...
+ WBUFL(buf,6) = 0xFFFFFFFF;
else
if(pvprank<=0)
pc_calc_pvprank(sd);
@@ -4814,7 +4887,7 @@ int clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type)
int clif_send0199(int map,int type)
{
struct block_list bl;
- char buf[16];
+ unsigned char buf[16];
bl.m = map;
WBUFW(buf,0)=0x199;
@@ -4845,6 +4918,8 @@ int clif_refine(int fd,struct map_session_data *sd,int fail,int index,int val)
*/
int clif_wis_message(int fd, char *nick, char *mes, int mes_len) // R 0097 <len>.w <nick>.24B <message>.?B
{
+// printf("clif_wis_message(%d, %s, %s)\n", fd, nick, mes);
+
WFIFOW(fd,0) = 0x97;
WFIFOW(fd,2) = mes_len + 24 + 4;
memcpy(WFIFOP(fd,4), nick, 24);
@@ -4858,7 +4933,7 @@ int clif_wis_message(int fd, char *nick, char *mes, int mes_len) // R 0097 <len>
*------------------------------------------
*/
int clif_wis_end(int fd, int flag) // R 0098 <type>.B: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-{
+{
WFIFOW(fd,0) = 0x98;
WFIFOW(fd,2) = flag;
WFIFOSET(fd,packet_len_table[0x98]);
@@ -5076,9 +5151,9 @@ int clif_item_skill(struct map_session_data *sd,int skillid,int skilllv,const ch
WFIFOW(fd,10)=skill_get_sp(skillid,skilllv);
range = skill_get_range(skillid,skilllv);
if(range < 0)
- range = battle_get_range(&sd->bl) - (range + 1);
+ range = status_get_range(&sd->bl) - (range + 1);
WFIFOW(fd,12)=range;
- memcpy(WFIFOP(fd,14),name,24);
+ strncpy((char*)WFIFOP(fd,14),name,24);
WFIFOB(fd,38)=0;
WFIFOSET(fd,packet_len_table[0x147]);
return 0;
@@ -5321,7 +5396,7 @@ int clif_showvendingboard(struct block_list* bl,char *message,int fd)
WBUFW(buf,0)=0x131;
WBUFL(buf,2)=bl->id;
- strncpy(WBUFP(buf,6),message,80);
+ strncpy((char*)WBUFP(buf,6),message,80);
if(fd){
memcpy(WFIFOP(fd,0),buf,packet_len_table[0x131]);
WFIFOSET(fd,packet_len_table[0x131]);
@@ -5535,6 +5610,8 @@ int clif_party_created(struct map_session_data *sd,int flag)
{
int fd;
+ // printf("clif_party_message(%s, %d, %s)\n", p->name, account_id, mes);
+
nullpo_retr(0, sd);
fd=sd->fd;
@@ -5748,6 +5825,70 @@ int clif_party_hp(struct party *p,struct map_session_data *sd)
return 0;
}
/*==========================================
+ * GMへ場所とHP通知
+ *------------------------------------------
+ */
+int clif_hpmeter(struct map_session_data *sd)
+{
+ struct map_session_data *md;
+ unsigned char buf[16];
+ unsigned char buf2[16];
+ int i;
+
+ nullpo_retr(0, sd);
+
+ WBUFW(buf,0)=0x107;
+ WBUFL(buf,2)=sd->bl.id;
+ WBUFW(buf,6)=sd->bl.x;
+ WBUFW(buf,8)=sd->bl.y;
+
+ for(i=0;i<fd_max;i++){
+ if(session[i] && (md = (struct map_session_data*)session[i]->session_data) && md->state.auth &&
+ md->bl.m == sd->bl.m && pc_isGM(md) && sd != md){
+ memcpy(WFIFOP(i,0),buf,packet_len_table[0x107]);
+ WFIFOSET(i,packet_len_table[0x107]);
+ }
+ }
+
+ WBUFW(buf2,0)=0x106;
+ WBUFL(buf2,2)=sd->status.account_id;
+ WBUFW(buf2,6)=(sd->status.hp > 0x7fff)? 0x7fff:sd->status.hp;
+ WBUFW(buf2,8)=(sd->status.max_hp > 0x7fff)? 0x7fff:sd->status.max_hp;
+ for(i=0;i<fd_max;i++){
+ if(session[i] && (md = (struct map_session_data*)session[i]->session_data) && md->state.auth &&
+ md->bl.m == sd->bl.m && pc_isGM(md) && sd != md){
+ memcpy(WFIFOP(i,0),buf2,packet_len_table[0x106]);
+ WFIFOSET(i,packet_len_table[0x106]);
+ }
+ }
+
+ return 0;
+}
+/*==================================================
+ * Update monster hp view if it has changed [Celest]
+ *--------------------------------------------------
+ */
+int clif_update_mobhp(struct mob_data *md)
+{
+ unsigned char buf[102];
+ char mobhp[50];
+
+ nullpo_retr(0, md);
+
+ WBUFW(buf,0) = 0x95;
+ WBUFL(buf,2) = md->bl.id;
+
+ memcpy(WBUFP(buf,6), md->name, 24);
+ sprintf(mobhp, "hp: %d/%d", md->hp, mob_db[md->class_].max_hp);
+ WBUFW(buf, 0) = 0x195;
+ memcpy(WBUFP(buf,30), mobhp, 24);
+ WBUFL(buf,54) = 0;
+ WBUFL(buf,78) = 0;
+ clif_send(buf,packet_len_table[0x195],&md->bl,AREA);
+
+ return 0;
+}
+/*==========================================
* パーティ場所移動(未使用)
*------------------------------------------
*/
@@ -5930,7 +6071,7 @@ int clif_pet_emotion(struct pet_data *pd,int param)
if(sd->petDB->talk_convert_class < 0)
return 0;
else if(sd->petDB->talk_convert_class > 0) {
- param -= (pd->class - 100)*100;
+ param -= (pd->class_ - 100)*100;
param += (sd->petDB->talk_convert_class - 100)*100;
}
}
@@ -6105,7 +6246,7 @@ int clif_combo_delay(struct block_list *bl,int wait)
*------------------------------------------
*/
int clif_bladestop(struct block_list *src,struct block_list *dst,
- int bool)
+ int _bool)
{
unsigned char buf[32];
@@ -6115,7 +6256,7 @@ int clif_bladestop(struct block_list *src,struct block_list *dst,
WBUFW(buf,0)=0x1d1;
WBUFL(buf,2)=src->id;
WBUFL(buf,6)=dst->id;
- WBUFL(buf,10)=bool;
+ WBUFL(buf,10)=_bool;
clif_send(buf,packet_len_table[0x1d1],src,AREA);
@@ -6129,7 +6270,7 @@ int clif_bladestop(struct block_list *src,struct block_list *dst,
int clif_changemapcell(int m,int x,int y,int cell_type,int type)
{
struct block_list bl;
- char buf[32];
+ unsigned char buf[32];
bl.m = m;
bl.x = x;
@@ -6247,6 +6388,8 @@ int clif_guild_memberlogin_notice(struct guild *g,int idx,int flag)
nullpo_retr(0, g);
+ // printf("clif_guild_message(%s, %d, %s)\n", g->name, account_id, mes);
+
WBUFW(buf, 0)=0x16d;
WBUFL(buf, 2)=g->member[idx].account_id;
WBUFL(buf, 6)=g->member[idx].char_id;
@@ -6317,32 +6460,32 @@ int clif_guild_basicinfo(struct map_session_data *sd)
if(g->guild_id == gc->guild_id) t++;
}
- if (t==1) memcpy(WFIFOP(fd,94),"One Castle",20);
- else if (t==2) memcpy(WFIFOP(fd,94),"Two Castles",20);
- else if (t==3) memcpy(WFIFOP(fd,94),"Three Castles",20);
- else if (t==4) memcpy(WFIFOP(fd,94),"Four Castles",20);
- else if (t==5) memcpy(WFIFOP(fd,94),"Five Castles",20);
- else if (t==6) memcpy(WFIFOP(fd,94),"Six Castles",20);
- else if (t==7) memcpy(WFIFOP(fd,94),"Seven Castles",20);
- else if (t==8) memcpy(WFIFOP(fd,94),"Eight Castles",20);
- else if (t==9) memcpy(WFIFOP(fd,94),"Nine Castles",20);
- else if (t==10) memcpy(WFIFOP(fd,94),"Ten Castles",20);
- else if (t==11) memcpy(WFIFOP(fd,94),"Eleven Castles",20);
- else if (t==12) memcpy(WFIFOP(fd,94),"Twelve Castles",20);
- else if (t==13) memcpy(WFIFOP(fd,94),"Thirteen Castles",20);
- else if (t==14) memcpy(WFIFOP(fd,94),"Fourteen Castles",20);
- else if (t==15) memcpy(WFIFOP(fd,94),"Fifteen Castles",20);
- else if (t==16) memcpy(WFIFOP(fd,94),"Sixteen Castles",20);
- else if (t==17) memcpy(WFIFOP(fd,94),"Seventeen Castles",20);
- else if (t==18) memcpy(WFIFOP(fd,94),"Eighteen Castles",20);
- else if (t==19) memcpy(WFIFOP(fd,94),"Nineteen Castles",20);
- else if (t==20) memcpy(WFIFOP(fd,94),"Twenty Castles",20);
- else if (t==21) memcpy(WFIFOP(fd,94),"Twenty One Castles",20);
- else if (t==22) memcpy(WFIFOP(fd,94),"Twenty Two Castles",20);
- else if (t==23) memcpy(WFIFOP(fd,94),"Twenty Three Castles",20);
- else if (t==24) memcpy(WFIFOP(fd,94),"Twenty Four Castles",20);
- else if (t==MAX_GUILDCASTLE) memcpy(WFIFOP(fd,94),"Total Domination",20);
- else memcpy(WFIFOP(fd,94),"None Taken",20);
+ if (t==1) strncpy((char*)WFIFOP(fd,94),"One Castle",20);
+ else if (t==2) strncpy((char*)WFIFOP(fd,94),"Two Castles",20);
+ else if (t==3) strncpy((char*)WFIFOP(fd,94),"Three Castles",20);
+ else if (t==4) strncpy((char*)WFIFOP(fd,94),"Four Castles",20);
+ else if (t==5) strncpy((char*)WFIFOP(fd,94),"Five Castles",20);
+ else if (t==6) strncpy((char*)WFIFOP(fd,94),"Six Castles",20);
+ else if (t==7) strncpy((char*)WFIFOP(fd,94),"Seven Castles",20);
+ else if (t==8) strncpy((char*)WFIFOP(fd,94),"Eight Castles",20);
+ else if (t==9) strncpy((char*)WFIFOP(fd,94),"Nine Castles",20);
+ else if (t==10) strncpy((char*)WFIFOP(fd,94),"Ten Castles",20);
+ else if (t==11) strncpy((char*)WFIFOP(fd,94),"Eleven Castles",20);
+ else if (t==12) strncpy((char*)WFIFOP(fd,94),"Twelve Castles",20);
+ else if (t==13) strncpy((char*)WFIFOP(fd,94),"Thirteen Castles",20);
+ else if (t==14) strncpy((char*)WFIFOP(fd,94),"Fourteen Castles",20);
+ else if (t==15) strncpy((char*)WFIFOP(fd,94),"Fifteen Castles",20);
+ else if (t==16) strncpy((char*)WFIFOP(fd,94),"Sixteen Castles",20);
+ else if (t==17) strncpy((char*)WFIFOP(fd,94),"Seventeen Castles",20);
+ else if (t==18) strncpy((char*)WFIFOP(fd,94),"Eighteen Castles",20);
+ else if (t==19) strncpy((char*)WFIFOP(fd,94),"Nineteen Castles",20);
+ else if (t==20) strncpy((char*)WFIFOP(fd,94),"Twenty Castles",20);
+ else if (t==21) strncpy((char*)WFIFOP(fd,94),"Twenty One Castles",20);
+ else if (t==22) strncpy((char*)WFIFOP(fd,94),"Twenty Two Castles",20);
+ else if (t==23) strncpy((char*)WFIFOP(fd,94),"Twenty Three Castles",20);
+ else if (t==24) strncpy((char*)WFIFOP(fd,94),"Twenty Four Castles",20);
+ else if (t==MAX_GUILDCASTLE) strncpy((char*)WFIFOP(fd,94),"Total Domination",20);
+ else strncpy((char*)WFIFOP(fd,94),"None Taken",20);
WFIFOSET(fd,packet_len_table[WFIFOW(fd,0)]);
clif_guild_emblem(sd,g); // Guild emblem vanish fix [Valaris]
@@ -6406,7 +6549,7 @@ int clif_guild_memberlist(struct map_session_data *sd)
WFIFOW(fd,c*104+12)=m->hair;
WFIFOW(fd,c*104+14)=m->hair_color;
WFIFOW(fd,c*104+16)=m->gender;
- WFIFOW(fd,c*104+18)=m->class;
+ WFIFOW(fd,c*104+18)=m->class_;
WFIFOW(fd,c*104+20)=m->lv;
WFIFOL(fd,c*104+22)=m->exp;
WFIFOL(fd,c*104+26)=m->online;
@@ -6564,35 +6707,51 @@ int clif_guild_skillinfo(struct map_session_data *sd)
memset(WFIFOP(fd,c*37+18),0,24);
if(g->skill[i].lv < guild_skill_get_max(id)) {
//Kafra and Guardian changed to require Approval [Sara]
- if (g->skill[i].id == GD_KAFRACONTACT && guild_checkskill(g,GD_APPROVAL) <= 0)
- up = 0;
- else if (g->skill[i].id == GD_GUARDIANRESEARCH && guild_checkskill(g,GD_APPROVAL) <= 0)
- up = 0;
- //Glory skill requirements -- Pretty sure correct [Sara]
- else if (g->skill[i].id == GD_LEADERSHIP && guild_checkskill(g,GD_GLORYGUILD) <= 0)
- up = 0;
- else if (g->skill[i].id == GD_GLORYWOUNDS && guild_checkskill(g,GD_GLORYGUILD) <= 0)
- up = 0;
- else if (g->skill[i].id == GD_SOULCOLD && guild_checkskill(g,GD_GLORYWOUNDS) <= 0)
- up = 0;
- else if (g->skill[i].id == GD_HAWKEYES && guild_checkskill(g,GD_LEADERSHIP) <= 0)
- up = 0;
- //Activated skill requirements -- Just guesses [Sara]
- else if (g->skill[i].id == GD_BATTLEORDER && guild_checkskill(g,GD_APPROVAL) <= 0)
- up = 0;
- else if (g->skill[i].id == GD_REGENERATION && guild_checkskill(g,GD_APPROVAL) <= 0)
- up = 0;
- else if (g->skill[i].id == GD_RESTORE && guild_checkskill(g,GD_REGENERATION) <= 0)
- up = 0;
- else if (g->skill[i].id == GD_EMERGENCYCALL && guild_checkskill(g,GD_APPROVAL) <= 0)
- up = 0;
- if (g->skill[i].id == GD_GUARDUP && guild_checkskill(g,GD_GUARDIANRESEARCH) <= 0)
- up = 0;
- //Unadded yet? Has extension description in kRO tables
- else if (g->skill[i].id == GD_DEVELOPMENT)
- up = 0;
- else
- up = 1;
+ switch (g->skill[i].id)
+ {
+ case GD_KAFRACONTACT:
+ case GD_GUARDIANRESEARCH:
+ case GD_GUARDUP:
+ case GD_DEVELOPMENT:
+ up = guild_checkskill(g,GD_APPROVAL) > 0;
+ break;
+ case GD_LEADERSHIP:
+ //Glory skill requirements -- Pretty sure correct [Sara]
+ up = (battle_config.require_glory_guild) ?
+ guild_checkskill(g,GD_GLORYGUILD) > 0 : 1;
+ // what skill does it need now that glory guild was removed? [celest]
+ break;
+ case GD_GLORYWOUNDS:
+ up = (battle_config.require_glory_guild) ?
+ guild_checkskill(g,GD_GLORYGUILD) > 0 : 1;
+ break;
+ case GD_SOULCOLD:
+ up = guild_checkskill(g,GD_GLORYWOUNDS) > 0;
+ break;
+ case GD_HAWKEYES:
+ up = guild_checkskill(g,GD_LEADERSHIP) > 0;
+ break;
+ case GD_BATTLEORDER:
+ up = guild_checkskill(g,GD_APPROVAL) > 0 &&
+ guild_checkskill(g,GD_EXTENSION) >= 2;
+ break;
+ case GD_REGENERATION:
+ up = guild_checkskill(g,GD_EXTENSION) >= 5 &&
+ guild_checkskill(g,GD_BATTLEORDER) > 0;
+ break;
+ case GD_RESTORE:
+ up = guild_checkskill(g,GD_REGENERATION) >= 2;
+ break;
+ case GD_EMERGENCYCALL:
+ up = guild_checkskill(g,GD_GUARDIANRESEARCH) > 0 &&
+ guild_checkskill(g,GD_REGENERATION) > 0;
+ break;
+ case GD_GLORYGUILD:
+ up = (battle_config.require_glory_guild) ? 1 : 0;
+ break;
+ default:
+ up = 1;
+ }
}
else {
up = 0;
@@ -6734,7 +6893,7 @@ int clif_guild_message(struct guild *g,int account_id,const char *mes,int len)
struct map_session_data *sd;
unsigned char *buf;
- buf = (unsigned char*)aCalloc(len + 4, sizeof(unsigned char));
+ buf = (unsigned char*)aCallocA(len + 4, sizeof(unsigned char));
WBUFW(buf, 0) = 0x17f;
WBUFW(buf, 2) = len + 4;
@@ -6743,7 +6902,7 @@ int clif_guild_message(struct guild *g,int account_id,const char *mes,int len)
if ((sd = guild_getavailablesd(g)) != NULL)
clif_send(buf, WBUFW(buf,2), &sd->bl, GUILD);
- if(buf) free(buf);
+ if(buf) aFree(buf);
return 0;
}
@@ -6937,10 +7096,34 @@ void clif_callpartner(struct map_session_data *sd)
}
*/
/*==========================================
+ * Adopt baby [Celest]
+ *------------------------------------------
+ */
+void clif_adopt_process(struct map_session_data *sd)
+{
+ int fd;
+ nullpo_retv(sd);
+
+ fd=sd->fd;
+ WFIFOW(fd,0)=0x1f8;
+ WFIFOSET(fd,packet_len_table[0x1f8]);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_ReqAdopt(int fd, struct map_session_data *sd) {
+ nullpo_retv(sd);
+
+ printf ("%d\n", RFIFOL(fd,2));
+}
+
+/*==========================================
* 座る
*------------------------------------------
*/
-void clif_sitting(struct map_session_data *sd)
+void clif_sitting(struct map_session_data *sd)
{
unsigned char buf[64];
@@ -6956,13 +7139,13 @@ void clif_sitting(struct map_session_data *sd)
*
*------------------------------------------
*/
-int clif_disp_onlyself(struct map_session_data *sd, char *mes, int len)
+int clif_disp_onlyself(struct map_session_data *sd, char *mes, int len)
{
unsigned char *buf;
nullpo_retr(0, sd);
- buf = (unsigned char*)aCalloc(len + 8, sizeof(unsigned char));
+ buf = (unsigned char*)aCallocA(len + 8, sizeof(unsigned char));
WBUFW(buf, 0) = 0x17f;
WBUFW(buf, 2) = len + 8;
@@ -6970,7 +7153,7 @@ int clif_disp_onlyself(struct map_session_data *sd, char *mes, int len)
clif_send(buf, WBUFW(buf,2), &sd->bl, SELF);
- if(buf) free(buf);
+ if(buf) aFree(buf);
return 0;
}
@@ -6980,7 +7163,7 @@ int clif_disp_onlyself(struct map_session_data *sd, char *mes, int len)
*------------------------------------------
*/
-int clif_GM_kickack(struct map_session_data *sd, int id)
+int clif_GM_kickack(struct map_session_data *sd, int id)
{
int fd;
@@ -7009,6 +7192,25 @@ int clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd,int ty
return 0;
}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+
+int clif_timedout(struct map_session_data *sd)
+{
+ nullpo_retr(0, sd);
+
+ sprintf(tmp_output,"%sCharacter with Account ID '"CL_WHITE"%d"CL_RESET"' timed out.\n", (pc_isGM(sd))?"GM ":"", sd->bl.id);
+ ShowInfo(tmp_output);
+ map_quit(sd);
+ clif_authfail_fd(sd->fd,3); // Even if player is not on we still send anyway
+ clif_setwaitclose(sd->fd); // Set session to EOF
+
+ return 0;
+}
+
/*==========================================
* Wis拒否許可応答
*------------------------------------------
@@ -7066,6 +7268,24 @@ void clif_soundeffect(struct map_session_data *sd,struct block_list *bl,char *na
return;
}
+
+int clif_soundeffectall(struct block_list *bl, char *name, int type)
+{
+ unsigned char buf[31];
+ memset(buf, 0, packet_len_table[0x1d3]);
+
+ nullpo_retr(0, bl);
+
+ WBUFW(buf,0)=0x1d3;
+ memcpy(WBUFP(buf,2), name, 24);
+ WBUFB(buf,26)=type;
+ WBUFL(buf,27)=0;
+ WBUFL(buf,31)=bl->id;
+ clif_send(buf, packet_len_table[0x1d3], bl, AREA);
+
+ return 0;
+}
+
// displaying special effects (npcs, weather, etc) [Valaris]
int clif_specialeffect(struct block_list *bl, int type, int flag) {
unsigned char buf[24];
@@ -7083,8 +7303,8 @@ int clif_specialeffect(struct block_list *bl, int type, int flag) {
struct map_session_data *pl_sd;
int i;
for(i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) != NULL &&
- pl_sd->state.auth &&
+ if (session[i] && (pl_sd = (struct map_session_data*)session[i]->session_data) != NULL &&
+ pl_sd->state.auth &&
(pc_isGM((struct map_session_data *)&bl) > pc_isGM((struct map_session_data *)&pl_sd->bl)))
clif_specialeffect(&pl_sd->bl, type, 1);
}
@@ -7093,7 +7313,7 @@ int clif_specialeffect(struct block_list *bl, int type, int flag) {
struct map_session_data *sd;
int i;
for(i = 0; i < fd_max; i++) {
- if (session[i] && (sd = session[i]->session_data) != NULL && sd->state.auth && sd->bl.m == bl->m)
+ if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) != NULL && sd->state.auth && sd->bl.m == bl->m)
clif_specialeffect(&sd->bl, type, 1);
}
}
@@ -7106,6 +7326,14 @@ int clif_specialeffect(struct block_list *bl, int type, int flag) {
return 0;
}
+
+// refresh the client's screen, getting rid of any effects
+int clif_refresh(struct map_session_data *sd) {
+ nullpo_retr(-1, sd);
+ clif_changemap(sd,sd->mapname,sd->bl.x,sd->bl.y);
+ return 0;
+}
+
// ------------
// clif_parse_*
// ------------
@@ -7114,10 +7342,10 @@ int clif_specialeffect(struct block_list *bl, int type, int flag) {
*
*------------------------------------------
*/
-void clif_parse_WantToConnection(int fd, struct map_session_data *sd)
+void clif_parse_WantToConnection(int fd, struct map_session_data *sd)
{
struct map_session_data *old_sd;
- int account_id; // account_id in the packet 0x72 or 0x7E
+ int cmd, account_id; // account_id in the packet 0x72 or 0x7E
if (sd) {
if (battle_config.error_log)
@@ -7125,8 +7353,14 @@ void clif_parse_WantToConnection(int fd, struct map_session_data *sd)
return;
}
+ cmd = RFIFOW(fd,0);
+
+ // packet DB
+ if (IS_PACKET_DB_VER(cmd)) {
+ //printf("Received bytes %d with packet 0x72.\n", RFIFOREST(fd));
+ account_id = RFIFOL(fd,packet_db[clif_config.packet_db_ver][clif_config.connect_cmd].pos[0]);
// 0x72
- if (RFIFOW(fd,0) == 0x72) {
+ } else if (cmd == 0x72) {
//printf("Received bytes %d with packet 0x72.\n", RFIFOREST(fd));
if (RFIFOREST(fd) >= 39 && (RFIFOB(fd,38) == 0 || RFIFOB(fd,38) == 1)) // 00 = Female, 01 = Male
account_id = RFIFOL(fd,12);
@@ -7135,14 +7369,14 @@ void clif_parse_WantToConnection(int fd, struct map_session_data *sd)
else // old packet version
account_id = RFIFOL(fd,2);
// 0x7E
- } else if (RFIFOW(fd,0) == 0x7E) {
+ } else if (cmd == 0x7E) {
//printf("Received bytes %d with packet 0x7E.\n", RFIFOREST(fd));
if (RFIFOREST(fd) >= 37 && (RFIFOB(fd,36) == 0 || RFIFOB(fd,36) == 1)) // 00 = Female, 01 = Male
account_id = RFIFOL(fd,9);
else
account_id = RFIFOL(fd,12);
// 0xF5
- } else {
+ } else if (cmd == 0xF5) {
//printf("Received bytes %d with packet 0xF5.\n", RFIFOREST(fd));
if (RFIFOREST(fd) >= 34 && (RFIFOB(fd,33) == 0 || RFIFOB(fd,33) == 1)) // 00 = Female, 01 = Male
account_id = RFIFOL(fd,7);
@@ -7150,20 +7384,37 @@ void clif_parse_WantToConnection(int fd, struct map_session_data *sd)
account_id = RFIFOL(fd,12);
else if (RFIFOREST(fd) >= 32 && (RFIFOB(fd,31) == 0 || RFIFOB(fd,31) == 1)) // 00 = Female, 01 = Male
account_id = RFIFOL(fd,10);
- else // 29 28 28
- account_id = RFIFOL(fd,5);
+ else { // 29 28 28 // search correct value
+ // if account id and char id of version 14
+ if (RFIFOL(fd,3) > 700000 && RFIFOL(fd,10) >= 150000 && RFIFOL(fd,10) < 5000000) // account id / char id (more than 5.000.000 characters?) [Yor]
+ account_id = RFIFOL(fd,3);
+ else
+ account_id = RFIFOL(fd,5);
+ }
+ // 0x9B
+ } else {
+ account_id = RFIFOL(fd,3);
}
// if same account already connected, we disconnect the 2 sessions
if ((old_sd = map_id2sd(account_id)) != NULL) {
- clif_authfail_fd(fd, 2); // same id
+ clif_authfail_fd(fd, 8); // still recognizes last connection
clif_authfail_fd(old_sd->fd, 2); // same id
+ if (sd != 0)
+ clif_setwaitclose(sd->fd); // Set session to EOF
} else {
- sd = session[fd]->session_data = (struct map_session_data*)aCalloc(1, sizeof(struct map_session_data));
+ sd = (struct map_session_data*)aCalloc(1, sizeof(struct map_session_data));
+ session[fd]->session_data = sd;
sd->fd = fd;
+ if (IS_PACKET_DB_VER(cmd)) {
+ sd->packet_ver = clif_config.packet_db_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ pc_setnewpc(sd, account_id, RFIFOL(fd,packet_db[clif_config.packet_db_ver][clif_config.connect_cmd].pos[1]),
+ RFIFOL(fd,packet_db[clif_config.packet_db_ver][clif_config.connect_cmd].pos[2]),
+ RFIFOL(fd,packet_db[clif_config.packet_db_ver][clif_config.connect_cmd].pos[3]),
+ RFIFOL(fd,packet_db[clif_config.packet_db_ver][clif_config.connect_cmd].pos[4]), fd);
// 0x72
- if (RFIFOW(fd,0) == 0x72) {
+ } else if (cmd == 0x72) {
if (RFIFOREST(fd) >= 39 && (RFIFOB(fd,38) == 0 || RFIFOB(fd,38) == 1)) { // 00 = Female, 01 = Male
sd->packet_ver = 7; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
pc_setnewpc(sd, account_id, RFIFOL(fd,22), RFIFOL(fd,30), RFIFOL(fd,34), RFIFOB(fd,38), fd);
@@ -7175,7 +7426,7 @@ void clif_parse_WantToConnection(int fd, struct map_session_data *sd)
pc_setnewpc(sd, account_id, RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOB(fd,18), fd);
}
// 0x7E
- } else if (RFIFOW(fd,0) == 0x7E) {
+ } else if (cmd == 0x7E) {
if (RFIFOREST(fd) >= 37 && (RFIFOB(fd,36) == 0 || RFIFOB(fd,36) == 1)) { // 00 = Female, 01 = Male
sd->packet_ver = 9; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
pc_setnewpc(sd, account_id, RFIFOL(fd,21), RFIFOL(fd,28), RFIFOL(fd,32), RFIFOB(fd,36), fd);
@@ -7184,7 +7435,7 @@ void clif_parse_WantToConnection(int fd, struct map_session_data *sd)
pc_setnewpc(sd, account_id, RFIFOL(fd,18), RFIFOL(fd,24), RFIFOL(fd,28), RFIFOB(fd,32), fd);
}
// 0xF5
- } else {
+ } else if (cmd == 0xF5) {
if (RFIFOREST(fd) >= 34 && (RFIFOB(fd,33) == 0 || RFIFOB(fd,33) == 1)) { // 00 = Female, 01 = Male
sd->packet_ver = 10; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
pc_setnewpc(sd, account_id, RFIFOL(fd,15), RFIFOL(fd,25), RFIFOL(fd,29), RFIFOB(fd,33), fd);
@@ -7195,9 +7446,19 @@ void clif_parse_WantToConnection(int fd, struct map_session_data *sd)
sd->packet_ver = 11; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
pc_setnewpc(sd, account_id, RFIFOL(fd,17), RFIFOL(fd,23), RFIFOL(fd,27), RFIFOB(fd,31), fd);
} else { // 29
- sd->packet_ver = 13; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- pc_setnewpc(sd, account_id, RFIFOL(fd,14), RFIFOL(fd,20), RFIFOL(fd,24), RFIFOB(fd,28), fd);
+ // if account id and char id of version 14
+ if (RFIFOL(fd,3) > 700000 && RFIFOL(fd,10) >= 150000 && RFIFOL(fd,10) < 5000000) { // account id / char id (more than 5.000.000 characters?)
+ sd->packet_ver = 15; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ pc_setnewpc(sd, account_id, RFIFOL(fd,10), RFIFOL(fd,20), RFIFOL(fd,24), RFIFOB(fd,28), fd);
+ } else {
+ sd->packet_ver = 13; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ pc_setnewpc(sd, account_id, RFIFOL(fd,14), RFIFOL(fd,20), RFIFOL(fd,24), RFIFOB(fd,28), fd);
+ }
}
+ // 0x9B
+ } else {
+ sd->packet_ver = 16; // 16: 10jan05
+ pc_setnewpc(sd, account_id, RFIFOL(fd,12), RFIFOL(fd,23), RFIFOL(fd,27), RFIFOB(fd,31), fd);
}
WFIFOL(fd,0) = sd->bl.id;
@@ -7299,10 +7560,10 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
if(sd->state.connect_new) {
sd->state.connect_new = 0;
- if(sd->status.class != sd->view_class)
+ if(sd->status.class_ != sd->view_class)
clif_changelook(&sd->bl,LOOK_BASE,sd->view_class);
if(sd->status.pet_id > 0 && sd->pd && sd->pet.intimate > 900)
- clif_pet_emotion(sd->pd,(sd->pd->class - 100)*100 + 50 + pet_hungry_val(sd));
+ clif_pet_emotion(sd->pd,(sd->pd->class_ - 100)*100 + 50 + pet_hungry_val(sd));
/* Stop players from spawning inside castles [Valaris] */
@@ -7326,16 +7587,17 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
if(battle_config.save_clothcolor==1 && sd->status.clothes_color > 0)
clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->status.clothes_color);
- if(sd->status.hp<sd->status.max_hp>>2 && pc_checkskill(sd,SM_AUTOBERSERK)>0 &&
+ //if(sd->status.hp<sd->status.max_hp>>2 && pc_checkskill(sd,SM_AUTOBERSERK)>0 &&
+ if(sd->status.hp<sd->status.max_hp>>2 && sd->sc_data[SC_AUTOBERSERK].timer != -1 &&
(sd->sc_data[SC_PROVOKE].timer==-1 || sd->sc_data[SC_PROVOKE].val2==0 ))
// オートバーサーク発動
- skill_status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0);
-
+ status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0);
+
// if(time(&timer) < ((weddingtime=pc_readglobalreg(sd,"PC_WEDDING_TIME")) + 3600))
-// skill_status_change_start(&sd->bl,SC_WEDDING,0,weddingtime,0,0,36000,0);
+// status_change_start(&sd->bl,SC_WEDDING,0,weddingtime,0,0,36000,0);
if(battle_config.muting_players && sd->status.manner < 0)
- skill_status_change_start(&sd->bl,SC_NOCHAT,0,0,0,0,0,0);
+ status_change_start(&sd->bl,SC_NOCHAT,0,0,0,0,0,0);
if (night_flag) {
if (battle_config.night_darkness_level > 0 && !map[sd->bl.m].flag.indoors)
@@ -7354,16 +7616,16 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
// option
clif_changeoption(&sd->bl);
if(sd->sc_data[SC_TRICKDEAD].timer != -1)
- skill_status_change_end(&sd->bl,SC_TRICKDEAD,-1);
+ status_change_end(&sd->bl,SC_TRICKDEAD,-1);
if(sd->sc_data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele))
- skill_status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1);
+ status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1);
if(sd->special_state.infinite_endure && sd->sc_data[SC_ENDURE].timer == -1)
- skill_status_change_start(&sd->bl,SC_ENDURE,10,1,0,0,0,0);
+ status_change_start(&sd->bl,SC_ENDURE,10,1,0,0,0,0);
for(i=0;i<MAX_INVENTORY;i++){
if(sd->status.inventory[i].equip && sd->status.inventory[i].equip & 0x0002 && sd->status.inventory[i].attribute==1)
- skill_status_change_start(&sd->bl,SC_BROKNWEAPON,0,0,0,0,0,0);
+ status_change_start(&sd->bl,SC_BROKNWEAPON,0,0,0,0,0,0);
if(sd->status.inventory[i].equip && sd->status.inventory[i].equip & 0x0010 && sd->status.inventory[i].attribute==1)
- skill_status_change_start(&sd->bl,SC_BROKNARMOR,0,0,0,0,0,0);
+ status_change_start(&sd->bl,SC_BROKNARMOR,0,0,0,0,0,0);
}
map_foreachinarea(clif_getareachar,sd->bl.m,sd->bl.x-AREA_SIZE,sd->bl.y-AREA_SIZE,sd->bl.x+AREA_SIZE,sd->bl.y+AREA_SIZE,0,sd);
@@ -7376,29 +7638,42 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
void clif_parse_TickSend(int fd, struct map_session_data *sd) {
nullpo_retv(sd);
- switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- case 8:
- sd->client_tick = RFIFOL(fd,6);
- break;
- case 9:
- sd->client_tick = RFIFOL(fd,9);
- break;
- case 10:
- sd->client_tick = RFIFOL(fd,7);
- break;
- case 11:
- sd->client_tick = RFIFOL(fd,10);
- break;
- case 12:
- sd->client_tick = RFIFOL(fd,6);
- break;
- case 13:
- sd->client_tick = RFIFOL(fd,5);
- break;
- default: // old version by default (and version 6 + 7)
- sd->client_tick = RFIFOL(fd,2);
- break;
+ if (USE_PACKET_DB(sd)) {
+ sd->client_tick=RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]);
+ } else {
+ switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ case 8:
+ sd->client_tick = RFIFOL(fd,6);
+ break;
+ case 9:
+ sd->client_tick = RFIFOL(fd,9);
+ break;
+ case 10:
+ sd->client_tick = RFIFOL(fd,7);
+ break;
+ case 11:
+ sd->client_tick = RFIFOL(fd,10);
+ break;
+ case 12:
+ sd->client_tick = RFIFOL(fd,6);
+ break;
+ case 13:
+ case 14:
+ sd->client_tick = RFIFOL(fd,5);
+ break;
+ case 15:
+ sd->client_tick = RFIFOL(fd,3);
+ break;
+ case 16:
+ sd->client_tick = RFIFOL(fd,5);
+ break;
+
+ default: // old version by default (and version 6 + 7)
+ sd->client_tick = RFIFOL(fd,2);
+ break;
+ }
}
+
sd->server_tick = gettick();
clif_servertick(sd);
}
@@ -7436,7 +7711,9 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) {
sd->sc_data[SC_TRICKDEAD].timer !=-1 || //死んだふり
sd->sc_data[SC_BLADESTOP].timer !=-1 || //白刃取り
sd->sc_data[SC_SPIDERWEB].timer !=-1 || //スパイダーウェッブ
- (sd->sc_data[SC_DANCING].timer !=-1 && sd->sc_data[SC_DANCING].val4)) //合奏スキル演奏中は動けない
+ (sd->sc_data[SC_DANCING].timer !=-1 && sd->sc_data[SC_DANCING].val4) || //合奏スキル演奏中は動けない
+ (sd->sc_data[SC_GOSPEL].timer !=-1 && sd->sc_data[SC_GOSPEL].val4 == BCT_SELF) || // cannot move while gospel is in effect
+ sd->sc_data[SC_CONFUSION].timer !=-1)
return;
if ((sd->status.option & 2) && pc_checkskill(sd, RG_TUNNELDRIVE) <= 0)
return;
@@ -7446,43 +7723,60 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) {
pc_stopattack(sd);
- switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- case 6:
- x = RFIFOB(fd,5) * 4 + (RFIFOB(fd,6) >> 6);
- y = ((RFIFOB(fd,6) & 0x3f) << 4) + (RFIFOB(fd,7) >> 4);
- break;
- case 7:
- x = RFIFOB(fd,6) * 4 + (RFIFOB(fd,7) >> 6);
- y = ((RFIFOB(fd,7) & 0x3f) << 4) + (RFIFOB(fd,8) >> 4);
- break;
- case 8:
- x = RFIFOB(fd,3) * 4 + (RFIFOB(fd,4) >> 6);
- y = ((RFIFOB(fd,4) & 0x3f) << 4) + (RFIFOB(fd,5) >> 4);
- break;
- case 9:
- x = RFIFOB(fd,12) * 4 + (RFIFOB(fd,13) >> 6);
- y = ((RFIFOB(fd,13) & 0x3f) << 4) + (RFIFOB(fd,14) >> 4);
- break;
- case 10:
- x = RFIFOB(fd,6) * 4 + (RFIFOB(fd,7) >> 6);
- y = ((RFIFOB(fd,7) & 0x3f) << 4) + (RFIFOB(fd,8) >> 4);
- break;
- case 11:
- x = RFIFOB(fd,11) * 4 + (RFIFOB(fd,12) >> 6);
- y = ((RFIFOB(fd,12) & 0x3f) << 4) + (RFIFOB(fd,13) >> 4);
- break;
- case 12:
- x = RFIFOB(fd,3) * 4 + (RFIFOB(fd,4) >> 6);
- y = ((RFIFOB(fd,4) & 0x3f) << 4) + (RFIFOB(fd,5) >> 4);
- break;
- case 13:
- x = RFIFOB(fd,3) * 4 + (RFIFOB(fd,4) >> 6);
- y = ((RFIFOB(fd,4) & 0x3f) << 4) + (RFIFOB(fd,5) >> 4);
- break;
- default: // old version by default
- x = RFIFOB(fd,2) * 4 + (RFIFOB(fd,3) >> 6);
- y = ((RFIFOB(fd,3) & 0x3f) << 4) + (RFIFOB(fd,4) >> 4);
- break;
+ if (USE_PACKET_DB(sd)) {
+ int cmd = RFIFOW(fd,0);
+ x = RFIFOB(fd,packet_db[clif_config.packet_db_ver][cmd].pos[0]) * 4 +
+ (RFIFOB(fd,packet_db[clif_config.packet_db_ver][cmd].pos[0] + 1) >> 6);
+ y = ((RFIFOB(fd,packet_db[clif_config.packet_db_ver][cmd].pos[0]+1) & 0x3f) << 4) +
+ (RFIFOB(fd,packet_db[clif_config.packet_db_ver][cmd].pos[0] + 2) >> 4);
+ } else {
+ switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ case 6:
+ x = RFIFOB(fd,5) * 4 + (RFIFOB(fd,6) >> 6);
+ y = ((RFIFOB(fd,6) & 0x3f) << 4) + (RFIFOB(fd,7) >> 4);
+ break;
+ case 7:
+ x = RFIFOB(fd,6) * 4 + (RFIFOB(fd,7) >> 6);
+ y = ((RFIFOB(fd,7) & 0x3f) << 4) + (RFIFOB(fd,8) >> 4);
+ break;
+ case 8:
+ x = RFIFOB(fd,3) * 4 + (RFIFOB(fd,4) >> 6);
+ y = ((RFIFOB(fd,4) & 0x3f) << 4) + (RFIFOB(fd,5) >> 4);
+ break;
+ case 9:
+ x = RFIFOB(fd,12) * 4 + (RFIFOB(fd,13) >> 6);
+ y = ((RFIFOB(fd,13) & 0x3f) << 4) + (RFIFOB(fd,14) >> 4);
+ break;
+ case 10:
+ x = RFIFOB(fd,6) * 4 + (RFIFOB(fd,7) >> 6);
+ y = ((RFIFOB(fd,7) & 0x3f) << 4) + (RFIFOB(fd,8) >> 4);
+ break;
+ case 11:
+ x = RFIFOB(fd,11) * 4 + (RFIFOB(fd,12) >> 6);
+ y = ((RFIFOB(fd,12) & 0x3f) << 4) + (RFIFOB(fd,13) >> 4);
+ break;
+ case 12:
+ x = RFIFOB(fd,3) * 4 + (RFIFOB(fd,4) >> 6);
+ y = ((RFIFOB(fd,4) & 0x3f) << 4) + (RFIFOB(fd,5) >> 4);
+ break;
+ case 13:
+ case 14:
+ x = RFIFOB(fd,3) * 4 + (RFIFOB(fd,4) >> 6);
+ y = ((RFIFOB(fd,4) & 0x3f) << 4) + (RFIFOB(fd,5) >> 4);
+ break;
+ case 15:
+ x = RFIFOB(fd,4) * 4 + (RFIFOB(fd,5) >> 6);
+ y = ((RFIFOB(fd,5) & 0x3f) << 4) + (RFIFOB(fd,6) >> 4);
+ break;
+ case 16:
+ x = RFIFOB(fd,10) * 4 + (RFIFOB(fd,11) >> 6);
+ y = ((RFIFOB(fd,11) & 0x3f) << 4) + (RFIFOB(fd,12) >> 4);
+ break;
+ default: // old version by default
+ x = RFIFOB(fd,2) * 4 + (RFIFOB(fd,3) >> 6);
+ y = ((RFIFOB(fd,3) & 0x3f) << 4) + (RFIFOB(fd,4) >> 4);
+ break;
+ }
}
pc_walktoxy(sd, x, y);
@@ -7527,28 +7821,39 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) {
struct block_list *bl;
int account_id;
- switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- case 8:
- account_id = RFIFOL(fd,11);
- break;
- case 9:
- account_id = RFIFOL(fd,8);
- break;
- case 10:
- account_id = RFIFOL(fd,10);
- break;
- case 11:
- account_id = RFIFOL(fd,6);
- break;
- case 12:
- account_id = RFIFOL(fd,11);
- break;
- case 13:
- account_id = RFIFOL(fd,6);
- break;
- default: // old version by default (+ packet version 6 and 7)
- account_id = RFIFOL(fd,2);
- break;
+ if (USE_PACKET_DB(sd)) {
+ account_id = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]);
+ } else {
+ switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ case 8:
+ account_id = RFIFOL(fd,11);
+ break;
+ case 9:
+ account_id = RFIFOL(fd,8);
+ break;
+ case 10:
+ account_id = RFIFOL(fd,10);
+ break;
+ case 11:
+ account_id = RFIFOL(fd,6);
+ break;
+ case 12:
+ account_id = RFIFOL(fd,11);
+ break;
+ case 13:
+ case 14:
+ account_id = RFIFOL(fd,6);
+ break;
+ case 15:
+ account_id = RFIFOL(fd,9);
+ break;
+ case 16:
+ account_id = RFIFOL(fd,4);
+ break;
+ default: // old version by default (+ packet version 6 and 7)
+ account_id = RFIFOL(fd,2);
+ break;
+ }
}
bl = map_id2bl(account_id);
if (bl == NULL)
@@ -7606,7 +7911,7 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) {
nullpo_retv(md);
memcpy(WFIFOP(fd,6), md->name, 24);
- if (md->class >= 1285 && md->class <= 1288 && md->guild_id) {
+ if (md->class_ >= 1285 && md->class_ <= 1288 && md->guild_id) {
struct guild *g;
struct guild_castle *gc = guild_mapname2gc(map[md->bl.m].name);
if (gc && gc->guild_id > 0 && (g = guild_search(gc->guild_id)) != NULL) {
@@ -7620,7 +7925,7 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) {
}
} else if (battle_config.show_mob_hp == 1) {
char mobhp[50];
- sprintf(mobhp, "hp: %d/%d", md->hp, mob_db[md->class].max_hp);
+ sprintf(mobhp, "hp: %d/%d", md->hp, mob_db[md->class_].max_hp);
WFIFOW(fd, 0) = 0x195;
memcpy(WFIFOP(fd,30), mobhp, 24);
WFIFOB(fd,54) = 0;
@@ -7644,42 +7949,47 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) {
*/
void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) { // S 008c <len>.w <str>.?B
char *message;
- char *buf;
+ unsigned char *buf;
nullpo_retv(sd);
- if (is_charcommand(fd, sd, RFIFOP(fd,4),0)!= CharCommand_None) return;
- if ((is_atcommand(fd, sd, RFIFOP(fd,4), 0) != AtCommand_None) ||
- (sd->sc_data &&
+ if ((is_atcommand(fd, sd, (char*)RFIFOP(fd,4), 0) != AtCommand_None) ||
+ (is_charcommand(fd, sd, (char*)RFIFOP(fd,4),0)!= CharCommand_None) ||
+ (sd->sc_data &&
(sd->sc_data[SC_BERSERK].timer != -1 || //バーサーク時は会話も不可
sd->sc_data[SC_NOCHAT].timer != -1 ))) //チャット禁止
return;
- message = (char*)aCalloc(RFIFOW(fd,2) + 128, sizeof(char));
- buf = (char*)aCalloc(RFIFOW(fd,2) + 4, sizeof(char));
+ message = (char*)aCallocA(RFIFOW(fd,2) + 128, sizeof(char));
+ buf = (unsigned char*)aCallocA(RFIFOW(fd,2) + 4, sizeof(char));
//printf("clif_parse_GlobalMessage: message: '%s'.\n", RFIFOP(fd,4));
- if (strncmp(RFIFOP(fd,4), sd->status.name, strlen(sd->status.name)) != 0) {
+ if (strncmp((char*)RFIFOP(fd,4), sd->status.name, strlen(sd->status.name)) != 0) {
printf("Hack on global message: character '%s' (account: %d), use an other name to send a (normal) message.\n", sd->status.name, sd->status.account_id);
// information is sended to all online GM
- sprintf(message, "Hack on global message (normal message): character '%s' (account: %d) uses an other name.", sd->status.name, sd->status.account_id);
- intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message, strlen(message) + 1);
- if (strlen(RFIFOP(fd,4)) == 0)
+ sprintf(message, "Hack on global message (normal message): character '%s' (account: %d) uses another name.", sd->status.name, sd->status.account_id);
+ intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message);
+ if (strlen((char*)RFIFOP(fd,4)) == 0)
strcpy(message, " This player sends a void name and a void message.");
else
sprintf(message, " This player sends (name:message): '%s'.", RFIFOP(fd,4));
- intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message, strlen(message) + 1);
+ intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message);
// message about the ban
if (battle_config.ban_spoof_namer > 0)
sprintf(message, " This player has been banned for %d minute(s).", battle_config.ban_spoof_namer);
else
sprintf(message, " This player hasn't been banned (Ban option is disabled).");
- intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message, strlen(message) + 1);
+ intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message);
// if we ban people
if (battle_config.ban_spoof_namer > 0) {
chrif_char_ask_name(-1, sd->status.name, 2, 0, 0, 0, 0, battle_config.ban_spoof_namer, 0); // type: 2 - ban (year, month, day, hour, minute, second)
clif_setwaitclose(fd); // forced to disconnect because of the hack
+
+ if(message) aFree(message);
+ if(buf) aFree(buf);
+
+ return;
}
// but for the hacker, we display on his screen (he see/look no difference).
} else {
@@ -7696,8 +8006,37 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) { // S 008c <
WFIFOW(fd,0) = 0x8e;
WFIFOSET(fd, WFIFOW(fd,2));
- if(message) free(message);
- if(buf) free(buf);
+#ifdef PCRE_SUPPORT
+ map_foreachinarea(npc_chat_sub, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_NPC, RFIFOP(fd,4), strlen(RFIFOP(fd,4)), &sd->bl);
+#endif
+
+ // Celest
+ if (pc_calc_base_job2 (sd->status.class_) == 23 ) {
+ int next = pc_nextbaseexp(sd)>0 ? pc_nextbaseexp(sd) : sd->status.base_exp;
+ if (next > 0 && (sd->status.base_exp*100/next)%10 == 0) {
+ estr_lower((char*)RFIFOP(fd,4));
+ if (sd->state.snovice_flag == 0 && strstr((char*)RFIFOP(fd,4), msg_txt(504)))
+ sd->state.snovice_flag = 1;
+ else if (sd->state.snovice_flag == 1) {
+ sprintf(message, msg_txt(505), sd->status.name);
+ estr_lower(message);
+ if (strstr((char*)RFIFOP(fd,4), message))
+ sd->state.snovice_flag = 2;
+ }
+ else if (sd->state.snovice_flag == 2 && strstr((char*)RFIFOP(fd,4), msg_txt(506)))
+ sd->state.snovice_flag = 3;
+ else if (sd->state.snovice_flag == 3) {
+ int i;
+ status_change_start(&sd->bl,SkillStatusChangeTable[MO_EXPLOSIONSPIRITS],1,0,0,0,skill_get_time(MO_EXPLOSIONSPIRITS,1),0 );
+ for(i=0;i<5;i++)
+ pc_addspiritball(sd,skill_get_time(MO_CALLSPIRITS,1),5);
+ sd->state.snovice_flag = 0;
+ }
+ }
+ }
+
+ if(message) aFree(message);
+ if(buf) aFree(buf);
return;
}
@@ -7714,7 +8053,7 @@ int clif_message(struct block_list *bl, char* msg)
WBUFL(buf, 4) = bl->id;
memcpy(WBUFP(buf, 8), msg, msg_len);
- clif_send(buf, WBUFW(buf,2), bl, AREA);
+ clif_send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); // by Gengar
return 0;
}
@@ -7725,17 +8064,20 @@ int clif_message(struct block_list *bl, char* msg)
*/
void clif_parse_MapMove(int fd, struct map_session_data *sd) {
// /m /mapmove (as @rura GM command)
- char output[100];
+ char output[30]; // 17+4+4=26, 30 max.
char map_name[17];
nullpo_retv(sd);
- memset(output, '\0', sizeof(output));
- memset(map_name, '\0', sizeof(map_name));
+// not needed at all as far as sprintf is used // [Ilpalazzo-sama]
+// memset(output, '\0', sizeof(output));
+// not needed -- map_name[16]='\0'; will do
+// memset(map_name, '\0', sizeof(map_name));
if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) &&
(pc_isGM(sd) >= get_atcommand_level(AtCommand_MapMove))) {
memcpy(map_name, RFIFOP(fd,2), 16);
+ map_name[16]='\0';
sprintf(output, "%s %d %d", map_name, RFIFOW(fd,18), RFIFOW(fd,20));
atcommand_rura(fd, sd, "@rura", output);
}
@@ -7747,58 +8089,89 @@ void clif_parse_MapMove(int fd, struct map_session_data *sd) {
*
*------------------------------------------
*/
-void clif_parse_ChangeDir(int fd, struct map_session_data *sd) {
+void clif_changed_dir(struct block_list *bl) {
unsigned char buf[64];
+ struct map_session_data *sd = NULL;
+
+ if (bl->type == BL_PC)
+ nullpo_retv (sd=(struct map_session_data *)bl);
+
+ WBUFW(buf,0) = 0x9c;
+ WBUFL(buf,2) = bl->id;
+ if (sd)
+ WBUFW(buf,6) = sd->head_dir;
+ WBUFB(buf,8) = status_get_dir(bl);
+ if (sd && sd->disguise > 23 && sd->disguise < 4001) // mob disguises [Valaris]
+ clif_send(buf, packet_len_table[0x9c], &sd->bl, AREA);
+ else
+ clif_send(buf, packet_len_table[0x9c], bl, AREA_WOS);
+
+ return;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_ChangeDir(int fd, struct map_session_data *sd) {
short headdir, dir;
nullpo_retv(sd);
- switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- case 7:
- headdir = RFIFOW(fd,5);
- dir = RFIFOB(fd,12);
- break;
- case 8:
- headdir = RFIFOW(fd,5);
- dir = RFIFOB(fd,12);
- break;
- case 9:
- headdir = RFIFOW(fd,7);
- dir = RFIFOB(fd,11);
- break;
- case 10:
- headdir = RFIFOW(fd,4);
- dir = RFIFOB(fd,9);
- break;
- case 11:
- headdir = RFIFOW(fd,8);
- dir = RFIFOB(fd,17);
- break;
- case 12:
- headdir = RFIFOW(fd,5);
- dir = RFIFOB(fd,12);
- break;
- case 13:
- headdir = RFIFOW(fd,6);
- dir = RFIFOB(fd,14);
- break;
- default: // old version by default (and packet version 6)
- headdir = RFIFOW(fd,2);
- dir = RFIFOB(fd,4);
- break;
+ if (USE_PACKET_DB(sd)) {
+ headdir = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]);
+ dir = RFIFOB(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]);
+ } else {
+ switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ case 7:
+ headdir = RFIFOW(fd,5);
+ dir = RFIFOB(fd,12);
+ break;
+ case 8:
+ headdir = RFIFOW(fd,5);
+ dir = RFIFOB(fd,12);
+ break;
+ case 9:
+ headdir = RFIFOW(fd,7);
+ dir = RFIFOB(fd,11);
+ break;
+ case 10:
+ headdir = RFIFOW(fd,4);
+ dir = RFIFOB(fd,9);
+ break;
+ case 11:
+ headdir = RFIFOW(fd,8);
+ dir = RFIFOB(fd,17);
+ break;
+ case 12:
+ headdir = RFIFOW(fd,5);
+ dir = RFIFOB(fd,12);
+ break;
+ case 13:
+ case 14:
+ headdir = RFIFOW(fd,6);
+ dir = RFIFOB(fd,14);
+ break;
+ case 15:
+ headdir = RFIFOW(fd,3);
+ dir = RFIFOB(fd,7);
+ break;
+ case 16:
+ headdir = RFIFOW(fd,12);
+ dir = RFIFOB(fd,22);
+ break;
+
+ default: // old version by default (and packet version 6)
+ headdir = RFIFOW(fd,2);
+ dir = RFIFOB(fd,4);
+ break;
+ }
}
pc_setdir(sd, dir, headdir);
- WBUFW(buf,0) = 0x9c;
- WBUFL(buf,2) = sd->bl.id;
- WBUFW(buf,6) = headdir;
- WBUFB(buf,8) = dir;
- if (sd->disguise > 23 && sd->disguise < 4001) // mob disguises [Valaris]
- clif_send(buf, packet_len_table[0x9c], &sd->bl, AREA);
- else
- clif_send(buf, packet_len_table[0x9c], &sd->bl, AREA_WOS);
-
+ clif_changed_dir(&sd->bl);
+ return;
}
/*==========================================
@@ -7811,10 +8184,20 @@ void clif_parse_Emotion(int fd, struct map_session_data *sd) {
nullpo_retv(sd);
if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, NV_BASIC) >= 2) {
+ if (RFIFOB(fd,2) == 34) {// prevent use of the mute emote [Valaris]
+ clif_skill_fail(sd, 1, 0, 1);
+ return;
+ }
+ // fix flood of emotion icon (ro-proxy): flood only the hacker player
+ if (sd->emotionlasttime >= time(NULL)) {
+ sd->emotionlasttime = time(NULL) + 2; // not more than 1 every 2 seconds (normal client is every 3-4 seconds)
+ clif_skill_fail(sd, 1, 0, 1);
+ return;
+ }
+ sd->emotionlasttime = time(NULL) + 2; // not more than 1 every 2 seconds (normal client is every 3-4 seconds)
+
WBUFW(buf,0) = 0xc0;
WBUFL(buf,2) = sd->bl.id;
- if(RFIFOB(fd,2)==34) // prevent use of the mute emote [Valaris]
- return;
WBUFB(buf,6) = RFIFOB(fd,2);
clif_send(buf, packet_len_table[0xc0], &sd->bl, AREA);
} else
@@ -7848,7 +8231,8 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) {
}
if (sd->npc_id != 0 || sd->opt1 > 0 || sd->status.option & 2 ||
(sd->sc_data &&
- (sd->sc_data[SC_AUTOCOUNTER].timer != -1 || //オートカウンター
+ (sd->sc_data[SC_TRICKDEAD].timer != -1 ||
+ sd->sc_data[SC_AUTOCOUNTER].timer != -1 || //オートカウンター
sd->sc_data[SC_BLADESTOP].timer != -1 || //白刃取り
sd->sc_data[SC_DANCING].timer != -1))) //ダンス中
return;
@@ -7858,35 +8242,50 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) {
pc_stop_walking(sd, 0);
pc_stopattack(sd);
- switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- case 8:
- target_id = RFIFOL(fd,3);
- action_type = RFIFOB(fd,8);
- break;
- case 9:
- target_id = RFIFOL(fd,7);
- action_type = RFIFOB(fd,17);
- break;
- case 10:
- target_id = RFIFOL(fd,9);
- action_type = RFIFOB(fd,22);
- break;
- case 11:
- target_id = RFIFOL(fd,3);
- action_type = RFIFOB(fd,8);
- break;
- case 12:
- target_id = RFIFOL(fd,3);
- action_type = RFIFOB(fd,8);
- break;
- case 13:
- target_id = RFIFOL(fd,4);
- action_type = RFIFOB(fd,14);
- break;
- default: // old version by default (and packet version 6 and 7)
- target_id = RFIFOL(fd,2);
- action_type = RFIFOB(fd,6);
- break;
+ if (USE_PACKET_DB(sd)) {
+ target_id = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]);
+ action_type = RFIFOB(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]);
+ } else {
+ switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ case 8:
+ target_id = RFIFOL(fd,3);
+ action_type = RFIFOB(fd,8);
+ break;
+ case 9:
+ target_id = RFIFOL(fd,7);
+ action_type = RFIFOB(fd,17);
+ break;
+ case 10:
+ target_id = RFIFOL(fd,9);
+ action_type = RFIFOB(fd,22);
+ break;
+ case 11:
+ target_id = RFIFOL(fd,3);
+ action_type = RFIFOB(fd,8);
+ break;
+ case 12:
+ target_id = RFIFOL(fd,3);
+ action_type = RFIFOB(fd,8);
+ break;
+ case 13:
+ case 14:
+ target_id = RFIFOL(fd,4);
+ action_type = RFIFOB(fd,14);
+ break;
+ case 15:
+ target_id = RFIFOL(fd,6);
+ action_type = RFIFOB(fd,17);
+ break;
+ case 16:
+ target_id = RFIFOL(fd,9);
+ action_type = RFIFOB(fd,19);
+ break;
+
+ default: // old version by default (and packet version 6 and 7)
+ target_id = RFIFOL(fd,2);
+ action_type = RFIFOB(fd,6);
+ break;
+ }
}
switch(action_type) {
@@ -7911,15 +8310,15 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) {
case 0x02: // sitdown
if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, NV_BASIC) >= 3) {
pc_stop_walking(sd, 1);
- skill_gangsterparadise(sd, 1); // ギャングスターパラダイス設定
pc_setsit(sd);
+ skill_gangsterparadise(sd, 1); // ギャングスターパラダイス設定 fixed Valaris
clif_sitting(sd);
} else
clif_skill_fail(sd, 1, 0, 2);
break;
case 0x03: // standup
- skill_gangsterparadise(sd, 0); // ギャングスターパラダイス解除
pc_setstand(sd);
+ skill_gangsterparadise(sd, 0); // ギャングスターパラダイス解除 fixed Valaris
WBUFW(buf, 0) = 0x8a;
WBUFL(buf, 2) = sd->bl.id;
WBUFB(buf,26) = 3;
@@ -7942,6 +8341,9 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) {
pc_setrestartvalue(sd, 3);
pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, 2);
}
+ // in case the player's status somehow wasn't updated yet [Celest]
+ else if (sd->status.hp <= 0)
+ pc_setdead(sd);
break;
case 0x01:
if(!pc_isdead(sd) && (sd->opt1 || (sd->opt2 && !(night_flag == 1 && sd->opt2 == STATE_BLIND))))
@@ -7971,32 +8373,32 @@ void clif_parse_Wis(int fd, struct map_session_data *sd) { // S 0096 <len>.w <ni
//printf("clif_parse_Wis: message: '%s'.\n", RFIFOP(fd,28));
- gm_command = (char*)aCalloc(strlen(RFIFOP(fd,28)) + 28, sizeof(char)); // 24+3+(RFIFOW(fd,2)-28)+1 or 24+3+(strlen(RFIFOP(fd,28))+1 (size can be wrong with hacker)
+ gm_command = (char*)aCallocA(strlen((const char*)RFIFOP(fd,28)) + 28, sizeof(char)); // 24+3+(RFIFOW(fd,2)-28)+1 or 24+3+(strlen(RFIFOP(fd,28))+1 (size can be wrong with hacker)
sprintf(gm_command, "%s : %s", sd->status.name, RFIFOP(fd,28));
if ((is_charcommand(fd, sd, gm_command, 0) != CharCommand_None) ||
(is_atcommand(fd, sd, gm_command, 0) != AtCommand_None) ||
- (sd && sd->sc_data &&
+ (sd && sd->sc_data &&
(sd->sc_data[SC_BERSERK].timer!=-1 || //バーサーク時は会話も不可
sd->sc_data[SC_NOCHAT].timer != -1))) //チャット禁止
{
- if(gm_command) free(gm_command);
+ if(gm_command) aFree(gm_command);
return;
}
- if(gm_command) free(gm_command);
+ if(gm_command) aFree(gm_command);
// searching destination character
- dstsd = map_nick2sd(RFIFOP(fd,4));
+ dstsd = map_nick2sd((char*)RFIFOP(fd,4));
// player is not on this map-server
if (dstsd == NULL ||
// At this point, don't send wisp/page if it's not exactly the same name, because (example)
// if there are 'Test' player on an other map-server and 'test' player on this map-server,
// and if we ask for 'Test', we must not contact 'test' player
// so, we send information to inter-server, which is the only one which decide (and copy correct name).
- strcmp(dstsd->status.name, RFIFOP(fd,4)) != 0) // not exactly same name
+ strcmp(dstsd->status.name, (const char*)RFIFOP(fd,4)) != 0) // not exactly same name
// send message to inter-server
- intif_wis_message(sd, RFIFOP(fd,4), RFIFOP(fd,28), RFIFOW(fd,2)-28);
+ intif_wis_message(sd, (char*)RFIFOP(fd,4), (char*)RFIFOP(fd,28), RFIFOW(fd,2)-28);
// player is on this map-server
else {
// if you send to your self, don't send anything to others
@@ -8015,7 +8417,7 @@ void clif_parse_Wis(int fd, struct map_session_data *sd) { // S 0096 <len>.w <ni
}
// if source player not found in ignore list
if (i == MAX_IGNORE_LIST) {
- clif_wis_message(dstsd->fd, sd->status.name, RFIFOP(fd,28), RFIFOW(fd,2) - 28);
+ clif_wis_message(dstsd->fd, sd->status.name, (char*)RFIFOP(fd,28), RFIFOW(fd,2) - 28);
clif_wis_end(fd, 0); // type: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
}
}
@@ -8035,7 +8437,7 @@ void clif_parse_GMmessage(int fd, struct map_session_data *sd) {
if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) &&
(pc_isGM(sd) >= get_atcommand_level(AtCommand_Broadcast)))
- intif_GMmessage(RFIFOP(fd,4), RFIFOW(fd,2)-4, 0);
+ intif_GMmessage((char*)RFIFOP(fd,4), RFIFOW(fd,2)-4, 0);
}
/*==========================================
@@ -8048,31 +8450,42 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd) {
nullpo_retv(sd);
- switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- case 7:
- map_object_id = RFIFOL(fd,6);
- break;
- case 8:
- map_object_id = RFIFOL(fd,6);
- break;
- case 9:
- map_object_id = RFIFOL(fd,9);
- break;
- case 10:
- map_object_id = RFIFOL(fd,7);
- break;
- case 11:
- map_object_id = RFIFOL(fd,10);
- break;
- case 12:
- map_object_id = RFIFOL(fd,6);
- break;
- case 13:
- map_object_id = RFIFOL(fd,5);
- break;
- default: // old version by default (and packet version 6)
- map_object_id = RFIFOL(fd,2);
- break;
+ if (USE_PACKET_DB(sd)) {
+ map_object_id = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]);
+ } else {
+ switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ case 7:
+ map_object_id = RFIFOL(fd,6);
+ break;
+ case 8:
+ map_object_id = RFIFOL(fd,6);
+ break;
+ case 9:
+ map_object_id = RFIFOL(fd,9);
+ break;
+ case 10:
+ map_object_id = RFIFOL(fd,7);
+ break;
+ case 11:
+ map_object_id = RFIFOL(fd,10);
+ break;
+ case 12:
+ map_object_id = RFIFOL(fd,6);
+ break;
+ case 13:
+ case 14:
+ map_object_id = RFIFOL(fd,5);
+ break;
+ case 15:
+ map_object_id = RFIFOL(fd,3);
+ break;
+ case 16:
+ map_object_id = RFIFOL(fd,5);
+ break;
+ default: // old version by default (and packet version 6)
+ map_object_id = RFIFOL(fd,2);
+ break;
+ }
}
fitem = (struct flooritem_data*)map_id2bl(map_object_id);
@@ -8113,35 +8526,49 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd) {
sd->sc_data[SC_BERSERK].timer != -1)) ) //バーサーク
return;
- switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- case 8:
- item_index = RFIFOW(fd,5) - 2;
- item_amount = RFIFOW(fd,12);
- break;
- case 9:
- item_index = RFIFOW(fd,8) - 2;
- item_amount = RFIFOW(fd,15);
- break;
- case 10:
- item_index = RFIFOW(fd,6) - 2;
- item_amount = RFIFOW(fd,15);
- break;
- case 11:
- item_index = RFIFOW(fd,12) - 2;
- item_amount = RFIFOW(fd,17);
- break;
- case 12:
- item_index = RFIFOW(fd,5) - 2;
- item_amount = RFIFOW(fd,12);
- break;
- case 13:
- item_index = RFIFOW(fd,6) - 2;
- item_amount = RFIFOW(fd,10);
- break;
- default: // old version by default (+ packet version 6 and 7)
- item_index = RFIFOW(fd,2) - 2;
- item_amount = RFIFOW(fd,4);
- break;
+ if (USE_PACKET_DB(sd)) {
+ item_index = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0])-2;
+ item_amount = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]);
+ } else {
+ switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ case 8:
+ item_index = RFIFOW(fd,5) - 2;
+ item_amount = RFIFOW(fd,12);
+ break;
+ case 9:
+ item_index = RFIFOW(fd,8) - 2;
+ item_amount = RFIFOW(fd,15);
+ break;
+ case 10:
+ item_index = RFIFOW(fd,6) - 2;
+ item_amount = RFIFOW(fd,15);
+ break;
+ case 11:
+ item_index = RFIFOW(fd,12) - 2;
+ item_amount = RFIFOW(fd,17);
+ break;
+ case 12:
+ item_index = RFIFOW(fd,5) - 2;
+ item_amount = RFIFOW(fd,12);
+ break;
+ case 13:
+ case 14:
+ item_index = RFIFOW(fd,6) - 2;
+ item_amount = RFIFOW(fd,10);
+ break;
+ case 15:
+ item_index = RFIFOW(fd,4) - 2;
+ item_amount = RFIFOW(fd,10);
+ break;
+ case 16:
+ item_index = RFIFOW(fd,15) - 2;
+ item_amount = RFIFOW(fd,18);
+ break;
+ default: // old version by default (+ packet version 6 and 7)
+ item_index = RFIFOW(fd,2) - 2;
+ item_amount = RFIFOW(fd,4);
+ break;
+ }
}
pc_dropitem(sd, item_index, item_amount);
@@ -8158,7 +8585,7 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd) {
clif_clearchar_area(&sd->bl, 1);
return;
}
- if (sd->npc_id!=0 || sd->vender_id != 0 || sd->opt1 > 0 ||
+ if (sd->npc_id!=0 || sd->vender_id != 0 || (sd->opt1 > 0 && sd->opt1 != 6) ||
(sd->sc_data && (sd->sc_data[SC_TRICKDEAD].timer != -1 || //死んだふり
sd->sc_data[SC_BLADESTOP].timer != -1 || //白刃取り
sd->sc_data[SC_BERSERK].timer!=-1 || //バーサーク
@@ -8168,34 +8595,45 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd) {
if (sd->invincible_timer != -1)
pc_delinvincibletimer(sd);
- switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- case 6:
- pc_useitem(sd,RFIFOW(fd,5)-2);
- break;
- case 7:
- pc_useitem(sd,RFIFOW(fd,6)-2);
- break;
- case 8:
- pc_useitem(sd,RFIFOW(fd,6)-2);
- break;
- case 9:
- pc_useitem(sd,RFIFOW(fd,9)-2);
- break;
- case 10:
- pc_useitem(sd,RFIFOW(fd,7)-2);
- break;
- case 11:
- pc_useitem(sd,RFIFOW(fd,10)-2);
- break;
- case 12:
- pc_useitem(sd,RFIFOW(fd,6)-2);
- break;
- case 13:
- pc_useitem(sd,RFIFOW(fd,5)-2);
- break;
- default: // old version by default
- pc_useitem(sd,RFIFOW(fd,2)-2);
- break;
+ if (USE_PACKET_DB(sd)) {
+ pc_useitem(sd,RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0])-2);
+ } else {
+ switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ case 6:
+ pc_useitem(sd,RFIFOW(fd,5)-2);
+ break;
+ case 7:
+ pc_useitem(sd,RFIFOW(fd,6)-2);
+ break;
+ case 8:
+ pc_useitem(sd,RFIFOW(fd,6)-2);
+ break;
+ case 9:
+ pc_useitem(sd,RFIFOW(fd,9)-2);
+ break;
+ case 10:
+ pc_useitem(sd,RFIFOW(fd,7)-2);
+ break;
+ case 11:
+ pc_useitem(sd,RFIFOW(fd,10)-2);
+ break;
+ case 12:
+ pc_useitem(sd,RFIFOW(fd,6)-2);
+ break;
+ case 13:
+ case 14:
+ pc_useitem(sd,RFIFOW(fd,5)-2);
+ break;
+ case 15:
+ pc_useitem(sd,RFIFOW(fd,3)-2);
+ break;
+ case 16:
+ pc_useitem(sd,RFIFOW(fd,5)-2);
+ break;
+ default: // old version by default
+ pc_useitem(sd,RFIFOW(fd,2)-2);
+ break;
+ }
}
}
@@ -8246,17 +8684,18 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd)
clif_clearchar_area(&sd->bl,1);
return;
}
+ if(sd->npc_id!=0 || sd->vender_id != 0 || sd->opt1 > 0)
+ return;
index = RFIFOW(fd,2)-2;
- if(sd->status.inventory[index].attribute == 1 && sd->sc_data && sd->sc_data[SC_BROKNWEAPON].timer!=-1)
- skill_status_change_end(&sd->bl,SC_BROKNWEAPON,-1);
+
+ /*if(sd->status.inventory[index].attribute == 1 && sd->sc_data && sd->sc_data[SC_BROKNWEAPON].timer!=-1)
+ status_change_end(&sd->bl,SC_BROKNWEAPON,-1);
if(sd->status.inventory[index].attribute == 1 && sd->sc_data && sd->sc_data[SC_BROKNARMOR].timer!=-1)
- skill_status_change_end(&sd->bl,SC_BROKNARMOR,-1);
- if(sd->sc_data && ( sd->sc_data[SC_BLADESTOP].timer!=-1 || sd->sc_data[SC_BERSERK].timer!=-1 ))
- return;
+ status_change_end(&sd->bl,SC_BROKNARMOR,-1);
+ if(sd->sc_count && ( sd->sc_data[SC_BLADESTOP].timer!=-1 || sd->sc_data[SC_BERSERK].timer!=-1 ))
+ return;*/
- if(sd->npc_id!=0 || sd->vender_id != 0 || sd->opt1 > 0)
- return;
- pc_unequipitem(sd,index,0,BF_NORMAL);
+ pc_unequipitem(sd,index,1);
}
/*==========================================
@@ -8330,7 +8769,7 @@ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd)
void clif_parse_CreateChatRoom(int fd,struct map_session_data *sd)
{
if(battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_BASIC) >= 4){
- chat_createchat(sd,RFIFOW(fd,4),RFIFOB(fd,6),RFIFOP(fd,7),RFIFOP(fd,15),RFIFOW(fd,2)-15);
+ chat_createchat(sd,RFIFOW(fd,4),RFIFOB(fd,6),(char*)RFIFOP(fd,7),(char*)RFIFOP(fd,15),RFIFOW(fd,2)-15);
} else
clif_skill_fail(sd,1,0,3);
}
@@ -8341,7 +8780,7 @@ void clif_parse_CreateChatRoom(int fd,struct map_session_data *sd)
*/
void clif_parse_ChatAddMember(int fd,struct map_session_data *sd)
{
- chat_joinchat(sd,RFIFOL(fd,2),RFIFOP(fd,6));
+ chat_joinchat(sd,RFIFOL(fd,2),(char*)RFIFOP(fd,6));
}
/*==========================================
@@ -8350,7 +8789,7 @@ void clif_parse_ChatAddMember(int fd,struct map_session_data *sd)
*/
void clif_parse_ChatRoomStatusChange(int fd,struct map_session_data *sd)
{
- chat_changechatstatus(sd,RFIFOW(fd,4),RFIFOB(fd,6),RFIFOP(fd,7),RFIFOP(fd,15),RFIFOW(fd,2)-15);
+ chat_changechatstatus(sd,RFIFOW(fd,4),RFIFOB(fd,6),(char*)RFIFOP(fd,7),(char*)RFIFOP(fd,15),RFIFOW(fd,2)-15);
}
/*==========================================
@@ -8359,7 +8798,7 @@ void clif_parse_ChatRoomStatusChange(int fd,struct map_session_data *sd)
*/
void clif_parse_ChangeChatOwner(int fd,struct map_session_data *sd)
{
- chat_changechatowner(sd,RFIFOP(fd,6));
+ chat_changechatowner(sd,(char*)RFIFOP(fd,6));
}
/*==========================================
@@ -8368,7 +8807,7 @@ void clif_parse_ChangeChatOwner(int fd,struct map_session_data *sd)
*/
void clif_parse_KickFromChat(int fd,struct map_session_data *sd)
{
- chat_kickchat(sd,RFIFOP(fd,2));
+ chat_kickchat(sd,(char*)RFIFOP(fd,2));
}
/*==========================================
@@ -8429,7 +8868,7 @@ void clif_parse_TradeOk(int fd,struct map_session_data *sd)
* 取引キャンセル
*------------------------------------------
*/
-void clif_parse_TradeCansel(int fd,struct map_session_data *sd)
+void clif_parse_TradeCancel(int fd,struct map_session_data *sd)
{
trade_tradecancel(sd);
}
@@ -8483,17 +8922,17 @@ void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd)
void clif_parse_RemoveOption(int fd,struct map_session_data *sd)
{
if(pc_isriding(sd)) { // jobchange when removing peco [Valaris]
- if(sd->status.class==13)
- sd->status.class=sd->view_class=7;
+ if(sd->status.class_==13)
+ sd->status.class_=sd->view_class=7;
- if(sd->status.class==21)
- sd->status.class=sd->view_class=14;
+ if(sd->status.class_==21)
+ sd->status.class_=sd->view_class=14;
- if(sd->status.class==4014)
- sd->status.class=sd->view_class=4008;
+ if(sd->status.class_==4014)
+ sd->status.class_=sd->view_class=4008;
- if(sd->status.class==4022)
- sd->status.class=sd->view_class=4015;
+ if(sd->status.class_==4022)
+ sd->status.class_=sd->view_class=4015;
}
pc_setoption(sd,0);
@@ -8539,52 +8978,69 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) {
if (sd->chatID || sd->npc_id != 0 || sd->vender_id != 0)
return;
- switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- case 6:
- skilllv = RFIFOW(fd,4);
- skillnum = RFIFOW(fd,9);
- target_id = RFIFOL(fd,11);
- break;
- case 7:
- skilllv = RFIFOW(fd,7);
- skillnum = RFIFOW(fd,9);
- target_id = RFIFOL(fd,15);
- break;
- case 8:
- skilllv = RFIFOW(fd,7);
- skillnum = RFIFOW(fd,12);
- target_id = RFIFOL(fd,16);
- break;
- case 9:
- skilllv = RFIFOW(fd,11);
- skillnum = RFIFOW(fd,18);
- target_id = RFIFOL(fd,22);
- break;
- case 10:
- skilllv = RFIFOW(fd,9);
- skillnum = RFIFOW(fd,15);
- target_id = RFIFOL(fd,18);
- break;
- case 11:
- skilllv = RFIFOW(fd,4);
- skillnum = RFIFOW(fd,7);
- target_id = RFIFOL(fd,10);
- break;
- case 12:
- skilllv = RFIFOW(fd,7);
- skillnum = RFIFOW(fd,12);
- target_id = RFIFOL(fd,16);
- break;
- case 13:
- skilllv = RFIFOW(fd,4);
- skillnum = RFIFOW(fd,10);
- target_id = RFIFOL(fd,22);
- break;
- default: // old version by default
- skilllv = RFIFOW(fd,2);
- skillnum = RFIFOW(fd,4);
- target_id = RFIFOL(fd,6);
- break;
+ if (USE_PACKET_DB(sd)) {
+ skilllv = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]);
+ skillnum = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]);
+ target_id = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[2]);
+ } else {
+ switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ case 6:
+ skilllv = RFIFOW(fd,4);
+ skillnum = RFIFOW(fd,9);
+ target_id = RFIFOL(fd,11);
+ break;
+ case 7:
+ skilllv = RFIFOW(fd,7);
+ skillnum = RFIFOW(fd,9);
+ target_id = RFIFOL(fd,15);
+ break;
+ case 8:
+ skilllv = RFIFOW(fd,7);
+ skillnum = RFIFOW(fd,12);
+ target_id = RFIFOL(fd,16);
+ break;
+ case 9:
+ skilllv = RFIFOW(fd,11);
+ skillnum = RFIFOW(fd,18);
+ target_id = RFIFOL(fd,22);
+ break;
+ case 10:
+ skilllv = RFIFOW(fd,9);
+ skillnum = RFIFOW(fd,15);
+ target_id = RFIFOL(fd,18);
+ break;
+ case 11:
+ skilllv = RFIFOW(fd,4);
+ skillnum = RFIFOW(fd,7);
+ target_id = RFIFOL(fd,10);
+ break;
+ case 12:
+ skilllv = RFIFOW(fd,7);
+ skillnum = RFIFOW(fd,12);
+ target_id = RFIFOL(fd,16);
+ break;
+ case 13:
+ case 14:
+ skilllv = RFIFOW(fd,4);
+ skillnum = RFIFOW(fd,10);
+ target_id = RFIFOL(fd,22);
+ break;
+ case 15:
+ skilllv = RFIFOW(fd,8);
+ skillnum = RFIFOW(fd,12);
+ target_id = RFIFOL(fd,18);
+ break;
+ case 16:
+ skilllv = RFIFOW(fd,8);
+ skillnum = RFIFOW(fd,16);
+ target_id = RFIFOL(fd,22);
+ break;
+ default: // old version by default
+ skilllv = RFIFOW(fd,2);
+ skillnum = RFIFOW(fd,4);
+ target_id = RFIFOL(fd,6);
+ break;
+ }
}
if (skillnotok(skillnum, sd))
@@ -8593,12 +9049,20 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) {
if (sd->skilltimer != -1) {
if (skillnum != SA_CASTCANCEL)
return;
- } else if (DIFF_TICK(tick, sd->canact_tick) < 0) {
+ } else if (DIFF_TICK(tick, sd->canact_tick) < 0 &&
+ // allow monk combos to ignore this delay [celest]
+ !(sd->sc_count && sd->sc_data[SC_COMBO].timer!=-1 &&
+ (skillnum == MO_EXTREMITYFIST ||
+ skillnum == MO_CHAINCOMBO ||
+ skillnum == MO_COMBOFINISH ||
+ skillnum == CH_PALMSTRIKE ||
+ skillnum == CH_TIGERFIST ||
+ skillnum == CH_CHAINCRUSH))) {
clif_skill_fail(sd, skillnum, 4, 0);
return;
}
- if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) ||
+ if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) ||
sd->sc_data[SC_BERSERK].timer != -1 || sd->sc_data[SC_NOCHAT].timer != -1 ||
sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class == 22)
return;
@@ -8621,6 +9085,20 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) {
return;
}
}
+ } else if (skillnum == CH_TIGERFIST) {
+ if (sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH) {
+ if (!sd->state.skill_flag ) {
+ sd->state.skill_flag = 1;
+ if (!sd->attacktarget) {
+ clif_skillinfo(sd, CH_TIGERFIST, 1, -2);
+ return;
+ } else
+ target_id = sd->attacktarget;
+ } else if (sd->bl.id == target_id) {
+ clif_skillinfo(sd, CH_TIGERFIST, 1, -2);
+ return;
+ }
+ }
}
if ((lv = pc_checkskill(sd, skillnum)) > 0) {
if (skilllv > lv)
@@ -8647,79 +9125,103 @@ void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) {
if(sd->chatID) return;
skillmoreinfo = -1;
- switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- case 6:
- skilllv = RFIFOW(fd,4);
- skillnum = RFIFOW(fd,9);
- x = RFIFOW(fd,11);
- y = RFIFOW(fd,13);
- if (RFIFOW(fd,0) == 0x190)
- skillmoreinfo = 15;
- break;
- case 7:
- skilllv = RFIFOW(fd,7);
- skillnum = RFIFOW(fd,9);
- x = RFIFOW(fd,15);
- y = RFIFOW(fd,17);
- if (RFIFOW(fd,0) == 0x190)
- skillmoreinfo = 19;
- break;
- case 8:
- skilllv = RFIFOW(fd,3);
- skillnum = RFIFOW(fd,6);
- x = RFIFOW(fd,17);
- y = RFIFOW(fd,21);
- if (RFIFOW(fd,0) == 0x0a2)
- skillmoreinfo = 23;
- break;
- case 9:
- skilllv = RFIFOW(fd,5);
- skillnum = RFIFOW(fd,15);
- x = RFIFOW(fd,29);
- y = RFIFOW(fd,38);
- if (RFIFOW(fd,0) == 0x0a2)
- skillmoreinfo = 40;
- break;
- case 10:
- skilllv = RFIFOW(fd,10);
- skillnum = RFIFOW(fd,14);
- x = RFIFOW(fd,18);
- y = RFIFOW(fd,23);
- if (RFIFOW(fd,0) == 0x08c)
- skillmoreinfo = 25;
- break;
- case 11:
- skilllv = RFIFOW(fd,6); // 16? to check.
- skillnum = RFIFOW(fd,20);
- x = RFIFOW(fd,23);
- y = RFIFOW(fd,27);
- if (RFIFOW(fd,0) == 0x08c)
- skillmoreinfo = 29;
- break;
- case 12:
- skilllv = RFIFOW(fd,3); // 2? to check.
- skillnum = RFIFOW(fd,6);
- x = RFIFOW(fd,17);
- y = RFIFOW(fd,21);
- if (RFIFOW(fd,0) == 0x08c)
- skillmoreinfo = 23;
- break;
- case 13:
- skilllv = RFIFOW(fd,6);
- skillnum = RFIFOW(fd,9);
- x = RFIFOW(fd,23);
- y = RFIFOW(fd,26);
- if (RFIFOW(fd,0) == 0x08c)
- skillmoreinfo = 28;
- break;
- default: // old version by default
- skilllv = RFIFOW(fd,2);
- skillnum = RFIFOW(fd,4);
- x = RFIFOW(fd,6);
- y = RFIFOW(fd,8);
- if (RFIFOW(fd,0) == 0x190)
- skillmoreinfo = 10;
- break;
+ if (USE_PACKET_DB(sd)) {
+ skilllv = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]);
+ skillnum = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]);
+ x = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[2]);
+ y = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[3]);
+ } else {
+ switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ case 6:
+ skilllv = RFIFOW(fd,4);
+ skillnum = RFIFOW(fd,9);
+ x = RFIFOW(fd,11);
+ y = RFIFOW(fd,13);
+ if (RFIFOW(fd,0) == 0x190)
+ skillmoreinfo = 15;
+ break;
+ case 7:
+ skilllv = RFIFOW(fd,7);
+ skillnum = RFIFOW(fd,9);
+ x = RFIFOW(fd,15);
+ y = RFIFOW(fd,17);
+ if (RFIFOW(fd,0) == 0x190)
+ skillmoreinfo = 19;
+ break;
+ case 8:
+ skilllv = RFIFOW(fd,3);
+ skillnum = RFIFOW(fd,6);
+ x = RFIFOW(fd,17);
+ y = RFIFOW(fd,21);
+ if (RFIFOW(fd,0) == 0x0a2)
+ skillmoreinfo = 23;
+ break;
+ case 9:
+ skilllv = RFIFOW(fd,5);
+ skillnum = RFIFOW(fd,15);
+ x = RFIFOW(fd,29);
+ y = RFIFOW(fd,38);
+ if (RFIFOW(fd,0) == 0x0a2)
+ skillmoreinfo = 40;
+ break;
+ case 10:
+ skilllv = RFIFOW(fd,10);
+ skillnum = RFIFOW(fd,14);
+ x = RFIFOW(fd,18);
+ y = RFIFOW(fd,23);
+ if (RFIFOW(fd,0) == 0x08c)
+ skillmoreinfo = 25;
+ break;
+ case 11:
+ skilllv = RFIFOW(fd,6); // 16? to check.
+ skillnum = RFIFOW(fd,20);
+ x = RFIFOW(fd,23);
+ y = RFIFOW(fd,27);
+ if (RFIFOW(fd,0) == 0x08c)
+ skillmoreinfo = 29;
+ break;
+ case 12:
+ skilllv = RFIFOW(fd,3); // 2? to check.
+ skillnum = RFIFOW(fd,6);
+ x = RFIFOW(fd,17);
+ y = RFIFOW(fd,21);
+ if (RFIFOW(fd,0) == 0x08c)
+ skillmoreinfo = 23;
+ break;
+ case 13:
+ case 14:
+ skilllv = RFIFOW(fd,6);
+ skillnum = RFIFOW(fd,9);
+ x = RFIFOW(fd,23);
+ y = RFIFOW(fd,26);
+ if (RFIFOW(fd,0) == 0x08c)
+ skillmoreinfo = 28;
+ break;
+ case 15:
+ skilllv = RFIFOW(fd,4);
+ skillnum = RFIFOW(fd,9);
+ x = RFIFOW(fd,22);
+ y = RFIFOW(fd,28);
+ if (RFIFOW(fd,0) == 0x113)
+ skillmoreinfo = 30;
+ break;
+ case 16:
+ skilllv = RFIFOW(fd,9);
+ skillnum = RFIFOW(fd,18);
+ x = RFIFOW(fd,22);
+ y = RFIFOW(fd,32);
+ if (RFIFOW(fd,0) == 0x07e)
+ skillmoreinfo = 34;
+ break;
+ default: // old version by default
+ skilllv = RFIFOW(fd,2);
+ skillnum = RFIFOW(fd,4);
+ x = RFIFOW(fd,6);
+ y = RFIFOW(fd,8);
+ if (RFIFOW(fd,0) == 0x190)
+ skillmoreinfo = 10;
+ break;
+ }
}
if (skillnotok(skillnum, sd))
@@ -8735,12 +9237,20 @@ void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) {
if (sd->skilltimer != -1)
return;
- else if (DIFF_TICK(tick, sd->canact_tick) < 0) {
+ else if (DIFF_TICK(tick, sd->canact_tick) < 0 &&
+ // allow monk combos to ignore this delay [celest]
+ !(sd->sc_count && sd->sc_data[SC_COMBO].timer!=-1 &&
+ (skillnum == MO_EXTREMITYFIST ||
+ skillnum == MO_CHAINCOMBO ||
+ skillnum == MO_COMBOFINISH ||
+ skillnum == CH_PALMSTRIKE ||
+ skillnum == CH_TIGERFIST ||
+ skillnum == CH_CHAINCRUSH))) {
clif_skill_fail(sd, skillnum, 4, 0);
return;
}
- if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) ||
+ if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) ||
sd->sc_data[SC_BERSERK].timer != -1 || sd->sc_data[SC_NOCHAT].timer != -1 ||
sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class == 22)
return;
@@ -8770,7 +9280,7 @@ void clif_parse_UseSkillMap(int fd,struct map_session_data *sd)
if(sd->chatID) return;
- if (sd->npc_id!=0 || sd->vender_id != 0 || (sd->sc_data &&
+ if (sd->npc_id!=0 || sd->vender_id != 0 || (sd->sc_data &&
(sd->sc_data[SC_TRICKDEAD].timer != -1 ||
sd->sc_data[SC_BERSERK].timer!=-1 ||
sd->sc_data[SC_NOCHAT].timer!=-1 ||
@@ -8781,7 +9291,7 @@ void clif_parse_UseSkillMap(int fd,struct map_session_data *sd)
if(sd->invincible_timer != -1)
pc_delinvincibletimer(sd);
- skill_castend_map(sd,RFIFOW(fd,2),RFIFOP(fd,4));
+ skill_castend_map(sd,RFIFOW(fd,2),(char*)RFIFOP(fd,4));
}
/*==========================================
* メモ要求
@@ -8854,7 +9364,7 @@ void clif_parse_NpcStringInput(int fd,struct map_session_data *sd)
memcpy(sd->npc_str,RFIFOP(fd,8),sizeof(sd->npc_str));
sd->npc_str[sizeof(sd->npc_str)-1]=0;
} else
- strcpy(sd->npc_str,RFIFOP(fd,8));
+ strcpy(sd->npc_str,(char*)RFIFOP(fd,8));
npc_scriptcont(sd,RFIFOL(fd,4));
}
@@ -8918,28 +9428,39 @@ void clif_parse_InsertCard(int fd,struct map_session_data *sd)
void clif_parse_SolveCharName(int fd, struct map_session_data *sd) {
int char_id;
- switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- case 8:
- char_id = RFIFOL(fd,8);
- break;
- case 9:
- char_id = RFIFOL(fd,7);
- break;
- case 10:
- char_id = RFIFOL(fd,10);
- break;
- case 11:
- char_id = RFIFOL(fd,6);
- break;
- case 12:
- char_id = RFIFOL(fd,8);
- break;
- case 13:
- char_id = RFIFOL(fd,12);
- break;
- default: // old version by default (+ packet version 6 and 7)
- char_id = RFIFOL(fd,2);
- break;
+ if (USE_PACKET_DB(sd)) {
+ char_id = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0]);
+ } else {
+ switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ case 8:
+ char_id = RFIFOL(fd,8);
+ break;
+ case 9:
+ char_id = RFIFOL(fd,7);
+ break;
+ case 10:
+ char_id = RFIFOL(fd,10);
+ break;
+ case 11:
+ char_id = RFIFOL(fd,6);
+ break;
+ case 12:
+ char_id = RFIFOL(fd,8);
+ break;
+ case 13:
+ case 14:
+ char_id = RFIFOL(fd,12);
+ break;
+ case 15:
+ char_id = RFIFOL(fd,10);
+ break;
+ case 16:
+ char_id = RFIFOL(fd,7);
+ break;
+ default: // old version by default (+ packet version 6 and 7)
+ char_id = RFIFOL(fd,2);
+ break;
+ }
}
clif_solved_charname(sd, char_id);
}
@@ -8951,15 +9472,14 @@ void clif_parse_SolveCharName(int fd, struct map_session_data *sd) {
void clif_parse_ResetChar(int fd, struct map_session_data *sd) {
nullpo_retv(sd);
- if (battle_config.atc_gmonly == 0 || pc_isGM(sd)) {
+ if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) &&
+ pc_isGM(sd) >= get_atcommand_level(AtCommand_ResetState)) {
switch(RFIFOW(fd,2)){
case 0:
- if (pc_isGM(sd) >= get_atcommand_level(AtCommand_ResetState))
- pc_resetstate(sd);
+ pc_resetstate(sd);
break;
case 1:
- if (pc_isGM(sd) >= get_atcommand_level(AtCommand_ResetState))
- pc_resetskill(sd);
+ pc_resetskill(sd);
break;
}
}
@@ -8970,7 +9490,7 @@ void clif_parse_ResetChar(int fd, struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_LGMmessage(int fd, struct map_session_data *sd) {
- unsigned char buf[64];
+ unsigned char buf[512];
nullpo_retv(sd);
@@ -8995,42 +9515,55 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) {
if (sd->npc_id != 0 || sd->vender_id != 0)
return;
- switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- case 8:
- item_index = RFIFOW(fd,5) - 2;
- item_amount = RFIFOL(fd,12);
- break;
- case 9:
- item_index = RFIFOW(fd,5) - 2;
- item_amount = RFIFOL(fd,19);
- break;
- case 10:
- item_index = RFIFOW(fd,3) - 2;
- item_amount = RFIFOL(fd,15);
- break;
- case 11:
- item_index = RFIFOW(fd,6) - 2;
- item_amount = RFIFOL(fd,21);
- break;
- case 12:
- item_index = RFIFOW(fd,5) - 2;
- item_amount = RFIFOL(fd,12);
- break;
- case 13:
- item_index = RFIFOW(fd,6) - 2;
- item_amount = RFIFOL(fd,9);
- break;
- default: // old version by default (+ packet version 6 and 7)
- item_index = RFIFOW(fd,2) - 2;
- item_amount = RFIFOL(fd,4);
- break;
+ if (USE_PACKET_DB(sd)) {
+ item_index = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0])-2;
+ item_amount = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]);
+ } else {
+ switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ case 8:
+ item_index = RFIFOW(fd,5) - 2;
+ item_amount = RFIFOL(fd,12);
+ break;
+ case 9:
+ item_index = RFIFOW(fd,5) - 2;
+ item_amount = RFIFOL(fd,19);
+ break;
+ case 10:
+ item_index = RFIFOW(fd,3) - 2;
+ item_amount = RFIFOL(fd,15);
+ break;
+ case 11:
+ item_index = RFIFOW(fd,6) - 2;
+ item_amount = RFIFOL(fd,21);
+ break;
+ case 12:
+ item_index = RFIFOW(fd,5) - 2;
+ item_amount = RFIFOL(fd,12);
+ break;
+ case 13:
+ case 14:
+ item_index = RFIFOW(fd,6) - 2;
+ item_amount = RFIFOL(fd,9);
+ break;
+ case 15:
+ item_index = RFIFOW(fd,4) - 2;
+ item_amount = RFIFOL(fd,10);
+ break;
+ case 16:
+ item_index = RFIFOW(fd,10) - 2;
+ item_amount = RFIFOL(fd,16);
+ break;
+ default: // old version by default (+ packet version 6 and 7)
+ item_index = RFIFOW(fd,2) - 2;
+ item_amount = RFIFOL(fd,4);
+ break;
+ }
}
if (item_index < 0 || item_index >= MAX_INVENTORY)
return;
if(itemdb_isdropable(sd->status.inventory[item_index].nameid) == 0)
-
return;
if (sd->state.storage_flag)
@@ -9048,35 +9581,49 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) {
nullpo_retv(sd);
- switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- case 8:
- item_index = RFIFOW(fd,10) - 1;
- item_amount = RFIFOL(fd,22);
- break;
- case 9:
- item_index = RFIFOW(fd,11) - 1;
- item_amount = RFIFOL(fd,22);
- break;
- case 10:
- item_index = RFIFOW(fd,3) - 1;
- item_amount = RFIFOL(fd,13);
- break;
- case 11:
- item_index = RFIFOW(fd,4) - 1;
- item_amount = RFIFOL(fd,8);
- break;
- case 12:
- item_index = RFIFOW(fd,10) - 1;
- item_amount = RFIFOL(fd,22);
- break;
- case 13:
- item_index = RFIFOW(fd,12) - 1;
- item_amount = RFIFOL(fd,18);
- break;
- default: // old version by default (+ packet version 6 and 7)
- item_index = RFIFOW(fd,2) - 1;
- item_amount = RFIFOL(fd,4);
- break;
+ if (USE_PACKET_DB(sd)) {
+ item_index = RFIFOW(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[0])-1;
+ item_amount = RFIFOL(fd,packet_db[clif_config.packet_db_ver][RFIFOW(fd,0)].pos[1]);
+ } else {
+ switch (sd->packet_ver) { // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ case 8:
+ item_index = RFIFOW(fd,10) - 1;
+ item_amount = RFIFOL(fd,22);
+ break;
+ case 9:
+ item_index = RFIFOW(fd,11) - 1;
+ item_amount = RFIFOL(fd,22);
+ break;
+ case 10:
+ item_index = RFIFOW(fd,3) - 1;
+ item_amount = RFIFOL(fd,13);
+ break;
+ case 11:
+ item_index = RFIFOW(fd,4) - 1;
+ item_amount = RFIFOL(fd,8);
+ break;
+ case 12:
+ item_index = RFIFOW(fd,10) - 1;
+ item_amount = RFIFOL(fd,22);
+ break;
+ case 13:
+ case 14:
+ item_index = RFIFOW(fd,12) - 1;
+ item_amount = RFIFOL(fd,18);
+ break;
+ case 15:
+ item_index = RFIFOW(fd,4) - 1;
+ item_amount = RFIFOL(fd,17);
+ break;
+ case 16:
+ item_index = RFIFOW(fd,11) - 1;
+ item_amount = RFIFOL(fd,17);
+ break;
+ default: // old version by default (+ packet version 6 and 7)
+ item_index = RFIFOW(fd,2) - 1;
+ item_amount = RFIFOL(fd,4);
+ break;
+ }
}
if (sd->npc_id != 0 || sd->vender_id != 0)
@@ -9137,7 +9684,7 @@ void clif_parse_CloseKafra(int fd, struct map_session_data *sd) {
*/
void clif_parse_CreateParty(int fd, struct map_session_data *sd) {
if (battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_BASIC) >= 7) {
- party_create(sd,RFIFOP(fd,2));
+ party_create(sd,(char*)RFIFOP(fd,2),0,0);
} else
clif_skill_fail(sd,1,0,4);
}
@@ -9148,9 +9695,9 @@ void clif_parse_CreateParty(int fd, struct map_session_data *sd) {
*/
void clif_parse_CreateParty2(int fd, struct map_session_data *sd) {
if (battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_BASIC) >= 7){
- party_create(sd, RFIFOP(fd,2));
+ party_create(sd,(char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOB(fd,27));
} else
- clif_skill_fail(sd, 1, 0, 4);
+ clif_skill_fail(sd,1,0,4);
}
/*==========================================
@@ -9187,7 +9734,7 @@ void clif_parse_LeaveParty(int fd, struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) {
- party_removemember(sd,RFIFOL(fd,2),RFIFOP(fd,6));
+ party_removemember(sd,RFIFOL(fd,2),(char*)RFIFOP(fd,6));
}
/*==========================================
@@ -9204,16 +9751,15 @@ void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd) {
*/
void clif_parse_PartyMessage(int fd, struct map_session_data *sd) {
nullpo_retv(sd);
- if (is_charcommand(fd, sd, RFIFOP(fd,4), 0) != CharCommand_None)
- return;
- if (is_atcommand(fd, sd, RFIFOP(fd,4), 0) != AtCommand_None)
- return;
- if(sd->sc_data &&
+
+ if (is_charcommand(fd, sd, (char*)RFIFOP(fd,4), 0) != CharCommand_None ||
+ is_atcommand(fd, sd, (char*)RFIFOP(fd,4), 0) != AtCommand_None ||
+ (sd->sc_data &&
(sd->sc_data[SC_BERSERK].timer!=-1 || //バーサーク時は会話も不可
- sd->sc_data[SC_NOCHAT].timer!=-1)) //チャット禁止
+ sd->sc_data[SC_NOCHAT].timer!=-1))) //チャット禁止
return;
- party_send_message(sd, RFIFOP(fd,4), RFIFOW(fd,2)-4);
+ party_send_message(sd, (char*)RFIFOP(fd,4), RFIFOW(fd,2)-4);
}
/*==========================================
@@ -9249,32 +9795,7 @@ void clif_parse_PurchaseReq(int fd, struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_OpenVending(int fd,struct map_session_data *sd) {
- vending_openvending(sd, RFIFOW(fd,2), RFIFOP(fd,4), RFIFOB(fd,84), RFIFOP(fd,85));
-}
-
-/*==========================================
- * /monster /item rewriten by [Yor]
- *------------------------------------------
- */
-void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) {
- char monster_item_name[25];
-
- nullpo_retv(sd);
-
- memset(monster_item_name, '\0', sizeof(monster_item_name));
-
- if (battle_config.atc_gmonly == 0 || pc_isGM(sd)) {
- memcpy(monster_item_name, RFIFOP(fd,2), 24);
-
- if (mobdb_searchname(monster_item_name) != 0) {
- if (pc_isGM(sd) >= get_atcommand_level(AtCommand_Monster))
- atcommand_spawn(fd, sd, "@spawn", monster_item_name); // as @spawn
- } else if (itemdb_searchname(monster_item_name) != NULL) {
- if (pc_isGM(sd) >= get_atcommand_level(AtCommand_Item))
- atcommand_item(fd, sd, "@item", monster_item_name); // as @item
- }
-
- }
+ vending_openvending(sd, RFIFOW(fd,2), (char*)RFIFOP(fd,4), RFIFOB(fd,84), RFIFOP(fd,85));
}
/*==========================================
@@ -9282,7 +9803,7 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_CreateGuild(int fd,struct map_session_data *sd) {
- guild_create(sd, RFIFOP(fd,6));
+ guild_create(sd, (char*)RFIFOP(fd,6));
}
/*==========================================
@@ -9297,7 +9818,7 @@ void clif_parse_GuildCheckMaster(int fd, struct map_session_data *sd) {
* ギルド情報要求
*------------------------------------------
*/
-void clif_parse_GuildReqeustInfo(int fd, struct map_session_data *sd) {
+void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd) {
switch(RFIFOL(fd,2)){
case 0: // ギルド基本情報、同盟敵対情報
clif_guild_basicinfo(sd);
@@ -9332,7 +9853,7 @@ void clif_parse_GuildChangePositionInfo(int fd, struct map_session_data *sd) {
int i;
for(i = 4; i < RFIFOW(fd,2); i += 40 ){
- guild_change_position(sd, RFIFOL(fd,i), RFIFOL(fd,i+4), RFIFOL(fd,i+12), RFIFOP(fd,i+16));
+ guild_change_position(sd, RFIFOL(fd,i), RFIFOL(fd,i+4), RFIFOL(fd,i+12), (char*)RFIFOP(fd,i+16));
}
}
@@ -9366,7 +9887,7 @@ void clif_parse_GuildRequestEmblem(int fd,struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_GuildChangeEmblem(int fd,struct map_session_data *sd) {
- guild_change_emblem(sd,RFIFOW(fd,2)-4,RFIFOP(fd,4));
+ guild_change_emblem(sd,RFIFOW(fd,2)-4,(char*)RFIFOP(fd,4));
}
/*==========================================
@@ -9374,7 +9895,7 @@ void clif_parse_GuildChangeEmblem(int fd,struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_GuildChangeNotice(int fd,struct map_session_data *sd) {
- guild_change_notice(sd,RFIFOL(fd,2),RFIFOP(fd,6),RFIFOP(fd,66));
+ guild_change_notice(sd,RFIFOL(fd,2),(char*)RFIFOP(fd,6),(char*)RFIFOP(fd,66));
}
/*==========================================
@@ -9398,7 +9919,7 @@ void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_GuildLeave(int fd,struct map_session_data *sd) {
- guild_leave(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOP(fd,14));
+ guild_leave(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14));
}
/*==========================================
@@ -9406,7 +9927,7 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_GuildExplusion(int fd,struct map_session_data *sd) {
- guild_explusion(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOP(fd,14));
+ guild_explusion(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14));
}
/*==========================================
@@ -9415,16 +9936,15 @@ void clif_parse_GuildExplusion(int fd,struct map_session_data *sd) {
*/
void clif_parse_GuildMessage(int fd,struct map_session_data *sd) {
nullpo_retv(sd);
- if (is_charcommand(fd, sd, RFIFOP(fd, 4), 0) != CharCommand_None)
- return;
- if (is_atcommand(fd, sd, RFIFOP(fd, 4), 0) != AtCommand_None)
- return;
- if(sd->sc_data &&
+
+ if (is_charcommand(fd, sd, (char*)RFIFOP(fd, 4), 0) != CharCommand_None ||
+ is_atcommand(fd, sd, (char*)RFIFOP(fd, 4), 0) != AtCommand_None ||
+ (sd->sc_data &&
(sd->sc_data[SC_BERSERK].timer!=-1 || //バーサーク時は会話も不可
- sd->sc_data[SC_NOCHAT].timer!=-1)) //チャット禁止
+ sd->sc_data[SC_NOCHAT].timer!=-1))) //チャット禁止
return;
- guild_send_message(sd, RFIFOP(fd,4), RFIFOW(fd,2)-4);
+ guild_send_message(sd, (char*)RFIFOP(fd,4), RFIFOW(fd,2)-4);
}
/*==========================================
@@ -9464,7 +9984,7 @@ void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_GuildBreak(int fd, struct map_session_data *sd) {
- guild_break(sd,RFIFOP(fd,2));
+ guild_break(sd,(char*)RFIFOP(fd,2));
}
// pet
@@ -9488,7 +10008,7 @@ void clif_parse_SendEmotion(int fd, struct map_session_data *sd) {
}
void clif_parse_ChangePetName(int fd, struct map_session_data *sd) {
- pet_change_name(sd,RFIFOP(fd,2));
+ pet_change_name(sd,(char*)RFIFOP(fd,2));
}
// Kick (right click menu for GM "(name) force to quit")
@@ -9559,6 +10079,31 @@ void clif_parse_Recall(int fd, struct map_session_data *sd) { // Added by RoVeRT
return;
}
+/*==========================================
+ * /monster /item rewriten by [Yor]
+ *------------------------------------------
+ */
+void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) {
+ char monster_item_name[25];
+
+ nullpo_retv(sd);
+
+ memset(monster_item_name, '\0', sizeof(monster_item_name));
+
+ if (battle_config.atc_gmonly == 0 || pc_isGM(sd)) {
+ memcpy(monster_item_name, RFIFOP(fd,2), 24);
+
+ if (mobdb_searchname(monster_item_name) != 0) {
+ if (pc_isGM(sd) >= get_atcommand_level(AtCommand_Monster))
+ atcommand_spawn(fd, sd, "@spawn", monster_item_name); // as @spawn
+ } else if (itemdb_searchname(monster_item_name) != NULL) {
+ if (pc_isGM(sd) >= get_atcommand_level(AtCommand_Item))
+ atcommand_item(fd, sd, "@item", monster_item_name); // as @item
+ }
+
+ }
+}
+
void clif_parse_GMHide(int fd, struct map_session_data *sd) { // Modified by [Yor]
nullpo_retv(sd);
@@ -9607,10 +10152,10 @@ void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd)
WFIFOSET(dstfd,packet_len_table[0x14b]);
dstsd->status.manner -= limit;
if(dstsd->status.manner < 0)
- skill_status_change_start(bl,SC_NOCHAT,0,0,0,0,0,0);
+ status_change_start(bl,SC_NOCHAT,0,0,0,0,0,0);
else{
dstsd->status.manner = 0;
- skill_status_change_end(bl,SC_NOCHAT,-1);
+ status_change_end(bl,SC_NOCHAT,-1);
}
printf("name:%s type:%d limit:%d manner:%d\n",dstsd->status.name,type,limit,dstsd->status.manner);
}
@@ -9628,7 +10173,7 @@ void clif_parse_GMReqNoChatCount(int fd, struct map_session_data *sd)
WFIFOW(fd,0) = 0x1e0;
WFIFOL(fd,2) = tid;
- sprintf(WFIFOP(fd,6),"%d",tid);
+ sprintf((char*)WFIFOP(fd,6),"%d",tid);
// memcpy(WFIFOP(fd,6), "TESTNAME", 24);
WFIFOSET(fd, packet_len_table[0x1e0]);
@@ -9642,14 +10187,14 @@ void clif_parse_PMIgnore(int fd, struct map_session_data *sd) { // Rewritten by
memset(output, '\0', sizeof(output));
- nick = RFIFOP(fd,2); // speed up
+ nick = (char*)RFIFOP(fd,2); // speed up
RFIFOB(fd,25) = '\0'; // to be sure that the player name have at maximum 23 characters
//printf("Ignore: char '%s' state: %d\n", nick, RFIFOB(fd,26));
WFIFOW(fd,0) = 0x0d1; // R 00d1 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
WFIFOB(fd,2) = RFIFOB(fd,26);
// do nothing only if nick can not exist
- if (strlen(nick) < 4) {
+ if (strlen(nick) < 4) {
WFIFOB(fd,3) = 1; // fail
WFIFOSET(fd, packet_len_table[0x0d1]);
if (RFIFOB(fd,26) == 0) // type
@@ -9669,7 +10214,7 @@ void clif_parse_PMIgnore(int fd, struct map_session_data *sd) { // Rewritten by
clif_wis_message(fd, wisp_server_name, "This player is already blocked.", strlen("This player is already blocked.") + 1);
if (strcmp(wisp_server_name, nick) == 0) { // to found possible bot users who automaticaly ignore people.
sprintf(output, "Character '%s' (account: %d) has tried AGAIN to block wisps from '%s' (wisp name of the server). Bot user?", sd->status.name, sd->status.account_id, wisp_server_name);
- intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output, strlen(output) + 1);
+ intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output);
}
return;
} else if (pos == -1 && sd->ignore[i].name[0] == '\0')
@@ -9682,7 +10227,7 @@ void clif_parse_PMIgnore(int fd, struct map_session_data *sd) { // Rewritten by
WFIFOSET(fd, packet_len_table[0x0d1]);
if (strcmp(wisp_server_name, nick) == 0) { // to found possible bot users who automaticaly ignore people.
sprintf(output, "Character '%s' (account: %d) has tried to block wisps from '%s' (wisp name of the server). Bot user?", sd->status.name, sd->status.account_id, wisp_server_name);
- intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output, strlen(output) + 1);
+ intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output);
// send something to be inform and force bot to ignore twice... If GM receiving block + block again, it's a bot :)
clif_wis_message(fd, wisp_server_name, "Add me in your ignore list, doesn't block my wisps.", strlen("Add me in your ignore list, doesn't block my wisps.") + 1);
}
@@ -9692,7 +10237,7 @@ void clif_parse_PMIgnore(int fd, struct map_session_data *sd) { // Rewritten by
clif_wis_message(fd, wisp_server_name, "You can not block more people.", strlen("You can not block more people.") + 1);
if (strcmp(wisp_server_name, nick) == 0) { // to found possible bot users who automaticaly ignore people.
sprintf(output, "Character '%s' (account: %d) has tried to block wisps from '%s' (wisp name of the server). Bot user?", sd->status.name, sd->status.account_id, wisp_server_name);
- intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output, strlen(output) + 1);
+ intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output);
}
}
// allow action (we remove all same nicks if they exist)
@@ -9701,7 +10246,7 @@ void clif_parse_PMIgnore(int fd, struct map_session_data *sd) { // Rewritten by
for(i = 0; i < MAX_IGNORE_LIST; i++)
if (strcmp(sd->ignore[i].name, nick) == 0) {
memset(sd->ignore[i].name, 0, sizeof(sd->ignore[i].name));
- if (pos != -1) {
+ if (pos == -1) {
WFIFOB(fd,3) = 0; // success
WFIFOSET(fd, packet_len_table[0x0d1]);
pos = i; // don't break, to remove ALL same nick
@@ -9753,6 +10298,38 @@ void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd) { // Rewritten
return;
}
+/*==========================================
+ * Wis拒否リスト
+ *------------------------------------------
+ */
+ int pstrcmp(const void *a, const void *b)
+{
+ return strcmp((char *)a, (char *)b);
+}
+void clif_parse_PMIgnoreList(int fd,struct map_session_data *sd)
+{
+ int i,j=0,count=0;
+
+ qsort (sd->ignore[0].name, MAX_IGNORE_LIST, sizeof(sd->ignore[0].name), pstrcmp);
+ for(i = 0; i < MAX_IGNORE_LIST; i++){ //中身があるのを数える
+ if(sd->ignore[i].name[0] != 0)
+ count++;
+ }
+ WFIFOW(fd,0) = 0xd4;
+ WFIFOW(fd,2) = 4 + (24 * count);
+ for(i = 0; i < MAX_IGNORE_LIST; i++){
+ if(sd->ignore[i].name[0] != 0){
+ memcpy(WFIFOP(fd, 4 + j * 24),sd->ignore[i].name, 24);
+ j++;
+ }
+ }
+ WFIFOSET(fd, WFIFOW(fd,2));
+ if(count >= MAX_IGNORE_LIST) //満タンなら最後の1個を消す
+ sd->ignore[MAX_IGNORE_LIST - 1].name[0] = 0;
+
+ return;
+}
+
void clif_parse_skillMessage(int fd, struct map_session_data *sd) { // Added by RoVeRT
int skillid,skilllv, x, y;
char *mes;
@@ -9763,7 +10340,7 @@ void clif_parse_skillMessage(int fd, struct map_session_data *sd) { // Added by
y = RFIFOB(fd,6);
x = RFIFOB(fd,8);
- mes = RFIFOP(fd,10);
+ mes = (char*)RFIFOP(fd,10);
// skill 220 = graffiti
// printf("skill: %d %d location: %3d %3d message: %s\n", skillid, skilllv, x, y, (char*)mes);
@@ -9795,11 +10372,11 @@ void clif_parse_sn_doridori(int fd, struct map_session_data *sd) {
* スパノビの爆裂波動
*------------------------------------------
*/
-void clif_parse_sn_explosionspirits(int fd, struct map_session_data *sd)
+void clif_parse_sn_explosionspirits(int fd, struct map_session_data *sd)
{
if(sd){
int nextbaseexp=pc_nextbaseexp(sd);
- struct pc_base_job s_class = pc_calc_base_job(sd->status.class);
+ struct pc_base_job s_class = pc_calc_base_job(sd->status.class_);
if (battle_config.etc_log){
if(nextbaseexp != 0)
printf("SuperNovice explosionspirits!! %d %d %d %d\n",sd->bl.id,s_class.job,sd->status.base_exp,(int)((double)1000*sd->status.base_exp/nextbaseexp));
@@ -9808,7 +10385,7 @@ void clif_parse_sn_explosionspirits(int fd, struct map_session_data *sd)
}
if(s_class.job == 23 && sd->status.base_exp > 0 && nextbaseexp > 0 && (int)((double)1000*sd->status.base_exp/nextbaseexp)%100==0){
clif_skill_nodamage(&sd->bl,&sd->bl,MO_EXPLOSIONSPIRITS,5,1);
- skill_status_change_start(&sd->bl,SkillStatusChangeTable[MO_EXPLOSIONSPIRITS],5,0,0,0,skill_get_time(MO_EXPLOSIONSPIRITS,5),0 );
+ status_change_start(&sd->bl,SkillStatusChangeTable[MO_EXPLOSIONSPIRITS],5,0,0,0,skill_get_time(MO_EXPLOSIONSPIRITS,5),0 );
}
}
return;
@@ -9839,7 +10416,7 @@ void clif_parse_friends_list_add(int fd, struct map_session_data *sd) {
struct map_session_data *f_sd;
int i;
- f_sd = map_nick2sd(RFIFOP(fd,2));
+ f_sd = map_nick2sd((char*)RFIFOP(fd,2));
// Friend doesn't exist (no player with this name)
if (f_sd == NULL) {
@@ -9917,9 +10494,28 @@ void clif_parse_GMkillall(int fd,struct map_session_data *sd)
return;
}
+/*==========================================
+ * パケットデバッグ
+ *------------------------------------------
+ */
+void clif_parse_debug(int fd,struct map_session_data *sd)
+{
+ int i, cmd;
+
+ cmd = RFIFOW(fd,0);
+
+ printf("packet debug 0x%4X\n",cmd);
+ printf("---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F");
+ for(i=0;i<packet_db[sd->packet_ver][cmd].len;i++){
+ if((i&15)==0)
+ printf("\n%04X ",i);
+ printf("%02X ",RFIFOB(fd,i));
+ }
+ printf("\n");
+}
+
// functions list
-static void (*clif_parse_func_table[7][0x220])() = {
- {
+static void (*clif_parse_func_table[MAX_PACKET_DB])(int, struct map_session_data *) = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -9951,11 +10547,11 @@ static void (*clif_parse_func_table[7][0x220])() = {
NULL, clif_parse_HowManyConnections, NULL, NULL, NULL, clif_parse_NpcBuySellSelected, NULL, NULL,
clif_parse_NpcBuyListSend, clif_parse_NpcSellListSend, NULL, NULL, clif_parse_GMKick, NULL, clif_parse_GMkillall, clif_parse_PMIgnore,
// d0
- clif_parse_PMIgnoreAll, NULL, NULL, NULL, NULL, clif_parse_CreateChatRoom, NULL, NULL,
+ clif_parse_PMIgnoreAll, NULL, NULL, clif_parse_PMIgnoreList, NULL, clif_parse_CreateChatRoom, NULL, NULL,
NULL, clif_parse_ChatAddMember, NULL, NULL, NULL, NULL, clif_parse_ChatRoomStatusChange, NULL,
// e0
clif_parse_ChangeChatOwner, NULL, clif_parse_KickFromChat, clif_parse_ChatLeave, clif_parse_TradeRequest, NULL, clif_parse_TradeAck, NULL,
- clif_parse_TradeAddItem, NULL, NULL, clif_parse_TradeOk, NULL, clif_parse_TradeCansel, NULL, clif_parse_TradeCommit,
+ clif_parse_TradeAddItem, NULL, NULL, clif_parse_TradeOk, NULL, clif_parse_TradeCancel, NULL, clif_parse_TradeCommit,
// f0
NULL, NULL, NULL, clif_parse_MoveToKafra, NULL, clif_parse_MoveFromKafra, NULL, clif_parse_CloseKafra,
NULL, clif_parse_CreateParty, NULL, NULL, clif_parse_PartyInvite, NULL, NULL, clif_parse_ReplyPartyInvite,
@@ -9975,7 +10571,7 @@ static void (*clif_parse_func_table[7][0x220])() = {
// 140
clif_parse_MapMove, NULL, NULL, clif_parse_NpcAmountInput, NULL, NULL, clif_parse_NpcCloseClicked, NULL,
- NULL, clif_parse_GMReqNoChat, NULL, NULL, NULL, clif_parse_GuildCheckMaster, NULL, clif_parse_GuildReqeustInfo,
+ NULL, clif_parse_GMReqNoChat, NULL, NULL, NULL, clif_parse_GuildCheckMaster, NULL, clif_parse_GuildRequestInfo,
// 150
NULL, clif_parse_GuildRequestEmblem, NULL, clif_parse_GuildChangeEmblem, NULL, clif_parse_GuildChangeMemberPosition, NULL, NULL,
NULL, clif_parse_GuildLeave, NULL, clif_parse_GuildExplusion, NULL, clif_parse_GuildBreak, NULL, NULL,
@@ -10010,7 +10606,8 @@ static void (*clif_parse_func_table[7][0x220])() = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, clif_parse_sn_doridori,
clif_parse_CreateParty2, NULL, NULL, NULL, NULL, clif_parse_sn_explosionspirits, NULL, NULL,
// 1f0
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, clif_parse_ReqAdopt,
+ NULL, NULL, NULL, NULL, NULL, NULL,
// 200
NULL, NULL, clif_parse_friends_list_add, clif_parse_friends_list_remove, NULL, NULL, NULL, NULL,
@@ -10020,13 +10617,6 @@ static void (*clif_parse_func_table[7][0x220])() = {
#if 0
case 0xd3: clif_parse_IgnoreList
#endif
- },
- {NULL},
- {NULL},
- {NULL},
- {NULL},
- {NULL},
- {NULL}
};
/*==========================================
@@ -10035,28 +10625,33 @@ static void (*clif_parse_func_table[7][0x220])() = {
*------------------------------------------
*/
static int clif_parse(int fd) {
- int packet_len = 0, cmd, packet_ver;
+ int packet_len = 0, cmd, packet_ver, dump = 0;
struct map_session_data *sd;
- sd = session[fd]->session_data;
+ sd = (struct map_session_data*)session[fd]->session_data;
// 接続が切れてるので後始末
if (!chrif_isconnect() || session[fd]->eof) { // char鯖に繋がってない間は接続禁止 (!chrif_isconnect())
if (sd && sd->state.auth) {
- if (chrif_isconnect())
- clif_quitsave(fd, sd);
+ clif_quitsave(fd, sd); // the function doesn't send to inter-server/char-server if it is not connected [Yor]
if (sd->status.name != NULL)
- printf("Player [%s] has logged off your server.\n", sd->status.name); // Player logout display [Valaris]
+ sprintf(tmp_output,"%sCharacter '"CL_WHITE"%s"CL_RESET"' logged off.\n", (pc_isGM(sd))?"GM ":"",sd->status.name); // Player logout display [Valaris]
else
- printf("Player with account [%d] has logged off your server.\n", sd->bl.id); // Player logout display [Yor]
+ sprintf(tmp_output,"%sCharacter with Account ID '"CL_WHITE"%d"CL_RESET"' logged off.\n", (pc_isGM(sd))?"GM ":"", sd->bl.id); // Player logout display [Yor]
} else if (sd) { // not authentified! (refused by char-server or disconnect before to be authentified)
- printf("Player with account [%d] has logged off your server (not auth account).\n", sd->bl.id); // Player logout display [Yor]
- map_deliddb(&sd->bl); // account_id has been included in the DB before auth answer
+ sprintf(tmp_output,"Player not authenticated with Account ID '"CL_WHITE"%d"CL_RESET"' logged off.\n", sd->bl.id); // Player logout display [Yor]
+// if (chrif_isconnect())
+// clif_quitsave(fd, sd);
+ map_deliddb(&sd->bl); // account_id has been included in the DB before auth answer [Yor]
+// sd = 0;
+ } else {
+ unsigned char *ip = (unsigned char *) &session[fd]->client_addr.sin_addr;
+ sprintf(tmp_output,"Player not identified with IP '"CL_WHITE"%d.%d.%d.%d"CL_RESET"' logged off.\n", ip[0],ip[1],ip[2],ip[3]);
}
+ ShowInfo(tmp_output);
close(fd);
- if (sd) // 追加
-
- map_deliddb(&sd->bl); // 追加
+// if (sd) // 追加
+// map_deliddb(&sd->bl); // 追加
delete_session(fd);
return 0;
}
@@ -10064,7 +10659,7 @@ static int clif_parse(int fd) {
if (RFIFOREST(fd) < 2)
return 0;
- //printf("clif_parse: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
+// printf("clif_parse: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
cmd = RFIFOW(fd,0);
@@ -10084,7 +10679,8 @@ static int clif_parse(int fd) {
RFIFOSKIP(fd,2);
break;
case 0x7532: // 接続の切断
- session[fd]->eof = 1;
+ close(fd);
+ session[fd]->eof=1;
break;
}
return 0;
@@ -10092,119 +10688,135 @@ static int clif_parse(int fd) {
// get packet version before to parse
packet_ver = 0;
- if (sd)
+ if (sd) {
packet_ver = sd->packet_ver;
+ if (packet_ver < 0 || packet_ver > MAX_PACKET_VER) { // unusual, but just in case
+ close(fd);
+ session[fd]->eof = 1;
+ printf("clif_parse: session #%d, bad packet version -> disconnected.\n", fd);
+ return 0;
+ }
// check authentification packet to know packet version
- else {
+ } else {
+ // packet DB
+ if (IS_PACKET_DB_VER (cmd)) {
+ if (RFIFOREST(fd) >= packet_db[clif_config.packet_db_ver][cmd].len &&
+ (RFIFOB(fd,packet_db[clif_config.packet_db_ver][cmd].pos[4]) == 0 ||
+ RFIFOB(fd,packet_db[clif_config.packet_db_ver][cmd].pos[4]) == 1)) {// 00 = Female, 01 = Male
+ packet_ver = clif_config.packet_db_ver;
+ }
// 0x72
- if (cmd == 0x72) {
+ } else if (cmd == 0x72) {
if (RFIFOREST(fd) >= 39 && (RFIFOB(fd,38) == 0 || RFIFOB(fd,38) == 1)) // 00 = Female, 01 = Male
- packet_ver = 7; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ packet_ver = 7; // 7: 13july04
else if (RFIFOREST(fd) >= 22 && (RFIFOB(fd,21) == 0 || RFIFOB(fd,21) == 1)) // 00 = Female, 01 = Male
- packet_ver = 6; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ packet_ver = 6; // 6: 7july04
else if (RFIFOREST(fd) >= 19 && (RFIFOB(fd,18) == 0 || RFIFOB(fd,18) == 1)) // 00 = Female, 01 = Male
- packet_ver = 5; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ packet_ver = 5; // 5: old
// else probably incomplete packet
else if (RFIFOREST(fd) < 19)
return 0;
// 0x7E
} else if (cmd == 0x7E) {
if (RFIFOREST(fd) >= 37 && (RFIFOB(fd,36) == 0 || RFIFOB(fd,36) == 1)) // 00 = Female, 01 = Male
- packet_ver = 9; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ packet_ver = 9; // 9: 9aug04/16aug04/17aug04
else if (RFIFOREST(fd) >= 33 && (RFIFOB(fd,32) == 0 || RFIFOB(fd,32) == 1)) // 00 = Female, 01 = Male
- packet_ver = 8; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ packet_ver = 8; // 8: 26july04
// else probably incomplete packet
else if (RFIFOREST(fd) < 33)
return 0;
// 0xF5
- } else {
+ } else if (cmd == 0xF5) {
if (RFIFOREST(fd) >= 34 && (RFIFOB(fd,33) == 0 || RFIFOB(fd,33) == 1)) // 00 = Female, 01 = Male
- packet_ver = 10; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ packet_ver = 10; // 10: 6sept04
else if (RFIFOREST(fd) >= 33 && (RFIFOB(fd,32) == 0 || RFIFOB(fd,32) == 1)) // 00 = Female, 01 = Male
- packet_ver = 12; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ packet_ver = 12; // 12: 18oct04
else if (RFIFOREST(fd) >= 32 && (RFIFOB(fd,31) == 0 || RFIFOB(fd,31) == 1)) // 00 = Female, 01 = Male
- packet_ver = 11; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
- else if (RFIFOREST(fd) >= 29 && (RFIFOB(fd,28) == 0 || RFIFOB(fd,28) == 1)) // 00 = Female, 01 = Male
- packet_ver = 13; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
+ packet_ver = 11; // 11: 21sept04
+ else if (RFIFOREST(fd) >= 29 && (RFIFOB(fd,28) == 0 || RFIFOB(fd,28) == 1)) { // 00 = Female, 01 = Male
+ if (RFIFOL(fd,3) > 700000 && RFIFOL(fd,10) >= 150000 && RFIFOL(fd,10) < 5000000) // account id / char id (more than 5.000.000 characters?) [Yor]
+ packet_ver = 15; // 14: 6dec04
+ else
+ packet_ver = 13; // 13: 25oct04 (by [Yor])
+ }
// else probably incomplete packet
else if (RFIFOREST(fd) < 29)
return 0;
+ // 0x9B
+ } else if (cmd == 0x9B) {
+ if (RFIFOREST(fd) >= 32 && (RFIFOB(fd,31) == 0 || RFIFOB(fd,31) == 1)) // 00 = Female, 01 = Male
+ packet_ver = 16; // 16: 10jan05
+ else if (RFIFOREST(fd) < 32)
+ return 0;
+ } else {
+ // unknown client? leave packet ver as 0 so it'll disconnect anyway
}
+
// check if version is accepted
- if ((packet_ver == 5 && (battle_config.packet_ver_flag & 1) == 0) ||
- (packet_ver == 6 && (battle_config.packet_ver_flag & 2) == 0) ||
- (packet_ver == 7 && (battle_config.packet_ver_flag & 4) == 0) ||
- (packet_ver == 8 && (battle_config.packet_ver_flag & 8) == 0) ||
- (packet_ver == 9 && (battle_config.packet_ver_flag & 16) == 0) ||
- (packet_ver == 10 && (battle_config.packet_ver_flag & 32) == 0) ||
- (packet_ver == 11 && (battle_config.packet_ver_flag & 64) == 0) ||
- (packet_ver == 12 && (battle_config.packet_ver_flag & 128) == 0) ||
- (packet_ver == 13 && (battle_config.packet_ver_flag & 256) == 0)) {
+ if (packet_ver < 5 || // reject really old client versions
+ (packet_ver <= 9 && (battle_config.packet_ver_flag & 1) == 0) || // older than 6sept04
+ (packet_ver == 10 && (battle_config.packet_ver_flag & 2) == 0) ||
+ (packet_ver == 11 && (battle_config.packet_ver_flag & 4) == 0) ||
+ (packet_ver == 12 && (battle_config.packet_ver_flag & 8) == 0) ||
+ (packet_ver == 13 && (battle_config.packet_ver_flag & 16) == 0) ||
+ (packet_ver == 14 && (battle_config.packet_ver_flag & 32) == 0) ||
+ (packet_ver == 15 && (battle_config.packet_ver_flag & 64) == 0) ||
+ (packet_ver == 16 && (battle_config.packet_ver_flag & 128) == 0) ||
+ packet_ver > MAX_PACKET_VER || // no packet version support yet
+ // identified version, but unknown client?
+ (!sd && packet_db[packet_ver][cmd].func != clif_parse_WantToConnection)) {
WFIFOW(fd,0) = 0x6a;
WFIFOB(fd,2) = 5; // 05 = Game's EXE is not the latest version
WFIFOSET(fd,23);
- session[fd]->eof = 1;
+ clif_setwaitclose(fd);
return 0;
}
}
// ゲーム用以外パケットか、認証を終える前に0072以外が来たら、切断する
- if (packet_ver < 5 || packet_ver > 13 || // if packet is not inside these values: session is incorrect?? or auth packet is unknown
- cmd >= 0x220 || packet_size_table[packet_ver-5][cmd] == 0) {
+ if (cmd >= MAX_PACKET_DB || packet_db[packet_ver][cmd].len == 0) { // if packet is not inside these values: session is incorrect?? or auth packet is unknown
if (!fd)
return 0;
+ close(fd);
session[fd]->eof = 1;
printf("clif_parse: session #%d, packet 0x%x (%d bytes received) -> disconnected.\n", fd, cmd, RFIFOREST(fd));
return 0;
}
// パケット長を計算
- packet_len = packet_size_table[packet_ver-5][cmd];
+ packet_len = packet_db[packet_ver][cmd].len;
if (packet_len == -1) {
if (RFIFOREST(fd) < 4)
return 0; // 可変長パケットで長さの所までデータが来てない
packet_len = RFIFOW(fd,2);
if (packet_len < 4 || packet_len > 32768) {
- session[fd]->eof = 1;
+ close(fd);
+ session[fd]->eof =1;
return 0;
}
}
if (RFIFOREST(fd) < packet_len)
return 0; // まだ1パケット分データが揃ってない
+ #if DUMP_ALL_PACKETS
+ dump = 1;
+ #endif
+
if (sd && sd->state.auth == 1 && sd->state.waitingdisconnect == 1) { // 切断待ちの場合パケットを処理しない
- } else if (packet_ver < 8 && clif_parse_func_table[0][cmd]) { // packet version 5-6-7 use same functions, but size are different
+ } else if (packet_db[packet_ver][cmd].func) { // packet version 5-6-7 use same functions, but size are different
// パケット処理
- clif_parse_func_table[0][cmd](fd, sd);
- } else if (packet_ver >= 8 && clif_parse_func_table[packet_ver - 7][cmd]) {
- // パケット処理
- clif_parse_func_table[packet_ver - 7][cmd](fd, sd);
+ packet_db[packet_ver][cmd].func(fd, sd);
} else {
// 不明なパケット
if (battle_config.error_log) {
- if (fd)
- printf("\nclif_parse: session #%d, packet 0x%x, lenght %d\n", fd, cmd, packet_len);
-#ifdef DUMP_UNKNOWN_PACKET
+#if DUMP_UNKNOWN_PACKET
{
int i;
FILE *fp;
char packet_txt[256] = "save/packet.txt";
time_t now;
- printf("---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F");
- for(i = 0; i < packet_len; i++) {
- if ((i & 15) == 0)
- printf("\n%04X ",i);
- printf("%02X ", RFIFOB(fd,i));
- }
- if (sd && sd->state.auth) {
- if (sd->status.name != NULL)
- printf("\nAccount ID %d, character ID %d, player name %s.\n",
- sd->status.account_id, sd->status.char_id, sd->status.name);
- else
- printf("\nAccount ID %d.\n", sd->bl.id);
- } else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified)
- printf("\nAccount ID %d.\n", sd->bl.id);
+ dump = 1;
if ((fp = fopen(packet_txt, "a")) == NULL) {
printf("clif.c: cant write [%s] !!! data is lost !!!\n", packet_txt);
@@ -10233,218 +10845,618 @@ static int clif_parse(int fd) {
#endif
}
}
+
+ if (dump) {
+ int i;
+ if (fd)
+ printf("\nclif_parse: session #%d, packet 0x%x, lenght %d\n", fd, cmd, packet_len);
+ printf("---- 00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F");
+ for(i = 0; i < packet_len; i++) {
+ if ((i & 15) == 0)
+ printf("\n%04X ",i);
+ printf("%02X ", RFIFOB(fd,i));
+ }
+ if (sd && sd->state.auth) {
+ if (sd->status.name != NULL)
+ printf("\nAccount ID %d, character ID %d, player name %s.\n",
+ sd->status.account_id, sd->status.char_id, sd->status.name);
+ else
+ printf("\nAccount ID %d.\n", sd->bl.id);
+ } else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified)
+ printf("\nAccount ID %d.\n", sd->bl.id);
+ }
+
RFIFOSKIP(fd, packet_len);
return 0;
}
/*==========================================
+ * パケットデータベース読み込み
+ *------------------------------------------
+ */
+static int packetdb_readdb(void)
+{
+ FILE *fp;
+ char line[1024];
+ int ln=0;
+ int cmd,j,k,packet_ver;
+ char *str[64],*p,*str2[64],*p2,w1[64],w2[64];
+
+ struct {
+ void (*func)(int, struct map_session_data *);
+ char *name;
+ } clif_parse_func[]={
+ {clif_parse_WantToConnection,"wanttoconnection"},
+ {clif_parse_LoadEndAck,"loadendack"},
+ {clif_parse_TickSend,"ticksend"},
+ {clif_parse_WalkToXY,"walktoxy"},
+ {clif_parse_QuitGame,"quitgame"},
+ {clif_parse_GetCharNameRequest,"getcharnamerequest"},
+ {clif_parse_GlobalMessage,"globalmessage"},
+ {clif_parse_MapMove,"mapmove"},
+ {clif_parse_ChangeDir,"changedir"},
+ {clif_parse_Emotion,"emotion"},
+ {clif_parse_HowManyConnections,"howmanyconnections"},
+ {clif_parse_ActionRequest,"actionrequest"},
+ {clif_parse_Restart,"restart"},
+ {clif_parse_Wis,"wis"},
+ {clif_parse_GMmessage,"gmmessage"},
+ {clif_parse_TakeItem,"takeitem"},
+ {clif_parse_DropItem,"dropitem"},
+ {clif_parse_UseItem,"useitem"},
+ {clif_parse_EquipItem,"equipitem"},
+ {clif_parse_UnequipItem,"unequipitem"},
+ {clif_parse_NpcClicked,"npcclicked"},
+ {clif_parse_NpcBuySellSelected,"npcbuysellselected"},
+ {clif_parse_NpcBuyListSend,"npcbuylistsend"},
+ {clif_parse_NpcSellListSend,"npcselllistsend"},
+ {clif_parse_CreateChatRoom,"createchatroom"},
+ {clif_parse_ChatAddMember,"chataddmember"},
+ {clif_parse_ChatRoomStatusChange,"chatroomstatuschange"},
+ {clif_parse_ChangeChatOwner,"changechatowner"},
+ {clif_parse_KickFromChat,"kickfromchat"},
+ {clif_parse_ChatLeave,"chatleave"},
+ {clif_parse_TradeRequest,"traderequest"},
+ {clif_parse_TradeAck,"tradeack"},
+ {clif_parse_TradeAddItem,"tradeadditem"},
+ {clif_parse_TradeOk,"tradeok"},
+ {clif_parse_TradeCancel,"tradecancel"},
+ {clif_parse_TradeCommit,"tradecommit"},
+ {clif_parse_StopAttack,"stopattack"},
+ {clif_parse_PutItemToCart,"putitemtocart"},
+ {clif_parse_GetItemFromCart,"getitemfromcart"},
+ {clif_parse_RemoveOption,"removeoption"},
+ {clif_parse_ChangeCart,"changecart"},
+ {clif_parse_StatusUp,"statusup"},
+ {clif_parse_SkillUp,"skillup"},
+ {clif_parse_UseSkillToId,"useskilltoid"},
+ {clif_parse_UseSkillToPos,"useskilltopos"},
+ {clif_parse_UseSkillMap,"useskillmap"},
+ {clif_parse_RequestMemo,"requestmemo"},
+ {clif_parse_ProduceMix,"producemix"},
+ {clif_parse_NpcSelectMenu,"npcselectmenu"},
+ {clif_parse_NpcNextClicked,"npcnextclicked"},
+ {clif_parse_NpcAmountInput,"npcamountinput"},
+ {clif_parse_NpcStringInput,"npcstringinput"},
+ {clif_parse_NpcCloseClicked,"npccloseclicked"},
+ {clif_parse_ItemIdentify,"itemidentify"},
+ {clif_parse_SelectArrow,"selectarrow"},
+ {clif_parse_AutoSpell,"autospell"},
+ {clif_parse_UseCard,"usecard"},
+ {clif_parse_InsertCard,"insertcard"},
+ {clif_parse_SolveCharName,"solvecharname"},
+ {clif_parse_ResetChar,"resetchar"},
+ {clif_parse_LGMmessage,"lgmmessage"},
+ {clif_parse_MoveToKafra,"movetokafra"},
+ {clif_parse_MoveFromKafra,"movefromkafra"},
+ {clif_parse_MoveToKafraFromCart,"movetokafrafromcart"},
+ {clif_parse_MoveFromKafraToCart,"movefromkafratocart"},
+ {clif_parse_CloseKafra,"closekafra"},
+ {clif_parse_CreateParty,"createparty"},
+ {clif_parse_CreateParty2,"createparty2"},
+ {clif_parse_PartyInvite,"partyinvite"},
+ {clif_parse_ReplyPartyInvite,"replypartyinvite"},
+ {clif_parse_LeaveParty,"leaveparty"},
+ {clif_parse_RemovePartyMember,"removepartymember"},
+ {clif_parse_PartyChangeOption,"partychangeoption"},
+ {clif_parse_PartyMessage,"partymessage"},
+ {clif_parse_CloseVending,"closevending"},
+ {clif_parse_VendingListReq,"vendinglistreq"},
+ {clif_parse_PurchaseReq,"purchasereq"},
+ {clif_parse_OpenVending,"openvending"},
+ {clif_parse_CreateGuild,"createguild"},
+ {clif_parse_GuildCheckMaster,"guildcheckmaster"},
+ {clif_parse_GuildRequestInfo,"guildrequestinfo"},
+ {clif_parse_GuildChangePositionInfo,"guildchangepositioninfo"},
+ {clif_parse_GuildChangeMemberPosition,"guildchangememberposition"},
+ {clif_parse_GuildRequestEmblem,"guildrequestemblem"},
+ {clif_parse_GuildChangeEmblem,"guildchangeemblem"},
+ {clif_parse_GuildChangeNotice,"guildchangenotice"},
+ {clif_parse_GuildInvite,"guildinvite"},
+ {clif_parse_GuildReplyInvite,"guildreplyinvite"},
+ {clif_parse_GuildLeave,"guildleave"},
+ {clif_parse_GuildExplusion,"guildexplusion"},
+ {clif_parse_GuildMessage,"guildmessage"},
+ {clif_parse_GuildRequestAlliance,"guildrequestalliance"},
+ {clif_parse_GuildReplyAlliance,"guildreplyalliance"},
+ {clif_parse_GuildDelAlliance,"guilddelalliance"},
+ {clif_parse_GuildOpposition,"guildopposition"},
+ {clif_parse_GuildBreak,"guildbreak"},
+ {clif_parse_PetMenu,"petmenu"},
+ {clif_parse_CatchPet,"catchpet"},
+ {clif_parse_SelectEgg,"selectegg"},
+ {clif_parse_SendEmotion,"sendemotion"},
+ {clif_parse_ChangePetName,"changepetname"},
+ {clif_parse_GMKick,"gmkick"},
+ {clif_parse_GMHide,"gmhide"},
+ {clif_parse_GMReqNoChat,"gmreqnochat"},
+ {clif_parse_GMReqNoChatCount,"gmreqnochatcount"},
+ {clif_parse_sn_doridori,"sndoridori"},
+ {clif_parse_sn_explosionspirits,"snexplosionspirits"},
+ {clif_parse_PMIgnore,"wisexin"},
+ {clif_parse_PMIgnoreList,"wisexlist"},
+ {clif_parse_PMIgnoreAll,"wisall"},
+ {clif_parse_friends_list_add,"friendslistadd"},
+ {clif_parse_friends_list_remove,"friendslistremove"},
+ {clif_parse_GMkillall,"killall"},
+ {clif_parse_Recall,"summon"},
+ {clif_parse_GM_Monster_Item,"itemmonster"},
+ {clif_parse_Shift,"shift"},
+ {clif_parse_debug,"debug"},
+
+ {NULL,NULL}
+ };
+
+ if( (fp=fopen("db/packet_db.txt","r"))==NULL ){
+ printf("can't read db/packet_db.txt\n");
+ return 1;
+ }
+
+ clif_config.packet_db_ver = MAX_PACKET_VER;
+ packet_ver = MAX_PACKET_VER; // read into packet_db's version by default
+
+ while(fgets(line,1020,fp)){
+ if(line[0]=='/' && line[1]=='/')
+ continue;
+ if (sscanf(line,"%[^:]: %[^\r\n]",w1,w2) == 2) {
+ if(strcmpi(w1,"packet_ver")==0) {
+ packet_ver = atoi(w2);
+ // copy from previous version into new version and continue
+ // - indicating all following packets should be read into the newer version
+ // -- on 2nd thought, rereading everything isn't the best thing to do...
+ // memcpy(&packet_db[packet_ver], &packet_db[packet_ver - 1], sizeof(packet_db[0]));
+ continue;
+ } else if(strcmpi(w1,"packet_db_ver")==0) {
+ // optional: if you do not wish to read multiple versions from the packet_db,
+ // remove all "packet_ver: ##" lines, and define the packet DB version with this
+ if(strcmpi(w2,"default")==0)
+ clif_config.packet_db_ver = MAX_PACKET_VER;
+ else {
+ // to manually set the packet DB version
+ clif_config.packet_db_ver = atoi(w2);
+ // check for invalid version
+ if (clif_config.packet_db_ver > MAX_PACKET_VER ||
+ clif_config.packet_db_ver < 0)
+ clif_config.packet_db_ver = MAX_PACKET_VER;
+ }
+ continue;
+ } else if(strcmpi(w1,"enable_packet_db")==0) {
+ // whether we want to allow identifying clients via the packet DB
+ clif_config.enable_packet_db = battle_config_switch(w2);
+ // if we don't want to read the packet DB, and use hardcoded values only
+ if (!clif_config.enable_packet_db)
+ return 0;
+ continue;
+ } else if(strcmpi(w1,"prefer_packet_db")==0) {
+ // whether the packet DB takes higher precedence over the hardcoded one (type 1)
+ // and whether to overwrite predefined packet length and functions when reading
+ // from the DB (type 2)
+ clif_config.prefer_packet_db = battle_config_switch(w2); // not used for now
+ continue;
+ }
+ }
+
+ memset(str,0,sizeof(str));
+ for(j=0,p=line;j<4 && p;j++){
+ str[j]=p;
+ p=strchr(p,',');
+ if(p) *p++=0;
+ }
+ if(str[0]==NULL)
+ continue;
+ cmd=strtol(str[0],(char **)NULL,0);
+ if(cmd<=0 || cmd>=MAX_PACKET_DB)
+ continue;
+ if(str[1]==NULL){
+ sprintf(tmp_output, "packet_db: packet len error\n");
+ ShowError(tmp_output);
+ continue;
+ }
+ k = atoi(str[1]);
+ // if (packet_db[packet_ver][cmd].len != k && clif_config.prefer_packet_db) // not used for now
+ packet_db[packet_ver][cmd].len = k;
+
+ if(str[2]==NULL){
+ ln++;
+ continue;
+ }
+ for(j=0;j<sizeof(clif_parse_func)/sizeof(clif_parse_func[0]);j++){
+ if(clif_parse_func[j].name != NULL &&
+ strcmp(str[2],clif_parse_func[j].name)==0){
+ // if (packet_db[packet_ver][cmd].func != clif_parse_func[j].func && !clif_config.prefer_packet_db)
+ // break; // not used for now
+ packet_db[packet_ver][cmd].func = clif_parse_func[j].func;
+ break;
+ }
+ }
+ // set the identifying cmd for the packet_db version
+ if (strcmp(str[2],"wanttoconnection")==0){
+ clif_config.connect_cmd = cmd;
+ }
+ if(str[3]==NULL){
+ sprintf(tmp_output, "packet_db: packet error\n");
+ ShowError(tmp_output);
+ exit(1);
+ }
+ for(j=0,p2=str[3];p2;j++){
+ str2[j]=p2;
+ p2=strchr(p2,':');
+ if(p2) *p2++=0;
+ k = atoi(str2[j]);
+ // if (packet_db[packet_ver][cmd].pos[j] != k && clif_config.prefer_packet_db) // not used for now
+ packet_db[packet_ver][cmd].pos[j] = k;
+ }
+
+ ln++;
+// if(packet_db[clif_config.packet_db_ver][cmd].len > 2 /* && packet_db[cmd].pos[0] == 0 */)
+// printf("packet_db ver %d: %d 0x%x %d %s %p\n",packet_ver,ln,cmd,packet_db[packet_ver][cmd].len,str[2],packet_db[packet_ver][cmd].func);
+ }
+
+ fclose(fp);
+ sprintf(tmp_output,"Done reading packet version '"CL_WHITE"%d"CL_RESET"' in '"CL_WHITE"%s"CL_RESET"'.\n", clif_config.packet_db_ver, "db/packet_db.txt");
+ ShowStatus(tmp_output);
+ return 0;
+
+}
+
+/*==========================================
*
*------------------------------------------
*/
int do_init_clif(void) {
-#ifndef __WIN32
int i;
-#endif
+ clif_config.enable_packet_db = 1; // whether to use the packet DB for client connection
+ clif_config.packet_db_ver = -1; // the main packet version of the DB
+ clif_config.prefer_packet_db = 1; // whether the packet version takes precedence
+ clif_config.connect_cmd = 0xF5; // the default packet used for connecting to the server
+
+ memset(packet_db,0,sizeof(packet_db));
+
+ // size of packet version 5 (old)
+ for(i=0;i<sizeof(packet_len_table)/sizeof(packet_len_table[0]);i++){
+ packet_db[0][i].len = packet_len_table[i];
+ }
+ // packet functions of version 5 (old)
+ for(i=0;i<sizeof(clif_parse_func_table)/sizeof(clif_parse_func_table[0]);i++){
+ packet_db[0][i].func = clif_parse_func_table[i];
+ }
+
+ // using hardcoded packet values isn't necessary with packet_db now,
+ // but... just in case, i'll leave it to initialise for now ^^;
+ // init packet version 5 and lower
+ memcpy(&packet_db[1], &packet_db[0], sizeof(packet_db[0]));
+ memcpy(&packet_db[2], &packet_db[1], sizeof(packet_db[0]));
+ memcpy(&packet_db[3], &packet_db[2], sizeof(packet_db[0]));
+ memcpy(&packet_db[4], &packet_db[3], sizeof(packet_db[0]));
+ memcpy(&packet_db[5], &packet_db[4], sizeof(packet_db[0]));
+
+#ifndef PREFER_PACKET_DB
// functions of packet version 5-6-7 are same, but size are different
+ // size of packet version 6 (7july04)
+ memcpy(&packet_db[6], &packet_db[5], sizeof(packet_db[0]));
+ packet_db[6][0x072].len = 22;
+ packet_db[6][0x085].len = 8;
+ packet_db[6][0x0a7].len = 13;
+ packet_db[6][0x113].len = 15;
+ packet_db[6][0x116].len = 15;
+ packet_db[6][0x190].len = 95;
+ // size of packet version 7 (13july04)
+ memcpy(&packet_db[7], &packet_db[6], sizeof(packet_db[0]));
+ packet_db[7][0x072].len = 39;
+ packet_db[7][0x085].len = 9;
+ packet_db[7][0x09b].len = 13;
+ packet_db[7][0x09f].len = 10;
+ packet_db[7][0x0a7].len = 17;
+ packet_db[7][0x113].len = 19;
+ packet_db[7][0x116].len = 19;
+ packet_db[7][0x190].len = 99;
// init packet function calls for packet ver 8
- memcpy(clif_parse_func_table[1], clif_parse_func_table[0], sizeof(clif_parse_func_table[0]));
- clif_parse_func_table[1][0x072] = clif_parse_DropItem;
- clif_parse_func_table[1][0x07e] = clif_parse_WantToConnection;
- clif_parse_func_table[1][0x085] = clif_parse_UseSkillToId;
- clif_parse_func_table[1][0x089] = clif_parse_GetCharNameRequest;
- clif_parse_func_table[1][0x08c] = clif_parse_UseSkillToPos;
- clif_parse_func_table[1][0x094] = clif_parse_TakeItem;
- clif_parse_func_table[1][0x09b] = clif_parse_WalkToXY;
- clif_parse_func_table[1][0x09f] = clif_parse_ChangeDir;
- clif_parse_func_table[1][0x0a2] = clif_parse_UseSkillToPos;
- clif_parse_func_table[1][0x0a7] = clif_parse_SolveCharName;
- clif_parse_func_table[1][0x0f3] = clif_parse_GlobalMessage;
- clif_parse_func_table[1][0x0f5] = clif_parse_UseItem;
- clif_parse_func_table[1][0x0f7] = clif_parse_TickSend;
- clif_parse_func_table[1][0x113] = clif_parse_MoveToKafra;
- clif_parse_func_table[1][0x116] = clif_parse_CloseKafra;
- clif_parse_func_table[1][0x190] = clif_parse_MoveFromKafra;
- clif_parse_func_table[1][0x193] = clif_parse_ActionRequest;
+ memcpy(packet_db[8], packet_db[7], sizeof(packet_db[0]));
+ packet_db[8][0x072].func = clif_parse_DropItem;
+ packet_db[8][0x07e].func = clif_parse_WantToConnection;
+ packet_db[8][0x085].func = clif_parse_UseSkillToId;
+ packet_db[8][0x089].func = clif_parse_GetCharNameRequest;
+ packet_db[8][0x08c].func = clif_parse_UseSkillToPos;
+ packet_db[8][0x094].func = clif_parse_TakeItem;
+ packet_db[8][0x09b].func = clif_parse_WalkToXY;
+ packet_db[8][0x09f].func = clif_parse_ChangeDir;
+ packet_db[8][0x0a2].func = clif_parse_UseSkillToPos;
+ packet_db[8][0x0a7].func = clif_parse_SolveCharName;
+ packet_db[8][0x0f3].func = clif_parse_GlobalMessage;
+ packet_db[8][0x0f5].func = clif_parse_UseItem;
+ packet_db[8][0x0f7].func = clif_parse_TickSend;
+ packet_db[8][0x113].func = clif_parse_MoveToKafra;
+ packet_db[8][0x116].func = clif_parse_CloseKafra;
+ packet_db[8][0x190].func = clif_parse_MoveFromKafra;
+ packet_db[8][0x193].func = clif_parse_ActionRequest;
+ // size of packet version 8 (26july04)
+ packet_db[8][0x072].len = 14;
+ packet_db[8][0x07e].len = 33;
+ packet_db[8][0x085].len = 20;
+ packet_db[8][0x089].len = 15;
+ packet_db[8][0x08c].len = 23;
+ packet_db[8][0x094].len = 10;
+ packet_db[8][0x09b].len = 6;
+ packet_db[8][0x09f].len = 13;
+ packet_db[8][0x0a2].len = 103;
+ packet_db[8][0x0a7].len = 12;
+ packet_db[8][0x0f3].len = -1;
+ packet_db[8][0x0f5].len = 17;
+ packet_db[8][0x0f7].len = 10;
+ packet_db[8][0x113].len = 16;
+ packet_db[8][0x116].len = 2;
+ packet_db[8][0x190].len = 26;
+ packet_db[8][0x193].len = 9;
// init packet function calls for packet ver 9 (same function of packet version 8, but size are different)
- memcpy(clif_parse_func_table[2], clif_parse_func_table[1], sizeof(clif_parse_func_table[0]));
+ memcpy(packet_db[9], packet_db[8], sizeof(packet_db[0]));
+ // size of packet version 9 (9aug04/16aug04/17aug04)
+ packet_db[9][0x072].len = 17;
+ packet_db[9][0x07e].len = 37;
+ packet_db[9][0x085].len = 26;
+ packet_db[9][0x089].len = 12;
+ packet_db[9][0x08c].len = 40;
+ packet_db[9][0x094].len = 13;
+ packet_db[9][0x09b].len = 15;
+ packet_db[9][0x09f].len = 12;
+ packet_db[9][0x0a2].len = 120;
+ packet_db[9][0x0a7].len = 11;
+// packet_db[9][0x0f3].len = -1;
+ packet_db[9][0x0f5].len = 24;
+ packet_db[9][0x0f7].len = 13;
+ packet_db[9][0x113].len = 23;
+// packet_db[9][0x116].len = 2;
+ packet_db[9][0x190].len = 26;
+ packet_db[9][0x193].len = 18;
+ // new packet
+ packet_db[9][0x20f].len = 10;
+ packet_db[9][0x210].len = 22;
+ packet_db[9][0x212].len = 26;
+ packet_db[9][0x213].len = 26;
+ packet_db[9][0x214].len = 42;
// init packet function calls for packet ver 10
- memcpy(clif_parse_func_table[3], clif_parse_func_table[2], sizeof(clif_parse_func_table[0]));
- clif_parse_func_table[3][0x072] = clif_parse_UseItem;
- clif_parse_func_table[3][0x07e] = clif_parse_MoveToKafra;
- clif_parse_func_table[3][0x085] = clif_parse_ActionRequest;
- clif_parse_func_table[3][0x089] = clif_parse_WalkToXY;
- clif_parse_func_table[3][0x08c] = clif_parse_UseSkillToPos;
- clif_parse_func_table[3][0x094] = clif_parse_DropItem;
- clif_parse_func_table[3][0x09b] = clif_parse_GetCharNameRequest;
- clif_parse_func_table[3][0x09f] = clif_parse_GlobalMessage;
- clif_parse_func_table[3][0x0a2] = clif_parse_SolveCharName;
- clif_parse_func_table[3][0x0a7] = clif_parse_UseSkillToPos;
- clif_parse_func_table[3][0x0f3] = clif_parse_ChangeDir;
- clif_parse_func_table[3][0x0f5] = clif_parse_WantToConnection;
- clif_parse_func_table[3][0x0f7] = clif_parse_CloseKafra;
- clif_parse_func_table[3][0x113] = clif_parse_TakeItem;
- clif_parse_func_table[3][0x116] = clif_parse_TickSend;
- clif_parse_func_table[3][0x190] = clif_parse_UseSkillToId;
- clif_parse_func_table[3][0x193] = clif_parse_MoveFromKafra;
+ memcpy(packet_db[10], packet_db[9], sizeof(packet_db[0]));
+ packet_db[10][0x072].func = clif_parse_UseItem;
+ packet_db[10][0x07e].func = clif_parse_MoveToKafra;
+ packet_db[10][0x085].func = clif_parse_ActionRequest;
+ packet_db[10][0x089].func = clif_parse_WalkToXY;
+ packet_db[10][0x08c].func = clif_parse_UseSkillToPos;
+ packet_db[10][0x094].func = clif_parse_DropItem;
+ packet_db[10][0x09b].func = clif_parse_GetCharNameRequest;
+ packet_db[10][0x09f].func = clif_parse_GlobalMessage;
+ packet_db[10][0x0a2].func = clif_parse_SolveCharName;
+ packet_db[10][0x0a7].func = clif_parse_UseSkillToPos;
+ packet_db[10][0x0f3].func = clif_parse_ChangeDir;
+ packet_db[10][0x0f5].func = clif_parse_WantToConnection;
+ packet_db[10][0x0f7].func = clif_parse_CloseKafra;
+ packet_db[10][0x113].func = clif_parse_TakeItem;
+ packet_db[10][0x116].func = clif_parse_TickSend;
+ packet_db[10][0x190].func = clif_parse_UseSkillToId;
+ packet_db[10][0x193].func = clif_parse_MoveFromKafra;
+ // size of packet version 10 (6sept04)
+ packet_db[10][0x072].len = 20;
+ packet_db[10][0x07e].len = 19;
+ packet_db[10][0x085].len = 23;
+ packet_db[10][0x089].len = 9;
+ packet_db[10][0x08c].len = 105;
+ packet_db[10][0x094].len = 17;
+ packet_db[10][0x09b].len = 14;
+ packet_db[10][0x09f].len = -1;
+ packet_db[10][0x0a2].len = 14;
+ packet_db[10][0x0a7].len = 25;
+ packet_db[10][0x0f3].len = 10;
+ packet_db[10][0x0f5].len = 34;
+ packet_db[10][0x0f7].len = 2;
+ packet_db[10][0x113].len = 11;
+ packet_db[10][0x116].len = 11;
+ packet_db[10][0x190].len = 22;
+ packet_db[10][0x193].len = 17;
// init packet function calls for packet ver 11 (same function of packet version 10, but size are different)
- memcpy(clif_parse_func_table[4], clif_parse_func_table[3], sizeof(clif_parse_func_table[0]));
+ memcpy(packet_db[11], packet_db[10], sizeof(packet_db[0]));
+ // size of packet version 11 (21sept04)
+ packet_db[11][0x072].len = 18;
+ packet_db[11][0x07e].len = 25;
+ packet_db[11][0x085].len = 9;
+ packet_db[11][0x089].len = 14;
+ packet_db[11][0x08c].len = 109;
+ packet_db[11][0x094].len = 19;
+ packet_db[11][0x09b].len = 10;
+// packet_db[11][0x09f].len = -1;
+ packet_db[11][0x0a2].len = 10;
+ packet_db[11][0x0a7].len = 29;
+ packet_db[11][0x0f3].len = 18;
+ packet_db[11][0x0f5].len = 32;
+// packet_db[11][0x0f7].len = 2;
+ packet_db[11][0x113].len = 14;
+ packet_db[11][0x116].len = 14;
+ packet_db[11][0x190].len = 14;
+ packet_db[11][0x193].len = 12;
// init packet function calls for packet ver 12 (same function of packet version 11, but size are different)
- memcpy(clif_parse_func_table[5], clif_parse_func_table[4], sizeof(clif_parse_func_table[0]));
+ memcpy(packet_db[12], packet_db[11], sizeof(packet_db[0]));
+ // size of packet version 12 (18oct04)
+ packet_db[12][0x072].len = 17;
+ packet_db[12][0x07e].len = 16;
+// packet_db[12][0x085].len = 9;
+ packet_db[12][0x089].len = 6;
+ packet_db[12][0x08c].len = 103;
+ packet_db[12][0x094].len = 14;
+ packet_db[12][0x09b].len = 15;
+// packet_db[12][0x09f].len = -1;
+ packet_db[12][0x0a2].len = 12;
+ packet_db[12][0x0a7].len = 23;
+ packet_db[12][0x0f3].len = 13;
+ packet_db[12][0x0f5].len = 33;
+// packet_db[12][0x0f7].len = 2;
+ packet_db[12][0x113].len = 10;
+ packet_db[12][0x116].len = 10;
+ packet_db[12][0x190].len = 20;
+ packet_db[12][0x193].len = 26;
// init packet function calls for packet ver 13 (same function of packet version 12, but size are different)
- memcpy(clif_parse_func_table[6], clif_parse_func_table[5], sizeof(clif_parse_func_table[0]));
-
- // size of packet version 5
- memcpy(&packet_size_table[0], &packet_len_table, sizeof(packet_len_table));
- // size of packet version 6
- memcpy(&packet_size_table[1], &packet_size_table[0], sizeof(packet_len_table));
- packet_size_table[1][0x072] = 22;
- packet_size_table[1][0x085] = 8;
- packet_size_table[1][0x0a7] = 13;
- packet_size_table[1][0x113] = 15;
- packet_size_table[1][0x116] = 15;
- packet_size_table[1][0x190] = 95;
- // size of packet version 7
- memcpy(&packet_size_table[2], &packet_size_table[1], sizeof(packet_len_table));
- packet_size_table[2][0x072] = 39;
- packet_size_table[2][0x085] = 9;
- packet_size_table[2][0x09b] = 13;
- packet_size_table[2][0x09f] = 10;
- packet_size_table[2][0x0a7] = 17;
- packet_size_table[2][0x113] = 19;
- packet_size_table[2][0x116] = 19;
- packet_size_table[2][0x190] = 99;
- // size of packet version 8
- memcpy(&packet_size_table[3], &packet_size_table[2], sizeof(packet_len_table));
- packet_size_table[3][0x072] = 14;
- packet_size_table[3][0x07e] = 33;
- packet_size_table[3][0x085] = 20;
- packet_size_table[3][0x089] = 15;
- packet_size_table[3][0x08c] = 23;
- packet_size_table[3][0x094] = 10;
- packet_size_table[3][0x09b] = 6;
- packet_size_table[3][0x09f] = 13;
- packet_size_table[3][0x0a2] = 103;
- packet_size_table[3][0x0a7] = 12;
- packet_size_table[3][0x0f3] = -1;
- packet_size_table[3][0x0f5] = 17;
- packet_size_table[3][0x0f7] = 10;
- packet_size_table[3][0x113] = 16;
- packet_size_table[3][0x116] = 2;
- packet_size_table[3][0x190] = 26;
- packet_size_table[3][0x193] = 9;
- // size of packet version 9
- memcpy(&packet_size_table[4], &packet_size_table[3], sizeof(packet_len_table));
- packet_size_table[4][0x072] = 17;
- packet_size_table[4][0x07e] = 37;
- packet_size_table[4][0x085] = 26;
- packet_size_table[4][0x089] = 12;
- packet_size_table[4][0x08c] = 40;
- packet_size_table[4][0x094] = 13;
- packet_size_table[4][0x09b] = 15;
- packet_size_table[4][0x09f] = 12;
- packet_size_table[4][0x0a2] = 120;
- packet_size_table[4][0x0a7] = 11;
-// packet_size_table[4][0x0f3] = -1;
- packet_size_table[4][0x0f5] = 24;
- packet_size_table[4][0x0f7] = 13;
- packet_size_table[4][0x113] = 23;
-// packet_size_table[4][0x116] = 2;
- packet_size_table[4][0x190] = 26;
- packet_size_table[4][0x193] = 18;
- // new packet
- packet_size_table[4][0x20f] = 10;
- packet_size_table[4][0x210] = 22;
- packet_size_table[4][0x212] = 26;
- packet_size_table[4][0x213] = 26;
- packet_size_table[4][0x214] = 42;
- // size of packet version 10
- memcpy(&packet_size_table[5], &packet_size_table[4], sizeof(packet_len_table));
- packet_size_table[5][0x072] = 20;
- packet_size_table[5][0x07e] = 19;
- packet_size_table[5][0x085] = 23;
- packet_size_table[5][0x089] = 9;
- packet_size_table[5][0x08c] = 105;
- packet_size_table[5][0x094] = 17;
- packet_size_table[5][0x09b] = 14;
- packet_size_table[5][0x09f] = -1;
- packet_size_table[5][0x0a2] = 14;
- packet_size_table[5][0x0a7] = 25;
- packet_size_table[5][0x0f3] = 10;
- packet_size_table[5][0x0f5] = 34;
- packet_size_table[5][0x0f7] = 2;
- packet_size_table[5][0x113] = 11;
- packet_size_table[5][0x116] = 11;
- packet_size_table[5][0x190] = 22;
- packet_size_table[5][0x193] = 17;
- // size of packet version 11
- memcpy(&packet_size_table[6], &packet_size_table[5], sizeof(packet_len_table));
- packet_size_table[6][0x072] = 18;
- packet_size_table[6][0x07e] = 25;
- packet_size_table[6][0x085] = 9;
- packet_size_table[6][0x089] = 14;
- packet_size_table[6][0x08c] = 109;
- packet_size_table[6][0x094] = 19;
- packet_size_table[6][0x09b] = 10;
-// packet_size_table[6][0x09f] = -1;
- packet_size_table[6][0x0a2] = 10;
- packet_size_table[6][0x0a7] = 29;
- packet_size_table[6][0x0f3] = 18;
- packet_size_table[6][0x0f5] = 32;
-// packet_size_table[6][0x0f7] = 2;
- packet_size_table[6][0x113] = 14;
- packet_size_table[6][0x116] = 14;
- packet_size_table[6][0x190] = 14;
- packet_size_table[6][0x193] = 12;
- // size of packet version 12
- memcpy(&packet_size_table[7], &packet_size_table[6], sizeof(packet_len_table));
- packet_size_table[7][0x072] = 17;
- packet_size_table[7][0x07e] = 16;
-// packet_size_table[7][0x085] = 9;
- packet_size_table[7][0x089] = 6;
- packet_size_table[7][0x08c] = 103;
- packet_size_table[7][0x094] = 14;
- packet_size_table[7][0x09b] = 15;
-// packet_size_table[7][0x09f] = -1;
- packet_size_table[7][0x0a2] = 12;
- packet_size_table[7][0x0a7] = 23;
- packet_size_table[7][0x0f3] = 13;
- packet_size_table[7][0x0f5] = 33;
-// packet_size_table[7][0x0f7] = 2;
- packet_size_table[7][0x113] = 10;
- packet_size_table[7][0x116] = 10;
- packet_size_table[7][0x190] = 20;
- packet_size_table[7][0x193] = 26;
- // size of packet version 13
- memcpy(&packet_size_table[8], &packet_size_table[7], sizeof(packet_len_table));
- packet_size_table[8][0x072] = 13;
- packet_size_table[8][0x07e] = 13;
- packet_size_table[8][0x085] = 15;
-// packet_size_table[8][0x089] = 6;
- packet_size_table[8][0x08c] = 108;
- packet_size_table[8][0x094] = 12;
- packet_size_table[8][0x09b] = 10;
-// packet_size_table[8][0x09f] = -1;
- packet_size_table[8][0x0a2] = 16;
- packet_size_table[8][0x0a7] = 28;
- packet_size_table[8][0x0f3] = 15;
- packet_size_table[8][0x0f5] = 29;
-// packet_size_table[8][0x0f7] = 2;
- packet_size_table[8][0x113] = 9;
- packet_size_table[8][0x116] = 9;
- packet_size_table[8][0x190] = 26;
- packet_size_table[8][0x193] = 22;
+ memcpy(packet_db[13], packet_db[12], sizeof(packet_db[0]));
+ // size of packet version 13 (25oct04)
+ packet_db[13][0x072].len = 13;
+ packet_db[13][0x07e].len = 13;
+ packet_db[13][0x085].len = 15;
+// packet_db[13][0x089].len = 6;
+ packet_db[13][0x08c].len = 108;
+ packet_db[13][0x094].len = 12;
+ packet_db[13][0x09b].len = 10;
+// packet_db[13][0x09f].len = -1;
+ packet_db[13][0x0a2].len = 16;
+ packet_db[13][0x0a7].len = 28;
+ packet_db[13][0x0f3].len = 15;
+ packet_db[13][0x0f5].len = 29;
+// packet_db[13][0x0f7].len = 2;
+ packet_db[13][0x113].len = 9;
+ packet_db[13][0x116].len = 9;
+ packet_db[13][0x190].len = 26;
+ packet_db[13][0x193].len = 22;
+ // init packet function calls for packet ver 14 (same function of packet version 13, but size are different)
+ memcpy(packet_db[14], packet_db[13], sizeof(packet_db[0]));
+ // size of packet version 14 - Added by nsstrunks (1nov04)
+ packet_db[14][0x072].len = 13;
+ packet_db[14][0x07e].len = 13;
+ packet_db[14][0x085].len = 15;
+ packet_db[14][0x089].len = 6;
+ packet_db[14][0x08c].len = 108;
+ packet_db[14][0x094].len = 12;
+ packet_db[14][0x09b].len = 10;
+ packet_db[14][0x09f].len = -1;
+ packet_db[14][0x0a2].len = 16;
+ packet_db[14][0x0a7].len = 28;
+ packet_db[14][0x0f3].len = 15;
+ packet_db[14][0x0f5].len = 29;
+ packet_db[14][0x113].len = 9;
+ packet_db[14][0x116].len = 9;
+ packet_db[14][0x190].len = 26;
+ packet_db[14][0x193].len = 22;
+ packet_db[14][0x215].len = 6;
+ packet_db[14][0x216].len = 6;
+ packet_db[14][0x217].len = 2;
+ packet_db[14][0x218].len = 2;
+ packet_db[14][0x219].len = 282;
+ packet_db[14][0x21a].len = 282;
+ packet_db[14][0x21b].len = 10;
+ packet_db[14][0x21c].len = 10;
+// packet_db[14][0x143].len = 23; // is this required? uncomment if it is
+ // Init packet function calls for packet ver 15
+ memcpy(packet_db[15], packet_db[14], sizeof(packet_db[0]));
+ packet_db[15][0x072].func = clif_parse_UseSkillToId;
+ packet_db[15][0x07e].func = clif_parse_UseSkillToPos;
+ packet_db[15][0x089].func = clif_parse_TickSend;
+ packet_db[15][0x085].func = clif_parse_GlobalMessage;
+ packet_db[15][0x08c].func = clif_parse_GetCharNameRequest;
+ packet_db[15][0x094].func = clif_parse_MoveToKafra;
+ packet_db[15][0x09b].func = clif_parse_CloseKafra;
+ packet_db[15][0x09f].func = clif_parse_ActionRequest;
+ packet_db[15][0x0a2].func = clif_parse_TakeItem;
+ packet_db[15][0x0a7].func = clif_parse_WalkToXY;
+ packet_db[15][0x0f3].func = clif_parse_ChangeDir;
+ packet_db[15][0x0f5].func = clif_parse_WantToConnection;
+ packet_db[15][0x0f7].func = clif_parse_SolveCharName;
+ packet_db[15][0x113].func = clif_parse_UseSkillToPos;
+ packet_db[15][0x116].func = clif_parse_DropItem;
+ packet_db[15][0x190].func = clif_parse_UseItem;
+ packet_db[15][0x193].func = clif_parse_MoveFromKafra;
+ // Size of packet version 15 - Added by nsstrunks (6dec04)
+ packet_db[15][0x072].len = 22;
+ packet_db[15][0x07e].len = 30;
+ packet_db[15][0x094].len = 14;
+ packet_db[15][0x09f].len = 18;
+ packet_db[15][0x085].len = -1;
+ packet_db[15][0x08c].len = 13;
+ packet_db[15][0x089].len = 7;
+ packet_db[15][0x09b].len = 2;
+ packet_db[15][0x0a2].len = 7;
+ packet_db[15][0x0a7].len = 7;
+ packet_db[15][0x0f3].len = 8;
+ packet_db[15][0x0f5].len = 29;
+ packet_db[15][0x0f7].len = 14;
+ packet_db[15][0x113].len = 110;
+ packet_db[15][0x116].len = 12;
+ packet_db[15][0x190].len = 15;
+ packet_db[15][0x193].len = 21;
+ packet_db[15][0x21d].len = 6;
+ packet_db[15][0x222].len = 6;
+ packet_db[15][0x221].len = -1;
+ packet_db[15][0x223].len = 8;
+ // Init packet function calls for packet ver 16
+ memcpy(packet_db[16], packet_db[15], sizeof(packet_db[0]));
+ packet_db[16][0x072].func = clif_parse_UseSkillToId;
+ packet_db[16][0x07e].func = clif_parse_UseSkillToPos;
+ packet_db[16][0x089].func = clif_parse_TickSend;
+ packet_db[16][0x0f3].func = clif_parse_GlobalMessage;
+ packet_db[16][0x08c].func = clif_parse_GetCharNameRequest;
+ packet_db[16][0x094].func = clif_parse_MoveToKafra;
+ packet_db[16][0x193].func = clif_parse_CloseKafra;
+ packet_db[16][0x190].func = clif_parse_ActionRequest;
+ packet_db[16][0x0f5].func = clif_parse_TakeItem;
+ packet_db[16][0x0a7].func = clif_parse_WalkToXY;
+ packet_db[16][0x085].func = clif_parse_ChangeDir;
+ packet_db[16][0x09b].func = clif_parse_WantToConnection;
+ packet_db[16][0x0a2].func = clif_parse_SolveCharName;
+ packet_db[16][0x113].func = clif_parse_UseSkillToPos;
+ packet_db[16][0x116].func = clif_parse_DropItem;
+ packet_db[16][0x09f].func = clif_parse_UseItem;
+ packet_db[16][0x0f7].func = clif_parse_MoveFromKafra;
+ // Size of packet version 16 [10jan05]
+ packet_db[16][0x072].len = 26;
+ packet_db[16][0x07e].len = 114;
+ packet_db[16][0x089].len = 9;
+ packet_db[16][0x0f3].len = -1;
+ packet_db[16][0x08c].len = 8;
+ packet_db[16][0x094].len = 20;
+ packet_db[16][0x193].len = 2;
+ packet_db[16][0x190].len = 20;
+ packet_db[16][0x0f5].len = 9;
+ packet_db[16][0x0a7].len = 13;
+ packet_db[16][0x085].len = 23;
+ packet_db[16][0x09b].len = 32;
+ packet_db[16][0x0a2].len = 11;
+ packet_db[16][0x113].len = 34;
+ packet_db[16][0x116].len = 20;
+ packet_db[16][0x09f].len = 17;
+ packet_db[16][0x0f7].len = 21;
+ packet_db[16][0x143].len = 10;
+ // Init packet function calls for the packet_db.txt (17)
+ memcpy(packet_db[MAX_PACKET_VER], packet_db[MAX_PACKET_VER - 1], sizeof(packet_db[0]));
+#endif
+
+ if (clif_config.enable_packet_db)
+ packetdb_readdb();
set_defaultparse(clif_parse);
#ifdef __WIN32
- if (!make_listen_port(map_port)) {
+ //if (!make_listen_port(map_port)) {
+ if (!make_listen_bind(bind_ip,map_port)) {
printf("cant bind game port\n");
exit(1);
}
#else
for(i = 0; i < 10; i++) {
- if (make_listen_port(map_port))
+ //if (make_listen_port(map_port))
+ if (make_listen_bind(bind_ip,map_port))
break;
sleep(20);
}
diff --git a/src/map/clif.h b/src/map/clif.h
index cf03820b1..b23eed5a6 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -13,7 +13,25 @@ typedef unsigned int in_addr_t;
#include "map.h"
+#define MAX_PACKET_DB 0x224
+#define MAX_PACKET_VER 17
+
+struct packet_db {
+ short len;
+ void (*func)(int, struct map_session_data *);
+ short pos[20];
+};
+extern struct packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB];
+
+extern struct Clif_Config {
+ int enable_packet_db;
+ int packet_db_ver;
+ int prefer_packet_db;
+ int connect_cmd;
+} clif_config;
+
void clif_setip(char*);
+void clif_setbindip(char*);
void clif_setport(int);
in_addr_t clif_getip(void);
@@ -74,7 +92,7 @@ int clif_misceffect(struct block_list*,int); // area
int clif_misceffect2(struct block_list *bl,int type);
int clif_changeoption(struct block_list*); // area
int clif_useitemack(struct map_session_data*,int,int,int); // self
-
+void clif_GlobalMessage(struct block_list *bl,char *message);
int clif_createchat(struct map_session_data*,int); // self
int clif_dispchat(struct chat_data*,int); // area or fd
int clif_joinchatfail(struct map_session_data*,int); // self
@@ -84,14 +102,17 @@ int clif_changechatowner(struct chat_data*,struct map_session_data*); // chat
int clif_clearchat(struct chat_data*,int); // area or fd
int clif_leavechat(struct chat_data*,struct map_session_data*); // chat
int clif_changechatstatus(struct chat_data*); // chat
+int clif_refresh(struct map_session_data*); // self
void clif_emotion(struct block_list *bl,int type);
void clif_talkiebox(struct block_list *bl,char* talkie);
void clif_wedding_effect(struct block_list *bl);
//void clif_sitting(int fd, struct map_session_data *sd);
//void clif_callpartner(struct map_session_data *sd);
+void clif_adopt_process(struct map_session_data *sd);
void clif_sitting(struct map_session_data *sd);
void clif_soundeffect(struct map_session_data *sd,struct block_list *bl,char *name,int type);
+int clif_soundeffectall(struct block_list *bl, char *name, int type);
// trade
int clif_traderequest(struct map_session_data *sd,char *name);
@@ -124,8 +145,8 @@ int clif_petinsight(struct block_list *bl,va_list ap);
int clif_npcoutsight(struct block_list *bl,va_list ap);
int clif_npcinsight(struct block_list *bl,va_list ap);
-int clif_class_change(struct block_list *bl,int class,int type);
-int clif_mob_class_change(struct mob_data *md,int class);
+int clif_class_change(struct block_list *bl,int class_,int type);
+int clif_mob_class_change(struct mob_data *md,int class_);
int clif_mob_equip(struct mob_data *md,int nameid); // [Valaris]
int clif_skillinfo(struct map_session_data *sd,int skillid,int type,int range);
@@ -164,7 +185,7 @@ int clif_autospell(struct map_session_data *sd,int skilllv);
int clif_devotion(struct map_session_data *sd,int target);
int clif_spiritball(struct map_session_data *sd);
int clif_combo_delay(struct block_list *src,int wait);
-int clif_bladestop(struct block_list *src,struct block_list *dst,int bool);
+int clif_bladestop(struct block_list *src,struct block_list *dst,int bool_);
int clif_changemapcell(int m,int x,int y,int cell_type,int type);
int clif_status_change(struct block_list *bl,int type,int flag);
@@ -173,6 +194,7 @@ int clif_wis_message(int fd,char *nick,char *mes,int mes_len);
int clif_wis_end(int fd,int flag);
int clif_solved_charname(struct map_session_data *sd,int char_id);
+int clif_update_mobhp(struct mob_data *md);
int clif_use_card(struct map_session_data *sd,int idx);
int clif_insert_card(struct map_session_data *sd,int idx_equip,int idx_card,int flag);
@@ -195,6 +217,7 @@ int clif_item_skill(struct map_session_data *sd,int skillid,int skilllv,const ch
int clif_mvp_effect(struct map_session_data *sd);
int clif_mvp_item(struct map_session_data *sd,int nameid);
int clif_mvp_exp(struct map_session_data *sd,int exp);
+void clif_changed_dir(struct block_list *bl);
// vending
int clif_openvendingreq(struct map_session_data *sd,int num);
@@ -218,6 +241,7 @@ int clif_party_message(struct party *p,int account_id,char *mes,int len);
int clif_party_move(struct party *p,struct map_session_data *sd,int online);
int clif_party_xy(struct party *p,struct map_session_data *sd);
int clif_party_hp(struct party *p,struct map_session_data *sd);
+int clif_hpmeter(struct map_session_data *sd);
// guild
int clif_guild_created(struct map_session_data *sd,int flag);
@@ -277,6 +301,7 @@ int clif_message(struct block_list *bl, char* msg); // messages (from mobs/npcs)
int clif_GM_kickack(struct map_session_data *sd,int id);
int clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd,int type);
+int clif_timedout(struct map_session_data *sd);
int clif_foreachclient(int (*)(struct map_session_data*,va_list),...);
diff --git a/src/map/guild.c b/src/map/guild.c
index a48bb3020..935377e19 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -13,11 +13,13 @@
#include "battle.h"
#include "npc.h"
#include "pc.h"
+#include "status.h"
#include "map.h"
#include "mob.h"
#include "intif.h"
#include "clif.h"
#include "skill.h"
+#include "showmsg.h"
#ifdef MEMWATCH
#include "memwatch.h"
@@ -43,6 +45,14 @@ struct guild_expcache {
int guild_id, account_id, char_id, exp;
};
+// timer for auto saving guild data during WoE
+#define GUILD_SAVE_INTERVAL 300000
+int guild_save_timer = -1;
+
+int guild_payexp_timer(int tid,unsigned int tick,int id,int data);
+int guild_gvg_eliminate_timer(int tid,unsigned int tick,int id,int data);
+int guild_save_sub(int tid,unsigned int tick,int id,int data);
+
// ギルドスキルdbのアクセサ(今は直打ちで代用)
int guild_skill_get_inf(int id) { // Modified for new skills [Sara]
if (id==GD_BATTLEORDER) return 4;
@@ -54,9 +64,21 @@ int guild_skill_get_inf(int id) { // Modified for new skills [Sara]
int guild_skill_get_sp(int id,int lv){ return 0; }
int guild_skill_get_range(int id){ return 0; }
int guild_skill_get_max(int id) { // Modified for new skills [Sara]
- if(id==GD_EXTENSION) return 10;
- else if(id==GD_REGENERATION) return 3;
- else return 1;
+ switch (id) {
+ case GD_GUARDUP:
+ return 3;
+ case GD_EXTENSION:
+ return 10;
+ case GD_LEADERSHIP:
+ case GD_GLORYWOUNDS:
+ case GD_SOULCOLD:
+ case GD_HAWKEYES:
+ return 5;
+ case GD_REGENERATION:
+ return 3;
+ default:
+ return 1;
+ }
}
// ギルドスキルがあるか確認
@@ -68,11 +90,6 @@ int guild_checkskill(struct guild *g,int id)
return g->skill[idx].lv;
}
-
-int guild_payexp_timer(int tid,unsigned int tick,int id,int data);
-int guild_gvg_eliminate_timer(int tid,unsigned int tick,int id,int data);
-
-
static int guild_read_castledb(void)
{
FILE *fp;
@@ -115,7 +132,8 @@ static int guild_read_castledb(void)
ln++;
}
fclose(fp);
- printf("read db/castle_db.txt done (count=%d)\n",ln);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/castle_db.txt");
+ ShowStatus(tmp_output);
return 0;
}
@@ -132,6 +150,7 @@ void do_init_guild(void)
add_timer_func_list(guild_gvg_eliminate_timer,"guild_gvg_eliminate_timer");
add_timer_func_list(guild_payexp_timer,"guild_payexp_timer");
+ add_timer_func_list(guild_save_sub, "guild_save_sub");
add_timer_interval(gettick()+GUILD_PAYEXP_INVERVAL,guild_payexp_timer,0,0,GUILD_PAYEXP_INVERVAL);
}
@@ -139,7 +158,7 @@ void do_init_guild(void)
// 検索
struct guild *guild_search(int guild_id)
{
- return numdb_search(guild_db,guild_id);
+ return (struct guild *) numdb_search(guild_db,guild_id);
}
int guild_searchname_sub(void *key,void *data,va_list ap)
{
@@ -160,7 +179,7 @@ struct guild* guild_searchname(char *str)
}
struct guild_castle *guild_castle_search(int gcid)
{
- return numdb_search(castle_db,gcid);
+ return (struct guild_castle *) numdb_search(castle_db,gcid);
}
// mapnameに対応したアジトのgcを返す
@@ -228,7 +247,7 @@ void guild_makemember(struct guild_member *m,struct map_session_data *sd)
m->hair =sd->status.hair;
m->hair_color =sd->status.hair_color;
m->gender =sd->sex;
- m->class =sd->status.class;
+ m->class_ =sd->status.class_;
m->lv =sd->status.base_level;
m->exp =0;
m->exp_payper =0;
@@ -270,7 +289,7 @@ int guild_payexp_timer_sub(void *key,void *data,va_list ap)
c->exp=0;
dellist[(*delp)++]=dataid;
- free(c);
+ aFree(c);
return 0;
}
int guild_payexp_timer(int tid,unsigned int tick,int id,int data)
@@ -317,7 +336,7 @@ int guild_created(int account_id,int guild_id)
struct guild *g;
sd->status.guild_id=guild_id;
sd->guild_sended=0;
- if((g=numdb_search(guild_db,guild_id))!=NULL){
+ if((g=(struct guild *) numdb_search(guild_db,guild_id))!=NULL){
printf("guild: id already exists!\n");
exit(1);
}
@@ -352,7 +371,7 @@ int guild_npc_request_info(int guild_id,const char *event)
return guild_request_info(guild_id);
ev=(struct eventlist *)aCalloc(1,sizeof(struct eventlist));
- memcpy(ev->name,event,sizeof(ev->name));
+ memcpy(ev->name,event,strlen(event));
ev->next=(struct eventlist *)numdb_search(guild_infoevent_db,guild_id);
numdb_insert(guild_infoevent_db,guild_id,ev);
return guild_request_info(guild_id);
@@ -367,7 +386,7 @@ int guild_check_member(const struct guild *g)
nullpo_retr(0, g);
for(i=0;i<fd_max;i++){
- if(session[i] && (sd=session[i]->session_data) && sd->state.auth){
+ if(session[i] && (sd=(struct map_session_data *) session[i]->session_data) && sd->state.auth && !sd->state.waitingdisconnect){
if(sd->status.guild_id==g->guild_id){
int j,f=1;
for(j=0;j<MAX_GUILD;j++){ // データがあるか
@@ -393,7 +412,7 @@ int guild_recv_noinfo(int guild_id)
int i;
struct map_session_data *sd;
for(i=0;i<fd_max;i++){
- if(session[i] && (sd=session[i]->session_data) && sd->state.auth){
+ if(session[i] && (sd=(struct map_session_data *) session[i]->session_data) && sd->state.auth && !sd->state.waitingdisconnect){
if(sd->status.guild_id==guild_id)
sd->status.guild_id=0;
}
@@ -409,7 +428,7 @@ int guild_recv_info(struct guild *sg)
nullpo_retr(0, sg);
- if((g=numdb_search(guild_db,sg->guild_id))==NULL){
+ if((g=(struct guild *) numdb_search(guild_db,sg->guild_id))==NULL){
g=(struct guild *)aCalloc(1,sizeof(struct guild));
numdb_insert(guild_db,sg->guild_id,g);
before=*sg;
@@ -423,9 +442,11 @@ int guild_recv_info(struct guild *sg)
for(i=bm=m=0;i<g->max_member;i++){ // sdの設定と人数の確認
if(g->member[i].account_id>0){
struct map_session_data *sd = map_id2sd(g->member[i].account_id);
- g->member[i].sd=(sd!=NULL &&
- sd->status.char_id==g->member[i].char_id &&
- sd->status.guild_id==g->guild_id)? sd:NULL;
+ if (sd && sd->status.char_id == g->member[i].char_id &&
+ sd->status.guild_id == g->guild_id &&
+ !sd->state.waitingdisconnect)
+ g->member[i].sd = sd;
+ else sd = NULL;
m++;
}else
g->member[i].sd=NULL;
@@ -460,10 +481,13 @@ int guild_recv_info(struct guild *sg)
}
// イベントの発生
- if( (ev=numdb_search(guild_infoevent_db,sg->guild_id))!=NULL ){
+ if( (ev=(struct eventlist *)numdb_search(guild_infoevent_db,sg->guild_id))!=NULL ){
numdb_erase(guild_infoevent_db,sg->guild_id);
- for(;ev;ev2=ev->next,free(ev),ev=ev2){
+ while(ev){
npc_event_do(ev->name);
+ ev2=ev->next;
+ aFree(ev);
+ ev=ev2;
}
}
@@ -566,17 +590,18 @@ int guild_member_added(int guild_id,int account_id,int char_id,int flag)
if( (g=guild_search(guild_id))==NULL )
return 0;
- if((sd==NULL || sd->guild_invite==0) && flag==0){
+ if(sd==NULL || sd->guild_invite==0){
// キャラ側に登録できなかったため脱退要求を出す
- if(battle_config.error_log)
- printf("guild: member added error %d is not online\n",account_id);
- intif_guild_leave(guild_id,account_id,char_id,0,"**登録失敗**");
+ if (flag == 0) {
+ if(battle_config.error_log)
+ printf("guild: member added error %d is not online\n",account_id);
+ intif_guild_leave(guild_id,account_id,char_id,0,"**登録失敗**");
+ }
return 0;
}
- sd->guild_invite=0;
- sd->guild_invite_account=0;
-
- sd2=map_id2sd(sd->guild_invite_account);
+ sd2 = map_id2sd(sd->guild_invite_account);
+ sd->guild_invite = 0;
+ sd->guild_invite_account = 0;
if(flag==1){ // 失敗
if( sd2!=NULL )
@@ -659,11 +684,10 @@ int guild_member_leaved(int guild_id,int account_id,int char_id,int flag,
{
struct map_session_data *sd=map_id2sd(account_id);
struct guild *g=guild_search(guild_id);
- int i;
if(g!=NULL){
int i;
- for(i=0;i<g->max_member;i++)
+ for(i=0;i<g->max_member;i++) {
if( g->member[i].account_id==account_id &&
g->member[i].char_id==char_id ){
struct map_session_data *sd2=sd;
@@ -679,19 +703,21 @@ int guild_member_leaved(int guild_id,int account_id,int char_id,int flag,
g->member[i].account_id=0;
g->member[i].sd=NULL;
}
+ // メンバーリストを全員に再通知
+ for(i=0;i<g->max_member;i++){
+ if( g->member[i].sd!=NULL )
+ clif_guild_memberlist(g->member[i].sd);
+ }
+ }
}
- if(sd!=NULL && sd->status.guild_id==guild_id){
- sd->status.guild_id=0;
- sd->guild_emblem_id=0;
- sd->guild_sended=0;
- }
-
- // メンバーリストを全員に再通知
- for(i=0;i<g->max_member;i++){
- if( g->member[i].sd!=NULL )
- clif_guild_memberlist(g->member[i].sd);
+ if(sd!=NULL) {
+ if (sd->status.guild_id==guild_id){
+ sd->status.guild_id=0;
+ sd->guild_emblem_id=0;
+ sd->guild_sended=0;
+ }
}
-
+
return 0;
}
// ギルドメンバのオンライン状態/Lv更新送信
@@ -708,7 +734,7 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online)
return 0;
intif_guild_memberinfoshort(g->guild_id,
- sd->status.account_id,sd->status.char_id,online,sd->status.base_level,sd->status.class);
+ sd->status.account_id,sd->status.char_id,online,sd->status.base_level,sd->status.class_);
if( !online ){ // ログアウトするならsdをクリアして終了
int i=guild_getindex(g,sd->status.account_id,sd->status.char_id);
@@ -736,7 +762,7 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online)
return 0;
}
// ギルドメンバのオンライン状態/Lv更新通知
-int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class)
+int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_)
{
int i,alv,c,idx=0,om=0,oldonline=-1;
struct guild *g=guild_search(guild_id);
@@ -748,7 +774,7 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin
oldonline=m->online;
m->online=online;
m->lv=lv;
- m->class=class;
+ m->class_=class_;
idx=i;
}
if(m->account_id>0){
@@ -771,9 +797,11 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin
for(i=0;i<g->max_member;i++){ // sd再設定
struct map_session_data *sd= map_id2sd(g->member[i].account_id);
- g->member[i].sd=(sd!=NULL &&
- sd->status.char_id==g->member[i].char_id &&
- sd->status.guild_id==guild_id)?sd:NULL;
+ if (sd && sd->status.char_id == g->member[i].char_id &&
+ sd->status.guild_id == g->guild_id &&
+ !sd->state.waitingdisconnect)
+ g->member[i].sd = sd;
+ else sd = NULL;
}
// ここにクライアントに送信処理が必要
@@ -788,6 +816,8 @@ int guild_send_message(struct map_session_data *sd,char *mes,int len)
if(sd->status.guild_id==0)
return 0;
intif_guild_message(sd->status.guild_id,sd->status.account_id,mes,len);
+ guild_recv_message(sd->status.guild_id,sd->status.account_id,mes,len);
+
return 0;
}
// ギルド会話受信
@@ -870,14 +900,16 @@ int guild_notice_changed(int guild_id,const char *mes1,const char *mes2)
// ギルドエンブレム変更
int guild_change_emblem(struct map_session_data *sd,int len,const char *data)
{
+ struct guild *g;
nullpo_retr(0, sd);
- struct guild *g = NULL;
- if ((g = guild_search(sd->status.guild_id)) && guild_checkskill(g, GD_GLORYGUILD)>0)
- return intif_guild_emblem(sd->status.guild_id,len,data);
+ if (battle_config.require_glory_guild &&
+ !((g = guild_search(sd->status.guild_id)) && guild_checkskill(g, GD_GLORYGUILD)>0)) {
+ clif_skill_fail(sd,GD_GLORYGUILD,0,0);
+ return 0;
+ }
- clif_skill_fail(sd,GD_GLORYGUILD,0,0);
- return 0;
+ return intif_guild_emblem(sd->status.guild_id,len,data);
}
// ギルドエンブレム変更通知
int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data)
@@ -920,8 +952,8 @@ int guild_payexp(struct map_session_data *sd,int exp)
if( (exp2=exp*per/100)<=0 )
return 0;
- if( (c=numdb_search(guild_expcache_db,sd->status.char_id))==NULL ){
- c=(struct guild_expcache *)aCalloc(1,sizeof(struct guild_expcache));
+ if( (c=(struct guild_expcache *) numdb_search(guild_expcache_db,sd->status.char_id))==NULL ){
+ c=(struct guild_expcache *)aCallocA(1,sizeof(struct guild_expcache));
c->guild_id=sd->status.guild_id;
c->account_id=sd->status.account_id;
c->char_id=sd->status.char_id;
@@ -933,6 +965,30 @@ int guild_payexp(struct map_session_data *sd,int exp)
return exp2;
}
+// Celest
+int guild_getexp(struct map_session_data *sd,int exp)
+{
+ struct guild *g;
+ struct guild_expcache *c;
+
+ nullpo_retr(0, sd);
+
+ if(sd->status.guild_id==0 || (g=guild_search(sd->status.guild_id))==NULL )
+ return 0;
+
+ if( (c=(struct guild_expcache *) numdb_search(guild_expcache_db,sd->status.char_id))==NULL ){
+ c=(struct guild_expcache *)aCallocA(1,sizeof(struct guild_expcache));
+ c->guild_id=sd->status.guild_id;
+ c->account_id=sd->status.account_id;
+ c->char_id=sd->status.char_id;
+ c->exp=exp;
+ numdb_insert(guild_expcache_db,c->char_id,c);
+ }else{
+ c->exp+=exp;
+ }
+ return exp;
+}
+
// スキルポイント割り振り
int guild_skillup(struct map_session_data *sd,int skill_num,int flag)
{
@@ -954,7 +1010,7 @@ int guild_skillup(struct map_session_data *sd,int skill_num,int flag)
g->skill[idx].lv < guild_skill_get_max(skill_num) ){
intif_guild_skillup(g->guild_id,skill_num,sd->status.account_id,flag);
}
- pc_calcstatus (sd, 0); // Celest
+ status_calc_pc (sd, 0); // Celest
return 0;
}
@@ -989,6 +1045,23 @@ int guild_get_alliance_count(struct guild *g,int flag)
}
return c;
}
+// 同盟関係かどうかチェック
+// 同盟なら1、それ以外は0
+int guild_check_alliance(int guild_id1, int guild_id2, int flag)
+{
+ struct guild *g;
+ int i;
+
+ g = guild_search(guild_id1);
+ if (g == NULL)
+ return 0;
+
+ for (i=0; i<MAX_GUILDALLIANCE; i++)
+ if ((g->alliance[i].guild_id == guild_id2) && (g->alliance[i].opposition == flag))
+ return 1;
+
+ return 0;
+}
// ギルド同盟要求
int guild_reqalliance(struct map_session_data *sd,int account_id)
{
@@ -1146,11 +1219,18 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id
int flag,const char *name1,const char *name2)
{
struct guild *g[2];
- int guild_id[2]={guild_id1,guild_id2};
- const char *guild_name[2]={name1,name2};
- struct map_session_data *sd[2]={map_id2sd(account_id1),map_id2sd(account_id2)};
+ int guild_id[2];
+ const char *guild_name[2];
+ struct map_session_data *sd[2];
int j,i;
+ guild_id[0] = guild_id1;
+ guild_id[1] = guild_id2;
+ guild_name[0] = name1;
+ guild_name[1] = name2;
+ sd[0] = map_id2sd(account_id1);
+ sd[1] = map_id2sd(account_id2);
+
g[0]=guild_search(guild_id1);
g[1]=guild_search(guild_id2);
@@ -1252,7 +1332,7 @@ int guild_broken(int guild_id,int flag)
numdb_foreach(guild_db,guild_broken_sub,guild_id);
numdb_erase(guild_db,guild_id);
guild_storage_delete(guild_id);
- free(g);
+ aFree(g);
return 0;
}
@@ -1301,7 +1381,7 @@ int guild_addcastleinfoevent(int castle_id,int index,const char *name)
ev=(struct eventlist *)aCalloc(1,sizeof(struct eventlist));
memcpy(ev->name,name,sizeof(ev->name));
- ev->next=numdb_search(guild_castleinfoevent_db,code);
+ ev->next=(struct eventlist *) numdb_search(guild_castleinfoevent_db,code);
numdb_insert(guild_castleinfoevent_db,code,ev);
return 0;
}
@@ -1346,10 +1426,13 @@ int guild_castledataloadack(int castle_id,int index,int value)
printf("guild_castledataloadack ERROR!! (Not found index=%d)\n", index);
return 0;
}
- if( (ev=numdb_search(guild_castleinfoevent_db,code))!=NULL ){
+ if( (ev=(struct eventlist *) numdb_search(guild_castleinfoevent_db,code))!=NULL ){
numdb_erase(guild_castleinfoevent_db,code);
- for(;ev;ev2=ev->next,free(ev),ev=ev2){
+ while(ev){
npc_event_do(ev->name);
+ ev2=ev->next;
+ aFree(ev);
+ ev=ev2;
}
}
return 1;
@@ -1439,6 +1522,8 @@ int guild_agit_start(void)
{ // Run All NPC_Event[OnAgitStart]
int c = npc_event_doall("OnAgitStart");
printf("NPC_Event:[OnAgitStart] Run (%d) Events by @AgitStart.\n",c);
+ // Start auto saving
+ guild_save_timer = add_timer_interval (gettick() + GUILD_SAVE_INTERVAL, guild_save_sub, 0, 0, GUILD_SAVE_INTERVAL);
return 0;
}
@@ -1446,20 +1531,82 @@ int guild_agit_end(void)
{ // Run All NPC_Event[OnAgitEnd]
int c = npc_event_doall("OnAgitEnd");
printf("NPC_Event:[OnAgitEnd] Run (%d) Events by @AgitEnd.\n",c);
+ // Stop auto saving
+ delete_timer (guild_save_timer, guild_save_sub);
return 0;
}
int guild_gvg_eliminate_timer(int tid,unsigned int tick,int id,int data)
{ // Run One NPC_Event[OnAgitEliminate]
- size_t len = strlen((const char*)data);
- char *evname=(char*)aCalloc(len + 4,sizeof(char));
+ char *name = (char*)data;
+ size_t len = (name) ? strlen(name) : 0;
+ // the rest is dangerous, but let it crash,
+ // if this happens, it's ruined anyway
+ char *evname=(char*)aMalloc( (len + 4) * sizeof(char));
int c=0;
- if(!agit_flag) return 0; // Agit already End
- memcpy(evname,(const char *)data,len - 5);
- strcpy(evname + len - 5,"Eliminate");
- c = npc_event_do(evname);
- printf("NPC_Event:[%s] Run (%d) Events.\n",evname,c);
+ if(agit_flag) // Agit not already End
+ {
+ memcpy(evname,name,len - 5);
+ strcpy(evname + len - 5,"Eliminate");
+ c = npc_event_do(evname);
+ printf("NPC_Event:[%s] Run (%d) Events.\n",evname,c);
+ }
+ if(name) aFree(name);
+ return 0;
+}
+
+static int Ghp[MAX_GUILDCASTLE][8]; // so save only if HP are changed // experimental code [Yor]
+static int Gid[MAX_GUILDCASTLE];
+int guild_save_sub(int tid,unsigned int tick,int id,int data)
+{
+ struct guild_castle *gc;
+ int i;
+
+ for(i = 0; i < MAX_GUILDCASTLE; i++) { // [Yor]
+ gc = guild_castle_search(i);
+ if (!gc) continue;
+ if (gc->guild_id != Gid[i]) {
+ // Re-save guild id if its owner guild has changed
+ // This should already be done in gldfunc_ev_agit.txt,
+ // but since people have complained... Well x3
+ guild_castledatasave(gc->castle_id, 1, gc->guild_id);
+ Gid[i] = gc->guild_id;
+ }
+ if (gc->visibleG0 == 1 && Ghp[i][0] != gc->Ghp0) {
+ guild_castledatasave(gc->castle_id, 18, gc->Ghp0);
+ Ghp[i][0] = gc->Ghp0;
+ }
+ if (gc->visibleG1 == 1 && Ghp[i][1] != gc->Ghp1) {
+ guild_castledatasave(gc->castle_id, 19, gc->Ghp1);
+ Ghp[i][1] = gc->Ghp1;
+ }
+ if (gc->visibleG2 == 1 && Ghp[i][2] != gc->Ghp2) {
+ guild_castledatasave(gc->castle_id, 20, gc->Ghp2);
+ Ghp[i][2] = gc->Ghp2;
+ }
+ if (gc->visibleG3 == 1 && Ghp[i][3] != gc->Ghp3) {
+ guild_castledatasave(gc->castle_id, 21, gc->Ghp3);
+ Ghp[i][3] = gc->Ghp3;
+ }
+ if (gc->visibleG4 == 1 && Ghp[i][4] != gc->Ghp4) {
+ guild_castledatasave(gc->castle_id, 22, gc->Ghp4);
+ Ghp[i][4] = gc->Ghp4;
+ }
+ if (gc->visibleG5 == 1 && Ghp[i][5] != gc->Ghp5) {
+ guild_castledatasave(gc->castle_id, 23, gc->Ghp5);
+ Ghp[i][5] = gc->Ghp5;
+ }
+ if (gc->visibleG6 == 1 && Ghp[i][6] != gc->Ghp6) {
+ guild_castledatasave(gc->castle_id, 24, gc->Ghp6);
+ Ghp[i][6] = gc->Ghp6;
+ }
+ if (gc->visibleG7 == 1 && Ghp[i][7] != gc->Ghp7) {
+ guild_castledatasave(gc->castle_id, 25, gc->Ghp7);
+ Ghp[i][7] = gc->Ghp7;
+ }
+ }
+
return 0;
}
@@ -1469,7 +1616,7 @@ int guild_agit_break(struct mob_data *md)
nullpo_retr(0, md);
- evname=(char *)aCalloc(strlen(md->npc_event) + 1, sizeof(char));
+ evname=(char *)aCallocA(strlen(md->npc_event) + 1, sizeof(char));
strcpy(evname,md->npc_event);
// Now By User to Run [OnAgitBreak] NPC Event...
@@ -1491,7 +1638,7 @@ int guild_checkcastles(struct guild *g) {
for(i=0;i<MAX_GUILDCASTLE;i++){
gc=guild_castle_search(i);
cas_id=gc->guild_id;
- if(g->guild_id==cas_id)
+ if(g->guild_id==cas_id)
nb_cas=nb_cas+1;
} //end for
return nb_cas;
@@ -1522,36 +1669,36 @@ int guild_isallied(struct guild *g, struct guild_castle *gc)
return 0;
}
-
+
static int guild_db_final(void *key,void *data,va_list ap)
{
- struct guild *g=data;
+ struct guild *g=(struct guild *) data;
- free(g);
+ aFree(g);
return 0;
}
static int castle_db_final(void *key,void *data,va_list ap)
{
- struct guild_castle *gc=data;
+ struct guild_castle *gc=(struct guild_castle *) data;
- free(gc);
+ aFree(gc);
return 0;
}
static int guild_expcache_db_final(void *key,void *data,va_list ap)
{
- struct guild_expcache *c=data;
+ struct guild_expcache *c=(struct guild_expcache *) data;
- free(c);
+ aFree(c);
return 0;
}
static int guild_infoevent_db_final(void *key,void *data,va_list ap)
{
- struct eventlist *ev=data;
+ struct eventlist *ev=(struct eventlist *) data;
- free(ev);
+ aFree(ev);
return 0;
}
diff --git a/src/map/guild.h b/src/map/guild.h
index 528605f7f..1dee350a1 100644
--- a/src/map/guild.h
+++ b/src/map/guild.h
@@ -29,6 +29,7 @@ struct map_session_data *guild_getavailablesd(struct guild *g);
int guild_getindex(struct guild *g,int account_id,int char_id);
int guild_getposition(struct map_session_data *sd,struct guild *g);
int guild_payexp(struct map_session_data *sd,int exp);
+int guild_getexp(struct map_session_data *sd,int exp); // [Celest]
int guild_create(struct map_session_data *sd,char *name);
int guild_created(int account_id,int guild_id);
@@ -53,9 +54,10 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id
int flag,const char *name1,const char *name2);
int guild_delalliance(struct map_session_data *sd,int guild_id,int flag);
int guild_opposition(struct map_session_data *sd,int char_id);
+int guild_check_alliance(int guild_id1, int guild_id2, int flag);
int guild_send_memberinfoshort(struct map_session_data *sd,int online);
-int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class);
+int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_);
int guild_change_memberposition(int guild_id,int account_id,int char_id,int idx);
int guild_memberposition_changed(struct guild *g,int idx,int pos);
int guild_change_position(struct map_session_data *sd,int idx,
diff --git a/src/map/intif.c b/src/map/intif.c
index fc79e5148..3aa472ad8 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -31,6 +31,7 @@
#include "guild.h"
#include "pet.h"
#include "nullpo.h"
+#include "malloc.h"
#ifdef MEMWATCH
#include "memwatch.h"
@@ -54,10 +55,16 @@ extern int char_fd; // inter serverのfdはchar_fdを使う
//-----------------------------------------------------------------
// inter serverへの送信
+int CheckForCharServer() {
+ return ((char_fd == -1) || session[char_fd] == NULL || session[char_fd]->wdata == NULL);
+}
+
// pet
int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,short pet_egg_id,
short pet_equip,short intimate,short hungry,char rename_flag,char incuvate,char *pet_name)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3080;
WFIFOL(inter_fd,2) = account_id;
WFIFOL(inter_fd,6) = char_id;
@@ -77,6 +84,8 @@ int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,sho
int intif_request_petdata(int account_id,int char_id,int pet_id)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3081;
WFIFOL(inter_fd,2) = account_id;
WFIFOL(inter_fd,6) = char_id;
@@ -88,6 +97,8 @@ int intif_request_petdata(int account_id,int char_id,int pet_id)
int intif_save_petdata(int account_id,struct s_pet *p)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3082;
WFIFOW(inter_fd,2) = sizeof(struct s_pet) + 8;
WFIFOL(inter_fd,4) = account_id;
@@ -99,6 +110,8 @@ int intif_save_petdata(int account_id,struct s_pet *p)
int intif_delete_petdata(int pet_id)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3083;
WFIFOL(inter_fd,2) = pet_id;
WFIFOSET(inter_fd,6);
@@ -110,18 +123,25 @@ int intif_delete_petdata(int pet_id)
int intif_GMmessage(char* mes,int len,int flag)
{
int lp = (flag&0x10) ? 8 : 4;
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3000;
WFIFOW(inter_fd,2) = lp + len;
WFIFOL(inter_fd,4) = 0x65756c62;
memcpy(WFIFOP(inter_fd,lp), mes, len);
WFIFOSET(inter_fd, WFIFOW(inter_fd,2));
+ // Send to the local players
+ clif_GMmessage(NULL, mes, len, 0);
+
return 0;
}
// The transmission of Wisp/Page to inter-server (player not found on this server)
int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, int mes_len) {
nullpo_retr(0, sd);
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3001;
WFIFOW(inter_fd,2) = mes_len + 52;
@@ -138,6 +158,8 @@ int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, int me
// The reply of Wisp/page
int intif_wis_replay(int id, int flag) {
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3002;
WFIFOL(inter_fd,2) = id;
WFIFOB(inter_fd,6) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
@@ -150,7 +172,11 @@ int intif_wis_replay(int id, int flag) {
}
// The transmission of GM only Wisp/Page from server to inter-server
-int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes, int mes_len) {
+int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes) {
+ int mes_len;
+ if (CheckForCharServer())
+ return 0;
+ mes_len = strlen(mes) + 1; // + null
WFIFOW(inter_fd,0) = 0x3003;
WFIFOW(inter_fd,2) = mes_len + 30;
memcpy(WFIFOP(inter_fd,4), Wisp_name, 24);
@@ -167,9 +193,14 @@ int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes, int me
// アカウント変数送信
int intif_saveaccountreg(struct map_session_data *sd) {
int j,p;
+ if (CheckForCharServer())
+ return 0;
nullpo_retr(0, sd);
+ if (sd->status.account_reg_num == -1)
+ return 0;
+
WFIFOW(inter_fd,0) = 0x3004;
WFIFOL(inter_fd,4) = sd->bl.id;
for(j=0,p=8;j<sd->status.account_reg_num;j++,p+=36){
@@ -184,16 +215,23 @@ int intif_saveaccountreg(struct map_session_data *sd) {
int intif_request_accountreg(struct map_session_data *sd)
{
nullpo_retr(0, sd);
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3005;
WFIFOL(inter_fd,2) = sd->bl.id;
WFIFOSET(inter_fd,6);
+
+ sd->status.account_reg_num = -1;
+
return 0;
}
// 倉庫データ要求
int intif_request_storage(int account_id)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3010;
WFIFOL(inter_fd,2) = account_id;
WFIFOSET(inter_fd,6);
@@ -202,6 +240,8 @@ int intif_request_storage(int account_id)
// 倉庫データ送信
int intif_send_storage(struct storage *stor)
{
+ if (CheckForCharServer())
+ return 0;
nullpo_retr(0, stor);
WFIFOW(inter_fd,0) = 0x3011;
WFIFOW(inter_fd,2) = sizeof(struct storage)+8;
@@ -213,6 +253,8 @@ int intif_send_storage(struct storage *stor)
int intif_request_guild_storage(int account_id,int guild_id)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3018;
WFIFOL(inter_fd,2) = account_id;
WFIFOL(inter_fd,6) = guild_id;
@@ -221,6 +263,8 @@ int intif_request_guild_storage(int account_id,int guild_id)
}
int intif_send_guild_storage(int account_id,struct guild_storage *gstor)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3019;
WFIFOW(inter_fd,2) = sizeof(struct guild_storage)+12;
WFIFOL(inter_fd,4) = account_id;
@@ -231,8 +275,10 @@ int intif_send_guild_storage(int account_id,struct guild_storage *gstor)
}
// パーティ作成要求
-int intif_create_party(struct map_session_data *sd,char *name)
+int intif_create_party(struct map_session_data *sd,char *name,int item,int item2)
{
+ if (CheckForCharServer())
+ return 0;
nullpo_retr(0, sd);
WFIFOW(inter_fd,0) = 0x3020;
@@ -241,7 +287,9 @@ int intif_create_party(struct map_session_data *sd,char *name)
memcpy(WFIFOP(inter_fd,30),sd->status.name,24);
memcpy(WFIFOP(inter_fd,54),map[sd->bl.m].name,16);
WFIFOW(inter_fd,70)= sd->status.base_level;
- WFIFOSET(inter_fd,72);
+ WFIFOB(inter_fd,72)= item;
+ WFIFOB(inter_fd,73)= item2;
+ WFIFOSET(inter_fd,74);
// if(battle_config.etc_log)
// printf("intif: create party\n");
return 0;
@@ -249,6 +297,8 @@ int intif_create_party(struct map_session_data *sd,char *name)
// パーティ情報要求
int intif_request_partyinfo(int party_id)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3021;
WFIFOL(inter_fd,2) = party_id;
WFIFOSET(inter_fd,6);
@@ -260,6 +310,8 @@ int intif_request_partyinfo(int party_id)
int intif_party_addmember(int party_id,int account_id)
{
struct map_session_data *sd;
+ if (CheckForCharServer())
+ return 0;
sd=map_id2sd(account_id);
// if(battle_config.etc_log)
// printf("intif: party add member %d %d\n",party_id,account_id);
@@ -277,6 +329,8 @@ int intif_party_addmember(int party_id,int account_id)
// パーティ設定変更
int intif_party_changeoption(int party_id,int account_id,int exp,int item)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0)=0x3023;
WFIFOL(inter_fd,2)=party_id;
WFIFOL(inter_fd,6)=account_id;
@@ -288,6 +342,8 @@ int intif_party_changeoption(int party_id,int account_id,int exp,int item)
// パーティ脱退要求
int intif_party_leave(int party_id,int account_id)
{
+ if (CheckForCharServer())
+ return 0;
// if(battle_config.etc_log)
// printf("intif: party leave %d %d\n",party_id,account_id);
WFIFOW(inter_fd,0)=0x3024;
@@ -299,6 +355,8 @@ int intif_party_leave(int party_id,int account_id)
// パーティ移動要求
int intif_party_changemap(struct map_session_data *sd,int online)
{
+ if (CheckForCharServer())
+ return 0;
if(sd!=NULL){
WFIFOW(inter_fd,0)=0x3025;
WFIFOL(inter_fd,2)=sd->status.party_id;
@@ -315,6 +373,8 @@ int intif_party_changemap(struct map_session_data *sd,int online)
// パーティー解散要求
int intif_break_party(int party_id)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0)=0x3026;
WFIFOL(inter_fd,2)=party_id;
WFIFOSET(inter_fd,6);
@@ -323,6 +383,8 @@ int intif_break_party(int party_id)
// パーティ会話送信
int intif_party_message(int party_id,int account_id,char *mes,int len)
{
+ if (CheckForCharServer())
+ return 0;
// if(battle_config.etc_log)
// printf("intif_party_message: %s\n",mes);
WFIFOW(inter_fd,0)=0x3027;
@@ -336,6 +398,8 @@ int intif_party_message(int party_id,int account_id,char *mes,int len)
// パーティ競合チェック要求
int intif_party_checkconflict(int party_id,int account_id,char *nick)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0)=0x3028;
WFIFOL(inter_fd,2)=party_id;
WFIFOL(inter_fd,6)=account_id;
@@ -347,6 +411,8 @@ int intif_party_checkconflict(int party_id,int account_id,char *nick)
// ギルド作成要求
int intif_guild_create(const char *name,const struct guild_member *master)
{
+ if (CheckForCharServer())
+ return 0;
nullpo_retr(0, master);
WFIFOW(inter_fd,0)=0x3030;
@@ -360,6 +426,8 @@ int intif_guild_create(const char *name,const struct guild_member *master)
// ギルド情報要求
int intif_guild_request_info(int guild_id)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3031;
WFIFOL(inter_fd,2) = guild_id;
WFIFOSET(inter_fd,6);
@@ -368,6 +436,8 @@ int intif_guild_request_info(int guild_id)
// ギルドメンバ追加要求
int intif_guild_addmember(int guild_id,struct guild_member *m)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0) = 0x3032;
WFIFOW(inter_fd,2) = sizeof(struct guild_member)+8;
WFIFOL(inter_fd,4) = guild_id;
@@ -378,6 +448,8 @@ int intif_guild_addmember(int guild_id,struct guild_member *m)
// ギルドメンバ脱退/追放要求
int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const char *mes)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd, 0) = 0x3034;
WFIFOL(inter_fd, 2) = guild_id;
WFIFOL(inter_fd, 6) = account_id;
@@ -389,21 +461,25 @@ int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const cha
}
// ギルドメンバのオンライン状況/Lv更新要求
int intif_guild_memberinfoshort(int guild_id,
- int account_id,int char_id,int online,int lv,int class)
+ int account_id,int char_id,int online,int lv,int class_)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd, 0) = 0x3035;
WFIFOL(inter_fd, 2) = guild_id;
WFIFOL(inter_fd, 6) = account_id;
WFIFOL(inter_fd,10) = char_id;
WFIFOB(inter_fd,14) = online;
WFIFOW(inter_fd,15) = lv;
- WFIFOW(inter_fd,17) = class;
+ WFIFOW(inter_fd,17) = class_;
WFIFOSET(inter_fd,19);
return 0;
}
// ギルド解散通知
int intif_guild_break(int guild_id)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd, 0) = 0x3036;
WFIFOL(inter_fd, 2) = guild_id;
WFIFOSET(inter_fd,6);
@@ -412,17 +488,22 @@ int intif_guild_break(int guild_id)
// ギルド会話送信
int intif_guild_message(int guild_id,int account_id,char *mes,int len)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0)=0x3037;
WFIFOW(inter_fd,2)=len+12;
WFIFOL(inter_fd,4)=guild_id;
WFIFOL(inter_fd,8)=account_id;
memcpy(WFIFOP(inter_fd,12),mes,len);
WFIFOSET(inter_fd,len+12);
+
return 0;
}
// ギルド競合チェック要求
int intif_guild_checkconflict(int guild_id,int account_id,int char_id)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd, 0)=0x3038;
WFIFOL(inter_fd, 2)=guild_id;
WFIFOL(inter_fd, 6)=account_id;
@@ -433,6 +514,8 @@ int intif_guild_checkconflict(int guild_id,int account_id,int char_id)
// ギルド基本情報変更要求
int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0)=0x3039;
WFIFOW(inter_fd,2)=len+10;
WFIFOL(inter_fd,4)=guild_id;
@@ -445,6 +528,8 @@ int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len)
int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id,
int type,const void *data,int len)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd, 0)=0x303a;
WFIFOW(inter_fd, 2)=len+18;
WFIFOL(inter_fd, 4)=guild_id;
@@ -458,6 +543,8 @@ int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id,
// ギルド役職変更要求
int intif_guild_position(int guild_id,int idx,struct guild_position *p)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0)=0x303b;
WFIFOW(inter_fd,2)=sizeof(struct guild_position)+12;
WFIFOL(inter_fd,4)=guild_id;
@@ -469,6 +556,8 @@ int intif_guild_position(int guild_id,int idx,struct guild_position *p)
// ギルドスキルアップ要求
int intif_guild_skillup(int guild_id,int skill_num,int account_id,int flag)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd, 0)=0x303c;
WFIFOL(inter_fd, 2)=guild_id;
WFIFOL(inter_fd, 6)=skill_num;
@@ -480,6 +569,8 @@ int intif_guild_skillup(int guild_id,int skill_num,int account_id,int flag)
// ギルド同盟/敵対要求
int intif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd, 0)=0x303d;
WFIFOL(inter_fd, 2)=guild_id1;
WFIFOL(inter_fd, 6)=guild_id2;
@@ -492,6 +583,8 @@ int intif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account
// ギルド告知変更要求
int intif_guild_notice(int guild_id,const char *mes1,const char *mes2)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0)=0x303e;
WFIFOL(inter_fd,2)=guild_id;
memcpy(WFIFOP(inter_fd,6),mes1,60);
@@ -502,6 +595,8 @@ int intif_guild_notice(int guild_id,const char *mes1,const char *mes2)
// ギルドエンブレム変更要求
int intif_guild_emblem(int guild_id,int len,const char *data)
{
+ if (CheckForCharServer())
+ return 0;
if(guild_id<=0 || len<0 || len>2000)
return 0;
WFIFOW(inter_fd,0)=0x303f;
@@ -515,6 +610,8 @@ int intif_guild_emblem(int guild_id,int len,const char *data)
//現在のギルド城占領ギルドを調べる
int intif_guild_castle_dataload(int castle_id,int index)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0)=0x3040;
WFIFOW(inter_fd,2)=castle_id;
WFIFOB(inter_fd,4)=index;
@@ -525,6 +622,8 @@ int intif_guild_castle_dataload(int castle_id,int index)
//ギルド城占領ギルド変更要求
int intif_guild_castle_datasave(int castle_id,int index, int value)
{
+ if (CheckForCharServer())
+ return 0;
WFIFOW(inter_fd,0)=0x3041;
WFIFOW(inter_fd,2)=castle_id;
WFIFOB(inter_fd,4)=index;
@@ -539,14 +638,15 @@ int intif_guild_castle_datasave(int castle_id,int index, int value)
// Wisp/Page reception
int intif_parse_WisMessage(int fd) { // rewritten by [Yor]
struct map_session_data* sd;
+ char *wisp_source;
int id=RFIFOL(fd,4);
int i=0; //,j=0;
// if(battle_config.etc_log)
// printf("intif_parse_wismessage: %d %s %s %s\n",id,RFIFOP(fd,6),RFIFOP(fd,30),RFIFOP(fd,54) );
-
- sd=map_nick2sd(RFIFOP(fd,32)); // 送信先を探す
- if(sd!=NULL && strcmp(sd->status.name, RFIFOP(fd,32)) == 0){
+
+ sd=(struct map_session_data *) map_nick2sd((char *) RFIFOP(fd,32)); // 送信先を探す
+ if(sd!=NULL && strcmp((char *) sd->status.name, (char *) RFIFOP(fd,32)) == 0){
/*
for(i=0;i<MAX_WIS_REFUSAL;i++){ //拒否リストに名前があるかどうか判定してあれば拒否
if(strcmp(sd->wis_refusal[i],RFIFOP(fd,8))==0){
@@ -563,9 +663,20 @@ int intif_parse_WisMessage(int fd) { // rewritten by [Yor]
else{
*/
- if(i == MAX_IGNORE_LIST) {
- clif_wis_message(sd->fd,RFIFOP(fd,8),RFIFOP(fd,56),RFIFOW(fd,2)-56);
- intif_wis_replay(RFIFOL(fd,4),0); // 送信成功
+ else {
+ wisp_source = (char *) RFIFOP(fd,8); // speed up [Yor]
+ for(i=0;i<MAX_IGNORE_LIST;i++){ //拒否リストに名前があるかどうか判定してあれば拒否
+ if(strcmp(sd->ignore[i].name, wisp_source)==0){
+ break;
+ }
+ }
+ if(i==MAX_IGNORE_LIST) // run out of list, so we are not ignored
+ {
+ clif_wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56);
+ intif_wis_replay(id,0); // 送信成功
+ }
+ else
+ intif_wis_replay(id, 2); // 受信拒否
}
}else
intif_wis_replay(id,1); // そんな人いません
@@ -578,7 +689,7 @@ int intif_parse_WisEnd(int fd) {
if (battle_config.etc_log)
printf("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP(fd,2), RFIFOB(fd,26)); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
- sd = map_nick2sd(RFIFOP(fd,2));
+ sd = (struct map_session_data *)map_nick2sd((char *) RFIFOP(fd,2));
if (sd != NULL)
clif_wis_end(sd->fd, RFIFOB(fd,26));
@@ -591,7 +702,7 @@ int mapif_parse_WisToGM(int fd) { // 0x3003/0x3803 <packet_len>.w <wispname>.24B
struct map_session_data *pl_sd;
char Wisp_name[24];
char mbuf[255];
- char *message = ((RFIFOW(fd,2) - 30) >= sizeof(mbuf)) ? (char *) malloc((RFIFOW(fd,2) - 30)) : mbuf;
+ char *message = (char *) (((RFIFOW(fd,2) - 30) >= sizeof(mbuf)) ? (char *) aMallocA((RFIFOW(fd,2) - 30)) : mbuf);
min_gm_level = (int)RFIFOW(fd,28);
memcpy(Wisp_name, RFIFOP(fd,4), 24);
@@ -600,12 +711,12 @@ int mapif_parse_WisToGM(int fd) { // 0x3003/0x3803 <packet_len>.w <wispname>.24B
message[sizeof(message) - 1] = '\0';
// information is sended to all online GM
for (i = 0; i < fd_max; i++)
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth)
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth)
if (pc_isGM(pl_sd) >= min_gm_level)
clif_wis_message(i, Wisp_name, message, strlen(message) + 1);
if (message != mbuf)
- free(message);
+ aFree(message);
return 0;
}
@@ -633,6 +744,13 @@ int intif_parse_LoadStorage(int fd) {
struct map_session_data *sd;
stor = account2storage( RFIFOL(fd,4));
+
+ if (stor->storage_status == 1) { // Already open.. lets ignore this update
+ if (battle_config.error_log)
+ printf("intif_parse_LoadStorage: storage received for a client already open\n");
+ return 0;
+ }
+
if (RFIFOW(fd,2)-8 != sizeof(struct storage)) {
if (battle_config.error_log)
printf("intif_parse_LoadStorage: data size error %d %d\n", RFIFOW(fd,2)-8, sizeof(struct storage));
@@ -647,6 +765,7 @@ int intif_parse_LoadStorage(int fd) {
if(battle_config.save_log)
printf("intif_openstorage: %d\n",RFIFOL(fd,4) );
memcpy(stor,RFIFOP(fd,8),sizeof(struct storage));
+ stor->dirty=0;
stor->storage_status=1;
sd->state.storage_flag = 0;
clif_storageitemlist(sd,stor);
@@ -712,7 +831,7 @@ int intif_parse_PartyCreated(int fd)
{
if(battle_config.etc_log)
printf("intif: party created\n");
- party_created(RFIFOL(fd,2),RFIFOB(fd,6),RFIFOL(fd,7),RFIFOP(fd,11));
+ party_created(RFIFOL(fd,2), RFIFOB(fd,6),RFIFOL(fd,7),(char *) RFIFOP(fd,11));
return 0;
}
// パーティ情報
@@ -752,7 +871,7 @@ int intif_parse_PartyMemberLeaved(int fd)
{
if(battle_config.etc_log)
printf("intif: party member leaved %d %d %s\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10));
- party_member_leaved(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10));
+ party_member_leaved(RFIFOL(fd,2),RFIFOL(fd,6),(char *) RFIFOP(fd,10));
return 0;
}
// パーティ解散通知
@@ -766,7 +885,7 @@ int intif_parse_PartyMove(int fd)
{
// if(battle_config.etc_log)
// printf("intif: party move %d %d %s %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27));
- party_recv_movemap(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27));
+ party_recv_movemap(RFIFOL(fd,2),RFIFOL(fd,6),(char *) RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27));
return 0;
}
// パーティメッセージ
@@ -774,7 +893,7 @@ int intif_parse_PartyMessage(int fd)
{
// if(battle_config.etc_log)
// printf("intif_parse_PartyMessage: %s\n",RFIFOP(fd,12));
- party_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),RFIFOP(fd,12),RFIFOW(fd,2)-12);
+ party_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12);
return 0;
}
@@ -815,7 +934,7 @@ int intif_parse_GuildMemberAdded(int fd)
int intif_parse_GuildMemberLeaved(int fd)
{
guild_member_leaved(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),
- RFIFOP(fd,55),RFIFOP(fd,15));
+ (char *) RFIFOP(fd,55), (char *) RFIFOP(fd,15));
return 0;
}
@@ -892,25 +1011,25 @@ int intif_parse_GuildSkillUp(int fd)
int intif_parse_GuildAlliance(int fd)
{
guild_allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),
- RFIFOB(fd,18),RFIFOP(fd,19),RFIFOP(fd,43));
+ RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43));
return 0;
}
// ギルド告知変更通知
int intif_parse_GuildNotice(int fd)
{
- guild_notice_changed(RFIFOL(fd,2),RFIFOP(fd,6),RFIFOP(fd,66));
+ guild_notice_changed(RFIFOL(fd,2),(char *) RFIFOP(fd,6),(char *) RFIFOP(fd,66));
return 0;
}
// ギルドエンブレム変更通知
int intif_parse_GuildEmblem(int fd)
{
- guild_emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8),RFIFOP(fd,12));
+ guild_emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8), (char *)RFIFOP(fd,12));
return 0;
}
// ギルド会話受信
int intif_parse_GuildMessage(int fd)
{
- guild_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),RFIFOP(fd,12),RFIFOW(fd,2)-12);
+ guild_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12);
return 0;
}
// ギルド城データ要求返信
@@ -999,7 +1118,7 @@ int intif_parse(int fd)
}
// 処理分岐
switch(cmd){
- case 0x3800: clif_GMmessage(NULL,RFIFOP(fd,4),packet_len-4,0); break;
+ case 0x3800: clif_GMmessage(NULL,(char *) RFIFOP(fd,4),packet_len-4,0); break;
case 0x3801: intif_parse_WisMessage(fd); break;
case 0x3802: intif_parse_WisEnd(fd); break;
case 0x3803: mapif_parse_WisToGM(fd); break;
diff --git a/src/map/intif.h b/src/map/intif.h
index 5077dbe18..17d6045ac 100644
--- a/src/map/intif.h
+++ b/src/map/intif.h
@@ -7,7 +7,7 @@ int intif_parse(int fd);
int intif_GMmessage(char* mes,int len,int flag);
int intif_wis_message(struct map_session_data *sd,char *nick,char *mes,int mes_len);
-int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes, int mes_len);
+int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes);
int intif_saveaccountreg(struct map_session_data *sd);
int intif_request_accountreg(struct map_session_data *sd);
@@ -18,7 +18,7 @@ int intif_request_guild_storage(int account_id, int guild_id);
int intif_send_guild_storage(int account_id, struct guild_storage *gstor);
-int intif_create_party(struct map_session_data *sd,char *name);
+int intif_create_party(struct map_session_data *sd,char *name,int item,int item2);
int intif_request_partyinfo(int party_id);
int intif_party_addmember(int party_id, int account_id);
int intif_party_changeoption(int party_id, int account_id, int exp, int item);
@@ -33,7 +33,7 @@ int intif_guild_create(const char *name, const struct guild_member *master);
int intif_guild_request_info(int guild_id);
int intif_guild_addmember(int guild_id, struct guild_member *m);
int intif_guild_leave(int guild_id, int account_id, int char_id, int flag, const char *mes);
-int intif_guild_memberinfoshort(int guild_id, int account_id, int char_id, int online, int lv, int class);
+int intif_guild_memberinfoshort(int guild_id, int account_id, int char_id, int online, int lv, int class_);
int intif_guild_break(int guild_id);
int intif_guild_message(int guild_id, int account_id, char *mes, int len);
int intif_guild_checkconflict(int guild_id, int account_id, int char_id);
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index a225cff83..91ec58c81 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -12,6 +12,7 @@
#include "itemdb.h"
#include "script.h"
#include "pc.h"
+#include "showmsg.h"
#ifdef MEMWATCH
#include "memwatch.h"
@@ -25,9 +26,9 @@
static struct dbt* item_db;
-static struct random_item_data blue_box[MAX_RANDITEM],violet_box[MAX_RANDITEM],card_album[MAX_RANDITEM],gift_box[MAX_RANDITEM],scroll[MAX_RANDITEM];
-static int blue_box_count=0,violet_box_count=0,card_album_count=0,gift_box_count=0,scroll_count=0;
-static int blue_box_default=0,violet_box_default=0,card_album_default=0,gift_box_default=0,scroll_default=0;
+static struct random_item_data blue_box[MAX_RANDITEM], violet_box[MAX_RANDITEM], card_album[MAX_RANDITEM], gift_box[MAX_RANDITEM], scroll[MAX_RANDITEM], finding_ore[MAX_RANDITEM];
+static int blue_box_count=0, violet_box_count=0, card_album_count=0, gift_box_count=0, scroll_count=0, finding_ore_count = 0;
+static int blue_box_default=0, violet_box_default=0, card_album_default=0, gift_box_default=0, scroll_default=0, finding_ore_default = 0;
// Function declarations
@@ -39,7 +40,11 @@ static int itemdb_read_sqldb(void);
static int itemdb_read_randomitem();
static int itemdb_read_itemavail(void);
static int itemdb_read_itemnametable(void);
+static int itemdb_read_itemslottable(void);
+static int itemdb_read_itemslotcounttable(void);
+static int itemdb_read_cardillustnametable(void);
static int itemdb_read_noequip(void);
+static int itemdb_read_norefine(void);
void itemdb_reload(void);
/*==========================================
@@ -97,16 +102,18 @@ int itemdb_searchrandomid(int flags)
struct {
int nameid,count;
struct random_item_data *list;
- } data[] ={
- { 0,0,NULL },
- { blue_box_default ,blue_box_count ,blue_box },
- { violet_box_default,violet_box_count ,violet_box },
- { card_album_default,card_album_count ,card_album },
- { gift_box_default ,gift_box_count ,gift_box },
- { scroll_default ,scroll_count ,scroll },
- };
-
- if(flags>=1 && flags<=5){
+ } data[7];
+
+ // for BCC32 compile error
+ data[0].nameid = 0; data[0].count = 0; data[0].list = NULL;
+ data[1].nameid = blue_box_default; data[1].count = blue_box_count; data[1].list = blue_box;
+ data[2].nameid = violet_box_default; data[2].count = violet_box_count; data[2].list = violet_box;
+ data[3].nameid = card_album_default; data[3].count = card_album_count; data[3].list = card_album;
+ data[4].nameid = gift_box_default; data[4].count = gift_box_count; data[4].list = gift_box;
+ data[5].nameid = scroll_default; data[5].count = scroll_count; data[5].list = scroll;
+ data[6].nameid = finding_ore_default; data[6].count = finding_ore_count; data[6].list = finding_ore;
+
+ if(flags>=1 && flags<=6){
nameid=data[flags].nameid;
count=data[flags].count;
list=data[flags].list;
@@ -130,7 +137,7 @@ int itemdb_searchrandomid(int flags)
*/
struct item_data* itemdb_exists(int nameid)
{
- return numdb_search(item_db,nameid);
+ return (struct item_data *) numdb_search(item_db,nameid);
}
/*==========================================
* DBの検索
@@ -140,7 +147,7 @@ struct item_data* itemdb_search(int nameid)
{
struct item_data *id;
- id=numdb_search(item_db,nameid);
+ id=(struct item_data *) numdb_search(item_db,nameid);
if(id) return id;
id=(struct item_data *)aCalloc(1,sizeof(struct item_data));
@@ -152,7 +159,7 @@ struct item_data* itemdb_search(int nameid)
id->weight=10;
id->sex=2;
id->elv=0;
- id->class=0xffffffff;
+ id->class_=0xffffffff;
id->flag.available=0;
id->flag.value_notdc=0; //一応・・・
id->flag.value_notoc=0;
@@ -237,66 +244,40 @@ int itemdb_isdropable(int nameid)
return 1;
}
-//
-// 初期化
-//
-/*==========================================
- *
- *------------------------------------------
- */
-static int itemdb_read_itemslottable(void)
-{
- char *buf,*p;
- int s;
-
- buf=grfio_read("data\\itemslottable.txt");
- if(buf==NULL)
- return -1;
- s=grfio_size("data\\itemslottable.txt");
- buf[s]=0;
- for(p=buf;p-buf<s;){
- int nameid,equip;
- sscanf(p,"%d#%d#",&nameid,&equip);
- itemdb_search(nameid)->equip=equip;
- p=strchr(p,10);
- if(!p) break;
- p++;
- p=strchr(p,10);
- if(!p) break;
- p++;
- }
- free(buf);
-
- return 0;
-}
-
-#ifndef TXT_ONLY
/*====================================
* Removed item_value_db, don't re-add
*------------------------------------
*/
static void itemdb_read(void)
{
- itemdb_read_itemslottable();
-
- if (db_use_sqldbs)
- {
- itemdb_read_sqldb();
- }
- else
- {
+ #ifndef TXT_ONLY
+ if (db_use_sqldbs)
+ {
+ itemdb_read_sqldb();
+ }
+ else
+ {
+ itemdb_readdb();
+ }
+ /* not TXT_ONLY */
+ #else
itemdb_readdb();
- }
+ #endif /* TXT_ONLY */
itemdb_read_randomitem();
itemdb_read_itemavail();
itemdb_read_noequip();
-
- if (!battle_config.item_name_override_grffile)
+ itemdb_read_norefine();
+ if (battle_config.cardillust_read_grffile)
+ itemdb_read_cardillustnametable();
+ if (battle_config.item_equip_override_grffile)
+ itemdb_read_itemslottable();
+ if (battle_config.item_slots_override_grffile)
+ itemdb_read_itemslotcounttable();
+ if (battle_config.item_name_override_grffile)
itemdb_read_itemnametable();
}
-#endif /* not TXT_ONLY */
/*==========================================
* アイテムデータベースの読み込み
*------------------------------------------
@@ -346,20 +327,36 @@ static int itemdb_readdb(void)
memcpy(id->name,str[1],24);
memcpy(id->jname,str[2],24);
id->type=atoi(str[3]);
- // buy≠sell*2 は item_value_db.txt で指定してください。
- if (atoi(str[5])) { // sell値を優先とする
- id->value_buy=atoi(str[5])*2;
- id->value_sell=atoi(str[5]);
- } else {
- id->value_buy=atoi(str[4]);
- id->value_sell=atoi(str[4])/2;
+
+ {
+ int buy = atoi(str[4]), sell = atoi(str[5]);
+ // if buying price > selling price * 2 consider it valid and don't change it [celest]
+ if (buy && sell && buy > sell*2){
+ id->value_buy = buy;
+ id->value_sell = sell;
+ } else {
+ // buy≠sell*2 は item_value_db.txt で指定してください。
+ if (sell) { // sell値を優先とする
+ id->value_buy = sell*2;
+ id->value_sell = sell;
+ } else {
+ id->value_buy = buy;
+ id->value_sell = buy/2;
+ }
+ }
+ // check for bad prices that can possibly cause exploits
+ if (id->value_buy*75/100 < id->value_sell*124/100) {
+ sprintf (tmp_output, "Item %s [%d] buying:%d < selling:%d\n",
+ id->name, id->nameid, id->value_buy*75/100, id->value_sell*124/100);
+ ShowWarning (tmp_output);
+ }
}
id->weight=atoi(str[6]);
id->atk=atoi(str[7]);
id->def=atoi(str[8]);
id->range=atoi(str[9]);
id->slot=atoi(str[10]);
- id->class=atoi(str[11]);
+ id->class_=atoi(str[11]);
id->sex=atoi(str[12]);
if(id->equip != atoi(str[13])){
id->equip=atoi(str[13]);
@@ -377,13 +374,17 @@ static int itemdb_readdb(void)
if((p=strchr(np,'{'))==NULL)
continue;
- id->use_script = parse_script(p,lines);
+ id->use_script = parse_script((unsigned char *) p,lines);
if((p=strchr(p+1,'{'))==NULL)
continue;
- id->equip_script = parse_script(p,lines);
+ id->equip_script = parse_script((unsigned char *) p,lines);
}
fclose(fp);
- printf("read %s done (count=%d)\n",filename[i],ln);
+ 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;
}
@@ -410,15 +411,16 @@ static int itemdb_read_randomitem()
{"db/item_bluebox.txt", blue_box, &blue_box_count, &blue_box_default },
{"db/item_violetbox.txt", violet_box, &violet_box_count, &violet_box_default },
{"db/item_cardalbum.txt", card_album, &card_album_count, &card_album_default },
- {"db/item_giftbox.txt", gift_box, &gift_box_count, &gift_box_default },
- {"db/item_scroll.txt", scroll, &scroll_count, &scroll_default },
+ {"db/item_giftbox.txt", gift_box, &gift_box_count, &gift_box_default },
+ {"db/item_scroll.txt", scroll, &scroll_count, &scroll_default },
+ {"db/item_findingore.txt", finding_ore,&finding_ore_count, &finding_ore_default },
};
for(i=0;i<sizeof(data)/sizeof(data[0]);i++){
struct random_item_data *pd=data[i].pdata;
int *pc=data[i].pcount;
int *pdefault=data[i].pdefault;
- char *fn=data[i].filename;
+ char *fn=(char *) data[i].filename;
*pdefault = 0;
if( (fp=fopen(fn,"r"))==NULL ){
@@ -458,7 +460,10 @@ static int itemdb_read_randomitem()
ln++;
}
fclose(fp);
- printf("read %s done (count=%d)\n",fn,*pc);
+ 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;
@@ -507,7 +512,8 @@ static int itemdb_read_itemavail(void)
ln++;
}
fclose(fp);
- printf("read db/item_avail.txt done (count=%d)\n",ln);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/item_avail.txt");
+ ShowStatus(tmp_output);
return 0;
}
@@ -520,7 +526,7 @@ static int itemdb_read_itemnametable(void)
char *buf,*p;
int s;
- buf=grfio_reads("data\\idnum2itemdisplaynametable.txt",&s);
+ buf=(char *) grfio_reads("data\\idnum2itemdisplaynametable.txt",&s);
if(buf==NULL)
return -1;
@@ -547,12 +553,13 @@ static int itemdb_read_itemnametable(void)
if(!p) break;
p++;
}
- free(buf);
- printf("read data\\idnum2itemdisplaynametable.txt done.\n");
+ aFree(buf);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\idnum2itemdisplaynametable.txt");
+ ShowStatus(tmp_output);
return 0;
}
-#ifdef TXT_ONLY
+
/*==========================================
* カードイラストのリソース名前テーブルを読み込む
*------------------------------------------
@@ -562,7 +569,7 @@ static int itemdb_read_cardillustnametable(void)
char *buf,*p;
int s;
- buf=grfio_reads("data\\num2cardillustnametable.txt",&s);
+ buf=(char *) grfio_reads("data\\num2cardillustnametable.txt",&s);
if(buf==NULL)
return -1;
@@ -582,12 +589,83 @@ static int itemdb_read_cardillustnametable(void)
if(!p) break;
p++;
}
- free(buf);
- printf("read data\\num2cardillustnametable.txt done.\n");
+ aFree(buf);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\num2cardillustnametable.txt");
+ ShowStatus(tmp_output);
+
+ return 0;
+}
+
+//
+// 初期化
+//
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int itemdb_read_itemslottable(void)
+{
+ char *buf,*p;
+ int s;
+
+ buf=(char *) grfio_read("data\\itemslottable.txt");
+ if(buf==NULL)
+ return -1;
+ s=grfio_size("data\\itemslottable.txt");
+ buf[s]=0;
+ for(p=buf;p-buf<s;){
+ int nameid,equip;
+ struct item_data* item;
+ sscanf(p,"%d#%d#",&nameid,&equip);
+ item = itemdb_search(nameid);
+ if (item && itemdb_isequip2(item))
+ item->equip=equip;
+ p=strchr(p,10);
+ if(!p) break;
+ p++;
+ p=strchr(p,10);
+ if(!p) break;
+ p++;
+ }
+ aFree(buf);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\itemslottable.txt");
+ ShowStatus(tmp_output);
+
+ return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int itemdb_read_itemslotcounttable(void)
+{
+ char *buf,*p;
+ int s;
+
+ buf=(char *) grfio_read("data\\itemslotcounttable.txt");
+ if(buf==NULL)
+ return -1;
+ s=grfio_size("data\\itemslotcounttable.txt");
+ buf[s]=0;
+ for(p=buf;p-buf<s;){
+ int nameid,slot;
+ sscanf(p,"%d#%d#",&nameid,&slot);
+ itemdb_search(nameid)->slot=slot;
+ p=strchr(p,10);
+ if(!p) break;
+ p++;
+ p=strchr(p,10);
+ if(!p) break;
+ p++;
+ }
+ aFree(buf);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\itemslotcounttable.txt");
+ ShowStatus(tmp_output);
return 0;
}
-#endif /* TXT_ONLY */
+
/*==========================================
* 装備制限ファイル読み出し
*------------------------------------------
@@ -627,9 +705,47 @@ static int itemdb_read_noequip(void)
}
fclose(fp);
- printf("read db/item_noequip.txt done (count=%d)\n",ln);
+ 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;
}
+
+/*================================================
+ * Whether the item can be refined or not [Celest]
+ *------------------------------------------------
+ */
+static int itemdb_read_norefine(void)
+{
+ int i, nameid;
+ struct item_data *id;
+ // To-do: let it read from a text file later
+ int cant_refine[] = {
+ 1243, 1530, 2110, 2112, 2201, 2202, 2203, 2204, 2205, 2210,
+ 2212, 2218, 2219, 2237, 2238, 2239, 2240, 2241, 2242, 2243,
+ 2250, 2253, 2260, 2262, 2263, 2264, 2265, 2266, 2267, 2268,
+ 2269, 2270, 2271, 2276, 2278, 2279, 2281, 2282, 2286, 2288,
+ 2289, 2290, 2291, 2292, 2293, 2295, 2296, 2297, 2298, 2352,
+ 2410, 2413, 2414, 2509, 2510, 2601, 2602, 2603, 2604, 2605,
+ 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616,
+ 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626,
+ 2627, 2628, 2629, 2630, 2631, 2634, 2635, 2636, 2637, 2638,
+ 2639, 2640, 5004, 5005, 5006, 5008, 5014, 5015, 5037, 5039,
+ 5040, 5043, 5046, 5049, 5050, 5051, 5053, 5054, 5055, 5058,
+ 5068, 5074, 5085, 5086, 5087, 5088, 5089, 5090, 5096, 5098, 0
+ };
+
+ for (i=0; i < (int)(sizeof(cant_refine) / sizeof(cant_refine[0])); i++) {
+ nameid = cant_refine[i];
+ if(nameid<=0 || nameid>=20000 || !(id=itemdb_exists(nameid)))
+ continue;
+ id->flag.no_refine = 1;
+ }
+
+ return 1;
+}
+
#ifndef TXT_ONLY
/*======================================
@@ -673,7 +789,7 @@ static int itemdb_read_sqldb(void)
// Insert a new row into the item database
- /*id = calloc(sizeof(struct item_data), 1);
+ /*id = aCalloc(sizeof(struct item_data), 1);
if (id == NULL)
{
@@ -723,7 +839,7 @@ static int itemdb_read_sqldb(void)
id->def = (sql_row[8] != NULL) ? atoi(sql_row[8]) : 0;
id->range = (sql_row[9] != NULL) ? atoi(sql_row[9]) : 0;
id->slot = (sql_row[10] != NULL) ? atoi(sql_row[10]) : 0;
- id->class = (sql_row[11] != NULL) ? atoi(sql_row[11]) : 0;
+ id->class_ = (sql_row[11] != NULL) ? atoi(sql_row[11]) : 0;
id->sex = (sql_row[12] != NULL) ? atoi(sql_row[12]) : 0;
id->equip = (sql_row[13] != NULL) ? atoi(sql_row[13]) : 0;
id->wlv = (sql_row[14] != NULL) ? atoi(sql_row[14]) : 0;
@@ -737,10 +853,10 @@ static int itemdb_read_sqldb(void)
if (sql_row[17] != NULL)
{
if (sql_row[17][0] == '{')
- id->use_script = parse_script(sql_row[17], 0);
+ id->use_script = parse_script((unsigned char *) sql_row[17], 0);
else {
sprintf(script, "{%s}", sql_row[17]);
- id->use_script = parse_script(script, 0);
+ id->use_script = parse_script((unsigned char *) script, 0);
}
}
else
@@ -751,10 +867,10 @@ static int itemdb_read_sqldb(void)
if (sql_row[18] != NULL)
{
if (sql_row[18][0] == '{')
- id->equip_script = parse_script(sql_row[18], 0);
+ id->equip_script = parse_script((unsigned char *) sql_row[18], 0);
else {
sprintf(script, "{%s}", sql_row[18]);
- id->equip_script = parse_script(script, 0);
+ id->equip_script = parse_script((unsigned char *) script, 0);
}
}
else
@@ -774,8 +890,8 @@ static int itemdb_read_sqldb(void)
{
printf("Database server error (retrieving rows from %s): %s\n", item_db_db, mysql_error(&mmysql_handle));
}
-
- printf("read %s done (count = %lu)\n", item_db_db, (unsigned long) mysql_num_rows(sql_res));
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",(unsigned long) mysql_num_rows(sql_res),item_db_db);
+ ShowStatus(tmp_output);
}
else
{
@@ -802,26 +918,20 @@ static int itemdb_final(void *key,void *data,va_list ap)
{
struct item_data *id;
- nullpo_retr(0, id=data);
+ nullpo_retr(0, id= (struct item_data *) data);
if(id->use_script)
- free(id->use_script);
+ aFree(id->use_script);
if(id->equip_script)
- free(id->equip_script);
- free(id);
+ aFree(id->equip_script);
+ aFree(id);
return 0;
}
void itemdb_reload(void)
{
- /*
-
- <empty item databases>
- itemdb_read();
-
- */
-
+ numdb_final(item_db,itemdb_final);
do_init_itemdb();
}
@@ -851,23 +961,6 @@ void itemdebugtxt()
fclose(dfp);
}
*/
-#ifdef TXT_ONLY
-/*====================================
- * Removed item_value_db, don't re-add
- *------------------------------------
- */
-static void itemdb_read(void)
-{
- itemdb_read_itemslottable();
- itemdb_readdb();
- itemdb_read_randomitem();
- itemdb_read_itemavail();
- itemdb_read_noequip();
- itemdb_read_cardillustnametable();
- if (!battle_config.item_name_override_grffile)
- itemdb_read_itemnametable();
-}
-#endif /* TXT_ONLY */
/*==========================================
*
*------------------------------------------
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index 0edfad243..2ba6ae7f6 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -12,7 +12,7 @@ struct item_data {
int value_buy;
int value_sell;
int type;
- int class;
+ int class_;
int sex;
int equip;
int weight;
@@ -33,6 +33,7 @@ struct item_data {
unsigned no_equip : 3;
unsigned no_drop : 1;
unsigned no_use : 1;
+ unsigned no_refine : 1; // [celest]
} flag;
int view_id;
};
diff --git a/src/map/log.c b/src/map/log.c
index 86c5a41a2..7cf4dfcf4 100644
--- a/src/map/log.c
+++ b/src/map/log.c
@@ -3,69 +3,117 @@
#include <stdio.h>
#include <string.h>
+#include "../common/strlib.h"
+#include "../common/nullpo.h"
+#include "itemdb.h"
#include "map.h"
-#include "nullpo.h"
#include "log.h"
struct Log_Config log_config;
+char timestring[255];
+time_t curtime;
+
+//FILTER OPTIONS
+//0 = Don't log
+//1 = Log any item
+//Bits: ||
+//2 - Healing items (0)
+//3 - Etc Items(3) + Arrows (10)
+//4 - Usable Items(2)
+//5 - Weapon(4)
+//6 - Shields,Armor,Headgears,Accessories,etc(5)
+//7 - Cards(6)
+//8 - Pet Accessories(8) + Eggs(7) (well, monsters don't drop 'em but we'll use the same system for ALL logs)
+//9 - Log expensive items ( >= price_log)
+//10 - Log big amount of items ( >= amount_log)
+//11 - Log refined items (if their refine >= refine_log )
+//12 - Log rare items (if their drop chance <= rare_log )
+
+//check if this item should be logger according the settings
+int should_log_item(int filter, int nameid) {
+ struct item_data *item_data;
+ if (nameid<512 || (item_data= itemdb_search(nameid)) == NULL) return 0;
+ if ( (filter&1) || // Filter = 1, we log any item
+ (filter&2 && item_data->type == 0 ) || //healing items
+ (filter&4 && (item_data->type == 3 || item_data->type == 10) ) || //etc+arrows
+ (filter&8 && item_data->type == 2 ) || //usable
+ (filter&16 && item_data->type == 4 ) || //weapon
+ (filter&32 && item_data->type == 5 ) || //armor
+ (filter&64 && item_data->type == 6 ) || //cards
+ (filter&128 && (item_data->type == 7 || item_data->type == 8) ) || //eggs+pet access
+ (filter&256 && item_data->value_buy >= log_config.price_items_log ) ||
+ (filter&512 && item_data->refine >= log_config.refine_items_log )
+ ) return item_data->nameid;
+
+ return 0;
+}
+
int log_branch(struct map_session_data *sd)
{
+#ifndef TXT_ONLY
+ char t_name[100];
+#endif
FILE *logfp;
if(log_config.enable_logs <= 0)
return 0;
nullpo_retr(0, sd);
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
if(log_config.sql_logs > 0)
{
- sprintf(tmp_sql, "INSERT INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%s')", log_config.log_branch_db, sd->status.account_id, sd->status.char_id, sd->status.name, sd->mapname);
+ sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%s')",
+ log_config.log_branch_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), sd->mapname);
if(mysql_query(&mmysql_handle, tmp_sql))
printf("DB server Error - %s\n",mysql_error(&mmysql_handle));
} else {
- #endif
- if((logfp=fopen(log_config.log_drop,"a+")) != NULL) {
- char timestring[255];
- time_t curtime;
+#endif
+ if((logfp=fopen(log_config.log_branch,"a+")) != NULL) {
time(&curtime);
strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
fprintf(logfp,"%s - %s[%d:%d]\t%s%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, sd->mapname, RETCODE);
fclose(logfp);
}
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
}
- #endif
+#endif
return 0;
}
int log_drop(struct map_session_data *sd, int monster_id, int *log_drop)
{
FILE *logfp;
+ int i,flag = 0;
if(log_config.enable_logs <= 0)
return 0;
nullpo_retr(0, sd);
- #ifndef TXT_ONLY
+ for (i = 0; i<10; i++) { //Should we log these items? [Lupus]
+ flag += should_log_item(log_config.drop,log_drop[i]);
+ }
+ if (flag==0) return 0; //we skip logging this items set - they doesn't met our logging conditions [Lupus]
+
+#ifndef TXT_ONLY
if(log_config.sql_logs > 0)
{
- sprintf(tmp_sql, "INSERT INTO `%s` (`drop_date`, `kill_char_id`, `monster_id`, `item1`, `item2`, `item3`, `item4`, `item5`, `item6`, `item7`, `item8`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s') ", log_config.log_drop_db, sd->status.char_id, monster_id, log_drop[0], log_drop[1], log_drop[2], log_drop[3], log_drop[4], log_drop[5], log_drop[6], log_drop[7], sd->mapname);
+ sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`drop_date`, `kill_char_id`, `monster_id`, `item1`, `item2`, `item3`, `item4`, `item5`, `item6`, `item7`, `item8`, `item9`, `itemCard`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s') ", log_config.log_drop_db, sd->status.char_id, monster_id, log_drop[0], log_drop[1], log_drop[2], log_drop[3], log_drop[4], log_drop[5], log_drop[6], log_drop[7], log_drop[8], log_drop[9], sd->mapname);
if(mysql_query(&mmysql_handle, tmp_sql))
printf("DB server Error - %s\n",mysql_error(&mmysql_handle));
} else {
- #endif
+#endif
if((logfp=fopen(log_config.log_drop,"a+")) != NULL) {
- char timestring[255];
+
time_t curtime;
time(&curtime);
strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
- fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d,%d,%d,%d,%d,%d,%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, log_drop[0], log_drop[1], log_drop[2], log_drop[3], log_drop[4], log_drop[5], log_drop[6], log_drop[7], RETCODE);
+ fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, log_drop[0], log_drop[1], log_drop[2], log_drop[3], log_drop[4], log_drop[5], log_drop[6], log_drop[7], log_drop[8], log_drop[9], RETCODE);
fclose(logfp);
}
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
}
- #endif
- return 0;
+#endif
+ return 1; //Logged
}
int log_mvpdrop(struct map_session_data *sd, int monster_id, int *log_mvp)
@@ -75,81 +123,87 @@ int log_mvpdrop(struct map_session_data *sd, int monster_id, int *log_mvp)
if(log_config.enable_logs <= 0)
return 0;
nullpo_retr(0, sd);
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
if(log_config.sql_logs > 0)
{
- sprintf(tmp_sql, "INSERT INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", log_config.log_mvpdrop_db, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], sd->mapname);
+ sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", log_config.log_mvpdrop_db, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], sd->mapname);
if(mysql_query(&mmysql_handle, tmp_sql))
printf("DB server Error - %s\n",mysql_error(&mmysql_handle));
} else {
- #endif
+#endif
if((logfp=fopen(log_config.log_mvpdrop,"a+")) != NULL) {
- char timestring[255];
- time_t curtime;
time(&curtime);
strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], RETCODE);
fclose(logfp);
}
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
}
- #endif
+#endif
return 0;
}
int log_present(struct map_session_data *sd, int source_type, int nameid)
{
FILE *logfp;
+#ifndef TXT_ONLY
+ char t_name[100];
+#endif
+
if(log_config.enable_logs <= 0)
return 0;
nullpo_retr(0, sd);
- #ifndef TXT_ONLY
+ if(!should_log_item(log_config.present,nameid)) return 0; //filter [Lupus]
+#ifndef TXT_ONLY
if(log_config.sql_logs > 0)
{
- sprintf(tmp_sql, "INSERT INTO `%s` (`present_date`, `src_id`, `account_id`, `char_id`, `char_name`, `nameid`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%s', '%d', '%s') ", log_config.log_present_db, source_type, sd->status.account_id, sd->status.char_id, sd->status.name, nameid, sd->mapname);
+ sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`present_date`, `src_id`, `account_id`, `char_id`, `char_name`, `nameid`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%s', '%d', '%s') ",
+ log_config.log_present_db, source_type, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), nameid, sd->mapname);
if(mysql_query(&mmysql_handle, tmp_sql))
printf("DB server Error - %s\n",mysql_error(&mmysql_handle));
} else {
- #endif
+#endif
if((logfp=fopen(log_config.log_present,"a+")) != NULL) {
- char timestring[255];
- time_t curtime;
time(&curtime);
strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, source_type, nameid, RETCODE);
fclose(logfp);
}
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
}
- #endif
+#endif
return 0;
}
int log_produce(struct map_session_data *sd, int nameid, int slot1, int slot2, int slot3, int success)
{
FILE *logfp;
+#ifndef TXT_ONLY
+ char t_name[100];
+#endif
+
if(log_config.enable_logs <= 0)
return 0;
nullpo_retr(0, sd);
- #ifndef TXT_ONLY
+ if(!should_log_item(log_config.produce,nameid)) return 0; //filter [Lupus]
+#ifndef TXT_ONLY
if(log_config.sql_logs > 0)
{
- sprintf(tmp_sql, "INSERT INTO `%s` (`produce_date`, `account_id`, `char_id`, `char_name`, `nameid`, `slot1`, `slot2`, `slot3`, `map`, `success`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%s', '%d') ", log_config.log_produce_db, sd->status.account_id, sd->status.char_id, sd->status.name, nameid, slot1, slot2, slot3, sd->mapname, success);
+ sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`produce_date`, `account_id`, `char_id`, `char_name`, `nameid`, `slot1`, `slot2`, `slot3`, `map`, `success`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%s', '%d') ",
+ log_config.log_produce_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), nameid, slot1, slot2, slot3, sd->mapname, success);
if(mysql_query(&mmysql_handle, tmp_sql))
printf("DB server Error - %s\n",mysql_error(&mmysql_handle));
} else {
- #endif
+#endif
if((logfp=fopen(log_config.log_produce,"a+")) != NULL) {
- char timestring[255];
- time_t curtime;
time(&curtime);
strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d,%d\t%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, nameid, slot1, slot2, slot3, success, RETCODE);
fclose(logfp);
}
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
}
- #endif
+#endif
return 0;
}
@@ -159,6 +213,9 @@ int log_refine(struct map_session_data *sd, int n, int success)
int log_card[4];
int item_level;
int i;
+#ifndef TXT_ONLY
+ char t_name[100];
+#endif
if(log_config.enable_logs <= 0)
return 0;
@@ -169,37 +226,100 @@ int log_refine(struct map_session_data *sd, int n, int success)
item_level = 0;
else
item_level = sd->status.inventory[n].refine + 1;
-
+ if(!should_log_item(log_config.refine,sd->status.inventory[n].nameid)) return 0; //filter [Lupus]
for(i=0;i<4;i++)
log_card[i] = sd->status.inventory[n].card[i];
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
if(log_config.sql_logs > 0)
{
- sprintf(tmp_sql, "INSERT INTO `%s` (`refine_date`, `account_id`, `char_id`, `char_name`, `nameid`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `success`, `item_level`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%d', '%d')", log_config.log_refine_db, sd->status.account_id, sd->status.char_id, sd->status.name, sd->status.inventory[n].nameid, sd->status.inventory[n].refine, log_card[0], log_card[1], log_card[2], log_card[3], sd->mapname, success, item_level);
+ sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`refine_date`, `account_id`, `char_id`, `char_name`, `nameid`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `success`, `item_level`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%d', '%d')",
+ log_config.log_refine_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), sd->status.inventory[n].nameid, sd->status.inventory[n].refine, log_card[0], log_card[1], log_card[2], log_card[3], sd->mapname, success, item_level);
if(mysql_query(&mmysql_handle, tmp_sql))
printf("DB server Error - %s\n",mysql_error(&mmysql_handle));
} else {
- #endif
+#endif
if((logfp=fopen(log_config.log_refine,"a+")) != NULL) {
- char timestring[255];
- time_t curtime;
time(&curtime);
strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
fprintf(logfp,"%s - %s[%d:%d]\t%d,%d\t%d%d%d%d\t%d,%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, sd->status.inventory[n].nameid, sd->status.inventory[n].refine, log_card[0], log_card[1], log_card[2], log_card[3], success, item_level, RETCODE);
fclose(logfp);
}
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
}
- #endif
+#endif
return 0;
}
+int log_tostorage(struct map_session_data *sd,int n, int guild)
+{
+ FILE *logfp;
+
+ if(log_config.enable_logs <= 0 || log_config.storage == 0 || log_config.log_storage[0] == '\0')
+ return 0;
+
+ nullpo_retr(0, sd);
+ if(sd->status.inventory[n].nameid==0 || sd->inventory_data[n] == NULL)
+ return 1;
+
+ if(sd->status.inventory[n].amount < 0)
+ return 1;
+
+ if((logfp=fopen(log_config.log_trade,"a+")) != NULL) {
+ time(&curtime);
+ strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
+ fprintf(logfp,"%s - to %s: %s[%d:%d]\t%d\t%d\t%d\t%d,%d,%d,%d%s", timestring, guild ? "guild_storage": "storage", sd->status.name, sd->status.account_id, sd->status.char_id,
+ sd->status.inventory[n].nameid,
+ sd->status.inventory[n].amount,
+ sd->status.inventory[n].refine,
+ sd->status.inventory[n].card[0],
+ sd->status.inventory[n].card[1],
+ sd->status.inventory[n].card[2],
+ sd->status.inventory[n].card[3], RETCODE);
+ fclose(logfp);
+ }
+ return 0;
+}
+
+int log_fromstorage(struct map_session_data *sd,int n, int guild)
+{
+ FILE *logfp;
+
+ if(log_config.enable_logs <= 0 || log_config.storage == 0 || log_config.log_storage[0] == '\0')
+ return 0;
+
+ nullpo_retr(0, sd);
+
+ if(sd->status.inventory[n].nameid==0 || sd->inventory_data[n] == NULL)
+ return 1;
+
+ if(sd->status.inventory[n].amount < 0)
+ return 1;
+
+ if((logfp=fopen(log_config.log_trade,"a+")) != NULL) {
+ time(&curtime);
+ strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
+ fprintf(logfp,"%s - from %s: %s[%d:%d]\t%d\t%d\t%d\t%d,%d,%d,%d%s", timestring, guild ? "guild_storage": "storage", sd->status.name, sd->status.account_id, sd->status.char_id,
+ sd->status.inventory[n].nameid,
+ sd->status.inventory[n].amount,
+ sd->status.inventory[n].refine,
+ sd->status.inventory[n].card[0],
+ sd->status.inventory[n].card[1],
+ sd->status.inventory[n].card[2],
+ sd->status.inventory[n].card[3], RETCODE);
+ fclose(logfp);
+ }
+ return 0;
+}
+
int log_trade(struct map_session_data *sd, struct map_session_data *target_sd, int n,int amount)
{
FILE *logfp;
int log_nameid, log_amount, log_refine, log_card[4];
int i;
+#ifndef TXT_ONLY
+ char t_name[100],t_name2[100];
+#endif
if(log_config.enable_logs <= 0)
return 0;
@@ -211,7 +331,7 @@ int log_trade(struct map_session_data *sd, struct map_session_data *target_sd, i
if(sd->status.inventory[n].amount < 0)
return 1;
-
+ if(!should_log_item(log_config.trade,sd->status.inventory[n].nameid)) return 0; //filter [Lupus]
log_nameid = sd->status.inventory[n].nameid;
log_amount = sd->status.inventory[n].amount;
log_refine = sd->status.inventory[n].refine;
@@ -219,25 +339,24 @@ int log_trade(struct map_session_data *sd, struct map_session_data *target_sd, i
for(i=0;i<4;i++)
log_card[i] = sd->status.inventory[n].card[i];
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
if(log_config.sql_logs > 0)
{
- sprintf(tmp_sql, "INSERT INTO `%s` (`trade_date`, `src_account_id`, `src_char_id`, `src_char_name`, `des_account_id`, `des_char_id`, `des_char_name`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')", log_config.log_trade_db, sd->status.account_id, sd->status.char_id, sd->status.name, target_sd->status.account_id, target_sd->status.char_id, target_sd->status.name, log_nameid, log_amount, log_refine, log_card[0], log_card[1], log_card[2], log_card[3], sd->mapname);
+ sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`trade_date`, `src_account_id`, `src_char_id`, `src_char_name`, `des_account_id`, `des_char_id`, `des_char_name`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')",
+ log_config.log_trade_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), target_sd->status.account_id, target_sd->status.char_id, jstrescapecpy(t_name2, target_sd->status.name), log_nameid, log_amount, log_refine, log_card[0], log_card[1], log_card[2], log_card[3], sd->mapname);
if(mysql_query(&mmysql_handle, tmp_sql))
printf("DB server Error - %s\n",mysql_error(&mmysql_handle));
} else {
- #endif
+#endif
if((logfp=fopen(log_config.log_trade,"a+")) != NULL) {
- char timestring[255];
- time_t curtime;
time(&curtime);
strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
fprintf(logfp,"%s - %s[%d:%d]\t%s[%d:%d]\t%d\t%d\t%d\t%d,%d,%d,%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, target_sd->status.name, target_sd->status.account_id, target_sd->status.char_id, log_nameid, log_amount, log_refine, log_card[0], log_card[1], log_card[2], log_card[3], RETCODE);
fclose(logfp);
}
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
}
- #endif
+#endif
return 0;
}
@@ -246,6 +365,9 @@ int log_vend(struct map_session_data *sd,struct map_session_data *vsd,int n,int
FILE *logfp;
int log_nameid, log_amount, log_refine, log_card[4];
int i;
+#ifndef TXT_ONLY
+ char t_name[100],t_name2[100];
+#endif
if(log_config.enable_logs <= 0)
return 0;
@@ -255,88 +377,124 @@ int log_vend(struct map_session_data *sd,struct map_session_data *vsd,int n,int
return 1;
if(sd->status.inventory[n].amount< 0)
return 1;
-
+ if(!should_log_item(log_config.vend,sd->status.inventory[n].nameid)) return 0; //filter [Lupus]
log_nameid = sd->status.inventory[n].nameid;
log_amount = sd->status.inventory[n].amount;
log_refine = sd->status.inventory[n].refine;
for(i=0;i<4;i++)
log_card[i] = sd->status.inventory[n].card[i];
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
if(log_config.sql_logs > 0)
{
- sprintf(tmp_sql, "INSERT INTO `%s` (`vend_date`, `vend_account_id`, `vend_char_id`, `vend_char_name`, `buy_account_id`, `buy_char_id`, `buy_char_name`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `zeny`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%d')", log_config.log_vend_db, sd->status.account_id, sd->status.char_id, sd->status.name, vsd->status.account_id, vsd->status.char_id, vsd->status.name, log_nameid, log_amount, log_refine, log_card[0], log_card[1], log_card[2], log_card[3], sd->mapname, zeny);
+ sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`vend_date`, `vend_account_id`, `vend_char_id`, `vend_char_name`, `buy_account_id`, `buy_char_id`, `buy_char_name`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `zeny`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%d')",
+ log_config.log_vend_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), vsd->status.account_id, vsd->status.char_id, jstrescapecpy(t_name2, vsd->status.name), log_nameid, log_amount, log_refine, log_card[0], log_card[1], log_card[2], log_card[3], sd->mapname, zeny);
if(mysql_query(&mmysql_handle, tmp_sql))
printf("DB server Error - %s\n",mysql_error(&mmysql_handle));
} else {
- #endif
+#endif
if((logfp=fopen(log_config.log_vend,"a+")) != NULL) {
- char timestring[255];
- time_t curtime;
time(&curtime);
strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
fprintf(logfp,"%s - %s[%d:%d]\t%s[%d:%d]\t%d\t%d\t%d\t%d,%d,%d,%d\t%d%s", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, vsd->status.name, vsd->status.account_id, vsd->status.char_id, log_nameid, log_amount, log_refine, log_card[0], log_card[1], log_card[2], log_card[3], zeny, RETCODE);
fclose(logfp);
}
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
}
- #endif
+#endif
return 0;
}
int log_zeny(struct map_session_data *sd, struct map_session_data *target_sd,int amount)
{
FILE *logfp;
+#ifndef TXT_ONLY
+ char t_name[100],t_name2[100];
+#endif
+
if(log_config.enable_logs <= 0)
return 0;
nullpo_retr(0, sd);
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
if(log_config.sql_logs > 0)
{
- sprintf(tmp_sql,"INSERT INTO `%s` (`trade_date`, `src_account_id`, `src_char_id`, `src_char_name`, `des_account_id`, `des_char_id`, `des_char_name`, `map`, `zeny`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%s', '%s', '%d')", log_config.log_trade_db, sd->status.account_id, sd->status.char_id, sd->status.name, target_sd->status.account_id, target_sd->status.char_id, target_sd->status.name, sd->mapname, sd->deal_zeny);
+ sprintf(tmp_sql,"INSERT DELAYED INTO `%s` (`trade_date`, `src_account_id`, `src_char_id`, `src_char_name`, `des_account_id`, `des_char_id`, `des_char_name`, `map`, `zeny`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%d', '%s', '%s', '%d')",
+ log_config.log_trade_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), target_sd->status.account_id, target_sd->status.char_id, jstrescapecpy(t_name2, target_sd->status.name), sd->mapname, sd->deal_zeny);
if(mysql_query(&mmysql_handle, tmp_sql))
printf("DB server Error - %s\n",mysql_error(&mmysql_handle));
} else {
- #endif
+#endif
if((logfp=fopen(log_config.log_trade,"a+")) != NULL) {
- char timestring[255];
- time_t curtime;
time(&curtime);
strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
fprintf(logfp,"%s - %s[%d]\t%s[%d]\t%d\t%s", timestring, sd->status.name, sd->status.account_id, target_sd->status.name, target_sd->status.account_id, sd->deal_zeny, RETCODE);
fclose(logfp);
}
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
}
- #endif
+#endif
return 0;
}
int log_atcommand(struct map_session_data *sd, const char *message)
{
FILE *logfp;
+#ifndef TXT_ONLY
+ char t_name[100];
+#endif
+
if(log_config.enable_logs <= 0)
return 0;
nullpo_retr(0, sd);
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
if(log_config.sql_logs > 0)
{
- sprintf(tmp_sql, "INSERT INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES(NOW(), '%d', '%d', '%s', '%s', '%s') ", log_config.log_gm_db, sd->status.account_id, sd->status.char_id, sd->status.name, sd->mapname, message);
+ sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES(NOW(), '%d', '%d', '%s', '%s', '%s') ",
+ log_config.log_gm_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), sd->mapname, message);
if(mysql_query(&mmysql_handle, tmp_sql))
printf("DB server Error - %s\n",mysql_error(&mmysql_handle));
} else {
- #endif
+#endif
if((logfp=fopen(log_config.log_gm,"a+")) != NULL) {
- char timestring[255];
- time_t curtime;
time(&curtime);
strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
fprintf(logfp,"%s - %s[%d]: %s%s",timestring,sd->status.name,sd->status.account_id,message,RETCODE);
fclose(logfp);
}
- #ifndef TXT_ONLY
+#ifndef TXT_ONLY
}
+#endif
+ return 0;
+}
+
+int log_npc(struct map_session_data *sd, const char *message)
+{ //[Lupus]
+ FILE *logfp;
+ #ifndef TXT_ONLY
+ char t_name[100];
#endif
+
+ if(log_config.enable_logs <= 0)
+ return 0;
+ nullpo_retr(0, sd);
+#ifndef TXT_ONLY
+ if(log_config.sql_logs > 0)
+ {
+ sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES(NOW(), '%d', '%d', '%s', '%s', '%s') ",
+ log_config.log_npc_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), sd->mapname, message);
+ if(mysql_query(&mmysql_handle, tmp_sql))
+ printf("DB server Error - %s\n",mysql_error(&mmysql_handle));
+ } else {
+#endif
+ if((logfp=fopen(log_config.log_npc,"a+")) != NULL) {
+ time(&curtime);
+ strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime));
+ fprintf(logfp,"%s - %s[%d]: %s%s",timestring,sd->status.name,sd->status.account_id,message,RETCODE);
+ fclose(logfp);
+ }
+#ifndef TXT_ONLY
+ }
+#endif
return 0;
}
@@ -345,11 +503,19 @@ int log_config_read(char *cfgName)
char line[1024], w1[1024], w2[1024];
FILE *fp;
+ memset(&log_config, 0, sizeof(log_config));
+
if((fp = fopen(cfgName, "r")) == NULL)
{
printf("Log configuration file not found at: %s\n", cfgName);
return 1;
}
+
+ //LOG FILTER Default values
+ log_config.refine_items_log = 7; //log refined items, with refine >= +7
+ log_config.rare_items_log = 100; //log rare items. drop chance <= 1%
+ log_config.price_items_log = 1000; //1000z
+ log_config.amount_items_log = 100;
while(fgets(line, sizeof(line) -1, fp))
{
@@ -362,6 +528,16 @@ int log_config_read(char *cfgName)
log_config.enable_logs = (atoi(w2));
} else if(strcmpi(w1,"sql_logs") == 0) {
log_config.sql_logs = (atoi(w2));
+//start of common filter settings
+ } else if(strcmpi(w1,"rare_items_log") == 0) {
+ log_config.rare_items_log = (atoi(w2));
+ } else if(strcmpi(w1,"refine_items_log") == 0) {
+ log_config.refine_items_log = (atoi(w2));
+ } else if(strcmpi(w1,"price_items_log") == 0) {
+ log_config.price_items_log = (atoi(w2));
+ } else if(strcmpi(w1,"amount_items_log") == 0) {
+ log_config.amount_items_log = (atoi(w2));
+//end of common filter settings
} else if(strcmpi(w1,"log_branch") == 0) {
log_config.branch = (atoi(w2));
} else if(strcmpi(w1,"log_drop") == 0) {
@@ -376,6 +552,8 @@ int log_config_read(char *cfgName)
log_config.refine = (atoi(w2));
} else if(strcmpi(w1,"log_trade") == 0) {
log_config.trade = (atoi(w2));
+ } else if(strcmpi(w1,"log_storage") == 0) {
+ log_config.storage = (atoi(w2));
} else if(strcmpi(w1,"log_vend") == 0) {
log_config.vend = (atoi(w2));
} else if(strcmpi(w1,"log_zeny") == 0) {
@@ -383,10 +561,13 @@ int log_config_read(char *cfgName)
log_config.zeny = 0;
else
log_config.zeny = (atoi(w2));
- } else if(strcmpi(w1,"log_gm") == 0) {
+ } else if(strcmpi(w1,"log_gm") == 0) {
log_config.gm = (atoi(w2));
+ } else if(strcmpi(w1,"log_npc") == 0) {
+ log_config.npc = (atoi(w2));
}
+#ifndef TXT_ONLY
else if(strcmpi(w1, "log_branch_db") == 0) {
strcpy(log_config.log_branch_db, w2);
if(log_config.branch == 1)
@@ -420,6 +601,13 @@ int log_config_read(char *cfgName)
printf("and Zeny Trades");
printf(" to table `%s`\n", w2);
}
+// } else if(strcmpi(w1, "log_storage_db") == 0) {
+// strcpy(log_config.log_storage_db, w2);
+// if(log_config.storage == 1)
+// {
+// printf("Logging Item Storages");
+// printf(" to table `%s`\n", w2);
+// }
} else if(strcmpi(w1, "log_vend_db") == 0) {
strcpy(log_config.log_vend_db, w2);
if(log_config.vend == 1)
@@ -428,49 +616,68 @@ int log_config_read(char *cfgName)
strcpy(log_config.log_gm_db, w2);
if(log_config.gm > 0)
printf("Logging GM Level %d Commands to table `%s`\n", log_config.gm, w2);
+ } else if(strcmpi(w1, "log_npc_db") == 0) {
+ strcpy(log_config.log_npc_db, w2);
+ if(log_config.npc > 0)
+ printf("Logging NPC 'logmes' to table `%s`\n", w2);
}
+#endif
- else if(strcmpi(w1, "log_branch") == 0) {
+ else if(strcmpi(w1, "log_branch_file") == 0) {
strcpy(log_config.log_branch, w2);
- if(log_config.branch == 1)
+ if(log_config.branch > 0 && log_config.sql_logs < 1)
printf("Logging Dead Branch Usage to file `%s`.txt\n", w2);
- } else if(strcmpi(w1, "log_drop") == 0) {
+ } else if(strcmpi(w1, "log_drop_file") == 0) {
strcpy(log_config.log_drop, w2);
- if(log_config.drop == 1)
+ if(log_config.drop > 0 && log_config.sql_logs < 1)
printf("Logging Item Drops to file `%s`.txt\n", w2);
- } else if(strcmpi(w1, "log_mvpdrop") == 0) {
+ } else if(strcmpi(w1, "log_mvpdrop_file") == 0) {
strcpy(log_config.log_mvpdrop, w2);
- if(log_config.mvpdrop == 1)
+ if(log_config.mvpdrop > 0 && log_config.sql_logs < 1)
printf("Logging MVP Drops to file `%s`.txt\n", w2);
- } else if(strcmpi(w1, "log_present") == 0) {
+ } else if(strcmpi(w1, "log_present_file") == 0) {
strcpy(log_config.log_present, w2);
- if(log_config.present == 1)
+ if(log_config.present > 0 && log_config.sql_logs < 1)
printf("Logging Present Usage & Results to file `%s`.txt\n", w2);
- } else if(strcmpi(w1, "log_produce") == 0) {
+ } else if(strcmpi(w1, "log_produce_file") == 0) {
strcpy(log_config.log_produce, w2);
- if(log_config.produce == 1)
+ if(log_config.produce > 0 && log_config.sql_logs < 1)
printf("Logging Producing to file `%s`.txt\n", w2);
- } else if(strcmpi(w1, "log_refine") == 0) {
+ } else if(strcmpi(w1, "log_refine_file") == 0) {
strcpy(log_config.log_refine, w2);
- if(log_config.refine == 1)
+ if(log_config.refine > 0 && log_config.sql_logs < 1)
printf("Logging Refining to file `%s`.txt\n", w2);
- } else if(strcmpi(w1, "log_trade") == 0) {
+ } else if(strcmpi(w1, "log_trade_file") == 0) {
strcpy(log_config.log_trade, w2);
- if(log_config.trade == 1)
+ if(log_config.trade > 0 && log_config.sql_logs < 1)
{
printf("Logging Item Trades");
- if(log_config.zeny == 1)
+ if(log_config.zeny > 0)
printf("and Zeny Trades");
printf(" to file `%s`.txt\n", w2);
}
- } else if(strcmpi(w1, "log_vend") == 0) {
+ } else if(strcmpi(w1, "log_storage_file") == 0) {
+ strcpy(log_config.log_storage, w2);
+ if(log_config.storage > 0 && log_config.sql_logs < 1)
+ {
+ printf("Logging Item Storages");
+ printf(" to file `%s`.txt\n", w2);
+ }
+ } else if(strcmpi(w1, "log_vend_file") == 0) {
strcpy(log_config.log_vend, w2);
- if(log_config.vend == 1)
+ if(log_config.vend > 0 && log_config.sql_logs < 1)
printf("Logging Vending to file `%s`.txt\n", w2);
- } else if(strcmpi(w1, "log_gm") == 0) {
+ } else if(strcmpi(w1, "log_gm_file") == 0) {
strcpy(log_config.log_gm, w2);
- if(log_config.gm > 0)
+ if(log_config.gm > 0 && log_config.sql_logs < 1)
printf("Logging GM Level %d Commands to file `%s`.txt\n", log_config.gm, w2);
+ } else if(strcmpi(w1, "log_npc_file") == 0) {
+ strcpy(log_config.log_npc, w2);
+ if(log_config.npc > 0 && log_config.sql_logs < 1)
+ printf("Logging NPC 'logmes' to file `%s`.txt\n", w2);
+ //support the import command, just like any other config
+ } else if(strcmpi(w1,"import") == 0) {
+ log_config_read(w2);
}
}
}
diff --git a/src/map/log.h b/src/map/log.h
index d4ad0bd66..cdb543f0d 100644
--- a/src/map/log.h
+++ b/src/map/log.h
@@ -16,18 +16,25 @@ int log_present(struct map_session_data *sd, int source_type, int nameid);
int log_produce(struct map_session_data *sd, int nameid, int slot1, int slot2, int slot3, int success);
int log_refine(struct map_session_data *sd, int n, int success);
int log_trade(struct map_session_data *sd,struct map_session_data *target_sd,int n,int amount);
+int log_tostorage(struct map_session_data *sd,int n, int guild);
+int log_fromstorage(struct map_session_data *sd,int n, int guild);
+
int log_vend(struct map_session_data *sd,struct map_session_data *vsd,int n,int amount,int zeny);
int log_zeny(struct map_session_data *sd, struct map_session_data *target_sd,int amount);
int log_atcommand(struct map_session_data *sd, const char *message);
+int log_npc(struct map_session_data *sd, const char *message);
int log_config_read(char *cfgName);
extern struct Log_Config {
int enable_logs;
int sql_logs;
- int branch, drop, mvpdrop, present, produce, refine, trade, vend, zeny, gm;
- char log_branch[32], log_drop[32], log_mvpdrop[32], log_present[32], log_produce[32], log_refine[32], log_trade[32], log_vend[32], log_gm[32];
- char log_branch_db[32], log_drop_db[32], log_mvpdrop_db[32], log_present_db[32], log_produce_db[32], log_refine_db[32], log_trade_db[32], log_vend_db[32], log_gm_db[32];
+ int rare_items_log,refine_items_log,price_items_log,amount_items_log;
+ int branch, drop, mvpdrop, present, produce, refine, trade, vend, zeny, gm, npc, storage;
+ char log_branch[32], log_drop[32], log_mvpdrop[32], log_present[32], log_produce[32], log_refine[32], log_trade[32], log_vend[32], log_gm[32], log_npc[32], log_storage[32];
+ char log_branch_db[32], log_drop_db[32], log_mvpdrop_db[32], log_present_db[32], log_produce_db[32], log_refine_db[32], log_trade_db[32], log_vend_db[32], log_gm_db[32], log_npc_db[32];
+ int uptime;
+ char log_uptime[32];
} log_config;
#endif
diff --git a/src/map/mail.c b/src/map/mail.c
index 019f6303d..42a83de52 100644
--- a/src/map/mail.c
+++ b/src/map/mail.c
@@ -1,18 +1,22 @@
+#ifndef TXT_ONLY
// Mail System for eAthena SQL
// Created by Valaris
+// moved all strings to msg_athena.conf [Lupus]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "socket.h"
-#include "timer.h"
-#include "nullpo.h"
+#include "../common/strlib.h"
+#include "../common/socket.h"
+#include "../common/timer.h"
+#include "../common/nullpo.h"
#include "map.h"
#include "clif.h"
#include "chrif.h"
#include "intif.h"
+#include "atcommand.h"
#include "pc.h"
#include "mail.h"
@@ -20,6 +24,7 @@ char mail_db[32] = "mail";
int MAIL_CHECK_TIME = 120000;
int mail_timer;
+//extern char *msg_table[1000]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others)
#ifdef MEMWATCH
#include "memwatch.h"
@@ -27,13 +32,13 @@ int mail_timer;
int mail_check(struct map_session_data *sd,int type)
{
- int i=0,new=0,priority=0;
+ int i = 0, new_ = 0, priority = 0;
char message[50];
- if(sd==NULL)
- return 0;
-
- sprintf(tmp_msql,"SELECT `message_id`,`to_account_id`,`from_char_name`,`read_flag`,`priority`,`check_flag` FROM `%s` WHERE `to_account_id` = \"%d\" ORDER by `message_id`", mail_db, sd->status.account_id);
+ nullpo_retr (0, sd);
+
+ sprintf(tmp_msql,"SELECT `message_id`,`to_account_id`,`from_char_name`,`read_flag`,`priority`,`check_flag` "
+ "FROM `%s` WHERE `to_account_id` = \"%d\" ORDER by `message_id`", mail_db, sd->status.account_id);
if (mysql_query(&mail_handle, tmp_msql)) {
printf("Database server error (executing query for %s): %s\n", mail_db, mysql_error(&mail_handle));
@@ -42,63 +47,66 @@ int mail_check(struct map_session_data *sd,int type)
mail_res = mysql_store_result(&mail_handle);
if(mail_res) {
- if (mysql_num_rows(mail_res) == 0) {
- clif_displaymessage(sd->fd,"You have no messages.");
- mysql_free_result(mail_res);
- return 0;
- }
+ if (mysql_num_rows(mail_res) == 0) {
+ //clif_displaymessage(sd->fd,"You have no messages.");
+ clif_displaymessage(sd->fd, msg_txt(516));
- while ((mail_row = mysql_fetch_row(mail_res))) {
- i++;
+ mysql_free_result(mail_res);
+ return 0;
+ }
- if(!atoi(mail_row[5])) {
+ while ((mail_row = mysql_fetch_row(mail_res))) {
+ i++;
+ if(!atoi(mail_row[5])) {
sprintf(tmp_msql,"UPDATE `%s` SET `check_flag`='1' WHERE `message_id`= \"%d\"", mail_db, atoi(mail_row[0]));
- if(mysql_query(&mail_handle, tmp_msql) ) {
- printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) );
- }
+ if(mysql_query(&mail_handle, tmp_msql) ) {
+ printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) );
}
+ }
- if(!atoi(mail_row[3])) {
- new++;
- if(atoi(mail_row[4]))
- priority++;
- if(type==2 || type==3) {
- if(atoi(mail_row[4])) {
- sprintf(message, "%d - From : %s (New - Priority)", i, mail_row[2]);
- clif_displaymessage(sd->fd, message);
- }
-
- else {
- sprintf(message, "%d - From : %s (New)", i, mail_row[2]);
- clif_displaymessage(sd->fd, message);
- }
+ if(!atoi(mail_row[3])) {
+ new_++;
+ if(atoi(mail_row[4]))
+ priority++;
+ if(type==2 || type==3) {
+ if(atoi(mail_row[4])) {
+ //sprintf(message, "%d - From : %s (New - Priority)", i, mail_row[2]);
+ sprintf(message, msg_txt(511), i, mail_row[2]);
+
+ clif_displaymessage(sd->fd, jstrescape(message));
+ } else {
+ //sprintf(message, "%d - From : %s (New)", i, mail_row[2]);
+ sprintf(message, msg_txt(512), i, mail_row[2]);
+ clif_displaymessage(sd->fd, jstrescape(message));
}
}
+ } else if(type==2){
+ //sprintf(message, "%d - From : %s", i, mail_row[2]);
+ sprintf(message, msg_txt(513), i, mail_row[2]);
+ clif_displaymessage(sd->fd, jstrescape(message));
+ }
+ }
- else if(type==2){
- sprintf(message, "%d - From : %s", i, mail_row[2]);
- clif_displaymessage(sd->fd, message);
- }
-
- }
-
mysql_free_result(mail_res);
-
} else {
- printf("MySQL error (storing query result for %s): %s\n", mail_db, mysql_error(&mail_handle));
+ printf("MySQL error (storing query result for %s): %s\n", mail_db, mysql_error(&mail_handle));
return 0;
- }
+ }
- if(i>0 && new>0 && type==1) {
- sprintf(message, "You have %d new messages.", new);
- clif_displaymessage(sd->fd, message);
+ if(i>0 && new_>0 && type==1) {
+ //sprintf(message, "You have %d new messages.", new_);
+ sprintf(message, msg_txt(514), new_);
+
+ clif_displaymessage(sd->fd, jstrescape(message));
}
- if(i>0 && new>0 && priority>0 && type==1) {
- sprintf(message, "You have %d unread priority messages.", priority);
- clif_displaymessage(sd->fd, message);
+ if(i>0 && new_>0 && priority>0 && type==1) {
+ //sprintf(message, "You have %d unread priority messages.", priority);
+ sprintf(message, msg_txt(515), priority);
+ clif_displaymessage(sd->fd, jstrescape(message));
}
- if(!new) {
- clif_displaymessage(sd->fd, "You have no new messages.");
+ if(!new_) {
+ //clif_displaymessage(sd->fd, "You have no new messages.");
+ clif_displaymessage(sd->fd, msg_txt(516));
}
return 0;
@@ -109,9 +117,8 @@ int mail_read(struct map_session_data *sd, int message_id)
char message[80];
- if(sd==NULL)
- return 0;
-
+ nullpo_retr (0, sd);
+
sprintf(tmp_msql,"SELECT `message_id`,`to_account_id`,`from_char_name`,`message`,`read_flag`,`priority`,`check_flag` from `%s` WHERE `to_account_id` = \"%d\" ORDER by `message_id` LIMIT %d, 1",mail_db,sd->status.account_id,message_id-1);
if (mysql_query(&mail_handle, tmp_msql)) {
@@ -121,48 +128,47 @@ int mail_read(struct map_session_data *sd, int message_id)
mail_res = mysql_store_result(&mail_handle);
if(mail_res) {
- if (mysql_num_rows(mail_res) == 0) {
- mysql_free_result(mail_res);
- clif_displaymessage(sd->fd, "Message not found.");
- return 0;
- }
-
- if ((mail_row = mysql_fetch_row(mail_res))) {
+ if (mysql_num_rows(mail_res) == 0) {
+ mysql_free_result(mail_res);
+ //clif_displaymessage(sd->fd, "Message not found.");
+ clif_displaymessage(sd->fd, msg_txt(517));
+ return 0;
+ }
+ if ((mail_row = mysql_fetch_row(mail_res))) {
if(!atoi(mail_row[6])) {
sprintf(tmp_msql,"UPDATE `%s` SET `check_flag`='1' WHERE `message_id`= \"%d\"", mail_db, atoi(mail_row[0]));
- if(mysql_query(&mail_handle, tmp_msql) ) {
- printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) );
- }
+ if(mysql_query(&mail_handle, tmp_msql) ) {
+ printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) );
+ }
}
- sprintf(message, "Reading message from %s", mail_row[2]);
- clif_displaymessage(sd->fd, message);
+ //sprintf(message, "Reading message from %s", mail_row[2]);
+ sprintf(message, msg_txt(518), mail_row[2]);
+ clif_displaymessage(sd->fd, jstrescape(message));
sprintf(message, "%s", mail_row[3]);
- clif_displaymessage(sd->fd, message);
+ clif_displaymessage(sd->fd, jstrescape(message));
sprintf(tmp_msql,"UPDATE `%s` SET `read_flag`='1' WHERE `message_id`= \"%d\"", mail_db, atoi(mail_row[0]));
- if(mysql_query(&mail_handle, tmp_msql) ) {
+ if(mysql_query(&mail_handle, tmp_msql) ) {
printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) );
- }
+ }
}
-
+
mysql_free_result(mail_res);
-
+
} else {
- printf("MySQL error (storing query result for %s): %s\n", mail_db, mysql_error(&mail_handle));
- return 0;
- }
+ printf("MySQL error (storing query result for %s): %s\n", mail_db, mysql_error(&mail_handle));
+ }
return 0;
}
int mail_delete(struct map_session_data *sd, int message_id)
{
- if(sd==NULL)
- return 0;
-
+ nullpo_retr (0, sd);
+
sprintf(tmp_msql,"SELECT `message_id`,`to_account_id`,`read_flag`,`priority`,`check_flag` from `%s` WHERE `to_account_id` = \"%d\" ORDER by `message_id` LIMIT %d, 1",mail_db,sd->status.account_id,message_id-1);
if (mysql_query(&mail_handle, tmp_msql)) {
@@ -172,21 +178,25 @@ int mail_delete(struct map_session_data *sd, int message_id)
mail_res = mysql_store_result(&mail_handle);
if(mail_res) {
- if (mysql_num_rows(mail_res) == 0) {
- mysql_free_result(mail_res);
- clif_displaymessage(sd->fd, "Message not found.");
- return 0;
- }
+ if (mysql_num_rows(mail_res) == 0) {
+ mysql_free_result(mail_res);
+ //clif_displaymessage(sd->fd, "Message not found.");
+ clif_displaymessage(sd->fd, msg_txt(517));
+ return 0;
+ }
- if ((mail_row = mysql_fetch_row(mail_res))) {
+ if ((mail_row = mysql_fetch_row(mail_res))) {
if(!atoi(mail_row[2]) && atoi(mail_row[3])) {
mysql_free_result(mail_res);
- clif_displaymessage(sd->fd,"Cannot delete unread priority mail.");
+ //clif_displaymessage(sd->fd,"Cannot delete unread priority mail.");
+ clif_displaymessage(sd->fd,msg_txt(519));
+
return 0;
}
if(!atoi(mail_row[4])) {
mysql_free_result(mail_res);
- clif_displaymessage(sd->fd,"You have recieved new mail, use @listmail before deleting.");
+ //clif_displaymessage(sd->fd,"You have recieved new mail, use @listmail before deleting.");
+ clif_displaymessage(sd->fd,msg_txt(520));
return 0;
}
sprintf(tmp_msql,"DELETE FROM `%s` WHERE `message_id` = \"%d\"", mail_db, atoi(mail_row[0]));
@@ -195,75 +205,77 @@ int mail_delete(struct map_session_data *sd, int message_id)
printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) );
return 0;
}
- else clif_displaymessage(sd->fd,"Message deleted.");
+ //else clif_displaymessage(sd->fd,"Message deleted.");
+ else clif_displaymessage(sd->fd,msg_txt(521));
}
-
+
mysql_free_result(mail_res);
-
+
} else {
- printf("MySQL error (delete query result for %s): %s\n", mail_db, mysql_error(&mail_handle));
- return 0;
- }
+ printf("MySQL error (delete query result for %s): %s\n", mail_db, mysql_error(&mail_handle));
+ }
return 0;
}
int mail_send(struct map_session_data *sd, char *name, char *message, int flag)
{
- if(sd==NULL)
- return 0;
-
+ nullpo_retr (0, sd);
+
if(pc_isGM(sd) < 80 && sd->mail_counter > 0) {
- clif_displaymessage(sd->fd,"You must wait 10 minutes before sending another message");
+ //clif_displaymessage(sd->fd,"You must wait 10 minutes before sending another message");
+ clif_displaymessage(sd->fd,msg_txt(522));
return 0;
}
if(strcmp(name,"*")==0) {
if(pc_isGM(sd) < 80) {
- clif_displaymessage(sd->fd, "Access Denied.");
+ //clif_displaymessage(sd->fd, "Access Denied.");
+ clif_displaymessage(sd->fd, msg_txt(523));
return 0;
}
else
sprintf(tmp_msql,"SELECT DISTINCT `account_id` FROM `%s` WHERE `account_id` <> '%d' ORDER BY `account_id`", char_db, sd->status.account_id);
}
else
- sprintf(tmp_msql,"SELECT `account_id`,`name` FROM `%s` WHERE `name` = \"%s\"", char_db, name);
+ sprintf(tmp_msql,"SELECT `account_id`,`name` FROM `%s` WHERE `name` = \"%s\"", char_db, jstrescape(name));
if (mysql_query(&mail_handle, tmp_msql)) {
printf("Database server error (executing query for %s): %s\n", char_db, mysql_error(&mail_handle));
return 0;
- }
-
+ }
+
mail_res = mysql_store_result(&mail_handle);
if(mail_res) {
- if (mysql_num_rows(mail_res) == 0) {
+ if (mysql_num_rows(mail_res) == 0) {
mysql_free_result(mail_res);
- clif_displaymessage(sd->fd,"Character does not exist.");
- return 0;
- }
+ //clif_displaymessage(sd->fd,"Character does not exist.");
+ clif_displaymessage(sd->fd,msg_txt(524));
+ return 0;
+ }
- while ((mail_row = mysql_fetch_row(mail_res))) {
+ while ((mail_row = mysql_fetch_row(mail_res))) {
if(strcmp(name,"*")==0) {
- sprintf(tmp_msql, "INSERT INTO `%s` (`to_account_id`,`from_account_id`,`from_char_name`,`message`,`priority`)"
- " VALUES ('%d', '%d', '%s', '%s', '%d')",mail_db, atoi(mail_row[0]), sd->status.account_id, sd->status.name, message, flag);
+ sprintf(tmp_msql, "INSERT DELAYED INTO `%s` (`to_account_id`,`from_account_id`,`from_char_name`,`message`,`priority`)"
+ " VALUES ('%d', '%d', '%s', '%s', '%d')",mail_db, atoi(mail_row[0]), sd->status.account_id, sd->status.name, jstrescape(message), flag);
}
else {
- sprintf(tmp_msql, "INSERT INTO `%s` (`to_account_id`,`to_char_name`,`from_account_id`,`from_char_name`,`message`,`priority`)"
- " VALUES ('%d', '%s', '%d', '%s', '%s', '%d')",mail_db, atoi(mail_row[0]), mail_row[1], sd->status.account_id, sd->status.name, message, flag);
+ sprintf(tmp_msql, "INSERT DELAYED INTO `%s` (`to_account_id`,`to_char_name`,`from_account_id`,`from_char_name`,`message`,`priority`)"
+ " VALUES ('%d', '%s', '%d', '%s', '%s', '%d')",mail_db, atoi(mail_row[0]), mail_row[1], sd->status.account_id, sd->status.name, jstrescape(message), flag);
if(pc_isGM(sd) < 80)
sd->mail_counter=5;
}
-
+
if(mysql_query(&mail_handle, tmp_msql) ) {
mysql_free_result(mail_res);
printf("DB server Error (insert `mail_db`)- %s\n", mysql_error(&mail_handle) );
return 0;
}
-
}
}
- clif_displaymessage(sd->fd,"Mail has been sent.");
+ //clif_displaymessage(sd->fd,"Mail has been sent.");
+ clif_displaymessage(sd->fd,msg_txt(525));
return 0;
}
@@ -271,43 +283,43 @@ int mail_send(struct map_session_data *sd, char *name, char *message, int flag)
int mail_check_timer(int tid,unsigned int tick,int id,int data)
{
struct map_session_data *sd = NULL;
- int i;
+ int i;
if(mail_timer != tid)
return 0;
sprintf(tmp_msql,"SELECT DISTINCT `to_account_id` FROM `%s` WHERE `read_flag` = '0' AND `check_flag` = '0'", mail_db);
-
+
if (mysql_query(&mail_handle, tmp_msql)) {
printf("Database server error (executing query for %s): %s\n", char_db, mysql_error(&mail_handle));
mail_timer=add_timer(gettick()+MAIL_CHECK_TIME,mail_check_timer,0,0);
return 0;
- }
+ }
mail_res = mysql_store_result(&mail_handle);
if (mail_res) {
-
- if (mysql_num_rows(mail_res) == 0) {
+ if (mysql_num_rows(mail_res) == 0) {
mysql_free_result(mail_res);
mail_timer=add_timer(gettick()+MAIL_CHECK_TIME,mail_check_timer,0,0);
- return 0;
- }
+ return 0;
+ }
- while ((mail_row = mysql_fetch_row(mail_res))) {
+ while ((mail_row = mysql_fetch_row(mail_res))) {
for (i = 0; i < fd_max; i++) {
- if (session[i] && (sd = session[i]->session_data) && sd->state.auth){
+ if (session[i] && (sd = (struct map_session_data *) session[i]->session_data) && sd->state.auth){
if(pc_isGM(sd) < 80 && sd->mail_counter > 0)
sd->mail_counter--;
if(sd->status.account_id==atoi(mail_row[0]))
- clif_displaymessage(sd->fd, "You have new mail.");
+ //clif_displaymessage(sd->fd, "You have new mail.");
+ clif_displaymessage(sd->fd, msg_txt(526));
}
}
}
}
sprintf(tmp_msql,"UPDATE `%s` SET `check_flag`='1' WHERE `check_flag`= '0' ", mail_db);
- if(mysql_query(&mail_handle, tmp_msql) ) {
+ if(mysql_query(&mail_handle, tmp_msql) ) {
printf("DB server Error (update Read `%s`)- %s\n", mail_db, mysql_error(&mail_handle) );
}
@@ -316,9 +328,10 @@ int mail_check_timer(int tid,unsigned int tick,int id,int data)
}
int do_init_mail(void)
-{
+{
add_timer_func_list(mail_check_timer,"mail_check_timer");
mail_timer=add_timer(gettick()+MAIL_CHECK_TIME,mail_check_timer,0,0);
return 0;
}
+#endif
diff --git a/src/map/map.c b/src/map/map.c
index 3214373f9..386b38954 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -8,12 +8,14 @@
#else
#include <netdb.h>
#endif
+#include <math.h>
#include "core.h"
#include "timer.h"
#include "db.h"
#include "grfio.h"
#include "malloc.h"
+#include "version.h"
#include "map.h"
#include "chrif.h"
@@ -21,6 +23,7 @@
#include "intif.h"
#include "npc.h"
#include "pc.h"
+#include "status.h"
#include "mob.h"
#include "chat.h"
#include "itemdb.h"
@@ -43,7 +46,8 @@
#include "memwatch.h"
#endif
-unsigned long ticks = 0; // by MC Cameri
+// maybe put basic macros to somewhere else
+#define swap(a,b) ((a == b) || ((a ^= b), (b ^= a), (a ^= b)))
#ifndef TXT_ONLY
@@ -99,19 +103,31 @@ int read_gm_interval = 600000;
char char_db[32] = "char";
static int online_timer(int,unsigned int,int,int);
-
int CHECK_INTERVAL = 3600000; // [Valaris]
-int check_online_timer=0; // [Valaris]
#endif /* not TXT_ONLY */
-// 極力 staticでローカルに収める
+
+char *INTER_CONF_NAME;
+char *LOG_CONF_NAME;
+char *MAP_CONF_NAME;
+char *BATTLE_CONF_FILENAME;
+char *ATCOMMAND_CONF_FILENAME;
+char *CHARCOMMAND_CONF_FILENAME;
+char *SCRIPT_CONF_NAME;
+char *MSG_CONF_NAME;
+char *GRF_PATH_FILENAME;
+
+#define USE_AFM
+#define USE_AF2
+
+// 極力 staticでロ?カルに?める
static struct dbt * id_db=NULL;
static struct dbt * map_db=NULL;
static struct dbt * nick_db=NULL;
static struct dbt * charid_db=NULL;
static int users=0;
-static struct block_list *object[MAX_FLOORITEM];
+static struct block_list *objects[MAX_FLOORITEM];
static int first_free_object_id=0,last_object_id=0;
#define block_free_max 1048576
@@ -145,23 +161,33 @@ struct charid2nick {
int req_id;
};
+// ォ゙ォテォラォュォ罩テォキォ袮ラ鯑ォユォ鬮ー(map_athana.conf?ェホread_map_from_cacheェヌヲ・)
+// 0:ララ鯑ェキェハェ、 1:゙ェ?ワチ 2:?ワチ
+int map_read_flag = READ_FROM_GAT;
+char map_cache_file[256]="db/map.info"; // ォ゙ォテォラォュォ罩テォキォ雖ユォ。ォ、ォ・」
+
char motd_txt[256] = "conf/motd.txt";
char help_txt[256] = "conf/help.txt";
char wisp_server_name[24] = "Server"; // can be modified in char-server configuration file
int console = 0;
+
/*==========================================
- * 全map鯖総計での接続数設定
+ * 全map鯖?計での接??設定
* (char鯖から送られてくる)
*------------------------------------------
*/
-void map_setusers(int n) {
- users = n;
+void map_setusers(int fd)
+{
+ users = RFIFOL(fd,2);
+ // send some anser
+ WFIFOW(fd,0) = 0x2718;
+ WFIFOSET(fd,2);
}
/*==========================================
- * 全map鯖総計での接続数取得 (/wへの応答用)
+ * 全map鯖?計での接??取得 (/wへの?答用)
*------------------------------------------
*/
int map_getusers(void) {
@@ -169,18 +195,18 @@ int map_getusers(void) {
}
//
-// block削除の安全性確保処理
+// block削除の安全性確保?理
//
/*==========================================
- * blockをfreeするときfreeの変わりに呼ぶ
+ * blockをfreeするときfreeの?わりに呼ぶ
* ロックされているときはバッファにためる
*------------------------------------------
*/
int map_freeblock( void *bl )
{
if(block_free_lock==0){
- free(bl);
+ aFree(bl);
bl = NULL;
}
else{
@@ -216,23 +242,40 @@ int map_freeblock_unlock(void) {
// printf("map_freeblock_unlock: free %d object\n",block_free_count);
// }
for(i=0;i<block_free_count;i++){
- free(block_free[i]);
+ aFree(block_free[i]);
block_free[i] = NULL;
}
block_free_count=0;
}else if(block_free_lock<0){
if(battle_config.error_log)
printf("map_freeblock_unlock: lock count < 0 !\n");
+ block_free_lock = 0; // 次回以降のロックに支障が出てくるのでリセット
}
return block_free_lock;
}
+// map_freeblock_lock() を呼んで map_freeblock_unlock() を呼ばない
+// 関数があったので、定期的にblock_free_lockをリセットするようにする。
+// この関数は、do_timer() のトップレベルから呼ばれるので、
+// block_free_lock を直接いじっても支障無いはず。
+
+int map_freeblock_timer(int tid,unsigned int tick,int id,int data) {
+ if(block_free_lock > 0) {
+ printf("map_freeblock_timer: block_free_lock(%d) is invalid.\n",block_free_lock);
+ block_free_lock = 1;
+ map_freeblock_unlock();
+ }
+ // else {
+ // printf("map_freeblock_timer: check ok\n");
+ // }
+ return 0;
+}
//
-// block化処理
+// block化?理
//
/*==========================================
- * map[]のblock_listから繋がっている場合に
+ * map[]のblock_listから?がっている場合に
* bl->prevにbl_headのアドレスを入れておく
*------------------------------------------
*/
@@ -240,9 +283,9 @@ static struct block_list bl_head;
/*==========================================
* map[]のblock_listに追加
- * mobは数が多いので別リスト
+ * mobは?が多いので別リスト
*
- * 既にlink済みかの確認が無い。危険かも
+ * ?にlink?みかの確認が無い。危?かも
*------------------------------------------
*/
int map_addblock(struct block_list *bl)
@@ -286,7 +329,7 @@ int map_addblock(struct block_list *bl)
/*==========================================
* map[]のblock_listから外す
- * prevがNULLの場合listに繋がってない
+ * prevがNULLの場合listに?がってない
*------------------------------------------
*/
int map_delblock(struct block_list *bl)
@@ -294,7 +337,7 @@ int map_delblock(struct block_list *bl)
int b;
nullpo_retr(0, bl);
- // 既にblocklistから抜けている
+ // ?にblocklistから?けている
if(bl->prev==NULL){
if(bl->next!=NULL){
// prevがNULLでnextがNULLでないのは有ってはならない
@@ -308,7 +351,8 @@ int map_delblock(struct block_list *bl)
if(bl->type==BL_PC)
map[bl->m].users--;
- if(bl->next) bl->next->prev = bl->prev;
+ if(bl->next)
+ bl->next->prev = bl->prev;
if(bl->prev==&bl_head){
// リストの頭なので、map[]のblock_listを更新する
if(bl->type==BL_MOB){
@@ -330,7 +374,7 @@ int map_delblock(struct block_list *bl)
}
/*==========================================
- * 周囲のPC人数を数える (現在未使用)
+ * 周?のPC人?を?える (現在未使用)
*------------------------------------------
*/
int map_countnearpc(int m, int x, int y) {
@@ -356,7 +400,7 @@ int map_countnearpc(int m, int x, int y) {
}
/*==========================================
- * セル上のPCとMOBの数を数える (グランドクロス用)
+ * セル上のPCとMOBの?を?える (グランドクロス用)
*------------------------------------------
*/
int map_count_oncell(int m, int x, int y) {
@@ -383,18 +427,47 @@ int map_count_oncell(int m, int x, int y) {
if(!count) count = 1;
return count;
}
+/*
+ * ォサォ・セェホフェヒフクェトェアェソォケォュォ・讚ヒォテォネェレェケ
+ */
+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 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;
+ bx = x/BLOCK_SIZE;
+ by = y/BLOCK_SIZE;
+
+ bl = map[m].block[bx+by*map[m].bxs];
+ c = map[m].block_count[bx+by*map[m].bxs];
+ for(i=0;i<c && bl;i++,bl=bl->next){
+ if (bl->x != x || bl->y != y || bl->type != BL_SKILL)
+ continue;
+ unit = (struct skill_unit *) bl;
+ 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;
+}
/*==========================================
- * map m (x0,y0)-(x1,y1)内の全objに対して
+ * map m (x0,y0)-(x1,y1)?の全objに?して
* funcを呼ぶ
* type!=0 ならその種類のみ
*------------------------------------------
*/
void map_foreachinarea(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int type,...) {
+ va_list ap;
int bx,by;
struct block_list *bl=NULL;
- va_list ap=NULL;
int blockcount=bl_list_count,i,c;
if(m < 0)
@@ -437,7 +510,7 @@ void map_foreachinarea(int (*func)(struct block_list*,va_list),int m,int x0,int
map_freeblock_lock(); // メモリからの解放を禁止する
for(i=blockcount;i<bl_list_count;i++)
- if(bl_list[i]->prev) // 有効かどうかチェック
+ if(bl_list[i]->prev) // 有?かどうかチェック
func(bl_list[i],ap);
map_freeblock_unlock(); // 解放を許可する
@@ -448,8 +521,8 @@ void map_foreachinarea(int (*func)(struct block_list*,va_list),int m,int x0,int
/*==========================================
* 矩形(x0,y0)-(x1,y1)が(dx,dy)移動した時の
- * 領域外になる領域(矩形かL字形)内のobjに
- * 対してfuncを呼ぶ
+ * 領域外になる領域(矩形かL字形)?のobjに
+ * ?してfuncを呼ぶ
*
* dx,dyは-1,0,1のみとする(どんな値でもいいっぽい?)
*------------------------------------------
@@ -457,7 +530,7 @@ void map_foreachinarea(int (*func)(struct block_list*,va_list),int m,int x0,int
void map_foreachinmovearea(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int dx,int dy,int type,...) {
int bx,by;
struct block_list *bl=NULL;
- va_list ap=NULL;
+ va_list ap;
int blockcount=bl_list_count,i,c;
va_start(ap,type);
@@ -546,8 +619,12 @@ void map_foreachinmovearea(int (*func)(struct block_list*,va_list),int m,int x0,
map_freeblock_lock(); // メモリからの解放を禁止する
for(i=blockcount;i<bl_list_count;i++)
- if(bl_list[i]->prev) // 有効かどうかチェック
+ if(bl_list[i]->prev) { // 有?かどうかチェック
+ if (bl_list[i]->type == BL_PC
+ && session[((struct map_session_data *) bl_list[i])->fd] == NULL)
+ continue;
func(bl_list[i],ap);
+ }
map_freeblock_unlock(); // 解放を許可する
@@ -562,7 +639,7 @@ void map_foreachinmovearea(int (*func)(struct block_list*,va_list),int m,int x0,
void map_foreachincell(int (*func)(struct block_list*,va_list),int m,int x,int y,int type,...) {
int bx,by;
struct block_list *bl=NULL;
- va_list ap=NULL;
+ va_list ap;
int blockcount=bl_list_count,i,c;
va_start(ap,type);
@@ -602,18 +679,445 @@ void map_foreachincell(int (*func)(struct block_list*,va_list),int m,int x,int y
map_freeblock_lock(); // メモリからの解放を禁止する
for(i=blockcount;i<bl_list_count;i++)
- if(bl_list[i]->prev) // 有効かどうかチェック
+ if(bl_list[i]->prev) // 有?かどうかチェック
+ func(bl_list[i],ap);
+
+ map_freeblock_unlock(); // 解放を許可する
+
+ va_end(ap);
+ bl_list_count = blockcount;
+}
+
+/*============================================================
+* For checking a path between two points (x0, y0) and (x1, y1)
+*------------------------------------------------------------
+ */
+void map_foreachinpath(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int range,int type,...)
+{
+/* va_list ap;
+ double deltax = 0.0;
+ double deltay = 0.0;
+ int t, bx, by;
+ int *xs, *ys;
+ int blockcount = bl_list_count, i, c;
+ struct block_list *bl = NULL;
+
+ if(m < 0)
+ return;
+ va_start(ap,type);
+ if (x0 < 0) x0 = 0;
+ if (y0 < 0) y0 = 0;
+ if (x1 >= map[m].xs) x1 = map[m].xs-1;
+ if (y1 >= map[m].ys) y1 = map[m].ys-1;
+
+ // I'm not finished thinking on it
+ // but first it might better use a parameter equation
+ // x=(x1-x0)*t+x0; y=(y1-y0)*t+y0; t=[0,1]
+ // would not need special case aproximating for infinity/zero slope
+ // so maybe this way:
+
+ // find maximum runindex
+ int tmax = abs(y1-y0);
+ if(tmax < abs(x1-x0))
+ tmax = abs(x1-x0);
+
+ xs = (int *)aCallocA(tmax + 1, sizeof(int));
+ ys = (int *)aCallocA(tmax + 1, sizeof(int));
+
+ // pre-calculate delta values for x and y destination
+ // should speed up cause you don't need to divide in the loop
+ if(tmax>0)
+ {
+ deltax = ((double)(x1-x0)) / ((double)tmax);
+ deltay = ((double)(y1-y0)) / ((double)tmax);
+ }
+ // go along the index
+ for(t=0; t<=tmax; t++)
+ {
+ int x = (int)floor(deltax * (double)t +0.5)+x0;
+ int y = (int)floor(deltay * (double)t +0.5)+y0;
+ // the xy pairs of points in line between x0y0 and x1y1
+ // including start and end point
+ xs[t] = x;
+ ys[t] = y;
+ }
+
+ if (type == 0 || type != BL_MOB)
+
+
+this here is wrong,
+there is no check if x0<x1 and y0<y1
+but this is not valid in 3 of 4 cases,
+so in this case here you check only blocks when shooting to a positive direction
+shooting in other directions just do nothing like the skill has failed
+if you want to keep this that way then check and swap x0,y0 with x1,y1
+
+ for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) {
+ for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
+ bl = map[m].block[bx+by*map[m].bxs];
+ c = map[m].block_count[bx+by*map[m].bxs];
+ for(i=0;i<c && bl;i++,bl=bl->next){
+ if(bl) {
+ if (type && bl->type!=type)
+ continue;
+ for(t=0; t<=tmax; t++)
+ if(bl->x==xs[t] && bl->y==ys[t] && bl_list_count<BL_LIST_MAX)
+ bl_list[bl_list_count++]=bl;
+ }
+ }
+ }
+ }
+ if(type==0 || type==BL_MOB)
+ for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
+ for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
+ bl = map[m].block_mob[bx+by*map[m].bxs];
+ c = map[m].block_mob_count[bx+by*map[m].bxs];
+ for(i=0;i<c && bl;i++,bl=bl->next){
+ if(bl) {
+ for(t=0; t<=tmax; t++)
+ if(bl->x==xs[t] && bl->y==ys[t] && bl_list_count<BL_LIST_MAX)
+ bl_list[bl_list_count++]=bl;
+ }
+ }
+ }
+ }
+
+ if(bl_list_count>=BL_LIST_MAX) {
+ if(battle_config.error_log)
+ printf("map_foreachinarea: *WARNING* block count too many!\n");
+ }
+
+ map_freeblock_lock(); // メモリからの解放を禁止する
+
+ for(i=blockcount;i<bl_list_count;i++)
+ if(bl_list[i]->prev) // 有?かどうかチェック
func(bl_list[i],ap);
map_freeblock_unlock(); // 解放を許可する
+ bl_list_count = blockcount;
+ aFree (xs);
+ aFree (ys);
+ va_end(ap);
+
+*/
+
+/*
+//////////////////////////////////////////////////////////////
+//
+// sharp shooting 1
+//
+//////////////////////////////////////////////////////////////
+// problem:
+// finding targets standing on and within some range of a line
+// (t1,t2 t3 and t4 get hit)
+//
+// target 1
+// x t4
+// t2
+// t3 x
+// x
+// S
+//////////////////////////////////////////////////////////////
+// solution 1 (straight forward, but a bit calculation expensive)
+// calculating perpendiculars from quesionable mobs to the straight line
+// if the mob is hit then depends on the distance to the line
+//
+// solution 2 (complex, need to handle many cases, but maybe faster)
+// make a formula to deside if a given (x,y) is within a shooting area
+// the shape can be ie. rectangular or triangular
+// if the mob is hit then depends on if the mob is inside or outside the area
+// I'm not going to implement this, but if somebody is interested
+// in vector algebra, it might be some fun
+
+//////////////////////////////////////////////////////////////
+// possible shooting ranges (I prefer the second one)
+//////////////////////////////////////////////////////////////
+//
+// ---------------- ------
+// ---------------- ------------
+// Sxxxxxxxxxxxxxxxxtarget Sxxxxxxxxxxxxxxxxtarget
+// ---------------- ------------
+// ---------------- -----
+//
+// the original code implemented the left structure
+// might be not that realistic, so I changed to the other one
+// I take "range" as max distance from the line
+//////////////////////////////////////////////////////////////
+
+ va_list ap;
+ int i, blockcount = bl_list_count;
+ struct block_list *bl;
+ int c1,c2;
+
+///////////
+ double deltax,deltay;
+ double k,kfact,knorm;
+ double v1,v2,distance;
+ double xm,ym,rd;
+ int bx,by,bx0,bx1,by0,by1;
+//////////////
+ // no map
+ if(m < 0) return;
+
+ // xy out of range
+ if (x0 < 0) x0 = 0;
+ if (y0 < 0) y0 = 0;
+ if (x1 >= map[m].xs) x1 = map[m].xs-1;
+ if (y1 >= map[m].ys) y1 = map[m].ys-1;
+
+ ///////////////////////////////
+ // stuff for a linear equation in xy coord to calculate
+ // the perpendicular from a block xy to the straight line
+ deltax = (x1-x0);
+ deltay = (y1-y0);
+ kfact = (deltax*deltax+deltay*deltay); // the sqare length of the line
+ knorm = -deltax*x0-deltay*y0; // the offset vector param
+
+//printf("(%i,%i)(%i,%i) range: %i\n",x0,y0,x1,y1,range);
+
+ if(kfact==0) return; // shooting at the standing position should not happen
+ kfact = 1/kfact; // divide here and multiply in the loop
+
+ range *= range; // compare with range^2 so we can skip a sqrt and signs
+
+ ///////////////////////////////
+ // prepare shooting area check
+ xm = (x1+x0)/2.0;
+ ym = (y1+y0)/2.0;// middle point on the shooting line
+ // the sqared radius of a circle around the shooting range
+ // plus the sqared radius of a block
+ rd = (x0-xm)*(x0-xm) + (y0-ym)*(y0-ym) + (range*range)
+ +BLOCK_SIZE*BLOCK_SIZE/2;
+ // so whenever a block midpoint is within this circle
+ // some of the block area is possibly within the shooting range
+
+ ///////////////////////////////
+ // what blocks we need to test
+ // blocks covered by the xy position of begin and end of the line
+ bx0 = x0/BLOCK_SIZE;
+ bx1 = x1/BLOCK_SIZE;
+ by0 = y0/BLOCK_SIZE;
+ by1 = y1/BLOCK_SIZE;
+ // swap'em for a smallest-to-biggest run
+ if(bx0>bx1) swap(bx0,bx1);
+ if(by0>by1) swap(by0,by1);
+
+ // enlarge the block area by a range value and 1
+ // so we can be sure to process all blocks that might touch the shooting area
+ // in this case here with BLOCK_SIZE=8 and range=2 it will be only enlarged by 1
+ // but I implement it anyway just in case that ranges will be larger
+ // or BLOCK_SIZE smaller in future
+ i = (range/BLOCK_SIZE+1);//temp value
+ if(bx0>i) bx0 -=i; else bx0=0;
+ if(by0>i) by0 -=i; else by0=0;
+ if(bx1+i<map[m].bxs) bx1 +=i; else bx1=map[m].bxs-1;
+ if(by1+i<map[m].bys) by1 +=i; else by1=map[m].bys-1;
+
+
+//printf("run for (%i,%i)(%i,%i)\n",bx0,by0,bx1,by1);
+ for(bx=bx0; bx<=bx1; bx++)
+ for(by=by0; by<=by1; by++)
+ { // block xy
+ c1 = map[m].block_count[bx+by*map[m].bxs]; // number of elements in the block
+ c2 = map[m].block_mob_count[bx+by*map[m].bxs]; // number of mobs in the mob block
+ if( (c1==0) && (c2==0) ) continue; // skip if nothing in the blocks
+
+//printf("block(%i,%i) %i %i\n",bx,by,c1,c2);fflush(stdout);
+ // test if the mid-point of the block is too far away
+ // so we could skip the whole block in this case
+ v1 = (bx*BLOCK_SIZE+BLOCK_SIZE/2-xm)*(bx*BLOCK_SIZE+BLOCK_SIZE/2-xm)
+ +(by*BLOCK_SIZE+BLOCK_SIZE/2-ym)*(by*BLOCK_SIZE+BLOCK_SIZE/2-ym);
+//printf("block(%i,%i) v1=%f rd=%f\n",bx,by,v1,rd);fflush(stdout);
+ // check for the worst case scenario
+ if(v1 > rd) continue;
+
+ // it seems that the block is at least partially covered by the shooting range
+ // so we go into it
+ if(type==0 || type!=BL_MOB) {
+ bl = map[m].block[bx+by*map[m].bxs]; // a block with the elements
+ for(i=0;i<c1 && bl;i++,bl=bl->next){ // go through all elements
+ if( bl && ( !type || bl->type==type ) && bl_list_count<BL_LIST_MAX )
+ {
+ // calculate the perpendicular from block xy to the straight line
+ k = kfact*(deltax*bl->x + deltay*bl->y + knorm);
+ // check if the perpendicular is within start and end of our line
+ if(k>=0 && k<=1)
+ { // calculate the distance
+ v1 = deltax*k+x0 - bl->x;
+ v2 = deltay*k+y0 - bl->y;
+ distance = v1*v1+v2*v2;
+ // triangular shooting range
+ if( distance <= range*k )
+ bl_list[bl_list_count++]=bl;
+ }
+ }
+ }//end for elements
+ }
+
+ if(type==0 || type==BL_MOB) {
+ bl = map[m].block_mob[bx+by*map[m].bxs]; // and the mob block
+ for(i=0;i<c2 && bl;i++,bl=bl->next){
+ if(bl && bl_list_count<BL_LIST_MAX) {
+ // calculate the perpendicular from block xy to the straight line
+ k = kfact*(deltax*bl->x + deltay*bl->y + knorm);
+//printf("mob: (%i,%i) k=%f ",bl->x,bl->y, k);
+ // check if the perpendicular is within start and end of our line
+ if(k>=0 && k<=1)
+ {
+ v1 = deltax*k+x0 - bl->x;
+ v2 = deltay*k+y0 - bl->y;
+ distance = v1*v1+v2*v2;
+//printf("dist: %f",distance);
+ // triangular shooting range
+ if( distance <= range*k )
+ {
+//printf(" hit");
+ bl_list[bl_list_count++]=bl;
+ }
+ }
+//printf("\n");
+ }
+ }//end for mobs
+ }
+ }//end for(bx,by)
+
+
+ if(bl_list_count>=BL_LIST_MAX) {
+ if(battle_config.error_log)
+ printf("map_foreachinarea: *WARNING* block count too many!\n");
+ }
+
+ va_start(ap,type);
+ map_freeblock_lock(); // メモリからの解放を禁止する
+
+ for(i=blockcount;i<bl_list_count;i++)
+ if(bl_list[i]->prev) // 有?かどうかチェック
+ func(bl_list[i],ap);
+
+ map_freeblock_unlock(); // 解放を許可する
+ va_end(ap);
+
+ bl_list_count = blockcount;
+
+*/
+
+
+//////////////////////////////////////////////////////////////
+//
+// sharp shooting 2
+//
+//////////////////////////////////////////////////////////////
+// problem:
+// finding targets standing exactly on a line
+// (only t1 and t2 get hit)
+//
+// target 1
+// x t4
+// t2
+// t3 x
+// x
+// S
+//////////////////////////////////////////////////////////////
+ va_list ap;
+ int i, blockcount = bl_list_count;
+ struct block_list *bl;
+ int c1,c2;
+
+ //////////////////////////////////////////////////////////////
+ // linear parametric equation
+ // x=(x1-x0)*t+x0; y=(y1-y0)*t+y0; t=[0,1]
+ //////////////////////////////////////////////////////////////
+ // linear equation for finding a single line between (x0,y0)->(x1,y1)
+ // independent of the given xy-values
+ double dx = 0.0;
+ double dy = 0.0;
+ int bx=-1; // initialize block coords to some impossible value
+ int by=-1;
+
+ int t;
+ ///////////////////////////////
+ // find maximum runindex
+ int tmax = abs(y1-y0);
+ if(tmax < abs(x1-x0))
+ tmax = abs(x1-x0);
+ // pre-calculate delta values for x and y destination
+ // should speed up cause you don't need to divide in the loop
+ if(tmax>0)
+ {
+ dx = ((double)(x1-x0)) / ((double)tmax);
+ dy = ((double)(y1-y0)) / ((double)tmax);
+ }
+ // go along the index
+ for(t=0; t<=tmax; t++)
+ { // xy-values of the line including start and end point
+ int x = (int)floor(dx * (double)t +0.5)+x0;
+ int y = (int)floor(dy * (double)t +0.5)+y0;
+
+ // check the block index of the calculated xy
+ if( (bx!=x/BLOCK_SIZE) || (by!=y/BLOCK_SIZE) )
+ { // we have reached a new block
+ // so we store the current block coordinates
+ bx = x/BLOCK_SIZE;
+ by = y/BLOCK_SIZE;
+
+ // and process the data
+ c1 = map[m].block_count[bx+by*map[m].bxs]; // number of elements in the block
+ c2 = map[m].block_mob_count[bx+by*map[m].bxs]; // number of mobs in the mob block
+ if( (c1==0) && (c2==0) ) continue; // skip if nothing in the block
+
+ if(type==0 || type!=BL_MOB) {
+ bl = map[m].block[bx+by*map[m].bxs]; // a block with the elements
+ for(i=0;i<c1 && bl;i++,bl=bl->next){ // go through all elements
+ if( bl && ( !type || bl->type==type ) && bl_list_count<BL_LIST_MAX )
+ {
+ // check if block xy is on the line
+ if( (bl->x-x0)*(y1-y0) == (bl->y-y0)*(x1-x0) )
+ // and if it is within start and end point
+ if( (((x0<=x1)&&(x0<=bl->x)&&(bl->x<=x1)) || ((x0>=x1)&&(x0>=bl->x)&&(bl->x>=x1))) &&
+ (((y0<=y1)&&(y0<=bl->y)&&(bl->y<=y1)) || ((y0>=y1)&&(y0>=bl->y)&&(bl->y>=y1))) )
+ bl_list[bl_list_count++]=bl;
+ }
+ }//end for elements
+ }
+
+ if(type==0 || type==BL_MOB) {
+ bl = map[m].block_mob[bx+by*map[m].bxs]; // and the mob block
+ for(i=0;i<c2 && bl;i++,bl=bl->next){
+ if(bl && bl_list_count<BL_LIST_MAX) {
+ // check if mob xy is on the line
+ if( (bl->x-x0)*(y1-y0) == (bl->y-y0)*(x1-x0) )
+ // and if it is within start and end point
+ if( (((x0<=x1)&&(x0<=bl->x)&&(bl->x<=x1)) || ((x0>=x1)&&(x0>=bl->x)&&(bl->x>=x1))) &&
+ (((y0<=y1)&&(y0<=bl->y)&&(bl->y<=y1)) || ((y0>=y1)&&(y0>=bl->y)&&(bl->y>=y1))) )
+ bl_list[bl_list_count++]=bl;
+ }
+ }//end for mobs
+ }
+ }
+ }//end for index
+
+ if(bl_list_count>=BL_LIST_MAX) {
+ if(battle_config.error_log)
+ printf("map_foreachinarea: *WARNING* block count too many!\n");
+ }
+
+ va_start(ap,type);
+ map_freeblock_lock(); // メモリからの解放を禁止する
+
+ for(i=blockcount;i<bl_list_count;i++)
+ if(bl_list[i]->prev) // 有?かどうかチェック
+ func(bl_list[i],ap);
+
+ map_freeblock_unlock(); // 解放を許可する
va_end(ap);
+
bl_list_count = blockcount;
}
/*==========================================
- * 床アイテムやエフェクト用の一時obj割り当て
- * object[]への保存とid_db登録まで
+ * 床アイテムやエフェクト用の一時obj割り?て
+ * object[]への保存とid_db登?まで
*
* bl->idもこの中で設定して問題無い?
*------------------------------------------
@@ -627,7 +1131,7 @@ int map_addobject(struct block_list *bl) {
if(first_free_object_id<2 || first_free_object_id>=MAX_FLOORITEM)
first_free_object_id=2;
for(i=first_free_object_id;i<MAX_FLOORITEM;i++)
- if(object[i]==NULL)
+ if(objects[i]==NULL)
break;
if(i>=MAX_FLOORITEM){
if(battle_config.error_log)
@@ -637,29 +1141,29 @@ int map_addobject(struct block_list *bl) {
first_free_object_id=i;
if(last_object_id<i)
last_object_id=i;
- object[i]=bl;
+ objects[i]=bl;
numdb_insert(id_db,i,bl);
return i;
}
/*==========================================
* 一時objectの解放
- * map_delobjectのfreeしないバージョン
+ * map_delobjectのfreeしないバ?ジョン
*------------------------------------------
*/
int map_delobjectnofree(int id) {
- if(object[id]==NULL)
+ if(objects[id]==NULL)
return 0;
- map_delblock(object[id]);
+ map_delblock(objects[id]);
numdb_erase(id_db,id);
-// map_freeblock(object[id]);
- object[id]=NULL;
+// map_freeblock(objects[id]);
+ objects[id]=NULL;
if(first_free_object_id>id)
first_free_object_id=id;
- while(last_object_id>2 && object[last_object_id]==NULL)
+ while(last_object_id>2 && objects[last_object_id]==NULL)
last_object_id--;
return 0;
@@ -670,11 +1174,11 @@ int map_delobjectnofree(int id) {
* block_listからの削除、id_dbからの削除
* object dataのfree、object[]へのNULL代入
*
- * addとの対称性が無いのが気になる
+ * addとの??性が無いのが?になる
*------------------------------------------
*/
int map_delobject(int id) {
- struct block_list *obj = object[id];
+ struct block_list *obj = objects[id];
if(obj==NULL)
return 0;
@@ -693,20 +1197,20 @@ int map_delobject(int id) {
void map_foreachobject(int (*func)(struct block_list*,va_list),int type,...) {
int i;
int blockcount=bl_list_count;
- va_list ap=NULL;
+ va_list ap;
va_start(ap,type);
for(i=2;i<=last_object_id;i++){
- if(object[i]){
- if(type && object[i]->type!=type)
+ if(objects[i]){
+ if(type && objects[i]->type!=type)
continue;
if(bl_list_count>=BL_LIST_MAX) {
if(battle_config.error_log)
printf("map_foreachobject: too many block !\n");
}
else
- bl_list[bl_list_count++]=object[i];
+ bl_list[bl_list_count++]=objects[i];
}
}
@@ -729,13 +1233,13 @@ void map_foreachobject(int (*func)(struct block_list*,va_list),int type,...) {
* data!=0の時は拾う等で消えた時として動作
*
* 後者は、map_clearflooritem(id)へ
- * map.h内で#defineしてある
+ * map.h?で#defineしてある
*------------------------------------------
*/
int map_clearflooritem_timer(int tid,unsigned int tick,int id,int data) {
struct flooritem_data *fitem=NULL;
- fitem = (struct flooritem_data *)object[id];
+ fitem = (struct flooritem_data *)objects[id];
if(fitem==NULL || fitem->bl.type!=BL_ITEM || (!data && fitem->cleartimer != tid)){
if(battle_config.error_log)
printf("map_clearflooritem_timer : error\n");
@@ -752,14 +1256,14 @@ int map_clearflooritem_timer(int tid,unsigned int tick,int id,int data) {
}
/*==========================================
- * (m,x,y)の周囲rangeマス内の空き(=侵入可能)cellの
- * 内から適当なマス目の座標をx+(y<<16)で返す
+ * (m,x,y)の周?rangeマス?の空き(=侵入可能)cellの
+ * ?から適?なマス目の座標をx+(y<<16)で返す
*
- * 現状range=1でアイテムドロップ用途のみ
+ * 現?range=1でアイテムドロップ用途のみ
*------------------------------------------
*/
int map_searchrandfreecell(int m,int x,int y,int range) {
- int free_cell,i,j,c;
+ int free_cell,i,j;
for(free_cell=0,i=-range;i<=range;i++){
if(i+y<0 || i+y>=map[m].ys)
@@ -767,7 +1271,7 @@ int map_searchrandfreecell(int m,int x,int y,int range) {
for(j=-range;j<=range;j++){
if(j+x<0 || j+x>=map[m].xs)
continue;
- if((c=read_gat(m,j+x,i+y))==1 || c==5)
+ if(map_getcell(m,j+x,i+y,CELL_CHKNOPASS))
continue;
free_cell++;
}
@@ -781,7 +1285,7 @@ int map_searchrandfreecell(int m,int x,int y,int range) {
for(j=-range;j<=range;j++){
if(j+x<0 || j+x>=map[m].xs)
continue;
- if((c=read_gat(m,j+x,i+y))==1 || c==5)
+ if(map_getcell(m,j+x,i+y,CELL_CHKNOPASS))
continue;
if(free_cell==0){
x+=j;
@@ -797,7 +1301,7 @@ int map_searchrandfreecell(int m,int x,int y,int range) {
}
/*==========================================
- * (m,x,y)を中心に3x3以内に床アイテム設置
+ * (m,x,y)を中心に3x3以?に床アイテム設置
*
* item_dataはamount以外をcopyする
*------------------------------------------
@@ -829,7 +1333,7 @@ int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,struct
fitem->bl.id = map_addobject(&fitem->bl);
if(fitem->bl.id==0){
- free(fitem);
+ aFree(fitem);
return 0;
}
@@ -876,9 +1380,9 @@ void map_addchariddb(int charid, char *name) {
struct charid2nick *p=NULL;
int req=0;
- p=numdb_search(charid_db,charid);
- if(p==NULL){ // データベースにない
- p = (struct charid2nick *)aCalloc(1,sizeof(struct charid2nick));
+ p = (struct charid2nick*)numdb_search(charid_db,charid);
+ if(p==NULL){ // デ?タベ?スにない
+ p = (struct charid2nick *)aCallocA(1,sizeof(struct charid2nick));
p->req_id=0;
}else
numdb_erase(charid_db,charid);
@@ -903,8 +1407,8 @@ int map_reqchariddb(struct map_session_data * sd,int charid) {
nullpo_retr(0, sd);
- p=numdb_search(charid_db,charid);
- if(p!=NULL) // データベースにすでにある
+ p = (struct charid2nick*)numdb_search(charid_db,charid);
+ if(p!=NULL) // デ?タベ?スにすでにある
return 0;
p = (struct charid2nick *)aCalloc(1,sizeof(struct charid2nick));
p->req_id=sd->bl.id;
@@ -943,105 +1447,133 @@ void map_addnickdb(struct map_session_data *sd) {
}
/*==========================================
- * PCのquit処理 map.c内分
+ * PCのquit?理 map.c?分
*
- * quit処理の主体が違うような気もしてきた
+ * quit?理の主?が違うような?もしてきた
*------------------------------------------
*/
int map_quit(struct map_session_data *sd) {
- int i;
-
nullpo_retr(0, sd);
- if(sd->chatID) // チャットから出る
- chat_leavechat(sd);
+ if(!sd->state.waitingdisconnect) {
+ if (sd->state.event_disconnect) {
+ if (script_config.event_script_type == 0) {
+ struct npc_data *npc;
+ if ((npc = npc_name2id(script_config.logout_event_name))) {
+ run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLogoutNPC
+ sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.logout_event_name);
+ ShowStatus(tmp_output);
+ }
+ } else {
+ sprintf (tmp_output, "%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
+ npc_event_doall_id(script_config.logout_event_name, sd->bl.id), script_config.logout_event_name);
+ ShowStatus(tmp_output);
+ }
+ }
- if(sd->trade_partner) // 取引を中断する
- trade_tradecancel(sd);
+ if(sd->chatID) // チャットから出る
+ chat_leavechat(sd);
- if(sd->party_invite>0) // パーティ勧誘を拒否する
- party_reply_invite(sd,sd->party_invite_account,0);
+ if(sd->trade_partner) // 取引を中?する
+ trade_tradecancel(sd);
- if(sd->guild_invite>0) // ギルド勧誘を拒否する
- guild_reply_invite(sd,sd->guild_invite,0);
- if(sd->guild_alliance>0) // ギルド同盟勧誘を拒否する
- guild_reply_reqalliance(sd,sd->guild_alliance_account,0);
+ if(sd->party_invite>0) // パ?ティ?誘を拒否する
+ party_reply_invite(sd,sd->party_invite_account,0);
- party_send_logout(sd); // パーティのログアウトメッセージ送信
+ if(sd->guild_invite>0) // ギルド?誘を拒否する
+ guild_reply_invite(sd,sd->guild_invite,0);
+ if(sd->guild_alliance>0) // ギルド同盟?誘を拒否する
+ guild_reply_reqalliance(sd,sd->guild_alliance_account,0);
- guild_send_memberinfoshort(sd,0); // ギルドのログアウトメッセージ送信
+ party_send_logout(sd); // パ?ティのログアウトメッセ?ジ送信
- pc_cleareventtimer(sd); // イベントタイマを破棄する
+ guild_send_memberinfoshort(sd,0); // ギルドのログアウトメッセ?ジ送信
- if(sd->state.storage_flag)
- storage_guild_storage_quit(sd,0);
- else
- storage_storage_quit(sd); // 倉庫を開いてるなら保存する
-
- skill_castcancel(&sd->bl,0); // 詠唱を中断する
- skill_stop_dancing(&sd->bl,1);// ダンス/演奏中断
-
- if(sd->sc_data && sd->sc_data[SC_BERSERK].timer!=-1) //バーサーク中の終了はHPを100に
- sd->status.hp = 100;
-
- skill_status_change_clear(&sd->bl,1); // ステータス異常を解除する
- skill_clear_unitgroup(&sd->bl); // スキルユニットグループの削除
- skill_cleartimerskill(&sd->bl);
- pc_stop_walking(sd,0);
- pc_stopattack(sd);
- pc_delinvincibletimer(sd);
- pc_delspiritball(sd,sd->spiritball,1);
- skill_gangsterparadise(sd,0);
-
- pc_calcstatus(sd,4);
-
- clif_clearchar_area(&sd->bl,2);
-
- if(sd->status.pet_id && sd->pd) {
- pet_lootitem_drop(sd->pd,sd);
- pet_remove_map(sd);
- if(sd->pet.intimate <= 0) {
- intif_delete_petdata(sd->status.pet_id);
- sd->status.pet_id = 0;
- sd->pd = NULL;
- sd->petDB = NULL;
- }
+ pc_cleareventtimer(sd); // イベントタイマを破棄する
+
+ if(sd->state.storage_flag)
+ storage_guild_storage_quit(sd,0);
else
- intif_save_petdata(sd->status.account_id,&sd->pet);
- }
-
- if(pc_isdead(sd))
- pc_setrestartvalue(sd,2);
- pc_makesavestatus(sd);
- //クローンスキルで覚えたスキルは消す
- for(i=0;i<MAX_SKILL;i++){
- if(sd->status.skill[i].flag == 13){
- sd->status.skill[i].id=0;
- sd->status.skill[i].lv=0;
- sd->status.skill[i].flag=0;
+ storage_storage_quit(sd); // 倉庫を開いてるなら保存する
+
+ // check if we've been authenticated [celest]
+ if (sd->state.auth)
+ skill_castcancel(&sd->bl,0); // 詠唱を中?する
+
+ skill_stop_dancing(&sd->bl,1);// ダンス/演奏中?
+
+ if(sd->sc_data && sd->sc_data[SC_BERSERK].timer!=-1) //バ?サ?ク中の終了はHPを100に
+ sd->status.hp = 100;
+
+ status_change_clear(&sd->bl,1); // ステ?タス異常を解除する
+ skill_clear_unitgroup(&sd->bl); // スキルユニットグル?プの削除
+ skill_cleartimerskill(&sd->bl);
+
+ // check if we've been authenticated [celest]
+ if (sd->state.auth) {
+ pc_stop_walking(sd,0);
+ pc_stopattack(sd);
+ pc_delinvincibletimer(sd);
+ }
+ pc_delspiritball(sd,sd->spiritball,1);
+ skill_gangsterparadise(sd,0);
+ skill_unit_move(&sd->bl,gettick(),0);
+
+ if (sd->state.auth)
+ status_calc_pc(sd,4);
+ // skill_clear_unitgroup(&sd->bl); // [Sara-chan]
+
+ clif_clearchar_area(&sd->bl,2);
+
+ if(sd->status.pet_id && sd->pd) {
+ pet_lootitem_drop(sd->pd,sd);
+ pet_remove_map(sd);
+ if(sd->pet.intimate <= 0) {
+ intif_delete_petdata(sd->status.pet_id);
+ sd->status.pet_id = 0;
+ sd->pd = NULL;
+ sd->petDB = NULL;
+ }
+ else
+ intif_save_petdata(sd->status.account_id,&sd->pet);
}
- }
- chrif_save(sd);
- storage_storage_save(sd);
- if( sd->npc_stackbuf && sd->npc_stackbuf != NULL)
- free( sd->npc_stackbuf );
+ if(pc_isdead(sd))
+ pc_setrestartvalue(sd,2);
- map_delblock(&sd->bl);
+ pc_clean_skilltree(sd);
+ pc_makesavestatus(sd);
+ chrif_save(sd);
+ storage_storage_dirty(sd);
+ storage_storage_save(sd);
+ map_delblock(&sd->bl);
+ }
+
+ if( sd->npc_stackbuf && sd->npc_stackbuf != NULL) {
+ aFree( sd->npc_stackbuf );
+ sd->npc_stackbuf = NULL;
+ }
-#ifndef TXT_ONLY
chrif_char_offline(sd);
-#endif
- numdb_erase(id_db,sd->bl.id);
+ {
+ void *p = numdb_search(charid_db,sd->status.char_id);
+ if(p) {
+ numdb_erase(charid_db,sd->status.char_id);
+ aFree(p);
+ }
+ }
strdb_erase(nick_db,sd->status.name);
numdb_erase(charid_db,sd->status.char_id);
+ numdb_erase(id_db,sd->bl.id);
+ aFree(sd->reg);
+ aFree(sd->regstr);
return 0;
}
/*==========================================
- * id番号のPCを探す。居なければNULL
+ * id番?のPCを探す。居なければNULL
*------------------------------------------
*/
struct map_session_data * map_id2sd(int id) {
@@ -1060,21 +1592,23 @@ struct map_session_data * map_id2sd(int id) {
return NULL;
*/
int i;
- struct map_session_data *sd=NULL;
+ struct map_session_data *sd;
+
+ if (id <= 0) return 0;
for(i = 0; i < fd_max; i++)
- if (session[i] && (sd = session[i]->session_data) && sd->bl.id == id)
+ if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd->bl.id == id)
return sd;
return NULL;
}
/*==========================================
- * char_id番号の名前を探す
+ * char_id番?の名前を探す
*------------------------------------------
*/
char * map_charid2nick(int id) {
- struct charid2nick *p=numdb_search(charid_db,id);
+ struct charid2nick *p = (struct charid2nick*)numdb_search(charid_db,id);
if(p==NULL)
return NULL;
@@ -1083,6 +1617,18 @@ char * map_charid2nick(int id) {
return p->nick;
}
+struct map_session_data * map_charid2sd(int id) {
+ int i;
+ struct map_session_data *sd;
+
+ if (id <= 0) return 0;
+
+ for(i = 0; i < fd_max; i++)
+ if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd->status.char_id == id)
+ return sd;
+
+ return NULL;
+}
/*==========================================
* Search session data from a nick name
@@ -1101,7 +1647,7 @@ struct map_session_data * map_nick2sd(char *nick) {
nicklen = strlen(nick);
for (i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth)
+ if (session[i] && (pl_sd = (struct map_session_data*)session[i]->session_data) && pl_sd->state.auth)
// Without case sensitive check (increase the number of similar character names found)
if (strnicmp(pl_sd->status.name, nick, nicklen) == 0) {
// Strict comparison (if found, we finish the function immediatly with correct value)
@@ -1121,27 +1667,27 @@ struct map_session_data * map_nick2sd(char *nick) {
}
/*==========================================
- * id番号の物を探す
+ * id番?の物を探す
* 一時objectの場合は配列を引くのみ
*------------------------------------------
*/
struct block_list * map_id2bl(int id)
{
struct block_list *bl=NULL;
- if(id<sizeof(object)/sizeof(object[0]))
- bl = object[id];
+ if(id >= 0 && id < sizeof(objects)/sizeof(objects[0]))
+ bl = objects[id];
else
- bl = numdb_search(id_db,id);
+ bl = (struct block_list*)numdb_search(id_db,id);
return bl;
}
/*==========================================
- * id_db内の全てにfuncを実行
+ * id_db?の全てにfuncを?行
*------------------------------------------
*/
int map_foreachiddb(int (*func)(void*,void*,va_list),...) {
- va_list ap=NULL;
+ va_list ap;
va_start(ap,func);
numdb_foreach(id_db,func,ap);
@@ -1179,48 +1725,60 @@ int map_addnpc(int m,struct npc_data *nd) {
}
void map_removenpc(void) {
- int i,m,n=0;
-
- for(m=0;m<map_num;m++) {
- for(i=0;i<map[m].npc_num && i<MAX_NPC_PER_MAP;i++) {
- if(map[m].npc[i]!=NULL) {
- clif_clearchar_area(&map[m].npc[i]->bl,2);
- map_delblock(&map[m].npc[i]->bl);
- numdb_erase(id_db,map[m].npc[i]->bl.id);
- if(map[m].npc[i]->bl.subtype==SCRIPT) {
-// free(map[m].npc[i]->u.scr.script);
-// free(map[m].npc[i]->u.scr.label_list);
- }
- free(map[m].npc[i]);
- map[m].npc[i] = NULL;
- n++;
- }
- }
- }
- printf("%d NPCs removed.\n",n);
+ int i,m,n=0;
+
+ for(m=0;m<map_num;m++) {
+ for(i=0;i<map[m].npc_num && i<MAX_NPC_PER_MAP;i++) {
+ if(map[m].npc[i]!=NULL) {
+ clif_clearchar_area(&map[m].npc[i]->bl,2);
+ map_delblock(&map[m].npc[i]->bl);
+ numdb_erase(id_db,map[m].npc[i]->bl.id);
+ if(map[m].npc[i]->bl.subtype==SCRIPT) {
+ aFree(map[m].npc[i]->u.scr.script);
+ aFree(map[m].npc[i]->u.scr.label_list);
+ }
+ aFree(map[m].npc[i]);
+ map[m].npc[i] = NULL;
+ n++;
+ }
+ }
+ }
+
+ sprintf(tmp_output,"Successfully removed and freed from memory '"CL_WHITE"%d"CL_RESET"' NPCs.\n",n);
+ ShowStatus(tmp_output);
}
/*==========================================
- * map名からmap番号へ変換
+ * map名からmap番?へ?換
*------------------------------------------
*/
int map_mapname2mapid(char *name) {
struct map_data *md=NULL;
- md=strdb_search(map_db,name);
+ md = (struct map_data*)strdb_search(map_db,name);
+
+#ifdef USE_AFM
+ // If we can't find the .gat map try .afm instead [celest]
+ if(md==NULL && strstr(name,".gat")) {
+ char *afm_name = strdup(name);
+ strcpy(&afm_name[strlen(name) - 3], "afm");
+ md = (struct map_data*)strdb_search(map_db,afm_name);
+ }
+#endif
+
if(md==NULL || md->gat==NULL)
return -1;
return md->m;
}
/*==========================================
- * 他鯖map名からip,port変換
+ * 他鯖map名からip,port?換
*------------------------------------------
*/
int map_mapname2ipport(char *name,int *ip,int *port) {
struct map_data_other_server *mdos=NULL;
- mdos=strdb_search(map_db,name);
+ mdos = (struct map_data_other_server*)strdb_search(map_db,name);
if(mdos==NULL || mdos->gat)
return -1;
*ip=mdos->ip;
@@ -1311,20 +1869,74 @@ int map_calc_dir( struct block_list *src,int x,int y) {
* (m,x,y)の状態を調べる
*------------------------------------------
*/
-int map_getcell(int m,int x,int y) {
- if(x<0 || x>=map[m].xs-1 || y<0 || y>=map[m].ys-1)
- return 1;
- return map[m].gat[x+y*map[m].xs];
+
+int map_getcell(int m,int x,int y,cell_t cellchk)
+{
+ return (m < 0 || m > MAX_MAP_PER_SERVER) ? 0 : map_getcellp(&map[m],x,y,cellchk);
+}
+
+int map_getcellp(struct map_data* m,int x,int y,cell_t cellchk)
+{
+ int type;
+ nullpo_ret(m);
+
+ if(x<0 || x>=m->xs-1 || y<0 || y>=m->ys-1)
+ {
+ if(cellchk==CELL_CHKNOPASS) return 1;
+ return 0;
+ }
+ type = m->gat[x+y*m->xs];
+ if (cellchk<0x10)
+ type &= CELL_MASK;
+
+ switch(cellchk)
+ {
+ case CELL_CHKPASS:
+ return (type!=1 && type!=5);
+ case CELL_CHKNOPASS:
+ return (type==1 || type==5);
+ case CELL_CHKWALL:
+ return (type==1);
+ case CELL_CHKWATER:
+ return (type==3);
+ case CELL_CHKGROUND:
+ return (type==5);
+ case CELL_GETTYPE:
+ return type;
+ case CELL_CHKNPC:
+ return (type&CELL_NPC);
+ case CELL_CHKBASILICA:
+ return (type&CELL_BASILICA);
+ default:
+ return 0;
+ }
}
/*==========================================
- * (m,x,y)の状態をtにする
+ * (m,x,y)の状態を設定する
*------------------------------------------
*/
-int map_setcell(int m,int x,int y,int t) {
+void map_setcell(int m,int x,int y,int cell)
+{
+ int j;
if(x<0 || x>=map[m].xs || y<0 || y>=map[m].ys)
- return t;
- return map[m].gat[x+y*map[m].xs]=t;
+ return;
+ j=x+y*map[m].xs;
+
+ 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;
+ }
}
/*==========================================
@@ -1335,22 +1947,46 @@ int map_setipport(char *name,unsigned long ip,int port) {
struct map_data *md=NULL;
struct map_data_other_server *mdos=NULL;
- md=strdb_search(map_db,name);
+ md = (struct map_data*)strdb_search(map_db,name);
if(md==NULL){ // not exist -> add new data
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 = 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;
+ aFree(mdos);
+ strdb_insert(map_db,md->name,md);
}
- } else { // update
- mdos=(struct map_data_other_server *)md;
+ } else {
+ // 他の鯖の担当マップなので置き換えるだけ
mdos->ip = ip;
mdos->port = port;
}
@@ -1358,12 +1994,62 @@ 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);
+ aFree(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=(struct map_data *) 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);
+ aFree(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;
+}
+
// 初期化周り
/*==========================================
* 水場高さ設定
*------------------------------------------
*/
-static struct {
+static struct waterlist_ {
char mapname[24];
int waterheight;
} *waterlist=NULL;
@@ -1391,7 +2077,7 @@ static void map_readwater(char *watertxt) {
return;
}
if(waterlist==NULL)
- waterlist=aCalloc(MAX_MAP_PER_SERVER,sizeof(*waterlist));
+ waterlist = (struct waterlist_*)aCallocA(MAX_MAP_PER_SERVER,sizeof(*waterlist));
while(fgets(line,1020,fp) && n < MAX_MAP_PER_SERVER){
int wh,count;
if(line[0] == '/' && line[1] == '/')
@@ -1408,8 +2094,244 @@ static void map_readwater(char *watertxt) {
}
fclose(fp);
}
+/*==========================================
+* マップキャッシュに追加する
+*===========================================*/
+
+// マップキャッシュの最大値
+#define MAX_MAP_CACHE 768
+
+//各マップごとの最小限情報を入れるもの、READ_FROM_BITMAP用
+struct map_cache_info {
+ char fn[32];//ファイル名
+ int xs,ys; //幅と高さ
+ int water_height;
+ int pos; // データが入れてある場所
+ int compressed; // zilb通せるようにする為の予約
+ int compressed_len; // zilb通せるようにする為の予約
+}; // 56 byte
+
+struct map_cache_head {
+ int sizeof_header;
+ int sizeof_map;
+ // 上の2つ改変不可
+ int nmaps; // マップの個数
+ int filesize;
+};
+
+struct {
+ struct map_cache_head head;
+ struct map_cache_info *map;
+ FILE *fp;
+ int dirty;
+} map_cache;
+
+static int map_cache_open(char *fn);
+static void map_cache_close(void);
+static int map_cache_read(struct map_data *m);
+static int map_cache_write(struct map_data *m);
+
+static int map_cache_open(char *fn)
+{
+ atexit(map_cache_close);
+ if(map_cache.fp) {
+ map_cache_close();
+ }
+ map_cache.fp = fopen(fn,"r+b");
+ if(map_cache.fp) {
+ fread(&map_cache.head,1,sizeof(struct map_cache_head),map_cache.fp);
+ fseek(map_cache.fp,0,SEEK_END);
+ if(
+ map_cache.head.sizeof_header == sizeof(struct map_cache_head) &&
+ map_cache.head.sizeof_map == sizeof(struct map_cache_info) &&
+ map_cache.head.nmaps == MAX_MAP_CACHE &&
+ map_cache.head.filesize == ftell(map_cache.fp)
+ ) {
+ // キャッシュ読み込み成功
+ map_cache.map = (struct map_cache_info *) aMalloc(sizeof(struct map_cache_info) * map_cache.head.nmaps);
+ fseek(map_cache.fp,sizeof(struct map_cache_head),SEEK_SET);
+ fread(map_cache.map,sizeof(struct map_cache_info),map_cache.head.nmaps,map_cache.fp);
+ return 1;
+ }
+ fclose(map_cache.fp);
+ }
+ // 読み込みに失敗したので新規に作成する
+ map_cache.fp = fopen(fn,"wb");
+ if(map_cache.fp) {
+ memset(&map_cache.head,0,sizeof(struct map_cache_head));
+ map_cache.map = (struct map_cache_info *) aCalloc(sizeof(struct map_cache_info),MAX_MAP_CACHE);
+ map_cache.head.nmaps = MAX_MAP_CACHE;
+ map_cache.head.sizeof_header = sizeof(struct map_cache_head);
+ map_cache.head.sizeof_map = sizeof(struct map_cache_info);
+
+ map_cache.head.filesize = sizeof(struct map_cache_head);
+ map_cache.head.filesize += sizeof(struct map_cache_info) * map_cache.head.nmaps;
+
+ map_cache.dirty = 1;
+ return 1;
+ }
+ return 0;
+}
+
+static void map_cache_close(void)
+{
+ if(!map_cache.fp) { return; }
+ if(map_cache.dirty) {
+ fseek(map_cache.fp,0,SEEK_SET);
+ fwrite(&map_cache.head,1,sizeof(struct map_cache_head),map_cache.fp);
+ fwrite(map_cache.map,map_cache.head.nmaps,sizeof(struct map_cache_info),map_cache.fp);
+ }
+ fclose(map_cache.fp);
+ aFree(map_cache.map);
+ map_cache.fp = NULL;
+ return;
+}
+
+int map_cache_read(struct map_data *m)
+{
+ int i;
+ if(!map_cache.fp) { return 0; }
+ for(i = 0;i < map_cache.head.nmaps ; i++) {
+ if(!strcmp(m->name,map_cache.map[i].fn)) {
+ if(map_cache.map[i].water_height != map_waterheight(m->name)) {
+ // 水場の高さが違うので読み直し
+ return 0;
+ } else if(map_cache.map[i].compressed == 0) {
+ // 非圧縮ファイル
+ int size = map_cache.map[i].xs * map_cache.map[i].ys;
+ m->xs = map_cache.map[i].xs;
+ m->ys = map_cache.map[i].ys;
+ m->gat = (unsigned char *)aCalloc(m->xs * m->ys,sizeof(unsigned char));
+ fseek(map_cache.fp,map_cache.map[i].pos,SEEK_SET);
+ if(fread(m->gat,1,size,map_cache.fp) == size) {
+ // 成功
+ return 1;
+ } else {
+ // なぜかファイル後半が欠けてるので読み直し
+ m->xs = 0; m->ys = 0; m->gat = NULL; aFree(m->gat);
+ return 0;
+ }
+ } else if(map_cache.map[i].compressed == 1) {
+ // 圧縮フラグ=1 : zlib
+ unsigned char *buf;
+ unsigned long dest_len;
+ int size_compress = map_cache.map[i].compressed_len;
+ m->xs = map_cache.map[i].xs;
+ m->ys = map_cache.map[i].ys;
+ m->gat = (unsigned char *)aMalloc(m->xs * m->ys * sizeof(unsigned char));
+ buf = (unsigned char*)aMalloc(size_compress);
+ fseek(map_cache.fp,map_cache.map[i].pos,SEEK_SET);
+ if(fread(buf,1,size_compress,map_cache.fp) != size_compress) {
+ // なぜかファイル後半が欠けてるので読み直し
+ printf("fread error\n");
+ aFree(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL;
+ aFree(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) {
+ // 正常に解凍が出来てない
+ aFree(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL;
+ aFree(buf);
+ return 0;
+ }
+ aFree(buf);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+static int map_cache_write(struct map_data *m)
+{
+ int i;
+ unsigned long len_new , len_old;
+ char *write_buf;
+ if(!map_cache.fp) { return 0; }
+ for(i = 0;i < map_cache.head.nmaps ; i++) {
+ if(!strcmp(m->name,map_cache.map[i].fn)) {
+ // 同じエントリーがあれば上書き
+ if(map_cache.map[i].compressed == 0) {
+ len_old = map_cache.map[i].xs * map_cache.map[i].ys;
+ } else if(map_cache.map[i].compressed == 1) {
+ len_old = map_cache.map[i].compressed_len;
+ } else {
+ // サポートされてない形式なので長さ0
+ len_old = 0;
+ }
+ if(map_read_flag == 2) {
+ // 圧縮保存
+ // さすがに2倍に膨れる事はないという事で
+ write_buf = (char *) aMalloc(m->xs * m->ys * 2);
+ len_new = m->xs * m->ys * 2;
+ encode_zip((unsigned char *) write_buf,&len_new,m->gat,m->xs * m->ys);
+ map_cache.map[i].compressed = 1;
+ map_cache.map[i].compressed_len = len_new;
+ } else {
+ len_new = m->xs * m->ys;
+ write_buf = (char *) m->gat;
+ map_cache.map[i].compressed = 0;
+ map_cache.map[i].compressed_len = 0;
+ }
+ if(len_new <= len_old) {
+ // サイズが同じか小さくなったので場所は変わらない
+ fseek(map_cache.fp,map_cache.map[i].pos,SEEK_SET);
+ fwrite(write_buf,1,len_new,map_cache.fp);
+ } else {
+ // 新しい場所に登録
+ fseek(map_cache.fp,map_cache.head.filesize,SEEK_SET);
+ fwrite(write_buf,1,len_new,map_cache.fp);
+ map_cache.map[i].pos = map_cache.head.filesize;
+ map_cache.head.filesize += len_new;
+ }
+ map_cache.map[i].xs = m->xs;
+ map_cache.map[i].ys = m->ys;
+ map_cache.map[i].water_height = map_waterheight(m->name);
+ map_cache.dirty = 1;
+ if(map_read_flag == 2) {
+ aFree(write_buf);
+ }
+ return 0;
+ }
+ }
+ // 同じエントリが無ければ書き込める場所を探す
+ for(i = 0;i < map_cache.head.nmaps ; i++) {
+ if(map_cache.map[i].fn[0] == 0) {
+ // 新しい場所に登録
+ if(map_read_flag == 2) {
+ write_buf = (char *) aMalloc(m->xs * m->ys * 2);
+ len_new = m->xs * m->ys * 2;
+ encode_zip((unsigned char *) write_buf,&len_new,m->gat,m->xs * m->ys);
+ map_cache.map[i].compressed = 1;
+ map_cache.map[i].compressed_len = len_new;
+ } else {
+ len_new = m->xs * m->ys;
+ write_buf = (char *) m->gat;
+ map_cache.map[i].compressed = 0;
+ map_cache.map[i].compressed_len = 0;
+ }
+ strncpy(map_cache.map[i].fn,m->name,sizeof(map_cache.map[0].fn));
+ fseek(map_cache.fp,map_cache.head.filesize,SEEK_SET);
+ fwrite(write_buf,1,len_new,map_cache.fp);
+ map_cache.map[i].pos = map_cache.head.filesize;
+ map_cache.map[i].xs = m->xs;
+ map_cache.map[i].ys = m->ys;
+ map_cache.map[i].water_height = map_waterheight(m->name);
+ map_cache.head.filesize += len_new;
+ map_cache.dirty = 1;
+ if(map_read_flag == 2) {
+ aFree(write_buf);
+ }
+ return 0;
+ }
+ }
+ // 書き込めなかった
+ return 1;
+}
+#ifdef USE_AFM
static int map_readafm(int m,char *fn) {
/*
@@ -1474,7 +2396,7 @@ static int map_readafm(int m,char *fn) {
size_t size;
char afm_line[65535];
- int afm_size[1];
+ int afm_size[2];
FILE *afm_file;
char *str;
@@ -1492,7 +2414,8 @@ static int map_readafm(int m,char *fn) {
map[m].m = m;
xs = map[m].xs = afm_size[0];
ys = map[m].ys = afm_size[1];
- map[m].gat = calloc(s = map[m].xs * map[m].ys, 1);
+ // check this, unsigned where it might not need to be
+ map[m].gat = (unsigned char*)aCallocA(s = map[m].xs * map[m].ys, 1);
if(map[m].gat==NULL){
printf("out of memory : map_readmap gat\n");
@@ -1515,14 +2438,14 @@ static int map_readafm(int m,char *fn) {
map[m].bxs=(xs+BLOCK_SIZE-1)/BLOCK_SIZE;
map[m].bys=(ys+BLOCK_SIZE-1)/BLOCK_SIZE;
size = map[m].bxs * map[m].bys * sizeof(struct block_list*);
- map[m].block = calloc(size, 1);
+ map[m].block = (struct block_list**)aCalloc(size, 1);
if(map[m].block == NULL){
printf("out of memory : map_readmap block\n");
exit(1);
}
- map[m].block_mob = calloc(size, 1);
+ map[m].block_mob = (struct block_list**)aCalloc(size, 1);
if (map[m].block_mob == NULL) {
printf("out of memory : map_readmap block_mob\n");
exit(1);
@@ -1530,14 +2453,14 @@ static int map_readafm(int m,char *fn) {
size = map[m].bxs*map[m].bys*sizeof(int);
- map[m].block_count = calloc(size, 1);
+ map[m].block_count = (int*)aCallocA(size, 1);
if(map[m].block_count==NULL){
printf("out of memory : map_readmap block\n");
exit(1);
}
memset(map[m].block_count,0,size);
- map[m].block_mob_count=calloc(size, 1);
+ map[m].block_mob_count = (int*)aCallocA(size, 1);
if(map[m].block_mob_count==NULL){
printf("out of memory : map_readmap block_mob\n");
exit(1);
@@ -1552,58 +2475,100 @@ static int map_readafm(int m,char *fn) {
return 0;
}
+#endif
/*==========================================
* マップ1枚読み込み
- *------------------------------------------
- */
-static int map_readmap(int m,char *fn, char *alias) {
- unsigned char *gat="";
- int s;
- int x,y,xs,ys;
- struct gat_1cell {float high[4]; int type;} *p=NULL;
- int wh;
+ * ===================================================*/
+static int map_readmap(int m,char *fn, char *alias, int *map_cache, int maxmap) {
+ char *gat="";
size_t size;
- // read & convert fn
- gat=grfio_read(fn);
- if(gat==NULL)
- return -1;
+ int i = 0;
+ int e = 0;
+ char progress[21] = " ";
+
+ //printf("\rLoading Maps [%d/%d]: %-50s ",m,map_num,fn);
+ if (maxmap) { //avoid map-server crashing if there are 0 maps
+ char c = '-';
+ static int lasti = -1;
+ static int last_time = -1;
+ i=m*20/maxmap;
+ if ((i != lasti) || (last_time != time(0))) {
+ lasti = i;
+ printf("\r");
+ ShowStatus("Progress: ");
+ printf("[");
+ for (e=0;e<i;e++) progress[e] = '#';
+ printf(progress);
+ printf("] Working: [");
+ last_time = time(0);
+ switch(last_time % 4) {
+ case 0: c='\\'; break;
+ case 1: c='|'; break;
+ case 2: c='/'; break;
+ case 3: c='-'; break;
+ }
+ printf("%c]",c);
+ fflush(stdout);
+ }
+ }
-// printf("\rLoading Maps [%d/%d]: %-50s ",m,map_num,fn);
-// fflush(stdout);
+ if(map_cache_read(&map[m])) {
+ // キャッシュから読み込めた
+ (*map_cache)++;
+ } else {
+ int s;
+ int wh;
+ int x,y,xs,ys;
+ struct gat_1cell {float high[4]; int type;} *p=NULL;
+ // read & convert fn
+ // again, might not need to be unsigned char
+ gat = (char*)grfio_read(fn);
+ if(gat==NULL) {
+ return -1;
+ // さすがにマップが読めないのはまずいので終了する
+ //printf("Can't load map %s\n",fn);
+ //exit(1);
+ }
- map[m].m=m;
- xs=map[m].xs=*(int*)(gat+6);
- ys=map[m].ys=*(int*)(gat+10);
- map[m].gat = (unsigned char *)aCalloc(s = map[m].xs * map[m].ys,sizeof(unsigned char));
- map[m].npc_num=0;
- map[m].users=0;
- memset(&map[m].flag,0,sizeof(map[m].flag));
- if(battle_config.pk_mode) map[m].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris]
- wh=map_waterheight(map[m].name);
- for(y=0;y<ys;y++){
- p=(struct gat_1cell*)(gat+y*xs*20+14);
- for(x=0;x<xs;x++){
- if(wh!=NO_WATER && p->type==0){
- // 水場判定
- map[m].gat[x+y*xs]=(p->high[0]>wh || p->high[1]>wh || p->high[2]>wh || p->high[3]>wh) ? 3 : 0;
- } else {
- map[m].gat[x+y*xs]=p->type;
+ xs=map[m].xs=*(int*)(gat+6);
+ ys=map[m].ys=*(int*)(gat+10);
+ map[m].gat = (unsigned char *)aCallocA(s = map[m].xs * map[m].ys,sizeof(unsigned char));
+ wh=map_waterheight(map[m].name);
+ for(y=0;y<ys;y++){
+ p=(struct gat_1cell*)(gat+y*xs*20+14);
+ for(x=0;x<xs;x++){
+ if(wh!=NO_WATER && p->type==0){
+ // 水場判定
+ map[m].gat[x+y*xs]=(p->high[0]>wh || p->high[1]>wh || p->high[2]>wh || p->high[3]>wh) ? 3 : 0;
+ } else {
+ map[m].gat[x+y*xs]=p->type;
+ }
+ p++;
}
- p++;
}
+ map_cache_write(&map[m]);
+ aFree(gat);
}
- free(gat);
- map[m].bxs=(xs+BLOCK_SIZE-1)/BLOCK_SIZE;
- map[m].bys=(ys+BLOCK_SIZE-1)/BLOCK_SIZE;
+ map[m].m=m;
+ map[m].npc_num=0;
+ map[m].users=0;
+ memset(&map[m].flag,0,sizeof(map[m].flag));
+ if(battle_config.pk_mode)
+ map[m].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris]
+ map[m].bxs=(map[m].xs+BLOCK_SIZE-1)/BLOCK_SIZE;
+ map[m].bys=(map[m].ys+BLOCK_SIZE-1)/BLOCK_SIZE;
size = map[m].bxs * map[m].bys * sizeof(struct block_list*);
map[m].block = (struct block_list **)aCalloc(1,size);
map[m].block_mob = (struct block_list **)aCalloc(1,size);
size = map[m].bxs*map[m].bys*sizeof(int);
- map[m].block_count = (int *)aCalloc(1,size);
- map[m].block_mob_count=(int *)aCalloc(1,size);
+ map[m].block_count = (int *)aCallocA(1,size);
+ map[m].block_mob_count=(int *)aCallocA(1,size);
+ if (alias)
+ strdb_insert(map_db,alias,&map[m]);
+ else
strdb_insert(map_db,map[m].name,&map[m]);
// printf("%s read done\n",fn);
@@ -1612,57 +2577,90 @@ static int map_readmap(int m,char *fn, char *alias) {
}
/*==========================================
- * 全てのmapデータを読み込む
+ * 全てのmapデ?タを?み?む
*------------------------------------------
*/
int map_readallmap(void) {
int i,maps_removed=0;
char fn[256];
+#ifdef USE_AFM
FILE *afm_file;
+#endif
+ int map_cache = 0;
+
+ // マップキャッシュを開く
+ if(map_read_flag >= READ_FROM_BITMAP) {
+ map_cache_open(map_cache_file);
+ }
+
+ sprintf(tmp_output, "Loading Maps%s...\n",
+ (map_read_flag == CREATE_BITMAP_COMPRESSED ? " (Generating Map Cache w/ Compression)" :
+ map_read_flag == CREATE_BITMAP ? " (Generating Map Cache)" :
+ map_read_flag >= READ_FROM_BITMAP ? " (w/ Map Cache)" :
+ map_read_flag == READ_FROM_AFM ? " (w/ AFM)" : ""));
+ ShowStatus(tmp_output);
// 先に全部のャbプの存在を確認
for(i=0;i<map_num;i++){
- char afm_name[256] = "";
- strncpy(afm_name, map[i].name, strlen(map[i].name) - 4);
- strcat(afm_name, ".afm");
+#ifdef USE_AFM
+ char afm_name[256] = "";
+ char *p;
+ if(!strstr(map[i].name,".afm")) {
+ // check if it's necessary to replace the extension - speeds up loading abit
+ strncpy(afm_name, map[i].name, strlen(map[i].name) - 4);
+ strcat(afm_name, ".afm");
+ }
+ map[i].alias = NULL;
sprintf(fn,"%s\\%s",afm_dir,afm_name);
+ for(p=&fn[0];*p!=0;p++) if (*p=='\\') *p = '/'; // * At the time of Unix
+
afm_file = fopen(fn, "r");
if (afm_file != NULL) {
map_readafm(i,fn);
fclose(afm_file);
}
else if(strstr(map[i].name,".gat")!=NULL) {
- char *p = strstr(map[i].name, ">"); // [MouseJstr]
+#else
+ if(strstr(map[i].name,".gat")!=NULL) {
+#endif
+ char *p = strstr(map[i].name, "<"); // [MouseJstr]
if (p != NULL) {
- char alias[64];
- *p = '\0';
- strcpy(alias, map[i].name);
- strcpy(map[i].name, p + 1);
- sprintf(fn,"data\\%s",map[i].name);
- if(map_readmap(i,fn, alias) == -1) {
- map_delmap(map[i].name);
- maps_removed++;
- }
- } else {
- sprintf(fn,"data\\%s",map[i].name);
- if(map_readmap(i,fn, NULL) == -1) {
- map_delmap(map[i].name);
- maps_removed++;
- }
+ char buf[64];
+ *p++ = '\0';
+ sprintf(buf,"data\\%s", p);
+ map[i].alias = aStrdup(buf);
+ } else
+ map[i].alias = NULL;
+
+ sprintf(fn,"data\\%s",map[i].name);
+ if(map_readmap(i,fn, p, &map_cache, map_num) == -1) {
+ map_delmap(map[i].name);
+ maps_removed++;
+ i--;
}
}
}
- free(waterlist);
- printf("\rMaps Loaded: %d %60s\n",map_num,"");
- printf("\rMaps Removed: %d \n",maps_removed);
+ aFree(waterlist);
+ printf("\r");
+ snprintf(tmp_output,sizeof(tmp_output),"Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps.%30s\n",map_num,"");
+ ShowInfo(tmp_output);
+
+ map_cache_close();
+ if(map_read_flag == CREATE_BITMAP || map_read_flag == CREATE_BITMAP_COMPRESSED) {
+ --map_read_flag;
+ }
+ if (maps_removed) {
+ snprintf(tmp_output,sizeof(tmp_output),"Maps Removed: '"CL_WHITE"%d"CL_RESET"'\n",maps_removed);
+ ShowNotice(tmp_output);
+ }
return 0;
}
/*==========================================
- * 読み込むmapを追加する
+ * ?み?むmapを追加する
*------------------------------------------
*/
int map_addmap(char *mapname) {
@@ -1672,7 +2670,9 @@ int map_addmap(char *mapname) {
}
if (map_num >= MAX_MAP_PER_SERVER - 1) {
- printf("too many map\n");
+ snprintf(tmp_output,sizeof(tmp_output),"Could not add map '"
+ CL_WHITE"%s"CL_RESET"', the limit of maps has been reached.\n",mapname);
+ ShowError(tmp_output);
return 1;
}
memcpy(map[map_num].name, mapname, 24);
@@ -1681,7 +2681,7 @@ int map_addmap(char *mapname) {
}
/*==========================================
- * 読み込むmapを削除する
+ * ?み?むmapを削除する
*------------------------------------------
*/
int map_delmap(char *mapname) {
@@ -1705,6 +2705,7 @@ int map_delmap(char *mapname) {
static int map_ip_set_ = 0;
static int char_ip_set_ = 0;
+//static int bind_ip_set_ = 0;
/*==========================================
* Console Command Parser [Wizputer]
@@ -1716,15 +2717,15 @@ int parse_console(char *buf) {
int m, n;
struct map_session_data *sd;
- sd = calloc(sizeof(*sd), 1);
+ sd = (struct map_session_data*)aCalloc(sizeof(*sd), 1);
sd->fd = 0;
strcpy( sd->status.name , "console");
- type = (char *)malloc(64);
- command = (char *)malloc(64);
- map = (char *)malloc(64);
- buf2 = (char *)malloc(72);
+ type = (char *)aMallocA(64);
+ command = (char *)aMallocA(64);
+ map = (char *)aMallocA(64);
+ buf2 = (char *)aMallocA(72);
memset(type,0,64);
memset(command,0,64);
@@ -1781,18 +2782,18 @@ int parse_console(char *buf) {
}
end:
- free(buf);
- free(type);
- free(command);
- free(map);
- free(buf2);
- free(sd);
+ aFree(buf);
+ aFree(type);
+ aFree(command);
+ aFree(map);
+ aFree(buf2);
+ aFree(sd);
return 0;
}
/*==========================================
- * 設定ファイルを読み込む
+ * 設定ファイルを?み?む
*------------------------------------------
*/
int map_config_read(char *cfgName) {
@@ -1817,7 +2818,7 @@ int map_config_read(char *cfgName) {
char_ip_set_ = 1;
h = gethostbyname (w2);
if(h != NULL) {
- snprintf(tmp_output,sizeof(tmp_output),"Character server IP address : %s -> %d.%d.%d.%d\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
+ snprintf(tmp_output,sizeof(tmp_output),"Char Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'.\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
ShowInfo(tmp_output);
sprintf(w2,"%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
}
@@ -1828,10 +2829,20 @@ int map_config_read(char *cfgName) {
map_ip_set_ = 1;
h = gethostbyname (w2);
if (h != NULL) {
- printf("Map server IP address : %s -> %d.%d.%d.%d\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
+ snprintf(tmp_output,sizeof(tmp_output),"Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'.\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
+ ShowInfo(tmp_output);
sprintf(w2, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
}
clif_setip(w2);
+ } else if (strcmpi(w1, "bind_ip") == 0) {
+ //bind_ip_set_ = 1;
+ h = gethostbyname (w2);
+ if (h != NULL) {
+ snprintf(tmp_output,sizeof(tmp_output),"Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'.\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
+ ShowInfo(tmp_output);
+ sprintf(w2, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
+ }
+ clif_setbindip(w2);
} else if (strcmpi(w1, "map_port") == 0) {
clif_setport(atoi(w2));
map_port = (atoi(w2));
@@ -1861,11 +2872,22 @@ int map_config_read(char *cfgName) {
strcpy(help_txt, w2);
} else if (strcmpi(w1, "mapreg_txt") == 0) {
strcpy(mapreg_txt, w2);
+ }else if(strcmpi(w1,"read_map_from_cache")==0){
+ if (atoi(w2) == 2)
+ map_read_flag = READ_FROM_BITMAP_COMPRESSED;
+ else if (atoi(w2) == 1)
+ map_read_flag = READ_FROM_BITMAP;
+ else
+ map_read_flag = READ_FROM_GAT;
+ }else if(strcmpi(w1,"map_cache_file")==0){
+ strncpy(map_cache_file,w2,255);
} else if (strcmpi(w1, "import") == 0) {
map_config_read(w2);
} else if (strcmpi(w1, "console") == 0) {
- if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 )
+ if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 ) {
console = 1;
+ ShowNotice("Console Commands is enabled.\n");
+ }
} else if(strcmpi(w1,"imalive_on")==0){ //Added by Mugendai for I'm Alive mod
imalive_on = atoi(w2); //Added by Mugendai for I'm Alive mod
} else if(strcmpi(w1,"imalive_time")==0){ //Added by Mugendai for I'm Alive mod
@@ -1883,82 +2905,7 @@ int map_config_read(char *cfgName) {
return 0;
}
-#ifndef TXT_ONLY
-/*=======================================
- * MySQL Init
- *---------------------------------------
- */
-
-int map_sql_init(void){
-
- mysql_init(&mmysql_handle);
-
- //DB connection start
- printf("Connect Map DB Server....\n");
- if(!mysql_real_connect(&mmysql_handle, map_server_ip, map_server_id, map_server_pw,
- map_server_db ,map_server_port, (char *)NULL, 0)) {
- //pointer check
- printf("%s\n",mysql_error(&mmysql_handle));
- exit(1);
- }
- else {
- printf ("connect success! (Map Server Connection)\n");
- }
-
- mysql_init(&lmysql_handle);
-
- //DB connection start
- printf("Connect Login DB Server....\n");
- if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw,
- login_server_db ,login_server_port, (char *)NULL, 0)) {
- //pointer check
- printf("%s\n",mysql_error(&lmysql_handle));
- exit(1);
- }
- else {
- printf ("connect success! (Login Server Connection)\n");
- }
-
- if(battle_config.mail_system) { // mail system [Valaris]
- mysql_init(&mail_handle);
- if(!mysql_real_connect(&mail_handle, map_server_ip, map_server_id, map_server_pw,
- map_server_db ,map_server_port, (char *)NULL, 0)) {
- printf("%s\n",mysql_error(&mail_handle));
- exit(1);
- }
- }
-
- return 0;
-}
-
-int map_sql_close(void){
- mysql_close(&mmysql_handle);
- printf("Close Map DB Connection....\n");
-
- mysql_close(&lmysql_handle);
- printf("Close Login DB Connection....\n");
- return 0;
-}
-
-int log_sql_init(void){
-
- mysql_init(&mmysql_handle);
-
- //DB connection start
- printf("\033[1;29m[SQL]\033[0;0m: Connecting to Log Database \033[1;29m%s\033[0;0m At \033[1;29m%s\033[0;0m...\n",log_db,log_db_ip);
- if(!mysql_real_connect(&mmysql_handle, log_db_ip, log_db_id, log_db_pw,
- log_db ,log_db_port, (char *)NULL, 0)) {
- //pointer check
- printf("\033[1;29m[SQL Error]\033[0;0m: %s\n",mysql_error(&mmysql_handle));
- exit(1);
- } else {
- printf("\033[1;29m[SQL]\033[0;0m: Successfully \033[1;32mconnected\033[0;0m to Database \033[1;29m%s\033[0;0m.\n", log_db);
- }
-
- return 0;
-}
-
-int sql_config_read(char *cfgName)
+int inter_config_read(char *cfgName)
{
int i;
char line[1024],w1[1024],w2[1024];
@@ -1966,7 +2913,8 @@ int sql_config_read(char *cfgName)
fp=fopen(cfgName,"r");
if(fp==NULL){
- printf("file not found: %s\n",cfgName);
+ snprintf(tmp_output,sizeof(tmp_output),"File not found: '%s'.\n",cfgName);
+ ShowError(tmp_output);
return 1;
}
while(fgets(line,1020,fp)){
@@ -1975,7 +2923,11 @@ int sql_config_read(char *cfgName)
i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
if(i!=2)
continue;
- if(strcmpi(w1,"item_db_db")==0){
+ //support the import command, just like any other config
+ if(strcmpi(w1,"import")==0){
+ inter_config_read(w2);
+ #ifndef TXT_ONLY
+ } else if(strcmpi(w1,"item_db_db")==0){
strcpy(item_db_db,w2);
} else if(strcmpi(w1,"mob_db_db")==0){
strcpy(mob_db_db,w2);
@@ -1996,45 +2948,32 @@ int sql_config_read(char *cfgName)
//Map Server SQL DB
} else if(strcmpi(w1,"map_server_ip")==0){
strcpy(map_server_ip, w2);
- printf ("set map_server_ip : %s\n",w2);
} else if(strcmpi(w1,"map_server_port")==0){
map_server_port=atoi(w2);
- printf ("set map_server_port : %s\n",w2);
} else if(strcmpi(w1,"map_server_id")==0){
strcpy(map_server_id, w2);
- printf ("set map_server_id : %s\n",w2);
} else if(strcmpi(w1,"map_server_pw")==0){
strcpy(map_server_pw, w2);
- printf ("set map_server_pw : %s\n",w2);
} else if(strcmpi(w1,"map_server_db")==0){
strcpy(map_server_db, w2);
- printf ("set map_server_db : %s\n",w2);
- //Map server option to use SQL db or not
} else if(strcmpi(w1,"use_sql_db")==0){
- if (strcmpi(w2,"yes")){db_use_sqldbs=0;} else if (strcmpi(w2,"no")){db_use_sqldbs=1;}
+ db_use_sqldbs = battle_config_switch(w2);
printf ("Using SQL dbs: %s\n",w2);
//Login Server SQL DB
} else if(strcmpi(w1,"login_server_ip")==0){
strcpy(login_server_ip, w2);
- printf ("set login_server_ip : %s\n",w2);
} else if(strcmpi(w1,"login_server_port")==0){
login_server_port = atoi(w2);
- printf ("set login_server_port : %s\n",w2);
} else if(strcmpi(w1,"login_server_id")==0){
strcpy(login_server_id, w2);
- printf ("set login_server_id : %s\n",w2);
} else if(strcmpi(w1,"login_server_pw")==0){
strcpy(login_server_pw, w2);
- printf ("set login_server_pw : %s\n",w2);
} else if(strcmpi(w1,"login_server_db")==0){
strcpy(login_server_db, w2);
- printf ("set login_server_db : %s\n",w2);
} else if(strcmpi(w1,"lowest_gm_level")==0){
lowest_gm_level = atoi(w2);
- printf ("set lowest_gm_level : %s\n",w2);
} else if(strcmpi(w1,"read_gm_interval")==0){
read_gm_interval = ( atoi(w2) * 60 * 1000 ); // Minutes multiplied by 60 secs per min by 1000 milliseconds per second
- printf ("set read_gm_interval : %s\n",w2);
} else if(strcmpi(w1,"log_db")==0) {
strcpy(log_db, w2);
} else if(strcmpi(w1,"log_db_ip")==0) {
@@ -2047,9 +2986,7 @@ int sql_config_read(char *cfgName)
strcpy(log_db_pw, w2);
} else if(strcmpi(w1,"log_db_port")==0) {
log_db_port = atoi(w2);
- //support the import command, just like any other config
- } else if(strcmpi(w1,"import")==0){
- sql_config_read(w2);
+ #endif
}
}
fclose(fp);
@@ -2057,63 +2994,100 @@ int sql_config_read(char *cfgName)
return 0;
}
-// sql online status checking [Valaris]
-void char_offline(struct map_session_data *sd)
-{
- if(sd && sd->status.char_id) {
- sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `char_id`='%d'", char_db, sd->status.char_id);
- if(mysql_query(&mmysql_handle, tmp_sql) ) {
- printf("DB server Error (update online `%s`)- %s\n", char_db, mysql_error(&mmysql_handle) );
- }
+#ifndef TXT_ONLY
+/*=======================================
+ * MySQL Init
+ *---------------------------------------
+ */
+
+int map_sql_init(void){
+
+ mysql_init(&mmysql_handle);
+
+ //DB connection start
+ printf("Connect Map DB Server....\n");
+ if(!mysql_real_connect(&mmysql_handle, map_server_ip, map_server_id, map_server_pw,
+ map_server_db ,map_server_port, (char *)NULL, 0)) {
+ //pointer check
+ printf("%s\n",mysql_error(&mmysql_handle));
+ exit(1);
+ }
+ else {
+ printf ("connect success! (Map Server Connection)\n");
}
-}
-void do_reset_online(void)
-{
- sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `online`='1'", char_db);
- if(mysql_query(&mmysql_handle, tmp_sql) ) {
- printf("DB server Error (reset_online `%s`)- %s\n", char_db, mysql_error(&mmysql_handle) );
+ mysql_init(&lmysql_handle);
+
+ //DB connection start
+ printf("Connect Login DB Server....\n");
+ if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw,
+ login_server_db ,login_server_port, (char *)NULL, 0)) {
+ //pointer check
+ printf("%s\n",mysql_error(&lmysql_handle));
+ exit(1);
+ }
+ else {
+ printf ("connect success! (Login Server Connection)\n");
+ }
+
+ if(battle_config.mail_system) { // mail system [Valaris]
+ mysql_init(&mail_handle);
+ if(!mysql_real_connect(&mail_handle, map_server_ip, map_server_id, map_server_pw,
+ map_server_db ,map_server_port, (char *)NULL, 0)) {
+ printf("%s\n",mysql_error(&mail_handle));
+ exit(1);
+ }
}
+
+ return 0;
}
-int online_timer(int tid,unsigned int tick,int id,int data)
-{
- if(check_online_timer != tid)
- return 0;
+int map_sql_close(void){
+ mysql_close(&mmysql_handle);
+ printf("Close Map DB Connection....\n");
- char_online_check();
+ mysql_close(&lmysql_handle);
+ printf("Close Login DB Connection....\n");
+ return 0;
+}
+
+int log_sql_init(void){
+
+ mysql_init(&mmysql_handle);
- check_online_timer=add_timer(gettick()+CHECK_INTERVAL,online_timer,0,0);
+ //DB connection start
+ printf(""CL_WHITE"[SQL]"CL_RESET": Connecting to Log Database "CL_WHITE"%s"CL_RESET" At "CL_WHITE"%s"CL_RESET"...\n",log_db,log_db_ip);
+ if(!mysql_real_connect(&mmysql_handle, log_db_ip, log_db_id, log_db_pw,
+ log_db ,log_db_port, (char *)NULL, 0)) {
+ //pointer check
+ printf(""CL_WHITE"[SQL Error]"CL_RESET": %s\n",mysql_error(&mmysql_handle));
+ exit(1);
+ } else {
+ printf(""CL_WHITE"[SQL]"CL_RESET": Successfully '"CL_GREEN"connected"CL_RESET"' to Database '"CL_WHITE"%s"CL_RESET"'.\n", log_db);
+ }
return 0;
}
+int online_timer (int tid,unsigned int tick,int id,int data)
+{
+ char_online_check();
+ return 0;
+}
void char_online_check(void)
{
int i;
- struct map_session_data *sd=NULL;
-
- do_reset_online();
+ struct map_session_data *sd;
- for(i=0;i<fd_max;i++){
- if (session[i] && (sd = session[i]->session_data) && sd && sd->state.auth &&
- !(battle_config.hide_GM_session && pc_isGM(sd)))
- if(sd->status.char_id) {
- sprintf(tmp_sql,"UPDATE `%s` SET `online`='1' WHERE `char_id`='%d'", char_db, sd->status.char_id);
- if(mysql_query(&mmysql_handle, tmp_sql) ) {
- printf("DB server Error (update online `%s`)- %s\n", char_db, mysql_error(&mmysql_handle) );
- }
- }
- }
+ chrif_char_reset_offline();
-
- if(check_online_timer && check_online_timer != -1) {
- delete_timer(check_online_timer,online_timer);
- add_timer(gettick()+CHECK_INTERVAL,online_timer,0,0);
+ for (i = 0; i < fd_max; i++) {
+ if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd->state.auth &&
+ !(battle_config.hide_GM_session && pc_isGM(sd)))
+ if(sd->status.char_id)
+ chrif_char_online(sd);
}
-
}
-
#endif /* not TXT_ONLY */
//-----------------------------------------------------
@@ -2135,23 +3109,32 @@ int flush_timer(int tid, unsigned int tick, int id, int data){
return 0;
}
-int id_db_final(void *k,void *d,va_list ap){ return 0; }
-int map_db_final(void *k,void *d,va_list ap){ return 0; }
-int nick_db_final(void *k,void *d,va_list ap){ return 0; }
-int charid_db_final(void *k,void *d,va_list ap){ return 0; }
-
-static int cleanup_sub(struct block_list *bl, va_list ap) {
+int id_db_final(void *k,void *d,va_list ap) { return 0; }
+int map_db_final(void *k,void *d,va_list ap) { return 0; }
+int nick_db_final(void *k,void *d,va_list ap)
+{
+ char *p = (char *) d;
+ if (p) aFree(p);
+ return 0;
+}
+int charid_db_final(void *k,void *d,va_list ap)
+{
+ struct charid2nick *p = (struct charid2nick *) d;
+ if (p) aFree(p);
+ return 0;
+}
+int cleanup_sub(struct block_list *bl, va_list ap) {
nullpo_retr(0, bl);
switch(bl->type) {
case BL_PC:
- map_delblock(bl); // There is something better...
+ map_quit((struct map_session_data *) bl);
break;
case BL_NPC:
- npc_delete((struct npc_data *)bl);
+ npc_unload((struct npc_data *)bl);
break;
case BL_MOB:
- mob_delete((struct mob_data *)bl);
+ mob_unload((struct mob_data *)bl);
break;
case BL_PET:
pet_remove_map((struct map_session_data *)bl);
@@ -2168,47 +3151,100 @@ static int cleanup_sub(struct block_list *bl, va_list ap) {
}
/*==========================================
- * map鯖終了時処理
+ * map鯖終了時?理
*------------------------------------------
*/
void do_final(void) {
- int map_id, i;
+ int i;
+ ShowStatus("Terminating...\n");
- for (map_id = 0; map_id < map_num;map_id++) {
- if(map[map_id].m)
- map_foreachinarea(cleanup_sub, map_id, 0, 0, map[map_id].xs, map[map_id].ys, 0, 0);
- }
+ for (i = 0; i < map_num; i++)
+ if(map[i].m)
+ map_foreachinarea(cleanup_sub, i, 0, 0, map[i].xs, map[i].ys, 0, 0);
- for (i = 0; i < fd_max; i++)
- delete_session(i);
+#ifndef TXT_ONLY
+ chrif_char_reset_offline();
+#endif
- map_removenpc();
- timer_final();
+ chrif_flush_fifo();
+
+//#if 0 // why is this here? >_>
+ do_final_chrif(); // この内部でキャラを全て切断する
+ do_final_npc();
+// map_removenpc();
+ do_final_script();
+ do_final_itemdb();
+ do_final_storage();
+ do_final_guild();
+ do_final_party();
+ do_final_pc();
+ do_final_pet();
+ do_final_msg();
+
+ for (i=0; i<map_num; i++) {
+ if(map[i].gat) aFree(map[i].gat);
+ if(map[i].block) aFree(map[i].block);
+ if(map[i].block_mob) aFree(map[i].block_mob);
+ if(map[i].block_count) aFree(map[i].block_count);
+ if(map[i].block_mob_count) aFree(map[i].block_mob_count);
+ }
+// do_final_timer(); (we used timer_final() instead)
+ timer_final();
numdb_final(id_db, id_db_final);
- strdb_final(map_db, map_db_final);
+ strdb_final(map_db, map_db_final);
strdb_final(nick_db, nick_db_final);
numdb_final(charid_db, charid_db_final);
+ exit_dbn();
+
+//#endif
- for(i=0;i<=map_num;i++){
- if(map[i].gat) free(map[i].gat);
- if(map[i].block) free(map[i].block);
- if(map[i].block_mob) free(map[i].block_mob);
- if(map[i].block_count) free(map[i].block_count);
- if(map[i].block_mob_count) free(map[i].block_mob_count);
- }
- do_final_script();
- do_final_itemdb();
- do_final_storage();
- do_final_guild();
#ifndef TXT_ONLY
- do_reset_online();
map_sql_close();
#endif /* not TXT_ONLY */
+ ShowStatus("Successfully terminated.\n");
}
-void map_helpscreen() {
- exit(1);
+/*======================================================
+ * Map-Server Version Screen [MC Cameri]
+ *------------------------------------------------------
+ */
+void map_helpscreen(int flag) { // by MC Cameri
+ puts("Usage: map-server [options]");
+ puts("Options:");
+ puts(CL_WHITE" Commands\t\t\tDescription"CL_RESET);
+ puts("-----------------------------------------------------------------------------");
+ puts(" --help, --h, --?, /? Displays this help screen");
+ puts(" --map-config <file> Load map-server configuration from <file>");
+ puts(" --battle-config <file> Load battle configuration from <file>");
+ puts(" --atcommand-config <file> Load atcommand configuration from <file>");
+ puts(" --charcommand-config <file> Load charcommand configuration from <file>");
+ puts(" --script-config <file> Load script configuration from <file>");
+ puts(" --msg-config <file> Load message configuration from <file>");
+ puts(" --grf-path-file <file> Load grf path file configuration from <file>");
+ puts(" --sql-config <file> Load inter-server configuration from <file>");
+ puts(" (SQL Only)");
+ puts(" --log-config <file> Load logging configuration from <file>");
+ puts(" (SQL Only)");
+ puts(" --version, --v, -v, /v Displays the server's version");
+ puts("\n");
+ if (flag) exit(1);
+}
+
+/*======================================================
+ * Map-Server Version Screen [MC Cameri]
+ *------------------------------------------------------
+ */
+void map_versionscreen(int flag) {
+ printf("CL_WHITE" "eAthena version %d.%02d.%02d, Athena Mod version %d" CL_RESET"\n",
+ ATHENA_MAJOR_VERSION, ATHENA_MINOR_VERSION, ATHENA_REVISION,
+ ATHENA_MOD_VERSION);
+ puts(CL_GREEN "Website/Forum:" CL_RESET "\thttp://eathena.deltaanime.net/");
+ puts(CL_GREEN "Download URL:" CL_RESET "\thttp://eathena.systeminplace.net/");
+ puts(CL_GREEN "IRC Channel:" CL_RESET "\tirc://irc.deltaanime.net/#athena");
+ puts("\nOpen " CL_WHITE "readme.html" CL_RESET " for more information.");
+ if (ATHENA_RELEASE_FLAG) ShowNotice("This version is not for release.\n");
+ if (flag) exit(1);
}
/*======================================================
@@ -2220,42 +3256,52 @@ int do_init(int argc, char *argv[]) {
FILE *data_conf;
char line[1024], w1[1024], w2[1024];
-#ifndef TXT_ONLY
- unsigned char *SQL_CONF_NAME="conf/inter_athena.conf";
- unsigned char *LOG_CONF_NAME="conf/log_athena.conf";
+ SERVER_TYPE = SERVER_MAP;
+#ifdef GCOLLECT
+ GC_enable_incremental();
#endif
- unsigned char *MAP_CONF_NAME = "conf/map_athena.conf";
- unsigned char *BATTLE_CONF_FILENAME = "conf/battle_athena.conf";
- unsigned char *ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf";
- unsigned char *CHARCOMMAND_CONF_FILENAME = "conf/charcommand_athena.conf";
- unsigned char *SCRIPT_CONF_NAME = "conf/script_athena.conf";
- unsigned char *MSG_CONF_NAME = "conf/msg_athena.conf";
- unsigned char *GRF_PATH_FILENAME = "conf/grf-files.txt";
+
+ INTER_CONF_NAME="conf/inter_athena.conf";
+ LOG_CONF_NAME="conf/log_athena.conf";
+ MAP_CONF_NAME = "conf/map_athena.conf";
+ BATTLE_CONF_FILENAME = "conf/battle_athena.conf";
+ ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf";
+ CHARCOMMAND_CONF_FILENAME = "conf/charcommand_athena.conf";
+ SCRIPT_CONF_NAME = "conf/script_athena.conf";
+ MSG_CONF_NAME = "conf/msg_athena.conf";
+ GRF_PATH_FILENAME = "conf/grf-files.txt";
+
+ chrif_connected = 0;
srand(gettick());
for (i = 1; i < argc ; i++) {
-
if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "--h") == 0 || strcmp(argv[i], "--?") == 0 || strcmp(argv[i], "/?") == 0)
- map_helpscreen();
- else if (strcmp(argv[i], "--map_config") == 0)
+ map_helpscreen(1);
+ if (strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "--v") == 0 || strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "/v") == 0)
+ map_versionscreen(1);
+ else if (strcmp(argv[i], "--map_config") == 0 || strcmp(argv[i], "--map-config") == 0)
MAP_CONF_NAME=argv[i+1];
- else if (strcmp(argv[i],"--battle_config") == 0)
+ else if (strcmp(argv[i],"--battle_config") == 0 || strcmp(argv[i],"--battle-config") == 0)
BATTLE_CONF_FILENAME = argv[i+1];
- else if (strcmp(argv[i],"--atcommand_config") == 0)
+ else if (strcmp(argv[i],"--atcommand_config") == 0 || strcmp(argv[i],"--atcommand-config") == 0)
ATCOMMAND_CONF_FILENAME = argv[i+1];
- else if (strcmp(argv[i],"--charcommand_config") == 0)
+ else if (strcmp(argv[i],"--charcommand_config") == 0 || strcmp(argv[i],"--charcommand-config") == 0)
CHARCOMMAND_CONF_FILENAME = argv[i+1];
- else if (strcmp(argv[i],"--script_config") == 0)
+ else if (strcmp(argv[i],"--script_config") == 0 || strcmp(argv[i],"--script-config") == 0)
SCRIPT_CONF_NAME = argv[i+1];
- else if (strcmp(argv[i],"--msg_config") == 0)
+ else if (strcmp(argv[i],"--msg_config") == 0 || strcmp(argv[i],"--msg-config") == 0)
MSG_CONF_NAME = argv[i+1];
- else if (strcmp(argv[i],"--grf_path_file") == 0)
+ else if (strcmp(argv[i],"--grf_path_file") == 0 || strcmp(argv[i],"--grf-path-file") == 0)
GRF_PATH_FILENAME = argv[i+1];
#ifndef TXT_ONLY
- else if (strcmp(argv[i],"--sql_config") == 0)
- SQL_CONF_NAME = argv[i+1];
+ else if (strcmp(argv[i],"--inter_config") == 0 || strcmp(argv[i],"--inter-config") == 0)
+ INTER_CONF_NAME = argv[i+1];
#endif /* not TXT_ONLY */
+ else if (strcmp(argv[i],"--log_config") == 0 || strcmp(argv[i],"--log-config") == 0)
+ LOG_CONF_NAME = argv[i+1];
+ else if (strcmp(argv[i],"--run_once") == 0) // close the map-server as soon as its done.. for testing [Celest]
+ runflag = 0;
}
map_config_read(MAP_CONF_NAME);
@@ -2285,16 +3331,14 @@ int do_init(int argc, char *argv[]) {
if (ptr[0] == 192 && ptr[1] == 168)
printf("\nFirewall detected.. \n edit lan_support.conf and map_athena.conf\n\n");
}
-
+ if (SHOW_DEBUG_MSG) ShowNotice("Server running in '"CL_WHITE"Debug Mode"CL_RESET"'.\n");
battle_config_read(BATTLE_CONF_FILENAME);
msg_config_read(MSG_CONF_NAME);
atcommand_config_read(ATCOMMAND_CONF_FILENAME);
charcommand_config_read(CHARCOMMAND_CONF_FILENAME);
script_config_read(SCRIPT_CONF_NAME);
-#ifndef TXT_ONLY
- sql_config_read(SQL_CONF_NAME);
+ inter_config_read(INTER_CONF_NAME);
log_config_read(LOG_CONF_NAME);
-#endif /* not TXT_ONLY */
atexit(do_final);
@@ -2323,45 +3367,48 @@ int do_init(int argc, char *argv[]) {
map_readallmap();
+ add_timer_func_list(map_freeblock_timer,"map_freeblock_timer");
add_timer_func_list(map_clearflooritem_timer, "map_clearflooritem_timer");
+ add_timer_interval(gettick()+1000,map_freeblock_timer,0,0,60*1000);
//Added by Mugendai for GUI support
if (flush_on)
- {
add_timer_interval(gettick()+10, flush_timer,0,0,flush_time);
- }
+ //Added for Mugendais I'm Alive mod
+ if (imalive_on)
+ add_timer_interval(gettick()+10, imalive_timer,0,0,imalive_time*1000);
#ifndef TXT_ONLY // online status timer, checks every hour [Valaris]
add_timer_func_list(online_timer, "online_timer");
- check_online_timer=add_timer(gettick()+CHECK_INTERVAL,online_timer,0,0);
+ add_timer_interval(gettick()+10, online_timer, 0, 0, CHECK_INTERVAL);
#endif /* not TXT_ONLY */
do_init_chrif();
do_init_clif();
do_init_itemdb();
- do_init_mob(); // npcの初期化時内でmob_spawnして、mob_dbを参照するのでinit_npcより先
+ do_init_mob(); // npcの初期化時?でmob_spawnして、mob_dbを?照するのでinit_npcより先
do_init_script();
- do_init_npc();
do_init_pc();
+ do_init_status();
do_init_party();
do_init_guild();
do_init_storage();
do_init_skill();
do_init_pet();
+ do_init_npc();
#ifndef TXT_ONLY /* mail system [Valaris] */
if(battle_config.mail_system)
do_init_mail();
- if (log_config.branch || log_config.drop || log_config.mvpdrop ||
- log_config.present || log_config.produce || log_config.refine ||
- log_config.trade)
+ if (log_config.sql_logs && (log_config.branch || log_config.drop || log_config.mvpdrop ||
+ log_config.present || log_config.produce || log_config.refine || log_config.trade))
{
log_sql_init();
}
#endif /* not TXT_ONLY */
- npc_event_do_oninit(); // npcのOnInitイベント実行
+ npc_event_do_oninit(); // npcのOnInitイベント?行
if ( console ) {
set_defaultconsoleparse(parse_console);
@@ -2369,15 +3416,22 @@ int do_init(int argc, char *argv[]) {
}
if (battle_config.pk_mode == 1)
- printf("The server is running in \033[1;31mPK Mode\033[0m.\n");
-
- //Added for Mugendais I'm Alive mod
- if (imalive_on)
- add_timer_interval(gettick()+10, imalive_timer,0,0,imalive_time*1000);
-
- printf("The map-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n", map_port);
- ticks = gettick();
+ ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n");
+ sprintf(tmp_output,"Server is '"CL_GREEN"ready"CL_RESET"' and listening on port '"CL_WHITE"%d"CL_RESET"'.\n\n", map_port);
+ ShowStatus(tmp_output);
return 0;
}
+
+int compare_item(struct item *a, struct item *b) {
+ return (
+ (a->nameid == b->nameid) &&
+ (a->identify == b->identify) &&
+ (a->refine == b->refine) &&
+ (a->attribute == b->attribute) &&
+ (a->card[0] == b->card[0]) &&
+ (a->card[1] == b->card[1]) &&
+ (a->card[2] == b->card[2]) &&
+ (a->card[3] == b->card[3]));
+}
diff --git a/src/map/map.h b/src/map/map.h
index bf443bf46..01d9fef0e 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -10,7 +10,7 @@
#define PC_CLASS_BASE2 (PC_CLASS_BASE + 4001)
#define PC_CLASS_BASE3 (PC_CLASS_BASE2 + 22)
#define MAX_NPC_PER_MAP 512
-#define BLOCK_SIZE 8
+#define BLOCK_SIZE 8 // Never zero
#define AREA_SIZE battle_config.area_size
#define LOCAL_REG_NUM 16
#define LIFETIME_FLOORITEM 60
@@ -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
@@ -32,6 +32,7 @@
#define MAX_WALKPATH 32
#define MAX_DROP_PER_MAP 48
#define MAX_IGNORE_LIST 80
+#define MAX_VENDING 12
#define DEFAULT_AUTOSAVE_INTERVAL 60*1000
@@ -52,6 +53,12 @@ struct walkpath_data {
unsigned char path_len,path_pos,path_half;
unsigned char path[MAX_WALKPATH];
};
+struct shootpath_data {
+ int rx,ry,len;
+ int x[MAX_WALKPATH];
+ int y[MAX_WALKPATH];
+};
+
struct script_reg {
int index;
int data;
@@ -84,13 +91,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;
@@ -99,7 +106,7 @@ struct skill_unit_group {
};
struct skill_unit_group_tickset {
unsigned int tick;
- int group_id;
+ int id;
};
struct skill_timerskill {
int timer;
@@ -137,6 +144,12 @@ struct map_session_data {
unsigned make_arrow_flag : 1;
unsigned potionpitcher_flag : 1;
unsigned storage_flag : 1;
+ unsigned snovice_flag : 4;
+ int gmaster_flag;
+ // originally by Qamera, adapted by celest
+ unsigned event_death : 1;
+ unsigned event_kill : 1;
+ unsigned event_disconnect : 1;
} state;
struct {
unsigned killer : 1;
@@ -149,15 +162,14 @@ struct map_session_data {
unsigned no_weapon_damage : 1;
unsigned no_gemstone : 1;
unsigned infinite_endure : 1;
- unsigned unbreakable_weapon : 1;
- unsigned unbreakable_armor : 1;
- unsigned infinite_autospell : 1;
} special_state;
int char_id, login_id1, login_id2, sex;
int packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
struct mmo_charstatus status;
struct item_data *inventory_data[MAX_INVENTORY];
short equip_index[11];
+ unsigned short unbreakable_equip;
+ unsigned short unbreakable; // chance to prevent equipment breaking [celest]
int weight,max_weight;
int cart_weight,cart_max_weight,cart_num,cart_max_num;
char mapname[24];
@@ -169,6 +181,7 @@ struct map_session_data {
unsigned int client_tick,server_tick;
struct walkpath_data walkpath;
int walktimer;
+ int next_walktime;
int npc_id,areanpc_id,npc_shopid;
int npc_pos;
int npc_menu;
@@ -178,6 +191,7 @@ struct map_session_data {
char *npc_stackbuf;
char npc_str[256];
unsigned int chatID;
+ unsigned long idletime;
struct{
char name[24];
@@ -192,6 +206,8 @@ struct map_session_data {
int followtimer; // [MouseJstr]
int followtarget;
+ time_t emotionlasttime; // to limit flood with emotion packets
+
short attackrange,attackrange_;
int skilltimer;
int skilltarget;
@@ -203,17 +219,21 @@ struct map_session_data {
struct skill_unit_group skillunit[MAX_SKILLUNITGROUP];
struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET];
struct skill_timerskill skilltimerskill[MAX_SKILLTIMERSKILL];
- int cloneskill_id,cloneskill_lv;
+ char blockskill[MAX_SKILL]; // [celest]
+ //unsigned int skillstatictimer[MAX_SKILL];
+ unsigned short timerskill_count; // [celest]
+ int cloneskill_id;
int potion_hp,potion_sp,potion_per_hp,potion_per_sp;
int invincible_timer;
unsigned int canact_tick;
unsigned int canmove_tick;
unsigned int canlog_tick;
+ unsigned int canregen_tick;
int hp_sub,sp_sub;
int inchealhptick,inchealsptick,inchealspirithptick,inchealspiritsptick;
// -- moonsoul (new tick for berserk self-damage)
- int berserkdamagetick;
+// int berserkdamagetick;
int fame;
short view_class;
@@ -224,12 +244,13 @@ struct map_session_data {
int watk,watk2,atkmods[3];
int def,def2,mdef,mdef2,critical,matk1,matk2;
int atk_ele,def_ele,star,overrefine;
- int castrate,hprate,sprate,dsprate;
+ int castrate,delayrate,hprate,sprate,dsprate;
int addele[10],addrace[12],addsize[3],subele[10],subrace[12];
int addeff[10],addeff2[10],reseff[10];
int watk_,watk_2,atkmods_[3],addele_[10],addrace_[12],addsize_[3]; //二刀流のために追加
int atk_ele_,star_,overrefine_; //二刀流のために追加
int base_atk,atk_rate;
+ int weapon_atk[16],weapon_atk_rate[16];
int arrow_atk,arrow_ele,arrow_cri,arrow_hit,arrow_range;
int arrow_addele[10],arrow_addrace[12],arrow_addsize[3],arrow_addeff[10],arrow_addeff2[10];
int nhealhp,nhealsp,nshealhp,nshealsp,nsshealhp,nsshealsp;
@@ -258,18 +279,42 @@ struct map_session_data {
short hp_drain_value,sp_drain_value,hp_drain_value_,sp_drain_value_;
int short_weapon_damage_return,long_weapon_damage_return;
int weapon_coma_ele[10],weapon_coma_race[12];
- short break_weapon_rate,break_armor_rate;
+ int break_weapon_rate,break_armor_rate;
short add_steal_rate;
+ //--- 02/15's new card effects [celest]
+ int crit_atk_rate;
+ int critaddrace[12];
+ short no_regen;
+ int addeff3[10];
+ short addeff3_type[10];
+ short autospell2_id,autospell2_lv,autospell2_rate,autospell2_type;
+ int skillatk[2];
+ unsigned short unstripable_equip;
+ short add_damage_classid2[10],add_damage_class_count2;
+ int add_damage_classrate2[10];
+ short sp_gain_value, hp_gain_value;
+ short sp_drain_type;
+ short ignore_def_mob, ignore_def_mob_;
+ int hp_loss_tick, hp_loss_rate;
+ short hp_loss_value, hp_loss_type;
+ int addrace2[12],addrace2_[12];
+ int subsize[3];
+ short unequip_losehp[11];
+ short unequip_losesp[11];
+ int itemid;
+ int itemhealrate[7];
+ //--- 03/15's new card effects
+ int expaddrace[12];
+ int subrace2[12];
+ short sp_gain_race[12];
short spiritball, spiritball_old;
int spirit_timer[MAX_SKILL_LEVEL];
int magic_damage_return; // AppleGirl Was Here
int random_attack_increase_add,random_attack_increase_per; // [Valaris]
int perfect_hiding; // [Valaris]
- int unbreakable;
int classchange; // [Valaris]
-
int die_counter;
short doridori_counter;
@@ -299,7 +344,7 @@ struct map_session_data {
int vender_id;
int vend_num;
char message[80];
- struct vending vending[12];
+ struct vending vending[MAX_VENDING];
int catch_target_class;
struct s_pet pet;
@@ -311,11 +356,15 @@ struct map_session_data {
char eventqueue[MAX_EVENTQUEUE][50];
int eventtimer[MAX_EVENTTIMER];
+ unsigned short eventcount; // [celest]
int last_skillid,last_skilllv; // Added by RoVeRT
- short sg_count;
unsigned char change_level; // [celest]
+ int autoloot; //by Upa-Kun
+ unsigned nodelay :1;
+ unsigned noexp :1;
+ unsigned detach :1;
#ifndef TXT_ONLY
int mail_counter; // mail counter for mail system [Valaris]
@@ -336,7 +385,7 @@ struct npc_item_list {
struct npc_data {
struct block_list bl;
short n;
- short class,dir;
+ short class_,dir;
short speed;
char name[24];
char exname[24];
@@ -360,7 +409,7 @@ struct npc_data {
char *script;
short xs,ys;
int guild_id;
- int timer,timerid,timeramount,nexttimer;
+ int timer,timerid,timeramount,nexttimer,rid;
unsigned int timertick;
struct npc_timerevent_list *timer_event;
int label_list_num;
@@ -379,11 +428,13 @@ struct npc_data {
char eventqueue[MAX_EVENTQUEUE][50];
int eventtimer[MAX_EVENTTIMER];
short arenaflag;
+
+ void *chatdb;
};
struct mob_data {
struct block_list bl;
short n;
- short base_class,class,dir,mode,level;
+ short base_class,class_,dir,mode,level;
short m,x0,y0,xs,ys;
char name[24];
int spawndelay1,spawndelay2;
@@ -398,9 +449,12 @@ struct mob_data {
unsigned change_walk_target : 1;
unsigned walk_easy : 1;
unsigned special_mob_ai : 3;
+ unsigned soul_change_flag : 1; // Celest
+ int provoke_flag; // Celest
} state;
int timer;
short to_x,to_y;
+ short target_dir;
short speed;
int hp;
int target_id,attacked_id;
@@ -422,7 +476,6 @@ struct mob_data {
short sc_count;
short opt1,opt2,opt3,option;
short min_chase;
- short sg_count;
int guild_id;
int deletetimer;
@@ -438,18 +491,22 @@ struct mob_data {
struct skill_unit_group skillunit[MAX_MOBSKILLUNITGROUP];
struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET];
char npc_event[50];
- short size;
+ unsigned char size;
+ short recall_flag;
+ int recallmob_count;
+ short recallcount;
};
struct pet_data {
struct block_list bl;
short n;
- short class,dir;
+ short class_,dir;
short speed;
char name[24];
struct {
unsigned state : 8 ;
unsigned skillstate : 8 ;
unsigned change_walk_target : 1 ;
+ short skillbonus;
} state;
int timer;
short to_x,to_y;
@@ -460,7 +517,8 @@ struct pet_data {
int move_fail_count;
unsigned int attackabletime,next_walktime,last_thinktime;
int skilltype,skillval,skilltimer,skillduration; // [Valaris]
- int skillbonustype,skillbonusval,skillbonustimer,skillbonusduration; // [Valaris]
+ //int skillbonustype,skillbonusval,skillbonustimer,skillbonusduration; // [Valaris]
+ int skillbonustype,skillbonusval,skillbonustimer;
struct item *lootitem;
short loot; // [Valaris]
short lootmax; // [Valaris]
@@ -479,10 +537,18 @@ enum { NONE_ATTACKABLE,ATTACKABLE };
enum { ATK_LUCKY=1,ATK_FLEE,ATK_DEF}; // 囲まれペナルティ計算用
+// 装備コード
+enum {
+ EQP_WEAPON = 0x0002, // 右手
+ EQP_ARMOR = 0x0010, // 体
+ EQP_SHIELD = 0x0020, // 左手
+ EQP_HELM = 0x0100, // 頭上段
+};
+
struct map_data {
char name[24];
- char alias[24]; // [MouseJstr]
unsigned char *gat; // NULLなら下のmap_data_other_serverとして扱う
+ char *alias; // [MouseJstr]
struct block_list **block;
struct block_list **block_mob;
int *block_count,*block_mob_count;
@@ -535,9 +601,8 @@ struct map_data_other_server {
unsigned char *gat; // NULL固定にして判断
unsigned long ip;
unsigned int port;
+ struct map_data* map;
};
-#define read_gat(m,x,y) (map[m].gat[(x)+(y)*map[m].xs])
-#define read_gatp(m,x,y) (m->gat[(x)+(y)*m->xs])
struct flooritem_data {
struct block_list bl;
@@ -556,7 +621,7 @@ enum {
SP_USTR,SP_UAGI,SP_UVIT,SP_UINT,SP_UDEX,SP_ULUK,SP_26,SP_27, // 32-39
SP_28,SP_ATK1,SP_ATK2,SP_MATK1,SP_MATK2,SP_DEF1,SP_DEF2,SP_MDEF1, // 40-47
SP_MDEF2,SP_HIT,SP_FLEE1,SP_FLEE2,SP_CRITICAL,SP_ASPD,SP_36,SP_JOBLEVEL, // 48-55
- SP_UPPER,SP_PARTNER,SP_CART,SP_FAME,SP_UNBREAKABLE, //56-58
+ SP_UPPER,SP_PARTNER,SP_CART,SP_FAME,SP_UNBREAKABLE, //56-60
SP_CARTINFO=99, // 99
SP_BASEJOB=119, // 100+19 - celest
@@ -584,15 +649,51 @@ enum {
SP_MAGIC_DAMAGE_RETURN,SP_RANDOM_ATTACK_INCREASE,SP_ALL_STATS,SP_AGI_VIT,SP_AGI_DEX_STR,SP_PERFECT_HIDE, // 1071-1076
SP_DISGUISE,SP_CLASSCHANGE, // 1077-1078
SP_HP_DRAIN_VALUE,SP_SP_DRAIN_VALUE, // 1079-1080
-
+ SP_WEAPON_ATK,SP_WEAPON_ATK_RATE, // 1081-1082
+ SP_DELAYRATE, // 1083
+
SP_RESTART_FULL_RECORVER=2000,SP_NO_CASTCANCEL,SP_NO_SIZEFIX,SP_NO_MAGIC_DAMAGE,SP_NO_WEAPON_DAMAGE,SP_NO_GEMSTONE, // 2000-2005
- SP_NO_CASTCANCEL2,SP_INFINITE_ENDURE,SP_UNBREAKABLE_WEAPON,SP_UNBREAKABLE_ARMOR // 2006-2009
+ SP_NO_CASTCANCEL2,SP_INFINITE_ENDURE,SP_UNBREAKABLE_WEAPON,SP_UNBREAKABLE_ARMOR, SP_UNBREAKABLE_HELM, // 2006-2010
+ SP_UNBREAKABLE_SHIELD, SP_LONG_ATK_RATE, // 2011-2012
+
+ SP_CRIT_ATK_RATE, SP_CRITICAL_ADDRACE, SP_NO_REGEN, SP_ADDEFF_WHENHIT, SP_AUTOSPELL_WHENHIT, // 2013-2017
+ SP_SKILL_ATK, SP_UNSTRIPABLE, SP_ADD_DAMAGE_BY_CLASS, // 2018-2020
+ SP_SP_GAIN_VALUE, SP_IGNORE_DEF_MOB, SP_HP_LOSS_RATE, SP_ADDRACE2, SP_HP_GAIN_VALUE, // 2021-2025
+ SP_SUBSIZE, SP_DAMAGE_WHEN_UNEQUIP, SP_ADD_ITEM_HEAL_RATE, SP_LOSESP_WHEN_UNEQUIP, SP_EXP_ADDRACE, // 2026-2030
+ SP_SP_GAIN_RACE, SP_SUBRACE2, SP_ADDEFF_WHENHIT_SHORT, // 2031-2033
+ SP_UNSTRIPABLE_WEAPON,SP_UNSTRIPABLE_ARMOR,SP_UNSTRIPABLE_HELM,SP_UNSTRIPABLE_SHIELD // 2034-2037
};
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セル
+#define CELL_MOONLIT 0x100
+#define CELL_REGEN 0x200
+/*
+ * map_getcell()で使用されるフラグ
+ */
+typedef enum {
+ 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()で使用されるフラグ
+enum {
+ CELL_SETNPC=0x10, // タッチタイプのNPCをセット
+ CELL_SETBASILICA, // バジリカをセット
+ CELL_CLRBASILICA, // バジリカをクリア
+};
+
struct chat_data {
struct block_list bl;
@@ -614,6 +715,17 @@ extern int autosave_interval;
extern int agit_flag;
extern int night_flag; // 0=day, 1=night [Yor]
+// gat?ヨァ
+int map_getcell(int,int,int,cell_t);
+int map_getcellp(struct map_data*,int,int,cell_t);
+void map_setcell(int,int,int,int);
+extern int map_read_flag; // 0: grfォユォ。ォ、ォ 1: ォュォ罩テォキォ 2: ォュォ罩テォキォ(?)
+enum {
+ READ_FROM_GAT, READ_FROM_AFM,
+ READ_FROM_BITMAP, CREATE_BITMAP,
+ READ_FROM_BITMAP_COMPRESSED, CREATE_BITMAP_COMPRESSED
+};
+
extern char motd_txt[];
extern char help_txt[];
@@ -635,9 +747,11 @@ void map_foreachinarea(int (*)(struct block_list*,va_list),int,int,int,int,int,i
// -- moonsoul (added map_foreachincell)
void map_foreachincell(int (*)(struct block_list*,va_list),int,int,int,int,...);
void map_foreachinmovearea(int (*)(struct block_list*,va_list),int,int,int,int,int,int,int,int,...);
+void map_foreachinpath(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int range,int type,...); // Celest
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(struct block_list *,int x,int y,int skill_id,struct skill_unit *);
// 一時的object関連
int map_addobject(struct block_list *);
int map_delobject(int);
@@ -659,6 +773,7 @@ void map_addchariddb(int charid,char *name);
void map_delchariddb(int charid);
int map_reqchariddb(struct map_session_data * sd,int charid);
char * map_charid2nick(int);
+struct map_session_data * map_charid2sd(int);
struct map_session_data * map_id2sd(int);
struct block_list * map_id2bl(int);
@@ -666,15 +781,13 @@ 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),...);
void map_addnickdb(struct map_session_data *);
struct map_session_data * map_nick2sd(char*);
-
-// gat関連
-int map_getcell(int,int,int);
-int map_setcell(int,int,int,int);
+int compare_item(struct item *a, struct item *b);
// その他
int map_check_dir(int s_dir,int t_dir);
@@ -682,18 +795,33 @@ int map_calc_dir( struct block_list *src,int x,int y);
// path.cより
int path_search(struct walkpath_data*,int,int,int,int,int,int);
+int path_search_long(struct shootpath_data *,int,int,int,int,int);
int path_blownpos(int m,int x0,int y0,int dx,int dy,int count);
int map_who(int fd);
+int cleanup_sub(struct block_list *bl, va_list ap);
+
void map_helpscreen(); // [Valaris]
int map_delmap(char *mapname);
-extern unsigned long ticks;
+extern char *INTER_CONF_NAME;
+extern char *LOG_CONF_NAME;
+extern char *MAP_CONF_NAME;
+extern char *BATTLE_CONF_FILENAME;
+extern char *ATCOMMAND_CONF_FILENAME;
+extern char *CHARCOMMAND_CONF_FILENAME;
+extern char *SCRIPT_CONF_NAME;
+extern char *MSG_CONF_NAME;
+extern char *GRF_PATH_FILENAME;
#ifndef TXT_ONLY
// MySQL
+#ifdef __WIN32
+#include <my_global.h>
+#include <my_sys.h>
+#endif
#include <mysql.h>
void char_online_check(void); // [Valaris]
diff --git a/src/map/mob.c b/src/map/mob.c
index ef67341f8..f076b7530 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -13,6 +13,7 @@
#include "clif.h"
#include "intif.h"
#include "pc.h"
+#include "status.h"
#include "mob.h"
#include "guild.h"
#include "itemdb.h"
@@ -21,6 +22,7 @@
#include "party.h"
#include "npc.h"
#include "log.h"
+#include "showmsg.h"
#ifdef MEMWATCH
#include "memwatch.h"
@@ -31,7 +33,9 @@
#define MOB_LAZYMOVEPERC 50 // Move probability in the negligent mode MOB (rate of 1000 minute)
#define MOB_LAZYWARPPERC 20 // Warp probability in the negligent mode MOB (rate of 1000 minute)
-struct mob_db mob_db[2001];
+struct mob_db mob_db[MAX_MOB_DB+1];
+
+#define CLASSCHANGE_BOSS_NUM 21
/*==========================================
* Local prototype declaration (only required thing)
@@ -42,7 +46,7 @@ static int mob_makedummymobdb(int);
static int mob_timer(int,unsigned int,int,int);
int mobskill_use(struct mob_data *md,unsigned int tick,int event);
int mobskill_deltimer(struct mob_data *md );
-int mob_skillid2skillidx(int class,int skillid);
+int mob_skillid2skillidx(int class_,int skillid);
int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx);
static int mob_unlocktarget(struct mob_data *md,int tick);
@@ -67,7 +71,7 @@ int mobdb_searchname(const char *str)
* Id Mob is checked.
*------------------------------------------
*/
-int mobdb_checkid(const int id)
+int mobdb_checkid(const int id)
{
if (id <= 0 || id >= (sizeof(mob_db) / sizeof(mob_db[0])) || mob_db[id].name[0] == '\0')
return 0;
@@ -79,28 +83,28 @@ int mobdb_checkid(const int id)
* The minimum data set for MOB spawning
*------------------------------------------
*/
-int mob_spawn_dataset(struct mob_data *md,const char *mobname,int class)
+int mob_spawn_dataset(struct mob_data *md,const char *mobname,int class_)
{
nullpo_retr(0, md);
md->bl.prev=NULL;
md->bl.next=NULL;
if(strcmp(mobname,"--en--")==0)
- memcpy(md->name,mob_db[class].name,24);
+ memcpy(md->name,mob_db[class_].name,24);
else if(strcmp(mobname,"--ja--")==0)
- memcpy(md->name,mob_db[class].jname,24);
+ memcpy(md->name,mob_db[class_].jname,24);
else
memcpy(md->name,mobname,24);
md->n = 0;
- md->base_class = md->class = class;
+ md->base_class = md->class_ = class_;
md->bl.id= npc_get_new_npc_id();
memset(&md->state,0,sizeof(md->state));
md->timer = -1;
md->target_id=0;
md->attacked_id=0;
- md->speed=mob_db[class].speed;
+ md->speed=mob_db[class_].speed;
return 0;
}
@@ -110,97 +114,108 @@ int mob_spawn_dataset(struct mob_data *md,const char *mobname,int class)
* The MOB appearance for one time (for scripts)
*------------------------------------------
*/
-int mob_once_spawn(struct map_session_data *sd,char *mapname,
- int x,int y,const char *mobname,int class,int amount,const char *event)
+int mob_once_spawn (struct map_session_data *sd, char *mapname,
+ int x, int y, const char *mobname, int class_, int amount, const char *event)
{
- struct mob_data *md=NULL;
- int m,count,lv=255,r=class;
-
- if( sd )
- lv=sd->status.base_level;
+ struct mob_data *md = NULL;
+ int m, count, lv = 255;
+ int i, j;
+
+ if(sd) lv = sd->status.base_level;
- if( sd && strcmp(mapname,"this")==0)
- m=sd->bl.m;
+ if(sd && strcmp(mapname,"this")==0)
+ m = sd->bl.m;
else
- m=map_mapname2mapid(mapname);
+ m = map_mapname2mapid(mapname);
- if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>6000) // 値が異常なら召喚を止める
+ if (m < 0 || amount <= 0 || (class_ >= 0 && class_ <= 1000) || class_ > MAX_MOB_DB + 4000) // 値が異常なら召喚を止める
return 0;
- if(class<0){ // ランダムに召喚
- int i=0;
- int j=-class-1;
+ if (class_ < 0) { // ランダムに召喚
int k;
- if(j>=0 && j<MAX_RANDOMMONSTER){
- do{
- class=rand()%1000+1001;
- k=rand()%1000000;
- }while((mob_db[class].max_hp <= 0 || mob_db[class].summonper[j] <= k ||
- (lv<mob_db[class].lv && battle_config.random_monster_checklv)) && (i++) < 2000);
- if(i>=2000){
- class=mob_db[0].summonper[j];
- }
- }else{
+ i = 0;
+ j = -class_-1;
+ if(j >= 0 && j < MAX_RANDOMMONSTER) {
+ do {
+ class_ = rand() % 1000 + 1001;
+ k = rand() % 1000000;
+ } while ((mob_db[class_].max_hp <= 0 || mob_db[class_].summonper[j] <= k ||
+ (battle_config.random_monster_checklv && lv < mob_db[class_].lv)) && (i++) < 2000);
+ if(i >= 2000)
+ class_ = mob_db[0].summonper[j];
+ } else
return 0;
- }
// if(battle_config.etc_log)
-// printf("mobclass=%d try=%d\n",class,i);
+// printf("mobclass=%d try=%d\n",class_,i);
}
- if(sd){
- if(x<=0) x=sd->bl.x;
- if(y<=0) y=sd->bl.y;
- }else if(x<=0 || y<=0){
- printf("mob_once_spawn: ??\n");
+ if (sd) { //even if the coords were wrong, spawn mob anyways (but look for most suitable coords first) Got from Freya [Lupus]
+ if (x <= 0 || y <= 0) {
+ if (x <= 0) x = sd->bl.x + rand() % 3 - 1;
+ if (y <= 0) y = sd->bl.y + rand() % 3 - 1;
+ if (map_getcell(m, x, y, CELL_CHKNOPASS)) {
+ x = sd->bl.x;
+ y = sd->bl.y;
+ }
+ }
+ } else if (x <= 0 || y <= 0) {
+ i = j = 0;
+ printf("mob_once_spawn: %i at %s x:%i y:%i\n ??\n",class_,map[m].name,x,y); //got idea from Freya [Lupus]
+ do {
+ x = rand() % (map[m].xs - 2) + 1;
+ y = rand() % (map[m].ys - 2) + 1;
+ } while ((i = map_getcell(m, x, y, CELL_CHKNOPASS)) && j++ < 64);
+ if (i) { // not solved?
+ x = 0;
+ y = 0;
+ }
}
- for(count=0;count<amount;count++){
- md=(struct mob_data *)aCalloc(1,sizeof(struct mob_data));
- memset(md, '\0', sizeof *md);
+ for (count = 0; count < amount; count++) {
+ md = (struct mob_data *)aCalloc(1,sizeof(struct mob_data));
+ memset (md, '\0', sizeof *md);
- if(class>4000) { // large/tiny mobs [Valaris]
- md->size=2;
- class-=4000;
- }
- else if(class>2000) {
- md->size=1;
- class-=2000;
+ if (class_ > MAX_MOB_DB + 2000) { // large/tiny mobs [Valaris]
+ md->size = 2;
+ class_ -= (MAX_MOB_DB + 2000);
+ } else if (class_ > MAX_MOB_DB) {
+ md->size = 1;
+ class_ -= MAX_MOB_DB;
}
- if(mob_db[class].mode&0x02)
- md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
+ if(mob_db[class_].mode & 0x02)
+ md->lootitem = (struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
else
- md->lootitem=NULL;
-
- mob_spawn_dataset(md,mobname,class);
- md->bl.m=m;
- md->bl.x=x;
- md->bl.y=y;
- if(r<0&&battle_config.dead_branch_active) md->mode=0x1+0x4+0x80; //移動してアクティブで反撃する
- md->m =m;
- md->x0=x;
- md->y0=y;
- md->xs=0;
- md->ys=0;
- md->spawndelay1=-1; // 一度のみフラグ
- md->spawndelay2=-1; // 一度のみフラグ
+ md->lootitem = NULL;
- memcpy(md->npc_event,event,sizeof(md->npc_event));
-
- md->bl.type=BL_MOB;
- map_addiddb(&md->bl);
- mob_spawn(md->bl.id);
-
- if(class==1288) { // emperium hp based on defense level [Valaris]
- struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
+ mob_spawn_dataset (md, mobname, class_);
+ md->bl.m = m;
+ md->bl.x = x;
+ md->bl.y = y;
+ if (class_ < 0 && battle_config.dead_branch_active)
+ md->mode = 0x1 + 0x4 + 0x80; //移動してアクティブで反撃する
+ md->m = m;
+ md->x0 = x;
+ md->y0 = y;
+ //md->xs = 0;
+ //md->ys = 0;
+ md->spawndelay1 = -1; // 一度のみフラグ
+ md->spawndelay2 = -1; // 一度のみフラグ
+
+ memcpy(md->npc_event, event, strlen(event));
+
+ md->bl.type = BL_MOB;
+ map_addiddb (&md->bl);
+ mob_spawn (md->bl.id);
+
+ if(class_ == 1288) { // emperium hp based on defense level [Valaris]
+ struct guild_castle *gc = guild_mapname2gc(map[md->bl.m].name);
if(gc) {
- mob_db[class].max_hp+=2000*gc->defense;
- md->hp=mob_db[class].max_hp;
+ mob_db[class_].max_hp += 2000 * gc->defense;
+ md->hp = mob_db[class_].max_hp;
}
} // end addition [Valaris]
-
-
}
- return (amount>0)?md->bl.id:0;
+ return (amount > 0) ? md->bl.id : 0;
}
/*==========================================
* The MOB appearance for one time (& area specification for scripts)
@@ -208,9 +223,9 @@ int mob_once_spawn(struct map_session_data *sd,char *mapname,
*/
int mob_once_spawn_area(struct map_session_data *sd,char *mapname,
int x0,int y0,int x1,int y1,
- const char *mobname,int class,int amount,const char *event)
+ const char *mobname,int class_,int amount,const char *event)
{
- int x,y,i,c,max,lx=-1,ly=-1,id=0;
+ int x,y,i,max,lx=-1,ly=-1,id=0;
int m;
if(strcmp(mapname,"this")==0)
@@ -221,7 +236,7 @@ int mob_once_spawn_area(struct map_session_data *sd,char *mapname,
max=(y1-y0+1)*(x1-x0+1)*3;
if(max>1000)max=1000;
- if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>6000) // A summon is stopped if a value is unusual
+ if(m<0 || amount<=0 || (class_>=0 && class_<=1000) || class_>MAX_MOB_DB) // A summon is stopped if a value is unusual
return 0;
for(i=0;i<amount;i++){
@@ -229,15 +244,17 @@ int mob_once_spawn_area(struct map_session_data *sd,char *mapname,
do{
x=rand()%(x1-x0+1)+x0;
y=rand()%(y1-y0+1)+y0;
- }while( ( (c=map_getcell(m,x,y))==1 || c==5)&& (++j)<max );
+ } while (map_getcell(m,x,y,CELL_CHKNOPASS) && (++j)<max);
+ // freya }while( ( (c=map_getcell(m,x,y))==1 || c==5)&& (++j)<max );
if(j>=max){
- if(lx>=0){ // 検索に失敗したので以前に沸いた場所を使う
+ if(lx>=0){ // Since reference went wrong, the place which boiled before is used.
x=lx;
y=ly;
}else
- return 0; // 最初に沸く場所の検索を失敗したのでやめる
+ return 0; // Since reference of the place which boils first went wrong, it stops.
}
- id=mob_once_spawn(sd,mapname,x,y,mobname,class,1,event);
+ if(x==0||y==0) printf("xory=0, x=%d,y=%d,x0=%d,y0=%d\n",x,y,x0,y0);
+ id=mob_once_spawn(sd,mapname,x,y,mobname,class_,1,event);
lx=x;
ly=y;
}
@@ -249,7 +266,7 @@ int mob_once_spawn_area(struct map_session_data *sd,char *mapname,
*------------------------------------------
*/
int mob_spawn_guardian(struct map_session_data *sd,char *mapname,
- int x,int y,const char *mobname,int class,int amount,const char *event,int guardian)
+ int x,int y,const char *mobname,int class_,int amount,const char *event,int guardian)
{
struct mob_data *md=NULL;
int m,count=1,lv=255;
@@ -262,33 +279,27 @@ int mob_spawn_guardian(struct map_session_data *sd,char *mapname,
else
m=map_mapname2mapid(mapname);
- if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>2000) // 値が異常なら召喚を止める
+ if(m<0 || amount<=0 || (class_>=0 && class_<=1000) || class_>MAX_MOB_DB) // Invalid monster classes
return 0;
- if(class<0)
+ if(class_<0)
return 0;
-
+
if(sd){
if(x<=0) x=sd->bl.x;
if(y<=0) y=sd->bl.y;
}
-
+
else if(x<=0 || y<=0)
printf("mob_spawn_guardian: ??\n");
-
+
for(count=0;count<amount;count++){
struct guild_castle *gc;
- md=calloc(sizeof(struct mob_data), 1);
- if(md==NULL){
- printf("mob_spawn_guardian: out of memory !\n");
- exit(1);
- }
+ md=(struct mob_data *) aCalloc(sizeof(struct mob_data), 1);
memset(md, '\0', sizeof *md);
-
-
- mob_spawn_dataset(md,mobname,class);
+ mob_spawn_dataset(md,mobname,class_);
md->bl.m=m;
md->bl.x=x;
md->bl.y=y;
@@ -308,7 +319,7 @@ int mob_spawn_guardian(struct map_session_data *sd,char *mapname,
gc=guild_mapname2gc(map[md->bl.m].name);
if(gc) {
- mob_db[class].max_hp+=2000*gc->defense;
+ mob_db[class_].max_hp+=2000*gc->defense;
if(guardian==0) { md->hp=gc->Ghp0; gc->GID0=md->bl.id; }
if(guardian==1) { md->hp=gc->Ghp1; gc->GID1=md->bl.id; }
if(guardian==2) { md->hp=gc->Ghp2; gc->GID2=md->bl.id; }
@@ -317,7 +328,6 @@ int mob_spawn_guardian(struct map_session_data *sd,char *mapname,
if(guardian==5) { md->hp=gc->Ghp5; gc->GID5=md->bl.id; }
if(guardian==6) { md->hp=gc->Ghp6; gc->GID6=md->bl.id; }
if(guardian==7) { md->hp=gc->Ghp7; gc->GID7=md->bl.id; }
-
}
}
@@ -366,49 +376,49 @@ int mob_exclusion_check(struct mob_data *md,struct map_session_data *sd)
* Appearance income of mob
*------------------------------------------
*/
-int mob_get_viewclass(int class)
+int mob_get_viewclass(int class_)
{
- return mob_db[class].view_class;
+ return mob_db[class_].view_class;
}
-int mob_get_sex(int class)
+int mob_get_sex(int class_)
{
- return mob_db[class].sex;
+ return mob_db[class_].sex;
}
-short mob_get_hair(int class)
+short mob_get_hair(int class_)
{
- return mob_db[class].hair;
+ return mob_db[class_].hair;
}
-short mob_get_hair_color(int class)
+short mob_get_hair_color(int class_)
{
- return mob_db[class].hair_color;
+ return mob_db[class_].hair_color;
}
-short mob_get_weapon(int class)
+short mob_get_weapon(int class_)
{
- return mob_db[class].weapon;
+ return mob_db[class_].weapon;
}
-short mob_get_shield(int class)
+short mob_get_shield(int class_)
{
- return mob_db[class].shield;
+ return mob_db[class_].shield;
}
-short mob_get_head_top(int class)
+short mob_get_head_top(int class_)
{
- return mob_db[class].head_top;
+ return mob_db[class_].head_top;
}
-short mob_get_head_mid(int class)
+short mob_get_head_mid(int class_)
{
- return mob_db[class].head_mid;
+ return mob_db[class_].head_mid;
}
-short mob_get_head_buttom(int class)
+short mob_get_head_buttom(int class_)
{
- return mob_db[class].head_buttom;
+ return mob_db[class_].head_buttom;
}
-short mob_get_clothes_color(int class) // Add for player monster dye - Valaris
+short mob_get_clothes_color(int class_) // Add for player monster dye - Valaris
{
- return mob_db[class].clothes_color; // End
+ return mob_db[class_].clothes_color; // End
}
-int mob_get_equip(int class) // mob equip [Valaris]
+int mob_get_equip(int class_) // mob equip [Valaris]
{
- return mob_db[class].equip;
+ return mob_db[class_].equip;
}
/*==========================================
* Is MOB in the state in which the present movement is possible or not?
@@ -425,7 +435,7 @@ int mob_can_move(struct mob_data *md)
md->sc_data[SC_AUTOCOUNTER].timer != -1 || //オートカウンター
md->sc_data[SC_BLADESTOP].timer != -1 || //白刃取り
md->sc_data[SC_SPIDERWEB].timer != -1 //スパイダーウェッブ
- )
+ )
return 0;
return 1;
@@ -442,8 +452,8 @@ static int calc_next_walk_step(struct mob_data *md)
if(md->walkpath.path_pos>=md->walkpath.path_len)
return -1;
if(md->walkpath.path[md->walkpath.path_pos]&1)
- return battle_get_speed(&md->bl)*14/10;
- return battle_get_speed(&md->bl);
+ return status_get_speed(&md->bl)*14/10;
+ return status_get_speed(&md->bl);
}
static int mob_walktoxy_sub(struct mob_data *md);
@@ -455,7 +465,7 @@ static int mob_walktoxy_sub(struct mob_data *md);
static int mob_walk(struct mob_data *md,unsigned int tick,int data)
{
int moveblock;
- int i,ctype;
+ int i;
static int dirx[8]={0,-1,-1,-1,0,1,1,1};
static int diry[8]={1,1,0,-1,-1,-1,0,1};
int x,y,dx,dy;
@@ -480,8 +490,7 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data)
x = md->bl.x;
y = md->bl.y;
- ctype = map_getcell(md->bl.m,x,y);
- if(ctype == 1 || ctype == 5) {
+ if(map_getcell(md->bl.m,x,y,CELL_CHKNOPASS)) {
mob_stop_walking(md,1);
return 0;
}
@@ -489,12 +498,20 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data)
dx = dirx[md->dir];
dy = diry[md->dir];
- ctype = map_getcell(md->bl.m,x+dx,y+dy);
- if(ctype == 1 || ctype == 5) {
+ 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_moonlit (&md->bl,x+dx,y+dy)) {
+ mob_walktoxy_sub(md);
+ return 0;
+ }
moveblock = ( x/BLOCK_SIZE != (x+dx)/BLOCK_SIZE || y/BLOCK_SIZE != (y+dy)/BLOCK_SIZE);
md->state.state=MS_WALK;
@@ -505,18 +522,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;
@@ -591,11 +608,11 @@ static int mob_attack(struct mob_data *md,unsigned int tick,int data)
if(!md->mode)
- mode=mob_db[md->class].mode;
+ mode=mob_db[md->class_].mode;
else
mode=md->mode;
- race=mob_db[md->class].race;
+ race=mob_db[md->class_].race;
if(!(mode&0x80)){
md->target_id=0;
md->state.targettype = NONE_ATTACKABLE;
@@ -604,11 +621,11 @@ static int mob_attack(struct mob_data *md,unsigned int tick,int data)
if(tsd && !(mode&0x20) && (tsd->sc_data[SC_TRICKDEAD].timer != -1 || tsd->sc_data[SC_BASILICA].timer != -1 ||
((pc_ishiding(tsd) || tsd->state.gangsterparadise) && !((race == 4 || race == 6) && !tsd->perfect_hiding) ) ) ) {
md->target_id=0;
- md->state.targettype = NONE_ATTACKABLE;
+ md->state.targettype = NONE_ATTACKABLE;
return 0;
}
- range = mob_db[md->class].range;
+ range = mob_db[md->class_].range;
if(mode&1)
range++;
if(distance(md->bl.x,md->bl.y,tbl->x,tbl->y) > range)
@@ -625,9 +642,9 @@ static int mob_attack(struct mob_data *md,unsigned int tick,int data)
md->target_lv = battle_weapon_attack(&md->bl,tbl,tick,0);
if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1)
- skill_status_change_end(&md->bl,SC_CLOAKING,-1);
+ status_change_end(&md->bl,SC_CLOAKING,-1);
- md->attackabletime = tick + battle_get_adelay(&md->bl);
+ md->attackabletime = tick + status_get_adelay(&md->bl);
md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
md->state.state=MS_ATTACK;
@@ -684,7 +701,7 @@ int mob_changestate(struct mob_data *md,int state,int type)
if(i>0 && i<2000)
md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
else if(type) {
- md->attackabletime = tick + battle_get_amotion(&md->bl);
+ md->attackabletime = tick + status_get_amotion(&md->bl);
md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
}
else {
@@ -702,8 +719,8 @@ 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_status_change_clear(&md->bl,2); // ステータス異常を解除する
+ skill_unit_move(&md->bl,gettick(),0);
+ status_change_clear(&md->bl,2); // ステータス異常を解除する
skill_clear_unitgroup(&md->bl); // 全てのスキルユニットグループを削除する
skill_cleartimerskill(&md->bl);
if(md->deletetimer!=-1)
@@ -730,15 +747,12 @@ static int mob_timer(int tid,unsigned int tick,int id,int data)
if( (bl=map_id2bl(id)) == NULL ){ //攻撃してきた敵がもういないのは正常のようだ
return 1;
}
-
+
if(!bl || !bl->type || bl->type!=BL_MOB)
return 1;
nullpo_retr(1, md=(struct mob_data*)bl);
- if(!md->bl.type || md->bl.type!=BL_MOB)
- return 1;
-
if(md->timer != tid){
if(battle_config.error_log)
printf("mob_timer %d != %d\n",md->timer,tid);
@@ -764,6 +778,10 @@ static int mob_timer(int tid,unsigned int tick,int id,int data)
printf("mob_timer : %d ?\n",md->state.state);
break;
}
+
+ if (md->timer == -1)
+ mob_changestate(md,MS_WALK,0);
+
map_freeblock_unlock();
return 0;
}
@@ -775,11 +793,25 @@ 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);
+ memset(&wpd, 0, sizeof(wpd));
+
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;
+ if (wpd.path[0] >= 8)
+ 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;
@@ -857,7 +889,7 @@ int mob_setdelayspawn(int id)
spawntime1=md->last_spawntime+md->spawndelay1;
spawntime2=md->last_deadtime+md->spawndelay2;
- spawntime3=gettick()+5000;
+ spawntime3=gettick()+5000+rand()%5000; //Lupus
// spawntime = max(spawntime1,spawntime2,spawntime3);
if(DIFF_TICK(spawntime1,spawntime2)>0)
spawntime=spawntime1;
@@ -882,7 +914,8 @@ int mob_spawn(int id)
struct mob_data *md;
struct block_list *bl;
- nullpo_retr(-1, bl=map_id2bl(id));
+ //nullpo_retr(-1, bl=map_id2bl(id));
+ bl=map_id2bl(id);
if(!bl || !bl->type || bl->type!=BL_MOB)
return -1;
@@ -891,15 +924,15 @@ int mob_spawn(int id)
if(!md || !md->bl.type || md->bl.type!=BL_MOB)
return -1;
-
+
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
- md->class = md->base_class;
+ md->class_ = md->base_class;
md->bl.m =md->m;
do {
@@ -911,7 +944,7 @@ int mob_spawn(int id)
y=md->y0+rand()%(md->ys+1)-md->ys/2;
}
i++;
- } while(((c=map_getcell(md->bl.m,x,y))==1 || c==5) && i<50);
+ } while(map_getcell(md->bl.m,x,y,CELL_CHKNOPASS) && i<50);
if(i>=50){
// if(battle_config.error_log==1)
@@ -923,8 +956,7 @@ int mob_spawn(int id)
md->to_x=md->bl.x=x;
md->to_y=md->bl.y=y;
md->dir=0;
-
- map_addblock(&md->bl);
+ md->target_dir=0;
memset(&md->state,0,sizeof(md->state));
md->attacked_id = 0;
@@ -932,11 +964,11 @@ int mob_spawn(int id)
md->move_fail_count = 0;
if(!md->speed)
- md->speed = mob_db[md->class].speed;
- md->def_ele = mob_db[md->class].element;
+ md->speed = mob_db[md->class_].speed;
+ md->def_ele = mob_db[md->class_].element;
if(!md->level) // [Valaris]
- md->level=mob_db[md->class].lv;
+ md->level=mob_db[md->class_].lv;
md->master_id=0;
md->master_dist=0;
@@ -950,13 +982,12 @@ int mob_spawn(int id)
md->canmove_tick = tick;
md->guild_id = 0;
- if (md->class >= 1285 && md->class <= 1288) {
+ if (md->class_ >= 1285 && md->class_ <= 1288) {
struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
if(gc)
md->guild_id = gc->guild_id;
}
-
- md->sg_count=0;
+
md->deletetimer=-1;
md->skilltimer=-1;
@@ -983,12 +1014,15 @@ int mob_spawn(int id)
memset(md->skillunit,0,sizeof(md->skillunit));
memset(md->skillunittick,0,sizeof(md->skillunittick));
- md->hp = battle_get_max_hp(&md->bl);
+ md->hp = status_get_max_hp(&md->bl);
if(md->hp<=0){
- mob_makedummymobdb(md->class);
- md->hp = battle_get_max_hp(&md->bl);
+ mob_makedummymobdb(md->class_);
+ md->hp = status_get_max_hp(&md->bl);
}
+ map_addblock(&md->bl);
+ skill_unit_move(&md->bl,tick,1);
+
clif_spawnmob(md);
return 0;
@@ -1026,10 +1060,9 @@ int mob_stop_walking(struct mob_data *md,int type)
{
nullpo_retr(0, md);
-
if(md->state.state == MS_WALK || md->state.state == MS_IDLE) {
int dx=0,dy=0;
-
+
md->walkpath.path_len=0;
if(type&4){
dx=md->to_x-md->bl.x;
@@ -1054,9 +1087,9 @@ int mob_stop_walking(struct mob_data *md,int type)
if(type&0x01)
clif_fixmobpos(md);
if(type&0x02) {
- int delay=battle_get_dmotion(&md->bl);
+ int delay=status_get_dmotion(&md->bl);
unsigned int tick = gettick();
- if(md->canmove_tick < tick)
+ if(battle_config.monster_damage_delay && md->canmove_tick < tick)
md->canmove_tick = tick + delay;
}
@@ -1079,46 +1112,43 @@ int mob_can_reach(struct mob_data *md,struct block_list *bl,int range)
dx=abs(bl->x - md->bl.x);
dy=abs(bl->y - md->bl.y);
+ if( md->bl.m != bl->m) // 違うャbプ
+ return 0;
+
+ if( range>0 && range < ((dx>dy)?dx:dy) ) // 遠すぎる
+ return 0;
+
+ if( md->bl.x==bl->x && md->bl.y==bl->y ) // 同じマス
+ return 1;
+
//=========== guildcastle guardian no search start===========
//when players are the guild castle member not attack them !
- if(md->class >= 1285 && md->class <= 1287){
+ /*if(md->class_ >= 1285 && md->class_ <= 1287){
struct map_session_data *sd;
struct guild *g=NULL;
struct guild_castle *gc=guild_mapname2gc(map[bl->m].name);
if(gc && agit_flag==0) // Guardians will not attack during non-woe time [Valaris]
return 0; // end addition [Valaris]
-
- if(bl && bl->type == BL_PC){
+
+ if(gc && bl->type == BL_PC){
nullpo_retr(0, sd=(struct map_session_data *)bl);
- if(!gc)
- return 0;
- if(gc && sd && sd->status.guild_id) {
- g=guild_search(sd->status.guild_id); // don't attack guild members [Valaris]
+ if(gc && sd->status.guild_id > 0) {
+ g=guild_search(sd->status.guild_id); // don't attack guild members [Valaris]
if(g && g->guild_id == gc->guild_id)
return 0;
if(g && gc && guild_isallied(g,gc))
return 0;
-
}
}
- }
+ }*/
//========== guildcastle guardian no search eof==============
- if(bl && bl->type == BL_PC && battle_config.monsters_ignore_gm) { // option to have monsters ignore GMs [Valaris]
+ /*if(bl->type == BL_PC && battle_config.monsters_ignore_gm) { // option to have monsters ignore GMs [Valaris]
struct map_session_data *sd;
if((sd=(struct map_session_data *)bl) != NULL && pc_isGM(sd) >= battle_config.monsters_ignore_gm)
return 0;
- }
-
- if( md->bl.m != bl->m) // 違うャbプ
- return 0;
-
- if( range>0 && range < ((dx>dy)?dx:dy) ) // 遠すぎる
- return 0;
-
- if( md->bl.x==bl->x && md->bl.y==bl->y ) // 同じマス
- return 1;
+ }*/
// Obstacle judging
wpd.path_len=0;
@@ -1156,12 +1186,12 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist)
nullpo_retr(0, md);
nullpo_retr(0, bl);
- sc_data = battle_get_sc_data(bl);
- option = battle_get_option(bl);
- race=mob_db[md->class].race;
+ sc_data = status_get_sc_data(bl);
+ option = status_get_option(bl);
+ race=mob_db[md->class_].race;
if(!md->mode)
- mode=mob_db[md->class].mode;
+ mode=mob_db[md->class_].mode;
else
mode=md->mode;
@@ -1170,7 +1200,9 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist)
return 0;
}
// Nothing will be carried out if there is no mind of changing TAGE by TAGE ending.
- if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && ( !(mode&0x04) || rand()%100>25) )
+ if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && (!(mode&0x04) || rand()%100>25) &&
+ // if the monster was provoked ignore the above rule [celest]
+ !(md->state.provoke_flag && md->state.provoke_flag == bl->id))
return 0;
if(mode&0x20 || // Coercion is exerted if it is MVPMOB.
@@ -1184,11 +1216,13 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist)
return 0;
}
- md->target_id=bl->id; // Since there was no disturbance, it locks on to target.
+ md->target_id = bl->id; // Since there was no disturbance, it locks on to target.
if(bl->type == BL_PC || bl->type == BL_MOB)
md->state.targettype = ATTACKABLE;
else
md->state.targettype = NONE_ATTACKABLE;
+ if (md->state.provoke_flag)
+ md->state.provoke_flag = 0;
md->min_chase=dist+13;
if(md->min_chase>26)
md->min_chase=26;
@@ -1223,18 +1257,18 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
return 0;
if(!smd->mode)
- mode=mob_db[smd->class].mode;
+ mode=mob_db[smd->class_].mode;
else
mode=smd->mode;
// アクティブでターゲット射程内にいるなら、ロックする
if( mode&0x04 ){
- race=mob_db[smd->class].race;
+ race=mob_db[smd->class_].race;
//対象がPCの場合
if(tsd &&
- !pc_isdead(tsd) &&
- tsd->bl.m == smd->bl.m &&
- tsd->invincible_timer == -1 &&
+ !pc_isdead(tsd) &&
+ tsd->bl.m == smd->bl.m &&
+ tsd->invincible_timer == -1 &&
!pc_isinvisible(tsd) &&
(dist=distance(smd->bl.x,smd->bl.y,tsd->bl.x,tsd->bl.y))<9
)
@@ -1246,7 +1280,7 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
rand()%1000<1000/(++(*pcc)) ){ // 範囲内PCで等確率にする
smd->target_id=tsd->bl.id;
smd->state.targettype = ATTACKABLE;
- smd->min_chase=13;
+ smd->min_chase=13;
}
}
}
@@ -1282,10 +1316,10 @@ static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
nullpo_retr(0, itc=va_arg(ap,int *));
if(!md->mode)
- mode=mob_db[md->class].mode;
+ mode=mob_db[md->class_].mode;
else
mode=md->mode;
-
+
if( !md->target_id && mode&0x02){
if(!md->lootitem || (battle_config.monster_loot_type == 1 && md->lootitem_count >= LOOTITEM_SIZE) )
@@ -1319,8 +1353,8 @@ static int mob_ai_sub_hard_linksearch(struct block_list *bl,va_list ap)
nullpo_retr(0, target=va_arg(ap,struct block_list *));
// same family free in a range at a link monster -- it will be made to lock if MOB is
-/* if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && mob_db[md->class].mode&0x08){
- if( tmd->class==md->class && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE) && tmd->bl.m == md->bl.m){
+/* if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && mob_db[md->class_].mode&0x08){
+ if( tmd->class_==md->class_ && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE) && tmd->bl.m == md->bl.m){
if( mob_can_reach(tmd,target,12) ){ // Reachability judging
tmd->target_id=md->target_id;
tmd->state.targettype = ATTACKABLE;
@@ -1328,8 +1362,8 @@ static int mob_ai_sub_hard_linksearch(struct block_list *bl,va_list ap)
}
}
}*/
- if( md->attacked_id > 0 && mob_db[md->class].mode&0x08){
- if( tmd->class==md->class && tmd->bl.m == md->bl.m && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE)){
+ if( md->attacked_id > 0 && mob_db[md->class_].mode&0x08){
+ if( tmd->class_==md->class_ && tmd->bl.m == md->bl.m && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE)){
if( mob_can_reach(tmd,target,12) ){ // Reachability judging
tmd->target_id=md->attacked_id;
tmd->state.targettype = ATTACKABLE;
@@ -1355,12 +1389,24 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
if((bl=map_id2bl(md->master_id)) != NULL )
mmd=(struct mob_data *)bl;
- mode=mob_db[md->class].mode;
+ mode=mob_db[md->class_].mode;
// It is not main monster/leader.
if(!mmd || mmd->bl.type!=BL_MOB || mmd->bl.id!=md->master_id)
return 0;
+ // 呼び戻し
+ if(mmd->recall_flag == 1){
+ if (mmd->recallcount < (mmd->recallmob_count+2) ){
+ mob_warp(md,-1,mmd->bl.x,mmd->bl.y,3);
+ mmd->recallcount += 1;
+ } else{
+ mmd->recall_flag = 0;
+ mmd->recallcount=0;
+ }
+ md->state.master_check = 1;
+ return 0;
+ }
// Since it is in the map on which the master is not, teleport is carried out and it pursues.
if( mmd->bl.m != md->bl.m ){
mob_warp(md,mmd->bl.m,mmd->bl.x,mmd->bl.y,3);
@@ -1380,7 +1426,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
}
// Although there is the master, since it is somewhat far, it approaches.
- if((!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mob_can_move(md) &&
+ if((!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mob_can_move(md) &&
(md->walkpath.path_pos>=md->walkpath.path_len || md->walkpath.path_len==0) && md->master_dist<15){
int i=0,dx,dy,ret;
if(md->master_dist>4) {
@@ -1426,7 +1472,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
struct map_session_data *sd=map_id2sd(mmd->target_id);
if(sd!=NULL && !pc_isdead(sd) && sd->invincible_timer == -1 && !pc_isinvisible(sd)){
- race=mob_db[md->class].race;
+ race=mob_db[md->class_].race;
if(mode&0x20 ||
(sd->sc_data[SC_TRICKDEAD].timer == -1 && sd->sc_data[SC_BASILICA].timer == -1 &&
( (!pc_ishiding(sd) && !sd->state.gangsterparadise) || ((race == 4 || race == 6) && !sd->perfect_hiding) ) ) ){ // 妨害がないか判定
@@ -1444,7 +1490,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
struct map_session_data *sd=map_id2sd(md->target_id);
if(sd!=NULL && !pc_isdead(sd) && sd->invincible_timer == -1 && !pc_isinvisible(sd)){
- race=mob_db[mmd->class].race;
+ race=mob_db[mmd->class_].race;
if(mode&0x20 ||
(sd->sc_data[SC_TRICKDEAD].timer == -1 &&
(!(sd->status.option&0x06) || race==4 || race==6)
@@ -1485,23 +1531,34 @@ static int mob_randomwalk(struct mob_data *md,int tick)
nullpo_retr(0, md);
- speed=battle_get_speed(&md->bl);
+ speed=status_get_speed(&md->bl);
if(DIFF_TICK(md->next_walktime,tick)<0){
int i,x,y,c,d=12-md->move_fail_count;
+ int mask[8][2] = {{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};
if(d<5) d=5;
for(i=0;i<retrycount;i++){ // Search of a movable place
int r=rand();
- x=md->bl.x+r%(d*2+1)-d;
- y=md->bl.y+r/(d*2+1)%(d*2+1)-d;
- if((c=map_getcell(md->bl.m,x,y))!=1 && c!=5 && mob_walktoxy(md,x,y,1)==0){
+ x=r%(d*2+1)-d;
+ y=r/(d*2+1)%(d*2+1)-d;
+ if (md->target_dir){
+ if (x<0) x=0-x;
+ if (y<0) y=0-y;
+ x *= mask[md->target_dir-1][0];
+ y *= mask[md->target_dir-1][1];
+ }
+ x+=md->bl.x;
+ y+=md->bl.y;
+
+ if((map_getcell(md->bl.m,x,y,CELL_CHKPASS)) && mob_walktoxy(md,x,y,1)==0){
md->move_fail_count=0;
break;
}
if(i+1>=retrycount){
md->move_fail_count++;
+ md->target_dir = 0;
if(md->move_fail_count>1000){
if(battle_config.error_log)
- printf("MOB cant move. random spawn %d, class = %d\n",md->bl.id,md->class);
+ printf("MOB cant move. random spawn %d, class = %d\n",md->bl.id,md->class_);
md->move_fail_count=0;
mob_spawn(md->bl.id);
}
@@ -1534,6 +1591,8 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
int i,dx,dy,ret,dist;
int attack_type=0;
int mode,race;
+ int search_size = AREA_SIZE*2;
+ int blind_flag = 0;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
@@ -1541,7 +1600,6 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
tick=va_arg(ap,unsigned int);
-
if(DIFF_TICK(tick,md->last_thinktime)<MIN_MOBTHINKTIME)
return 0;
md->last_thinktime=tick;
@@ -1553,16 +1611,19 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
}
if(!md->mode)
- mode=mob_db[md->class].mode;
+ mode=mob_db[md->class_].mode;
else
mode=md->mode;
- race=mob_db[md->class].race;
+ race=mob_db[md->class_].race;
// Abnormalities
if((md->opt1 > 0 && md->opt1 != 6) || md->state.state==MS_DELAY || md->sc_data[SC_BLADESTOP].timer != -1)
return 0;
+ if (md->sc_data && md->sc_data[SC_BLIND].timer != -1)
+ blind_flag = 1;
+
if(!(mode&0x80) && md->target_id > 0)
md->target_id = 0;
@@ -1587,7 +1648,8 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
if(abl->type==BL_PC)
asd=(struct map_session_data *)abl;
if(asd==NULL || md->bl.m != abl->m || abl->prev == NULL || asd->invincible_timer != -1 || pc_isinvisible(asd) ||
- (dist=distance(md->bl.x,md->bl.y,abl->x,abl->y))>=32 || battle_check_target(bl,abl,BCT_ENEMY)==0)
+ (dist=distance(md->bl.x,md->bl.y,abl->x,abl->y))>=32 || battle_check_target(bl,abl,BCT_ENEMY)==0 ||
+ (blind_flag && dist>3))
md->attacked_id=0;
else {
//距離が遠い場合はタゲを変更しない
@@ -1614,15 +1676,16 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
if( (!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mode&0x04 && !md->state.master_check &&
battle_config.monster_active_enable){
i=0;
+ search_size = (blind_flag) ? 3 : AREA_SIZE*2;
if(md->state.special_mob_ai){
map_foreachinarea(mob_ai_sub_hard_activesearch,md->bl.m,
- md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2,
- md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2,
+ md->bl.x-search_size,md->bl.y-search_size,
+ md->bl.x+search_size,md->bl.y+search_size,
0,md,&i);
}else{
map_foreachinarea(mob_ai_sub_hard_activesearch,md->bl.m,
- md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2,
- md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2,
+ md->bl.x-search_size,md->bl.y-search_size,
+ md->bl.x+search_size,md->bl.y+search_size,
BL_PC,md,&i);
}
}
@@ -1630,9 +1693,10 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
// The item search of a route monster
if( !md->target_id && mode&0x02 && !md->state.master_check){
i=0;
+ search_size = (blind_flag) ? 3 : AREA_SIZE*2;
map_foreachinarea(mob_ai_sub_hard_lootsearch,md->bl.m,
- md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2,
- md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2,
+ md->bl.x-search_size,md->bl.y-search_size,
+ md->bl.x+search_size,md->bl.y+search_size,
BL_ITEM,md,&i);
}
@@ -1644,13 +1708,13 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
else if(tbl->type==BL_MOB)
tmd=(struct mob_data *)tbl;
if(tsd || tmd) {
- if(tbl->m != md->bl.m || tbl->prev == NULL || (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y))>=md->min_chase)
+ if(tbl->m != md->bl.m || tbl->prev == NULL || (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y)) >= search_size || (blind_flag && dist>3))
mob_unlocktarget(md,tick); // 別マップか、視界外
else if( tsd && !(mode&0x20) && (tsd->sc_data[SC_TRICKDEAD].timer != -1 || tsd->sc_data[SC_BASILICA].timer != -1 ||
((pc_ishiding(tsd) || tsd->state.gangsterparadise) &&
!((race == 4 || race == 6) && !tsd->perfect_hiding) )) )
mob_unlocktarget(md,tick); // スキルなどによる策敵妨害
- else if(!battle_check_range(&md->bl,tbl,mob_db[md->class].range)){
+ else if(!battle_check_range(&md->bl,tbl,mob_db[md->class_].range)){
// 攻撃範囲外なので移動
if(!(mode&1)){ // 移動しないモード
mob_unlocktarget(md,tick);
@@ -1663,9 +1727,11 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
// if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tsd->bl.x,tsd->bl.y)<2) )
if(md->timer != -1 && md->state.state!=MS_ATTACK && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tbl->x,tbl->y)<2) )
return 0; // 既に移動中
- if( !mob_can_reach(md,tbl,(md->min_chase>13)?md->min_chase:13) )
+ search_size = (blind_flag) ? 3 :
+ ((md->min_chase > 13) ? md->min_chase : 13);
+ if(!mob_can_reach(md,tbl, search_size))
mob_unlocktarget(md,tick); // 移動できないのでタゲ解除(IWとか?)
- else{
+ else {
// 追跡
md->next_walktime=tick+500;
i=0;
@@ -1692,15 +1758,15 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
ret=mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
i++;
} while(ret && i<5);
-
+
if(ret){ // 移動不可能な所からの攻撃なら2歩下る
if(dx<0) dx=2;
else if(dx>0) dx=-2;
if(dy<0) dy=2;
else if(dy>0) dy=-2;
mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
+ }
}
- }
} else { // 攻撃射程範囲内
md->state.skillstate=MSS_ATTACK;
if(md->state.state==MS_WALK)
@@ -1708,23 +1774,17 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
if(md->state.state==MS_ATTACK)
return 0; // 既に攻撃中
mob_changestate(md,MS_ATTACK,attack_type);
-
-/* if(mode&0x08){ // リンクモンスター
- map_foreachinarea(mob_ai_sub_hard_linksearch,md->bl.m,
- md->bl.x-13,md->bl.y-13,
- md->bl.x+13,md->bl.y+13,
- BL_MOB,md,&tsd->bl);
- }*/
}
return 0;
- }else{ // ルートモンスター処理
+ } else { // ルートモンスター処理
if(tbl == NULL || tbl->type != BL_ITEM ||tbl->m != md->bl.m ||
- (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y))>=md->min_chase || !md->lootitem){
+ (dist=distance(md->bl.x,md->bl.y,tbl->x,tbl->y))>=md->min_chase || !md->lootitem |
+ (blind_flag && dist>=4)){
// 遠すぎるかアイテムがなくなった
mob_unlocktarget(md,tick);
if(md->state.state==MS_WALK)
mob_stop_walking(md,1); // 歩行中なら停止
- }else if(dist){
+ } else if(dist) {
if(!(mode&1)){ // 移動しないモード
mob_unlocktarget(md,tick);
return 0;
@@ -1838,7 +1898,8 @@ static int mob_ai_hard(int tid,unsigned int tick,int id,int data)
*/
static int mob_ai_sub_lazy(void * key,void * data,va_list app)
{
- struct mob_data *md=data;
+ struct mob_data *md=(struct mob_data *)data;
+ struct mob_data *mmd=NULL;
unsigned int tick;
va_list ap;
@@ -1849,8 +1910,9 @@ static int mob_ai_sub_lazy(void * key,void * data,va_list app)
if(md->bl.type!=BL_MOB)
return 0;
- if(!md->bl.type || md->bl.type!=BL_MOB)
- return 0;
+ if (md->master_id > 0) {
+ mmd = (struct mob_data *)map_id2bl(md->master_id); //自分のBOSSの情報
+ }
tick=va_arg(ap,unsigned int);
@@ -1864,8 +1926,14 @@ static int mob_ai_sub_lazy(void * key,void * data,va_list app)
return 0;
}
+ // 取り巻きモンスターの処理(呼び戻しされた時)
+ if(mmd && md->state.special_mob_ai == 0 && mmd->recall_flag == 1) {
+ mob_ai_sub_hard_slavemob (md,tick);
+ return 0;
+ }
+
if(DIFF_TICK(md->next_walktime,tick)<0 &&
- (mob_db[md->class].mode&1) && mob_can_move(md) ){
+ (mob_db[md->class_].mode&1) && mob_can_move(md) ){
if( map[md->bl.m].users>0 ){
// Since PC is in the same map, somewhat better negligent processing is carried out.
@@ -1876,7 +1944,7 @@ static int mob_ai_sub_lazy(void * key,void * data,va_list app)
// MOB which is not not the summons MOB but BOSS, either sometimes reboils.
else if( rand()%1000<MOB_LAZYWARPPERC && md->x0<=0 && md->master_id!=0 &&
- mob_db[md->class].mexp <= 0 && !(mob_db[md->class].mode & 0x20))
+ mob_db[md->class_].mexp <= 0 && !(mob_db[md->class_].mode & 0x20))
mob_spawn(md->bl.id);
}else{
@@ -1884,7 +1952,7 @@ static int mob_ai_sub_lazy(void * key,void * data,va_list app)
// MOB which is not BOSS which is not Summons MOB, either -- a case -- sometimes -- leaping
if( rand()%1000<MOB_LAZYWARPPERC && md->x0<=0 && md->master_id!=0 &&
- mob_db[md->class].mexp <= 0 && !(mob_db[md->class].mode & 0x20))
+ mob_db[md->class_].mexp <= 0 && !(mob_db[md->class_].mode & 0x20))
mob_warp(md,-1,-1,-1,-1);
}
@@ -1931,7 +1999,7 @@ static int mob_delay_item_drop(int tid,unsigned int tick,int id,int data)
{
struct delay_item_drop *ditem;
struct item temp_item;
- int flag;
+ int flag, drop_flag = 1;
nullpo_retr(0, ditem=(struct delay_item_drop *)id);
@@ -1940,18 +2008,45 @@ static int mob_delay_item_drop(int tid,unsigned int tick,int id,int data)
temp_item.amount = ditem->amount;
temp_item.identify = !itemdb_isequip3(temp_item.nameid);
- if(battle_config.item_auto_get){
- if(ditem->first_sd && (flag = pc_additem(ditem->first_sd,&temp_item,ditem->amount))){
- clif_additem(ditem->first_sd,0,0,flag);
- map_addflooritem(&temp_item,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
+ if (ditem->first_sd){
+ #if 0
+ if (ditem->first_sd->status.party_id > 0){
+ struct party *p;
+ if((p=party_search(ditem->first_sd->status.party_id)) && p->item){
+ struct map_session_data *sd = NULL;
+ int i;
+ for (i = p->itemc + 1; i!=p->itemc; i++) { // initialise counter and loop through the party
+ if (i >= MAX_PARTY)
+ i = 0; // reset counter to 1st person in party so it'll stop when it reaches "itemc"
+ if ((sd=p->member[i].sd)!=NULL && sd->bl.m == ditem->first_sd->bl.m)
+ break;
+ }
+ if (sd){ // if an appropiate party member was found
+ drop_flag = 0;
+ if ((p->itemc++) >= MAX_PARTY)
+ p->itemc = 0;
+ if ((flag = pc_additem(ditem->first_sd,&temp_item,ditem->amount))) {
+ clif_additem(ditem->first_sd,0,0,flag);
+ drop_flag = 1;
+ }
+ }
+ }
+ } else
+ #endif
+ if(battle_config.item_auto_get || ditem->first_sd->autoloot){//Autoloot added by Upa-Kun
+ drop_flag = 0;
+ if((flag = pc_additem(ditem->first_sd,&temp_item,ditem->amount))){
+ clif_additem(ditem->first_sd,0,0,flag);
+ drop_flag = 1;
+ }
}
- free(ditem);
- return 0;
}
- map_addflooritem(&temp_item,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
+ if (drop_flag) {
+ map_addflooritem(&temp_item,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
+ }
- free(ditem);
+ aFree(ditem);
return 0;
}
@@ -1962,22 +2057,49 @@ static int mob_delay_item_drop(int tid,unsigned int tick,int id,int data)
static int mob_delay_item_drop2(int tid,unsigned int tick,int id,int data)
{
struct delay_item_drop2 *ditem;
- int flag;
+ int flag, drop_flag = 1;
nullpo_retr(0, ditem=(struct delay_item_drop2 *)id);
- if(battle_config.item_auto_get){
- if(ditem->first_sd && (flag = pc_additem(ditem->first_sd,&ditem->item_data,ditem->item_data.amount))){
- clif_additem(ditem->first_sd,0,0,flag);
- map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
+ if (ditem->first_sd){
+ #if 0
+ if (ditem->first_sd->status.party_id > 0){
+ struct party *p;
+ if((p=party_search(ditem->first_sd->status.party_id)) && p->item){
+ struct map_session_data *sd = NULL;
+ int i;
+ for (i = p->itemc + 1; i!=p->itemc; i++) { // initialise counter and loop through the party
+ if (i >= MAX_PARTY)
+ i = 0; // reset counter to 1st person in party so it'll stop when it reaches "itemc"
+ if ((sd=p->member[i].sd)!=NULL && sd->bl.m == ditem->first_sd->bl.m)
+ break;
+ }
+ if (sd){ // if an appropiate party member was found
+ drop_flag = 0;
+ if ((p->itemc++) >= MAX_PARTY)
+ p->itemc = 0;
+ if((flag = pc_additem(ditem->first_sd,&ditem->item_data,ditem->item_data.amount))){
+ clif_additem(ditem->first_sd,0,0,flag);
+ drop_flag = 1;
+ }
+ }
+ }
+ } else
+ #endif
+ if(battle_config.item_auto_get || ditem->first_sd->autoloot){//Autoloot added by Upa-Kun
+ drop_flag = 0;
+ if((flag = pc_additem(ditem->first_sd,&ditem->item_data,ditem->item_data.amount))){
+ clif_additem(ditem->first_sd,0,0,flag);
+ drop_flag = 1;
+ }
}
- free(ditem);
- return 0;
}
- map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
+ if (drop_flag) {
+ map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
+ }
- free(ditem);
+ aFree(ditem);
return 0;
}
@@ -1985,44 +2107,49 @@ static int mob_delay_item_drop2(int tid,unsigned int tick,int id,int data)
* mob data is erased.
*------------------------------------------
*/
-int mob_delete(struct mob_data *md)
+void mob_unload(struct mob_data *md)
+{
+ nullpo_retv(md);
+ mob_remove_map(md, 0);
+ map_deliddb(&md->bl);
+ aFree(md);
+ md = NULL;
+}
+int mob_remove_map(struct mob_data *md, int type)
{
nullpo_retr(1, md);
if(md->bl.prev == NULL)
return 1;
mob_changestate(md,MS_DEAD,0);
- clif_clearchar_area(&md->bl,1);
+ clif_clearchar_area(&md->bl,type);
map_delblock(&md->bl);
- if(mob_get_viewclass(md->class) <= 1000)
- clif_clearchar_delay(gettick()+3000,&md->bl,0);
- mob_deleteslave(md);
- mob_setdelayspawn(md->bl.id);
+ if (md->lootitem){
+ aFree(md->lootitem);
+ md->lootitem = NULL;
+ }
+
return 0;
}
-
-int mob_catch_delete(struct mob_data *md,int type)
+int mob_delete(struct mob_data *md)
{
nullpo_retr(1, md);
- if(md->bl.prev == NULL)
- return 1;
- mob_changestate(md,MS_DEAD,0);
- clif_clearchar_area(&md->bl,type);
- map_delblock(&md->bl);
+ mob_remove_map(md, 1);
+ if (mob_get_viewclass(md->class_) <= 1000)
+ clif_clearchar_delay(gettick()+3000,&md->bl,0);
+ mob_deleteslave(md);
mob_setdelayspawn(md->bl.id);
return 0;
}
-
int mob_timer_delete(int tid, unsigned int tick, int id, int data)
{
- struct block_list *bl=map_id2bl(id);
- struct mob_data *md;
-
- nullpo_retr(0, bl);
+ struct mob_data *md=(struct mob_data *)map_id2bl(id);
+ nullpo_retr(0, md);
- md = (struct mob_data *)bl;
- mob_catch_delete(md,3);
+//for Alchemist CANNIBALIZE [Lupus]
+ mob_remove_map(md, 3);
+ mob_setdelayspawn(md->bl.id);
return 0;
}
@@ -2074,15 +2201,17 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
int mvp_damage,max_hp;
unsigned int tick = gettick();
struct map_session_data *mvp_sd = NULL, *second_sd = NULL,*third_sd = NULL;
- double dmg_rate,tdmg,temp;
+ struct block_list *master = NULL;
+ double tdmg,temp;
struct item item;
int ret;
int drop_rate;
- int skill,sp;
-
+ int race;
+
nullpo_retr(0, md); //srcはNULLで呼ばれる場合もあるので、他でチェック
- max_hp = battle_get_max_hp(&md->bl);
+ max_hp = status_get_max_hp(&md->bl);
+ race = status_get_race(&md->bl);
if(src && src->type == BL_PC) {
sd = (struct map_session_data *)src;
@@ -2108,7 +2237,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
return 0;
}
- if(md->sc_data[SC_ENDURE].timer == -1)
+ if(battle_config.monster_damage_delay && md->sc_data[SC_ENDURE].timer == -1)
mob_stop_walking(md,3);
if(damage > max_hp>>2)
skill_stop_dancing(&md->bl,0);
@@ -2123,7 +2252,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
if(!(type&2)) {
if(sd!=NULL){
for(i=0,minpos=0,mindmg=0x7fffffff;i<DAMAGELOG_SIZE;i++){
- if(md->dmglog[i].id==sd->bl.id)
+ //if(md->dmglog[i].id==sd->bl.id)
+ if(md->dmglog[i].id==sd->status.char_id)
break;
if(md->dmglog[i].id==0){
minpos=i;
@@ -2137,7 +2267,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
if(i<DAMAGELOG_SIZE)
md->dmglog[i].dmg+=damage;
else {
- md->dmglog[minpos].id=sd->bl.id;
+ //md->dmglog[minpos].id=sd->bl.id;
+ md->dmglog[minpos].id=sd->status.char_id;
md->dmglog[minpos].dmg=damage;
}
@@ -2148,7 +2279,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
struct pet_data *pd = (struct pet_data *)src;
nullpo_retr(0, pd);
for(i=0,minpos=0,mindmg=0x7fffffff;i<DAMAGELOG_SIZE;i++){
- if(md->dmglog[i].id==pd->msd->bl.id)
+ //if(md->dmglog[i].id==pd->msd->bl.id)
+ if(md->dmglog[i].id==pd->msd->status.char_id)
break;
if(md->dmglog[i].id==0){
minpos=i;
@@ -2162,7 +2294,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
if(i<DAMAGELOG_SIZE)
md->dmglog[i].dmg+=(damage*battle_config.pet_attack_exp_rate)/100;
else {
- md->dmglog[minpos].id=pd->msd->bl.id;
+ //md->dmglog[minpos].id=pd->msd->bl.id;
+ md->dmglog[minpos].id=pd->msd->status.char_id;
md->dmglog[minpos].dmg=(damage*battle_config.pet_attack_exp_rate)/100;
}
}
@@ -2195,88 +2328,92 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
}
md->hp-=damage;
-
- if(md->class >= 1285 && md->class <=1287) { // guardian hp update [Valaris]
+
+ if(md->class_ >= 1285 && md->class_ <=1287) { // guardian hp update [Valaris]
struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
if(gc) {
- if(md->bl.id==gc->GID0) {
+ if(md->bl.id==gc->GID0) {
gc->Ghp0=md->hp;
if(gc->Ghp0<=0) {
guild_castledatasave(gc->castle_id,10,0);
guild_castledatasave(gc->castle_id,18,0);
}
- }
- if(md->bl.id==gc->GID1) {
+ }
+ if(md->bl.id==gc->GID1) {
gc->Ghp1=md->hp;
if(gc->Ghp1<=0) {
guild_castledatasave(gc->castle_id,11,0);
guild_castledatasave(gc->castle_id,19,0);
}
}
- if(md->bl.id==gc->GID2) {
+ if(md->bl.id==gc->GID2) {
gc->Ghp2=md->hp;
if(gc->Ghp2<=0) {
guild_castledatasave(gc->castle_id,12,0);
guild_castledatasave(gc->castle_id,20,0);
}
}
- if(md->bl.id==gc->GID3) {
+ if(md->bl.id==gc->GID3) {
gc->Ghp3=md->hp;
if(gc->Ghp3<=0) {
guild_castledatasave(gc->castle_id,13,0);
guild_castledatasave(gc->castle_id,21,0);
}
}
- if(md->bl.id==gc->GID4) {
+ if(md->bl.id==gc->GID4) {
gc->Ghp4=md->hp;
if(gc->Ghp4<=0) {
guild_castledatasave(gc->castle_id,14,0);
guild_castledatasave(gc->castle_id,22,0);
}
}
- if(md->bl.id==gc->GID5) {
+ if(md->bl.id==gc->GID5) {
gc->Ghp5=md->hp;
if(gc->Ghp5<=0) {
guild_castledatasave(gc->castle_id,15,0);
guild_castledatasave(gc->castle_id,23,0);
}
}
- if(md->bl.id==gc->GID6) {
+ if(md->bl.id==gc->GID6) {
gc->Ghp6=md->hp;
if(gc->Ghp6<=0) {
guild_castledatasave(gc->castle_id,16,0);
guild_castledatasave(gc->castle_id,24,0);
}
}
- if(md->bl.id==gc->GID7) {
+ if(md->bl.id==gc->GID7) {
gc->Ghp7=md->hp;
if(gc->Ghp7<=0) {
guild_castledatasave(gc->castle_id,17,0);
guild_castledatasave(gc->castle_id,25,0);
-
+
}
}
}
} // end addition [Valaris]
-
+
if(md->option&2 )
- skill_status_change_end(&md->bl, SC_HIDING, -1);
+ status_change_end(&md->bl, SC_HIDING, -1);
if(md->option&4 )
- skill_status_change_end(&md->bl, SC_CLOAKING, -1);
+ status_change_end(&md->bl, SC_CLOAKING, -1);
if(md->state.special_mob_ai == 2){//スフィアーマイン
int skillidx=0;
-
- if((skillidx=mob_skillid2skillidx(md->class,NPC_SELFDESTRUCTION2))>=0){
+
+ if((skillidx=mob_skillid2skillidx(md->class_,NPC_SELFDESTRUCTION2))>=0){
md->mode |= 0x1;
md->next_walktime=tick;
mobskill_use_id(md,&md->bl,skillidx);//自爆詠唱開始
md->state.special_mob_ai++;
}
+ if (src && md->master_id==src->id)
+ md->target_dir=map_calc_dir(src,md->bl.x,md->bl.y)+1;
}
if(md->hp>0){
+ if (battle_config.show_mob_hp)
+ clif_update_mobhp (md);
return 0;
}
@@ -2289,19 +2426,33 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
memset(tmpsd,0,sizeof(tmpsd));
memset(pt,0,sizeof(pt));
- max_hp = battle_get_max_hp(&md->bl);
+ max_hp = status_get_max_hp(&md->bl);
if(src && src->type == BL_MOB)
mob_unlocktarget((struct mob_data *)src,tick);
- /* ソウルドレイン */
- if(sd && (skill=pc_checkskill(sd,HW_SOULDRAIN))>0){
- clif_skill_nodamage(src,&md->bl,HW_SOULDRAIN,skill,1);
- sp = (battle_get_lv(&md->bl))*(65+15*skill)/100;
- if(sd->status.sp + sp > sd->status.max_sp)
- sp = sd->status.max_sp - sd->status.sp;
- sd->status.sp += sp;
- clif_heal(sd->fd,SP_SP,sp);
+
+ if(sd) {
+ int sp = 0, hp = 0;
+ if (sd->state.attack_type == BF_MAGIC && (i=pc_checkskill(sd,HW_SOULDRAIN))>0){ /* ソウルドレイン */
+ clif_skill_nodamage(src,&md->bl,HW_SOULDRAIN,i,1);
+ sp += (status_get_lv(&md->bl))*(65+15*i)/100;
+ }
+ sp += sd->sp_gain_value;
+ sp += sd->sp_gain_race[race];
+ hp += sd->hp_gain_value;
+ if (sp > 0) {
+ if(sd->status.sp + sp > sd->status.max_sp)
+ sp = sd->status.max_sp - sd->status.sp;
+ sd->status.sp += sp;
+ clif_heal(sd->fd,SP_SP,sp);
+ }
+ if (hp > 0) {
+ if(sd->status.hp + hp > sd->status.max_hp)
+ hp = sd->status.max_hp - sd->status.hp;
+ sd->status.hp += hp;
+ clif_heal(sd->fd,SP_HP,hp);
+ }
}
// map外に消えた人は計算から除くので
@@ -2311,7 +2462,12 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
for(i=0,count=0,mvp_damage=0;i<DAMAGELOG_SIZE;i++){
if(md->dmglog[i].id==0)
continue;
- tmpsd[i] = map_id2sd(md->dmglog[i].id);
+ // Will this slow things down too much?
+ tmpsd[i] = map_charid2sd(md->dmglog[i].id);
+ // try finding again
+ if(tmpsd[i] == NULL)
+ tmpsd[i] = map_id2sd(md->dmglog[i].id);
+ // if we still can't find the player
if(tmpsd[i] == NULL)
continue;
count++;
@@ -2327,64 +2483,81 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
}
}
- // [MouseJstr]
- if((map[md->bl.m].flag.pvp == 0) || (battle_config.pvp_exp == 1)) {
-
- if((double)max_hp < tdmg)
- dmg_rate = ((double)max_hp) / tdmg;
- else dmg_rate = 1;
+ // [MouseJstr]
+ if((map[md->bl.m].flag.pvp == 0) || (battle_config.pvp_exp == 1)) {
// 経験値の分配
for(i=0;i<DAMAGELOG_SIZE;i++){
int pid,base_exp,job_exp,flag=1,zeny=0;
double per;
struct party *p;
- if(tmpsd[i]==NULL || tmpsd[i]->bl.m != md->bl.m)
+ if(tmpsd[i]==NULL || tmpsd[i]->bl.m != md->bl.m || pc_isdead(tmpsd[i]))
continue;
-/* jAthena's exp formula
- per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./((double)max_hp) * dmg_rate;
- temp = ((double)mob_db[md->class].base_exp * (double)battle_config.base_exp_rate / 100. * per);
- base_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
- if(mob_db[md->class].base_exp > 0 && base_exp < 1) base_exp = 1;
- if(base_exp < 0) base_exp = 0;
- temp = ((double)mob_db[md->class].job_exp * (double)battle_config.job_exp_rate / 100. * per);
- job_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
- if(mob_db[md->class].job_exp > 0 && job_exp < 1) job_exp = 1;
- if(job_exp < 0) job_exp = 0;
-*/
-//eAthena's exp formula rather than jAthena's
- per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/(double)max_hp;
- if(per>512) per=512;
- if(per<1) per=1;
- base_exp=mob_db[md->class].base_exp*per/256;
-
- if(base_exp < 1) base_exp = 1;
- if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class].lv - sd->status.base_level >= 20)) {
- base_exp*=1.15; // pk_mode additional exp if monster >20 levels [Valaris]
- }
- job_exp=mob_db[md->class].job_exp*per/256;
- if(job_exp < 1) job_exp = 1;
- if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class].lv - sd->status.base_level >= 20)) {
- job_exp*=1.15; // pk_mode additional exp if monster >20 levels [Valaris]
+
+ if (battle_config.exp_calc_type == 0) {
+ // jAthena's exp formula
+ per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./tdmg;
+ temp = (double)mob_db[md->class_].base_exp * per;
+ base_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
+ if(mob_db[md->class_].base_exp > 0 && base_exp < 1) base_exp = 1;
+ if(base_exp < 0) base_exp = 0;
+ temp = (double)mob_db[md->class_].job_exp * per;
+ job_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
+ if(mob_db[md->class_].job_exp > 0 && job_exp < 1) job_exp = 1;
+ if(job_exp < 0) job_exp = 0;
}
- if(md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) { // for summoned creatures [Valaris]
- base_exp = 0;
- job_exp = 0;
+ else if (battle_config.exp_calc_type == 1) {
+ //eAthena's exp formula rather than jAthena's
+ per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/(double)max_hp;
+ if(per>512) per=512;
+ if(per<1) per=1;
+ base_exp=(int) (mob_db[md->class_].base_exp*per/256);
+ if(base_exp < 1) base_exp = 1;
+ job_exp=(int) (mob_db[md->class_].job_exp*per/256);
+ if(job_exp < 1) job_exp = 1;
}
else {
- if(battle_config.zeny_from_mobs) {
- if(md->level > 0) zeny=(md->level+rand()%md->level)*per/256; // zeny calculation moblv + random moblv [Valaris]
- if(mob_db[md->class].mexp > 0)
+ //eAthena's exp formula rather than jAthena's, but based on total damage dealt
+ per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/tdmg;
+ if(per>512) per=512;
+ if(per<1) per=1;
+ base_exp=(int) (mob_db[md->class_].base_exp*per/256);
+ if(base_exp < 1) base_exp = 1;
+ job_exp=(int) (mob_db[md->class_].job_exp*per/256);
+ if(job_exp < 1) job_exp = 1;
+ }
+
+ if(sd) {
+ int rate;
+ if ((rate = sd->expaddrace[race]) > 0) {
+ base_exp = (100+rate)*base_exp/100;
+ job_exp = (100+rate)*job_exp/100;
+ }
+ if (battle_config.pk_mode && (mob_db[md->class_].lv - sd->status.base_level >= 20)) {
+ base_exp = (int) (base_exp *1.15); // pk_mode additional exp if monster >20 levels [Valaris]
+ job_exp = (int) (job_exp * 1.15);
+ }
+ }
+ if(md->master_id) {
+ if(((master = map_id2bl(md->master_id)) && status_get_mode(master)&0x20) || // check if its master is a boss (MVP's and minibosses)
+ (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1)) { // for summoned creatures [Valaris]
+ base_exp = 0;
+ job_exp = 0;
+ }
+ } else {
+ if(battle_config.zeny_from_mobs) {
+ if(md->level > 0) zeny=(int) ((md->level+rand()%md->level)*per/256); // zeny calculation moblv + random moblv [Valaris]
+ if(mob_db[md->class_].mexp > 0)
zeny*=rand()%250;
}
- if(battle_config.mobs_level_up && md->level > mob_db[md->class].lv) { // [Valaris]
- job_exp+=((md->level-mob_db[md->class].lv)*mob_db[md->class].job_exp*.03)*per/256;
- base_exp+=((md->level-mob_db[md->class].lv)*mob_db[md->class].base_exp*.03)*per/256;
+ if(battle_config.mobs_level_up && md->level > mob_db[md->class_].lv) { // [Valaris]
+ job_exp+=(int) (((md->level-mob_db[md->class_].lv)*mob_db[md->class_].job_exp*.03)*per/256);
+ base_exp+=(int) (((md->level-mob_db[md->class_].lv)*mob_db[md->class_].base_exp*.03)*per/256);
}
}
-
+
if((pid=tmpsd[i]->status.party_id)>0){ // パーティに入っている
- int j=0;
+ int j;
for(j=0;j<pnum;j++) // 公平パーティリストにいるかどうか
if(pt[j].id==pid)
break;
@@ -2422,26 +2595,31 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
// item drop
if(!(type&1)) {
- int log_item[8] = {0};
- for(i=0;i<8;i++){
+ int log_item[10] = {0}; //8 -> 10 Lupus
+ int drop_ore = -1,drop_items=0; //slot N for DROP LOG, number of dropped items
+ for(i=0;i<10;i++){ // 8 -> 10 Lupus
struct delay_item_drop *ditem;
int drop_rate;
- if(md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1) // Added [Valaris]
+ if((master && status_get_mode(master)&0x20) || // check if its master is a boss (MVP's and minibosses)
+ (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1)) // Added [Valaris]
break; // End
- if(mob_db[md->class].dropitem[i].nameid <= 0)
+ if(mob_db[md->class_].dropitem[i].nameid <= 0)
continue;
- drop_rate = mob_db[md->class].dropitem[i].p;
- if(drop_rate <= 0 && battle_config.drop_rate0item)
+ drop_rate = mob_db[md->class_].dropitem[i].p;
+ if(drop_rate <= 0 && !battle_config.drop_rate0item)
drop_rate = 1;
if(battle_config.drops_by_luk>0 && sd && md) drop_rate+=(sd->status.luk*battle_config.drops_by_luk)/100; // drops affected by luk [Valaris]
- if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class].lv - sd->status.base_level >= 20)) drop_rate*=1.25; // pk_mode increase drops if 20 level difference [Valaris]
- if(drop_rate <= rand()%10000)
+ if(sd && md && battle_config.pk_mode==1 && (mob_db[md->class_].lv - sd->status.base_level >= 20)) drop_rate = (int) (drop_rate*1.25); // pk_mode increase drops if 20 level difference [Valaris]
+ if(drop_rate < rand() % 10000 + 1) { //fixed 0.01% impossible drops bug [Lupus]
+ drop_ore = i; //we remember an empty slot to put there ORE DISCOVERY drop later.
continue;
+ }
+ drop_items++; //we count if there were any drops
ditem=(struct delay_item_drop *)aCalloc(1,sizeof(struct delay_item_drop));
- ditem->nameid = mob_db[md->class].dropitem[i].nameid;
+ ditem->nameid = mob_db[md->class_].dropitem[i].nameid;
log_item[i] = ditem->nameid;
ditem->amount = 1;
ditem->m = md->bl.m;
@@ -2453,18 +2631,14 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
add_timer(tick+500+i,mob_delay_item_drop,(int)ditem,0);
}
- #ifndef TXT_ONLY
- if(log_config.drop > 0)
- log_drop(mvp_sd, md->class, log_item);
- #endif
-
// Ore Discovery [Celest]
- if (pc_checkskill(sd,BS_FINDINGORE)>0 && 1 >= rand()%1000) {
+ if (sd == mvp_sd && pc_checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/100 >= rand()%1000) {
struct delay_item_drop *ditem;
- int itemid[17] = { 714, 756, 757, 969, 984, 985, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1002 };
ditem=(struct delay_item_drop *)aCalloc(1,sizeof(struct delay_item_drop));
- ditem->nameid = itemid[rand()%17];
- log_item[i] = ditem->nameid;
+ ditem->nameid = itemdb_searchrandomid(6);
+ if (drop_ore<0) i=8; //we have only 10 slots in LOG, there's a check to not overflow (9th item usually a card, so we use 8th slot)
+ log_item[i] = ditem->nameid; //it's for logging only
+ drop_items++; //we count if there were any drops
ditem->amount = 1;
ditem->m = md->bl.m;
ditem->x = md->bl.x;
@@ -2475,20 +2649,18 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
add_timer(tick+500+i,mob_delay_item_drop,(int)ditem,0);
}
- #ifndef TXT_ONLY
- if(log_config.drop > 0)
- log_drop(mvp_sd, md->class, log_item);
- #endif
+ //this drop log contains ALL dropped items + ORE (if there was ORE Recovery) [Lupus]
+ if(sd && log_config.drop > 0 && drop_items) //we check were there any drops.. and if not - don't write the log
+ log_drop(sd, md->class_, log_item); //mvp_sd
if(sd && sd->state.attack_type == BF_WEAPON) {
for(i=0;i<sd->monster_drop_item_count;i++) {
struct delay_item_drop *ditem;
- int race = battle_get_race(&md->bl);
if(sd->monster_drop_itemid[i] <= 0)
continue;
- if(sd->monster_drop_race[i] & (1<<race) ||
- (mob_db[md->class].mode & 0x20 && sd->monster_drop_race[i] & 1<<10) ||
- (!(mob_db[md->class].mode & 0x20) && sd->monster_drop_race[i] & 1<<11) ) {
+ if(sd->monster_drop_race[i] & (1<<race) ||
+ (mob_db[md->class_].mode & 0x20 && sd->monster_drop_race[i] & 1<<10) ||
+ (!(mob_db[md->class_].mode & 0x20) && sd->monster_drop_race[i] & 1<<11) ) {
if(sd->monster_drop_itemrate[i] <= rand()%10000)
continue;
@@ -2505,7 +2677,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
}
}
if(sd->get_zeny_num > 0)
- pc_getzeny(sd,mob_db[md->class].lv*10 + rand()%(sd->get_zeny_num+1));
+ pc_getzeny(sd,mob_db[md->class_].lv*10 + rand()%(sd->get_zeny_num+1));
}
if(md->lootitem) {
for(i=0;i<md->lootitem_count;i++) {
@@ -2525,11 +2697,11 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
}
// mvp処理
- if(mvp_sd && mob_db[md->class].mexp > 0 ){
+ if(mvp_sd && mob_db[md->class_].mexp > 0 ){
int log_mvp[2] = {0};
int j;
int mexp;
- temp = ((double)mob_db[md->class].mexp * (double)battle_config.mvp_exp_rate * (9.+(double)count)/1000.);
+ temp = ((double)mob_db[md->class_].mexp * (9.+(double)count)/10.); //[Gengar]
mexp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
if(mexp < 1) mexp = 1;
clif_mvp_effect(mvp_sd); // エフェクト
@@ -2538,19 +2710,20 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
log_mvp[1] = mexp;
for(j=0;j<3;j++){
i = rand() % 3;
- if(mob_db[md->class].mvpitem[i].nameid <= 0)
+ if(mob_db[md->class_].mvpitem[i].nameid <= 0)
continue;
- drop_rate = mob_db[md->class].mvpitem[i].p;
- if(drop_rate <= 0 && battle_config.drop_rate0item)
+ drop_rate = mob_db[md->class_].mvpitem[i].p;
+ if(drop_rate <= 0 && !battle_config.drop_rate0item)
drop_rate = 1;
- if(drop_rate < battle_config.item_drop_mvp_min)
+/* if(drop_rate < battle_config.item_drop_mvp_min)
drop_rate = battle_config.item_drop_mvp_min;
- if(drop_rate > battle_config.item_drop_mvp_max)
+ else if(drop_rate > battle_config.item_drop_mvp_max) //fixed
drop_rate = battle_config.item_drop_mvp_max;
- if(drop_rate <= rand()%10000)
+*/
+ if(drop_rate <= rand()%10000+1) //if ==0, then it doesn't drop
continue;
memset(&item,0,sizeof(item));
- item.nameid=mob_db[md->class].mvpitem[i].nameid;
+ item.nameid=mob_db[md->class_].mvpitem[i].nameid;
item.identify=!itemdb_isequip3(item.nameid);
clif_mvp_item(mvp_sd,item.nameid);
log_mvp[0] = item.nameid;
@@ -2562,10 +2735,9 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
}
break;
}
- #ifndef TXT_ONLY
- if(log_config.mvpdrop > 0)
- log_mvpdrop(mvp_sd, md->class, log_mvp);
- #endif
+
+ if(log_config.mvpdrop > 0)
+ log_mvpdrop(mvp_sd, md->class_, log_mvp);
}
} // [MouseJstr]
@@ -2574,7 +2746,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
if(md->npc_event[0] && strcmp(((md->npc_event)+strlen(md->npc_event)-13),"::OnAgitBreak") == 0) {
printf("MOB.C: Run NPC_Event[OnAgitBreak].\n");
if (agit_flag == 1) //Call to Run NPC_Event[OnAgitBreak]
- guild_agit_break(md);
+ guild_agit_break(md);
}
// SCRIPT実行
@@ -2590,7 +2762,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
struct map_session_data *tmpsd;
int i;
for(i=0;i<fd_max;i++){
- if(session[i] && (tmpsd=session[i]->session_data) && tmpsd->state.auth) {
+ if(session[i] && (tmpsd= (struct map_session_data *) session[i]->session_data) && tmpsd->state.auth) {
if(md->bl.m == tmpsd->bl.m) {
sd = tmpsd;
break;
@@ -2606,7 +2778,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
clif_clearchar_area(&md->bl,1);
if(md->level) md->level=0;
map_delblock(&md->bl);
- if(mob_get_viewclass(md->class) <= 1000)
+ if(mob_get_viewclass(md->class_) <= 1000)
clif_clearchar_delay(tick+3000,&md->bl,0);
mob_deleteslave(md);
mob_setdelayspawn(md->bl.id);
@@ -2622,26 +2794,26 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
int mob_class_change(struct mob_data *md,int *value)
{
unsigned int tick = gettick();
- int i,c,hp_rate,max_hp,class,count = 0;
+ int i,c,hp_rate,max_hp,class_,count = 0;
nullpo_retr(0, md);
nullpo_retr(0, value);
- if(value[0]<=1000 || value[0]>2000)
+ if(value[0]<=1000 || value[0]>MAX_MOB_DB)
return 0;
if(md->bl.prev == NULL) return 0;
- while(count < 5 && value[count] > 1000 && value[count] <= 2000) count++;
+ while(count < 5 && value[count] > 1000 && value[count] <= MAX_MOB_DB) count++;
if(count < 1) return 0;
- class = value[rand()%count];
- if(class<=1000 || class>2000) return 0;
+ class_ = value[rand()%count];
+ if(class_<=1000 || class_>MAX_MOB_DB) return 0;
- max_hp = battle_get_max_hp(&md->bl);
+ max_hp = status_get_max_hp(&md->bl);
hp_rate = md->hp*100/max_hp;
- clif_mob_class_change(md,class);
- md->class = class;
- max_hp = battle_get_max_hp(&md->bl);
+ clif_mob_class_change(md,class_);
+ md->class_ = class_;
+ max_hp = status_get_max_hp(&md->bl);
if(battle_config.monster_class_change_full_recover==1) {
md->hp = max_hp;
memset(md->dmglog,0,sizeof(md->dmglog));
@@ -2651,14 +2823,14 @@ int mob_class_change(struct mob_data *md,int *value)
if(md->hp > max_hp) md->hp = max_hp;
else if(md->hp < 1) md->hp = 1;
- memcpy(md->name,mob_db[class].jname,24);
+ memcpy(md->name,mob_db[class_].jname,24);
memset(&md->state,0,sizeof(md->state));
md->attacked_id = 0;
md->target_id = 0;
md->move_fail_count = 0;
- md->speed = mob_db[md->class].speed;
- md->def_ele = mob_db[md->class].element;
+ md->speed = mob_db[md->class_].speed;
+ md->def_ele = mob_db[md->class_].element;
mob_changestate(md,MS_IDLE,0);
skill_castcancel(&md->bl,0);
@@ -2667,14 +2839,13 @@ int mob_class_change(struct mob_data *md,int *value)
md->next_walktime = tick+rand()%50+5000;
md->attackabletime = tick;
md->canmove_tick = tick;
- md->sg_count=0;
for(i=0,c=tick-1000*3600*10;i<MAX_MOBSKILL;i++)
md->skilldelay[i] = c;
md->skillid=0;
md->skilllv=0;
- if(md->lootitem == NULL && mob_db[class].mode&0x02)
+ if(md->lootitem == NULL && mob_db[class_].mode&0x02)
md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
skill_clear_unitgroup(&md->bl);
@@ -2692,15 +2863,16 @@ int mob_class_change(struct mob_data *md,int *value)
*/
int mob_heal(struct mob_data *md,int heal)
{
- int max_hp = battle_get_max_hp(&md->bl);
+ int max_hp;
nullpo_retr(0, md);
+ max_hp = status_get_max_hp(&md->bl);
md->hp += heal;
if( max_hp < md->hp )
md->hp = max_hp;
- if(md->class >= 1285 && md->class <=1287) { // guardian hp update [Valaris]
+ if(md->class_ >= 1285 && md->class_ <=1287) { // guardian hp update [Valaris]
struct guild_castle *gc=guild_mapname2gc(map[md->bl.m].name);
if(gc) {
if(md->bl.id==gc->GID0) gc->Ghp0=md->hp;
@@ -2714,6 +2886,9 @@ int mob_heal(struct mob_data *md,int heal)
}
} // end addition [Valaris]
+ if (battle_config.show_mob_hp)
+ clif_update_mobhp(md);
+
return 0;
}
@@ -2755,7 +2930,8 @@ 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,c,xs=0,ys=0,bx=x,by=y;
+ int i=0,xs=0,ys=0,bx=x,by=y;
+ int tick = gettick();
nullpo_retr(0, md);
@@ -2769,14 +2945,14 @@ 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セルを探索
xs=ys=9;
}
- while( ( x<0 || y<0 || ((c=read_gat(m,x,y))==1 || c==5) ) && (i++)<1000 ){
+ while( ( x<0 || y<0 || map_getcell(m,x,y,CELL_CHKNOPASS)) && (i++)<1000 ){
if( xs>0 && ys>0 && i<250 ){ // 指定位置付近の探索
x=bx+rand()%xs-xs/2;
y=by+rand()%ys-ys/2;
@@ -2793,7 +2969,7 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type)
}else {
m=md->bl.m;
if(battle_config.error_log==1)
- printf("MOB %d warp failed, class = %d\n",md->bl.id,md->class);
+ printf("MOB %d warp failed, class = %d\n",md->bl.id,md->class_);
}
md->target_id=0; // タゲを解除する
@@ -2804,10 +2980,11 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type)
if(type>0 && i==1000) {
if(battle_config.battle_log)
- printf("MOB %d warp to (%d,%d), class = %d\n",md->bl.id,x,y,md->class);
+ printf("MOB %d warp to (%d,%d), class = %d\n",md->bl.id,x,y,md->class_);
}
map_addblock(&md->bl);
+ skill_unit_move(&md->bl,tick,1);
if(type>0)
{
clif_spawnmob(md);
@@ -2833,7 +3010,6 @@ int mob_countslave_sub(struct block_list *bl,va_list ap)
nullpo_retr(0, c=va_arg(ap,int *));
nullpo_retr(0, md = (struct mob_data *)bl);
-
if( md->master_id==id )
(*c)++;
return 0;
@@ -2860,7 +3036,7 @@ int mob_countslave(struct mob_data *md)
int mob_summonslave(struct mob_data *md2,int *value,int amount,int flag)
{
struct mob_data *md;
- int bx,by,m,count = 0,class,k,a = amount;
+ int bx,by,m,count = 0,class_,k,a = amount;
nullpo_retr(0, md2);
nullpo_retr(0, value);
@@ -2869,24 +3045,24 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,int flag)
by=md2->bl.y;
m=md2->bl.m;
- if(value[0]<=1000 || value[0]>2000) // 値が異常なら召喚を止める
+ if(value[0]<=1000 || value[0]>MAX_MOB_DB) // 値が異常なら召喚を止める
return 0;
- while(count < 5 && value[count] > 1000 && value[count] <= 2000) count++;
+ while(count < 21 && value[count] > 1000 && value[count] <= 2000) count++;
if(count < 1) return 0;
for(k=0;k<count;k++) {
amount = a;
- class = value[k];
- if(class<=1000 || class>2000) continue;
+ class_ = value[k];
+ if(class_<=1000 || class_>MAX_MOB_DB) continue;
for(;amount>0;amount--){
- int x=0,y=0,c=0,i=0;
+ int x=0,y=0,i=0;
md=(struct mob_data *)aCalloc(1,sizeof(struct mob_data));
- if(mob_db[class].mode&0x02)
+ if(mob_db[class_].mode&0x02)
md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
else
md->lootitem=NULL;
- while((x<=0 || y<=0 || (c=map_getcell(m,x,y))==1 || c==5 ) && (i++)<100){
+ while((x<=0 || y<=0 || map_getcell(m,x,y,CELL_CHKNOPASS)) && (i++)<100){
x=rand()%9-4+bx;
y=rand()%9-4+by;
}
@@ -2895,7 +3071,7 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,int flag)
y=by;
}
- mob_spawn_dataset(md,"--ja--",class);
+ mob_spawn_dataset(md,"--ja--",class_);
md->bl.m=m;
md->bl.x=x;
md->bl.y=y;
@@ -2976,15 +3152,15 @@ int mob_counttargeted(struct mob_data *md,struct block_list *src,int target_lv)
*MOBskillから該当skillidのskillidxを返す
*------------------------------------------
*/
-int mob_skillid2skillidx(int class,int skillid)
+int mob_skillid2skillidx(int class_,int skillid)
{
int i;
- struct mob_skill *ms=mob_db[class].skill;
-
+ struct mob_skill *ms=mob_db[class_].skill;
+
if(ms==NULL)
return -1;
- for(i=0;i<mob_db[class].maxskill;i++){
+ for(i=0;i<mob_db[class_].maxskill;i++){
if(ms[i].skill_id == skillid)
return i;
}
@@ -3023,7 +3199,9 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
md->skilltimer=-1;
//沈黙や状態異常など
if(md->sc_data){
- if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1)
+ if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 ||
+ (!(mob_db[md->class_].mode & 0x20) && md->sc_data[SC_ROKISWEIL].timer != -1) ||
+ md->sc_data[SC_STEELBODY].timer != -1)
return 0;
if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
return 0;
@@ -3033,7 +3211,7 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
return 0;
}
if(md->skillid != NPC_EMOTION)
- md->last_thinktime=tick + battle_get_adelay(&md->bl);
+ md->last_thinktime=tick + status_get_adelay(&md->bl);
if((bl = map_id2bl(md->skilltarget)) == NULL || bl->prev==NULL){ //スキルターゲットが存在しない
//printf("mobskill_castend_id nullpo\n");//ターゲットがいないときはnullpoじゃなくて普通に終了
@@ -3043,12 +3221,12 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
return 0;
if(md->skillid == PR_LEXAETERNA) {
- struct status_change *sc_data = battle_get_sc_data(bl);
+ struct status_change *sc_data = status_get_sc_data(bl);
if(sc_data && (sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0)))
return 0;
}
else if(md->skillid == RG_BACKSTAP) {
- int dir = map_calc_dir(&md->bl,bl->x,bl->y),t_dir = battle_get_dir(bl);
+ int dir = map_calc_dir(&md->bl,bl->x,bl->y),t_dir = status_get_dir(bl);
int dist = distance(md->bl.x,md->bl.y,bl->x,bl->y);
if(bl->type != BL_SKILL && (dist == 0 || map_check_dir(dir,t_dir)))
return 0;
@@ -3058,14 +3236,14 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
return 0;
range = skill_get_range(md->skillid,md->skilllv);
if(range < 0)
- range = battle_get_range(&md->bl) - (range + 1);
+ range = status_get_range(&md->bl) - (range + 1);
if(range + battle_config.mob_skill_add_range < distance(md->bl.x,md->bl.y,bl->x,bl->y))
return 0;
md->skilldelay[md->skillidx]=tick;
if(battle_config.mob_skill_log)
- printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class);
+ printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class_);
// mob_stop_walking(md,0);
switch( skill_get_nk(md->skillid) )
@@ -3075,8 +3253,8 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
skill_castend_damage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0);
break;
case 1:// 支援系
- if(!mob_db[md->class].skill[md->skillidx].val[0] &&
- (md->skillid==AL_HEAL || (md->skillid==ALL_RESURRECTION && bl->type != BL_PC)) && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) )
+ if(!mob_db[md->class_].skill[md->skillidx].val[0] &&
+ (md->skillid==AL_HEAL || (md->skillid==ALL_RESURRECTION && bl->type != BL_PC)) && battle_check_undead(status_get_race(bl),status_get_elem_type(bl)) )
skill_castend_damage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0);
else
skill_castend_nodamage_id(&md->bl,bl,md->skillid,md->skilllv,tick,0);
@@ -3094,15 +3272,10 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data )
int mobskill_castend_pos( int tid, unsigned int tick, int id,int data )
{
struct mob_data* md=NULL;
- struct block_list *bl;
int range,maxcount;
- //mobskill_castend_id同様詠唱したMobが詠唱完了時にもういないというのはありそうなのでnullpoから除外
- if((bl=map_id2bl(id))==NULL)
- return 0;
+ nullpo_retr(0, md=(struct mob_data *)map_id2bl(id));
- nullpo_retr(0, md=(struct mob_data *)bl);
-
if( md->bl.type!=BL_MOB || md->bl.prev==NULL )
return 0;
@@ -3111,7 +3284,9 @@ int mobskill_castend_pos( int tid, unsigned int tick, int id,int data )
md->skilltimer=-1;
if(md->sc_data){
- if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1)
+ if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 ||
+ (!(mob_db[md->class_].mode & 0x20) && md->sc_data[SC_ROKISWEIL].timer != -1) ||
+ md->sc_data[SC_STEELBODY].timer != -1)
return 0;
if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
return 0;
@@ -3121,59 +3296,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, 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);
@@ -3190,13 +3322,13 @@ int mobskill_castend_pos( int tid, unsigned int tick, int id,int data )
range = skill_get_range(md->skillid,md->skilllv);
if(range < 0)
- range = battle_get_range(&md->bl) - (range + 1);
+ range = status_get_range(&md->bl) - (range + 1);
if(range + battle_config.mob_skill_add_range < distance(md->bl.x,md->bl.y,md->skillx,md->skilly))
return 0;
md->skilldelay[md->skillidx]=tick;
if(battle_config.mob_skill_log)
- printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class);
+ printf("MOB skill castend skill=%d, class = %d\n",md->skillid,md->class_);
// mob_stop_walking(md,0);
skill_castend_pos2(&md->bl,md->skillx,md->skilly,md->skillid,md->skilllv,tick,0);
@@ -3216,8 +3348,8 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
int skill_id, skill_lv, forcecast = 0;
nullpo_retr(0, md);
- nullpo_retr(0, ms=&mob_db[md->class].skill[skill_idx]);
-
+ nullpo_retr(0, ms=&mob_db[md->class_].skill[skill_idx]);
+
if( target==NULL && (target=map_id2bl(md->target_id))==NULL )
return 0;
@@ -3229,7 +3361,9 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
// 沈黙や異常
if(md->sc_data){
- if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1)
+ if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 ||
+ (!(mob_db[md->class_].mode & 0x20) && md->sc_data[SC_ROKISWEIL].timer != -1) ||
+ md->sc_data[SC_STEELBODY].timer != -1)
return 0;
if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
return 0;
@@ -3244,17 +3378,15 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
if(md->option&2 && skill_id!=TF_HIDING && skill_id!=AS_GRIMTOOTH && skill_id!=RG_BACKSTAP && skill_id!=RG_RAID)
return 0;
- if(map[md->bl.m].flag.gvg && (skill_id == SM_ENDURE || skill_id == AL_TELEPORT || skill_id == AL_WARP ||
- skill_id == WZ_ICEWALL || skill_id == TF_BACKSLIDING))
+ if(map[md->bl.m].flag.gvg && skill_db[skill_id].nocast & 4)
return 0;
-
if(skill_get_inf2(skill_id)&0x200 && md->bl.id == target->id)
return 0;
// 射程と障害物チェック
range = skill_get_range(skill_id,skill_lv);
if(range < 0)
- range = battle_get_range(&md->bl) - (range + 1);
+ range = status_get_range(&md->bl) - (range + 1);
if(!battle_check_range(&md->bl,target,range))
return 0;
@@ -3266,7 +3398,7 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
switch(skill_id){ /* 何か特殊な処理が必要 */
case ALL_RESURRECTION: /* リザレクション */
- if(target->type != BL_PC && battle_check_undead(battle_get_race(target),battle_get_elem_type(target))){ /* 敵がアンデッドなら */
+ if(target->type != BL_PC && battle_check_undead(status_get_race(target),status_get_elem_type(target))){ /* 敵がアンデッドなら */
forcecast=1; /* ターンアンデットと同じ詠唱時間 */
casttime=skill_castfix(&md->bl, skill_get_cast(PR_TURNUNDEAD,skill_lv) );
}
@@ -3276,10 +3408,15 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
case SA_SPELLBREAKER:
forcecast=1;
break;
+ case NPC_SUMMONSLAVE:
+ case NPC_SUMMONMONSTER:
+ if(md->master_id!=0)
+ return 0;
+ break;
}
if(battle_config.mob_skill_log)
- printf("MOB skill use target_id=%d skill=%d lv=%d cast=%d, class = %d\n",target->id,skill_id,skill_lv,casttime,md->class);
+ printf("MOB skill use target_id=%d skill=%d lv=%d cast=%d, class = %d\n",target->id,skill_id,skill_lv,casttime,md->class_);
if(casttime>0 || forcecast){ // 詠唱が必要
// struct mob_data *md2;
@@ -3288,8 +3425,9 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
md->bl.id, target->id, 0,0, skill_id,casttime);
// 詠唱反応モンスター
-/* if( target->type==BL_MOB && mob_db[(md2=(struct mob_data *)target)->class].mode&0x10 &&
- md2->state.state!=MS_ATTACK){
+ // future homunculus support?
+/* if(md->master_id && target->type==BL_MOB && (md2=(struct mob_data *)target) &&
+ mob_db[md2->class_].mode&0x10 && md2->state.state!=MS_ATTACK){
md2->target_id=md->bl.id;
md->state.targettype = ATTACKABLE;
md2->min_chase=13;
@@ -3307,7 +3445,7 @@ int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx)
md->skillidx = skill_idx;
if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1 && md->skillid != AS_CLOAKING)
- skill_status_change_end(&md->bl,SC_CLOAKING,-1);
+ status_change_end(&md->bl,SC_CLOAKING,-1);
if( casttime>0 ){
md->skilltimer =
@@ -3332,7 +3470,7 @@ int mobskill_use_pos( struct mob_data *md,
int skill_id, skill_lv;
nullpo_retr(0, md);
- nullpo_retr(0, ms=&mob_db[md->class].skill[skill_idx]);
+ nullpo_retr(0, ms=&mob_db[md->class_].skill[skill_idx]);
if( md->bl.prev==NULL )
return 0;
@@ -3342,7 +3480,9 @@ int mobskill_use_pos( struct mob_data *md,
//沈黙や状態異常など
if(md->sc_data){
- if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 || md->sc_data[SC_ROKISWEIL].timer != -1 || md->sc_data[SC_STEELBODY].timer != -1)
+ if(md->opt1>0 || md->sc_data[SC_DIVINA].timer != -1 ||
+ (!(mob_db[md->class_].mode & 0x20) && md->sc_data[SC_ROKISWEIL].timer != -1) ||
+ md->sc_data[SC_STEELBODY].timer != -1)
return 0;
if(md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER) //オートカウンター
return 0;
@@ -3366,7 +3506,7 @@ int mobskill_use_pos( struct mob_data *md,
bl.y = skill_y;
range = skill_get_range(skill_id,skill_lv);
if(range < 0)
- range = battle_get_range(&md->bl) - (range + 1);
+ range = status_get_range(&md->bl) - (range + 1);
if(!battle_check_range(&md->bl,&bl,range))
return 0;
@@ -3377,7 +3517,7 @@ int mobskill_use_pos( struct mob_data *md,
if(battle_config.mob_skill_log)
printf("MOB skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d, class = %d\n",
- skill_x,skill_y,skill_id,skill_lv,casttime,md->class);
+ skill_x,skill_y,skill_id,skill_lv,casttime,md->class_);
if( casttime>0 ) { // A cast time is required.
mob_stop_walking(md,0); // 歩行停止
@@ -3396,7 +3536,7 @@ int mobskill_use_pos( struct mob_data *md,
md->skilllv = skill_lv;
md->skillidx = skill_idx;
if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1)
- skill_status_change_end(&md->bl,SC_CLOAKING,-1);
+ status_change_end(&md->bl,SC_CLOAKING,-1);
if( casttime>0 ){
md->skilltimer =
add_timer( gettick()+casttime, mobskill_castend_pos, md->bl.id, 0 );
@@ -3428,7 +3568,7 @@ int mob_getfriendhpltmaxrate_sub(struct block_list *bl,va_list ap)
return 0;
rate=va_arg(ap,int);
fr=va_arg(ap,struct mob_data **);
- if( md->hp < mob_db[md->class].max_hp*rate/100 )
+ if( md->hp < mob_db[md->class_].max_hp*rate/100 )
(*fr)=md;
return 0;
}
@@ -3500,9 +3640,9 @@ int mobskill_use(struct mob_data *md,unsigned int tick,int event)
int i,max_hp;
nullpo_retr(0, md);
- nullpo_retr(0, ms = mob_db[md->class].skill);
+ nullpo_retr(0, ms = mob_db[md->class_].skill);
- max_hp = battle_get_max_hp(&md->bl);
+ max_hp = status_get_max_hp(&md->bl);
if(battle_config.mob_skill_use == 0 || md->skilltimer != -1)
return 0;
@@ -3513,7 +3653,7 @@ int mobskill_use(struct mob_data *md,unsigned int tick,int event)
if(md->sc_data[SC_SELFDESTRUCTION].timer!=-1) //自爆中はスキルを使わない
return 0;
- for(i=0;i<mob_db[md->class].maxskill;i++){
+ for(i=0;i<mob_db[md->class_].maxskill;i++){
int c2=ms[i].cond2,flag=0;
struct mob_data *fmd=NULL;
@@ -3579,24 +3719,24 @@ int mobskill_use(struct mob_data *md,unsigned int tick,int event)
continue;
// 自分の周囲
if( ms[i].target>=MST_AROUND1 ){
- int bx=x, by=y, i=0, c, m=bl->m, r=ms[i].target-MST_AROUND1;
+ int bx=x, by=y, i=0, m=bl->m, r=ms[i].target-MST_AROUND1;
do{
bx=x + rand()%(r*2+3) - r;
by=y + rand()%(r*2+3) - r;
}while( ( bx<=0 || by<=0 || bx>=map[m].xs || by>=map[m].ys ||
- ((c=read_gat(m,bx,by))==1 || c==5) ) && (i++)<1000);
+ map_getcell(m,bx,by,CELL_CHKNOPASS)) && (i++)<1000);
if(i<1000){
x=bx; y=by;
}
}
// 相手の周囲
if( ms[i].target>=MST_AROUND5 ){
- int bx=x, by=y, i=0, c, m=bl->m, r=(ms[i].target-MST_AROUND5)+1;
+ int bx=x, by=y, i=0,m=bl->m, r=(ms[i].target-MST_AROUND5)+1;
do{
bx=x + rand()%(r*2+1) - r;
by=y + rand()%(r*2+1) - r;
}while( ( bx<=0 || by<=0 || bx>=map[m].xs || by>=map[m].ys ||
- ((c=read_gat(m,bx,by))==1 || c==5) ) && (i++)<1000);
+ map_getcell(m,bx,by,CELL_CHKNOPASS)) && (i++)<1000);
if(i<1000){
x=bx; y=by;
}
@@ -3645,27 +3785,30 @@ int mobskill_event(struct mob_data *md,int flag)
int mob_gvmobcheck(struct map_session_data *sd, struct block_list *bl)
{
struct mob_data *md=NULL;
-
+
nullpo_retr(0,sd);
nullpo_retr(0,bl);
-
+
if(bl->type==BL_MOB && (md=(struct mob_data *)bl) &&
- (md->class == 1288 || md->class == 1287 || md->class == 1286 || md->class == 1285))
+ (md->class_ == 1288 || md->class_ == 1287 || md->class_ == 1286 || md->class_ == 1285))
{
struct guild_castle *gc=guild_mapname2gc(map[sd->bl.m].name);
struct guild *g=guild_search(sd->status.guild_id);
- if(g == NULL && md->class == 1288)
+ if(g == NULL && md->class_ == 1288)
return 0;//ギルド未加入ならダメージ無し
else if(gc != NULL && !map[sd->bl.m].flag.gvg)
return 0;//砦内でGvじゃないときはダメージなし
- else if(g && gc != NULL && g->guild_id == gc->guild_id)
- return 0;//自占領ギルドのエンペならダメージ無し
- else if(g && guild_checkskill(g,GD_APPROVAL) <= 0 && md->class == 1288)
- return 0;//正規ギルド承認がないとダメージ無し
-
+ else if(g) {
+ if (gc != NULL && g->guild_id == gc->guild_id)
+ return 0;//自占領ギルドのエンペならダメージ無し
+ else if(guild_checkskill(g,GD_APPROVAL) <= 0 && md->class_ == 1288)
+ return 0;//正規ギルド承認がないとダメージ無し
+ else if (gc && guild_check_alliance(gc->guild_id, g->guild_id, 0) == 1)
+ return 0; // 同盟ならダメージ無し
+ }
}
-
+
return 1;
}
/*==========================================
@@ -3692,53 +3835,53 @@ int mobskill_deltimer(struct mob_data *md )
* Since un-setting [ mob ] up was used, it is an initial provisional value setup.
*------------------------------------------
*/
-static int mob_makedummymobdb(int class)
+static int mob_makedummymobdb(int class_)
{
int i;
- sprintf(mob_db[class].name,"mob%d",class);
- sprintf(mob_db[class].jname,"mob%d",class);
- mob_db[class].lv=1;
- mob_db[class].max_hp=1000;
- mob_db[class].max_sp=1;
- mob_db[class].base_exp=2;
- mob_db[class].job_exp=1;
- mob_db[class].range=1;
- mob_db[class].atk1=7;
- mob_db[class].atk2=10;
- mob_db[class].def=0;
- mob_db[class].mdef=0;
- mob_db[class].str=1;
- mob_db[class].agi=1;
- mob_db[class].vit=1;
- mob_db[class].int_=1;
- mob_db[class].dex=6;
- mob_db[class].luk=2;
- mob_db[class].range2=10;
- mob_db[class].range3=10;
- mob_db[class].size=0;
- mob_db[class].race=0;
- mob_db[class].element=0;
- mob_db[class].mode=0;
- mob_db[class].speed=300;
- mob_db[class].adelay=1000;
- mob_db[class].amotion=500;
- mob_db[class].dmotion=500;
- mob_db[class].dropitem[0].nameid=909; // Jellopy
- mob_db[class].dropitem[0].p=1000;
- for(i=1;i<8;i++){
- mob_db[class].dropitem[i].nameid=0;
- mob_db[class].dropitem[i].p=0;
+ sprintf(mob_db[class_].name,"mob%d",class_);
+ sprintf(mob_db[class_].jname,"mob%d",class_);
+ mob_db[class_].lv=1;
+ mob_db[class_].max_hp=1000;
+ mob_db[class_].max_sp=1;
+ mob_db[class_].base_exp=2;
+ mob_db[class_].job_exp=1;
+ mob_db[class_].range=1;
+ mob_db[class_].atk1=7;
+ mob_db[class_].atk2=10;
+ mob_db[class_].def=0;
+ mob_db[class_].mdef=0;
+ mob_db[class_].str=1;
+ mob_db[class_].agi=1;
+ mob_db[class_].vit=1;
+ mob_db[class_].int_=1;
+ mob_db[class_].dex=6;
+ mob_db[class_].luk=2;
+ mob_db[class_].range2=10;
+ mob_db[class_].range3=10;
+ mob_db[class_].size=0;
+ mob_db[class_].race=0;
+ mob_db[class_].element=0;
+ mob_db[class_].mode=0;
+ mob_db[class_].speed=300;
+ mob_db[class_].adelay=1000;
+ mob_db[class_].amotion=500;
+ mob_db[class_].dmotion=500;
+ //mob_db[class_].dropitem[0].nameid=909; // Jellopy
+ //mob_db[class_].dropitem[0].p=1000;
+ for(i=1;i<10;i++){ // 8-> 10 Lupus
+ mob_db[class_].dropitem[i].nameid=0;
+ mob_db[class_].dropitem[i].p=0;
}
// Item1,Item2
- mob_db[class].mexp=0;
- mob_db[class].mexpper=0;
+ mob_db[class_].mexp=0;
+ mob_db[class_].mexpper=0;
for(i=0;i<3;i++){
- mob_db[class].mvpitem[i].nameid=0;
- mob_db[class].mvpitem[i].p=0;
+ mob_db[class_].mvpitem[i].nameid=0;
+ mob_db[class_].mvpitem[i].p=0;
}
for(i=0;i<MAX_RANDOMMONSTER;i++)
- mob_db[class].summonper[i]=0;
+ mob_db[class_].summonper[i]=0;
return 0;
}
@@ -3764,13 +3907,13 @@ static int mob_readdb(void)
return -1;
}
while(fgets(line,1020,fp)){
- int class,i;
- char *str[55],*p,*np;
+ int class_,i;
+ char *str[60],*p,*np; // 55->60 Lupus
if(line[0] == '/' && line[1] == '/')
continue;
- for(i=0,p=line;i<55;i++){
+ for(i=0,p=line;i<60;i++){
if((np=strchr(p,','))!=NULL){
str[i]=p;
*np=0;
@@ -3779,113 +3922,122 @@ static int mob_readdb(void)
str[i]=p;
}
- class=atoi(str[0]);
- if(class<=1000 || class>2000)
+ class_=atoi(str[0]);
+ if(class_<=1000 || class_>MAX_MOB_DB)
continue;
- mob_db[class].view_class=class;
- memcpy(mob_db[class].name,str[1],24);
- memcpy(mob_db[class].jname,str[2],24);
- mob_db[class].lv=atoi(str[3]);
- mob_db[class].max_hp=atoi(str[4]);
- mob_db[class].max_sp=atoi(str[5]);
-
- mob_db[class].base_exp=atoi(str[6]);
- if(mob_db[class].base_exp < 0)
- mob_db[class].base_exp = 0;
- else if(mob_db[class].base_exp > 0 && (mob_db[class].base_exp*battle_config.base_exp_rate/100 > 1000000000 ||
- mob_db[class].base_exp*battle_config.base_exp_rate/100 < 0))
- mob_db[class].base_exp=1000000000;
- else
- mob_db[class].base_exp*= battle_config.base_exp_rate/100;
-
- mob_db[class].job_exp=atoi(str[7]);
- if(mob_db[class].job_exp < 0)
- mob_db[class].job_exp = 0;
- else if(mob_db[class].job_exp > 0 && (mob_db[class].job_exp*battle_config.job_exp_rate/100 > 1000000000 ||
- mob_db[class].job_exp*battle_config.job_exp_rate/100 < 0))
- mob_db[class].job_exp=1000000000;
- else
- mob_db[class].job_exp*=battle_config.job_exp_rate/100;
-
- mob_db[class].range=atoi(str[8]);
- mob_db[class].atk1=atoi(str[9]);
- mob_db[class].atk2=atoi(str[10]);
- mob_db[class].def=atoi(str[11]);
- mob_db[class].mdef=atoi(str[12]);
- mob_db[class].str=atoi(str[13]);
- mob_db[class].agi=atoi(str[14]);
- mob_db[class].vit=atoi(str[15]);
- mob_db[class].int_=atoi(str[16]);
- mob_db[class].dex=atoi(str[17]);
- mob_db[class].luk=atoi(str[18]);
- mob_db[class].range2=atoi(str[19]);
- mob_db[class].range3=atoi(str[20]);
- mob_db[class].size=atoi(str[21]);
- mob_db[class].race=atoi(str[22]);
- mob_db[class].element=atoi(str[23]);
- mob_db[class].mode=atoi(str[24]);
- mob_db[class].speed=atoi(str[25]);
- mob_db[class].adelay=atoi(str[26]);
- mob_db[class].amotion=atoi(str[27]);
- mob_db[class].dmotion=atoi(str[28]);
-
- for(i=0;i<8;i++){
+ mob_db[class_].view_class=class_;
+ memcpy(mob_db[class_].name,str[1],24);
+ memcpy(mob_db[class_].jname,str[2],24);
+ mob_db[class_].lv=atoi(str[3]);
+ mob_db[class_].max_hp=atoi(str[4]);
+ mob_db[class_].max_sp=atoi(str[5]);
+
+ mob_db[class_].base_exp = atoi(str[6]);
+ if (mob_db[class_].base_exp <= 0)
+ mob_db[class_].base_exp = 0;
+ else if (mob_db[class_].base_exp * battle_config.base_exp_rate / 100 > 1000000000 ||
+ mob_db[class_].base_exp * battle_config.base_exp_rate / 100 < 0)
+ mob_db[class_].base_exp = 1000000000;
+ else {
+ mob_db[class_].base_exp = mob_db[class_].base_exp * battle_config.base_exp_rate / 100;
+ if (mob_db[class_].base_exp < 1)
+ mob_db[class_].base_exp = 1;
+ }
+
+ mob_db[class_].job_exp = atoi(str[7]);
+ if (mob_db[class_].job_exp <= 0)
+ mob_db[class_].job_exp = 0;
+ else if (mob_db[class_].job_exp * battle_config.job_exp_rate / 100 > 1000000000 ||
+ mob_db[class_].job_exp * battle_config.job_exp_rate / 100 < 0)
+ mob_db[class_].job_exp = 1000000000;
+ else {
+ mob_db[class_].job_exp = mob_db[class_].job_exp * battle_config.job_exp_rate / 100;
+ if (mob_db[class_].job_exp < 1)
+ mob_db[class_].job_exp = 1;
+ }
+
+ mob_db[class_].range=atoi(str[8]);
+ mob_db[class_].atk1=atoi(str[9]);
+ mob_db[class_].atk2=atoi(str[10]);
+ mob_db[class_].def=atoi(str[11]);
+ mob_db[class_].mdef=atoi(str[12]);
+ mob_db[class_].str=atoi(str[13]);
+ mob_db[class_].agi=atoi(str[14]);
+ mob_db[class_].vit=atoi(str[15]);
+ mob_db[class_].int_=atoi(str[16]);
+ mob_db[class_].dex=atoi(str[17]);
+ mob_db[class_].luk=atoi(str[18]);
+ mob_db[class_].range2=atoi(str[19]);
+ mob_db[class_].range3=atoi(str[20]);
+ mob_db[class_].size=atoi(str[21]);
+ mob_db[class_].race=atoi(str[22]);
+ mob_db[class_].element=atoi(str[23]);
+ mob_db[class_].mode=atoi(str[24]);
+ mob_db[class_].speed=atoi(str[25]);
+ mob_db[class_].adelay=atoi(str[26]);
+ mob_db[class_].amotion=atoi(str[27]);
+ mob_db[class_].dmotion=atoi(str[28]);
+
+ for(i=0;i<10;i++){ // 8 -> 10 Lupus
int rate = 0,type,ratemin,ratemax;
- mob_db[class].dropitem[i].nameid=atoi(str[29+i*2]);
- type = itemdb_type(mob_db[class].dropitem[i].nameid);
- if (type == 0) { // Added [Valaris]
- rate = battle_config.item_rate_heal;
+ mob_db[class_].dropitem[i].nameid=atoi(str[29+i*2]);
+ type = itemdb_type(mob_db[class_].dropitem[i].nameid);
+ if (type == 0) {
+ rate = battle_config.item_rate_heal * atoi(str[30+i*2]) / 100; //fix by Yor
ratemin = battle_config.item_drop_heal_min;
ratemax = battle_config.item_drop_heal_max;
}
else if (type == 2) {
- rate = battle_config.item_rate_use;
+ rate = battle_config.item_rate_use * atoi(str[30+i*2]) / 100; //fix by Yor
ratemin = battle_config.item_drop_use_min;
ratemax = battle_config.item_drop_use_max; // End
}
else if (type == 4 || type == 5 || type == 8) { // Changed to include Pet Equip
- rate = battle_config.item_rate_equip;
+ rate = battle_config.item_rate_equip * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_equip_min;
ratemax = battle_config.item_drop_equip_max;
}
else if (type == 6) {
- rate = battle_config.item_rate_card;
+ rate = battle_config.item_rate_card * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_card_min;
ratemax = battle_config.item_drop_card_max;
}
else {
- rate = battle_config.item_rate_common;
+ rate = battle_config.item_rate_common * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_common_min;
ratemax = battle_config.item_drop_common_max;
}
- rate = (rate / 100) * atoi(str[30+i*2]);
- rate = (rate < ratemin)? ratemin: (rate > ratemax)? ratemax: rate;
- mob_db[class].dropitem[i].p = rate;
+ mob_db[class_].dropitem[i].p = (rate < ratemin) ? ratemin : (rate > ratemax) ? ratemax: rate;
}
- // Item1,Item2
- mob_db[class].mexp=atoi(str[45])*battle_config.mvp_exp_rate/100;
- mob_db[class].mexpper=atoi(str[46]);
+ // MVP EXP Bonus, Chance: MEXP,ExpPer
+ mob_db[class_].mexp=atoi(str[49])*battle_config.mvp_exp_rate/100;
+ mob_db[class_].mexpper=atoi(str[50]);
+ // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per
for(i=0;i<3;i++){
- mob_db[class].mvpitem[i].nameid=atoi(str[47+i*2]);
- mob_db[class].mvpitem[i].p=atoi(str[48+i*2])*battle_config.mvp_item_rate/100;
+ int rate=atoi(str[52+i*2])*battle_config.mvp_item_rate/100; //idea of the fix from Freya
+ mob_db[class_].mvpitem[i].nameid=atoi(str[51+i*2]);
+ mob_db[class_].mvpitem[i].p= (rate < battle_config.item_drop_mvp_min)
+ ? battle_config.item_drop_mvp_min : (rate > battle_config.item_drop_mvp_max)
+ ? battle_config.item_drop_mvp_max : rate;
}
for(i=0;i<MAX_RANDOMMONSTER;i++)
- mob_db[class].summonper[i]=0;
- mob_db[class].maxskill=0;
-
- mob_db[class].sex=0;
- mob_db[class].hair=0;
- mob_db[class].hair_color=0;
- mob_db[class].weapon=0;
- mob_db[class].shield=0;
- mob_db[class].head_top=0;
- mob_db[class].head_mid=0;
- mob_db[class].head_buttom=0;
- mob_db[class].clothes_color=0; //Add for player monster dye - Valaris
+ mob_db[class_].summonper[i]=0;
+ mob_db[class_].maxskill=0;
+
+ mob_db[class_].sex=0;
+ mob_db[class_].hair=0;
+ mob_db[class_].hair_color=0;
+ mob_db[class_].weapon=0;
+ mob_db[class_].shield=0;
+ mob_db[class_].head_top=0;
+ mob_db[class_].head_mid=0;
+ mob_db[class_].head_buttom=0;
+ mob_db[class_].clothes_color=0; //Add for player monster dye - Valaris
}
fclose(fp);
- printf("read %s done\n",filename[i]);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n",filename[i]);
+ ShowStatus(tmp_output);
}
return 0;
}
@@ -3899,7 +4051,7 @@ static int mob_readdb_mobavail(void)
FILE *fp;
char line[1024];
int ln=0;
- int class,j,k;
+ int class_,j,k;
char *str[20],*p,*np;
if( (fp=fopen("db/mob_avail.txt","r"))==NULL ){
@@ -3918,39 +4070,42 @@ static int mob_readdb_mobavail(void)
*np=0;
p=np+1;
} else
- str[j]=p;
- }
+ str[j]=p;
+ }
if(str[0]==NULL)
continue;
- class=atoi(str[0]);
-
- if(class<=1000 || class>2000) // 値が異常なら処理しない。
+ class_=atoi(str[0]);
+ if(class_<=1000 || class_>MAX_MOB_DB) // 値が異常なら処理しない。
continue;
+
k=atoi(str[1]);
- if(k >= 0)
- mob_db[class].view_class=k;
-
- if((mob_db[class].view_class < 24) || (mob_db[class].view_class > 4000)) {
- mob_db[class].sex=atoi(str[2]);
- mob_db[class].hair=atoi(str[3]);
- mob_db[class].hair_color=atoi(str[4]);
- mob_db[class].weapon=atoi(str[5]);
- mob_db[class].shield=atoi(str[6]);
- mob_db[class].head_top=atoi(str[7]);
- mob_db[class].head_mid=atoi(str[8]);
- mob_db[class].head_buttom=atoi(str[9]);
- mob_db[class].option=atoi(str[10])&~0x46;
- mob_db[class].clothes_color=atoi(str[11]); // Monster player dye option - Valaris
+ if(k < 0)
+ continue;
+ if (j > 3 && k > 23 && k < 69)
+ k += 3977; // advanced job/baby class
+ mob_db[class_].view_class=k;
+
+ if((k < 24) || (k > 4000)) {
+ mob_db[class_].sex=atoi(str[2]);
+ mob_db[class_].hair=atoi(str[3]);
+ mob_db[class_].hair_color=atoi(str[4]);
+ mob_db[class_].weapon=atoi(str[5]);
+ mob_db[class_].shield=atoi(str[6]);
+ mob_db[class_].head_top=atoi(str[7]);
+ mob_db[class_].head_mid=atoi(str[8]);
+ mob_db[class_].head_buttom=atoi(str[9]);
+ mob_db[class_].option=atoi(str[10])&~0x46;
+ mob_db[class_].clothes_color=atoi(str[11]); // Monster player dye option - Valaris
}
-
- else if(atoi(str[2]) > 0) mob_db[class].equip=atoi(str[2]); // mob equipment [Valaris]
+ else if(atoi(str[2]) > 0) mob_db[class_].equip=atoi(str[2]); // mob equipment [Valaris]
ln++;
}
fclose(fp);
- printf("read db/mob_avail.txt done (count=%d)\n",ln);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/mob_avail.txt");
+ ShowStatus(tmp_output);
return 0;
}
@@ -3978,7 +4133,7 @@ static int mob_read_randommonster(void)
return -1;
}
while(fgets(line,1020,fp)){
- int class,per;
+ int class_,per;
if(line[0] == '/' && line[1] == '/')
continue;
memset(str,0,sizeof(str));
@@ -3991,13 +4146,14 @@ static int mob_read_randommonster(void)
if(str[0]==NULL || str[2]==NULL)
continue;
- class = atoi(str[0]);
+ class_ = atoi(str[0]);
per=atoi(str[2]);
- if((class>1000 && class<=2000) || class==0)
- mob_db[class].summonper[i]=per;
+ if((class_>1000 && class_<=MAX_MOB_DB) || class_==0)
+ mob_db[class_].summonper[i]=per;
}
fclose(fp);
- printf("read %s done\n",mobfile[i]);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n",mobfile[i]);
+ ShowStatus(tmp_output);
}
return 0;
}
@@ -4116,7 +4272,10 @@ static int mob_readskilldb(void)
ms->state=state[j].id;
}
ms->skill_id=atoi(sp[3]);
- ms->skill_lv=atoi(sp[4]);
+ j=atoi(sp[4]);
+ if (j<=0 || j>MAX_SKILL_DB)
+ continue;
+ ms->skill_lv=j;
ms->permillage=atoi(sp[5]);
ms->casttime=atoi(sp[6]);
ms->delay=atoi(sp[7]);
@@ -4149,21 +4308,61 @@ static int mob_readskilldb(void)
mob_db[mob_id].maxskill=i+1;
}
fclose(fp);
- printf("read %s done\n",filename[x]);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n",filename[x]);
+ ShowStatus(tmp_output);
}
return 0;
}
-
-void mob_reload(void)
+/*==========================================
+ * db/mob_race_db.txt reading
+ *------------------------------------------
+ */
+static int mob_readdb_race(void)
{
- /*
+ FILE *fp;
+ char line[1024];
+ int race,j,k;
+ char *str[20],*p,*np;
- <empty monster database>
- mob_read();
+ if( (fp=fopen("db/mob_race2_db.txt","r"))==NULL ){
+ printf("can't read db/mob_race2_db.txt\n");
+ return -1;
+ }
+
+ while(fgets(line,1020,fp)){
+ if(line[0]=='/' && line[1]=='/')
+ continue;
+ memset(str,0,sizeof(str));
- */
+ for(j=0,p=line;j<12;j++){
+ if((np=strchr(p,','))!=NULL){
+ str[j]=p;
+ *np=0;
+ p=np+1;
+ } else
+ str[j]=p;
+ }
+ if(str[0]==NULL)
+ continue;
+
+ race=atoi(str[0]);
+ if (race < 0 || race >= MAX_MOB_RACE_DB)
+ continue;
- do_init_mob();
+ for (j=1; j<20; j++) {
+ if (!str[j])
+ break;
+ k=atoi(str[j]);
+ if (k < 1000 || k > MAX_MOB_DB)
+ continue;
+ mob_db[k].race2 = race;
+ //mob_race_db[race][j] = k;
+ }
+ }
+ fclose(fp);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/mob_race2_db.txt");
+ ShowStatus(tmp_output);
+ return 0;
}
#ifndef TXT_ONLY
@@ -4174,11 +4373,12 @@ void mob_reload(void)
static int mob_read_sqldb(void)
{
char line[1024];
- int i,class,ln=0;
- char *str[55],*p,*np;
-
+ int i,class_;
+ long unsigned int ln=0;
+ char *str[60],*p,*np; // 55->60 Lupus
+
memset(mob_db,0,sizeof(mob_db));
-
+
sprintf (tmp_sql, "SELECT * FROM `%s`",mob_db_db);
if(mysql_query(&mmysql_handle, tmp_sql) ) {
printf("DB server Error (select %s to Memory)- %s\n",mob_db_db,mysql_error(&mmysql_handle) );
@@ -4186,7 +4386,7 @@ static int mob_read_sqldb(void)
sql_res = mysql_store_result(&mmysql_handle);
if (sql_res) {
while((sql_row = mysql_fetch_row(sql_res))){
- sprintf(line,"%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
+ sprintf(line,"%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
sql_row[0],sql_row[1],sql_row[2],sql_row[3],sql_row[4],
sql_row[5],sql_row[6],sql_row[7],sql_row[8],sql_row[9],
sql_row[10],sql_row[11],sql_row[12],sql_row[13],sql_row[14],
@@ -4197,9 +4397,10 @@ static int mob_read_sqldb(void)
sql_row[35],sql_row[36],sql_row[37],sql_row[38],sql_row[39],
sql_row[40],sql_row[41],sql_row[42],sql_row[43],sql_row[44],
sql_row[45],sql_row[46],sql_row[47],sql_row[48],sql_row[49],
- sql_row[50],sql_row[51],sql_row[52]);
+ sql_row[50],sql_row[51],sql_row[52],sql_row[53],sql_row[54],
+ sql_row[55],sql_row[56]);
- for(i=0,p=line;i<55;i++){
+ for(i=0,p=line;i<57;i++){
if((np=strchr(p,','))!=NULL){
str[i]=p;
*np=0;
@@ -4207,109 +4408,141 @@ static int mob_read_sqldb(void)
} else
str[i]=p;
}
-
- class=atoi(str[0]);
- if(class<=1000 || class>2000)
+
+ class_=atoi(str[0]);
+ if(class_<=1000 || class_>MAX_MOB_DB)
continue;
-
+
ln++;
-
- mob_db[class].view_class=class;
- memcpy(mob_db[class].name,str[1],24);
- memcpy(mob_db[class].jname,str[2],24);
- mob_db[class].lv=atoi(str[3]);
- mob_db[class].max_hp=atoi(str[4]);
- mob_db[class].max_sp=atoi(str[5]);
- mob_db[class].base_exp=atoi(str[6])*
- battle_config.base_exp_rate/100;
- if(mob_db[class].base_exp <= 0)
- mob_db[class].base_exp = 1;
- mob_db[class].job_exp=atoi(str[7])*
- battle_config.job_exp_rate/100;
- if(mob_db[class].job_exp <= 0)
- mob_db[class].job_exp = 1;
- mob_db[class].range=atoi(str[8]);
- mob_db[class].atk1=atoi(str[9]);
- mob_db[class].atk2=atoi(str[10]);
- mob_db[class].def=atoi(str[11]);
- mob_db[class].mdef=atoi(str[12]);
- mob_db[class].str=atoi(str[13]);
- mob_db[class].agi=atoi(str[14]);
- mob_db[class].vit=atoi(str[15]);
- mob_db[class].int_=atoi(str[16]);
- mob_db[class].dex=atoi(str[17]);
- mob_db[class].luk=atoi(str[18]);
- mob_db[class].range2=atoi(str[19]);
- mob_db[class].range3=atoi(str[20]);
- mob_db[class].size=atoi(str[21]);
- mob_db[class].race=atoi(str[22]);
- mob_db[class].element=atoi(str[23]);
- mob_db[class].mode=atoi(str[24]);
- mob_db[class].speed=atoi(str[25]);
- mob_db[class].adelay=atoi(str[26]);
- mob_db[class].amotion=atoi(str[27]);
- mob_db[class].dmotion=atoi(str[28]);
-
- for(i=0;i<8;i++){
+
+ mob_db[class_].view_class=class_;
+ memcpy(mob_db[class_].name,str[1],24);
+ memcpy(mob_db[class_].jname,str[2],24);
+ mob_db[class_].lv=atoi(str[3]);
+ mob_db[class_].max_hp=atoi(str[4]);
+ mob_db[class_].max_sp=atoi(str[5]);
+
+ mob_db[class_].base_exp = atoi(str[6]);
+ if (mob_db[class_].base_exp <= 0)
+ mob_db[class_].base_exp = 0;
+ else if (mob_db[class_].base_exp * battle_config.base_exp_rate / 100 > 1000000000 ||
+ mob_db[class_].base_exp * battle_config.base_exp_rate / 100 < 0)
+ mob_db[class_].base_exp = 1000000000;
+ else {
+ mob_db[class_].base_exp = mob_db[class_].base_exp * battle_config.base_exp_rate / 100;
+ if (mob_db[class_].base_exp < 1)
+ mob_db[class_].base_exp = 1;
+ }
+ mob_db[class_].job_exp = atoi(str[7]);
+ if (mob_db[class_].job_exp <= 0)
+ mob_db[class_].job_exp = 0;
+ else if (mob_db[class_].job_exp * battle_config.job_exp_rate / 100 > 1000000000 ||
+ mob_db[class_].job_exp * battle_config.job_exp_rate / 100 < 0)
+ mob_db[class_].job_exp = 1000000000;
+ else {
+ mob_db[class_].job_exp = mob_db[class_].job_exp * battle_config.job_exp_rate / 100;
+ if (mob_db[class_].job_exp < 1)
+ mob_db[class_].job_exp = 1;
+ }
+
+ mob_db[class_].range=atoi(str[8]);
+ mob_db[class_].atk1=atoi(str[9]);
+ mob_db[class_].atk2=atoi(str[10]);
+ mob_db[class_].def=atoi(str[11]);
+ mob_db[class_].mdef=atoi(str[12]);
+ mob_db[class_].str=atoi(str[13]);
+ mob_db[class_].agi=atoi(str[14]);
+ mob_db[class_].vit=atoi(str[15]);
+ mob_db[class_].int_=atoi(str[16]);
+ mob_db[class_].dex=atoi(str[17]);
+ mob_db[class_].luk=atoi(str[18]);
+ mob_db[class_].range2=atoi(str[19]);
+ mob_db[class_].range3=atoi(str[20]);
+ mob_db[class_].size=atoi(str[21]);
+ mob_db[class_].race=atoi(str[22]);
+ mob_db[class_].element=atoi(str[23]);
+ mob_db[class_].mode=atoi(str[24]);
+ mob_db[class_].speed=atoi(str[25]);
+ mob_db[class_].adelay=atoi(str[26]);
+ mob_db[class_].amotion=atoi(str[27]);
+ mob_db[class_].dmotion=atoi(str[28]);
+
+ for(i=0;i<10;i++){ // 8 -> 10 Lupus
int rate = 0,type,ratemin,ratemax;
- mob_db[class].dropitem[i].nameid=atoi(str[29+i*2]);
- type = itemdb_type(mob_db[class].dropitem[i].nameid);
+ mob_db[class_].dropitem[i].nameid=atoi(str[29+i*2]);
+ type = itemdb_type(mob_db[class_].dropitem[i].nameid);
if (type == 0) { // Added by Valaris
- rate = battle_config.item_rate_heal;
+ rate = battle_config.item_rate_heal * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_heal_min;
ratemax = battle_config.item_drop_heal_max;
}
else if (type == 2) {
- rate = battle_config.item_rate_use;
+ rate = battle_config.item_rate_use * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_use_min;
ratemax = battle_config.item_drop_use_max; // End
}
else if (type == 4 || type == 5 || type == 8) { // Changed to include Pet Equip
- rate = battle_config.item_rate_equip;
+ rate = battle_config.item_rate_equip * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_equip_min;
ratemax = battle_config.item_drop_equip_max;
}
else if (type == 6) {
- rate = battle_config.item_rate_card;
+ rate = battle_config.item_rate_card * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_card_min;
ratemax = battle_config.item_drop_card_max;
}
else {
- rate = battle_config.item_rate_common;
+ rate = battle_config.item_rate_common * atoi(str[30+i*2]) / 100;
ratemin = battle_config.item_drop_common_min;
ratemax = battle_config.item_drop_common_max;
}
- rate = (rate / 100) * atoi(str[30+i*2]);
- rate = (rate < ratemin)? ratemin: (rate > ratemax)? ratemax: rate;
- mob_db[class].dropitem[i].p = rate;
+
+ mob_db[class_].dropitem[i].p = (rate < ratemin) ? ratemin : (rate > ratemax) ? ratemax: rate;
}
-
- mob_db[class].mexp=atoi(str[45])*battle_config.mvp_exp_rate/100;
- mob_db[class].mexpper=atoi(str[46]);
+ // MVP EXP Bonus, Chance: MEXP,ExpPer
+ mob_db[class_].mexp=atoi(str[49])*battle_config.mvp_exp_rate/100;
+ mob_db[class_].mexpper=atoi(str[50]);
+ // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per
for(i=0;i<3;i++){
- mob_db[class].mvpitem[i].nameid=atoi(str[47+i*2]);
- mob_db[class].mvpitem[i].p=atoi(str[48+i*2])*battle_config.mvp_item_rate/100;
+ mob_db[class_].mvpitem[i].nameid=atoi(str[51+i*2]);
+ mob_db[class_].mvpitem[i].p=atoi(str[52+i*2])*battle_config.mvp_item_rate/100;
}
for(i=0;i<MAX_RANDOMMONSTER;i++)
- mob_db[class].summonper[i]=0;
- mob_db[class].maxskill=0;
-
- mob_db[class].sex=0;
- mob_db[class].hair=0;
- mob_db[class].hair_color=0;
- mob_db[class].weapon=0;
- mob_db[class].shield=0;
- mob_db[class].head_top=0;
- mob_db[class].head_mid=0;
- mob_db[class].head_buttom=0;
+ mob_db[class_].summonper[i]=0;
+ mob_db[class_].maxskill=0;
+
+ mob_db[class_].sex=0;
+ mob_db[class_].hair=0;
+ mob_db[class_].hair_color=0;
+ mob_db[class_].weapon=0;
+ mob_db[class_].shield=0;
+ mob_db[class_].head_top=0;
+ mob_db[class_].head_mid=0;
+ mob_db[class_].head_buttom=0;
}
mysql_free_result(sql_res);
- printf("read %s done (count=%d)\n",mob_db_db,ln);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,mob_db_db);
+ ShowStatus(tmp_output);
}
return 0;
}
-
#endif /* not TXT_ONLY */
+
+void mob_reload(void)
+{
+#ifndef TXT_ONLY
+ if(db_use_sqldbs)
+ mob_read_sqldb();
+ else
+#endif /* TXT_ONLY */
+ mob_readdb();
+
+ mob_readdb_mobavail();
+ mob_read_randommonster();
+ mob_readskilldb();
+ mob_readdb_race();
+}
+
/*==========================================
* Circumference initialization of mob
*------------------------------------------
@@ -4319,13 +4552,14 @@ int do_init_mob(void)
#ifndef TXT_ONLY
if(db_use_sqldbs)
mob_read_sqldb();
- else
+ else
#endif /* TXT_ONLY */
mob_readdb();
mob_readdb_mobavail();
mob_read_randommonster();
mob_readskilldb();
+ mob_readdb_race();
add_timer_func_list(mob_timer,"mob_timer");
add_timer_func_list(mob_delayspawn,"mob_delayspawn");
diff --git a/src/map/mob.h b/src/map/mob.h
index e5a83be0f..6613c5b6b 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -3,6 +3,10 @@
#define _MOB_H_
#define MAX_RANDOMMONSTER 3
+#define MAX_MOB_RACE_DB 6
+#define MAX_MOB_DB 2000 /* Change this to increase the table size in your mob_db to accomodate
+ numbers more than 2000 for mobs if you want to (and know what you're doing).
+ Be sure to note that 4001 to 4047 are for advanced classes. */
struct mob_skill {
short state;
@@ -26,9 +30,10 @@ struct mob_db {
int str,agi,vit,int_,dex,luk;
int range,range2,range3;
int size,race,element,mode;
+ short race2; // celest
int speed,adelay,amotion,dmotion;
int mexp,mexpper;
- struct { int nameid,p; } dropitem[8];
+ struct { int nameid,p; } dropitem[10]; //8 -> 10 Lupus
struct { int nameid,p; } mvpitem[3];
int view_class,sex;
short hair,hair_color,weapon,shield,head_top,head_mid,head_buttom,option,clothes_color; // [Valaris]
@@ -72,32 +77,35 @@ enum {
};
enum {
- MSS_IDLE, // 待機
- MSS_WALK, // 移動
- MSS_ATTACK, // 攻撃
- MSS_DEAD, // 死亡
- MSS_LOOT, // ルート
- MSS_CHASE, // 突撃
+ MSS_IDLE, // ?@
+ MSS_WALK, // ?
+ MSS_ATTACK, // U
+ MSS_DEAD, // S
+ MSS_LOOT, // [g
+ MSS_CHASE, // ?
};
int mobdb_searchname(const char *str);
int mobdb_checkid(const int id);
int mob_once_spawn(struct map_session_data *sd,char *mapname,
- int x,int y,const char *mobname,int class,int amount,const char *event);
+ int x,int y,const char *mobname,int class_,int amount,const char *event);
int mob_once_spawn_area(struct map_session_data *sd,char *mapname,
int x0,int y0,int x1,int y1,
- const char *mobname,int class,int amount,const char *event);
+ const char *mobname,int class_,int amount,const char *event);
int mob_spawn_guardian(struct map_session_data *sd,char *mapname, // Spawning Guardians [Valaris]
- int x,int y,const char *mobname,int class,int amount,const char *event,int guardian); // Spawning Guardians [Valaris]
+ int x,int y,const char *mobname,int class_,int amount,const char *event,int guardian); // Spawning Guardians [Valaris]
int mob_walktoxy(struct mob_data *md,int x,int y,int easy);
+//int mob_randomwalk(struct mob_data *md,int tick);
+//int mob_can_move(struct mob_data *md);
int mob_target(struct mob_data *md,struct block_list *bl,int dist);
int mob_stop_walking(struct mob_data *md,int type);
int mob_stopattack(struct mob_data *);
int mob_spawn(int);
+int mob_setdelayspawn(int);
int mob_damage(struct block_list *,struct mob_data*,int,int);
int mob_changestate(struct mob_data *md,int state,int type);
int mob_heal(struct mob_data*,int);
@@ -116,8 +124,9 @@ short mob_get_clothes_color(int); //player mob dye [Valaris]
int mob_get_equip(int); // mob equip [Valaris]
int do_init_mob(void);
+void mob_unload(struct mob_data *md);
+int mob_remove_map(struct mob_data *md, int type);
int mob_delete(struct mob_data *md);
-int mob_catch_delete(struct mob_data *md,int type);
int mob_timer_delete(int tid, unsigned int tick, int id, int data);
int mob_deleteslave(struct mob_data *md);
@@ -132,6 +141,7 @@ int mobskill_event(struct mob_data *md,int flag);
int mobskill_castend_id( int tid, unsigned int tick, int id,int data );
int mobskill_castend_pos( int tid, unsigned int tick, int id,int data );
int mob_summonslave(struct mob_data *md2,int *value,int amount,int flag);
+int mob_countslave(struct mob_data *md);
int mob_gvmobcheck(struct map_session_data *sd, struct block_list *bl);
void mob_reload(void);
diff --git a/src/map/npc.c b/src/map/npc.c
index b1f9c54ec..069597f83 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -15,29 +15,39 @@
#include "clif.h"
#include "intif.h"
#include "pc.h"
+#include "status.h"
#include "itemdb.h"
#include "script.h"
#include "mob.h"
#include "pet.h"
#include "battle.h"
#include "skill.h"
+#include "grfio.h"
+#include "showmsg.h"
#ifdef MEMWATCH
#include "memwatch.h"
#endif
-
+#ifdef _WIN32
+#undef isspace
+#define isspace(x) (x == ' ' || x == '\t')
+#endif
struct npc_src_list {
struct npc_src_list * next;
- struct npc_src_list * prev;
+// struct npc_src_list * prev; //[Shinomori]
char name[4];
-} ;
+};
-static struct npc_src_list *npc_src_first,*npc_src_last;
+static struct npc_src_list *npc_src_first=NULL;
+static struct npc_src_list *npc_src_last=NULL;
static int npc_id=START_NPC_NUM;
-static int npc_warp,npc_shop,npc_script,npc_mob;
-
+static int npc_warp=0;
+static int npc_shop=0;
+static int npc_script=0;
+static int npc_mob=0;
+char *current_file = NULL;
int npc_get_new_npc_id(void){ return npc_id++; }
static struct dbt *ev_db;
@@ -62,31 +72,33 @@ int npc_enable_sub( struct block_list *bl, va_list ap )
{
struct map_session_data *sd;
struct npc_data *nd;
- char *name=(char *)aCalloc(50,sizeof(char));
+ //char *name=(char *)aCallocA(50,sizeof(char)); // fixed [Shinomori]
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, nd=va_arg(ap,struct npc_data *));
if(bl->type == BL_PC && (sd=(struct map_session_data *)bl)){
+ char name[50]; // need 24 + 9 for the "::OnTouch"
if (nd->flag&1) // 無効化されている
return 1;
- memcpy(name,nd->name,50);
if(sd->areanpc_id==nd->bl.id)
return 1;
sd->areanpc_id=nd->bl.id;
- npc_event(sd,strcat(name,"::OnTouch"),0);
+
+ sprintf(name,"%s::OnTouch", nd->name);
+ npc_event(sd,name,0);
}
- free(name);
+ //aFree(name);
return 0;
}
int npc_enable(const char *name,int flag)
{
- struct npc_data *nd=strdb_search(npcname_db,name);
+ struct npc_data *nd= (struct npc_data *) strdb_search(npcname_db,name);
if (nd==NULL)
return 0;
-
+
if (flag&1) { // 有効化
nd->flag&=~1;
clif_spawnnpc(nd);
@@ -114,8 +126,17 @@ int npc_enable(const char *name,int flag)
*/
struct npc_data* npc_name2id(const char *name)
{
- return strdb_search(npcname_db,name);
+ return (struct npc_data *) strdb_search(npcname_db,name);
+}
+
+void ev_release(struct dbn *db, int which)
+{
+ if (which & 0x1)
+ aFree(db->key);
+ if (which & 0x2)
+ aFree(db->data);
}
+
/*==========================================
* イベントキューのイベント処理
*------------------------------------------
@@ -126,47 +147,69 @@ int npc_event_dequeue(struct map_session_data *sd)
sd->npc_id=0;
if (sd->eventqueue[0][0]) { // キューのイベント処理
- char *name=(char *)aCalloc(50,sizeof(char));
- int i;
+ size_t ev;
- memcpy(name,sd->eventqueue[0],50);
- for(i=MAX_EVENTQUEUE-2;i>=0;i--)
- memcpy(sd->eventqueue[i],sd->eventqueue[i+1],50);
- add_timer(gettick()+100,npc_event_timer,sd->bl.id,(int)name);
+ // find an empty place in eventtimer list
+ for(ev=0;ev<MAX_EVENTTIMER;ev++)
+ if( sd->eventtimer[ev]==-1 )
+ break;
+ if(ev<MAX_EVENTTIMER)
+ { // generate and insert the timer
+ int i;
+ // copy the first event name
+ char *name=(char *)aMalloc(50*sizeof(char));
+ memcpy(name,sd->eventqueue[0],50);
+ // shift queued events down by one
+ for(i=1;i<MAX_EVENTQUEUE;i++)
+ memcpy(sd->eventqueue[i-1],sd->eventqueue[i],50);
+ // clear the last event
+ sd->eventqueue[MAX_EVENTQUEUE-1][0]=0;
+ // add the timer
+ sd->eventtimer[ev]=add_timer(gettick()+100,pc_eventtimer,sd->bl.id,(int)name);//!!todo!!
+
+ }else
+ printf("npc_event_dequeue: event timer is full !\n");
}
return 0;
}
-int npc_delete(struct npc_data *nd)
-{
- nullpo_retr(1, nd);
-
- if(nd->bl.prev == NULL)
- return 1;
-
- clif_clearchar_area(&nd->bl,1);
- map_delblock(&nd->bl);
- return 0;
-}
-
/*==========================================
* イベントの遅延実行
*------------------------------------------
*/
int npc_event_timer(int tid,unsigned int tick,int id,int data)
{
+ char *eventname = (char *)data;
+ struct event_data *ev = (struct event_data *)strdb_search(ev_db,eventname);
+ struct npc_data *nd;
struct map_session_data *sd=map_id2sd(id);
- if (sd==NULL)
- return 0;
-
- npc_event(sd,(const char *)data,0);
- free((void*)data);
+ size_t i;
+
+ if((ev==NULL || (nd=ev->nd)==NULL))
+ {
+ if(battle_config.error_log)
+ printf("npc_event: event not found [%s]\n",eventname);
+ }
+ else
+ {
+ for(i=0;i<MAX_EVENTTIMER;i++) {
+ if( nd->eventtimer[i]==tid ) {
+ nd->eventtimer[i]=-1;
+ npc_event(sd,eventname,0); // sd NULL check is within
+ break;
+ }
+ }
+ if(i==MAX_EVENTTIMER && battle_config.error_log)
+ printf("npc_event_timer: event timer not found [%s]!\n",eventname);
+ }
+
+ aFree(eventname);
return 0;
}
int npc_timer_event(const char *eventname) // Added by RoVeRT
{
- struct event_data *ev=strdb_search(ev_db,eventname);
+ struct event_data *ev=(struct event_data *) strdb_search(ev_db,eventname);
struct npc_data *nd;
// int xs,ys;
@@ -220,7 +263,7 @@ int npc_timer(int tid,unsigned int tick,int id,int data) // Added by RoVeRT
{
strdb_foreach(npcname_db,npc_timer_sub);
- free((void*)data);
+ aFree((void*)data);
return 0;
}*/
/*==========================================
@@ -233,14 +276,14 @@ int npc_event_export(void *key,void *data,va_list ap)
char *lname=(char *)key;
int pos=(int)data;
struct npc_data *nd=va_arg(ap,struct npc_data *);
-
+
if ((lname[0]=='O' || lname[0]=='o')&&(lname[1]=='N' || lname[1]=='n')) {
struct event_data *ev;
char *buf;
char *p=strchr(lname,':');
// エクスポートされる
- ev=calloc(sizeof(struct event_data), 1);
- buf=calloc(50, 1);
+ ev=(struct event_data *) aCalloc(sizeof(struct event_data), 1);
+ buf=(char *) aCallocA(50, 1);
if (ev==NULL || buf==NULL) {
printf("npc_event_export: out of memory !\n");
exit(1);
@@ -261,62 +304,6 @@ int npc_event_export(void *key,void *data,va_list ap)
return 0;
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*==========================================
* 全てのNPCのOn*イベント実行
*------------------------------------------
@@ -326,29 +313,39 @@ int npc_event_doall_sub(void *key,void *data,va_list ap)
char *p=(char *)key;
struct event_data *ev;
int *c;
+ int rid;
const char *name;
nullpo_retr(0, ev=(struct event_data *)data);
nullpo_retr(0, ap);
nullpo_retr(0, c=va_arg(ap,int *));
-
name=va_arg(ap,const char *);
+ rid=va_arg(ap, int);
if( (p=strchr(p,':')) && p && strcmpi(name,p)==0 ){
- run_script(ev->nd->u.scr.script,ev->pos,0,ev->nd->bl.id);
+ run_script(ev->nd->u.scr.script,ev->pos,rid,ev->nd->bl.id);
(*c)++;
}
-
+
return 0;
}
int npc_event_doall(const char *name)
{
int c=0;
char buf[64]="::";
-
+
+ strncpy(buf+2,name,62);
+ strdb_foreach(ev_db,npc_event_doall_sub,&c,buf,0);
+ return c;
+}
+int npc_event_doall_id(const char *name, int rid)
+{
+ int c=0;
+ char buf[64]="::";
+
strncpy(buf+2,name,62);
- strdb_foreach(ev_db,npc_event_doall_sub,&c,buf);
- return c;
+ strdb_foreach(ev_db,npc_event_doall_sub,&c,buf,rid);
+ return c;
}
int npc_event_do_sub(void *key,void *data,va_list ap)
@@ -374,7 +371,7 @@ int npc_event_do_sub(void *key,void *data,va_list ap)
int npc_event_do(const char *name)
{
int c=0;
-
+
if (*name==':' && name[1]==':') {
return npc_event_doall(name+2);
}
@@ -394,7 +391,7 @@ int npc_event_do_clock(int tid,unsigned int tick,int id,int data)
char buf[64];
char *day="";
int c=0;
-
+
time(&timer);
t=localtime(&timer);
@@ -407,7 +404,7 @@ int npc_event_do_clock(int tid,unsigned int tick,int id,int data)
case 5: day = "Fri"; break;
case 6: day = "Sat"; break;
}
-
+
if (t->tm_min != ev_tm_b.tm_min ) {
sprintf(buf,"OnMinute%02d",t->tm_min);
c+=npc_event_doall(buf);
@@ -433,8 +430,10 @@ int npc_event_do_clock(int tid,unsigned int tick,int id,int data)
*/
int npc_event_do_oninit(void)
{
- int c = npc_event_doall("OnInit");
- printf("npc: OnInit Event done. (%d npc)\n",c);
+// int c = npc_event_doall("OnInit");
+ sprintf(tmp_output,"Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"
+ CL_WHITE"%d"CL_RESET"' NPCs.\n",npc_event_doall("OnInit"));
+ ShowStatus(tmp_output);
add_timer_interval(gettick()+100,
npc_event_do_clock,0,0,1000);
@@ -452,7 +451,7 @@ int npc_addeventtimer(struct npc_data *nd,int tick,const char *name)
if( nd->eventtimer[i]==-1 )
break;
if(i<MAX_EVENTTIMER){
- char *evname=malloc(24);
+ char *evname=(char *) aMallocA(24);
if(evname==NULL){
printf("npc_addeventtimer: out of memory !\n");exit(1);
}
@@ -493,33 +492,33 @@ int npc_cleareventtimer(struct npc_data *nd)
int npc_do_ontimer_sub(void *key,void *data,va_list ap)
{
- char *p=(char *)key;
- struct event_data *ev=(struct event_data *)data;
- int *c=va_arg(ap,int *);
+ char *p = (char *)key;
+ struct event_data *ev = (struct event_data *)data;
+ int *c = va_arg(ap,int *);
// struct map_session_data *sd=va_arg(ap,struct map_session_data *);
- int option=va_arg(ap,int);
- int tick=0;
+ int option = va_arg(ap,int);
+ int tick = 0;
char temp[10];
char event[50];
- if(ev->nd->bl.id==(int)*c && (p=strchr(p,':')) && p && strnicmp("::OnTimer",p,8)==0 ){
- sscanf(&p[9],"%s",temp);
- tick=atoi(temp);
+ if(ev->nd->bl.id == (int)*c && (p = strchr(p,':')) && strnicmp("::OnTimer",p,8) == 0){
+ sscanf(&p[9], "%s", temp);
+ tick = atoi(temp);
- strcpy( event, ev->nd->name);
- strcat( event, p);
+ strcpy(event, ev->nd->name);
+ strcat(event, p);
if (option!=0) {
- npc_addeventtimer(ev->nd,tick,event);
+ npc_addeventtimer(ev->nd, tick, event);
} else {
- npc_deleventtimer(ev->nd,event);
+ npc_deleventtimer(ev->nd, event);
}
}
return 0;
}
-int npc_do_ontimer(int npc_id, struct map_session_data *sd, int option)
+int npc_do_ontimer(int npc_id, int option)
{
- strdb_foreach(ev_db,npc_do_ontimer_sub,&npc_id,sd,option);
+ strdb_foreach(ev_db, npc_do_ontimer_sub, &npc_id, option);
return 0;
}
/*==========================================
@@ -533,13 +532,13 @@ int npc_timerevent_import(void *key,void *data,va_list ap)
int pos=(int)data;
struct npc_data *nd=va_arg(ap,struct npc_data *);
int t=0,i=0;
-
+
if(sscanf(lname,"OnTimer%d%n",&t,&i)==1 && lname[i]==':') {
// タイマーイベント
struct npc_timerevent_list *te=nd->u.scr.timer_event;
int j,i=nd->u.scr.timeramount;
- if(te==NULL) te=malloc(sizeof(struct npc_timerevent_list));
- else te=realloc( te, sizeof(struct npc_timerevent_list) * (i+1) );
+ if(te==NULL) te=(struct npc_timerevent_list*)aMallocA(sizeof(struct npc_timerevent_list));
+ else te= (struct npc_timerevent_list*)aRealloc( te, sizeof(struct npc_timerevent_list) * (i+1) );
if(te==NULL){
printf("npc_timerevent_import: out of memory !\n");
exit(1);
@@ -573,7 +572,7 @@ int npc_timerevent(int tid,unsigned int tick,int id,int data)
nd->u.scr.timertick=tick;
te=nd->u.scr.timer_event+ nd->u.scr.nexttimer;
nd->u.scr.timerid = -1;
-
+
t = nd->u.scr.timer+=data;
nd->u.scr.nexttimer++;
if( nd->u.scr.timeramount>nd->u.scr.nexttimer ){
@@ -581,14 +580,14 @@ int npc_timerevent(int tid,unsigned int tick,int id,int data)
nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,id,next);
}
- run_script(nd->u.scr.script,te->pos,0,nd->bl.id);
+ run_script(nd->u.scr.script,te->pos,nd->u.scr.rid,nd->bl.id);
return 0;
}
/*==========================================
* タイマーイベント開始
*------------------------------------------
*/
-int npc_timerevent_start(struct npc_data *nd)
+int npc_timerevent_start(struct npc_data *nd, int rid)
{
int j,n, next;
@@ -597,17 +596,19 @@ int npc_timerevent_start(struct npc_data *nd)
n=nd->u.scr.timeramount;
if( nd->u.scr.nexttimer>=0 || n==0 )
return 0;
-
+
for(j=0;j<n;j++){
if( nd->u.scr.timer_event[j].timer > nd->u.scr.timer )
break;
}
+ if(j>=n) // check if there is a timer to use !!BEFORE!! you write stuff to the structures [Shinomori]
+ return 0;
+
nd->u.scr.nexttimer=j;
nd->u.scr.timertick=gettick();
+ if (rid >= 0) nd->u.scr.rid=rid; // changed to: attaching to given rid by default [Shinomori]
+ // if rid is less than 0 leave it unchanged [celest]
- if(j>=n)
- return 0;
-
next = nd->u.scr.timer_event[j].timer - nd->u.scr.timer;
nd->u.scr.timerid = add_timer(gettick()+next,npc_timerevent,nd->bl.id,next);
return 0;
@@ -626,6 +627,7 @@ int npc_timerevent_stop(struct npc_data *nd)
if(nd->u.scr.timerid!=-1)
delete_timer(nd->u.scr.timerid,npc_timerevent);
nd->u.scr.timerid = -1;
+ nd->u.scr.rid = 0;
}
return 0;
}
@@ -660,7 +662,7 @@ int npc_settimerevent_tick(struct npc_data *nd,int newtimer)
npc_timerevent_stop(nd);
nd->u.scr.timer=newtimer;
if(flag>=0)
- npc_timerevent_start(nd);
+ npc_timerevent_start(nd, -1);
return 0;
}
@@ -670,7 +672,7 @@ int npc_settimerevent_tick(struct npc_data *nd,int newtimer)
*/
int npc_event(struct map_session_data *sd,const char *eventname,int mob_kill)
{
- struct event_data *ev=strdb_search(ev_db,eventname);
+ struct event_data *ev=(struct event_data *) strdb_search(ev_db,eventname);
struct npc_data *nd;
int xs,ys;
char mobevent[100];
@@ -686,7 +688,7 @@ int npc_event(struct map_session_data *sd,const char *eventname,int mob_kill)
if(mob_kill && (ev==NULL || (nd=ev->nd)==NULL)){
strcpy( mobevent, eventname);
strcat( mobevent, "::OnMyMobDead");
- ev=strdb_search(ev_db,mobevent);
+ ev= (struct event_data *) strdb_search(ev_db,mobevent);
if (ev==NULL || (nd=ev->nd)==NULL) {
if (strnicmp(eventname,"GM_MONSTER",10)!=0)
printf("npc_event: event not found [%s]\n",mobevent);
@@ -732,7 +734,7 @@ int npc_event(struct map_session_data *sd,const char *eventname,int mob_kill)
npc_event_dequeue(sd);
return 0;
}
-
+
sd->npc_id=nd->bl.id;
sd->npc_pos=run_script(nd->u.scr.script,ev->pos,sd->bl.id,nd->bl.id);
return 0;
@@ -753,7 +755,7 @@ int npc_command_sub(void *key,void *data,va_list ap)
if (strcmp(command,temp)==0)
run_script(ev->nd->u.scr.script,ev->pos,0,ev->nd->bl.id);
}
-
+
return 0;
}
@@ -782,7 +784,7 @@ int npc_touch_areanpc(struct map_session_data *sd,int m,int x,int y)
f=0;
continue;
}
-
+
switch(map[m].npc[i]->bl.subtype) {
case WARP:
xs=map[m].npc[i]->u.warp.xs;
@@ -813,15 +815,18 @@ int npc_touch_areanpc(struct map_session_data *sd,int m,int x,int y)
break;
case SCRIPT:
{
- char *name=(char *)aCalloc(50,sizeof(char));
+ //char *name=(char *)aCallocA(50,sizeof(char)); // fixed [Shinomori]
+ char name[50]; // need 24 max + 9 for "::OnTouch"
- memcpy(name,map[m].npc[i]->name,50);
- if(sd->areanpc_id==map[m].npc[i]->bl.id)
+ if(sd->areanpc_id == map[m].npc[i]->bl.id)
return 1;
- sd->areanpc_id=map[m].npc[i]->bl.id;
- if(npc_event(sd,strcat(name,"::OnTouch"),0)>0)
+ sd->areanpc_id = map[m].npc[i]->bl.id;
+
+ sprintf(name,"%s::OnTouch", map[m].npc[i]->name);
+
+ if( npc_event(sd,name,0)>0 )
npc_click(sd,map[m].npc[i]->bl.id);
- free(name);
+ //aFree(name);
break;
}
}
@@ -844,8 +849,8 @@ int npc_checknear(struct map_session_data *sd,int id)
printf("no such npc : %d\n",id);
return 1;
}
-
- if (nd->class<0) // イベント系は常にOK
+
+ if (nd->class_<0) // イベント系は常にOK
return 0;
// エリア判定
@@ -858,6 +863,32 @@ int npc_checknear(struct map_session_data *sd,int id)
}
/*==========================================
+ * NPCのオープンチャット発言
+ *------------------------------------------
+ */
+int npc_globalmessage(const char *name,char *mes)
+{
+ struct npc_data *nd=(struct npc_data *) strdb_search(npcname_db,name);
+ char temp[100];
+ char ntemp[50];
+ char *ltemp;
+
+ if(nd==NULL) return 0;
+ if(name==NULL) return 0;
+
+ ltemp=strchr(name,'#');
+ if(ltemp!=NULL) {
+ strncpy(ntemp,name,ltemp - name); // 123#456 の # から後ろを削除する
+ ntemp[ltemp - name]=0x00; // strncpy のバグ?使い方間違ってる?
+ }
+
+ snprintf(temp, sizeof temp ,"%s : %s",ntemp,mes);
+ clif_GlobalMessage(&nd->bl,temp);
+
+ return 0;
+}
+
+/*==========================================
* クリック時のNPC処理
*------------------------------------------
*/
@@ -957,7 +988,7 @@ int npc_buylist(struct map_session_data *sd,int n,unsigned short *item_list)
{
struct npc_data *nd;
double z;
- int i,j,w,skill,itemamount=0,new=0;
+ int i,j,w,skill,itemamount=0,new_=0;
nullpo_retr(3, sd);
nullpo_retr(3, item_list);
@@ -987,7 +1018,7 @@ int npc_buylist(struct map_session_data *sd,int n,unsigned short *item_list)
case ADDITEM_EXIST:
break;
case ADDITEM_NEW:
- new++;
+ new_++;
break;
case ADDITEM_OVERAMOUNT:
return 2;
@@ -999,7 +1030,7 @@ int npc_buylist(struct map_session_data *sd,int n,unsigned short *item_list)
return 1; // zeny不足
if (w+sd->weight > sd->max_weight)
return 2; // 重量超過
- if (pc_inventoryblank(sd)<new)
+ if (pc_inventoryblank(sd)<new_)
return 3; // 種類数超過
pc_payzeny(sd,(int)z);
@@ -1014,7 +1045,7 @@ int npc_buylist(struct map_session_data *sd,int n,unsigned short *item_list)
}
//商人経験値
-/* if ((sd->status.class == 5) || (sd->status.class == 10) || (sd->status.class == 18)) {
+/* if ((sd->status.class_ == 5) || (sd->status.class_ == 10) || (sd->status.class_ == 18)) {
z = z * pc_checkskill(sd,MC_DISCOUNT) / ((1 + 300 / itemamount) * 4000) * battle_config.shop_exp;
pc_gainexp(sd,0,z);
}*/
@@ -1022,7 +1053,7 @@ int npc_buylist(struct map_session_data *sd,int n,unsigned short *item_list)
if (sd->status.skill[MC_DISCOUNT].flag != 0)
skill = sd->status.skill[MC_DISCOUNT].flag - 2;
if (skill > 0) {
- z = (log(z * (double)skill) * (double)battle_config.shop_exp/100.);
+ z = z * (double)skill * (double)battle_config.shop_exp/10000.;
if (z < 1)
z = 1;
pc_gainexp(sd,0,(int)z);
@@ -1074,7 +1105,7 @@ int npc_selllist(struct map_session_data *sd,int n,unsigned short *item_list)
}
//商人経験値
-/* if ((sd->status.class == 5) || (sd->status.class == 10) || (sd->status.class == 18)) {
+/* if ((sd->status.class_ == 5) || (sd->status.class_ == 10) || (sd->status.class_ == 18)) {
z = z * pc_checkskill(sd,MC_OVERCHARGE) / ((1 + 500 / itemamount) * 4000) * battle_config.shop_exp ;
pc_gainexp(sd,0,z);
}*/
@@ -1082,7 +1113,7 @@ int npc_selllist(struct map_session_data *sd,int n,unsigned short *item_list)
if (sd->status.skill[MC_OVERCHARGE].flag != 0)
skill = sd->status.skill[MC_OVERCHARGE].flag - 2;
if (skill > 0) {
- z = (log(z * (double)skill) * (double)battle_config.shop_exp/100.);
+ z = z * (double)skill * (double)battle_config.shop_exp/10000.;
if (z < 1)
z = 1;
pc_gainexp(sd,0,(int)z);
@@ -1106,8 +1137,8 @@ static int calc_next_walk_step(struct npc_data *nd)
if(nd->walkpath.path_pos>=nd->walkpath.path_len)
return -1;
if(nd->walkpath.path[nd->walkpath.path_pos]&1)
- return battle_get_speed(&nd->bl)*14/10;
- return battle_get_speed(&nd->bl);
+ return status_get_speed(&nd->bl)*14/10;
+ return status_get_speed(&nd->bl);
}
@@ -1118,7 +1149,7 @@ static int calc_next_walk_step(struct npc_data *nd)
static int npc_walk(struct npc_data *nd,unsigned int tick,int data)
{
int moveblock;
- int i,ctype;
+ int i;
static int dirx[8]={0,-1,-1,-1,0,1,1,1};
static int diry[8]={1,1,0,-1,-1,-1,0,1};
int x,y,dx,dy;
@@ -1143,8 +1174,7 @@ static int npc_walk(struct npc_data *nd,unsigned int tick,int data)
x = nd->bl.x;
y = nd->bl.y;
- ctype = map_getcell(nd->bl.m,x,y);
- if(ctype == 1 || ctype == 5) {
+ if(map_getcell(nd->bl.m,x,y,CELL_CHKNOPASS)) {
npc_stop_walking(nd,1);
return 0;
}
@@ -1152,8 +1182,7 @@ static int npc_walk(struct npc_data *nd,unsigned int tick,int data)
dx = dirx[nd->dir];
dy = diry[nd->dir];
- ctype = map_getcell(nd->bl.m,x+dx,y+dy);
- if(ctype == 1 || ctype == 5) {
+ if(map_getcell(nd->bl.m,x+dx,y+dy,CELL_CHKNOPASS)) {
npc_walktoxy_sub(nd);
return 0;
}
@@ -1183,7 +1212,7 @@ static int npc_walk(struct npc_data *nd,unsigned int tick,int data)
if(nd->walkpath.path_pos>=nd->walkpath.path_len)
clif_fixnpcpos(nd); // When npc stops, retransmission current of a position.
-
+
}
return 0;
}
@@ -1228,7 +1257,7 @@ static int npc_walktimer(int tid,unsigned int tick,int id,int data)
if(nd->walktimer != tid){
return 0;
}
-
+
nd->walktimer=-1;
if(nd->bl.prev == NULL)
@@ -1293,7 +1322,7 @@ int npc_stop_walking(struct npc_data *nd,int type)
if(nd->state.state == MS_WALK || nd->state.state == MS_IDLE) {
int dx=0,dy=0;
-
+
nd->walkpath.path_len=0;
if(type&4){
dx=nd->to_x-nd->bl.x;
@@ -1318,7 +1347,7 @@ int npc_stop_walking(struct npc_data *nd,int type)
if(type&0x01)
clif_fixnpcpos(nd);
if(type&0x02) {
- int delay=battle_get_dmotion(&nd->bl);
+ int delay=status_get_dmotion(&nd->bl);
unsigned int tick = gettick();
if(nd->canmove_tick < tick)
nd->canmove_tick = tick + delay;
@@ -1327,6 +1356,56 @@ int npc_stop_walking(struct npc_data *nd,int type)
return 0;
}
+int npc_remove_map (struct npc_data *nd)
+{
+ nullpo_retr(1, nd);
+
+ if(nd->bl.prev == NULL)
+ return 1;
+
+#ifdef PCRE_SUPPORT
+ npc_chat_finalize(nd);
+#endif
+ clif_clearchar_area(&nd->bl,2);
+ strdb_erase(npcname_db, nd->name);
+ map_delblock(&nd->bl);
+ map_deliddb(&nd->bl);
+
+ return 0;
+}
+
+int npc_unload(struct npc_data *nd)
+{
+ nullpo_retr (0, nd);
+
+ if (nd->chat_id) {
+ struct chat_data *cd = (struct chat_data*)map_id2bl(nd->chat_id);
+ if (cd) aFree (cd);
+ cd = NULL;
+ }
+ if (nd->bl.subtype == SCRIPT) {
+ if (nd->u.scr.timerid != -1)
+ delete_timer(nd->u.scr.timerid, npc_timerevent);
+ npc_cleareventtimer (nd);
+ if (nd->u.scr.timer_event)
+ aFree(nd->u.scr.timer_event);
+ if (nd->u.scr.src_id == 0) {
+ if(nd->u.scr.script) {
+ aFree(nd->u.scr.script);
+ nd->u.scr.script = NULL;
+ }
+ if (nd->u.scr.label_list) {
+ aFree(nd->u.scr.label_list);
+ nd->u.scr.label_list = NULL;
+ }
+ }
+ }
+ npc_remove_map (nd);
+ aFree(nd);
+ nd = NULL;
+
+ return 0;
+}
//
// 初期化関係
@@ -1343,7 +1422,7 @@ void npc_clearsrcfile()
while( p ) {
struct npc_src_list *p2=p;
p=p->next;
- free(p2);
+ aFree(p2);
}
npc_src_first=NULL;
npc_src_last=NULL;
@@ -1354,7 +1433,7 @@ void npc_clearsrcfile()
*/
void npc_addsrcfile(char *name)
{
- struct npc_src_list *new;
+ struct npc_src_list *new_;
size_t len;
if ( strcmpi(name,"clear")==0 ) {
@@ -1362,16 +1441,27 @@ void npc_addsrcfile(char *name)
return;
}
- len = sizeof(*new) + strlen(name);
- new=(struct npc_src_list *)aCalloc(1,len);
- new->next = NULL;
- strncpy(new->name,name,strlen(name)+1);
+ {
+ // prevent multiple insert of source files
+ struct npc_src_list *p=npc_src_first;
+ while( p )
+ { // found the file, no need to insert it again
+ if( 0==strcmp(name,p->name) )
+ return;
+ p=p->next;
+ }
+ }
+
+ len = sizeof(*new_) + strlen(name);
+ new_=(struct npc_src_list *)aCalloc(1,len);
+ new_->next = NULL;
+ strncpy(new_->name,name,strlen(name)+1);
if (npc_src_first==NULL)
- npc_src_first = new;
+ npc_src_first = new_;
if (npc_src_last)
- npc_src_last->next = new;
+ npc_src_last->next = new_;
- npc_src_last=new;
+ npc_src_last=new_;
}
/*==========================================
* 読み込むnpcファイルの削除
@@ -1391,7 +1481,7 @@ void npc_delsrcfile(char *name)
*lp=p->next;
if ( npc_src_last==p )
npc_src_last=pp;
- free(p);
+ aFree(p);
break;
}
}
@@ -1432,9 +1522,9 @@ int npc_parse_warp(char *w1,char *w2,char *w3,char *w4)
nd->chat_id=0;
if (!battle_config.warp_point_debug)
- nd->class=WARP_CLASS;
+ nd->class_=WARP_CLASS;
else
- nd->class=WARP_DEBUG_CLASS;
+ nd->class_=WARP_DEBUG_CLASS;
nd->speed=200;
nd->option = 0;
nd->opt1 = 0;
@@ -1449,11 +1539,9 @@ int npc_parse_warp(char *w1,char *w2,char *w3,char *w4)
for(i=0;i<ys;i++) {
for(j=0;j<xs;j++) {
- int t;
- t=map_getcell(m,x-xs/2+j,y-ys/2+i);
- if (t==1 || t==5)
+ if(map_getcell(m,x-xs/2+j,y-ys/2+i,CELL_CHKNOPASS))
continue;
- map_setcell(m,x-xs/2+j,y-ys/2+i,t|0x80);
+ map_setcell(m,x-xs/2+j,y-ys/2+i,CELL_SETNPC);
}
}
@@ -1494,20 +1582,26 @@ static int npc_parse_shop(char *w1,char *w2,char *w3,char *w4)
while (p && pos < max) {
int nameid,value;
+ struct item_data *id;
p++;
if (sscanf(p, "%d:%d", &nameid, &value) != 2)
break;
nd->u.shop_item[pos].nameid = nameid;
- if (value < 0) {
- struct item_data *id = itemdb_search(nameid);
+ id = itemdb_search(nameid);
+ if (value < 0)
value = id->value_buy;
- }
nd->u.shop_item[pos].value = value;
+ // check for bad prices that can possibly cause exploits
+ if (value*75/100 < id->value_sell*124/100) {
+ sprintf (tmp_output, "Item %s [%d] buying:%d < selling:%d\n",
+ id->name, id->nameid, value*75/100, id->value_sell*124/100);
+ ShowWarning (tmp_output);
+ }
pos++;
p=strchr(p,',');
}
if (pos == 0) {
- free(nd);
+ aFree(nd);
return 1;
}
nd->u.shop_item[pos++].nameid = 0;
@@ -1520,14 +1614,14 @@ static int npc_parse_shop(char *w1,char *w2,char *w3,char *w4)
nd->dir = dir;
nd->flag = 0;
memcpy(nd->name, w3, 24);
- nd->class = atoi(w4);
+ nd->class_ = atoi(w4);
nd->speed = 200;
nd->chat_id = 0;
nd->option = 0;
nd->opt1 = 0;
nd->opt2 = 0;
nd->opt3 = 0;
-
+
nd = (struct npc_data *)aRealloc(nd,
sizeof(struct npc_data) + sizeof(nd->u.shop_item[0]) * pos);
@@ -1554,20 +1648,28 @@ int npc_convertlabel_db(void *key,void *data,va_list ap)
struct npc_label_list *lst;
int num;
char *p=strchr(lname,':');
-
+
nullpo_retr(0, ap);
nullpo_retr(0, nd=va_arg(ap,struct npc_data *));
lst=nd->u.scr.label_list;
num=nd->u.scr.label_list_num;
if(!lst){
- lst=(struct npc_label_list *)aCalloc(1,sizeof(struct npc_label_list));
+ lst=(struct npc_label_list *)aCallocA(1,sizeof(struct npc_label_list));
num=0;
}else
lst=(struct npc_label_list *)aRealloc(lst,sizeof(struct npc_label_list)*(num+1));
*p='\0';
- strncpy(lst[num].name,lname,24);
+
+ // here we check if the label fit into the buffer
+ if (strlen(lname)>23) {
+ printf("npc_parse_script: label name longer than 23 chars! '%s'\n (%s)", lname, current_file);
+ exit(1);
+ }
+ memcpy(lst[num].name,lname,strlen(lname)+1); //including EOS
+
+
*p=':';
lst[num].pos=pos;
nd->u.scr.label_list=lst;
@@ -1580,7 +1682,7 @@ int npc_convertlabel_db(void *key,void *data,va_list ap)
*/
static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line,FILE *fp,int *lines)
{
- int x,y,dir=0,m,xs=0,ys=0,class=0; // [Valaris] thanks to fov
+ int x,y,dir=0,m,xs=0,ys=0,class_=0; // [Valaris] thanks to fov
char mapname[24];
unsigned char *srcbuf=NULL,*script;
int srcsize=65536;
@@ -1609,94 +1711,92 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line
if(strcmp(w2,"script")==0){
// スクリプトの解析
- srcbuf=(char *)aCalloc(srcsize,sizeof(char));
+ srcbuf=(unsigned char *)aCallocA(srcsize,sizeof(char));
if (strchr(first_line,'{')) {
- strcpy(srcbuf,strchr(first_line,'{'));
+ strcpy((char *) srcbuf,strchr(first_line,'{'));
startline=*lines;
} else
srcbuf[0]=0;
while(1) {
- for(i=strlen(srcbuf)-1;i>=0 && isspace(srcbuf[i]);i--);
+ for(i=strlen((const char *) srcbuf)-1;i>=0 && isspace(srcbuf[i]);i--);
if (i>=0 && srcbuf[i]=='}')
break;
- fgets(line,1020,fp);
+ fgets((char *) line,1020,fp);
(*lines)++;
if (feof(fp))
break;
- if (strlen(srcbuf)+strlen(line)+1>=srcsize) {
+ if (strlen((char *) srcbuf)+strlen((char *) line)+1>=srcsize) {
srcsize += 65536;
- srcbuf = (char *)aRealloc(srcbuf, srcsize);
+ srcbuf = (unsigned char *)aRealloc(srcbuf, srcsize);
memset(srcbuf + srcsize - 65536, '\0', 65536);
}
if (srcbuf[0]!='{') {
- if (strchr(line,'{')) {
- strcpy(srcbuf,strchr(line,'{'));
+ if (strchr((char *) line,'{')) {
+ strcpy((char *) srcbuf,strchr((const char *) line,'{'));
startline=*lines;
}
} else
- strcat(srcbuf,line);
+ strcat((char *) srcbuf,(const char *) line);
}
- script=parse_script(srcbuf,startline);
+ script=(unsigned char *) parse_script((unsigned char *) srcbuf,startline);
if (script==NULL) {
// script parse error?
- free(srcbuf);
+ aFree(srcbuf);
return 1;
}
}else{
// duplicateする
-
+
char srcname[128];
struct npc_data *nd2;
if( sscanf(w2,"duplicate(%[^)])",srcname)!=1 ){
- printf("bad duplicate name! : %s",w2);
+ printf("bad duplicate name (in %s)! : %s",current_file, w2);
return 0;
}
if( (nd2=npc_name2id(srcname))==NULL ){
- printf("bad duplicate name! (not exist) : %s\n",srcname);
+ printf("bad duplicate name (in %s)! (not exist) : %s\n", current_file, srcname);
return 0;
}
- script=nd2->u.scr.script;
+ script=(unsigned char *)nd2->u.scr.script;
label_dup=nd2->u.scr.label_list;
label_dupnum=nd2->u.scr.label_list_num;
src_id=nd2->bl.id;
-
+
}// end of スクリプト解析
nd=(struct npc_data *)aCalloc(1,sizeof(struct npc_data));
if(m==-1){
// スクリプトコピー用のダミーNPC
-
- }else if( sscanf(w4,"%d,%d,%d",&class,&xs,&ys)==3) {
+
+ }else if( sscanf(w4,"%d,%d,%d",&class_,&xs,&ys)==3) {
// 接触型NPC
int i,j;
-
+
if (xs>=0)xs=xs*2+1;
if (ys>=0)ys=ys*2+1;
-
- if (class>=0) {
+
+ if (class_>=0) {
for(i=0;i<ys;i++) {
for(j=0;j<xs;j++) {
- int t;
- t=map_getcell(m,x-xs/2+j,y-ys/2+i);
- if (t==1 || t==5)
+ if(map_getcell(m,x-xs/2+j,y-ys/2+i,CELL_CHKNOPASS))
continue;
- map_setcell(m,x-xs/2+j,y-ys/2+i,t|0x80);
+ map_setcell(m,x-xs/2+j,y-ys/2+i,CELL_SETNPC);
}
}
}
-
+
nd->u.scr.xs=xs;
nd->u.scr.ys=ys;
} else { // クリック型NPC
- class=atoi(w4);
+ class_=atoi(w4);
nd->u.scr.xs=0;
nd->u.scr.ys=0;
}
-
- if (class<0 && m>=0) { // イベント型NPC
+
+ if (class_<0 && m>=0) { // イベント型NPC
evflag=1;
}
@@ -1719,9 +1819,9 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line
nd->bl.id=npc_get_new_npc_id();
nd->dir = dir;
nd->flag=0;
- nd->class=class;
+ nd->class_=class_;
nd->speed=200;
- nd->u.scr.script=script;
+ nd->u.scr.script=(char *) script;
nd->u.scr.src_id=src_id;
nd->chat_id=0;
nd->option = 0;
@@ -1730,7 +1830,7 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line
nd->opt3 = 0;
nd->walktimer=-1;
- //printf("script npc %s %d %d read done\n",mapname,nd->bl.id,nd->class);
+ //printf("script npc %s %d %d read done\n",mapname,nd->bl.id,nd->class_);
npc_script++;
nd->bl.type=BL_NPC;
nd->bl.subtype=SCRIPT;
@@ -1738,6 +1838,11 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line
nd->n=map_addnpc(m,nd);
map_addblock(&nd->bl);
+ // clear event timers upon initialise
+ memset(nd->eventqueue, 0, sizeof(nd->eventqueue));
+ for(i = 0; i < MAX_EVENTTIMER; i++)
+ nd->eventtimer[i] = -1;
+
if (evflag) { // イベント型
struct event_data *ev=(struct event_data *)aCalloc(1,sizeof(struct event_data));
ev->nd=nd;
@@ -1750,21 +1855,21 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line
//-----------------------------------------
- // ラベルデータの準備
+ // ラベルデータの準備
if(srcbuf){
// script本体がある場合の処理
-
+
// ラベルデータのコンバート
label_db=script_get_label_db();
strdb_foreach(label_db,npc_convertlabel_db,nd);
-
+
// もう使わないのでバッファ解放
- free(srcbuf);
+ aFree(srcbuf);
}else{
// duplicate
-// nd->u.scr.label_list=malloc(sizeof(struct npc_label_list)*label_dupnum);
+// nd->u.scr.label_list=aMallocA(sizeof(struct npc_label_list)*label_dupnum);
// memcpy(nd->u.scr.label_list,label_dup,sizeof(struct npc_label_list)*label_dupnum);
nd->u.scr.label_list=label_dup; // ラベルデータ共有
@@ -1776,25 +1881,76 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line
for(i=0;i<nd->u.scr.label_list_num;i++){
char *lname=nd->u.scr.label_list[i].name;
int pos=nd->u.scr.label_list[i].pos;
-
+
if ((lname[0]=='O' || lname[0]=='o')&&(lname[1]=='N' || lname[1]=='n')) {
+/*
+I rearrange the code so this is just for commenting; remove it if you have enough if it [Shinomori]
struct event_data *ev;
char *buf;
// エクスポートされる
ev=(struct event_data *)aCalloc(1,sizeof(struct event_data));
- buf=(char *)aCalloc(50,sizeof(char));
+why allocing 50 chars ?
+ buf=(char *)aCallocA(50,sizeof(char));
+why checking here?
+lname is identical to nd->u.scr.label_list[i].name which is only 24 chars so check for strlen should be 23
if (strlen(lname)>24) {
- printf("npc_parse_script: label name error !\n");
+ printf("npc_parse_script: label name error (%s) !\n", current_file);
exit(1);
}else{
+ //struct event_data *ev2;
ev->nd=nd;
ev->pos=pos;
sprintf(buf,"%s::%s",nd->exname,lname);
+ //ev2 = strdb_search(ev_db,buf);
+ //if(ev2 != NULL) {
+ // printf("npc_parse_script : duplicate event %s\n",buf);
+ // aFree(ev2);
+ //}
+you are sure reentering the same database key will overwrite the existing entry?
strdb_insert(ev_db,buf,ev);
+anyway instead of removing data from the db and inserting a new one
+wouldn't it be easier just not to insert the new duplicate event, it is a duplicate anyway?
+ }
+*/
+ // this check is useless here because the buffer is only 24 chars
+ // and already overwritten if this is here is reached
+ // I leave the check anyway but place it correctly to npc_convertlabel_db
+ if (strlen(lname)>23) {
+ printf("npc_parse_script: label name longer than 23 chars! '%s' (%s)\n", lname, current_file);
+ exit(1);
+ }else{
+ struct event_data *ev;
+ struct event_data *ev2;
+ char *buf;
+ // エクスポートされる
+
+ // 51 comes from: 24 for npc name + 24 for label + 2 for a "::" and 1 for EOS
+ //buf=(char *)aMalloc(51,sizeof(char));
+ // but to save some memory we alloc only the really necessary space
+ buf=(char *)aMalloc( (3+strlen(nd->exname)+strlen(lname))*sizeof(char));
+ sprintf(buf,"%s::%s",nd->exname,lname);
+
+ // search the label in ev_db;
+ // remember the label is max 50 chars + eos; see the strdb_init below
+ ev2 = (struct event_data *)strdb_search(ev_db,buf);
+ if(ev2 != NULL) {
+ printf("npc_parse_script : duplicate event %s (%s)\n",buf, current_file);
+
+ // just skip the label insertion and free the alloced buffer
+ aFree(buf);
+ }
+ else
+ { // generate the data and insert it
+ ev=(struct event_data *)aCalloc(1,sizeof(struct event_data));
+ ev->nd=nd;
+ ev->pos=pos;
+ strdb_insert(ev_db,buf,ev);
+ }
+
}
}
}
-
+
//-----------------------------------------
// ラベルデータからタイマーイベント取り込み
for(i=0;i<nd->u.scr.label_list_num;i++){
@@ -1806,7 +1962,7 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line
struct npc_timerevent_list *te=nd->u.scr.timer_event;
int j,k=nd->u.scr.timeramount;
if(te==NULL)
- te=(struct npc_timerevent_list *)aCalloc(1,sizeof(struct npc_timerevent_list));
+ te=(struct npc_timerevent_list *)aCallocA(1,sizeof(struct npc_timerevent_list));
else
te=(struct npc_timerevent_list *)aRealloc( te, sizeof(struct npc_timerevent_list) * (k+1) );
for(j=0;j<k;j++){
@@ -1824,7 +1980,7 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line
nd->u.scr.nexttimer=-1;
nd->u.scr.timerid=-1;
-
+
return 0;
}
@@ -1843,7 +1999,7 @@ static int npc_parse_function(char *w1,char *w2,char *w3,char *w4,char *first_li
char *p;
// スクリプトの解析
- srcbuf=(char *)aCalloc(srcsize,sizeof(char));
+ srcbuf=(char *)aCallocA(srcsize,sizeof(char));
if (strchr(first_line,'{')) {
strcpy(srcbuf,strchr(first_line,'{'));
startline=*lines;
@@ -1870,14 +2026,14 @@ static int npc_parse_function(char *w1,char *w2,char *w3,char *w4,char *first_li
} else
strcat(srcbuf,line);
}
- script=parse_script(srcbuf,startline);
+ script= parse_script((unsigned char *) srcbuf,startline);
if (script==NULL) {
// script parse error?
- free(srcbuf);
+ aFree(srcbuf);
return 1;
}
- p=(char *)aCalloc(50,sizeof(char));
+ p=(char *)aCallocA(50,sizeof(char));
strncpy(p,w3,50);
strdb_insert(script_get_userfunc_db(),p,script);
@@ -1885,10 +2041,10 @@ static int npc_parse_function(char *w1,char *w2,char *w3,char *w4,char *first_li
// label_db=script_get_label_db();
// もう使わないのでバッファ解放
- free(srcbuf);
-
+ aFree(srcbuf);
+
// printf("function %s => %p\n",p,script);
-
+
return 0;
}
@@ -1899,7 +2055,7 @@ static int npc_parse_function(char *w1,char *w2,char *w3,char *w4,char *first_li
*/
int npc_parse_mob(char *w1,char *w2,char *w3,char *w4)
{
- int m,x,y,xs,ys,class,num,delay1,delay2,level;
+ int m,x,y,xs,ys,class_,num,delay1,delay2,level;
int i;
char mapname[24];
char mobname[24];
@@ -1910,7 +2066,7 @@ int npc_parse_mob(char *w1,char *w2,char *w3,char *w4)
delay1=delay2=0;
// 引数の個数チェック
if (sscanf(w1,"%[^,],%d,%d,%d,%d",mapname,&x,&y,&xs,&ys) < 3 ||
- sscanf(w4,"%d,%d,%d,%d,%s",&class,&num,&delay1,&delay2,eventname) < 2 ) {
+ sscanf(w4,"%d,%d,%d,%d,%s",&class_,&num,&delay1,&delay2,eventname) < 2 ) {
printf("bad monster line : %s\n",w3);
return 1;
}
@@ -1925,13 +2081,13 @@ int npc_parse_mob(char *w1,char *w2,char *w3,char *w4)
for(i=0;i<num;i++) {
md=(struct mob_data *)aCalloc(1,sizeof(struct mob_data));
- if(class>4000) { // large/tiny mobs [Valaris]
+ if(class_>4000) { // large/tiny mobs [Valaris]
md->size=2;
- class-=4000;
+ class_-=4000;
}
- else if(class>2000) {
+ else if(class_>2000) {
md->size=1;
- class-=2000;
+ class_-=2000;
}
md->bl.prev=NULL;
@@ -1940,19 +2096,16 @@ int npc_parse_mob(char *w1,char *w2,char *w3,char *w4)
md->bl.x=x;
md->bl.y=y;
- if(sscanf(w3,"%[^,],%d",mobname,&level) > 1) {
- if(strcmp(mobname,"--en--")==0)
- memcpy(md->name,mob_db[class].name,24);
- else if(strcmp(mobname,"--ja--")==0)
- memcpy(md->name,mob_db[class].jname,24);
+ if(sscanf(w3,"%[^,],%d",mobname,&level) > 1)
md->level=level;
- }
-
- else
- memcpy(md->name,w3,24);
+ if(strcmp(mobname,"--en--")==0)
+ memcpy(md->name,mob_db[class_].name,24);
+ else if(strcmp(mobname,"--ja--")==0)
+ memcpy(md->name,mob_db[class_].jname,24);
+ else memcpy(md->name,mobname,24);
md->n = i;
- md->base_class = md->class = class;
+ md->base_class = md->class_ = class_;
md->bl.id=npc_get_new_npc_id();
md->m =m;
md->x0=x;
@@ -1966,9 +2119,9 @@ int npc_parse_mob(char *w1,char *w2,char *w3,char *w4)
md->timer = -1;
md->target_id=0;
md->attacked_id=0;
- md->speed=mob_db[class].speed;
+ md->speed=mob_db[class_].speed;
- if (mob_db[class].mode&0x02)
+ if (mob_db[class_].mode&0x02)
md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item));
else
md->lootitem=NULL;
@@ -2013,7 +2166,7 @@ static int npc_parse_mapflag(char *w1,char *w2,char *w3,char *w4)
//マップフラグ
if ( strcmpi(w3,"nosave")==0) {
if (strcmp(w4,"SavePoint")==0) {
- memcpy(map[m].save.map,"SavePoint",16);
+ memcpy(map[m].save.map,"SavePoint",10);
map[m].save.x=-1;
map[m].save.y=-1;
}else if (sscanf(w4,"%[^,],%d,%d",savemap,&savex,&savey)==3) {
@@ -2106,19 +2259,19 @@ static int npc_parse_mapflag(char *w1,char *w2,char *w3,char *w4)
}
else if (strcmpi(w3,"noicewall")==0) { // noicewall [Valaris]
map[m].flag.noicewall=1;
- }
+ }
else if (strcmpi(w3,"snow")==0) { // snow [Valaris]
map[m].flag.snow=1;
- }
+ }
else if (strcmpi(w3,"fog")==0) { // fog [Valaris]
map[m].flag.fog=1;
- }
+ }
else if (strcmpi(w3,"sakura")==0) { // sakura [Valaris]
map[m].flag.sakura=1;
- }
+ }
else if (strcmpi(w3,"leaves")==0) { // leaves [Valaris]
map[m].flag.leaves=1;
- }
+ }
else if (strcmpi(w3,"rain")==0) { // rain [Valaris]
map[m].flag.rain=1;
}
@@ -2128,15 +2281,116 @@ static int npc_parse_mapflag(char *w1,char *w2,char *w3,char *w4)
else if (strcmpi(w3,"nogo")==0) { // celest
map[m].flag.nogo=1;
}
-
+
+ return 0;
+}
+
+void npc_parsesrcfile(char *name)
+{
+ int m, lines = 0;
+ char line[1024];
+
+ FILE *fp = fopen (name,"r");
+ if (fp == NULL) {
+ ShowError ("File not found : %s\n", name);
+ exit(1);
+ }
+ current_file = name;
+
+ while (fgets(line, 1020, fp)) {
+ char w1[1024], w2[1024], w3[1024], w4[1024], mapname[1024];
+ int i, j, w4pos, count;
+ lines++;
+
+ if (line[0] == '/' && line[1] == '/')
+ continue;
+ // 不要なスペースやタブの連続は詰める
+ for (i = j = 0; line[i]; i++) {
+ if (line[i]==' ') {
+ if (!((line[i+1] && (isspace(line[i+1]) || line[i+1]==',')) ||
+ (j && line[j-1]==',')))
+ line[j++]=' ';
+ } else if (line[i]=='\t') {
+ if (!(j && line[j-1]=='\t'))
+ line[j++]='\t';
+ } else
+ line[j++]=line[i];
+ }
+ // 最初はタブ区切りでチェックしてみて、ダメならスペース区切りで確認
+ if ((count = sscanf(line,"%[^\t]\t%[^\t]\t%[^\t\r\n]\t%n%[^\t\r\n]", w1, w2, w3, &w4pos, w4)) < 3 &&
+ (count = sscanf(line,"%s%s%s%n%s", w1, w2, w3, &w4pos, w4)) < 3) {
+ continue;
+ }
+ // マップの存在確認
+ if (strcmp(w1,"-") !=0 && strcmpi(w1,"function") != 0 ){
+ sscanf(w1,"%[^,]",mapname);
+ m = map_mapname2mapid(mapname);
+ if (strlen(mapname)>16 || m<0) {
+ // "mapname" is not assigned to this server
+ continue;
+ }
+ }
+ if (strcmpi(w2,"warp") == 0 && count > 3) {
+ npc_parse_warp(w1,w2,w3,w4);
+ } else if (strcmpi(w2,"shop") == 0 && count > 3) {
+ npc_parse_shop(w1,w2,w3,w4);
+ } else if (strcmpi(w2,"script") == 0 && count > 3) {
+ if (strcmpi(w1,"function") == 0) {
+ npc_parse_function(w1,w2,w3,w4,line+w4pos,fp,&lines);
+ } else {
+ npc_parse_script(w1,w2,w3,w4,line+w4pos,fp,&lines);
+ }
+ } else if ((i = 0, sscanf(w2,"duplicate%n",&i), (i > 0 && w2[i] == '(')) && count > 3) {
+ npc_parse_script(w1,w2,w3,w4,line+w4pos,fp,&lines);
+ } else if (strcmpi(w2,"monster") == 0 && count > 3) {
+ npc_parse_mob(w1,w2,w3,w4);
+ } else if (strcmpi(w2,"mapflag") == 0 && count >= 3) {
+ npc_parse_mapflag(w1,w2,w3,w4);
+ }
+ }
+ fclose(fp);
+
+ return;
+}
+
+static int npc_read_indoors(void)
+{
+ char *buf,*p;
+ int s, m;
+
+ buf=(char *) grfio_reads("data\\indoorrswtable.txt",&s);
+
+ if(buf==NULL)
+ return -1;
+
+ buf[s]=0;
+ for(p=buf;p-buf<s;){
+ char buf2[64];
+
+ if(sscanf(p,"%[^#]#",buf2) == 1){
+ char map_name[64] = "";
+ strncpy(map_name, buf2, strlen(buf2) - 4);
+ strcat(map_name, ".gat");
+ if ((m = map_mapname2mapid(map_name)) >= 0)
+ map[m].flag.indoors=1;
+ }
+
+ p=strchr(p,10);
+ if(!p) break;
+ p++;
+ }
+ aFree(buf);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\indoorrswtable.txt");
+ ShowStatus(tmp_output);
+
return 0;
}
static int ev_db_final(void *key,void *data,va_list ap)
{
- free(data);
- if(strstr(key,"::")!=NULL)
- free(key);
+ aFree(data);
+ if(strstr((const char *) key,"::")!=NULL)
+ aFree(key);
return 0;
}
static int npcname_db_final(void *key,void *data,va_list ap)
@@ -2144,6 +2398,75 @@ static int npcname_db_final(void *key,void *data,va_list ap)
return 0;
}
/*==========================================
+ *
+ *------------------------------------------
+ */
+int npc_cleanup_sub (struct block_list *bl, va_list ap) {
+ nullpo_retr(0, bl);
+
+ switch(bl->type) {
+ case BL_NPC:
+ npc_unload((struct npc_data *)bl);
+ break;
+ case BL_MOB:
+ mob_unload((struct mob_data *)bl);
+ break;
+ }
+
+ return 0;
+}
+int npc_reload(void)
+{
+ struct npc_src_list *nsl;
+ int m, last_npc_id;
+ time_t last_time = time(0);
+ int busy = 0;
+ char c = '-';
+
+ for (m = 0; m < map_num; m++) {
+ map_foreachinarea(npc_cleanup_sub, m, 0, 0, map[m].xs, map[m].ys, 0);
+ map[m].npc_num = 0;
+ }
+ if(ev_db)
+ strdb_final(ev_db,ev_db_final);
+ if(npcname_db)
+ strdb_final(npcname_db,npcname_db_final);
+
+ // anything else we should cleanup?
+ // Reloading npc's now
+ ev_db = strdb_init(51);
+ npcname_db = strdb_init(24);
+ ev_db->release = ev_release;
+ npc_warp = npc_shop = npc_script = npc_mob = 0;
+ last_npc_id = npc_id;
+
+ for (nsl = npc_src_first; nsl; nsl = nsl->next) {
+ npc_parsesrcfile(nsl->name);
+ printf("\r");
+ ShowStatus("Loading NPCs... Working: ");
+ if (last_time != time(0)) {
+ last_time = time(0);
+ switch(busy) {
+ case 0: c='\\'; busy++; break;
+ case 1: c='|'; busy++; break;
+ case 2: c='/'; busy++; break;
+ case 3: c='-'; busy=0;
+ }
+ }
+ printf("[%c]",c);
+ fflush(stdout);
+ }
+ printf("\r");
+ ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:%30s\n\t-'"
+ CL_WHITE"%d"CL_RESET"' Warps\n\t-'"
+ CL_WHITE"%d"CL_RESET"' Shops\n\t-'"
+ CL_WHITE"%d"CL_RESET"' Scripts\n\t-'"
+ CL_WHITE"%d"CL_RESET"' Mobs\n",
+ npc_id - last_npc_id, "", npc_warp, npc_shop, npc_script, npc_mob);
+
+ return 0;
+}
+/*==========================================
* 終了
*------------------------------------------
*/
@@ -2153,7 +2476,6 @@ int do_final_npc(void)
struct block_list *bl;
struct npc_data *nd;
struct mob_data *md;
- struct chat_data *cd;
struct pet_data *pd;
if(ev_db)
@@ -2161,53 +2483,27 @@ int do_final_npc(void)
if(npcname_db)
strdb_final(npcname_db,npcname_db_final);
- for(i=START_NPC_NUM;i<npc_id;i++){
- if((bl=map_id2bl(i))){
+ npc_clearsrcfile();
+
+ for (i = START_NPC_NUM; i < npc_id; i++){
+ if((bl = map_id2bl(i))){
if(bl->type == BL_NPC && (nd = (struct npc_data *)bl)){
- if(nd->chat_id && (cd=(struct chat_data*)map_id2bl(nd->chat_id))){
- free(cd);
- cd = NULL;
- }
- if(nd->bl.subtype == SCRIPT){
- if(nd->u.scr.timer_event)
- free(nd->u.scr.timer_event);
- if(nd->u.scr.src_id==0){
- if(nd->u.scr.script){
- free(nd->u.scr.script);
- nd->u.scr.script=NULL;
- }
- if(nd->u.scr.label_list){
- free(nd->u.scr.label_list);
- nd->u.scr.label_list = NULL;
- }
- }
- }
- free(nd);
- nd = NULL;
- }else if(bl->type == BL_MOB && (md = (struct mob_data *)bl)){
- if(md->lootitem){
- free(md->lootitem);
+ npc_unload(nd);
+ }else if (bl->type == BL_MOB && (md = (struct mob_data *)bl)){
+ if (md->lootitem){
+ aFree(md->lootitem);
md->lootitem = NULL;
}
- free(md);
+ aFree(md);
md = NULL;
}else if(bl->type == BL_PET && (pd = (struct pet_data *)bl)){
- free(pd);
+ aFree(pd);
pd = NULL;
}
}
}
-
- return 0;
-}
-
-void ev_release(struct dbn *db, int which)
-{
- if (which & 0x1)
- free(db->key);
- if (which & 0x2)
- free(db->data);
+ return 0;
}
/*==========================================
@@ -2217,86 +2513,56 @@ void ev_release(struct dbn *db, int which)
int do_init_npc(void)
{
struct npc_src_list *nsl;
- FILE *fp;
- char line[1024];
- int m,lines;
-
- ev_db=strdb_init(24);
- npcname_db=strdb_init(24);
-
- ev_db->release = ev_release;
-
- memset(&ev_tm_b,-1,sizeof(ev_tm_b));
-
- for(nsl=npc_src_first;nsl;nsl=nsl->next) {
- if(nsl->prev){
- free(nsl->prev);
+ time_t last_time = time(0);
+ int busy = 0;
+ char c = '-';
+
+ // indoorrswtable.txt and etcinfo.txt [Celest]
+ if (battle_config.indoors_override_grffile)
+ npc_read_indoors();
+ //npc_read_weather();
+
+ // comparing only the first 24 chars of labels that are 50 chars long isn't that nice
+ // will cause "duplicated" labels where actually no dup is...
+ //ev_db=strdb_init(24);
+ ev_db = strdb_init(51);
+ npcname_db = strdb_init(24);
+ ev_db->release = ev_release;
+
+ memset(&ev_tm_b, -1, sizeof(ev_tm_b));
+
+ for (nsl = npc_src_first; nsl; nsl = nsl->next) {
+ /*if(nsl->prev){ // [Shinomori]
+ aFree(nsl->prev);
nsl->prev = NULL;
- }
- fp=fopen(nsl->name,"r");
- if (fp==NULL) {
- printf("file not found : %s\n",nsl->name);
- exit(1);
- }
- lines=0;
- while(fgets(line,1020,fp)) {
- char w1[1024],w2[1024],w3[1024],w4[1024],mapname[1024];
- int i,j,w4pos,count;
- lines++;
-
- if (line[0] == '/' && line[1] == '/')
- continue;
- // 不要なスペースやタブの連続は詰める
- for(i=j=0;line[i];i++) {
- if (line[i]==' ') {
- if (!((line[i+1] && (isspace(line[i+1]) || line[i+1]==',')) ||
- (j && line[j-1]==',')))
- line[j++]=' ';
- } else if (line[i]=='\t') {
- if (!(j && line[j-1]=='\t'))
- line[j++]='\t';
- } else
- line[j++]=line[i];
- }
- // 最初はタブ区切りでチェックしてみて、ダメならスペース区切りで確認
- if ((count=sscanf(line,"%[^\t]\t%[^\t]\t%[^\t\r\n]\t%n%[^\t\r\n]",w1,w2,w3,&w4pos,w4)) < 3 &&
- (count=sscanf(line,"%s%s%s%n%s",w1,w2,w3,&w4pos,w4)) < 3) {
- continue;
- }
- // マップの存在確認
- if( strcmp(w1,"-")!=0 && strcmpi(w1,"function")!=0 ){
- sscanf(w1,"%[^,]",mapname);
- m = map_mapname2mapid(mapname);
- if (strlen(mapname)>16 || m<0) {
- // "mapname" is not assigned to this server
- continue;
- }
- }
- if (strcmpi(w2,"warp")==0 && count > 3) {
- npc_parse_warp(w1,w2,w3,w4);
- } else if (strcmpi(w2,"shop")==0 && count > 3) {
- npc_parse_shop(w1,w2,w3,w4);
- } else if (strcmpi(w2,"script")==0 && count > 3) {
- if( strcmpi(w1,"function")==0 ){
- npc_parse_function(w1,w2,w3,w4,line+w4pos,fp,&lines);
- }else{
- npc_parse_script(w1,w2,w3,w4,line+w4pos,fp,&lines);
- }
- } else if ( (i=0,sscanf(w2,"duplicate%n",&i), (i>0 && w2[i]=='(')) && count > 3) {
- npc_parse_script(w1,w2,w3,w4,line+w4pos,fp,&lines);
- } else if (strcmpi(w2,"monster")==0 && count > 3) {
- npc_parse_mob(w1,w2,w3,w4);
- } else if (strcmpi(w2,"mapflag")==0 && count >= 3) {
- npc_parse_mapflag(w1,w2,w3,w4);
+ }*/
+ //
+ npc_parsesrcfile(nsl->name);
+ current_file = NULL;
+ printf("\r");
+ ShowStatus("Loading NPCs... Working: ");
+ if (last_time != time(0)) {
+ last_time = time(0);
+ switch(busy) {
+ case 0: c='\\'; busy++; break;
+ case 1: c='|'; busy++; break;
+ case 2: c='/'; busy++; break;
+ case 3: c='-'; busy=0;
}
}
- fclose(fp);
+ printf("[%c]",c);
+ fflush(stdout);
// printf("\rLoading NPCs [%d]: %-54s",npc_id-START_NPC_NUM,nsl->name);
// fflush(stdout);
}
- printf("\rNPCs Loaded: %d [Warps:%d Shops:%d Scripts:%d Mobs:%d]\n",
- npc_id-START_NPC_NUM,npc_warp,npc_shop,npc_script,npc_mob);
-
+ printf("\r");
+ ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:%30s\n\t-'"
+ CL_WHITE"%d"CL_RESET"' Warps\n\t-'"
+ CL_WHITE"%d"CL_RESET"' Shops\n\t-'"
+ CL_WHITE"%d"CL_RESET"' Scripts\n\t-'"
+ CL_WHITE"%d"CL_RESET"' Mobs\n",
+ npc_id - START_NPC_NUM, "", npc_warp, npc_shop, npc_script, npc_mob);
+
add_timer_func_list(npc_walktimer,"npc_walktimer"); // [Valaris]
add_timer_func_list(npc_event_timer,"npc_event_timer");
add_timer_func_list(npc_event_do_clock,"npc_event_do_clock");
diff --git a/src/map/npc.h b/src/map/npc.h
index 4f0c43cba..2f81345d7 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -8,6 +8,10 @@
#define WARP_DEBUG_CLASS 722
#define INVISIBLE_CLASS 32767
+#ifdef PCRE_SUPPORT
+void npc_chat_finalize(struct npc_data *nd);
+#endif
+int npc_chat_sub(struct block_list *bl, va_list ap);
int npc_event_dequeue(struct map_session_data *sd);
int npc_event_timer(int tid,unsigned int tick,int id,int data);
int npc_event(struct map_session_data *sd,const char *npcname,int);
@@ -22,6 +26,7 @@ int npc_buylist(struct map_session_data *,int,unsigned short *);
int npc_selllist(struct map_session_data *,int,unsigned short *);
int npc_parse_mob(char *w1,char *w2,char *w3,char *w4);
int npc_parse_warp(char *w1,char *w2,char *w3,char *w4);
+int npc_globalmessage(const char *name,char *mes);
int npc_enable(const char *name,int flag);
struct npc_data* npc_name2id(const char *name);
@@ -37,16 +42,21 @@ void npc_delsrcfile(char *);
int do_final_npc(void);
int do_init_npc(void);
int npc_event_do_oninit(void);
-int npc_do_ontimer(int,struct map_session_data *,int);
+int npc_do_ontimer(int,int);
int npc_event_doall(const char *name);
int npc_event_do(const char *name);
+int npc_event_doall_id(const char *name, int id);
-int npc_timerevent_start(struct npc_data *nd);
+int npc_timerevent_start(struct npc_data *nd, int rid);
int npc_timerevent_stop(struct npc_data *nd);
int npc_gettimerevent_tick(struct npc_data *nd);
int npc_settimerevent_tick(struct npc_data *nd,int newtimer);
-int npc_delete(struct npc_data *nd);
+int npc_remove_map(struct npc_data *nd);
+int npc_unload(struct npc_data *nd);
+int npc_reload(void);
+
+extern char *current_file;
#endif
diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c
new file mode 100644
index 000000000..5ec8540ae
--- /dev/null
+++ b/src/map/npc_chat.c
@@ -0,0 +1,502 @@
+#ifdef PCRE_SUPPORT
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#ifdef __WIN32
+#define __USE_W32_SOCKETS
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include <time.h>
+
+#include "../common/timer.h"
+#include "../common/malloc.h"
+#include "../common/version.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+
+#include "map.h"
+#include "status.h"
+#include "npc.h"
+#include "chat.h"
+#include "script.h"
+#include "battle.h"
+
+#include "pcre.h"
+
+/**
+ * Written by MouseJstr in a vision... (2/21/2005)
+ *
+ * This allows you to make npc listen for spoken text (global
+ * messages) and pattern match against that spoken text using perl
+ * regular expressions.
+ *
+ * Please feel free to copy this code into your own personal ragnarok
+ * servers or distributions but please leave my name. Also, please
+ * wait until I've put it into the main eA branch which means I
+ * believe it is ready for distribution.
+ *
+ * So, how do people use this?
+ *
+ * The first and most important function is defpattern
+ *
+ * defpattern 1, "[^:]+: (.*) loves (.*)", "label";
+ *
+ * this defines a new pattern in set 1 using perl syntax
+ * (http://www.troubleshooters.com/codecorn/littperl/perlreg.htm)
+ * and tells it to jump to the supplied label when the pattern
+ * is matched.
+ *
+ * each of the matched Groups will result in a variable being
+ * set ($p1$ through $p9$ with $p0$ being the entire string)
+ * before the script gets executed.
+ *
+ * activatepset 1;
+ *
+ * This activates a set of patterns.. You can have many pattern
+ * sets defined and many active all at once. This feature allows
+ * you to set up "conversations" and ever changing expectations of
+ * the pattern matcher
+ *
+ * deactivatepset 1;
+ *
+ * turns off a pattern set;
+ *
+ * deactivatepset -1;
+ *
+ * turns off ALL pattern sets;
+ *
+ * deletepset 1;
+ *
+ * deletes a pset
+ */
+
+/* Structure containing all info associated with a single pattern
+ block */
+
+struct pcrematch_entry {
+ struct pcrematch_entry *next_;
+ char *pattern_;
+ pcre *pcre_;
+ pcre_extra *pcre_extra_;
+ char *label_;
+};
+
+/* A set of patterns that can be activated and deactived with a single
+ command */
+
+struct pcrematch_set {
+ struct pcrematch_set *next_, *prev_;
+ struct pcrematch_entry *head_;
+ int setid_;
+};
+
+/*
+ * Entire data structure hung off a NPC
+ *
+ * The reason I have done it this way (a void * in npc_data and then
+ * this) was to reduce the number of patches that needed to be applied
+ * to a ragnarok distribution to bring this code online. I
+ * also wanted people to be able to grab this one file to get updates
+ * without having to do a large number of changes.
+ */
+
+struct npc_parse {
+ struct pcrematch_set *active_;
+ struct pcrematch_set *inactive_;
+};
+
+
+/**
+ * delete everythign associated with a entry
+ *
+ * This does NOT do the list management
+ */
+
+void finalize_pcrematch_entry(struct pcrematch_entry *e) {
+ free(e->pcre_);
+ free(e->pcre_extra_);
+ aFree(e->pattern_);
+ aFree(e->label_);
+}
+
+/**
+ * Lookup (and possibly create) a new set of patterns by the set id
+ */
+static struct pcrematch_set * lookup_pcreset(struct npc_data *nd,int setid)
+{
+ struct pcrematch_set *pcreset;
+ struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
+ if (npcParse == NULL)
+ nd->chatdb = npcParse = (struct npc_parse *)
+ aCalloc(sizeof(struct npc_parse), 1);
+
+ pcreset = npcParse->active_;
+
+ while (pcreset != NULL) {
+ if (pcreset->setid_ == setid)
+ break;
+ pcreset = pcreset->next_;
+ }
+ if (pcreset == NULL)
+ pcreset = npcParse->inactive_;
+
+ while (pcreset != NULL) {
+ if (pcreset->setid_ == setid)
+ break;
+ pcreset = pcreset->next_;
+ }
+
+ if (pcreset == NULL) {
+ pcreset = (struct pcrematch_set *)
+ aCalloc(sizeof(struct pcrematch_set), 1);
+ pcreset->next_ = npcParse->inactive_;
+ if (pcreset->next_ != NULL)
+ pcreset->next_->prev_ = pcreset;
+ pcreset->prev_ = 0;
+ npcParse->inactive_ = pcreset;
+ pcreset->setid_ = setid;
+ }
+
+ return pcreset;
+}
+
+/**
+ * activate a set of patterns.
+ *
+ * if the setid does not exist, this will silently return
+ */
+
+static void activate_pcreset(struct npc_data *nd,int setid) {
+ struct pcrematch_set *pcreset;
+ struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
+ if (npcParse == NULL)
+ return; // Nothing to activate...
+ pcreset = npcParse->inactive_;
+ while (pcreset != NULL) {
+ if (pcreset->setid_ == setid)
+ break;
+ pcreset = pcreset->next_;
+ }
+ if (pcreset == NULL)
+ return; // not in inactive list
+ if (pcreset->next_ != NULL)
+ pcreset->next_->prev_ = pcreset->prev_;
+ if (pcreset->prev_ != NULL)
+ pcreset->prev_->next_ = pcreset->next_;
+ else
+ npcParse->inactive_ = pcreset->next_;
+
+ pcreset->prev_ = NULL;
+ pcreset->next_ = npcParse->active_;
+ if (pcreset->next_ != NULL)
+ pcreset->next_->prev_ = pcreset;
+ npcParse->active_ = pcreset;
+}
+
+/**
+ * deactivate a set of patterns.
+ *
+ * if the setid does not exist, this will silently return
+ */
+
+static void deactivate_pcreset(struct npc_data *nd,int setid) {
+ struct pcrematch_set *pcreset;
+ struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
+ if (npcParse == NULL)
+ return; // Nothing to deactivate...
+ if (setid == -1) {
+ while(npcParse->active_ != NULL)
+ deactivate_pcreset(nd, npcParse->active_->setid_);
+ return;
+ }
+ pcreset = npcParse->active_;
+ while (pcreset != NULL) {
+ if (pcreset->setid_ == setid)
+ break;
+ pcreset = pcreset->next_;
+ }
+ if (pcreset == NULL)
+ return; // not in active list
+ if (pcreset->next_ != NULL)
+ pcreset->next_->prev_ = pcreset->prev_;
+ if (pcreset->prev_ != NULL)
+ pcreset->prev_->next_ = pcreset->next_;
+ else
+ npcParse->active_ = pcreset->next_;
+
+ pcreset->prev_ = NULL;
+ pcreset->next_ = npcParse->inactive_;
+ if (pcreset->next_ != NULL)
+ pcreset->next_->prev_ = pcreset;
+ npcParse->inactive_ = pcreset;
+}
+
+/**
+ * delete a set of patterns.
+ */
+static void delete_pcreset(struct npc_data *nd,int setid) {
+ int active = 1;
+ struct pcrematch_set *pcreset;
+ struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
+ if (npcParse == NULL)
+ return; // Nothing to deactivate...
+ pcreset = npcParse->active_;
+ while (pcreset != NULL) {
+ if (pcreset->setid_ == setid)
+ break;
+ pcreset = pcreset->next_;
+ }
+ if (pcreset == NULL) {
+ active = 0;
+ pcreset = npcParse->inactive_;
+ while (pcreset != NULL) {
+ if (pcreset->setid_ == setid)
+ break;
+ pcreset = pcreset->next_;
+ }
+ }
+ if (pcreset == NULL)
+ return;
+
+ if (pcreset->next_ != NULL)
+ pcreset->next_->prev_ = pcreset->prev_;
+ if (pcreset->prev_ != NULL)
+ pcreset->prev_->next_ = pcreset->next_;
+ else if(active == 1)
+ npcParse->active_ = pcreset->next_;
+ else
+ npcParse->inactive_ = pcreset->next_;
+
+ pcreset->prev_ = NULL;
+ pcreset->next_ = NULL;
+
+ while (pcreset->head_) {
+ struct pcrematch_entry *n = pcreset->head_->next_;;
+ finalize_pcrematch_entry(pcreset->head_);
+ pcreset->head_ = n;
+ }
+
+ aFree(pcreset);
+}
+
+/**
+ * create a new pattern entry
+ */
+static struct pcrematch_entry *create_pcrematch_entry(struct pcrematch_set * set) {
+ struct pcrematch_entry * e = (struct pcrematch_entry *)
+ aCalloc(sizeof(struct pcrematch_entry), 1);
+ struct pcrematch_entry * last = set->head_;
+
+ // Normally we would have just stuck it at the end of the list but
+ // this doesn't sink up with peoples usage pattern. They wanted
+ // the items defined first to have a higher priority then the
+ // items defined later.. as a result, we have to do some work up
+ // front..
+
+ /* if we are the first pattern, stick us at the end */
+ if (last == NULL) {
+ set->head_ = e;
+ return e;
+ }
+
+ /* Look for the last entry */
+ while (last->next_ != NULL)
+ last = last->next_;
+
+ last->next_ = e;
+ e->next_ = NULL;
+
+ return e;
+}
+
+/**
+ * define/compile a new pattern
+ */
+
+void npc_chat_def_pattern(struct npc_data *nd, int setid,
+ const char *pattern, const char *label)
+{
+ const char *err;
+ int erroff;
+
+ struct pcrematch_set * s = lookup_pcreset(nd, setid);
+ struct pcrematch_entry *e = create_pcrematch_entry(s);
+ e->pattern_ = aStrdup(pattern);
+ e->label_ = aStrdup(label);
+ e->pcre_ = pcre_compile(pattern, PCRE_CASELESS, &err, &erroff, NULL);
+ e->pcre_extra_ = pcre_study(e->pcre_, 0, &err);
+}
+
+/**
+ * Delete everything associated with a NPC concerning the pattern
+ * matching code
+ *
+ * this could be more efficent but.. how often do you do this?
+ */
+void npc_chat_finalize(struct npc_data *nd)
+{
+ struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
+ if (npcParse == NULL)
+ return;
+
+ while(npcParse->active_)
+ delete_pcreset(nd, npcParse->active_->setid_);
+
+ while(npcParse->inactive_)
+ delete_pcreset(nd, npcParse->inactive_->setid_);
+}
+
+/**
+ * Handler called whenever a global message is spoken in a NPC's area
+ */
+int npc_chat_sub(struct block_list *bl, va_list ap)
+{
+ struct npc_data *nd = (struct npc_data *)bl;
+ struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
+ unsigned char *msg;
+ int len, pos, i;
+ struct map_session_data *sd;
+ struct npc_label_list *lst;
+ struct pcrematch_set *pcreset;
+
+ // Not interested in anything you might have to say...
+ if (npcParse == NULL || npcParse->active_ == NULL)
+ return 0;
+
+ msg = va_arg(ap,unsigned char*);
+ len = va_arg(ap,int);
+ sd = va_arg(ap,struct map_session_data *);
+
+ // grab the active list
+ pcreset = npcParse->active_;
+
+ // interate across all active sets
+ while (pcreset != NULL) {
+ struct pcrematch_entry *e = pcreset->head_;
+ // interate across all patterns in that set
+ while (e != NULL) {
+ int offsets[20];
+ char buf[255];
+ // perform pattern match
+ int r = pcre_exec(e->pcre_, e->pcre_extra_, msg, len, 0,
+ 0, offsets, sizeof(offsets) / sizeof(offsets[0]));
+ if (r >= 0) {
+ // save out the matched strings
+ switch (r) {
+ case 10:
+ memcpy(buf, &msg[offsets[18]], offsets[19]);
+ buf[offsets[19]] = '\0';
+ set_var(sd, "$p9$", buf);
+ case 9:
+ memcpy(buf, &msg[offsets[16]], offsets[17]);
+ buf[offsets[17]] = '\0';
+ set_var(sd, "$p8$", buf);
+ case 8:
+ memcpy(buf, &msg[offsets[14]], offsets[15]);
+ buf[offsets[15]] = '\0';
+ set_var(sd, "$p7$", buf);
+ case 7:
+ memcpy(buf, &msg[offsets[12]], offsets[13]);
+ buf[offsets[13]] = '\0';
+ set_var(sd, "$p6$", buf);
+ case 6:
+ memcpy(buf, &msg[offsets[10]], offsets[11]);
+ buf[offsets[11]] = '\0';
+ set_var(sd, "$p5$", buf);
+ case 5:
+ memcpy(buf, &msg[offsets[8]], offsets[9]);
+ buf[offsets[9]] = '\0';
+ set_var(sd, "$p4$", buf);
+ case 4:
+ memcpy(buf, &msg[offsets[6]], offsets[7]);
+ buf[offsets[7]] = '\0';
+ set_var(sd, "$p3$", buf);
+ case 3:
+ memcpy(buf, &msg[offsets[4]], offsets[5]);
+ buf[offsets[5]] = '\0';
+ set_var(sd, "$p2$", buf);
+ case 2:
+ memcpy(buf, &msg[offsets[2]], offsets[3]);
+ buf[offsets[3]] = '\0';
+ set_var(sd, "$p1$", buf);
+ case 1:
+ memcpy(buf, &msg[offsets[0]], offsets[1]);
+ buf[offsets[1]] = '\0';
+ set_var(sd, "$p0$", buf);
+ }
+
+ // find the target label.. this sucks..
+ lst=nd->u.scr.label_list;
+ pos = -1;
+ for (i = 0; i < nd->u.scr.label_list_num; i++) {
+ if (strncmp(lst[i].name, e->label_, sizeof(lst[i].name)) == 0) {
+ pos = lst[i].pos;
+ break;
+ }
+ }
+ if (pos == -1) {
+ printf("Unable to find label: %s", e->label_);
+ // unable to find label... do something..
+ return 0;
+ }
+ // run the npc script
+ run_script(nd->u.scr.script,pos,sd->bl.id,nd->bl.id);
+ return 0;
+ }
+ e = e->next_;
+ }
+ pcreset = pcreset->next_;
+ }
+
+ return 0;
+}
+
+// Various script builtins used to support these functions
+
+int buildin_defpattern(struct script_state *st) {
+ int setid=conv_num(st,& (st->stack->stack_data[st->start+2]));
+ char *pattern=conv_str(st,& (st->stack->stack_data[st->start+3]));
+ char *label=conv_str(st,& (st->stack->stack_data[st->start+4]));
+ struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid);
+
+ npc_chat_def_pattern(nd, setid, pattern, label);
+
+ return 0;
+}
+
+int buildin_activatepset(struct script_state *st) {
+ int setid=conv_num(st,& (st->stack->stack_data[st->start+2]));
+ struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid);
+
+ activate_pcreset(nd, setid);
+
+ return 0;
+}
+int buildin_deactivatepset(struct script_state *st) {
+ int setid=conv_num(st,& (st->stack->stack_data[st->start+2]));
+ struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid);
+
+ deactivate_pcreset(nd, setid);
+
+ return 0;
+}
+int buildin_deletepset(struct script_state *st) {
+ int setid=conv_num(st,& (st->stack->stack_data[st->start+2]));
+ struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid);
+
+ delete_pcreset(nd, setid);
+
+ return 0;
+}
+
+
+#endif
diff --git a/src/map/party.c b/src/map/party.c
index 82b77cf6b..7eb3f02dc 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -30,7 +30,7 @@ int party_send_xyhp_timer(int tid,unsigned int tick,int id,int data);
*/
static int party_db_final(void *key,void *data,va_list ap)
{
- free(data);
+ aFree(data);
return 0;
}
void do_final_party(void)
@@ -49,7 +49,7 @@ void do_init_party(void)
// 検索
struct party *party_search(int party_id)
{
- return numdb_search(party_db,party_id);
+ return (struct party *) numdb_search(party_db,party_id);
}
int party_searchname_sub(void *key,void *data,va_list ap)
{
@@ -69,12 +69,12 @@ struct party* party_searchname(char *str)
return p;
}
// 作成要求
-int party_create(struct map_session_data *sd,char *name)
+int party_create(struct map_session_data *sd,char *name,int item,int item2)
{
nullpo_retr(0, sd);
if(sd->status.party_id==0)
- intif_create_party(sd,name);
+ intif_create_party(sd,name,item,item2);
else
clif_party_created(sd,2);
return 0;
@@ -91,7 +91,7 @@ int party_created(int account_id,int fail,int party_id,char *name)
if(fail==0){
struct party *p;
sd->status.party_id=party_id;
- if((p=numdb_search(party_db,party_id))!=NULL){
+ if((p=(struct party *) numdb_search(party_db,party_id))!=NULL){
printf("party: id already exists!\n");
exit(1);
}
@@ -121,7 +121,7 @@ int party_check_member(struct party *p)
nullpo_retr(0, p);
for(i=0;i<fd_max;i++){
- if(session[i] && (sd=session[i]->session_data) && sd->state.auth){
+ if(session[i] && (sd=(struct map_session_data *) session[i]->session_data) && sd->state.auth){
if(sd->status.party_id==p->party_id){
int j,f=1;
for(j=0;j<MAX_PARTY;j++){ // パーティにデータがあるか確認
@@ -149,7 +149,7 @@ int party_recv_noinfo(int party_id)
int i;
struct map_session_data *sd;
for(i=0;i<fd_max;i++){
- if(session[i] && (sd=session[i]->session_data) && sd->state.auth){
+ if(session[i] && (sd=(struct map_session_data *) session[i]->session_data) && sd->state.auth){
if(sd->status.party_id==party_id)
sd->status.party_id=0;
}
@@ -164,7 +164,7 @@ int party_recv_info(struct party *sp)
nullpo_retr(0, sp);
- if((p=numdb_search(party_db,sp->party_id))==NULL){
+ if((p=(struct party *) numdb_search(party_db,sp->party_id))==NULL){
p=(struct party *)aCalloc(1,sizeof(struct party));
numdb_insert(party_db,sp->party_id,p);
@@ -175,7 +175,7 @@ int party_recv_info(struct party *sp)
for(i=0;i<MAX_PARTY;i++){ // sdの設定
struct map_session_data *sd = map_id2sd(p->member[i].account_id);
- p->member[i].sd=(sd!=NULL && sd->status.party_id==p->party_id)?sd:NULL;
+ p->member[i].sd=(sd!=NULL && sd->status.party_id==p->party_id && !sd->state.waitingdisconnect)?sd:NULL;
}
clif_party_info(p,-1);
@@ -250,11 +250,13 @@ int party_reply_invite(struct map_session_data *sd,int account_id,int flag)
// パーティが追加された
int party_member_added(int party_id,int account_id,int flag)
{
- struct map_session_data *sd= map_id2sd(account_id),*sd2;
- if(sd==NULL && flag==0){
- if(battle_config.error_log)
- printf("party: member added error %d is not online\n",account_id);
- intif_party_leave(party_id,account_id); // キャラ側に登録できなかったため脱退要求を出す
+ struct map_session_data *sd = map_id2sd(account_id),*sd2;
+ if(sd == NULL){
+ if (flag == 0) {
+ if(battle_config.error_log)
+ printf("party: member added error %d is not online\n",account_id);
+ intif_party_leave(party_id,account_id); // キャラ側に登録できなかったため脱退要求を出す
+ }
return 0;
}
sd2=map_id2sd(sd->party_invite_account);
@@ -417,7 +419,7 @@ int party_recv_movemap(int party_id,int account_id,char *map,int online,int lv)
for(i=0;i<MAX_PARTY;i++){ // sd再設定
struct map_session_data *sd= map_id2sd(p->member[i].account_id);
- p->member[i].sd=(sd!=NULL && sd->status.party_id==p->party_id)?sd:NULL;
+ p->member[i].sd=(sd!=NULL && sd->status.party_id==p->party_id && !sd->state.waitingdisconnect)?sd:NULL;
}
party_send_xy_clear(p); // 座標再通知要請
@@ -481,6 +483,7 @@ int party_send_message(struct map_session_data *sd,char *mes,int len)
if(sd->status.party_id==0)
return 0;
intif_party_message(sd->status.party_id,sd->status.account_id,mes,len);
+ party_recv_message(sd->status.party_id,sd->status.account_id,mes,len);
return 0;
}
@@ -583,16 +586,23 @@ int party_exp_share(struct party *p,int map,int base_exp,int job_exp,int zeny)
nullpo_retr(0, p);
- for(i=c=0;i<MAX_PARTY;i++)
- if((sd=p->member[i].sd)!=NULL && sd->bl.m==map)
+ for (i=c=0; i < MAX_PARTY; i++)
+ if ((sd = p->member[i].sd) != NULL && p->member[i].online && sd->bl.m == map /*&& session[sd->fd] != NULL*/) // should be done in socket.c
c++;
- if(c==0)
+
+ if(c == 0)
return 0;
- for(i=0;i<MAX_PARTY;i++)
- if((sd=p->member[i].sd)!=NULL && sd->bl.m==map) {
- pc_gainexp(sd,base_exp/c+1,job_exp/c+1);
- if(battle_config.zeny_from_mobs) // zeny from mobs [Valaris]
- pc_getzeny(sd,zeny/c+1);
+ for (i = 0; i < MAX_PARTY; i++)
+ if ((sd = p->member[i].sd) != NULL && p->member[i].online && sd->bl.m == map /*&& session[sd->fd] != NULL*/) {
+ if (battle_config.idle_no_share && (/* pc_issit(sd) || */ sd->chatID || (sd->idletime < (tick_ - 120))))
+ continue;
+ #ifdef TWILIGHT
+ pc_gainexp(sd,base_exp,job_exp);
+ #else
+ pc_gainexp(sd,(base_exp/c)+1,(job_exp/c)+1);
+ #endif
+ if (battle_config.zeny_from_mobs) // zeny from mobs [Valaris]
+ pc_getzeny(sd,(zeny/c)+1);
}
return 0;
}
diff --git a/src/map/party.h b/src/map/party.h
index 5259df7ff..203dd1057 100644
--- a/src/map/party.h
+++ b/src/map/party.h
@@ -13,7 +13,7 @@ void do_final_party(void);
struct party *party_search(int party_id);
struct party* party_searchname(char *str);
-int party_create(struct map_session_data *sd,char *name);
+int party_create(struct map_session_data *sd,char *name, int item, int item2);
int party_created(int account_id,int fail,int party_id,char *name);
int party_request_info(int party_id);
int party_invite(struct map_session_data *sd,int account_id);
diff --git a/src/map/path.c b/src/map/path.c
index b2e0a78a8..c2b852469 100644
--- a/src/map/path.c
+++ b/src/map/path.c
@@ -168,17 +168,13 @@ static int add_path(int *heap,struct tmp_path *tp,int x,int y,int dist,int dir,i
*/
static int can_place(struct map_data *m,int x,int y,int flag)
{
- int c;
-
nullpo_retr(0, m);
- c=read_gatp(m,x,y);
-
- if(c==1)
- return 0;
- if(!(flag&0x10000) && c==5)
- return 0;
- return 1;
+ if(map_getcellp(m,x,y,CELL_CHKPASS))
+ return 1;
+ else if((flag&0x10000)&&map_getcellp(m,x,y,CELL_CHKGROUND))
+ return 1;
+ return 0;
}
/*==========================================
@@ -246,6 +242,76 @@ int path_blownpos(int m,int x0,int y0,int dx,int dy,int count)
}
/*==========================================
+ * タヒ袮ヘ?ェャハヲメェォェノェヲェォェレェケ
+ *------------------------------------------
+ */
+#define swap(x,y) { int t; t = x; x = y; y = t; }
+int path_search_long(struct shootpath_data *spd,int m,int x0,int y0,int x1,int y1)
+{
+ int dx, dy;
+ int wx = 0, wy = 0;
+ int weight;
+ struct map_data *md;
+
+ if (!map[m].gat)
+ return 0;
+ md = &map[m];
+
+ dx = (x1 - x0);
+ if (dx < 0) {
+ swap(x0, x1);
+ swap(y0, y1);
+ dx = -dx;
+ }
+ dy = (y1 - y0);
+
+ if (spd) {
+ spd->rx = spd->ry = 0;
+ spd->len = 1;
+ spd->x[0] = x0;
+ spd->y[0] = y0;
+ }
+
+ if (map_getcellp(md,x1,y1,CELL_CHKWALL))
+ return 0;
+
+ if (dx > abs(dy)) {
+ weight = dx;
+ if (spd)
+ spd->ry=1;
+ } else {
+ weight = abs(y1 - y0);
+ if (spd)
+ spd->rx=1;
+ }
+
+ while (x0 != x1 || y0 != y1) {
+ if (map_getcellp(md,x0,y0,CELL_CHKWALL))
+ return 0;
+ wx += dx;
+ wy += dy;
+ if (wx >= weight) {
+ wx -= weight;
+ x0 ++;
+ }
+ if (wy >= weight) {
+ wy -= weight;
+ y0 ++;
+ } else if (wy < 0) {
+ wy += weight;
+ y0 --;
+ }
+ if (spd && spd->len<MAX_WALKPATH) {
+ spd->x[spd->len] = x0;
+ spd->y[spd->len] = y0;
+ spd->len++;
+ }
+ }
+
+ return 1;
+}
+
+/*==========================================
* path探索 (x0,y0)->(x1,y1)
*------------------------------------------
*/
@@ -262,7 +328,7 @@ int path_search(struct walkpath_data *wpd,int m,int x0,int y0,int x1,int y1,int
if(!map[m].gat)
return -1;
md=&map[m];
- if(x1<0 || x1>=md->xs || y1<0 || y1>=md->ys || (i=read_gatp(md,x1,y1))==1 || i==5)
+ if(x1<0 || x1>=md->xs || y1<0 || y1>=md->ys || map_getcellp(md,x1,y1,CELL_CHKNOPASS))
return -1;
// easy
diff --git a/src/map/pc.c b/src/map/pc.c
index 917bbf0a4..e0c13012d 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -1,4 +1,4 @@
-// $Id: pc.c 101 2004-11-26 5:47:29 PM Celestia $
+// $Id: pc.c 101 2004-12-13 7:23:07 PM Celestia $
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -15,6 +15,7 @@
#include "clif.h"
#include "intif.h"
#include "pc.h"
+#include "status.h"
#include "npc.h"
#include "mob.h"
#include "pet.h"
@@ -43,29 +44,16 @@
#define PVP_CALCRANK_INTERVAL 1000 // PVP順位計算の間隔
-#define STATE_BLIND 0x10
-
-static int max_weight_base[MAX_PC_CLASS];
-static int hp_coefficient[MAX_PC_CLASS];
-static int hp_coefficient2[MAX_PC_CLASS];
-static int hp_sigma_val[MAX_PC_CLASS][MAX_LEVEL];
-static int sp_coefficient[MAX_PC_CLASS];
-static int aspd_base[MAX_PC_CLASS][20];
-static char job_bonus[3][MAX_PC_CLASS][MAX_LEVEL];
static int exp_table[14][MAX_LEVEL];
-static char statp[255][7];
+static short statp[MAX_LEVEL];
-/*static struct {
- int id;
- int max;
- struct {
- short id,lv;
- } need[6];
-} skill_tree[3][MAX_PC_CLASS][100];*/ // moved to pc.h - celest
+extern char msg_table[1000][256];
-static int atkmods[3][20]; // 武器ATKサイズ修正(size_fix.txt)
-static int refinebonus[5][3]; // 精?ボ?ナステ?ブル(refine_db.txt)
-static int percentrefinery[5][10]; // 精?成功率(refine_db.txt)
+// h-files are for declarations, not for implementations... [Shinomori]
+struct skill_tree_entry skill_tree[3][25][MAX_SKILL_TREE];
+// timer for night.day implementation
+int day_timer_tid;
+int night_timer_tid;
static int dirx[8]={0,-1,-1,-1,0,1,1,1};
static int diry[8]={1,1,0,-1,-1,-1,0,1};
@@ -89,11 +77,11 @@ int pc_isGM(struct map_session_data *sd) {
if (p == NULL)
return 0;
return p->level;*/
-
+
//For console [Wizputer]
if ( sd->fd == 0 )
return 99;
-
+
for(i = 0; i < GM_num; i++)
if (gm_account[i].account_id == sd->status.account_id)
return gm_account[i].level;
@@ -128,18 +116,12 @@ int pc_set_gm_level(int account_id, int level) {
}
GM_num++;
- gm_account = realloc(gm_account, sizeof(struct gm_account) * GM_num);
+ gm_account = (struct gm_account *) aRealloc(gm_account, sizeof(struct gm_account) * GM_num);
gm_account[GM_num - 1].account_id = account_id;
gm_account[GM_num - 1].level = level;
return 0;
}
-int pc_getrefinebonus(int lv, int type) {
- if (lv >= 0 && lv < 5 && type >= 0 && type < 3)
- return refinebonus[lv][type];
- return 0;
-}
-
static int distance(int x0, int y0, int x1, int y1) {
int dx, dy;
@@ -160,6 +142,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;
}
@@ -180,12 +163,12 @@ 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;
}
static int pc_spiritball_timer(int tid,unsigned int tick,int id,int data) {
struct map_session_data *sd;
- int i;
if( (sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC )
return 1;
@@ -195,22 +178,26 @@ static int pc_spiritball_timer(int tid,unsigned int tick,int id,int data) {
printf("spirit_timer %d != %d\n",sd->spirit_timer[0],tid);
return 0;
}
- sd->spirit_timer[0]=-1;
- for(i=1;i<sd->spiritball;i++) {
- sd->spirit_timer[i-1] = sd->spirit_timer[i];
- sd->spirit_timer[i] = -1;
+
+ if(sd->spiritball <= 0) {
+ if(battle_config.error_log)
+ printf("Spiritballs are already 0 when pc_spiritball_timer gets called");
+ sd->spiritball = 0;
+ return 0;
}
+
sd->spiritball--;
- if(sd->spiritball < 0)
- sd->spiritball = 0;
+ // I leave this here as bad example [Shinomori]
+ //memcpy( &sd->spirit_timer[0], &sd->spirit_timer[1], sizeof(sd->spirit_timer[0]) * sd->spiritball );
+ memmove( sd->spirit_timer+0, sd->spirit_timer+1, (sd->spiritball)*sizeof(int) );
+ sd->spirit_timer[sd->spiritball]=-1;
+
clif_spiritball(sd);
return 0;
}
int pc_addspiritball(struct map_session_data *sd,int interval,int max) {
- int i;
-
nullpo_retr(0, sd);
if(max > MAX_SKILL_LEVEL)
@@ -219,16 +206,13 @@ int pc_addspiritball(struct map_session_data *sd,int interval,int max) {
sd->spiritball = 0;
if(sd->spiritball >= max) {
- if(sd->spirit_timer[0] != -1) {
+ if(sd->spirit_timer[0] != -1)
delete_timer(sd->spirit_timer[0],pc_spiritball_timer);
- sd->spirit_timer[0] = -1;
- }
- for(i=1;i<max;i++) {
- sd->spirit_timer[i-1] = sd->spirit_timer[i];
- sd->spirit_timer[i] = -1;
- }
- }
- else
+ // I leave this here as bad example [Shinomori]
+ //memcpy( &sd->spirit_timer[0], &sd->spirit_timer[1], sizeof(sd->spirit_timer[0]) * (sd->spiritball - 1));
+ memmove( sd->spirit_timer+0, sd->spirit_timer+1, (sd->spiritball - 1)*sizeof(int) );
+ //sd->spirit_timer[sd->spiritball-1] = -1; // intentionally, but will be overwritten
+ } else
sd->spiritball++;
sd->spirit_timer[sd->spiritball-1] = add_timer(gettick()+interval,pc_spiritball_timer,sd->bl.id,0);
@@ -276,13 +260,18 @@ int pc_setrestartvalue(struct map_session_data *sd,int type) {
nullpo_retr(0, sd);
- s_class = pc_calc_base_job(sd->status.class);
+ s_class = pc_calc_base_job(sd->status.class_);
//-----------------------
// 死亡した
- if(sd->special_state.restart_full_recover) { // オシリスカ?ド
+ if(sd->special_state.restart_full_recover || // オシリスカ?ド
+ sd->state.snovice_flag == 4) { // [Celest]
sd->status.hp=sd->status.max_hp;
sd->status.sp=sd->status.max_sp;
+ if (sd->state.snovice_flag == 4) {
+ sd->state.snovice_flag = 0;
+ status_change_start(&sd->bl,SkillStatusChangeTable[MO_STEELBODY],1,0,0,0,skill_get_time(MO_STEELBODY,1),0 );
+ }
}
else {
if(s_class.job == 0 && battle_config.restart_hp_rate < 50) { //ノビは半分回復
@@ -310,7 +299,7 @@ int pc_setrestartvalue(struct map_session_data *sd,int type) {
/* removed exp penalty on spawn [Valaris] */
- if(type&2 && sd->status.class != 0 && battle_config.zeny_penalty > 0 && !map[sd->bl.m].flag.nozenypenalty) {
+ if(type&2 && sd->status.class_ != 0 && battle_config.zeny_penalty > 0 && !map[sd->bl.m].flag.nozenypenalty) {
int zeny = (int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.);
if(zeny < 1) zeny = 1;
sd->status.zeny -= zeny;
@@ -378,37 +367,40 @@ int pc_makesavestatus(struct map_session_data *sd)
{
nullpo_retr(0, sd);
- // 服の色は色?弊害が多いので保存?象にはしない
+ // 秒フ色は色?弊害が多いので保存?象にはしない
if(!battle_config.save_clothcolor)
sd->status.clothes_color=0;
// 死亡?態だったのでhpを1、位置をセ?ブ場所に?更
- if(pc_isdead(sd)){
- pc_setrestartvalue(sd,0);
- memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point));
- } else {
- memcpy(sd->status.last_point.map,sd->mapname,24);
- sd->status.last_point.x = sd->bl.x;
- sd->status.last_point.y = sd->bl.y;
- }
-
- // セ?ブ禁止マップだったので指定位置に移動
- if(map[sd->bl.m].flag.nosave){
- struct map_data *m=&map[sd->bl.m];
- if(strcmp(m->save.map,"SavePoint")==0)
+ if(!sd->state.waitingdisconnect) {
+ if(pc_isdead(sd)){
+ pc_setrestartvalue(sd,0);
memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point));
- else
- memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point));
+ } else {
+ memcpy(sd->status.last_point.map,sd->mapname,24);
+ sd->status.last_point.x = sd->bl.x;
+ sd->status.last_point.y = sd->bl.y;
+ }
+
+ // セ?ブ禁止マップだったので指定位置に移動
+ if(map[sd->bl.m].flag.nosave){
+ struct map_data *m=&map[sd->bl.m];
+ if(strcmp(m->save.map,"SavePoint")==0)
+ memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point));
+ else
+ memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point));
+ }
}
//マナ?ポイントがプラスだった場合0に
if(battle_config.muting_players && sd->status.manner > 0)
sd->status.manner = 0;
+
return 0;
}
/*==========================================
- * 接?時の初期化
+ * 接?暫フ初期化
*------------------------------------------
*/
int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int login_id1, int client_tick, int sex, int fd) {
@@ -437,7 +429,7 @@ int pc_equippoint(struct map_session_data *sd,int n)
nullpo_retr(0, sd);
- s_class = pc_calc_base_job(sd->status.class);
+ s_class = pc_calc_base_job(sd->status.class_);
if(sd->inventory_data[n]) {
ep = sd->inventory_data[n]->equip;
@@ -543,8 +535,8 @@ int pc_isequip(struct map_session_data *sd,int n)
nullpo_retr(0, sd);
item = sd->inventory_data[n];
- sc_data = battle_get_sc_data(&sd->bl);
- //s_class = pc_calc_base_job(sd->status.class);
+ sc_data = status_get_sc_data(&sd->bl);
+ //s_class = pc_calc_base_job(sd->status.class_);
if( battle_config.gm_allequip>0 && pc_isGM(sd)>=battle_config.gm_allequip )
return 1;
@@ -559,18 +551,18 @@ int pc_isequip(struct map_session_data *sd,int n)
// as it allows all advanced classes to equip items their normal versions
// could equip)
//
- if(((sd->status.class==13 || sd->status.class==4014) && ((1<<7)&item->class) == 0) || // have mounted classes use unmounted equipment [Valaris]
- ((sd->status.class==21 || sd->status.class==4022) && ((1<<14)&item->class) == 0))
+ if(((sd->status.class_==13 || sd->status.class_==4014) && ((1<<7)&item->class_) == 0) || // have mounted classes use unmounted equipment [Valaris]
+ ((sd->status.class_==21 || sd->status.class_==4022) && ((1<<14)&item->class_) == 0))
return 0;
- if(sd->status.class!=13 && sd->status.class!=4014 && sd->status.class!=21 && sd->status.class!=4022)
- if((sd->status.class<=4000 && ((1<<sd->status.class)&item->class) == 0) || (sd->status.class>4000 && sd->status.class<4023 && ((1<<(sd->status.class-4001))&item->class) == 0) ||
- (sd->status.class>=4023 && ((1<<(sd->status.class-4023))&item->class) == 0))
+ if(sd->status.class_!=13 && sd->status.class_!=4014 && sd->status.class_!=21 && sd->status.class_!=4022)
+ if((sd->status.class_<=4000 && ((1<<sd->status.class_)&item->class_) == 0) || (sd->status.class_>4000 && sd->status.class_<4023 && ((1<<(sd->status.class_-4001))&item->class_) == 0) ||
+ (sd->status.class_>=4023 && ((1<<(sd->status.class_-4023))&item->class_) == 0))
return 0;
-// if(((1<<sd->status.class)&item->class) == 0)
+// if(((1<<sd->status.class_)&item->class_) == 0)
// return 0;
- if(map[sd->bl.m].flag.pvp && (item->flag.no_equip==1 || item->flag.no_equip==3))
+ if(map[sd->bl.m].flag.pvp && (item->flag.no_equip&1)) //optimized by Lupus
return 0;
- if(map[sd->bl.m].flag.gvg && (item->flag.no_equip==2 || item->flag.no_equip==3))
+ if(map[sd->bl.m].flag.gvg && (item->flag.no_equip>1)) //optimized by Lupus
return 0;
if(item->equip & 0x0002 && sc_data && sc_data[SC_STRIPWEAPON].timer != -1)
return 0;
@@ -583,69 +575,52 @@ int pc_isequip(struct map_session_data *sd,int n)
return 1;
}
-/*==========================================
- * Weapon Breaking [Valaris]
- *------------------------------------------
- */
-int pc_breakweapon(struct map_session_data *sd)
+//装備破壊
+int pc_break_equip(struct map_session_data *sd, unsigned short where)
{
- struct item_data* item;
- char output[255];
int i;
+ int sc;
- if(sd==NULL)
- return -1;
- if(sd->unbreakable>=rand()%100)
+ nullpo_retr(-1, sd);
+ if(sd->unbreakable_equip & where)
return 0;
- if(sd->sc_data && sd->sc_data[SC_CP_WEAPON].timer != -1)
+ if(sd->unbreakable >= rand()%100)
return 0;
-
- for(i=0;i<MAX_INVENTORY;i++){
- if(sd->status.inventory[i].equip && sd->status.inventory[i].equip & 0x0002 && !sd->status.inventory[i].attribute==1){
- item=sd->inventory_data[i];
- sd->status.inventory[i].attribute=1;
- pc_unequipitem(sd,i,0,BF_NORMAL);
- sprintf(output, "%s has broken.",item->jname);
- clif_emotion(&sd->bl,23);
- clif_displaymessage(sd->fd, output);
- clif_equiplist(sd);
- return 1;
- }
+ switch (where) {
+ case EQP_WEAPON:
+ sc = SC_CP_WEAPON;
+ break;
+ case EQP_ARMOR:
+ sc = SC_CP_ARMOR;
+ break;
+ case EQP_SHIELD:
+ sc = SC_CP_SHIELD;
+ break;
+ case EQP_HELM:
+ sc = SC_CP_HELM;
+ break;
+ default:
+ return 0;
}
-
- return 0;
-}
-/*==========================================
- * Armor Breaking [Valaris]
- *------------------------------------------
- */
-int pc_breakarmor(struct map_session_data *sd)
-{
- struct item_data* item;
- char output[255];
- int i;
-
- if(sd==NULL)
- return -1;
- if(sd->unbreakable>=rand()%100)
- return 0;
- if(sd->sc_data && sd->sc_data[SC_CP_ARMOR].timer != -1)
+ if(sd->sc_count && sd->sc_data[sc].timer != -1)
return 0;
- for(i=0;i<MAX_INVENTORY;i++){
- if(sd->status.inventory[i].equip && sd->status.inventory[i].equip & 0x0010 && !sd->status.inventory[i].attribute==1){
- item=sd->inventory_data[i];
- sd->status.inventory[i].attribute=1;
- pc_unequipitem(sd,i,0,BF_NORMAL);
- sprintf(output, "%s has broken.",item->jname);
+ for (i=0;i<MAX_INVENTORY;i++) {
+ if (sd->status.inventory[i].equip & where &&
+ sd->status.inventory[i].attribute != 1) {
+ sd->status.inventory[i].attribute = 1;
+ pc_unequipitem(sd,i,3);
+ sprintf(tmp_output, "%s has broken.",sd->inventory_data[i]->jname);
clif_emotion(&sd->bl,23);
- clif_displaymessage(sd->fd, output);
+ clif_displaymessage(sd->fd, tmp_output);
clif_equiplist(sd);
+ break;
}
}
- return 0;
+ return 1;
}
+
/*==========================================
* session idに問題無し
* char鯖から送られてきたステ?タスを設定
@@ -663,8 +638,14 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars
sd = map_id2sd(id);
nullpo_retr(1, sd);
+ // check if double login occured
+ if(sd->new_fd){
+ // 2重login状態だったので、両方落す
+ clif_authfail_fd(sd->fd,2); // same id
+ clif_authfail_fd(sd->new_fd,8); // same id
+ return 1;
+ }
sd->login_id2 = login_id2;
-
memcpy(&sd->status, st, sizeof(*st));
if (sd->status.sex != sd->sex) {
@@ -678,21 +659,21 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars
sd->bl.prev = sd->bl.next = NULL;
sd->weapontype1 = sd->weapontype2 = 0;
- sd->view_class = sd->status.class;
+ sd->view_class = sd->status.class_;
sd->speed = DEFAULT_WALK_SPEED;
sd->state.dead_sit = 0;
sd->dir = 0;
sd->head_dir = 0;
sd->state.auth = 1;
sd->walktimer = -1;
+ sd->next_walktime = -1;
sd->attacktimer = -1;
sd->followtimer = -1; // [MouseJstr]
sd->skilltimer = -1;
sd->skillitem = -1;
sd->skillitemlv = -1;
sd->invincible_timer = -1;
- sd->sg_count = 0;
-
+
sd->deal_locked = 0;
sd->trade_partner = 0;
@@ -704,11 +685,11 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars
sd->inchealspiritsptick = 0;
sd->canact_tick = tick;
sd->canmove_tick = tick;
+ sd->canregen_tick = tick;
sd->attackabletime = tick;
-
+ sd->reg_num = 0;
sd->doridori_counter = 0;
-
- sd->change_level = pc_readglobalreg(sd,"jobchange_level");
+ sd->change_level = pc_readglobalreg(sd,"jobchange_level");
#ifndef TXT_ONLY // mail system [Valaris]
if(battle_config.mail_system)
@@ -719,13 +700,16 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars
sd->spirit_timer[i] = -1;
for(i = 0; i < MAX_SKILLTIMERSKILL; i++)
sd->skilltimerskill[i].timer = -1;
+ sd->timerskill_count=0;
+
+ memset(sd->blockskill,0,sizeof(sd->blockskill));
memset(&sd->dev,0,sizeof(struct square));
for(i = 0; i < 5; i++) {
sd->dev.val1[i] = 0;
sd->dev.val2[i] = 0;
}
-
+
// アカウント??の送信要求
intif_request_accountreg(sd);
@@ -753,7 +737,7 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars
// スキルユニット?係の初期化
memset(sd->skillunit, 0, sizeof(sd->skillunit));
- memset(sd->skillunittick, 0, sizeof(sd->skillunittick));
+ memset(sd->skillunittick, 0, sizeof(sd->skillunittick));
// パ?ティ??係の初期化
sd->party_sended = 0;
@@ -771,9 +755,22 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars
memset(sd->eventqueue, 0, sizeof(sd->eventqueue));
for(i = 0; i < MAX_EVENTTIMER; i++)
sd->eventtimer[i] = -1;
+ sd->eventcount=0;
// 位置の設定
- pc_setpos(sd,sd->status.last_point.map, sd->status.last_point.x, sd->status.last_point.y, 0);
+ if (pc_setpos(sd,sd->status.last_point.map, sd->status.last_point.x, sd->status.last_point.y, 0) != 0) {
+ if(battle_config.error_log) {
+ char buf[32];
+ sprintf(buf, "Last_point_map %s not found\n", sd->status.last_point.map);
+ ShowError (buf);
+ }
+ // try warping to a default map instead
+ if (pc_setpos(sd, "prontera.gat", 273, 354, 0) != 0) {
+ // if we fail again
+ clif_authfail_fd(sd->fd, 0);
+ return 1;
+ }
+ }
// pet
if (sd->status.pet_id > 0)
@@ -800,6 +797,18 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars
//スパノビ用死にカウンタ?のスクリプト??からの?み出しとsdへのセット
sd->die_counter = pc_readglobalreg(sd,"PC_DIE_COUNTER");
+ // Automated script events
+ if (script_config.event_requires_trigger) {
+ sd->state.event_death = pc_readglobalreg(sd, script_config.die_event_name);
+ sd->state.event_kill = pc_readglobalreg(sd, script_config.kill_event_name);
+ sd->state.event_disconnect = pc_readglobalreg(sd, script_config.logout_event_name);
+ // if script triggers are not required
+ } else {
+ sd->state.event_death = 1;
+ sd->state.event_kill = 1;
+ sd->state.event_disconnect = 1;
+ }
+
if (night_flag == 1 && !map[sd->bl.m].flag.indoors) {
char tmpstr[1024];
strcpy(tmpstr, msg_txt(500)); // Actually, it's the night...
@@ -812,16 +821,28 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars
}
// ステ?タス初期計算など
- pc_calcstatus(sd,1);
+ status_calc_pc(sd,1);
if (pc_isGM(sd))
- printf("Connection accepted: character '%s' (account: %d; GM level %d).\n", sd->status.name, sd->status.account_id, pc_isGM(sd));
+ sprintf(tmp_output,"GM Character '"CL_WHITE"%s"CL_RESET"' logged in. (Acc. ID: '"CL_WHITE"%d"CL_RESET"', GM Level '"CL_WHITE"%d"CL_RESET"').\n", sd->status.name, sd->status.account_id, pc_isGM(sd));
else
- printf("Connection accepted: Character '%s' (account: %d).\n", sd->status.name, sd->status.account_id);
+ sprintf(tmp_output,"Character '"CL_WHITE"%s"CL_RESET"' logged in. (Account ID: '"CL_WHITE"%d"CL_RESET"').\n", sd->status.name, sd->status.account_id);
+ ShowInfo(tmp_output);
+
+ if (script_config.event_script_type == 0) {
+ struct npc_data *npc;
+ //printf("pc: OnPCLogin event done. (%d events)\n", npc_event_doall("OnPCLogin") );
+ if ((npc = npc_name2id(script_config.login_event_name))) {
+ run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLoginNPC
+ sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.login_event_name);
+ ShowStatus(tmp_output);
+ }
+ } else {
+ sprintf (tmp_output, "%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
+ npc_event_doall_id(script_config.login_event_name, sd->bl.id), script_config.login_event_name);
+ ShowStatus(tmp_output);
+ }
- //printf("pc: OnPCLogin event done. (%d events)\n", npc_event_doall("OnPCLogin") );
- if (npc_name2id("PCLoginEvent"))
- run_script(npc_name2id("PCLoginEvent")->u.scr.script,0,sd->bl.id,npc_name2id("PCLoginEvent")->bl.id); // PCLoginNPC
// Send friends list
clif_friends_list_send(sd);
@@ -838,13 +859,16 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars
break;
}
}
- clif_displaymessage(sd->fd, buf);
+ if (battle_config.motd_type)
+ clif_disp_onlyself(sd,buf,strlen(buf));
+ else
+ clif_displaymessage(sd->fd, buf);
}
fclose(fp);
}
else if(battle_config.error_log) {
- sprintf(buf, "%s not found\n", motd_txt);
- ShowWarning (buf);
+ sprintf(tmp_output, "In function pc_atuhok() -> File '"CL_WHITE"%s"CL_RESET"' not found.\n", motd_txt);
+ ShowWarning(tmp_output);
}
}
@@ -874,6 +898,13 @@ int pc_authfail(int id) {
if (sd == NULL)
return 1;
+ if(sd->new_fd){
+ // 2重login状態だったので、新しい接続のみ落す
+ clif_authfail_fd(sd->new_fd,0);
+ sd->new_fd=0;
+ return 0;
+ }
+
clif_authfail_fd(sd->fd, 0);
return 0;
@@ -913,7 +944,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
nullpo_retr(0, sd);
- s_class = pc_calc_base_job(sd->status.class);
+ s_class = pc_calc_base_job(sd->status.class_);
c = s_class.job;
//s = (s_class.upper==1) ? 1 : 0 ; //?生以外は通常のスキル?
s = s_class.upper;
@@ -921,7 +952,10 @@ int pc_calc_skilltree(struct map_session_data *sd)
c = pc_calc_skilltree_normalize_job(c, sd);
for(i=0;i<MAX_SKILL;i++){
- if (sd->status.skill[i].flag != 13) sd->status.skill[i].id=0;
+// if(skill_get_inf2(i) & 0x01)
+// continue;
+ if (sd->status.skill[i].flag != 13)
+ sd->status.skill[i].id=0;
if (sd->status.skill[i].flag && sd->status.skill[i].flag != 13){ // cardスキルなら、
sd->status.skill[i].lv=(sd->status.skill[i].flag==1)?0:sd->status.skill[i].flag-2; // 本?のlvに
sd->status.skill[i].flag=0; // flagは0にしておく
@@ -934,39 +968,60 @@ int pc_calc_skilltree(struct map_session_data *sd)
sd->status.skill[i].id=i;
for(i=210;i<291;i++)
sd->status.skill[i].id=i;
- for(i=304;i<337;i++){
+ for(i=304;i<338;i++){
if(i==331) continue;
sd->status.skill[i].id=i;
}
- if(battle_config.enable_upper_class){ //confで無?でなければ?み?む
- for(i=355;i<MAX_SKILL;i++)
+ for(i=355;i<411;i++)
sd->status.skill[i].id=i;
- }
- }else{
- // 通常の計算
- do{
- flag=0;
- for(i=0;(id=skill_tree[s][c][i].id)>0;i++){
- int j,f=1;
- if(!battle_config.skillfree) {
- for(j=0;j<5;j++) {
- if( skill_tree[s][c][i].need[j].id &&
- pc_checkskill(sd,skill_tree[s][c][i].need[j].id) < skill_tree[s][c][i].need[j].lv)
+ for(i=475;i<480;i++)
+ sd->status.skill[i].id=i;
+ } else {
+ do {
+ flag=0;
+ for(i=0;(id=skill_tree[s][c][i].id)>0;i++){
+ int j,f=1;
+ if(!battle_config.skillfree) {
+ for(j=0;j<5;j++) {
+ if( skill_tree[s][c][i].need[j].id &&
+ pc_checkskill(sd,skill_tree[s][c][i].need[j].id) <
+ skill_tree[s][c][i].need[j].lv) {
+ f=0;
+ break;
+ }
+ }
+ if (sd->status.job_level < skill_tree[s][c][i].joblv)
f=0;
+ else if (id >= 2 && id <= 53 && pc_checkskill(sd, NV_BASIC) < 9)
+ f=0;
+ }
+ if(f && sd->status.skill[id].id==0 ){
+ sd->status.skill[id].id=id;
+ flag=1;
}
}
- if(f && sd->status.skill[id].id==0 ){
- sd->status.skill[id].id=id;
- flag=1;
- }
- }
- }while(flag);
+ } while(flag);
}
// if(battle_config.etc_log)
// printf("calc skill_tree\n");
return 0;
}
+// Make sure all the skills are in the correct condition
+// before persisting to the backend.. [MouseJstr]
+int pc_clean_skilltree(struct map_session_data *sd) {
+ int i;
+ for (i = 0; i < MAX_SKILL; i++){
+ if (sd->status.skill[i].flag == 13){
+ sd->status.skill[i].id = 0;
+ sd->status.skill[i].lv = 0;
+ sd->status.skill[i].flag = 0;
+ }
+ }
+
+ return 0;
+}
+
int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd) {
//if((battle_config.skillup_limit) && ((c >= 0 && c < 23) || (c >= 4001 && c < 4023) || (c >= 4023 && c < 4045))) {
if (battle_config.skillup_limit && c >= 0 && c < 23) {
@@ -975,10 +1030,12 @@ int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd) {
c = 0;
//else if((sd->status.skill_point >= sd->status.job_level && skill_point < 58) && ((c > 6 && c < 23) || (c > 4007 && c < 4023) || (c > 4029 && c < 4045))) {
//else if ((sd->status.skill_point >= sd->status.job_level && skill_point < 58) && (c > 6 && c < 23)) {
- else if ((sd->status.skill_point >= sd->status.job_level && skill_point < sd->change_level+8) && (c > 6 && c < 23)) {
+ else if (sd->status.skill_point >= sd->status.job_level && ((sd->change_level > 0 && skill_point < sd->change_level+8) || skill_point < 58) && (c > 6 && c < 23)) {
switch(c) {
case 7:
+ case 13:
case 14:
+ case 21:
c = 1;
break;
case 8:
@@ -1002,8 +1059,11 @@ int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd) {
case 17:
c = 6;
break;
- /*case 4008:
+#if 0
+ case 4008:
+ case 4014:
case 4015:
+ case 4022:
c = 4002;
break;
case 4009:
@@ -1028,7 +1088,9 @@ int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd) {
c = 4007;
break;
case 4030:
+ case 4036:
case 4037:
+ case 4044:
c = 4024;
break;
case 4031:
@@ -1051,7 +1113,8 @@ int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd) {
case 4035:
case 4043:
c = 4029;
- break;*/
+ break;
+#endif
}
}
}
@@ -1072,1127 +1135,29 @@ int pc_checkweighticon(struct map_session_data *sd)
flag=1;
if(sd->weight*10 >= sd->max_weight*9)
flag=2;
-
+
if(flag==1){
if(sd->sc_data[SC_WEIGHT50].timer==-1)
- skill_status_change_start(&sd->bl,SC_WEIGHT50,0,0,0,0,0,0);
+ status_change_start(&sd->bl,SC_WEIGHT50,0,0,0,0,0,0);
}else{
- skill_status_change_end(&sd->bl,SC_WEIGHT50,-1);
+ status_change_end(&sd->bl,SC_WEIGHT50,-1);
}
if(flag==2){
if(sd->sc_data[SC_WEIGHT90].timer==-1)
- skill_status_change_start(&sd->bl,SC_WEIGHT90,0,0,0,0,0,0);
+ status_change_start(&sd->bl,SC_WEIGHT90,0,0,0,0,0,0);
}else{
- skill_status_change_end(&sd->bl,SC_WEIGHT90,-1);
+ status_change_end(&sd->bl,SC_WEIGHT90,-1);
}
return 0;
}
/*==========================================
- * パラメ?タ計算
- * first==0の時、計算?象のパラメ?タが呼び出し前から
- * ? 化した場合自動でsendするが、
- * 能動的に?化させたパラメ?タは自前でsendするように
- *------------------------------------------
- */
-int pc_calcstatus(struct map_session_data* sd,int first)
-{
- int b_speed,b_max_hp,b_max_sp,b_hp,b_sp,b_weight,b_max_weight,b_paramb[6],b_parame[6],b_hit,b_flee;
- int b_aspd,b_watk,b_def,b_watk2,b_def2,b_flee2,b_critical,b_attackrange,b_matk1,b_matk2,b_mdef,b_mdef2,b_class;
- int b_base_atk;
- struct skill b_skill[MAX_SKILL];
- int i,bl,index;
- int skill,aspd_rate,wele,wele_,def_ele,refinedef=0;
- int pele=0,pdef_ele=0;
- int str,dstr,dex;
- struct pc_base_job s_class;
-
- nullpo_retr(0, sd);
-
- //?生や養子の場合の元の職業を算出する
- s_class = pc_calc_base_job(sd->status.class);
-
- b_speed = sd->speed;
- b_max_hp = sd->status.max_hp;
- b_max_sp = sd->status.max_sp;
- b_hp = sd->status.hp;
- b_sp = sd->status.sp;
- b_weight = sd->weight;
- b_max_weight = sd->max_weight;
- memcpy(b_paramb,&sd->paramb,sizeof(b_paramb));
- memcpy(b_parame,&sd->paramc,sizeof(b_parame));
- memcpy(b_skill,&sd->status.skill,sizeof(b_skill));
- b_hit = sd->hit;
- b_flee = sd->flee;
- b_aspd = sd->aspd;
- b_watk = sd->watk;
- b_def = sd->def;
- b_watk2 = sd->watk2;
- b_def2 = sd->def2;
- b_flee2 = sd->flee2;
- b_critical = sd->critical;
- b_attackrange = sd->attackrange;
- b_matk1 = sd->matk1;
- b_matk2 = sd->matk2;
- b_mdef = sd->mdef;
- b_mdef2 = sd->mdef2;
- b_class = sd->view_class;
- sd->view_class = sd->status.class;
- b_base_atk = sd->base_atk;
-
- pc_calc_skilltree(sd); // スキルツリ?の計算
-
- sd->max_weight = max_weight_base[s_class.job]+sd->status.str*300;
-
- if(first&1) {
- sd->weight=0;
- for(i=0;i<MAX_INVENTORY;i++){
- if(sd->status.inventory[i].nameid==0 || sd->inventory_data[i] == NULL)
- continue;
- sd->weight += sd->inventory_data[i]->weight*sd->status.inventory[i].amount;
- }
- sd->cart_max_weight=battle_config.max_cart_weight;
- sd->cart_weight=0;
- sd->cart_max_num=MAX_CART;
- sd->cart_num=0;
- for(i=0;i<MAX_CART;i++){
- if(sd->status.cart[i].nameid==0)
- continue;
- sd->cart_weight+=itemdb_weight(sd->status.cart[i].nameid)*sd->status.cart[i].amount;
- sd->cart_num++;
- }
- }
-
- memset(sd->paramb,0,sizeof(sd->paramb));
- memset(sd->parame,0,sizeof(sd->parame));
- sd->hit = 0;
- sd->flee = 0;
- sd->flee2 = 0;
- sd->critical = 0;
- sd->aspd = 0;
- sd->watk = 0;
- sd->def = 0;
- sd->mdef = 0;
- sd->watk2 = 0;
- sd->def2 = 0;
- sd->mdef2 = 0;
- sd->status.max_hp = 0;
- sd->status.max_sp = 0;
- sd->attackrange = 0;
- sd->attackrange_ = 0;
- sd->atk_ele = 0;
- sd->def_ele = 0;
- sd->star =0;
- sd->overrefine =0;
- sd->matk1 =0;
- sd->matk2 =0;
- sd->speed = DEFAULT_WALK_SPEED ;
- sd->hprate=100;
- sd->sprate=100;
- sd->castrate=100;
- sd->dsprate=100;
- sd->base_atk=0;
- sd->arrow_atk=0;
- sd->arrow_ele=0;
- sd->arrow_hit=0;
- sd->arrow_range=0;
- sd->nhealhp=sd->nhealsp=sd->nshealhp=sd->nshealsp=sd->nsshealhp=sd->nsshealsp=0;
- memset(sd->addele,0,sizeof(sd->addele));
- memset(sd->addrace,0,sizeof(sd->addrace));
- memset(sd->addsize,0,sizeof(sd->addsize));
- memset(sd->addele_,0,sizeof(sd->addele_));
- memset(sd->addrace_,0,sizeof(sd->addrace_));
- memset(sd->addsize_,0,sizeof(sd->addsize_));
- memset(sd->subele,0,sizeof(sd->subele));
- memset(sd->subrace,0,sizeof(sd->subrace));
- memset(sd->addeff,0,sizeof(sd->addeff));
- memset(sd->addeff2,0,sizeof(sd->addeff2));
- memset(sd->reseff,0,sizeof(sd->reseff));
- memset(&sd->special_state,0,sizeof(sd->special_state));
- memset(sd->weapon_coma_ele,0,sizeof(sd->weapon_coma_ele));
- memset(sd->weapon_coma_race,0,sizeof(sd->weapon_coma_race));
-
- sd->watk_ = 0; //二刀流用(?)
- sd->watk_2 = 0;
- sd->atk_ele_ = 0;
- sd->star_ = 0;
- sd->overrefine_ = 0;
-
- sd->aspd_rate = 100;
- sd->speed_rate = 100;
- sd->hprecov_rate = 100;
- sd->sprecov_rate = 100;
- sd->critical_def = 0;
- sd->double_rate = 0;
- sd->near_attack_def_rate = sd->long_attack_def_rate = 0;
- sd->atk_rate = sd->matk_rate = 100;
- sd->ignore_def_ele = sd->ignore_def_race = 0;
- sd->ignore_def_ele_ = sd->ignore_def_race_ = 0;
- sd->ignore_mdef_ele = sd->ignore_mdef_race = 0;
- sd->arrow_cri = 0;
- sd->magic_def_rate = sd->misc_def_rate = 0;
- memset(sd->arrow_addele,0,sizeof(sd->arrow_addele));
- memset(sd->arrow_addrace,0,sizeof(sd->arrow_addrace));
- memset(sd->arrow_addsize,0,sizeof(sd->arrow_addsize));
- memset(sd->arrow_addeff,0,sizeof(sd->arrow_addeff));
- memset(sd->arrow_addeff2,0,sizeof(sd->arrow_addeff2));
- memset(sd->magic_addele,0,sizeof(sd->magic_addele));
- memset(sd->magic_addrace,0,sizeof(sd->magic_addrace));
- memset(sd->magic_subrace,0,sizeof(sd->magic_subrace));
- sd->perfect_hit = 0;
- sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100;
- sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100;
- sd->def_ratio_atk_ele = sd->def_ratio_atk_ele_ = 0;
- sd->def_ratio_atk_race = sd->def_ratio_atk_race_ = 0;
- sd->get_zeny_num = 0;
- sd->add_damage_class_count = sd->add_damage_class_count_ = sd->add_magic_damage_class_count = 0;
- sd->add_def_class_count = sd->add_mdef_class_count = 0;
- sd->monster_drop_item_count = 0;
- memset(sd->add_damage_classrate,0,sizeof(sd->add_damage_classrate));
- memset(sd->add_damage_classrate_,0,sizeof(sd->add_damage_classrate_));
- memset(sd->add_magic_damage_classrate,0,sizeof(sd->add_magic_damage_classrate));
- memset(sd->add_def_classrate,0,sizeof(sd->add_def_classrate));
- memset(sd->add_mdef_classrate,0,sizeof(sd->add_mdef_classrate));
- memset(sd->monster_drop_race,0,sizeof(sd->monster_drop_race));
- memset(sd->monster_drop_itemrate,0,sizeof(sd->monster_drop_itemrate));
- sd->speed_add_rate = sd->aspd_add_rate = 100;
- sd->double_add_rate = sd->perfect_hit_add = sd->get_zeny_add_num = 0;
- sd->splash_range = sd->splash_add_range = 0;
- sd->autospell_id = sd->autospell_lv = sd->autospell_rate = 0;
- sd->hp_drain_rate = sd->hp_drain_per = sd->sp_drain_rate = sd->sp_drain_per = 0;
- sd->hp_drain_rate_ = sd->hp_drain_per_ = sd->sp_drain_rate_ = sd->sp_drain_per_ = 0;
- sd->short_weapon_damage_return = sd->long_weapon_damage_return = 0;
- sd->magic_damage_return = 0; //AppleGirl Was Here
- sd->random_attack_increase_add = sd->random_attack_increase_per = 0;
-
- if(!sd->disguiseflag && sd->disguise) {
- sd->disguise=0;
- clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
- clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
- clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
- clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
- clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
- clif_clearchar(&sd->bl, 9);
- pc_setpos(sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
- }
-
- for(i=0;i<10;i++) {
- index = sd->equip_index[i];
- if(index < 0)
- continue;
- if(i == 9 && sd->equip_index[8] == index)
- continue;
- if(i == 5 && sd->equip_index[4] == index)
- continue;
- if(i == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index))
- continue;
-
- if(sd->inventory_data[index]) {
- if(sd->inventory_data[index]->type == 4) {
- if(sd->status.inventory[index].card[0]!=0x00ff && sd->status.inventory[index].card[0]!=0x00fe && sd->status.inventory[index].card[0]!=(short)0xff00) {
- int j;
- for(j=0;j<sd->inventory_data[index]->slot;j++){ // カ?ド
- int c=sd->status.inventory[index].card[j];
- if(c>0){
- if(i == 8 && sd->status.inventory[index].equip == 0x20)
- sd->state.lr_flag = 1;
- run_script(itemdb_equipscript(c),0,sd->bl.id,0);
- sd->state.lr_flag = 0;
- }
- }
- }
- }
- else if(sd->inventory_data[index]->type==5){ // 防具
- if(sd->status.inventory[index].card[0]!=0x00ff && sd->status.inventory[index].card[0]!=0x00fe && sd->status.inventory[index].card[0]!=(short)0xff00) {
- int j;
- for(j=0;j<sd->inventory_data[index]->slot;j++){ // カ?ド
- int c=sd->status.inventory[index].card[j];
- if(c>0)
- run_script(itemdb_equipscript(c),0,sd->bl.id,0);
- }
- }
- }
- }
- }
- wele = sd->atk_ele;
- wele_ = sd->atk_ele_;
- def_ele = sd->def_ele;
- if(sd->status.pet_id > 0) {
- struct pet_data *pd=sd->pd;
- if((pd && battle_config.pet_status_support==1) && (battle_config.pet_equip_required==0 || (battle_config.pet_equip_required && pd->equip > 0))) {
- if(sd->status.pet_id > 0 && sd->petDB && sd->pet.intimate > 0)
- run_script(sd->petDB->script,0,sd->bl.id,0);
- pele = sd->atk_ele;
- pdef_ele = sd->def_ele;
- sd->atk_ele = sd->def_ele = 0;
- }
- }
- memcpy(sd->paramcard,sd->parame,sizeof(sd->paramcard));
-
- // ?備品によるステ?タス?化はここで?行
- for(i=0;i<10;i++) {
- index = sd->equip_index[i];
- if(index < 0)
- continue;
- if(i == 9 && sd->equip_index[8] == index)
- continue;
- if(i == 5 && sd->equip_index[4] == index)
- continue;
- if(i == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index))
- continue;
- if(sd->inventory_data[index]) {
- sd->def += sd->inventory_data[index]->def;
- if(sd->inventory_data[index]->type == 4) {
- int r,wlv = sd->inventory_data[index]->wlv;
- if(i == 8 && sd->status.inventory[index].equip == 0x20) {
- //二刀流用デ?タ入力
- sd->watk_ += sd->inventory_data[index]->atk;
- sd->watk_2 = (r=sd->status.inventory[index].refine)* // 精?攻?力
- refinebonus[wlv][0];
- if( (r-=refinebonus[wlv][2])>0 ) // 過?精?ボ?ナス
- sd->overrefine_ = r*refinebonus[wlv][1];
-
- if(sd->status.inventory[index].card[0]==0x00ff){ // 製造武器
- sd->star_ = (sd->status.inventory[index].card[1]>>8); // 星のかけら
- wele_= (sd->status.inventory[index].card[1]&0x0f); // ? 性
- }
- sd->attackrange_ += sd->inventory_data[index]->range;
- sd->state.lr_flag = 1;
- run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
- sd->state.lr_flag = 0;
- }
- else { //二刀流武器以外
- sd->watk += sd->inventory_data[index]->atk;
- sd->watk2 += (r=sd->status.inventory[index].refine)* // 精?攻?力
- refinebonus[wlv][0];
- if( (r-=refinebonus[wlv][2])>0 ) // 過?精?ボ?ナス
- sd->overrefine += r*refinebonus[wlv][1];
-
- if(sd->status.inventory[index].card[0]==0x00ff){ // 製造武器
- sd->star += (sd->status.inventory[index].card[1]>>8); // 星のかけら
- wele = (sd->status.inventory[index].card[1]&0x0f); // ? 性
- }
- sd->attackrange += sd->inventory_data[index]->range;
- run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
- }
- }
- else if(sd->inventory_data[index]->type == 5) {
- sd->watk += sd->inventory_data[index]->atk;
- refinedef += sd->status.inventory[index].refine*refinebonus[0][0];
- run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
- }
- }
- }
-
- if(sd->equip_index[10] >= 0){ // 矢
- index = sd->equip_index[10];
- if(sd->inventory_data[index]){ //まだ?性が入っていない
- sd->state.lr_flag = 2;
- run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
- sd->state.lr_flag = 0;
- sd->arrow_atk += sd->inventory_data[index]->atk;
- }
- }
- sd->def += (refinedef+50)/100;
-
- if(sd->attackrange < 1) sd->attackrange = 1;
- if(sd->attackrange_ < 1) sd->attackrange_ = 1;
- if(sd->attackrange < sd->attackrange_)
- sd->attackrange = sd->attackrange_;
- if(sd->status.weapon == 11)
- sd->attackrange += sd->arrow_range;
- if(wele > 0)
- sd->atk_ele = wele;
- if(wele_ > 0)
- sd->atk_ele_ = wele_;
- if(def_ele > 0)
- sd->def_ele = def_ele;
- if(battle_config.pet_status_support) {
- if(pele > 0 && !sd->atk_ele)
- sd->atk_ele = pele;
- if(pdef_ele > 0 && !sd->def_ele)
- sd->def_ele = pdef_ele;
- }
- sd->double_rate += sd->double_add_rate;
- sd->perfect_hit += sd->perfect_hit_add;
- sd->get_zeny_num += sd->get_zeny_add_num;
- sd->splash_range += sd->splash_add_range;
- if(sd->speed_add_rate != 100)
- sd->speed_rate += sd->speed_add_rate - 100;
- if(sd->aspd_add_rate != 100)
- sd->aspd_rate += sd->aspd_add_rate - 100;
-
- // 武器ATKサイズ補正 (右手)
- sd->atkmods[0] = atkmods[0][sd->weapontype1];
- sd->atkmods[1] = atkmods[1][sd->weapontype1];
- sd->atkmods[2] = atkmods[2][sd->weapontype1];
- //武器ATKサイズ補正 (左手)
- sd->atkmods_[0] = atkmods[0][sd->weapontype2];
- sd->atkmods_[1] = atkmods[1][sd->weapontype2];
- sd->atkmods_[2] = atkmods[2][sd->weapontype2];
-
- // jobボ?ナス分
- for(i=0;i<sd->status.job_level && i<MAX_LEVEL;i++){
- if(job_bonus[s_class.upper][s_class.job][i])
- sd->paramb[job_bonus[s_class.upper][s_class.job][i]-1]++;
- }
-
- if( (skill=pc_checkskill(sd,MC_INCCARRY))>0 ) // skill can be used with an item now, thanks to orn [Valaris]
- sd->max_weight += skill*1000;
-
- if( (skill=pc_checkskill(sd,AC_OWL))>0 ) // ふくろうの目
- sd->paramb[4] += skill;
-
- if((skill=pc_checkskill(sd,BS_HILTBINDING))>0) { // Hilt binding gives +1 str +4 atk
- sd->paramb[0] ++;
- sd->base_atk += 4;
- }
-
- // New guild skills - Celest
- if (sd->status.guild_id > 0) {
- struct guild *g;
- if ((g = guild_search(sd->status.guild_id)) && strcmp(sd->status.name,g->master)==0) {
- if (!sd->sc_data[SC_LEADERSHIP].val4 && guild_checkskill(g, GD_LEADERSHIP)>0) {
- //skill_status_change_start(&sd->bl,SC_LEADERSHIP,1,0,0,0,0,0 );
- skill_unitsetting(&sd->bl,GD_LEADERSHIP,1,sd->bl.x,sd->bl.y,0);
- }
- if (!sd->sc_data[SC_GLORYWOUNDS].val4 && guild_checkskill(g, GD_GLORYWOUNDS)>0) {
- //skill_status_change_start(&sd->bl,SC_GLORYWOUNDS,1,0,0,0,0,0 );
- skill_unitsetting(&sd->bl,GD_GLORYWOUNDS,1,sd->bl.x,sd->bl.y,0);
- }
- if (!sd->sc_data[SC_SOULCOLD].val4 && guild_checkskill(g, GD_SOULCOLD)>0) {
- //skill_status_change_start(&sd->bl,SC_SOULCOLD,1,0,0,0,0,0 );
- skill_unitsetting(&sd->bl,GD_SOULCOLD,1,sd->bl.x,sd->bl.y,0);
- }
- if (!sd->sc_data[SC_HAWKEYES].val4 && guild_checkskill(g, GD_HAWKEYES)>0) {
- //skill_status_change_start(&sd->bl,SC_HAWKEYES,1,0,0,0,0,0 );
- skill_unitsetting(&sd->bl,GD_HAWKEYES,1,sd->bl.x,sd->bl.y,0);
- }
- }
- else {
- if (sd->sc_data[SC_LEADERSHIP].timer != -1)
- sd->paramb[0] += 2;
- if (sd->sc_data[SC_GLORYWOUNDS].timer != -1)
- sd->paramb[2] += 2;
- if (sd->sc_data[SC_SOULCOLD].timer != -1)
- sd->paramb[1] += 2;
- if (sd->sc_data[SC_HAWKEYES].timer != -1)
- sd->paramb[4] += 2;
- if (sd->sc_data[SC_BATTLEORDERS].timer != -1) {
- sd->paramb[0]+= 5;
- sd->paramb[3]+= 5;
- sd->paramb[4]+= 5;
- }
- }
- }
-
- // ステ?タス?化による基本パラメ?タ補正
- if(sd->sc_count){
- if(sd->sc_data[SC_CONCENTRATE].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1){ // 集中力向上
- sd->paramb[1]+= (sd->status.agi+sd->paramb[1]+sd->parame[1]-sd->paramcard[1])*(2+sd->sc_data[SC_CONCENTRATE].val1)/100;
- sd->paramb[4]+= (sd->status.dex+sd->paramb[4]+sd->parame[4]-sd->paramcard[4])*(2+sd->sc_data[SC_CONCENTRATE].val1)/100;
- }
- if(sd->sc_data[SC_INCREASEAGI].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1){ // 速度?加
- sd->paramb[1]+= 2+sd->sc_data[SC_INCREASEAGI].val1;
- sd->speed -= sd->speed *25/100;
- }
- if(sd->sc_data[SC_DECREASEAGI].timer!=-1) // 速度減少(agiはbattle.cで)
- sd->speed = sd->speed *125/100;
- if(sd->sc_data[SC_CLOAKING].timer!=-1) {
- sd->critical_rate += 100; // critical increases
- sd->speed = sd->speed * (sd->sc_data[SC_CLOAKING].val3-sd->sc_data[SC_CLOAKING].val1*3) /100;
- // Ours is accurate enough - refer skill_check_cloaking. ^^
- //sd->speed = (sd->speed*(76+(sd->sc_data[SC_CLOAKING].val1*3)))/100; // Fixed by MiKa & Asa [Lupus]
- }
- //sd->speed = (sd->speed*(76+(sd->sc_data[SC_INCREASEAGI].val1*3)))/100;
- if(sd->sc_data[SC_CHASEWALK].timer!=-1)
- sd->speed = sd->speed * sd->sc_data[SC_CHASEWALK].val3 /100; // slow down by chasewalk
- if(sd->sc_data[SC_BLESSING].timer!=-1){ // ブレッシング
- sd->paramb[0]+= sd->sc_data[SC_BLESSING].val1;
- sd->paramb[3]+= sd->sc_data[SC_BLESSING].val1;
- sd->paramb[4]+= sd->sc_data[SC_BLESSING].val1;
- }
- if(sd->sc_data[SC_GLORIA].timer!=-1) // グロリア
- sd->paramb[5]+= 30;
- if(sd->sc_data[SC_LOUD].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1) // ラウドボイス
- sd->paramb[0]+= 4;
- if(sd->sc_data[SC_QUAGMIRE].timer!=-1){ // クァグマイア
- int agib = (sd->status.agi+sd->paramb[1]+sd->parame[1])*(sd->sc_data[SC_QUAGMIRE].val1*10)/100;
- int dexb = (sd->status.dex+sd->paramb[4]+sd->parame[4])*(sd->sc_data[SC_QUAGMIRE].val1*10)/100;
- sd->paramb[1]-= agib > 50 ? 50 : agib;
- sd->paramb[4]-= dexb > 50 ? 50 : dexb;
- sd->speed = sd->speed*3/2;
- }
- if(sd->sc_data[SC_TRUESIGHT].timer!=-1){ // トゥル?サイト
- sd->paramb[0]+= 5;
- sd->paramb[1]+= 5;
- sd->paramb[2]+= 5;
- sd->paramb[3]+= 5;
- sd->paramb[4]+= 5;
- sd->paramb[5]+= 5;
- }
- if(sd->sc_data[SC_MARIONETTE].timer!=-1){
- sd->paramb[0]-= sd->status.str/2; // bonuses not included
- sd->paramb[1]-= sd->status.agi/2;
- sd->paramb[2]-= sd->status.vit/2;
- sd->paramb[3]-= sd->status.int_/2;
- sd->paramb[4]-= sd->status.dex/2;
- sd->paramb[5]-= sd->status.luk/2;
- }
- else if(sd->sc_data[SC_MARIONETTE2].timer!=-1){
- struct map_session_data *psd = (struct map_session_data *)map_id2bl(sd->sc_data[SC_MARIONETTE2].val3);
- if (psd) { // if partner is found
- sd->paramb[0] += sd->status.str+psd->status.str/2 > 99 ? 99-sd->status.str : psd->status.str/2;
- sd->paramb[1] += sd->status.agi+psd->status.agi/2 > 99 ? 99-sd->status.agi : psd->status.agi/2;
- sd->paramb[2] += sd->status.vit+psd->status.vit/2 > 99 ? 99-sd->status.vit : psd->status.vit/2;
- sd->paramb[3] += sd->status.int_+psd->status.int_/2 > 99 ? 99-sd->status.int_ : psd->status.int_/2;
- sd->paramb[4] += sd->status.dex+psd->status.dex/2 > 99 ? 99-sd->status.dex : psd->status.dex/2;
- sd->paramb[5] += sd->status.luk+psd->status.luk/2 > 99 ? 99-sd->status.luk : psd->status.luk/2;
- }
- }
- }
-
- //1度も死んでないJob70スパノビに+10
- if(s_class.job == 23 && sd->die_counter == 0 && sd->status.job_level >= 70){
- sd->paramb[0]+= 15;
- sd->paramb[1]+= 15;
- sd->paramb[2]+= 15;
- sd->paramb[3]+= 15;
- sd->paramb[4]+= 15;
- sd->paramb[5]+= 15;
- }
- sd->paramc[0]=sd->status.str+sd->paramb[0]+sd->parame[0];
- sd->paramc[1]=sd->status.agi+sd->paramb[1]+sd->parame[1];
- sd->paramc[2]=sd->status.vit+sd->paramb[2]+sd->parame[2];
- sd->paramc[3]=sd->status.int_+sd->paramb[3]+sd->parame[3];
- sd->paramc[4]=sd->status.dex+sd->paramb[4]+sd->parame[4];
- sd->paramc[5]=sd->status.luk+sd->paramb[5]+sd->parame[5];
- for(i=0;i<6;i++)
- if(sd->paramc[i] < 0) sd->paramc[i] = 0;
-
- if(sd->status.weapon == 11 || sd->status.weapon == 13 || sd->status.weapon == 14) {
- str = sd->paramc[4];
- dex = sd->paramc[0];
- }
- else {
- str = sd->paramc[0];
- dex = sd->paramc[4];
- }
- dstr = str/10;
- sd->base_atk += str + dstr*dstr + dex/5 + sd->paramc[5]/5;
- sd->matk1 += sd->paramc[3]+(sd->paramc[3]/5)*(sd->paramc[3]/5);
- sd->matk2 += sd->paramc[3]+(sd->paramc[3]/7)*(sd->paramc[3]/7);
- if(sd->matk1 < sd->matk2) {
- int temp = sd->matk2;
- sd->matk2 = sd->matk1;
- sd->matk1 = temp;
- }
- sd->hit += sd->paramc[4] + sd->status.base_level;
- sd->flee += sd->paramc[1] + sd->status.base_level;
- sd->def2 += sd->paramc[2];
- sd->mdef2 += sd->paramc[3];
- sd->flee2 += sd->paramc[5]+10;
- sd->critical += (sd->paramc[5]*3)+10;
-
- if(sd->base_atk < 1)
- sd->base_atk = 1;
- if(sd->critical_rate != 100)
- sd->critical = (sd->critical*sd->critical_rate)/100;
- if(sd->critical < 10) sd->critical = 10;
- if(sd->hit_rate != 100)
- sd->hit = (sd->hit*sd->hit_rate)/100;
- if(sd->hit < 1) sd->hit = 1;
- if(sd->flee_rate != 100)
- sd->flee = (sd->flee*sd->flee_rate)/100;
- if(sd->flee < 1) sd->flee = 1;
- if(sd->flee2_rate != 100)
- sd->flee2 = (sd->flee2*sd->flee2_rate)/100;
- if(sd->flee2 < 10) sd->flee2 = 10;
- if(sd->def_rate != 100)
- sd->def = (sd->def*sd->def_rate)/100;
- if(sd->def < 0) sd->def = 0;
- if(sd->def2_rate != 100)
- sd->def2 = (sd->def2*sd->def2_rate)/100;
- if(sd->def2 < 1) sd->def2 = 1;
- if(sd->mdef_rate != 100)
- sd->mdef = (sd->mdef*sd->mdef_rate)/100;
- if(sd->mdef < 0) sd->mdef = 0;
- if(sd->mdef2_rate != 100)
- sd->mdef2 = (sd->mdef2*sd->mdef2_rate)/100;
- if(sd->mdef2 < 1) sd->mdef2 = 1;
-
- // 二刀流 ASPD 修正
- if (sd->status.weapon <= 16)
- sd->aspd += aspd_base[s_class.job][sd->status.weapon]-(sd->paramc[1]*4+sd->paramc[4])*aspd_base[s_class.job][sd->status.weapon]/1000;
- else
- sd->aspd += (
- (aspd_base[s_class.job][sd->weapontype1]-(sd->paramc[1]*4+sd->paramc[4])*aspd_base[s_class.job][sd->weapontype1]/1000) +
- (aspd_base[s_class.job][sd->weapontype2]-(sd->paramc[1]*4+sd->paramc[4])*aspd_base[s_class.job][sd->weapontype2]/1000)
- ) * 140 / 200;
-
- aspd_rate = sd->aspd_rate;
-
- //攻?速度?加
-
- if( (skill=pc_checkskill(sd,AC_VULTURE))>0){ // ワシの目
- sd->hit += skill;
- if(sd->status.weapon == 11)
- sd->attackrange += skill;
- }
-
- if( (skill=pc_checkskill(sd,BS_WEAPONRESEARCH))>0) // 武器?究の命中率?加
- sd->hit += skill*2;
- if(sd->status.option&2 && (skill = pc_checkskill(sd,RG_TUNNELDRIVE))>0 ) // トンネルドライブ // トンネルドライブ
- sd->speed += (1.2*DEFAULT_WALK_SPEED - skill*9);
- if (pc_iscarton(sd) && (skill=pc_checkskill(sd,MC_PUSHCART))>0) // カ?トによる速度低下
- sd->speed += (10-skill) * (DEFAULT_WALK_SPEED * 0.1);
- else if (pc_isriding(sd)) { // ペコペコ?りによる速度?加
- sd->speed -= (0.25 * DEFAULT_WALK_SPEED);
- sd->max_weight += 10000;
- }
- if(sd->sc_count){
- if(sd->sc_data[SC_WINDWALK].timer!=-1) //ウィンドウォ?ク時はLv*2%減算
- sd->speed -= sd->speed *(sd->sc_data[SC_WINDWALK].val1*2)/100;
- if(sd->sc_data[SC_CARTBOOST].timer!=-1) // カ?トブ?スト
- sd->speed -= (DEFAULT_WALK_SPEED * 20)/100;
- if(sd->sc_data[SC_BERSERK].timer!=-1) //バ?サ?ク中はIAと同じぐらい速い?
- sd->speed -= sd->speed *25/100;
- if(sd->sc_data[SC_WEDDING].timer!=-1) //結婚中は?くのが?い
- sd->speed = 2*DEFAULT_WALK_SPEED;
- }
-
- if((skill=pc_checkskill(sd,CR_TRUST))>0) { // フェイス
- sd->status.max_hp += skill*200;
- sd->subele[6] += skill*5;
- }
- if((skill=pc_checkskill(sd,BS_SKINTEMPER))>0)
- {
- sd->subele[0] += skill;
- sd->subele[3] += skill*5;
- }
-
- bl=sd->status.base_level;
-
- sd->status.max_hp += (3500 + bl*hp_coefficient2[s_class.job] + hp_sigma_val[s_class.job][(bl > 0)? bl-1:0])/100 * (100 + sd->paramc[2])/100 + (sd->parame[2] - sd->paramcard[2]);
- if (s_class.upper==1) // [MouseJstr]
- sd->status.max_hp = sd->status.max_hp * 130/100;
- else if (s_class.upper==2)
- sd->status.max_hp = sd->status.max_hp * 70/100;
-
- if(sd->hprate!=100)
- sd->status.max_hp = sd->status.max_hp*sd->hprate/100;
-
- if(sd->sc_data && sd->sc_data[SC_BERSERK].timer!=-1){ // バ?サ?ク
- sd->status.max_hp = sd->status.max_hp * 3;
- // sd->status.hp = sd->status.hp * 3;
- if(sd->status.max_hp > battle_config.max_hp) // removed negative max hp bug by Valaris
- sd->status.max_hp = battle_config.max_hp;
- if(sd->status.hp > battle_config.max_hp) // removed negative max hp bug by Valaris
- sd->status.hp = battle_config.max_hp;
- }
- if(s_class.job == 23 && sd->status.base_level >= 99){
- sd->status.max_hp = sd->status.max_hp + 2000;
- }
-
- if(sd->status.max_hp > battle_config.max_hp) // removed negative max hp bug by Valaris
- sd->status.max_hp = battle_config.max_hp;
- if(sd->status.max_hp <= 0) sd->status.max_hp = 1; // end
-
- // 最大SP計算
- sd->status.max_sp += ((sp_coefficient[s_class.job] * bl) + 1000)/100 * (100 + sd->paramc[3])/100 + (sd->parame[3] - sd->paramcard[3]);
- if (s_class.upper==1) // [MouseJstr]
- sd->status.max_sp = sd->status.max_sp * 130/100;
- else if (s_class.upper==2)
- sd->status.max_sp = sd->status.max_sp * 70/100;
- if(sd->sprate!=100)
- sd->status.max_sp = sd->status.max_sp*sd->sprate/100;
-
- if((skill=pc_checkskill(sd,HP_MEDITATIO))>0) // メディテイティオ
- sd->status.max_sp += sd->status.max_sp*skill/100;
- if((skill=pc_checkskill(sd,HW_SOULDRAIN))>0) /* ソウルドレイン */
- sd->status.max_sp += sd->status.max_sp*2*skill/100;
-
- if(sd->status.max_sp < 0 || sd->status.max_sp > battle_config.max_sp)
- sd->status.max_sp = battle_config.max_sp;
-
- //自然回復HP
- sd->nhealhp = 1 + (sd->paramc[2]/5) + (sd->status.max_hp/200);
- if((skill=pc_checkskill(sd,SM_RECOVERY)) > 0) { /* HP回復力向上 */
- sd->nshealhp = skill*5 + (sd->status.max_hp*skill/500);
- if(sd->nshealhp > 0x7fff) sd->nshealhp = 0x7fff;
- }
- //自然回復SP
- sd->nhealsp = 1 + (sd->paramc[3]/6) + (sd->status.max_sp/100);
- if(sd->paramc[3] >= 120)
- sd->nhealsp += ((sd->paramc[3]-120)>>1) + 4;
- if((skill=pc_checkskill(sd,MG_SRECOVERY)) > 0) { /* SP回復力向上 */
- sd->nshealsp = skill*3 + (sd->status.max_sp*skill/500);
- if(sd->nshealsp > 0x7fff) sd->nshealsp = 0x7fff;
- }
-
- if((skill = pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0) {
- sd->nsshealhp = skill*4 + (sd->status.max_hp*skill/500);
- sd->nsshealsp = skill*2 + (sd->status.max_sp*skill/500);
- if(sd->nsshealhp > 0x7fff) sd->nsshealhp = 0x7fff;
- if(sd->nsshealsp > 0x7fff) sd->nsshealsp = 0x7fff;
- }
- if(sd->hprecov_rate != 100) {
- sd->nhealhp = sd->nhealhp*sd->hprecov_rate/100;
- if(sd->nhealhp < 1) sd->nhealhp = 1;
- }
- if(sd->sprecov_rate != 100) {
- sd->nhealsp = sd->nhealsp*sd->sprecov_rate/100;
- if(sd->nhealsp < 1) sd->nhealsp = 1;
- }
- /* if((skill=pc_checkskill(sd,HP_MEDITATIO)) > 0) { // f?fffBfefCfefBfI,I'SPR,A*,I',E`,。ゥZ((c)。ョR「カn~.ゥォ,E',(c),(c),e'
- sd->nhealsp += 3*skill*(sd->status.max_sp)/100;
- if(sd->nhealsp > 0x7fff) sd->nhealsp = 0x7fff;
- } Increase natural SP regen instead of colossal SP Recovery effect [DracoRPG]*/
-
- // 種族耐性(これでいいの? ディバインプロテクションと同じ?理がいるかも)
- if( (skill=pc_checkskill(sd,SA_DRAGONOLOGY))>0 ){ // ドラゴノロジ?
- skill = skill*4;
- sd->addrace[9]+=skill;
- sd->addrace_[9]+=skill;
- sd->subrace[9]+=skill;
- sd->magic_addrace[9]+=skill;
- sd->magic_subrace[9]-=skill;
- }
-
- //Flee上昇
- if( (skill=pc_checkskill(sd,TF_MISS))>0 ){ // 回避率?加
- if(sd->status.class==6||sd->status.class==4007 || sd->status.class==23){
- sd->flee += skill*3;
- }
- if(sd->status.class==12||sd->status.class==17||sd->status.class==4013||sd->status.class==4018)
- sd->flee += skill*4;
- if(sd->status.class==12||sd->status.class==4013)
- sd->speed -= sd->speed *(skill*1.5)/100;
- }
- if( (skill=pc_checkskill(sd,MO_DODGE))>0 ) // 見切り
- sd->flee += (skill*3)>>1;
-
- // スキルやステ?タス異常による?りのパラメ?タ補正
- if(sd->sc_count){
- // ATK/DEF?化形
- if(sd->sc_data[SC_ANGELUS].timer!=-1) // エンジェラス
- sd->def2 = sd->def2*(110+5*sd->sc_data[SC_ANGELUS].val1)/100;
- if(sd->sc_data[SC_IMPOSITIO].timer!=-1) {// インポシティオマヌス
- sd->watk += sd->sc_data[SC_IMPOSITIO].val1*5;
- index = sd->equip_index[8];
- if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4)
- sd->watk_ += sd->sc_data[SC_IMPOSITIO].val1*5;
- }
- if(sd->sc_data[SC_PROVOKE].timer!=-1){ // プロボック
- sd->def2 = sd->def2*(100-6*sd->sc_data[SC_PROVOKE].val1)/100;
- sd->base_atk = sd->base_atk*(100+2*sd->sc_data[SC_PROVOKE].val1)/100;
- sd->watk = sd->watk*(100+2*sd->sc_data[SC_PROVOKE].val1)/100;
- index = sd->equip_index[8];
- if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4)
- sd->watk_ = sd->watk_*(100+2*sd->sc_data[SC_PROVOKE].val1)/100;
- }
- if(sd->sc_data[SC_ENDURE].timer!=-1)
- sd->mdef2 += sd->sc_data[SC_ENDURE].val1;
- if(sd->sc_data[SC_MINDBREAKER].timer!=-1){ // プロボック
- sd->mdef2 = sd->mdef2*(100-6*sd->sc_data[SC_MINDBREAKER].val1)/100;
- sd->matk1 = sd->matk1*(100+2*sd->sc_data[SC_MINDBREAKER].val1)/100;
- sd->matk2 = sd->matk2*(100+2*sd->sc_data[SC_MINDBREAKER].val1)/100;
- }
- if(sd->sc_data[SC_POISON].timer!=-1) // 毒?態
- sd->def2 = sd->def2*75/100;
- if(sd->sc_data[SC_DRUMBATTLE].timer!=-1){ // ?太鼓の響き
- sd->watk += sd->sc_data[SC_DRUMBATTLE].val2;
- sd->def += sd->sc_data[SC_DRUMBATTLE].val3;
- index = sd->equip_index[8];
- if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4)
- sd->watk_ += sd->sc_data[SC_DRUMBATTLE].val2;
- }
- if(sd->sc_data[SC_NIBELUNGEN].timer!=-1) { // ニ?ベルングの指輪
- index = sd->equip_index[9];
- if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 3)
- sd->watk += sd->sc_data[SC_NIBELUNGEN].val3;
- index = sd->equip_index[8];
- if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 3)
- sd->watk_ += sd->sc_data[SC_NIBELUNGEN].val3;
- if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4)
- sd->watk += sd->sc_data[SC_NIBELUNGEN].val2;
- index = sd->equip_index[8];
- if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4)
- sd->watk_ += sd->sc_data[SC_NIBELUNGEN].val2;
- }
-
- if(sd->sc_data[SC_VOLCANO].timer!=-1 && sd->def_ele==3){ // ボルケ?ノ
- sd->watk += sd->sc_data[SC_VIOLENTGALE].val3;
- }
-
- if(sd->sc_data[SC_SIGNUMCRUCIS].timer!=-1)
- sd->def = sd->def * (100 - sd->sc_data[SC_SIGNUMCRUCIS].val2)/100;
- if(sd->sc_data[SC_ETERNALCHAOS].timer!=-1) // エタ?ナルカオス
- sd->def=0;
-
- if(sd->sc_data[SC_CONCENTRATION].timer!=-1){ //コンセントレ?ション
- sd->watk = sd->watk * (100 + 5*sd->sc_data[SC_CONCENTRATION].val1)/100;
- index = sd->equip_index[8];
- if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4)
- sd->watk_ = sd->watk * (100 + 5*sd->sc_data[SC_CONCENTRATION].val1)/100;
- sd->def = sd->def * (100 - 5*sd->sc_data[SC_CONCENTRATION].val1)/100;
- }
-
- if(sd->sc_data[SC_MAGICPOWER].timer!=-1){ //魔法力?幅
- sd->matk1 = sd->matk1*(100+5*sd->sc_data[SC_MAGICPOWER].val1)/100;
- sd->matk2 = sd->matk2*(100+5*sd->sc_data[SC_MAGICPOWER].val1)/100;
- }
- if(sd->sc_data[SC_ATKPOT].timer!=-1)
- sd->watk += sd->sc_data[SC_ATKPOT].val1;
- if(sd->sc_data[SC_MATKPOT].timer!=-1){
- sd->matk1 += sd->sc_data[SC_MATKPOT].val1;
- sd->matk2 += sd->sc_data[SC_MATKPOT].val1;
- }
-
- // ASPD/移動速度?化系
- if(sd->sc_data[SC_TWOHANDQUICKEN].timer != -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
- aspd_rate -= 30;
- if(sd->sc_data[SC_ADRENALINE].timer != -1 && sd->sc_data[SC_TWOHANDQUICKEN].timer == -1 &&
- sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) { // アドレナリンラッシュ
- if(sd->sc_data[SC_ADRENALINE].val2 || !battle_config.party_skill_penaly)
- aspd_rate -= 30;
- else
- aspd_rate -= 25;
- }
- if(sd->sc_data[SC_SPEARSQUICKEN].timer != -1 && sd->sc_data[SC_ADRENALINE].timer == -1 &&
- sd->sc_data[SC_TWOHANDQUICKEN].timer == -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) // スピアクィッケン
- aspd_rate -= sd->sc_data[SC_SPEARSQUICKEN].val2;
- if(sd->sc_data[SC_ASSNCROS].timer!=-1 && // 夕陽のアサシンクロス
- sd->sc_data[SC_TWOHANDQUICKEN].timer==-1 && sd->sc_data[SC_ADRENALINE].timer==-1 && sd->sc_data[SC_SPEARSQUICKEN].timer==-1 &&
- sd->sc_data[SC_DONTFORGETME].timer == -1)
- aspd_rate -= 5+sd->sc_data[SC_ASSNCROS].val1+sd->sc_data[SC_ASSNCROS].val2+sd->sc_data[SC_ASSNCROS].val3;
- if(sd->sc_data[SC_DONTFORGETME].timer!=-1){ // 私を忘れないで
- aspd_rate += sd->sc_data[SC_DONTFORGETME].val1*3 + sd->sc_data[SC_DONTFORGETME].val2 + (sd->sc_data[SC_DONTFORGETME].val3>>16);
- sd->speed= sd->speed*(100+sd->sc_data[SC_DONTFORGETME].val1*2 + sd->sc_data[SC_DONTFORGETME].val2 + (sd->sc_data[SC_DONTFORGETME].val3&0xffff))/100;
- }
- if( sd->sc_data[i=SC_SPEEDPOTION2].timer!=-1 ||
- sd->sc_data[i=SC_SPEEDPOTION1].timer!=-1 ||
- sd->sc_data[i=SC_SPEEDPOTION0].timer!=-1) // ? 速ポ?ション
- aspd_rate -= sd->sc_data[i].val2;
-
- // HIT/FLEE?化系
- if(sd->sc_data[SC_WHISTLE].timer!=-1){ // 口笛
- sd->flee += sd->flee * (sd->sc_data[SC_WHISTLE].val1
- +sd->sc_data[SC_WHISTLE].val2+(sd->sc_data[SC_WHISTLE].val3>>16))/100;
- sd->flee2+= (sd->sc_data[SC_WHISTLE].val1+sd->sc_data[SC_WHISTLE].val2+(sd->sc_data[SC_WHISTLE].val3&0xffff)) * 10;
- }
- if(sd->sc_data[SC_HUMMING].timer!=-1) // ハミング
- sd->hit += (sd->sc_data[SC_HUMMING].val1*2+sd->sc_data[SC_HUMMING].val2
- +sd->sc_data[SC_HUMMING].val3) * sd->hit/100;
- if(sd->sc_data[SC_VIOLENTGALE].timer!=-1 && sd->def_ele==4){ // バイオレントゲイル
- sd->flee += sd->flee*sd->sc_data[SC_VIOLENTGALE].val3/100;
- }
- if(sd->sc_data[SC_BLIND].timer!=-1){ // 暗?
- sd->hit -= sd->hit*25/100;
- sd->flee -= sd->flee*25/100;
- }
- if(sd->sc_data[SC_WINDWALK].timer!=-1) // ウィンドウォ?ク
- sd->flee += sd->flee*(sd->sc_data[SC_WINDWALK].val2)/100;
- if(sd->sc_data[SC_SPIDERWEB].timer!=-1) //スパイダ?ウェブ
- sd->flee -= sd->flee*50/100;
- if(sd->sc_data[SC_TRUESIGHT].timer!=-1) //トゥル?サイト
- sd->hit += 3*(sd->sc_data[SC_TRUESIGHT].val1);
- if(sd->sc_data[SC_CONCENTRATION].timer!=-1) //コンセントレ?ション
- sd->hit += (10*(sd->sc_data[SC_CONCENTRATION].val1));
-
- // 耐性
- if(sd->sc_data[SC_SIEGFRIED].timer!=-1){ // 不死身のジ?クフリ?ド
- sd->subele[1] += sd->sc_data[SC_SIEGFRIED].val2; // 水
- sd->subele[2] += sd->sc_data[SC_SIEGFRIED].val2; // 水
- sd->subele[3] += sd->sc_data[SC_SIEGFRIED].val2; // 火
- sd->subele[4] += sd->sc_data[SC_SIEGFRIED].val2; // 水
- sd->subele[5] += sd->sc_data[SC_SIEGFRIED].val2; // 水
- sd->subele[6] += sd->sc_data[SC_SIEGFRIED].val2; // 水
- sd->subele[7] += sd->sc_data[SC_SIEGFRIED].val2; // 水
- sd->subele[8] += sd->sc_data[SC_SIEGFRIED].val2; // 水
- sd->subele[9] += sd->sc_data[SC_SIEGFRIED].val2; // 水
- }
- if(sd->sc_data[SC_PROVIDENCE].timer!=-1){ // プロヴィデンス
- sd->subele[6] += sd->sc_data[SC_PROVIDENCE].val2; // ? 聖?性
- sd->subrace[6] += sd->sc_data[SC_PROVIDENCE].val2; // ? ?魔
- }
-
- // その他
- if(sd->sc_data[SC_APPLEIDUN].timer!=-1){ // イドゥンの林檎
- sd->status.max_hp += ((5+sd->sc_data[SC_APPLEIDUN].val1*2+((sd->sc_data[SC_APPLEIDUN].val2+1)>>1)
- +sd->sc_data[SC_APPLEIDUN].val3/10) * sd->status.max_hp)/100;
- if(sd->status.max_hp < 0 || sd->status.max_hp > battle_config.max_hp)
- sd->status.max_hp = battle_config.max_hp;
- }
- if(sd->sc_data[SC_DELUGE].timer!=-1 && sd->def_ele==1){ // デリュ?ジ
- sd->status.max_hp += sd->status.max_hp*sd->sc_data[SC_DELUGE].val3/100;
- if(sd->status.max_hp < 0 || sd->status.max_hp > battle_config.max_hp)
- sd->status.max_hp = battle_config.max_hp;
- }
- if(sd->sc_data[SC_SERVICE4U].timer!=-1) { // サ?ビスフォ?ユ?
- sd->status.max_sp += sd->status.max_sp*(10+sd->sc_data[SC_SERVICE4U].val1+sd->sc_data[SC_SERVICE4U].val2
- +sd->sc_data[SC_SERVICE4U].val3)/100;
- if(sd->status.max_sp < 0 || sd->status.max_sp > battle_config.max_sp)
- sd->status.max_sp = battle_config.max_sp;
- sd->dsprate-=(10+sd->sc_data[SC_SERVICE4U].val1*3+sd->sc_data[SC_SERVICE4U].val2
- +sd->sc_data[SC_SERVICE4U].val3);
- if(sd->dsprate<0)sd->dsprate=0;
- }
-
- if(sd->sc_data[SC_FORTUNE].timer!=-1) // 幸運のキス
- sd->critical += (10+sd->sc_data[SC_FORTUNE].val1+sd->sc_data[SC_FORTUNE].val2
- +sd->sc_data[SC_FORTUNE].val3)*10;
-
- if(sd->sc_data[SC_EXPLOSIONSPIRITS].timer!=-1){ // 爆裂波動
- if(s_class.job==23)
- sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val1*100;
- else
- sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val2;
- }
-
- if(sd->sc_data[SC_STEELBODY].timer!=-1){ // 金剛
- sd->def = 90;
- sd->mdef = 90;
- aspd_rate += 25;
- sd->speed = (sd->speed * 125) / 100;
- }
- if(sd->sc_data[SC_DEFENDER].timer != -1) {
- sd->aspd += (550 - sd->sc_data[SC_DEFENDER].val1*50);
- sd->speed = (sd->speed * (155 - sd->sc_data[SC_DEFENDER].val1*5)) / 100;
- }
- if(sd->sc_data[SC_ENCPOISON].timer != -1)
- sd->addeff[4] += sd->sc_data[SC_ENCPOISON].val2;
-
- if( sd->sc_data[SC_DANCING].timer!=-1 ){ // 演奏/ダンス使用中
- sd->speed*=4;
- sd->nhealsp = 0;
- sd->nshealsp = 0;
- sd->nsshealsp = 0;
- }
- if(sd->sc_data[SC_CURSE].timer!=-1)
- sd->speed += 450;
-
- if(sd->sc_data[SC_TRUESIGHT].timer!=-1) //トゥル?サイト
- sd->critical += sd->critical*(sd->sc_data[SC_TRUESIGHT].val1)/100;
-
-/* if(sd->sc_data[SC_VOLCANO].timer!=-1) // エンチャントポイズン(?性はbattle.cで)
- sd->addeff[2]+=sd->sc_data[SC_VOLCANO].val2;//% of granting
- if(sd->sc_data[SC_DELUGE].timer!=-1) // エンチャントポイズン(?性はbattle.cで)
- sd->addeff[0]+=sd->sc_data[SC_DELUGE].val2;//% of granting
- */
- if(sd->sc_data[SC_BERSERK].timer!=-1) { //All Def/MDef reduced to 0 while in Berserk [DracoRPG]
- sd->def = sd->def2 = 0;
- sd->mdef = sd->mdef2 = 0;
- sd->flee -= sd->flee*50/100;
- aspd_rate -= 30;
- //sd->base_atk *= 3;
- }
- if(sd->sc_data[SC_KEEPING].timer!=-1)
- sd->def = 100;
- if(sd->sc_data[SC_BARRIER].timer!=-1)
- sd->mdef = 100;
- }
-
- if(sd->speed_rate != 100)
- sd->speed = sd->speed*sd->speed_rate/100;
- if(sd->speed < 1) sd->speed = 1;
- if(aspd_rate != 100)
- sd->aspd = sd->aspd*aspd_rate/100;
- if(pc_isriding(sd)) // 騎兵修練
- sd->aspd = sd->aspd*(100 + 10*(5 - pc_checkskill(sd,KN_CAVALIERMASTERY)))/ 100;
- if(sd->aspd < battle_config.max_aspd) sd->aspd = battle_config.max_aspd;
- sd->amotion = sd->aspd;
- sd->dmotion = 800-sd->paramc[1]*4;
- if(sd->dmotion<400)
- sd->dmotion = 400;
- if(sd->skilltimer != -1 && (skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
- sd->prev_speed = sd->speed;
- sd->speed = sd->speed*(175 - skill*5)/100;
- }
-
- if(sd->status.hp>sd->status.max_hp)
- sd->status.hp=sd->status.max_hp;
- if(sd->status.sp>sd->status.max_sp)
- sd->status.sp=sd->status.max_sp;
-
- if(first&4)
- return 0;
- if(first&3) {
- clif_updatestatus(sd,SP_SPEED);
- clif_updatestatus(sd,SP_MAXHP);
- clif_updatestatus(sd,SP_MAXSP);
- if(first&1) {
- clif_updatestatus(sd,SP_HP);
- clif_updatestatus(sd,SP_SP);
- }
- return 0;
- }
-
- if(b_class != sd->view_class) {
- clif_changelook(&sd->bl,LOOK_BASE,sd->view_class);
-#if PACKETVER < 4
- clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
- clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
-#else
- clif_changelook(&sd->bl,LOOK_WEAPON,0);
-#endif
- }
-
- if( memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill)) || b_attackrange != sd->attackrange)
- clif_skillinfoblock(sd); // スキル送信
-
- if(b_speed != sd->speed)
- clif_updatestatus(sd,SP_SPEED);
- if(b_weight != sd->weight)
- clif_updatestatus(sd,SP_WEIGHT);
- if(b_max_weight != sd->max_weight) {
- clif_updatestatus(sd,SP_MAXWEIGHT);
- pc_checkweighticon(sd);
- }
- for(i=0;i<6;i++)
- if(b_paramb[i] + b_parame[i] != sd->paramb[i] + sd->parame[i])
- clif_updatestatus(sd,SP_STR+i);
- if(b_hit != sd->hit)
- clif_updatestatus(sd,SP_HIT);
- if(b_flee != sd->flee)
- clif_updatestatus(sd,SP_FLEE1);
- if(b_aspd != sd->aspd)
- clif_updatestatus(sd,SP_ASPD);
- if(b_watk != sd->watk || b_base_atk != sd->base_atk)
- clif_updatestatus(sd,SP_ATK1);
- if(b_def != sd->def)
- clif_updatestatus(sd,SP_DEF1);
- if(b_watk2 != sd->watk2)
- clif_updatestatus(sd,SP_ATK2);
- if(b_def2 != sd->def2)
- clif_updatestatus(sd,SP_DEF2);
- if(b_flee2 != sd->flee2)
- clif_updatestatus(sd,SP_FLEE2);
- if(b_critical != sd->critical)
- clif_updatestatus(sd,SP_CRITICAL);
- if(b_matk1 != sd->matk1)
- clif_updatestatus(sd,SP_MATK1);
- if(b_matk2 != sd->matk2)
- clif_updatestatus(sd,SP_MATK2);
- if(b_mdef != sd->mdef)
- clif_updatestatus(sd,SP_MDEF1);
- if(b_mdef2 != sd->mdef2)
- clif_updatestatus(sd,SP_MDEF2);
- if(b_attackrange != sd->attackrange)
- clif_updatestatus(sd,SP_ATTACKRANGE);
- if(b_max_hp != sd->status.max_hp)
- clif_updatestatus(sd,SP_MAXHP);
- if(b_max_sp != sd->status.max_sp)
- clif_updatestatus(sd,SP_MAXSP);
- if(b_hp != sd->status.hp)
- clif_updatestatus(sd,SP_HP);
- if(b_sp != sd->status.sp)
- clif_updatestatus(sd,SP_SP);
-
-/* if(before.cart_num != before.cart_num || before.cart_max_num != before.cart_max_num ||
- before.cart_weight != before.cart_weight || before.cart_max_weight != before.cart_max_weight )
- clif_updatestatus(sd,SP_CARTINFO);*/
-
- if(sd->status.hp<sd->status.max_hp>>2 && pc_checkskill(sd,SM_AUTOBERSERK)>0 &&
- (sd->sc_data[SC_PROVOKE].timer==-1 || sd->sc_data[SC_PROVOKE].val2==0 ) && !pc_isdead(sd))
- // オ?トバ?サ?ク?動
- skill_status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0);
-
- return 0;
-}
-
-/*==========================================
- * For quick calculating [Celest]
- *------------------------------------------
- */
-int pc_calcspeed (struct map_session_data *sd)
-{
- int b_speed, skill;
- struct pc_base_job s_class;
-
- nullpo_retr(0, sd);
-
- s_class = pc_calc_base_job(sd->status.class);
-
- b_speed = sd->speed;
- sd->speed = DEFAULT_WALK_SPEED ;
-
- if(sd->sc_count){
- if(sd->sc_data[SC_INCREASEAGI].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1){ // 速度?加
- sd->speed -= sd->speed *25/100;
- }
- if(sd->sc_data[SC_DECREASEAGI].timer!=-1) {
- sd->speed = sd->speed *125/100;
- }
- if(sd->sc_data[SC_CLOAKING].timer!=-1) {
- sd->speed = sd->speed * (sd->sc_data[SC_CLOAKING].val3-sd->sc_data[SC_CLOAKING].val1*3) /100;
- }
- if(sd->sc_data[SC_CHASEWALK].timer!=-1) {
- sd->speed = sd->speed * sd->sc_data[SC_CHASEWALK].val3 /100;
- }
- if(sd->sc_data[SC_QUAGMIRE].timer!=-1){
- sd->speed = sd->speed*3/2;
- }
- if(sd->sc_data[SC_WINDWALK].timer!=-1) {
- sd->speed -= sd->speed *(sd->sc_data[SC_WINDWALK].val1*2)/100;
- }
- if(sd->sc_data[SC_CARTBOOST].timer!=-1) {
- sd->speed -= (DEFAULT_WALK_SPEED * 20)/100;
- }
- if(sd->sc_data[SC_BERSERK].timer!=-1) {
- sd->speed -= sd->speed *25/100;
- }
- if(sd->sc_data[SC_WEDDING].timer!=-1) {
- sd->speed = 2*DEFAULT_WALK_SPEED;
- }
- if(sd->sc_data[SC_DONTFORGETME].timer!=-1){
- sd->speed= sd->speed*(100+sd->sc_data[SC_DONTFORGETME].val1*2 + sd->sc_data[SC_DONTFORGETME].val2 + (sd->sc_data[SC_DONTFORGETME].val3&0xffff))/100;
- }
- if(sd->sc_data[SC_STEELBODY].timer!=-1){
- sd->speed = (sd->speed * 125) / 100;
- }
- if(sd->sc_data[SC_DEFENDER].timer != -1) {
- sd->speed = (sd->speed * (155 - sd->sc_data[SC_DEFENDER].val1*5)) / 100;
- }
- if( sd->sc_data[SC_DANCING].timer!=-1 ){
- sd->speed*=4;
- }
- if(sd->sc_data[SC_CURSE].timer!=-1)
- sd->speed += 450;
- }
-
- if(sd->status.option&2 && (skill = pc_checkskill(sd,RG_TUNNELDRIVE))>0 )
- sd->speed += (1.2*DEFAULT_WALK_SPEED - skill*9);
- if (pc_iscarton(sd) && (skill=pc_checkskill(sd,MC_PUSHCART))>0)
- sd->speed += (10-skill) * (DEFAULT_WALK_SPEED * 0.1);
- else if (pc_isriding(sd)) {
- sd->speed -= (0.25 * DEFAULT_WALK_SPEED);
- }
- if((skill=pc_checkskill(sd,TF_MISS))>0)
- if(s_class.job==12)
- sd->speed -= sd->speed *(skill*1.5)/100;
-
- if(sd->speed_rate != 100)
- sd->speed = sd->speed*sd->speed_rate/100;
- if(sd->speed < 1) sd->speed = 1;
-
- if(sd->skilltimer != -1 && (skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
- sd->prev_speed = sd->speed;
- sd->speed = sd->speed*(175 - skill*5)/100;
- }
-
- if(b_speed != sd->speed)
- clif_updatestatus(sd,SP_SPEED);
-
- return 0;
-}
-
-/*==========================================
* ? 備品による能力等のボ?ナス設定
*------------------------------------------
*/
int pc_bonus(struct map_session_data *sd,int type,int val)
{
+ int i;
nullpo_retr(0, sd);
switch(type){
@@ -2523,20 +1488,12 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
sd->parame[SP_INT-SP_STR]+=val;
sd->parame[SP_DEX-SP_STR]+=val;
sd->parame[SP_LUK-SP_STR]+=val;
- clif_updatestatus(sd,13);
- clif_updatestatus(sd,14);
- clif_updatestatus(sd,15);
- clif_updatestatus(sd,16);
- clif_updatestatus(sd,17);
- clif_updatestatus(sd,18);
}
break;
case SP_AGI_VIT: // [Valaris]
if(sd->state.lr_flag!=2) {
sd->parame[SP_AGI-SP_STR]+=val;
sd->parame[SP_VIT-SP_STR]+=val;
- clif_updatestatus(sd,14);
- clif_updatestatus(sd,15);
}
break;
case SP_AGI_DEX_STR: // [Valaris]
@@ -2544,9 +1501,6 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
sd->parame[SP_AGI-SP_STR]+=val;
sd->parame[SP_DEX-SP_STR]+=val;
sd->parame[SP_STR-SP_STR]+=val;
- clif_updatestatus(sd,14);
- clif_updatestatus(sd,17);
- clif_updatestatus(sd,13);
}
break;
case SP_PERFECT_HIDE: // [Valaris]
@@ -2570,11 +1524,106 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
sd->unbreakable += val;
}
break;
+ case SP_UNBREAKABLE_WEAPON:
+ if(sd->state.lr_flag != 2)
+ sd->unbreakable_equip |= EQP_WEAPON;
+ break;
+ case SP_UNBREAKABLE_ARMOR:
+ if(sd->state.lr_flag != 2)
+ sd->unbreakable_equip |= EQP_ARMOR;
+ break;
+ case SP_UNBREAKABLE_HELM:
+ if(sd->state.lr_flag != 2)
+ sd->unbreakable_equip |= EQP_HELM;
+ break;
+ case SP_UNBREAKABLE_SHIELD:
+ if(sd->state.lr_flag != 2)
+ sd->unbreakable_equip |= EQP_SHIELD;
+ break;
case SP_CLASSCHANGE: // [Valaris]
if(sd->state.lr_flag !=2){
sd->classchange=val;
}
break;
+ case SP_LONG_ATK_RATE:
+ if(sd->status.weapon == 11 && sd->state.lr_flag != 2)
+ sd->atk_rate += val;
+ break;
+ case SP_BREAK_WEAPON_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->break_weapon_rate+=val;
+ break;
+ case SP_BREAK_ARMOR_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->break_armor_rate+=val;
+ break;
+ case SP_ADD_STEAL_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->add_steal_rate+=val;
+ break;
+ case SP_DELAYRATE:
+ if(sd->state.lr_flag != 2)
+ sd->delayrate+=val;
+ break;
+ case SP_CRIT_ATK_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->crit_atk_rate += val;
+ break;
+ case SP_NO_REGEN:
+ if(sd->state.lr_flag != 2)
+ sd->no_regen = val;
+ break;
+ case SP_UNSTRIPABLE_WEAPON:
+ if(sd->state.lr_flag != 2)
+ sd->unstripable_equip |= EQP_WEAPON;
+ break;
+ case SP_UNSTRIPABLE:
+ case SP_UNSTRIPABLE_ARMOR:
+ if(sd->state.lr_flag != 2)
+ sd->unstripable_equip |= EQP_ARMOR;
+ break;
+ case SP_UNSTRIPABLE_HELM:
+ if(sd->state.lr_flag != 2)
+ sd->unstripable_equip |= EQP_HELM;
+ break;
+ case SP_UNSTRIPABLE_SHIELD:
+ if(sd->state.lr_flag != 2)
+ sd->unstripable_equip |= EQP_SHIELD;
+ break;
+ case SP_SP_GAIN_VALUE:
+ if(!sd->state.lr_flag)
+ sd->sp_gain_value += val;
+ break;
+ case SP_IGNORE_DEF_MOB: // 0:normal monsters only, 1:affects boss monsters as well
+ if(!sd->state.lr_flag)
+ sd->ignore_def_mob |= 1<<val;
+ else if(sd->state.lr_flag == 1)
+ sd->ignore_def_mob_ |= 1<<val;
+ break;
+ case SP_HP_GAIN_VALUE:
+ if(!sd->state.lr_flag)
+ sd->hp_gain_value += val;
+ break;
+ case SP_DAMAGE_WHEN_UNEQUIP:
+ if(!sd->state.lr_flag) {
+ for (i=0; i<11; i++) {
+ if (sd->inventory_data[current_equip_item_index]->equip & equip_pos[i]) {
+ sd->unequip_losehp[i] += val;
+ break;
+ }
+ }
+ }
+ break;
+ case SP_LOSESP_WHEN_UNEQUIP:
+ if(!sd->state.lr_flag) {
+ for (i=0; i<11; i++) {
+ if (sd->inventory_data[current_equip_item_index]->equip & equip_pos[i]) {
+ sd->unequip_losesp[i] += val;
+ break;
+ }
+ }
+ }
+ break;
default:
if(battle_config.error_log)
printf("pc_bonus: unknown type %d %d !\n",type,val);
@@ -2754,8 +1803,9 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
}
else if(sd->state.lr_flag == 1) {
sd->sp_drain_rate_ += type2;
- sd->sp_drain_per_ += val;
+ sd->sp_drain_per_ += val;
}
+ sd->sp_drain_type = 0;
break;
case SP_SP_DRAIN_VALUE:
if(!sd->state.lr_flag) {
@@ -2766,7 +1816,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
sd->sp_drain_rate_ += type2;
sd->sp_drain_value_ += val;
}
-
+ sd->sp_drain_type = 0;
break;
case SP_WEAPON_COMA_ELE:
if(sd->state.lr_flag != 2)
@@ -2780,8 +1830,92 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
if(sd->state.lr_flag !=2){
sd->random_attack_increase_add = type2;
sd->random_attack_increase_per += val;
- }
+ }
+ break;
+ case SP_WEAPON_ATK:
+ if(sd->state.lr_flag != 2)
+ sd->weapon_atk[type2]+=val;
+ break;
+ case SP_WEAPON_ATK_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->weapon_atk_rate[type2]+=val;
+ break;
+ case SP_CRITICAL_ADDRACE:
+ if(sd->state.lr_flag != 2)
+ sd->critaddrace[type2]+=val;
+ break;
+ case SP_ADDEFF_WHENHIT:
+ if(sd->state.lr_flag != 2) {
+ sd->addeff3[type2]+=val;
+ sd->addeff3_type[type2]=1;
+ }
break;
+ case SP_ADDEFF_WHENHIT_SHORT:
+ if(sd->state.lr_flag != 2) {
+ sd->addeff3[type2]+=val;
+ sd->addeff3_type[type2]=0;
+ }
+ break;
+ case SP_SKILL_ATK:
+ if(sd->state.lr_flag != 2) {
+ if (sd->skillatk[0] == type2)
+ sd->skillatk[1] += val;
+ else {
+ sd->skillatk[0] = type2;
+ sd->skillatk[1] = val;
+ }
+ }
+ break;
+ case SP_ADD_DAMAGE_BY_CLASS:
+ if(sd->state.lr_flag != 2) {
+ for(i=0;i<sd->add_damage_class_count2;i++) {
+ if(sd->add_damage_classid2[i] == type2) {
+ sd->add_damage_classrate2[i] += val;
+ break;
+ }
+ }
+ if(i >= sd->add_damage_class_count2 && sd->add_damage_class_count2 < 10) {
+ sd->add_damage_classid2[sd->add_damage_class_count2] = type2;
+ sd->add_damage_classrate2[sd->add_damage_class_count2] += val;
+ sd->add_damage_class_count2++;
+ }
+ }
+ break;
+ case SP_HP_LOSS_RATE:
+ if(sd->state.lr_flag != 2) {
+ sd->hp_loss_value = type2;
+ sd->hp_loss_rate = val;
+ }
+ break;
+ case SP_ADDRACE2:
+ if (type2 > 0 && type2 < MAX_MOB_RACE_DB)
+ break;
+ if(sd->state.lr_flag != 2)
+ sd->addrace2[type2] += val;
+ else
+ sd->addrace2_[type2] += val;
+ break;
+ case SP_SUBSIZE:
+ if(sd->state.lr_flag != 2)
+ sd->subsize[type2]+=val;
+ break;
+ case SP_SUBRACE2:
+ if(sd->state.lr_flag != 2)
+ sd->subrace2[type2]+=val;
+ break;
+ case SP_ADD_ITEM_HEAL_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->itemhealrate[type2 - 1] += val;
+ break;
+ case SP_EXP_ADDRACE:
+ if(sd->state.lr_flag != 2)
+ sd->expaddrace[type2]+=val;
+ break;
+ case SP_SP_GAIN_RACE:
+ if(sd->state.lr_flag != 2)
+ sd->sp_gain_race[type2]+=val;
+ break;
+
default:
if(battle_config.error_log)
printf("pc_bonus2: unknown type %d %d %d!\n",type,type2,val);
@@ -2819,6 +1953,42 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
sd->autospell_rate = val;
}
break;
+ case SP_AUTOSPELL_WHENHIT:
+ if(sd->state.lr_flag != 2){
+ sd->autospell2_id = type2;
+ sd->autospell2_lv = type3;
+ sd->autospell2_rate = val;
+ sd->autospell2_type = 1; // enemy
+ }
+ break;
+ case SP_HP_LOSS_RATE:
+ if(sd->state.lr_flag != 2) {
+ sd->hp_loss_value = type2;
+ sd->hp_loss_rate = type3;
+ sd->hp_loss_type = val;
+ }
+ break;
+ case SP_SP_DRAIN_RATE:
+ if(!sd->state.lr_flag) {
+ sd->sp_drain_rate += type2;
+ sd->sp_drain_per += type3;
+ }
+ else if(sd->state.lr_flag == 1) {
+ sd->sp_drain_rate_ += type2;
+ sd->sp_drain_per_ += type3;
+ }
+ sd->sp_drain_type = val;
+ break;
+ case SP_SP_DRAIN_VALUE:
+ if(!sd->state.lr_flag) {
+ sd->sp_drain_rate += type2;
+ sd->sp_drain_value += type3;
+ }
+ else if(sd->state.lr_flag == 1) {
+ sd->sp_drain_rate_ += type2;
+ sd->sp_drain_value_ += type3;
+ }
+ sd->sp_drain_type = val;
default:
if(battle_config.error_log)
printf("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val);
@@ -2828,6 +1998,26 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
return 0;
}
+int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4,int val)
+{
+ switch(type){
+ case SP_AUTOSPELL_WHENHIT:
+ if(sd->state.lr_flag != 2){
+ sd->autospell2_id = type2;
+ sd->autospell2_lv = type3;
+ sd->autospell2_rate = type4;
+ sd->autospell2_type = val; // 0: self, 1: enemy
+ }
+ break;
+ default:
+ if(battle_config.error_log)
+ printf("pc_bonus4: unknown type %d %d %d %d %d!\n",type,type2,type3,type4,val);
+ break;
+ }
+
+ return 0;
+}
+
/*==========================================
* スクリプトによるスキル所得
*------------------------------------------
@@ -2843,12 +2033,12 @@ int pc_skill(struct map_session_data *sd,int id,int level,int flag)
}
if(!flag && (sd->status.skill[id].id == id || level == 0)){ // クエスト所得ならここで?件を確認して送信する
sd->status.skill[id].lv=level;
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
clif_skillinfoblock(sd);
}
else if(flag==2 && (sd->status.skill[id].id == id || level == 0)){ // クエスト所得ならここで?件を確認して送信する
sd->status.skill[id].lv+=level;
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
clif_skillinfoblock(sd);
}
else if(sd->status.skill[id].lv < level){ // ?えられるがlvが小さいなら
@@ -2865,6 +2055,32 @@ int pc_skill(struct map_session_data *sd,int id,int level,int flag)
}
/*==========================================
+ *
+ *------------------------------------------
+ */
+int pc_blockskill_end(int tid,unsigned int tick,int id,int data)
+{
+ struct map_session_data *sd = map_id2sd(id);
+ if (data <= 0 || data >= MAX_SKILL)
+ return 0;
+ if (sd) sd->blockskill[data] = 0;
+
+ return 1;
+}
+int pc_blockskill_start (struct map_session_data *sd, int skillid, int tick)
+{
+ nullpo_retr (-1, sd);
+
+ if (skillid >= 10000 && skillid < 10015)
+ skillid -= 9500;
+ else if (skillid < 1 || skillid > MAX_SKILL)
+ return -1;
+
+ sd->blockskill[skillid] = 1;
+ return add_timer(gettick()+tick,pc_blockskill_end,sd->bl.id,skillid);
+}
+
+/*==========================================
* カ?ド?入
*------------------------------------------
*/
@@ -2950,7 +2166,7 @@ int pc_modifysellvalue(struct map_session_data *sd,int orig_value)
}
/*==========================================
- * アイテムを買った時に、新しいアイテム欄を使うか、
+ * アイテムを買った暫ノ、新しいアイテム欄を使うか、
* 3万個制限にかかるか確認
*------------------------------------------
*/
@@ -3074,7 +2290,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount)
i = MAX_INVENTORY;
if(!itemdb_isequip2(data)){
- // ? 備品ではないので、?所有品なら個?のみ?化させる
+ // 装 備品ではないので、既所有品なら個数のみ変化させる
for(i=0;i<MAX_INVENTORY;i++)
if(sd->status.inventory[i].nameid == item_data->nameid &&
sd->status.inventory[i].card[0] == item_data->card[0] && sd->status.inventory[i].card[1] == item_data->card[1] &&
@@ -3087,7 +2303,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount)
}
}
if(i >= MAX_INVENTORY){
- // ? 備品か未所有品だったので空き欄へ追加
+ // 装 備品か未所有品だったので空き欄へ追加
i = pc_search_inventory(sd,0);
if(i >= 0) {
memcpy(&sd->status.inventory[i],item_data,sizeof(sd->status.inventory[0]));
@@ -3118,7 +2334,7 @@ int pc_delitem(struct map_session_data *sd,int n,int amount,int type)
sd->weight -= sd->inventory_data[n]->weight*amount ;
if(sd->status.inventory[n].amount<=0){
if(sd->status.inventory[n].equip)
- pc_unequipitem(sd,n,0,BF_NORMAL);
+ pc_unequipitem(sd,n,3);
memset(&sd->status.inventory[n],0,sizeof(sd->status.inventory[0]));
sd->inventory_data[n] = NULL;
}
@@ -3139,19 +2355,17 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount)
nullpo_retr(1, sd);
if(n < 0 || n >= MAX_INVENTORY)
-
return 1;
-
if(amount <= 0)
-
return 1;
-
if (sd->status.inventory[n].nameid <= 0 ||
sd->status.inventory[n].amount < amount ||
sd->trade_partner != 0 || sd->vender_id != 0 ||
- sd->status.inventory[n].amount <= 0)
+ sd->status.inventory[n].amount <= 0 ||
+ itemdb_isdropable(sd->status.inventory[n].nameid) == 0 || // Celest
+ pc_candrop(sd,sd->status.inventory[n].nameid))
return 1;
map_addflooritem(&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, NULL, NULL, NULL, 0);
pc_delitem(sd, n, amount, 0);
@@ -3227,6 +2441,8 @@ int pc_isUseitem(struct map_session_data *sd,int n)
if(item == NULL)
return 0;
+ if(item->type != 0 && item->type != 2)
+ return 0;
if((nameid == 605) && map[sd->bl.m].flag.gvg)
return 0;
if(nameid == 601 && (map[sd->bl.m].flag.noteleport || map[sd->bl.m].flag.gvg)) {
@@ -3241,18 +2457,16 @@ int pc_isUseitem(struct map_session_data *sd,int n)
return 0;
if(item->elv > 0 && sd->status.base_level < item->elv)
return 0;
- if(((sd->status.class==13 || sd->status.class==4014) && ((1<<7)&item->class) == 0) || // have mounted classes use unmounted items [Valaris]
- ((sd->status.class==21 || sd->status.class==4022) && ((1<<14)&item->class) == 0))
+ if(((sd->status.class_==13 || sd->status.class_==4014) && ((1<<7)&item->class_) == 0) || // have mounted classes use unmounted items [Valaris]
+ ((sd->status.class_==21 || sd->status.class_==4022) && ((1<<14)&item->class_) == 0))
return 0;
- if(sd->status.class!=13 && sd->status.class!=4014 && sd->status.class!=21 && sd->status.class!=4022)
- if((sd->status.class<=4000 && ((1<<sd->status.class)&item->class) == 0) || (sd->status.class>4000 && sd->status.class<4023 && ((1<<(sd->status.class-4001))&item->class) == 0) ||
- (sd->status.class>=4023 && ((1<<(sd->status.class-4023))&item->class) == 0))
+ if(sd->status.class_!=13 && sd->status.class_!=4014 && sd->status.class_!=21 && sd->status.class_!=4022)
+ if((sd->status.class_<=4000 && ((1<<sd->status.class_)&item->class_) == 0) || (sd->status.class_>4000 && sd->status.class_<4023 && ((1<<(sd->status.class_-4001))&item->class_) == 0) ||
+ (sd->status.class_>=4023 && ((1<<(sd->status.class_-4023))&item->class_) == 0))
return 0;
-#ifndef TXT_ONLY
if((log_config.branch > 0) && (nameid == 604))
log_branch(sd);
-#endif
return 1;
}
@@ -3263,28 +2477,31 @@ int pc_isUseitem(struct map_session_data *sd,int n)
*/
int pc_useitem(struct map_session_data *sd,int n)
{
- int nameid,amount;
+ int amount;
nullpo_retr(1, sd);
if(n >=0 && n < MAX_INVENTORY) {
- nameid = sd->status.inventory[n].nameid;
+ char *script;
+ sd->itemid = sd->status.inventory[n].nameid;
amount = sd->status.inventory[n].amount;
if(sd->status.inventory[n].nameid <= 0 ||
sd->status.inventory[n].amount <= 0 ||
sd->sc_data[SC_BERSERK].timer!=-1 ||
sd->sc_data[SC_MARIONETTE].timer!=-1 ||
+ (pc_issit(sd) && (sd->itemid == 605 || sd->itemid == 606)) ||
+ //added item_noequip.txt items check by Maya&[Lupus]
+ (map[sd->bl.m].flag.pvp && (sd->inventory_data[n]->flag.no_equip&1) ) || // PVP
+ (map[sd->bl.m].flag.gvg && (sd->inventory_data[n]->flag.no_equip>1) ) || // GVG
!pc_isUseitem(sd,n) ) {
clif_useitemack(sd,n,0,0);
return 1;
}
- if(sd->inventory_data[n])
- run_script(sd->inventory_data[n]->use_script,0,sd->bl.id,0);
-
- pc_delitem(sd,n,1,1);
+ script = sd->inventory_data[n]->use_script;
amount = sd->status.inventory[n].amount;
-
- clif_useitemack(sd,n,amount,1);
+ clif_useitemack(sd,n,amount-1,1);
+ run_script(script,0,sd->bl.id,0);
+ pc_delitem(sd,n,1,1);
}
return 0;
@@ -3311,7 +2528,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
i=MAX_CART;
if(!itemdb_isequip2(data)){
- // ? 備品ではないので、?所有品なら個?のみ?化させる
+ // 装 備品ではないので、既所有品なら個数のみ変化させる
for(i=0;i<MAX_CART;i++){
if(sd->status.cart[i].nameid==item_data->nameid &&
sd->status.cart[i].card[0] == item_data->card[0] && sd->status.cart[i].card[1] == item_data->card[1] &&
@@ -3325,7 +2542,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
}
}
if(i >= MAX_CART){
- // ? 備品か未所有品だったので空き欄へ追加
+ // 装 備品か未所有品だったので空き欄へ追加
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]));
@@ -3380,6 +2597,10 @@ int pc_putitemtocart(struct map_session_data *sd,int idx,int amount) {
nullpo_retr(0, sd);
nullpo_retr(0, item_data = &sd->status.inventory[idx]);
+ if(itemdb_isdropable(sd->status.inventory[idx].nameid) == 0)
+ return 1;
+ if(pc_candrop(sd,sd->status.inventory[idx].nameid)==1)
+ return 1;
if (item_data->nameid==0 || item_data->amount<amount || sd->vender_id)
return 1;
if (pc_cart_additem(sd,item_data,amount) == 0)
@@ -3460,18 +2681,31 @@ int pc_item_identify(struct map_session_data *sd,int idx)
*/
int pc_item_repair(struct map_session_data *sd,int idx)
{
- int flag=1;
+ int flag=1, material;
+ int materials[5] = { 0, 1002, 998, 999, 756 };
+ struct item *item;
nullpo_retr(0, sd);
+ item = &sd->status.inventory[idx];
+
if(idx >= 0 && idx < MAX_INVENTORY) {
- if(sd->status.inventory[idx].nameid > 0 && sd->status.inventory[idx].attribute == 1 ) {
+ if(item->nameid > 0 && item->attribute == 1 ) {
+ if (itemdb_type(item->nameid)==4)
+ material = materials [itemdb_wlv (item->nameid)];
+ else
+ material = materials [3];
+
+ if (pc_search_inventory(sd, material) < 0 ) { //fixed by Lupus (item pos can be = 0!)
+ clif_skill_fail(sd,sd->skillid,0,0);
+ return 0;
+ }
flag=0;
- sd->status.inventory[idx].attribute=0;
+ item->attribute=0;
//Temporary Weapon Repair code [DracoRPG]
- pc_delitem(sd, pc_search_inventory(sd, 999), 1, 0);
+ pc_delitem(sd, pc_search_inventory(sd, material), 1, 0);
clif_equiplist(sd);
- clif_produceeffect(sd, 0, sd->status.inventory[idx].nameid);
+ clif_produceeffect(sd, 0, item->nameid);
clif_misceffect(&sd->bl, 3);
clif_displaymessage(sd->fd,"Item has been repaired.");
}
@@ -3486,63 +2720,49 @@ int pc_item_repair(struct map_session_data *sd,int idx)
*/
int pc_item_refine(struct map_session_data *sd,int idx)
{
- int flag = 1, i = 0, count = 0, ep = 0, per, refine;
+ int flag = 1, i = 0, ep = 0, per;
int material[5] = { 0, 1010, 1011, 984, 984 };
-
+ struct item *item;
+
nullpo_retr(0, sd);
- struct item *item = &sd->status.inventory[idx];
+ item = &sd->status.inventory[idx];
if(idx >= 0 && idx < MAX_INVENTORY) {
if(item->nameid > 0 && itemdb_type(item->nameid)==4) {
// if it's no longer refineable
- if (item->refine == 10) {
+ if (item->refine >= sd->skilllv || item->refine == 10) {
clif_skill_fail(sd,sd->skillid,0,0);
return 0;
}
- refine = item->refine + sd->skilllv > 10
- ? 10 - item->refine : sd->skilllv;
- for (i=0; i < MAX_INVENTORY; i++)
- if(sd->status.inventory[i].nameid == material [itemdb_wlv (item->nameid)])
- count += sd->status.inventory[i].amount;
- if (count < refine ) {
+ if ((i=pc_search_inventory(sd, material [itemdb_wlv (item->nameid)])) < 0 ) { //fixed by Lupus (item pos can be = 0!)
clif_skill_fail(sd,sd->skillid,0,0);
return 0;
}
- per = percentrefinery [itemdb_wlv (item->nameid)][item->refine + refine - 1];
+
+ per = percentrefinery [itemdb_wlv (item->nameid)][(int)item->refine];
//per += pc_checkskill(sd,BS_WEAPONRESEARCH);
per *= (75 + sd->status.job_level/2)/100;
-
+
if (per > rand() % 100) {
flag = 0;
- item->refine += refine;
-
- for (i=0; i < MAX_INVENTORY; i++)
- if(sd->status.inventory[i].nameid == material [itemdb_wlv (item->nameid)]) {
- if (sd->status.inventory[i].amount >= refine) {
- pc_delitem(sd,i,refine,0);
- break;
- } else {
- refine -= sd->status.inventory[i].amount;
- pc_delitem(sd,i,sd->status.inventory[i].amount,0);
- }
- }
-
+ item->refine++;
+ pc_delitem(sd, i, 1, 0);
if(item->equip) {
ep = item->equip;
- pc_unequipitem(sd,idx,0, BF_NORMAL);
+ pc_unequipitem(sd,idx,3);
}
clif_refine(sd->fd,sd,0,idx,item->refine);
- clif_delitem(sd,idx,1);
+ clif_delitem(sd,idx,1);
clif_additem(sd,idx,1,0);
if (ep)
pc_equipitem(sd,idx,ep);
clif_misceffect(&sd->bl,3);
}
else {
- clif_delitem(sd,i,refine);
+ pc_delitem(sd, i, 1, 0);
item->refine = 0;
if(item->equip)
- pc_unequipitem(sd,idx,0, BF_NORMAL);
+ pc_unequipitem(sd,idx,3);
clif_refine(sd->fd,sd,1,idx,item->refine);
pc_delitem(sd,idx,1,0);
clif_misceffect(&sd->bl,2);
@@ -3596,28 +2816,29 @@ int pc_show_steal(struct block_list *bl,va_list ap)
int pc_steal_item(struct map_session_data *sd,struct block_list *bl)
{
if(sd != NULL && bl != NULL && bl->type == BL_MOB) {
- int i,skill,rate,itemid,flag, count;
+ int i,skill,itemid,flag, count;
struct mob_data *md;
md=(struct mob_data *)bl;
- if(!md->state.steal_flag && mob_db[md->class].mexp <= 0 && !(mob_db[md->class].mode&0x20) && md->sc_data[SC_STONE].timer == -1 && md->sc_data[SC_FREEZE].timer == -1 &&
- (!(md->class>1324 && md->class<1364))) // prevent stealing from treasure boxes [Valaris]
+ if(!md->state.steal_flag && mob_db[md->class_].mexp <= 0 && !(mob_db[md->class_].mode&0x20) &&
+ (!(md->class_>1324 && md->class_<1364))) // prevent stealing from treasure boxes [Valaris]
{
+ if (md->sc_data && (md->sc_data[SC_STONE].timer != -1 || md->sc_data[SC_FREEZE].timer != -1))
+ return 0;
skill = battle_config.skill_steal_type == 1
- ? (sd->paramc[4] - mob_db[md->class].dex)/2 + pc_checkskill(sd,TF_STEAL)*6 + 10
- : sd->paramc[4] - mob_db[md->class].dex + pc_checkskill(sd,TF_STEAL)*3 + 10;
+ ? (sd->paramc[4] - mob_db[md->class_].dex)/2 + pc_checkskill(sd,TF_STEAL)*6 + 10
+ : sd->paramc[4] - mob_db[md->class_].dex + pc_checkskill(sd,TF_STEAL)*3 + 10;
if(0 < skill)
{
- for(count = 8; count <= 8 && count != 0; count--)
+ for(count = 10; count <= 10 && count != 0; count--) //8 -> 10 Lupus
{
- i = rand()%8;
- itemid = mob_db[md->class].dropitem[i].nameid;
+ i = rand()%10; //8 -> 10 Lupus
+ itemid = mob_db[md->class_].dropitem[i].nameid;
if(itemid > 0 && itemdb_type(itemid) != 6)
{
- rate = (mob_db[md->class].dropitem[i].p / battle_config.item_rate_common * 100 * skill)/100;
-
- if(rand()%10000 < rate)
+ //fixed rate. From Freya [Lupus]
+ if (rand() % 10000 < ((mob_db[md->class_].dropitem[i].p * skill) / 100 + sd->add_steal_rate))
{
struct item tmp_item;
memset(&tmp_item,0,sizeof(tmp_item));
@@ -3659,11 +2880,13 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *bl)
if(sd != NULL && bl != NULL && bl->type == BL_MOB) {
int rate,skill;
struct mob_data *md=(struct mob_data *)bl;
- if(md && !md->state.steal_coin_flag && md->sc_data && md->sc_data[SC_STONE].timer == -1 && md->sc_data[SC_FREEZE].timer == -1) {
+ if(md && !md->state.steal_coin_flag) {
+ if (md->sc_data && (md->sc_data[SC_STONE].timer != -1 || md->sc_data[SC_FREEZE].timer != -1))
+ return 0;
skill = pc_checkskill(sd,RG_STEALCOIN)*10;
- rate = skill + (sd->status.base_level - mob_db[md->class].lv)*3 + sd->paramc[4]*2 + sd->paramc[5]*2;
+ rate = skill + (sd->status.base_level - mob_db[md->class_].lv)*3 + sd->paramc[4]*2 + sd->paramc[5]*2;
if(rand()%1000 < rate) {
- pc_getzeny(sd,mob_db[md->class].lv*10 + rand()%100);
+ pc_getzeny(sd,mob_db[md->class_].lv*10 + rand()%100);
md->state.steal_coin_flag = 1;
return 1;
}
@@ -3682,7 +2905,7 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *bl)
int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrtype)
{
char mapname[24];
- int m=0,c=0,disguise=0;
+ int m=0,disguise=0;
nullpo_retr(0, sd);
@@ -3711,43 +2934,58 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
skill_gangsterparadise(sd,0);
}
- if(sd->sc_data[SC_TRICKDEAD].timer != -1)
- skill_status_change_end(&sd->bl, SC_TRICKDEAD, -1);
+ if (sd->sc_count) {
+ if(sd->sc_data[SC_TRICKDEAD].timer != -1)
+ status_change_end(&sd->bl, SC_TRICKDEAD, -1);
+ if(sd->sc_data[SC_BLADESTOP].timer!=-1)
+ 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]);*/
+
+ struct skill_unit_group *sg = (struct skill_unit_group *)sd->sc_data[SC_BASILICA].val4;
+ if (sg && sg->src_id == sd->bl.id)
+ skill_delunitgroup (sg);
+ status_change_end(&sd->bl,SC_BASILICA,-1);
+ }
+ }
+
if(sd->status.option&2)
- skill_status_change_end(&sd->bl, SC_HIDING, -1);
+ status_change_end(&sd->bl, SC_HIDING, -1);
if(sd->status.option&4)
- skill_status_change_end(&sd->bl, SC_CLOAKING, -1);
- if(sd->status.option&16386)
- skill_status_change_end(&sd->bl, SC_CHASEWALK, -1);
- if(sd->sc_data[SC_BLADESTOP].timer!=-1)
- skill_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);
+ status_change_end(&sd->bl, SC_CLOAKING, -1);
+ if(sd->status.option&16384)
+ status_change_end(&sd->bl, SC_CHASEWALK, -1);
if(sd->status.pet_id > 0 && sd->pd && sd->pet.intimate > 0) {
pet_stopattack(sd->pd);
pet_changestate(sd->pd,MS_IDLE,0);
}
-
+
if(sd->disguise) { // clear disguises when warping [Valaris]
clif_clearchar(&sd->bl, 9);
disguise=sd->disguise;
sd->disguise=0;
}
- memcpy(mapname,mapname_org,24);
+ strncpy(mapname,mapname_org,sizeof(mapname));
mapname[16]=0;
- if(strstr(mapname,".gat")==NULL && strlen(mapname)<16){
+ if(strstr(mapname,".gat")==NULL && strstr(mapname,".afm")==NULL && strlen(mapname)<16){
strcat(mapname,".gat");
}
m=map_mapname2mapid(mapname);
+
if(m<0){
if(sd->mapname[0]){
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);
@@ -3759,7 +2997,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
sd->pd = NULL;
sd->petDB = NULL;
if(battle_config.pet_status_support)
- pc_calcstatus(sd,2);
+ status_calc_pc(sd,2);
}
else if(sd->pet.intimate > 0) {
pet_stopattack(sd->pd);
@@ -3772,11 +3010,13 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
sd->bl.x=x;
sd->bl.y=y;
sd->state.waitingdisconnect=1;
+ pc_clean_skilltree(sd);
pc_makesavestatus(sd);
if(sd->status.pet_id > 0 && sd->pd)
intif_save_petdata(sd->status.account_id,&sd->pet);
chrif_save(sd);
storage_storage_save(sd);
+ storage_delete(sd->status.account_id);
chrif_changemapserver(sd, mapname, x, y, ip, port);
return 0;
}
@@ -3790,7 +3030,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
if(x <0 || x >= map[m].xs || y <0 || y >= map[m].ys)
x=y=0;
- if((x==0 && y==0) || (c=read_gat(m,x,y))==1 || c==5){
+ if((x==0 && y==0) || map_getcell(m,x,y,CELL_CHKNOPASS)){
if(x||y) {
if(battle_config.error_log)
printf("stacked (%d,%d)\n",x,y);
@@ -3798,11 +3038,11 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
do {
x=rand()%(map[m].xs-2)+1;
y=rand()%(map[m].ys-2)+1;
- } while((c=read_gat(m,x,y))==1 || c==5);
+ } while(map_getcell(m,x,y,CELL_CHKNOPASS));
}
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);
@@ -3815,7 +3055,8 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
sd->pd = NULL;
sd->petDB = NULL;
if(battle_config.pet_status_support)
- pc_calcstatus(sd,2);
+ status_calc_pc(sd,2);
+ pc_clean_skilltree(sd);
pc_makesavestatus(sd);
chrif_save(sd);
storage_storage_save(sd);
@@ -3832,13 +3073,13 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
if(disguise) // disguise teleport fix [Valaris]
sd->disguise=disguise;
-
+
memcpy(sd->mapname,mapname,24);
sd->bl.m = m;
sd->to_x = x;
sd->to_y = y;
- // moved and changed dance effect stopping
+ // moved and changed dance effect stopping
sd->bl.x = x;
sd->bl.y = y;
@@ -3861,7 +3102,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
*------------------------------------------
*/
int pc_randomwarp(struct map_session_data *sd, int type) {
- int x,y,c,i=0;
+ int x,y,i=0;
int m;
nullpo_retr(0, sd);
@@ -3874,7 +3115,7 @@ int pc_randomwarp(struct map_session_data *sd, int type) {
do{
x=rand()%(map[m].xs-2)+1;
y=rand()%(map[m].ys-2)+1;
- } while (((c=read_gat(m,x,y)) == 1 || c == 5) && (i++) < 1000);
+ }while(map_getcell(m,x,y,CELL_CHKNOPASS) && (i++)<1000 );
if (i < 1000)
pc_setpos(sd,map[m].name,x,y,type);
@@ -3957,7 +3198,7 @@ int pc_can_reach(struct map_session_data *sd,int x,int y)
// ? 行物
//
/*==========================================
- * 次の1?にかかる時間を計算
+ * 次の1?にかかる史ヤを計算
*------------------------------------------
*/
static int calc_next_walk_step(struct map_session_data *sd)
@@ -3979,12 +3220,11 @@ static int calc_next_walk_step(struct map_session_data *sd)
static int pc_walk(int tid,unsigned int tick,int id,int data)
{
struct map_session_data *sd;
- int i,ctype;
+ int i;
int moveblock;
int x,y,dx,dy;
- sd=map_id2sd(id);
- if(sd==NULL)
+ if ((sd = map_id2sd(id)) == NULL)
return 0;
if(sd->walktimer != tid){
@@ -4001,32 +3241,34 @@ static int pc_walk(int tid,unsigned int tick,int id,int data)
sd->inchealspiritsptick = 0;
sd->walkpath.path_half ^= 1;
- if(sd->walkpath.path_half==0){ // マス目中心へ到着
+ if(sd->walkpath.path_half==0){ // マス目中心へ途
sd->walkpath.path_pos++;
+
if(sd->state.change_walk_target){
pc_walktoxy_sub(sd);
return 0;
}
- } else { // マス目境界へ到着
+ } else { // マス目境界へ途
if(sd->walkpath.path[sd->walkpath.path_pos]>=8)
return 1;
x = sd->bl.x;
y = sd->bl.y;
- ctype = map_getcell(sd->bl.m,x,y);
- if(ctype == 1 || ctype == 5) {
+ if(map_getcell(sd->bl.m,x,y,CELL_CHKNOPASS)) {
pc_stop_walking(sd,1);
return 0;
}
sd->dir=sd->head_dir=sd->walkpath.path[sd->walkpath.path_pos];
dx = dirx[(int)sd->dir];
dy = diry[(int)sd->dir];
- ctype = map_getcell(sd->bl.m,x+dx,y+dy);
- if(ctype == 1 || ctype == 5) {
+ if(map_getcell(sd->bl.m,x,y,CELL_CHKNOPASS)) {
pc_walktoxy_sub(sd);
return 0;
}
-
+ if (skill_check_moonlit (&sd->bl,x+dx,y+dy)) {
+ pc_stop_walking(sd,1);
+ return 0;
+ }
moveblock = ( x/BLOCK_SIZE != (x+dx)/BLOCK_SIZE || y/BLOCK_SIZE != (y+dy)/BLOCK_SIZE);
sd->walktimer = 1;
@@ -4035,26 +3277,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);
-
- if (sd->status.guild_id > 0) {
- struct skill_unit *su;
- if (sd->sc_data[SC_LEADERSHIP].val4 && (su=(struct skill_unit *)sd->sc_data[SC_LEADERSHIP].val4)) {
- skill_unit_move_unit_group(su->group,sd->bl.m,dx,dy);
- }
- if (sd->sc_data[SC_GLORYWOUNDS].val4 && (su=(struct skill_unit *)sd->sc_data[SC_GLORYWOUNDS].val4)) {
- skill_unit_move_unit_group(su->group,sd->bl.m,dx,dy);
- }
- if (sd->sc_data[SC_SOULCOLD].val4 && (su=(struct skill_unit *)sd->sc_data[SC_SOULCOLD].val4)) {
- skill_unit_move_unit_group(su->group,sd->bl.m,dx,dy);
- }
- if (sd->sc_data[SC_HAWKEYES].val4 && (su=(struct skill_unit *)sd->sc_data[SC_HAWKEYES].val4)) {
- skill_unit_move_unit_group(su->group,sd->bl.m,dx,dy);
- }
- }
+ skill_unit_move(&sd->bl,tick,1);
map_foreachinmovearea(clif_pcinsight,sd->bl.m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,-dx,-dy,0,sd);
sd->walktimer = -1;
@@ -4084,21 +3312,18 @@ 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) {
- skill_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*/
+ struct skill_unit_group *sg = (struct skill_unit_group *)sd->sc_data[SC_BASILICA].val4;
+ if (sg && sg->src_id == sd->bl.id)
+ skill_delunitgroup (sg);
+ status_change_end(&sd->bl,SC_BASILICA,-1);
}
}
- skill_unit_move(&sd->bl,tick,1); // スキルユニットの?査
-
- if(map_getcell(sd->bl.m,x,y)&0x80)
+ if(map_getcell(sd->bl.m,x,y,CELL_CHKNPC))
npc_touch_areanpc(sd,sd->bl.m,x,y);
else
sd->areanpc_id=0;
@@ -4109,6 +3334,8 @@ static int pc_walk(int tid,unsigned int tick,int id,int data)
i = 1;
sd->walktimer=add_timer(tick+i,pc_walk,id,sd->walkpath.path_pos);
}
+ if(battle_config.disp_hpmeter)
+ clif_hpmeter(sd);
return 0;
}
@@ -4151,15 +3378,24 @@ int pc_walktoxy(struct map_session_data *sd,int x,int y)
sd->to_x=x;
sd->to_y=y;
+ sd->idletime = tick_;
if(sd->walktimer != -1 && sd->state.change_walk_target==0){
- // 現在?いている最中の目的地?更なのでマス目の中心に?た時に
+ // 現在?いている最中の目的地?更なのでマス目の中心に?た暫ノ
// timer??からpc_walktoxy_subを呼ぶようにする
sd->state.change_walk_target=1;
} else {
pc_walktoxy_sub(sd);
}
+ if (sd->state.gmaster_flag > 0) {
+ struct guild *g = (struct guild *)sd->state.gmaster_flag;
+ if (g)
+ map_foreachinarea (skill_guildaura_sub, sd->bl.m,
+ sd->bl.x-2, sd->bl.y-2, sd->bl.x+2, sd->bl.y+2, BL_PC,
+ sd->bl.id, sd->status.guild_id, g);
+ }
+
return 0;
}
@@ -4182,7 +3418,7 @@ int pc_stop_walking(struct map_session_data *sd,int type)
clif_fixpos(&sd->bl);
if(type&0x02 && battle_config.pc_damage_delay) {
unsigned int tick = gettick();
- int delay = battle_get_dmotion(&sd->bl);
+ int delay = status_get_dmotion(&sd->bl);
if(sd->canmove_tick < tick)
sd->canmove_tick = tick + delay;
}
@@ -4191,13 +3427,47 @@ int pc_stop_walking(struct map_session_data *sd,int type)
}
/*==========================================
+ * Random walk
+ *------------------------------------------
+ */
+int pc_randomwalk(struct map_session_data *sd,int tick)
+{
+ const int retrycount = 20;
+ nullpo_retr(0, sd);
+
+ if(DIFF_TICK(sd->next_walktime,tick)<0){
+ int i,x,y,d;
+ d = rand()%7+5;
+ for(i=0;i<retrycount;i++){ // Search of a movable place
+ int r=rand();
+ x=sd->bl.x+r%(d*2+1)-d;
+ y=sd->bl.y+r/(d*2+1)%(d*2+1)-d;
+ if((map_getcell(sd->bl.m,x,y,CELL_CHKPASS)) && pc_walktoxy(sd,x,y)==0)
+ break;
+ }
+ // Working on this part later [celest]
+ /*for(i=c=0;i<sd->walkpath.path_len;i++){ // The next walk start time is calculated.
+ if(sd->walkpath.path[i]&1)
+ c+=sd->speed*14/10;
+ else
+ c+=sd->speed;
+ }
+ sd->next_walktime = (d=tick+rand()%3000+c);
+ return d;*/
+ return 1;
+ }
+ return 0;
+}
+
+/*==========================================
*
*------------------------------------------
*/
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;
@@ -4210,16 +3480,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);
@@ -4236,9 +3507,7 @@ 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)&0x80)
+ 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
sd->areanpc_id=0;
@@ -4281,46 +3550,44 @@ int pc_checkskill(struct map_session_data *sd,int skill_id)
int pc_checkallowskill(struct map_session_data *sd)
{
nullpo_retr(0, sd);
-
- if( sd->sc_data == NULL )
- return 0;
+ nullpo_retr(0, sd->sc_data);
if(!(skill_get_weapontype(KN_TWOHANDQUICKEN)&(1<<sd->status.weapon)) && sd->sc_data[SC_TWOHANDQUICKEN].timer!=-1) { // 2HQ
- skill_status_change_end(&sd->bl,SC_TWOHANDQUICKEN,-1); // 2HQを解除
+ status_change_end(&sd->bl,SC_TWOHANDQUICKEN,-1); // 2HQを解除
return -1;
}
if(!(skill_get_weapontype(LK_AURABLADE)&(1<<sd->status.weapon)) && sd->sc_data[SC_AURABLADE].timer!=-1) { /* オ?ラブレ?ド */
- skill_status_change_end(&sd->bl,SC_AURABLADE,-1); /* オ?ラブレ?ドを解除 */
+ status_change_end(&sd->bl,SC_AURABLADE,-1); /* オ?ラブレ?ドを解除 */
return -1;
}
if(!(skill_get_weapontype(LK_PARRYING)&(1<<sd->status.weapon)) && sd->sc_data[SC_PARRYING].timer!=-1) { /* パリイング */
- skill_status_change_end(&sd->bl,SC_PARRYING,-1); /* パリイングを解除 */
+ status_change_end(&sd->bl,SC_PARRYING,-1); /* パリイングを解除 */
return -1;
}
if(!(skill_get_weapontype(LK_CONCENTRATION)&(1<<sd->status.weapon)) && sd->sc_data[SC_CONCENTRATION].timer!=-1) { /* コンセントレ?ション */
- skill_status_change_end(&sd->bl,SC_CONCENTRATION,-1); /* コンセントレ?ションを解除 */
+ status_change_end(&sd->bl,SC_CONCENTRATION,-1); /* コンセントレ?ションを解除 */
return -1;
}
if(!(skill_get_weapontype(CR_SPEARQUICKEN)&(1<<sd->status.weapon)) && sd->sc_data[SC_SPEARSQUICKEN].timer!=-1){ // スピアクィッケン
- skill_status_change_end(&sd->bl,SC_SPEARSQUICKEN,-1); // スピアクイッケンを解除
+ status_change_end(&sd->bl,SC_SPEARSQUICKEN,-1); // スピアクイッケンを解除
return -1;
}
if(!(skill_get_weapontype(BS_ADRENALINE)&(1<<sd->status.weapon)) && sd->sc_data[SC_ADRENALINE].timer!=-1){ // アドレナリンラッシュ
- skill_status_change_end(&sd->bl,SC_ADRENALINE,-1); // アドレナリンラッシュを解除
+ status_change_end(&sd->bl,SC_ADRENALINE,-1); // アドレナリンラッシュを解除
return -1;
}
if(sd->status.shield <= 0) {
if(sd->sc_data[SC_AUTOGUARD].timer!=-1){ // オ?トガ?ド
- skill_status_change_end(&sd->bl,SC_AUTOGUARD,-1);
+ status_change_end(&sd->bl,SC_AUTOGUARD,-1);
return -1;
}
if(sd->sc_data[SC_DEFENDER].timer!=-1){ // ディフェンダ?
- skill_status_change_end(&sd->bl,SC_DEFENDER,-1);
+ status_change_end(&sd->bl,SC_DEFENDER,-1);
return -1;
}
if(sd->sc_data[SC_REFLECTSHIELD].timer!=-1){ //リフレクトシ?ルド
- skill_status_change_end(&sd->bl,SC_REFLECTSHIELD,-1);
+ status_change_end(&sd->bl,SC_REFLECTSHIELD,-1);
return -1;
}
}
@@ -4372,10 +3639,6 @@ struct pc_base_job pc_calc_base_job(int b_class)
bj.upper = 2;
}
- if(battle_config.enable_upper_class==0){ //confで無?になっていたらupper=0
- bj.upper = 0;
- }
-
if(bj.job == 0){
bj.type = 0;
}else if(bj.job < 7){
@@ -4383,7 +3646,7 @@ struct pc_base_job pc_calc_base_job(int b_class)
}else{
bj.type = 2;
}
-
+
return bj;
}
@@ -4399,7 +3662,7 @@ int pc_calc_base_job2 (int b_class)
return b_class - 4001;
else if(b_class == 4045)
return 23;
- return b_class - 4023;
+ return b_class - 4023;
}
int pc_calc_upper(int b_class)
@@ -4426,6 +3689,9 @@ int pc_attack_timer(int tid,unsigned int tick,int id,int data)
sd=map_id2sd(id);
if(sd == NULL)
return 0;
+
+ sd->idletime = tick_;
+
if(sd->attacktimer != tid){
if(battle_config.error_log)
printf("pc_attack_timer %d != %d\n",sd->attacktimer,tid);
@@ -4440,8 +3706,12 @@ int pc_attack_timer(int tid,unsigned int tick,int id,int data)
if(bl==NULL || bl->prev == NULL)
return 0;
- if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))
- return 0;
+ if(bl->type == BL_PC) {
+ if (pc_isdead((struct map_session_data *)bl))
+ return 0;
+ else if (pc_ishiding((struct map_session_data *)bl))
+ return 0;
+ }
// 同じmapでないなら攻?しない
// PCが死んでても攻?しない
@@ -4452,17 +3722,21 @@ int pc_attack_timer(int tid,unsigned int tick,int id,int data)
if( sd->opt1>0 || sd->status.option&2 || sd->status.option&16384) // 異常などで攻?できない
return 0;
- if(sd->sc_data[SC_AUTOCOUNTER].timer != -1)
- return 0;
- if(sd->sc_data[SC_BLADESTOP].timer != -1)
- return 0;
+ if (sd->sc_count) {
+ if(sd->sc_data[SC_AUTOCOUNTER].timer != -1)
+ return 0;
+ if(sd->sc_data[SC_BLADESTOP].timer != -1)
+ return 0;
+ }
- //if((opt = battle_get_option(bl)) != NULL && *opt&0x46)
- if((opt = battle_get_option(bl)) != NULL && *opt&0x42)
+ //if((opt = status_get_option(bl)) != NULL && *opt&0x46)
+ if((opt = status_get_option(bl)) != NULL && *opt&0x42)
return 0;
- if(((sc_data = battle_get_sc_data(bl)) != NULL && sc_data[SC_TRICKDEAD].timer != -1) ||
- ((sc_data = battle_get_sc_data(bl)) != NULL && sc_data[SC_BASILICA].timer != -1 ))
+ if((sc_data = status_get_sc_data(bl)) != NULL) {
+ if (sc_data[SC_TRICKDEAD].timer != -1 ||
+ sc_data[SC_BASILICA].timer != -1)
return 0;
+ }
if(sd->skilltimer != -1 && pc_checkskill(sd,SA_FREECAST) <= 0)
return 0;
@@ -4474,6 +3748,11 @@ int pc_attack_timer(int tid,unsigned int tick,int id,int data)
}
}
+ if(sd->status.weapon == 11 && sd->equip_index[10] < 0) {
+ clif_arrow_fail(sd,0);
+ return 0;
+ }
+
dist = distance(sd->bl.x,sd->bl.y,bl->x,bl->y);
range = sd->attackrange;
if(sd->status.weapon != 11) range++;
@@ -4501,7 +3780,7 @@ int pc_attack_timer(int tid,unsigned int tick,int id,int data)
sd->attacktarget_lv = battle_weapon_attack(&sd->bl,bl,tick,0);
// &2 = ? - Celest
if(!(battle_config.pc_cloak_check_type&2) && sd->sc_data[SC_CLOAKING].timer != -1)
- skill_status_change_end(&sd->bl,SC_CLOAKING,-1);
+ status_change_end(&sd->bl,SC_CLOAKING,-1);
if(sd->status.pet_id > 0 && sd->pd && sd->petDB && battle_config.pet_attack_support)
pet_target_check(sd,bl,0);
map_freeblock_unlock();
@@ -4536,19 +3815,22 @@ int pc_attack(struct map_session_data *sd,int target_id,int type)
struct block_list *bl;
int d;
+
nullpo_retr(0, sd);
bl=map_id2bl(target_id);
if(bl==NULL)
return 1;
-
+
+ sd->idletime = tick_;
+
if(bl->type==BL_NPC) { // monster npcs [Valaris]
//npc_click(sd,RFIFOL(sd->fd,2));
npc_click(sd,target_id); // submitted by leinsirk10 [Celest]
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);
@@ -4589,7 +3871,8 @@ int pc_follow_timer(int tid,unsigned int tick,int id,int data)
struct map_session_data *sd, *bl;
sd=map_id2sd(id);
- if(sd == NULL || sd->followtimer != tid)
+
+ if(sd == NULL || sd->followtimer != tid || pc_isdead(sd))
return 0;
sd->followtimer=-1;
@@ -4648,7 +3931,7 @@ int pc_checkbaselevelup(struct map_session_data *sd)
nullpo_retr(0, sd);
if(sd->status.base_exp >= next && next > 0){
- struct pc_base_job s_class = pc_calc_base_job(sd->status.class);
+ struct pc_base_job s_class = pc_calc_base_job(sd->status.class_);
// base側レベルアップ?理
sd->status.base_exp -= next;
@@ -4658,16 +3941,16 @@ int pc_checkbaselevelup(struct map_session_data *sd)
clif_updatestatus(sd,SP_STATUSPOINT);
clif_updatestatus(sd,SP_BASELEVEL);
clif_updatestatus(sd,SP_NEXTBASEEXP);
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
pc_heal(sd,sd->status.max_hp,sd->status.max_sp);
//スパノビはキリエ、イムポ、マニピ、グロ、サフラLv1がかかる
if(s_class.job == 23){
- skill_status_change_start(&sd->bl,SkillStatusChangeTable[PR_KYRIE],1,0,0,0,skill_get_time(PR_KYRIE,1),0 );
- skill_status_change_start(&sd->bl,SkillStatusChangeTable[PR_IMPOSITIO],1,0,0,0,skill_get_time(PR_IMPOSITIO,1),0 );
- skill_status_change_start(&sd->bl,SkillStatusChangeTable[PR_MAGNIFICAT],1,0,0,0,skill_get_time(PR_MAGNIFICAT,1),0 );
- skill_status_change_start(&sd->bl,SkillStatusChangeTable[PR_GLORIA],1,0,0,0,skill_get_time(PR_GLORIA,1),0 );
- skill_status_change_start(&sd->bl,SkillStatusChangeTable[PR_SUFFRAGIUM],1,0,0,0,skill_get_time(PR_SUFFRAGIUM,1),0 );
+ status_change_start(&sd->bl,SkillStatusChangeTable[PR_KYRIE],1,0,0,0,skill_get_time(PR_KYRIE,1),0 );
+ status_change_start(&sd->bl,SkillStatusChangeTable[PR_IMPOSITIO],1,0,0,0,skill_get_time(PR_IMPOSITIO,1),0 );
+ status_change_start(&sd->bl,SkillStatusChangeTable[PR_MAGNIFICAT],1,0,0,0,skill_get_time(PR_MAGNIFICAT,1),0 );
+ status_change_start(&sd->bl,SkillStatusChangeTable[PR_GLORIA],1,0,0,0,skill_get_time(PR_GLORIA,1),0 );
+ status_change_start(&sd->bl,SkillStatusChangeTable[PR_SUFFRAGIUM],1,0,0,0,skill_get_time(PR_SUFFRAGIUM,1),0 );
}
clif_misceffect(&sd->bl,0);
@@ -4694,7 +3977,7 @@ int pc_checkjoblevelup(struct map_session_data *sd)
clif_updatestatus(sd,SP_NEXTJOBEXP);
sd->status.skill_point ++;
clif_updatestatus(sd,SP_SKILLPOINT);
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
clif_misceffect(&sd->bl,1);
return 1;
@@ -4710,6 +3993,8 @@ int pc_checkjoblevelup(struct map_session_data *sd)
int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp)
{
char output[256];
+ float nextbp=0, nextjp=0;
+ int nextb=0, nextj=0;
nullpo_retr(0, sd);
if(sd->bl.prev == NULL || pc_isdead(sd))
@@ -4734,11 +4019,17 @@ int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp)
if (base_exp < 0)
base_exp = 0;
}
+ nextb = pc_nextbaseexp(sd);
+ nextj = pc_nextjobexp(sd);
+ if (nextb > 0)
+ nextbp = (float) base_exp / (float) nextb;
+ if (nextj > 0)
+ nextjp = (float) job_exp / (float) nextj;
sd->status.base_exp += base_exp;
if(sd->status.base_exp < 0)
sd->status.base_exp = 0;
-
+
while(pc_checkbaselevelup(sd)) ;
clif_updatestatus(sd,SP_BASEEXP);
@@ -4751,14 +4042,14 @@ int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp)
sd->status.job_exp += job_exp;
if(sd->status.job_exp < 0)
sd->status.job_exp = 0;
-
+
while(pc_checkjoblevelup(sd)) ;
clif_updatestatus(sd,SP_JOBEXP);
- if(battle_config.disp_experience){
- sprintf(output,
- "Experienced Gained Base:%d Job:%d",base_exp,job_exp);
+ if(battle_config.disp_experience && !sd->noexp){
+ sprintf(output,
+ "Experienced Gained Base:%d (%.2f%%) Job:%d (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100);
clif_disp_onlyself(sd,output,strlen(output));
}
@@ -4778,12 +4069,12 @@ int pc_nextbaseexp(struct map_session_data *sd)
if(sd->status.base_level>=MAX_LEVEL || sd->status.base_level<=0)
return 0;
- if(sd->status.class==0) i=0;
- else if(sd->status.class<=6) i=1;
- else if(sd->status.class<=22) i=2;
- else if(sd->status.class==23) i=3;
- else if(sd->status.class==4001) i=4;
- else if(sd->status.class<=4007) i=5;
+ if(sd->status.class_==0) i=0;
+ else if(sd->status.class_<=6) i=1;
+ else if(sd->status.class_<=22) i=2;
+ else if(sd->status.class_==23) i=3;
+ else if(sd->status.class_==4001) i=4;
+ else if(sd->status.class_<=4007) i=5;
else i=6;
return exp_table[i][sd->status.base_level-1];
@@ -4802,12 +4093,12 @@ int pc_nextjobexp(struct map_session_data *sd)
if(sd->status.job_level>=MAX_LEVEL || sd->status.job_level<=0)
return 0;
- if(sd->status.class==0) i=7;
- else if(sd->status.class<=6) i=8;
- else if(sd->status.class<=22) i=9;
- else if(sd->status.class==23) i=10;
- else if(sd->status.class==4001) i=11;
- else if(sd->status.class<=4007) i=12;
+ if(sd->status.class_==0) i=7;
+ else if(sd->status.class_<=6) i=8;
+ else if(sd->status.class_<=22) i=9;
+ else if(sd->status.class_==23) i=10;
+ else if(sd->status.class_==4001) i=11;
+ else if(sd->status.class_<=4007) i=12;
else i=13;
return exp_table[i][sd->status.job_level-1];
@@ -4826,12 +4117,12 @@ int pc_nextbaseafter(struct map_session_data *sd)
if(sd->status.base_level>=MAX_LEVEL || sd->status.base_level<=0)
return 0;
- if(sd->status.class==0) i=0;
- else if(sd->status.class<=6) i=1;
- else if(sd->status.class<=22) i=2;
- else if(sd->status.class==23) i=3;
- else if(sd->status.class==4001) i=4;
- else if(sd->status.class<=4007) i=5;
+ if(sd->status.class_==0) i=0;
+ else if(sd->status.class_<=6) i=1;
+ else if(sd->status.class_<=22) i=2;
+ else if(sd->status.class_==23) i=3;
+ else if(sd->status.class_==4001) i=4;
+ else if(sd->status.class_<=4007) i=5;
else i=6;
return exp_table[i][sd->status.base_level];
@@ -4850,12 +4141,12 @@ int pc_nextjobafter(struct map_session_data *sd)
if(sd->status.job_level>=MAX_LEVEL || sd->status.job_level<=0)
return 0;
- if(sd->status.class==0) i=7;
- else if(sd->status.class<=6) i=8;
- else if(sd->status.class<=22) i=9;
- else if(sd->status.class==23) i=10;
- else if(sd->status.class==4001) i=11;
- else if(sd->status.class<=4007) i=12;
+ if(sd->status.class_==0) i=7;
+ else if(sd->status.class_<=6) i=8;
+ else if(sd->status.class_<=22) i=9;
+ else if(sd->status.class_==23) i=10;
+ else if(sd->status.class_==4001) i=11;
+ else if(sd->status.class_<=4007) i=12;
else i=13;
return exp_table[i][sd->status.job_level];
@@ -4890,10 +4181,10 @@ int pc_need_status_point(struct map_session_data *sd,int type)
int pc_statusup(struct map_session_data *sd,int type)
{
int max, need,val = 0;
-
+
nullpo_retr(0, sd);
- max = (pc_calc_upper(sd->status.class)==2) ? 80 : battle_config.max_parameter;
+ max = (pc_calc_upper(sd->status.class_)==2) ? 80 : battle_config.max_parameter;
need=pc_need_status_point(sd,type);
if(type<SP_STR || type>SP_LUK || need<0 || need>sd->status.status_point){
@@ -4950,7 +4241,7 @@ int pc_statusup(struct map_session_data *sd,int type)
}
clif_updatestatus(sd,SP_STATUSPOINT);
clif_updatestatus(sd,type);
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
clif_statusupack(sd,type,1,val);
return 0;
@@ -5026,7 +4317,7 @@ int pc_statusup2(struct map_session_data *sd,int type,int val)
}
clif_updatestatus(sd,type-SP_STR+SP_USTR);
clif_updatestatus(sd,type);
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
clif_statusupack(sd,type,1,val);
return 0;
@@ -5048,11 +4339,11 @@ int pc_skillup(struct map_session_data *sd,int skill_num)
if( sd->status.skill_point>0 &&
sd->status.skill[skill_num].id!=0 &&
//sd->status.skill[skill_num].lv < skill_get_max(skill_num) ) - celest
- sd->status.skill[skill_num].lv < skill_tree_get_max(skill_num, sd->status.class) )
+ sd->status.skill[skill_num].lv < skill_tree_get_max(skill_num, sd->status.class_) )
{
sd->status.skill[skill_num].lv++;
sd->status.skill_point--;
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
clif_skillup(sd,skill_num);
clif_updatestatus(sd,SP_SKILLPOINT);
clif_skillinfoblock(sd);
@@ -5074,7 +4365,7 @@ int pc_allskillup(struct map_session_data *sd)
nullpo_retr(0, sd);
- s_class = pc_calc_base_job(sd->status.class);
+ s_class = pc_calc_base_job(sd->status.class_);
c = s_class.job;
s = (s_class.upper==1) ? 1 : 0 ; //?生以外は通常のスキル?
@@ -5092,21 +4383,25 @@ int pc_allskillup(struct map_session_data *sd)
sd->status.skill[i].lv=skill_get_max(i);
for(i=210;i<291;i++)
sd->status.skill[i].lv=skill_get_max(i);
- for(i=304;i<MAX_SKILL;i++){
+ for(i=304;i<338;i++){
if(i==331) continue;
sd->status.skill[i].lv=skill_get_max(i);
}
+ for(i=355;i<411;i++)
+ sd->status.skill[i].lv=skill_get_max(i);
+ for(i=475;i<480;i++)
+ sd->status.skill[i].lv=skill_get_max(i);
}
else {
for(i=0;(id=skill_tree[s][c][i].id)>0;i++){
if(sd->status.skill[id].id==0 && (!(skill_get_inf2(id)&0x01) || battle_config.quest_skill_learn) ) {
sd->status.skill[id].id = id; // celest
// sd->status.skill[id].lv=skill_get_max(id);
- sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class); // celest
+ sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_); // celest
}
}
}
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
return 0;
}
@@ -5118,9 +4413,9 @@ int pc_allskillup(struct map_session_data *sd)
int pc_resetlvl(struct map_session_data* sd,int type)
{
int i;
-
+
nullpo_retr(0, sd);
-
+
for(i=1;i<MAX_SKILL;i++){
sd->status.skill[i].lv = 0;
}
@@ -5140,8 +4435,11 @@ int pc_resetlvl(struct map_session_data* sd,int type)
sd->status.int_=1;
sd->status.dex=1;
sd->status.luk=1;
- if(sd->status.class == 4001)
- sd->status.status_point=88;
+ if(sd->status.class_ == 4001)
+ sd->status.status_point=100; // not 88 [celest]
+ // give platinum skills upon changing
+ pc_skill(sd,142,1,0);
+ pc_skill(sd,143,1,0);
}
if(type == 2){
@@ -5158,7 +4456,7 @@ int pc_resetlvl(struct map_session_data* sd,int type)
if(type == 4){
sd->status.job_level=1;
sd->status.job_exp=0;
- }
+ }
clif_updatestatus(sd,SP_STATUSPOINT);
clif_updatestatus(sd,SP_STR);
@@ -5184,11 +4482,11 @@ int pc_resetlvl(struct map_session_data* sd,int type)
for(i=0;i<11;i++) { // unequip items that can't be equipped by base 1 [Valaris]
if(sd->equip_index[i] >= 0)
if(!pc_isequip(sd,sd->equip_index[i]))
- pc_unequipitem(sd,sd->equip_index[i],1,BF_NORMAL);
+ pc_unequipitem(sd,sd->equip_index[i],2);
}
clif_skillinfoblock(sd);
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
return 0;
}
@@ -5200,14 +4498,17 @@ int pc_resetstate(struct map_session_data* sd)
{
#define sumsp(a) ((a)*((a-2)/10+2) - 5*((a-2)/10)*((a-2)/10) - 6*((a-2)/10) -2)
// int add=0; // Removed by Dexity
+ int lv;
nullpo_retr(0, sd);
+ // allow it to just read the last entry [celest]
+ lv = sd->status.base_level < MAX_LEVEL ? sd->status.base_level : MAX_LEVEL - 1;
// New statpoint table used here - Dexity
- sd->status.status_point = atoi (statp[sd->status.base_level - 1]);
- if(sd->status.class >= 4001 && sd->status.class <= 4024)
- sd->status.status_point+=40;
-// End addition
+ sd->status.status_point = statp[lv];
+ if(sd->status.class_ >= 4001 && sd->status.class_ <= 4024)
+ sd->status.status_point+=52; // extra 52+48=100 stat points
+// End addition
// Removed by Dexity - old count
// add += sumsp(sd->status.str);
@@ -5241,7 +4542,7 @@ int pc_resetstate(struct map_session_data* sd)
clif_updatestatus(sd,SP_UDEX);
clif_updatestatus(sd,SP_ULUK); // End Addition
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
return 0;
}
@@ -5257,7 +4558,8 @@ int pc_resetskill(struct map_session_data* sd)
nullpo_retr(0, sd);
for(i=1;i<MAX_SKILL;i++){
- if( (skill = pc_checkskill(sd,i)) > 0) {
+ skill = ( i >= 10000 ) ? pc_checkskill(sd,i) : sd->status.skill[i].lv;
+ if( skill > 0) {
if(!(skill_get_inf2(i)&0x01) || battle_config.quest_skill_learn) {
if(!sd->status.skill[i].flag)
sd->status.skill_point += skill;
@@ -5269,13 +4571,13 @@ int pc_resetskill(struct map_session_data* sd)
else if(battle_config.quest_skill_reset)
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = 0;
- }
- else
+ } else {
sd->status.skill[i].lv = 0;
+ }
}
clif_updatestatus(sd,SP_SKILLPOINT);
clif_skillinfoblock(sd);
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
return 0;
}
@@ -5292,7 +4594,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
nullpo_retr(0, sd);
//?生や養子の場合の元の職業を算出する
- s_class = pc_calc_base_job(sd->status.class);
+ s_class = pc_calc_base_job(sd->status.class_);
// ?に死んでいたら無?
if(pc_isdead(sd))
return 0;
@@ -5303,11 +4605,16 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
}
// ? いていたら足を止める
- if(sd->sc_data[SC_ENDURE].timer == -1 && sd->sc_data[SC_BERSERK].timer && !sd->special_state.infinite_endure)
- pc_stop_walking(sd,3);
- else if(sd->sc_data[SC_ENDURE].timer != -1 && src->type==BL_MOB) // [Celest]
- if((--sd->sc_data[SC_ENDURE].val2) <= 0)
- skill_status_change_end(&sd->bl, SC_ENDURE, -1);
+ if (sd->sc_data) {
+ if (sd->sc_data[SC_BERSERK].timer != -1 ||
+ sd->special_state.infinite_endure)
+ ; // do nothing
+ else if (sd->sc_data[SC_ENDURE].timer != -1 && (src != NULL && src->type == BL_MOB) && !map[sd->bl.m].flag.gvg) {
+ if ((--sd->sc_data[SC_ENDURE].val2) < 0)
+ status_change_end(&sd->bl, SC_ENDURE, -1);
+ } else pc_stop_walking(sd,3);
+ }
+
// 演奏/ダンスの中?
if(damage > sd->status.max_hp>>2)
skill_stop_dancing(&sd->bl,0);
@@ -5317,22 +4624,23 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
pet_target_check(sd,src,1);
if (sd->sc_data[SC_TRICKDEAD].timer != -1)
- skill_status_change_end(&sd->bl, SC_TRICKDEAD, -1);
+ status_change_end(&sd->bl, SC_TRICKDEAD, -1);
if(sd->status.option&2)
- skill_status_change_end(&sd->bl, SC_HIDING, -1);
+ status_change_end(&sd->bl, SC_HIDING, -1);
if(sd->status.option&4)
- skill_status_change_end(&sd->bl, SC_CLOAKING, -1);
- if(sd->status.option&16386)
- skill_status_change_end(&sd->bl, SC_CHASEWALK, -1);
+ status_change_end(&sd->bl, SC_CLOAKING, -1);
+ if(sd->status.option&16384)
+ status_change_end(&sd->bl, SC_CHASEWALK, -1);
if(sd->status.hp>0){
// まだ生きているならHP更新
clif_updatestatus(sd,SP_HP);
- if(sd->status.hp<sd->status.max_hp>>2 && pc_checkskill(sd,SM_AUTOBERSERK)>0 &&
+ //if(sd->status.hp<sd->status.max_hp>>2 && pc_checkskill(sd,SM_AUTOBERSERK)>0 &&
+ if(sd->status.hp<sd->status.max_hp>>2 && sd->sc_data[SC_AUTOBERSERK].timer != -1 &&
(sd->sc_data[SC_PROVOKE].timer==-1 || sd->sc_data[SC_PROVOKE].val2==0 ))
// オ?トバ?サ?ク?動
- skill_status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0);
+ status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0);
sd->canlog_tick = gettick();
@@ -5344,7 +4652,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
return 0;
}
sd->status.hp = 0;
- pc_setdead(sd);
+ //pc_setdead(sd);
if(sd->vender_id)
vending_closevending(sd);
@@ -5360,45 +4668,104 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
pc_stop_walking(sd,0);
skill_castcancel(&sd->bl,0); // 詠唱の中止
clif_clearchar_area(&sd->bl,1);
- skill_unit_out_all(&sd->bl,gettick(),1);
+ pc_setdead(sd);
+ skill_unit_move(&sd->bl,gettick(),0);
if(sd->sc_data[SC_BLADESTOP].timer!=-1)//白刃は事前に解除
- skill_status_change_end(&sd->bl,SC_BLADESTOP,-1);
+ status_change_end(&sd->bl,SC_BLADESTOP,-1);
pc_setglobalreg(sd,"PC_DIE_COUNTER",++sd->die_counter); //死にカウンタ?書き?み
- skill_status_change_clear(&sd->bl,0); // ステ?タス異常を解除する
+ status_change_clear(&sd->bl,0); // ステ?タス異常を解除する
clif_updatestatus(sd,SP_HP);
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
+
+ if (src && src->type == BL_PC) {
+ struct map_session_data *ssd = (struct map_session_data *)src;
+ if (ssd) {
+ if (sd->state.event_death)
+ pc_setglobalreg(sd,"killerrid",(ssd->status.account_id));
+ if (ssd->state.event_kill) {
+ if (script_config.event_script_type == 0) {
+ struct npc_data *npc;
+ if ((npc = npc_name2id(script_config.kill_event_name))) {
+ run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCKillNPC
+ sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.kill_event_name);
+ ShowStatus(tmp_output);
+ }
+ } else {
+ sprintf (tmp_output, "%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
+ npc_event_doall_id(script_config.kill_event_name, sd->bl.id), script_config.kill_event_name);
+ ShowStatus(tmp_output);
+ }
+ }
+ }
+ }
+
+ if (sd->state.event_death) {
+ if (script_config.event_script_type == 0) {
+ struct npc_data *npc;
+ if ((npc = npc_name2id(script_config.die_event_name))) {
+ run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCDeathNPC
+ sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.die_event_name);
+ ShowStatus(tmp_output);
+ }
+ } else {
+ sprintf (tmp_output, "%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
+ npc_event_doall_id(script_config.die_event_name, sd->bl.id), script_config.die_event_name);
+ ShowStatus(tmp_output);
+ }
+ }
+
+ if(battle_config.bone_drop==2
+ || (battle_config.bone_drop==1 && map[sd->bl.m].flag.pvp)){ // ドクロドロップ
+ struct item item_tmp;
+ memset(&item_tmp,0,sizeof(item_tmp));
+ item_tmp.nameid=7005;
+ item_tmp.identify=1;
+ item_tmp.card[0]=0x00fe;
+ item_tmp.card[1]=0;
+ *((unsigned long *)(&item_tmp.card[2]))=sd->char_id; /* キャラID */
+ map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
+ }
+
+ // activate Steel body if a super novice dies at 99+% exp [celest]
+ if (s_class.job == 23) {
+ if ((i=pc_nextbaseexp(sd))<=0)
+ i=sd->status.base_exp;
+ if (i>0 && (j=sd->status.base_exp*1000/i)>=990 && j<=1000)
+ sd->state.snovice_flag = 4;
+ }
for(i=0;i<5;i++)
if(sd->dev.val1[i]){
- skill_status_change_end(&map_id2sd(sd->dev.val1[i])->bl,SC_DEVOTION,-1);
+ status_change_end(&map_id2sd(sd->dev.val1[i])->bl,SC_DEVOTION,-1);
sd->dev.val1[i] = sd->dev.val2[i]=0;
}
if(battle_config.death_penalty_type>0) { // changed penalty options, added death by player if pk_mode [Valaris]
- if(sd->status.class != 0 && !map[sd->bl.m].flag.nopenalty && !map[sd->bl.m].flag.gvg){ // only novices will recieve no penalty
+ if(sd->status.class_ != 0 && !map[sd->bl.m].flag.nopenalty && !map[sd->bl.m].flag.gvg && // only novices will recieve no penalty
+ !(sd->sc_count && sd->sc_data[SC_BABY].timer!=-1)) {
if(battle_config.death_penalty_type==1 && battle_config.death_penalty_base > 0)
- sd->status.base_exp -= (double)pc_nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000;
+ sd->status.base_exp -= (int) ((double)pc_nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000);
if(battle_config.pk_mode && src && src->type==BL_PC)
- sd->status.base_exp -= (double)pc_nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000;
+ sd->status.base_exp -= (int) ((double)pc_nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000);
else if(battle_config.death_penalty_type==2 && battle_config.death_penalty_base > 0) {
if(pc_nextbaseexp(sd) > 0)
- sd->status.base_exp -= (double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000;
+ sd->status.base_exp -= (int) ((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000);
if(battle_config.pk_mode && src && src->type==BL_PC)
- sd->status.base_exp -= (double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000;
+ sd->status.base_exp -= (int) ((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000);
}
if(sd->status.base_exp < 0)
sd->status.base_exp = 0;
clif_updatestatus(sd,SP_BASEEXP);
if(battle_config.death_penalty_type==1 && battle_config.death_penalty_job > 0)
- sd->status.job_exp -= (double)pc_nextjobexp(sd) * (double)battle_config.death_penalty_job/10000;
+ sd->status.job_exp -= (int) ((double)pc_nextjobexp(sd) * (double)battle_config.death_penalty_job/10000);
if(battle_config.pk_mode && src && src->type==BL_PC)
- sd->status.job_exp -= (double)pc_nextjobexp(sd) * (double)battle_config.death_penalty_job/10000;
+ sd->status.job_exp -= (int) ((double)pc_nextjobexp(sd) * (double)battle_config.death_penalty_job/10000);
else if(battle_config.death_penalty_type==2 && battle_config.death_penalty_job > 0) {
if(pc_nextjobexp(sd) > 0)
- sd->status.job_exp -= (double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000;
+ sd->status.job_exp -= (int) ((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000);
if(battle_config.pk_mode && src && src->type==BL_PC)
- sd->status.job_exp -= (double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000;
+ sd->status.job_exp -= (int) ((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000);
}
if(sd->status.job_exp < 0)
sd->status.job_exp = 0;
@@ -5415,7 +4782,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
if(md && md->state.state!=MS_DEAD && md->level < 99) {
clif_misceffect(&md->bl,0);
md->level++;
- md->hp+=sd->status.max_hp*.1;
+ md->hp+=(int) (sd->status.max_hp*.1);
}
}
@@ -5450,7 +4817,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
int n = eq_n[rand()%eq_num];//該?アイテムの中からランダム
if(rand()%10000 < per){
if(sd->status.inventory[n].equip)
- pc_unequipitem(sd,n,0,BF_NORMAL);
+ pc_unequipitem(sd,n,3);
pc_dropitem(sd,n,1);
}
}
@@ -5463,7 +4830,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
|| (type == 2 && sd->status.inventory[i].equip)
|| type == 3) ){
if(sd->status.inventory[i].equip)
- pc_unequipitem(sd,i,0,BF_NORMAL);
+ pc_unequipitem(sd,i,3);
pc_dropitem(sd,i,1);
break;
}
@@ -5510,8 +4877,8 @@ int pc_readparam(struct map_session_data *sd,int type)
{
int val=0;
struct pc_base_job s_class;
-
- s_class = pc_calc_base_job(sd->status.class);
+
+ s_class = pc_calc_base_job(sd->status.class_);
nullpo_retr(0, sd);
@@ -5535,7 +4902,7 @@ int pc_readparam(struct map_session_data *sd,int type)
if(val>=24 && val < 45)
val+=3978;
else
- val= sd->status.class;
+ val= sd->status.class_;
break;
case SP_BASEJOB:
val= s_class.job;
@@ -5594,6 +4961,12 @@ int pc_readparam(struct map_session_data *sd,int type)
case SP_LUK:
val= sd->status.luk;
break;
+ case SP_KARMA: // celest
+ val = sd->status.karma;
+ break;
+ case SP_MANNER:
+ val = sd->status.manner;
+ break;
case SP_FAME:
val= sd->fame;
break;
@@ -5613,7 +4986,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
nullpo_retr(0, sd);
- s_class = pc_calc_base_job(sd->status.class);
+ s_class = pc_calc_base_job(sd->status.class_);
switch(type){
case SP_BASELEVEL:
@@ -5627,24 +5000,27 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
clif_updatestatus(sd, SP_NEXTBASEEXP);
clif_updatestatus(sd, SP_STATUSPOINT);
clif_updatestatus(sd, SP_BASEEXP);
- pc_calcstatus(sd, 0);
+ status_calc_pc(sd, 0);
pc_heal(sd, sd->status.max_hp, sd->status.max_sp);
break;
case SP_JOBLEVEL:
- if (sd->status.class == 0)
+ if (s_class.job == 0)
up_level -= 40;
- if ((sd->status.class == 23) || (sd->status.class >= 4001 && sd->status.class <= 4022))
+ // super novices can go up to 99 [celest]
+ else if (s_class.job == 23)
+ up_level += 49;
+ else if (sd->status.class_ >= 4008 && sd->status.class_ <= 4022)
up_level += 20;
if (val >= sd->status.job_level) {
if (val > up_level)val = up_level;
sd->status.skill_point += (val-sd->status.job_level);
- sd->status.job_level = val;
+ sd->status.job_level = val;
sd->status.job_exp = 0;
clif_updatestatus(sd, SP_JOBLEVEL);
clif_updatestatus(sd, SP_NEXTJOBEXP);
clif_updatestatus(sd, SP_JOBEXP);
clif_updatestatus(sd, SP_SKILLPOINT);
- pc_calcstatus(sd, 0);
+ status_calc_pc(sd, 0);
clif_misceffect(&sd->bl, 1);
} else {
sd->status.job_level = val;
@@ -5652,7 +5028,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
clif_updatestatus(sd, SP_JOBLEVEL);
clif_updatestatus(sd, SP_NEXTJOBEXP);
clif_updatestatus(sd, SP_JOBEXP);
- pc_calcstatus(sd, 0);
+ status_calc_pc(sd, 0);
}
clif_updatestatus(sd,type);
break;
@@ -5663,7 +5039,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) {
@@ -5720,6 +5110,12 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
case SP_LUK:
sd->status.luk = val;
break;
+ case SP_KARMA:
+ sd->status.karma = val;
+ break;
+ case SP_MANNER:
+ sd->status.manner = val;
+ break;
case SP_FAME:
sd->fame = val;
break;
@@ -5749,7 +5145,7 @@ int pc_heal(struct map_session_data *sd,int hp,int sp)
sp = 0;
}
- if(sd->sc_data && sd->sc_data[SC_BERSERK].timer!=-1) //バ?サ?ク中は回復させないらしい
+ if(sd->sc_count && sd->sc_data[SC_BERSERK].timer!=-1) //バ?サ?ク中は回復させないらしい
return 0;
if(hp+sd->status.hp>sd->status.max_hp)
@@ -5784,13 +5180,13 @@ int pc_heal(struct map_session_data *sd,int hp,int sp)
*/
int pc_itemheal(struct map_session_data *sd,int hp,int sp)
{
- int bonus;
+ int bonus, type = 0;
// if(battle_config.battle_log)
// printf("heal %d %d\n",hp,sp);
nullpo_retr(0, sd);
- if(sd->sc_data && sd->sc_data[SC_GOSPEL].timer!=-1) //バ?サ?ク中は回復させないらしい
+ if(sd->sc_count && sd->sc_data[SC_GOSPEL].timer!=-1) //バ?サ?ク中は回復させないらしい
return 0;
if(sd->state.potionpitcher_flag) {
@@ -5807,19 +5203,33 @@ int pc_itemheal(struct map_session_data *sd,int hp,int sp)
if(sp > 0)
sp = 0;
}
+
+ if (sd->itemid >= 501 && sd->itemid <= 505)
+ type = 1; // potions
+ else if (sd->itemid >= 507 && sd->itemid <= 510)
+ type = 2; // herbs
+ else if (sd->itemid >= 512 && sd->itemid <= 516)
+ type = 3; // fruits
+ else if (sd->itemid == 517 || sd->itemid == 528)
+ type = 4; // meat
+ else if (sd->itemid == 529 || sd->itemid == 530)
+ type = 5; // candy
+ else if (sd->itemid >= 531 && sd->itemid <= 534)
+ type = 6; // juice
+ else if (sd->itemid == 544 || sd->itemid == 551)
+ type = 7; // sashimi
+
if(hp > 0) {
- bonus = (sd->paramc[2]<<1) + 100 + pc_checkskill(sd,SM_RECOVERY)*10;
- if(bonus != 100)
- hp = hp * bonus / 100;
- bonus = 100 + pc_checkskill(sd,AM_LEARNINGPOTION)*5;
+ bonus = (sd->paramc[2]<<1) + 100 + pc_checkskill(sd,SM_RECOVERY)*10
+ + pc_checkskill(sd,AM_LEARNINGPOTION)*5;
+ if (type > 0)
+ bonus += sd->itemhealrate[type - 1];
if(bonus != 100)
hp = hp * bonus / 100;
}
if(sp > 0) {
- bonus = (sd->paramc[3]<<1) + 100 + pc_checkskill(sd,MG_SRECOVERY)*10;
- if(bonus != 100)
- sp = sp * bonus / 100;
- bonus = 100 + pc_checkskill(sd,AM_LEARNINGPOTION)*5;
+ bonus = (sd->paramc[3]<<1) + 100 + pc_checkskill(sd,MG_SRECOVERY)*10
+ + pc_checkskill(sd,AM_LEARNINGPOTION)*5;
if(bonus != 100)
sp = sp * bonus / 100;
}
@@ -5920,13 +5330,13 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
int i;
int b_class = 0;
//?生や養子の場合の元の職業を算出する
- struct pc_base_job s_class = pc_calc_base_job(sd->status.class);
-
+ struct pc_base_job s_class = pc_calc_base_job(sd->status.class_);
+
nullpo_retr(0, sd);
if (upper < 0 || upper > 2) //現在?生かどうかを判?する
upper = s_class.upper;
-
+
b_class = job; //通常職ならjobそのまんま
if (job < 23) {
if (upper == 1)
@@ -5948,7 +5358,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
if((sd->status.sex == 0 && job == 19) || (sd->status.sex == 1 && job == 20) ||
// not needed [celest]
//(sd->status.sex == 0 && job == 4020) || (sd->status.sex == 1 && job == 4021) ||
- job == 22 || sd->status.class == b_class) //♀はバ?ドになれない、♂はダンサ?になれない、結婚衣裳もお?り
+ job == 22 || sd->status.class_ == b_class) //♀はバ?ドになれない、♂はダンサ?になれない、結婚衣裳もお?り
return 1;
// check if we are changing from 1st to 2nd job
@@ -5958,12 +5368,12 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
else
sd->change_level = 40;
}
- else
- sd->change_level = 0;
+ else
+ sd->change_level = 0;
- pc_setglobalreg (sd, "jobchange_level", sd->change_level);
-
- sd->status.class = sd->view_class = b_class;
+ pc_setglobalreg (sd, "jobchange_level", sd->change_level);
+
+ sd->status.class_ = sd->view_class = b_class;
sd->status.job_level=1;
sd->status.job_exp=0;
@@ -5974,7 +5384,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
for(i=0;i<11;i++) {
if(sd->equip_index[i] >= 0)
if(!pc_isequip(sd,sd->equip_index[i]))
- pc_unequipitem(sd,sd->equip_index[i],1,BF_NORMAL); // ?備外し
+ pc_unequipitem(sd,sd->equip_index[i],2); // ?備外し
}
clif_changelook(&sd->bl,LOOK_BASE,sd->view_class); // move sprite update to prevent client crashes with incompatible equipment [Valaris]
@@ -5983,18 +5393,18 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
if(battle_config.muting_players && sd->status.manner < 0)
clif_changestatus(&sd->bl,SP_MANNER,sd->status.manner);
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
pc_checkallowskill(sd);
pc_equiplookall(sd);
clif_equiplist(sd);
if(pc_isriding(sd)) { // remove peco status if changing into invalid class [Valaris]
- if(!(pc_checkskill(sd,KN_RIDING)))
+ if(!(pc_checkskill(sd,KN_RIDING)))
pc_setoption(sd,sd->status.option|-0x0000);
if(pc_checkskill(sd,KN_RIDING)>0)
pc_setriding(sd);
}
-
+
return 0;
}
@@ -6071,7 +5481,7 @@ int pc_setoption(struct map_session_data *sd,int type)
sd->status.option=type;
clif_changeoption(&sd->bl);
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
return 0;
}
@@ -6129,23 +5539,35 @@ int pc_setriding(struct map_session_data *sd)
if((pc_checkskill(sd,KN_RIDING)>0)){ // ライディングスキル所持
pc_setoption(sd,sd->status.option|0x0020);
- if(sd->status.class==7)
- sd->status.class=sd->view_class=13;
-
- if(sd->status.class==14)
- sd->status.class=sd->view_class=21;
-
- if(sd->status.class==4008)
- sd->status.class=sd->view_class=4014;
-
- if(sd->status.class==4015)
- sd->status.class=sd->view_class=4022;
+ if(sd->status.class_==7)
+ sd->status.class_=sd->view_class=13;
+
+ if(sd->status.class_==14)
+ sd->status.class_=sd->view_class=21;
+
+ if(sd->status.class_==4008)
+ sd->status.class_=sd->view_class=4014;
+
+ if(sd->status.class_==4015)
+ sd->status.class_=sd->view_class=4022;
}
return 0;
}
/*==========================================
+ * アイテムドロップ可不可判定
+ *------------------------------------------
+ */
+int pc_candrop(struct map_session_data *sd,int item_id)
+{
+ int level;
+ if((level=pc_isGM(sd))>0 && level < battle_config.gm_can_drop_lv) // search only once [Celest]
+ return 1;
+ return 0;
+}
+
+/*==========================================
* script用??の値を?む
*------------------------------------------
*/
@@ -6178,14 +5600,7 @@ int pc_setreg(struct map_session_data *sd,int reg,int val)
}
}
sd->reg_num++;
- sd->reg = realloc(sd->reg, sizeof(*(sd->reg)) * sd->reg_num);
- if (sd->reg == NULL){
- printf("out of memory : pc_setreg\n");
- exit(1);
- }
-/* memset(sd->reg + (sd->reg_num - 1) * sizeof(*(sd->reg)), 0,
- sizeof(*(sd->reg)));
-*/
+ sd->reg = (struct script_reg *) aRealloc(sd->reg, sizeof(*(sd->reg)) * sd->reg_num);
sd->reg[i].index = reg;
sd->reg[i].data = val;
@@ -6229,7 +5644,7 @@ int pc_setregstr(struct map_session_data *sd,int reg,char *str)
return 0;
}
sd->regstr_num++;
- sd->regstr = realloc(sd->regstr, sizeof(sd->regstr[0]) * sd->regstr_num);
+ sd->regstr = (struct script_regstr *) aRealloc(sd->regstr, sizeof(sd->regstr[0]) * sd->regstr_num);
if(sd->regstr==NULL){
printf("out of memory : pc_setreg\n");
exit(1);
@@ -6271,11 +5686,18 @@ int pc_setglobalreg(struct map_session_data *sd,char *reg,int val)
nullpo_retr(0, sd);
- //PC_DIE_COUNTERがスクリプトなどで?更された時の?理
+ //PC_DIE_COUNTERがスクリプトなどで?更された暫フ?理
if(strcmp(reg,"PC_DIE_COUNTER") == 0 && sd->die_counter != val){
sd->die_counter = val;
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
+ } else if(strcmp(reg,script_config.die_event_name) == 0){
+ sd->state.event_death = val;
+ } else if(strcmp(reg,script_config.kill_event_name) == 0){
+ sd->state.event_kill = val;
+ } else if(strcmp(reg,script_config.logout_event_name) == 0){
+ sd->state.event_disconnect = val;
}
+
if(val==0){
for(i=0;i<sd->status.global_reg_num;i++){
if(strcmp(sd->status.global_reg[i].str,reg)==0){
@@ -6331,6 +5753,12 @@ int pc_setaccountreg(struct map_session_data *sd,char *reg,int val)
nullpo_retr(0, sd);
+ if (sd->status.account_reg_num == -1) {
+ if(battle_config.error_log)
+ printf("pc_setaccountreg : refusing to set until vars are received\n");
+ return 1;
+ }
+
if(val==0){
for(i=0;i<sd->status.account_reg_num;i++){
if(strcmp(sd->status.account_reg[i].str,reg)==0){
@@ -6418,29 +5846,6 @@ int pc_setaccountreg2(struct map_session_data *sd,char *reg,int val)
return 1;
}
-/*==========================================
- * 精?成功率
- *------------------------------------------
- */
-int pc_percentrefinery(struct map_session_data *sd,struct item *item)
-{
- int percent;
-
- nullpo_retr(0, item);
- percent=percentrefinery[itemdb_wlv(item->nameid)][(int)item->refine];
-
- percent += pc_checkskill(sd,BS_WEAPONRESEARCH); // 武器?究スキル所持
-
- // 確率の有?範?チェック
- if( percent > 100 ){
- percent = 100;
- }
- if( percent < 0 ){
- percent = 0;
- }
-
- return percent;
-}
/*==========================================
* イベントタイマ??理
@@ -6449,6 +5854,7 @@ int pc_percentrefinery(struct map_session_data *sd,struct item *item)
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;
@@ -6456,11 +5862,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;
}
}
- free((void *)data);
+ aFree(p);
if(i==MAX_EVENTTIMER) {
if(battle_config.error_log)
printf("pc_eventtimer: no such event timer\n");
@@ -6483,10 +5889,12 @@ 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 *)aCalloc(24,sizeof(char));
- memcpy(evname,name,24);
+ 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++;
}
return 0;
@@ -6502,12 +5910,19 @@ int pc_deleventtimer(struct map_session_data *sd,const char *name)
nullpo_retr(0, sd);
+ if (sd->eventcount <= 0)
+ 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--;
+ aFree(p);
break;
+ }
}
return 0;
@@ -6543,10 +5958,15 @@ int pc_cleareventtimer(struct map_session_data *sd)
nullpo_retr(0, sd);
+ if (sd->eventcount <= 0)
+ return 0;
+
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;
+ aFree(p);
}
return 0;
@@ -6579,7 +5999,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos)
// -- moonsoul (if player is berserk then cannot equip)
//
- if(sd->sc_data[SC_BERSERK].timer!=-1){
+ if(sd->sc_count && sd->sc_data[SC_BERSERK].timer!=-1){
clif_equipitemack(sd,n,0,0); // fail
return 0;
}
@@ -6597,7 +6017,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos)
// 二刀流?理
if ((pos==0x22) // 一?、?備要求箇所が二刀流武器かチェックする
&& (id->equip==2) // ? 手武器
- && (pc_checkskill(sd, AS_LEFT) > 0 || pc_calc_base_job2(sd->status.class) == 12) ) // 左手修?有
+ && (pc_checkskill(sd, AS_LEFT) > 0 || pc_calc_base_job2(sd->status.class_) == 12) ) // 左手修?有
{
int tpos=0;
if(sd->equip_index[8] >= 0)
@@ -6611,7 +6031,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos)
arrow=pc_search_inventory(sd,pc_checkequip(sd,9)); // Added by RoVeRT
for(i=0;i<11;i++) {
if(sd->equip_index[i] >= 0 && sd->status.inventory[sd->equip_index[i]].equip&pos) {
- pc_unequipitem(sd,sd->equip_index[i],1,BF_NORMAL);
+ pc_unequipitem(sd,sd->equip_index[i],2);
}
}
// 弓矢?備
@@ -6680,40 +6100,47 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos)
clif_changelook(&sd->bl,LOOK_SHOES,0);
pc_checkallowskill(sd); // ?備品でスキルか解除されるかチェック
- if (itemdb_look(sd->status.inventory[n].nameid) == 11 && arrow){ // Added by RoVeRT
+ if (itemdb_look(sd->status.inventory[n].nameid) == 11 && (arrow >= 0)){ // Added by RoVeRT
clif_arrowequip(sd,arrow);
sd->status.inventory[arrow].equip=32768;
}
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
if(sd->special_state.infinite_endure) {
if(sd->sc_data[SC_ENDURE].timer == -1)
- skill_status_change_start(&sd->bl,SC_ENDURE,10,1,0,0,0,0);
+ status_change_start(&sd->bl,SC_ENDURE,10,1,0,0,0,0);
}
else {
- if(sd->sc_data[SC_ENDURE].timer != -1 && sd->sc_data[SC_ENDURE].val2)
- skill_status_change_end(&sd->bl,SC_ENDURE,-1);
+ if(sd->sc_count && sd->sc_data[SC_ENDURE].timer != -1 && sd->sc_data[SC_ENDURE].val2)
+ status_change_end(&sd->bl,SC_ENDURE,-1);
}
- if(sd->sc_data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele))
- skill_status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1);
- if(sd->sc_data[SC_DANCING].timer!=-1 && (sd->status.weapon != 13 && sd->status.weapon !=14))
- skill_stop_dancing(&sd->bl,0);
+ if(sd->sc_count) {
+ if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele))
+ status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1);
+ if(sd->sc_data[SC_DANCING].timer!=-1 && (sd->status.weapon != 13 && sd->status.weapon !=14))
+ skill_stop_dancing(&sd->bl,0);
+ }
return 0;
}
/*==========================================
* ? 備した物を外す
+ * type:
+ * 0 - only unequip
+ * 1 - calculate status after unequipping
+ * 2 - force unequip
*------------------------------------------
*/
-int pc_unequipitem(struct map_session_data *sd,int n,int type, int flag)
+int pc_unequipitem(struct map_session_data *sd,int n,int flag)
{
- nullpo_retr(0, sd);
+ short hp = 0, sp = 0;
+ nullpo_retr(0, sd);
// -- moonsoul (if player is berserk then cannot unequip)
//
- if(!flag && sd->sc_data[SC_BERSERK].timer!=-1){
+ if(flag<2 && sd->sc_count && (sd->sc_data[SC_BLADESTOP].timer!=-1 || sd->sc_data[SC_BERSERK].timer!=-1)){
clif_unequipitemack(sd,n,0,0);
return 0;
}
@@ -6723,8 +6150,17 @@ int pc_unequipitem(struct map_session_data *sd,int n,int type, int flag)
if(sd->status.inventory[n].equip){
int i;
for(i=0;i<11;i++) {
- if(sd->status.inventory[n].equip & equip_pos[i])
+ if(sd->status.inventory[n].equip & equip_pos[i]) {
sd->equip_index[i] = -1;
+ if(sd->unequip_losehp[i] > 0) {
+ hp += sd->unequip_losehp[i];
+ sd->unequip_losehp[i] = 0;
+ }
+ if(sd->unequip_losesp[i] > 0) {
+ sp += sd->unequip_losesp[i];
+ sd->unequip_losesp[i] = 0;
+ }
+ }
}
if(sd->status.inventory[n].equip & 0x0002) {
sd->weapontype1 = 0;
@@ -6752,23 +6188,37 @@ int pc_unequipitem(struct map_session_data *sd,int n,int type, int flag)
if(sd->status.inventory[n].equip & 0x0040)
clif_changelook(&sd->bl,LOOK_SHOES,0);
- if(sd->sc_data[SC_BROKNWEAPON].timer != -1 && sd->status.inventory[n].equip & 0x0002 &&
- sd->status.inventory[i].attribute==1)
- skill_status_change_end(&sd->bl,SC_BROKNWEAPON,-1);
+ if(sd->sc_count) {
+ if (sd->sc_data[SC_BROKNWEAPON].timer != -1 && sd->status.inventory[n].equip & 0x0002 &&
+ sd->status.inventory[n].attribute == 1)
+ status_change_end(&sd->bl,SC_BROKNWEAPON,-1);
+ if(sd->sc_data[SC_BROKNARMOR].timer != -1 && sd->status.inventory[n].equip & 0x0010 &&
+ sd->status.inventory[n].attribute == 1)
+ status_change_end(&sd->bl,SC_BROKNARMOR,-1);
+ }
clif_unequipitemack(sd,n,sd->status.inventory[n].equip,1);
sd->status.inventory[n].equip=0;
- if(!type)
+ if(flag&1)
pc_checkallowskill(sd);
if(sd->weapontype1 == 0 && sd->weapontype2 == 0)
- skill_encchant_eremental_end(&sd->bl,-1); //武器持ち誓えは無?件で?性付?解除
+ skill_enchant_elemental_end(&sd->bl,-1); //武器持ち誓えは無?件で?性付?解除
} else {
clif_unequipitemack(sd,n,0,0);
}
- if(!type) {
- pc_calcstatus(sd,0);
- if(sd->sc_data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele))
- skill_status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1);
+
+ if(flag&1) {
+ status_calc_pc(sd,0);
+ if(sd->sc_count && sd->sc_data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele))
+ status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1);
+ }
+
+ if (hp > 0 || sp > 0) {
+ if (hp > sd->status.hp)
+ hp = sd->status.hp;
+ if (sp > sd->status.sp)
+ sp = sd->status.sp;
+ pc_heal(sd,-hp,-sp);
}
return 0;
@@ -6838,10 +6288,10 @@ int pc_checkitem(struct map_session_data *sd)
calc_flag = 1;
}
//?備制限チェック
- if(sd->status.inventory[i].equip && map[sd->bl.m].flag.pvp && (it->flag.no_equip==1 || it->flag.no_equip==3)){//PvP制限
+ if(sd->status.inventory[i].equip && map[sd->bl.m].flag.pvp && (it->flag.no_equip&1)){//PVP check for forbiden items. optimized by [Lupus]
sd->status.inventory[i].equip=0;
calc_flag = 1;
- }else if(sd->status.inventory[i].equip && map[sd->bl.m].flag.gvg && (it->flag.no_equip==2 || it->flag.no_equip==3)){//GvG制限
+ }else if(sd->status.inventory[i].equip && map[sd->bl.m].flag.gvg && (it->flag.no_equip>1)){//GvG optimized by [Lupus]
sd->status.inventory[i].equip=0;
calc_flag = 1;
}
@@ -6849,7 +6299,7 @@ int pc_checkitem(struct map_session_data *sd)
pc_setequipindex(sd);
if(calc_flag)
- pc_calcstatus(sd,2);
+ status_calc_pc(sd,2);
return 0;
}
@@ -6912,7 +6362,7 @@ int pc_calc_pvprank(struct map_session_data *sd)
nullpo_retr(0, sd);
nullpo_retr(0, m=&map[sd->bl.m]);
-
+
old=sd->pvp_rank;
if( !(m->flag.pvp) )
@@ -6958,12 +6408,12 @@ int pc_ismarried(struct map_session_data *sd)
return 0;
}
/*==========================================
- * sdがdstsdと結婚(dstsd→sdの結婚?理も同時に行う)
+ * sdがdstsdと結婚(dstsd→sdの結婚?理も同暫ノ行う)
*------------------------------------------
*/
int pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd)
{
- if(sd == NULL || dstsd == NULL || sd->status.partner_id > 0 || dstsd->status.partner_id > 0 || pc_calc_upper(sd->status.class)==2)
+ if(sd == NULL || dstsd == NULL || sd->status.partner_id > 0 || dstsd->status.partner_id > 0 || pc_calc_upper(sd->status.class_)==2)
return -1;
sd->status.partner_id=dstsd->status.char_id;
dstsd->status.partner_id=sd->status.char_id;
@@ -6971,7 +6421,7 @@ int pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd)
}
/*==========================================
- * sdが離婚(相手はsd->status.partner_idに依る)(相手も同時に離婚?結婚指輪自動?奪)
+ * sdが離婚(相手はsd->status.partner_idに依る)(相手も同暫ノ離婚?結婚指輪自動?奪)
*------------------------------------------
*/
int pc_divorce(struct map_session_data *sd)
@@ -7003,25 +6453,78 @@ int pc_divorce(struct map_session_data *sd)
}
/*==========================================
+ * sd - father dstsd - mother jasd - child
+ */
+int pc_adoption(struct map_session_data *sd,struct map_session_data *dstsd, struct map_session_data *jasd)
+{
+ int j;
+ if(sd == NULL || dstsd == NULL || jasd == NULL || sd->status.partner_id <= 0 || dstsd->status.partner_id <= 0 || sd->status.partner_id != dstsd->status.char_id || dstsd->status.partner_id != sd->status.char_id || sd->status.child > 0 || dstsd->status.child || jasd->status.father > 0 || jasd->status.mother > 0)
+ return -1;
+ jasd->status.father=sd->status.char_id;
+ jasd->status.mother=dstsd->status.char_id;
+ sd->status.child=jasd->status.char_id;
+ dstsd->status.child=jasd->status.char_id;
+ for (j=0; j < MAX_INVENTORY; j++) {
+ if(jasd->status.inventory[j].nameid>0 && jasd->status.inventory[j].equip!=0)
+ pc_unequipitem(jasd, j, 3);
+ }
+ if (pc_jobchange(jasd, 4023, 0) == 0)
+ clif_displaymessage(jasd->fd, msg_table[12]); // Your job has been changed.
+ else {
+ clif_displaymessage(jasd->fd, msg_table[155]); // Impossible to change your job.
+ return -1;
+ }
+ return 0;
+}
+
+/*==========================================
* sdの相方のmap_session_dataを返す
*------------------------------------------
*/
struct map_session_data *pc_get_partner(struct map_session_data *sd)
{
- struct map_session_data *p_sd = NULL;
- char *nick;
- if(sd == NULL || !pc_ismarried(sd))
- return NULL;
+ //struct map_session_data *p_sd = NULL;
+ //char *nick;
+ //if(sd == NULL || !pc_ismarried(sd))
+ // return NULL;
+ //nick=map_charid2nick(sd->status.partner_id);
+ //if (nick==NULL)
+ // return NULL;
+ //if((p_sd=map_nick2sd(nick)) == NULL )
+ // return NULL;
- nick=map_charid2nick(sd->status.partner_id);
+ if (sd && pc_ismarried(sd))
+ // charid2sd returns NULL if not found
+ return map_charid2sd(sd->status.partner_id);
- if (nick==NULL)
- return NULL;
+ return NULL;
+}
- if((p_sd=map_nick2sd(nick)) == NULL )
- return NULL;
+struct map_session_data *pc_get_father (struct map_session_data *sd)
+{
+ if (sd && pc_calc_upper(sd->status.class_) == 2 && sd->status.father > 0)
+ // charid2sd returns NULL if not found
+ return map_charid2sd(sd->status.father);
- return p_sd;
+ return NULL;
+}
+
+struct map_session_data *pc_get_mother (struct map_session_data *sd)
+{
+ if (sd && pc_calc_upper(sd->status.class_) == 2 && sd->status.mother > 0)
+ // charid2sd returns NULL if not found
+ return map_charid2sd(sd->status.mother);
+
+ return NULL;
+}
+
+struct map_session_data *pc_get_child (struct map_session_data *sd)
+{
+ if (sd && pc_ismarried(sd) && sd->status.child > 0)
+ // charid2sd returns NULL if not found
+ return map_charid2sd(sd->status.child);
+
+ return NULL;
}
//
@@ -7054,8 +6557,8 @@ static int pc_spheal(struct map_session_data *sd)
if(gc) {
struct guild *g;
g=guild_search(sd->status.guild_id);
- if(g && g->guild_id == gc->guild_id)
- a += a;
+ if(g && g->guild_id == gc->guild_id)
+ a += a;
} // end addition [Valaris]
return a;
@@ -7084,8 +6587,8 @@ static int pc_hpheal(struct map_session_data *sd)
if(gc) {
struct guild *g;
g=guild_search(sd->status.guild_id);
- if(g && g->guild_id == gc->guild_id)
- a += a;
+ if(g && g->guild_id == gc->guild_id)
+ a += a;
} // end addition [Valaris]
return a;
@@ -7098,7 +6601,10 @@ static int pc_natural_heal_hp(struct map_session_data *sd)
nullpo_retr(0, sd);
- if (sd->sc_data[SC_TRICKDEAD].timer != -1) // Modified by RoVeRT
+ if (sd->sc_count && sd->sc_data[SC_TRICKDEAD].timer != -1) // Modified by RoVeRT
+ return 0;
+
+ if (sd->no_regen & 1)
return 0;
if(pc_checkoverhp(sd)) {
@@ -7111,11 +6617,11 @@ static int pc_natural_heal_hp(struct map_session_data *sd)
if(sd->walktimer == -1) {
inc_num = pc_hpheal(sd);
- if( sd->sc_data[SC_TENSIONRELAX].timer!=-1 ){ // テンションリラックス
+ if(sd->sc_data[SC_TENSIONRELAX].timer!=-1 ){ // テンションリラックス
sd->hp_sub += 2*inc_num;
sd->inchealhptick += 3*natural_heal_diff_tick;
- }else{
- sd->hp_sub += inc_num;
+ } else {
+ sd->hp_sub += inc_num;
sd->inchealhptick += natural_heal_diff_tick;
}
}
@@ -7168,7 +6674,7 @@ static int pc_natural_heal_hp(struct map_session_data *sd)
return 0;
- if(sd->sc_data[SC_APPLEIDUN].timer!=-1) { // Apple of Idun
+ if(sd->sc_count && sd->sc_data[SC_APPLEIDUN].timer!=-1 && sd->sc_data[SC_BERSERK].timer==-1) { // Apple of Idun
if(sd->inchealhptick >= 6000 && sd->status.hp < sd->status.max_hp) {
bonus = skill*20;
while(sd->inchealhptick >= 6000) {
@@ -7196,8 +6702,12 @@ static int pc_natural_heal_sp(struct map_session_data *sd)
nullpo_retr(0, sd);
- if (sd->sc_data[SC_TRICKDEAD].timer != -1 || // Modified by RoVeRT
- sd->sc_data[SC_BERSERK].timer != -1)
+ if (sd->sc_count && (sd->sc_data[SC_TRICKDEAD].timer != -1 || // Modified by RoVeRT
+ sd->sc_data[SC_BERSERK].timer != -1 ||
+ sd->sc_data[SC_BLEEDING].timer != -1))
+ return 0;
+
+ if (sd->no_regen & 2)
return 0;
if(pc_checkoversp(sd)) {
@@ -7232,7 +6742,7 @@ static int pc_natural_heal_sp(struct map_session_data *sd)
if(sd->nshealsp > 0) {
if(sd->inchealsptick >= battle_config.natural_heal_skill_interval && sd->status.sp < sd->status.max_sp) {
- struct pc_base_job s_class = pc_calc_base_job(sd->status.class);
+ struct pc_base_job s_class = pc_calc_base_job(sd->status.class_);
if(sd->doridori_counter && s_class.job == 23)
bonus = sd->nshealsp*2;
else
@@ -7256,7 +6766,7 @@ static int pc_natural_heal_sp(struct map_session_data *sd)
return 0;
}
-static int pc_spirit_heal_hp(struct map_session_data *sd,int level)
+static int pc_spirit_heal_hp(struct map_session_data *sd)
{
int bonus_hp,interval = battle_config.natural_heal_skill_interval;
@@ -7296,7 +6806,7 @@ static int pc_spirit_heal_hp(struct map_session_data *sd,int level)
return 0;
}
-static int pc_spirit_heal_sp(struct map_session_data *sd,int level)
+static int pc_spirit_heal_sp(struct map_session_data *sd)
{
int bonus_sp,interval = battle_config.natural_heal_skill_interval;
@@ -7337,6 +6847,30 @@ static int pc_spirit_heal_sp(struct map_session_data *sd,int level)
return 0;
}
+static int pc_bleeding (struct map_session_data *sd)
+{
+ int interval, hp;
+
+ nullpo_retr(0, sd);
+ interval = sd->hp_loss_rate;
+ hp = sd->hp_loss_value;
+
+ sd->hp_loss_tick += natural_heal_diff_tick;
+ if(sd->hp_loss_tick >= interval) {
+ while(sd->hp_loss_tick >= interval) {
+ sd->hp_loss_tick -= interval;
+ if (sd->status.hp < hp)
+ hp = sd->status.hp;
+ if (sd->hp_loss_type == 1) {
+ clif_damage(&sd->bl,&sd->bl,gettick(),0,0,hp,0,0,0);
+ }
+ pc_heal(sd,-hp,0);
+ sd->hp_loss_tick = 0;
+ }
+ }
+ return 0;
+}
+
/*==========================================
* HP/SP 自然回復 各クライアント
*------------------------------------------
@@ -7344,33 +6878,43 @@ static int pc_spirit_heal_sp(struct map_session_data *sd,int level)
static int pc_natural_heal_sub(struct map_session_data *sd,va_list ap) {
int skill;
+ int tick;
nullpo_retr(0, sd);
+ tick = va_arg(ap,int);
// -- moonsoul (if conditions below altered to disallow natural healing if under berserk status)
if ((battle_config.natural_heal_weight_rate > 100 || sd->weight*100/sd->max_weight < battle_config.natural_heal_weight_rate) &&
- !pc_isdead(sd) &&
- !pc_ishiding(sd) &&
- !(sd->sc_data[SC_POISON].timer != -1 && sd->sc_data[SC_SLOWPOISON].timer == -1) &&
- sd->sc_data[SC_BERSERK].timer == -1 ) {
+ !pc_isdead(sd) &&
+ !pc_ishiding(sd) &&
+ //-- cannot regen for 5 minutes after using Berserk --- [Celest]
+ DIFF_TICK (tick, sd->canregen_tick)>=0 &&
+ (sd->sc_data && !(sd->sc_data[SC_POISON].timer != -1 && sd->sc_data[SC_SLOWPOISON].timer == -1) &&
+ sd->sc_data[SC_BERSERK].timer == -1 )) {
pc_natural_heal_hp(sd);
if( sd->sc_data && sd->sc_data[SC_EXTREMITYFIST].timer == -1 && //阿修羅?態ではSPが回復しない
sd->sc_data[SC_DANCING].timer == -1 && //ダンス?態ではSPが回復しない
sd->sc_data[SC_BERSERK].timer == -1 ) //バ?サ?ク?態ではSPが回復しない
pc_natural_heal_sp(sd);
+ sd->canregen_tick = tick;
} else {
sd->hp_sub = sd->inchealhptick = 0;
sd->sp_sub = sd->inchealsptick = 0;
}
if((skill = pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0 && !pc_ishiding(sd) &&
sd->sc_data[SC_POISON].timer == -1 && sd->sc_data[SC_BERSERK].timer == -1){
- pc_spirit_heal_hp(sd,skill);
- pc_spirit_heal_sp(sd,skill);
+ pc_spirit_heal_hp(sd);
+ pc_spirit_heal_sp(sd);
}
else {
sd->inchealspirithptick = 0;
sd->inchealspiritsptick = 0;
}
+ if (sd->hp_loss_value > 0)
+ pc_bleeding(sd);
+ else
+ sd->hp_loss_tick = 0;
+
return 0;
}
@@ -7382,7 +6926,7 @@ int pc_natural_heal(int tid,unsigned int tick,int id,int data)
{
natural_heal_tick = tick;
natural_heal_diff_tick = DIFF_TICK(natural_heal_tick,natural_heal_prev_tick);
- clif_foreachclient(pc_natural_heal_sub);
+ clif_foreachclient(pc_natural_heal_sub, tick);
natural_heal_prev_tick = tick;
return 0;
@@ -7412,9 +6956,10 @@ static int pc_autosave_sub(struct map_session_data *sd,va_list ap)
{
nullpo_retr(0, sd);
- if(save_flag==0 && sd->fd>last_save_fd){
- struct guild_castle *gc=NULL;
- int i;
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+
+ if(save_flag==0 && sd->fd>last_save_fd && !sd->state.waitingdisconnect){
+
// if(battle_config.save_log)
// printf("autosave %d\n",sd->fd);
// pet
@@ -7424,19 +6969,6 @@ static int pc_autosave_sub(struct map_session_data *sd,va_list ap)
chrif_save(sd);
storage_storage_save(sd);
- for(i=0;i<MAX_GUILDCASTLE;i++){
- gc=guild_castle_search(i);
- if(!gc) continue;
- if(gc->visibleG0==1) guild_castledatasave(gc->castle_id,18,gc->Ghp0);
- if(gc->visibleG1==1) guild_castledatasave(gc->castle_id,19,gc->Ghp1);
- if(gc->visibleG2==1) guild_castledatasave(gc->castle_id,20,gc->Ghp2);
- if(gc->visibleG3==1) guild_castledatasave(gc->castle_id,21,gc->Ghp3);
- if(gc->visibleG4==1) guild_castledatasave(gc->castle_id,22,gc->Ghp4);
- if(gc->visibleG5==1) guild_castledatasave(gc->castle_id,23,gc->Ghp5);
- if(gc->visibleG6==1) guild_castledatasave(gc->castle_id,24,gc->Ghp6);
- if(gc->visibleG7==1) guild_castledatasave(gc->castle_id,25,gc->Ghp7);
- }
-
save_flag=1;
last_save_fd = sd->fd;
}
@@ -7471,10 +7003,10 @@ int pc_read_gm_account(int fd)
int i = 0;
#endif
if (gm_account != NULL)
- free(gm_account);
+ aFree(gm_account);
GM_num = 0;
#ifdef TXT_ONLY
- gm_account = calloc(sizeof(struct gm_account) * ((RFIFOW(fd,2) - 4) / 5), 1);
+ gm_account = (struct gm_account *) aCallocA(sizeof(struct gm_account) * ((RFIFOW(fd,2) - 4) / 5), 1);
for (i = 4; i < RFIFOW(fd,2); i = i + 5) {
gm_account[GM_num].account_id = RFIFOL(fd,i);
gm_account[GM_num].level = (int)RFIFOB(fd,i+4);
@@ -7488,7 +7020,7 @@ int pc_read_gm_account(int fd)
}
lsql_res = mysql_store_result(&lmysql_handle);
if (lsql_res) {
- gm_account = calloc(sizeof(struct gm_account) * mysql_num_rows(lsql_res), 1);
+ gm_account = (struct gm_account *) aCallocA(sizeof(struct gm_account) * mysql_num_rows(lsql_res), 1);
while ((lsql_row = mysql_fetch_row(lsql_res))) {
gm_account[GM_num].account_id = atoi(lsql_row[0]);
gm_account[GM_num].level = atoi(lsql_row[1]);
@@ -7496,7 +7028,7 @@ int pc_read_gm_account(int fd)
GM_num++;
}
}
-
+
mysql_free_result(lsql_res);
#endif /* TXT_ONLY */
return GM_num;
@@ -7516,9 +7048,13 @@ int map_day_timer(int tid, unsigned int tick, int id, int data) { // by [yor]
strcpy(tmpstr, msg_txt(502)); // The day has arrived!
night_flag = 0; // 0=day, 1=night [Yor]
for(i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth) {
- pl_sd->opt2 &= ~STATE_BLIND;
- clif_changeoption(&pl_sd->bl);
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth) {
+ if (battle_config.night_darkness_level > 0)
+ clif_refresh (pl_sd);
+ else {
+ pl_sd->opt2 &= ~STATE_BLIND;
+ clif_changeoption(&pl_sd->bl);
+ }
clif_wis_message(pl_sd->fd, wisp_server_name, tmpstr, strlen(tmpstr)+1);
}
}
@@ -7542,7 +7078,7 @@ int map_night_timer(int tid, unsigned int tick, int id, int data) { // by [yor]
strcpy(tmpstr, msg_txt(503)); // The night has fallen...
night_flag = 1; // 0=day, 1=night [Yor]
for(i = 0; i < fd_max; i++) {
- if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth && !map[pl_sd->bl.m].flag.indoors) {
+ if (session[i] && (pl_sd = (struct map_session_data *) session[i]->session_data) && pl_sd->state.auth && !map[pl_sd->bl.m].flag.indoors) {
if (battle_config.night_darkness_level > 0)
clif_specialeffect(&pl_sd->bl, 474 + battle_config.night_darkness_level, 0);
else {
@@ -7562,8 +7098,8 @@ int map_night_timer(int tid, unsigned int tick, int id, int data) { // by [yor]
void pc_setstand(struct map_session_data *sd){
nullpo_retv(sd);
- if(sd->sc_data && sd->sc_data[SC_TENSIONRELAX].timer!=-1)
- skill_status_change_end(&sd->bl,SC_TENSIONRELAX,-1);
+ if(sd->sc_count && sd->sc_data[SC_TENSIONRELAX].timer!=-1)
+ status_change_end(&sd->bl,SC_TENSIONRELAX,-1);
sd->state.dead_sit = 0;
}
@@ -7590,7 +7126,7 @@ int pc_readdb(void)
char line[1024],*p;
// 必要??値?み?み
-
+ memset(exp_table,0,sizeof(exp_table));
fp=fopen("db/exp.txt","r");
if(fp==NULL){
printf("can't read db/exp.txt\n");
@@ -7622,93 +7158,8 @@ int pc_readdb(void)
break;
}
fclose(fp);
- printf("read db/exp.txt done\n");
-
- // JOB補正?値1
- fp=fopen("db/job_db1.txt","r");
- if(fp==NULL){
- printf("can't read db/job_db1.txt\n");
- return 1;
- }
- i=0;
- while(fgets(line, sizeof(line)-1, fp)){
- char *split[50];
- if(line[0]=='/' && line[1]=='/')
- continue;
- for(j=0,p=line;j<21 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
- if(j<21)
- continue;
- max_weight_base[i]=atoi(split[0]);
- hp_coefficient[i]=atoi(split[1]);
- hp_coefficient2[i]=atoi(split[2]);
- sp_coefficient[i]=atoi(split[3]);
- for(j=0;j<17;j++)
- aspd_base[i][j]=atoi(split[j+4]);
- i++;
-// -- moonsoul (below two lines added to accommodate high numbered new class ids)
- if(i==24)
- i=4001;
- if(i==MAX_PC_CLASS)
- break;
- }
- fclose(fp);
- printf("read db/job_db1.txt done\n");
-
- // JOBボ?ナス
- fp=fopen("db/job_db2.txt","r");
- if(fp==NULL){
- printf("can't read db/job_db2.txt\n");
- return 1;
- }
- i=0;
- while(fgets(line, sizeof(line)-1, fp)){
- if(line[0]=='/' && line[1]=='/')
- continue;
- for(j=0,p=line;j<MAX_LEVEL && p;j++){
- if(sscanf(p,"%d",&k)==0)
- break;
- job_bonus[0][i][j]=k;
- job_bonus[2][i][j]=k; //養子職のボ?ナスは分からないので?
- p=strchr(p,',');
- if(p) p++;
- }
- i++;
-// -- moonsoul (below two lines added to accommodate high numbered new class ids)
- if(i==24)
- i=4001;
- if(i==MAX_PC_CLASS)
- break;
- }
- fclose(fp);
- printf("read db/job_db2.txt done\n");
-
- // JOBボ?ナス2 ?生職用
- fp=fopen("db/job_db2-2.txt","r");
- if(fp==NULL){
- printf("can't read db/job_db2-2.txt\n");
- return 1;
- }
- i=0;
- while(fgets(line, sizeof(line)-1, fp)){
- if(line[0]=='/' && line[1]=='/')
- continue;
- for(j=0,p=line;j<MAX_LEVEL && p;j++){
- if(sscanf(p,"%d",&k)==0)
- break;
- job_bonus[1][i][j]=k;
- p=strchr(p,',');
- if(p) p++;
- }
- i++;
- if(i==MAX_PC_CLASS)
- break;
- }
- fclose(fp);
- printf("read db/job_db2-2.txt done\n");
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/exp.txt");
+ ShowStatus(tmp_output);
// スキルツリ?
memset(skill_tree,0,sizeof(skill_tree));
@@ -7720,36 +7171,41 @@ int pc_readdb(void)
while(fgets(line, sizeof(line)-1, fp)){
char *split[50];
+ int f=0, m=3;
if(line[0]=='/' && line[1]=='/')
continue;
- for(j=0,p=line;j<13 && p;j++){
+ for(j=0,p=line;j<14 && p;j++){
split[j]=p;
p=strchr(p,',');
if(p) *p++=0;
}
if(j<13)
continue;
- //i=atoi(split[0]);
+ if (j == 14) {
+ f=1; // MinJobLvl has been added
+ m++;
+ }
s_class = pc_calc_base_job(atoi(split[0]));
i = s_class.job;
u = s_class.upper;
- for(j=0;skill_tree[u][i][j].id;j++);
+ // check for bounds [celest]
+ if (i > 25 || u > 3)
+ continue;
+ for(j = 0; skill_tree[u][i][j].id && j < MAX_SKILL_TREE; j++);
+ if (j == MAX_SKILL_TREE)
+ continue;
skill_tree[u][i][j].id=atoi(split[1]);
skill_tree[u][i][j].max=atoi(split[2]);
-
- //not required - Celest
- //skill_tree[2][i][j].id=atoi(split[1]); //養子職は良く分からないので暫定
- //skill_tree[2][i][j].max=atoi(split[2]); //養子職は良く分からないので暫定
+ if (f) skill_tree[u][i][j].joblv=atoi(split[3]);
for(k=0;k<5;k++){
- skill_tree[u][i][j].need[k].id=atoi(split[k*2+3]);
- skill_tree[u][i][j].need[k].lv=atoi(split[k*2+4]);
- //skill_tree[2][i][j].need[k].id=atoi(split[k*2+3]); //養子職は良く分からないので暫定
- //skill_tree[2][i][j].need[k].lv=atoi(split[k*2+4]); //養子職は良く分からないので暫定
+ skill_tree[u][i][j].need[k].id=atoi(split[k*2+m]);
+ skill_tree[u][i][j].need[k].lv=atoi(split[k*2+m+1]);
}
}
fclose(fp);
- printf("read db/skill_tree.txt done\n");
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_tree.txt");
+ ShowStatus(tmp_output);
// ?性修正テ?ブル
for(i=0;i<4;i++)
@@ -7795,135 +7251,52 @@ int pc_readdb(void)
}
}
fclose(fp);
- printf("read db/attr_fix.txt done\n");
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/attr_fix.txt");
+ ShowStatus(tmp_output);
- // サイズ補正テ?ブル
- for(i=0;i<3;i++)
- for(j=0;j<20;j++)
- atkmods[i][j]=100;
- fp=fopen("db/size_fix.txt","r");
- if(fp==NULL){
- printf("can't read db/size_fix.txt\n");
- return 1;
- }
- i=0;
- while(fgets(line, sizeof(line)-1, fp)){
- char *split[20];
- if(line[0]=='/' && line[1]=='/')
- continue;
- if(atoi(line)<=0)
- continue;
- memset(split,0,sizeof(split));
- for(j=0,p=line;j<20 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
+ // スキルツリ?
+ memset(statp,0,sizeof(statp));
+ i=1;
+ j=45; // base points
+ fp=fopen("db/statpoint.txt","r");
+ if(fp == NULL){
+ sprintf(tmp_output,"Can't read '"CL_WHITE"%s"CL_RESET"'... Generating DB.\n","db/statpoint.txt");
+ //return 1;
+ } else {
+ while(fgets(line, sizeof(line)-1, fp)){
+ if(line[0]=='/' && line[1]=='/')
+ continue;
+ if ((j=atoi(line))<0)
+ j=0;
+ if (i >= MAX_LEVEL)
+ break;
+ statp[i]=j;
+ i++;
}
- for(j=0;j<20 && split[j];j++)
- atkmods[i][j]=atoi(split[j]);
- i++;
- }
- fclose(fp);
- printf("read db/size_fix.txt done\n");
-
- // 精?デ?タテ?ブル
- for(i=0;i<5;i++){
- for(j=0;j<10;j++)
- percentrefinery[i][j]=100;
- refinebonus[i][0]=0;
- refinebonus[i][1]=0;
- refinebonus[i][2]=10;
- }
- fp=fopen("db/refine_db.txt","r");
- if(fp==NULL){
- printf("can't read db/refine_db.txt\n");
- return 1;
+ fclose(fp);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/statpoint.txt");
}
- i=0;
- while(fgets(line, sizeof(line)-1, fp)){
- char *split[16];
- if(line[0]=='/' && line[1]=='/')
- continue;
- if(atoi(line)<=0)
- continue;
- memset(split,0,sizeof(split));
- for(j=0,p=line;j<16 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
- refinebonus[i][0]=atoi(split[0]); // 精?ボ?ナス
- refinebonus[i][1]=atoi(split[1]); // 過?精?ボ?ナス
- refinebonus[i][2]=atoi(split[2]); // 安全精?限界
- for(j=0;j<10 && split[j];j++)
- percentrefinery[i][j]=atoi(split[j+3]);
- i++;
+ // generate the remaining parts of the db if necessary
+ for (; i < MAX_LEVEL; i++) {
+ j += (i+15)/5;
+ statp[i] = j;
}
- fclose(fp); //Lupus. close this file!!!
- printf("read db/refine_db.txt done\n");
-
- return 0;
-}
-
-static int pc_calc_sigma(void)
-{
- int i,j,k;
+ ShowStatus(tmp_output);
- for(i=0;i<MAX_PC_CLASS;i++) {
- memset(hp_sigma_val[i],0,sizeof(hp_sigma_val[i]));
- for(k=0,j=2;j<=MAX_LEVEL;j++) {
- k += hp_coefficient[i]*j + 50;
- k -= k%100;
- hp_sigma_val[i][j-1] = k;
- }
- }
return 0;
}
-static void pc_statpointdb(void)
-{
- char * buf_stat;
- int i=0,j=0,k=0,l=0, end = 0;
-
- FILE *stp;
-
- stp=fopen("db/statpoint.txt","r");
-
- if(stp==NULL){
- printf("can't read db/statpoint.txt\n");
- return;
- }
-
- fseek(stp, 0, SEEK_END);
- end = ftell(stp);
- rewind(stp);
-
- buf_stat = (char *) malloc (end + 1);
- l = fread(buf_stat,1,end,stp);
- fclose(stp);
- printf("read db/statpoint.txt done (size=%d)\n",l);
-
- for(i=0;i<255;i++) {
- j=0;
- while (*(buf_stat+k)!='\n') {
- statp[i][j]=*(buf_stat+k);
- j++;k++;
- }
- statp[i][j+1]='\0';
- k++;
- }
-
- free(buf_stat);
-}
-
/*==========================================
* pc? 係初期化
*------------------------------------------
*/
+void do_final_pc(void) {
+ if (gm_account)
+ aFree(gm_account);
+ return;
+}
int do_init_pc(void) {
pc_readdb();
- pc_statpointdb();
- pc_calc_sigma();
// gm_account_db = numdb_init();
@@ -7942,16 +7315,13 @@ int do_init_pc(void) {
pc_read_gm_account(0);
#endif /* not TXT_ONLY */
- // add night/day timer (by [yor])
- add_timer_func_list(map_day_timer, "map_day_timer"); // by [yor]
- add_timer_func_list(map_night_timer, "map_night_timer"); // by [yor]
- {
+ if (battle_config.day_duration > 0 && battle_config.night_duration > 0) {
int day_duration = battle_config.day_duration;
int night_duration = battle_config.night_duration;
- if (day_duration < 60000)
- day_duration = 60000;
- if (night_duration < 60000)
- night_duration = 60000;
+ // add night/day timer (by [yor])
+ add_timer_func_list(map_day_timer, "map_day_timer"); // by [yor]
+ add_timer_func_list(map_night_timer, "map_night_timer"); // by [yor]
+
if (battle_config.night_at_start == 0) {
night_flag = 0; // 0=day, 1=night [Yor]
day_timer_tid = add_timer_interval(gettick() + day_duration + night_duration, map_day_timer, 0, 0, day_duration + night_duration);
diff --git a/src/map/pc.h b/src/map/pc.h
index 372dd72f7..6aec36d38 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -7,6 +7,9 @@
#define OPTION_MASK 0xd7b8
#define CART_MASK 0x788
+#define STATE_BLIND 0x10
+
+#define MAX_SKILL_TREE 51
#define pc_setdead(sd) ((sd)->state.dead_sit = 1)
#define pc_setsit(sd) ((sd)->state.dead_sit = 2)
@@ -37,14 +40,19 @@ int pc_authfail(int);
int pc_isequip(struct map_session_data *sd,int n);
int pc_equippoint(struct map_session_data *sd,int n);
-int pc_breakweapon(struct map_session_data *sd); // weapon breaking [Valaris]
-int pc_breakarmor(struct map_session_data *sd); // armor breaking [Valaris]
+int pc_break_equip(struct map_session_data *, unsigned short);
+#define pc_breakweapon(sd) (pc_break_equip(sd, EQP_WEAPON))
+#define pc_breakarmor(sd) (pc_break_equip(sd, EQP_ARMOR))
+#define pc_breakshield(sd) (pc_break_equip(sd, EQP_SHIELD))
+#define pc_breakhelm(sd) (pc_break_equip(sd, EQP_HELM))
int pc_checkskill(struct map_session_data *sd,int skill_id);
int pc_checkallowskill(struct map_session_data *sd);
int pc_checkequip(struct map_session_data *sd,int pos);
+int pc_calc_skilltree(struct map_session_data *sd);
int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd);
+int pc_clean_skilltree(struct map_session_data *sd);
int pc_checkoverhp(struct map_session_data*);
int pc_checkoversp(struct map_session_data*);
@@ -57,6 +65,8 @@ int pc_setpos(struct map_session_data*,char*,int,int,int);
int pc_setsavepoint(struct map_session_data*,char*,int,int);
int pc_randomwarp(struct map_session_data *sd,int type);
int pc_memo(struct map_session_data *sd,int i);
+int pc_randomwalk(struct map_session_data*,int tick);
+int pc_remove_map(struct map_session_data *sd,int clrtype);
int pc_checkadditem(struct map_session_data*,int,int);
int pc_inventoryblank(struct map_session_data*);
@@ -78,13 +88,14 @@ int pc_dropitem(struct map_session_data*,int,int);
int pc_checkweighticon(struct map_session_data *sd);
-int pc_calcstatus(struct map_session_data*,int);
-int pc_calcspeed(struct map_session_data*); // [Celest]
int pc_bonus(struct map_session_data*,int,int);
int pc_bonus2(struct map_session_data *sd,int,int,int);
int pc_bonus3(struct map_session_data *sd,int,int,int,int);
+int pc_bonus4(struct map_session_data *sd,int,int,int,int,int);
int pc_skill(struct map_session_data*,int,int,int);
+int pc_blockskill_start (struct map_session_data*,int,int); // [celest]
+
int pc_insert_card(struct map_session_data *sd,int idx_card,int idx_equip);
int pc_item_identify(struct map_session_data *sd,int idx);
@@ -117,7 +128,7 @@ int pc_resetlvl(struct map_session_data*,int type);
int pc_resetstate(struct map_session_data*);
int pc_resetskill(struct map_session_data*);
int pc_equipitem(struct map_session_data*,int,int);
-int pc_unequipitem(struct map_session_data*,int,int,int);
+int pc_unequipitem(struct map_session_data*,int,int);
int pc_checkitem(struct map_session_data*);
int pc_useitem(struct map_session_data*,int);
@@ -145,7 +156,6 @@ int pc_readaccountreg(struct map_session_data*,char*);
int pc_setaccountreg(struct map_session_data*,char*,int);
int pc_readaccountreg2(struct map_session_data*,char*);
int pc_setaccountreg2(struct map_session_data*,char*,int);
-int pc_percentrefinery(struct map_session_data *sd,struct item *item);
int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name);
int pc_deleventtimer(struct map_session_data *sd,const char *name);
@@ -158,10 +168,16 @@ int pc_calc_pvprank_timer(int tid,unsigned int tick,int id,int data);
int pc_ismarried(struct map_session_data *sd);
int pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd);
int pc_divorce(struct map_session_data *sd);
+int pc_adoption(struct map_session_data *sd,struct map_session_data *dstsd,struct map_session_data *jasd);
struct map_session_data *pc_get_partner(struct map_session_data *sd);
+struct map_session_data *pc_get_father(struct map_session_data *sd);
+struct map_session_data *pc_get_mother(struct map_session_data *sd);
+struct map_session_data *pc_get_child(struct map_session_data *sd);
+
int pc_set_gm_level(int account_id, int level);
void pc_setstand(struct map_session_data *sd);
-
+int pc_break_equip(struct map_session_data *sd, unsigned short where);
+int pc_candrop(struct map_session_data *sd,int item_id);
struct pc_base_job{
int job; //職業、ただし転生職や養子職の場合は元の職業を返す(廃プリ→プリ)
@@ -174,12 +190,15 @@ int pc_calc_base_job2(int b_class); // Celest
int pc_calc_upper(int b_class);
struct skill_tree_entry {
- int id;
- int max;
+ short id;
+ unsigned char max;
+ unsigned char joblv;
struct {
- short id,lv;
- } need[6];
-} skill_tree[3][MAX_PC_CLASS][100]; // Celest
+ short id;
+ unsigned char lv;
+ } need[5];
+}; // Celest
+extern struct skill_tree_entry skill_tree[3][25][MAX_SKILL_TREE];
int pc_read_gm_account(int fd);
int pc_setinvincibletimer(struct map_session_data *sd,int);
@@ -187,13 +206,17 @@ int pc_delinvincibletimer(struct map_session_data *sd);
int pc_addspiritball(struct map_session_data *sd,int,int);
int pc_delspiritball(struct map_session_data *sd,int,int);
+int pc_eventtimer(int tid,unsigned int tick,int id,int data); // for npc_dequeue
+
+int pc_readdb(void);
int do_init_pc(void);
+void do_final_pc(void);
enum {ADDITEM_EXIST,ADDITEM_NEW,ADDITEM_OVERAMOUNT};
// timer for night.day
-int day_timer_tid;
-int night_timer_tid;
+extern int day_timer_tid;
+extern int night_timer_tid;
int map_day_timer(int,unsigned int,int,int); // by [yor]
int map_night_timer(int,unsigned int,int,int); // by [yor]
diff --git a/src/map/pet.c b/src/map/pet.c
index 6026b1ebf..6f4713d75 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -9,6 +9,7 @@
#include "nullpo.h"
#include "malloc.h"
#include "pc.h"
+#include "status.h"
#include "map.h"
#include "intif.h"
#include "clif.h"
@@ -20,6 +21,7 @@
#include "npc.h"
#include "script.h"
#include "skill.h"
+#include "showmsg.h"
#ifdef MEMWATCH
#include "memwatch.h"
@@ -48,6 +50,8 @@ static int calc_next_walk_step(struct pet_data *pd)
{
nullpo_retr(0, pd);
+ Assert((pd->msd == 0) || (pd->msd->pd == pd));
+
if(pd->walkpath.path_pos>=pd->walkpath.path_len)
return -1;
if(pd->walkpath.path[pd->walkpath.path_pos]&1)
@@ -59,6 +63,8 @@ static int pet_performance_val(struct map_session_data *sd)
{
nullpo_retr(0, sd);
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+
if(sd->pet.intimate > 900)
return (sd->petDB->s_perfor > 0)? 4:3;
else if(sd->pet.intimate > 750)
@@ -71,6 +77,8 @@ int pet_hungry_val(struct map_session_data *sd)
{
nullpo_retr(0, sd);
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+
if(sd->pet.hungry > 90)
return 4;
else if(sd->pet.hungry > 75)
@@ -89,6 +97,8 @@ static int pet_can_reach(struct pet_data *pd,int x,int y)
nullpo_retr(0, pd);
+ Assert((pd->msd == 0) || (pd->msd->pd == pd));
+
if( pd->bl.x==x && pd->bl.y==y ) // 同じマス
return 1;
@@ -106,6 +116,8 @@ static int pet_calc_pos(struct pet_data *pd,int tx,int ty,int dir)
nullpo_retr(0, pd);
+ Assert((pd->msd == 0) || (pd->msd->pd == pd));
+
pd->to_x = tx;
pd->to_y = ty;
@@ -161,23 +173,27 @@ static int pet_attack(struct pet_data *pd,unsigned int tick,int data)
nullpo_retr(0, pd);
+ Assert((pd->msd == 0) || (pd->msd->pd == pd));
+
pd->state.state=MS_IDLE;
md=(struct mob_data *)map_id2bl(pd->target_id);
if(md == NULL || md->bl.type != BL_MOB || pd->bl.m != md->bl.m || md->bl.prev == NULL ||
- distance(pd->bl.x,pd->bl.y,md->bl.x,md->bl.y) > 13) {
+ distance(pd->bl.x,pd->bl.y,md->bl.x,md->bl.y) > 13 ||
+ (!agit_flag && md->class_ >= 1285 && md->class_ <= 1288)) // Cannot attack Guardians outside of WoE
+ {
pd->target_id=0;
return 0;
}
- mode=mob_db[pd->class].mode;
- race=mob_db[pd->class].race;
- if(mob_db[pd->class].mexp <= 0 && !(mode&0x20) && (md->option & 0x06 && race != 4 && race != 6) ) {
+ mode=mob_db[pd->class_].mode;
+ race=mob_db[pd->class_].race;
+ if(mob_db[pd->class_].mexp <= 0 && !(mode&0x20) && (md->option & 0x06 && race != 4 && race != 6) ) {
pd->target_id=0;
return 0;
}
- range = mob_db[pd->class].range + 1;
+ range = mob_db[pd->class_].range + 1;
if(distance(pd->bl.x,pd->bl.y,md->bl.x,md->bl.y) > range)
return 0;
if(battle_config.monster_attack_direction_change)
@@ -187,7 +203,7 @@ static int pet_attack(struct pet_data *pd,unsigned int tick,int data)
pd->target_lv = battle_weapon_attack(&pd->bl,&md->bl,tick,0);
- pd->attackabletime = tick + battle_get_adelay(&pd->bl);
+ pd->attackabletime = tick + status_get_adelay(&pd->bl);
pd->timer=add_timer(pd->attackabletime,pet_timer,pd->bl.id,0);
pd->state.state=MS_ATTACK;
@@ -202,11 +218,13 @@ static int pet_attack(struct pet_data *pd,unsigned int tick,int data)
static int pet_walk(struct pet_data *pd,unsigned int tick,int data)
{
int moveblock;
- int i,ctype;
+ int i;
int x,y,dx,dy;
nullpo_retr(0, pd);
+ Assert((pd->msd == 0) || (pd->msd->pd == pd));
+
pd->state.state=MS_IDLE;
if(pd->walkpath.path_pos >= pd->walkpath.path_len || pd->walkpath.path_pos != data)
return 0;
@@ -234,8 +252,7 @@ static int pet_walk(struct pet_data *pd,unsigned int tick,int data)
dx = dirx[pd->dir];
dy = diry[pd->dir];
- ctype = map_getcell(pd->bl.m,x+dx,y+dy);
- if(ctype == 1 || ctype == 5) {
+ if(map_getcell(pd->bl.m,x+dx,y+dy,CELL_CHKNOPASS)){
pet_walktoxy_sub(pd);
return 0;
}
@@ -273,6 +290,8 @@ int pet_stopattack(struct pet_data *pd)
{
nullpo_retr(0, pd);
+ Assert((pd->msd == 0) || (pd->msd->pd == pd));
+
pd->target_id=0;
if(pd->state.state == MS_ATTACK)
pet_changestate(pd,MS_IDLE,0);
@@ -290,15 +309,17 @@ int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type)
pd = sd->pd;
- if(bl && pd && bl->type == BL_MOB && sd->pet.intimate > 900 && sd->pet.hungry > 0 && pd->class != battle_get_class(bl)
+ Assert((pd->msd == 0) || (pd->msd->pd == pd));
+
+ if(bl && pd && bl->type == BL_MOB && sd->pet.intimate > 900 && sd->pet.hungry > 0 && pd->class_ != status_get_class(bl)
&& pd->state.state != MS_DELAY) {
- mode=mob_db[pd->class].mode;
- race=mob_db[pd->class].race;
+ mode=mob_db[pd->class_].mode;
+ race=mob_db[pd->class_].race;
md=(struct mob_data *)bl;
if(md->bl.type != BL_MOB || pd->bl.m != md->bl.m || md->bl.prev == NULL ||
distance(pd->bl.x,pd->bl.y,md->bl.x,md->bl.y) > 13)
return 0;
- if(mob_db[pd->class].mexp <= 0 && !(mode&0x20) && (md->option & 0x06 && race!=4 && race!=6) )
+ if(mob_db[pd->class_].mexp <= 0 && !(mode&0x20) && (md->option & 0x06 && race!=4 && race!=6) )
return 0;
if(!type) {
rate = sd->petDB->attack_rate;
@@ -331,6 +352,8 @@ int pet_changestate(struct pet_data *pd,int state,int type)
nullpo_retr(0, pd);
+ Assert((pd->msd == 0) || (pd->msd->pd == pd));
+
if(pd->timer != -1)
delete_timer(pd->timer,pet_timer);
pd->timer=-1;
@@ -368,6 +391,8 @@ static int pet_timer(int tid,unsigned int tick,int id,int data)
if(pd == NULL || pd->bl.type != BL_PET)
return 1;
+ Assert((pd->msd == 0) || (pd->msd->pd == pd));
+
if(pd->timer != tid){
if(battle_config.error_log)
printf("pet_timer %d != %d\n",pd->timer,tid);
@@ -403,6 +428,8 @@ static int pet_walktoxy_sub(struct pet_data *pd)
nullpo_retr(0, pd);
+ Assert((pd->msd == 0) || (pd->msd->pd == pd));
+
if(path_search(&wpd,pd->bl.m,pd->bl.x,pd->bl.y,pd->to_x,pd->to_y,0))
return 1;
memcpy(&pd->walkpath,&wpd,sizeof(wpd));
@@ -422,6 +449,8 @@ int pet_walktoxy(struct pet_data *pd,int x,int y)
nullpo_retr(0, pd);
+ Assert((pd->msd == 0) || (pd->msd->pd == pd));
+
if(pd->state.state == MS_WALK && path_search(&wpd,pd->bl.m,pd->bl.x,pd->bl.y,x,y,0))
return 1;
@@ -441,6 +470,8 @@ int pet_stop_walking(struct pet_data *pd,int type)
{
nullpo_retr(0, pd);
+ Assert((pd->msd == 0) || (pd->msd->pd == pd));
+
if(pd->state.state == MS_WALK || pd->state.state == MS_IDLE) {
pd->walkpath.path_len=0;
pd->to_x=pd->bl.x;
@@ -461,10 +492,13 @@ static int pet_hungry(int tid,unsigned int tick,int id,int data)
struct map_session_data *sd;
int interval,t;
+
sd=map_id2sd(id);
if(sd==NULL)
return 1;
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+
if(sd->pet_hungry_timer != tid){
if(battle_config.error_log)
printf("pet_hungry_timer %d != %d\n",sd->pet_hungry_timer,tid);
@@ -485,9 +519,9 @@ static int pet_hungry(int tid,unsigned int tick,int id,int data)
sd->pet.intimate = 0;
if(battle_config.pet_status_support && t > 0) {
if(sd->bl.prev != NULL)
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
else
- pc_calcstatus(sd,2);
+ status_calc_pc(sd,2);
}
}
clif_send_petdata(sd,1,sd->pet.intimate);
@@ -510,11 +544,11 @@ int search_petDB_index(int key,int type)
int i;
for(i=0;i<MAX_PET_DB;i++) {
- if(pet_db[i].class <= 0)
+ if(pet_db[i].class_ <= 0)
continue;
switch(type) {
case PET_CLASS:
- if(pet_db[i].class == key)
+ if(pet_db[i].class_ == key)
return i;
break;
case PET_CATCH:
@@ -556,26 +590,29 @@ int pet_remove_map(struct map_session_data *sd)
{
nullpo_retr(0, sd);
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+
if(sd->status.pet_id && sd->pd) {
struct pet_data *pd=sd->pd; // [Valaris]
if(pd->skillbonustimer!=-1) pd->skillbonustimer=-1;
- if(pd->skillbonusduration!=-1) pd->skillbonusduration=-1;
- if(pd->skilltype !=-1) pd->skilltype=-1;
- if(pd->skillval !=-1) pd->skillval=-1;
+ pd->skilltype=0;
+ pd->skillval=0;
if(pd->skilltimer!=-1) pd->skilltimer=-1;
- if(pd->skillduration!=-1) pd->skillduration=-1;
- if(pd->skillbonustype!=-1) pd->skillbonustype=-1;
- if(pd->skillbonusval!=-1) pd->skillbonusval=-1;
- if(sd->perfect_hiding==1) sd->perfect_hiding=0; // end additions
+ pd->state.skillbonus=-1;
+ pd->skillduration=0;
+ pd->skillbonustype=0;
+ pd->skillbonusval=0;
+ if(sd->perfect_hiding==1) sd->perfect_hiding=0; // end additions
pet_changestate(sd->pd,MS_IDLE,0);
if(sd->pet_hungry_timer != -1)
pet_hungry_timer_delete(sd);
clif_clearchar_area(&sd->pd->bl,0);
map_delblock(&sd->pd->bl);
+ if (sd->pd->lootitem)
+ aFree(sd->pd->lootitem);
map_deliddb(&sd->pd->bl);
- map_freeblock(sd->pd);
}
return 0;
}
@@ -598,6 +635,8 @@ int pet_performance(struct map_session_data *sd)
nullpo_retr(0, sd);
nullpo_retr(0, pd=sd->pd);
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+
pet_stop_walking(pd,2000<<8);
clif_pet_performance(&pd->bl,rand()%pet_performance_val(sd) + 1);
// ルートしたItemを落とさせる
@@ -613,8 +652,11 @@ int pet_return_egg(struct map_session_data *sd)
nullpo_retr(0, sd);
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+
if(sd->status.pet_id && sd->pd) {
- struct pet_data *pd=sd->pd;
+ // ルートしたItemを落とさせる
+ pet_lootitem_drop(sd->pd,sd);
pet_remove_map(sd);
sd->status.pet_id = 0;
sd->pd = NULL;
@@ -634,12 +676,10 @@ int pet_return_egg(struct map_session_data *sd)
}
if(battle_config.pet_status_support && sd->pet.intimate > 0) {
if(sd->bl.prev != NULL)
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
else
- pc_calcstatus(sd,2);
+ status_calc_pc(sd,2);
}
- // ルートしたItemを落とさせる
- pet_lootitem_drop(pd,sd);
intif_save_petdata(sd->status.account_id,&sd->pet);
pc_makesavestatus(sd);
@@ -659,13 +699,15 @@ int pet_data_init(struct map_session_data *sd)
nullpo_retr(1, sd);
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+
if(sd->status.account_id != sd->pet.account_id || sd->status.char_id != sd->pet.char_id ||
sd->status.pet_id != sd->pet.pet_id) {
sd->status.pet_id = 0;
return 1;
}
- i = search_petDB_index(sd->pet.class,PET_CLASS);
+ i = search_petDB_index(sd->pet.class_,PET_CLASS);
if(i < 0) {
sd->status.pet_id = 0;
return 1;
@@ -682,7 +724,7 @@ int pet_data_init(struct map_session_data *sd)
pd->bl.y = pd->to_y;
pd->bl.id = npc_get_new_npc_id();
memcpy(pd->name,sd->pet.name,24);
- pd->class = sd->pet.class;
+ pd->class_ = sd->pet.class_;
pd->equip = sd->pet.equip;
pd->dir = sd->dir;
pd->speed = sd->petDB->speed;
@@ -696,9 +738,13 @@ int pet_data_init(struct map_session_data *sd)
pd->move_fail_count = 0;
pd->next_walktime = pd->attackabletime = pd->last_thinktime = gettick();
pd->msd = sd;
-
+
map_addiddb(&pd->bl);
+ // initialise
+ pd->state.skillbonus = -1;
+ run_script(pet_db[i].script,0,sd->bl.id,0);
+
if(sd->pet_hungry_timer != -1)
pet_hungry_timer_delete(sd);
if(battle_config.pet_hungry_delay_rate != 100)
@@ -719,6 +765,8 @@ int pet_birth_process(struct map_session_data *sd)
{
nullpo_retr(1, sd);
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+
if(sd->status.pet_id && sd->pet.incuvate == 1) {
sd->status.pet_id = 0;
return 1;
@@ -747,6 +795,8 @@ int pet_birth_process(struct map_session_data *sd)
clif_pet_equip(sd->pd,sd->pet.equip);
clif_send_petstatus(sd);
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+
return 0;
}
@@ -766,7 +816,7 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag)
pet_birth_process(sd);
else {
pet_data_init(sd);
- if(sd->bl.prev != NULL) {
+ if(sd->pd && sd->bl.prev != NULL) {
map_addblock(&sd->pd->bl);
clif_spawnpet(sd->pd);
clif_send_petdata(sd,0,0);
@@ -777,9 +827,9 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag)
}
if(battle_config.pet_status_support && sd->pet.intimate > 0) {
if(sd->bl.prev != NULL)
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
else
- pc_calcstatus(sd,2);
+ status_calc_pc(sd,2);
}
return 0;
@@ -823,27 +873,28 @@ int pet_catch_process2(struct map_session_data *sd,int target_id)
return 1;
}
- i = search_petDB_index(md->class,PET_CLASS);
- if(md == NULL || md->bl.type != BL_MOB || md->bl.prev == NULL || i < 0 || sd->catch_target_class != md->class) {
+ i = search_petDB_index(md->class_,PET_CLASS);
+ if(md == NULL || md->bl.type != BL_MOB || md->bl.prev == NULL || i < 0 || sd->catch_target_class != md->class_) {
clif_pet_rulet(sd,0);
return 1;
}
//target_idによる敵→卵判定
// if(battle_config.etc_log)
-// printf("mob_id = %d, mob_class = %d\n",md->bl.id,md->class);
+// printf("mob_id = %d, mob_class = %d\n",md->bl.id,md->class_);
//成功の場合
- pet_catch_rate = (pet_db[i].capture + (sd->status.base_level - mob_db[md->class].lv)*30 + sd->paramc[5]*20)*(200 - md->hp*100/mob_db[md->class].max_hp)/100;
+ pet_catch_rate = (pet_db[i].capture + (sd->status.base_level - mob_db[md->class_].lv)*30 + sd->paramc[5]*20)*(200 - md->hp*100/mob_db[md->class_].max_hp)/100;
if(pet_catch_rate < 1) pet_catch_rate = 1;
if(battle_config.pet_catch_rate != 100)
pet_catch_rate = (pet_catch_rate*battle_config.pet_catch_rate)/100;
if(rand()%10000 < pet_catch_rate) {
- mob_catch_delete(md,0);
+ mob_remove_map(md,0);
+ mob_setdelayspawn(md->bl.id);
clif_pet_rulet(sd,1);
// if(battle_config.etc_log)
// printf("rulet success %d\n",target_id);
- intif_create_pet(sd->status.account_id,sd->status.char_id,pet_db[i].class,mob_db[pet_db[i].class].lv,
+ intif_create_pet(sd->status.account_id,sd->status.char_id,pet_db[i].class_,mob_db[pet_db[i].class_].lv,
pet_db[i].EggID,0,pet_db[i].intimate,100,0,1,pet_db[i].jname);
}
else
@@ -869,7 +920,7 @@ int pet_get_egg(int account_id,int pet_id,int flag)
tmp_item.nameid = pet_db[i].EggID;
tmp_item.identify = 1;
tmp_item.card[0] = 0xff00;
- *((long *)(&tmp_item.card[1])) = pet_id;
+ tmp_item.card[1] = pet_id;
tmp_item.card[3] = sd->pet.rename_flag;
if((ret = pc_additem(sd,&tmp_item,1))) {
clif_additem(sd,0,0,ret);
@@ -913,7 +964,7 @@ int pet_change_name(struct map_session_data *sd,char *name)
nullpo_retr(1, sd);
- if(sd->pet.rename_flag == 1 && battle_config.pet_rename == 0)
+ if((sd->pd == NULL) || (sd->pet.rename_flag == 1 && battle_config.pet_rename == 0))
return 1;
for(i=0;i<24 && name[i];i++){
@@ -951,7 +1002,7 @@ int pet_equipitem(struct map_session_data *sd,int index)
else {
pc_delitem(sd,index,1,0);
sd->pet.equip = sd->pd->equip = nameid;
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
clif_pet_equip(sd->pd,nameid);
}
@@ -972,7 +1023,7 @@ int pet_unequipitem(struct map_session_data *sd)
nameid = sd->pet.equip;
sd->pet.equip = sd->pd->equip = 0;
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
clif_pet_equip(sd->pd,0);
memset(&tmp_item,0,sizeof(tmp_item));
tmp_item.nameid = nameid;
@@ -991,6 +1042,8 @@ int pet_food(struct map_session_data *sd)
nullpo_retr(1, sd);
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+
if(sd->petDB == NULL)
return 1;
i=pc_search_inventory(sd,sd->petDB->FoodID);
@@ -1023,9 +1076,9 @@ int pet_food(struct map_session_data *sd)
sd->pet.intimate = 0;
if(battle_config.pet_status_support && t > 0) {
if(sd->bl.prev != NULL)
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
else
- pc_calcstatus(sd,2);
+ status_calc_pc(sd,2);
}
}
else if(sd->pet.intimate > 1000)
@@ -1048,7 +1101,9 @@ static int pet_randomwalk(struct pet_data *pd,int tick)
nullpo_retr(0, pd);
- speed = battle_get_speed(&pd->bl);
+ Assert((pd->msd == 0) || (pd->msd->pd == pd));
+
+ speed = status_get_speed(&pd->bl);
if(DIFF_TICK(pd->next_walktime,tick) < 0){
int i,x,y,c,d=12-pd->move_fail_count;
@@ -1057,7 +1112,7 @@ static int pet_randomwalk(struct pet_data *pd,int tick)
int r=rand();
x=pd->bl.x+r%(d*2+1)-d;
y=pd->bl.y+r/(d*2+1)%(d*2+1)-d;
- if((c=map_getcell(pd->bl.m,x,y))!=1 && c!=5 && pet_walktoxy(pd,x,y)==0){
+ if((map_getcell(pd->bl.m,x,y,CELL_CHKPASS))&&( pet_walktoxy(pd,x,y)==0)){
pd->move_fail_count=0;
break;
}
@@ -1065,7 +1120,7 @@ static int pet_randomwalk(struct pet_data *pd,int tick)
pd->move_fail_count++;
if(pd->move_fail_count>1000){
if(battle_config.error_log)
- printf("PET cant move. hold position %d, class = %d\n",pd->bl.id,pd->class);
+ printf("PET cant move. hold position %d, class = %d\n",pd->bl.id,pd->class_);
pd->move_fail_count=0;
pet_changestate(pd,MS_DELAY,60000);
return 0;
@@ -1105,6 +1160,8 @@ static int pet_ai_sub_hard(struct pet_data *pd,unsigned int tick)
sd = pd->msd;
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+
if(pd->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL)
return 0;
@@ -1136,22 +1193,22 @@ static int pet_ai_sub_hard(struct pet_data *pd,unsigned int tick)
pet_randomwalk(pd,tick);
}
else if(pd->target_id - MAX_FLOORITEM > 0) {
- mode=mob_db[pd->class].mode;
- race=mob_db[pd->class].race;
+ mode=mob_db[pd->class_].mode;
+ race=mob_db[pd->class_].race;
md=(struct mob_data *)map_id2bl(pd->target_id);
if(md == NULL || md->bl.type != BL_MOB || pd->bl.m != md->bl.m || md->bl.prev == NULL ||
distance(pd->bl.x,pd->bl.y,md->bl.x,md->bl.y) > 13)
pet_unlocktarget(pd);
- else if(mob_db[pd->class].mexp <= 0 && !(mode&0x20) && (md->option & 0x06 && race!=4 && race!=6) )
+ else if(mob_db[pd->class_].mexp <= 0 && !(mode&0x20) && (md->option & 0x06 && race!=4 && race!=6) )
pet_unlocktarget(pd);
- else if(!battle_check_range(&pd->bl,&md->bl,mob_db[pd->class].range)){
+ else if(!battle_check_range(&pd->bl,&md->bl,mob_db[pd->class_].range)){
if(pd->timer != -1 && pd->state.state == MS_WALK && distance(pd->to_x,pd->to_y,md->bl.x,md->bl.y) < 2)
return 0;
if( !pet_can_reach(pd,md->bl.x,md->bl.y))
pet_unlocktarget(pd);
else {
i=0;
- pd->speed = battle_get_speed(&pd->bl);
+ pd->speed = status_get_speed(&pd->bl);
do {
if(i==0) { // 最初はAEGISと同じ方法で検索
dx=md->bl.x - pd->bl.x;
@@ -1235,14 +1292,14 @@ static int pet_ai_sub_hard(struct pet_data *pd,unsigned int tick)
else {
if(dist <= 3 || (pd->timer != -1 && pd->state.state == MS_WALK && distance(pd->to_x,pd->to_y,sd->bl.x,sd->bl.y) < 3) )
return 0;
- pd->speed = battle_get_speed(&pd->bl);
+ pd->speed = status_get_speed(&pd->bl);
pet_calc_pos(pd,sd->bl.x,sd->bl.y,sd->dir);
if(pet_walktoxy(pd,pd->to_x,pd->to_y))
pet_randomwalk(pd,tick);
}
}
else {
- pd->speed = battle_get_speed(&pd->bl);
+ pd->speed = status_get_speed(&pd->bl);
if(pd->state.state == MS_ATTACK)
pet_stopattack(pd);
pet_randomwalk(pd,tick);
@@ -1326,13 +1383,12 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd)
clif_additem(sd,0,0,flag);
map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
}
- free(ditem);
+ aFree(ditem);
}
else
add_timer(gettick()+540+i,pet_delay_item_drop2,(int)ditem,0);
}
- pd->lootitem=NULL;
- pd->lootitem=(struct item *)aCalloc(PETLOOT_SIZE,sizeof(struct item));
+ memset(pd->lootitem,0,LOOTITEM_SIZE * sizeof(struct item));
pd->lootitem_count = 0;
pd->lootitem_weight = 0;
pd->lootitem_timer = gettick()+10000; // 10*1000msの間拾わない
@@ -1349,7 +1405,7 @@ int pet_delay_item_drop2(int tid,unsigned int tick,int id,int data)
map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
- free(ditem);
+ aFree(ditem);
return 0;
}
@@ -1357,29 +1413,13 @@ int pet_delay_item_drop2(int tid,unsigned int tick,int id,int data)
* pet bonus giving skills [Valaris]
*------------------------------------------
*/
-
-int pet_skill_bonus(struct map_session_data *sd,struct pet_data *pd,int type,int val,int duration,int timer,int data)
-{
- if(pd==NULL || sd==NULL)
- return 1;
-
- pd->skillbonustype=type;
- pd->skillbonusval=val;
- pd->skillduration=duration;
- pd->skilltimer=timer;
-
- pd->skillbonustimer=add_timer(gettick()+pd->skilltimer*1000,pet_skill_bonus_timer,sd->bl.id,0);
-
- return 0;
-
-}
-
int pet_skill_bonus_timer(int tid,unsigned int tick,int id,int data)
{
- struct map_session_data *sd=(struct map_session_data*)map_id2bl(id);
+ struct map_session_data *sd=map_id2sd(id);
struct pet_data *pd;
+ int timer = 0;
- if(sd==NULL || sd->bl.type!=BL_PC)
+ if(sd==NULL)
return 1;
pd=sd->pd;
@@ -1390,38 +1430,26 @@ int pet_skill_bonus_timer(int tid,unsigned int tick,int id,int data)
if(pd->skillbonustimer != tid)
return 0;
- pd->skillbonustimer=-1;
-
- pc_bonus(sd,pd->skillbonustype,pd->skillbonusval);
- if(pd->skillbonustype < 56) clif_updatestatus(sd,pd->skillbonustype);
- pd->skillbonusduration=add_timer(gettick()+pd->skillduration*1000,pet_skill_bonus_duration,sd->bl.id,0);
-
- return 0;
-}
-
-int pet_skill_bonus_duration(int tid,unsigned int tick,int id,int data)
-{
- struct map_session_data *sd=(struct map_session_data*)map_id2bl(id);
- struct pet_data *pd;
-
- if(sd==NULL || sd->bl.type!=BL_PC)
- return 1;
-
- pd=sd->pd;
-
- if(pd==NULL || pd->bl.type!=BL_PET)
- return 1;
-
- if(pd->skillbonusduration != tid)
- return 0;
-
- pd->skillbonusduration=-1;
+ // determine the time for the next timer
+ if (pd->state.skillbonus == 0) {
+ // pet bonuses are not active at the moment, so,
+ pd->state.skillbonus = 1;
+ timer = pd->skillduration; // the duration for pet bonuses to be in effect
+ } else if (pd->state.skillbonus == 1) {
+ // pet bonuses are already active, so,
+ pd->state.skillbonus = 0;
+ timer = pd->skilltimer; // the duration which pet bonuses will be reactivated again
+ }
- pc_bonus(sd,pd->skillbonustype,-pd->skillbonusval);
- if(pd->skillbonustype < 56) clif_updatestatus(sd,pd->skillbonustype);
+ if (pd->state.skillbonus == 1 && sd->petDB)
+ run_script(sd->petDB->script,0,sd->bl.id,0);
- pet_skill_bonus(sd,pd,pd->skillbonustype,pd->skillbonusval,pd->skillduration,pd->skilltimer,0);
+ // add/remove our bonuses, which will be handled by sd->petbonus[]
+ status_calc_pc(sd, 0);
+ // wait for the next timer
+ if (timer) pd->skillbonustimer=add_timer(gettick()+timer,pet_skill_bonus_timer,sd->bl.id,0);
+
return 0;
}
@@ -1442,7 +1470,7 @@ int pet_recovery_timer(int tid,unsigned int tick,int id,int data)
return 0;
if(sd->sc_data[pd->skilltype].timer != -1)
- skill_status_change_end(&sd->bl,pd->skilltype,-1);
+ status_change_end(&sd->bl,pd->skilltype,-1);
pd->skillbonustimer=add_timer(gettick()+pd->skilltimer*1000,pet_recovery_timer,sd->bl.id,0);
@@ -1493,7 +1521,7 @@ int pet_mag_timer(int tid,unsigned int tick,int id,int data)
if(sd->status.hp < sd->status.max_hp * pd->skilltype/100 && sd->status.sp < sd->status.max_sp * pd->skillduration/100) {
clif_skill_nodamage(&pd->bl,&sd->bl,PR_MAGNIFICAT,pd->skillval,1);
- skill_status_change_start(&sd->bl,SkillStatusChangeTable[PR_MAGNIFICAT],pd->skillval,0,0,0,skill_get_time(PR_MAGNIFICAT,pd->skillval),0 );
+ status_change_start(&sd->bl,SkillStatusChangeTable[PR_MAGNIFICAT],pd->skillval,0,0,0,skill_get_time(PR_MAGNIFICAT,pd->skillval),0 );
}
pd->skillbonustimer=add_timer(gettick()+pd->skilltimer*1000,pet_mag_timer,sd->bl.id,0);
@@ -1527,19 +1555,22 @@ int pet_skillattack_timer(int tid,unsigned int tick,int id,int data)
}
if(md && rand()%100 < sd->pet.intimate*pd->skilltimer/100 ) {
- if(pd->skilltype==6 || pd->skilltype==176) {
+ switch(pd->skilltype)
+ {
+ case SM_PROVOKE:
+ //case NPC_POISON: poison is not handled there
skill_castend_nodamage_id(&pd->bl,&md->bl,pd->skilltype,pd->skillval,tick,0);
- }
-
- else if(pd->skilltype==110){
+ break;
+ case BS_HAMMERFALL:
skill_castend_pos2(&pd->bl,md->bl.x,md->bl.y,pd->skilltype,pd->skillval,tick,0);
- }
-
- else if(pd->skilltype==91) {
+ break;
+ case WZ_HEAVENDRIVE:
skill_castend_pos2(&pd->bl,md->bl.x,md->bl.y,pd->skilltype,pd->skillval+rand()%100,tick,0);
- }
- else
+ break;
+ default:
skill_castend_damage_id(&pd->bl,&md->bl,pd->skilltype,pd->skillval,tick,0);
+ break;
+ }
pd->skillbonustimer=add_timer(gettick()+1000,pet_skillattack_timer,sd->bl.id,0);
return 0;
}
@@ -1557,9 +1588,11 @@ int read_petdb()
{
FILE *fp;
char line[1024];
- int i;
+ int nameid,i,k;
int j=0;
+ int lines;
char *filename[]={"db/pet_db.txt","db/pet_db2.txt"};
+ char *str[32],*p,*np;
memset(pet_db,0,sizeof(pet_db));
for(i=0;i<2;i++){
@@ -1570,20 +1603,21 @@ int read_petdb()
printf("can't read %s\n",filename[i]);
return -1;
}
+ lines = 0;
while(fgets(line,1020,fp)){
- int nameid,i;
- char *str[32],*p,*np;
+
+ lines++;
if(line[0] == '/' && line[1] == '/')
continue;
- for(i=0,p=line;i<20;i++){
+ for(k=0,p=line;k<20;k++){
if((np=strchr(p,','))!=NULL){
- str[i]=p;
+ str[k]=p;
*np=0;
p=np+1;
} else {
- str[i]=p;
+ str[k]=p;
p+=strlen(p);
}
}
@@ -1593,7 +1627,7 @@ int read_petdb()
continue;
//MobID,Name,JName,ItemID,EggID,AcceID,FoodID,"Fullness (1回の餌での満腹度増加率%)","HungryDeray (/min)","R_Hungry (空腹時餌やり親密度増加率%)","R_Full (とても満腹時餌やり親密度減少率%)","Intimate (捕獲時親密度%)","Die (死亡時親密度減少率%)","Capture (捕獲率%)",(Name)
- pet_db[j].class = nameid;
+ pet_db[j].class_ = nameid;
memcpy(pet_db[j].name,str[1],24);
memcpy(pet_db[j].jname,str[2],24);
pet_db[j].itemID=atoi(str[3]);
@@ -1618,11 +1652,12 @@ int read_petdb()
pet_db[j].script = NULL;
if((np=strchr(p,'{'))==NULL)
continue;
- pet_db[j].script = parse_script(np,0);
+ pet_db[j].script = parse_script((unsigned char *) np,lines);
j++;
}
fclose(fp);
- printf("read %s done (count=%d)\n",filename[i],j);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' pets in '"CL_WHITE"%s"CL_RESET"'.\n",j,filename[i]);
+ ShowStatus(tmp_output);
}
return 0;
}
@@ -1639,7 +1674,6 @@ int do_init_pet(void)
add_timer_func_list(pet_hungry,"pet_hungry");
add_timer_func_list(pet_ai_hard,"pet_ai_hard");
add_timer_func_list(pet_skill_bonus_timer,"pet_skill_bonus_timer"); // [Valaris]
- add_timer_func_list(pet_skill_bonus_duration,"pet_skill_bonus_duration"); // [Valaris]
add_timer_func_list(pet_recovery_timer,"pet_recovery_timer"); // [Valaris]
add_timer_func_list(pet_mag_timer,"pet_mag_timer"); // [Valaris]
add_timer_func_list(pet_heal_timer,"pet_heal_timer"); // [Valaris]
@@ -1649,3 +1683,12 @@ int do_init_pet(void)
return 0;
}
+int do_final_pet(void) {
+ int i;
+ for(i = 0;i < MAX_PET_DB; i++) {
+ if(pet_db[i].script) {
+ aFree(pet_db[i].script);
+ }
+ }
+ return 0;
+}
diff --git a/src/map/pet.h b/src/map/pet.h
index 365a4490f..4d81583b1 100644
--- a/src/map/pet.h
+++ b/src/map/pet.h
@@ -2,11 +2,11 @@
#ifndef _PET_H_
#define _PET_H_
-#define MAX_PET_DB 100
+#define MAX_PET_DB 300
#define PETLOOT_SIZE 20 // [Valaris]
struct pet_db {
- int class;
+ int class_;
char name[24],jname[24];
int itemID;
int EggID;
@@ -55,15 +55,15 @@ int pet_food(struct map_session_data *sd);
int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd);
int pet_delay_item_drop2(int tid,unsigned int tick,int id,int data);
int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap);
-int pet_skill_bonus(struct map_session_data *sd,struct pet_data *pd,int type,int val,int duration,int timer,int data);
int pet_skill_bonus_timer(int tid,unsigned int tick,int id,int data); // [Valaris]
-int pet_skill_bonus_duration(int tid,unsigned int tick,int id,int data); // [Valaris]
int pet_recovery_timer(int tid,unsigned int tick,int id,int data); // [Valaris]
int pet_mag_timer(int tid,unsigned int tick,int id,int data); // [Valaris]
int pet_heal_timer(int tid,unsigned int tick,int id,int data); // [Valaris]
int pet_skillattack_timer(int tid,unsigned int tick,int id,int data); // [Valaris]
+int read_petdb();
int do_init_pet(void);
+int do_final_pet(void);
#endif
diff --git a/src/map/script.c b/src/map/script.c
index f198d42fe..9602f3505 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -14,52 +14,58 @@
#include <time.h>
-#include "socket.h"
-#include "timer.h"
-#include "malloc.h"
-#include "lock.h"
+#include "../common/socket.h"
+#include "../common/timer.h"
+#include "../common/malloc.h"
+#include "../common/lock.h"
+#include "../common/db.h"
#include "map.h"
#include "clif.h"
#include "chrif.h"
#include "itemdb.h"
#include "pc.h"
+#include "status.h"
#include "script.h"
#include "storage.h"
#include "mob.h"
#include "npc.h"
#include "pet.h"
#include "intif.h"
-#include "db.h"
#include "skill.h"
#include "chat.h"
#include "battle.h"
#include "party.h"
#include "guild.h"
-#include "lock.h"
#include "atcommand.h"
#include "log.h"
+#include "showmsg.h"
#ifdef MEMWATCH
#include "memwatch.h"
#endif
#define SCRIPT_BLOCK_SIZE 256
+
+#define FETCH(n, t) \
+ if(st->end>st->start+(n)) \
+ (t)=conv_num(st,&(st->stack->stack_data[st->start+(n)]));
+
enum { LABEL_NEXTLINE=1,LABEL_START };
-static unsigned char * script_buf;
+static unsigned char * script_buf = NULL;
static int script_pos,script_size;
char *str_buf;
int str_pos,str_size;
-static struct {
+static struct str_data_struct {
int type;
int str;
int backpatch;
int label;
- int (*func)();
+ int (*func)(struct script_state *);
int val;
int next;
-} *str_data;
+} *str_data = NULL;
int str_num=LABEL_START,str_data_size;
int str_hash[16];
@@ -78,17 +84,13 @@ struct dbt* script_get_userfunc_db(){ if(!userfunc_db) userfunc_db=strdb_init(50
int scriptlabel_final(void *k,void *d,va_list ap){ return 0; }
static char pos[11][100] = {"頭","体","左手","右手","ローブ","靴","アクセサリー1","アクセサリー2","頭2","頭3","装着していない"};
-static struct Script_Config {
- int warn_func_no_comma;
- int warn_cmd_no_comma;
- int warn_func_mismatch_paramnum;
- int warn_cmd_mismatch_paramnum;
- int check_cmdcount;
- int check_gotocount;
-} script_config;
+struct Script_Config script_config;
+
static int parse_cmd_if=0;
static int parse_cmd;
+extern int current_equip_item_index; //for New CARS Scripts. It contains Inventory Index of the EQUIP_SCRIPT caller item. [Lupus]
+
/*==========================================
* ローカルプロトタイプ宣言 (必要な物のみ)
*------------------------------------------
@@ -155,6 +157,7 @@ int buildin_statusup2(struct script_state *st);
int buildin_bonus(struct script_state *st);
int buildin_bonus2(struct script_state *st);
int buildin_bonus3(struct script_state *st);
+int buildin_bonus4(struct script_state *st);
int buildin_skill(struct script_state *st);
int buildin_addtoskill(struct script_state *st); // [Valaris]
int buildin_guildskill(struct script_state *st);
@@ -193,6 +196,8 @@ int buildin_stopnpctimer(struct script_state *st);
int buildin_startnpctimer(struct script_state *st);
int buildin_setnpctimer(struct script_state *st);
int buildin_getnpctimer(struct script_state *st);
+int buildin_attachnpctimer(struct script_state *st); // [celest]
+int buildin_detachnpctimer(struct script_state *st); // [celest]
int buildin_announce(struct script_state *st);
int buildin_mapannounce(struct script_state *st);
int buildin_areaannounce(struct script_state *st);
@@ -250,6 +255,9 @@ int buildin_failedremovecards(struct script_state *st);
int buildin_marriage(struct script_state *st);
int buildin_wedding_effect(struct script_state *st);
int buildin_divorce(struct script_state *st);
+int buildin_ispartneron(struct script_state *st); // MouseJstr
+int buildin_getpartnerid(struct script_state *st); // MouseJstr
+int buildin_warppartner(struct script_state *st); // MouseJstr
int buildin_getitemname(struct script_state *st);
int buildin_makepet(struct script_state *st);
int buildin_getexp(struct script_state *st);
@@ -259,6 +267,7 @@ int buildin_clearitem(struct script_state *st);
int buildin_classchange(struct script_state *st);
int buildin_misceffect(struct script_state *st);
int buildin_soundeffect(struct script_state *st);
+int buildin_soundeffectall(struct script_state *st);
int buildin_setcastledata(struct script_state *st);
int buildin_mapwarp(struct script_state *st);
int buildin_inittimer(struct script_state *st);
@@ -274,6 +283,7 @@ int buildin_petloot(struct script_state *st); // pet looting [Valaris]
int buildin_petheal(struct script_state *st); // pet healing [Valaris]
int buildin_petmag(struct script_state *st); // pet magnificat [Valaris]
int buildin_petskillattack(struct script_state *st); // pet skill attacks [Valaris]
+int buildin_skilleffect(struct script_state *st); // skill effects [Celest]
int buildin_npcskilleffect(struct script_state *st); // skill effects for npcs [Valaris]
int buildin_specialeffect(struct script_state *st); // special effect script [Valaris]
int buildin_specialeffect2(struct script_state *st); // special effect script [Valaris]
@@ -289,6 +299,28 @@ int buildin_npcspeed(struct script_state *st); // [Valaris]
int buildin_npcwalkto(struct script_state *st); // [Valaris]
int buildin_npcstop(struct script_state *st); // [Valaris]
int buildin_getmapxy(struct script_state *st); //get map position for player/npc/pet/mob by Lorky [Lupus]
+int buildin_checkoption1(struct script_state *st); // [celest]
+int buildin_checkoption2(struct script_state *st); // [celest]
+int buildin_guildgetexp(struct script_state *st); // [celest]
+int buildin_skilluseid(struct script_state *st); // originally by Qamera [celest]
+int buildin_skillusepos(struct script_state *st); // originally by Qamera [celest]
+int buildin_logmes(struct script_state *st); // [Lupus]
+int buildin_summon(struct script_state *st); // [celest]
+int buildin_isnight(struct script_state *st); // [celest]
+int buildin_isday(struct script_state *st); // [celest]
+int buildin_isequipped(struct script_state *st); // [celest]
+int buildin_isequippedcnt(struct script_state *st); // [celest]
+int buildin_cardscnt(struct script_state *st); // [Lupus]
+int buildin_getrefine(struct script_state *st); // [celest]
+int buildin_getusersname(struct script_state *st); //jA commands added [Lupus]
+int buildin_dispbottom(struct script_state *st);
+int buildin_recovery(struct script_state *st);
+int buildin_getpetinfo(struct script_state *st);
+int buildin_checkequipedcard(struct script_state *st);
+int buildin_globalmes(struct script_state *st);
+int buildin_jump_zero(struct script_state *st);
+int buildin_select(struct script_state *st);
+int buildin_getmapmobs(struct script_state *st); //jA addition end
void push_val(struct script_stack *stack,int type,int val);
@@ -297,8 +329,15 @@ int run_func(struct script_state *st);
int mapreg_setreg(int num,int val);
int mapreg_setregstr(int num,const char *str);
+#ifdef PCRE_SUPPORT
+int buildin_defpattern(struct script_state *st); // MouseJstr
+int buildin_activatepset(struct script_state *st); // MouseJstr
+int buildin_deactivatepset(struct script_state *st); // MouseJstr
+int buildin_deletepset(struct script_state *st); // MouseJstr
+#endif
+
struct {
- int (*func)();
+ int (*func)(struct script_state *);
char *name;
char *arg;
} buildin_func[]={
@@ -363,6 +402,7 @@ struct {
{buildin_bonus,"bonus","ii"},
{buildin_bonus2,"bonus2","iii"},
{buildin_bonus3,"bonus3","iiii"},
+ {buildin_bonus4,"bonus4","iiiii"},
{buildin_skill,"skill","ii*"},
{buildin_addtoskill,"addtoskill","ii*"}, // [Valaris]
{buildin_guildskill,"guildskill","ii"},
@@ -403,6 +443,8 @@ struct {
{buildin_startnpctimer,"startnpctimer","*"},
{buildin_setnpctimer,"setnpctimer","*"},
{buildin_getnpctimer,"getnpctimer","i*"},
+ {buildin_attachnpctimer,"attachnpctimer","*"}, // attached the player id to the npc timer [Celest]
+ {buildin_detachnpctimer,"detachnpctimer","*"}, // detached the player id from the npc timer [Celest]
{buildin_announce,"announce","si"},
{buildin_mapannounce,"mapannounce","ssi"},
{buildin_areaannounce,"areaannounce","siiiisi"},
@@ -460,7 +502,10 @@ struct {
{buildin_failedremovecards,"failedremovecards","ii"},
{buildin_marriage,"marriage","s"},
{buildin_wedding_effect,"wedding",""},
- {buildin_divorce,"divorce",""},
+ {buildin_divorce,"divorce","*"},
+ {buildin_ispartneron,"ispartneron","*"},
+ {buildin_getpartnerid,"getpartnerid","*"},
+ {buildin_warppartner,"warppartner","sii"},
{buildin_getitemname,"getitemname","i"},
{buildin_makepet,"makepet","i"},
{buildin_getexp,"getexp","ii"},
@@ -470,6 +515,7 @@ struct {
{buildin_classchange,"classchange","ii"},
{buildin_misceffect,"misceffect","i"},
{buildin_soundeffect,"soundeffect","si"},
+ {buildin_soundeffectall,"soundeffectall","si"}, // SoundEffectAll [Codemaster]
{buildin_strmobinfo,"strmobinfo","ii"}, // display mob data [Valaris]
{buildin_guardian,"guardian","siisii*i"}, // summon guardians
{buildin_guardianinfo,"guardianinfo","i"}, // display guardian data [Valaris]
@@ -479,6 +525,7 @@ struct {
{buildin_petheal,"petheal","iii"}, // [Valaris]
{buildin_petmag,"petmag","iiii"}, // [Valaris]
{buildin_petskillattack,"petskillattack","iiii"}, // [Valaris]
+ {buildin_skilleffect,"skilleffect","ii"}, // skill effect [Celest]
{buildin_npcskilleffect,"npcskilleffect","iiii"}, // npc skill effect [Valaris]
{buildin_specialeffect,"specialeffect","i"}, // npc skill effect [Valaris]
{buildin_specialeffect2,"specialeffect2","i"}, // skill effect on players[Valaris]
@@ -493,16 +540,43 @@ struct {
{buildin_npctalk,"npctalk","*"}, // [Valaris]
{buildin_hasitems,"hasitems","*"}, // [Valaris]
{buildin_mobcount,"mobcount","ss"},
- {buildin_getlook,"getlook","i"},
+ {buildin_getlook,"getlook","i"},
{buildin_getsavepoint,"getsavepoint","i"},
{buildin_npcspeed,"npcspeed","i"}, // [Valaris]
{buildin_npcwalkto,"npcwalkto","ii"}, // [Valaris]
{buildin_npcstop,"npcstop",""}, // [Valaris]
{buildin_getmapxy,"getmapxy","siii*"}, //by Lorky [Lupus]
+ {buildin_checkoption1,"checkoption1","i"},
+ {buildin_checkoption2,"checkoption2","i"},
+ {buildin_guildgetexp,"guildgetexp","i"},
+ {buildin_skilluseid,"skilluseid","ii"}, // originally by Qamera [Celest]
+ {buildin_skilluseid,"doskill","ii"}, // since a lot of scripts would already use 'doskill'...
+ {buildin_skillusepos,"skillusepos","iiii"}, // [Celest]
+ {buildin_logmes,"logmes","s"}, //this command actls as MES but prints info into LOG file either SQL/TXT [Lupus]
+ {buildin_summon,"summon","si*"}, // summons a slave monster [Celest]
+ {buildin_isnight,"isnight",""}, // check whether it is night time [Celest]
+ {buildin_isday,"isday",""}, // check whether it is day time [Celest]
+ {buildin_isequipped,"isequipped","i*"}, // check whether another item/card has been equipped [Celest]
+ {buildin_isequippedcnt,"isequippedcnt","i*"}, // check how many items/cards are being equipped [Celest]
+ {buildin_cardscnt,"cardscnt","i*"}, // check how many items/cards are being equipped in the same arm [Lupus]
+ {buildin_getrefine,"getrefine",""}, // returns the refined number of the current item, or an item with index specified [celest]
+#ifdef PCRE_SUPPORT
+ {buildin_defpattern, "defpattern", "iss"}, // Define pattern to listen for [MouseJstr]
+ {buildin_activatepset, "activatepset", "i"}, // Activate a pattern set [MouseJstr]
+ {buildin_deactivatepset, "deactivatepset", "i"}, // Deactive a pattern set [MouseJstr]
+ {buildin_deletepset, "deletepset", "i"}, // Delete a pattern set [MouseJstr]
+#endif
+ {buildin_dispbottom,"dispbottom","s"}, //added from jA [Lupus]
+ {buildin_getusersname,"getusersname","*"},
+ {buildin_recovery,"recovery",""},
+ {buildin_getpetinfo,"getpetinfo","i"},
+ {buildin_checkequipedcard,"checkequipedcard","i"},
+ {buildin_jump_zero,"jump_zero","ii"}, //for future jA script compatibility
+ {buildin_select,"select","*"}, //for future jA script compatibility
+ {buildin_globalmes,"globalmes","s*"},
+ {buildin_getmapmobs,"getmapmobs","s"}, //end jA addition
{NULL,NULL,NULL},
};
-int buildin_message(struct script_state *st); // [MouseJstr]
-
enum {
C_NOP,C_POS,C_INT,C_PARAM,C_FUNC,C_STR,C_CONSTSTR,C_ARG,
@@ -536,7 +610,7 @@ static int search_str(const unsigned char *p)
int i;
i=str_hash[calc_hash(p)];
while(i){
- if(strcmp(str_buf+str_data[i].str,p)==0){
+ if(strcmp(str_buf+str_data[i].str,(char *) p)==0){
return i;
}
i=str_data[i].next;
@@ -554,14 +628,14 @@ static int add_str(const unsigned char *p)
int i;
char *lowcase;
- lowcase=strdup(p);
+ lowcase=aStrdup((char *) p);
for(i=0;lowcase[i];i++)
lowcase[i]=tolower(lowcase[i]);
- if((i=search_str(lowcase))>=0){
- free(lowcase);
+ if((i=search_str((unsigned char *) lowcase))>=0){
+ aFree(lowcase);
return i;
}
- free(lowcase);
+ aFree(lowcase);
i=calc_hash(p);
if(str_hash[i]==0){
@@ -569,7 +643,7 @@ static int add_str(const unsigned char *p)
} else {
i=str_hash[i];
for(;;){
- if(strcmp(str_buf+str_data[i].str,p)==0){
+ if(strcmp(str_buf+str_data[i].str,(char *) p)==0){
return i;
}
if(str_data[i].next==0)
@@ -580,22 +654,22 @@ static int add_str(const unsigned char *p)
}
if(str_num>=str_data_size){
str_data_size+=128;
- str_data=aRealloc(str_data,sizeof(str_data[0])*str_data_size);
+ str_data=(struct str_data_struct *) aRealloc(str_data,sizeof(str_data[0])*str_data_size);
memset(str_data + (str_data_size - 128), '\0', 128);
}
- while(str_pos+strlen(p)+1>=str_size){
+ while(str_pos+(int)strlen((char *) p)+1>=str_size){
str_size+=256;
str_buf=(char *)aRealloc(str_buf,str_size);
memset(str_buf + (str_size - 256), '\0', 256);
}
- strcpy(str_buf+str_pos,p);
+ strcpy(str_buf+str_pos, (char *) p);
str_data[str_num].type=C_NOP;
str_data[str_num].str=str_pos;
str_data[str_num].next=0;
str_data[str_num].func=NULL;
str_data[str_num].backpatch=-1;
str_data[str_num].label=-1;
- str_pos+=strlen(p)+1;
+ str_pos+=strlen( (char *) p)+1;
return str_num++;
}
@@ -608,7 +682,7 @@ static void check_script_buf(int size)
{
if(script_pos+size>=script_size){
script_size+=SCRIPT_BLOCK_SIZE;
- script_buf=(char *)aRealloc(script_buf,script_size);
+ script_buf=(unsigned char *)aRealloc(script_buf,script_size);
memset(script_buf + script_size - SCRIPT_BLOCK_SIZE, '\0',
SCRIPT_BLOCK_SIZE);
}
@@ -769,13 +843,17 @@ static void disp_error_message(const char *mes,const unsigned char *pos)
for(line=startline,p=startptr;p && *p;line++){
linestart=p;
- lineend=strchr(p,'\n');
+ lineend=(unsigned char *) strchr((char *) p,'\n');
if(lineend){
c=*lineend;
*lineend=0;
}
if(lineend==NULL || pos<lineend){
- printf("%s line %d : ",mes,line);
+ if (current_file) {
+ printf("%s in "CL_WHITE"\'%s\'"CL_RESET" line "CL_WHITE"\'%d\'"CL_RESET" : ", mes, current_file, line);
+ } else {
+ printf("%s line "CL_WHITE"\'%d\'"CL_RESET" : ", mes, line);
+ }
for(i=0;(linestart[i]!='\r') && (linestart[i]!='\n') && linestart[i];i++){
if(linestart+i!=pos)
printf("%c",linestart[i]);
@@ -819,9 +897,9 @@ unsigned char* parse_simpleexpr(unsigned char *p)
}
} else if(isdigit(*p) || ((*p=='-' || *p=='+') && isdigit(p[1]))){
char *np;
- i=strtoul(p,&np,0);
+ i=strtoul((char *) p,&np,0);
add_scripti(i);
- p=np;
+ p=(unsigned char *) np;
} else if(*p=='"'){
add_scriptc(C_STR);
p++;
@@ -848,12 +926,12 @@ unsigned char* parse_simpleexpr(unsigned char *p)
disp_error_message("unexpected character",p);
exit(1);
}
- p2=skip_word(p);
+ p2=(char *) skip_word(p);
c=*p2; *p2=0; // 名前をadd_strする
l=add_str(p);
parse_cmd=l; // warn_*_mismatch_paramnumのために必要
- if(l==search_str("if")) // warn_cmd_no_commaのために必要
+ if(l== search_str((unsigned char *) "if")) // warn_cmd_no_commaのために必要
parse_cmd_if++;
/*
// 廃止予定のl14/l15,およびプレフィックスlの警告
@@ -864,11 +942,12 @@ unsigned char* parse_simpleexpr(unsigned char *p)
disp_error_message("prefix 'l' is DEPRECATED. use prefix '@' instead.",p2);
}
*/
- *p2=c; p=p2;
+ *p2=c;
+ p=(unsigned char *) p2;
if(str_data[l].type!=C_FUNC && c=='['){
// array(name[i] => getelementofarray(name,i) )
- add_scriptl(search_str("getelementofarray"));
+ add_scriptl(search_str((unsigned char *) "getelementofarray"));
add_scriptc(C_ARG);
add_scriptl(l);
p=parse_subexpr(p+1,-1);
@@ -906,14 +985,14 @@ unsigned char* parse_subexpr(unsigned char *p,int limit)
p=skip_space(p);
if(*p=='-'){
- tmpp=skip_space(p+1);
+ tmpp=(char *) skip_space((unsigned char *) (p+1));
if(*tmpp==';' || *tmpp==','){
add_scriptl(LABEL_NEXTLINE);
p++;
return p;
}
}
- tmpp=p;
+ tmpp=(char *) p;
if((op=C_NEG,*p=='-') || (op=C_LNOT,*p=='!') || (op=C_NOT,*p=='~')){
p=parse_subexpr(p+1,100);
add_scriptc(op);
@@ -945,13 +1024,13 @@ unsigned char* parse_subexpr(unsigned char *p,int limit)
const char *plist[128];
if( str_data[func].type!=C_FUNC ){
- disp_error_message("expect function",tmpp);
+ disp_error_message("expect function",(unsigned char *) tmpp);
exit(0);
}
add_scriptc(C_ARG);
do {
- plist[i]=p;
+ plist[i]=(char *) p;
p=parse_subexpr(p,-1);
p=skip_space(p);
if(*p==',') p++;
@@ -961,7 +1040,7 @@ unsigned char* parse_subexpr(unsigned char *p,int limit)
p=skip_space(p);
i++;
} while(*p && *p!=')' && i<128);
- plist[i]=p;
+ plist[i]=(char *) p;
if(*(p++)!=')'){
disp_error_message("func request '(' ')'",p);
exit(1);
@@ -972,7 +1051,7 @@ unsigned char* parse_subexpr(unsigned char *p,int limit)
int j=0;
for(j=0;arg[j];j++) if(arg[j]=='*')break;
if( (arg[j]==0 && i!=j) || (arg[j]=='*' && i<j) ){
- disp_error_message("illegal number of parameters",plist[(i<j)?i:j]);
+ disp_error_message("illegal number of parameters",(unsigned char *) (plist[(i<j)?i:j]));
}
}
} else {
@@ -1029,19 +1108,19 @@ unsigned char* parse_line(unsigned char *p)
parse_cmd_if=0; // warn_cmd_no_commaのために必要
// 最初は関数名
- p2=p;
+ p2=(char *) p;
p=parse_simpleexpr(p);
p=skip_space(p);
cmd=parse_cmd;
if( str_data[cmd].type!=C_FUNC ){
- disp_error_message("expect command",p2);
+ disp_error_message("expect command",(unsigned char *) p2);
// exit(0);
}
add_scriptc(C_ARG);
while(p && *p && *p!=';' && i<128){
- plist[i]=p;
+ plist[i]=(char *) p;
p=parse_expr(p);
p=skip_space(p);
@@ -1053,7 +1132,7 @@ unsigned char* parse_line(unsigned char *p)
p=skip_space(p);
i++;
}
- plist[i]=p;
+ plist[i]=(char *) p;
if(!p || *(p++)!=';'){
disp_error_message("need ';'",p);
exit(1);
@@ -1065,7 +1144,7 @@ unsigned char* parse_line(unsigned char *p)
int j=0;
for(j=0;arg[j];j++) if(arg[j]=='*')break;
if( (arg[j]==0 && i!=j) || (arg[j]=='*' && i<j) ){
- disp_error_message("illegal number of parameters",plist[(i<j)?i:j]);
+ disp_error_message("illegal number of parameters",(unsigned char *) (plist[(i<j)?i:j]));
}
}
@@ -1081,7 +1160,7 @@ static void add_buildin_func(void)
{
int i,n;
for(i=0;buildin_func[i].func;i++){
- n=add_str(buildin_func[i].name);
+ n=add_str((unsigned char *) buildin_func[i].name);
str_data[n].type=C_FUNC;
str_data[n].val=i;
str_data[n].func=buildin_func[i].func;
@@ -1111,7 +1190,7 @@ static void read_constdb(void)
sscanf(line,"%[A-Za-z0-9_] %d %d",name,&val,&type)>=2){
for(i=0;name[i];i++)
name[i]=tolower(name[i]);
- n=add_str(name);
+ n=add_str((const unsigned char *) name);
if(type==0)
str_data[n].type=C_INT;
else
@@ -1126,7 +1205,7 @@ static void read_constdb(void)
* スクリプトの解析
*------------------------------------------
*/
-unsigned char* parse_script(unsigned char *src,int line)
+char* parse_script(unsigned char *src,int line)
{
unsigned char *p,*tmpp;
int i;
@@ -1137,7 +1216,7 @@ unsigned char* parse_script(unsigned char *src,int line)
read_constdb();
}
first=0;
- script_buf=(unsigned char *)aCalloc(SCRIPT_BLOCK_SIZE,sizeof(unsigned char));
+ script_buf=(unsigned char *)aCallocA(SCRIPT_BLOCK_SIZE,sizeof(unsigned char));
script_pos=0;
script_size=SCRIPT_BLOCK_SIZE;
str_data[LABEL_NEXTLINE].type=C_NOP;
@@ -1202,7 +1281,7 @@ unsigned char* parse_script(unsigned char *src,int line)
add_scriptc(C_NOP);
script_size = script_pos;
- script_buf=(char *)aRealloc(script_buf,script_pos + 1);
+ script_buf=(unsigned char *)aRealloc(script_buf,script_pos + 1);
// 未解決のラベルを解決
for(i=LABEL_START;i<str_num;i++){
@@ -1229,7 +1308,7 @@ unsigned char* parse_script(unsigned char *src,int line)
printf("\n");
#endif
- return script_buf;
+ return (char *) script_buf;
}
//
@@ -1364,6 +1443,11 @@ static int set_reg(struct map_session_data *sd,int num,char *name,void *v)
return 0;
}
+int set_var(struct map_session_data *sd, char *name, void *val)
+{
+ return set_reg(sd, add_str((unsigned char *) name), name, val);
+}
+
/*==========================================
* 文字列への変換
*------------------------------------------
@@ -1373,7 +1457,7 @@ char* conv_str(struct script_state *st,struct script_data *data)
get_val(st,data);
if(data->type==C_INT){
char *buf;
- buf=(char *)aCalloc(16,sizeof(char));
+ buf=(char *)aCallocA(16,sizeof(char));
sprintf(buf,"%d",data->u.num);
data->type=C_STR;
data->u.str=buf;
@@ -1399,7 +1483,7 @@ int conv_num(struct script_state *st,struct script_data *data)
p=data->u.str;
data->u.num = atoi(p);
if(data->type==C_STR)
- free(p);
+ aFree(p);
data->type=C_INT;
}
return data->u.num;
@@ -1441,7 +1525,7 @@ void push_str(struct script_stack *stack,int type,unsigned char *str)
// if(battle_config.etc_log)
// printf("push (%d,%x)-> %d\n",type,str,stack->sp);
stack->stack_data[stack->sp].type=type;
- stack->stack_data[stack->sp].u.str=str;
+ stack->stack_data[stack->sp].u.str=(char *) str;
stack->sp++;
}
@@ -1453,10 +1537,10 @@ void push_copy(struct script_stack *stack,int pos)
{
switch(stack->stack_data[pos].type){
case C_CONSTSTR:
- push_str(stack,C_CONSTSTR,stack->stack_data[pos].u.str);
+ push_str(stack,C_CONSTSTR,(unsigned char *) stack->stack_data[pos].u.str);
break;
case C_STR:
- push_str(stack,C_STR,strdup(stack->stack_data[pos].u.str));
+ push_str(stack,C_STR,(unsigned char *) aStrdup(stack->stack_data[pos].u.str));
break;
default:
push_val(stack,stack->stack_data[pos].type,stack->stack_data[pos].u.num);
@@ -1473,7 +1557,7 @@ void pop_stack(struct script_stack* stack,int start,int end)
int i;
for(i=start;i<end;i++){
if(stack->stack_data[i].type==C_STR){
- free(stack->stack_data[i].u.str);
+ aFree(stack->stack_data[i].u.str);
}
}
if(stack->sp>end){
@@ -1505,7 +1589,7 @@ int buildin_goto(struct script_state *st)
int pos;
if( st->stack->stack_data[st->start+2].type!=C_POS ){
- printf("script: goto: not label !\n");
+ printf("script: goto: not label!\n");
st->state=END;
return 0;
}
@@ -1525,7 +1609,7 @@ int buildin_callfunc(struct script_state *st)
char *scr;
char *str=conv_str(st,& (st->stack->stack_data[st->start+2]));
- if( (scr=strdb_search(script_get_userfunc_db(),str)) ){
+ if( (scr=(char *) strdb_search(script_get_userfunc_db(),str)) ){
int i,j;
for(i=st->start+3,j=0;i<st->end;i++,j++)
push_copy(st->stack,i);
@@ -1641,7 +1725,7 @@ int buildin_menu(struct script_state *st)
char *buf;
int len,i;
struct map_session_data *sd;
-
+
sd=script_rid2sd(st);
if(sd->state.menu_or_input==0){
@@ -1651,21 +1735,21 @@ int buildin_menu(struct script_state *st)
conv_str(st,& (st->stack->stack_data[i]));
len+=strlen(st->stack->stack_data[i].u.str)+1;
}
- buf=(char *)aCalloc(len,sizeof(char));
+ buf=(char *)aCallocA(len+1,sizeof(char));
buf[0]=0;
for(i=st->start+2,len=0;i<st->end;i+=2){
strcat(buf,st->stack->stack_data[i].u.str);
strcat(buf,":");
}
clif_scriptmenu(script_rid2sd(st),st->oid,buf);
- free(buf);
+ aFree(buf);
} else if(sd->npc_menu==0xff){ // cansel
sd->state.menu_or_input=0;
st->state=END;
} else { // goto動作
// ragemu互換のため
- pc_setreg(sd,add_str("l15"),sd->npc_menu);
- pc_setreg(sd,add_str("@menu"),sd->npc_menu);
+ pc_setreg(sd,add_str((unsigned char *) "l15"),sd->npc_menu);
+ pc_setreg(sd,add_str((unsigned char *) "@menu"),sd->npc_menu);
sd->state.menu_or_input=0;
if(sd->npc_menu>0 && sd->npc_menu<(st->end-st->start)/2){
int pos;
@@ -1688,21 +1772,23 @@ int buildin_menu(struct script_state *st)
*/
int buildin_rand(struct script_state *st)
{
- int range,min,max;
+ int range;
- if(st->end>st->start+3){
- min=conv_num(st,& (st->stack->stack_data[st->start+2]));
- max=conv_num(st,& (st->stack->stack_data[st->start+3]));
- if(max<min){
- int tmp;
- tmp=min;
- min=max;
- max=tmp;
+ if (st->end > st->start+3){
+ int min, max;
+ min = conv_num(st,& (st->stack->stack_data[st->start+2]));
+ max = conv_num(st,& (st->stack->stack_data[st->start+3]));
+ if (max < min){
+ int tmp = min;
+ min = max;
+ max = tmp;
}
- range=max-min+1;
+ range = max - min + 1;
+ if (range == 0) range = 1;
push_val(st->stack,C_INT,rand()%range+min);
} else {
- range=conv_num(st,& (st->stack->stack_data[st->start+2]));
+ range = conv_num(st,& (st->stack->stack_data[st->start+2]));
+ if (range == 0) range = 1;
push_val(st->stack,C_INT,rand()%range);
}
return 0;
@@ -1846,7 +1932,7 @@ int buildin_input(struct script_state *st)
{
struct map_session_data *sd=NULL;
int num=(st->end>st->start+2)?st->stack->stack_data[st->start+2].u.num:0;
- char *name=(st->end>st->start+2)?str_buf+str_data[num&0x00ffffff].str:"";
+ char *name=(char *) ((st->end>st->start+2)?str_buf+str_data[num&0x00ffffff].str:"");
// char prefix=*name;
char postfix=name[strlen(name)-1];
@@ -1877,7 +1963,7 @@ int buildin_input(struct script_state *st)
set_reg(sd,num,name,(void*)sd->npc_amount);
} else {
// ragemu互換のため
- pc_setreg(sd,add_str("l14"),sd->npc_amount);
+ pc_setreg(sd,add_str((unsigned char *) "l14"),sd->npc_amount);
}
}
} else {
@@ -2102,7 +2188,7 @@ int buildin_deletearray(struct script_state *st)
}
for(;i<(128-(num>>24));i++){
if( postfix!='$' ) set_reg(sd,num+(i<<24),name, 0);
- if( postfix=='$' ) set_reg(sd,num+(i<<24),name, "");
+ if( postfix=='$' ) set_reg(sd,num+(i<<24),name, (void *) "");
}
return 0;
}
@@ -2274,7 +2360,7 @@ int buildin_checkweight(struct script_state *st)
*/
int buildin_getitem(struct script_state *st)
{
- int nameid,amount,flag = 0;
+ int nameid,nameidsrc,amount,flag = 0;
struct item item_tmp;
struct map_session_data *sd;
struct script_data *data;
@@ -2296,12 +2382,12 @@ int buildin_getitem(struct script_state *st)
return 0; //return if amount <=0, skip the useles iteration
}
//Violet Box, Blue Box, etc - random item pick
- if(nameid<0) { // ランダム
+ if((nameidsrc = nameid)<0) { // Save real ID of the source Box [Lupus]
nameid=itemdb_searchrandomid(-nameid);
- #ifndef TXT_ONLY
+
if(log_config.present > 0)
- log_present(sd, -nameid, nameid);
- #endif //USE_SQL
+ log_present(sd, -nameidsrc, nameid); //fixed missing ID by Lupus
+
flag = 1;
}
@@ -2318,7 +2404,8 @@ int buildin_getitem(struct script_state *st)
return 0;
if((flag = pc_additem(sd,&item_tmp,amount))) {
clif_additem(sd,0,0,flag);
- map_addflooritem(&item_tmp,amount,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
+ if(!pc_candrop(sd,nameid))
+ map_addflooritem(&item_tmp,amount,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
}
}
@@ -2499,7 +2586,7 @@ int buildin_delitem(struct script_state *st)
if(sd->inventory_data[i]->type==7 && sd->status.inventory[i].card[0] == (short)0xff00 && search_petDB_index(nameid, PET_EGG) >= 0 ){
intif_delete_petdata(*((long *)(&sd->status.inventory[i].card[1])));
//clear egg flag. so it won't be put in IMPORTANT items (eggs look like item with 2 cards ^_^)
- sd->status.inventory[i].card[1] = sd->status.inventory[i].card[0] = 0;
+ sd->status.inventory[i].card[1] = sd->status.inventory[i].card[0] = 0;
//now this egg'll be deleted as a common unimportant item
}
//is this item important? does it have cards? or Player's name? or Refined/Upgraded
@@ -2528,7 +2615,7 @@ int buildin_delitem(struct script_state *st)
continue;
if(sd->status.inventory[i].amount>=amount){
- pc_delitem(sd,i,amount,0);
+ pc_delitem(sd,i,amount,0);
return 0; //we deleted exact amount of items. now exit
} else {
amount-=sd->status.inventory[i].amount;
@@ -2604,7 +2691,7 @@ char *buildin_getpartyname_sub(int party_id)
if(p!=NULL){
char *buf;
- buf=(char *)aCalloc(24,sizeof(char));
+ buf=(char *)aCallocA(24,sizeof(char));
strcpy(buf,p->name);
return buf;
}
@@ -2619,9 +2706,9 @@ int buildin_getpartyname(struct script_state *st)
party_id=conv_num(st,& (st->stack->stack_data[st->start+2]));
name=buildin_getpartyname_sub(party_id);
if(name!=0)
- push_str(st->stack,C_STR,name);
+ push_str(st->stack,C_STR,(unsigned char *)name);
else
- push_str(st->stack,C_CONSTSTR,"null");
+ push_str(st->stack,C_CONSTSTR, (unsigned char *) "null");
return 0;
}
@@ -2641,12 +2728,12 @@ int buildin_getpartymember(struct script_state *st)
for(i=0;i<MAX_PARTY;i++){
if(p->member[i].account_id){
// printf("name:%s %d\n",p->member[i].name,i);
- mapreg_setregstr(add_str("$@partymembername$")+(i<<24),p->member[i].name);
+ mapreg_setregstr(add_str((unsigned char *) "$@partymembername$")+(i<<24),p->member[i].name);
j++;
}
}
}
- mapreg_setreg(add_str("$@partymembercount"),j);
+ mapreg_setreg(add_str((unsigned char *) "$@partymembercount"),j);
return 0;
}
@@ -2661,7 +2748,7 @@ char *buildin_getguildname_sub(int guild_id)
if(g!=NULL){
char *buf;
- buf=(char *)aCalloc(24,sizeof(char));
+ buf=(char *)aCallocA(24,sizeof(char));
strcpy(buf,g->name);
return buf;
}
@@ -2673,9 +2760,9 @@ int buildin_getguildname(struct script_state *st)
int guild_id=conv_num(st,& (st->stack->stack_data[st->start+2]));
name=buildin_getguildname_sub(guild_id);
if(name!=0)
- push_str(st->stack,C_STR,name);
+ push_str(st->stack,C_STR,(unsigned char *) name);
else
- push_str(st->stack,C_CONSTSTR,"null");
+ push_str(st->stack,C_CONSTSTR,(unsigned char *) "null");
return 0;
}
@@ -2690,7 +2777,7 @@ char *buildin_getguildmaster_sub(int guild_id)
if(g!=NULL){
char *buf;
- buf=(char *)aCalloc(24,sizeof(char));
+ buf=(char *)aCallocA(24,sizeof(char));
strncpy(buf,g->master, 23);
return buf;
}
@@ -2703,9 +2790,9 @@ int buildin_getguildmaster(struct script_state *st)
int guild_id=conv_num(st,& (st->stack->stack_data[st->start+2]));
master=buildin_getguildmaster_sub(guild_id);
if(master!=0)
- push_str(st->stack,C_STR,master);
+ push_str(st->stack,C_STR,(unsigned char *) master);
else
- push_str(st->stack,C_CONSTSTR,"null");
+ push_str(st->stack,C_CONSTSTR,(unsigned char *) "null");
return 0;
}
@@ -2740,25 +2827,25 @@ int buildin_strcharinfo(struct script_state *st)
num=conv_num(st,& (st->stack->stack_data[st->start+2]));
if(num==0){
char *buf;
- buf=(char *)aCalloc(24,sizeof(char));
+ buf=(char *)aCallocA(24,sizeof(char));
strncpy(buf,sd->status.name, 23);
- push_str(st->stack,C_STR,buf);
+ push_str(st->stack,C_STR,(unsigned char *) buf);
}
if(num==1){
char *buf;
buf=buildin_getpartyname_sub(sd->status.party_id);
if(buf!=0)
- push_str(st->stack,C_STR,buf);
+ push_str(st->stack,C_STR,(unsigned char *) buf);
else
- push_str(st->stack,C_CONSTSTR,"");
+ push_str(st->stack,C_CONSTSTR,(unsigned char *) "");
}
if(num==2){
char *buf;
buf=buildin_getguildname_sub(sd->status.guild_id);
if(buf!=0)
- push_str(st->stack,C_STR,buf);
+ push_str(st->stack,C_STR,(unsigned char *) buf);
else
- push_str(st->stack,C_CONSTSTR,"");
+ push_str(st->stack,C_CONSTSTR,(unsigned char *) "");
}
return 0;
@@ -2807,7 +2894,7 @@ int buildin_getequipname(struct script_state *st)
struct item_data* item;
char *buf;
- buf=(char *)aCalloc(64,sizeof(char));
+ buf=(char *)aCallocA(64,sizeof(char));
sd=script_rid2sd(st);
num=conv_num(st,& (st->stack->stack_data[st->start+2]));
i=pc_checkequip(sd,equip[num-1]);
@@ -2820,7 +2907,7 @@ int buildin_getequipname(struct script_state *st)
}else{
sprintf(buf,"%s-[%s]",pos[num-1],pos[10]);
}
- push_str(st->stack,C_STR,buf);
+ push_str(st->stack,C_STR,(unsigned char *) buf);
return 0;
}
@@ -2833,9 +2920,9 @@ int buildin_getbrokenid(struct script_state *st)
{
int i,num,id=0,brokencounter=0;
struct map_session_data *sd;
-
+
sd=script_rid2sd(st);
-
+
num=conv_num(st,& (st->stack->stack_data[st->start+2]));
for(i=0; i<MAX_INVENTORY; i++) {
if(sd->status.inventory[i].attribute==1){
@@ -2846,7 +2933,7 @@ int buildin_getbrokenid(struct script_state *st)
}
}
}
-
+
push_val(st->stack,C_INT,id);
return 0;
@@ -2864,7 +2951,7 @@ int buildin_repair(struct script_state *st)
sd=script_rid2sd(st);
-
+
num=conv_num(st,& (st->stack->stack_data[st->start+2]));
for(i=0; i<MAX_INVENTORY; i++) {
if(sd->status.inventory[i].attribute==1){
@@ -2916,10 +3003,13 @@ int buildin_getequipisenableref(struct script_state *st)
num=conv_num(st,& (st->stack->stack_data[st->start+2]));
sd=script_rid2sd(st);
i=pc_checkequip(sd,equip[num-1]);
- if(i >= 0 && num<7 && sd->inventory_data[i] && (num!=1
+ if(i >= 0 && num<7 && sd->inventory_data[i] && !sd->inventory_data[i]->flag.no_refine)
+ // replaced by Celest
+ /*(num!=1
|| sd->inventory_data[i]->def > 1
|| (sd->inventory_data[i]->def==1 && sd->inventory_data[i]->equip_script==NULL)
- || (sd->inventory_data[i]->def<=0 && sd->inventory_data[i]->equip_script!=NULL)))
+ || (sd->inventory_data[i]->def<=0 && sd->inventory_data[i]->equip_script!=NULL)))*/
+
{
push_val(st->stack,C_INT,1);
} else {
@@ -3002,7 +3092,7 @@ int buildin_getequippercentrefinery(struct script_state *st)
sd=script_rid2sd(st);
i=pc_checkequip(sd,equip[num-1]);
if(i >= 0)
- push_val(st->stack,C_INT,pc_percentrefinery(sd,&sd->status.inventory[i]));
+ push_val(st->stack,C_INT,status_percentrefinery(sd,&sd->status.inventory[i]));
else
push_val(st->stack,C_INT,0);
@@ -3024,13 +3114,11 @@ int buildin_successrefitem(struct script_state *st)
if(i >= 0) {
ep=sd->status.inventory[i].equip;
- #ifndef TXT_ONLY
if(log_config.refine > 0)
log_refine(sd, i, 1);
- #endif //USE_SQL
sd->status.inventory[i].refine++;
- pc_unequipitem(sd,i,0, BF_NORMAL);
+ pc_unequipitem(sd,i,2);
clif_refine(sd->fd,sd,0,i,sd->status.inventory[i].refine);
clif_delitem(sd,i,1);
clif_additem(sd,i,1,0);
@@ -3054,13 +3142,11 @@ int buildin_failedrefitem(struct script_state *st)
sd=script_rid2sd(st);
i=pc_checkequip(sd,equip[num-1]);
if(i >= 0) {
- #ifndef TXT_ONLY
if(log_config.refine > 0)
log_refine(sd, i, 0);
- #endif //USE_SQL
sd->status.inventory[i].refine = 0;
- pc_unequipitem(sd,i,0, BF_NORMAL);
+ pc_unequipitem(sd,i,3);
// 精錬失敗エフェクトのパケット
clif_refine(sd->fd,sd,1,i,sd->status.inventory[i].refine);
pc_delitem(sd,i,1,0);
@@ -3153,6 +3239,22 @@ int buildin_bonus3(struct script_state *st)
return 0;
}
+
+int buildin_bonus4(struct script_state *st)
+{
+ int type,type2,type3,type4,val;
+ struct map_session_data *sd;
+
+ type=conv_num(st,& (st->stack->stack_data[st->start+2]));
+ type2=conv_num(st,& (st->stack->stack_data[st->start+3]));
+ type3=conv_num(st,& (st->stack->stack_data[st->start+4]));
+ type4=conv_num(st,& (st->stack->stack_data[st->start+5]));
+ val=conv_num(st,& (st->stack->stack_data[st->start+6]));
+ sd=script_rid2sd(st);
+ pc_bonus4(sd,type,type2,type3,type4,val);
+
+ return 0;
+}
/*==========================================
* スキル所得
*------------------------------------------
@@ -3219,15 +3321,15 @@ int buildin_getskilllv(struct script_state *st)
return 0;
}
/*==========================================
- * getgdskilllv(Guild_ID, Skill_ID);
- * skill_id = 10000 : GD_APPROVAL
- * 10001 : GD_KAFRACONTACT
- * 10002 : GD_GUARDIANRESEARCH
- * 10003 : GD_GUARDUP
- * 10004 : GD_EXTENSION
+ * getgdskilllv(Guild_ID, Skill_ID);
+ * skill_id = 10000 : GD_APPROVAL
+ * 10001 : GD_KAFRACONTACT
+ * 10002 : GD_GUARDIANRESEARCH
+ * 10003 : GD_GUARDUP
+ * 10004 : GD_EXTENSION
*------------------------------------------
*/
-int buildin_getgdskilllv(struct script_state *st)
+int buildin_getgdskilllv(struct script_state *st)
{
int guild_id=conv_num(st,& (st->stack->stack_data[st->start+2]));
int skill_id=conv_num(st,& (st->stack->stack_data[st->start+3]));
@@ -3299,6 +3401,46 @@ int buildin_checkoption(struct script_state *st)
return 0;
}
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_checkoption1(struct script_state *st)
+{
+ int type;
+ struct map_session_data *sd;
+
+ type=conv_num(st,& (st->stack->stack_data[st->start+2]));
+ sd=script_rid2sd(st);
+
+ if(sd->opt1 & type){
+ push_val(st->stack,C_INT,1);
+ } else {
+ push_val(st->stack,C_INT,0);
+ }
+
+ return 0;
+}
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_checkoption2(struct script_state *st)
+{
+ int type;
+ struct map_session_data *sd;
+
+ type=conv_num(st,& (st->stack->stack_data[st->start+2]));
+ sd=script_rid2sd(st);
+
+ if(sd->opt2 & type){
+ push_val(st->stack,C_INT,1);
+ } else {
+ push_val(st->stack,C_INT,0);
+ }
+
+ return 0;
+}
/*==========================================
*
@@ -3524,11 +3666,11 @@ int buildin_gettimestr(struct script_state *st)
fmtstr=conv_str(st,& (st->stack->stack_data[st->start+2]));
maxlen=conv_num(st,& (st->stack->stack_data[st->start+3]));
- tmpstr=(char *)aCalloc(maxlen+1,sizeof(char));
+ tmpstr=(char *)aCallocA(maxlen+1,sizeof(char));
strftime(tmpstr,maxlen,fmtstr,localtime(&now));
tmpstr[maxlen]='\0';
- push_str(st->stack,C_STR,tmpstr);
+ push_str(st->stack,C_STR,(unsigned char *) tmpstr);
return 0;
}
@@ -3608,11 +3750,11 @@ int buildin_makepet(struct script_state *st)
if (pet_id < 0)
pet_id = search_petDB_index(id, PET_EGG);
if (pet_id >= 0 && sd) {
- sd->catch_target_class = pet_db[pet_id].class;
+ sd->catch_target_class = pet_db[pet_id].class_;
intif_create_pet(
sd->status.account_id, sd->status.char_id,
- pet_db[pet_id].class, mob_db[pet_db[pet_id].class].lv,
- pet_db[pet_id].EggID, 0, pet_db[pet_id].intimate,
+ (short)pet_db[pet_id].class_, (short)mob_db[pet_db[pet_id].class_].lv,
+ (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate,
100, 0, 1, pet_db[pet_id].jname);
}
@@ -3638,24 +3780,42 @@ int buildin_getexp(struct script_state *st)
}
/*==========================================
+ * Gain guild exp [Celest]
+ *------------------------------------------
+ */
+int buildin_guildgetexp(struct script_state *st)
+{
+ struct map_session_data *sd = script_rid2sd(st);
+ int exp;
+
+ exp = conv_num(st,& (st->stack->stack_data[st->start+2]));
+ if(exp < 0)
+ return 0;
+ if(sd && sd->status.guild_id > 0)
+ guild_getexp (sd, exp);
+
+ return 0;
+}
+
+/*==========================================
* モンスター発生
*------------------------------------------
*/
int buildin_monster(struct script_state *st)
{
- int class,amount,x,y;
+ int class_,amount,x,y;
char *str,*map,*event="";
map =conv_str(st,& (st->stack->stack_data[st->start+2]));
x =conv_num(st,& (st->stack->stack_data[st->start+3]));
y =conv_num(st,& (st->stack->stack_data[st->start+4]));
str =conv_str(st,& (st->stack->stack_data[st->start+5]));
- class=conv_num(st,& (st->stack->stack_data[st->start+6]));
+ class_=conv_num(st,& (st->stack->stack_data[st->start+6]));
amount=conv_num(st,& (st->stack->stack_data[st->start+7]));
if( st->end>st->start+8 )
event=conv_str(st,& (st->stack->stack_data[st->start+8]));
- mob_once_spawn(map_id2sd(st->rid),map,x,y,str,class,amount,event);
+ mob_once_spawn(map_id2sd(st->rid),map,x,y,str,class_,amount,event);
return 0;
}
/*==========================================
@@ -3664,7 +3824,7 @@ int buildin_monster(struct script_state *st)
*/
int buildin_areamonster(struct script_state *st)
{
- int class,amount,x0,y0,x1,y1;
+ int class_,amount,x0,y0,x1,y1;
char *str,*map,*event="";
map =conv_str(st,& (st->stack->stack_data[st->start+2]));
@@ -3673,12 +3833,12 @@ int buildin_areamonster(struct script_state *st)
x1 =conv_num(st,& (st->stack->stack_data[st->start+5]));
y1 =conv_num(st,& (st->stack->stack_data[st->start+6]));
str =conv_str(st,& (st->stack->stack_data[st->start+7]));
- class=conv_num(st,& (st->stack->stack_data[st->start+8]));
+ class_=conv_num(st,& (st->stack->stack_data[st->start+8]));
amount=conv_num(st,& (st->stack->stack_data[st->start+9]));
if( st->end>st->start+10 )
event=conv_str(st,& (st->stack->stack_data[st->start+10]));
- mob_once_spawn_area(map_id2sd(st->rid),map,x0,y0,x1,y1,str,class,amount,event);
+ mob_once_spawn_area(map_id2sd(st->rid),map,x0,y0,x1,y1,str,class_,amount,event);
return 0;
}
/*==========================================
@@ -3808,7 +3968,7 @@ int buildin_initnpctimer(struct script_state *st)
nd=(struct npc_data *)map_id2bl(st->oid);
npc_settimerevent_tick(nd,0);
- npc_timerevent_start(nd);
+ npc_timerevent_start(nd, st->rid);
return 0;
}
/*==========================================
@@ -3823,7 +3983,7 @@ int buildin_startnpctimer(struct script_state *st)
else
nd=(struct npc_data *)map_id2bl(st->oid);
- npc_timerevent_start(nd);
+ npc_timerevent_start(nd, st->rid);
return 0;
}
/*==========================================
@@ -3882,6 +4042,46 @@ int buildin_setnpctimer(struct script_state *st)
}
/*==========================================
+ * attaches the player rid to the timer [Celest]
+ *------------------------------------------
+ */
+int buildin_attachnpctimer(struct script_state *st)
+{
+ struct map_session_data *sd;
+ struct npc_data *nd;
+
+ nd=(struct npc_data *)map_id2bl(st->oid);
+ if( st->end > st->start+2 ) {
+ char *name = conv_str(st,& (st->stack->stack_data[st->start+2]));
+ sd=map_nick2sd(name);
+ } else {
+ sd = script_rid2sd(st);
+ }
+
+ if (sd==NULL)
+ return 0;
+
+ nd->u.scr.rid = sd->bl.id;
+ return 0;
+}
+
+/*==========================================
+ * detaches a player rid from the timer [Celest]
+ *------------------------------------------
+ */
+int buildin_detachnpctimer(struct script_state *st)
+{
+ struct npc_data *nd;
+ if( st->end > st->start+2 )
+ nd=npc_name2id(conv_str(st,& (st->stack->stack_data[st->start+2])));
+ else
+ nd=(struct npc_data *)map_id2bl(st->oid);
+
+ nd->u.scr.rid = 0;
+ return 0;
+}
+
+/*==========================================
* 天の声アナウンス
*------------------------------------------
*/
@@ -3971,6 +4171,25 @@ int buildin_getusers(struct script_state *st)
return 0;
}
/*==========================================
+ * Works like @WHO - displays all online users names in window
+ *------------------------------------------
+ */
+int buildin_getusersname(struct script_state *st)
+{
+ struct map_session_data *pl_sd = NULL;
+ int i=0,disp_num=1;
+
+ for (i=0;i<fd_max;i++)
+ if(session[i] && (pl_sd=(struct map_session_data *) session[i]->session_data) && pl_sd->state.auth){
+ if( !(battle_config.hide_GM_session && pc_isGM(pl_sd)) ){
+ if((disp_num++)%10==0)
+ clif_scriptnext(script_rid2sd(st),st->oid);
+ clif_scriptmes(script_rid2sd(st),st->oid,pl_sd->status.name);
+ }
+ }
+ return 0;
+}
+/*==========================================
* マップ指定ユーザー数所得
*------------------------------------------
*/
@@ -4146,9 +4365,12 @@ int buildin_sc_start(struct script_state *st)
bl = map_id2bl(conv_num(st,& (st->stack->stack_data[st->start+5])));
else
bl = map_id2bl(st->rid);
- if(bl->type == BL_PC && ((struct map_session_data *)bl)->state.potionpitcher_flag)
- bl = map_id2bl(((struct map_session_data *)bl)->skilltarget);
- skill_status_change_start(bl,type,val1,0,0,0,tick,0);
+
+ if (bl != 0) {
+ if(bl->type == BL_PC && ((struct map_session_data *)bl)->state.potionpitcher_flag)
+ bl = map_id2bl(((struct map_session_data *)bl)->skilltarget);
+ status_change_start(bl,type,val1,0,0,0,tick,0);
+ }
return 0;
}
@@ -4171,7 +4393,7 @@ int buildin_sc_start2(struct script_state *st)
if(bl->type == BL_PC && ((struct map_session_data *)bl)->state.potionpitcher_flag)
bl = map_id2bl(((struct map_session_data *)bl)->skilltarget);
if(rand()%10000 < per)
- skill_status_change_start(bl,type,val1,0,0,0,tick,0);
+ status_change_start(bl,type,val1,0,0,0,tick,0);
return 0;
}
@@ -4187,7 +4409,7 @@ int buildin_sc_end(struct script_state *st)
bl = map_id2bl(st->rid);
if(bl->type == BL_PC && ((struct map_session_data *)bl)->state.potionpitcher_flag)
bl = map_id2bl(((struct map_session_data *)bl)->skilltarget);
- skill_status_change_end(bl,type,-1);
+ status_change_end(bl,type,-1);
// if(battle_config.etc_log)
// printf("sc_end : %d %d\n",st->rid,type);
return 0;
@@ -4199,8 +4421,7 @@ int buildin_sc_end(struct script_state *st)
int buildin_getscrate(struct script_state *st)
{
struct block_list *bl;
- int sc_def=100,sc_def_mdef2,sc_def_vit2,sc_def_int2,sc_def_luk2;
- int type,rate,luk;
+ int sc_def,type,rate;
type=conv_num(st,& (st->stack->stack_data[st->start+2]));
rate=conv_num(st,& (st->stack->stack_data[st->start+3]));
@@ -4209,22 +4430,9 @@ int buildin_getscrate(struct script_state *st)
else
bl = map_id2bl(st->rid);
- luk = battle_get_luk(bl);
- sc_def_mdef2=100 - (3 + battle_get_mdef(bl) + luk/3);
- sc_def_vit2=100 - (3 + battle_get_vit(bl) + luk/3);
- sc_def_int2=100 - (3 + battle_get_int(bl) + luk/3);
- sc_def_luk2=100 - (3 + luk);
-
- if(type==SC_STONE || type==SC_FREEZE)
- sc_def=sc_def_mdef2;
- else if(type==SC_STAN || type==SC_POISON || type==SC_SILENCE)
- sc_def=sc_def_vit2;
- else if(type==SC_SLEEP || type==SC_CONFUSION || type==SC_BLIND)
- sc_def=sc_def_int2;
- else if(type==SC_CURSE)
- sc_def=sc_def_luk2;
-
- rate=rate*sc_def/100;
+ sc_def = status_get_sc_def(bl,type);
+
+ rate = rate * sc_def / 100;
push_val(st->stack,C_INT,rate);
return 0;
@@ -4347,13 +4555,13 @@ int buildin_changesex(struct script_state *st) {
if (sd->status.sex == 0) {
sd->status.sex = 1;
sd->sex = 1;
- if (sd->status.class == 20 || sd->status.class == 4021)
- sd->status.class -= 1;
+ if (sd->status.class_ == 20 || sd->status.class_ == 4021)
+ sd->status.class_ -= 1;
} else if (sd->status.sex == 1) {
sd->status.sex = 0;
sd->sex = 0;
- if(sd->status.class == 19 || sd->status.class == 4020)
- sd->status.class += 1;
+ if(sd->status.class_ == 19 || sd->status.class_ == 4020)
+ sd->status.class_ += 1;
}
chrif_char_ask_name(-1, sd->status.name, 5, 0, 0, 0, 0, 0, 0); // type: 5 - changesex
chrif_save(sd);
@@ -4395,6 +4603,29 @@ int buildin_waitingroom(struct script_state *st)
return 0;
}
/*==========================================
+ * Works like 'announce' but outputs in the common chat window
+ *------------------------------------------
+ */
+int buildin_globalmes(struct script_state *st)
+{
+ struct block_list *bl = map_id2bl(st->oid);
+ struct npc_data *nd = (struct npc_data *)bl;
+ char *name=NULL,*mes;
+
+ mes=conv_str(st,& (st->stack->stack_data[st->start+2])); // メッセージの取得
+ if(mes==NULL) return 0;
+
+ if(st->end>st->start+3){ // NPC名の取得(123#456)
+ name=conv_str(st,& (st->stack->stack_data[st->start+3]));
+ } else {
+ name=nd->name;
+ }
+
+ npc_globalmessage(name,mes); // グローバルメッセージ送信
+
+ return 0;
+}
+/*==========================================
* npcチャット削除
*------------------------------------------
*/
@@ -4496,13 +4727,13 @@ int buildin_getwaitingroomstate(struct script_state *st)
case 33: val=(cd->users >= cd->trigger); break;
case 4:
- push_str(st->stack,C_CONSTSTR,cd->title);
+ push_str(st->stack,C_CONSTSTR,(unsigned char *) cd->title);
return 0;
case 5:
- push_str(st->stack,C_CONSTSTR,cd->pass);
+ push_str(st->stack,C_CONSTSTR,(unsigned char *) cd->pass);
return 0;
case 16:
- push_str(st->stack,C_CONSTSTR,cd->npc_event);
+ push_str(st->stack,C_CONSTSTR,(unsigned char *) cd->npc_event);
return 0;
}
push_val(st->stack,C_INT,val);
@@ -4534,7 +4765,7 @@ int buildin_warpwaitingpc(struct script_state *st)
for(i=0;i<n;i++){
struct map_session_data *sd=cd->usersd[0]; // リスト先頭のPCを次々に。
- mapreg_setreg(add_str("$@warpwaitingpc")+(i<<24),sd->bl.id);
+ mapreg_setreg(add_str((unsigned char *) "$@warpwaitingpc")+(i<<24),sd->bl.id);
if(strcmp(str,"Random")==0)
pc_randomwarp(sd,3);
@@ -4547,7 +4778,7 @@ int buildin_warpwaitingpc(struct script_state *st)
}else
pc_setpos(sd,str,x,y,0);
}
- mapreg_setreg(add_str("$@warpwaitingpcnum"),n);
+ mapreg_setreg(add_str((unsigned char *) "$@warpwaitingpcnum"),n);
return 0;
}
/*==========================================
@@ -4790,7 +5021,7 @@ int buildin_pvpon(struct script_state *st)
return 0;
for(i=0;i<fd_max;i++){ //人数分ループ
- if(session[i] && (pl_sd=session[i]->session_data) && pl_sd->state.auth){
+ if(session[i] && (pl_sd=(struct map_session_data *) session[i]->session_data) && pl_sd->state.auth){
if(m == pl_sd->bl.m && pl_sd->pvp_timer == -1) {
pl_sd->pvp_timer=add_timer(gettick()+200,pc_calc_pvprank_timer,pl_sd->bl.id,0);
pl_sd->pvp_rank=0;
@@ -4820,7 +5051,7 @@ int buildin_pvpoff(struct script_state *st)
return 0;
for(i=0;i<fd_max;i++){ //人数分ループ
- if(session[i] && (pl_sd=session[i]->session_data) && pl_sd->state.auth){
+ if(session[i] && (pl_sd=(struct map_session_data *) session[i]->session_data) && pl_sd->state.auth){
if(m == pl_sd->bl.m) {
clif_pvpset(pl_sd,0,0,2);
if(pl_sd->pvp_timer != -1) {
@@ -4899,7 +5130,7 @@ int buildin_maprespawnguildid_sub(struct block_list *bl,va_list ap)
pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,3); // end addition [Valaris]
}
if(md && flag&4){
- if(md->class < 1285 || md->class > 1288)
+ if(md->class_ < 1285 || md->class_ > 1288)
mob_delete(md);
}
return 0;
@@ -4942,15 +5173,15 @@ int buildin_agitcheck(struct script_state *st)
struct map_session_data *sd;
int cond;
- sd=script_rid2sd(st);
cond=conv_num(st,& (st->stack->stack_data[st->start+2]));
if(cond == 0) {
if (agit_flag==1) push_val(st->stack,C_INT,1);
if (agit_flag==0) push_val(st->stack,C_INT,0);
} else {
- if (agit_flag==1) pc_setreg(sd,add_str("@agit_flag"),1);
- if (agit_flag==0) pc_setreg(sd,add_str("@agit_flag"),0);
+ sd=script_rid2sd(st);
+ if (agit_flag==1) pc_setreg(sd,add_str((unsigned char *) "@agit_flag"),1);
+ if (agit_flag==0) pc_setreg(sd,add_str((unsigned char *) "@agit_flag"),0);
}
return 0;
}
@@ -4974,16 +5205,16 @@ int buildin_getcastlename(struct script_state *st)
for(i=0;i<MAX_GUILDCASTLE;i++){
if( (gc=guild_castle_search(i)) != NULL ){
if(strcmp(mapname,gc->map_name)==0){
- buf=(char *)aCalloc(24,sizeof(char));
+ buf=(char *)aCallocA(24,sizeof(char));
strncpy(buf,gc->castle_name,24);
break;
}
}
}
if(buf)
- push_str(st->stack,C_STR,buf);
+ push_str(st->stack,C_STR,(unsigned char *) buf);
else
- push_str(st->stack,C_CONSTSTR,"");
+ push_str(st->stack,C_CONSTSTR,(unsigned char *) "");
return 0;
}
@@ -5130,9 +5361,9 @@ int buildin_getequipcardcnt(struct script_state *st)
return 0;
}
do{
- if( (sd->status.inventory[i].card[c-1] > 4000) &&
- (sd->status.inventory[i].card[c-1] < 5000)){
-
+ if( (sd->status.inventory[i].card[c-1] > 4000 &&
+ sd->status.inventory[i].card[c-1] < 5000) ||
+ itemdb_type(sd->status.inventory[i].card[c-1]) == 6){ // [Celest]
push_val(st->stack,C_INT,(c));
return 0;
}
@@ -5159,8 +5390,9 @@ int buildin_successremovecards(struct script_state *st)
return 0;
}
do{
- if( (sd->status.inventory[i].card[c-1] > 4000) &&
- (sd->status.inventory[i].card[c-1] < 5000)){
+ if( (sd->status.inventory[i].card[c-1] > 4000 &&
+ sd->status.inventory[i].card[c-1] < 5000) ||
+ itemdb_type(sd->status.inventory[i].card[c-1]) == 6){ // [Celest]
cardflag = 1;
item_tmp.id=0,item_tmp.nameid=sd->status.inventory[i].card[c-1];
@@ -5212,10 +5444,11 @@ int buildin_failedremovecards(struct script_state *st)
return 0;
}
do{
- if(( sd->status.inventory[i].card[c-1] > 4000) &&
- (sd->status.inventory[i].card[c-1] < 5000)){
-
- cardflag = 1;
+ if( (sd->status.inventory[i].card[c-1] > 4000 &&
+ sd->status.inventory[i].card[c-1] < 5000) ||
+ itemdb_type(sd->status.inventory[i].card[c-1]) == 6){ // [Celest]
+
+ cardflag = 1;
if(typefail == 2){ // 武具のみ損失なら、カードは受け取らせる
item_tmp.id=0,item_tmp.nameid=sd->status.inventory[i].card[c-1];
@@ -5293,9 +5526,9 @@ int buildin_cmdothernpc(struct script_state *st) // Added by RoVeRT
int buildin_inittimer(struct script_state *st) // Added by RoVeRT
{
// struct npc_data *nd=(struct npc_data*)map_id2bl(st->oid);
-
// nd->lastaction=nd->timer=gettick();
- npc_do_ontimer(st->oid, map_id2sd(st->rid), 1);
+
+ npc_do_ontimer(st->oid, 1);
return 0;
}
@@ -5303,9 +5536,9 @@ int buildin_inittimer(struct script_state *st) // Added by RoVeRT
int buildin_stoptimer(struct script_state *st) // Added by RoVeRT
{
// struct npc_data *nd=(struct npc_data*)map_id2bl(st->oid);
-
// nd->lastaction=nd->timer=-1;
- npc_do_ontimer(st->oid, map_id2sd(st->rid), 0);
+
+ npc_do_ontimer(st->oid, 0);
return 0;
}
@@ -5354,10 +5587,13 @@ int buildin_marriage(struct script_state *st)
int buildin_wedding_effect(struct script_state *st)
{
struct map_session_data *sd=script_rid2sd(st);
+ struct block_list *bl;
- if(sd==NULL)
- return 0;
- clif_wedding_effect(&sd->bl);
+ if(sd==NULL) {
+ bl=map_id2bl(st->oid);
+ } else
+ bl=&sd->bl;
+ clif_wedding_effect(bl);
return 0;
}
int buildin_divorce(struct script_state *st)
@@ -5371,6 +5607,56 @@ int buildin_divorce(struct script_state *st)
return 0;
}
+int buildin_ispartneron(struct script_state *st)
+{
+ struct map_session_data *sd=script_rid2sd(st);
+ struct map_session_data *p_sd=NULL;
+
+ if(sd==NULL || !pc_ismarried(sd) ||
+ ((p_sd=map_nick2sd(map_charid2nick(sd->status.partner_id))) == NULL)) {
+ push_val(st->stack,C_INT,0);
+ return 0;
+ }
+
+ push_val(st->stack,C_INT,1);
+ return 0;
+}
+
+int buildin_getpartnerid(struct script_state *st)
+{
+ struct map_session_data *sd=script_rid2sd(st);
+ if (sd == NULL) {
+ push_val(st->stack,C_INT,0);
+ return 0;
+ }
+
+ push_val(st->stack,C_INT,sd->status.partner_id);
+ return 0;
+}
+
+int buildin_warppartner(struct script_state *st)
+{
+ int x,y;
+ char *str;
+ struct map_session_data *sd=script_rid2sd(st);
+ struct map_session_data *p_sd=NULL;
+
+ if(sd==NULL || !pc_ismarried(sd) ||
+ ((p_sd=map_nick2sd(map_charid2nick(sd->status.partner_id))) == NULL)) {
+ push_val(st->stack,C_INT,0);
+ return 0;
+ }
+
+ str=conv_str(st,& (st->stack->stack_data[st->start+2]));
+ x=conv_num(st,& (st->stack->stack_data[st->start+3]));
+ y=conv_num(st,& (st->stack->stack_data[st->start+4]));
+
+ pc_setpos(p_sd,str,x,y,0);
+
+ push_val(st->stack,C_INT,1);
+ return 0;
+}
+
/*================================================
* Script for Displaying MOB Information [Valaris]
*------------------------------------------------
@@ -5379,35 +5665,48 @@ int buildin_strmobinfo(struct script_state *st)
{
int num=conv_num(st,& (st->stack->stack_data[st->start+2]));
- int class=conv_num(st,& (st->stack->stack_data[st->start+3]));
+ int class_=conv_num(st,& (st->stack->stack_data[st->start+3]));
- if(num<=0 || num>=8 || (class>=0 && class<=1000) || class >2000)
+ if((class_>=0 && class_<=1000) || class_ >2000)
return 0;
- if(num==1) {
- char *buf;
- buf=calloc(24, 1);
- buf=mob_db[class].name;
- push_str(st->stack,C_STR,buf);
- return 0;
- }
- else if(num==2) {
- char *buf;
- buf=calloc(24, 1);
- buf=mob_db[class].jname;
- push_str(st->stack,C_STR,buf);
- return 0;
+ switch (num) {
+ case 1:
+ {
+ char *buf;
+ buf=(char *) aCallocA(24, 1);
+// buf=mob_db[class_].name;
+// for string assignments you would need to go for c++ [Shinomori]
+ strcpy(buf,mob_db[class_].name);
+ push_str(st->stack,C_STR,(unsigned char *) buf);
+ break;
+ }
+ case 2:
+ {
+ char *buf;
+ buf=(char *) aCallocA(24, 1);
+// buf=mob_db[class_].jname;
+// for string assignments you would need to go for c++ [Shinomori]
+ strcpy(buf,mob_db[class_].jname);
+ push_str(st->stack,C_STR,(unsigned char *) buf);
+ break;
+ }
+ case 3:
+ push_val(st->stack,C_INT,mob_db[class_].lv);
+ break;
+ case 4:
+ push_val(st->stack,C_INT,mob_db[class_].max_hp);
+ break;
+ case 5:
+ push_val(st->stack,C_INT,mob_db[class_].max_sp);
+ break;
+ case 6:
+ push_val(st->stack,C_INT,mob_db[class_].base_exp);
+ break;
+ case 7:
+ push_val(st->stack,C_INT,mob_db[class_].job_exp);
+ break;
}
- else if(num==3)
- push_val(st->stack,C_INT,mob_db[class].lv);
- else if(num==4)
- push_val(st->stack,C_INT,mob_db[class].max_hp);
- else if(num==5)
- push_val(st->stack,C_INT,mob_db[class].max_sp);
- else if(num==6)
- push_val(st->stack,C_INT,mob_db[class].base_exp);
- else if(num==7)
- push_val(st->stack,C_INT,mob_db[class].job_exp);
return 0;
}
@@ -5417,20 +5716,20 @@ int buildin_strmobinfo(struct script_state *st)
*/
int buildin_guardian(struct script_state *st)
{
- int class=0,amount=1,x=0,y=0,guardian=0;
+ int class_=0,amount=1,x=0,y=0,guardian=0;
char *str,*map,*event="";
map =conv_str(st,& (st->stack->stack_data[st->start+2]));
x =conv_num(st,& (st->stack->stack_data[st->start+3]));
y =conv_num(st,& (st->stack->stack_data[st->start+4]));
str =conv_str(st,& (st->stack->stack_data[st->start+5]));
- class=conv_num(st,& (st->stack->stack_data[st->start+6]));
+ class_=conv_num(st,& (st->stack->stack_data[st->start+6]));
amount=conv_num(st,& (st->stack->stack_data[st->start+7]));
event=conv_str(st,& (st->stack->stack_data[st->start+8]));
if( st->end>st->start+9 )
guardian=conv_num(st,& (st->stack->stack_data[st->start+9]));
- mob_spawn_guardian(map_id2sd(st->rid),map,x,y,str,class,amount,event,guardian);
+ mob_spawn_guardian(map_id2sd(st->rid),map,x,y,str,class_,amount,event,guardian);
return 0;
}
@@ -5471,10 +5770,10 @@ int buildin_getitemname(struct script_state *st)
i_data = NULL;
i_data = itemdb_search(item_id);
- item_name=(char *)aCalloc(24,sizeof(char));
+ item_name=(char *)aCallocA(24,sizeof(char));
strncpy(item_name,i_data->jname,23);
- push_str(st->stack,C_STR,item_name);
+ push_str(st->stack,C_STR,(unsigned char *) item_name);
return 0;
}
@@ -5485,12 +5784,12 @@ int buildin_getitemname(struct script_state *st)
int buildin_petskillbonus(struct script_state *st)
{
- int type,val,duration,timer;
+ int type,val,duration,timer;
struct pet_data *pd;
- struct map_session_data *sd=script_rid2sd(st);
+ struct map_session_data *sd=script_rid2sd(st);
- if(sd==NULL || sd->pd==NULL)
+ if(sd==NULL || sd->pd==NULL)
return 0;
pd=sd->pd;
@@ -5503,10 +5802,17 @@ int buildin_petskillbonus(struct script_state *st)
duration=conv_num(st,& (st->stack->stack_data[st->start+4]));
timer=conv_num(st,& (st->stack->stack_data[st->start+5]));
- pd->skillbonusduration=-1;
- pd->skillbonustimer=-1;
-
- pet_skill_bonus(sd,pd,type,val,duration,timer,0);
+ // initialise bonuses
+ pd->skillbonustype=type;
+ pd->skillbonusval=val;
+ pd->skillduration=duration*1000;
+ pd->skilltimer=timer*1000;
+
+ if (pd->state.skillbonus == -1)
+ pd->state.skillbonus=0; // waiting state
+
+ // wait for timer to start
+ pd->skillbonustimer=add_timer(gettick()+pd->skilltimer,pet_skill_bonus_timer,sd->bl.id,0);
return 0;
}
@@ -5533,7 +5839,7 @@ int buildin_petloot(struct script_state *st)
if(!max)
return 0;
-
+
pd->loot=1;
pd->lootmax=max;
@@ -5550,20 +5856,20 @@ int buildin_getinventorylist(struct script_state *st)
if(!sd) return 0;
for(i=0;i<MAX_INVENTORY;i++){
if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0){
- pc_setreg(sd,add_str("@inventorylist_id")+(j<<24),sd->status.inventory[i].nameid);
- pc_setreg(sd,add_str("@inventorylist_amount")+(j<<24),sd->status.inventory[i].amount);
- pc_setreg(sd,add_str("@inventorylist_equip")+(j<<24),sd->status.inventory[i].equip);
- pc_setreg(sd,add_str("@inventorylist_refine")+(j<<24),sd->status.inventory[i].refine);
- pc_setreg(sd,add_str("@inventorylist_identify")+(j<<24),sd->status.inventory[i].identify);
- pc_setreg(sd,add_str("@inventorylist_attribute")+(j<<24),sd->status.inventory[i].attribute);
- pc_setreg(sd,add_str("@inventorylist_card1")+(j<<24),sd->status.inventory[i].card[0]);
- pc_setreg(sd,add_str("@inventorylist_card2")+(j<<24),sd->status.inventory[i].card[1]);
- pc_setreg(sd,add_str("@inventorylist_card3")+(j<<24),sd->status.inventory[i].card[2]);
- pc_setreg(sd,add_str("@inventorylist_card4")+(j<<24),sd->status.inventory[i].card[3]);
+ pc_setreg(sd,add_str((unsigned char *) "@inventorylist_id")+(j<<24),sd->status.inventory[i].nameid);
+ pc_setreg(sd,add_str((unsigned char *) "@inventorylist_amount")+(j<<24),sd->status.inventory[i].amount);
+ pc_setreg(sd,add_str((unsigned char *) "@inventorylist_equip")+(j<<24),sd->status.inventory[i].equip);
+ pc_setreg(sd,add_str((unsigned char *) "@inventorylist_refine")+(j<<24),sd->status.inventory[i].refine);
+ pc_setreg(sd,add_str((unsigned char *) "@inventorylist_identify")+(j<<24),sd->status.inventory[i].identify);
+ pc_setreg(sd,add_str((unsigned char *) "@inventorylist_attribute")+(j<<24),sd->status.inventory[i].attribute);
+ pc_setreg(sd,add_str((unsigned char *) "@inventorylist_card1")+(j<<24),sd->status.inventory[i].card[0]);
+ pc_setreg(sd,add_str((unsigned char *) "@inventorylist_card2")+(j<<24),sd->status.inventory[i].card[1]);
+ pc_setreg(sd,add_str((unsigned char *) "@inventorylist_card3")+(j<<24),sd->status.inventory[i].card[2]);
+ pc_setreg(sd,add_str((unsigned char *) "@inventorylist_card4")+(j<<24),sd->status.inventory[i].card[3]);
j++;
}
}
- pc_setreg(sd,add_str("@inventorylist_count"),j);
+ pc_setreg(sd,add_str((unsigned char *) "@inventorylist_count"),j);
return 0;
}
@@ -5574,13 +5880,13 @@ int buildin_getskilllist(struct script_state *st)
if(!sd) return 0;
for(i=0;i<MAX_SKILL;i++){
if(sd->status.skill[i].id > 0 && sd->status.skill[i].lv > 0){
- pc_setreg(sd,add_str("@skilllist_id")+(j<<24),sd->status.skill[i].id);
- pc_setreg(sd,add_str("@skilllist_lv")+(j<<24),sd->status.skill[i].lv);
- pc_setreg(sd,add_str("@skilllist_flag")+(j<<24),sd->status.skill[i].flag);
+ pc_setreg(sd,add_str((unsigned char *) "@skilllist_id")+(j<<24),sd->status.skill[i].id);
+ pc_setreg(sd,add_str((unsigned char *)"@skilllist_lv")+(j<<24),sd->status.skill[i].lv);
+ pc_setreg(sd,add_str((unsigned char *)"@skilllist_flag")+(j<<24),sd->status.skill[i].flag);
j++;
}
}
- pc_setreg(sd,add_str("@skilllist_count"),j);
+ pc_setreg(sd,add_str((unsigned char *) "@skilllist_count"),j);
return 0;
}
@@ -5604,14 +5910,14 @@ int buildin_clearitem(struct script_state *st)
*/
int buildin_classchange(struct script_state *st)
{
- int class,type;
+ int _class,type;
struct block_list *bl=map_id2bl(st->oid);
-
+
if(bl==NULL) return 0;
- class=conv_num(st,& (st->stack->stack_data[st->start+2]));
+ _class=conv_num(st,& (st->stack->stack_data[st->start+2]));
type=conv_num(st,& (st->stack->stack_data[st->start+3]));
- clif_class_change(bl,class,type);
+ clif_class_change(bl,_class,type);
return 0;
}
@@ -5655,6 +5961,24 @@ int buildin_soundeffect(struct script_state *st)
}
return 0;
}
+
+int buildin_soundeffectall(struct script_state *st)
+{
+ struct map_session_data *sd=script_rid2sd(st);
+ char *name;
+ int type=0;
+
+ name=conv_str(st,& (st->stack->stack_data[st->start+2]));
+ type=conv_num(st,& (st->stack->stack_data[st->start+3]));
+ if(sd)
+ {
+ if(st->oid)
+ clif_soundeffectall(map_id2bl(st->oid),name,type);
+ else
+ clif_soundeffectall(&sd->bl,name,type);
+ }
+ return 0;
+}
/*==========================================
* pet status recovery [Valaris]
*------------------------------------------
@@ -5663,9 +5987,9 @@ int buildin_petrecovery(struct script_state *st)
{
struct pet_data *pd;
- struct map_session_data *sd=script_rid2sd(st);
+ struct map_session_data *sd=script_rid2sd(st);
- if(sd==NULL || sd->pd==NULL)
+ if(sd==NULL || sd->pd==NULL)
return 0;
pd=sd->pd;
@@ -5689,9 +6013,9 @@ int buildin_petheal(struct script_state *st)
{
struct pet_data *pd;
- struct map_session_data *sd=script_rid2sd(st);
+ struct map_session_data *sd=script_rid2sd(st);
- if(sd==NULL || sd->pd==NULL)
+ if(sd==NULL || sd->pd==NULL)
return 0;
pd=sd->pd;
@@ -5707,7 +6031,7 @@ int buildin_petheal(struct script_state *st)
return 0;
}
-
+
/*==========================================
* pet magnificat [Valaris]
*------------------------------------------
@@ -5715,9 +6039,9 @@ int buildin_petheal(struct script_state *st)
int buildin_petmag(struct script_state *st)
{
struct pet_data *pd;
- struct map_session_data *sd=script_rid2sd(st);
+ struct map_session_data *sd=script_rid2sd(st);
- if(sd==NULL || sd->pd==NULL)
+ if(sd==NULL || sd->pd==NULL)
return 0;
pd=sd->pd;
@@ -5742,9 +6066,9 @@ int buildin_petmag(struct script_state *st)
int buildin_petskillattack(struct script_state *st)
{
struct pet_data *pd;
- struct map_session_data *sd=script_rid2sd(st);
+ struct map_session_data *sd=script_rid2sd(st);
- if(sd==NULL || sd->pd==NULL)
+ if(sd==NULL || sd->pd==NULL)
return 0;
pd=sd->pd;
@@ -5753,7 +6077,7 @@ int buildin_petskillattack(struct script_state *st)
return 0;
pd->skilltype=conv_num(st,& (st->stack->stack_data[st->start+2]));
- pd->skillval=conv_num(st,& (st->stack->stack_data[st->start+3]));
+ pd->skillval=conv_num(st,& (st->stack->stack_data[st->start+3]));
pd->skillduration=conv_num(st,& (st->stack->stack_data[st->start+4]));
pd->skilltimer=conv_num(st,& (st->stack->stack_data[st->start+5]));
@@ -5761,6 +6085,24 @@ int buildin_petskillattack(struct script_state *st)
return 0;
}
+
+/*==========================================
+ * Scripted skill effects [Celest]
+ *------------------------------------------
+ */
+int buildin_skilleffect(struct script_state *st)
+{
+ struct map_session_data *sd;
+
+ int skillid=conv_num(st,& (st->stack->stack_data[st->start+2]));
+ int skilllv=conv_num(st,& (st->stack->stack_data[st->start+3]));
+ sd=script_rid2sd(st);
+
+ clif_skill_nodamage(&sd->bl,&sd->bl,skillid,skilllv,1);
+
+ return 0;
+}
+
/*==========================================
* NPC skill effects [Valaris]
*------------------------------------------
@@ -5768,9 +6110,9 @@ int buildin_petskillattack(struct script_state *st)
int buildin_npcskilleffect(struct script_state *st)
{
struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid);
-
+
int skillid=conv_num(st,& (st->stack->stack_data[st->start+2]));
- int skilllv=conv_num(st,& (st->stack->stack_data[st->start+3]));
+ int skilllv=conv_num(st,& (st->stack->stack_data[st->start+3]));
int x=conv_num(st,& (st->stack->stack_data[st->start+4]));
int y=conv_num(st,& (st->stack->stack_data[st->start+5]));
@@ -5814,15 +6156,15 @@ int buildin_specialeffect2(struct script_state *st)
int buildin_nude(struct script_state *st)
{
- struct map_session_data *sd=script_rid2sd(st);
+ struct map_session_data *sd=script_rid2sd(st);
int i;
if(sd==NULL)
return 0;
-
- for(i=0;i<11;i++)
+
+ for(i=0;i<11;i++)
if(sd->equip_index[i] >= 0)
- pc_unequipitem(sd,sd->equip_index[i],1, BF_NORMAL);
+ pc_unequipitem(sd,sd->equip_index[i],2);
return 0;
}
@@ -5848,6 +6190,221 @@ int buildin_gmcommand(struct script_state *st)
}
/*==========================================
+ * Displays a message for the player only (like system messages like "you got an apple" )
+ *------------------------------------------
+ */
+int buildin_dispbottom(struct script_state *st)
+{
+ struct map_session_data *sd=script_rid2sd(st);
+ char *message;
+ message=conv_str(st,& (st->stack->stack_data[st->start+2]));
+ if(sd)
+ clif_disp_onlyself(sd,message,strlen(message));
+ return 0;
+}
+
+/*==========================================
+ * All The Players Full Recovery
+ (HP/SP full restore and resurrect if need)
+ *------------------------------------------
+ */
+int buildin_recovery(struct script_state *st)
+{
+ int i = 0;
+ for (i = 0; i < fd_max; i++) {
+ if (session[i]){
+ struct map_session_data *sd = (struct map_session_data *) session[i]->session_data;
+ if (sd && sd->state.auth) {
+ sd->status.hp = sd->status.max_hp;
+ sd->status.sp = sd->status.max_sp;
+ clif_updatestatus(sd, SP_HP);
+ clif_updatestatus(sd, SP_SP);
+ if(pc_isdead(sd)){
+ pc_setstand(sd);
+ clif_resurrection(&sd->bl, 1);
+ }
+ clif_displaymessage(sd->fd,"You have been recovered!");
+ }
+ }
+ }
+ return 0;
+}
+/*==========================================
+ * Get your pet info: getpetinfo(n)
+ * n -> 0:pet_id 1:pet_class 2:pet_name
+ 3:friendly 4:hungry
+ *------------------------------------------
+ */
+int buildin_getpetinfo(struct script_state *st)
+{
+ struct map_session_data *sd=script_rid2sd(st);
+ int type=conv_num(st,& (st->stack->stack_data[st->start+2]));
+
+ if(sd && sd->status.pet_id){
+ switch(type){
+ case 0:
+ push_val(st->stack,C_INT,sd->status.pet_id);
+ break;
+ case 1:
+ if(sd->pet.class_)
+ push_val(st->stack,C_INT,sd->pet.class_);
+ else
+ push_val(st->stack,C_INT,0);
+ break;
+ case 2:
+ if(sd->pet.name)
+ push_str(st->stack,C_STR,(unsigned char *) sd->pet.name);
+ else
+ push_val(st->stack,C_INT,0);
+ break;
+ case 3:
+ //if(sd->pet.intimate)
+ push_val(st->stack,C_INT,sd->pet.intimate);
+ break;
+ case 4:
+ //if(sd->pet.hungry)
+ push_val(st->stack,C_INT,sd->pet.hungry);
+ break;
+ default:
+ push_val(st->stack,C_INT,0);
+ break;
+ }
+ }else{
+ push_val(st->stack,C_INT,0);
+ }
+ return 0;
+}
+/*==========================================
+ * Shows wether your inventory(and equips) contain
+ selected card or not.
+ checkequipedcard(4001);
+ *------------------------------------------
+ */
+int buildin_checkequipedcard(struct script_state *st)
+{
+ struct map_session_data *sd=script_rid2sd(st);
+ int n,i,c=0;
+ c=conv_num(st,& (st->stack->stack_data[st->start+2]));
+
+ if(sd){
+ for(i=0;i<MAX_INVENTORY;i++){
+ if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount){
+ for(n=0;n<4;n++){
+ if(sd->status.inventory[i].card[n]==c){
+ push_val(st->stack,C_INT,1);
+ return 0;
+ }
+ }
+ }
+ }
+ }
+ push_val(st->stack,C_INT,0);
+ return 0;
+}
+
+int buildin_jump_zero(struct script_state *st) {
+ int sel;
+ sel=conv_num(st,& (st->stack->stack_data[st->start+2]));
+ if(!sel) {
+ int pos;
+ if( st->stack->stack_data[st->start+3].type!=C_POS ){
+ printf("script: jump_zero: not label !\n");
+ st->state=END;
+ return 0;
+ }
+
+ pos=conv_num(st,& (st->stack->stack_data[st->start+3]));
+ st->pos=pos;
+ st->state=GOTO;
+ // printf("script: jump_zero: jumpto : %d\n",pos);
+ } else {
+ // printf("script: jump_zero: fail\n");
+ }
+ return 0;
+}
+
+int buildin_select(struct script_state *st)
+{
+ char *buf;
+ int len,i;
+ struct map_session_data *sd;
+
+ sd=script_rid2sd(st);
+
+ if(sd->state.menu_or_input==0){
+ st->state=RERUNLINE;
+ sd->state.menu_or_input=1;
+ for(i=st->start+2,len=16;i<st->end;i++){
+ conv_str(st,& (st->stack->stack_data[i]));
+ len+=strlen(st->stack->stack_data[i].u.str)+1;
+ }
+ buf=(char *)aCalloc(len+1,sizeof(char));
+ buf[0]=0;
+ for(i=st->start+2,len=0;i<st->end;i++){
+ strcat(buf,st->stack->stack_data[i].u.str);
+ strcat(buf,":");
+ }
+ clif_scriptmenu(script_rid2sd(st),st->oid,buf);
+ aFree(buf);
+ } else if(sd->npc_menu==0xff){ // cansel
+ sd->state.menu_or_input=0;
+ st->state=END;
+ } else {
+ pc_setreg(sd,add_str((unsigned char *) "l15"),sd->npc_menu);
+ pc_setreg(sd,add_str((unsigned char *) "@menu"),sd->npc_menu);
+ sd->state.menu_or_input=0;
+ push_val(st->stack,C_INT,sd->npc_menu);
+ }
+ return 0;
+}
+
+/*==========================================
+ * GetMapMobs
+ returns mob counts on a set map:
+ e.g. GetMapMobs("prontera.gat")
+ use "this" - for player's map
+ *------------------------------------------
+ */
+int buildin_getmapmobs(struct script_state *st)
+{
+ char *str=NULL;
+ int m=-1,bx,by,i;
+ int count=0,c;
+ struct block_list *bl;
+
+ str=conv_str(st,& (st->stack->stack_data[st->start+2]));
+
+ if(strcmp(str,"this")==0){
+ struct map_session_data *sd=script_rid2sd(st);
+ if(sd)
+ m=sd->bl.m;
+ else{
+ push_val(st->stack,C_INT,-1);
+ return 0;
+ }
+ }else
+ m=map_mapname2mapid(str);
+
+ if(m < 0){
+ push_val(st->stack,C_INT,-1);
+ return 0;
+ }
+
+ for(by=0;by<=(map[m].ys-1)/BLOCK_SIZE;by++){
+ for(bx=0;bx<=(map[m].xs-1)/BLOCK_SIZE;bx++){
+ bl = map[m].block_mob[bx+by*map[m].bxs];
+ c = map[m].block_mob_count[bx+by*map[m].bxs];
+ for(i=0;i<c && bl;i++,bl=bl->next){
+ if(bl->x>=0 && bl->x<=map[m].xs-1 && bl->y>=0 && bl->y<=map[m].ys-1)
+ count++;
+ }
+ }
+ }
+ push_val(st->stack,C_INT,count);
+ return 0;
+}
+
+/*==========================================
* movenpc [MouseJstr]
*------------------------------------------
*/
@@ -5896,7 +6453,7 @@ int buildin_message(struct script_state *st)
* area) [Valaris]
*------------------------------------------
*/
-
+
int buildin_npctalk(struct script_state *st)
{
char *str;
@@ -5926,16 +6483,16 @@ int buildin_hasitems(struct script_state *st)
{
int i;
struct map_session_data *sd;
-
+
sd=script_rid2sd(st);
-
+
for(i=0; i<MAX_INVENTORY; i++) {
if(sd->status.inventory[i].amount) {
push_val(st->stack,C_INT,1);
return 0;
}
}
-
+
push_val(st->stack,C_INT,0);
return 0;
@@ -6040,14 +6597,14 @@ int buildin_getsavepoint(struct script_state *st)
sd=script_rid2sd(st);
type=conv_num(st,& (st->stack->stack_data[st->start+2]));
- mapname=calloc(24, 1);
+ mapname=(char *) aCallocA(24, 1);
x=sd->status.save_point.x;
y=sd->status.save_point.y;
strncpy(mapname,sd->status.save_point.map,24);
switch(type){
case 0:
- push_str(st->stack,C_STR,mapname);
+ push_str(st->stack,C_STR,(unsigned char *) mapname);
break;
case 1:
push_val(st->stack,C_INT,x);
@@ -6109,7 +6666,7 @@ int buildin_getmapxy(struct script_state *st){
//??????????? >>> Possible needly check function parameters on C_STR,C_INT,C_INT <<< ???????????//
type=conv_num(st,& (st->stack->stack_data[st->start+5]));
- mapname=calloc(24, 1);
+ mapname=(char *) aCallocA(24, 1);
switch (type){
case 0: //Get Character Position
@@ -6141,7 +6698,7 @@ int buildin_getmapxy(struct script_state *st){
}
x=nd->bl.x;
- y=nd->bl.y;
+ y=nd->bl.y;
strncpy(mapname,map[nd->bl.m].name,24);
printf(">>>>%s %d %d\n",mapname,x,y);
break;
@@ -6163,7 +6720,7 @@ int buildin_getmapxy(struct script_state *st){
return 0;
}
x=pd->bl.x;
- y=pd->bl.y;
+ y=pd->bl.y;
strncpy(mapname,map[pd->bl.m].name,24);
printf(">>>>%s %d %d\n",mapname,x,y);
@@ -6218,6 +6775,260 @@ int buildin_getmapxy(struct script_state *st){
return 0;
}
+/*=====================================================
+ * Allows players to use a skill - by Qamera
+ *-----------------------------------------------------
+ */
+int buildin_skilluseid (struct script_state *st)
+{
+ int skid,sklv;
+ struct map_session_data *sd;
+
+ skid=conv_num(st,& (st->stack->stack_data[st->start+2]));
+ sklv=conv_num(st,& (st->stack->stack_data[st->start+3]));
+ sd=script_rid2sd(st);
+ skill_use_id(sd,sd->status.account_id,skid,sklv);
+
+ return 0;
+}
+
+/*=====================================================
+ * Allows players to use a skill on a position [Celest]
+ *-----------------------------------------------------
+ */
+int buildin_skillusepos(struct script_state *st)
+{
+ int skid,sklv,x,y;
+ struct map_session_data *sd;
+
+ skid=conv_num(st,& (st->stack->stack_data[st->start+2]));
+ sklv=conv_num(st,& (st->stack->stack_data[st->start+3]));
+ x=conv_num(st,& (st->stack->stack_data[st->start+4]));
+ y=conv_num(st,& (st->stack->stack_data[st->start+5]));
+
+ sd=script_rid2sd(st);
+ skill_use_pos(sd,x,y,skid,sklv);
+
+ return 0;
+}
+
+/*==========================================
+ * Allows player to write NPC logs (i.e. Bank NPC, etc) [Lupus]
+ *------------------------------------------
+ */
+int buildin_logmes(struct script_state *st)
+{
+ if (log_config.npc <= 0 ) return 0;
+ conv_str(st,& (st->stack->stack_data[st->start+2]));
+ log_npc(script_rid2sd(st),st->stack->stack_data[st->start+2].u.str);
+ return 0;
+}
+
+int buildin_summon(struct script_state *st)
+{
+ int _class, id;
+ char *str,*event="";
+ struct map_session_data *sd;
+ struct mob_data *md;
+
+ sd=script_rid2sd(st);
+ if (sd) {
+ int tick = gettick();
+ str =conv_str(st,& (st->stack->stack_data[st->start+2]));
+ _class=conv_num(st,& (st->stack->stack_data[st->start+3]));
+ if( st->end>st->start+4 )
+ event=conv_str(st,& (st->stack->stack_data[st->start+4]));
+
+ id=mob_once_spawn(sd, "this", 0, 0, str,_class,1,event);
+ if((md=(struct mob_data *)map_id2bl(id))){
+ md->master_id=sd->bl.id;
+ md->state.special_mob_ai=1;
+ md->mode=mob_db[md->class_].mode|0x04;
+ md->deletetimer=add_timer(tick+60000,mob_timer_delete,id,0);
+ clif_misceffect2(&md->bl,344);
+ }
+ clif_skill_poseffect(&sd->bl,AM_CALLHOMUN,1,sd->bl.x,sd->bl.y,tick);
+ }
+
+ return 0;
+}
+
+int buildin_isnight(struct script_state *st)
+{
+ push_val(st->stack,C_INT, (night_flag == 1));
+ return 0;
+}
+
+int buildin_isday(struct script_state *st)
+{
+ push_val(st->stack,C_INT, (night_flag == 0));
+ return 0;
+}
+
+/*================================================
+ * Check whether another item/card has been
+ * equipped - used for 2/15's cards patch [celest]
+ *------------------------------------------------
+ */
+int buildin_isequipped(struct script_state *st)
+{
+ struct map_session_data *sd;
+ int i, j, k, id = 1;
+ int ret = -1;
+
+ sd = script_rid2sd(st);
+
+ for (i=0; id!=0; i++) {
+ int flag = 0;
+
+ FETCH (i+2, id) else id = 0;
+ if (id <= 0)
+ continue;
+
+ for (j=0; j<10; j++) {
+ int index, type;
+ index = sd->equip_index[j];
+ if(index < 0) continue;
+ if(j == 9 && sd->equip_index[8] == index) continue;
+ if(j == 5 && sd->equip_index[4] == index) continue;
+ if(j == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index)) continue;
+ type = itemdb_type(id);
+
+ if(sd->inventory_data[index]) {
+ if (type == 4 || type == 5) {
+ if (sd->inventory_data[index]->nameid == id)
+ flag = 1;
+ } else if (type == 6) {
+ for(k=0; k<sd->inventory_data[index]->slot; k++) {
+ if (sd->status.inventory[index].card[0]!=0x00ff &&
+ sd->status.inventory[index].card[0]!=0x00fe &&
+ sd->status.inventory[index].card[0]!=(short)0xff00 &&
+ sd->status.inventory[index].card[k] == id) {
+ flag = 1;
+ break;
+ }
+ }
+ }
+ if (flag) break;
+ }
+ }
+ if (ret == -1)
+ ret = flag;
+ else
+ ret &= flag;
+ if (!ret) break;
+ }
+
+ push_val(st->stack,C_INT,ret);
+ return 0;
+}
+
+/*================================================
+ * Check how many items/cards in the list are
+ * equipped - used for 2/15's cards patch [celest]
+ *------------------------------------------------
+ */
+int buildin_isequippedcnt(struct script_state *st)
+{
+ struct map_session_data *sd;
+ int i, j, k, id = 1;
+ int ret = 0;
+
+ sd = script_rid2sd(st);
+
+ for (i=0; id!=0; i++) {
+ FETCH (i+2, id) else id = 0;
+ if (id <= 0)
+ continue;
+
+ for (j=0; j<10; j++) {
+ int index, type;
+ index = sd->equip_index[j];
+ if(index < 0) continue;
+ if(j == 9 && sd->equip_index[8] == index) continue;
+ if(j == 5 && sd->equip_index[4] == index) continue;
+ if(j == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index)) continue;
+ type = itemdb_type(id);
+
+ if(sd->inventory_data[index]) {
+ if (type == 4 || type == 5) {
+ if (sd->inventory_data[index]->nameid == id)
+ ret++; //[Lupus]
+ } else if (type == 6) {
+ for(k=0; k<sd->inventory_data[index]->slot; k++) {
+ if (sd->status.inventory[index].card[0]!=0x00ff &&
+ sd->status.inventory[index].card[0]!=0x00fe &&
+ sd->status.inventory[index].card[0]!=(short)0xff00 &&
+ sd->status.inventory[index].card[k] == id) {
+ ret++; //[Lupus]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ push_val(st->stack,C_INT,ret);
+ return 0;
+}
+
+/*================================================
+ * Check how many given inserted cards in the CURRENT
+ * weapon - used for 2/15's cards patch [Lupus]
+ *------------------------------------------------
+ */
+int buildin_cardscnt(struct script_state *st)
+{
+ struct map_session_data *sd;
+ int i, k, id = 1;
+ int ret = 0;
+ int index, type;
+
+ sd = script_rid2sd(st);
+
+ for (i=0; id!=0; i++) {
+ FETCH (i+2, id) else id = 0;
+ if (id <= 0)
+ continue;
+
+ index = current_equip_item_index; //we get CURRENT WEAPON inventory index from status.c [Lupus]
+ if(index < 0) continue;
+
+ type = itemdb_type(id);
+
+ if(sd->inventory_data[index]) {
+ if (type == 4 || type == 5) {
+ if (sd->inventory_data[index]->nameid == id)
+ ret++;
+ } else if (type == 6) {
+ for(k=0; k<sd->inventory_data[index]->slot; k++) {
+ if (sd->status.inventory[index].card[0]!=0x00ff &&
+ sd->status.inventory[index].card[0]!=0x00fe &&
+ sd->status.inventory[index].card[0]!=(short)0xff00 &&
+ sd->status.inventory[index].card[k] == id) {
+ ret++;
+ }
+ }
+ }
+ }
+ }
+ push_val(st->stack,C_INT,ret);
+// push_val(st->stack,C_INT,current_equip_item_index);
+ return 0;
+}
+
+/*=======================================================
+ * Returns the refined number of the current item, or an
+ * item with inventory index specified
+ *-------------------------------------------------------
+ */
+int buildin_getrefine(struct script_state *st)
+{
+ struct map_session_data *sd;
+ if ((sd = script_rid2sd(st))!= NULL)
+ push_val(st->stack, C_INT, sd->status.inventory[current_equip_item_index].refine);
+ return 0;
+}
//
// 実行部main
@@ -6309,14 +7120,14 @@ void op_add(struct script_state* st)
st->stack->stack_data[st->stack->sp-1].u.num += st->stack->stack_data[st->stack->sp].u.num;
} else { // ssの予定
char *buf;
- buf=(char *)aCalloc(strlen(st->stack->stack_data[st->stack->sp-1].u.str)+
+ buf=(char *)aCallocA(strlen(st->stack->stack_data[st->stack->sp-1].u.str)+
strlen(st->stack->stack_data[st->stack->sp].u.str)+1,sizeof(char));
strcpy(buf,st->stack->stack_data[st->stack->sp-1].u.str);
strcat(buf,st->stack->stack_data[st->stack->sp].u.str);
if(st->stack->stack_data[st->stack->sp-1].type==C_STR)
- free(st->stack->stack_data[st->stack->sp-1].u.str);
+ aFree(st->stack->stack_data[st->stack->sp-1].u.str);
if(st->stack->stack_data[st->stack->sp].type==C_STR)
- free(st->stack->stack_data[st->stack->sp].u.str);
+ aFree(st->stack->stack_data[st->stack->sp].u.str);
st->stack->stack_data[st->stack->sp-1].type=C_STR;
st->stack->stack_data[st->stack->sp-1].u.str=buf;
}
@@ -6358,8 +7169,8 @@ void op_2str(struct script_state *st,int op,int sp1,int sp2)
push_val(st->stack,C_INT,a);
- if(st->stack->stack_data[sp1].type==C_STR) free(s1);
- if(st->stack->stack_data[sp2].type==C_STR) free(s2);
+ if(st->stack->stack_data[sp1].type==C_STR) aFree(s1);
+ if(st->stack->stack_data[sp2].type==C_STR) aFree(s2);
}
/*==========================================
* 二項演算子(数値)
@@ -6373,7 +7184,11 @@ void op_2num(struct script_state *st,int op,int i1,int i2)
break;
case C_MUL:
{
+ #ifndef _MSC_VER
long long res = i1 * i2;
+ #else
+ __int64 res = i1 * i2;
+ #endif
if (res > 2147483647 )
i1 = 2147483647;
else
@@ -6572,7 +7387,7 @@ int run_func(struct script_state *st)
* スクリプトの実行メイン部分
*------------------------------------------
*/
-int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_state *st,unsigned char *rootscript)
+int run_script_main(char *script,int pos,int rid,int oid,struct script_state *st,char *rootscript)
{
int c,rerun_pos;
int cmdcount=script_config.check_cmdcount;
@@ -6584,7 +7399,7 @@ int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_
rerun_pos=st->pos;
for(st->state=0;st->state==0;){
- switch(c=get_com(script,&st->pos)){
+ switch(c= get_com((unsigned char *) script,&st->pos)){
case C_EOL:
if(stack->sp!=st->defsp){
if(battle_config.error_log)
@@ -6594,7 +7409,7 @@ int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_
rerun_pos=st->pos;
break;
case C_INT:
- push_val(stack,C_INT,get_num(script,&st->pos));
+ push_val(stack,C_INT,get_num((unsigned char *) script,&st->pos));
break;
case C_POS:
case C_NAME:
@@ -6605,7 +7420,7 @@ int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_
push_val(stack,c,0);
break;
case C_STR:
- push_str(stack,C_CONSTSTR,script+st->pos);
+ push_str(stack,C_CONSTSTR,(unsigned char *) (script+st->pos));
while(script[st->pos++]);
break;
case C_FUNC:
@@ -6689,7 +7504,7 @@ int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_
struct map_session_data *sd=map_id2sd(st->rid);
if(sd/* && sd->npc_stackbuf==NULL*/){
if( sd->npc_stackbuf )
- free( sd->npc_stackbuf );
+ aFree( sd->npc_stackbuf );
sd->npc_stackbuf = (char *)aCalloc(sizeof(stack->stack_data[0])*stack->sp_max,sizeof(char));
memcpy(sd->npc_stackbuf, stack->stack_data, sizeof(stack->stack_data[0]) * stack->sp_max);
sd->npc_stack = stack->sp;
@@ -6706,24 +7521,24 @@ int run_script_main(unsigned char *script,int pos,int rid,int oid,struct script_
* スクリプトの実行
*------------------------------------------
*/
-int run_script(unsigned char *script,int pos,int rid,int oid)
+int run_script(char *script,int pos,int rid,int oid)
{
struct script_stack stack;
struct script_state st;
struct map_session_data *sd=map_id2sd(rid);
- unsigned char *rootscript=script;
+ char *rootscript=script;
if(script==NULL || pos<0)
return -1;
- if(sd && sd->npc_stackbuf && sd->npc_scriptroot==(char*)rootscript){
+ if(sd && sd->npc_stackbuf && sd->npc_scriptroot==rootscript){
// 前回のスタックを復帰
script=sd->npc_script;
stack.sp=sd->npc_stack;
stack.sp_max=sd->npc_stackmax;
stack.stack_data=(struct script_data *)aCalloc(stack.sp_max,sizeof(stack.stack_data[0]));
memcpy(stack.stack_data,sd->npc_stackbuf,sizeof(stack.stack_data[0])*stack.sp_max);
- free(sd->npc_stackbuf);
+ aFree(sd->npc_stackbuf);
sd->npc_stackbuf=NULL;
}else{
// スタック初期化
@@ -6737,7 +7552,7 @@ int run_script(unsigned char *script,int pos,int rid,int oid)
st.oid=oid;
run_script_main(script,pos,rid,oid,&st,rootscript);
- free(stack.stack_data);
+ aFree(stack.stack_data);
stack.stack_data=NULL;
return st.pos;
}
@@ -6765,15 +7580,15 @@ int mapreg_setregstr(int num,const char *str)
{
char *p;
- if( (p=numdb_search(mapregstr_db,num))!=NULL )
- free(p);
+ if( (p=(char *) numdb_search(mapregstr_db,num))!=NULL )
+ aFree(p);
if( str==NULL || *str==0 ){
numdb_erase(mapregstr_db,num);
mapreg_dirty=1;
return 0;
}
- p=(char *)aCalloc(strlen(str)+1, sizeof(char));
+ p=(char *)aCallocA(strlen(str)+1, sizeof(char));
strcpy(p,str);
numdb_insert(mapregstr_db,num,p);
mapreg_dirty=1;
@@ -6803,16 +7618,16 @@ static int script_load_mapreg()
printf("%s: %s broken data !\n",mapreg_txt,buf1);
continue;
}
- p=(char *)aCalloc(strlen(buf2) + 1,sizeof(char));
+ p=(char *)aCallocA(strlen(buf2) + 1,sizeof(char));
strcpy(p,buf2);
- s=add_str(buf1);
+ s= add_str((unsigned char *) buf1);
numdb_insert(mapregstr_db,(i<<24)|s,p);
}else{
if( sscanf(line+n,"%d",&v)!=1 ){
printf("%s: %s broken data !\n",mapreg_txt,buf1);
continue;
}
- s=add_str(buf1);
+ s= add_str((unsigned char *) buf1);
numdb_insert(mapreg_db,(i<<24)|s,v);
}
}
@@ -6871,7 +7686,7 @@ static int script_autosave_mapreg(int tid,unsigned int tick,int id,int data)
}
/*==========================================
- *
+ *
*------------------------------------------
*/
static int set_posword(char *p)
@@ -6903,8 +7718,16 @@ int script_config_read(char *cfgName)
script_config.warn_cmd_no_comma=1;
script_config.warn_func_mismatch_paramnum=1;
script_config.warn_cmd_mismatch_paramnum=1;
- script_config.check_cmdcount=8192;
- script_config.check_gotocount=512;
+ script_config.check_cmdcount=65535;
+ script_config.check_gotocount=2048;
+
+ script_config.die_event_name = (char *)aCallocA(24,sizeof(char));
+ script_config.kill_event_name = (char *)aCallocA(24,sizeof(char));
+ script_config.login_event_name = (char *)aCallocA(24,sizeof(char));
+ script_config.logout_event_name = (char *)aCallocA(24,sizeof(char));
+
+ script_config.event_script_type = 0;
+ script_config.event_requires_trigger = 1;
fp=fopen(cfgName,"r");
if(fp==NULL){
@@ -6920,7 +7743,43 @@ int script_config_read(char *cfgName)
if(strcmpi(w1,"refine_posword")==0) {
set_posword(w2);
}
- if(strcmpi(w1,"import")==0){
+ else if(strcmpi(w1,"warn_func_no_comma")==0) {
+ script_config.warn_func_no_comma = battle_config_switch(w2);
+ }
+ else if(strcmpi(w1,"warn_cmd_no_comma")==0) {
+ script_config.warn_cmd_no_comma = battle_config_switch(w2);
+ }
+ else if(strcmpi(w1,"warn_func_mismatch_paramnum")==0) {
+ script_config.warn_func_mismatch_paramnum = battle_config_switch(w2);
+ }
+ else if(strcmpi(w1,"warn_cmd_mismatch_paramnum")==0) {
+ script_config.warn_cmd_mismatch_paramnum = battle_config_switch(w2);
+ }
+ else if(strcmpi(w1,"check_cmdcount")==0) {
+ script_config.check_cmdcount = battle_config_switch(w2);
+ }
+ else if(strcmpi(w1,"check_gotocount")==0) {
+ script_config.check_gotocount = battle_config_switch(w2);
+ }
+ else if(strcmpi(w1,"event_script_type")==0) {
+ script_config.event_script_type = battle_config_switch(w2);
+ }
+ else if(strcmpi(w1,"die_event_name")==0) {
+ strcpy(script_config.die_event_name, w2);
+ }
+ else if(strcmpi(w1,"kill_event_name")==0) {
+ strcpy(script_config.kill_event_name, w2);
+ }
+ else if(strcmpi(w1,"login_event_name")==0) {
+ strcpy(script_config.login_event_name, w2);
+ }
+ else if(strcmpi(w1,"logout_event_name")==0) {
+ strcpy(script_config.logout_event_name, w2);
+ }
+ else if(strcmpi(w1,"require_set_trigger")==0) {
+ script_config.event_requires_trigger = battle_config_switch(w2);
+ }
+ else if(strcmpi(w1,"import")==0){
script_config_read(w2);
}
}
@@ -6939,7 +7798,7 @@ static int mapreg_db_final(void *key,void *data,va_list ap)
}
static int mapregstr_db_final(void *key,void *data,va_list ap)
{
- free(data);
+ aFree(data);
return 0;
}
static int scriptlabel_db_final(void *key,void *data,va_list ap)
@@ -6948,16 +7807,16 @@ static int scriptlabel_db_final(void *key,void *data,va_list ap)
}
static int userfunc_db_final(void *key,void *data,va_list ap)
{
- free(key);
- free(data);
+ aFree(key);
+ aFree(data);
return 0;
}
int do_final_script()
{
if(mapreg_dirty>=0)
script_save_mapreg();
- if(script_buf)
- free(script_buf);
+// if(script_buf)
+// aFree(script_buf);
if(mapreg_db)
numdb_final(mapreg_db,mapreg_db_final);
@@ -6968,10 +7827,19 @@ int do_final_script()
if(userfunc_db)
strdb_final(userfunc_db,userfunc_db_final);
- if (str_data)
- free(str_data);
- if (str_buf)
- free(str_buf);
+ if (str_data)
+ aFree(str_data);
+ if (str_buf)
+ aFree(str_buf);
+
+ if (script_config.die_event_name)
+ aFree(script_config.die_event_name);
+ if (script_config.kill_event_name)
+ aFree(script_config.kill_event_name);
+ if (script_config.login_event_name)
+ aFree(script_config.login_event_name);
+ if (script_config.logout_event_name)
+ aFree(script_config.logout_event_name);
return 0;
}
diff --git a/src/map/script.h b/src/map/script.h
index b50c46693..b30201a67 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -2,6 +2,22 @@
#ifndef _SCRIPT_H_
#define _SCRIPT_H_
+extern struct Script_Config {
+ int warn_func_no_comma;
+ int warn_cmd_no_comma;
+ int warn_func_mismatch_paramnum;
+ int warn_cmd_mismatch_paramnum;
+ int check_cmdcount;
+ int check_gotocount;
+
+ int event_script_type;
+ char* die_event_name;
+ char* kill_event_name;
+ char* login_event_name;
+ char* logout_event_name;
+ int event_requires_trigger;
+} script_config;
+
struct script_data {
int type;
union {
@@ -23,8 +39,12 @@ struct script_state {
int defsp,new_pos,new_defsp;
};
-unsigned char * parse_script(unsigned char *,int);
-int run_script(unsigned char *,int,int,int);
+char * parse_script(unsigned char *,int);
+int run_script(char *,int,int,int);
+
+int set_var(struct map_session_data *sd, char *name, void *val);
+int conv_num(struct script_state *st,struct script_data *data);
+char* conv_str(struct script_state *st,struct script_data *data);
struct dbt* script_get_label_db();
struct dbt* script_get_userfunc_db();
diff --git a/src/map/skill.c b/src/map/skill.c
index dc708c906..c53a7a9d6 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -1,4 +1,4 @@
-// $Id: skill.c,v 1.8 2004/11/26 7:12:23 PM Celestia Exp $
+// $Id: skill.c,v 1.8 2004/02/27 5:34:51 PM Celestia $
/* スキル?係 */
#include <stdio.h>
@@ -14,6 +14,7 @@
#include "map.h"
#include "clif.h"
#include "pc.h"
+#include "status.h"
#include "pet.h"
#include "mob.h"
#include "battle.h"
@@ -24,245 +25,16 @@
#include "log.h"
#include "chrif.h"
#include "guild.h"
+#include "showmsg.h"
+#include "grfio.h"
#ifdef MEMWATCH
#include "memwatch.h"
#endif
#define SKILLUNITTIMER_INVERVAL 100
-
#define STATE_BLIND 0x10
-
-/* スキル番?=>ステ?タス異常番??換テ?ブル */
-int SkillStatusChangeTable[]={ /* skill.hのenumのSC_***とあわせること */
-/* 0- */
- -1,-1,-1,-1,-1,-1,
- SC_PROVOKE, /* プロボック */
- -1, 1,-1,
-/* 10- */
- SC_SIGHT, /* サイト */
- -1,-1,-1,-1,
- SC_FREEZE, /* フロストダイバ? */
- SC_STONE, /* スト?ンカ?ス */
- -1,-1,-1,
-/* 20- */
- -1,-1,-1,-1,
- SC_RUWACH, /* ルアフ */
- -1,-1,-1,-1,
- SC_INCREASEAGI, /* 速度?加 */
-/* 30- */
- SC_DECREASEAGI, /* 速度減少 */
- -1,
- SC_SIGNUMCRUCIS, /* シグナムクルシス */
- SC_ANGELUS, /* エンジェラス */
- SC_BLESSING, /* ブレッシング */
- -1,-1,-1,-1,-1,
-/* 40- */
- -1,-1,-1,-1,-1,
- SC_CONCENTRATE, /* 集中力向上 */
- -1,-1,-1,-1,
-/* 50- */
- -1,
- SC_HIDING, /* ハイディング */
- -1,-1,-1,-1,-1,-1,-1,-1,
-/* 60- */
- SC_TWOHANDQUICKEN, /* 2HQ */
- SC_AUTOCOUNTER,
- -1,-1,-1,-1,
- SC_IMPOSITIO, /* インポシティオマヌス */
- SC_SUFFRAGIUM, /* サフラギウム */
- SC_ASPERSIO, /* アスペルシオ */
- SC_BENEDICTIO, /* 聖?降福 */
-/* 70- */
- -1,
- SC_SLOWPOISON,
- -1,
- SC_KYRIE, /* キリエエレイソン */
- SC_MAGNIFICAT, /* マグニフィカ?ト */
- SC_GLORIA, /* グロリア */
- SC_DIVINA, /* レックスディビ?ナ */
- -1,
- SC_AETERNA, /* レックスエ?テルナ */
- -1,
-/* 80- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-/* 90- */
- -1,-1,
- SC_QUAGMIRE, /* クァグマイア */
- -1,-1,-1,-1,-1,-1,-1,
-/* 100- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-/* 110- */
- -1,
- SC_ADRENALINE, /* アドレナリンラッシュ */
- SC_WEAPONPERFECTION,/* ウェポンパ?フェクション */
- SC_OVERTHRUST, /* オ?バ?トラスト */
- SC_MAXIMIZEPOWER, /* マキシマイズパワ? */
- -1,-1,-1,-1,-1,
-/* 120- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-/* 130- */
- -1,-1,-1,-1,-1,
- SC_CLOAKING, /* クロ?キング */
- SC_STAN, /* ソニックブロ? */
- -1,
- SC_ENCPOISON, /* エンチャントポイズン */
- SC_POISONREACT, /* ポイズンリアクト */
-/* 140- */
- SC_POISON, /* ベノムダスト */
- SC_SPLASHER, /* ベナムスプラッシャ? */
- -1,
- SC_TRICKDEAD, /* 死んだふり */
- -1,-1,-1,-1,-1,-1,
-/* 150- */
- -1,-1,-1,-1,-1,
- SC_LOUD, /* ラウドボイス */
- -1,
- SC_ENERGYCOAT, /* エナジ?コ?ト */
- -1,-1,
-/* 160- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,
- SC_SELFDESTRUCTION,
- -1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
- -1,
- SC_KEEPING,
- -1,-1,
- SC_BARRIER,
- -1,-1,
- SC_HALLUCINATION,
- -1,-1,
-/* 210- */
- -1,-1,-1,-1,-1,
- SC_STRIPWEAPON,
- SC_STRIPSHIELD,
- SC_STRIPARMOR,
- SC_STRIPHELM,
- -1,
-/* 220- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-/* 230- */
- -1,-1,-1,-1,
- SC_CP_WEAPON,
- SC_CP_SHIELD,
- SC_CP_ARMOR,
- SC_CP_HELM,
- -1,-1,
-/* 240- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,
- SC_AUTOGUARD,
-/* 250- */
- -1,-1,
- SC_REFLECTSHIELD,
- -1,-1,
- SC_DEVOTION,
- SC_PROVIDENCE,
- SC_DEFENDER,
- SC_SPEARSQUICKEN,
- -1,
-/* 260- */
- -1,-1,-1,-1,-1,-1,-1,-1,
- SC_STEELBODY,
- SC_BLADESTOP_WAIT,
-/* 270- */
- SC_EXPLOSIONSPIRITS,
- SC_EXTREMITYFIST,
- -1,-1,-1,-1,
- SC_MAGICROD,
- -1,-1,-1,
-/* 280- */
- SC_FLAMELAUNCHER,
- SC_FROSTWEAPON,
- SC_LIGHTNINGLOADER,
- SC_SEISMICWEAPON,
- -1,
- SC_VOLCANO,
- SC_DELUGE,
- SC_VIOLENTGALE,
- SC_LANDPROTECTOR,
- -1,
-/* 290- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-/* 300- */
- -1,-1,-1,-1,-1,-1,
- SC_LULLABY,
- SC_RICHMANKIM,
- SC_ETERNALCHAOS,
- SC_DRUMBATTLE,
-/* 310- */
- SC_NIBELUNGEN,
- SC_ROKISWEIL,
- SC_INTOABYSS,
- SC_SIEGFRIED,
- -1,-1,-1,
- SC_DISSONANCE,
- -1,
- SC_WHISTLE,
-/* 320- */
- SC_ASSNCROS,
- SC_POEMBRAGI,
- SC_APPLEIDUN,
- -1,-1,
- SC_UGLYDANCE,
- -1,
- SC_HUMMING,
- SC_DONTFORGETME,
- SC_FORTUNE,
-/* 330- */
- SC_SERVICE4U,
- SC_SELFDESTRUCTION,
- -1,-1,-1,-1,-1,-1,-1,-1,
-/* 340- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-/* 350- */
- -1,-1,-1,-1,-1,
- SC_AURABLADE,
- SC_PARRYING,
- SC_CONCENTRATION,
- SC_TENSIONRELAX,
- SC_BERSERK,
-/* 360- */
- SC_BERSERK,
- SC_ASSUMPTIO,
- SC_BASILICA,
- -1,-1,-1,
- SC_MAGICPOWER,
- -1,-1,
- SC_GOSPEL,
-/* 370- */
- -1,-1,-1,-1,-1,-1,-1,-1,
-
- SC_EDP,
-
- -1,
-/* 380- */
- SC_TRUESIGHT,
- -1,-1,
- SC_WINDWALK,
- SC_MELTDOWN,
- -1,-1,
- SC_CARTBOOST,
- -1,
- SC_CHASEWALK,
-/* 390- */
- SC_REJECTSWORD,
- -1,-1,-1,-1,-1,
- SC_MARIONETTE,
- -1,
- SC_HEADCRUSH,
- SC_JOINTBEAT,
-/* 400 */
- -1,-1,
- SC_MINDBREAKER,
- SC_MEMORIZE,
- SC_FOGWALL,
- SC_SPIDERWEB,
- -1,-1,-1,-1,
-/* 410- */
- -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-};
+#define swap(x,y) { int t; t = x; x = y; y = t; }
const struct skill_name_db skill_names[] = {
{ AC_CHARGEARROW, "CHARGEARROW", "Charge_Arrow" } ,
@@ -398,6 +170,10 @@ const struct skill_name_db skill_names[] = {
{ DC_SERVICEFORYOU, "SERVICEFORYOU", "Prostitute" } ,
{ DC_THROWARROW, "THROWARROW", "Throw_Arrow" } ,
{ DC_UGLYDANCE, "UGLYDANCE", "Ugly_Dance" } ,
+ { GD_BATTLEORDER, "BATTLEORDER", "Battle_Orders" } ,
+ { GD_REGENERATION, "REGENERATION", "Regeneration" } ,
+ { GD_RESTORE, "RESTORE", "Restore" } ,
+ { GD_EMERGENCYCALL, "EMERGENCYCALL", "Emergency_Call" } ,
{ HP_ASSUMPTIO, "ASSUMPTIO", "Assumptio" } ,
{ HP_BASILICA, "BASILICA", "Basilica" } ,
{ HP_MEDITATIO, "MEDITATIO", "Meditation" } ,
@@ -698,9 +474,9 @@ const struct skill_name_db skill_names[] = {
{ TK_SPTIME, "SPTIME", "SP Time" } ,
{ TK_STORMKICK, "STORMKICK", "Storm Kick" } ,
{ TK_TURNKICK, "TURNKICK", "Turn Kick" } ,
- { WE_BABY, "BABY", "Adopt_Baby" } ,
- { WE_CALLBABY, "CALLBABY", "Call_Baby" } ,
- { WE_CALLPARENT, "CALLPARENT", "Call_Parent" } ,
+ { WE_BABY, "BABY", "I Love Mama and Fafa" } ,
+ { WE_CALLBABY, "CALLBABY", "Come With Me, Baby" } ,
+ { WE_CALLPARENT, "CALLPARENT", "I Miss My Parents" } ,
{ WE_CALLPARTNER, "CALLPARTNER", "I Want to See You" } ,
{ WE_FEMALE, "FEMALE", "I Only Look Up to You" } ,
{ WE_MALE, "MALE", "I Will Protect You" } ,
@@ -724,7 +500,7 @@ const struct skill_name_db skill_names[] = {
{ WZ_STORMGUST, "STORMGUST", "Storm_Gust" } ,
{ WZ_VERMILION, "VERMILION", "Lord_of_Vermilion" } ,
{ WZ_WATERBALL, "WATERBALL", "Water_Ball" } ,
- { 0, 0, 0 }
+ { 0, 0, 0 }
};
static const int dirx[8]={0,-1,-1,-1,0,1,1,1};
@@ -744,94 +520,49 @@ struct skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB];
/* アブラカダブラ?動スキルデ?タベ?ス */
struct skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB];
-int skill_get_hit( int id ){
- if (id >= 10000 && id < 10015) id -= 9500;
- return skill_db[id].hit;
-}
-int skill_get_inf( int id ){
- return (id < 500) ? skill_db[id].inf : guild_skill_get_inf(id);
-}
-int skill_get_pl( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].pl;
-}
-int skill_get_nk( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].nk;
-}
-int skill_get_max( int id ){
- return (id < 500) ? skill_db[id].max : guild_skill_get_max(id);
-}
-int skill_get_range( int id , int lv ){
- if (lv <= 0) return 0;
- return (id < 500) ? skill_db[id].range[lv-1] : guild_skill_get_range(id);
-}
-int skill_get_hp( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0: skill_db[id].hp[lv-1];
-}
-int skill_get_sp( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- //if (lv <= 0) return 0;
- //return (id < 500) ? skill_db[id].sp[lv-1] : guild_skill_get_sp(id, lv);
- return (lv <= 0) ? 0: skill_db[id].sp[lv-1];
-}
-int skill_get_zeny( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].zeny[lv-1];
-}
-int skill_get_num( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].num[lv-1];
-}
-int skill_get_cast( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].cast[lv-1];
-}
-int skill_get_delay( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].delay[lv-1];
-}
-int skill_get_time( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].upkeep_time[lv-1];
-}
-int skill_get_time2( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].upkeep_time2[lv-1];
-}
-int skill_get_castdef( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].cast_def_rate;
-}
-int skill_get_weapontype( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].weapon;
-}
-int skill_get_inf2( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].inf2;
-}
-int skill_get_castcancel( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].maxcount;
-}
-int skill_get_maxcount( int id ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return skill_db[id].maxcount;
-}
-int skill_get_blewcount( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].blewcount[lv-1];
-}
-int skill_get_mhp( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].mhp[lv-1];
-}
-int skill_get_castnodex( int id ,int lv ){
- if (id >= 10000 && id < 10015) id-= 9500;
- return (lv <= 0) ? 0:skill_db[id].castnodex[lv-1];
-}
+// macros to check for out of bounds errors [celest]
+// i: Skill ID, l: Skill Level, var: Value to return after checking
+// for values that don't require level just put a one (putting 0 will trigger return 0; instead
+// for values that might need to use a different function just skill_chk would suffice.
+#define skill_chk(i, l) \
+ if (i >= 10000 && i < 10015) {i -= 9500;} \
+ if (i < 1 || i > MAX_SKILL_DB) {return 0;} \
+ if (l <= 0 || l > MAX_SKILL_LEVEL) {return 0;}
+#define skill_get(var, i, l) \
+ { skill_chk(i, l); return var; }
+
+// Skill DB
+int skill_get_hit( int id ){ skill_get (skill_db[id].hit, id, 1); }
+int skill_get_inf( int id ){ skill_chk (id, 1); return (id < 500) ? skill_db[id].inf : guild_skill_get_inf(id); }
+int skill_get_pl( int id ){ skill_get (skill_db[id].pl, id, 1); }
+int skill_get_nk( int id ){ skill_get (skill_db[id].nk, id, 1); }
+int skill_get_max( int id ){ skill_chk (id, 1); return (id < 500) ? skill_db[id].max : guild_skill_get_max(id); }
+int skill_get_range( int id , int lv ){ skill_chk (id, lv); return (id < 500) ? skill_db[id].range[lv-1] : guild_skill_get_range(id); }
+int skill_get_hp( int id ,int lv ){ skill_get (skill_db[id].hp[lv-1], id, lv); }
+int skill_get_sp( int id ,int lv ){ skill_get (skill_db[id].sp[lv-1], id, lv); }
+int skill_get_zeny( int id ,int lv ){ skill_get (skill_db[id].zeny[lv-1], id, lv); }
+int skill_get_num( int id ,int lv ){ skill_get (skill_db[id].num[lv-1], id, lv); }
+int skill_get_cast( int id ,int lv ){ skill_get (skill_db[id].cast[lv-1], id, lv); }
+int skill_get_delay( int id ,int lv ){ skill_get (skill_db[id].delay[lv-1], id, lv); }
+int skill_get_time( int id ,int lv ){ skill_get (skill_db[id].upkeep_time[lv-1], id, lv); }
+int skill_get_time2( int id ,int lv ){ skill_get (skill_db[id].upkeep_time2[lv-1], id, lv); }
+int skill_get_castdef( int id ){ skill_get (skill_db[id].cast_def_rate, id, 1); }
+int skill_get_weapontype( int id ){ skill_get (skill_db[id].weapon, id, 1); }
+int skill_get_inf2( int id ){ skill_get (skill_db[id].inf2, id, 1); }
+int skill_get_castcancel( int id ){ skill_get (skill_db[id].castcancel, id, 1); }
+int skill_get_maxcount( int id ){ skill_get (skill_db[id].maxcount, id, 1); }
+int skill_get_blewcount( int id ,int lv ){ skill_get (skill_db[id].blewcount[lv-1], id, lv); }
+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);
int i, skillid;
@@ -845,42 +576,64 @@ int skill_tree_get_max(int id, int b_class){
int skill_check_condition( struct map_session_data *sd,int type);
int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag );
int skill_frostjoke_scream(struct block_list *bl,va_list ap);
-int skill_status_change_timer_sub(struct block_list *bl, va_list ap );
+int status_change_timer_sub(struct block_list *bl, va_list ap );
int skill_attack_area(struct block_list *bl,va_list ap);
-int skill_abra_dataset(int skilllv);
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);
+
+int enchant_eff[5] = { 10, 14, 17, 19, 20 };
+int deluge_eff[5] = { 5, 9, 12, 14, 15 };
// [MouseJstr] - skill ok to cast? and when?
-int skillnotok(int skillid, struct map_session_data *sd) {
- if (sd == 0)
- return 0;
- if (pc_isGM(sd) >= 20)
- return 0; // gm's can do anything damn thing they want
+int skillnotok(int skillid, struct map_session_data *sd)
+{
+ nullpo_retr (1, sd);
+ //if (sd == 0)
+ //return 0;
+ //return 1;
+ // I think it was meant to be "no skills allowed when not a valid sd"
+
+ if (!(skillid >= 10000 && skillid < 10015))
+ if ((skillid > MAX_SKILL) || (skillid < 0))
+ return 1;
+
+ {
+ int i = skillid;
+ if (i >= 10000 && i < 10015)
+ i -= 9500;
+ if (sd->blockskill[i] > 0)
+ return 1;
+ }
+
+ if (pc_isGM(sd) >= 20)
+ return 0; // gm's can do anything damn thing they want
// Check skill restrictions [Celest]
- if(!map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.gvg && skill_db[skillid].nocast & 1)
+ if(!map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.gvg && skill_get_nocast (skillid) & 1)
return 1;
- if(map[sd->bl.m].flag.pvp && skill_db[skillid].nocast & 2)
+ if(map[sd->bl.m].flag.pvp && skill_get_nocast (skillid) & 2)
return 1;
- if(map[sd->bl.m].flag.gvg && skill_db[skillid].nocast & 4)
+ if(map[sd->bl.m].flag.gvg && skill_get_nocast (skillid) & 4)
return 1;
- if (agit_flag && skill_db[skillid].nocast & 8)
+ if (agit_flag && skill_get_nocast (skillid) & 8)
return 1;
- if (battle_config.pk_mode && !map[sd->bl.m].flag.nopvp && skill_db[skillid].nocast & 16)
+ if (battle_config.pk_mode && !map[sd->bl.m].flag.nopvp && skill_get_nocast (skillid) & 16)
return 1;
-
- switch (skillid) {
- case AL_WARP:
- case AL_TELEPORT:
- case MC_VENDING:
- case MC_IDENTIFY:
- return 0; // always allowed
- default:
- return(map[sd->bl.m].flag.noskill);
- }
+
+ switch (skillid) {
+ case AL_WARP:
+ case AL_TELEPORT:
+ case MC_VENDING:
+ case MC_IDENTIFY:
+ return 0; // always allowed
+ default:
+ return (map[sd->bl.m].flag.noskill);
+ }
}
@@ -888,105 +641,58 @@ static int distance(int x0,int y0,int x1,int y1)
{
int dx,dy;
- dx=abs(x0-x1);
- dy=abs(y0-y1);
- return dx>dy ? dx : dy;
+ dx = abs(x0 - x1);
+ dy = abs(y0 - 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;
- 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 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 =
- */
+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;
+
+ 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];
}
+// 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 =
+
/*==========================================
* スキル追加?果
*------------------------------------------
*/
-int skill_additional_effect( struct block_list* src, struct block_list *bl,int skillid,int skilllv,int attack_type,unsigned int tick)
+int skill_additional_effect (struct block_list* src, struct block_list *bl, int skillid, int skilllv, int attack_type, unsigned int tick)
{
/* MOB追加?果スキル用 */
const int sc[]={
@@ -1006,7 +712,7 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s
struct pet_data *pd=NULL;
int skill,skill2;
- int rate,luk;
+ int rate;
int sc_def_mdef,sc_def_vit,sc_def_int,sc_def_luk;
int sc_def_mdef2,sc_def_vit2,sc_def_int2,sc_def_luk2;
@@ -1014,102 +720,83 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s
nullpo_retr(0, src);
nullpo_retr(0, bl);
- //if(skilllv <= 0) return 0;
+ if(skillid < 0)
+ { // remove the debug print when this case is finished
+ printf("skill_additional_effect: skillid=%i\ncall: %p %p %i %i %i %i",skillid,
+ src, bl,skillid,skilllv,attack_type,tick);
+ return 0;
+ }
if(skillid > 0 && skilllv <= 0) return 0; // don't forget auto attacks! - celest
- if(src->type==BL_PC){
- nullpo_retr(0, sd=(struct map_session_data *)src);
- }else if(src->type==BL_MOB){
- nullpo_retr(0, md=(struct mob_data *)src); //未使用?
- }else if(src->type==BL_PET){
- nullpo_retr(0, pd=(struct pet_data *)src); // [Valaris]
+ if (src->type == BL_PC){
+ nullpo_retr(0, sd = (struct map_session_data *)src);
+ } else if (src->type == BL_MOB){
+ nullpo_retr(0, md = (struct mob_data *)src); //未使用?
+ } else if (src->type == BL_PET){
+ nullpo_retr(0, pd = (struct pet_data *)src); // [Valaris]
+ }
+
+ if(bl->type == BL_PC) {
+ nullpo_retr(0, dstsd=(struct map_session_data *)bl);
+ } else if(bl->type == BL_MOB) {
+ nullpo_retr(0, dstmd=(struct mob_data *)bl); //未使用?
}
//?象の耐性
- luk = battle_get_luk(bl);
- sc_def_mdef=100 - (3 + battle_get_mdef(bl) + luk/3);
- sc_def_vit=100 - (3 + battle_get_vit(bl) + luk/3);
- sc_def_int=100 - (3 + battle_get_int(bl) + luk/3);
- sc_def_luk=100 - (3 + luk);
+ sc_def_mdef = status_get_sc_def_mdef(bl);
+ sc_def_vit = status_get_sc_def_vit(bl);
+ sc_def_int = status_get_sc_def_int(bl);
+ sc_def_luk = status_get_sc_def_luk(bl);
+
//自分の耐性
- luk = battle_get_luk(src);
- sc_def_mdef2=100 - (3 + battle_get_mdef(src) + luk/3);
- sc_def_vit2=100 - (3 + battle_get_vit(src) + luk/3);
- sc_def_int2=100 - (3 + battle_get_int(src) + luk/3);
- sc_def_luk2=100 - (3 + luk);
- if(bl->type==BL_PC)
- dstsd=(struct map_session_data *)bl;
- else if(bl->type==BL_MOB){
- dstmd=(struct mob_data *)bl; //未使用?
- if(sc_def_mdef<50)
- sc_def_mdef=50;
- if(sc_def_vit<50)
- sc_def_vit=50;
- if(sc_def_int<50)
- sc_def_int=50;
- if(sc_def_luk<50)
- sc_def_luk=50;
- }
- if(sc_def_mdef<0)
- sc_def_mdef=0;
- if(sc_def_vit<0)
- sc_def_vit=0;
- if(sc_def_int<0)
- sc_def_int=0;
+ sc_def_mdef2 = status_get_sc_def_mdef(src);
+ sc_def_vit2 = status_get_sc_def_vit(src);
+ sc_def_int2 = status_get_sc_def_int(src);
+ sc_def_luk2 = status_get_sc_def_luk(src);
switch(skillid){
case 0: /* 通常攻? */
/* 自動鷹 */
- if( sd && pc_isfalcon(sd) && sd->status.weapon == 11 && (skill=pc_checkskill(sd,HT_BLITZBEAT))>0 &&
- rand()%1000 <= sd->paramc[5]*10/3+1 ) {
- int lv=(sd->status.job_level+9)/10;
- skill_castend_damage_id(src,bl,HT_BLITZBEAT,(skill<lv)?skill:lv,tick,0xf00000);
- }
- // スナッチャ?
- if(sd && sd->status.weapon != 11 && (skill=pc_checkskill(sd,RG_SNATCHER)) > 0)
- if((skill*15 + 55) + (skill2 = pc_checkskill(sd,TF_STEAL))*10 > rand()%1000) {
+ if(sd) {
+ struct status_change *sc_data = status_get_sc_data(bl);
+ if (pc_isfalcon(sd) && sd->status.weapon == 11 && (skill=pc_checkskill(sd,HT_BLITZBEAT))>0 &&
+ rand()%1000 <= sd->paramc[5]*10/3+1 ) {
+ int lv=(sd->status.job_level+9)/10;
+ skill_castend_damage_id(src,bl,HT_BLITZBEAT,(skill<lv)?skill:lv,tick,0xf00000);
+ }
+ // スナッチャ?
+ if(sd->status.weapon != 11 && (skill=pc_checkskill(sd,RG_SNATCHER)) > 0 &&
+ (skill*15 + 55) + (skill2 = pc_checkskill(sd,TF_STEAL))*10 > rand()%1000) {
if(pc_steal_item(sd,bl))
clif_skill_nodamage(src,bl,TF_STEAL,skill2,1);
else if (battle_config.display_snatcher_skill_fail)
- clif_skill_fail(sd,skillid,0,0); // it's annoying! =p [Celest]
- }
- // エンチャントデットリ?ポイズン(猛毒?果)
- if (sd && sd->sc_data[SC_EDP].timer != -1 && rand() % 10000 < sd->sc_data[SC_EDP].val2 * sc_def_vit) {
- int mhp = battle_get_max_hp(bl);
- int hp = battle_get_hp(bl);
- int lvl = sd->sc_data[SC_EDP].val1;
- int diff;
- // MHPの1/4以下にはならない
- if(hp > mhp>>2) {
- if(bl->type == BL_PC) {
- diff = mhp*10/100;
- if (hp - diff < mhp>>2)
- diff = hp - (mhp>>2);
- pc_heal((struct map_session_data *)bl, -hp, 0);
- } else if(bl->type == BL_MOB) {
- struct mob_data *md = (struct mob_data *)bl;
- hp -= mhp*15/100;
- if (hp > mhp>>2)
- md->hp = hp;
- else
- md->hp = mhp>>2;
- }
+ clif_skill_fail(sd,skillid,0,0);
+ }
+ // enchant poison has a chance of poisoning enemy
+ if (sd->sc_data[SC_ENCPOISON].timer != -1 && sc_data && sc_data[SC_POISON].timer == -1 &&
+ rand() % 100 < sd->sc_data[SC_ENCPOISON].val1 * sc_def_vit / 100) {
+ status_change_start(bl,SC_POISON,sd->sc_data[SC_ENCPOISON].val1,
+ 0,0,0,skill_get_time2(AS_ENCHANTPOISON,sd->sc_data[SC_ENCPOISON].val1),0);
}
- skill_status_change_start(bl,SC_DPOISON,lvl,0,0,0,skill_get_time2(ASC_EDP,lvl),0);
+ // エンチャントデットリ?ポイズン(猛毒?果)
+ if (sd->sc_data[SC_EDP].timer != -1 && sc_data && sc_data[SC_DPOISON].timer == -1 &&
+ rand() % 100 < sd->sc_data[SC_EDP].val2 * sc_def_vit / 100)
+ status_change_start(bl,SC_DPOISON,sd->sc_data[SC_EDP].val1,
+ 0,0,0,skill_get_time2(ASC_EDP,sd->sc_data[SC_EDP].val1),0);
}
break;
case SM_BASH: /* バッシュ(急所攻?) */
if( sd && (skill=pc_checkskill(sd,SM_FATALBLOW))>0 ){
if( rand()%100 < 6*(skilllv-5)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(SM_FATALBLOW,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(SM_FATALBLOW,skilllv),0);
}
break;
case TF_POISON: /* インベナム */
case AS_SPLASHER: /* ベナムスプラッシャ? */
if(rand()%100< (2*skilllv+10)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_POISON,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_POISON,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
else{
if(sd && skillid==TF_POISON)
clif_skill_fail(sd,skillid,0,0);
@@ -1118,122 +805,140 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s
case AS_SONICBLOW: /* ソニックブロ? */
if( rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ break;
+
+ case AS_GRIMTOOTH:
+ if (bl->type == BL_MOB) {
+ struct status_change *sc_data = status_get_sc_data(bl);
+ if (sc_data && sc_data[SC_SLOWDOWN].timer == -1)
+ status_change_start(bl,SC_SLOWDOWN,0,0,0,0,1000,0);
+ }
break;
case HT_FREEZINGTRAP: /* フリ?ジングトラップ */
rate=skilllv*3+35;
if(rand()%100 < rate*sc_def_mdef/100)
- skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case MG_FROSTDIVER: /* フロストダイバ? */
case WZ_FROSTNOVA: /* フロストノヴァ */
- rate=(skilllv*3+35)*sc_def_mdef/100-(battle_get_int(bl)+battle_get_luk(bl))/15;
- rate=rate<=5?5:rate;
- if(rand()%100 < rate)
- skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
- else if(sd && skillid==MG_FROSTDIVER)
- clif_skill_fail(sd,skillid,0,0);
+ {
+ struct status_change *sc_data = status_get_sc_data(bl);
+ rate = (skilllv*3+35)*sc_def_mdef/100-(status_get_int(bl)+status_get_luk(bl))/15;
+ if (rate <= 5)
+ rate = 5;
+ if(sc_data && sc_data[SC_FREEZE].timer == -1 && rand()%100 < rate)
+ status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv)*(1-sc_def_mdef/100),0);
+ else if (sd && skillid == MG_FROSTDIVER)
+ clif_skill_fail(sd,skillid,0,0);
+ }
break;
case WZ_STORMGUST: /* スト?ムガスト */
{
- struct status_change *sc_data = battle_get_sc_data(bl);
+ struct status_change *sc_data = status_get_sc_data(bl);
if(sc_data) {
sc_data[SC_FREEZE].val3++;
if(sc_data[SC_FREEZE].val3 >= 3)
- skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
}
}
break;
case HT_LANDMINE: /* ランドマイン */
if( rand()%100 < (5*skilllv+30)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case HT_SHOCKWAVE: /* ショックウェ?ブトラップ */
if(map[bl->m].flag.pvp && dstsd){
dstsd->status.sp -= dstsd->status.sp*(5+15*skilllv)/100;
- pc_calcstatus(dstsd,0);
+ status_calc_pc(dstsd,0);
}
break;
case HT_SANDMAN: /* サンドマン */
if( rand()%100 < (5*skilllv+30)*sc_def_int/100 )
- skill_status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case TF_SPRINKLESAND: /* 砂まき */
if( rand()%100 < 20*sc_def_int/100 )
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case TF_THROWSTONE: /* 石投げ */
if( rand()%100 < 7*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case CR_HOLYCROSS: /* ホ?リ?クロス */
if( rand()%100 < 3*skilllv*sc_def_int/100 )
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case CR_GRANDCROSS: /* グランドクロス */
+ case NPC_DARKGRANDCROSS: /*闇グランドクロス*/
{
- int race = battle_get_race(bl);
- if( (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6) && rand()%100 < 100000*sc_def_int/100) //?制付?だが完全耐性には無?
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ int race = status_get_race(bl);
+ if( (battle_check_undead(race,status_get_elem_type(bl)) || race == 6) && rand()%100 < 100000*sc_def_int/100) //?制付?だが完全耐性には無?
+ status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
}
break;
+ case AM_ACIDTERROR:
+ if( rand()%100 < (skilllv*3)*sc_def_vit/100 )
+ status_change_start(bl,SC_BLEEDING,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ break;
+
case CR_SHIELDCHARGE: /* シ?ルドチャ?ジ */
if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case RG_RAID: /* サプライズアタック */
if( rand()%100 < (10+3*skilllv)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
if( rand()%100 < (10+3*skilllv)*sc_def_int/100 )
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case BA_FROSTJOKE:
if(rand()%100 < (15+5*skilllv)*sc_def_mdef/100)
- skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case DC_SCREAM:
if( rand()%100 < (25+5*skilllv)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case BD_LULLABY: /* 子守唄 */
if( rand()%100 < 15*sc_def_int/100 )
- skill_status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_SLEEP,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
/* MOBの追加?果付きスキル */
case NPC_PETRIFYATTACK:
if(rand()%100 < sc_def_mdef)
- skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case NPC_POISON:
case NPC_SILENCEATTACK:
case NPC_STUNATTACK:
if(rand()%100 < sc_def_vit && src->type!=BL_PET)
- skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
if(src->type==BL_PET)
- skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skilllv*1000,0);
+ status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skilllv*1000,0);
break;
case NPC_CURSEATTACK:
if(rand()%100 < sc_def_luk)
- skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case NPC_SLEEPATTACK:
case NPC_BLINDATTACK:
if(rand()%100 < sc_def_int)
- skill_status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,sc[skillid-NPC_POISON],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case NPC_MENTALBREAKER:
if(dstsd) {
@@ -1247,126 +952,164 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s
//
case WZ_METEOR:
if(rand()%100 < sc_def_vit)
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case WZ_VERMILION:
if(rand()%100 < sc_def_int)
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
// -- moonsoul (stun ability of new champion skill tigerfist)
//
case CH_TIGERFIST:
- if( rand()%100 < (10 + skilllv*10)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ if (rand()%100 < (10 + skilllv*10)*sc_def_vit/100) {
+ int sec = skill_get_time2 (skillid,skilllv) - status_get_agi(bl)/10;
+ if (dstsd) {
+ dstsd->canmove_tick += sec;
+ dstsd->canact_tick += sec;
+ } else if (dstmd)
+ dstmd->canmove_tick += sec;
+ }
break;
case LK_SPIRALPIERCE:
if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case ST_REJECTSWORD: /* フリ?ジングトラップ */
if( rand()%100 < (skilllv*15) )
- skill_status_change_start(bl,SC_AUTOCOUNTER,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_AUTOCOUNTER,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case PF_FOGWALL: /* ホ?リ?クロス */
- if( rand()%100 < 3*skilllv*sc_def_int/100 )
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ if (src != bl) {
+ struct status_change *sc_data = status_get_sc_data(bl);
+ if (sc_data && sc_data[SC_DELUGE].timer == -1)
+ status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ }
break;
case LK_HEADCRUSH: /* ヘッドクラッシュ */
{//?件が良く分からないので適?に
- int race=battle_get_race(bl);
- if( !(battle_check_undead(race,battle_get_elem_type(bl)) || race == 6) && rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_HEADCRUSH,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ int race=status_get_race(bl);
+ if( !(battle_check_undead(race,status_get_elem_type(bl)) || race == 6) && rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
}
break;
case LK_JOINTBEAT: /* ジョイントビ?ト */
//?件が良く分からないので適?に
- if( rand()%100 < (2*skilllv+10)*sc_def_vit/100 )
- skill_status_change_start(bl,SC_JOINTBEAT,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ if( rand()%100 < (5*skilllv+5)*sc_def_vit/100 )
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case PF_SPIDERWEB: /* スパイダ?ウェッブ */
{
- if(bl->type == BL_MOB)
- {
- int sec=skill_get_time2(skillid,skilllv);
- if(map[src->m].flag.pvp) //PvPでは拘束時間半減?
- sec = sec/2;
- battle_stopwalking(bl,1);
- skill_status_change_start(bl,SC_SPIDERWEB,skilllv,0,0,0,sec,0);
- }
+ int sec = skill_get_time2(skillid,skilllv);
+ if(map[src->m].flag.pvp) //PvPでは拘束時間半減?
+ sec = sec/2;
+ battle_stopwalking(bl,1);
+ status_change_start(bl,SC_SPIDERWEB,skilllv,0,0,0,sec,0);
}
break;
case ASC_METEORASSAULT: /* メテオアサルト */
if( rand()%100 < (15 + skilllv*5)*sc_def_vit/100 ) //?態異常は詳細が分からないので適?に
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
if( rand()%100 < (10+3*skilllv)*sc_def_int/100 )
- skill_status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_BLIND,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case MO_EXTREMITYFIST: /* 阿修羅覇凰拳 */
//阿修羅を使うと5分間自然回復しないようになる
- skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0 );
+ status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time2(skillid,skilllv),0 );
break;
case HW_NAPALMVULCAN: /* ナパ?ムバルカン */
// skilllv*5%の確率で呪い
if (rand()%10000 < 5*skilllv*sc_def_luk)
- skill_status_change_start(bl,SC_CURSE,7,0,0,0,skill_get_time2(NPC_CURSEATTACK,7),0);
+ status_change_start(bl,SC_CURSE,7,0,0,0,skill_get_time2(NPC_CURSEATTACK,7),0);
break;
}
- if(sd && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){ /* カ?ドによる追加?果 */
- int i;
+ if((sd||dstsd) && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){ /* カ?ドによる追加?果 */
+ int i, type;
int sc_def_card=100;
for(i=SC_STONE;i<=SC_BLIND;i++){
+ type=i-SC_STONE;
//?象に?態異常
- if(i==SC_STONE || i==SC_FREEZE)
- sc_def_card=sc_def_mdef;
- else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE)
- sc_def_card=sc_def_vit;
- else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND)
- sc_def_card=sc_def_int;
- else if(i==SC_CURSE)
- sc_def_card=sc_def_luk;
-
- if(!sd->state.arrow_atk) {
- if(rand()%10000 < (sd->addeff[i-SC_STONE])*sc_def_card/100 ){
- if(battle_config.battle_log)
- printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
- skill_status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
- }
+ switch (i) {
+ case SC_STONE:
+ case SC_FREEZE:
+ sc_def_card=sc_def_mdef;
+ break;
+ case SC_STAN:
+ case SC_POISON:
+ case SC_SILENCE:
+ sc_def_card=sc_def_vit;
+ break;
+ case SC_SLEEP:
+ case SC_CONFUSION:
+ case SC_BLIND:
+ sc_def_card=sc_def_int;
+ break;
+ case SC_CURSE:
+ sc_def_card=sc_def_luk;
}
- else {
- if(rand()%10000 < (sd->addeff[i-SC_STONE]+sd->arrow_addeff[i-SC_STONE])*sc_def_card/100 ){
- if(battle_config.battle_log)
- printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
- skill_status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
+
+ if (sd) {
+ if(!sd->state.arrow_atk) {
+ if(rand()%10000 < (sd->addeff[type])*sc_def_card/100 ){
+ if(battle_config.battle_log)
+ printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[type]);
+ status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0);
+ }
+ }
+ else {
+ if(rand()%10000 < (sd->addeff[type]+sd->arrow_addeff[type])*sc_def_card/100 ){
+ if(battle_config.battle_log)
+ printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[type]);
+ status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0);
+ }
}
}
//自分に?態異常
- if(i==SC_STONE || i==SC_FREEZE)
- sc_def_card=sc_def_mdef2;
- else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE)
- sc_def_card=sc_def_vit2;
- else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND)
- sc_def_card=sc_def_int2;
- else if(i==SC_CURSE)
- sc_def_card=sc_def_luk2;
-
- if(!sd->state.arrow_atk) {
- if(rand()%10000 < (sd->addeff2[i-SC_STONE])*sc_def_card/100 ){
- if(battle_config.battle_log)
- printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
- skill_status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
- }
+ switch (i) {
+ case SC_STONE:
+ case SC_FREEZE:
+ sc_def_card=sc_def_mdef2;
+ break;
+ case SC_STAN:
+ case SC_POISON:
+ case SC_SILENCE:
+ sc_def_card=sc_def_vit2;
+ break;
+ case SC_SLEEP:
+ case SC_CONFUSION:
+ case SC_BLIND:
+ sc_def_card=sc_def_int2;
+ break;
+ case SC_CURSE:
+ sc_def_card=sc_def_luk2;
}
- else {
- if(rand()%10000 < (sd->addeff2[i-SC_STONE]+sd->arrow_addeff2[i-SC_STONE])*sc_def_card/100 ){
- if(battle_config.battle_log)
- printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
- skill_status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
+
+ if (sd) {
+ if(!sd->state.arrow_atk) {
+ if(rand()%10000 < (sd->addeff2[type])*sc_def_card/100 ){
+ if(battle_config.battle_log)
+ printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[type]);
+ status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0);
+ }
+ }
+ else {
+ if(rand()%10000 < (sd->addeff2[type]+sd->arrow_addeff2[type])*sc_def_card/100 ){
+ if(battle_config.battle_log)
+ printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[type]);
+ status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0);
+ }
}
}
+ if (dstsd && rand()%10000 < dstsd->addeff3[type]*sc_def_card/100){
+ if (dstsd->addeff3_type[type] != 1 && ((sd && !sd->state.arrow_atk) || (status_get_range(src)<=2)))
+ continue;
+ if(battle_config.battle_log)
+ printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,dstsd->addeff3[type]);
+ status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[type],7),0);
+ }
}
}
return 0;
@@ -1379,7 +1122,7 @@ int skill_blown( struct block_list *src, struct block_list *target,int count)
{
int dx=0,dy=0,nx,ny;
int x=target->x,y=target->y;
- int ret,prev_state=MS_IDLE;
+ int dir,ret,prev_state=MS_IDLE;
int moveblock;
struct map_session_data *sd=NULL;
struct mob_data *md=NULL;
@@ -1390,25 +1133,24 @@ 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))){ /* 指定なしなら位置?係から方向を求める */
- 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);
- }
- if(dx==0 && dy==0){
- int dir=battle_get_dir(target);
- if(dir>=0 && dir<8){
- dx=-dirx[dir];
- dy=-diry[dir];
- }
+ if (count&0xf00000)
+ dir = (count>>20)&0xf;
+ else if (count&0x10000 || (target->x==src->x && target->y==src->y))
+ dir = status_get_dir(target);
+ else
+ dir = map_calc_dir(target,src->x,src->y);
+ if (dir>=0 && dir<8){
+ dx = -dirx[dir];
+ dy = -diry[dir];
}
ret=path_blownpos(target->m,x,y,dx,dy,count&0xffff);
@@ -1456,18 +1198,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=battle_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) { /* ?面?に入ってきたので表示 */
@@ -1486,8 +1223,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;
}
@@ -1510,15 +1245,16 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
struct Damage dmg;
struct status_change *sc_data;
int type,lv,damage;
+ static int tmpdmg = 0;
- if(skilllv <= 0) return 0;
+ if(skillid > 0 && skilllv <= 0) return 0;
rdamage = 0;
nullpo_retr(0, src);
nullpo_retr(0, dsrc);
nullpo_retr(0, bl);
- sc_data = battle_get_sc_data(bl);
+ sc_data = status_get_sc_data(bl);
//何もしない判定ここから
if(dsrc->m != bl->m) //?象が同じマップにいなければ何もしない
@@ -1527,11 +1263,11 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
return 0;
if(src->type == BL_PC && pc_isdead((struct map_session_data *)src)) //術者?がPCですでに死んでいたら何もしない
return 0;
- if(dsrc->type == BL_PC && pc_isdead((struct map_session_data *)dsrc)) //術者?がPCですでに死んでいたら何もしない
+ if(src != dsrc && dsrc->type == BL_PC && pc_isdead((struct map_session_data *)dsrc)) //術者?がPCですでに死んでいたら何もしない
return 0;
if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)) //?象がPCですでに死んでいたら何もしない
return 0;
- if(bl->type == BL_PC && skillnotok(skillid, (struct map_session_data *) bl))
+ if(bl->type == BL_PC && skillnotok(skillid, (struct map_session_data *)bl))
return 0; // [MouseJstr]
if(sc_data && sc_data[SC_HIDING].timer != -1) { //ハイディング?態で
if(skill_get_pl(skillid) != 2) //スキルの?性が地?性でなければ何もしない
@@ -1562,27 +1298,30 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
if(attack_type&BF_MAGIC && sc_data && sc_data[SC_MAGICROD].timer != -1 && src == dsrc) { //魔法攻?でマジックロッド?態でsrc=dsrcなら
dmg.damage = dmg.damage2 = 0; //ダメ?ジ0
if(bl->type == BL_PC) { //?象がPCの場合
- int sp = skill_get_sp(skillid,skilllv); //使用されたスキルのSPを吸?
- sp = sp * sc_data[SC_MAGICROD].val2 / 100; //吸?率計算
- if(skillid == WZ_WATERBALL && skilllv > 1) //ウォ?タ?ボ?ルLv1以上
- sp = sp/((skilllv|1)*(skilllv|1)); //さらに計算?
- if(sp > 0x7fff) sp = 0x7fff; //SP多すぎの場合は理論最大値
- else if(sp < 1) sp = 1; //1以下の場合は1
- if(((struct map_session_data *)bl)->status.sp + sp > ((struct map_session_data *)bl)->status.max_sp) { //回復SP+現在のSPがMSPより大きい場合
- sp = ((struct map_session_data *)bl)->status.max_sp - ((struct map_session_data *)bl)->status.sp; //SPをMSP-現在SPにする
- ((struct map_session_data *)bl)->status.sp = ((struct map_session_data *)bl)->status.max_sp; //現在のSPにMSPを代入
- }
- else //回復SP+現在のSPがMSPより小さい場合は回復SPを加算
- ((struct map_session_data *)bl)->status.sp += sp;
- clif_heal(((struct map_session_data *)bl)->fd,SP_SP,sp); //SP回復エフェクトの表示
- ((struct map_session_data *)bl)->canact_tick = tick + skill_delayfix(bl, skill_get_delay(SA_MAGICROD,sc_data[SC_MAGICROD].val1)); //
+ struct map_session_data *sd = (struct map_session_data *)bl;
+ if (sd) {
+ int sp = skill_get_sp(skillid,skilllv); //使用されたスキルのSPを吸?
+ sp = sp * sc_data[SC_MAGICROD].val2 / 100; //吸?率計算
+ if(skillid == WZ_WATERBALL && skilllv > 1) //ウォ?タ?ボ?ルLv1以上
+ sp = sp/((skilllv|1)*(skilllv|1)); //さらに計算?
+ if(sp > 0x7fff) sp = 0x7fff; //SP多すぎの場合は理論最大値
+ else if(sp < 1) sp = 1; //1以下の場合は1
+ if(sd->status.sp + sp > sd->status.max_sp) { //回復SP+現在のSPがMSPより大きい場合
+ sp = sd->status.max_sp - sd->status.sp; //SPをMSP-現在SPにする
+ sd->status.sp = sd->status.max_sp; //現在のSPにMSPを代入
+ }
+ else //回復SP+現在のSPがMSPより小さい場合は回復SPを加算
+ sd->status.sp += sp;
+ clif_heal(sd->fd,SP_SP,sp); //SP回復エフェクトの表示
+ sd->canact_tick = tick + skill_delayfix(bl, skill_get_delay(SA_MAGICROD,sc_data[SC_MAGICROD].val1)); //
+ }
}
clif_skill_nodamage(bl,bl,SA_MAGICROD,sc_data[SC_MAGICROD].val1,1); //マジックロッドエフェクトを表示
}
//マジックロッド?理ここまで
if(src->type==BL_PET) { // [Valaris]
- dmg.damage=battle_attr_fix(skilllv, skill_get_pl(skillid), battle_get_element(bl) );
+ dmg.damage=battle_attr_fix(skilllv, skill_get_pl(skillid), status_get_element(bl) );
dmg.damage2=0;
}
@@ -1597,7 +1336,7 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
if(damage <= 0 || damage < dmg.div_) //吹き飛ばし判定?※
dmg.blewcount = 0;
- if(skillid == CR_GRANDCROSS) {//グランドクロス
+ if(skillid == CR_GRANDCROSS||skillid == NPC_DARKGRANDCROSS) {//グランドクロス
if(battle_config.gx_disptype) dsrc = src; // 敵ダメ?ジ白文字表示
if( src == bl) type = 4; // 反動はダメ?ジモ?ションなし
}
@@ -1608,12 +1347,12 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
nullpo_retr(0, sd);
//連打掌(MO_CHAINCOMBO)ここから
if(skillid == MO_CHAINCOMBO) {
- int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src); //基本ディレイの計算
- if(damage < battle_get_hp(bl)) { //ダメ?ジが?象のHPより小さい場合
+ int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src); //基本ディレイの計算
+ if(damage < status_get_hp(bl)) { //ダメ?ジが?象のHPより小さい場合
if(pc_checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0) //猛龍拳(MO_COMBOFINISH)取得&?球保持時は+300ms
delay += 300 * battle_config.combo_delay_rate /100; //追加ディレイをconfにより調整
- skill_status_change_start(src,SC_COMBO,MO_CHAINCOMBO,skilllv,0,0,delay,0); //コンボ?態に
+ status_change_start(src,SC_COMBO,MO_CHAINCOMBO,skilllv,0,0,delay,0); //コンボ?態に
}
sd->attackabletime = sd->canmove_tick = tick + delay;
clif_combo_delay(src,delay); //コンボディレイパケットの送信
@@ -1621,8 +1360,8 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
//連打掌(MO_CHAINCOMBO)ここまで
//猛龍拳(MO_COMBOFINISH)ここから
else if(skillid == MO_COMBOFINISH) {
- int delay = 700 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src);
- if(damage < battle_get_hp(bl)) {
+ int delay = 700 - 4 * status_get_agi(src) - 2 * status_get_dex(src);
+ if(damage < status_get_hp(bl)) {
//阿修羅覇凰拳(MO_EXTREMITYFIST)取得&?球4個保持&爆裂波動(MO_EXPLOSIONSPIRITS)?態時は+300ms
//伏虎拳(CH_TIGERFIST)取得時も+300ms
if((pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball >= 4 && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1) ||
@@ -1630,7 +1369,7 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
(pc_checkskill(sd, CH_CHAINCRUSH) > 0 && sd->spiritball > 1))
delay += 300 * battle_config.combo_delay_rate /100; //追加ディレイをconfにより調整
- skill_status_change_start(src,SC_COMBO,MO_COMBOFINISH,skilllv,0,0,delay,0); //コンボ?態に
+ status_change_start(src,SC_COMBO,MO_COMBOFINISH,skilllv,0,0,delay,0); //コンボ?態に
}
sd->attackabletime = sd->canmove_tick = tick + delay;
clif_combo_delay(src,delay); //コンボディレイパケットの送信
@@ -1638,12 +1377,12 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
//猛龍拳(MO_COMBOFINISH)ここまで
//伏虎拳(CH_TIGERFIST)ここから
else if(skillid == CH_TIGERFIST) {
- int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src);
- if(damage < battle_get_hp(bl)) {
+ int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src);
+ if(damage < status_get_hp(bl)) {
if(pc_checkskill(sd, CH_CHAINCRUSH) > 0) //連柱崩?(CH_CHAINCRUSH)取得時は+300ms
delay += 300 * battle_config.combo_delay_rate /100; //追加ディレイをconfにより調整
- skill_status_change_start(src,SC_COMBO,CH_TIGERFIST,skilllv,0,0,delay,0); //コンボ?態に
+ status_change_start(src,SC_COMBO,CH_TIGERFIST,skilllv,0,0,delay,0); //コンボ?態に
}
sd->attackabletime = sd->canmove_tick = tick + delay;
clif_combo_delay(src,delay); //コンボディレイパケットの送信
@@ -1651,13 +1390,13 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
//伏虎拳(CH_TIGERFIST)ここまで
//連柱崩?(CH_CHAINCRUSH)ここから
else if(skillid == CH_CHAINCRUSH) {
- int delay = 1000 - 4 * battle_get_agi(src) - 2 * battle_get_dex(src);
- if(damage < battle_get_hp(bl)) {
+ int delay = 1000 - 4 * status_get_agi(src) - 2 * status_get_dex(src);
+ if(damage < status_get_hp(bl)) {
//阿修羅覇凰拳(MO_EXTREMITYFIST)取得&?球4個保持&爆裂波動(MO_EXPLOSIONSPIRITS)?態時は+300ms
if(pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball >= 4 && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1)
delay += 300 * battle_config.combo_delay_rate /100; //追加ディレイをconfにより調整
- skill_status_change_start(src,SC_COMBO,CH_CHAINCRUSH,skilllv,0,0,delay,0); //コンボ?態に
+ status_change_start(src,SC_COMBO,CH_CHAINCRUSH,skilllv,0,0,delay,0); //コンボ?態に
}
sd->attackabletime = sd->canmove_tick = tick + delay;
clif_combo_delay(src,delay); //コンボディレイパケットの送信
@@ -1708,23 +1447,32 @@ 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;
+ case ASC_BREAKER: // [celest]
+ if (attack_type&BF_MAGIC) { // only display damage for the 2nd attack
+ if (damage + tmpdmg != 0) // if both attacks missed, do not display a 2nd 'miss'
+ clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, damage+tmpdmg, dmg.div_, skillid, skilllv, type);
+ tmpdmg = 0; // clear the temporary damage
+ } else {
+ if (damage == 0) // if weapon attack missed, display the 'miss'
+ clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, 0, dmg.div_, skillid, skilllv, type);
+ tmpdmg = damage; // store the temporary weapon damage
+ }
+ break;
case NPC_SELFDESTRUCTION:
case NPC_SELFDESTRUCTION2:
break;
+ case SN_SHARPSHOOTING:
+ clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,0,0,0);
+ break;
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)
@@ -1735,28 +1483,31 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
map_freeblock_lock();
/* ?際にダメ?ジ?理を行う */
- if(skillid != KN_BOWLINGBASH || flag)
- battle_damage(src,bl,damage,0);
- if(skillid == RG_INTIMIDATE && damage > 0 && !(battle_get_mode(bl)&0x20) && !map[src->m].flag.gvg ) {
- int s_lv = battle_get_lv(src),t_lv = battle_get_lv(bl);
+ 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;
rate = rate + (s_lv - t_lv);
if(rand()%100 < rate)
skill_addtimerskill(src,tick + 800,bl->id,0,0,skillid,skilllv,0,flag);
}
- if(damage > 0 && dmg.flag&BF_SKILL && bl->type==BL_PC && pc_checkskill((struct map_session_data *)bl,RG_PLAGIARISM) && sc_data[SC_PRESERVE].timer != -1){
+ if(damage > 0 && dmg.flag&BF_SKILL && bl->type==BL_PC && pc_checkskill((struct map_session_data *)bl,RG_PLAGIARISM) && sc_data[SC_PRESERVE].timer == -1){
struct map_session_data *tsd = (struct map_session_data *)bl;
nullpo_retr(0, tsd);
- if(!tsd->status.skill[skillid].id && !tsd->status.skill[skillid].id
- && !(skillid > NPC_PIERCINGATT && skillid < NPC_SUMMONMONSTER) ){
+ if(!tsd->status.skill[skillid].id && !tsd->status.skill[skillid].lv
+ && !(skillid > NPC_PIERCINGATT && skillid < NPC_SUMMONMONSTER)
+ && !(skillid > NPC_SELFDESTRUCTION2 && skillid < NPC_UNDEADATTACK)){
//?に?んでいるスキルがあれば該?スキルを消す
- if (tsd->cloneskill_id && tsd->cloneskill_lv && tsd->status.skill[tsd->cloneskill_id].flag==13){
+ if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag==13){
tsd->status.skill[tsd->cloneskill_id].id=0;
- tsd->status.skill[tsd->cloneskill_id].lv=0;
tsd->status.skill[tsd->cloneskill_id].flag=0;
}
tsd->cloneskill_id=skillid;
- tsd->cloneskill_lv=skilllv;
tsd->status.skill[skillid].id=skillid;
tsd->status.skill[skillid].lv=(pc_checkskill(tsd,RG_PLAGIARISM) > skill_get_max(skillid))?
skill_get_max(skillid):pc_checkskill(tsd,RG_PLAGIARISM);
@@ -1766,13 +1517,11 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
}
/* ダメ?ジがあるなら追加?果判定 */
if(bl->prev != NULL){
- struct map_session_data *sd = (struct map_session_data *)bl;
- nullpo_retr(0, sd);
- if( bl->type != BL_PC || (sd && !pc_isdead(sd)) ) {
- if(damage > 0)
- skill_additional_effect(src,bl,skillid,skilllv,attack_type,tick);
- if(bl->type==BL_MOB && src!=bl) /* スキル使用?件のMOBスキル */
- {
+ if(!status_isdead(bl)) {
+ if(damage > 0)
+ skill_additional_effect(src,bl,skillid,skilllv,attack_type,tick);
+ if(bl->type==BL_MOB && src!=bl) /* スキル使用?件のMOBスキル */
+ {
struct mob_data *md=(struct mob_data *)bl;
nullpo_retr(0, md);
if(battle_config.mob_changetarget_byskill == 1)
@@ -1814,16 +1563,23 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
if(sd->sp_drain_rate_ > 0 && sp < 1) sp = 1;
else if(sd->sp_drain_rate_ < 0 && sp > -1) sp = -1;
}
- if(hp || sp) pc_heal(sd,hp,sp);
+ if(hp || sp)
+ pc_heal(sd,hp,sp);
+ if (sd->sp_drain_type && bl->type == BL_PC)
+ battle_heal(NULL,bl,0,-sp,0);
}
- if((skillid != KN_BOWLINGBASH || 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)
battle_weapon_attack(bl,dsrc,tick,0x8000|sc_data[SC_AUTOCOUNTER].val1);
- skill_status_change_end(bl,SC_AUTOCOUNTER,-1);
+ status_change_end(bl,SC_AUTOCOUNTER,-1);
}
map_freeblock_unlock();
@@ -1870,9 +1626,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);
@@ -1885,57 +1640,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;
}
@@ -1943,6 +1687,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);
@@ -1954,32 +1700,117 @@ 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(struct block_list *bl, int m,int x,int y,int skillid, int skilllv)
{
- int c = 0;
+ int c = 0, range, type;
+
+ switch (skillid) { // to be expanded later
+ case WZ_ICEWALL:
+ range = 2;
+ break;
+ default:
+ {
+ 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;
+ }
+ // とりあえず正方形のユニットレイアウトのみ対応
+ range = skill_get_unit_range(skillid) + layout_type;
+ }
+ break;
+ }
- map_foreachinarea(skill_check_unit_range2_sub,m,x-range,y-range,x+range,y+range,0,&c);
+ // if the caster is a monster/NPC, only check for players
+ // otherwise just check everything
+ if (bl->type == BL_PC)
+ type = 0;
+ else type = BL_PC;
+
+ map_foreachinarea(skill_check_unit_range2_sub, m,
+ x - range, y - range, x + range, y + range,
+ type, &c, skillid);
return c;
}
+int skill_guildaura_sub (struct block_list *bl,va_list ap)
+{
+ struct map_session_data *sd;
+ struct guild *g;
+ int gid, id;
+ int flag = 0;
+
+ nullpo_retr(0, sd=(struct map_session_data *)bl);
+
+ nullpo_retr(0, ap);
+ id = va_arg(ap,int);
+ gid = va_arg(ap,int);
+ if (sd->status.guild_id != gid)
+ return 0;
+
+ g = va_arg(ap,struct guild *);
+ if (guild_checkskill(g, GD_LEADERSHIP)>0) flag |= 1<<0;
+ if (guild_checkskill(g, GD_GLORYWOUNDS)>0) flag |= 1<<1;
+ if (guild_checkskill(g, GD_SOULCOLD)>0) flag |= 1<<2;
+ if (guild_checkskill(g, GD_HAWKEYES)>0) flag |= 1<<3;
+ if (guild_checkskill(g, GD_CHARISMA)>0) flag |= 1<<4;
+
+ if (flag > 0) {
+ if (sd->sc_count && sd->sc_data[SC_GUILDAURA].timer != -1) {
+ if (sd->sc_data[SC_GUILDAURA].val4 != flag) {
+ sd->sc_data[SC_GUILDAURA].val4 = flag;
+ status_calc_pc (sd, 0);
+ }
+ return 0;
+ }
+ status_change_start(&sd->bl, SC_GUILDAURA,1,id,0,flag,0,0 );
+ }
+
+ return 0;
+}
+
/*=========================================================================
* 範?スキル使用?理小分けここから
*/
/* ?象の?をカウントする。(skill_area_temp[0]を初期化しておくこと) */
int skill_area_sub_count(struct block_list *src,struct block_list *target,int skillid,int skilllv,unsigned int tick,int flag)
{
- if(skilllv <= 0) return 0;
if(skill_area_temp[0] < 0xffff)
skill_area_temp[0]++;
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;
+}
+
/*==========================================
*
*------------------------------------------
@@ -2017,6 +1848,10 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data )
nullpo_retr(0, skl);
skl->timer = -1;
+ if (sd) {
+ sd->timerskill_count--;
+ }
+
if(skl->target_id) {
struct block_list tbl;
target = map_id2bl(skl->target_id);
@@ -2045,13 +1880,13 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data )
break;
case RG_INTIMIDATE:
if(sd && !map[src->m].flag.noteleport) {
- int x,y,i,j,c;
+ int x,y,i,j;
pc_randomwarp(sd,3);
for(i=0;i<16;i++) {
j = rand()%8;
x = sd->bl.x + dirx[j];
y = sd->bl.y + diry[j];
- if((c=map_getcell(sd->bl.m,x,y)) != 1 && c != 5)
+ if(map_getcell(sd->bl.m,x,y,CELL_CHKPASS))
break;
}
if(i >= 16) {
@@ -2066,13 +1901,13 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data )
}
}
else if(md && !map[src->m].flag.monster_noteleport) {
- int x,y,i,j,c;
+ int x,y,i,j;
mob_warp(md,-1,-1,-1,3);
for(i=0;i<16;i++) {
j = rand()%8;
x = md->bl.x + dirx[j];
y = md->bl.y + diry[j];
- if((c=map_getcell(md->bl.m,x,y)) != 1 && c != 5)
+ if(map_getcell(md->bl.m,x,y,CELL_CHKPASS))
break;
}
if(i >= 16) {
@@ -2090,11 +1925,26 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data )
case BA_FROSTJOKE: /* 寒いジョ?ク */
case DC_SCREAM: /* スクリ?ム */
- range=15; //視界全?
+ range=battle_config.area_size; //視界全?
map_foreachinarea(skill_frostjoke_scream,src->m,src->x-range,src->y-range,
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);
+ if (skl->type <= 1) { // partial fix: it still doesn't end if the target dies
+ // should put outside of the switch, but since this is the only
+ // mage targetted spell for now,
+ struct status_change *sc_data = status_get_sc_data(src);
+ if(sc_data && sc_data[SC_MAGICPOWER].timer != -1) //マジックパワ?の?果終了
+ status_change_end(src,SC_MAGICPOWER,-1);
+ }
+ break;
default:
skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
break;
@@ -2143,6 +1993,7 @@ int skill_addtimerskill(struct block_list *src,unsigned int tick,int target,int
sd->skilltimerskill[i].y = y;
sd->skilltimerskill[i].type = type;
sd->skilltimerskill[i].flag = flag;
+ sd->timerskill_count++;
return 0;
}
@@ -2207,10 +2058,15 @@ int skill_cleartimerskill(struct block_list *src)
if(src->type == BL_PC) {
struct map_session_data *sd = (struct map_session_data *)src;
nullpo_retr(0, sd);
+
+ if (sd->timerskill_count <= 0)
+ return 0;
+
for(i=0;i<MAX_SKILLTIMERSKILL;i++) {
if(sd->skilltimerskill[i].timer != -1) {
delete_timer(sd->skilltimerskill[i].timer, skill_timerskill);
sd->skilltimerskill[i].timer = -1;
+ sd->timerskill_count--;
}
}
}
@@ -2237,27 +2093,37 @@ int skill_cleartimerskill(struct block_list *src)
* (スパゲッティに向けて1?前進!(ダメポ))
*------------------------------------------
*/
-int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag )
+int skill_castend_damage_id (struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag)
{
- struct map_session_data *sd=NULL;
- struct status_change *sc_data = battle_get_sc_data(src);
+ struct map_session_data *sd = NULL, *tsd = NULL;
+ struct status_change *sc_data;
int i;
- if(skilllv <= 0) return 0;
+ if(skillid < 0)
+ { // remove the debug print when this case is finished
+ printf("skill_castend_damage_id: skillid=%i\ncall: %p %p %i %i %i %i",skillid,
+ src, bl,skillid,skilllv,tick,flag);
+ return 0;
+ }
+ if(skillid > 0 && skilllv <= 0) return 0;
nullpo_retr(1, src);
nullpo_retr(1, bl);
- if(src->type==BL_PC)
- sd=(struct map_session_data *)src;
- if(sd && pc_isdead(sd))
+ sc_data = status_get_sc_data(src);
+
+ if (src->type == BL_PC)
+ sd = (struct map_session_data *)src;
+ if (sd && pc_isdead(sd))
return 1;
- if((skillid == WZ_SIGHTRASHER || skillid == CR_GRANDCROSS) && src != bl)
+ if ((skillid == CR_GRANDCROSS || skillid == NPC_DARKGRANDCROSS) && src != bl)
bl = src;
- if(bl->prev == NULL)
+ if (bl->prev == NULL)
return 1;
- if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))
+ if (bl->type == BL_PC)
+ tsd = (struct map_session_data *)bl;
+ if (tsd && pc_isdead(tsd))
return 1;
map_freeblock_lock();
@@ -2270,10 +2136,10 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
case AS_SONICBLOW: /* ソニックブロ? */
case KN_PIERCE: /* ピア?ス */
case KN_SPEARBOOMERANG: /* スピアブ?メラン */
+ case KN_BRANDISHSPEAR: /* ブランディッシュスピア */
case TF_POISON: /* インベナム */
case TF_SPRINKLESAND: /* 砂まき */
case AC_CHARGEARROW: /* チャ?ジアロ? */
- case KN_SPEARSTAB: /* スピアスタブ */
case RG_RAID: /* サプライズアタック */
case RG_INTIMIDATE: /* インティミデイト */
case BA_MUSICALSTRIKE: /* ミュ?ジカルストライク */
@@ -2282,7 +2148,6 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
case CR_HOLYCROSS: /* ホ?リ?クロス */
case CR_SHIELDCHARGE:
case CR_SHIELDBOOMERANG:
-
/* 以下MOB?用 */
/* ??攻?、SP減少攻?、遠距離攻?、防御無視攻?、多段攻? */
case NPC_PIERCINGATT:
@@ -2311,187 +2176,195 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
case NPC_HOLYATTACK:
case NPC_DARKNESSATTACK:
case NPC_TELEKINESISATTACK:
+ case NPC_UNDEADATTACK:
+ case NPC_BREAKARMOR:
+ case NPC_BREAKWEAPON:
+ case NPC_BREAKHELM:
+ case NPC_BREAKSHIELD:
case LK_AURABLADE: /* オ?ラブレ?ド */
case LK_SPIRALPIERCE: /* スパイラルピア?ス */
case LK_HEADCRUSH: /* ヘッドクラッシュ */
case LK_JOINTBEAT: /* ジョイントビ?ト */
- case PA_PRESSURE: /* プレッシャ? */
- case PA_SACRIFICE: /* サクリファイス */
- case SN_SHARPSHOOTING: /* シャ?プシュ?ティング */
case CG_ARROWVULCAN: /* アロ?バルカン */
- case ASC_BREAKER: /* ソウルブレ?カ? */
case HW_MAGICCRASHER: /* マジッククラッシャ? */
+ case ASC_METEORASSAULT: /* メテオアサルト */
+ case ITM_TOMAHAWK:
+ case MO_COMBOFINISH: /* 猛龍拳 */
+ case CH_CHAINCRUSH: /* 連柱崩? */
+ case CH_PALMSTRIKE: /* 猛虎硬派山 */
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
break;
+
+ case ASC_BREAKER: /* ソウルブレ?カ? */ // [DracoRPG]
+ // separate weapon and magic attacks
+ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+ skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
+ break;
+
+ case SN_SHARPSHOOTING: /* シャ?プシュ?ティング */
+ map_foreachinpath (skill_attack_area,src->m, // function, map
+ src->x,src->y, // source xy
+ bl->x,bl->y, // target xy
+ 2,0, // range, type
+ BF_WEAPON,src,src,skillid,skilllv,tick,flag,BCT_ENEMY); // varargs
+ break;
+
+ case PA_PRESSURE: /* プレッシャ? */
+ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+ if (rand()%100 < 50)
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(PA_PRESSURE,skilllv),0);
+ else
+ status_change_start(bl,SC_BLEEDING,skilllv,0,0,0,skill_get_time2(PA_PRESSURE,skilllv),0);
+ if (tsd) {
+ int sp = tsd->status.max_sp * 10 * skilllv / 100;
+ if (sp > tsd->status.sp) sp = tsd->status.sp;
+ tsd->status.sp -= sp;
+ clif_updatestatus(tsd,SP_SP);
+ }
+ break;
+
case NPC_DARKBREATH:
clif_emotion(src,7);
skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
break;
+
case MO_INVESTIGATE: /* ?勁 */
{
- struct status_change *sc_data = battle_get_sc_data(src);
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
- if(sc_data[SC_BLADESTOP].timer != -1)
- skill_status_change_end(src,SC_BLADESTOP,-1);
+ if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
+ status_change_end(src,SC_BLADESTOP,-1);
}
break;
+
case SN_FALCONASSAULT: /* ファルコンアサルト */
skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
break;
- case KN_BRANDISHSPEAR: /* ブランディッシュスピア */
- {
- struct mob_data *md = (struct mob_data *)bl;
- nullpo_retr(1, md);
- skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
- if(md->hp > 0){
- skill_blown(src,bl,skill_get_blewcount(skillid,skilllv));
- 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);
- }
- }
- break;
+
case RG_BACKSTAP: /* バックスタブ */
{
- int dir = map_calc_dir(src,bl->x,bl->y),t_dir = battle_get_dir(bl);
- int dist = distance(src->x,src->y,bl->x,bl->y);
- if((dist > 0 && !map_check_dir(dir,t_dir)) || bl->type == BL_SKILL) {
- struct status_change *sc_data = battle_get_sc_data(src);
- if(sc_data && sc_data[SC_HIDING].timer != -1)
- skill_status_change_end(src, SC_HIDING, -1); // ハイディング解除
- skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+ int dir = map_calc_dir(src,bl->x,bl->y), t_dir = status_get_dir(bl);
+ int dist = distance(src->x, src->y, bl->x, bl->y);
+ if ((dist > 0 && !map_check_dir(dir, t_dir)) || bl->type == BL_SKILL) {
+ if (sc_data && sc_data[SC_HIDING].timer != -1)
+ status_change_end(src, SC_HIDING, -1); // ハイディング解除
+ skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag);
dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest]
- if (bl->type == BL_PC)
- ((struct map_session_data *)bl)->dir=dir;
- else if (bl->type == BL_MOB)
- ((struct mob_data *)bl)->dir=dir;
- //skill_blown(src,bl,skill_get_blewcount(skillid,skilllv));
+ if (tsd)
+ tsd->dir = dir;
+ else if (bl->type == BL_MOB) {
+ struct mob_data *md = (struct mob_data *)bl;
+ if (md) md->dir = dir;
+ }
+ clif_changed_dir(bl);
}
- else if(src->type == BL_PC)
+ else if (sd)
clif_skill_fail(sd,sd->skillid,0,0);
}
break;
case AM_ACIDTERROR: /* アシッドテラ? */
- skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
- if(bl->type == BL_PC && rand()%100 < skill_get_time(skillid,skilllv) && battle_config.equipment_breaking)
- pc_breakarmor((struct map_session_data *)bl);
+ skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag);
+ if (tsd && battle_config.equipment_breaking && rand()%100 < skill_get_time(skillid,skilllv)) {
+ pc_breakarmor(tsd);
+ clif_emotion(bl, 23);
+ }
break;
+
case MO_FINGEROFFENSIVE: /* 指? */
{
- struct status_change *sc_data = battle_get_sc_data(src);
-
- if(!battle_config.finger_offensive_type)
- skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
- else {
- skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
- if(sd) {
- for(i=1;i<sd->spiritball_old;i++)
- skill_addtimerskill(src,tick+i*200,bl->id,0,0,skillid,skilllv,BF_WEAPON,flag);
- sd->canmove_tick = tick + (sd->spiritball_old-1)*200;
- }
+ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+ if (battle_config.finger_offensive_type && sd) {
+ for (i = 1; i < sd->spiritball_old; i++)
+ skill_addtimerskill(src, tick + i * 200, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag);
+ sd->canmove_tick = tick + (sd->spiritball_old - 1) * 200;
}
- if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
- skill_status_change_end(src,SC_BLADESTOP,-1);
+ if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
+ status_change_end(src,SC_BLADESTOP,-1);
}
break;
+
case MO_CHAINCOMBO: /* 連打掌 */
{
- struct status_change *sc_data = battle_get_sc_data(src);
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
- if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
- skill_status_change_end(src,SC_BLADESTOP,-1);
+ if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
+ status_change_end(src,SC_BLADESTOP,-1);
}
break;
- case MO_COMBOFINISH: /* 猛龍拳 */
+
case CH_TIGERFIST: /* 伏虎拳 */
- case CH_CHAINCRUSH: /* 連柱崩? */
- case CH_PALMSTRIKE: /* 猛虎硬派山 */
+ if (tsd && !(map[bl->m].flag.gvg || map[bl->m].flag.pvp)) {
+ map_freeblock_unlock();
+ return 1;
+ }
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
break;
+
case MO_EXTREMITYFIST: /* 阿修羅覇鳳拳 */
{
- struct status_change *sc_data = battle_get_sc_data(src);
+ if(sd) {
+ struct walkpath_data wpd;
+ int dx,dy;
- if(sd) {
- struct walkpath_data wpd;
- int dx,dy;
-
- dx = bl->x - sd->bl.x;
- dy = bl->y - sd->bl.y;
- if(dx > 0) dx++;
- else if(dx < 0) dx--;
- if(dy > 0) dy++;
- else if(dy < 0) dy--;
- if(dx == 0 && dy == 0) dx++;
- if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
dx = bl->x - sd->bl.x;
dy = bl->y - sd->bl.y;
- if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
- clif_skill_fail(sd,sd->skillid,0,0);
- break;
+ if(dx > 0) dx++;
+ else if(dx < 0) dx--;
+ if (dy > 0) dy++;
+ else if(dy < 0) dy--;
+ if(dx == 0 && dy == 0) dx++;
+ if (path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
+ dx = bl->x - sd->bl.x;
+ dy = bl->y - sd->bl.y;
+ if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
+ clif_skill_fail(sd,sd->skillid,0,0);
+ break;
+ }
}
+ sd->to_x = sd->bl.x + dx;
+ sd->to_y = sd->bl.y + dy;
+ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+ clif_walkok(sd);
+ clif_movechar(sd);
+ if(dx < 0) dx = -dx;
+ if(dy < 0) dy = -dy;
+ sd->attackabletime = sd->canmove_tick = tick + 100 + sd->speed * ((dx > dy)? dx:dy);
+ if(sd->canact_tick < sd->canmove_tick)
+ sd->canact_tick = sd->canmove_tick;
+ pc_movepos(sd,sd->to_x,sd->to_y);
+ status_change_end(&sd->bl,SC_COMBO,-1);
}
- sd->to_x = sd->bl.x + dx;
- sd->to_y = sd->bl.y + dy;
- skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
- clif_walkok(sd);
- clif_movechar(sd);
- if(dx < 0) dx = -dx;
- if(dy < 0) dy = -dy;
- sd->attackabletime = sd->canmove_tick = tick + 100 + sd->speed * ((dx > dy)? dx:dy);
- if(sd->canact_tick < sd->canmove_tick)
- sd->canact_tick = sd->canmove_tick;
- pc_movepos(sd,sd->to_x,sd->to_y);
- skill_status_change_end(&sd->bl,SC_COMBO,-1);
- }
- else
- skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
- skill_status_change_end(src, SC_EXPLOSIONSPIRITS, -1);
- if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
- skill_status_change_end(src,SC_BLADESTOP,-1);
+ else
+ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+ status_change_end(src, SC_EXPLOSIONSPIRITS, -1);
+ if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
+ status_change_end(src,SC_BLADESTOP,-1);
}
break;
+
/* 武器系範?攻?スキル */
case AC_SHOWER: /* アロ?シャワ? */
- case SM_MAGNUM: /* マグナムブレイク */
case AS_GRIMTOOTH: /* グリムトゥ?ス */
case MC_CARTREVOLUTION: /* カ?トレヴォリュ?ション */
case NPC_SPLASHATTACK: /* スプラッシュアタック */
- case ASC_METEORASSAULT: /* メテオアサルト */
case AS_SPLASHER: /* [Valaris] */
if(flag&1){
/* 個別にダメ?ジを?える */
if(bl->id!=skill_area_temp[1]){
- int dist=0;
- if(skillid==SM_MAGNUM){ /* マグナムブレイクなら中心からの距離を計算 */
- int dx=abs( bl->x - skill_area_temp[2] );
- int dy=abs( bl->y - skill_area_temp[3] );
- dist=((dx>dy)?dx:dy);
- }
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,
- 0x0500|dist );
+ 0x0500);
}
- }else{
- int ar=1;
- int x=bl->x,y=bl->y;
- if( skillid==SM_MAGNUM){
- x=src->x;
- y=src->y;
- }else if(skillid==AC_SHOWER || skillid==ASC_METEORASSAULT) /* アロ?シャワ?、メテオアサルト範?5*5 */
- ar=2;
- else if(skillid==AS_SPLASHER) /* ベナムスプラッシャ?範?3*3 */
- ar=1;
- else if(skillid==NPC_SPLASHATTACK) /* スプラッシュアタックは範?7*7 */
- ar=3;
-
- // meteor assault cast effect (not sure how else to properly add it =p) [Celest]
- if (skillid == ASC_METEORASSAULT)
- clif_specialeffect(&sd->bl,409, 1);
-
+ } else {
+ int ar = 1;
+ int x = bl->x, y = bl->y;
+ switch (skillid) {
+ case AC_SHOWER:
+ ar=2;
+ break;
+ case NPC_SPLASHATTACK:
+ ar=3;
+ break;
+ }
+
skill_area_temp[1]=bl->id;
skill_area_temp[2]=x;
skill_area_temp[3]=y;
@@ -2502,13 +2375,24 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
bl->m,x-ar,y-ar,x+ar,y+ar,0,
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
skill_castend_damage_id);
- if (skillid == SM_MAGNUM) // fire element for 10 seconds
- skill_status_change_start(src,SC_FLAMELAUNCHER,0,0,0,0,10000,0);
}
- if (bl->type == BL_MOB && skillid == AS_GRIMTOOTH) {
- struct status_change *sc_data = battle_get_sc_data(bl);
- if (sc_data && sc_data[SC_SLOWDOWN].timer == -1)
- skill_status_change_start(bl,SC_SLOWDOWN,0,0,0,0,1000,0);
+ break;
+
+ case SM_MAGNUM: /* マグナムブレイク [celest] */
+ if(flag&1 && bl->id != skill_area_temp[1]){
+ int dist = distance (bl->x, bl->y, skill_area_temp[2], skill_area_temp[3]);
+ skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,
+ 0x0500|dist);
+ } else {
+ skill_area_temp[1]=src->id;
+ skill_area_temp[2]=src->x;
+ skill_area_temp[3]=src->y;
+ map_foreachinarea(skill_area_sub,
+ src->m,src->x-2,src->y-2,src->x+2,src->y+2,0,
+ src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
+ skill_castend_damage_id);
+ status_change_start (src,SC_FLAMELAUNCHER,0,0,0,0,10000,0);
+ clif_skill_nodamage (src,src,skillid,skilllv,1);
}
break;
@@ -2517,13 +2401,11 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
/* 個別にダメ?ジを?える */
if(bl->id!=skill_area_temp[1])
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500);
- }
- else {
- int damage;
- map_freeblock_lock();
- damage = skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0);
- if(damage > 0) {
+ } else {
int i,c; /* 他人から聞いた動きなので間違ってる可能性大&?率が?いっす>< */
+ /* まずターゲットに攻撃を加える */
+ if (!skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0))
+ break;
c = skill_get_blewcount(skillid,skilllv);
if(map[bl->m].flag.gvg) c = 0;
for(i=0;i<c;i++){
@@ -2542,24 +2424,42 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
if(skill_area_temp[0]>1) break;
}
skill_area_temp[1]=bl->id;
- skill_area_temp[2]=bl->x;
- skill_area_temp[3]=bl->y;
/* その後タ?ゲット以外の範??の敵全?に?理を行う */
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|1,
skill_castend_damage_id);
- battle_damage(src,bl,damage,1);
- if(rdamage > 0)
- battle_damage(bl,src,rdamage,0);
+ }
+ break;
+
+ case KN_SPEARSTAB: /* スピアスタブ */
+ if(flag&1){
+ /* 個別にダメージを与える */
+ if (bl->id==skill_area_temp[1])
+ break;
+ if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500))
+ skill_blown(src,bl,skill_area_temp[2]);
+ } else {
+ int x=bl->x,y=bl->y,i,dir;
+ /* まずターゲットに攻撃を加える */
+ dir = map_calc_dir(bl,src->x,src->y);
+ skill_area_temp[1] = bl->id;
+ skill_area_temp[2] = skill_get_blewcount(skillid,skilllv)|dir<<20;
+ if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0))
+ skill_blown(src,bl,skill_area_temp[2]);
+ for (i=0;i<4;i++) {
+ map_foreachinarea(skill_area_sub,bl->m,x,y,x,y,0,
+ src,skillid,skilllv,tick,flag|BCT_ENEMY|1,
+ skill_castend_damage_id);
+ x += dirx[dir];
+ y += diry[dir];
}
- map_freeblock_unlock();
}
break;
case ALL_RESURRECTION: /* リザレクション */
case PR_TURNUNDEAD: /* タ?ンアンデッド */
- if(bl->type != BL_PC && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
+ if(bl->type != BL_PC && battle_check_undead(status_get_race(bl),status_get_elem_type(bl)))
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
else {
map_freeblock_unlock();
@@ -2569,67 +2469,95 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
/* 魔法系スキル */
case MG_SOULSTRIKE: /* ソウルストライク */
- case MG_COLDBOLT: /* コ?ルドボルト */
- case MG_FIREBOLT: /* ファイア?ボルト */
+ case NPC_DARKSOULSTRIKE: /*闇ソウルストライク*/
+ case MG_COLDBOLT: /* コールドボルト */
+ case MG_FIREBOLT: /* ファイアーボルト */
case MG_LIGHTNINGBOLT: /* ライトニングボルト */
- case WZ_EARTHSPIKE: /* ア?ススパイク */
- case AL_HEAL: /* ヒ?ル */
- case AL_HOLYLIGHT: /* ホ?リ?ライト */
- case MG_FROSTDIVER: /* フロストダイバ? */
- case WZ_JUPITEL: /* ユピテルサンダ? */
+ case WZ_EARTHSPIKE: /* アーススパイク */
+ case AL_HEAL: /* ヒール */
+ case AL_HOLYLIGHT: /* ホーリーライト */
+ case WZ_JUPITEL: /* ユピテルサンダー */
+ case NPC_DARKJUPITEL: /*闇ユピテル*/
case NPC_MAGICALATTACK: /* MOB:魔法打?攻? */
case PR_ASPERSIO: /* アスペルシオ */
-// case HW_NAPALMVULCAN: /* ナパームバルカン */
+ case MG_FROSTDIVER: /* フロストダイバー */
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
break;
case WZ_WATERBALL: /* ウォ?タ?ボ?ル */
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
- if(skilllv>1)
- skill_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: /* 聖?降福 */
- if(battle_get_race(bl)==1 || battle_get_race(bl)==6)
+ if(status_get_race(bl)==1 || status_get_race(bl)==6)
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
break;
/* 魔法系範?攻?スキル */
case MG_NAPALMBEAT: /* ナパ?ムビ?ト */
case MG_FIREBALL: /* ファイヤ?ボ?ル */
- if(flag&1){
+ case WZ_SIGHTRASHER: /* サイトラッシャー */
+ if (flag & 1) {
/* 個別にダメ?ジを?える */
- if(bl->id!=skill_area_temp[1]){
- if(skillid==MG_FIREBALL){ /* ファイヤ?ボ?ルなら中心からの距離を計算 */
- int dx=abs( bl->x - skill_area_temp[2] );
- int dy=abs( bl->y - skill_area_temp[3] );
- skill_area_temp[0]=((dx>dy)?dx:dy);
+ if (bl->id != skill_area_temp[1]){
+ if(skillid == MG_FIREBALL){ /* ファイヤ?ボ?ルなら中心からの距離を計算 */
+ skill_area_temp[0] = distance(bl->x, bl->y, skill_area_temp[2], skill_area_temp[3]);
}
skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,
skill_area_temp[0]| 0x0500);
}
- }else{
- int ar=(skillid==MG_NAPALMBEAT)?1:2;
+ } else {
+ 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;
@@ -2663,15 +2591,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
break;
case WZ_FROSTNOVA: /* フロストノヴァ */
- skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0);
- //skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
- 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);
- skill_status_change_end(src,SC_SIGHT,-1);
+ 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;
/* その他 */
@@ -2697,6 +2617,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
break;
case CR_GRANDCROSS: /* グランドクロス */
+ case NPC_DARKGRANDCROSS: /*闇グランドクロス*/
/* スキルユニット配置 */
skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0);
if(sd)
@@ -2710,6 +2631,32 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,0 );
break;
+ // Celest
+ case PF_SOULBURN:
+ {
+ int per = skilllv < 5 ? 20+ skilllv*10 : 60;
+ if (rand()%100 < per) {
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if (skilllv == 5)
+ skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,0 );
+ if (tsd && (map[src->m].flag.pvp || map[src->m].flag.gvg)) {
+ tsd->status.sp = 0;
+ clif_updatestatus(tsd,SP_SP);
+ }
+ } else {
+ clif_skill_nodamage(src,src,skillid,skilllv,1);
+ if (skilllv == 5)
+ skill_attack(BF_MAGIC,src,src,src,skillid,skilllv,tick,0 );
+ if (sd) {
+ sd->status.sp = 0;
+ clif_updatestatus(sd,SP_SP);
+ }
+ }
+ if (sd)
+ pc_blockskill_start (sd, skillid, (skilllv < 5 ? 10000: 15000));
+ }
+ break;
+
case NPC_SELFDESTRUCTION: /* 自爆 */
case NPC_SELFDESTRUCTION2: /* 自爆2 */
if(flag&1){
@@ -2726,7 +2673,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
struct mob_data *md;
if((md=(struct mob_data *)src)){
skill_area_temp[1]=bl->id;
- skill_area_temp[2]=battle_get_hp(src);
+ skill_area_temp[2]=status_get_hp(src);
clif_skill_nodamage(src,src,NPC_SELFDESTRUCTION,-1,1);
map_foreachinarea(skill_area_sub,
bl->m,bl->x-5,bl->y-5,bl->x+5,bl->y+5,0,
@@ -2754,6 +2701,14 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
}
}
break;
+
+ // unknown skills [Celest]
+ case NPC_BIND:
+ case NPC_EXPLOSIONSPIRITS:
+ case NPC_INCAGI:
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ break;
+
case 0:
if(sd) {
if(flag&3){
@@ -2772,12 +2727,13 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
break;
default:
+ printf("Unknown skill used:%d\n",skillid);
map_freeblock_unlock();
return 1;
}
if(sc_data) {
if (sc_data[SC_MAGICPOWER].timer != -1 && skillid != HW_MAGICPOWER) //マジックパワ?の?果終了
- skill_status_change_end(src,SC_MAGICPOWER,-1);
+ status_change_end(src,SC_MAGICPOWER,-1);
}
map_freeblock_unlock();
@@ -2788,107 +2744,96 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
* スキル使用(詠唱完了、ID指定支援系)
*------------------------------------------
*/
-int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag )
+int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, int skillid, int skilllv, unsigned int tick, int flag)
{
- struct map_session_data *sd=NULL;
- struct map_session_data *dstsd=NULL;
- struct mob_data *md=NULL;
- struct mob_data *dstmd=NULL;
- int i,abra_skillid=0,abra_skilllv;
- int sc_def_vit,sc_def_mdef,strip_fix,strip_time,strip_per;
- int sc_dex,sc_luk;
- //クラスチェンジ用ボスモンスタ?ID
- int changeclass[]={1038,1039,1046,1059,1086,1087,1112,1115
- ,1157,1159,1190,1272,1312,1373,1492};
- int poringclass[]={1002};
-
- if(skilllv <= 0) return 0;
+ struct map_session_data *sd = NULL;
+ struct map_session_data *dstsd = NULL;
+ struct mob_data *md = NULL;
+ struct mob_data *dstmd = NULL;
+ int i;
+ int sc_def_vit, sc_def_mdef;
+ int sc_dex, sc_luk;
+
+ if(skillid < 0)
+ { // remove the debug print when this case is finished
+ printf("skill_castend_damage_id: skillid=%i\ncall: %p %p %i %i %i %i",skillid,
+ src, bl,skillid,skilllv,tick,flag);
+ return 0;
+ }
+ if(skillid > 0 && skilllv <= 0) return 0; // celest
nullpo_retr(1, src);
nullpo_retr(1, bl);
- if(src->type==BL_PC)
- sd=(struct map_session_data *)src;
- else if(src->type==BL_MOB)
- md=(struct mob_data *)src;
-
- sc_dex=battle_get_mdef(bl);
- sc_luk=battle_get_luk(bl);
- sc_def_vit = 100 - (3 + battle_get_vit(bl) + battle_get_luk(bl)/3);
- //sc_def_vit = 100 - (3 + battle_get_vit(bl) + battle_get_luk(bl)/3);
- sc_def_mdef = 100 - (3 + battle_get_mdef(bl) + battle_get_luk(bl)/3);
- strip_fix = battle_get_dex(src) - battle_get_dex(bl);
-
- if(bl->type==BL_PC){
- nullpo_retr(1, dstsd=(struct map_session_data *)bl);
- }else if(bl->type==BL_MOB){
- nullpo_retr(1, dstmd=(struct mob_data *)bl);
- if(sc_def_vit>50)
- sc_def_vit=50;
- if(sc_def_mdef>50)
- sc_def_mdef=50;
- }
- if(sc_def_vit < 0)
- sc_def_vit=0;
- if(sc_def_mdef < 0)
- sc_def_mdef=0;
- if(strip_fix < 0)
- strip_fix=0;
-
- if(bl == NULL || bl->prev == NULL)
+ if (src->type == BL_PC) {
+ nullpo_retr (1, sd = (struct map_session_data *)src);
+ } else if (src->type == BL_MOB) {
+ nullpo_retr (1, md = (struct mob_data *)src);
+ }
+
+ sc_dex = status_get_mdef (bl);
+ sc_luk = status_get_luk (bl);
+ sc_def_vit = status_get_sc_def_vit (bl);
+ sc_def_mdef = status_get_sc_def_mdef (bl);
+
+ if (bl->type == BL_PC){
+ nullpo_retr (1, dstsd = (struct map_session_data *)bl);
+ } else if (bl->type == BL_MOB){
+ nullpo_retr (1, dstmd = (struct mob_data *)bl);
+ }
+
+ if(bl->prev == NULL)
return 1;
if(sd && pc_isdead(sd))
return 1;
if(dstsd && pc_isdead(dstsd) && skillid != ALL_RESURRECTION)
return 1;
- if(battle_get_class(bl) == 1288)
+ if(status_get_class(bl) == 1288)
return 1;
- if (skillnotok(skillid, (struct map_session_data *)bl)) // [MouseJstr]
+ if (sd && skillnotok(skillid, sd)) // [MouseJstr]
return 0;
-
+
map_freeblock_lock();
switch(skillid)
{
case AL_HEAL: /* ヒ?ル */
{
- int heal=skill_calc_heal( src, skilllv );
+ int heal = skill_calc_heal(src, skilllv);
int heal_get_jobexp;
int skill;
- struct pc_base_job s_class;
- if( dstsd && dstsd->special_state.no_magic_damage )
+ if (skilllv > 10)
+ heal = 9999; //9999ヒール
+ if (dstsd && dstsd->special_state.no_magic_damage)
heal=0; /* ?金蟲カ?ド(ヒ?ル量0) */
- if (sd){
- s_class = pc_calc_base_job(sd->status.class);
- if((skill=pc_checkskill(sd,HP_MEDITATIO))>0) // メディテイティオ
- heal += heal*skill*2/100;
- if(sd && dstsd && sd->status.partner_id == dstsd->status.char_id && s_class.job == 23 && sd->status.sex == 0) //自分も?象もPC、?象が自分のパ?トナ?、自分がスパノビ、自分が♀なら
+ if (sd) {
+ if ((skill = pc_checkskill(sd, HP_MEDITATIO)) > 0) // メディテイティオ
+ heal += heal * skill * 2 / 100;
+ if (sd && dstsd && sd->status.partner_id == dstsd->status.char_id &&
+ pc_calc_base_job2(sd->status.class_) == 23 && sd->status.sex == 0) //自分も?象もPC、?象が自分のパ?トナ?、自分がスパノビ、自分が♀なら
heal = heal*2; //スパノビの嫁が旦那にヒ?ルすると2倍になる
}
-
- clif_skill_nodamage(src,bl,skillid,heal,1);
+ clif_skill_nodamage (src, bl, skillid, heal, 1);
heal_get_jobexp = battle_heal(NULL,bl,heal,0,0);
// JOB??値獲得
- if(src->type == BL_PC && bl->type==BL_PC && heal > 0 && src != bl && battle_config.heal_exp > 0){
+ if(sd && dstsd && heal > 0 && sd != dstsd && battle_config.heal_exp > 0){
heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100;
- if(heal_get_jobexp <= 0)
+ if (heal_get_jobexp <= 0)
heal_get_jobexp = 1;
- pc_gainexp((struct map_session_data *)src,0,heal_get_jobexp);
+ pc_gainexp (sd, 0, heal_get_jobexp);
}
}
break;
case ALL_RESURRECTION: /* リザレクション */
- if(bl->type==BL_PC){
- int per=0;
- struct map_session_data *tsd = (struct map_session_data*)bl;
- nullpo_retr(1, tsd);
- if( (map[bl->m].flag.pvp) && tsd->pvp_point<0 )
+ if(dstsd) {
+ int per = 0;
+ if (map[bl->m].flag.pvp && dstsd->pvp_point < 0)
break; /* PVPで復活不可能?態 */
- if(pc_isdead(tsd)){ /* 死亡判定 */
+ if (pc_isdead(dstsd)) { /* 死亡判定 */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
switch(skilllv){
case 1: per=10; break;
@@ -2896,139 +2841,153 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case 3: per=50; break;
case 4: per=80; break;
}
- tsd->status.hp=tsd->status.max_hp*per/100;
- if(tsd->status.hp<=0) tsd->status.hp=1;
- if(tsd->special_state.restart_full_recover ){ /* オシリスカ?ド */
- tsd->status.hp=tsd->status.max_hp;
- tsd->status.sp=tsd->status.max_sp;
+ dstsd->status.hp = dstsd->status.max_hp * per / 100;
+ if (dstsd->status.hp <= 0) dstsd->status.hp = 1;
+ if (dstsd->special_state.restart_full_recover) { /* オシリスカ?ド */
+ dstsd->status.hp = dstsd->status.max_hp;
+ dstsd->status.sp = dstsd->status.max_sp;
}
- pc_setstand(tsd);
+ pc_setstand(dstsd);
if(battle_config.pc_invincible_time > 0)
- pc_setinvincibletimer(tsd,battle_config.pc_invincible_time);
- clif_updatestatus(tsd,SP_HP);
- clif_resurrection(&tsd->bl,1);
- if(src != bl && sd && battle_config.resurrection_exp > 0) {
+ pc_setinvincibletimer(dstsd, battle_config.pc_invincible_time);
+ clif_updatestatus(dstsd, SP_HP);
+ clif_resurrection(bl, 1);
+ if(sd && sd != dstsd && battle_config.resurrection_exp > 0) {
int exp = 0,jexp = 0;
- int lv = tsd->status.base_level - sd->status.base_level, jlv = tsd->status.job_level - sd->status.job_level;
+ int lv = dstsd->status.base_level - sd->status.base_level, jlv = dstsd->status.job_level - sd->status.job_level;
if(lv > 0) {
- exp = (int)((double)tsd->status.base_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.);
- if(exp < 1) exp = 1;
+ exp = (int)((double)dstsd->status.base_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.);
+ if (exp < 1) exp = 1;
}
if(jlv > 0) {
- jexp = (int)((double)tsd->status.job_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.);
- if(jexp < 1) jexp = 1;
+ jexp = (int)((double)dstsd->status.job_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.);
+ if (jexp < 1) jexp = 1;
}
if(exp > 0 || jexp > 0)
- pc_gainexp(sd,exp,jexp);
+ pc_gainexp (sd, exp, jexp);
}
}
}
break;
case AL_DECAGI: /* 速度減少 */
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if (dstsd && dstsd->special_state.no_magic_damage)
break;
- if( rand()%100 < (50+skilllv*3+(battle_get_lv(src)+battle_get_int(src)/5)-sc_def_mdef) ) {
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
+ if (rand() % 100 < (50 + skilllv * 3 + (status_get_lv(src) + status_get_int(src) / 5) - sc_def_mdef)) {
+ clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+ status_change_start (bl, SkillStatusChangeTable[skillid], skilllv, 0, 0, 0, skill_get_time(skillid,skilllv), 0);
}
break;
case AL_CRUCIS:
- if(flag&1) {
- int race = battle_get_race(bl),ele = battle_get_elem_type(bl);
- if(battle_check_target(src,bl,BCT_ENEMY) && (race == 6 || battle_check_undead(race,ele))) {
- int slv=battle_get_lv(src),tlv=battle_get_lv(bl),rate;
- rate = 25 + skilllv*2 + slv - tlv;
- if(rand()%100 < rate)
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,0,0);
+ if (flag & 1) {
+ int race = status_get_race (bl), ele = status_get_elem_type (bl);
+ if (battle_check_target (src, bl, BCT_ENEMY) && (race == 6 || battle_check_undead (race, ele))) {
+ int slv = status_get_lv (src),tlv = status_get_lv (bl);
+ int rate = 25 + skilllv*2 + slv - tlv;
+ if (rand()%100 < rate)
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,0,0);
}
- }
- else {
- int range = 15;
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ } else {
+ clif_skill_nodamage(src, bl, skillid, skilllv, 1);
map_foreachinarea(skill_area_sub,
- src->m,src->x-range,src->y-range,src->x+range,src->y+range,0,
- src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
+ src->m, src->x-15, src->y-15, src->x+15, src->y+15, 0,
+ src, skillid, skilllv, tick, flag|BCT_ENEMY|1,
skill_castend_nodamage_id);
}
break;
case PR_LEXDIVINA: /* レックスディビ?ナ */
{
- struct status_change *sc_data = battle_get_sc_data(bl);
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ struct status_change *sc_data = status_get_sc_data(bl);
+ clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+ if (dstsd && dstsd->special_state.no_magic_damage)
break;
- if(sc_data && sc_data[SC_DIVINA].timer != -1)
- skill_status_change_end(bl,SC_DIVINA,-1);
- else if( rand()%100 < sc_def_vit ) {
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
+ if (sc_data && sc_data[SC_DIVINA].timer != -1)
+ status_change_end(bl,SC_DIVINA, -1);
+ else if (rand() % 100 < sc_def_vit) {
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
}
break;
+
case SA_ABRACADABRA:
- //require 1 yellow gemstone even with mistress card or Into the Abyss
- if ((i=pc_search_inventory(sd, 715)) < 0 ) { //bug fixed by Lupus (item pos can be 0, too!)
- clif_skill_fail(sd,sd->skillid,0,0);
- break;
+ {
+ int abra_skillid = 0, abra_skilllv;
+ //require 1 yellow gemstone even with mistress card or Into the Abyss
+ if ((i = pc_search_inventory(sd, 715)) < 0 ) { //bug fixed by Lupus (item pos can be 0, too!)
+ clif_skill_fail(sd,sd->skillid,0,0);
+ break;
+ }
+ pc_delitem(sd, i, 1, 0);
+ do {
+ abra_skillid = rand() % 331;
+ if (skill_abra_db[abra_skillid].req_lv > skilllv ||
+ rand()%10000 >= skill_abra_db[abra_skillid].per || //dbに基づくレベル?確率判定
+ (abra_skillid >= NPC_PIERCINGATT && abra_skillid <= NPC_SUMMONMONSTER) || //NPCスキルはダメ
+ skill_get_unit_flag(abra_skillid) & UF_DANCE) //演奏スキルはダメ
+ abra_skillid = 0; // reset to get a new id
+ } while (abra_skillid == 0);
+ abra_skilllv = skill_get_max(abra_skillid) > skilllv ? skilllv : skill_get_max(abra_skillid);
+ clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+ sd->skillitem = abra_skillid;
+ sd->skillitemlv = abra_skilllv;
+ clif_item_skill (sd, abra_skillid, abra_skilllv, "Abracadabra");
}
- //pc_delitem(sd, pc_search_inventory(sd, 715), 1, 0);
- pc_delitem(sd, i, 1, 0);
- //
- do{
- abra_skillid=skill_abra_dataset(skilllv);
- }while(abra_skillid == 0);
- abra_skilllv=skill_get_max(abra_skillid)>pc_checkskill(sd,SA_ABRACADABRA)?pc_checkskill(sd,SA_ABRACADABRA):skill_get_max(abra_skillid);
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- sd->skillitem=abra_skillid;
- sd->skillitemlv=abra_skilllv;
- clif_item_skill(sd,abra_skillid,abra_skilllv,"アブラカダブラ");
break;
+
case SA_COMA:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
- break;
- if(dstsd){
- dstsd->status.hp=1;
- dstsd->status.sp=1;
- clif_updatestatus(dstsd,SP_HP);
- clif_updatestatus(dstsd,SP_SP);
+ if (dstsd) {
+ if (dstsd->special_state.no_magic_damage)
+ break;
+ dstsd->status.hp = 1;
+ dstsd->status.sp = 1;
+ clif_updatestatus(dstsd, SP_HP);
+ clif_updatestatus(dstsd, SP_SP);
}
- if(dstmd) dstmd->hp=1;
+ if(dstmd) dstmd->hp = 1;
break;
case SA_FULLRECOVERY:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
- break;
- if(dstsd) pc_heal(dstsd,dstsd->status.max_hp,dstsd->status.max_sp);
- if(dstmd) dstmd->hp=battle_get_max_hp(&dstmd->bl);
+ if (dstsd) {
+ if (dstsd->special_state.no_magic_damage)
+ break;
+ pc_heal (dstsd, dstsd->status.max_hp, dstsd->status.max_sp);
+ }
+ if (dstmd) dstmd->hp = status_get_max_hp(bl);
break;
case SA_SUMMONMONSTER:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if (sd) mob_once_spawn(sd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,"--ja--",-1,1,"");
+ if (sd) mob_once_spawn(sd,map[src->m].name,src->x,src->y,"--ja--",-1,1,"");
break;
case SA_LEVELUP:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if (sd && pc_nextbaseexp(sd)) pc_gainexp(sd,pc_nextbaseexp(sd)*10/100,0);
+ if (sd && pc_nextbaseexp(sd)) pc_gainexp(sd, pc_nextbaseexp(sd) * 10 / 100, 0);
break;
-
case SA_INSTANTDEATH:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if (sd) pc_damage(NULL,sd,sd->status.max_hp);
break;
-
case SA_QUESTION:
case SA_GRAVITY:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
break;
case SA_CLASSCHANGE:
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if(dstmd) mob_class_change(dstmd,changeclass);
+ {
+ //クラスチェンジ用ボスモンスタ?ID
+ int changeclass[]={1038,1039,1046,1059,1086,1087,1112,1115
+ ,1157,1159,1190,1272,1312,1373,1492};
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if(dstmd) mob_class_change(dstmd,changeclass);
+ }
break;
case SA_MONOCELL:
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if(dstmd) mob_class_change(dstmd,poringclass);
+ {
+ int poringclass[]={1002};
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if(dstmd) mob_class_change(dstmd,poringclass);
+ }
break;
case SA_DEATH:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
@@ -3041,19 +3000,20 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case SA_FORTUNE:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if(sd) pc_getzeny(sd,battle_get_lv(bl)*100);
+ if(sd) pc_getzeny(sd,status_get_lv(bl)*100);
break;
case SA_TAMINGMONSTER:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if (dstmd){
- for(i=0;i<MAX_PET_DB;i++){
- if(dstmd->class == pet_db[i].class){
- pet_catch_process1(sd,dstmd->class);
+ if (dstmd) {
+ for (i = 0; i < MAX_PET_DB; i++) {
+ if (dstmd->class_ == pet_db[i].class_) {
+ pet_catch_process1 (sd, dstmd->class_);
break;
}
}
}
break;
+
case AL_INCAGI: /* 速度?加 */
case AL_BLESSING: /* ブレッシング */
case PR_SLOWPOISON:
@@ -3062,38 +3022,37 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case PR_SUFFRAGIUM: /* サフラギウム */
case PR_BENEDICTIO: /* 聖?降福 */
case CR_PROVIDENCE: /* プロヴィデンス */
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ){
+ if (dstsd && dstsd->special_state.no_magic_damage)
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- }else{
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ else {
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
case CG_MARIONETTE: /* マリオネットコントロ?ル */
- if(sd && dstsd){
- struct status_change *sc_data = battle_get_sc_data(src);
- struct status_change *tsc_data = battle_get_sc_data(bl);
+ if (sd && dstsd){
+ struct status_change *sc_data = status_get_sc_data(src);
+ struct status_change *tsc_data = status_get_sc_data(bl);
int sc = SkillStatusChangeTable[skillid];
int sc2 = SC_MARIONETTE2;
-
- if((dstsd->bl.type!=BL_PC)
- || (sd->bl.id == dstsd->bl.id)
+
+ if ((sd == dstsd)
|| (!sd->status.party_id)
- || (sd->status.party_id != dstsd->status.party_id)) {
+ || (sd->status.party_id != dstsd->status.party_id)) {
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
}
if(sc_data && tsc_data){
- if(sc_data[sc].timer == -1 && tsc_data[sc2].timer == -1) {
- skill_status_change_start (src,sc,skilllv,0,bl->id,0,skill_get_time(skillid,skilllv),0);
- skill_status_change_start (bl,sc2,skilllv,0,src->id,0,skill_get_time(skillid,skilllv),0);
+ if (sc_data[sc].timer == -1 && tsc_data[sc2].timer == -1) {
+ status_change_start (src,sc,skilllv,0,bl->id,0,skill_get_time(skillid,skilllv),0);
+ status_change_start (bl,sc2,skilllv,0,src->id,0,skill_get_time(skillid,skilllv),0);
}
else if (sc_data[sc].timer != -1 && tsc_data[sc2].timer != -1 &&
- sc_data[sc].val3 == bl->id && tsc_data[sc2].val3 == src->id) {
- skill_status_change_end(src, sc, -1);
- skill_status_change_end(bl, sc2, -1);
+ sc_data[sc].val3 == bl->id && tsc_data[sc2].val3 == src->id) {
+ status_change_end(src, sc, -1);
+ status_change_end(bl, sc2, -1);
}
else {
clif_skill_fail(sd,skillid,0,0);
@@ -3102,57 +3061,60 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
- }
+ }
break;
case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris]
case SA_FROSTWEAPON:
case SA_LIGHTNINGLOADER:
case SA_SEISMICWEAPON:
- if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ){
- clif_skill_nodamage(src,bl,skillid,skilllv,0);
- break;
- }
- if(bl->type==BL_PC) {
- struct map_session_data *sd2=(struct map_session_data *)bl;
- if(sd2->status.weapon==0 || sd2->sc_data[SC_FLAMELAUNCHER].timer!=-1 || sd2->sc_data[SC_FROSTWEAPON].timer!=-1 ||
- sd2->sc_data[SC_LIGHTNINGLOADER].timer!=-1 || sd2->sc_data[SC_SEISMICWEAPON].timer!=-1 ||
- sd2->sc_data[SC_ENCPOISON].timer!=-1) {
- clif_skill_fail(sd,skillid,0,0);
+ if (dstsd) {
+ if (dstsd->special_state.no_magic_damage) {
+ clif_skill_nodamage(src,bl,skillid,skilllv,0);
+ break;
+ }
+ if(dstsd->status.weapon == 0 ||
+ (sd && sd->status.party_id > 0 && sd->status.party_id != dstsd->status.party_id) ||
+ dstsd->sc_data[SC_FLAMELAUNCHER].timer != -1 ||
+ dstsd->sc_data[SC_FROSTWEAPON].timer != -1 ||
+ dstsd->sc_data[SC_LIGHTNINGLOADER].timer != -1 ||
+ dstsd->sc_data[SC_SEISMICWEAPON].timer != -1 ||
+ dstsd->sc_data[SC_ENCPOISON].timer != -1) {
+ if (sd) clif_skill_fail(sd,skillid,0,0);
clif_skill_nodamage(src,bl,skillid,skilllv,0);
break;
}
}
- if(rand()%100 > (75+skilllv*1) && (skilllv != 5)) {
- clif_skill_fail(sd,skillid,0,0);
+ if(skilllv < 5 && rand()%100 > (60+skilllv*10) ) { //fixed by Lupus (4 -> 5) or else it has 100% success even at lv4
+ if (sd) clif_skill_fail(sd,skillid,0,0);
clif_skill_nodamage(src,bl,skillid,skilllv,0);
- if(bl->type==BL_PC && battle_config.equipment_breaking) {
- struct map_session_data *sd2=(struct map_session_data *)bl;
- if(sd!=sd2) clif_displaymessage(sd->fd,"You broke target's weapon");
- pc_breakweapon(sd2);
+ if(dstsd && battle_config.equipment_breaking) {
+ if(sd && sd != dstsd) clif_displaymessage(sd->fd,"You broke target's weapon");
+ pc_breakweapon(dstsd);
}
break;
- }
- else {
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ } else {
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
case PR_ASPERSIO: /* アスペルシオ */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if (dstsd && dstsd->special_state.no_magic_damage)
break;
- if(bl->type==BL_MOB)
+ if (dstmd)
break;
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
+
case PR_KYRIE: /* キリエエレイソン */
clif_skill_nodamage(bl,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if (dstsd && dstsd->special_state.no_magic_damage)
break;
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
+
case KN_AUTOCOUNTER: /* オ?トカウンタ? */
case KN_TWOHANDQUICKEN: /* ツ?ハンドクイッケン */
case CR_SPEARQUICKEN: /* スピアクイッケン */
@@ -3176,68 +3138,87 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case ST_REJECTSWORD: /* リジェクトソ?ド */
case HW_MAGICPOWER: /* 魔法力?幅 */
case PF_MEMORIZE: /* メモライズ */
+ case PA_SACRIFICE:
case ASC_EDP: // [Celest]
+ case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
+
case SM_ENDURE: /* インデュア */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
- skill_status_change_start(src,SC_BLOCKSKILL,skilllv,0,skillid,0,10000,0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ if (sd)
+ pc_blockskill_start (sd, skillid, 10000);
break;
-
-
+
+ case SM_AUTOBERSERK: // Celest
+ {
+ struct status_change *tsc_data = status_get_sc_data(bl);
+ int sc = SkillStatusChangeTable[skillid];
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if (tsc_data && tsc_data[sc].timer != -1)
+ status_change_end(bl, sc, -1);
+ else
+ status_change_start(bl,sc,skilllv,0,0,0,0,0);
+ }
+ break;
+
case AS_ENCHANTPOISON: // Prevent spamming [Valaris]
- if(bl->type==BL_PC) {
- struct map_session_data *sd2=(struct map_session_data *)bl;
- if(sd2->sc_data[SC_FLAMELAUNCHER].timer!=-1 || sd2->sc_data[SC_FROSTWEAPON].timer!=-1 ||
- sd2->sc_data[SC_LIGHTNINGLOADER].timer!=-1 || sd2->sc_data[SC_SEISMICWEAPON].timer!=-1 ||
- sd2->sc_data[SC_ENCPOISON].timer!=-1) {
- clif_skill_nodamage(src,bl,skillid,skilllv,0);
- clif_skill_fail(sd,skillid,0,0);
- break;
+ if (dstsd) {
+ if(dstsd->sc_data[SC_FLAMELAUNCHER].timer != -1 ||
+ dstsd->sc_data[SC_FROSTWEAPON].timer != -1 ||
+ dstsd->sc_data[SC_LIGHTNINGLOADER].timer != -1 ||
+ dstsd->sc_data[SC_SEISMICWEAPON].timer != -1 ||
+ dstsd->sc_data[SC_ENCPOISON].timer != -1) {
+ clif_skill_nodamage(src,bl,skillid,skilllv,0);
+ clif_skill_fail(sd,skillid,0,0);
+ break;
}
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
+
case LK_TENSIONRELAX: /* テンションリラックス */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
pc_setsit(sd);
clif_sitting(sd);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case LK_BERSERK: /* バ?サ?ク */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
//sd->status.hp = sd->status.max_hp * 3;
break;
+
case MC_CHANGECART:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
break;
+
case AC_CONCENTRATION: /* 集中力向上 */
{
int range = 1;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
- map_foreachinarea( skill_status_change_timer_sub,
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ map_foreachinarea( status_change_timer_sub,
src->m, src->x-range, src->y-range, src->x+range,src->y+range,0,
src,SkillStatusChangeTable[skillid],tick);
}
break;
+
case SM_PROVOKE: /* プロボック */
{
- struct status_change *sc_data = battle_get_sc_data(bl);
+ struct status_change *sc_data = status_get_sc_data(bl);
/* MVPmobと不死には?かない */
- if((bl->type==BL_MOB && battle_get_mode(bl)&0x20) || battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) //不死には?かない
- {
+ if((dstmd && status_get_mode(bl)&0x20) || battle_check_undead(status_get_race(bl),status_get_elem_type(bl))) { //不死には?かない
map_freeblock_unlock();
return 1;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
if(dstmd && dstmd->skilltimer!=-1 && dstmd->state.skillcastcancel) // 詠唱妨害
skill_castcancel(bl,0);
@@ -3247,18 +3228,17 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
if(sc_data){
if(sc_data[SC_FREEZE].timer!=-1)
- skill_status_change_end(bl,SC_FREEZE,-1);
+ status_change_end(bl,SC_FREEZE,-1);
if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0)
- skill_status_change_end(bl,SC_STONE,-1);
+ status_change_end(bl,SC_STONE,-1);
if(sc_data[SC_SLEEP].timer!=-1)
- skill_status_change_end(bl,SC_SLEEP,-1);
+ status_change_end(bl,SC_SLEEP,-1);
}
- if(bl->type==BL_MOB) {
+ if(dstmd) {
int range = skill_get_range(skillid,skilllv);
- if(range < 0)
- range = battle_get_range(src) - (range + 1);
- mob_target((struct mob_data *)bl,src,range);
+ dstmd->state.provoke_flag = src->id;
+ mob_target(dstmd,src,range);
}
}
break;
@@ -3266,27 +3246,27 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case CR_DEVOTION: /* ディボ?ション */
if(sd && dstsd){
//?生や養子の場合の元の職業を算出する
- struct pc_base_job dst_s_class = pc_calc_base_job(dstsd->status.class);
-
- int lv = sd->status.base_level-dstsd->status.base_level;
- lv = (lv<0)?-lv:lv;
- if((dstsd->bl.type!=BL_PC) // 相手はPCじゃないとだめ
- ||(sd->bl.id == dstsd->bl.id) // 相手が自分はだめ
- ||(lv > 10) // レベル差±10まで
- ||(!sd->status.party_id && !sd->status.guild_id) // PTにもギルドにも所?無しはだめ
- ||((sd->status.party_id != dstsd->status.party_id) // 同じパ?ティ?か、
- &&(sd->status.guild_id != dstsd->status.guild_id)) // 同じギルドじゃないとだめ
- ||(dst_s_class.job==14||dst_s_class.job==21)){ // クルセだめ
+ int s_class = pc_calc_base_job2 (dstsd->status.class_);
+
+ int lv = sd->status.base_level - dstsd->status.base_level;
+ if (lv < 0) lv = -lv;
+ if ((sd == dstsd) // 相手はPCじゃないとだめ
+ || (sd->bl.id == dstsd->bl.id) // 相手が自分はだめ
+ || (lv > battle_config.devotion_level_difference) // レベル差±10まで
+ || (!sd->status.party_id && !sd->status.guild_id) // PTにもギルドにも所?無しはだめ
+ || ((sd->status.party_id != dstsd->status.party_id) // 同じパ?ティ?か、
+ &&(sd->status.guild_id != dstsd->status.guild_id)) // 同じギルドじゃないとだめ
+ || (s_class == 14 || s_class == 21)) { // クルセだめ
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
}
- for(i=0;i<skilllv;i++){
- if(!sd->dev.val1[i]){ // 空きがあったら入れる
+ for (i = 0; i < skilllv; i++) {
+ if (!sd->dev.val1[i]) { // 空きがあったら入れる
sd->dev.val1[i] = bl->id;
sd->dev.val2[i] = bl->id;
break;
- }else if(i==skilllv-1){ // 空きがなかった
+ } else if (i == skilllv - 1) { // 空きがなかった
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 1;
@@ -3294,54 +3274,56 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
clif_devotion(sd,bl->id);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],src->id,1,0,0,1000*(15+15*skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],src->id,1,0,0,1000*(15+15*skilllv),0 );
}
- else clif_skill_fail(sd,skillid,0,0);
+ else clif_skill_fail(sd,skillid,0,0);
break;
+
case MO_CALLSPIRITS: // ?功
if(sd) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
pc_addspiritball(sd,skill_get_time(skillid,skilllv),skilllv);
}
break;
+
case CH_SOULCOLLECT: // 狂?功
if(sd) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- for(i=0;i<5;i++)
+ for (i = 0; i < 5; i++)
pc_addspiritball(sd,skill_get_time(skillid,skilllv),5);
}
break;
+
case MO_BLADESTOP: // 白刃取り
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
+
case MO_ABSORBSPIRITS: // ?奪
i=0;
- if(sd && dstsd) {
- if(sd == dstsd || map[sd->bl.m].flag.pvp || map[sd->bl.m].flag.gvg) {
- if(dstsd->spiritball > 0) {
+ if (dstsd) {
+ if ((sd && sd == dstsd) || map[src->m].flag.pvp || map[src->m].flag.gvg) {
+ if (dstsd->spiritball > 0) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
i = dstsd->spiritball * 7;
pc_delspiritball(dstsd,dstsd->spiritball,0);
if(i > 0x7FFF)
i = 0x7FFF;
- if(sd->status.sp + i > sd->status.max_sp)
+ if(sd && sd->status.sp + i > sd->status.max_sp)
i = sd->status.max_sp - sd->status.sp;
- }
+ }
}
- }else if(sd && dstmd){ //?象がモンスタ?の場合
+ } else if (dstmd) { //?象がモンスタ?の場合
//20%の確率で?象のLv*2のSPを回復する。成功したときはタ?ゲット(σ?Д?)σ????!!
- if(rand()%100<20){
- i=2*mob_db[dstmd->class].lv;
+ if(rand() % 100 < 20) {
+ i = 2 * mob_db[dstmd->class_].lv;
mob_target(dstmd,src,0);
}
}
- if(i){
- sd->status.sp += i;
- clif_heal(sd->fd,SP_SP,i);
- }
- else
- clif_skill_nodamage(src,bl,skillid,skilllv,0);
+ if (i && sd){
+ sd->status.sp += i;
+ clif_heal(sd->fd,SP_SP,i);
+ } else clif_skill_nodamage(src,bl,skillid,skilllv,0);
break;
case AC_MAKINGARROW: /* 矢作成 */
@@ -3375,29 +3357,30 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
clif_skill_produce_mix_list(sd,256);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
- break;
+ break;
case BS_HAMMERFALL: /* ハンマ?フォ?ル */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_weapon_damage )
+ if(dstsd && dstsd->special_state.no_weapon_damage)
break;
- if( rand()%100 < (20+ 10*skilllv)*sc_def_vit/100 ) {
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
- }
+ if(rand() % 100 < (20 + 10 * skilllv) * sc_def_vit / 100 )
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case RG_RAID: /* サプライズアタック */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- {
- int x=bl->x,y=bl->y;
- skill_area_temp[1]=bl->id;
- skill_area_temp[2]=x;
- skill_area_temp[3]=y;
- map_foreachinarea(skill_area_sub,
- bl->m,x-1,y-1,x+1,y+1,0,
- src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
- skill_castend_damage_id);
- }
- skill_status_change_end(src, SC_HIDING, -1); // ハイディング解除
+ 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|1,
+ skill_castend_damage_id);
+ status_change_end(src, SC_HIDING, -1); // ハイディング解除
+ break;
+
+ case ASC_METEORASSAULT: /* メテオアサルト */
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ map_foreachinarea(skill_area_sub,
+ bl->m,bl->x-2,bl->y-2,bl->x+2,bl->y+2,0,
+ src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
+ skill_castend_damage_id);
break;
case KN_BRANDISHSPEAR: /*ブランディッシュスピア*/
@@ -3455,30 +3438,29 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case PR_MAGNIFICAT: /* マグニフィカ?ト */
case PR_GLORIA: /* グロリア */
case SN_WINDWALK: /* ウインドウォ?ク */
- if(sd == NULL || sd->status.party_id==0 || (flag&1) ){
+ if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) {
/* 個別の?理 */
clif_skill_nodamage(bl,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if(dstsd && dstsd->special_state.no_magic_damage)
break;
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
- }
- else{
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
+ } else if (sd) {
/* パ?ティ全?への?理 */
- party_foreachsamemap(skill_area_sub,
+ party_foreachsamemap (skill_area_sub,
sd,1,
src,skillid,skilllv,tick, flag|BCT_PARTY|1,
skill_castend_nodamage_id);
}
break;
+
case BS_ADRENALINE: /* アドレナリンラッシュ */
case BS_WEAPONPERFECT: /* ウェポンパ?フェクション */
case BS_OVERTHRUST: /* オ?バ?トラスト */
- if(sd == NULL || sd->status.party_id==0 || (flag&1) ){
+ if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) {
/* 個別の?理 */
clif_skill_nodamage(bl,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,(src == bl)? 1:0,0,0,skill_get_time(skillid,skilllv),0);
- }
- else{
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,(src == bl)? 1:0,0,0,skill_get_time(skillid,skilllv),0);
+ } else if (sd) {
/* パ?ティ全?への?理 */
party_foreachsamemap(skill_area_sub,
sd,1,
@@ -3493,66 +3475,54 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case CR_DEFENDER: /* ディフェンダ? */
case CR_AUTOGUARD: /* オ?トガ?ド */
{
- struct status_change *tsc_data = battle_get_sc_data(bl);
- int sc=SkillStatusChangeTable[skillid];
+ struct status_change *tsc_data = status_get_sc_data(bl);
+ int sc = SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( tsc_data ){
- if( tsc_data[sc].timer==-1 )
- /* 付加する */
- skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
- else
- /* 解除する */
- skill_status_change_end(bl, sc, -1);
- }
+ if (tsc_data && tsc_data[sc].timer != -1)
+ status_change_end(bl, sc, -1);
+ else
+ status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
break;
case TF_HIDING: /* ハイディング */
{
- struct status_change *tsc_data = battle_get_sc_data(bl);
- int sc=SkillStatusChangeTable[skillid];
+ struct status_change *tsc_data = status_get_sc_data(bl);
+ int sc = SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,-1,1);
- if( tsc_data ){
- if( tsc_data[sc].timer==-1 )
- /* 付加する */
- skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
+ if (tsc_data && tsc_data[sc].timer != -1)
+ status_change_end(bl, sc, -1);
else
- /* 解除する */
- skill_status_change_end(bl, sc, -1);
- }
+ status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
break;
case AS_CLOAKING: /* クロ?キング */
{
- struct status_change *tsc_data = battle_get_sc_data(bl);
+ struct status_change *tsc_data = status_get_sc_data(bl);
int sc=SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,-1,1);
- if( tsc_data ){
- if( tsc_data[sc].timer==-1 )
- /* 付加する */
- skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
- else
+ if(tsc_data && tsc_data[sc].timer!=-1 )
/* 解除する */
- skill_status_change_end(bl, sc, -1);
- }
+ status_change_end(bl, sc, -1);
+ else
+ /* 付加する */
+ status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
//skill_check_cloaking(bl);
}
break;
case ST_CHASEWALK: /* ハイディング */
{
- struct status_change *tsc_data = battle_get_sc_data(bl);
+ struct status_change *tsc_data = status_get_sc_data(bl);
int sc=SkillStatusChangeTable[skillid];
clif_skill_nodamage(src,bl,skillid,-1,1);
- if( tsc_data ){
- if( tsc_data[sc].timer==-1 )
- /* 付加する */
- skill_status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
- else
+ if(tsc_data && tsc_data[sc].timer!=-1 )
/* 解除する */
- skill_status_change_end(bl, sc, -1);
- }
+ status_change_end(bl, sc, -1);
+ else
+ /* 付加する */
+ status_change_start(bl,sc,skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
}
break;
@@ -3575,32 +3545,20 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case DC_DONTFORGETME: /* 私を忘れないで… */
case DC_FORTUNEKISS: /* 幸運のキス */
case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */
- case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
+// case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
break;
case HP_BASILICA: /* バジリカ */
{
- // cancel Basilica if already in effect
- struct status_change *sc_data = battle_get_sc_data(src);
- if(sc_data && sc_data[SC_BASILICA].timer != -1){
- struct skill_unit *su;
- if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) {
- struct skill_unit_group *sg;
- if ((sg = su->group) && sg->src_id == sd->bl.id) {
- skill_status_change_end(src,SC_BASILICA,-1);
- skill_delunitgroup (sg);
- break;
- }
- }
- } else {
- // otherwise allow casting
- skill_status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
- skill_clear_unitgroup(src);
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
- }
+ struct skill_unit_group *sg;
+ battle_stopwalking(src,1);
+ skill_clear_unitgroup(src);
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
+ status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,(int)sg,
+ skill_get_time(skillid,skilllv),0);
}
break;
@@ -3608,11 +3566,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
skill_clear_unitgroup(src);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_unitsetting(src,skillid,skilllv,src->x,src->y,0);
+ status_change_start(src,SkillStatusChangeTable[skillid],skilllv,0,0,BCT_SELF,skill_get_time(skillid,skilllv),0);
break;
case BD_ADAPTATION: /* アドリブ */
{
- struct status_change *sc_data = battle_get_sc_data(src);
+ struct status_change *sc_data = status_get_sc_data(src);
if(sc_data && sc_data[SC_DANCING].timer!=-1){
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skill_stop_dancing(src,0);
@@ -3636,11 +3595,11 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case RG_STEALCOIN: // スティ?ルコイン
- if(sd) {
+ if(sd) {
if(pc_steal_coin(sd,bl)) {
int range = skill_get_range(skillid,skilllv);
if(range < 0)
- range = battle_get_range(src) - (range + 1);
+ range = status_get_range(src) - (range + 1);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
mob_target((struct mob_data *)bl,src,range);
}
@@ -3650,17 +3609,41 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case MG_STONECURSE: /* スト?ンカ?ス */
- if (bl->type==BL_MOB && battle_get_mode(bl)&0x20) {
- clif_skill_fail(sd,sd->skillid,0,0);
- break;
+ {
+ struct status_change *sc_data = status_get_sc_data(bl);
+ // Level 6-10 doesn't consume a red gem if it fails [celest]
+ int i, gem_flag = 1, fail_flag = 0;
+ if (dstmd && status_get_mode(bl)&0x20) {
+ clif_skill_fail(sd,sd->skillid,0,0);
+ break;
+ }
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if(dstsd && dstsd->special_state.no_magic_damage )
+ break;
+ if (sc_data && sc_data[SC_STONE].timer != -1) {
+ status_change_end(bl,SC_STONE,-1);
+ if (sd) {
+ fail_flag = 1;
+ clif_skill_fail(sd,skillid,0,0);
+ }
+ }
+ else if( rand()%100 < skilllv*4+20 && !battle_check_undead(status_get_race(bl),status_get_elem_type(bl)))
+ status_change_start(bl,SC_STONE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ else if(sd) {
+ if (skilllv > 5) gem_flag = 0;
+ clif_skill_fail(sd,skillid,0,0);
+ fail_flag = 1;
+ }
+ if (dstmd)
+ mob_target(dstmd,src,skill_get_range(skillid,skilllv));
+ if (sd && gem_flag) {
+ if ((i=pc_search_inventory(sd, skill_db[skillid].itemid[0])) < 0 ) {
+ if (!fail_flag) clif_skill_fail(sd,sd->skillid,0,0);
+ break;
+ }
+ pc_delitem(sd, i, skill_db[skillid].amount[0], 0);
+ }
}
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
- break;
- if( rand()%100 < skilllv*4+20 && !battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
- skill_status_change_start(bl,SC_STONE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
- else if(sd)
- clif_skill_fail(sd,skillid,0,0);
break;
case NV_FIRSTAID: /* ?急手? */
@@ -3670,37 +3653,36 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case AL_CURE: /* キュア? */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if(dstsd && dstsd->special_state.no_magic_damage )
break;
- skill_status_change_end(bl, SC_SILENCE , -1 );
- skill_status_change_end(bl, SC_BLIND , -1 );
- skill_status_change_end(bl, SC_CONFUSION, -1 );
- if( battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) ){//アンデッドなら暗闇?果
- skill_status_change_start(bl, SC_CONFUSION,1,0,0,0,6000,0);
+ status_change_end(bl, SC_SILENCE , -1 );
+ status_change_end(bl, SC_BLIND , -1 );
+ status_change_end(bl, SC_CONFUSION, -1 );
+ if( battle_check_undead(status_get_race(bl),status_get_elem_type(bl)) ){//アンデッドなら暗闇?果
+ status_change_start(bl, SC_CONFUSION,1,0,0,0,6000,0);
}
break;
case TF_DETOXIFY: /* 解毒 */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_end(bl, SC_POISON , -1 );
- skill_status_change_end(bl, SC_DPOISON , -1 );
+ status_change_end(bl, SC_POISON , -1 );
+ status_change_end(bl, SC_DPOISON , -1 );
break;
case PR_STRECOVERY: /* リカバリ? */
{
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if(dstsd && dstsd->special_state.no_magic_damage)
break;
- skill_status_change_end(bl, SC_FREEZE , -1 );
- skill_status_change_end(bl, SC_STONE , -1 );
- skill_status_change_end(bl, SC_SLEEP , -1 );
- skill_status_change_end(bl, SC_STAN , -1 );
- if( battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)) ){//アンデッドなら暗闇?果
- int blind_time;
- //blind_time=30-battle_get_vit(bl)/10-battle_get_int/15;
- blind_time=30*(100-(battle_get_int(bl)+battle_get_vit(bl))/2)/100;
- if(rand()%100 < (100-(battle_get_int(bl)/2+battle_get_vit(bl)/3+battle_get_luk(bl)/10)))
- skill_status_change_start(bl, SC_BLIND,1,0,0,0,blind_time,0);
+ status_change_end(bl, SC_FREEZE , -1 );
+ status_change_end(bl, SC_STONE , -1 );
+ status_change_end(bl, SC_SLEEP , -1 );
+ status_change_end(bl, SC_STAN , -1 );
+ if( battle_check_undead(status_get_race(bl),status_get_elem_type(bl)) ){//アンデッドなら暗闇?果
+ if(rand()%100 < (100-(status_get_int(bl)/2+status_get_vit(bl)/3+status_get_luk(bl)/10))) {
+ status_change_start(bl, SC_BLIND,1,0,0,0,
+ 1000 * 30 * (100-(status_get_int(bl)+status_get_vit(bl))/2)/100,0);
+ }
}
if(dstmd){
dstmd->attacked_id=0;
@@ -3713,7 +3695,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case WZ_ESTIMATION: /* モンスタ?情報 */
- if(src->type==BL_PC){
+ if(sd) {
clif_skill_nodamage(src,bl,skillid,skilllv,1);
clif_skill_estimation((struct map_session_data *)src,bl);
}
@@ -3727,11 +3709,11 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case BS_REPAIRWEAPON: /* 武器修理 */
if(sd) {
//動作しないのでとりあえずコメントアウト
- if (pc_search_inventory(sd, 999) < 0 ) { //fixed by Lupus (item pos can be = 0!)
+ /*if (pc_search_inventory(sd, 999) < 0 ) { //fixed by Lupus (item pos can be = 0!)
clif_skill_fail(sd,sd->skillid,0,0);
map_freeblock_unlock();
return 1;
- }
+ }*/
clif_item_repair_list(sd);
}
break;
@@ -3742,20 +3724,20 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case AL_TELEPORT: /* テレポ?ト */
- if( sd ){
- if(map[sd->bl.m].flag.noteleport){ /* テレポ禁止 */
+ if(sd) {
+ if (map[sd->bl.m].flag.noteleport) { /* テレポ禁止 */
clif_skill_teleportmessage(sd,0);
break;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( sd->skilllv==1 )
+ if(sd->skilllv == 1)
clif_skill_warppoint(sd,sd->skillid,"Random","","","");
- else{
+ else {
clif_skill_warppoint(sd,sd->skillid,"Random",
sd->status.save_point.map,"","");
}
- }else if( bl->type==BL_MOB )
- mob_warp((struct mob_data *)bl,-1,-1,-1,3);
+ } else if(dstmd)
+ mob_warp(dstmd,-1,-1,-1,3);
break;
case AL_HOLYWATER: /* アクアベネディクタ */
@@ -3799,136 +3781,102 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case RG_STRIPWEAPON: /* ストリップウェポン */
- {
- struct status_change *tsc_data = battle_get_sc_data(bl);
-
- if(tsc_data && tsc_data[SC_CP_WEAPON].timer != -1 )
+ case RG_STRIPSHIELD: /* ストリップシールド */
+ case RG_STRIPARMOR: /* ストリップアーマー */
+ case RG_STRIPHELM: /* ストリップヘルム */
+ {
+ struct status_change *tsc_data;
+ int strip_time, strip_per, strip_fix;
+ int scid, cp_scid = 0, equip;
+
+ tsc_data = status_get_sc_data(bl);
+ scid = SkillStatusChangeTable[skillid];
+ switch (skillid) {
+ case RG_STRIPWEAPON:
+ equip = EQP_WEAPON;
+ cp_scid = SC_CP_WEAPON;
break;
- strip_per = 5+2*skilllv+strip_fix/5;
- strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
- if(rand()%100 < strip_per){
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
- if(dstsd){
- for(i=0;i<MAX_INVENTORY;i++){
- if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0002){
- pc_unequipitem(dstsd,i,0,BF_SKILL);
- break;
- }
- }
- }
- }
- }
- break;
-
- case RG_STRIPSHIELD: /* ストリップシ?ルド */
- {
- struct status_change *tsc_data = battle_get_sc_data(bl);
-
- if(tsc_data && tsc_data[SC_CP_SHIELD].timer != -1 )
+ case RG_STRIPSHIELD:
+ equip = EQP_SHIELD;
+ cp_scid = SC_CP_SHIELD;
break;
- strip_per = 5+2*skilllv+strip_fix/5;
- strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
- if(rand()%100 < strip_per){
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
- if(dstsd){
- for(i=0;i<MAX_INVENTORY;i++){
- if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0020){
- pc_unequipitem(dstsd,i,0,BF_SKILL);
- break;
- }
- }
- }
- }
- }
- break;
-
- case RG_STRIPARMOR: /* ストリップア?マ? */
- {
- struct status_change *tsc_data = battle_get_sc_data(bl);
-
- if(tsc_data && tsc_data[SC_CP_ARMOR].timer != -1 )
+ case RG_STRIPARMOR:
+ equip = EQP_ARMOR;
+ cp_scid = SC_CP_ARMOR;
break;
- strip_per = 5+2*skilllv+strip_fix/5;
- strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
- if(rand()%100 < strip_per){
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
- if(dstsd){
- for(i=0;i<MAX_INVENTORY;i++){
- if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0010){
- pc_unequipitem(dstsd,i,0,BF_SKILL);
- break;
- }
- }
- }
- }
- }
- break;
-
- case RG_STRIPHELM: /* ストリップヘルム */
- {
- struct status_change *tsc_data = battle_get_sc_data(bl);
-
- if(tsc_data && tsc_data[SC_CP_HELM].timer != -1 )
+ case RG_STRIPHELM:
+ equip = EQP_HELM;
+ cp_scid = SC_CP_HELM;
break;
- strip_per = 5+2*skilllv+strip_fix/5;
- strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
- if(rand()%100 < strip_per){
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
- if(dstsd){
- for(i=0;i<MAX_INVENTORY;i++){
- if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0100){
- pc_unequipitem(dstsd,i,0,BF_SKILL);
- break;
- }
- }
- }
- }
+ default:
+ map_freeblock_unlock();
+ return 1;
}
- break;
- // Full Strip [Celest]
- case ST_FULLSTRIP:
- {
- struct status_change *tsc_data = battle_get_sc_data(bl);
- int c=0, i, j;
- int striplist[2][4] = { { 0, 0, 0, 0 },
- { 0x0002, 0x0020, 0x0010, 0x0100 } };
+ if (tsc_data && (tsc_data[scid].timer != -1 || tsc_data[cp_scid].timer != -1))
+ break;
+ if (dstsd && dstsd->unstripable_equip & equip)
+ break;
- strip_per = 5+2*skilllv+strip_fix/5;
- strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
- for (i=0; i<4; i++) {
- if(tsc_data && tsc_data[SC_CP_WEAPON + i].timer != -1)
+ strip_fix = status_get_dex(src) - status_get_dex(bl);
+ if(strip_fix < 0)
+ strip_fix=0;
+ strip_per = 5+5*skilllv+strip_fix/5;
+ if (rand()%100 >= strip_per)
+ break;
+
+ if (dstsd) {
+ for (i=0;i<MAX_INVENTORY;i++) {
+ if (dstsd->status.inventory[i].equip && (dstsd->status.inventory[i].equip & equip)){
+ pc_unequipitem(dstsd,i,3);
break;
- if(rand()%100 < strip_per) {
- striplist[0][i] = 1;
- c++;
}
}
-
- if (c > 0) {
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- for (j=0; j<4 && c > 0; j++) {
- if (striplist[0][j]) {
- skill_status_change_start(bl,SC_STRIPWEAPON + i,skilllv,0,0,0,strip_time,0 );
- if(dstsd){
- for(i=0;i<MAX_INVENTORY;i++){
- if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & striplist[1][j]){
- pc_unequipitem(dstsd,i,0,BF_SKILL);
- --c;
- break;
- }
- }
- }
+ if (i == MAX_INVENTORY)
+ break;
+ }
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
+ status_change_start(bl,scid,skilllv,0,0,0,strip_time,0 );
+ break;
+ }
+ case ST_FULLSTRIP: // Celest
+ {
+ struct status_change *tsc_data;
+ int i, j, strip_time, strip_per, strip_fix;
+ int equip[4] = { EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HELM };
+ int scid[4] = { SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM };
+ int cp_scid[4] = { SC_CP_WEAPON, SC_CP_SHIELD, SC_CP_ARMOR, SC_CP_HELM };
+
+ tsc_data = status_get_sc_data(bl);
+ strip_fix = status_get_dex(src) - status_get_dex(bl);
+ if(strip_fix < 0)
+ strip_fix = 0;
+ strip_per = 5+5*skilllv+strip_fix/5;
+ if (rand()%100 >= strip_per)
+ break;
+ strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
+
+ for (i=0; i<4; i++) {
+ if (dstsd) {
+ if (tsc_data && (tsc_data[scid[i]].timer != -1 || tsc_data[cp_scid[i]].timer != -1))
+ continue;
+ if (dstsd->unstripable_equip & equip[i])
+ continue;
+ for (j=0; j<MAX_INVENTORY; j++) {
+ if (dstsd->status.inventory[j].equip && (dstsd->status.inventory[j].equip & equip[i])){
+ pc_unequipitem(dstsd,j,3);
+ break;
}
}
+ if (j == MAX_INVENTORY)
+ continue;
}
+ status_change_start(bl,scid[i],skilllv,0,0,0,strip_time,0 );
}
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
break;
-
+ }
/* PotionPitcher */
case AM_POTIONPITCHER: /* ポ?ションピッチャ? */
@@ -3936,10 +3884,6 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
struct block_list tbl;
int i,x,hp = 0,sp = 0;
if(sd) {
- if(sd==dstsd) { // cancel use on oneself
- map_freeblock_unlock();
- return 1;
- }
x = skilllv%11 - 1;
i = pc_search_inventory(sd,skill_db[skillid].itemid[x]);
if(i < 0 || skill_db[skillid].itemid[x] <= 0) {
@@ -3959,7 +3903,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
pc_delitem(sd,i,skill_db[skillid].amount[x],0);
sd->state.potionpitcher_flag = 0;
if(sd->potion_per_hp > 0 || sd->potion_per_sp > 0) {
- hp = battle_get_max_hp(bl) * sd->potion_per_hp / 100;
+ hp = status_get_max_hp(bl) * sd->potion_per_hp / 100;
hp = hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
if(dstsd) {
sp = dstsd->status.max_sp * sd->potion_per_sp / 100;
@@ -3969,13 +3913,13 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
else {
if(sd->potion_hp > 0) {
hp = sd->potion_hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
- hp = hp * (100 + (battle_get_vit(bl)<<1)) / 100;
+ hp = hp * (100 + (status_get_vit(bl)<<1)) / 100;
if(dstsd)
hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100;
}
if(sd->potion_sp > 0) {
sp = sd->potion_sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
- sp = sp * (100 + (battle_get_int(bl)<<1)) / 100;
+ sp = sp * (100 + (status_get_int(bl)<<1)) / 100;
if(dstsd)
sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100;
}
@@ -3983,7 +3927,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
else {
hp = (1 + rand()%400) * (100 + skilllv*10) / 100;
- hp = hp * (100 + (battle_get_vit(bl)<<1)) / 100;
+ hp = hp * (100 + (status_get_vit(bl)<<1)) / 100;
if(dstsd)
hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100;
}
@@ -4000,39 +3944,16 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
break;
case AM_CP_WEAPON:
- {
- struct status_change *tsc_data = battle_get_sc_data(bl);
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if(tsc_data && tsc_data[SC_STRIPWEAPON].timer != -1)
- skill_status_change_end(bl, SC_STRIPWEAPON, -1 );
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
- }
- break;
case AM_CP_SHIELD:
- {
- struct status_change *tsc_data = battle_get_sc_data(bl);
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if(tsc_data && tsc_data[SC_STRIPSHIELD].timer != -1)
- skill_status_change_end(bl, SC_STRIPSHIELD, -1 );
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
- }
- break;
case AM_CP_ARMOR:
- {
- struct status_change *tsc_data = battle_get_sc_data(bl);
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if(tsc_data && tsc_data[SC_STRIPARMOR].timer != -1)
- skill_status_change_end(bl, SC_STRIPARMOR, -1 );
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
- }
- break;
case AM_CP_HELM:
{
- struct status_change *tsc_data = battle_get_sc_data(bl);
+ int scid = SC_STRIPWEAPON + (skillid - AM_CP_WEAPON);
+ struct status_change *tsc_data = status_get_sc_data(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if(tsc_data && tsc_data[SC_STRIPHELM].timer != -1)
- skill_status_change_end(bl, SC_STRIPHELM, -1 );
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ if(tsc_data && tsc_data[scid].timer != -1)
+ status_change_end(bl, scid, -1 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
}
break;
@@ -4040,7 +3961,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
{
int i;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if(dstsd && dstsd->special_state.no_magic_damage )
break;
for(i=0;i<136;i++){
if(i==SC_RIDING || i== SC_FALCON || i==SC_HALLUCINATION || i==SC_WEIGHT50
@@ -4048,7 +3969,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
|| i==SC_STRIPHELM || i==SC_CP_WEAPON || i==SC_CP_SHIELD || i==SC_CP_ARMOR
|| i==SC_CP_HELM || i==SC_COMBO)
continue;
- skill_status_change_end(bl,i,-1);
+ status_change_end(bl,i,-1);
}
}
break;
@@ -4056,12 +3977,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case TF_BACKSLIDING: /* バックステップ */
battle_stopwalking(src,1);
skill_blown(src,bl,skill_get_blewcount(skillid,skilllv)|0x10000);
- if(src->type == BL_MOB)
- clif_fixmobpos((struct mob_data *)src);
- else if(src->type == BL_PET)
- clif_fixpetpos((struct pet_data *)src);
- else if(src->type == BL_PC)
+ if (sd)
clif_fixpos(src);
+ else if (md)
+ clif_fixmobpos(md);
+ else if (src->type == BL_PET)
+ clif_fixpetpos((struct pet_data *)src);
skill_addtimerskill(src,tick + 200,src->id,0,0,skillid,skilllv,0,flag);
break;
@@ -4077,7 +3998,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case SA_SPELLBREAKER: // スペルブレイカ?
{
- struct status_change *sc_data = battle_get_sc_data(bl);
+ struct status_change *sc_data = status_get_sc_data(bl);
int sp;
if(sc_data && sc_data[SC_MAGICROD].timer != -1) {
if(dstsd) {
@@ -4140,9 +4061,9 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
break;
case SA_MAGICROD:
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if (dstsd && dstsd->special_state.no_magic_damage )
break;
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case SA_AUTOSPELL: /* オ?トスペル */
clif_skill_nodamage(src,bl,skillid,skilllv,1);
@@ -4173,7 +4094,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
maxlv = 3;
}
if(spellid > 0)
- skill_status_change_start(src,SC_AUTOSPELL,skilllv,spellid,maxlv,0,
+ status_change_start(src,SC_AUTOSPELL,skilllv,spellid,maxlv,0,
skill_get_time(SA_AUTOSPELL,skilllv),0);
}
break;
@@ -4201,14 +4122,14 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case NPC_PROVOCATION:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
if(md)
- clif_pet_performance(src,mob_db[md->class].skill[md->skillidx].val[0]);
+ clif_pet_performance(src,mob_db[md->class_].skill[md->skillidx].val[0]);
break;
case NPC_HALLUCINATION:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if(dstsd && dstsd->special_state.no_magic_damage )
break;
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
break;
case NPC_KEEPING:
@@ -4216,25 +4137,25 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
{
int skill_time = skill_get_time(skillid,skilllv);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_time,0 );
- if (bl->type == BL_MOB)
- mob_changestate((struct mob_data *)src,MS_DELAY,skill_time);
- else if (bl->type == BL_PC)
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_time,0 );
+ if (md)
+ mob_changestate(md,MS_DELAY,skill_time);
+ else if (sd)
sd->attackabletime = sd->canmove_tick = tick + skill_time;
}
break;
case NPC_DARKBLESSING:
{
- int sc_def = 100 - battle_get_mdef(bl);
+ int sc_def = 100 - status_get_mdef(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
+ if(dstsd && dstsd->special_state.no_magic_damage )
break;
- if(battle_get_elem_type(bl) == 7 || battle_get_race(bl) == 6)
+ if(status_get_elem_type(bl) == 7 || status_get_race(bl) == 6)
break;
if(rand()%100 < sc_def*(50+skilllv*5)/100) {
if(dstsd) {
- int hp = battle_get_hp(bl)-1;
+ int hp = status_get_hp(bl)-1;
pc_heal(dstsd,-hp,0);
}
else if(dstmd)
@@ -4245,16 +4166,17 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case NPC_SELFDESTRUCTION: /* 自爆 */
case NPC_SELFDESTRUCTION2: /* 自爆2 */
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,0,0,skill_get_time(skillid,skilllv),0);
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,0,0,skill_get_time(skillid,skilllv),0);
break;
case NPC_LICK:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_weapon_damage )
- break;
- if(dstsd)
+ if (dstsd) {
+ if (dstsd->special_state.no_weapon_damage )
+ break;
pc_heal(dstsd,0,-100);
+ }
if(rand()%100 < (skilllv*5)*sc_def_vit/100)
- skill_status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case NPC_SUICIDE: /* 自決 */
@@ -4269,26 +4191,106 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case NPC_SUMMONSLAVE: /* 手下召喚 */
case NPC_SUMMONMONSTER: /* MOB召喚 */
- if(md && !md->master_id){
- mob_summonslave(md,mob_db[md->class].skill[md->skillidx].val,skilllv,(skillid==NPC_SUMMONSLAVE)?1:0);
+ if(md)
+ mob_summonslave(md,mob_db[md->class_].skill[md->skillidx].val,skilllv,(skillid==NPC_SUMMONSLAVE)?1:0);
+ break;
+
+ case NPC_RECALL: //取り巻き呼び戻し
+ if(md) {
+ int mobcount;
+ md->recallcount = 0;//初期化
+ md->recall_flag = 0;
+ mobcount = mob_countslave(md);
+ if(mobcount > 0) {
+ md->recall_flag = 1; //mob.cの[取り巻きモンスターの処理]で利用
+ md->recallmob_count = mobcount;
+ }
+ }
+ break;
+
+ case NPC_RUNAWAY: //後退
+ if(md) {
+ int check;
+ int dist = skilllv;//後退する距離
+ check = md->dir; //自分がどの方向に向いてるかチェック
+ md->attacked_id = 0;
+ md->target_id = 0;
+ md->state.targettype = NONE_ATTACKABLE;
+ md->state.skillstate = MSS_IDLE;
+ switch (check) {
+ case 0: //自分の向いてる方向と逆に移動する
+ mob_walktoxy(md,md->bl.x,md->bl.y-dist,0);//そして、移動する
+ break;
+ case 1:
+ mob_walktoxy(md,md->bl.x-dist,md->bl.y-dist,0);
+ break;
+ case 2:
+ mob_walktoxy(md,md->bl.x+dist,md->bl.y,0);
+ break;
+ case 3:
+ mob_walktoxy(md,md->bl.x+dist,md->bl.y+dist,0);
+ break;
+ case 4:
+ mob_walktoxy(md,md->bl.x,md->bl.y+dist,0);
+ break;
+ case 5:
+ mob_walktoxy(md,md->bl.x-dist,md->bl.y+dist,0);
+ break;
+ case 6:
+ mob_walktoxy(md,md->bl.x-dist,md->bl.y,0);
+ break;
+ case 7:
+ mob_walktoxy(md,md->bl.x-dist,md->bl.y-dist,0);
+ break;
+ }
}
break;
case NPC_TRANSFORMATION:
case NPC_METAMORPHOSIS:
if(md)
- mob_class_change(md,mob_db[md->class].skill[md->skillidx].val);
+ mob_class_change(md,mob_db[md->class_].skill[md->skillidx].val);
break;
case NPC_EMOTION: /* エモ?ション */
if(md)
- clif_emotion(&md->bl,mob_db[md->class].skill[md->skillidx].val[0]);
+ clif_emotion(&md->bl,mob_db[md->class_].skill[md->skillidx].val[0]);
break;
case NPC_DEFENDER:
clif_skill_nodamage(src,bl,skillid,skilllv,1);
break;
+ // Equipment breaking monster skills [Celest]
+ case NPC_BREAKWEAPON:
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if(dstsd && battle_config.equipment_breaking)
+ pc_breakweapon(dstsd);
+ break;
+
+ case NPC_BREAKARMOR:
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if(dstsd && battle_config.equipment_breaking)
+ pc_breakarmor(dstsd);
+ break;
+
+ case NPC_BREAKHELM:
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if(dstsd && battle_config.equipment_breaking)
+ pc_breakhelm(dstsd);
+ break;
+
+ case NPC_BREAKSHIELD:
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ if(dstsd && battle_config.equipment_breaking)
+ pc_breakshield(dstsd);
+ break;
+
+ case NPC_EXPLOSIONSPIRITS: //NPC爆裂波動
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ status_change_start(bl,SC_EXPLOSIONSPIRITS,skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ break;
+
case WE_MALE: /* 君だけは護るよ */
if(sd && dstsd){
int hp_rate=(skilllv <= 0)? 0:skill_db[skillid].hp_rate[skilllv-1];
@@ -4310,27 +4312,85 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
if(sd && dstsd){
if((dstsd = pc_get_partner(sd)) == NULL){
clif_skill_fail(sd,skillid,0,0);
+ map_freeblock_unlock();
return 0;
}
if(map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto || map[dstsd->bl.m].flag.nowarp){
clif_skill_teleportmessage(sd,1);
+ map_freeblock_unlock();
return 0;
- }
+ }
skill_unitsetting(src,skillid,skilllv,sd->bl.x,sd->bl.y,0);
}
break;
+// parent-baby skills
+ case WE_BABY:
+ if(sd && dstsd){
+ struct map_session_data *f_sd = pc_get_father(sd);
+ struct map_session_data *m_sd = pc_get_mother(sd);
+ // if neither was found
+ if(!f_sd && !m_sd){
+ clif_skill_fail(sd,skillid,0,0);
+ map_freeblock_unlock();
+ return 0;
+ }
+ status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+ if (f_sd) status_change_start(&f_sd->bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ if (m_sd) status_change_start(&m_sd->bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ }
+ break;
+
+ case WE_CALLPARENT:
+ if(sd && dstsd){
+ struct map_session_data *f_sd = pc_get_father(sd);
+ struct map_session_data *m_sd = pc_get_mother(sd);
+ // if neither was found
+ if(!f_sd && !m_sd){
+ clif_skill_fail(sd,skillid,0,0);
+ map_freeblock_unlock();
+ return 0;
+ }
+ if(map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto || map[dstsd->bl.m].flag.nowarp){
+ clif_skill_teleportmessage(sd,1);
+ map_freeblock_unlock();
+ return 0;
+ }
+ if (f_sd) pc_setpos(f_sd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,3);
+ if (m_sd) pc_setpos(f_sd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,3);
+ }
+ break;
+
+ case WE_CALLBABY:
+ if(sd && dstsd){
+ if((dstsd = pc_get_child(sd)) == NULL){
+ clif_skill_fail(sd,skillid,0,0);
+ map_freeblock_unlock();
+ return 0;
+ }
+ if(map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto || map[dstsd->bl.m].flag.nowarp){
+ clif_skill_teleportmessage(sd,1);
+ map_freeblock_unlock();
+ return 0;
+ }
+ pc_setpos(dstsd,map[sd->bl.m].name,sd->bl.x,sd->bl.y,3);
+ }
+ break;
+
case PF_HPCONVERSION: /* ライフ置き換え */
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if(sd){
- int conv_hp=0,conv_sp=0;
- conv_hp=sd->status.hp/10; //基本はHPの10%
- sd->status.hp -= conv_hp; //HPを減らす
- conv_sp=conv_hp*10*skilllv/100;
- conv_sp=(sd->status.sp+conv_sp>sd->status.max_sp)?sd->status.max_sp-sd->status.sp:conv_sp;
- sd->status.sp += conv_sp; //SPを?やす
- pc_heal(sd,-conv_hp,conv_sp);
- clif_heal(sd->fd,SP_SP,conv_sp);
+ clif_skill_nodamage(src, bl, skillid, skilllv, 1);
+ if (sd) {
+ int hp, sp;
+ hp = sd->status.max_hp / 10; //基本はHPの10%
+ sp = hp * 10 * skilllv / 100;
+ if (sd->status.sp + sp > sd->status.max_sp)
+ sp = sd->status.max_sp - sd->status.sp;
+ // we need to check with the sp that was taken away when casting too
+ if (sd->status.sp + skill_get_sp(skillid, skilllv) >= sd->status.max_sp)
+ hp = sp = 0;
+ pc_heal(sd, -hp, sp);
+ clif_heal(sd->fd, SP_SP, sp);
+ clif_updatestatus(sd, SP_SP);
}
break;
case HT_REMOVETRAP: /* リム?ブトラップ */
@@ -4346,13 +4406,13 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
(su->group->unit_id != 0x92)){ //?を取り返す
if(sd){
if(battle_config.skill_removetrap_type == 1){
- for(i=0;i<10;i++) {
- if(skill_db[su->group->skill_id].itemid[i] > 0){
- memset(&item_tmp,0,sizeof(item_tmp));
- item_tmp.nameid = skill_db[su->group->skill_id].itemid[i];
- item_tmp.identify = 1;
- if(item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,skill_db[su->group->skill_id].amount[i]))){
- clif_additem(sd,0,0,flag);
+ for(i=0;i<10;i++) {
+ if(skill_db[su->group->skill_id].itemid[i] > 0){
+ memset(&item_tmp,0,sizeof(item_tmp));
+ item_tmp.nameid = skill_db[su->group->skill_id].itemid[i];
+ item_tmp.identify = 1;
+ if(item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,skill_db[su->group->skill_id].amount[i]))){
+ clif_additem(sd,0,0,flag);
map_addflooritem(&item_tmp,skill_db[su->group->skill_id].amount[i],sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
}
}
@@ -4366,12 +4426,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
}
}
-
+
}
if(su->group->unit_id == 0x91 && su->group->val2){
struct block_list *target=map_id2bl(su->group->val2);
if(target && (target->type == BL_PC || target->type == BL_MOB))
- skill_status_change_end(target,SC_ANKLE,-1);
+ status_change_end(target,SC_ANKLE,-1);
}
skill_delunit(su);
}
@@ -4383,6 +4443,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
struct skill_unit *su=NULL;
if((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group) ){
switch(su->group->unit_id){
+ case 0x91: // ankle snare
+ if (su->group->val2 != 0)
+ // if it is already trapping something don't spring it,
+ // remove trap should be used instead
+ break;
+ // otherwise fallthrough to below
case 0x8f: /* ブラストマイン */
case 0x90: /* スキッドトラップ */
case 0x93: /* ランドマイン */
@@ -4407,25 +4473,27 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
break;
case AS_SPLASHER: /* ベナムスプラッシャ? */
- if((double)battle_get_max_hp(bl)*2/3 < battle_get_hp(bl)) //HPが2/3以上?っていたら失敗
+ if((double)status_get_max_hp(bl)*2/3 < status_get_hp(bl)) { //HPが2/3以上?っていたら失敗
+ map_freeblock_unlock();
return 1;
+ }
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,src->id,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,skillid,src->id,skill_get_time(skillid,skilllv),1000,0 );
break;
case PF_MINDBREAKER: /* プロボック */
{
- struct status_change *sc_data = battle_get_sc_data(bl);
+ struct status_change *sc_data = status_get_sc_data(bl);
/* MVPmobと不死には?かない */
- if((bl->type==BL_MOB && battle_get_mode(bl)&0x20) || battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))) //不死には?かない
+ if((dstmd && status_get_mode(bl)&0x20) || battle_check_undead(status_get_race(bl),status_get_elem_type(bl))) //不死には?かない
{
map_freeblock_unlock();
return 1;
}
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
+ status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
if(dstmd && dstmd->skilltimer!=-1 && dstmd->state.skillcastcancel) // 詠唱妨害
skill_castcancel(bl,0);
@@ -4435,22 +4503,55 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
if(sc_data){
if(sc_data[SC_FREEZE].timer!=-1)
- skill_status_change_end(bl,SC_FREEZE,-1);
+ status_change_end(bl,SC_FREEZE,-1);
if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0)
- skill_status_change_end(bl,SC_STONE,-1);
+ status_change_end(bl,SC_STONE,-1);
if(sc_data[SC_SLEEP].timer!=-1)
- skill_status_change_end(bl,SC_SLEEP,-1);
+ status_change_end(bl,SC_SLEEP,-1);
}
- if(bl->type==BL_MOB) {
- int range = skill_get_range(skillid,skilllv);
- if(range < 0)
- range = battle_get_range(src) - (range + 1);
- mob_target((struct mob_data *)bl,src,range);
+ if(dstmd)
+ mob_target(dstmd,src,skill_get_range(skillid,skilllv));
+ }
+ break;
+
+ case PF_SOULCHANGE:
+ {
+ int sp1 = 0, sp2 = 0;
+ if (sd) {
+ if (dstsd) {
+ sp1 = sd->status.sp > dstsd->status.max_sp ? dstsd->status.max_sp : sd->status.sp;
+ sp2 = dstsd->status.sp > sd->status.max_sp ? sd->status.max_sp : dstsd->status.sp;
+ sd->status.sp = sp2;
+ dstsd->status.sp = sp1;
+ clif_heal(sd->fd,SP_SP,sp2);
+ clif_updatestatus(sd,SP_SP);
+ clif_heal(dstsd->fd,SP_SP,sp1);
+ clif_updatestatus(dstsd,SP_SP);
+ } else if (dstmd) {
+ if (dstmd->state.soul_change_flag) {
+ clif_skill_fail(sd,skillid,0,0);
+ map_freeblock_unlock();
+ return 0;
+ }
+ sp2 = sd->status.max_sp * 3 /100;
+ if (sd->status.sp + sp2 > sd->status.max_sp)
+ sp2 = sd->status.max_sp - sd->status.sp;
+ sd->status.sp += sp2;
+ clif_heal(sd->fd,SP_SP,sp2);
+ clif_updatestatus(sd,SP_SP);
+ dstmd->state.soul_change_flag = 1;
+ }
}
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
}
break;
+ case PF_SPIDERWEB: /* スパイダ?ウェッブ */
+ clif_skill_nodamage(src,bl,skillid,skilllv,1);
+ skill_unitsetting(src,skillid,skilllv,bl->x,bl->y,0);
+ break;
+
// Weapon Refining [Celest]
case WS_WEAPONREFINE:
if(sd)
@@ -4461,12 +4562,18 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case CR_SLIMPITCHER:
{
if (sd && flag&1) {
- int hp = sd->potion_hp * (100 + pc_checkskill(sd,CR_SLIMPITCHER)*5 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
- hp = hp * (100 + (battle_get_vit(bl)<<1))/100;
- if (dstsd)
+ struct block_list tbl;
+ int hp = sd->potion_hp * (100 + pc_checkskill(sd,CR_SLIMPITCHER)*10 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)/100;
+ hp = hp * (100 + (status_get_vit(bl)<<1))/100;
+ if (dstsd) {
hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10)/100;
- clif_skill_nodamage(src,bl,skillid,skilllv,1);
- battle_heal(src,bl,hp,0,0);
+ }
+ tbl.id = 0;
+ tbl.m = src->m;
+ tbl.x = src->x;
+ tbl.y = src->y;
+ clif_skill_nodamage(&tbl,bl,AL_HEAL,hp,1);
+ battle_heal(NULL,bl,hp,0,0);
}
}
break;
@@ -4474,13 +4581,13 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
case CR_FULLPROTECTION:
{
int i, skilltime;
- struct status_change *tsc_data = battle_get_sc_data(bl);
+ struct status_change *tsc_data = status_get_sc_data(bl);
clif_skill_nodamage(src,bl,skillid,skilllv,1);
skilltime = skill_get_time(skillid,skilllv);
for (i=0; i<4; i++) {
if(tsc_data && tsc_data[SC_STRIPWEAPON + i].timer != -1)
- skill_status_change_end(bl, SC_STRIPWEAPON + i, -1 );
- skill_status_change_start(bl,SC_CP_WEAPON + i,skilllv,0,0,0,skilltime,0 );
+ status_change_end(bl, SC_STRIPWEAPON + i, -1 );
+ status_change_start(bl,SC_CP_WEAPON + i,skilllv,0,0,0,skilltime,0 );
}
}
break;
@@ -4498,6 +4605,15 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
}
break;
+ case ST_PRESERVE:
+ if (sd){
+ if (sd->sc_count && sd->sc_data[SC_PRESERVE].timer != -1)
+ status_change_end(src, SC_PRESERVE, -1 );
+ else
+ status_change_start(src,SC_PRESERVE,skilllv,0,0,0,skill_get_time(skillid, skilllv),0 );
+ clif_skill_nodamage(src,src,skillid,skilllv,1);
+ }
+ break;
// New guild skills [Celest]
case GD_BATTLEORDER:
@@ -4511,7 +4627,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
if(flag&1) {
if (dstsd && dstsd->status.guild_id == sd->status.guild_id) {
- skill_status_change_start(&dstsd->bl,SC_BATTLEORDERS,skilllv,0,0,0,0,0 );
+ status_change_start(&dstsd->bl,SC_BATTLEORDERS,skilllv,0,0,0,0,0 );
}
}
else if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) &&
@@ -4521,6 +4637,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
src->m,src->x-15,src->y-15,src->x+15,src->y+15,0,
src,skillid,skilllv,tick, flag|BCT_ALL|1,
skill_castend_nodamage_id);
+ pc_blockskill_start (sd, skillid, 300000);
}
}
break;
@@ -4535,7 +4652,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
}
if(flag&1) {
if (dstsd && dstsd->status.guild_id == sd->status.guild_id) {
- skill_status_change_start(&dstsd->bl,SC_REGENERATION,skilllv,0,0,0,0,0 );
+ status_change_start(&dstsd->bl,SC_REGENERATION,skilllv,0,0,0,0,0 );
}
}
else if (sd && sd->status.guild_id > 0 && (g = guild_search(sd->status.guild_id)) &&
@@ -4545,10 +4662,11 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
src->m,src->x-15,src->y-15,src->x+15,src->y+15,0,
src,skillid,skilllv,tick, flag|BCT_ALL|1,
skill_castend_nodamage_id);
+ pc_blockskill_start (sd, skillid, 300000);
}
}
break;
- case GD_RESTORE:
+ case GD_RESTORE:
{
struct guild *g = NULL;
// Only usable during WoE
@@ -4560,8 +4678,8 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
if(flag&1) {
if (dstsd && dstsd->status.guild_id == sd->status.guild_id) {
int hp, sp;
- hp = dstsd->status.max_hp*0.9;
- sp = dstsd->status.max_sp*0.9;
+ hp = dstsd->status.max_hp*9/10;
+ sp = dstsd->status.max_sp*9/10;
sp = dstsd->status.sp + sp <= dstsd->status.max_sp ? sp : dstsd->status.max_sp - dstsd->status.sp;
clif_skill_nodamage(src,bl,AL_HEAL,hp,1);
battle_heal(NULL,bl,hp,sp,0);
@@ -4574,6 +4692,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
src->m,src->x-15,src->y-15,src->x+15,src->y+15,0,
src,skillid,skilllv,tick, flag|BCT_ALL|1,
skill_castend_nodamage_id);
+ pc_blockskill_start (sd, skillid, 300000);
}
}
break;
@@ -4581,10 +4700,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
{
int dx[9]={-1, 1, 0, 0,-1, 1,-1, 1, 0};
int dy[9]={ 0, 0, 1,-1, 1,-1,-1, 1, 0};
- int c, j = 0;
+ int j = 0;
struct guild *g = NULL;
// Only usable during WoE
- if (!agit_flag) {
+ if (!agit_flag ||
+ (sd && map[sd->bl.m].flag.nowarpto && // if not allowed to warp to the map
+ guild_mapname2gc(sd->mapname) == NULL)) { // and it's not a castle...
clif_skill_fail(sd,skillid,0,0);
map_freeblock_unlock();
return 0;
@@ -4594,17 +4715,21 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
strcmp(sd->status.name,g->master)==0) {
for(i = 0; i < g->max_member; i++, j++) {
if (j>8) j=0;
- if ((dstsd = g->member[i].sd) != NULL && sd != dstsd &&
- !map[sd->bl.m].flag.nowarpto && !map[dstsd->bl.m].flag.nowarp) {
+ if ((dstsd = g->member[i].sd) != NULL && sd != dstsd) {
+ if (map[dstsd->bl.m].flag.nowarp &&
+ guild_mapname2gc(sd->mapname) == NULL)
+ continue;
clif_skill_nodamage(src,bl,skillid,skilllv,1);
- if ((c=read_gat(sd->bl.m,sd->bl.x+dx[j],sd->bl.y+dy[j]))==1 || c==5)
+ if(map_getcell(sd->bl.m,sd->bl.x+dx[j],sd->bl.y+dy[j],CELL_CHKNOPASS))
dx[j] = dy[j] = 0;
pc_setpos(dstsd, sd->mapname, sd->bl.x+dx[j], sd->bl.y+dy[j], 2);
}
}
+ pc_blockskill_start (sd, skillid, 300000);
}
}
break;
+
default:
printf("Unknown skill used:%d\n",skillid);
map_freeblock_unlock();
@@ -4653,7 +4778,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data )
}
if(sd->skillid == PR_LEXAETERNA) {
- struct status_change *sc_data = battle_get_sc_data(bl);
+ struct status_change *sc_data = status_get_sc_data(bl);
if(sc_data && (sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0))) {
clif_skill_fail(sd,sd->skillid,0,0);
sd->canact_tick = tick;
@@ -4663,7 +4788,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data )
}
}
else if(sd->skillid == RG_BACKSTAP) {
- int dir = map_calc_dir(&sd->bl,bl->x,bl->y),t_dir = battle_get_dir(bl);
+ int dir = map_calc_dir(&sd->bl,bl->x,bl->y),t_dir = status_get_dir(bl);
int dist = distance(sd->bl.x,sd->bl.y,bl->x,bl->y);
if(bl->type != BL_SKILL && (dist == 0 || map_check_dir(dir,t_dir))) {
clif_skill_fail(sd,sd->skillid,0,0);
@@ -4686,7 +4811,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data )
int fail_flag = 1;
if(inf2 & 0x400 && battle_check_target(&sd->bl,bl, BCT_PARTY) > 0)
fail_flag = 0;
- if(inf2 & 0x800 && sd->status.guild_id > 0 && sd->status.guild_id == battle_get_guild_id(bl))
+ if(inf2 & 0x800 && sd->status.guild_id > 0 && sd->status.guild_id == status_get_guild_id(bl))
fail_flag = 0;
if(fail_flag) {
clif_skill_fail(sd,sd->skillid,0,0);
@@ -4699,7 +4824,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data )
range = skill_get_range(sd->skillid,sd->skilllv);
if(range < 0)
- range = battle_get_range(&sd->bl) - (range + 1);
+ range = status_get_range(&sd->bl) - (range + 1);
range += battle_config.pc_skill_add_range;
if((sd->skillid == MO_EXTREMITYFIST && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) ||
(sd->skillid == CH_TIGERFIST && sd->sc_data[SC_COMBO].timer != -1 && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH) ||
@@ -4742,7 +4867,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data )
skill_castend_damage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0);
break;
case 1:/* 支援系 */
- if( (sd->skillid==AL_HEAL || (sd->skillid==ALL_RESURRECTION && bl->type != BL_PC) || sd->skillid==PR_ASPERSIO) && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
+ if( (sd->skillid==AL_HEAL || (sd->skillid==ALL_RESURRECTION && bl->type != BL_PC) || sd->skillid==PR_ASPERSIO) && battle_check_undead(status_get_race(bl),status_get_elem_type(bl)))
skill_castend_damage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0);
else
skill_castend_nodamage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0);
@@ -4761,21 +4886,21 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
struct map_session_data *sd=NULL;
int i,tmpx = 0,tmpy = 0, x1 = 0, y1 = 0;
- if(skilllv <= 0) return 0;
+ //if(skilllv <= 0) return 0;
+ if(skillid > 0 && skilllv <= 0) return 0; // celest
nullpo_retr(0, src);
if(src->type==BL_PC){
nullpo_retr(0, sd=(struct map_session_data *)src);
}
- if( skillid != WZ_METEOR &&
- skillid != WZ_SIGHTRASHER &&
+ if( skillid != WZ_METEOR &&
skillid != AM_CANNIBALIZE &&
skillid != AM_SPHEREMINE)
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
- if (skillnotok(skillid, sd)) // [MouseJstr]
- return 0;
+ if (sd && skillnotok(skillid, sd)) // [MouseJstr]
+ return 0;
switch(skillid)
{
@@ -4792,20 +4917,31 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
break;
case BS_HAMMERFALL: /* ハンマ?フォ?ル */
- skill_area_temp[1]=src->id;
- skill_area_temp[2]=x;
- skill_area_temp[3]=y;
- map_foreachinarea(skill_area_sub,
- src->m,x-2,y-2,x+2,y+2,0,
- src,skillid,skilllv,tick, flag|BCT_ENEMY|2,
- skill_castend_nodamage_id);
+ {
+ int r = 2;
+ if (skilllv > 5) {
+ r = 14;
+ skilllv = 5; // スタン率上がりすぎるため計算はLv5で固定
+ }
+ skill_area_temp[1] = src->id;
+ skill_area_temp[2] = x;
+ skill_area_temp[3] = y;
+ map_foreachinarea (skill_area_sub,
+ src->m, x-r, y-r, x+r, y+r, 0,
+ src, skillid, skilllv, tick, flag|BCT_ENEMY|2,
+ skill_castend_nodamage_id);
+ }
break;
case HT_DETECTING: /* ディテクティング */
{
- const int range=7;
- map_foreachinarea( skill_status_change_timer_sub,
- src->m, src->x-range, src->y-range, src->x+range,src->y+range,0,
+ int range=skilllv*2+1;
+ if(src->x!=x)
+ x+=(src->x-x>0)?-range:range;
+ if(src->y!=y)
+ y+=(src->y-y>0)?-range:range;
+ map_foreachinarea( status_change_timer_sub,
+ src->m, x-range, y-range, x+range,y+range,0,
src,SC_SIGHT,tick);
}
break;
@@ -4816,15 +4952,15 @@ 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: /* フロストノヴァ */
+ //case WZ_FROSTNOVA: /* フロストノヴァ */
case WZ_STORMGUST: /* スト?ムガスト */
case WZ_HEAVENDRIVE: /* ヘヴンズドライブ */
case PR_SANCTUARY: /* サンクチュアリ */
case PR_MAGNUS: /* マグヌスエクソシズム */
case CR_GRANDCROSS: /* グランドクロス */
+ case NPC_DARKGRANDCROSS: /*闇グランドクロス*/
case HT_SKIDTRAP: /* スキッドトラップ */
case HT_LANDMINE: /* ランドマイン */
case HT_ANKLESNARE: /* アンクルスネア */
@@ -4836,12 +4972,11 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
case HT_CLAYMORETRAP: /* クレイモア?トラップ */
case AS_VENOMDUST: /* ベノムダスト */
case AM_DEMONSTRATION: /* デモンストレ?ション */
- case PF_SPIDERWEB: /* スパイダ?ウェッブ */
case PF_FOGWALL: /* フォグウォ?ル */
case HT_TALKIEBOX: /* ト?キ?ボックス */
skill_unitsetting(src,skillid,skilllv,x,y,0);
break;
-
+
case RG_GRAFFITI: /* Graffiti [Valaris] */
skill_clear_unitgroup(src);
skill_unitsetting(src,skillid,skilllv,x,y,0);
@@ -4859,7 +4994,7 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
{
int flag=0;
for(i=0;i<2+(skilllv>>1);i++) {
- int j=0, c;
+ int j=0;
do {
tmpx = x + (rand()%7 - 3);
tmpy = y + (rand()%7 - 3);
@@ -4872,7 +5007,7 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
else if(tmpy >= map[src->m].ys)
tmpy = map[src->m].ys - 1;
j++;
- } while(((c=map_getcell(src->m,tmpx,tmpy))==1 || c==5) && j<100);
+ } while((map_getcell(src->m,tmpx,tmpy,CELL_CHKNOPASS)) && j<100);
if(j >= 100)
continue;
if(flag==0){
@@ -4903,37 +5038,43 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
pc_movepos(sd,x,y);
}else if( src->type==BL_MOB )
mob_warp((struct mob_data *)src,-1,x,y,0);
+ if (sd)
+ pc_blockskill_start (sd, MO_EXTREMITYFIST, 2000);
break;
case AM_CANNIBALIZE: // バイオプラント
- if(sd){
- int mx,my,id=0;
+ if(sd) {
+ int id;
+ int summons[5] = { 1020, 1068, 1118, 1500, 1368 };
struct mob_data *md;
- mx = x;// + (rand()%10 - 5);
- my = y;// + (rand()%10 - 5);
- id=mob_once_spawn(sd,"this",mx,my,"--ja--",1118,1,"");
+ // Correct info, don't change any of this! [celest]
+ id = mob_once_spawn (sd, "this", x, y, "--ja--", summons[skilllv-1] ,1,"");
+
if( (md=(struct mob_data *)map_id2bl(id)) !=NULL ){
- md->master_id=sd->bl.id;
- md->hp=2210+skilllv*200;
- md->state.special_mob_ai=1;
- md->deletetimer=add_timer(gettick()+skill_get_time(skillid,skilllv),mob_timer_delete,id,0);
- }
+ md->master_id = sd->bl.id;
+ // different levels of HP according to skill level
+ md->hp = 1500 + skilllv * 200 + sd->status.base_level * 10;
+ md->state.special_mob_ai = 1;
+ //非移動でアクティブで反撃する[0x0:非移動 0x1:移動 0x4:ACT 0x8:非ACT 0x40:反撃無 0x80:反撃有]
+ md->mode = 0x0 + 0x4 + 0x80;
+ md->deletetimer = add_timer (gettick() + skill_get_time(skillid,skilllv), mob_timer_delete, id, 0);
+ }
+ // To-do: 召還されるモンスターには召還したプレーヤーの名前が付きます
+ // (attach name of player?)
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
}
break;
case AM_SPHEREMINE: // スフィア?マイン
if(sd){
- int mx,my,id=0;
+ int id;
struct mob_data *md;
- mx = x;// + (rand()%10 - 5);
- my = y;// + (rand()%10 - 5);
- id=mob_once_spawn(sd,"this",mx,my,"--ja--",1142,1,"");
+ id = mob_once_spawn(sd, "this", x, y, "--ja--", 1142, 1, "");
if( (md=(struct mob_data *)map_id2bl(id)) !=NULL ){
- md->master_id=sd->bl.id;
- md->hp=1000+skilllv*200;
- md->state.special_mob_ai=2;
- md->deletetimer=add_timer(gettick()+skill_get_time(skillid,skilllv),mob_timer_delete,id,0);
+ md->master_id = sd->bl.id;
+ md->hp = 2000 + skilllv * 400;
+ md->state.special_mob_ai = 2;
+ md->deletetimer = add_timer (gettick() + skill_get_time(skillid,skilllv), mob_timer_delete, id, 0);
}
clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
}
@@ -4943,24 +5084,24 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
case CR_SLIMPITCHER:
{
if (sd) {
- int x = skilllv%11 - 1;
- int i = pc_search_inventory(sd,skill_db[skillid].itemid[x]);
- if(i < 0 || skill_db[skillid].itemid[x] <= 0 || sd->inventory_data[i] == NULL ||
- sd->status.inventory[i].amount < skill_db[skillid].amount[x]) {
+ int i = skilllv%11 - 1;
+ int j = pc_search_inventory(sd,skill_db[skillid].itemid[i]);
+ if(j < 0 || skill_db[skillid].itemid[i] <= 0 || sd->inventory_data[j] == NULL ||
+ sd->status.inventory[j].amount < skill_db[skillid].amount[i]) {
clif_skill_fail(sd,skillid,0,0);
- map_freeblock_unlock();
return 1;
}
sd->state.potionpitcher_flag = 1;
sd->potion_hp = 0;
- run_script(sd->inventory_data[i]->use_script,0,sd->bl.id,0);
- pc_delitem(sd,i,skill_db[skillid].amount[x],0);
+ run_script(sd->inventory_data[j]->use_script,0,sd->bl.id,0);
+ pc_delitem(sd,j,skill_db[skillid].amount[i],0);
sd->state.potionpitcher_flag = 0;
+ clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
if(sd->potion_hp > 0) {
map_foreachinarea(skill_area_sub,
src->m,x-3,y-3,x+3,y+3,0,
- src,skillid,skilllv,tick,flag|BCT_ALL|1,
- skill_castend_nodamage_id);
+ src,skillid,skilllv,tick,flag|BCT_PARTY|1,
+ skill_castend_nodamage_id);
}
}
}
@@ -4982,13 +5123,13 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma
if( sd->bl.prev == NULL || pc_isdead(sd) )
return 0;
- if(skillnotok(skill_num, sd))
- return 0;
+ if(skillnotok(skill_num, sd))
+ return 0;
if( sd->opt1>0 || sd->status.option&2 )
return 0;
//スキルが使えない?態異常中
- if(sd->sc_data){
+ if(sd->sc_count){
if( sd->sc_data[SC_DIVINA].timer!=-1 ||
sd->sc_data[SC_ROKISWEIL].timer!=-1 ||
sd->sc_data[SC_AUTOCOUNTER].timer != -1 ||
@@ -4997,10 +5138,6 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma
sd->sc_data[SC_BERSERK].timer != -1 ||
sd->sc_data[SC_MARIONETTE].timer != -1)
return 0;
-
- if (sd->sc_data[SC_BLOCKSKILL].timer!=-1)
- if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3)
- return 0;
}
if( skill_num != sd->skillid) /* 不正パケットらしい */
@@ -5026,13 +5163,14 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma
case AL_WARP: /* ワ?プポ?タル */
{
- const struct point *p[]={
- &sd->status.save_point,&sd->status.memo_point[0],
- &sd->status.memo_point[1],&sd->status.memo_point[2],
- };
+ const struct point *p[4];
struct skill_unit_group *group;
int i;
int maxcount=0;
+ p[0] = &sd->status.save_point;
+ p[1] = &sd->status.memo_point[0];
+ p[2] = &sd->status.memo_point[1];
+ p[3] = &sd->status.memo_point[2];
if((maxcount = skill_get_maxcount(sd->skillid)) > 0) {
int c;
@@ -5064,7 +5202,7 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma
return 0;
if((group=skill_unitsetting(&sd->bl,sd->skillid,sd->skilllv,sd->skillx,sd->skilly,0))==NULL)
return 0;
- group->valstr=(char *)aCalloc(24,sizeof(char));
+ group->valstr=(char *)aCallocA(24,sizeof(char));
memcpy(group->valstr,map,24);
group->val2=(x<<16)|y;
}
@@ -5081,561 +5219,176 @@ 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
- struct status_change *sc_data = battle_get_sc_data(src); // for firewall and fogwall - celest
+ 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;
+ int active_flag=1;
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 *= 1.5;
- }
- // 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);
+ active_flag=0;
break;
case PR_SANCTUARY: /* サンクチュアリ */
- count=21;
- limit=skill_get_time(skillid,skilllv);
- val1=skilllv+3;
+ 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
- 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;
+ if(skilllv >= 6)
+ range=2;
break;
-
- case WZ_STORMGUST: /* スト?ムガスト */
- limit=4600;
- interval=450;
- range=5;
+ case WZ_METEOR:
+ if (skilllv > 10) //広範囲メテオ
+ range = 10;
break;
-
- case WZ_QUAGMIRE: /* クァグマイア */
- limit=skill_get_time(skillid,skilllv);
- interval=200;
- count=25;
+ case WZ_VERMILION:
+ if (skilllv > 10) //広範囲LOV
+ range = 25;
break;
case HT_SANDMAN: /* サンドマン */
case HT_CLAYMORETRAP: /* クレイモア?トラップ */
- limit=skill_get_time(skillid,skilllv);
- 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);
- range=1;
+ // longer trap times in WOE [celest]
+ if (map[src->m].flag.gvg) limit *= 4;
break;
-
- case HT_TALKIEBOX: /* ト?キ?ボックス */
- limit=skill_get_time(skillid,skilllv);
- range=1;
- target=BCT_ALL;
- 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: /* グランドクロス */
- 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);
- 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=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=5;
- target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1;
- val2 = ((battle_get_agi(src)/10)&0xffff)<<16;
- val2 |= (battle_get_luk(src)/10)&0xffff;
+ 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=5;
- target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
- val2 = battle_get_dex(src)/10;
- break;
-
- case BA_DISSONANCE: /* 不協和音 */
- case DC_UGLYDANCE: /* 自分勝手なダンス */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=5;
- target=BCT_ENEMY;
+ val2 = status_get_dex(src)/10;
break;
-
case DC_DONTFORGETME: /* 私を忘れないで… */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=5;
- target=BCT_ENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
- val2 = ((battle_get_str(src)/20)&0xffff)<<16;
- val2 |= (battle_get_agi(src)/10)&0xffff;
+ val2 = ((status_get_dex(src)/20)&0xffff)<<16;
+ val2 |= (status_get_agi(src)/10)&0xffff;
break;
case BA_POEMBRAGI: /* ブラギの詩 */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=5;
- target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON);
- val2 = ((battle_get_dex(src)/10)&0xffff)<<16;
- val2 |= (battle_get_int(src)/5)&0xffff;
+ 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=5;
- target=BCT_NOENEMY;
if(src->type == BL_PC)
- val1 = ((pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON))&0xffff)<<16;
- else
- val1 = 0;
- val1 |= (battle_get_vit(src))&0xffff;
- val2 = 0;//回復用タイムカウンタ(6秒?に1?加)
+ val1 = pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)&0xffff;
+ val2 |= (status_get_vit(src))&0xffff;
+ val3 = 0;//回復用タイムカウンタ(6秒?に1?加)
break;
case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=5;
- target=BCT_PARTY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
- val2 = battle_get_int(src)/10;
+ val2 = status_get_int(src)/10;
break;
case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=5;
- target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1;
- val2 = battle_get_agi(src)/20;
+ val2 = status_get_agi(src)/20;
break;
case DC_FORTUNEKISS: /* 幸運のキス */
- count=49;
- limit=skill_get_time(skillid,skilllv);
- range=5;
- target=BCT_NOENEMY;
if(src->type == BL_PC)
val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1;
- val2 = battle_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);
- //skill_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);
+ val2 = status_get_luk(src)/10;
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:
- case GD_GLORYWOUNDS:
- case GD_SOULCOLD:
- case GD_HAWKEYES:
- range=2;
- target=BCT_NOENEMY;
- limit=600000;
break;
}
- 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=calloc(80, 1);
+ group->valstr=(char *) aCallocA(80, 1);
if(group->valstr==NULL){
printf("skill_castend_map: out of memory !\n");
exit(1);
}
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];
- }
+ val2=group->val2;
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];
- }
- 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: /* グランドクロス */
- {
- 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);
@@ -5647,7 +5400,7 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,
map_foreachinarea(skill_landprotector,src->m,ux,uy,ux,uy,BL_SKILL,skillid,&alive);
if(skillid==WZ_ICEWALL && alive){
- val2=map_getcell(src->m,ux,uy);
+ val2=map_getcell(src->m,ux,uy,CELL_GETTYPE);
if(val2==5 || val2==1)
alive=0;
else {
@@ -5663,30 +5416,13 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,
unit->limit=limit;
unit->range=range;
- // [celest]
- if (sc_data) {
- // attach the unit's id to the caster
- switch (skillid) {
- case HP_BASILICA:
- if (sc_data[SC_BASILICA].timer!=-1)
- sc_data[SC_BASILICA].val4 = (int)unit;
- break;
- case GD_LEADERSHIP:
- sc_data[SC_LEADERSHIP].val4 = (int)unit;
- break;
- case GD_GLORYWOUNDS:
- sc_data[SC_GLORYWOUNDS].val4 = (int)unit;
- break;
- case GD_SOULCOLD:
- sc_data[SC_SOULCOLD].val4 = (int)unit;
- break;
- case GD_HAWKEYES:
- sc_data[SC_HAWKEYES].val4 = (int)unit;
- break;
- }
- }
+ if (range==0 && active_flag)
+ 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;
}
@@ -5698,126 +5434,245 @@ 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);
-
- 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->group_id));
- 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;
- ts->group_id=sg->group_id;
+ 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=battle_get_race(bl);
- int damage_flag = (battle_check_undead(race,battle_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( battle_get_hp(bl)>=battle_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;
+ }
+ status_change_start(bl,type,sg->skill_lv,(int)src,0,0,
+ skill_get_time2(sg->skill_id,sg->skill_lv),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
- skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,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: /* サ?ビスフォ?ユ? */
+ 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;
- case 0x84: /* マグヌスエクソシズム */
- {
- int race=battle_get_race(bl);
- int damage_flag = (battle_check_undead(race,battle_get_elem_type(bl)) || race == 6)? 1:0;
+ case 0xb4: // Basilica
+ if (battle_check_target(&src->bl,bl,BCT_NOENEMY)>0) {
+ if (sc_data && sc_data[type].timer!=-1) {
+ struct skill_unit_group *sg2 = (struct skill_unit_group *)sc_data[type].val4;
+ if (sg2 && (sg2 == src->group || DIFF_TICK(sg->tick,sg2->tick)<=0))
+ break;
+ } else
+ status_change_start(bl,type,sg->skill_lv,(int)src,0,0,
+ skill_get_time2(sg->skill_id,sg->skill_lv),0);
+ } else if (!status_get_mode(bl)&0x20)
+ skill_blown(&src->bl,bl,1);
+ 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) {
+ struct skill_unit_group *sg2 = (struct skill_unit_group *)sc_data[type].val4;
+ if (sg2 && (sg2 == src->group || DIFF_TICK(sg->tick,sg2->tick)<=0))
+ break;
}
+ status_change_start (bl, type, sg->skill_lv, sg->val1, sg->val2, (int)sg,
+ skill_get_time2(sg->skill_id, sg->skill_lv), 0);
+ if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0)
+ skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv, BF_MISC, tick);
+ break;
+
+ case 0xb2: /* あなたを_?いたいです */
+ case 0xb3: /* ゴスペル */
+ //とりあえず何もしない
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;*/
+ }
- case 0x85: /* ニュ?マ */
+ 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: /* サンクチュアリ */
{
- struct skill_unit *unit2;
- struct status_change *sc_data=battle_get_sc_data(bl);
- int type=SC_PNEUMA;
- if(sc_data && sc_data[type].timer==-1)
- skill_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(DIFF_TICK(sg->tick,unit2->group->tick)>0 )
- skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
- ts->tick-=sg->interval;
- }
+ int race = status_get_race(bl);
+
+ 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 [hekate]
+ 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;
}
- break;
- case 0x7e: /* セイフティウォ?ル */
+
+ case 0x84: /* マグヌスエクソシズム */
{
- struct skill_unit *unit2;
- struct status_change *sc_data=battle_get_sc_data(bl);
- int type=SC_SAFETYWALL;
- if(sc_data && sc_data[type].timer==-1)
- skill_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(sg->val1 < unit2->group->val1 )
- skill_status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0);
- ts->tick-=sg->interval;
- }
+ 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;
}
- break;
- case 0x86: /* ロ?ドオブヴァ?ミリオン(&スト?ムガスト &グランドクロス) */
+ case 0x7f: /* ファイヤーウォール */
skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
- break;
-
- 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 (--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: /* スキッドトラップ */
@@ -5830,7 +5685,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);
@@ -5859,20 +5714,22 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int
break;
case 0x91: /* アンクルスネア */
- {
- struct status_change *sc_data=battle_get_sc_data(bl);
- if(sg->val2==0 && sc_data && sc_data[SC_ANKLE].timer==-1){
+ 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) - (double)battle_get_agi(bl)*0.1;
- if(battle_get_mode(bl)&0x20)
- sec = sec/5;
- battle_stopwalking(bl,1);
- skill_status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0);
-
+ 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)
@@ -5880,129 +5737,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;
- }
+ sg->interval = -1;
+ src->range = 0;
}
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);
- }
- break;
-
- case 0x8e: /* クァグマイア */
- {
- int type=SkillStatusChangeTable[sg->skill_id];
- if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
- break;
- if( battle_get_sc_data(bl)[type].timer==-1 )
- skill_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=battle_get_sc_data(bl);
- int type=SkillStatusChangeTable[sg->skill_id];
- if( sc_data && sc_data[type].timer==-1 )
- skill_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=battle_get_sc_data(bl);
- int type=SkillStatusChangeTable[sg->skill_id];
- if(sc_data && sc_data[type].timer==-1)
- skill_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( DIFF_TICK(sg->tick,unit2->group->tick)>0 )
- skill_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=battle_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)
- skill_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->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 )
- skill_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=battle_get_sc_data(bl);
- int type=SkillStatusChangeTable[sg->skill_id];
- if(sg->src_id == bl->id)
- break;
- if( sc_data && sc_data[type].timer==-1)
- skill_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( DIFF_TICK(sg->tick,unit2->group->tick)>0 )
- skill_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 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);
@@ -6011,68 +5765,40 @@ 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;
+
+ // Basilica
+ 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 && 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 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->sc_data[SC_LEADERSHIP].timer == -1 && !sd->sc_data[SC_LEADERSHIP].val4)
- skill_status_change_start(bl,SC_LEADERSHIP,1,0,0,0,0,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->sc_data[SC_GLORYWOUNDS].timer == -1 && !sd->sc_data[SC_GLORYWOUNDS].val4)
- skill_status_change_start(bl,SC_GLORYWOUNDS,1,0,0,0,0,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->sc_data[SC_SOULCOLD].timer == -1 && !sd->sc_data[SC_SOULCOLD].val4)
- skill_status_change_start(bl,SC_SOULCOLD,1,0,0,0,0,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->sc_data[SC_HAWKEYES].timer == -1 && !sd->sc_data[SC_HAWKEYES].val4)
- skill_status_change_start(bl,SC_HAWKEYES,1,0,0,0,0,0 );
+ sg->interval = -1;
+ src->range = 0;
}
break;
@@ -6081,6 +5807,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)
@@ -6104,85 +5831,55 @@ 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=battle_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){
- skill_status_change_end(bl,type,-1);
- }
- } break;
-
- case 0x91: /* アンクルスネア */
- {
- struct block_list *target=map_id2bl(sg->val2);
- if( target && target==bl ){
- skill_status_change_end(bl,SC_ANKLE,-1);
- sg->limit=DIFF_TICK(tick,sg->tick)+1000;
- }
- }
- break;
- case 0xb5:
- case 0xb8:
- {
- struct block_list *target=map_id2bl(sg->val2);
- if( target==bl )
- skill_status_change_end(bl,SC_SPIDERWEB,-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 0xb6:
- {
- struct block_list *target=map_id2bl(sg->val2);
- struct status_change *sc_data=battle_get_sc_data(bl);
- if( target==bl ) {
- skill_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, skill_status_change_timer, bl->id, 0);
- }
+ 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 0x9a: /* ボルケ?ノ */
- case 0x9b: /* デリュ?ジ */
- case 0x9c: /* バイオレントゲイル */
- {
- struct status_change *sc_data=battle_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 ){
- skill_status_change_end(bl,type,-1);
- }
- }
- break;
-
+ }
case 0x9e: /* 子守唄 */
case 0x9f: /* ニヨルドの宴 */
case 0xa0: /* 永遠の混沌 */
- case 0xa1: /* ?太鼓の響き */
- case 0xa2: /* ニ?ベルングの指輪 */
+ case 0xa1: /* 戦太鼓の響き */
+ case 0xa2: /* ニーベルングの指輪 */
case 0xa3: /* ロキの叫び */
case 0xa4: /* 深淵の中に */
- case 0xa5: /* 不死身のジ?クフリ?ド */
+ case 0xa5: /* 不死身のジークフリード */
+ case 0xad: /* 私を忘れないで… */
+ if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)src) {
+ status_change_end(bl,type,-1);
+ }
+ break;
+
case 0xa6: /* 不協和音 */
case 0xa7: /* 口笛 */
case 0xa8: /* 夕陽のアサシンクロス */
@@ -6190,123 +5887,94 @@ int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int t
case 0xaa: /* イドゥンの林檎 */
case 0xab: /* 自分勝手なダンス */
case 0xac: /* ハミング */
- case 0xad: /* 私を忘れないで… */
case 0xae: /* 幸運のキス */
case 0xaf: /* サ?ビスフォ?ユ? */
- case 0xb4:
- {
- struct status_change *sc_data=battle_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 ){
- skill_status_change_end(bl,type,-1);
- }
- }
- break;
- case 0xb7: /* スパイダ?ウェッブ */
- {
- struct block_list *target=map_id2bl(sg->val2);
- if( target && target==bl )
- skill_status_change_end(bl,SC_SPIDERWEB,-1);
- sg->limit=DIFF_TICK(tick,sg->tick)+1000;
+ if (sg->src_id==bl->id) {
+ status_change_end(bl,type,-1);
+ break;
}
- break;
- // New guild skills [Celest]
- case 0xc1: // GD_LEADERSHIP
- {
- struct status_change *sc_data=battle_get_sc_data(bl);
- if (sc_data && sc_data[SC_LEADERSHIP].timer != -1)
- skill_status_change_end(bl,SC_LEADERSHIP,-1);
+ if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)src) {
+ sc_data[type].timer = add_timer(20000+tick, status_change_timer, bl->id, type);
}
- break;
- case 0xc2: // GD_GLORYWOUNDS
- {
- struct status_change *sc_data=battle_get_sc_data(bl);
- if (sc_data && sc_data[SC_GLORYWOUNDS].timer != -1)
- skill_status_change_end(bl,SC_GLORYWOUNDS,-1);
+ break;
+
+ case 0xb4: // Basilica
+ if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)sg) {
+ status_change_end(bl,type,-1);
}
break;
- case 0xc3: // GD_SOULCOLD
+
+ case 0xb6:
{
- struct status_change *sc_data=battle_get_sc_data(bl);
- if (sc_data && sc_data[SC_SOULCOLD].timer != -1)
- skill_status_change_end(bl,SC_SOULCOLD,-1);
+ if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)sg) {
+ 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;
}
- break;
- case 0xc4: // GD_HAWKEYES
+
+ case 0xb7: /* スパイダ?ウェッブ */
{
- struct status_change *sc_data=battle_get_sc_data(bl);
- if (sc_data && sc_data[SC_HAWKEYES].timer != -1)
- skill_status_change_end(bl,SC_HAWKEYES,-1);
+ 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;
+ break;
}
- 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->group_id);
+
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;
+ static int called = 0;
- 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 && called == 0) {
+ called = 1;
+ skill_unit_onplace(unit,bl,tick);
+ called = 0;
+ }
}
- skill_unitgrouptickset_delete(bl,sg->group_id);
+
return 0;
}
+
/*==========================================
* スキルユニットの限界イベント
*------------------------------------------
@@ -6314,7 +5982,6 @@ int skill_unit_ondelete(struct skill_unit *src,struct block_list *bl,unsigned in
int skill_unit_onlimit(struct skill_unit *src,unsigned int tick)
{
struct skill_unit_group *sg;
-
nullpo_retr(0, src);
nullpo_retr(0, sg=src->group);
@@ -6326,7 +5993,7 @@ int skill_unit_onlimit(struct skill_unit *src,unsigned int tick)
src->bl.x,src->bl.y,1);
if(group == NULL)
return 0;
- group->valstr=calloc(24, 1);
+ group->valstr=(char *) aCallocA(24, 1);
if(group->valstr==NULL){
printf("skill_unit_onlimit: out of memory !\n");
exit(1);
@@ -6344,7 +6011,7 @@ int skill_unit_onlimit(struct skill_unit *src,unsigned int tick)
{
struct map_session_data *sd = NULL;
struct map_session_data *p_sd = NULL;
- if((sd = (struct map_session_data *)(map_id2bl(sg->src_id))) == NULL)
+ if((sd = map_id2sd(sg->src_id)) == NULL)
return 0;
if((p_sd = pc_get_partner(sd)) == NULL)
return 0;
@@ -6352,38 +6019,6 @@ int skill_unit_onlimit(struct skill_unit *src,unsigned int tick)
pc_setpos(p_sd,map[src->bl.m].name,src->bl.x,src->bl.y,3);
}
break;
- case 0xc1: // GD_LEADERSHIP
- {
- struct map_session_data *sd;
- if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
- sd->sc_data[SC_LEADERSHIP].val4 = 0;
- }
- }
- break;
- case 0xc2: // GD_GLORYWOUNDS
- {
- struct map_session_data *sd;
- if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
- sd->sc_data[SC_GLORYWOUNDS].val4 = 0;
- }
- }
- break;
- case 0xc3: // GD_SOULCOLD
- {
- struct map_session_data *sd;
- if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
- sd->sc_data[SC_SOULCOLD].val4 = 0;
- }
- }
- break;
- case 0xc4: // GD_HAWKEYES
- {
- struct map_session_data *sd;
- if ((sd = (struct map_session_data *)(map_id2bl(sg->src_id)))!= NULL) {
- sd->sc_data[SC_HAWKEYES].val4 = 0;
- }
- }
- break;
}
return 0;
}
@@ -6444,10 +6079,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:
@@ -6460,28 +6092,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:
@@ -6492,25 +6119,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 = 1;
+ 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,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) {
@@ -6532,7 +6156,7 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data )
if(sd->skilllv <= 0) return 0;
range = skill_get_range(sd->skillid,sd->skilllv);
if(range < 0)
- range = battle_get_range(&sd->bl) - (range + 1);
+ range = status_get_range(&sd->bl) - (range + 1);
range += battle_config.pc_skill_add_range;
if(battle_config.skill_out_range_consume) { // changed to allow casting when target walks out of range [Valaris]
if(range < distance(sd->bl.x,sd->bl.y,sd->skillx,sd->skilly)) {
@@ -6589,14 +6213,14 @@ static int skill_check_condition_char_sub(struct block_list *bl,va_list ap)
nullpo_retr(0, c=va_arg(ap,int *));
nullpo_retr(0, ssd=(struct map_session_data*)src);
- s_class = pc_calc_base_job(sd->status.class);
+ s_class = pc_calc_base_job(sd->status.class_);
//チェックしない設定ならcにありえない大きな?字を返して終了
if(!battle_config.player_skill_partner_check){ //本?はforeachの前にやりたいけど設定適用箇所をまとめるためにここへ
(*c)=99;
return 0;
}
- ss_class = pc_calc_base_job(ssd->status.class);
+ ss_class = pc_calc_base_job(ssd->status.class_);
switch(ssd->skillid){
case PR_BENEDICTIO: /* 聖?降福 */
@@ -6650,24 +6274,25 @@ static int skill_check_condition_use_sub(struct block_list *bl,va_list ap)
nullpo_retr(0, c=va_arg(ap,int *));
nullpo_retr(0, ssd=(struct map_session_data*)src);
- s_class = pc_calc_base_job(sd->status.class);
-
+ s_class = pc_calc_base_job(sd->status.class_);
+
//チェックしない設定ならcにありえない大きな?字を返して終了
if(!battle_config.player_skill_partner_check){ //本?はforeachの前にやりたいけど設定適用箇所をまとめるためにここへ
(*c)=99;
return 0;
}
- ss_class = pc_calc_base_job(ssd->status.class);
+ ss_class = pc_calc_base_job(ssd->status.class_);
skillid=ssd->skillid;
skilllv=ssd->skilllv;
- if(skilllv <= 0) return 0;
+ //if(skilllv <= 0) return 0;
+ if(skillid > 0 && skilllv <= 0) return 0; // celest
switch(skillid){
case PR_BENEDICTIO: /* 聖?降福 */
if(sd != ssd && (s_class.job == 4 || s_class.job == 8 || s_class.job == 15) &&
(sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1) && sd->status.sp >= 10){
sd->status.sp -= 10;
- pc_calcstatus(sd,0);
+ status_calc_pc(sd,0);
(*c)++;
}
break;
@@ -6692,7 +6317,7 @@ static int skill_check_condition_use_sub(struct block_list *bl,va_list ap)
){
ssd->sc_data[SC_DANCING].val4=bl->id;
clif_skill_nodamage(bl,src,skillid,skilllv,1);
- skill_status_change_start(bl,SC_DANCING,skillid,ssd->sc_data[SC_DANCING].val2,0,src->id,skill_get_time(skillid,skilllv)+1000,0);
+ status_change_start(bl,SC_DANCING,skillid,ssd->sc_data[SC_DANCING].val2,0,src->id,skill_get_time(skillid,skilllv)+1000,0);
sd->skillid_dance=sd->skillid=skillid;
sd->skilllv_dance=sd->skilllv=skilllv;
(*c)++;
@@ -6718,7 +6343,7 @@ static int skill_check_condition_mob_master_sub(struct block_list *bl,va_list ap
nullpo_retr(0, mob_class=va_arg(ap,int));
nullpo_retr(0, c=va_arg(ap,int *));
- if(md->class==mob_class && md->master_id==src_id)
+ if(md->class_==mob_class && md->master_id==src_id)
(*c)++;
return 0;
}
@@ -6731,6 +6356,7 @@ int skill_check_condition(struct map_session_data *sd,int type)
{
int i,hp,sp,hp_rate,sp_rate,zeny,weapon,state,spiritball,skill,lv,mhp;
int index[10],itemid[10],amount[10];
+ int arrow_flag = 0;
nullpo_retr(0, sd);
@@ -6769,7 +6395,7 @@ int skill_check_condition(struct map_session_data *sd,int type)
clif_skill_fail(sd,sd->skillid,0,0);
return 0;
}
- if(sd->sc_data){
+ if(sd->sc_count){
if( sd->sc_data[SC_DIVINA].timer!=-1 ||
sd->sc_data[SC_ROKISWEIL].timer!=-1 ||
(sd->sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) ||
@@ -6778,11 +6404,13 @@ int skill_check_condition(struct map_session_data *sd,int type)
(sd->sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE)){
clif_skill_fail(sd,sd->skillid,0,0);
return 0; /* ?態異常や沈?など */
- }
+ }
}
skill = sd->skillid;
lv = sd->skilllv;
if(lv <= 0) return 0;
+ // for the guild skills [celest]
+ if (skill >= 10000 && skill < 10015) skill-= 9500;
hp=skill_get_hp(skill, lv); /* 消費HP */
sp=skill_get_sp(skill, lv); /* 消費SP */
if((sd->skillid_old == BD_ENCORE) && skill==sd->skillid_dance)
@@ -6854,6 +6482,10 @@ int skill_check_condition(struct map_session_data *sd,int type)
}
else sd->spiritball_old = lv;
break;
+ case MO_BODYRELOCATION:
+ if (sd->sc_count && sd->sc_data[SC_EXPLOSIONSPIRITS].timer!=-1)
+ spiritball = 0;
+ break;
case MO_CHAINCOMBO: //連打掌
if(sd->sc_data[SC_BLADESTOP].timer==-1){
if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_TRIPLEATTACK)
@@ -6865,7 +6497,7 @@ int skill_check_condition(struct map_session_data *sd,int type)
return 0;
break;
case CH_TIGERFIST: //伏虎拳
- if(sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH)
+ if((sd->sc_data[SC_COMBO].timer == -1 || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH) && !sd->state.skill_flag)
return 0;
break;
case CH_CHAINCRUSH: //連柱崩?
@@ -6916,8 +6548,9 @@ int skill_check_condition(struct map_session_data *sd,int type)
case AM_SPHEREMINE: /* スフィア?マイン */
if(type&1){
int c=0;
- int maxcount=skill_get_maxcount(skill);
- int mob_class=(skill==AM_CANNIBALIZE)?1118:1142;
+ int summons[5] = { 1020, 1068, 1118, 1500, 1368 };
+ int maxcount = (skill==AM_CANNIBALIZE)? 6-lv : skill_get_maxcount(skill);
+ int mob_class = (skill==AM_CANNIBALIZE)? summons[lv-1] :1142;
if(battle_config.pc_land_skill_limit && maxcount>0) {
map_foreachinarea(skill_check_condition_mob_master_sub ,sd->bl.m, 0, 0, map[sd->bl.m].xs, map[sd->bl.m].ys, BL_MOB, sd->bl.id, mob_class,&c );
if(c >= maxcount){
@@ -6929,7 +6562,7 @@ int skill_check_condition(struct map_session_data *sd,int type)
break;
case MG_FIREWALL: /* ファイア?ウォ?ル */
case WZ_QUAGMIRE:
- case WZ_FIREPILLAR: // celest
+ case WZ_FIREPILLAR: // celest
case PF_FOGWALL:
/* ?制限 */
if(battle_config.pc_land_skill_limit) {
@@ -6947,6 +6580,29 @@ int skill_check_condition(struct map_session_data *sd,int type)
}
}
break;
+ // skills require arrows as of 12/07 [celest]
+ case AC_DOUBLE:
+ case AC_SHOWER:
+ case AC_CHARGEARROW:
+ case BA_MUSICALSTRIKE:
+ case DC_THROWARROW:
+ case SN_SHARPSHOOTING:
+ case CG_ARROWVULCAN:
+ if(sd->equip_index[10] < 0) {
+ clif_arrow_fail(sd,0);
+ return 0;
+ }
+ arrow_flag = 1;
+ break;
+ case RG_BACKSTAP:
+ if(sd->status.weapon == 11) {
+ if (sd->equip_index[10] < 0) {
+ clif_arrow_fail(sd,0);
+ return 0;
+ }
+ arrow_flag = 1;
+ }
+ break;
}
if(!(type&2)){
@@ -7022,6 +6678,9 @@ int skill_check_condition(struct map_session_data *sd,int type)
}
break;
case ST_EXPLOSIONSPIRITS:
+ if (skill == MO_EXTREMITYFIST && ((sd->sc_data[SC_COMBO].timer != -1 && (sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH || sd->sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) || sd->sc_data[SC_BLADESTOP].timer!=-1)) {
+ break;
+ }
if(sd->sc_data[SC_EXPLOSIONSPIRITS].timer == -1) {
clif_skill_fail(sd,skill,0,0);
return 0;
@@ -7043,7 +6702,7 @@ int skill_check_condition(struct map_session_data *sd,int type)
}
break;
case ST_WATER:
- if(map_getcell(sd->bl.m,sd->bl.x,sd->bl.y) != 3 && (sd->sc_data[SC_DELUGE].timer==-1)){ //水場判定
+ if((!map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKWATER))&& (sd->sc_data[SC_DELUGE].timer==-1)){ //水場判定
clif_skill_fail(sd,skill,0,0);
return 0;
}
@@ -7060,8 +6719,9 @@ int skill_check_condition(struct map_session_data *sd,int type)
if(((itemid[i] >= 715 && itemid[i] <= 717) || itemid[i] == 1065) && sd->sc_data[SC_INTOABYSS].timer != -1)
continue;
if(skill == WZ_FIREPILLAR && lv<=5)
- continue; // no gemstones for 1-5 [Celest]
- if(skill == AM_POTIONPITCHER && i != x)
+ continue; // no gemstones for 1-5 [Celest]
+ if((skill == AM_POTIONPITCHER ||
+ skill == CR_SLIMPITCHER) && i != x)
continue;
index[i] = pc_search_inventory(sd,itemid[i]);
@@ -7077,13 +6737,17 @@ int skill_check_condition(struct map_session_data *sd,int type)
if(!(type&1))
return 1;
- if(skill != AM_POTIONPITCHER) {
+ if(skill != AM_POTIONPITCHER &&
+ skill != CR_SLIMPITCHER &&
+ skill != MG_STONECURSE) {
if(skill == AL_WARP && !(type&2))
return 1;
for(i=0;i<10;i++) {
if(index[i] >= 0)
pc_delitem(sd,index[i],amount[i],0); // アイテム消費
}
+ if (arrow_flag && battle_config.arrow_decrement)
+ pc_delitem(sd,sd->equip_index[10],1,0);
}
if(type&2)
@@ -7112,56 +6776,50 @@ int skill_check_condition(struct map_session_data *sd,int type)
*/
int skill_castfix( struct block_list *bl, int time )
{
- struct map_session_data *sd;
+ struct map_session_data *sd = NULL;
struct mob_data *md; // [Valaris]
struct status_change *sc_data;
- int dex;
int castrate=100;
- int skill,lv,castnodex;
+ int skill,lv;
nullpo_retr(0, bl);
if(bl->type==BL_MOB){ // Crash fix [Valaris]
- md=(struct mob_data*)bl;
+ nullpo_retr(0, md=(struct mob_data*)bl);
skill = md->skillid;
lv = md->skilllv;
- }
-
- else {
- sd=(struct map_session_data*)bl;
+ } else {
+ nullpo_retr(0, sd=(struct map_session_data*)bl);
skill = sd->skillid;
lv = sd->skilllv;
}
if(lv <= 0) return 0;
- sc_data = battle_get_sc_data(bl);
- dex=battle_get_dex(bl);
+ sc_data = status_get_sc_data(bl);
if (skill > MAX_SKILL_DB || skill < 0)
return 0;
- castnodex=skill_get_castnodex(skill, lv);
+ /* サフラギウム */
+ if(sc_data && sc_data[SC_SUFFRAGIUM].timer!=-1 )
+ time=time*(100-sc_data[SC_SUFFRAGIUM].val1*15)/100;
+ status_change_end( bl, SC_SUFFRAGIUM, -1);
if(time==0)
return 0;
- if(castnodex > 0 && bl->type==BL_PC)
- castrate=((struct map_session_data *)bl)->castrate;
- else if (castnodex <= 0 && bl->type==BL_PC) {
- castrate=((struct map_session_data *)bl)->castrate;
- time=time*castrate*(battle_config.castrate_dex_scale - dex)/(battle_config.castrate_dex_scale * 100);
- time=time*battle_config.cast_rate/100;
+ if (sd) {
+ if(!skill_get_castnodex(skill, lv) > 0) {
+ castrate=((struct map_session_data *)bl)->castrate;
+ time=time*castrate*(battle_config.castrate_dex_scale - status_get_dex(bl))/(battle_config.castrate_dex_scale * 100);
+ time=time*battle_config.cast_rate/100;
+ }
}
- /* サフラギウム */
- if(sc_data && sc_data[SC_SUFFRAGIUM].timer!=-1 ){
- time=time*(100-sc_data[SC_SUFFRAGIUM].val1*15)/100;
- skill_status_change_end( bl, SC_SUFFRAGIUM, -1);
- }
/* ブラギの詩 */
- if(sc_data && sc_data[SC_POEMBRAGI].timer!=-1 )
+ if(sc_data && sc_data[SC_POEMBRAGI].timer!=-1)
time=time*(100-(sc_data[SC_POEMBRAGI].val1*3+sc_data[SC_POEMBRAGI].val2
- +(sc_data[SC_POEMBRAGI].val3>>16)))/100;
+ +(sc_data[SC_POEMBRAGI].val3>>16)))/100;
return (time>0)?time:0;
}
@@ -7172,23 +6830,48 @@ int skill_castfix( struct block_list *bl, int time )
int skill_delayfix( struct block_list *bl, int time )
{
struct status_change *sc_data;
+ struct map_session_data *sd = NULL;
+ int skill = 0,lv = 0;
+ int delayrate = 100;
nullpo_retr(0, bl);
- sc_data = battle_get_sc_data(bl);
- if(time<=0)
- return 0;
+ if(bl->type == BL_PC){
+ nullpo_retr(0, sd = (struct map_session_data*)bl);
+ skill = sd->skillid;
+ lv = sd->skilllv;
+ }
- if(bl->type == BL_PC) {
- if( battle_config.delay_dependon_dex ) /* dexの影響を計算する */
- time=time*(battle_config.castrate_dex_scale - battle_get_dex(bl))/battle_config.castrate_dex_scale;
- time=time*battle_config.delay_rate/100;
+ if(lv <= 0) return 0;
+
+ sc_data = status_get_sc_data(bl);
+
+ if(sd) {
+ delayrate = sd->delayrate;
+
+ // instant cast attack skills depend on aspd as delay [celest]
+ if (time == 0) {
+ if (skill_db[skill].skill_type == BF_WEAPON)
+ time = status_get_adelay (bl)/2;
+ else
+ time = 300; // default delay, according to official servers
+ } else if (time < 0)
+ time = abs(time) + status_get_adelay (bl)/2; // if set to <0, the aspd delay will be added
+
+ if(battle_config.delay_dependon_dex && /* dexの影響を計算する */
+ !skill_get_delaynodex(skill, lv)) // if skill casttime is allowed to be reduced by dex
+ time = time * (battle_config.castrate_dex_scale - status_get_dex(bl)) / (battle_config.castrate_dex_scale);
+
+ time = time * delayrate * battle_config.delay_rate / 10000;
+
+ if (time < battle_config.min_skill_delay_limit) // check minimum skill delay
+ time = battle_config.min_skill_delay_limit;
}
/* ブラギの詩 */
- if(sc_data && sc_data[SC_POEMBRAGI].timer!=-1 )
- time=time*(100-(sc_data[SC_POEMBRAGI].val1*3+sc_data[SC_POEMBRAGI].val2
- +(sc_data[SC_POEMBRAGI].val3&0xffff)))/100;
+ if(sc_data && sc_data[SC_POEMBRAGI].timer != -1 )
+ time = time * (100 - (sc_data[SC_POEMBRAGI].val1 * 3 + sc_data[SC_POEMBRAGI].val2
+ + (sc_data[SC_POEMBRAGI].val3 & 0xffff))) / 100;
return (time>0)?time:0;
}
@@ -7197,128 +6880,97 @@ int skill_delayfix( struct block_list *bl, int time )
* スキル使用(ID指定)
*------------------------------------------
*/
-int skill_use_id( struct map_session_data *sd, int target_id,
- int skill_num, int skill_lv)
+int skill_use_id (struct map_session_data *sd, int target_id, int skill_num, int skill_lv)
{
- unsigned int tick;
- int casttime=0,delay=0,skill,range;
- struct map_session_data* target_sd=NULL;
- int forcecast=0;
- struct block_list *bl;
+ int casttime = 0, delay = 0, skill, range;
+ struct map_session_data* tsd = NULL;
+ struct block_list *bl = NULL;
struct status_change *sc_data;
- tick=gettick();
+ int forcecast = 0;
+ unsigned int tick = gettick();
nullpo_retr(0, sd);
- if( (bl=map_id2bl(target_id)) == NULL ){
-/* if(battle_config.error_log)
- printf("skill target not found %d\n",target_id); */
+ if ((bl = map_id2bl(target_id)) == NULL)
return 0;
+ if (bl->type == BL_PC) {
+ nullpo_retr(0, tsd = (struct map_session_data*)bl);
}
if(sd->bl.m != bl->m || pc_isdead(sd))
return 0;
-
if(skillnotok(skill_num, sd)) // [MouseJstr]
return 0;
-
- sc_data=sd->sc_data;
+ if (tsd && skill_num == ALL_RESURRECTION && !pc_isdead(tsd))
+ return 0;
+
+ sc_data = sd->sc_data;
/* 沈?や異常(ただし、グリムなどの判定をする) */
- if( sd->opt1>0 )
+ if (sd->opt1 > 0)
return 0;
- if(sd->sc_data){
- if(sc_data[SC_CHASEWALK].timer != -1) return 0;
- if(sc_data[SC_VOLCANO].timer != -1){
- if(skill_num==WZ_ICEWALL) return 0;
- }
- if(sc_data[SC_ROKISWEIL].timer!=-1){
- if(skill_num==BD_ADAPTATION) return 0;
- }
- if( sd->sc_data[SC_DIVINA].timer!=-1 ||
- sd->sc_data[SC_ROKISWEIL].timer!=-1 ||
- (sd->sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) ||
- sd->sc_data[SC_STEELBODY].timer != -1 ||
- sd->sc_data[SC_BERSERK].timer != -1 ||
- (sd->sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE)){
+ if (sc_data) {
+ // allow to use only Chasewalk [celest]
+ if (sc_data[SC_CHASEWALK].timer != -1 && skill_num != ST_CHASEWALK)
+ return 0;
+ if (sc_data[SC_VOLCANO].timer != -1 && skill_num == WZ_ICEWALL)
+ return 0;
+ if (sc_data[SC_ROKISWEIL].timer != -1 && skill_num == BD_ADAPTATION)
+ return 0;
+ if (sc_data[SC_DIVINA].timer != -1 ||
+ sc_data[SC_ROKISWEIL].timer != -1 ||
+ (sc_data[SC_AUTOCOUNTER].timer != -1 && sd->skillid != KN_AUTOCOUNTER) ||
+ sc_data[SC_STEELBODY].timer != -1 ||
+ sc_data[SC_BERSERK].timer != -1 ||
+ (sc_data[SC_MARIONETTE].timer != -1 && sd->skillid != CG_MARIONETTE))
return 0; /* ?態異常や沈?など */
+ if (sc_data[SC_BLADESTOP].timer != -1) {
+ if (sc_data[SC_BLADESTOP].val2 == 1) return 0;//白羽された側なのでダメ
+ switch (sc_data[SC_BLADESTOP].val1) {
+ case 1: return 0;
+ case 2: if (skill_num != MO_FINGEROFFENSIVE) return 0; else break;
+ case 3: if (skill_num != MO_FINGEROFFENSIVE && skill_num != MO_INVESTIGATE) return 0; else break;
+ case 4: if (skill_num != MO_FINGEROFFENSIVE && skill_num != MO_INVESTIGATE && skill_num != MO_CHAINCOMBO) return 0; else break;
+ case 5: if (skill_num != MO_FINGEROFFENSIVE && skill_num != MO_INVESTIGATE && skill_num != MO_CHAINCOMBO && skill_num!=MO_EXTREMITYFIST) return 0; else break;
+ }
}
-
- if(sc_data[SC_BLADESTOP].timer != -1){
- int lv = sc_data[SC_BLADESTOP].val1;
- if(sc_data[SC_BLADESTOP].val2==1) return 0;//白羽された側なのでダメ
- if(lv==1) return 0;
- if(lv==2 && skill_num!=MO_FINGEROFFENSIVE) return 0;
- if(lv==3 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE) return 0;
- if(lv==4 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE && skill_num!=MO_CHAINCOMBO) return 0;
- if(lv==5 && skill_num!=MO_FINGEROFFENSIVE && skill_num!=MO_INVESTIGATE && skill_num!=MO_CHAINCOMBO && skill_num!=MO_EXTREMITYFIST) return 0;
- }
-
- if (sd->sc_data[SC_BLOCKSKILL].timer!=-1)
- if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3)
- return 0;
-
if (sc_data[SC_BASILICA].timer != -1) { // Disallow all other skills in Basilica [celest]
- struct skill_unit *su;
- if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) {
- struct skill_unit_group *sg;
- // if caster is the owner of basilica
- if ((sg = su->group) && sg->src_id == sd->bl.id) {
- // skill_status_change_end(&sd->bl,SC_BASILICA,-1);
- // skill_delunitgroup (sg);
- if (skill_num != HP_BASILICA) return 0;
- } // otherwise...
- else
- return 0;
- }
- }
+ struct skill_unit_group *sg = (struct skill_unit_group *)sc_data[SC_BASILICA].val4;
+ // if caster is the owner of basilica
+ if (sg && sg->src_id == sd->bl.id &&
+ skill_num == HP_BASILICA) ; // do nothing
+ // otherwise...
+ else return 0;
+ }
+ /* 演奏/ダンス中 */
+ if (sc_data[SC_DANCING].timer != -1) {
+ if (sc_data[SC_DANCING].val4 && skill_num != BD_ADAPTATION) //合奏中はアドリブ以外不可
+ return 0;
+ if (skill_num != BD_ADAPTATION && skill_num != BA_MUSICALSTRIKE && skill_num != DC_THROWARROW)
+ return 0;
+ }
}
- if(sd->status.option&4 && skill_num==TF_HIDING)
+ if (sd->status.option & 4 && skill_num == TF_HIDING)
return 0;
- if(sd->status.option&2 && skill_num!=TF_HIDING && skill_num!=AS_GRIMTOOTH && skill_num!=RG_BACKSTAP && skill_num!=RG_RAID )
+ if (sd->status.option & 2 && skill_num != TF_HIDING && skill_num != AS_GRIMTOOTH && skill_num != RG_BACKSTAP && skill_num != RG_RAID)
return 0;
-
- /*if(map[sd->bl.m].flag.gvg){ //GvGで使用できないスキル
- switch(skill_num){
- case SM_ENDURE:
- case AL_TELEPORT:
- case AL_WARP:
- case WZ_ICEWALL:
- case TF_BACKSLIDING:
- //case LK_BERSERK: // now usable in WoE - celest
- case HP_BASILICA:
- case HP_ASSUMPTIO:
- case ST_CHASEWALK:
+ if(skill_get_inf2(skill_num) & 0x200 && sd->bl.id == target_id)
return 0;
- }
- }*/
- /* 演奏/ダンス中 */
- if( sc_data && sc_data[SC_DANCING].timer!=-1 ){
-// if(battle_config.pc_skill_log)
-// printf("dancing! %d\n",skill_num);
- if( sc_data[SC_DANCING].val4 && skill_num!=BD_ADAPTATION ) //合奏中はアドリブ以外不可
- return 0;
- if(skill_num!=BD_ADAPTATION && skill_num!=BA_MUSICALSTRIKE && skill_num!=DC_THROWARROW){
- return 0;
- }
- }
-
- if(skill_get_inf2(skill_num)&0x200 && sd->bl.id == target_id)
- return 0;
//直前のスキルが何か?える必要のあるスキル
- switch(skill_num){
+ switch (skill_num) {
case SA_CASTCANCEL:
- if(sd->skillid != skill_num){ //キャストキャンセル自?は?えない
+ if (sd->skillid != skill_num){ //キャストキャンセル自?は?えない
sd->skillid_old = sd->skillid;
sd->skilllv_old = sd->skilllv;
break;
}
+
case BD_ENCORE: /* アンコ?ル */
- if(!sd->skillid_dance){ //前回使用した踊りがないとだめ
+ if (!sd->skillid_dance) { //前回使用した踊りがないとだめ
clif_skill_fail(sd,skill_num,0,0);
return 0;
- }else{
+ } else {
sd->skillid_old = skill_num;
}
break;
@@ -7331,19 +6983,15 @@ int skill_use_id( struct map_session_data *sd, int target_id,
struct guild *g;
if (!sd->status.guild_id)
return 0;
- if (!(g = guild_search(sd->status.guild_id)))
+ if ((g = guild_search(sd->status.guild_id)) == NULL)
return 0;
if (strcmp(sd->status.name,g->master))
return 0;
- if (skill_lv <= 0) skill_lv = 1;
+ skill_lv = guild_checkskill(g, skill_num);
+ if (skill_lv <= 0) return 0;
}
break;
- }
-
- sd->skillid = skill_num;
- sd->skilllv = skill_lv;
- switch(skill_num){ //事前にレベルが?わったりするスキル
case BD_LULLABY: /* 子守歌 */
case BD_RICHMANKIM: /* ニヨルドの宴 */
case BD_ETERNALCHAOS: /* 永遠の混沌 */
@@ -7355,120 +7003,179 @@ int skill_use_id( struct map_session_data *sd, int target_id,
case BD_RAGNAROK: /* 神?の?昏 */
case CG_MOONLIT: /* 月明りの泉に落ちる花びら */
{
- int range=1;
- int c=0;
- map_foreachinarea(skill_check_condition_char_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(c<1){
+ int range = 1;
+ int c = 0;
+ map_foreachinarea (skill_check_condition_char_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 (c < 1) {
clif_skill_fail(sd,skill_num,0,0);
return 0;
- }else if(c==99){ //相方不要設定だった
+ } else if (c == 99) { //相方不要設定だった
;
- }else{
- sd->skilllv=(c + skill_lv)/2;
+ } else {
+ sd->skilllv = (c + skill_lv)/2;
}
}
break;
}
- if(!skill_check_condition(sd,0)) return 0;
-
- /* 射程と障害物チェック */
- range = skill_get_range(skill_num,skill_lv);
- if(range < 0)
- range = battle_get_range(&sd->bl) - (range + 1);
- if(!battle_check_range(&sd->bl,bl,range) )
- return 0;
+ sd->skillid = skill_num;
+ sd->skilllv = skill_lv;
+ if (!skill_check_condition(sd,0)) return 0;
- if(bl->type==BL_PC) {
- target_sd=(struct map_session_data*)bl;
- if(target_sd && skill_num == ALL_RESURRECTION && !pc_isdead(target_sd))
- return 0;
+ {
+ int check_range_flag = 0;
+
+ /* 射程と障害物チェック */
+ range = skill_get_range(skill_num,skill_lv);
+ if(range < 0)
+ range = status_get_range(&sd->bl) - (range + 1);
+ // be lenient if the skill was cast before we have moved to the correct position [Celest]
+ if (sd->walktimer != -1)
+ range++;
+ else check_range_flag = 1;
+ if(!battle_check_range(&sd->bl,bl,range)) {
+ if (check_range_flag && battle_check_range(&sd->bl,bl,range + 1)) {
+ int mask[8][2] = {{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};
+ int dir = map_calc_dir(&sd->bl,bl->x,bl->y);
+ pc_walktoxy (sd, sd->bl.x + mask[dir][0], sd->bl.y + mask[dir][1]);
+ } else
+ return 0;
+ }
}
- if((skill_num != MO_CHAINCOMBO &&
- skill_num != MO_COMBOFINISH &&
- skill_num != MO_EXTREMITYFIST &&
- skill_num != CH_TIGERFIST &&
- skill_num != CH_CHAINCRUSH) ||
+
+ if ((skill_num != MO_CHAINCOMBO &&
+ skill_num != MO_COMBOFINISH &&
+ skill_num != MO_EXTREMITYFIST &&
+ skill_num != CH_TIGERFIST &&
+ skill_num != CH_CHAINCRUSH) ||
+ (skill_num == CH_CHAINCRUSH && sd->state.skill_flag) ||
(skill_num == MO_EXTREMITYFIST && sd->state.skill_flag) )
pc_stopattack(sd);
- casttime=skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) );
- if(skill_num != SA_MAGICROD)
- delay=skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) );
- //sd->state.skillcastcancel = skill_db[skill_num].castcancel;
+ casttime = skill_castfix(&sd->bl, skill_get_cast(skill_num, skill_lv));
+ if (skill_num != SA_MAGICROD)
+ delay = skill_delayfix(&sd->bl, skill_get_delay(skill_num, skill_lv));
sd->state.skillcastcancel = skill_get_castcancel(skill_num);
- switch(skill_num){ /* 何か特殊な?理が必要 */
-// case AL_HEAL: /* ヒ?ル */
-// if(battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
-// forcecast=1; /* ヒ?ルアタックなら詠唱エフェクト有り */
-// break;
+ switch (skill_num) { /* 何か特殊な?理が必要 */
case ALL_RESURRECTION: /* リザレクション */
- if(bl->type != BL_PC && battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl))){ /* 敵がアンデッドなら */
- forcecast=1; /* タ?ンアンデットと同じ詠唱時間 */
- casttime=skill_castfix(&sd->bl, skill_get_cast(PR_TURNUNDEAD,skill_lv) );
+ if (!tsd && battle_check_undead(status_get_race(bl),status_get_elem_type(bl))) { /* 敵がアンデッドなら */
+ forcecast = 1; /* タ?ンアンデットと同じ詠唱時間 */
+ casttime = skill_castfix(&sd->bl, skill_get_cast(PR_TURNUNDEAD, skill_lv));
}
break;
+
case MO_FINGEROFFENSIVE: /* 指? */
- casttime += casttime * ((skill_lv > sd->spiritball)? sd->spiritball:skill_lv);
+ casttime += casttime * ((skill_lv > sd->spiritball) ? sd->spiritball : skill_lv);
break;
+
case MO_CHAINCOMBO: /*連打掌*/
target_id = sd->attacktarget;
- if( sc_data && sc_data[SC_BLADESTOP].timer!=-1 ){
+ if (sc_data && sc_data[SC_BLADESTOP].timer != -1){
struct block_list *tbl;
- if((tbl=(struct block_list *)sc_data[SC_BLADESTOP].val4) == NULL) //タ?ゲットがいない?
+ if ((tbl=(struct block_list *)sc_data[SC_BLADESTOP].val4) == NULL) //タ?ゲットがいない?
return 0;
target_id = tbl->id;
}
break;
- case MO_COMBOFINISH: /*猛龍拳*/
- case CH_TIGERFIST: /* 伏虎拳 */
+ case MO_COMBOFINISH: /*猛龍拳*/
case CH_CHAINCRUSH: /* 連柱崩? */
target_id = sd->attacktarget;
break;
+ case CH_TIGERFIST: /* 伏虎拳 */
+ if (sc_data && sc_data[SC_COMBO].timer != -1 && sc_data[SC_COMBO].val1 == MO_COMBOFINISH)
+ target_id = sd->attacktarget;
+ break;
+
// -- moonsoul (altered to allow proper usage of extremity from new champion combos)
//
case MO_EXTREMITYFIST: /*阿修羅覇鳳拳*/
- if(sc_data && sc_data[SC_COMBO].timer != -1 && (sc_data[SC_COMBO].val1 == MO_COMBOFINISH || sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) {
+ if (sc_data && sc_data[SC_COMBO].timer != -1 && (sc_data[SC_COMBO].val1 == MO_COMBOFINISH || sc_data[SC_COMBO].val1 == CH_CHAINCRUSH)) {
casttime = 0;
target_id = sd->attacktarget;
}
- forcecast=1;
+ forcecast = 1;
break;
+
case SA_MAGICROD:
case SA_SPELLBREAKER:
- forcecast=1;
+ forcecast = 1;
break;
+
case WE_MALE:
case WE_FEMALE:
{
- struct map_session_data *p_sd = NULL;
- if((p_sd = pc_get_partner(sd)) == NULL)
+ struct map_session_data *p_sd = pc_get_partner(sd);
+ if (p_sd == NULL)
+ return 0;
+ if (skill_num == WE_MALE && sd->status.hp <= ((15*sd->status.max_hp)/100)) // Requires more than 15% of Max HP for WE_MALE
+ return 0;
+ else if (skill_num == WE_FEMALE && sd->status.sp <= ((15*sd->status.max_sp)/100)) // Requires more than 15% of Max SP for WE_FEMALE
return 0;
target_id = p_sd->bl.id;
//rangeをもう1回?査
- range = skill_get_range(skill_num,skill_lv);
- if(range < 0)
- range = battle_get_range(&sd->bl) - (range + 1);
- if(!battle_check_range(&sd->bl,&p_sd->bl,range))
+ if (!battle_check_range(&sd->bl, &p_sd->bl, skill_get_range(skill_num,skill_lv)))
return 0;
}
break;
- case AS_SPLASHER: /* ベナムスプラッシャ? */
+
+ // parent-baby skills
+ case WE_BABY:
+ case WE_CALLPARENT:
+ {
+ struct map_session_data *f_sd = pc_get_father(sd);
+ struct map_session_data *m_sd = pc_get_mother(sd);
+
+ // set target as any one of the parent
+ if (f_sd) target_id = f_sd->bl.id;
+ else if (m_sd) target_id = m_sd->bl.id;
+ else return 0; // neither are found
+
+ // skip range check
+ //rangeをもう1回?査
+ //range = skill_get_range(skill_num,skill_lv);
+ //if(!battle_check_range(&sd->bl,&p_sd->bl,range))
+ // return 0;
+ }
+ break;
+
+ case WE_CALLBABY:
{
- struct status_change *t_sc_data = battle_get_sc_data(bl);
- if(t_sc_data && t_sc_data[SC_POISON].timer==-1){
- clif_skill_fail(sd,skill_num,0,10);
+ struct map_session_data *p_sd = pc_get_child(sd);
+ if (p_sd == NULL)
+ return 0;
+ target_id = p_sd->bl.id;
+ //rangeをもう1回?査
+ if(!battle_check_range(&sd->bl, &p_sd->bl, skill_get_range(skill_num,skill_lv)))
return 0;
- }
}
break;
- case PF_MEMORIZE: /* メモライズ */
- casttime = 12000;
+
+ 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,sd->bl.m,sd->bl.x,sd->bl.y,sd->skillid,sd->skilllv)) {
+ clif_skill_fail(sd,sd->skillid,0,0);
+ return 0;
+ }
+ // cancel Basilica if already in effect
+ if (sc_data && sc_data[SC_BASILICA].timer != -1) {
+ struct skill_unit_group *sg = (struct skill_unit_group *)sd->sc_data[SC_BASILICA].val4;
+ if (sg && sg->src_id == sd->bl.id) {
+ status_change_end(&sd->bl,SC_BASILICA,-1);
+ skill_delunitgroup (sg);
+ return 0;
+ }
+ }
+ }
break;
+
case GD_BATTLEORDER:
case GD_REGENERATION:
case GD_RESTORE:
@@ -7478,62 +7185,52 @@ int skill_use_id( struct map_session_data *sd, int target_id,
}
//メモライズ?態ならキャストタイムが1/3
- if(sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0){
+ if (sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0) {
casttime = casttime/2;
- if((--sc_data[SC_MEMORIZE].val2)<=0)
- skill_status_change_end(&sd->bl, SC_MEMORIZE, -1);
+ if ((--sc_data[SC_MEMORIZE].val2) <= 0)
+ status_change_end(&sd->bl, SC_MEMORIZE, -1);
}
- if(battle_config.pc_skill_log)
- printf("PC %d skill use target_id=%d skill=%d lv=%d cast=%d\n",sd->bl.id,target_id,skill_num,skill_lv,casttime);
+ if (battle_config.pc_skill_log)
+ printf ("PC %d skill use target_id=%d skill=%d lv=%d cast=%d\n",
+ sd->bl.id, target_id, skill_num, skill_lv, casttime);
-// if(sd->skillitem == skill_num)
-// casttime = delay = 0;
-
- if( casttime>0 || forcecast ){ /* 詠唱が必要 */
+ if (casttime > 0 || forcecast) { /* 詠唱が必要 */
struct mob_data *md;
- clif_skillcasting( &sd->bl, sd->bl.id, target_id, 0,0, skill_num,casttime);
+ clif_skillcasting(&sd->bl, sd->bl.id, target_id, 0,0, skill_num,casttime);
/* 詠唱反?モンスタ? */
- if( bl->type==BL_MOB && (md=(struct mob_data *)bl) && mob_db[md->class].mode&0x10 &&
- md->state.state!=MS_ATTACK && sd->invincible_timer == -1){
- md->target_id=sd->bl.id;
+ if (bl->type == BL_MOB && (md = (struct mob_data *)bl) && mob_db[md->class_].mode & 0x10 &&
+ md->state.state != MS_ATTACK && sd->invincible_timer == -1){
+ md->target_id = sd->bl.id;
md->state.targettype = ATTACKABLE;
- md->min_chase=13;
+ md->min_chase = 13;
}
}
- if( casttime<=0 ) /* 詠唱の無いものはキャンセルされない */
- sd->state.skillcastcancel=0;
-
- sd->skilltarget = target_id;
-/* sd->cast_target_bl = bl; */
- sd->skillx = 0;
- sd->skilly = 0;
+ sd->skilltarget = target_id;
+ sd->skillx = 0;
+ sd->skilly = 0;
sd->canact_tick = tick + casttime + delay;
sd->canmove_tick = tick;
- if(!(battle_config.pc_cloak_check_type&2) && sc_data && sc_data[SC_CLOAKING].timer != -1 && sd->skillid != AS_CLOAKING)
- skill_status_change_end(&sd->bl,SC_CLOAKING,-1);
- if(casttime > 0) {
- sd->skilltimer = add_timer( tick+casttime, skill_castend_id, sd->bl.id, 0 );
- if((skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
+
+ if (!(battle_config.pc_cloak_check_type & 2) && sc_data && sc_data[SC_CLOAKING].timer != -1 && sd->skillid != AS_CLOAKING)
+ status_change_end(&sd->bl,SC_CLOAKING,-1);
+ if (casttime > 0) {
+ sd->skilltimer = add_timer (tick + casttime, skill_castend_id, sd->bl.id, 0);
+ if ((skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
sd->prev_speed = sd->speed;
- sd->speed = sd->speed*(175 - skill*5)/100;
- clif_updatestatus(sd,SP_SPEED);
+ status_calc_speed (sd);
}
else
pc_stop_walking(sd,0);
- }
- else {
- if(skill_num != SA_CASTCANCEL)
+ } else {
+ sd->state.skillcastcancel = 0; /* 詠唱の無いものはキャンセルされない */
+ if (skill_num != SA_CASTCANCEL)
sd->skilltimer = -1;
skill_castend_id(sd->skilltimer,tick,sd->bl.id,0);
}
- //マジックパワ?の?果終了
- //if(sc_data && sc_data[SC_MAGICPOWER].timer != -1 && skill_num != HW_MAGICPOWER)
- // skill_status_change_end(&sd->bl,SC_MAGICPOWER,-1); // moved
-
return 0;
}
@@ -7541,137 +7238,127 @@ int skill_use_id( struct map_session_data *sd, int target_id,
* スキル使用(場所指定)
*------------------------------------------
*/
-int skill_use_pos( struct map_session_data *sd,
- int skill_x, int skill_y, int skill_num, int skill_lv)
+int skill_use_pos (struct map_session_data *sd, int skill_x, int skill_y, int skill_num, int skill_lv)
{
struct block_list bl;
struct status_change *sc_data;
- unsigned int tick;
- int casttime=0,delay=0,skill,range;
+ int casttime = 0, delay = 0, skill, range;
+ unsigned int tick = gettick();
nullpo_retr(0, sd);
- if(pc_isdead(sd))
+ if (pc_isdead(sd))
return 0;
-
if (skillnotok(skill_num, sd)) // [MoueJstr]
return 0;
-
- if(skill_num==WZ_ICEWALL && map[sd->bl.m].flag.noicewall && !map[sd->bl.m].flag.pvp) { // noicewall flag [Valaris]
+ if (skill_num == WZ_ICEWALL && map[sd->bl.m].flag.noicewall && !map[sd->bl.m].flag.pvp) { // noicewall flag [Valaris]
clif_skill_fail(sd,sd->skillid,0,0);
return 0;
}
- sc_data=sd->sc_data;
+ sc_data = sd->sc_data;
- if( sd->opt1>0 )
+ if (sd->opt1 > 0)
return 0;
- if(sc_data){
- if( sc_data[SC_DIVINA].timer!=-1 ||
- sc_data[SC_ROKISWEIL].timer!=-1 ||
+ if (sc_data){
+ if (sc_data[SC_DIVINA].timer != -1 ||
+ sc_data[SC_ROKISWEIL].timer != -1 ||
sc_data[SC_AUTOCOUNTER].timer != -1 ||
sc_data[SC_STEELBODY].timer != -1 ||
sc_data[SC_DANCING].timer!=-1 ||
sc_data[SC_BERSERK].timer != -1 ||
- sd->sc_data[SC_MARIONETTE].timer != -1)
+ sc_data[SC_MARIONETTE].timer != -1)
return 0; /* ?態異常や沈?など */
- if (sd->sc_data[SC_BLOCKSKILL].timer!=-1)
- if (skill_num == sd->sc_data[SC_BLOCKSKILL].val3)
- return 0;
-
- if (sc_data[SC_BASILICA].timer != -1) { // Basilica cancels if caster moves [celest]
- struct skill_unit *su;
- if ((su = (struct skill_unit *)sc_data[SC_BASILICA].val4)) {
- struct skill_unit_group *sg;
- // if caster is the owner of basilica
- if ((sg = su->group) && sg->src_id == sd->bl.id) {
- // skill_status_change_end(&sd->bl,SC_BASILICA,-1);
- // skill_delunitgroup (sg);
- if (skill_num != HP_BASILICA) return 0;
- } // otherwise...
- else
- return 0;
- }
+ if (sc_data[SC_BASILICA].timer != -1) {
+ struct skill_unit_group *sg = (struct skill_unit_group *)sc_data[SC_BASILICA].val4;
+ // if caster is the owner of basilica
+ if (sg && sg->src_id == sd->bl.id &&
+ skill_num == HP_BASILICA) ; // do nothing
+ // otherwise...
+ else return 0;
}
}
- if(sd->status.option&2)
+ if(sd->status.option & 2)
return 0;
-/* if(map[sd->bl.m].flag.gvg &&
- (skill_num == SM_ENDURE || skill_num == AL_TELEPORT ||
- skill_num == AL_WARP || skill_num == WZ_ICEWALL ||
- skill_num == TF_BACKSLIDING))
- return 0;*/
-
sd->skillid = skill_num;
sd->skilllv = skill_lv;
- if(skill_lv <= 0) return 0;
+ if (skill_lv <= 0) return 0;
sd->skillx = skill_x;
sd->skilly = skill_y;
- if(!skill_check_condition(sd,0)) return 0;
+ if (!skill_check_condition(sd,0)) return 0;
/* 射程と障害物チェック */
bl.type = BL_NUL;
bl.m = sd->bl.m;
bl.x = skill_x;
bl.y = skill_y;
- range = skill_get_range(skill_num,skill_lv);
- if(range < 0)
- range = battle_get_range(&sd->bl) - (range + 1);
- if(!battle_check_range(&sd->bl,&bl,range) )
- return 0;
+
+ {
+ int check_range_flag = 0;
+
+ /* 射程と障害物チェック */
+ range = skill_get_range(skill_num,skill_lv);
+ if(range < 0)
+ range = status_get_range(&sd->bl) - (range + 1);
+ // be lenient if the skill was cast before we have moved to the correct position [Celest]
+ if (sd->walktimer != -1)
+ range ++;
+ else check_range_flag = 1;
+ if(!battle_check_range(&sd->bl,&bl,range)) {
+ if (check_range_flag && battle_check_range(&sd->bl,&bl,range + 1)) {
+ int mask[8][2] = {{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1},{1,0},{1,1}};
+ int dir = map_calc_dir(&sd->bl,bl.x,bl.y);
+ pc_walktoxy (sd, sd->bl.x + mask[dir][0], sd->bl.y + mask[dir][1]);
+ } else
+ return 0;
+ }
+ }
pc_stopattack(sd);
- casttime=skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) );
- delay=skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) );
+ casttime = skill_castfix(&sd->bl, skill_get_cast( skill_num,skill_lv) );
+ delay = skill_delayfix(&sd->bl, skill_get_delay( skill_num,skill_lv) );
sd->state.skillcastcancel = skill_db[skill_num].castcancel;
- if(battle_config.pc_skill_log)
- printf("PC %d skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d\n",sd->bl.id,skill_x,skill_y,skill_num,skill_lv,casttime);
+ if (battle_config.pc_skill_log)
+ printf("PC %d skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d\n",
+ sd->bl.id, skill_x, skill_y, skill_num, skill_lv, casttime);
-// if(sd->skillitem == skill_num)
-// casttime = delay = 0;
//メモライズ?態ならキャストタイムが1/3
- if(sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0){
+ if (sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0){
casttime = casttime/3;
- if((--sc_data[SC_MEMORIZE].val2)<=0)
- skill_status_change_end(&sd->bl, SC_MEMORIZE, -1);
+ if ((--sc_data[SC_MEMORIZE].val2)<=0)
+ status_change_end(&sd->bl, SC_MEMORIZE, -1);
}
- if( casttime>0 ) /* 詠唱が必要 */
- clif_skillcasting( &sd->bl,
- sd->bl.id, 0, skill_x,skill_y, skill_num,casttime);
-
- if( casttime<=0 ) /* 詠唱の無いものはキャンセルされない */
- sd->state.skillcastcancel=0;
-
+ if (casttime > 0) /* 詠唱が必要 */
+ clif_skillcasting(&sd->bl, sd->bl.id, 0, skill_x, skill_y, skill_num, casttime);
+
sd->skilltarget = 0;
-/* sd->cast_target_bl = NULL; */
- tick=gettick();
sd->canact_tick = tick + casttime + delay;
sd->canmove_tick = tick;
- if(!(battle_config.pc_cloak_check_type&2) && sc_data && sc_data[SC_CLOAKING].timer != -1)
- skill_status_change_end(&sd->bl,SC_CLOAKING,-1);
- if(casttime > 0) {
- sd->skilltimer = add_timer( tick+casttime, skill_castend_pos, sd->bl.id, 0 );
- if((skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
+ if (!(battle_config.pc_cloak_check_type&2) && sc_data && sc_data[SC_CLOAKING].timer != -1)
+ status_change_end(&sd->bl,SC_CLOAKING,-1);
+ if (casttime > 0) {
+ sd->skilltimer = add_timer(tick + casttime, skill_castend_pos, sd->bl.id, 0);
+ if ((skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
sd->prev_speed = sd->speed;
- sd->speed = sd->speed*(175 - skill*5)/100;
- clif_updatestatus(sd,SP_SPEED);
+ status_calc_speed (sd);
}
else
pc_stop_walking(sd,0);
- }
- else {
+ } else {
+ sd->state.skillcastcancel = 0; /* 詠唱の無いものはキャンセルされない */
sd->skilltimer = -1;
skill_castend_pos(sd->skilltimer,tick,sd->bl.id,0);
}
//マジックパワ?の?果終了
- if(sc_data && sc_data[SC_MAGICPOWER].timer != -1 && skill_num != HW_MAGICPOWER)
- skill_status_change_end(&sd->bl,SC_MAGICPOWER,-1);
+ if (skill_get_unit_id(skill_num, 0) != 0x86 &&
+ sc_data && sc_data[SC_MAGICPOWER].timer != -1)
+ status_change_end(&sd->bl,SC_MAGICPOWER,-1);
return 0;
}
@@ -7680,60 +7367,59 @@ int skill_use_pos( struct map_session_data *sd,
* スキル詠唱キャンセル
*------------------------------------------
*/
-int skill_castcancel(struct block_list *bl,int type)
+int skill_castcancel (struct block_list *bl, int type)
{
int inf;
- int ret=0;
+ int ret = 0;
nullpo_retr(0, bl);
- if(bl->type==BL_PC){
- struct map_session_data *sd=(struct map_session_data *)bl;
- unsigned long tick=gettick();
+ if (bl->type == BL_PC) {
+ struct map_session_data *sd = (struct map_session_data *)bl;
+ unsigned long tick = gettick();
nullpo_retr(0, sd);
- sd->canact_tick=tick;
+ sd->canact_tick = tick;
sd->canmove_tick = tick;
- if( sd->skilltimer!=-1){
- if(pc_checkskill(sd,SA_FREECAST) > 0) {
+ if (sd->skilltimer != -1) {
+ if (pc_checkskill(sd,SA_FREECAST) > 0) {
sd->speed = sd->prev_speed;
clif_updatestatus(sd,SP_SPEED);
}
- if(!type) {
- if((inf = skill_get_inf( sd->skillid )) == 2 || inf == 32)
- ret=delete_timer( sd->skilltimer, skill_castend_pos );
+ if (!type) {
+ if ((inf = skill_get_inf( sd->skillid )) == 2 || inf == 32)
+ ret = delete_timer( sd->skilltimer, skill_castend_pos );
else
ret=delete_timer( sd->skilltimer, skill_castend_id );
- if(ret<0)
- printf("delete timer error : skillid : %d\n",sd->skillid);
- }
- else {
- if((inf = skill_get_inf( sd->skillid_old )) == 2 || inf == 32)
- ret=delete_timer( sd->skilltimer, skill_castend_pos );
+ if (ret < 0)
+ printf("delete timer error : skillid : %d\n", sd->skillid);
+ } else {
+ if ((inf = skill_get_inf( sd->skillid_old )) == 2 || inf == 32)
+ ret = delete_timer( sd->skilltimer, skill_castend_pos );
else
- ret=delete_timer( sd->skilltimer, skill_castend_id );
- if(ret<0)
- printf("delete timer error : skillid : %d\n",sd->skillid_old);
+ ret = delete_timer( sd->skilltimer, skill_castend_id );
+ if (ret < 0)
+ printf("delete timer error : skillid : %d\n", sd->skillid_old);
}
- sd->skilltimer=-1;
+ sd->skilltimer = -1;
clif_skillcastcancel(bl);
}
-
return 0;
- }else if(bl->type==BL_MOB){
- struct mob_data *md=(struct mob_data *)bl;
+ } else if (bl->type == BL_MOB) {
+ struct mob_data *md = (struct mob_data *)bl;
nullpo_retr(0, md);
- if( md->skilltimer!=-1 ){
- if((inf = skill_get_inf( md->skillid )) == 2 || inf == 32)
- ret=delete_timer( md->skilltimer, mobskill_castend_pos );
+ if (md->skilltimer != -1) {
+ if ((inf = skill_get_inf( md->skillid )) == 2 || inf == 32)
+ ret = delete_timer( md->skilltimer, mobskill_castend_pos );
else
- ret=delete_timer( md->skilltimer, mobskill_castend_id );
- md->skilltimer=-1;
+ ret = delete_timer( md->skilltimer, mobskill_castend_id );
+ md->skilltimer = -1;
clif_skillcastcancel(bl);
}
- if(ret<0)
- printf("delete timer error : skillid : %d\n",md->skillid);
+ if (ret < 0)
+ printf("delete timer error : skillid : %d\n", md->skillid);
return 0;
}
+
return 1;
}
/*=========================================
@@ -7912,13 +7598,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; // 離れた時は、?を切るだけ
@@ -7936,7 +7623,7 @@ void skill_devotion_end(struct map_session_data *md,struct map_session_data *sd,
md->dev.val1[target]=md->dev.val2[target]=0;
if(sd && sd->sc_data){
- // skill_status_change_end(sd->bl,SC_DEVOTION,-1);
+ // status_change_end(sd->bl,SC_DEVOTION,-1);
sd->sc_data[SC_DEVOTION].val1=0;
sd->sc_data[SC_DEVOTION].val2=0;
clif_status_change(&sd->bl,SC_DEVOTION,0);
@@ -7978,7 +7665,7 @@ int skill_autospell(struct map_session_data *sd,int skillid)
if(maxlv > (lv=pc_checkskill(sd,skillid)))
maxlv = lv;
- skill_status_change_start(&sd->bl,SC_AUTOSPELL,skilllv,skillid,maxlv,0, // val1:スキルID val2:使用最大Lv
+ status_change_start(&sd->bl,SC_AUTOSPELL,skilllv,skillid,maxlv,0, // val1:スキルID val2:使用最大Lv
skill_get_time(SA_AUTOSPELL,skilllv),0);// にしてみたけどbscriptが書き易い????
return 0;
}
@@ -8087,34 +7774,64 @@ int skill_frostjoke_scream(struct block_list *bl,va_list ap)
if(src == bl)//自分には?かない
return 0;
- if(battle_check_target(src,bl,BCT_ENEMY) > 0)
+ if (map[src->m].flag.gvg || map[src->m].flag.pvp)
skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick);
- else if(battle_check_target(src,bl,BCT_PARTY) > 0) {
- if(rand()%100 < 10)//PTメンバにも低確率でかかる(とりあえず10%)
+ // we freeze everybody except of ourselfes on pvp/gvg [veider]
+ else {
+ if(battle_check_target(src,bl,BCT_ENEMY) > 0)
+ skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick);
+ else if(battle_check_target(src,bl,BCT_PARTY) > 0 && rand()%100 < 10)
skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,tick);
}
+ // so on non-pvp/gvg we are just freezing as freezed before
return 0;
}
/*==========================================
- *アブラカダブラの使用スキル決定(決定スキルがダメなら0を返す)
+ * Moonlit creates a 'safe zone' [celest]
*------------------------------------------
*/
-int skill_abra_dataset(int skilllv)
+static int skill_moonlit_count(struct block_list *bl,va_list ap)
{
- int skill = rand()%331;
+ int *c, id;
+ struct map_session_data *sd;
- if(skilllv <= 0) return 0;
+ nullpo_retr(0, bl);
+ nullpo_retr(0, ap);
+ nullpo_retr(0, (sd=(struct map_session_data *)bl));
- //dbに基づくレベル?確率判定
- if(skill_abra_db[skill].req_lv > skilllv || rand()%10000 >= skill_abra_db[skill].per) return 0;
- //NPCスキルはダメ
- if(skill >= NPC_PIERCINGATT && skill <= NPC_SUMMONMONSTER) return 0;
- //演奏スキルはダメ
- if(skill_is_danceskill(skill)) return 0;
+ id=va_arg(ap,int);
+ c=va_arg(ap,int *);
- return skill;
+ if (sd->bl.id != id && sd->sc_count && sd->sc_data[SC_MOONLIT].timer != -1 && c)
+ (*c)++;
+ return 0;
+}
+
+int skill_check_moonlit (struct block_list *bl, int dx, int dy)
+{
+ int c=0;
+ nullpo_retr(0, bl);
+ map_foreachinarea(skill_moonlit_count,bl->m,
+ dx-1,dy-1,dx+1,dy+1,BL_PC,bl->id,&c);
+ return (c>0);
+}
+
+/*==========================================
+ * バジリカのセルを設定する
+ *------------------------------------------
+ */
+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);
+ }
}
/*==========================================
@@ -8137,7 +7854,8 @@ int skill_attack_area(struct block_list *bl,va_list ap)
return 0;
skillid=va_arg(ap,int);
skilllv=va_arg(ap,int);
- if(skilllv <= 0) return 0;
+ //if(skilllv <= 0) return 0;
+ if(skillid > 0 && skilllv <= 0) return 0; // celest
tick=va_arg(ap,unsigned int);
flag=va_arg(ap,int);
type=va_arg(ap,int);
@@ -8155,16 +7873,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)
@@ -8190,43 +7912,43 @@ int skill_landprotector(struct block_list *bl, va_list ap )
nullpo_retr(0, bl);
nullpo_retr(0, ap);
- skillid=va_arg(ap,int);
- alive=va_arg(ap,int *);
- if((unit=(struct skill_unit *)bl) == NULL)
+ skillid = va_arg(ap,int);
+ alive = va_arg(ap,int *);
+
+ if ((unit = (struct skill_unit *)bl) == NULL)
return 0;
- if(skillid==SA_LANDPROTECTOR){
+ if (skillid == SA_LANDPROTECTOR)
skill_delunit(unit);
- }else{
- if(alive && unit->group->skill_id==SA_LANDPROTECTOR)
- (*alive)=0;
- }
+ else if (alive && unit->group && unit->group->skill_id == SA_LANDPROTECTOR)
+ (*alive) = 0;
+
return 0;
}
/*==========================================
* イドゥンの林檎の回復?理(foreachinarea)
*------------------------------------------
*/
-int skill_idun_heal(struct block_list *bl, va_list ap )
+int skill_idun_heal (struct block_list *bl, va_list ap)
{
struct skill_unit *unit;
struct skill_unit_group *sg;
int heal;
nullpo_retr(0, bl);
+ if (bl->type != BL_PC && bl->type != BL_MOB)
+ return 0;
+
nullpo_retr(0, ap);
nullpo_retr(0, unit = va_arg(ap,struct skill_unit *));
nullpo_retr(0, sg = unit->group);
-
- heal=30+sg->skill_lv*5+((sg->val1)>>16)*5+((sg->val1)&0xfff)/2;
-
- if(bl->type == BL_SKILL || bl->id == sg->src_id)
+ if (bl->id == sg->src_id)
return 0;
- if(bl->type == BL_PC || bl->type == BL_MOB){
- clif_skill_nodamage(&unit->bl,bl,AL_HEAL,heal,1);
- battle_heal(NULL,bl,heal,0,0);
- }
+ heal = 30 + sg->skill_lv * 5 + ((sg->val1) >> 16) * 5 + ((sg->val1) & 0xfff) / 2;
+ clif_skill_nodamage(&unit->bl, bl, AL_HEAL, heal, 1);
+ battle_heal(NULL, bl, heal, 0, 0);
+
return 0;
}
@@ -8234,18 +7956,19 @@ 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;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
- if((src = va_arg(ap,struct block_list *)) == NULL)
+ if ((src = va_arg(ap,struct block_list *)) == NULL)
return 0;
- if((c = va_arg(ap,int *)) == NULL)
+ if ((c = va_arg(ap,int *)) == NULL)
return 0;
- if(battle_check_target(src,bl,BCT_ENEMY) > 0)
+ if (battle_check_target(src,bl,BCT_ENEMY) > 0)
(*c)++;
return 0;
}
@@ -8253,7 +7976,7 @@ int skill_count_target(struct block_list *bl, va_list ap ){
* トラップ範??理(foreachinarea)
*------------------------------------------
*/
-int skill_trap_splash(struct block_list *bl, va_list ap )
+int skill_trap_splash (struct block_list *bl, va_list ap)
{
struct block_list *src;
int tick;
@@ -8285,6 +8008,7 @@ int skill_trap_splash(struct block_list *bl, va_list ap )
for(i=0;i<splash_count;i++){
skill_attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,(sg->val2)?0x0500:0);
}
+ break;
case 0x97: /* フリ?ジングトラップ */
skill_attack(BF_WEAPON, ss,src,bl,sg->skill_id,sg->skill_lv,tick,(sg->val2)?0x0500:0);
break;
@@ -8295,1720 +8019,74 @@ int skill_trap_splash(struct block_list *bl, va_list ap )
return 0;
}
-/*----------------------------------------------------------------------------
- * ステ?タス異常
- *----------------------------------------------------------------------------
- */
-
-/*==========================================
- * ステ?タス異常タイマ?範??理
- *------------------------------------------
- */
-int skill_status_change_timer_sub(struct block_list *bl, va_list ap )
-{
- struct block_list *src;
- int type;
- unsigned int tick;
-
- nullpo_retr(0, bl);
- nullpo_retr(0, ap);
- nullpo_retr(0, src=va_arg(ap,struct block_list*));
- type=va_arg(ap,int);
- tick=va_arg(ap,unsigned int);
-
- if(bl->type!=BL_PC && bl->type!=BL_MOB)
- return 0;
-
- switch( type ){
- case SC_SIGHT: /* サイト */
- case SC_CONCENTRATE:
- if( (*battle_get_option(bl))&6 ){
- skill_status_change_end( bl, SC_HIDING, -1);
- skill_status_change_end( bl, SC_CLOAKING, -1);
- }
- break;
- case SC_RUWACH: /* ルアフ */
- if( (*battle_get_option(bl))&6 ){
- skill_status_change_end( bl, SC_HIDING, -1);
- skill_status_change_end( bl, SC_CLOAKING, -1);
- if(battle_check_target( src,bl, BCT_ENEMY ) > 0) {
- struct status_change *sc_data = battle_get_sc_data(bl);
- skill_attack(BF_MAGIC,src,src,bl,AL_RUWACH,sc_data[type].val1,tick,0);
- }
- }
- break;
- }
- return 0;
-}
-
-/*==========================================
- * ステ?タス異常終了
- *------------------------------------------
- */
-int skill_status_change_end(struct block_list* bl, int type, int tid)
-{
- struct status_change* sc_data;
- int opt_flag=0, calc_flag = 0;
- short *sc_count, *option, *opt1, *opt2, *opt3;
-
- nullpo_retr(0, bl);
- if(bl->type!=BL_PC && bl->type!=BL_MOB) {
- if(battle_config.error_log)
- printf("skill_status_change_end: neither MOB nor PC !\n");
- return 0;
- }
- nullpo_retr(0, sc_data = battle_get_sc_data(bl));
- nullpo_retr(0, sc_count = battle_get_sc_count(bl));
- nullpo_retr(0, option = battle_get_option(bl));
- nullpo_retr(0, opt1 = battle_get_opt1(bl));
- nullpo_retr(0, opt2 = battle_get_opt2(bl));
- nullpo_retr(0, opt3 = battle_get_opt3(bl));
-
- if ((*sc_count) > 0 && sc_data[type].timer != -1 && (sc_data[type].timer == tid || tid == -1)) {
-
- if (tid == -1) // タイマから呼ばれていないならタイマ削除をする
- delete_timer(sc_data[type].timer,skill_status_change_timer);
-
- /* 該?の異常を正常に?す */
- sc_data[type].timer=-1;
- (*sc_count)--;
-
- switch(type){ /* 異常の種類ごとの?理 */
- case SC_PROVOKE: /* プロボック */
- case SC_ENDURE: // celest
- case SC_CONCENTRATE: /* 集中力向上 */
- case SC_BLESSING: /* ブレッシング */
- case SC_ANGELUS: /* アンゼルス */
- case SC_INCREASEAGI: /* 速度上昇 */
- case SC_DECREASEAGI: /* 速度減少 */
- case SC_SIGNUMCRUCIS: /* シグナムクルシス */
- case SC_HIDING:
- case SC_TWOHANDQUICKEN: /* 2HQ */
- case SC_ADRENALINE: /* アドレナリンラッシュ */
- case SC_ENCPOISON: /* エンチャントポイズン */
- case SC_IMPOSITIO: /* インポシティオマヌス */
- case SC_GLORIA: /* グロリア */
- case SC_LOUD: /* ラウドボイス */
- case SC_QUAGMIRE: /* クァグマイア */
- case SC_PROVIDENCE: /* プロヴィデンス */
- case SC_SPEARSQUICKEN: /* スピアクイッケン */
- case SC_VOLCANO:
- case SC_DELUGE:
- case SC_VIOLENTGALE:
- case SC_ETERNALCHAOS: /* エタ?ナルカオス */
- case SC_DRUMBATTLE: /* ?太鼓の響き */
- case SC_NIBELUNGEN: /* ニ?ベルングの指輪 */
- case SC_SIEGFRIED: /* 不死身のジ?クフリ?ド */
- case SC_WHISTLE: /* 口笛 */
- case SC_ASSNCROS: /* 夕陽のアサシンクロス */
- case SC_HUMMING: /* ハミング */
- case SC_DONTFORGETME: /* 私を忘れないで */
- case SC_FORTUNE: /* 幸運のキス */
- case SC_SERVICE4U: /* サ?ビスフォ?ユ? */
- case SC_EXPLOSIONSPIRITS: // 爆裂波動
- case SC_STEELBODY: // 金剛
- case SC_DEFENDER:
- case SC_SPEEDPOTION0: /* ?速ポ?ション */
- case SC_SPEEDPOTION1:
- case SC_SPEEDPOTION2:
- case SC_APPLEIDUN: /* イドゥンの林檎 */
- case SC_RIDING:
- case SC_BLADESTOP_WAIT:
- case SC_AURABLADE: /* オ?ラブレ?ド */
- case SC_PARRYING: /* パリイング */
- case SC_CONCENTRATION: /* コンセントレ?ション */
- case SC_TENSIONRELAX: /* テンションリラックス */
- case SC_ASSUMPTIO: /* アシャンプティオ */
- case SC_WINDWALK: /* ウインドウォ?ク */
- case SC_TRUESIGHT: /* トゥル?サイト */
- case SC_SPIDERWEB: /* スパイダ?ウェッブ */
- case SC_MAGICPOWER: /* 魔法力?幅 */
- case SC_CHASEWALK:
- case SC_ATKPOT: /* attack potion [Valaris] */
- case SC_MATKPOT: /* magic attack potion [Valaris] */
- case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
- case SC_MELTDOWN: /* メルトダウン */
- // Celest
- case SC_EDP:
- case SC_MARIONETTE:
- case SC_MARIONETTE2:
- case SC_SLOWDOWN:
- case SC_LEADERSHIP:
- case SC_GLORYWOUNDS:
- case SC_SOULCOLD:
- case SC_HAWKEYES:
- case SC_BATTLEORDERS:
- case SC_REGENERATION:
- calc_flag = 1;
- break;
- case SC_BERSERK: /* バ?サ?ク */
- calc_flag = 1;
- clif_status_change(bl,SC_INCREASEAGI,0); /* アイコン消去 */
- break;
- case SC_DEVOTION: /* ディボ?ション */
- {
- struct map_session_data *md = map_id2sd(sc_data[type].val1);
- sc_data[type].val1=sc_data[type].val2=0;
- skill_devotion(md,bl->id);
- calc_flag = 1;
- }
- break;
- case SC_BLADESTOP:
- {
- struct status_change *t_sc_data = battle_get_sc_data((struct block_list *)sc_data[type].val4);
- //片方が切れたので相手の白刃?態が切れてないのなら解除
- if(t_sc_data && t_sc_data[SC_BLADESTOP].timer!=-1)
- skill_status_change_end((struct block_list *)sc_data[type].val4,SC_BLADESTOP,-1);
-
- if(sc_data[type].val2==2)
- clif_bladestop((struct block_list *)sc_data[type].val3,(struct block_list *)sc_data[type].val4,0);
- }
- break;
- case SC_DANCING:
- {
- struct map_session_data *dsd;
- struct status_change *d_sc_data;
- if(sc_data[type].val4 && (dsd=map_id2sd(sc_data[type].val4))){
- d_sc_data = dsd->sc_data;
- //合奏で相手がいる場合相手のval4を0にする
- if(d_sc_data && d_sc_data[type].timer!=-1)
- d_sc_data[type].val4=0;
- }
- }
- calc_flag = 1;
- break;
- case SC_GRAFFITI:
- {
- struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[type].val4; //val4がグラフィティのgroup_id
- if(sg)
- skill_delunitgroup(sg);
- }
- break;
- case SC_NOCHAT: //チャット禁止?態
- {
- struct map_session_data *sd=NULL;
- if(bl->type == BL_PC && (sd=(struct map_session_data *)bl)){
- if (sd->status.manner >= 0) // weeee ^^ [celest]
- sd->status.manner = 0;
- clif_updatestatus(sd,SP_MANNER);
- }
- }
- break;
- case SC_SPLASHER: /* ベナムスプラッシャ? */
- {
- struct block_list *src=map_id2bl(sc_data[type].val3);
- if(src && tid!=-1){
- //自分にダメ?ジ&周?3*3にダメ?ジ
- skill_castend_damage_id(src, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 );
- }
- }
- break;
- case SC_SELFDESTRUCTION: /* 自爆 */
- {
- //自分のダメ?ジは0にして
- struct mob_data *md=NULL;
- if(bl->type == BL_MOB && (md=(struct mob_data*)bl))
- skill_castend_damage_id(bl, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 );
- }
- break;
- /* option1 */
- case SC_FREEZE:
- sc_data[type].val3 = 0;
- break;
-
- /* option2 */
- case SC_POISON: /* 毒 */
- case SC_BLIND: /* 暗? */
- case SC_CURSE:
- calc_flag = 1;
- break;
- }
-
- if(bl->type==BL_PC && type<SC_SENDMAX)
- clif_status_change(bl,type,0); /* アイコン消去 */
-
- switch(type){ /* 正常に?るときなにか?理が必要 */
- case SC_STONE:
- case SC_FREEZE:
- case SC_STAN:
- case SC_SLEEP:
- *opt1 = 0;
- opt_flag = 1;
- break;
-
- case SC_POISON:
- if (sc_data[SC_DPOISON].timer != -1) //
- break; // DPOISON用のオプション
- *opt2 &= ~1; // が?用に用意された場合には
- opt_flag = 1; // ここは削除する
- break; //
- case SC_CURSE:
- case SC_SILENCE:
- case SC_BLIND:
- *opt2 &= ~(1<<(type-SC_POISON));
- opt_flag = 1;
- break;
- case SC_DPOISON:
- if (sc_data[SC_POISON].timer != -1) // DPOISON用のオプションが
- break; // 用意されたら削除
- *opt2 &= ~1; // 毒?態解除
- opt_flag = 1;
- break;
- case SC_SIGNUMCRUCIS:
- *opt2 &= ~0x40;
- opt_flag = 1;
- break;
-
- case SC_HIDING:
- case SC_CLOAKING:
- *option &= ~((type == SC_HIDING) ? 2 : 4);
- calc_flag = 1; // orn
- opt_flag = 1 ;
- break;
-
- case SC_CHASEWALK:
- *option &= ~16388;
- opt_flag = 1 ;
- break;
-
- case SC_SIGHT:
- *option &= ~1;
- opt_flag = 1;
- break;
- case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
- *option &= ~4096;
- opt_flag = 1;
- break;
- case SC_RUWACH:
- *option &= ~8192;
- opt_flag = 1;
- break;
-
- //opt3
- case SC_TWOHANDQUICKEN: /* 2HQ */
- case SC_SPEARSQUICKEN: /* スピアクイッケン */
- case SC_CONCENTRATION: /* コンセントレ?ション */
- *opt3 &= ~1;
- break;
- case SC_OVERTHRUST: /* オ?バ?スラスト */
- *opt3 &= ~2;
- break;
- case SC_ENERGYCOAT: /* エナジ?コ?ト */
- *opt3 &= ~4;
- break;
- case SC_EXPLOSIONSPIRITS: // 爆裂波動
- *opt3 &= ~8;
- break;
- case SC_STEELBODY: // 金剛
- *opt3 &= ~16;
- break;
- case SC_BLADESTOP: /* 白刃取り */
- *opt3 &= ~32;
- break;
- case SC_BERSERK: /* バ?サ?ク */
- *opt3 &= ~128;
- break;
- case SC_MARIONETTE: /* マリオネットコントロ?ル */
- case SC_MARIONETTE2:
- *opt3 &= ~1024;
- break;
- case SC_ASSUMPTIO: /* アスムプティオ */
- *opt3 &= ~2048;
- break;
- }
-
- if (night_flag == 1 && (*opt2 & STATE_BLIND) == 0 && bl->type == BL_PC && // by [Yor]
- !map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) { // [celest]
- *opt2 |= STATE_BLIND;
- opt_flag = 1;
- }
-
- if(opt_flag) /* optionの?更を?える */
- clif_changeoption(bl);
-
- if (bl->type == BL_PC && calc_flag)
- pc_calcstatus((struct map_session_data *)bl,0); /* ステ?タス再計算 */
- }
-
- return 0;
-}
-/*==========================================
- * ステ?タス異常終了タイマ?
- *------------------------------------------
- */
-int skill_status_change_timer(int tid, unsigned int tick, int id, int data)
-{
- int type=data;
- struct block_list *bl;
- struct map_session_data *sd=NULL;
- struct status_change *sc_data;
- //short *sc_count; //使ってない?
-
- if( (bl=map_id2bl(id)) == NULL )
- return 0; //該?IDがすでに消滅しているというのはいかにもありそうなのでスル?してみる
- nullpo_retr(0, sc_data=battle_get_sc_data(bl));
-
- if(bl->type==BL_PC)
- sd=(struct map_session_data *)bl;
-
- //sc_count=battle_get_sc_count(bl); //使ってない?
-
- if(sc_data[type].timer != tid) {
- if(battle_config.error_log)
- printf("skill_status_change_timer %d != %d\n",tid,sc_data[type].timer);
- }
-
- switch(type){ /* 特殊な?理になる場合 */
- case SC_MAXIMIZEPOWER: /* マキシマイズパワ? */
- case SC_CLOAKING:
- if(sd){
- if( sd->status.sp > 0 ){ /* SP切れるまで持? */
- sd->status.sp--;
- clif_updatestatus(sd,SP_SP);
- sc_data[type].timer=add_timer( /* タイマ?再設定 */
- sc_data[type].val2+tick, skill_status_change_timer, bl->id, data);
- return 0;
- }
- }
- break;
-
- case SC_CHASEWALK:
- if(sd){
- if( sd->status.sp > 19+sc_data[SC_CHASEWALK].val1*3){
- sd->status.sp-=(19+(sc_data[SC_CHASEWALK].val1*3)); // update sp cost [Celest]
- clif_updatestatus(sd,SP_SP);
- sc_data[type].timer=add_timer( /* タイマ?再設定 */
- sc_data[type].val2+tick, skill_status_change_timer, bl->id, data);
- return 0;
- }
- }
- break;
-
- case SC_HIDING: /* ハイディング */
- if(sd){ /* SPがあって、時間制限の間は持? */
- if( sd->status.sp > 0 && (--sc_data[type].val2)>0 ){
- if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){
- sd->status.sp--;
- clif_updatestatus(sd,SP_SP);
- }
- sc_data[type].timer=add_timer( /* タイマ?再設定 */
- 1000+tick, skill_status_change_timer,
- bl->id, data);
- return 0;
- }
- }
- break;
-
- case SC_SIGHT: /* サイト */
- {
- const int range=7;
- map_foreachinarea( skill_status_change_timer_sub,
- bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0,
- bl,type,tick);
-
- if( (--sc_data[type].val2)>0 ){
- sc_data[type].timer=add_timer( /* タイマ?再設定 */
- 250+tick, skill_status_change_timer,
- bl->id, data);
- return 0;
- }
- }
- break;
- case SC_RUWACH: /* ルアフ */
- {
- const int range=5;
- map_foreachinarea( skill_status_change_timer_sub,
- bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0,
- bl,type,tick);
-
- if( (--sc_data[type].val2)>0 ){
- sc_data[type].timer=add_timer( /* タイマ?再設定 */
- 250+tick, skill_status_change_timer,
- bl->id, data);
- return 0;
- }
- }
- break;
-
- case SC_SIGNUMCRUCIS: /* シグナムクルシス */
- {
- int race = battle_get_race(bl);
- if(race == 6 || battle_check_undead(race,battle_get_elem_type(bl))) {
- sc_data[type].timer=add_timer(1000*600+tick,skill_status_change_timer, bl->id, data );
- return 0;
- }
- }
- break;
-
- case SC_PROVOKE: /* プロボック/オ?トバ?サ?ク */
- if(sc_data[type].val2!=0){ /* オ?トバ?サ?ク(1秒ごとにHPチェック) */
- if(sd && sd->status.hp>sd->status.max_hp>>2) /* 停止 */
- break;
- sc_data[type].timer=add_timer( 1000+tick,skill_status_change_timer, bl->id, data );
- return 0;
- }
- break;
-
- case SC_WATERBALL: /* ウォ?タ?ボ?ル */
- {
- struct block_list *target=map_id2bl(sc_data[type].val2);
- if(target==NULL || target->prev==NULL)
- break;
- 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,skill_status_change_timer, bl->id, data );
- return 0;
- }
- }
- break;
-
- case SC_ENDURE: /* インデュア */
- if(sd && sd->special_state.infinite_endure) {
- sc_data[type].timer=add_timer( 1000*60+tick,skill_status_change_timer, bl->id, data );
- //sc_data[type].val2=1;
- return 0;
- }
- break;
-
- case SC_DISSONANCE: /* 不協和音 */
- if( (--sc_data[type].val2)>0){
- struct skill_unit *unit=
- (struct skill_unit *)sc_data[type].val4;
- struct block_list *src;
-
- if(!unit || !unit->group)
- break;
- src=map_id2bl(unit->group->src_id);
- if(!src)
- break;
- skill_attack(BF_MISC,src,&unit->bl,bl,unit->group->skill_id,sc_data[type].val1,tick,0);
- sc_data[type].timer=add_timer(skill_get_time2(unit->group->skill_id,unit->group->skill_lv)+tick,
- skill_status_change_timer, bl->id, data );
- return 0;
- }
- break;
-
- case SC_LULLABY: /* 子守唄 */
- if( (--sc_data[type].val2)>0){
- struct skill_unit *unit=
- (struct skill_unit *)sc_data[type].val4;
- if(!unit || !unit->group || unit->group->src_id==bl->id)
- break;
- skill_additional_effect(bl,bl,unit->group->skill_id,sc_data[type].val1,BF_LONG|BF_SKILL|BF_MISC,tick);
- sc_data[type].timer=add_timer(skill_get_time(unit->group->skill_id,unit->group->skill_lv)/10+tick,
- skill_status_change_timer, bl->id, data );
- return 0;
- }
- break;
-
- case SC_STONE:
- if(sc_data[type].val2 != 0) {
- short *opt1 = battle_get_opt1(bl);
- sc_data[type].val2 = 0;
- sc_data[type].val4 = 0;
- battle_stopwalking(bl,1);
- if(opt1) {
- *opt1 = 1;
- clif_changeoption(bl);
- }
- sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
- return 0;
- }
- else if( (--sc_data[type].val3) > 0) {
- int hp = battle_get_max_hp(bl);
- if((++sc_data[type].val4)%5 == 0 && battle_get_hp(bl) > hp>>2) {
- hp = hp/100;
- if(hp < 1) hp = 1;
- if(bl->type == BL_PC)
- pc_heal((struct map_session_data *)bl,-hp,0);
- else if(bl->type == BL_MOB){
- struct mob_data *md;
- if((md=((struct mob_data *)bl)) == NULL)
- break;
- md->hp -= hp;
- }
- }
- sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
- return 0;
- }
- break;
- case SC_POISON:
- if(sc_data[SC_SLOWPOISON].timer == -1) {
- if( (--sc_data[type].val3) > 0) {
- int hp = battle_get_max_hp(bl);
- if(battle_get_hp(bl) > hp>>2) {
- if(bl->type == BL_PC) {
- hp = 3 + hp*3/200;
- pc_heal((struct map_session_data *)bl,-hp,0);
- }
- else if(bl->type == BL_MOB) {
- struct mob_data *md;
- if((md=((struct mob_data *)bl)) == NULL)
- break;
- hp = 3 + hp/200;
- md->hp -= hp;
- }
- }
- sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
- }
- }
- else
- sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
- break;
- case SC_DPOISON:
- if (sc_data[SC_SLOWPOISON].timer == -1 && (--sc_data[type].val3) > 0) {
- int hp = battle_get_max_hp(bl);
- if (battle_get_hp(bl) > hp>>2) {
- if(bl->type == BL_PC) {
- hp = 3 + hp/50;
- pc_heal((struct map_session_data *)bl, -hp, 0);
- } else if (bl->type == BL_MOB) {
- struct mob_data *md;
- if ((md=((struct mob_data *)bl)) == NULL)
- break;
- hp = 3 + hp/100;
- md->hp -= hp;
- }
- }
- }
- if (sc_data[type].val3 > 0)
- sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
- break;
-
- case SC_TENSIONRELAX: /* テンションリラックス */
- if(sd){ /* SPがあって、HPが?タンでなければ?? */
- if( sd->status.sp > 12 && sd->status.max_hp > sd->status.hp ){
-/* if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){
- sd->status.sp -= 12;
- clif_updatestatus(sd,SP_SP);
- } */
- sc_data[type].timer=add_timer( /* タイマ?再設定 */
- 10000+tick, skill_status_change_timer,
- bl->id, data);
- return 0;
- }
- if(sd->status.max_hp <= sd->status.hp)
- skill_status_change_end(&sd->bl,SC_TENSIONRELAX,-1);
- }
- break;
- case SC_HEADCRUSH: // temporary damage [celest]
-// case SC_BLEEDING:
- if((--sc_data[type].val3) > 0) {
- int hp = battle_get_max_hp(bl);
- if(bl->type == BL_PC) {
- hp = 3 + hp*3/200;
- pc_heal((struct map_session_data *)bl,-hp,0);
- }
- else if(bl->type == BL_MOB) {
- struct mob_data *md;
- if((md=((struct mob_data *)bl)) == NULL)
- break;
- hp = 3 + hp/200;
- md->hp -= hp;
- }
- sc_data[type].timer=add_timer(1000+tick,skill_status_change_timer, bl->id, data );
- }
- break;
-
- /* 時間切れ無し?? */
- case SC_AETERNA:
- case SC_TRICKDEAD:
- case SC_RIDING:
- case SC_FALCON:
- case SC_WEIGHT50:
- case SC_WEIGHT90:
- case SC_MAGICPOWER: /* 魔法力?幅 */
- case SC_REJECTSWORD: /* リジェクトソ?ド */
- case SC_MEMORIZE: /* メモライズ */
- case SC_BROKNWEAPON:
- case SC_BROKNARMOR:
- if(sc_data[type].timer==tid)
- sc_data[type].timer=add_timer( 1000*600+tick,skill_status_change_timer, bl->id, data );
- return 0;
-
- case SC_DANCING: //ダンススキルの時間SP消費
- {
- int s=0;
- if(sd){
- if(sd->status.sp > 0 && (--sc_data[type].val3)>0){
- switch(sc_data[type].val1){
- case BD_RICHMANKIM: /* ニヨルドの宴 3秒にSP1 */
- case BD_DRUMBATTLEFIELD: /* ?太鼓の響き 3秒にSP1 */
- case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 3秒にSP1 */
- case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド 3秒にSP1 */
- case BA_DISSONANCE: /* 不協和音 3秒でSP1 */
- case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス 3秒でSP1 */
- case DC_UGLYDANCE: /* 自分勝手なダンス 3秒でSP1 */
- s=3;
- break;
- case BD_LULLABY: /* 子守歌 4秒にSP1 */
- case BD_ETERNALCHAOS: /* 永遠の混沌 4秒にSP1 */
- case BD_ROKISWEIL: /* ロキの叫び 4秒にSP1 */
- case DC_FORTUNEKISS: /* 幸運のキス 4秒でSP1 */
- s=4;
- break;
- case BD_INTOABYSS: /* 深淵の中に 5秒にSP1 */
- case BA_WHISTLE: /* 口笛 5秒でSP1 */
- case DC_HUMMING: /* ハミング 5秒でSP1 */
- case BA_POEMBRAGI: /* ブラギの詩 5秒でSP1 */
- case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? 5秒でSP1 */
- s=5;
- break;
- case BA_APPLEIDUN: /* イドゥンの林檎 6秒でSP1 */
- s=6;
- break;
- case DC_DONTFORGETME: /* 私を忘れないで… 10秒でSP1 */
- case CG_MOONLIT: /* 月明りの泉に落ちる花びら 10秒でSP1? */
- s=10;
- break;
- }
- if(s && ((sc_data[type].val3 % s) == 0)){
- sd->status.sp--;
- clif_updatestatus(sd,SP_SP);
- }
- sc_data[type].timer=add_timer( /* タイマ?再設定 */
- 1000+tick, skill_status_change_timer,
- bl->id, data);
- return 0;
- }
- }
- }
- break;
- case SC_BERSERK: /* バ?サ?ク */
- if(sd){ /* HPが100以上なら?? */
- if( (sd->status.hp - sd->status.max_hp*5/100) > 100 ){ // 5% every 10 seconds [DracoRPG]
- sd->status.hp -= sd->status.max_hp*5/100; // changed to max hp [celest]
- clif_updatestatus(sd,SP_HP);
- sc_data[type].timer = add_timer( /* タイマ?再設定 */
- 10000+tick, skill_status_change_timer,
- bl->id, data);
- return 0;
- }
- }
- break;
- case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
- if(sd){
- time_t timer;
- if(time(&timer) < ((sc_data[type].val2) + 3600)){ //1時間たっていないので??
- sc_data[type].timer=add_timer( /* タイマ?再設定 */
- 10000+tick, skill_status_change_timer,
- bl->id, data);
- return 0;
- }
- }
- break;
- case SC_NOCHAT: //チャット禁止?態
- if(sd && battle_config.muting_players){
- time_t timer;
- if((++sd->status.manner) && time(&timer) < ((sc_data[type].val2) + 60*(0-sd->status.manner))){ //開始からstatus.manner分?ってないので??
- clif_updatestatus(sd,SP_MANNER);
- sc_data[type].timer=add_timer( /* タイマ?再設定(60秒) */
- 60000+tick, skill_status_change_timer,
- bl->id, data);
- return 0;
- }
- }
- break;
- case SC_SELFDESTRUCTION: /* 自爆 */
- if(--sc_data[type].val3>0){
- struct mob_data *md;
- if(bl->type==BL_MOB && (md=(struct mob_data *)bl) && md->speed > 250){
- md->speed -= 250;
- md->next_walktime=tick;
- }
- sc_data[type].timer=add_timer( /* タイマ?再設定 */
- 1000+tick, skill_status_change_timer,
- bl->id, data);
- return 0;
- }
- break;
- case SC_LEADERSHIP:
- case SC_GLORYWOUNDS:
- case SC_SOULCOLD:
- case SC_HAWKEYES:
- if (sd) {
- sc_data[type].timer = add_timer(
- 1000+tick, skill_status_change_timer,
- bl->id, data);
- }
- break;
- }
-
-
-
- return skill_status_change_end( bl,type,tid );
-}
/*==========================================
* ステ?タス異常終了
*------------------------------------------
*/
-int skill_encchant_eremental_end(struct block_list *bl,int type)
+int skill_enchant_elemental_end (struct block_list *bl, int type)
{
struct status_change *sc_data;
nullpo_retr(0, bl);
- nullpo_retr(0, sc_data=battle_get_sc_data(bl));
-
- if( type!=SC_ENCPOISON && sc_data[SC_ENCPOISON].timer!=-1 ) /* エンチャントポイズン解除 */
- skill_status_change_end(bl,SC_ENCPOISON,-1);
- if( type!=SC_ASPERSIO && sc_data[SC_ASPERSIO].timer!=-1 ) /* アスペルシオ解除 */
- skill_status_change_end(bl,SC_ASPERSIO,-1);
- if( type!=SC_FLAMELAUNCHER && sc_data[SC_FLAMELAUNCHER].timer!=-1 ) /* フレイムランチャ解除 */
- skill_status_change_end(bl,SC_FLAMELAUNCHER,-1);
- if( type!=SC_FROSTWEAPON && sc_data[SC_FROSTWEAPON].timer!=-1 ) /* フロストウェポン解除 */
- skill_status_change_end(bl,SC_FROSTWEAPON,-1);
- if( type!=SC_LIGHTNINGLOADER && sc_data[SC_LIGHTNINGLOADER].timer!=-1 ) /* ライトニングロ?ダ?解除 */
- skill_status_change_end(bl,SC_LIGHTNINGLOADER,-1);
- if( type!=SC_SEISMICWEAPON && sc_data[SC_SEISMICWEAPON].timer!=-1 ) /* サイスミックウェポン解除 */
- skill_status_change_end(bl,SC_SEISMICWEAPON,-1);
+ nullpo_retr(0, sc_data = status_get_sc_data(bl));
+
+ if (type != SC_ENCPOISON && sc_data[SC_ENCPOISON].timer != -1) /* エンチャントポイズン解除 */
+ status_change_end(bl, SC_ENCPOISON, -1);
+ if (type != SC_ASPERSIO && sc_data[SC_ASPERSIO].timer != -1) /* アスペルシオ解除 */
+ status_change_end(bl, SC_ASPERSIO, -1);
+ if (type != SC_FLAMELAUNCHER && sc_data[SC_FLAMELAUNCHER].timer != -1) /* フレイムランチャ解除 */
+ status_change_end(bl, SC_FLAMELAUNCHER, -1);
+ if (type != SC_FROSTWEAPON && sc_data[SC_FROSTWEAPON].timer != -1) /* フロストウェポン解除 */
+ status_change_end(bl, SC_FROSTWEAPON, -1);
+ if (type != SC_LIGHTNINGLOADER && sc_data[SC_LIGHTNINGLOADER].timer != -1) /* ライトニングロ?ダ?解除 */
+ status_change_end(bl, SC_LIGHTNINGLOADER, -1);
+ if (type != SC_SEISMICWEAPON && sc_data[SC_SEISMICWEAPON].timer != -1) /* サイスミックウェポン解除 */
+ status_change_end(bl, SC_SEISMICWEAPON, -1);
return 0;
}
-/*==========================================
- * ステ?タス異常開始
- *------------------------------------------
- */
-int skill_status_change_start(struct block_list *bl, int type, int val1, int val2, int val3, int val4, int tick, int flag)
+
+/* クロ?キング?査(周りに移動不可能地?があるか) */
+int skill_check_cloaking(struct block_list *bl)
{
struct map_session_data *sd = NULL;
- struct status_change* sc_data;
- short *sc_count, *option, *opt1, *opt2, *opt3;
- int opt_flag = 0, calc_flag = 0,updateflag = 0, save_flag = 0, race, mode, elem, undead_flag;
- int scdef=0;
-
- nullpo_retr(0, bl);
- if(bl->type == BL_SKILL)
- return 0;
- nullpo_retr(0, sc_data=battle_get_sc_data(bl));
- nullpo_retr(0, sc_count=battle_get_sc_count(bl));
- nullpo_retr(0, option=battle_get_option(bl));
- nullpo_retr(0, opt1=battle_get_opt1(bl));
- nullpo_retr(0, opt2=battle_get_opt2(bl));
- nullpo_retr(0, opt3=battle_get_opt3(bl));
-
-
- race=battle_get_race(bl);
- mode=battle_get_mode(bl);
- elem=battle_get_elem_type(bl);
- undead_flag=battle_check_undead(race,elem);
-
- if(type == SC_AETERNA && (sc_data[SC_STONE].timer != -1 || sc_data[SC_FREEZE].timer != -1) )
- return 0;
-
- switch(type){
- case SC_STONE:
- case SC_FREEZE:
- scdef=3+battle_get_mdef(bl)+battle_get_luk(bl)/3;
- break;
- case SC_STAN:
- case SC_SILENCE:
- case SC_POISON:
- case SC_DPOISON:
- scdef=3+battle_get_vit(bl)+battle_get_luk(bl)/3;
- break;
- case SC_SLEEP:
- case SC_BLIND:
- scdef=3+battle_get_int(bl)+battle_get_luk(bl)/3;
- break;
- case SC_CURSE:
- scdef=3+battle_get_luk(bl);
- break;
-
-// case SC_CONFUSION:
- default:
- scdef=0;
- }
- if(scdef>=100)
- return 0;
- if(bl->type==BL_PC){
- sd=(struct map_session_data *)bl;
- if( sd && type == SC_ADRENALINE && !(skill_get_weapontype(BS_ADRENALINE)&(1<<sd->status.weapon)))
- return 0;
-
- if(SC_STONE<=type && type<=SC_BLIND){ /* カ?ドによる耐性 */
- if( sd && sd->reseff[type-SC_STONE] > 0 && rand()%10000<sd->reseff[type-SC_STONE]){
- if(battle_config.battle_log)
- printf("PC %d skill_sc_start: cardによる異常耐性?動\n",sd->bl.id);
- return 0;
- }
- }
- }
- else if(bl->type == BL_MOB) {
- }
- else {
- if(battle_config.error_log)
- printf("skill_status_change_start: neither MOB nor PC !\n");
- return 0;
- }
-
- if(type==SC_FREEZE && undead_flag && !(flag&1))
- return 0;
-
- if((type == SC_ADRENALINE || type == SC_WEAPONPERFECTION || type == SC_OVERTHRUST) &&
- sc_data[type].timer != -1 && sc_data[type].val2 && !val2)
- return 0;
-
- if(mode & 0x20 && (type==SC_STONE || type==SC_FREEZE ||
- type==SC_STAN || type==SC_SLEEP || type==SC_SILENCE || type==SC_QUAGMIRE || type == SC_DECREASEAGI || type == SC_SIGNUMCRUCIS || type == SC_PROVOKE ||
- (type == SC_BLESSING && (undead_flag || race == 6))) && !(flag&1)){
- /* ボスには?かない(ただしカ?ドによる?果は適用される) */
- return 0;
- }
- if(type==SC_FREEZE || type==SC_STAN || type==SC_SLEEP)
- battle_stopwalking(bl,1);
+ static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1}; //optimized by Lupus
+ static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1};
+ int end = 1,i;
- if(sc_data[type].timer != -1){ /* すでに同じ異常になっている場合タイマ解除 */
- if(sc_data[type].val1 > val1 && type != SC_COMBO && type != SC_DANCING && type != SC_DEVOTION &&
- type != SC_SPEEDPOTION0 && type != SC_SPEEDPOTION1 && type != SC_SPEEDPOTION2
- && type != SC_ATKPOT && type != SC_MATKPOT) // added atk and matk potions [Valaris]
- return 0;
- if(type >=SC_STAN && type <= SC_BLIND)
- return 0;/* ?ぎ足しができない?態異常である時は?態異常を行わない */
- if(type == SC_GRAFFITI){ //異常中にもう一度?態異常になった時に解除してから再度かかる
- skill_status_change_end(bl,type,-1);
- } else {
- (*sc_count)--;
- delete_timer(sc_data[type].timer, skill_status_change_timer);
- sc_data[type].timer = -1;
- }
- }
-
- switch(type){ /* 異常の種類ごとの?理 */
- case SC_PROVOKE: /* プロボック */
- calc_flag = 1;
- if(tick <= 0) tick = 1000; /* (オ?トバ?サ?ク) */
- break;
- case SC_ENDURE: /* インデュア */
- if(tick <= 0) tick = 1000 * 60;
- calc_flag = 1; // for updating mdef
- val2 = 7; // [Celest]
- break;
- case SC_CONCENTRATE: /* 集中力向上 */
- calc_flag = 1;
- break;
- case SC_BLESSING: /* ブレッシング */
- {
- if(bl->type == BL_PC || (!undead_flag && race != 6)) {
- if(sc_data[SC_CURSE].timer!=-1 )
- skill_status_change_end(bl,SC_CURSE,-1);
- if(sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2 == 0)
- skill_status_change_end(bl,SC_STONE,-1);
- }
- calc_flag = 1;
- }
- break;
- case SC_ANGELUS: /* アンゼルス */
- calc_flag = 1;
- break;
- case SC_INCREASEAGI: /* 速度上昇 */
- calc_flag = 1;
- if(sc_data[SC_DECREASEAGI].timer!=-1 )
- skill_status_change_end(bl,SC_DECREASEAGI,-1);
- if(sc_data[SC_WINDWALK].timer!=-1 ) /* ウインドウォ?ク */
- skill_status_change_end(bl,SC_WINDWALK,-1);
- break;
- case SC_DECREASEAGI: /* 速度減少 */
- if (bl->type == BL_PC) // Celest
- tick>>=1;
- calc_flag = 1;
- if(sc_data[SC_INCREASEAGI].timer!=-1 )
- skill_status_change_end(bl,SC_INCREASEAGI,-1);
- if(sc_data[SC_ADRENALINE].timer!=-1 )
- skill_status_change_end(bl,SC_ADRENALINE,-1);
- if(sc_data[SC_SPEARSQUICKEN].timer!=-1 )
- skill_status_change_end(bl,SC_SPEARSQUICKEN,-1);
- if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 )
- skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1);
- break;
- case SC_SIGNUMCRUCIS: /* シグナムクルシス */
- calc_flag = 1;
-// val2 = 14 + val1;
- val2 = 10 + val1*2;
- tick = 600*1000;
- clif_emotion(bl,4);
- break;
- case SC_SLOWPOISON:
- if (sc_data[SC_POISON].timer == -1 && sc_data[SC_DPOISON].timer == -1)
- return 0;
- break;
- case SC_TWOHANDQUICKEN: /* 2HQ */
- if(sc_data[SC_DECREASEAGI].timer!=-1)
- return 0;
- *opt3 |= 1;
- calc_flag = 1;
- break;
- case SC_ADRENALINE: /* アドレナリンラッシュ */
- if(sc_data[SC_DECREASEAGI].timer!=-1)
- return 0;
- calc_flag = 1;
- break;
- case SC_WEAPONPERFECTION: /* ウェポンパ?フェクション */
- if(battle_config.party_skill_penaly && !val2) tick /= 5;
- break;
- case SC_OVERTHRUST: /* オ?バ?スラスト */
- *opt3 |= 2;
- if(battle_config.party_skill_penaly && !val2) tick /= 10;
- break;
- case SC_MAXIMIZEPOWER: /* マキシマイズパワ?(SPが1減る時間,val2にも) */
- if(bl->type == BL_PC)
- val2 = tick;
- else
- tick = 5000*val1;
- break;
- case SC_ENCPOISON: /* エンチャントポイズン */
- calc_flag = 1;
- val2=(((val1 - 1) / 2) + 3)*100; /* 毒付?確率 */
- skill_encchant_eremental_end(bl,SC_ENCPOISON);
- break;
- case SC_EDP: // [Celest]
- val2 = val1 + 2; /* 猛毒付?確率(%) */
- calc_flag = 1;
- break;
- case SC_POISONREACT: /* ポイズンリアクト */
- val2=val1/2 + val1%2; // [Celest]
- break;
- case SC_IMPOSITIO: /* インポシティオマヌス */
- calc_flag = 1;
- break;
- case SC_ASPERSIO: /* アスペルシオ */
- skill_encchant_eremental_end(bl,SC_ASPERSIO);
- break;
- case SC_SUFFRAGIUM: /* サフラギム */
- case SC_BENEDICTIO: /* 聖? */
- case SC_MAGNIFICAT: /* マグニフィカ?ト */
- case SC_AETERNA: /* エ?テルナ */
- break;
- case SC_ENERGYCOAT: /* エナジ?コ?ト */
- *opt3 |= 4;
- break;
- case SC_MAGICROD:
- val2 = val1*20;
- break;
- case SC_KYRIE: /* キリエエレイソン */
- val2 = battle_get_max_hp(bl) * (val1 * 2 + 10) / 100;/* 耐久度 */
- val3 = (val1 / 2 + 5); /* 回? */
-// -- moonsoul (added to undo assumptio status if target has it)
- if(sc_data[SC_ASSUMPTIO].timer!=-1 )
- skill_status_change_end(bl,SC_ASSUMPTIO,-1);
- break;
- case SC_MINDBREAKER:
- calc_flag = 1;
- if(tick <= 0) tick = 1000; /* (オ?トバ?サ?ク) */
- case SC_GLORIA: /* グロリア */
- calc_flag = 1;
- break;
- case SC_LOUD: /* ラウドボイス */
- calc_flag = 1;
- break;
- case SC_TRICKDEAD: /* 死んだふり */
- break;
- case SC_QUAGMIRE: /* クァグマイア */
- calc_flag = 1;
- if(sc_data[SC_CONCENTRATE].timer!=-1 ) /* 集中力向上解除 */
- skill_status_change_end(bl,SC_CONCENTRATE,-1);
- if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* 速度上昇解除 */
- skill_status_change_end(bl,SC_INCREASEAGI,-1);
- if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 )
- skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1);
- if(sc_data[SC_SPEARSQUICKEN].timer!=-1 )
- skill_status_change_end(bl,SC_SPEARSQUICKEN,-1);
- if(sc_data[SC_ADRENALINE].timer!=-1 )
- skill_status_change_end(bl,SC_ADRENALINE,-1);
- if(sc_data[SC_LOUD].timer!=-1 )
- skill_status_change_end(bl,SC_LOUD,-1);
- if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* トゥル?サイト */
- skill_status_change_end(bl,SC_TRUESIGHT,-1);
- if(sc_data[SC_WINDWALK].timer!=-1 ) /* ウインドウォ?ク */
- skill_status_change_end(bl,SC_WINDWALK,-1);
- if(sc_data[SC_CARTBOOST].timer!=-1 ) /* カ?トブ?スト */
- skill_status_change_end(bl,SC_CARTBOOST,-1);
- break;
- case SC_FLAMELAUNCHER: /* フレ?ムランチャ? */
- skill_encchant_eremental_end(bl,SC_FLAMELAUNCHER);
- break;
- case SC_FROSTWEAPON: /* フロストウェポン */
- skill_encchant_eremental_end(bl,SC_FROSTWEAPON);
- break;
- case SC_LIGHTNINGLOADER: /* ライトニングロ?ダ? */
- skill_encchant_eremental_end(bl,SC_LIGHTNINGLOADER);
- break;
- case SC_SEISMICWEAPON: /* サイズミックウェポン */
- skill_encchant_eremental_end(bl,SC_SEISMICWEAPON);
- break;
- case SC_DEVOTION: /* ディボ?ション */
- calc_flag = 1;
- break;
- case SC_PROVIDENCE: /* プロヴィデンス */
- calc_flag = 1;
- val2=val1*5;
- break;
- case SC_REFLECTSHIELD:
- val2=10+val1*3;
- break;
- case SC_STRIPWEAPON:
- case SC_STRIPSHIELD:
- case SC_STRIPARMOR:
- case SC_STRIPHELM:
- case SC_CP_WEAPON:
- case SC_CP_SHIELD:
- case SC_CP_ARMOR:
- case SC_CP_HELM:
- break;
-
- case SC_AUTOSPELL: /* オ?トスペル */
- val4 = 5 + val1*2;
- break;
-
- case SC_VOLCANO:
- calc_flag = 1;
- val3 = val1*10;
- val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) );
- break;
- case SC_DELUGE:
- calc_flag = 1;
- val3 = val1>=5?15: (val1==4?14: (val1==3?12: ( val1==2?9:5 ) ) );
- val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) );
- break;
- case SC_VIOLENTGALE:
- calc_flag = 1;
- val3 = val1*3;
- val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) );
- break;
-
- case SC_SPEARSQUICKEN: /* スピアクイッケン */
- calc_flag = 1;
- val2 = 20+val1;
- *opt3 |= 1;
- break;
- case SC_COMBO:
- break;
- case SC_BLADESTOP_WAIT: /* 白刃取り(待ち) */
- break;
- case SC_BLADESTOP: /* 白刃取り */
- if(val2==2) clif_bladestop((struct block_list *)val3,(struct block_list *)val4,1);
- *opt3 |= 32;
- break;
-
- case SC_LULLABY: /* 子守唄 */
- val2 = 11;
- break;
- case SC_RICHMANKIM:
- break;
- case SC_ETERNALCHAOS: /* エタ?ナルカオス */
- calc_flag = 1;
- break;
- case SC_DRUMBATTLE: /* ?太鼓の響き */
- calc_flag = 1;
- val2 = (val1+1)*25;
- val3 = (val1+1)*2;
- break;
- case SC_NIBELUNGEN: /* ニ?ベルングの指輪 */
- calc_flag = 1;
- val2 = (val1+2)*50;
- val3 = (val1+2)*25;
- break;
- case SC_ROKISWEIL: /* ロキの叫び */
- break;
- case SC_INTOABYSS: /* 深淵の中に */
- break;
- case SC_SIEGFRIED: /* 不死身のジ?クフリ?ド */
- calc_flag = 1;
- val2 = 40 + val1*5;
- val3 = val1*10;
- break;
- case SC_DISSONANCE: /* 不協和音 */
- val2 = 10;
- break;
- case SC_WHISTLE: /* 口笛 */
- calc_flag = 1;
- break;
- case SC_ASSNCROS: /* 夕陽のアサシンクロス */
- calc_flag = 1;
- break;
- case SC_POEMBRAGI: /* ブラギの詩 */
- break;
- case SC_APPLEIDUN: /* イドゥンの林檎 */
- calc_flag = 1;
- break;
- case SC_UGLYDANCE: /* 自分勝手なダンス */
- val2 = 10;
- break;
- case SC_HUMMING: /* ハミング */
- calc_flag = 1;
- break;
- case SC_DONTFORGETME: /* 私を忘れないで */
- calc_flag = 1;
- if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* 速度上昇解除 */
- skill_status_change_end(bl,SC_INCREASEAGI,-1);
- if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 )
- skill_status_change_end(bl,SC_TWOHANDQUICKEN,-1);
- if(sc_data[SC_SPEARSQUICKEN].timer!=-1 )
- skill_status_change_end(bl,SC_SPEARSQUICKEN,-1);
- if(sc_data[SC_ADRENALINE].timer!=-1 )
- skill_status_change_end(bl,SC_ADRENALINE,-1);
- if(sc_data[SC_ASSNCROS].timer!=-1 )
- skill_status_change_end(bl,SC_ASSNCROS,-1);
- if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* トゥル?サイト */
- skill_status_change_end(bl,SC_TRUESIGHT,-1);
- if(sc_data[SC_WINDWALK].timer!=-1 ) /* ウインドウォ?ク */
- skill_status_change_end(bl,SC_WINDWALK,-1);
- if(sc_data[SC_CARTBOOST].timer!=-1 ) /* カ?トブ?スト */
- skill_status_change_end(bl,SC_CARTBOOST,-1);
- break;
- case SC_FORTUNE: /* 幸運のキス */
- calc_flag = 1;
- break;
- case SC_SERVICE4U: /* サ?ビスフォ?ユ? */
- calc_flag = 1;
- break;
- case SC_DANCING: /* ダンス/演奏中 */
- calc_flag = 1;
- val3= tick / 1000;
- tick = 1000;
- break;
-
- case SC_EXPLOSIONSPIRITS: // 爆裂波動
- calc_flag = 1;
- val2 = 75 + 25*val1;
- *opt3 |= 8;
- break;
- case SC_STEELBODY: // 金剛
- calc_flag = 1;
- *opt3 |= 16;
- break;
- case SC_EXTREMITYFIST: /* 阿修羅覇凰拳 */
- break;
- case SC_AUTOCOUNTER:
- val3 = val4 = 0;
- break;
-
- case SC_SPEEDPOTION0: /* ?速ポ?ション */
- case SC_SPEEDPOTION1:
- case SC_SPEEDPOTION2:
- calc_flag = 1;
- tick = 1000 * tick;
- val2 = 5*(2+type-SC_SPEEDPOTION0);
- break;
-
- /* atk & matk potions [Valaris] */
- case SC_ATKPOT:
- case SC_MATKPOT:
- calc_flag = 1;
- tick = 1000 * tick;
- break;
- case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
- {
- time_t timer;
-
- calc_flag = 1;
- tick = 10000;
- if(!val2)
- val2 = time(&timer);
- }
- break;
- case SC_NOCHAT: //チャット禁止?態
- {
- time_t timer;
-
- if(!battle_config.muting_players)
- break;
-
- tick = 60000;
- if(!val2)
- val2 = time(&timer);
- updateflag = SP_MANNER;
- save_flag = 1; // celest
- }
- break;
- case SC_SELFDESTRUCTION: //自爆
- clif_skillcasting(bl,bl->id, bl->id,0,0,331,skill_get_time(val2,val1));
- val3 = tick / 1000;
- tick = 1000;
- break;
-
- /* option1 */
- case SC_STONE: /* 石化 */
- if(!(flag&2)) {
- int sc_def = battle_get_mdef(bl)*200;
- tick = tick - sc_def;
- }
- val3 = tick/1000;
- if(val3 < 1) val3 = 1;
- tick = 5000;
- val2 = 1;
- break;
- case SC_SLEEP: /* 睡眠 */
- if(!(flag&2)) {
-// int sc_def = 100 - (battle_get_int(bl) + battle_get_luk(bl)/3);
-// tick = tick * sc_def / 100;
-// if(tick < 1000) tick = 1000;
- tick = 30000;//睡眠はステ?タス耐性に?わらず30秒
- }
- break;
- case SC_FREEZE: /* 凍結 */
- if(!(flag&2)) {
- int sc_def = 100 - battle_get_mdef(bl);
- tick = tick * sc_def / 100;
- }
- break;
- case SC_STAN: /* スタン(val2にミリ秒セット) */
- if(!(flag&2)) {
- int sc_def = 100 - (battle_get_vit(bl) + battle_get_luk(bl)/3);
- tick = tick * sc_def / 100;
- }
- break;
-
- /* option2 */
- case SC_POISON: /* 毒 */
- case SC_DPOISON: /* 猛毒 */
- calc_flag = 1;
- if(!(flag&2)) {
- int sc_def = 100 - (battle_get_vit(bl) + battle_get_luk(bl)/5);
- tick = tick * sc_def / 100;
- }
- val3 = tick/1000;
- if(val3 < 1) val3 = 1;
- tick = 1000;
- break;
- case SC_SILENCE: /* 沈?(レックスデビ?ナ) */
- if(!(flag&2)) {
- int sc_def = 100 - battle_get_vit(bl);
- tick = tick * sc_def / 100;
- }
- break;
- case SC_BLIND: /* 暗? */
- calc_flag = 1;
- if(!(flag&2)) {
- int sc_def = battle_get_lv(bl)/10 + battle_get_int(bl)/15;
- tick = 30000 - sc_def;
- }
- break;
- case SC_CURSE:
- calc_flag = 1;
- if(!(flag&2)) {
- int sc_def = 100 - battle_get_vit(bl);
- tick = tick * sc_def / 100;
- }
- break;
-
- /* option */
- case SC_HIDING: /* ハイディング */
- calc_flag = 1;
- if(bl->type == BL_PC) {
- val2 = tick / 1000; /* 持?時間 */
- tick = 1000;
- }
- break;
- case SC_CHASEWALK:
- case SC_CLOAKING: /* クロ?キング */
- if(bl->type == BL_PC) {
- calc_flag = 1; // [Celest]
- val2 = tick;
- val3 = type==SC_CLOAKING ? 130-val1*3 : 135-val1*5;
- }
- else
- tick = 5000*val1;
- break;
- case SC_SIGHT: /* サイト/ルアフ */
- case SC_RUWACH:
- val2 = tick/250;
- tick = 10;
- break;
-
- /* セ?フティウォ?ル、ニュ?マ */
- case SC_SAFETYWALL: case SC_PNEUMA:
- tick=((struct skill_unit *)val2)->group->limit;
- break;
-
- /* アンクル */
- 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;
- tick = 600*1000;
- break;
- case SC_FALCON:
- case SC_WEIGHT50:
- case SC_WEIGHT90:
- case SC_BROKNWEAPON:
- case SC_BROKNARMOR:
- tick=600*1000;
- break;
-
- case SC_AUTOGUARD:
- {
- int i,t;
- for(i=val2=0;i<val1;i++) {
- t = 5-(i>>1);
- val2 += (t < 0)? 1:t;
- }
- }
- break;
-
- case SC_DEFENDER:
- calc_flag = 1;
- val2 = 5 + val1*15;
- break;
-
- case SC_KEEPING:
- case SC_BARRIER:
- calc_flag = 1;
-
- case SC_HALLUCINATION:
- break;
-
- case SC_CONCENTRATION: /* コンセントレ?ション */
- *opt3 |= 1;
- calc_flag = 1;
- break;
-
- case SC_TENSIONRELAX: /* テンションリラックス */
- calc_flag = 1;
- if(bl->type == BL_PC) {
- tick = 10000;
- }
- break;
-
- case SC_AURABLADE: /* オ?ラブレ?ド */
- case SC_PARRYING: /* パリイング */
-// case SC_ASSUMPTIO: /* */
- case SC_HEADCRUSH: /* ヘッドクラッシュ */
- case SC_JOINTBEAT: /* ジョイントビ?ト */
-// case SC_MARIONETTE: /* マリオネットコントロ?ル */
-
- //とりあえず手?き
- break;
-
-// -- moonsoul (for new upper class related skill status effects)
-/*
- case SC_AURABLADE:
- val2 = val1*10;
- break;
- case SC_PARRYING:
- val2=val1*3;
- break;
- case SC_CONCENTRATION:
- calc_flag=1;
- val2=val1*10;
- val3=val1*5;
- break;
- case SC_TENSIONRELAX:
-// val2 = 10;
-// val3 = 15;
- break;
- case SC_BERSERK:
- calc_flag=1;
- break;
- case SC_ASSUMPTIO:
- if(sc_data[SC_KYRIE].timer!=-1 )
- skill_status_change_end(bl,SC_KYRIE,-1);
- break;
-*/
- case SC_WINDWALK: /* ウインドウォ?ク */
- calc_flag = 1;
- val2 = (val1 / 2); //Flee上昇率
- break;
-
- case SC_BERSERK: /* バ?サ?ク */
- if(sd){
- sd->status.hp = sd->status.max_hp * 3;
- sd->status.sp = 0;
- clif_updatestatus(sd,SP_HP);
- clif_updatestatus(sd,SP_SP);
- clif_status_change(bl,SC_INCREASEAGI,1); /* アイコン表示 */
- }
- *opt3 |= 128;
- tick = 10000;
- calc_flag = 1;
- break;
-
- case SC_ASSUMPTIO: /* アスムプティオ */
- *opt3 |= 2048;
- break;
-
- case SC_BASILICA: // [celest]
- break;
-
- case SC_MARIONETTE: /* マリオネットコントロ?ル */
- case SC_MARIONETTE2:
- calc_flag = 1;
- *opt3 |= 1024;
- break;
-
- case SC_MELTDOWN: /* メルトダウン */
- case SC_CARTBOOST: /* カ?トブ?スト */
- case SC_TRUESIGHT: /* トゥル?サイト */
- case SC_SPIDERWEB: /* スパイダ?ウェッブ */
- case SC_MAGICPOWER: /* 魔法力?幅 */
- calc_flag = 1;
- break;
-
- case SC_REJECTSWORD: /* リジェクトソ?ド */
- val2 = 3; //3回攻?を跳ね返す
- break;
-
- case SC_MEMORIZE: /* メモライズ */
- val2 = 3; //3回詠唱を1/3にする
- break;
-
- case SC_GRAFFITI: /* グラフィティ */
- {
- struct skill_unit_group *sg = skill_unitsetting(bl,RG_GRAFFITI,val1,val2,val3,0);
- if(sg)
- val4 = (int)sg;
- }
- break;
-
- case SC_SPLASHER: /* ベナムスプラッシャ? */
- break;
-
- case SC_FOGWALL:
- val2 = 75;
- // calc_flag = 1; // not sure of effects yet [celest]
- break;
-
- case SC_BLOCKSKILL:
- if (!tick) tick = 60000;
- if (!val3) val3 = -1;
- break;
-
- case SC_SLOWDOWN:
- calc_flag = 1;
- break;
-
- case SC_LEADERSHIP:
- case SC_GLORYWOUNDS:
- case SC_SOULCOLD:
- case SC_HAWKEYES:
- tick = 1000;
- calc_flag = 1;
- //val4 = 1;
- break;
-
- case SC_REGENERATION:
- val1 = 2;
- case SC_BATTLEORDERS:
- tick = 60000; // 1 minute
- calc_flag = 1;
- break;
+ nullpo_retr(1, bl);
- default:
- if(battle_config.error_log)
- printf("UnknownStatusChange [%d]\n", type);
+ if (bl->type == BL_PC) {
+ nullpo_retr(1, sd = (struct map_session_data *)bl);
+ if (!battle_config.pc_cloak_check_type) // If it's No it shouldn't be checked
return 0;
- }
-
- if(bl->type==BL_PC && type<SC_SENDMAX)
- clif_status_change(bl,type,1); /* アイコン表示 */
-
- /* optionの?更 */
- switch(type){
- case SC_STONE:
- case SC_FREEZE:
- case SC_STAN:
- case SC_SLEEP:
- battle_stopattack(bl); /* 攻?停止 */
- skill_stop_dancing(bl,0); /* 演奏/ダンスの中? */
- { /* 同時に掛からないステ?タス異常を解除 */
- int i;
- for(i = SC_STONE; i <= SC_SLEEP; i++){
- if(sc_data[i].timer != -1){
- (*sc_count)--;
- delete_timer(sc_data[i].timer, skill_status_change_timer);
- sc_data[i].timer = -1;
- }
- }
- }
- if(type == SC_STONE)
- *opt1 = 6;
- else
- *opt1 = type - SC_STONE + 1;
- opt_flag = 1;
- break;
- case SC_POISON:
- case SC_CURSE:
- case SC_SILENCE:
- case SC_BLIND:
- *opt2 |= 1<<(type-SC_POISON);
- opt_flag = 1;
- break;
- case SC_DPOISON: // 暫定で毒のエフェクトを使用
- *opt2 |= 1;
- opt_flag = 1;
- break;
- case SC_SIGNUMCRUCIS:
- *opt2 |= 0x40;
- opt_flag = 1;
- break;
- case SC_HIDING:
- case SC_CLOAKING:
- battle_stopattack(bl); /* 攻?停止 */
- *option |= ((type==SC_HIDING)?2:4);
- opt_flag =1 ;
- break;
- case SC_CHASEWALK:
- battle_stopattack(bl); /* 攻?停止 */
- *option |= 16388;
- opt_flag =1 ;
- break;
- case SC_SIGHT:
- *option |= 1;
- opt_flag = 1;
- break;
- case SC_RUWACH:
- *option |= 8192;
- opt_flag = 1;
- break;
- case SC_WEDDING:
- *option |= 4096;
- opt_flag = 1;
- }
-
- if(opt_flag) /* optionの?更 */
- clif_changeoption(bl);
-
- (*sc_count)++; /* ステ?タス異常の? */
-
- sc_data[type].val1 = val1;
- sc_data[type].val2 = val2;
- sc_data[type].val3 = val3;
- sc_data[type].val4 = val4;
- /* タイマ?設定 */
- sc_data[type].timer = add_timer(
- gettick() + tick, skill_status_change_timer, bl->id, type);
-
- if(bl->type==BL_PC && calc_flag)
- pc_calcstatus(sd,0); /* ステ?タス再計算 */
-
- if(bl->type==BL_PC && save_flag)
- chrif_save(sd); // save the player status
-
- if(bl->type==BL_PC && updateflag)
- clif_updatestatus(sd,updateflag); /* ステ?タスをクライアントに送る */
-
- return 0;
-}
-/*==========================================
- * ステ?タス異常全解除
- *------------------------------------------
- */
-int skill_status_change_clear(struct block_list *bl, int type)
-{
- struct status_change* sc_data;
- short *sc_count, *option, *opt1, *opt2, *opt3;
- int i;
-
- nullpo_retr(0, bl);
- nullpo_retr(0, sc_data = battle_get_sc_data(bl));
- nullpo_retr(0, sc_count = battle_get_sc_count(bl));
- nullpo_retr(0, option = battle_get_option(bl));
- nullpo_retr(0, opt1 = battle_get_opt1(bl));
- nullpo_retr(0, opt2 = battle_get_opt2(bl));
- nullpo_retr(0, opt3 = battle_get_opt3(bl));
-
- if (*sc_count == 0)
+ } else if (bl->type == BL_MOB && !battle_config.monster_cloak_check_type)
return 0;
- for(i = 0; i < MAX_STATUSCHANGE; i++){
- if(sc_data[i].timer != -1){ /* 異常があるならタイマ?を削除する */
-/*
- delete_timer(sc_data[i].timer, skill_status_change_timer);
- sc_data[i].timer = -1;
-
- if (!type && i < SC_SENDMAX)
- clif_status_change(bl, i, 0);
-*/
-
- skill_status_change_end(bl, i, -1);
- }
- }
- *sc_count = 0;
- *opt1 = 0;
- *opt2 = 0;
- *opt3 = 0;
- *option &= OPTION_MASK;
-
- if (night_flag == 1 && type == BL_PC && !map[bl->m].flag.indoors && // by [Yor]
- !map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) // [celest]
- *opt2 |= STATE_BLIND;
- if(!type || type&2)
- clif_changeoption(bl);
-
- return 0;
-}
-
-/* クロ?キング?査(周りに移動不可能地?があるか) */
-int skill_check_cloaking(struct block_list *bl)
-{
- static int dx[]={ 0, 1, 0, -1, -1, 1, 1, -1}; //optimized by Lupus
- static int dy[]={-1, 0, 1, 0, -1, -1, 1, 1};
- int end=1,i;
-
- //missing sd [Found by Celest, commited by Aria]
- struct map_session_data *sd=(struct map_session_data *)bl;
-
- nullpo_retr(0, bl);
-
- if(bl->type == BL_PC && !battle_config.pc_cloak_check_type) // If it's No it shouldn't be checked
- return 0;
- else if(bl->type == BL_MOB && !battle_config.monster_cloak_check_type)
- return 0;
- for(i=0;i<sizeof(dx)/sizeof(dx[0]);i++){
- int c=map_getcell(bl->m,bl->x+dx[i],bl->y+dy[i]);
- if(c==1 || c==5) {
- end=0;
+ for (i = 0; i < 8; i++) {
+ if (map_getcell(bl->m, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS)) {
+ end = 0;
break;
}
}
if(end){
- if ((bl->type == BL_PC && pc_checkskill(sd,AS_CLOAKING)<3) || bl->type == BL_MOB) {
- skill_status_change_end(bl, SC_CLOAKING, -1);
- *battle_get_option(bl)&=~4; /* 念のための?理 */
+ if ((sd && pc_checkskill(sd,AS_CLOAKING)<3) || bl->type == BL_MOB) {
+ status_change_end(bl, SC_CLOAKING, -1);
}
- else if (bl->type == BL_PC && sd->sc_data[SC_CLOAKING].val3 != 130) {
+ else if (sd && sd->sc_data[SC_CLOAKING].val3 != 130) {
sd->sc_data[SC_CLOAKING].val3 = 130;
- pc_calcspeed (sd);
+ status_calc_speed (sd);
}
}
else {
- if (bl->type == BL_PC && sd->sc_data[SC_CLOAKING].val3 != 103) {
+ if (sd && sd->sc_data[SC_CLOAKING].val3 != 103) {
sd->sc_data[SC_CLOAKING].val3 = 103;
- pc_calcspeed (sd);
+ status_calc_speed (sd);
}
}
- return end;
-}
-int skill_type_cloaking(struct block_list *bl)
-{
- static int dx[]={ 0, 1, 0, -1, -1, 1, 1, -1}; //optimized by Lupus
- static int dy[]={-1, 0, 1, 0, -1, -1, 1, 1};
- int i;
-
- nullpo_retr(0, bl);
- if(bl->type == BL_PC && battle_config.pc_cloak_check_type&1)
- return 0;
- else if(bl->type == BL_MOB && battle_config.monster_cloak_check_type&1)
- return 0;
- for(i=0; i<sizeof(dx)/sizeof(dx[0]); i++)
- {
- int c=map_getcell(bl->m,bl->x+dx[i],bl->y+dy[i]);
- if(c==1 || c==5)
- return 0;
- }
- return 1;
+ return end;
}
/*
@@ -10018,48 +8096,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で合奏中なら相方にユニットを任せる
*
@@ -10069,47 +8105,47 @@ void skill_stop_dancing(struct block_list *src, int flag)
{
struct status_change* sc_data;
struct skill_unit_group* group;
+ short* sc_count;
nullpo_retv(src);
-
- sc_data=battle_get_sc_data(src);
- if(sc_data && sc_data[SC_DANCING].timer != -1) {
- group=(struct skill_unit_group *)sc_data[SC_DANCING].val2; //ダンスのスキルユニットIDはval2に入ってる
- if(group && src->type==BL_PC && sc_data && sc_data[SC_DANCING].val4){ //合奏中?
- struct map_session_data* dsd=map_id2sd(sc_data[SC_DANCING].val4); //相方のsd取得
- if(flag){ //ログアウトなど片方が落ちても演奏が??される
- if(dsd && src->id == group->src_id){ //グル?プを持ってるPCが落ちる
- group->src_id=sc_data[SC_DANCING].val4; //相方にグル?プを任せる
- if(flag&1) //ログアウト
- dsd->sc_data[SC_DANCING].val4=0; //相方の相方を0にして合奏終了→通常のダンス?態
- if(flag&2) //ハエ飛びなど
- return; //合奏もダンス?態も終了させない&スキルユニットは置いてけぼり
- }else if(dsd && dsd->bl.id == group->src_id){ //相方がグル?プを持っているPCが落ちる(自分はグル?プを持っていない)
- if(flag&1) //ログアウト
- dsd->sc_data[SC_DANCING].val4=0; //相方の相方を0にして合奏終了→通常のダンス?態
- if(flag&2) //ハエ飛びなど
- return; //合奏もダンス?態も終了させない&スキルユニットは置いてけぼり
+ nullpo_retv(sc_data = status_get_sc_data(src));
+ nullpo_retv(sc_count = status_get_sc_count(src));
+
+ if((*sc_count) > 0 && sc_data[SC_DANCING].timer != -1) {
+ group = (struct skill_unit_group *)sc_data[SC_DANCING].val2; //ダンスのスキルユニットIDはval2に入ってる
+ if (src->type == BL_PC) {
+ if (group && sc_data[SC_DANCING].val4){ //合奏中?
+ struct map_session_data* dsd = map_id2sd(sc_data[SC_DANCING].val4); //相方のsd取得
+ if (flag && dsd) { //ログアウトなど片方が落ちても演奏が??される
+ if (src->id == group->src_id) { //グル?プを持ってるPCが落ちる
+ group->src_id = sc_data[SC_DANCING].val4; //相方にグル?プを任せる
+ if (flag & 1) //ログアウト
+ dsd->sc_data[SC_DANCING].val4 = 0; //相方の相方を0にして合奏終了→通常のダンス?態
+ if(flag & 2) //ハエ飛びなど
+ return; //合奏もダンス?態も終了させない&スキルユニットは置いてけぼり
+ } else if (dsd->bl.id == group->src_id) { //相方がグル?プを持っているPCが落ちる(自分はグル?プを持っていない)
+ if (flag & 1) //ログアウト
+ dsd->sc_data[SC_DANCING].val4 = 0; //相方の相方を0にして合奏終了→通常のダンス?態
+ if(flag & 2) //ハエ飛びなど
+ return; //合奏もダンス?態も終了させない&スキルユニットは置いてけぼり
+ }
+ status_change_end(src, SC_DANCING, -1); //自分のステ?タスを終了させる
+ //そしてグル?プは消さない&消さないのでステ?タス計算もいらない?
+ return;
+ } else if (dsd) {
+ if (src->id == group->src_id) //グル?プを持ってるPCが止める
+ status_change_end(&dsd->bl, SC_DANCING, -1); //相手のステ?タスを終了させる
+ if(dsd->bl.id == group->src_id) //相方がグル?プを持っているPCが止める(自分はグル?プを持っていない)
+ status_change_end(src, SC_DANCING, -1); //自分のステ?タスを終了させる
}
- skill_status_change_end(src,SC_DANCING,-1);//自分のステ?タスを終了させる
- //そしてグル?プは消さない&消さないのでステ?タス計算もいらない?
+ }
+ if(flag & 2 && group) { //ハエで飛んだときとかはユニットも飛ぶ
+ struct map_session_data *sd = (struct map_session_data *)src;
+ if (sd) skill_unit_move_unit_group(group, sd->bl.m, (sd->to_x - sd->bl.x), (sd->to_y - sd->bl.y));
return;
- }else{
- if(dsd && src->id == group->src_id){ //グル?プを持ってるPCが止める
- skill_status_change_end((struct block_list *)dsd,SC_DANCING,-1);//相手のステ?タスを終了させる
- }
- if(dsd && dsd->bl.id == group->src_id){ //相方がグル?プを持っているPCが止める(自分はグル?プを持っていない)
- skill_status_change_end(src,SC_DANCING,-1);//自分のステ?タスを終了させる
- }
}
}
- if(flag&2 && group && src->type==BL_PC){ //ハエで飛んだときとかはユニットも飛ぶ
- struct map_session_data *sd = (struct map_session_data *)src;
- skill_unit_move_unit_group(group, sd->bl.m,(sd->to_x - sd->bl.x),(sd->to_y - sd->bl.y));
- return;
- }
skill_delunitgroup(group);
- if(src->type==BL_PC)
- pc_calcstatus((struct map_session_data *)src,0);
}
}
@@ -10138,10 +8174,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 );
/*==========================================
* スキルユニット削除
*------------------------------------------
@@ -10149,7 +8188,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)
@@ -10159,11 +8197,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);
@@ -10179,7 +8221,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)
{
@@ -10227,11 +8269,11 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src,
}
group->src_id=src->id;
- group->party_id=battle_get_party_id(src);
- group->guild_id=battle_get_guild_id(src);
+ group->party_id=status_get_party_id(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;
@@ -10239,39 +8281,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;
}
- skill_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);
- }
- }
+ status_change_start(src,SC_DANCING,skillid,(int)group,0,0,skill_get_time(skillid,skilllv)+1000,0);
+ //合奏スキルは相方をダンス状態にする
+ 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;
@@ -10291,10 +8317,16 @@ int skill_delunitgroup(struct skill_unit_group *group)
return 0;
src=map_id2bl(group->src_id);
- if( skill_is_danceskill(group->skill_id) ){ //ダンススキルはダンス?態を解除する
- if(src)
- skill_status_change_end(src,SC_DANCING,-1);
+ //ダンススキルはダンス状態を解除する
+ if(src) {
+ if (skill_get_unit_flag(group->skill_id)&UF_DANCE)
+ status_change_end(src,SC_DANCING,-1);
+ if (group->unit_id == 0x86) {
+ struct status_change *sc_data = status_get_sc_data(src);
+ if(sc_data && sc_data[SC_MAGICPOWER].timer != -1) //マジックパワ?の?果終了
+ status_change_end(src,SC_MAGICPOWER,-1);
}
+ }
group->alive_count=0;
if(group->unit!=NULL){
@@ -10307,7 +8339,7 @@ int skill_delunitgroup(struct skill_unit_group *group)
group->valstr=NULL;
}
- map_freeblock(group->unit); /* free()の替わり */
+ map_freeblock(group->unit); /* aFree()の替わり */
group->unit=NULL;
group->src_id=0;
group->group_id=0;
@@ -10329,13 +8361,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++)
@@ -10350,54 +8383,46 @@ int skill_clear_unitgroup(struct block_list *src)
*------------------------------------------
*/
struct skill_unit_group_tickset *skill_unitgrouptickset_search(
- struct block_list *bl,int group_id)
+ struct block_list *bl,struct skill_unit_group *group,int tick)
{
- int i,j=0,k,s=group_id%MAX_SKILLUNITGROUPTICKSET;
- struct skill_unit_group_tickset *set=NULL;
+ 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;
- }else{
- set=((struct mob_data *)bl)->skillunittick;
- }
- if(set==NULL)
+ 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;
- for(i=0;i<MAX_SKILLUNITGROUPTICKSET;i++)
- if( set[(k=(i+s)%MAX_SKILLUNITGROUPTICKSET)].group_id == group_id )
- return &set[k];
- else if( set[k].group_id==0 )
- j=k;
- return &set[j];
-}
-
-/*==========================================
- * スキルユニットグル?プの被影響tick削除
- *------------------------------------------
- */
-int skill_unitgrouptickset_delete(struct block_list *bl,int group_id)
-{
- int i,s=group_id%MAX_SKILLUNITGROUPTICKSET;
- struct skill_unit_group_tickset *set=NULL,*ts;
-
- nullpo_retr(0, bl);
+ if (skill_get_unit_flag(group->skill_id)&UF_NOOVERLAP)
+ id = s = group->skill_id;
+ else
+ id = s = group->group_id;
- if(bl->type==BL_PC){
- set=((struct map_session_data *)bl)->skillunittick;
- }else{
- set=((struct mob_data *)bl)->skillunittick;
+ for (i=0; i<MAX_SKILLUNITGROUPTICKSET; i++) {
+ k = (i+s) % MAX_SKILLUNITGROUPTICKSET;
+ if (set[k].id == id)
+ return &set[k];
+ else if (j==-1 && (DIFF_TICK(tick,set[k].tick)>0 || set[k].id==0))
+ j=k;
}
- if(set!=NULL){
-
- for(i=0;i<MAX_SKILLUNITGROUPTICKSET;i++)
- if( (ts=&set[(i+s)%MAX_SKILLUNITGROUPTICKSET])->group_id == group_id )
- ts->group_id=0;
-
+ if (j == -1) {
+ if(battle_config.error_log) {
+ sprintf (tmp_output, "skill_unitgrouptickset_search: tickset is full\n");
+ ShowWarning (tmp_output);
+ }
+ j = id % MAX_SKILLUNITGROUPTICKSET;
}
- return 0;
+
+ set[j].id = id;
+ set[j].tick = tick;
+ return &set[j];
}
/*==========================================
@@ -10406,49 +8431,27 @@ int skill_unitgrouptickset_delete(struct block_list *bl,int group_id)
*/
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*);
-
- tick=va_arg(ap,unsigned int);
- su = (struct skill_unit *)src;
+ unit = va_arg(ap,struct skill_unit *);
+ tick = va_arg(ap,unsigned int);
- 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;
}
@@ -10466,28 +8469,38 @@ 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;
+ group=unit->group;
- range=(unit->range!=0)?unit->range:group->range;
+ nullpo_retr(0, 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;
@@ -10516,7 +8529,21 @@ int skill_unit_timer_sub( struct block_list *bl, va_list ap )
map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,NULL,NULL,NULL,0); // ?返還
}
}
+ skill_delunit(unit);
}
+ break;
+
+ case 0xc1:
+ case 0xc2:
+ case 0xc3:
+ case 0xc4:
+ {
+ struct block_list *src=map_id2bl(group->src_id);
+ if (src)
+ group->tick = tick;
+ }
+ break;
+
default:
skill_delunit(unit);
}
@@ -10549,92 +8576,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;
}
@@ -10643,173 +8611,117 @@ 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 );
+ map_foreachinarea(skill_unit_move_sub,
+ bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,bl,tick,flag);
return 0;
}
/*==========================================
- * スキルユニット自?の移動時?理(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;
-}
-
-/*==========================================
* スキルユニット自?の移動時?理
* 引?はグル?プと移動量
*------------------------------------------
*/
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 = (int *) aMalloc(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 *) malloc(sizeof(int) * group->unit_count);
- s_flag = (int *) malloc(sizeof(int) * group->unit_count);
- m_flag = (int *) malloc(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;
}
}
- free(r_flag);
- free(s_flag);
- free(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);
}
}
+ aFree(m_flag);
return 0;
}
@@ -10935,62 +8847,57 @@ int skill_produce_mix( struct map_session_data *sd,
/* 確率判定 */
equip = itemdb_isequip(nameid);
if(!equip) {
+// Corrected rates [DracoRPG] --------------------------//
if(skill_produce_db[idx].req_skill==AM_PHARMACY) {
- if((nameid >= 501 && nameid <= 506) || (nameid >= 545 && nameid <= 547) || nameid == 525)
- make_per = 2000 + 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 + pc_checkskill(sd,AM_POTIONPITCHER)*100;
- else if(nameid == 970)
- make_per = 1500 + 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(nameid == 7135)
- 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 + pc_checkskill(sd,AM_DEMONSTRATION)*100;
- else if(nameid == 7136)
- 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 + pc_checkskill(sd,AM_ACIDTERROR)*100;
- else if(nameid == 7137)
- 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 + pc_checkskill(sd,AM_CANNIBALIZE)*100;
- else if(nameid == 7138)
- 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 + pc_checkskill(sd,AM_SPHEREMINE)*100;
- else if(nameid == 7139)
- 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 + 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;
+ make_per = pc_checkskill(sd,AM_LEARNINGPOTION)*100
+ + pc_checkskill(sd,AM_PHARMACY)*300 + sd->status.job_level*20
+ + sd->paramc[4]*10+sd->paramc[5]*10;
+
+ if(nameid >= 501 && nameid <= 505) // Normal potions
+ 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
+ ;
+ else if(nameid == 970) // Alcohol
+ make_per += 1000;
+ else if(nameid == 7135) // Bottle Grenade
+ make_per += 500 + pc_checkskill(sd,AM_DEMONSTRATION)*100;
+ else if(nameid == 7136) // Acid Bottle
+ make_per += 500 + pc_checkskill(sd,AM_ACIDTERROR)*100;
+ else if(nameid == 7137) // Plant Bottle
+ make_per += 500 + pc_checkskill(sd,AM_CANNIBALIZE)*100;
+ else if(nameid == 7138) // Marine Sphere Bottle
+ make_per += 500 + pc_checkskill(sd,AM_SPHEREMINE)*100;
+ else if(nameid == 7139) // Glistening Coat
+ 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 if (skill_produce_db[idx].req_skill == ASC_CDP) {
make_per = 2000 + 40*sd->paramc[4] + 20*sd->paramc[5];
- //make_per = 20 + (20*sd->paramc[4])/50 + (20*sd->paramc[5])/100;
} else {
if(nameid == 998)
- make_per = 2000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*600;
- else if(nameid == 985)
- make_per = 1000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + (pc_checkskill(sd,skill_produce_db[idx].req_skill)-1)*500;
+ make_per = 1500 + sd->status.job_level*35 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*600;
else
- make_per = 1000 + sd->status.base_level*30 + sd->paramc[4]*20 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500;
- }
- }
- else {
- int add_per;
- if(pc_search_inventory(sd,989) >= 0) add_per = 750;
- else if(pc_search_inventory(sd,988) >= 0) add_per = 500;
- else if(pc_search_inventory(sd,987) >= 0) add_per = 250;
- else if(pc_search_inventory(sd,986) >= 0) add_per = 0;
- else add_per = -500;
- if(ele) add_per -= 500;
- add_per -= sc*500;
+ make_per = 1000 + sd->status.job_level*35 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500;
+ }
+ if(battle_config.pp_rate != 100)
+ make_per = make_per * battle_config.pp_rate / 100;
+ } else { // Corrected rates [DracoRPG]
+ int add_per=0;
+ if(pc_search_inventory(sd,989) >= 0) add_per = 400;
+ else if(pc_search_inventory(sd,988) >= 0) add_per = 300;
+ else if(pc_search_inventory(sd,987) >= 0) add_per = 200;
+ else if(pc_search_inventory(sd,986) >= 0) add_per = 100;
wlv = itemdb_wlv(nameid);
- make_per = ((250 + sd->status.base_level*15 + sd->paramc[4]*10 + sd->paramc[5]*5 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*500 +
- add_per) * (100 - (wlv - 1)*20))/100 + pc_checkskill(sd,BS_WEAPONRESEARCH)*100 + ((wlv >= 3)? pc_checkskill(sd,BS_ORIDEOCON)*100 : 0);
+ make_per = 1500 + sd->status.job_level*35 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,skill_produce_db[idx].req_skill)*1000 + pc_checkskill(sd,BS_WEAPONRESEARCH)*100 +
+ ((wlv >= 3)? pc_checkskill(sd,BS_ORIDEOCON)*100 : 0) + add_per - (ele? 2500:0) - sc*((4-wlv)*500) - wlv*1000;
+ if(battle_config.wp_rate != 100) /* 確率補正 */
+ make_per = make_per * battle_config.wp_rate / 100;
}
+// -----------------------------------------------------//
if(make_per < 1) make_per = 1;
- if(skill_produce_db[idx].req_skill==AM_PHARMACY ||
- skill_produce_db[idx].req_skill==ASC_CDP) {
- if( battle_config.pp_rate!=100 )
- make_per=make_per*battle_config.pp_rate/100;
- }
- else {
- if( battle_config.wp_rate!=100 ) /* 確率補正 */
- make_per=make_per*battle_config.wp_rate/100;
- }
-
// if(battle_config.etc_log)
// printf("make rate = %d\n",make_per);
@@ -11013,10 +8920,8 @@ int skill_produce_mix( struct map_session_data *sd,
*((unsigned long *)(&tmp_item.card[2]))=sd->char_id; /* キャラID */
}
- #ifndef TXT_ONLY
if(log_config.produce > 0)
log_produce(sd,nameid,slot1,slot2,slot3,1);
- #endif //USE_SQL
switch (skill_produce_db[idx].req_skill) {
case AM_PHARMACY:
@@ -11037,12 +8942,9 @@ 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 {
- #ifndef TXT_ONLY
+ } else {
if(log_config.produce > 0)
log_produce(sd,nameid,slot1,slot2,slot3,0);
- #endif //USE_SQL
switch (skill_produce_db[idx].req_skill) {
case AM_PHARMACY:
@@ -11110,6 +9012,230 @@ 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;
+ }
+ case PA_GOSPEL:
+ {
+ 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;
+ }
+ 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 スキルデ?タ
@@ -11134,46 +9260,27 @@ 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;
i=atoi(split[0]);
if (i>=10000 && i<10015) // for guild skills [Celest]
i -= 9500;
- else if(i<0 || i>MAX_SKILL_DB)
+ else if(i<=0 || i>MAX_SKILL_DB)
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[7],skill_db[i].num);
if(strcmpi(split[8],"yes") == 0)
skill_db[i].castcancel=1;
@@ -11190,17 +9297,11 @@ 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);
- printf("read db/skill_db.txt done\n");
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_db.txt");
+ ShowStatus(tmp_output);
fp=fopen("db/skill_require_db.txt","r");
if(fp==NULL){
@@ -11208,91 +9309,39 @@ 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;
i=atoi(split[0]);
if (i>=10000 && i<10015) // for guild skills [Celest]
i -= 9500;
- else if(i<0 || i>MAX_SKILL_DB)
+ 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;
@@ -11309,14 +9358,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]);
@@ -11339,7 +9381,8 @@ int skill_readdb(void)
skill_db[i].amount[9]=atoi(split[29]);
}
fclose(fp);
- printf("read db/skill_require_db.txt done\n");
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_require_db.txt");
+ ShowStatus(tmp_output);
/* キャスティングデ?タベ?ス */
fp=fopen("db/skill_cast_db.txt","r");
@@ -11348,62 +9391,70 @@ 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;
i=atoi(split[0]);
if (i>=10000 && i<10015) // for guild skills [Celest]
i -= 9500;
- else if(i<0 || i>MAX_SKILL_DB)
+ 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;
+ }
+ k = 0;
+ 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);
- printf("read db/skill_cast_db.txt done\n");
+ 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));
@@ -11422,16 +9473,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;
- }
- if(split[0]==NULL)
+ 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]);
@@ -11446,7 +9492,8 @@ int skill_readdb(void)
break;
}
fclose(fp);
- printf("read %s done (count=%d)\n",filename[m],k);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",k,filename[m]);
+ ShowStatus(tmp_output);
}
memset(skill_arrow_db,0,sizeof(skill_arrow_db));
@@ -11462,12 +9509,8 @@ 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;
- }
- if(split[0]==NULL)
+ j = skill_split_str(line,split,13);
+ if(split[0]==0) //fixed by Lupus
continue;
i=atoi(split[0]);
if(i<=0)
@@ -11484,7 +9527,8 @@ int skill_readdb(void)
break;
}
fclose(fp);
- printf("read db/create_arrow_db.txt done (count=%d)\n",k);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",k,"db/create_arrow_db.txt");
+ ShowStatus(tmp_output);
memset(skill_abra_db,0,sizeof(skill_abra_db));
fp=fopen("db/abra_db.txt","r");
@@ -11498,12 +9542,8 @@ 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;
- }
- if(split[0]==NULL)
+ j = skill_split_str(line,split,13);
+ if(split[0]==0) //fixed by Lupus
continue;
i=atoi(split[0]);
if(i<=0)
@@ -11517,7 +9557,8 @@ int skill_readdb(void)
break;
}
fclose(fp);
- printf("read db/abra_db.txt done (count=%d)\n",k);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",k,"db/abra_db.txt");
+ ShowStatus(tmp_output);
fp=fopen("db/skill_castnodex_db.txt","r");
if(fp==NULL){
@@ -11525,33 +9566,27 @@ int skill_readdb(void)
return 1;
}
while(fgets(line,1020,fp)){
- char *split[50], *split2[MAX_SKILL_LEVEL];
- memset(split,0,sizeof(split));
+ char *split[50];
if(line[0]=='/' && line[1]=='/')
continue;
- for(j=0,p=line;j<2 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
-
+ memset(split,0,sizeof(split));
+ j = skill_split_str(line,split,3);
+ if(split[0]==0) //fixed by Lupus
+ continue;
i=atoi(split[0]);
if (i>=10000 && i<10015) // for guild skills [Celest]
i -= 9500;
- else if(i<0 || i>MAX_SKILL_DB)
+ 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;
+ skill_split_atoi(split[2],skill_db[i].delaynodex);
}
fclose(fp);
- printf("read db/skill_castnodex_db.txt done\n");
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_castnodex_db.txt");
+ ShowStatus(tmp_output);
fp=fopen("db/skill_nocast_db.txt","r");
if(fp==NULL){
@@ -11564,35 +9599,75 @@ 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;
- }
- if(split[0]==NULL)
+ j = skill_split_str(line,split,2);
+ if(split[0]==0) //fixed by Lupus
continue;
i=atoi(split[0]);
- if(i < 0 || i > MAX_SKILL_DB)
+ if (i>=10000 && i<10015) // for guild skills [Celest]
+ i -= 9500;
+ else if(i<=0 || i>MAX_SKILL_DB)
continue;
skill_db[i].nocast=atoi(split[1]);
k++;
}
fclose(fp);
- printf("read db/skill_nocast_db done\n");
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_nocast_db");
+ ShowStatus(tmp_output);
return 0;
}
-void skill_reload(void)
+/*===============================================
+ * For reading leveluseskillspamount.txt [Celest]
+ *-----------------------------------------------
+ */
+static int skill_read_skillspamount(void)
{
- /*
+ char *buf,*p;
+ struct skill_db *skill = NULL;
+ int s, idx, new_flag=1, level=1, sp=0;
+
+ buf=(char *) grfio_reads("data\\leveluseskillspamount.txt",&s);
+
+ if(buf==NULL)
+ return -1;
+
+ buf[s]=0;
+ for(p=buf;p-buf<s;){
+ char buf2[64];
+
+ if (sscanf(p,"%[@]",buf2) == 1) {
+ level = 1;
+ new_flag = 1;
+ } else if (new_flag && sscanf(p,"%[^#]#",buf2) == 1) {
+ for (idx=0; skill_names[idx].id != 0; idx++) {
+ if (strstr(buf2, skill_names[idx].name) != NULL) {
+ skill = &skill_db[ skill_names[idx].id ];
+ new_flag = 0;
+ break;
+ }
+ }
+ } else if (!new_flag && sscanf(p,"%d#",&sp) == 1) {
+ skill->sp[level-1]=sp;
+ level++;
+ }
- <empty skill database>
- <?>
+ p=strchr(p,10);
+ if(!p) break;
+ p++;
+ }
+ aFree(buf);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\leveluseskillspamount.txt");
+ ShowStatus(tmp_output);
- */
+ return 0;
+}
- do_init_skill();
+void skill_reload(void)
+{
+ skill_readdb();
+ if (battle_config.skill_sp_override_grffile)
+ skill_read_skillspamount();
}
/*==========================================
@@ -11602,12 +9677,13 @@ void skill_reload(void)
int do_init_skill(void)
{
skill_readdb();
+ if (battle_config.skill_sp_override_grffile)
+ skill_read_skillspamount();
add_timer_func_list(skill_unit_timer,"skill_unit_timer");
add_timer_func_list(skill_castend_id,"skill_castend_id");
add_timer_func_list(skill_castend_pos,"skill_castend_pos");
add_timer_func_list(skill_timerskill,"skill_timerskill");
- add_timer_func_list(skill_status_change_timer,"skill_status_change_timer");
add_timer_interval(gettick()+SKILLUNITTIMER_INVERVAL,skill_unit_timer,0,0,SKILLUNITTIMER_INVERVAL);
return 0;
diff --git a/src/map/skill.h b/src/map/skill.h
index a8bf30e3c..67d7a906c 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -1,10 +1,10 @@
-// $Id: skill.h,v 1.5 2004/11/26 5:47:12 PM Celestia Exp $
+// $Id: skill.h,v 1.5 2004/12/23 7:43:16 PM Celestia $
#ifndef _SKILL_H_
#define _SKILL_H_
#include "map.h"
-#define MAX_SKILL_DB 515
+#define MAX_SKILL_DB 750
#define MAX_SKILL_PRODUCE_DB 150
#define MAX_PRODUCE_RESOURCE 7
#define MAX_SKILL_ARROW_DB 150
@@ -23,7 +23,14 @@ struct skill_db {
int weapon,state,spiritball[MAX_SKILL_LEVEL];
int itemid[10],amount[10];
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];
@@ -34,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;
@@ -57,6 +82,9 @@ struct skill_abra_db {
};
extern struct skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB];
+extern int enchant_eff[5];
+extern int deluge_eff[5];
+
struct block_list;
struct map_session_data;
struct skill_unit;
@@ -86,6 +114,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
// スキルの使用
@@ -109,9 +138,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,int group_id);
-int skill_unitgrouptickset_delete(struct block_list *bl,int group_id);
int skill_clear_unitgroup(struct block_list *src);
int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl,
@@ -119,21 +145,25 @@ 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(struct block_list *bl,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 );
void skill_stop_dancing(struct block_list *src, int flag);
+// Guild skills [celest]
+int skill_guildaura_sub (struct block_list *bl,va_list ap);
+
// 詠唱キャンセル
int skill_castcancel(struct block_list *bl,int type);
int skill_gangsterparadise(struct map_session_data *sd ,int type);
+int skill_check_moonlit (struct block_list *bl, int dx, int dy);
void skill_brandishspear_first(struct square *tc,int dir,int x,int y);
void skill_brandishspear_dir(struct square *tc,int dir,int are);
int skill_autospell(struct map_session_data *md,int skillid);
@@ -142,19 +172,13 @@ void skill_devotion2(struct block_list *bl,int crusader);
int skill_devotion3(struct block_list *bl,int target);
void skill_devotion_end(struct map_session_data *md,struct map_session_data *sd,int target);
-#define skill_calc_heal(bl,skill_lv) (( battle_get_lv(bl)+battle_get_int(bl) )/8 *(4+ skill_lv*8))
+#define skill_calc_heal(bl,skill_lv) (( status_get_lv(bl)+status_get_int(bl) )/8 *(4+ skill_lv*8))
// その他
int skill_check_cloaking(struct block_list *bl);
-int skill_type_cloaking(struct block_list *bl);
-int skill_is_danceskill(int id);
// ステ?タス異常
-int skill_status_change_start(struct block_list *bl,int type,int val1,int val2,int val3,int val4,int tick,int flag);
-int skill_status_change_timer(int tid, unsigned int tick, int id, int data);
-int skill_encchant_eremental_end(struct block_list *bl, int type);
-int skill_status_change_end( struct block_list* bl , int type,int tid );
-int skill_status_change_clear(struct block_list *bl,int type);
+int skill_enchant_elemental_end(struct block_list *bl, int type);
int skillnotok(int skillid, struct map_session_data *sd);
// アイテム作成
@@ -180,201 +204,6 @@ enum {
ST_RECOV_WEIGHT_RATE,ST_MOVE_ENABLE,ST_WATER,
};
-enum { // struct map_session_data の status_changeの番?テ?ブル
-// SC_SENDMAX未?はクライアントへの通知あり。
-// 2-2次職の値はなんかめちゃくちゃっぽいので暫定。たぶん?更されます。
- SC_SENDMAX =128,
- SC_PROVOKE = 0,
- SC_ENDURE = 1,
- SC_TWOHANDQUICKEN = 2,
- SC_CONCENTRATE = 3,
- SC_HIDING = 4,
- SC_CLOAKING = 5,
- SC_ENCPOISON = 6,
- SC_POISONREACT = 7,
- SC_QUAGMIRE = 8,
- SC_ANGELUS = 9,
- SC_BLESSING =10,
- SC_SIGNUMCRUCIS =11,
- SC_INCREASEAGI =12,
- SC_DECREASEAGI =13,
- SC_SLOWPOISON =14,
- SC_IMPOSITIO =15,
- SC_SUFFRAGIUM =16,
- SC_ASPERSIO =17,
- SC_BENEDICTIO =18,
- SC_KYRIE =19,
- SC_MAGNIFICAT =20,
- SC_GLORIA =21,
- SC_AETERNA =22,
- SC_ADRENALINE =23,
- SC_WEAPONPERFECTION =24,
- SC_OVERTHRUST =25,
- SC_MAXIMIZEPOWER =26,
- SC_RIDING =27,
- SC_FALCON =28,
- SC_TRICKDEAD =29,
- SC_LOUD =30,
- SC_ENERGYCOAT =31,
- SC_HALLUCINATION =34,
- SC_WEIGHT50 =35,
- SC_WEIGHT90 =36,
- SC_SPEEDPOTION0 =37,
- SC_SPEEDPOTION1 =38,
- SC_SPEEDPOTION2 =39,
- SC_STRIPWEAPON =50,
- SC_STRIPSHIELD =51,
- SC_STRIPARMOR =52,
- SC_STRIPHELM =53,
- SC_CP_WEAPON =54,
- SC_CP_SHIELD =55,
- SC_CP_ARMOR =56,
- SC_CP_HELM =57,
- SC_AUTOGUARD =58,
- SC_REFLECTSHIELD =59,
- SC_DEVOTION =60,
- SC_PROVIDENCE =61,
- SC_DEFENDER =62,
- SC_AUTOSPELL =65,
- SC_SPEARSQUICKEN =68,
- SC_EXPLOSIONSPIRITS =86,
- SC_STEELBODY =87,
- SC_COMBO =89,
- SC_FLAMELAUNCHER =90,
- SC_FROSTWEAPON =91,
- SC_LIGHTNINGLOADER =92,
- SC_SEISMICWEAPON =93,
- SC_AURABLADE =103, /* オ?ラブレ?ド */
- SC_PARRYING =104, /* パリイング */
- SC_CONCENTRATION =105, /* コンセントレ?ション */
- SC_TENSIONRELAX =106, /* テンションリラックス */
- SC_BERSERK =107, /* バ?サ?ク */
- SC_ASSUMPTIO =110, /* アシャンプティオ */
- SC_MAGICPOWER =113, /* 魔法力?幅 */
- SC_TRUESIGHT =115, /* トゥル?サイト */
- SC_WINDWALK =116, /* ウインドウォ?ク */
- SC_MELTDOWN =117, /* メルトダウン */
- SC_CARTBOOST =118, /* カ?トブ?スト */
- SC_REJECTSWORD =120, /* リジェクトソ?ド */
- SC_MARIONETTE =121, /* マリオネットコントロ?ル */
- SC_HEADCRUSH =124, /* ヘッドクラッシュ */
- SC_JOINTBEAT =125, /* ジョイントビ?ト */
-
- SC_STONE =128,
- SC_FREEZE =129,
- SC_STAN =130,
- SC_SLEEP =131,
- SC_POISON =132,
- SC_CURSE =133,
- SC_SILENCE =134,
- SC_CONFUSION =135,
- SC_BLIND =136,
- SC_DIVINA = SC_SILENCE,
-
- SC_SAFETYWALL =140,
- SC_PNEUMA =141,
- SC_WATERBALL =142,
- SC_ANKLE =143,
- SC_DANCING =144,
- SC_KEEPING =145,
- SC_BARRIER =146,
-
- SC_MAGICROD =149,
- SC_SIGHT =150,
- SC_RUWACH =151,
- SC_AUTOCOUNTER =152,
- SC_VOLCANO =153,
- SC_DELUGE =154,
- SC_VIOLENTGALE =155,
- SC_BLADESTOP_WAIT =156,
- SC_BLADESTOP =157,
- SC_EXTREMITYFIST =158,
- SC_GRAFFITI =159,
-
- SC_LULLABY =160,
- SC_RICHMANKIM =161,
- SC_ETERNALCHAOS =162,
- SC_DRUMBATTLE =163,
- SC_NIBELUNGEN =164,
- SC_ROKISWEIL =165,
- SC_INTOABYSS =166,
- SC_SIEGFRIED =167,
- SC_DISSONANCE =168,
- SC_WHISTLE =169,
- SC_ASSNCROS =170,
- SC_POEMBRAGI =171,
- SC_APPLEIDUN =172,
- SC_UGLYDANCE =173,
- SC_HUMMING =174,
- SC_DONTFORGETME =175,
- SC_FORTUNE =176,
- SC_SERVICE4U =177,
-
- SC_SPIDERWEB =180, /* スパイダ?ウェッブ */
- SC_MEMORIZE =181, /* メモライズ */
-// SC_DPOISON =182, /* 猛毒 */
-
-// SC_EDP =183, /* エフェクトが判明したら移動 */
-
- SC_WEDDING =187, //結婚用(結婚衣裳になって?くのが?いとか)
- SC_NOCHAT =188, //赤エモ?態
- SC_SPLASHER =189, /* ベナムスプラッシャ? */
- SC_SELFDESTRUCTION =190, /* 自爆 */
-
-
-// Used by English Team
- SC_BROKNARMOR =32,
- SC_BROKNWEAPON =33,
- SC_SLOWDOWN =45, // for skill slowdown
- SC_SIGHTTRASHER =73,
-// SC_BASILICA =125, // 125 is the same id as joint break
- SC_BASILICA =102, // temporarily use this before an actual id is found [celest]
- SC_EDP =114, //
- SC_MARIONETTE2 =122, // Marionette target
- SC_ENSEMBLE =159,
- SC_FOGWALL =178,
- SC_GOSPEL =179,
- SC_LANDPROTECTOR =182,
- SC_ADAPTATION =183,
- SC_CHASEWALK =184,
- SC_ATKPOT =185, // [Valaris]
- SC_MATKPOT =186, // [Valaris]
- SC_MINDBREAKER =191,
- SC_SPELLBREAKER =192,
- SC_DPOISON =193, /* 猛毒 */
- SC_BLOCKSKILL =194, // for disallowing the use of a skill for a time period
-
-// [Celest]
- SC_BLEEDING = 124, // Temporarily same id as headcrush
- SC_MOONLIT = 195,
- SC_LEADERSHIP = 196,
- SC_GLORYWOUNDS = 197,
- SC_SOULCOLD = 198,
- SC_HAWKEYES = 199,
- SC_BATTLEORDERS = 200,
- SC_REGENERATION = 201,
- SC_PRESERVE = 202,
-
-// -- testing various SC effects
-// SC_AURABLADE =81,
-// SC_CONCENTRATION =83,
-// SC_TENSIONRELAX =84,
-// SC_BERSERK =85,
-// SC_CALLSPIRITS =100,
-// SC_PARRYING =100,
-// SC_FREECAST =101,
-// SC_ABSORBSPIRIT =102,
-// SC_ASSUMPTIO =114,
-// SC_SHARPSHOOT =127,
-// SC_GANGSTER =184,
-// SC_CANNIBALIZE =186,
-// SC_SPHEREMINE =187,
-// SC_METEOSTORM =189,
-// SC_CASTCANCEL =190,
-// SC_SPIDERWEB =191,
-};
-extern int SkillStatusChangeTable[];
-
enum {
NV_BASIC = 1,
@@ -737,6 +566,22 @@ enum {
NPC_SELFDESTRUCTION2 = 331,
ITM_TOMAHAWK = 337,
NPC_DARKCROSS = 338,
+ NPC_DARKGRANDCROSS,
+ NPC_DARKSOULSTRIKE,
+ NPC_DARKJUPITEL,
+ // temporary names for mob skills [Celest]
+ NPC_BIND,
+ NPC_BREAKWEAPON,
+ NPC_BREAKARMOR,
+ NPC_BREAKHELM,
+ NPC_BREAKSHIELD,
+ NPC_UNDEADATTACK,
+
+ NPC_RUNAWAY = 348,
+ NPC_EXPLOSIONSPIRITS,
+ NPC_INCAGI,
+
+ NPC_RECALL = 354,
LK_AURABLADE = 355,
LK_PARRYING,
@@ -794,7 +639,8 @@ enum {
WE_BABY,
WE_CALLPARENT,
WE_CALLBABY,
- TK_RUN,
+
+ TK_RUN = 411,
TK_READYSTORM,
TK_STORMKICK,
TK_READYDOWN,
diff --git a/src/map/status.c b/src/map/status.c
new file mode 100644
index 000000000..a9967d956
--- /dev/null
+++ b/src/map/status.c
@@ -0,0 +1,5159 @@
+
+// ステータス計算、状態異常処理
+#include <time.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+
+#include "pc.h"
+#include "map.h"
+#include "pet.h"
+#include "mob.h"
+#include "clif.h"
+#include "guild.h"
+#include "skill.h"
+#include "itemdb.h"
+#include "battle.h"
+#include "chrif.h"
+#include "status.h"
+
+#include "timer.h"
+#include "nullpo.h"
+#include "script.h"
+#include "showmsg.h"
+
+/* スキル番?=>ステ?タス異常番??換テ?ブル */
+int SkillStatusChangeTable[]={ /* status.hのenumのSC_***とあわせること */
+/* 0- */
+ -1,-1,-1,-1,-1,-1,
+ SC_PROVOKE, /* プロボック */
+ -1, 1,-1,
+/* 10- */
+ SC_SIGHT, /* サイト */
+ -1,
+ SC_SAFETYWALL, /* セーフティーウォール */
+ -1,-1,-1,
+ SC_FREEZE, /* フロストダイバ? */
+ SC_STONE, /* スト?ンカ?ス */
+ -1,-1,
+/* 20- */
+ -1,-1,-1,-1,
+ SC_RUWACH, /* ルアフ */
+ SC_PNEUMA, /* ニューマ */
+ -1,-1,-1,
+ SC_INCREASEAGI, /* 速度?加 */
+/* 30- */
+ SC_DECREASEAGI, /* 速度減少 */
+ -1,
+ SC_SIGNUMCRUCIS, /* シグナムクルシス */
+ SC_ANGELUS, /* エンジェラス */
+ SC_BLESSING, /* ブレッシング */
+ -1,-1,-1,-1,-1,
+/* 40- */
+ -1,-1,-1,-1,-1,
+ SC_CONCENTRATE, /* 集中力向上 */
+ -1,-1,-1,-1,
+/* 50- */
+ -1,
+ SC_HIDING, /* ハイディング */
+ -1,-1,-1,-1,-1,-1,-1,-1,
+/* 60- */
+ SC_TWOHANDQUICKEN, /* 2HQ */
+ SC_AUTOCOUNTER,
+ -1,-1,-1,-1,
+ SC_IMPOSITIO, /* インポシティオマヌス */
+ SC_SUFFRAGIUM, /* サフラギウム */
+ SC_ASPERSIO, /* アスペルシオ */
+ SC_BENEDICTIO, /* 聖?降福 */
+/* 70- */
+ -1,
+ SC_SLOWPOISON,
+ -1,
+ SC_KYRIE, /* キリエエレイソン */
+ SC_MAGNIFICAT, /* マグニフィカ?ト */
+ SC_GLORIA, /* グロリア */
+ SC_DIVINA, /* レックスディビ?ナ */
+ -1,
+ SC_AETERNA, /* レックスエ?テルナ */
+ -1,
+/* 80- */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+/* 90- */
+ -1,-1,
+ SC_QUAGMIRE, /* クァグマイア */
+ -1,-1,-1,-1,-1,-1,-1,
+/* 100- */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+/* 110- */
+ -1,
+ SC_ADRENALINE, /* アドレナリンラッシュ */
+ SC_WEAPONPERFECTION,/* ウェポンパ?フェクション */
+ SC_OVERTHRUST, /* オ?バ?トラスト */
+ SC_MAXIMIZEPOWER, /* マキシマイズパワ? */
+ -1,-1,-1,-1,-1,
+/* 120- */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+/* 130- */
+ -1,-1,-1,-1,-1,
+ SC_CLOAKING, /* クロ?キング */
+ SC_STAN, /* ソニックブロ? */
+ -1,
+ SC_ENCPOISON, /* エンチャントポイズン */
+ SC_POISONREACT, /* ポイズンリアクト */
+/* 140- */
+ SC_POISON, /* ベノムダスト */
+ SC_SPLASHER, /* ベナムスプラッシャ? */
+ -1,
+ SC_TRICKDEAD, /* 死んだふり */
+ -1,-1,SC_AUTOBERSERK,-1,-1,-1,
+/* 150- */
+ -1,-1,-1,-1,-1,
+ SC_LOUD, /* ラウドボイス */
+ -1,
+ SC_ENERGYCOAT, /* エナジ?コ?ト */
+ -1,-1,
+/* 160- */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,
+ SC_SELFDESTRUCTION,
+ -1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+ -1,
+ SC_KEEPING,
+ -1,-1,
+ SC_BARRIER,
+ -1,-1,
+ SC_HALLUCINATION,
+ -1,-1,
+/* 210- */
+ -1,-1,-1,-1,-1,
+ SC_STRIPWEAPON,
+ SC_STRIPSHIELD,
+ SC_STRIPARMOR,
+ SC_STRIPHELM,
+ -1,
+/* 220- */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+/* 230- */
+ -1,-1,-1,-1,
+ SC_CP_WEAPON,
+ SC_CP_SHIELD,
+ SC_CP_ARMOR,
+ SC_CP_HELM,
+ -1,-1,
+/* 240- */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,
+ SC_AUTOGUARD,
+/* 250- */
+ -1,-1,
+ SC_REFLECTSHIELD,
+ -1,-1,
+ SC_DEVOTION,
+ SC_PROVIDENCE,
+ SC_DEFENDER,
+ SC_SPEARSQUICKEN,
+ -1,
+/* 260- */
+ -1,-1,-1,-1,-1,-1,-1,-1,
+ SC_STEELBODY,
+ SC_BLADESTOP_WAIT,
+/* 270- */
+ SC_EXPLOSIONSPIRITS,
+ SC_EXTREMITYFIST,
+ -1,-1,-1,-1,
+ SC_MAGICROD,
+ -1,-1,-1,
+/* 280- */
+ SC_FLAMELAUNCHER,
+ SC_FROSTWEAPON,
+ SC_LIGHTNINGLOADER,
+ SC_SEISMICWEAPON,
+ -1,
+ SC_VOLCANO,
+ SC_DELUGE,
+ SC_VIOLENTGALE,
+ SC_LANDPROTECTOR,
+ -1,
+/* 290- */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+/* 300- */
+ -1,-1,-1,-1,-1,-1,
+ SC_LULLABY,
+ SC_RICHMANKIM,
+ SC_ETERNALCHAOS,
+ SC_DRUMBATTLE,
+/* 310- */
+ SC_NIBELUNGEN,
+ SC_ROKISWEIL,
+ SC_INTOABYSS,
+ SC_SIEGFRIED,
+ -1,-1,-1,
+ SC_DISSONANCE,
+ -1,
+ SC_WHISTLE,
+/* 320- */
+ SC_ASSNCROS,
+ SC_POEMBRAGI,
+ SC_APPLEIDUN,
+ -1,-1,
+ SC_UGLYDANCE,
+ -1,
+ SC_HUMMING,
+ SC_DONTFORGETME,
+ SC_FORTUNE,
+/* 330- */
+ SC_SERVICE4U,
+ SC_SELFDESTRUCTION,
+ -1,-1,-1,-1,-1,-1,-1,-1,
+/* 340- */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+/* 350- */
+ -1,-1,-1,-1,-1,
+ SC_AURABLADE,
+ SC_PARRYING,
+ SC_CONCENTRATION,
+ SC_TENSIONRELAX,
+ SC_BERSERK,
+/* 360- */
+ SC_BERSERK,
+ SC_ASSUMPTIO,
+ SC_BASILICA,
+ -1,-1,-1,
+ SC_MAGICPOWER,
+ -1,
+ SC_SACRIFICE,
+ SC_GOSPEL,
+/* 370- */
+ -1,-1,-1,-1,-1,-1,-1,-1,
+ SC_EDP,
+ -1,
+/* 380- */
+ SC_TRUESIGHT,
+ -1,-1,
+ SC_WINDWALK,
+ SC_MELTDOWN,
+ -1,-1,
+ SC_CARTBOOST,
+ -1,
+ SC_CHASEWALK,
+/* 390- */
+ SC_REJECTSWORD,
+ -1,-1,-1,-1,
+ SC_MOONLIT,
+ SC_MARIONETTE,
+ -1,
+ SC_BLEEDING,
+ SC_JOINTBEAT,
+/* 400 */
+ -1,-1,
+ SC_MINDBREAKER,
+ SC_MEMORIZE,
+ SC_FOGWALL,
+ SC_SPIDERWEB,
+ -1,-1,
+ SC_BABY,
+ -1,
+/* 410- */
+ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+};
+
+static int max_weight_base[MAX_PC_CLASS];
+static int hp_coefficient[MAX_PC_CLASS];
+static int hp_coefficient2[MAX_PC_CLASS];
+static int hp_sigma_val[MAX_PC_CLASS][MAX_LEVEL];
+static int sp_coefficient[MAX_PC_CLASS];
+static int aspd_base[MAX_PC_CLASS][20];
+static int refinebonus[5][3]; // 精錬ボーナステーブル(refine_db.txt)
+int percentrefinery[5][10]; // 精錬成功率(refine_db.txt)
+static int atkmods[3][20]; // 武器ATKサイズ修正(size_fix.txt)
+static char job_bonus[3][MAX_PC_CLASS][MAX_LEVEL];
+
+int current_equip_item_index; //Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus]
+//we need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only
+//to avoid cards exploits
+
+/*==========================================
+ * 精錬ボーナス
+ *------------------------------------------
+ */
+int status_getrefinebonus(int lv,int type)
+{
+ if (lv >= 0 && lv < 5 && type >= 0 && type < 3)
+ return refinebonus[lv][type];
+ return 0;
+}
+
+/*==========================================
+ * 精錬成功率
+ *------------------------------------------
+ */
+int status_percentrefinery(struct map_session_data *sd,struct item *item)
+{
+ int percent;
+
+ nullpo_retr(0, item);
+ percent=percentrefinery[itemdb_wlv(item->nameid)][(int)item->refine];
+
+ percent += pc_checkskill(sd,BS_WEAPONRESEARCH); // 武器研究スキル所持
+
+ // 確率の有効範囲チェック
+ if( percent > 100 ){
+ percent = 100;
+ }
+ if( percent < 0 ){
+ percent = 0;
+ }
+
+ return percent;
+}
+
+/*==========================================
+ * パラメータ計算
+ * first==0の時、計算対象のパラメータが呼び出し前から
+ * 変 化した場合自動でsendするが、
+ * 能動的に変化させたパラメータは自前でsendするように
+ *------------------------------------------
+ */
+
+int status_calc_pc(struct map_session_data* sd,int first)
+{
+ int b_speed,b_max_hp,b_max_sp,b_hp,b_sp,b_weight,b_max_weight,b_paramb[6],b_parame[6],b_hit,b_flee;
+ int b_aspd,b_watk,b_def,b_watk2,b_def2,b_flee2,b_critical,b_attackrange,b_matk1,b_matk2,b_mdef,b_mdef2,b_class;
+ int b_base_atk;
+ struct skill b_skill[MAX_SKILL];
+ int i,bl,index;
+ int skill,aspd_rate,wele,wele_,def_ele,refinedef=0;
+ int pele=0,pdef_ele=0;
+ int str,dstr,dex;
+ struct pc_base_job s_class;
+
+ nullpo_retr(0, sd);
+
+ //?生や養子の場合の元の職業を算出する
+ s_class = pc_calc_base_job(sd->status.class_);
+
+ b_speed = sd->speed;
+ b_max_hp = sd->status.max_hp;
+ b_max_sp = sd->status.max_sp;
+ b_hp = sd->status.hp;
+ b_sp = sd->status.sp;
+ b_weight = sd->weight;
+ b_max_weight = sd->max_weight;
+ memcpy(b_paramb,&sd->paramb,sizeof(b_paramb));
+ memcpy(b_parame,&sd->paramc,sizeof(b_parame));
+ memcpy(b_skill,&sd->status.skill,sizeof(b_skill));
+ b_hit = sd->hit;
+ b_flee = sd->flee;
+ b_aspd = sd->aspd;
+ b_watk = sd->watk;
+ b_def = sd->def;
+ b_watk2 = sd->watk2;
+ b_def2 = sd->def2;
+ b_flee2 = sd->flee2;
+ b_critical = sd->critical;
+ b_attackrange = sd->attackrange;
+ b_matk1 = sd->matk1;
+ b_matk2 = sd->matk2;
+ b_mdef = sd->mdef;
+ b_mdef2 = sd->mdef2;
+ b_class = sd->view_class;
+ sd->view_class = sd->status.class_;
+ b_base_atk = sd->base_atk;
+
+ pc_calc_skilltree(sd); // スキルツリ?の計算
+
+ sd->max_weight = max_weight_base[s_class.job]+sd->status.str*300;
+
+ if(first&1) {
+ sd->weight=0;
+ for(i=0;i<MAX_INVENTORY;i++){
+ if(sd->status.inventory[i].nameid==0 || sd->inventory_data[i] == NULL)
+ continue;
+ sd->weight += sd->inventory_data[i]->weight*sd->status.inventory[i].amount;
+ }
+ sd->cart_max_weight=battle_config.max_cart_weight;
+ sd->cart_weight=0;
+ sd->cart_max_num=MAX_CART;
+ sd->cart_num=0;
+ for(i=0;i<MAX_CART;i++){
+ if(sd->status.cart[i].nameid==0)
+ continue;
+ sd->cart_weight+=itemdb_weight(sd->status.cart[i].nameid)*sd->status.cart[i].amount;
+ sd->cart_num++;
+ }
+ }
+
+ memset(sd->paramb,0,sizeof(sd->paramb));
+ memset(sd->parame,0,sizeof(sd->parame));
+ sd->hit = 0;
+ sd->flee = 0;
+ sd->flee2 = 0;
+ sd->critical = 0;
+ sd->aspd = 0;
+ sd->watk = 0;
+ sd->def = 0;
+ sd->mdef = 0;
+ sd->watk2 = 0;
+ sd->def2 = 0;
+ sd->mdef2 = 0;
+ sd->status.max_hp = 0;
+ sd->status.max_sp = 0;
+ sd->attackrange = 0;
+ sd->attackrange_ = 0;
+ sd->atk_ele = 0;
+ sd->def_ele = 0;
+ sd->star =0;
+ sd->overrefine =0;
+ sd->matk1 =0;
+ sd->matk2 =0;
+ sd->speed = DEFAULT_WALK_SPEED ;
+ sd->hprate=battle_config.hp_rate;
+ sd->sprate=battle_config.sp_rate;
+ sd->castrate=100;
+ sd->delayrate=100;
+ sd->dsprate=100;
+ sd->base_atk=0;
+ sd->arrow_atk=0;
+ sd->arrow_ele=0;
+ sd->arrow_hit=0;
+ sd->arrow_range=0;
+ sd->nhealhp=sd->nhealsp=sd->nshealhp=sd->nshealsp=sd->nsshealhp=sd->nsshealsp=0;
+ memset(sd->addele,0,sizeof(sd->addele));
+ memset(sd->addrace,0,sizeof(sd->addrace));
+ memset(sd->addsize,0,sizeof(sd->addsize));
+ memset(sd->addele_,0,sizeof(sd->addele_));
+ memset(sd->addrace_,0,sizeof(sd->addrace_));
+ memset(sd->addsize_,0,sizeof(sd->addsize_));
+ memset(sd->subele,0,sizeof(sd->subele));
+ memset(sd->subrace,0,sizeof(sd->subrace));
+ memset(sd->addeff,0,sizeof(sd->addeff));
+ memset(sd->addeff2,0,sizeof(sd->addeff2));
+ memset(sd->reseff,0,sizeof(sd->reseff));
+ memset(&sd->special_state,0,sizeof(sd->special_state));
+ memset(sd->weapon_coma_ele,0,sizeof(sd->weapon_coma_ele));
+ memset(sd->weapon_coma_race,0,sizeof(sd->weapon_coma_race));
+ memset(sd->weapon_atk,0,sizeof(sd->weapon_atk));
+ memset(sd->weapon_atk_rate,0,sizeof(sd->weapon_atk_rate));
+
+ sd->watk_ = 0; //二刀流用(?)
+ sd->watk_2 = 0;
+ sd->atk_ele_ = 0;
+ sd->star_ = 0;
+ sd->overrefine_ = 0;
+
+ sd->aspd_rate = 100;
+ sd->speed_rate = 100;
+ sd->hprecov_rate = 100;
+ sd->sprecov_rate = 100;
+ sd->critical_def = 0;
+ sd->double_rate = 0;
+ sd->near_attack_def_rate = sd->long_attack_def_rate = 0;
+ sd->atk_rate = sd->matk_rate = 100;
+ sd->ignore_def_ele = sd->ignore_def_race = 0;
+ sd->ignore_def_ele_ = sd->ignore_def_race_ = 0;
+ sd->ignore_mdef_ele = sd->ignore_mdef_race = 0;
+ sd->arrow_cri = 0;
+ sd->magic_def_rate = sd->misc_def_rate = 0;
+ memset(sd->arrow_addele,0,sizeof(sd->arrow_addele));
+ memset(sd->arrow_addrace,0,sizeof(sd->arrow_addrace));
+ memset(sd->arrow_addsize,0,sizeof(sd->arrow_addsize));
+ memset(sd->arrow_addeff,0,sizeof(sd->arrow_addeff));
+ memset(sd->arrow_addeff2,0,sizeof(sd->arrow_addeff2));
+ memset(sd->magic_addele,0,sizeof(sd->magic_addele));
+ memset(sd->magic_addrace,0,sizeof(sd->magic_addrace));
+ memset(sd->magic_subrace,0,sizeof(sd->magic_subrace));
+ sd->perfect_hit = 0;
+ sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100;
+ sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100;
+ sd->def_ratio_atk_ele = sd->def_ratio_atk_ele_ = 0;
+ sd->def_ratio_atk_race = sd->def_ratio_atk_race_ = 0;
+ sd->get_zeny_num = 0;
+ sd->add_damage_class_count = sd->add_damage_class_count_ = sd->add_magic_damage_class_count = 0;
+ sd->add_def_class_count = sd->add_mdef_class_count = 0;
+ sd->monster_drop_item_count = 0;
+ memset(sd->add_damage_classrate,0,sizeof(sd->add_damage_classrate));
+ memset(sd->add_damage_classrate_,0,sizeof(sd->add_damage_classrate_));
+ memset(sd->add_magic_damage_classrate,0,sizeof(sd->add_magic_damage_classrate));
+ memset(sd->add_def_classrate,0,sizeof(sd->add_def_classrate));
+ memset(sd->add_mdef_classrate,0,sizeof(sd->add_mdef_classrate));
+ memset(sd->monster_drop_race,0,sizeof(sd->monster_drop_race));
+ memset(sd->monster_drop_itemrate,0,sizeof(sd->monster_drop_itemrate));
+ sd->speed_add_rate = sd->aspd_add_rate = 100;
+ sd->double_add_rate = sd->perfect_hit_add = sd->get_zeny_add_num = 0;
+ sd->splash_range = sd->splash_add_range = 0;
+ sd->autospell_id = sd->autospell_lv = sd->autospell_rate = 0;
+ sd->hp_drain_rate = sd->hp_drain_per = sd->sp_drain_rate = sd->sp_drain_per = 0;
+ sd->hp_drain_rate_ = sd->hp_drain_per_ = sd->sp_drain_rate_ = sd->sp_drain_per_ = 0;
+ sd->short_weapon_damage_return = sd->long_weapon_damage_return = 0;
+ sd->magic_damage_return = 0; //AppleGirl Was Here
+ sd->random_attack_increase_add = sd->random_attack_increase_per = 0;
+ sd->hp_drain_value = sd->hp_drain_value_ = sd->sp_drain_value = sd->sp_drain_value_ = 0;
+ sd->unbreakable_equip = 0;
+
+ sd->break_weapon_rate = sd->break_armor_rate = 0;
+ sd->add_steal_rate = 0;
+ sd->crit_atk_rate = 0;
+ sd->no_regen = 0;
+ sd->unstripable_equip = 0;
+ sd->autospell2_id = sd->autospell2_lv = sd->autospell2_rate = 0;
+ memset(sd->critaddrace,0,sizeof(sd->critaddrace));
+ memset(sd->addeff3,0,sizeof(sd->addeff3));
+ memset(sd->addeff3_type,0,sizeof(sd->addeff3_type));
+ memset(sd->skillatk,0,sizeof(sd->skillatk));
+ sd->add_damage_class_count = sd->add_damage_class_count_ = sd->add_magic_damage_class_count = 0;
+ sd->add_def_class_count = sd->add_mdef_class_count = 0;
+ sd->add_damage_class_count2 = 0;
+ memset(sd->add_damage_classid,0,sizeof(sd->add_damage_classid));
+ memset(sd->add_damage_classid_,0,sizeof(sd->add_damage_classid_));
+ memset(sd->add_magic_damage_classid,0,sizeof(sd->add_magic_damage_classid));
+ memset(sd->add_damage_classrate,0,sizeof(sd->add_damage_classrate));
+ memset(sd->add_damage_classrate_,0,sizeof(sd->add_damage_classrate_));
+ memset(sd->add_magic_damage_classrate,0,sizeof(sd->add_magic_damage_classrate));
+ memset(sd->add_def_classid,0,sizeof(sd->add_def_classid));
+ memset(sd->add_def_classrate,0,sizeof(sd->add_def_classrate));
+ memset(sd->add_mdef_classid,0,sizeof(sd->add_mdef_classid));
+ memset(sd->add_mdef_classrate,0,sizeof(sd->add_mdef_classrate));
+ memset(sd->add_damage_classid2,0,sizeof(sd->add_damage_classid2));
+ memset(sd->add_damage_classrate2,0,sizeof(sd->add_damage_classrate2));
+ sd->sp_gain_value = 0;
+ sd->ignore_def_mob = sd->ignore_def_mob_ = 0;
+ sd->hp_loss_rate = sd->hp_loss_value = sd->hp_loss_type = 0;
+ memset(sd->addrace2,0,sizeof(sd->addrace2));
+ memset(sd->addrace2_,0,sizeof(sd->addrace2_));
+ sd->hp_gain_value = sd->sp_drain_type = 0;
+ memset(sd->subsize,0,sizeof(sd->subsize));
+ memset(sd->unequip_losehp,0,sizeof(sd->unequip_losehp));
+ memset(sd->unequip_losesp,0,sizeof(sd->unequip_losesp));
+ memset(sd->subrace2,0,sizeof(sd->subrace2));
+ memset(sd->expaddrace,0,sizeof(sd->expaddrace));
+ memset(sd->sp_gain_race,0,sizeof(sd->sp_gain_race));
+
+ if(!sd->disguiseflag && sd->disguise) {
+ sd->disguise=0;
+ clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
+ clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
+ clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
+ clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
+ clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
+ clif_clearchar(&sd->bl, 9);
+ pc_setpos(sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
+ }
+
+ if (sd->status.guild_id > 0) {
+ struct guild *g = guild_search(sd->status.guild_id);
+ if (g && strcmp(sd->status.name,g->master)==0)
+ sd->state.gmaster_flag = (int)g;
+ }
+
+ for(i=0;i<10;i++) {
+ current_equip_item_index = index = sd->equip_index[i]; //We pass INDEX to current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus]
+ if(index < 0)
+ continue;
+ if(i == 9 && sd->equip_index[8] == index)
+ continue;
+ if(i == 5 && sd->equip_index[4] == index)
+ continue;
+ if(i == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index))
+ continue;
+
+ if(sd->inventory_data[index]) {
+ if(sd->inventory_data[index]->type == 4) {
+ if(sd->status.inventory[index].card[0]!=0x00ff && sd->status.inventory[index].card[0]!=0x00fe && sd->status.inventory[index].card[0]!=(short)0xff00) {
+ int j;
+ for(j=0;j<sd->inventory_data[index]->slot;j++){ // カ?ド
+ int c=sd->status.inventory[index].card[j];
+ if(c>0){
+ if(i == 8 && sd->status.inventory[index].equip == 0x20)
+ sd->state.lr_flag = 1;
+ run_script(itemdb_equipscript(c),0,sd->bl.id,0);
+ sd->state.lr_flag = 0;
+ }
+ }
+ }
+ }
+ else if(sd->inventory_data[index]->type==5){ // 防具
+ if(sd->status.inventory[index].card[0]!=0x00ff && sd->status.inventory[index].card[0]!=0x00fe && sd->status.inventory[index].card[0]!=(short)0xff00) {
+ int j;
+ for(j=0;j<sd->inventory_data[index]->slot;j++){ // カ?ド
+ int c=sd->status.inventory[index].card[j];
+ if(c>0)
+ run_script(itemdb_equipscript(c),0,sd->bl.id,0);
+ }
+ }
+ }
+ }
+ }
+ wele = sd->atk_ele;
+ wele_ = sd->atk_ele_;
+ def_ele = sd->def_ele;
+ if(sd->status.pet_id > 0) {
+ struct pet_data *pd=sd->pd;
+ if((pd && battle_config.pet_status_support==1) && (battle_config.pet_equip_required==0 || (battle_config.pet_equip_required && pd->equip > 0))) {
+ if(sd->status.pet_id > 0 && sd->petDB && sd->pet.intimate > 0 &&
+ pd->state.skillbonus == 1) {
+ pc_bonus(sd,pd->skillbonustype,pd->skillbonusval);
+// run_script(sd->petDB->script,0,sd->bl.id,0);
+ }
+ pele = sd->atk_ele;
+ pdef_ele = sd->def_ele;
+ sd->atk_ele = sd->def_ele = 0;
+ }
+ }
+ memcpy(sd->paramcard,sd->parame,sizeof(sd->paramcard));
+
+ // ?備品によるステ?タス?化はここで?行
+ for(i=0;i<10;i++) {
+ current_equip_item_index = index = sd->equip_index[i]; //We pass INDEX to current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus]
+ if(index < 0)
+ continue;
+ if(i == 9 && sd->equip_index[8] == index)
+ continue;
+ if(i == 5 && sd->equip_index[4] == index)
+ continue;
+ if(i == 6 && (sd->equip_index[5] == index || sd->equip_index[4] == index))
+ continue;
+ if(sd->inventory_data[index]) {
+ sd->def += sd->inventory_data[index]->def;
+ if(sd->inventory_data[index]->type == 4) {
+ int r,wlv = sd->inventory_data[index]->wlv;
+ if(i == 8 && sd->status.inventory[index].equip == 0x20) {
+ //二刀流用デ?タ入力
+ sd->watk_ += sd->inventory_data[index]->atk;
+ sd->watk_2 = (r=sd->status.inventory[index].refine)* // 精?攻?力
+ refinebonus[wlv][0];
+ if( (r-=refinebonus[wlv][2])>0 ) // 過?精?ボ?ナス
+ sd->overrefine_ = r*refinebonus[wlv][1];
+
+ if(sd->status.inventory[index].card[0]==0x00ff){ // 製造武器
+ sd->star_ = (sd->status.inventory[index].card[1]>>8); // 星のかけら
+ wele_= (sd->status.inventory[index].card[1]&0x0f); // ? 性
+ }
+ sd->attackrange_ += sd->inventory_data[index]->range;
+ sd->state.lr_flag = 1;
+ run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
+ sd->state.lr_flag = 0;
+ }
+ else { //二刀流武器以外
+ sd->watk += sd->inventory_data[index]->atk;
+ sd->watk2 += (r=sd->status.inventory[index].refine)* // 精?攻?力
+ refinebonus[wlv][0];
+ if( (r-=refinebonus[wlv][2])>0 ) // 過?精?ボ?ナス
+ sd->overrefine += r*refinebonus[wlv][1];
+
+ if(sd->status.inventory[index].card[0]==0x00ff){ // 製造武器
+ sd->star += (sd->status.inventory[index].card[1]>>8); // 星のかけら
+ wele = (sd->status.inventory[index].card[1]&0x0f); // ? 性
+ }
+ sd->attackrange += sd->inventory_data[index]->range;
+ run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
+ }
+ }
+ else if(sd->inventory_data[index]->type == 5) {
+ sd->watk += sd->inventory_data[index]->atk;
+ refinedef += sd->status.inventory[index].refine*refinebonus[0][0];
+ run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
+ }
+ }
+ }
+
+ if(sd->equip_index[10] >= 0){ // 矢
+ index = sd->equip_index[10];
+ if(sd->inventory_data[index]){ //まだ?性が入っていない
+ sd->state.lr_flag = 2;
+ run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
+ sd->state.lr_flag = 0;
+ sd->arrow_atk += sd->inventory_data[index]->atk;
+ }
+ }
+ sd->def += (refinedef+50)/100;
+
+ if(sd->attackrange < 1) sd->attackrange = 1;
+ if(sd->attackrange_ < 1) sd->attackrange_ = 1;
+ if(sd->attackrange < sd->attackrange_)
+ sd->attackrange = sd->attackrange_;
+ if(sd->status.weapon == 11)
+ sd->attackrange += sd->arrow_range;
+ if(wele > 0)
+ sd->atk_ele = wele;
+ if(wele_ > 0)
+ sd->atk_ele_ = wele_;
+ if(def_ele > 0)
+ sd->def_ele = def_ele;
+ if(battle_config.pet_status_support) {
+ if(pele > 0 && !sd->atk_ele)
+ sd->atk_ele = pele;
+ if(pdef_ele > 0 && !sd->def_ele)
+ sd->def_ele = pdef_ele;
+ }
+ sd->double_rate += sd->double_add_rate;
+ sd->perfect_hit += sd->perfect_hit_add;
+ sd->get_zeny_num += sd->get_zeny_add_num;
+ sd->splash_range += sd->splash_add_range;
+ if(sd->speed_add_rate != 100)
+ sd->speed_rate += sd->speed_add_rate - 100;
+ if(sd->aspd_add_rate != 100)
+ sd->aspd_rate += sd->aspd_add_rate - 100;
+
+ // 武器ATKサイズ補正 (右手)
+ sd->atkmods[0] = atkmods[0][sd->weapontype1];
+ sd->atkmods[1] = atkmods[1][sd->weapontype1];
+ sd->atkmods[2] = atkmods[2][sd->weapontype1];
+ //武器ATKサイズ補正 (左手)
+ sd->atkmods_[0] = atkmods[0][sd->weapontype2];
+ sd->atkmods_[1] = atkmods[1][sd->weapontype2];
+ sd->atkmods_[2] = atkmods[2][sd->weapontype2];
+
+ // jobボ?ナス分
+ for(i=0;i<sd->status.job_level && i<MAX_LEVEL;i++){
+ if(job_bonus[s_class.upper][s_class.job][i])
+ sd->paramb[job_bonus[s_class.upper][s_class.job][i]-1]++;
+ }
+
+ if( (skill=pc_checkskill(sd,MC_INCCARRY))>0 ) // skill can be used with an item now, thanks to orn [Valaris]
+ sd->max_weight += skill*2000;
+
+ if( (skill=pc_checkskill(sd,AC_OWL))>0 ) // ふくろうの目
+ sd->paramb[4] += skill;
+
+ if((skill=pc_checkskill(sd,BS_HILTBINDING))>0) { // Hilt binding gives +1 str +4 atk
+ sd->paramb[0] ++;
+ sd->base_atk += 4;
+ }
+ if((skill=pc_checkskill(sd,SA_DRAGONOLOGY))>0 ){ // Dragonology increases +1 int every 2 levels
+ sd->paramb[3] += (int) ((skill+1)*0.5);
+ }
+
+ // ステ?タス?化による基本パラメ?タ補正
+ if(sd->sc_count){
+ if(sd->sc_data[SC_CONCENTRATE].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1){ // 集中力向上
+ sd->paramb[1]+= (sd->status.agi+sd->paramb[1]+sd->parame[1]-sd->paramcard[1])*(2+sd->sc_data[SC_CONCENTRATE].val1)/100;
+ sd->paramb[4]+= (sd->status.dex+sd->paramb[4]+sd->parame[4]-sd->paramcard[4])*(2+sd->sc_data[SC_CONCENTRATE].val1)/100;
+ }
+ if(sd->sc_data[SC_INCREASEAGI].timer!=-1){ // 速度?加
+ sd->paramb[1]+= 2+sd->sc_data[SC_INCREASEAGI].val1;
+ sd->speed -= sd->speed *25/100;
+ }
+ if(sd->sc_data[SC_DECREASEAGI].timer!=-1) { // 速度減少(agiはbattle.cで)
+ sd->speed = sd->speed *125/100;
+ sd->paramb[1] -= 2 + sd->sc_data[SC_DECREASEAGI].val1; // reduce agility [celest]
+ }
+ if(sd->sc_data[SC_CLOAKING].timer!=-1) {
+ sd->critical_rate += 100; // critical increases
+ sd->speed = sd->speed * (sd->sc_data[SC_CLOAKING].val3-sd->sc_data[SC_CLOAKING].val1*3) /100;
+ }
+ if(sd->sc_data[SC_CHASEWALK].timer!=-1) {
+ sd->speed = sd->speed * sd->sc_data[SC_CHASEWALK].val3 /100; // slow down by chasewalk
+ if(sd->sc_data[SC_CHASEWALK].val4)
+ sd->paramb[0] += (1<<(sd->sc_data[SC_CHASEWALK].val1-1)); // increases strength after 10 seconds
+ }
+ if(sd->sc_data[SC_SLOWDOWN].timer!=-1)
+ sd->speed = sd->speed*150/100;
+ if(sd->sc_data[SC_SPEEDUP0].timer!=-1 && sd->sc_data[SC_INCREASEAGI].timer==-1)
+ sd->speed -= sd->speed*25/100;
+ if(sd->sc_data[SC_BLESSING].timer!=-1){ // ブレッシング
+ sd->paramb[0]+= sd->sc_data[SC_BLESSING].val1;
+ sd->paramb[3]+= sd->sc_data[SC_BLESSING].val1;
+ sd->paramb[4]+= sd->sc_data[SC_BLESSING].val1;
+ }
+ if(sd->sc_data[SC_GLORIA].timer!=-1) // グロリア
+ sd->paramb[5]+= 30;
+ if(sd->sc_data[SC_LOUD].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1) // ラウドボイス
+ sd->paramb[0]+= 4;
+ if(sd->sc_data[SC_QUAGMIRE].timer!=-1){ // クァグマイア
+ //int agib = (sd->status.agi+sd->paramb[1]+sd->parame[1])*(sd->sc_data[SC_QUAGMIRE].val1*10)/100;
+ //int dexb = (sd->status.dex+sd->paramb[4]+sd->parame[4])*(sd->sc_data[SC_QUAGMIRE].val1*10)/100;
+ //sd->paramb[1]-= agib > 50 ? 50 : agib;
+ //sd->paramb[4]-= dexb > 50 ? 50 : dexb;
+ sd->paramb[1]-= sd->sc_data[SC_QUAGMIRE].val1*5;
+ sd->paramb[4]-= sd->sc_data[SC_QUAGMIRE].val1*5;
+ sd->speed = sd->speed*3/2;
+ }
+ if(sd->sc_data[SC_TRUESIGHT].timer!=-1){ // トゥル?サイト
+ sd->paramb[0]+= 5;
+ sd->paramb[1]+= 5;
+ sd->paramb[2]+= 5;
+ sd->paramb[3]+= 5;
+ sd->paramb[4]+= 5;
+ sd->paramb[5]+= 5;
+ }
+ if(sd->sc_data[SC_MARIONETTE].timer!=-1){
+ // skip partner checking -- should be handled in status_change_timer
+ //struct map_session_data *psd = map_id2sd(sd->sc_data[SC_MARIONETTE2].val3);
+ //if (psd) { // if partner is found
+ sd->paramb[0]-= sd->status.str/2; // bonuses not included
+ sd->paramb[1]-= sd->status.agi/2;
+ sd->paramb[2]-= sd->status.vit/2;
+ sd->paramb[3]-= sd->status.int_/2;
+ sd->paramb[4]-= sd->status.dex/2;
+ sd->paramb[5]-= sd->status.luk/2;
+ //}
+ }
+ else if(sd->sc_data[SC_MARIONETTE2].timer!=-1){
+ struct map_session_data *psd = map_id2sd(sd->sc_data[SC_MARIONETTE2].val3);
+ if (psd) { // if partner is found
+ sd->paramb[0] += sd->status.str+psd->status.str/2 > 99 ? 99-sd->status.str : psd->status.str/2;
+ sd->paramb[1] += sd->status.agi+psd->status.agi/2 > 99 ? 99-sd->status.agi : psd->status.agi/2;
+ sd->paramb[2] += sd->status.vit+psd->status.vit/2 > 99 ? 99-sd->status.vit : psd->status.vit/2;
+ sd->paramb[3] += sd->status.int_+psd->status.int_/2 > 99 ? 99-sd->status.int_ : psd->status.int_/2;
+ sd->paramb[4] += sd->status.dex+psd->status.dex/2 > 99 ? 99-sd->status.dex : psd->status.dex/2;
+ sd->paramb[5] += sd->status.luk+psd->status.luk/2 > 99 ? 99-sd->status.luk : psd->status.luk/2;
+ }
+ }
+ if(sd->sc_data[SC_GOSPEL].timer!=-1 && sd->sc_data[SC_GOSPEL].val4 == BCT_PARTY){
+ if (sd->sc_data[SC_GOSPEL].val3 == 6) {
+ sd->paramb[0]+= 2;
+ sd->paramb[1]+= 2;
+ sd->paramb[2]+= 2;
+ sd->paramb[3]+= 2;
+ sd->paramb[4]+= 2;
+ sd->paramb[5]+= 2;
+ }
+ }
+ // New guild skills - Celest
+ if (sd->sc_data[SC_BATTLEORDERS].timer != -1) {
+ sd->paramb[0]+= 5;
+ sd->paramb[3]+= 5;
+ sd->paramb[4]+= 5;
+ }
+ if (sd->sc_data[SC_GUILDAURA].timer != -1) {
+ if (sd->sc_data[SC_GUILDAURA].val4 & 1<<0)
+ sd->paramb[0] += 2;
+ if (sd->sc_data[SC_GUILDAURA].val4 & 1<<1)
+ sd->paramb[2] += 2;
+ if (sd->sc_data[SC_GUILDAURA].val4 & 1<<2)
+ sd->paramb[1] += 2;
+ if (sd->sc_data[SC_GUILDAURA].val4 & 1<<3)
+ sd->paramb[4] += 2;
+ }
+ }
+
+ //1度も死んでないJob70スパノビに+10
+ if(s_class.job == 23 && sd->die_counter == 0 && sd->status.job_level >= 70){
+ sd->paramb[0]+= 15;
+ sd->paramb[1]+= 15;
+ sd->paramb[2]+= 15;
+ sd->paramb[3]+= 15;
+ sd->paramb[4]+= 15;
+ sd->paramb[5]+= 15;
+ }
+ sd->paramc[0]=sd->status.str+sd->paramb[0]+sd->parame[0];
+ sd->paramc[1]=sd->status.agi+sd->paramb[1]+sd->parame[1];
+ sd->paramc[2]=sd->status.vit+sd->paramb[2]+sd->parame[2];
+ sd->paramc[3]=sd->status.int_+sd->paramb[3]+sd->parame[3];
+ sd->paramc[4]=sd->status.dex+sd->paramb[4]+sd->parame[4];
+ sd->paramc[5]=sd->status.luk+sd->paramb[5]+sd->parame[5];
+ for(i=0;i<6;i++)
+ if(sd->paramc[i] < 0) sd->paramc[i] = 0;
+
+ if (sd->sc_count) {
+ if (sd->sc_data[SC_CURSE].timer!=-1)
+ sd->paramc[5] = 0;
+ }
+
+ if(sd->status.weapon == 11 || sd->status.weapon == 13 || sd->status.weapon == 14) {
+ str = sd->paramc[4];
+ dex = sd->paramc[0];
+ }
+ else {
+ str = sd->paramc[0];
+ dex = sd->paramc[4];
+ }
+ dstr = str/10;
+ sd->base_atk += str + dstr*dstr + dex/5 + sd->paramc[5]/5;
+ sd->matk1 += sd->paramc[3]+(sd->paramc[3]/5)*(sd->paramc[3]/5);
+ sd->matk2 += sd->paramc[3]+(sd->paramc[3]/7)*(sd->paramc[3]/7);
+ if(sd->matk1 < sd->matk2) {
+ int temp = sd->matk2;
+ sd->matk2 = sd->matk1;
+ sd->matk1 = temp;
+ }
+ sd->hit += sd->paramc[4] + sd->status.base_level;
+ sd->flee += sd->paramc[1] + sd->status.base_level;
+ sd->def2 += sd->paramc[2];
+ sd->mdef2 += sd->paramc[3];
+ sd->flee2 += sd->paramc[5]+10;
+ sd->critical += (sd->paramc[5]*3)+10;
+
+ if(sd->base_atk < 1)
+ sd->base_atk = 1;
+ if(sd->critical_rate != 100)
+ sd->critical = (sd->critical*sd->critical_rate)/100;
+ if(sd->critical < 10) sd->critical = 10;
+ if(sd->hit_rate != 100)
+ sd->hit = (sd->hit*sd->hit_rate)/100;
+ if(sd->hit < 1) sd->hit = 1;
+ if(sd->flee_rate != 100)
+ sd->flee = (sd->flee*sd->flee_rate)/100;
+ if(sd->flee < 1) sd->flee = 1;
+ if(sd->flee2_rate != 100)
+ sd->flee2 = (sd->flee2*sd->flee2_rate)/100;
+ if(sd->flee2 < 10) sd->flee2 = 10;
+ if(sd->def_rate != 100)
+ sd->def = (sd->def*sd->def_rate)/100;
+ if(sd->def < 0) sd->def = 0;
+ if(sd->def2_rate != 100)
+ sd->def2 = (sd->def2*sd->def2_rate)/100;
+ if(sd->def2 < 1) sd->def2 = 1;
+ if(sd->mdef_rate != 100)
+ sd->mdef = (sd->mdef*sd->mdef_rate)/100;
+ if(sd->mdef < 0) sd->mdef = 0;
+ if(sd->mdef2_rate != 100)
+ sd->mdef2 = (sd->mdef2*sd->mdef2_rate)/100;
+ if(sd->mdef2 < 1) sd->mdef2 = 1;
+
+ // 二刀流 ASPD 修正
+ if (sd->status.weapon <= 16)
+ sd->aspd += aspd_base[s_class.job][sd->status.weapon]-(sd->paramc[1]*4+sd->paramc[4])*aspd_base[s_class.job][sd->status.weapon]/1000;
+ else
+ sd->aspd += (
+ (aspd_base[s_class.job][sd->weapontype1]-(sd->paramc[1]*4+sd->paramc[4])*aspd_base[s_class.job][sd->weapontype1]/1000) +
+ (aspd_base[s_class.job][sd->weapontype2]-(sd->paramc[1]*4+sd->paramc[4])*aspd_base[s_class.job][sd->weapontype2]/1000)
+ ) * 140 / 200;
+
+ aspd_rate = sd->aspd_rate;
+
+ //攻?速度?加
+
+ if((skill=pc_checkskill(sd,AC_VULTURE))>0){ // ワシの目
+ sd->hit += skill;
+ if(sd->status.weapon == 11)
+ sd->attackrange += skill;
+ }
+
+ if( (skill=pc_checkskill(sd,BS_WEAPONRESEARCH))>0) // 武器?究の命中率?加
+ sd->hit += skill*2;
+ if(sd->status.option&2 && (skill = pc_checkskill(sd,RG_TUNNELDRIVE))>0 ) // トンネルドライブ // トンネルドライブ
+ sd->speed += (100-16*skill)*DEFAULT_WALK_SPEED/100;
+ //sd->speed += (1.2*DEFAULT_WALK_SPEED - skill*9);
+ if (pc_iscarton(sd) && (skill=pc_checkskill(sd,MC_PUSHCART))>0) // カ?トによる速度低下
+ sd->speed += (short) ((10-skill) * (DEFAULT_WALK_SPEED * 0.1));
+ else if (pc_isriding(sd)) { // ペコペコ?りによる速度?加
+ sd->speed -= (short) ((0.25 * DEFAULT_WALK_SPEED));
+ sd->max_weight += 10000;
+ }
+ if((skill=pc_checkskill(sd,CR_TRUST))>0) { // フェイス
+ sd->status.max_hp += skill*200;
+ sd->subele[6] += skill*5;
+ }
+ if((skill=pc_checkskill(sd,BS_SKINTEMPER))>0) {
+ sd->subele[0] += skill;
+ sd->subele[3] += skill*5;
+ }
+ if((skill=pc_checkskill(sd,SA_ADVANCEDBOOK))>0 )
+ aspd_rate -= (int) (skill*0.5);
+
+ bl=sd->status.base_level;
+
+ sd->status.max_hp += (3500 + bl*hp_coefficient2[s_class.job] + hp_sigma_val[s_class.job][(bl > 0)? bl-1:0])/100 * (100 + sd->paramc[2])/100 + (sd->parame[2] - sd->paramcard[2]);
+ if (s_class.upper==1) // [MouseJstr]
+ sd->status.max_hp = sd->status.max_hp * 130/100;
+ else if (s_class.upper==2)
+ sd->status.max_hp = sd->status.max_hp * 70/100;
+
+ if (sd->hprate <= 0)
+ sd->hprate = 1;
+ if(sd->hprate!=100)
+ sd->status.max_hp = sd->status.max_hp*sd->hprate/100;
+
+ if(sd->sc_count && sd->sc_data[SC_BERSERK].timer!=-1){ // バ?サ?ク
+ sd->status.max_hp = sd->status.max_hp * 3;
+ // sd->status.hp = sd->status.hp * 3;
+ if(sd->status.max_hp > battle_config.max_hp) // removed negative max hp bug by Valaris
+ sd->status.max_hp = battle_config.max_hp;
+ if(sd->status.hp > battle_config.max_hp) // removed negative max hp bug by Valaris
+ sd->status.hp = battle_config.max_hp;
+ }
+ if(s_class.job == 23 && sd->status.base_level >= 99){
+ sd->status.max_hp = sd->status.max_hp + 2000;
+ }
+
+ if(sd->status.max_hp > battle_config.max_hp) // removed negative max hp bug by Valaris
+ sd->status.max_hp = battle_config.max_hp;
+ if(sd->status.max_hp <= 0) sd->status.max_hp = 1; // end
+
+ // 最大SP計算
+ sd->status.max_sp += ((sp_coefficient[s_class.job] * bl) + 1000)/100 * (100 + sd->paramc[3])/100 + (sd->parame[3] - sd->paramcard[3]);
+ if (s_class.upper==1) // [MouseJstr]
+ sd->status.max_sp = sd->status.max_sp * 130/100;
+ else if (s_class.upper==2)
+ sd->status.max_sp = sd->status.max_sp * 70/100;
+ if (sd->sprate <= 0)
+ sd->sprate = 1;
+ if(sd->sprate!=100)
+ sd->status.max_sp = sd->status.max_sp*sd->sprate/100;
+
+ if((skill=pc_checkskill(sd,HP_MEDITATIO))>0) // メディテイティオ
+ sd->status.max_sp += sd->status.max_sp*skill/100;
+ if((skill=pc_checkskill(sd,HW_SOULDRAIN))>0) /* ソウルドレイン */
+ sd->status.max_sp += sd->status.max_sp*2*skill/100;
+
+ if(sd->status.max_sp < 0 || sd->status.max_sp > battle_config.max_sp)
+ sd->status.max_sp = battle_config.max_sp;
+
+ //自然回復HP
+ sd->nhealhp = 1 + (sd->paramc[2]/5) + (sd->status.max_hp/200);
+ if((skill=pc_checkskill(sd,SM_RECOVERY)) > 0) { /* HP回復力向上 */
+ sd->nshealhp = skill*5 + (sd->status.max_hp*skill/500);
+ if(sd->nshealhp > 0x7fff) sd->nshealhp = 0x7fff;
+ }
+ //自然回復SP
+ sd->nhealsp = 1 + (sd->paramc[3]/6) + (sd->status.max_sp/100);
+ if(sd->paramc[3] >= 120)
+ sd->nhealsp += ((sd->paramc[3]-120)>>1) + 4;
+ if((skill=pc_checkskill(sd,MG_SRECOVERY)) > 0) { /* SP回復力向上 */
+ sd->nshealsp = skill*3 + (sd->status.max_sp*skill/500);
+ if(sd->nshealsp > 0x7fff) sd->nshealsp = 0x7fff;
+ }
+
+ if((skill = pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0) {
+ sd->nsshealhp = skill*4 + (sd->status.max_hp*skill/500);
+ sd->nsshealsp = skill*2 + (sd->status.max_sp*skill/500);
+ if(sd->nsshealhp > 0x7fff) sd->nsshealhp = 0x7fff;
+ if(sd->nsshealsp > 0x7fff) sd->nsshealsp = 0x7fff;
+ }
+ if(sd->hprecov_rate != 100) {
+ sd->nhealhp = sd->nhealhp*sd->hprecov_rate/100;
+ if(sd->nhealhp < 1) sd->nhealhp = 1;
+ }
+ if(sd->sprecov_rate != 100) {
+ sd->nhealsp = sd->nhealsp*sd->sprecov_rate/100;
+ if(sd->nhealsp < 1) sd->nhealsp = 1;
+ }
+ /* if((skill=pc_checkskill(sd,HP_MEDITATIO)) > 0) { // f?fffBfefCfefBfI,I'SPR,A*,I',E`,。ゥZ((c)。ョR「カn~.ゥォ,E',(c),(c),e'
+ sd->nhealsp += 3*skill*(sd->status.max_sp)/100;
+ if(sd->nhealsp > 0x7fff) sd->nhealsp = 0x7fff;
+ } Increase natural SP regen instead of colossal SP Recovery effect [DracoRPG]*/
+
+ // 種族耐性(これでいいの? ディバインプロテクションと同じ?理がいるかも)
+ if( (skill=pc_checkskill(sd,SA_DRAGONOLOGY))>0 ){ // ドラゴノロジ?
+ skill = skill*4;
+ sd->addrace[9]+=skill;
+ sd->addrace_[9]+=skill;
+ sd->subrace[9]+=skill;
+ sd->magic_addrace[9]+=skill;
+ sd->magic_subrace[9]-=skill;
+ }
+
+ //Flee上昇
+ if( (skill=pc_checkskill(sd,TF_MISS))>0 ){ // 回避率?加
+ sd->flee += skill*((sd->status.class_==12 || sd->status.class_==17 || sd->status.class_==4013 || sd->status.class_==4018) ? 4 : 3);
+ if((sd->status.class_==12 || sd->status.class_==4013) && (sd->sc_count && sd->sc_data[SC_CLOAKING].timer==-1))
+ sd->speed -= (short)(skill*1.5/100 * DEFAULT_WALK_SPEED);
+ }
+ if( (skill=pc_checkskill(sd,MO_DODGE))>0 ) // 見切り
+ sd->flee += (skill*3)>>1;
+
+ // スキルやステ?タス異常による?りのパラメ?タ補正
+ if(sd->sc_count){
+ // ATK/DEF?化形
+ if(sd->sc_data[SC_ANGELUS].timer!=-1) // エンジェラス
+ sd->def2 = sd->def2*(110+5*sd->sc_data[SC_ANGELUS].val1)/100;
+ if(sd->sc_data[SC_IMPOSITIO].timer!=-1) {// インポシティオマヌス
+ sd->watk += sd->sc_data[SC_IMPOSITIO].val1*5;
+ index = sd->equip_index[8];
+ if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4)
+ sd->watk_ += sd->sc_data[SC_IMPOSITIO].val1*5;
+ }
+ if(sd->sc_data[SC_PROVOKE].timer!=-1){ // プロボック
+ sd->def2 = sd->def2*(100-6*sd->sc_data[SC_PROVOKE].val1)/100;
+ sd->base_atk = sd->base_atk*(100+2*sd->sc_data[SC_PROVOKE].val1)/100;
+ sd->watk = sd->watk*(100+2*sd->sc_data[SC_PROVOKE].val1)/100;
+ index = sd->equip_index[8];
+ if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4)
+ sd->watk_ = sd->watk_*(100+2*sd->sc_data[SC_PROVOKE].val1)/100;
+ }
+ if(sd->sc_data[SC_ENDURE].timer!=-1)
+ sd->mdef2 += sd->sc_data[SC_ENDURE].val1;
+ if(sd->sc_data[SC_MINDBREAKER].timer!=-1){ // プロボック
+ sd->mdef2 = sd->mdef2*(100-6*sd->sc_data[SC_MINDBREAKER].val1)/100;
+ sd->matk1 = sd->matk1*(100+2*sd->sc_data[SC_MINDBREAKER].val1)/100;
+ sd->matk2 = sd->matk2*(100+2*sd->sc_data[SC_MINDBREAKER].val1)/100;
+ }
+ if(sd->sc_data[SC_POISON].timer!=-1) // 毒?態
+ sd->def2 = sd->def2*75/100;
+ if(sd->sc_data[SC_CURSE].timer!=-1){
+ sd->base_atk = sd->base_atk*75/100;
+ sd->watk = sd->watk*75/100;
+ index = sd->equip_index[8];
+ if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4)
+ sd->watk_ = sd->watk_*75/100;
+ }
+ if(sd->sc_data[SC_DRUMBATTLE].timer!=-1){ // ?太鼓の響き
+ sd->watk += sd->sc_data[SC_DRUMBATTLE].val2;
+ sd->def += sd->sc_data[SC_DRUMBATTLE].val3;
+ index = sd->equip_index[8];
+ if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4)
+ sd->watk_ += sd->sc_data[SC_DRUMBATTLE].val2;
+ }
+ if(sd->sc_data[SC_NIBELUNGEN].timer!=-1) { // ニ?ベルングの指輪
+ index = sd->equip_index[9];
+ /*if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 3)
+ sd->watk += sd->sc_data[SC_NIBELUNGEN].val3;
+ index = sd->equip_index[8];
+ if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 3)
+ sd->watk_ += sd->sc_data[SC_NIBELUNGEN].val3;
+ index = sd->equip_index[9];*/
+ if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4)
+ sd->watk2 += sd->sc_data[SC_NIBELUNGEN].val3;
+ index = sd->equip_index[8];
+ if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4)
+ sd->watk_2 += sd->sc_data[SC_NIBELUNGEN].val3;
+ }
+
+ if(sd->sc_data[SC_VOLCANO].timer!=-1 && sd->def_ele==3){ // ボルケ?ノ
+ sd->watk += sd->sc_data[SC_VOLCANO].val3;
+ }
+
+ if(sd->sc_data[SC_SIGNUMCRUCIS].timer!=-1)
+ sd->def = sd->def * (100 - sd->sc_data[SC_SIGNUMCRUCIS].val2)/100;
+ if(sd->sc_data[SC_ETERNALCHAOS].timer!=-1) // エタ?ナルカオス
+ sd->def=0;
+
+ if(sd->sc_data[SC_CONCENTRATION].timer!=-1){ //コンセントレ?ション
+ sd->watk = sd->watk * (100 + 5*sd->sc_data[SC_CONCENTRATION].val1)/100;
+ index = sd->equip_index[8];
+ if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == 4)
+ sd->watk_ = sd->watk * (100 + 5*sd->sc_data[SC_CONCENTRATION].val1)/100;
+ sd->def = sd->def * (100 - 5*sd->sc_data[SC_CONCENTRATION].val1)/100;
+ }
+
+ if(sd->sc_data[SC_MAGICPOWER].timer!=-1){ //魔法力?幅
+ sd->matk1 = sd->matk1*(100+5*sd->sc_data[SC_MAGICPOWER].val1)/100;
+ sd->matk2 = sd->matk2*(100+5*sd->sc_data[SC_MAGICPOWER].val1)/100;
+ }
+ if(sd->sc_data[SC_ATKPOT].timer!=-1)
+ sd->watk += sd->sc_data[SC_ATKPOT].val1;
+ if(sd->sc_data[SC_MATKPOT].timer!=-1){
+ sd->matk1 += sd->sc_data[SC_MATKPOT].val1;
+ sd->matk2 += sd->sc_data[SC_MATKPOT].val1;
+ }
+
+ // ASPD/移動速度?化系
+ if(sd->sc_data[SC_TWOHANDQUICKEN].timer != -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
+ aspd_rate -= 30;
+ if(sd->sc_data[SC_ADRENALINE].timer != -1 && sd->sc_data[SC_TWOHANDQUICKEN].timer == -1 &&
+ sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) { // アドレナリンラッシュ
+ if(sd->sc_data[SC_ADRENALINE].val2 || !battle_config.party_skill_penalty)
+ aspd_rate -= 30;
+ else
+ aspd_rate -= 25;
+ }
+ if(sd->sc_data[SC_SPEARSQUICKEN].timer != -1 && sd->sc_data[SC_ADRENALINE].timer == -1 &&
+ sd->sc_data[SC_TWOHANDQUICKEN].timer == -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) // スピアクィッケン
+ aspd_rate -= sd->sc_data[SC_SPEARSQUICKEN].val2;
+ if(sd->sc_data[SC_ASSNCROS].timer!=-1 && // 夕陽のアサシンクロス
+ sd->sc_data[SC_TWOHANDQUICKEN].timer==-1 && sd->sc_data[SC_ADRENALINE].timer==-1 && sd->sc_data[SC_SPEARSQUICKEN].timer==-1 &&
+ sd->sc_data[SC_DONTFORGETME].timer == -1)
+ aspd_rate -= 5+sd->sc_data[SC_ASSNCROS].val1+sd->sc_data[SC_ASSNCROS].val2+sd->sc_data[SC_ASSNCROS].val3;
+ if(sd->sc_data[SC_DONTFORGETME].timer!=-1){ // 私を忘れないで
+ aspd_rate += sd->sc_data[SC_DONTFORGETME].val1*3 + sd->sc_data[SC_DONTFORGETME].val2 + (sd->sc_data[SC_DONTFORGETME].val3>>16);
+ sd->speed= sd->speed*(100+sd->sc_data[SC_DONTFORGETME].val1*2 + sd->sc_data[SC_DONTFORGETME].val2 + (sd->sc_data[SC_DONTFORGETME].val3&0xffff))/100;
+ }
+ if( sd->sc_data[i=SC_SPEEDPOTION3].timer!=-1 ||
+ sd->sc_data[i=SC_SPEEDPOTION2].timer!=-1 ||
+ sd->sc_data[i=SC_SPEEDPOTION1].timer!=-1 ||
+ sd->sc_data[i=SC_SPEEDPOTION0].timer!=-1) // ? 速ポ?ション
+ aspd_rate -= sd->sc_data[i].val2;
+ if(sd->sc_data[SC_WINDWALK].timer!=-1 && sd->sc_data[SC_INCREASEAGI].timer==-1) //ウィンドウォ?ク暫ヘLv*2%減算
+ sd->speed -= sd->speed *(sd->sc_data[SC_WINDWALK].val1*2)/100;
+ if(sd->sc_data[SC_CARTBOOST].timer!=-1) // カ?トブ?スト
+ sd->speed -= (DEFAULT_WALK_SPEED * 20)/100;
+ if(sd->sc_data[SC_BERSERK].timer!=-1) //バ?サ?ク中はIAと同じぐらい速い?
+ sd->speed -= sd->speed *25/100;
+ if(sd->sc_data[SC_WEDDING].timer!=-1) //結婚中は?くのが?い
+ sd->speed = 2*DEFAULT_WALK_SPEED;
+
+ // HIT/FLEE?化系
+ if(sd->sc_data[SC_WHISTLE].timer!=-1){ // 口笛
+ sd->flee += sd->flee * (sd->sc_data[SC_WHISTLE].val1
+ +sd->sc_data[SC_WHISTLE].val2+(sd->sc_data[SC_WHISTLE].val3>>16))/100;
+ sd->flee2+= (sd->sc_data[SC_WHISTLE].val1+sd->sc_data[SC_WHISTLE].val2+(sd->sc_data[SC_WHISTLE].val3&0xffff)) * 10;
+ }
+ if(sd->sc_data[SC_HUMMING].timer!=-1) // ハミング
+ sd->hit += (sd->sc_data[SC_HUMMING].val1*2+sd->sc_data[SC_HUMMING].val2
+ +sd->sc_data[SC_HUMMING].val3) * sd->hit/100;
+ if(sd->sc_data[SC_VIOLENTGALE].timer!=-1 && sd->def_ele==4){ // バイオレントゲイル
+ sd->flee += sd->flee*sd->sc_data[SC_VIOLENTGALE].val3/100;
+ }
+ if(sd->sc_data[SC_BLIND].timer!=-1){ // 暗?
+ sd->hit -= sd->hit*25/100;
+ sd->flee -= sd->flee*25/100;
+ }
+ if(sd->sc_data[SC_WINDWALK].timer!=-1) // ウィンドウォ?ク
+ sd->flee += sd->flee*(sd->sc_data[SC_WINDWALK].val2)/100;
+ if(sd->sc_data[SC_SPIDERWEB].timer!=-1) //スパイダ?ウェブ
+ sd->flee -= sd->flee*50/100;
+ if(sd->sc_data[SC_TRUESIGHT].timer!=-1) //トゥル?サイト
+ sd->hit += 3*(sd->sc_data[SC_TRUESIGHT].val1);
+ if(sd->sc_data[SC_CONCENTRATION].timer!=-1) //コンセントレ?ション
+ sd->hit += (10*(sd->sc_data[SC_CONCENTRATION].val1));
+
+ // 耐性
+ if(sd->sc_data[SC_SIEGFRIED].timer!=-1){ // 不死身のジ?クフリ?ド
+ sd->subele[1] += sd->sc_data[SC_SIEGFRIED].val2; // 水
+ sd->subele[2] += sd->sc_data[SC_SIEGFRIED].val2; // 水
+ sd->subele[3] += sd->sc_data[SC_SIEGFRIED].val2; // 火
+ sd->subele[4] += sd->sc_data[SC_SIEGFRIED].val2; // 水
+ sd->subele[5] += sd->sc_data[SC_SIEGFRIED].val2; // 水
+ sd->subele[6] += sd->sc_data[SC_SIEGFRIED].val2; // 水
+ sd->subele[7] += sd->sc_data[SC_SIEGFRIED].val2; // 水
+ sd->subele[8] += sd->sc_data[SC_SIEGFRIED].val2; // 水
+ sd->subele[9] += sd->sc_data[SC_SIEGFRIED].val2; // 水
+ }
+ if(sd->sc_data[SC_PROVIDENCE].timer!=-1){ // プロヴィデンス
+ sd->subele[6] += sd->sc_data[SC_PROVIDENCE].val2; // ? 聖?性
+ sd->subrace[6] += sd->sc_data[SC_PROVIDENCE].val2; // ? ?魔
+ }
+
+ // その他
+ if(sd->sc_data[SC_APPLEIDUN].timer!=-1){ // イドゥンの林檎
+ sd->status.max_hp += ((5+sd->sc_data[SC_APPLEIDUN].val1*2+((sd->sc_data[SC_APPLEIDUN].val2+1)>>1)
+ +sd->sc_data[SC_APPLEIDUN].val3/10) * sd->status.max_hp)/100;
+ if(sd->status.max_hp < 0 || sd->status.max_hp > battle_config.max_hp)
+ sd->status.max_hp = battle_config.max_hp;
+ }
+ if(sd->sc_data[SC_DELUGE].timer!=-1 && sd->def_ele==1){ // デリュ?ジ
+ sd->status.max_hp += sd->status.max_hp * deluge_eff[sd->sc_data[SC_DELUGE].val1-1]/100;
+ if(sd->status.max_hp < 0 || sd->status.max_hp > battle_config.max_hp)
+ sd->status.max_hp = battle_config.max_hp;
+ }
+ if(sd->sc_data[SC_SERVICE4U].timer!=-1) { // サ?ビスフォ?ユ?
+ sd->status.max_sp += sd->status.max_sp*(10+sd->sc_data[SC_SERVICE4U].val1+sd->sc_data[SC_SERVICE4U].val2
+ +sd->sc_data[SC_SERVICE4U].val3)/100;
+ if(sd->status.max_sp < 0 || sd->status.max_sp > battle_config.max_sp)
+ sd->status.max_sp = battle_config.max_sp;
+ sd->dsprate-=(10+sd->sc_data[SC_SERVICE4U].val1*3+sd->sc_data[SC_SERVICE4U].val2
+ +sd->sc_data[SC_SERVICE4U].val3);
+ if(sd->dsprate<0)sd->dsprate=0;
+ }
+
+ if(sd->sc_data[SC_FORTUNE].timer!=-1) // 幸運のキス
+ sd->critical += (10+sd->sc_data[SC_FORTUNE].val1+sd->sc_data[SC_FORTUNE].val2
+ +sd->sc_data[SC_FORTUNE].val3)*10;
+
+ if(sd->sc_data[SC_EXPLOSIONSPIRITS].timer!=-1){ // 爆裂波動
+ if(s_class.job==23)
+ sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val1*100;
+ else
+ sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val2;
+ }
+
+ if(sd->sc_data[SC_STEELBODY].timer!=-1){ // 金剛
+ sd->def = 90;
+ sd->mdef = 90;
+ aspd_rate += 25;
+ sd->speed = (sd->speed * 125) / 100;
+ }
+ if(sd->sc_data[SC_DEFENDER].timer != -1) {
+ //sd->aspd += (550 - sd->sc_data[SC_DEFENDER].val1*50);
+ aspd_rate += (25 - sd->sc_data[SC_DEFENDER].val1*5);
+ sd->speed = (sd->speed * (155 - sd->sc_data[SC_DEFENDER].val1*5)) / 100;
+ }
+ if(sd->sc_data[SC_ENCPOISON].timer != -1)
+ sd->addeff[4] += sd->sc_data[SC_ENCPOISON].val2;
+
+ if( sd->sc_data[SC_DANCING].timer!=-1 ){ // 演奏/ダンス使用中
+ sd->speed = (short) ((double)sd->speed * (6.- 0.4 * pc_checkskill(sd, ((s_class.job == 19) ? BA_MUSICALLESSON : DC_DANCINGLESSON))));
+ //sd->speed*=4;
+ sd->nhealsp = 0;
+ sd->nshealsp = 0;
+ sd->nsshealsp = 0;
+ }
+ if(sd->sc_data[SC_CURSE].timer!=-1)
+ sd->speed += 450;
+
+ if(sd->sc_data[SC_TRUESIGHT].timer!=-1) //トゥル?サイト
+ sd->critical += sd->critical*(sd->sc_data[SC_TRUESIGHT].val1)/100;
+
+/* if(sd->sc_data[SC_VOLCANO].timer!=-1) // エンチャントポイズン(?性はbattle.cで)
+ sd->addeff[2]+=sd->sc_data[SC_VOLCANO].val2;//% of granting
+ if(sd->sc_data[SC_DELUGE].timer!=-1) // エンチャントポイズン(?性はbattle.cで)
+ sd->addeff[0]+=sd->sc_data[SC_DELUGE].val2;//% of granting
+ */
+ if(sd->sc_data[SC_BERSERK].timer!=-1) { //All Def/MDef reduced to 0 while in Berserk [DracoRPG]
+ sd->def = sd->def2 = 0;
+ sd->mdef = sd->mdef2 = 0;
+ sd->flee -= sd->flee*50/100;
+ aspd_rate -= 30;
+ //sd->base_atk *= 3;
+ }
+ if(sd->sc_data[SC_KEEPING].timer!=-1)
+ sd->def = 100;
+ if(sd->sc_data[SC_BARRIER].timer!=-1)
+ sd->mdef = 100;
+
+ if(sd->sc_data[SC_JOINTBEAT].timer!=-1) { // Random break [DracoRPG]
+ switch(sd->sc_data[SC_JOINTBEAT].val2) {
+ case 1: //Ankle break
+ sd->speed_rate += 50;
+ break;
+ case 2: //Wrist break
+ sd->aspd_rate += 25;
+ break;
+ case 3: //Knee break
+ sd->speed_rate += 30;
+ sd->aspd_rate += 10;
+ break;
+ case 4: //Shoulder break
+ sd->def2 -= sd->def2*50/100;
+ break;
+ case 5: //Waist break
+ sd->def2 -= sd->def2*50/100;
+ sd->base_atk -= sd->base_atk*25/100;
+ break;
+ }
+ }
+
+ if(sd->sc_data[SC_GOSPEL].timer!=-1) {
+ if (sd->sc_data[SC_GOSPEL].val4 == BCT_PARTY){
+ switch (sd->sc_data[SC_GOSPEL].val3)
+ {
+ case 4:
+ sd->status.max_hp += sd->status.max_hp * 25 / 100;
+ if(sd->status.max_hp > battle_config.max_hp)
+ sd->status.max_hp = battle_config.max_hp;
+ break;
+ case 5:
+ sd->status.max_sp += sd->status.max_sp * 25 / 100;
+ if(sd->status.max_sp > battle_config.max_sp)
+ sd->status.max_sp = battle_config.max_sp;
+ break;
+ case 11:
+ sd->def += sd->def * 25 / 100;
+ sd->def2 += sd->def2 * 25 / 100;
+ break;
+ case 12:
+ sd->base_atk += sd->base_atk * 8 / 100;
+ break;
+ case 13:
+ sd->flee += sd->flee * 5 / 100;
+ break;
+ case 14:
+ sd->hit += sd->hit * 5 / 100;
+ break;
+ }
+ } else if (sd->sc_data[SC_GOSPEL].val4 == BCT_ENEMY){
+ switch (sd->sc_data[SC_GOSPEL].val3)
+ {
+ case 5:
+ sd->def = 0;
+ sd->def2 = 0;
+ break;
+ case 6:
+ sd->base_atk = 0;
+ sd->watk = 0;
+ sd->watk2 = 0;
+ break;
+ case 7:
+ sd->flee = 0;
+ break;
+ case 8:
+ sd->speed_rate += 75;
+ aspd_rate += 75;
+ break;
+ }
+ }
+ }
+ // custom stats, since there's no info on how much it actually gives ^^; [Celest]
+ if (sd->sc_data[SC_GUILDAURA].timer != -1) {
+ if (sd->sc_data[SC_GUILDAURA].val4 & 1<<4) {
+ sd->hit += 10;
+ sd->flee += 10;
+ }
+ }
+ }
+
+ if (sd->speed_rate <= 0)
+ sd->speed_rate = 1;
+
+ if(sd->speed_rate != 100)
+ sd->speed = sd->speed*sd->speed_rate/100;
+ if(sd->speed < 1) sd->speed = 1;
+ if(aspd_rate != 100)
+ sd->aspd = sd->aspd*aspd_rate/100;
+ if(pc_isriding(sd)) // 騎兵修練
+ sd->aspd = sd->aspd*(100 + 10*(5 - pc_checkskill(sd,KN_CAVALIERMASTERY)))/ 100;
+ if(sd->aspd < battle_config.max_aspd) sd->aspd = battle_config.max_aspd;
+ sd->amotion = sd->aspd;
+ sd->dmotion = 800-sd->paramc[1]*4;
+ if(sd->dmotion<400)
+ sd->dmotion = 400;
+ if(sd->skilltimer != -1 && (skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
+ sd->prev_speed = sd->speed;
+ sd->speed = sd->speed*(175 - skill*5)/100;
+ }
+
+ if(sd->status.hp>sd->status.max_hp)
+ sd->status.hp=sd->status.max_hp;
+ if(sd->status.sp>sd->status.max_sp)
+ sd->status.sp=sd->status.max_sp;
+
+ if(first&4)
+ return 0;
+ if(first&3) {
+ clif_updatestatus(sd,SP_SPEED);
+ clif_updatestatus(sd,SP_MAXHP);
+ clif_updatestatus(sd,SP_MAXSP);
+ if(first&1) {
+ clif_updatestatus(sd,SP_HP);
+ clif_updatestatus(sd,SP_SP);
+ }
+ return 0;
+ }
+
+ if(b_class != sd->view_class) {
+ clif_changelook(&sd->bl,LOOK_BASE,sd->view_class);
+#if PACKETVER < 4
+ clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
+ clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
+#else
+ clif_changelook(&sd->bl,LOOK_WEAPON,0);
+#endif
+ }
+
+ if( memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill)) || b_attackrange != sd->attackrange)
+ clif_skillinfoblock(sd); // スキル送信
+
+ if(b_speed != sd->speed)
+ clif_updatestatus(sd,SP_SPEED);
+ if(b_weight != sd->weight)
+ clif_updatestatus(sd,SP_WEIGHT);
+ if(b_max_weight != sd->max_weight) {
+ clif_updatestatus(sd,SP_MAXWEIGHT);
+ pc_checkweighticon(sd);
+ }
+ for(i=0;i<6;i++)
+ if(b_paramb[i] + b_parame[i] != sd->paramb[i] + sd->parame[i])
+ clif_updatestatus(sd,SP_STR+i);
+ if(b_hit != sd->hit)
+ clif_updatestatus(sd,SP_HIT);
+ if(b_flee != sd->flee)
+ clif_updatestatus(sd,SP_FLEE1);
+ if(b_aspd != sd->aspd)
+ clif_updatestatus(sd,SP_ASPD);
+ if(b_watk != sd->watk || b_base_atk != sd->base_atk)
+ clif_updatestatus(sd,SP_ATK1);
+ if(b_def != sd->def)
+ clif_updatestatus(sd,SP_DEF1);
+ if(b_watk2 != sd->watk2)
+ clif_updatestatus(sd,SP_ATK2);
+ if(b_def2 != sd->def2)
+ clif_updatestatus(sd,SP_DEF2);
+ if(b_flee2 != sd->flee2)
+ clif_updatestatus(sd,SP_FLEE2);
+ if(b_critical != sd->critical)
+ clif_updatestatus(sd,SP_CRITICAL);
+ if(b_matk1 != sd->matk1)
+ clif_updatestatus(sd,SP_MATK1);
+ if(b_matk2 != sd->matk2)
+ clif_updatestatus(sd,SP_MATK2);
+ if(b_mdef != sd->mdef)
+ clif_updatestatus(sd,SP_MDEF1);
+ if(b_mdef2 != sd->mdef2)
+ clif_updatestatus(sd,SP_MDEF2);
+ if(b_attackrange != sd->attackrange)
+ clif_updatestatus(sd,SP_ATTACKRANGE);
+ if(b_max_hp != sd->status.max_hp)
+ clif_updatestatus(sd,SP_MAXHP);
+ if(b_max_sp != sd->status.max_sp)
+ clif_updatestatus(sd,SP_MAXSP);
+ if(b_hp != sd->status.hp)
+ clif_updatestatus(sd,SP_HP);
+ if(b_sp != sd->status.sp)
+ clif_updatestatus(sd,SP_SP);
+
+/* if(before.cart_num != before.cart_num || before.cart_max_num != before.cart_max_num ||
+ before.cart_weight != before.cart_weight || before.cart_max_weight != before.cart_max_weight )
+ clif_updatestatus(sd,SP_CARTINFO);*/
+
+ //if(sd->status.hp<sd->status.max_hp>>2 && pc_checkskill(sd,SM_AUTOBERSERK)>0 &&
+ if(sd->status.hp<sd->status.max_hp>>2 && sd->sc_data[SC_AUTOBERSERK].timer != -1 &&
+ (sd->sc_data[SC_PROVOKE].timer==-1 || sd->sc_data[SC_PROVOKE].val2==0 ) && !pc_isdead(sd))
+ // オ?トバ?サ?ク?動
+ status_change_start(&sd->bl,SC_PROVOKE,10,1,0,0,0,0);
+
+ return 0;
+}
+
+/*==========================================
+ * For quick calculating [Celest]
+ *------------------------------------------
+ */
+int status_calc_speed (struct map_session_data *sd)
+{
+ int b_speed, skill;
+ struct pc_base_job s_class;
+
+ nullpo_retr(0, sd);
+
+ s_class = pc_calc_base_job(sd->status.class_);
+
+ b_speed = sd->speed;
+ sd->speed = DEFAULT_WALK_SPEED ;
+
+ if(sd->sc_count){
+ if(sd->sc_data[SC_INCREASEAGI].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1){ // 速度?加
+ sd->speed -= sd->speed *25/100;
+ }
+ if(sd->sc_data[SC_DECREASEAGI].timer!=-1) {
+ sd->speed = sd->speed *125/100;
+ }
+ if(sd->sc_data[SC_CLOAKING].timer!=-1) {
+ sd->speed = sd->speed * (sd->sc_data[SC_CLOAKING].val3-sd->sc_data[SC_CLOAKING].val1*3) /100;
+ }
+ if(sd->sc_data[SC_CHASEWALK].timer!=-1) {
+ sd->speed = sd->speed * sd->sc_data[SC_CHASEWALK].val3 /100;
+ }
+ if(sd->sc_data[SC_QUAGMIRE].timer!=-1){
+ sd->speed = sd->speed*3/2;
+ }
+ if(sd->sc_data[SC_WINDWALK].timer!=-1 && sd->sc_data[SC_INCREASEAGI].timer==-1) {
+ sd->speed -= sd->speed *(sd->sc_data[SC_WINDWALK].val1*2)/100;
+ }
+ if(sd->sc_data[SC_CARTBOOST].timer!=-1) {
+ sd->speed -= (DEFAULT_WALK_SPEED * 20)/100;
+ }
+ if(sd->sc_data[SC_BERSERK].timer!=-1) {
+ sd->speed -= sd->speed *25/100;
+ }
+ if(sd->sc_data[SC_WEDDING].timer!=-1) {
+ sd->speed = 2*DEFAULT_WALK_SPEED;
+ }
+ if(sd->sc_data[SC_DONTFORGETME].timer!=-1){
+ sd->speed= sd->speed*(100+sd->sc_data[SC_DONTFORGETME].val1*2 + sd->sc_data[SC_DONTFORGETME].val2 + (sd->sc_data[SC_DONTFORGETME].val3&0xffff))/100;
+ }
+ if(sd->sc_data[SC_STEELBODY].timer!=-1){
+ sd->speed = (sd->speed * 125) / 100;
+ }
+ if(sd->sc_data[SC_DEFENDER].timer != -1) {
+ sd->speed = (sd->speed * (155 - sd->sc_data[SC_DEFENDER].val1*5)) / 100;
+ }
+ if( sd->sc_data[SC_DANCING].timer!=-1 ){
+ sd->speed = (int) ((double)sd->speed * (6.- 0.4 * pc_checkskill(sd, ((s_class.job == 19) ? BA_MUSICALLESSON : DC_DANCINGLESSON))));
+ }
+ if(sd->sc_data[SC_CURSE].timer!=-1)
+ sd->speed += 450;
+ if(sd->sc_data[SC_SLOWDOWN].timer!=-1)
+ sd->speed = sd->speed*150/100;
+ if(sd->sc_data[SC_SPEEDUP0].timer!=-1)
+ sd->speed -= sd->speed*25/100;
+ }
+
+ if(sd->status.option&2 && (skill = pc_checkskill(sd,RG_TUNNELDRIVE))>0 )
+ sd->speed += (100-16*skill)*DEFAULT_WALK_SPEED/100;
+ if (pc_iscarton(sd) && (skill=pc_checkskill(sd,MC_PUSHCART))>0)
+ sd->speed += (short) ((10-skill) * (DEFAULT_WALK_SPEED * 0.1));
+ else if (pc_isriding(sd)) {
+ sd->speed -= (short) ((0.25 * DEFAULT_WALK_SPEED));
+ }
+ if((skill=pc_checkskill(sd,TF_MISS))>0)
+ if(s_class.job==12)
+ sd->speed -= (short) (sd->speed *(skill*1.5)/100);
+
+ if(sd->speed_rate != 100)
+ sd->speed = sd->speed*sd->speed_rate/100;
+ if(sd->speed < 1) sd->speed = 1;
+
+ if(sd->skilltimer != -1 && (skill = pc_checkskill(sd,SA_FREECAST)) > 0) {
+ sd->prev_speed = sd->speed;
+ sd->speed = sd->speed*(175 - skill*5)/100;
+ }
+
+ if(b_speed != sd->speed)
+ clif_updatestatus(sd,SP_SPEED);
+
+ return 0;
+}
+
+/*==========================================
+ * 対象のClassを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_class(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return ((struct mob_data *)bl)->class_;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->status.class_;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ return ((struct pet_data *)bl)->class_;
+ else
+ return 0;
+}
+/*==========================================
+ * 対象の方向を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_dir(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return ((struct mob_data *)bl)->dir;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->dir;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ return ((struct pet_data *)bl)->dir;
+ else
+ return 0;
+}
+/*==========================================
+ * 対象のレベルを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_lv(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return ((struct mob_data *)bl)->level;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->status.base_level;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ return ((struct pet_data *)bl)->msd->pet.level;
+ else
+ return 0;
+}
+
+/*==========================================
+ * 対象の射程を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_range(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return mob_db[((struct mob_data *)bl)->class_].range;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->attackrange;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ return mob_db[((struct pet_data *)bl)->class_].range;
+ else
+ return 0;
+}
+/*==========================================
+ * 対象のHPを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_hp(struct block_list *bl)
+{
+ nullpo_retr(1, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return ((struct mob_data *)bl)->hp;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->status.hp;
+ else
+ return 1;
+}
+/*==========================================
+ * 対象のMHPを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_max_hp(struct block_list *bl)
+{
+ nullpo_retr(1, bl);
+
+ if(bl->type==BL_PC && ((struct map_session_data *)bl))
+ return ((struct map_session_data *)bl)->status.max_hp;
+ else {
+ struct status_change *sc_data;
+ int max_hp = 1;
+
+ if(bl->type == BL_MOB) {
+ struct mob_data *md;
+ nullpo_retr(1, md = (struct mob_data *)bl);
+ max_hp = mob_db[md->class_].max_hp;
+
+ if(battle_config.mobs_level_up) // mobs leveling up increase [Valaris]
+ max_hp += (md->level - mob_db[md->class_].lv) * status_get_vit(bl);
+
+ if(mob_db[md->class_].mexp > 0) { //MVP Monsters
+ if(battle_config.mvp_hp_rate != 100) {
+ double hp = (double)max_hp * battle_config.mvp_hp_rate / 100.0;
+ max_hp = (hp > 0x7FFFFFFF ? 0x7FFFFFFF : (int)hp);
+ }
+ }
+ else { //Common MONSTERS
+ if(battle_config.monster_hp_rate != 100) {
+ double hp = (double)max_hp * battle_config.monster_hp_rate / 100.0;
+ max_hp = (hp > 0x7FFFFFFF ? 0x7FFFFFFF : (int)hp);
+ }
+ }
+ }
+ else if(bl->type == BL_PET) {
+ struct pet_data *pd;
+ nullpo_retr(1, pd = (struct pet_data*)bl);
+ max_hp = mob_db[pd->class_].max_hp;
+
+ if(mob_db[pd->class_].mexp > 0) { //MVP Monsters
+ if(battle_config.mvp_hp_rate != 100)
+ max_hp = (max_hp * battle_config.mvp_hp_rate)/100;
+ }
+ else { //Common MONSTERS
+ if(battle_config.monster_hp_rate != 100)
+ max_hp = (max_hp * battle_config.monster_hp_rate)/100;
+ }
+ }
+
+ sc_data = status_get_sc_data(bl);
+ if(sc_data) {
+ if(sc_data[SC_APPLEIDUN].timer != -1)
+ max_hp += ((5 + sc_data[SC_APPLEIDUN].val1 * 2 + ((sc_data[SC_APPLEIDUN].val2 + 1) >> 1)
+ + sc_data[SC_APPLEIDUN].val3 / 10) * max_hp)/100;
+ if(sc_data[SC_GOSPEL].timer != -1 &&
+ sc_data[SC_GOSPEL].val4 == BCT_PARTY &&
+ sc_data[SC_GOSPEL].val3 == 4)
+ max_hp += max_hp * 25 / 100;
+ }
+ if(max_hp < 1) max_hp = 1;
+ return max_hp;
+ }
+ return 1;
+}
+/*==========================================
+ * 対象のStrを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_str(struct block_list *bl)
+{
+ int str = 0;
+ nullpo_retr(0, bl);
+
+ if (bl->type == BL_PC && ((struct map_session_data *)bl))
+ return ((struct map_session_data *)bl)->paramc[0];
+ else {
+ struct status_change *sc_data;
+ sc_data = status_get_sc_data(bl);
+
+ if(bl->type == BL_MOB && ((struct mob_data *)bl)) {
+ str = mob_db[((struct mob_data *)bl)->class_].str;
+ if(battle_config.mobs_level_up) // mobs leveling up increase [Valaris]
+ str += ((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv;
+ }
+ else if(bl->type == BL_PET && ((struct pet_data *)bl))
+ str = mob_db[((struct pet_data *)bl)->class_].str;
+
+ if(sc_data) {
+ if(sc_data[SC_LOUD].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1)
+ str += 4;
+ if( sc_data[SC_BLESSING].timer != -1){ // ブレッシング
+ int race = status_get_race(bl);
+ if(battle_check_undead(race,status_get_elem_type(bl)) || race == 6)
+ str >>= 1; // 悪 魔/不死
+ else str += sc_data[SC_BLESSING].val1; // その他
+ }
+ if(sc_data[SC_TRUESIGHT].timer!=-1) // トゥルーサイト
+ str += 5;
+ }
+ }
+ if(str < 0) str = 0;
+ return str;
+}
+/*==========================================
+ * 対象のAgiを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+
+int status_get_agi(struct block_list *bl)
+{
+ int agi=0;
+ nullpo_retr(0, bl);
+
+ if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->paramc[1];
+ else {
+ struct status_change *sc_data;
+ sc_data = status_get_sc_data(bl);
+ if(bl->type == BL_MOB && (struct mob_data *)bl) {
+ agi = mob_db[((struct mob_data *)bl)->class_].agi;
+ if(battle_config.mobs_level_up) // increase of mobs leveling up [Valaris]
+ agi += ((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv;
+ }
+ else if(bl->type == BL_PET && (struct pet_data *)bl)
+ agi = mob_db[((struct pet_data *)bl)->class_].agi;
+
+ if(sc_data) {
+ if(sc_data[SC_INCREASEAGI].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 速度増加(PCはpc.cで)
+ agi += 2 + sc_data[SC_INCREASEAGI].val1;
+ if(sc_data[SC_CONCENTRATE].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1)
+ agi += agi * (2 + sc_data[SC_CONCENTRATE].val1)/100;
+ if(sc_data[SC_DECREASEAGI].timer!=-1) // 速度減少
+ agi -= 2 + sc_data[SC_DECREASEAGI].val1;
+ if(sc_data[SC_QUAGMIRE].timer!=-1 ) { // クァグマイア
+ //agi >>= 1;
+ //int agib = agi*(sc_data[SC_QUAGMIRE].val1*10)/100;
+ //agi -= agib > 50 ? 50 : agib;
+ agi -= sc_data[SC_QUAGMIRE].val1*10;
+ }
+ if(sc_data[SC_TRUESIGHT].timer!=-1) // トゥルーサイト
+ agi += 5;
+ }
+ }
+ if(agi < 0) agi = 0;
+ return agi;
+}
+/*==========================================
+ * 対象のVitを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_vit(struct block_list *bl)
+{
+ int vit = 0;
+ nullpo_retr(0, bl);
+
+ if(bl->type == BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->paramc[2];
+ else {
+ struct status_change *sc_data;
+ sc_data = status_get_sc_data(bl);
+ if(bl->type == BL_MOB && (struct mob_data *)bl) {
+ vit = mob_db[((struct mob_data *)bl)->class_].vit;
+ if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris]
+ vit += ((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv;
+ }
+ else if(bl->type == BL_PET && (struct pet_data *)bl)
+ vit = mob_db[((struct pet_data *)bl)->class_].vit;
+ if(sc_data) {
+ if(sc_data[SC_STRIPARMOR].timer != -1)
+ vit = vit*60/100;
+ if(sc_data[SC_TRUESIGHT].timer!=-1) // トゥルーサイト
+ vit += 5;
+ }
+ }
+ if(vit < 0) vit = 0;
+ return vit;
+}
+/*==========================================
+ * 対象のIntを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_int(struct block_list *bl)
+{
+ int int_=0;
+ nullpo_retr(0, bl);
+
+ if(bl->type == BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->paramc[3];
+ else {
+ struct status_change *sc_data;
+ sc_data = status_get_sc_data(bl);
+ if(bl->type == BL_MOB && (struct mob_data *)bl){
+ int_ = mob_db[((struct mob_data *)bl)->class_].int_;
+ if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris]
+ int_ += ((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv;
+ }
+ else if(bl->type == BL_PET && (struct pet_data *)bl)
+ int_ = mob_db[((struct pet_data *)bl)->class_].int_;
+
+ if(sc_data) {
+ if(sc_data[SC_BLESSING].timer != -1){ // ブレッシング
+ int race = status_get_race(bl);
+ if(battle_check_undead(race,status_get_elem_type(bl)) || race == 6 )
+ int_ >>= 1; // 悪 魔/不死
+ else
+ int_ += sc_data[SC_BLESSING].val1; // その他
+ }
+ if(sc_data[SC_STRIPHELM].timer != -1)
+ int_ = int_*60/100;
+ if(sc_data[SC_TRUESIGHT].timer!=-1) // トゥルーサイト
+ int_ += 5;
+ }
+ }
+ if(int_ < 0) int_ = 0;
+ return int_;
+}
+/*==========================================
+ * 対象のDexを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_dex(struct block_list *bl)
+{
+ int dex = 0;
+ nullpo_retr(0, bl);
+
+ if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->paramc[4];
+ else {
+ struct status_change *sc_data;
+ sc_data = status_get_sc_data(bl);
+ if(bl->type == BL_MOB && (struct mob_data *)bl) {
+ dex = mob_db[((struct mob_data *)bl)->class_].dex;
+ if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris]
+ dex += ((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv;
+ }
+ else if(bl->type == BL_PET && (struct pet_data *)bl)
+ dex = mob_db[((struct pet_data *)bl)->class_].dex;
+
+ if(sc_data) {
+ if(sc_data[SC_CONCENTRATE].timer!=-1 && sc_data[SC_QUAGMIRE].timer == -1)
+ dex += dex*(2+sc_data[SC_CONCENTRATE].val1)/100;
+ if(sc_data[SC_BLESSING].timer != -1){ // ブレッシング
+ int race = status_get_race(bl);
+ if(battle_check_undead(race,status_get_elem_type(bl)) || race == 6 )
+ dex >>= 1; // 悪 魔/不死
+ else dex += sc_data[SC_BLESSING].val1; // その他
+ }
+ if(sc_data[SC_QUAGMIRE].timer!=-1) { // クァグマイア
+ // dex >>= 1;
+ //int dexb = dex*(sc_data[SC_QUAGMIRE].val1*10)/100;
+ //dex -= dexb > 50 ? 50 : dexb;
+ dex -= sc_data[SC_QUAGMIRE].val1*10;
+ }
+ if(sc_data[SC_TRUESIGHT].timer!=-1) // トゥルーサイト
+ dex += 5;
+ }
+ }
+ if(dex < 0) dex = 0;
+ return dex;
+}
+/*==========================================
+ * 対象のLukを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_luk(struct block_list *bl)
+{
+ int luk = 0;
+ nullpo_retr(0, bl);
+
+ if(bl->type == BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->paramc[5];
+ else {
+ struct status_change *sc_data;
+ sc_data = status_get_sc_data(bl);
+ if(bl->type == BL_MOB && (struct mob_data *)bl) {
+ luk = mob_db[((struct mob_data *)bl)->class_].luk;
+ if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris]
+ luk += ((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv;
+ }
+ else if(bl->type == BL_PET && (struct pet_data *)bl)
+ luk = mob_db[((struct pet_data *)bl)->class_].luk;
+ if(sc_data) {
+ if(sc_data[SC_GLORIA].timer!=-1) // グロリア(PCはpc.cで)
+ luk += 30;
+ if(sc_data[SC_TRUESIGHT].timer!=-1) // トゥルーサイト
+ luk += 5;
+ if(sc_data[SC_CURSE].timer!=-1) // 呪い
+ luk = 0;
+ }
+ }
+ if(luk < 0) luk = 0;
+ return luk;
+}
+
+/*==========================================
+ * 対象のFleeを返す(汎用)
+ * 戻りは整数で1以上
+ *------------------------------------------
+ */
+int status_get_flee(struct block_list *bl)
+{
+ int flee = 1;
+ nullpo_retr(1, bl);
+
+ if(bl->type == BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->flee;
+ else {
+ struct status_change *sc_data;
+ sc_data = status_get_sc_data(bl);
+ flee = status_get_agi(bl) + status_get_lv(bl);
+
+ if(sc_data){
+ if(sc_data[SC_WHISTLE].timer!=-1)
+ flee += flee*(sc_data[SC_WHISTLE].val1+sc_data[SC_WHISTLE].val2
+ +(sc_data[SC_WHISTLE].val3>>16))/100;
+ if(sc_data[SC_BLIND].timer!=-1)
+ flee -= flee*25/100;
+ if(sc_data[SC_WINDWALK].timer!=-1) // ウィンドウォーク
+ flee += flee*(sc_data[SC_WINDWALK].val2)/100;
+ if(sc_data[SC_SPIDERWEB].timer!=-1) //スパイダーウェブ
+ flee -= flee*50/100;
+ if(sc_data[SC_GOSPEL].timer!=-1) {
+ if (sc_data[SC_GOSPEL].val4 == BCT_PARTY &&
+ sc_data[SC_GOSPEL].val3 == 13)
+ flee += flee*5/100;
+ else if (sc_data[SC_GOSPEL].val4 == BCT_ENEMY &&
+ sc_data[SC_GOSPEL].val3 == 7)
+ flee = 0;
+ }
+ }
+ }
+ if(flee < 1) flee = 1;
+ return flee;
+}
+/*==========================================
+ * 対象のHitを返す(汎用)
+ * 戻りは整数で1以上
+ *------------------------------------------
+ */
+int status_get_hit(struct block_list *bl)
+{
+ int hit = 1;
+ nullpo_retr(1, bl);
+ if(bl->type == BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->hit;
+ else {
+ struct status_change *sc_data;
+ sc_data = status_get_sc_data(bl);
+ hit = status_get_dex(bl) + status_get_lv(bl);
+
+ if(sc_data) {
+ if(sc_data[SC_HUMMING].timer!=-1) //
+ hit += hit*(sc_data[SC_HUMMING].val1*2+sc_data[SC_HUMMING].val2
+ +sc_data[SC_HUMMING].val3)/100;
+ if(sc_data[SC_BLIND].timer!=-1) // 呪い
+ hit -= hit*25/100;
+ if(sc_data[SC_TRUESIGHT].timer!=-1) // トゥルーサイト
+ hit += 3*(sc_data[SC_TRUESIGHT].val1);
+ if(sc_data[SC_CONCENTRATION].timer!=-1) //コンセントレーション
+ hit += (hit*(10*(sc_data[SC_CONCENTRATION].val1)))/100;
+ if(sc_data[SC_GOSPEL].timer!=-1 &&
+ sc_data[SC_GOSPEL].val4 == BCT_PARTY &&
+ sc_data[SC_GOSPEL].val3 == 14)
+ hit += hit*5/100;
+ if(sc_data[SC_EXPLOSIONSPIRITS].timer!=-1)
+ hit += 20*sc_data[SC_EXPLOSIONSPIRITS].val1;
+ }
+ }
+ if(hit < 1) hit = 1;
+ return hit;
+}
+/*==========================================
+ * 対象の完全回避を返す(汎用)
+ * 戻りは整数で1以上
+ *------------------------------------------
+ */
+int status_get_flee2(struct block_list *bl)
+{
+ int flee2 = 1;
+ nullpo_retr(1, bl);
+
+ if(bl->type==BL_PC && (struct map_session_data *)bl){
+ return ((struct map_session_data *)bl)->flee2;
+ } else {
+ struct status_change *sc_data;
+ sc_data = status_get_sc_data(bl);
+ flee2 = status_get_luk(bl)+1;
+
+ if(sc_data) {
+ if(sc_data[SC_WHISTLE].timer!=-1)
+ flee2 += (sc_data[SC_WHISTLE].val1+sc_data[SC_WHISTLE].val2
+ +(sc_data[SC_WHISTLE].val3&0xffff))*10;
+ }
+ }
+ if(flee2 < 1) flee2 = 1;
+ return flee2;
+}
+/*==========================================
+ * 対象のクリティカルを返す(汎用)
+ * 戻りは整数で1以上
+ *------------------------------------------
+ */
+int status_get_critical(struct block_list *bl)
+{
+ int critical = 1;
+ nullpo_retr(1, bl);
+
+ if(bl->type == BL_PC && (struct map_session_data *)bl){
+ return ((struct map_session_data *)bl)->critical;
+ } else {
+ struct status_change *sc_data;
+ sc_data = status_get_sc_data(bl);
+ critical = status_get_luk(bl)*3 + 1;
+
+ if(sc_data) {
+ if(sc_data[SC_FORTUNE].timer!=-1)
+ critical += (10+sc_data[SC_FORTUNE].val1+sc_data[SC_FORTUNE].val2
+ + sc_data[SC_FORTUNE].val3)*10;
+ if(sc_data[SC_EXPLOSIONSPIRITS].timer!=-1)
+ critical += sc_data[SC_EXPLOSIONSPIRITS].val2;
+ if(sc_data[SC_TRUESIGHT].timer!=-1) //トゥルーサイト
+ critical += critical*sc_data[SC_TRUESIGHT].val1/100;
+ }
+ }
+ if(critical < 1) critical = 1;
+ return critical;
+}
+/*==========================================
+ * base_atkの取得
+ * 戻りは整数で1以上
+ *------------------------------------------
+ */
+int status_get_baseatk(struct block_list *bl)
+{
+ int batk = 1;
+ nullpo_retr(1, bl);
+
+ if(bl->type==BL_PC && (struct map_session_data *)bl) {
+ batk = ((struct map_session_data *)bl)->base_atk; //設定されているbase_atk
+ if (((struct map_session_data *)bl)->status.weapon < 16)
+ batk += ((struct map_session_data *)bl)->weapon_atk[((struct map_session_data *)bl)->status.weapon];
+ } else { //それ以外なら
+ struct status_change *sc_data;
+ int str,dstr;
+ str = status_get_str(bl); //STR
+ dstr = str/10;
+ batk = dstr*dstr + str; //base_atkを計算する
+ sc_data = status_get_sc_data(bl);
+
+ if(sc_data) { //状態異常あり
+ if(sc_data[SC_PROVOKE].timer!=-1) //PCでプロボック(SM_PROVOKE)状態
+ batk = batk*(100+2*sc_data[SC_PROVOKE].val1)/100; //base_atk増加
+ if(sc_data[SC_CURSE].timer!=-1) //呪われていたら
+ batk -= batk*25/100; //base_atkが25%減少
+ if(sc_data[SC_CONCENTRATION].timer!=-1) //コンセントレーション
+ batk += batk*(5*sc_data[SC_CONCENTRATION].val1)/100;
+ }
+ }
+ if(batk < 1) batk = 1; //base_atkは最低でも1
+ return batk;
+}
+/*==========================================
+ * 対象のAtkを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_atk(struct block_list *bl)
+{
+ int atk = 0;
+ nullpo_retr(0, bl);
+
+ if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data*)bl)->watk;
+ else {
+ struct status_change *sc_data;
+ sc_data=status_get_sc_data(bl);
+
+ if(bl->type == BL_MOB && (struct mob_data *)bl)
+ atk = mob_db[((struct mob_data*)bl)->class_].atk1;
+ else if(bl->type == BL_PET && (struct pet_data *)bl)
+ atk = mob_db[((struct pet_data*)bl)->class_].atk1;
+
+ if(sc_data) {
+ if(sc_data[SC_PROVOKE].timer!=-1)
+ atk = atk*(100+2*sc_data[SC_PROVOKE].val1)/100;
+ if(sc_data[SC_CURSE].timer!=-1)
+ atk -= atk*25/100;
+ if(sc_data[SC_CONCENTRATION].timer!=-1) //コンセントレーション
+ atk += atk*(5*sc_data[SC_CONCENTRATION].val1)/100;
+ if(sc_data[SC_EXPLOSIONSPIRITS].timer!=-1)
+ atk += (1000*sc_data[SC_EXPLOSIONSPIRITS].val1);
+ if(sc_data[SC_STRIPWEAPON].timer!=-1)
+ atk -= atk*10/100;
+
+ if(sc_data[SC_GOSPEL].timer!=-1) {
+ if (sc_data[SC_GOSPEL].val4 == BCT_PARTY &&
+ sc_data[SC_GOSPEL].val3 == 12)
+ atk += atk*8/100;
+ else if (sc_data[SC_GOSPEL].val4 == BCT_ENEMY &&
+ sc_data[SC_GOSPEL].val3 == 6)
+ atk = 0;
+ }
+ }
+ }
+ if(atk < 0) atk = 0;
+ return atk;
+}
+/*==========================================
+ * 対象の左手Atkを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_atk_(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_PC && (struct map_session_data *)bl){
+ int atk=((struct map_session_data*)bl)->watk_;
+ return atk;
+ }
+ else
+ return 0;
+}
+/*==========================================
+ * 対象のAtk2を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_atk2(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data*)bl)->watk2;
+ else {
+ struct status_change *sc_data=status_get_sc_data(bl);
+ int atk2=0;
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ atk2 = mob_db[((struct mob_data*)bl)->class_].atk2;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ atk2 = mob_db[((struct pet_data*)bl)->class_].atk2;
+ if(sc_data) {
+ if( sc_data[SC_IMPOSITIO].timer!=-1)
+ atk2 += sc_data[SC_IMPOSITIO].val1*5;
+ if( sc_data[SC_PROVOKE].timer!=-1 )
+ atk2 = atk2*(100+2*sc_data[SC_PROVOKE].val1)/100;
+ if( sc_data[SC_CURSE].timer!=-1 )
+ atk2 -= atk2*25/100;
+ if(sc_data[SC_DRUMBATTLE].timer!=-1)
+ atk2 += sc_data[SC_DRUMBATTLE].val2;
+ if(sc_data[SC_NIBELUNGEN].timer!=-1 && (status_get_element(bl)/10) >= 8 )
+ atk2 += sc_data[SC_NIBELUNGEN].val3;
+ if(sc_data[SC_STRIPWEAPON].timer!=-1)
+ atk2 = atk2*sc_data[SC_STRIPWEAPON].val2/100;
+ if(sc_data[SC_CONCENTRATION].timer!=-1) //コンセントレーション
+ atk2 += atk2*(5*sc_data[SC_CONCENTRATION].val1)/100;
+ if(sc_data[SC_EXPLOSIONSPIRITS].timer!=-1)
+ atk2 += (1000*sc_data[SC_EXPLOSIONSPIRITS].val1);
+ }
+ if(atk2 < 0) atk2 = 0;
+ return atk2;
+ }
+ return 0;
+}
+/*==========================================
+ * 対象の左手Atk2を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_atk_2(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data*)bl)->watk_2;
+ else
+ return 0;
+}
+/*==========================================
+ * 対象のMAtk1を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_matk1(struct block_list *bl)
+{
+ int matk = 0;
+ nullpo_retr(0, bl);
+
+ if(bl->type == BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->matk1;
+ else {
+ struct status_change *sc_data;
+ int int_ = status_get_int(bl);
+ matk = int_+(int_/5)*(int_/5);
+
+ sc_data = status_get_sc_data(bl);
+ if(sc_data) {
+ if(sc_data[SC_MINDBREAKER].timer!=-1)
+ matk = matk*(100+2*sc_data[SC_MINDBREAKER].val1)/100;
+ }
+ }
+ return matk;
+}
+/*==========================================
+ * 対象のMAtk2を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_matk2(struct block_list *bl)
+{
+ int matk = 0;
+ nullpo_retr(0, bl);
+
+ if(bl->type == BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->matk2;
+ else {
+ struct status_change *sc_data = status_get_sc_data(bl);
+ int int_ = status_get_int(bl);
+ matk = int_+(int_/7)*(int_/7);
+
+ if(sc_data) {
+ if(sc_data[SC_MINDBREAKER].timer!=-1)
+ matk = matk*(100+2*sc_data[SC_MINDBREAKER].val1)/100;
+ }
+ }
+ return matk;
+}
+/*==========================================
+ * 対象のDefを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_def(struct block_list *bl)
+{
+ struct status_change *sc_data;
+ int def=0,skilltimer=-1,skillid=0;
+
+ nullpo_retr(0, bl);
+ sc_data=status_get_sc_data(bl);
+ if(bl->type==BL_PC && (struct map_session_data *)bl){
+ def = ((struct map_session_data *)bl)->def;
+ skilltimer = ((struct map_session_data *)bl)->skilltimer;
+ skillid = ((struct map_session_data *)bl)->skillid;
+ }
+ else if(bl->type==BL_MOB && (struct mob_data *)bl) {
+ def = mob_db[((struct mob_data *)bl)->class_].def;
+ skilltimer = ((struct mob_data *)bl)->skilltimer;
+ skillid = ((struct mob_data *)bl)->skillid;
+ }
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ def = mob_db[((struct pet_data *)bl)->class_].def;
+
+ if(def < 1000000) {
+ if(sc_data) {
+ //凍結、石化時は右シフト
+ if(sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0))
+ def >>= 1;
+
+ if (bl->type != BL_PC) {
+ //キーピング時はDEF100
+ if( sc_data[SC_KEEPING].timer!=-1)
+ def = 100;
+ //プロボック時は減算
+ if( sc_data[SC_PROVOKE].timer!=-1)
+ def = (def*(100 - 6*sc_data[SC_PROVOKE].val1)+50)/100;
+ //戦太鼓の響き時は加算
+ if( sc_data[SC_DRUMBATTLE].timer!=-1)
+ def += sc_data[SC_DRUMBATTLE].val3;
+ //毒にかかっている時は減算
+ if(sc_data[SC_POISON].timer!=-1)
+ def = def*75/100;
+ //ストリップシールド時は減算
+ if(sc_data[SC_STRIPSHIELD].timer!=-1)
+ def = def*sc_data[SC_STRIPSHIELD].val2/100;
+ //シグナムクルシス時は減算
+ if(sc_data[SC_SIGNUMCRUCIS].timer!=-1)
+ def = def * (100 - sc_data[SC_SIGNUMCRUCIS].val2)/100;
+ //永遠の混沌時はDEF0になる
+ if(sc_data[SC_ETERNALCHAOS].timer!=-1)
+ def = 0;
+ //コンセントレーション時は減算
+ if( sc_data[SC_CONCENTRATION].timer!=-1)
+ def = (def*(100 - 5*sc_data[SC_CONCENTRATION].val1))/100;
+
+ if(sc_data[SC_GOSPEL].timer!=-1) {
+ if (sc_data[SC_GOSPEL].val4 == BCT_PARTY &&
+ sc_data[SC_GOSPEL].val3 == 11)
+ def += def*25/100;
+ else if (sc_data[SC_GOSPEL].val4 == BCT_ENEMY &&
+ sc_data[SC_GOSPEL].val3 == 5)
+ def = 0;
+ }
+ if(sc_data[SC_JOINTBEAT].timer!=-1) {
+ if (sc_data[SC_JOINTBEAT].val2 == 4)
+ def -= def*50/100;
+ else if (sc_data[SC_JOINTBEAT].val2 == 5)
+ def -= def*25/100;
+ }
+ }
+ }
+ //詠唱中は詠唱時減算率に基づいて減算
+ if(skilltimer != -1) {
+ int def_rate = skill_get_castdef(skillid);
+ if(def_rate != 0)
+ def = (def * (100 - def_rate))/100;
+ }
+ }
+ if(def < 0) def = 0;
+ return def;
+}
+/*==========================================
+ * 対象のMDefを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_mdef(struct block_list *bl)
+{
+ struct status_change *sc_data;
+ int mdef=0;
+
+ nullpo_retr(0, bl);
+ sc_data=status_get_sc_data(bl);
+ if(bl->type==BL_PC && (struct map_session_data *)bl)
+ mdef = ((struct map_session_data *)bl)->mdef;
+ else if(bl->type==BL_MOB && (struct mob_data *)bl)
+ mdef = mob_db[((struct mob_data *)bl)->class_].mdef;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ mdef = mob_db[((struct pet_data *)bl)->class_].mdef;
+
+ if(mdef < 1000000) {
+ if(sc_data) {
+ //バリアー状態時はMDEF100
+ if(sc_data[SC_BARRIER].timer != -1)
+ mdef = 100;
+ //凍結、石化時は1.25倍
+ if(sc_data[SC_FREEZE].timer != -1 || (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0))
+ mdef = mdef*125/100;
+ if( sc_data[SC_MINDBREAKER].timer!=-1 && bl->type != BL_PC)
+ mdef -= (mdef*6*sc_data[SC_MINDBREAKER].val1)/100;
+ }
+ }
+ if(mdef < 0) mdef = 0;
+ return mdef;
+}
+/*==========================================
+ * 対象のDef2を返す(汎用)
+ * 戻りは整数で1以上
+ *------------------------------------------
+ */
+int status_get_def2(struct block_list *bl)
+{
+ int def2 = 1;
+ nullpo_retr(1, bl);
+
+ if(bl->type==BL_PC)
+ return ((struct map_session_data *)bl)->def2;
+ else {
+ struct status_change *sc_data;
+
+ if(bl->type==BL_MOB)
+ def2 = mob_db[((struct mob_data *)bl)->class_].vit;
+ else if(bl->type==BL_PET)
+ def2 = mob_db[((struct pet_data *)bl)->class_].vit;
+
+ sc_data = status_get_sc_data(bl);
+ if(sc_data) {
+ if(sc_data[SC_ANGELUS].timer != -1)
+ def2 = def2*(110+5*sc_data[SC_ANGELUS].val1)/100;
+ if(sc_data[SC_PROVOKE].timer!=-1)
+ def2 = (def2*(100 - 6*sc_data[SC_PROVOKE].val1)+50)/100;
+ if(sc_data[SC_POISON].timer!=-1)
+ def2 = def2*75/100;
+ //コンセントレーション時は減算
+ if( sc_data[SC_CONCENTRATION].timer!=-1)
+ def2 = def2*(100 - 5*sc_data[SC_CONCENTRATION].val1)/100;
+
+ if(sc_data[SC_GOSPEL].timer!=-1) {
+ if (sc_data[SC_GOSPEL].val4 == BCT_PARTY &&
+ sc_data[SC_GOSPEL].val3 == 11)
+ def2 += def2*25/100;
+ else if (sc_data[SC_GOSPEL].val4 == BCT_ENEMY &&
+ sc_data[SC_GOSPEL].val3 == 5)
+ def2 = 0;
+ }
+ }
+ }
+ if(def2 < 1) def2 = 1;
+ return def2;
+}
+/*==========================================
+ * 対象のMDef2を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int status_get_mdef2(struct block_list *bl)
+{
+ int mdef2 = 0;
+ nullpo_retr(0, bl);
+
+ if(bl->type == BL_PC)
+ return ((struct map_session_data *)bl)->mdef2 + (((struct map_session_data *)bl)->paramc[2]>>1);
+ else {
+ struct status_change *sc_data = status_get_sc_data(bl);
+ if(bl->type == BL_MOB)
+ mdef2 = mob_db[((struct mob_data *)bl)->class_].int_ + (mob_db[((struct mob_data *)bl)->class_].vit>>1);
+ else if(bl->type == BL_PET)
+ mdef2 = mob_db[((struct pet_data *)bl)->class_].int_ + (mob_db[((struct pet_data *)bl)->class_].vit>>1);
+ if(sc_data) {
+ if(sc_data[SC_MINDBREAKER].timer!=-1)
+ mdef2 -= (mdef2*6*sc_data[SC_MINDBREAKER].val1)/100;
+ }
+ }
+ if(mdef2 < 0) mdef2 = 0;
+ return mdef2;
+}
+/*==========================================
+ * 対象のSpeed(移動速度)を返す(汎用)
+ * 戻りは整数で1以上
+ * Speedは小さいほうが移動速度が速い
+ *------------------------------------------
+ */
+int status_get_speed(struct block_list *bl)
+{
+ nullpo_retr(1000, bl);
+ if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->speed;
+ else {
+ struct status_change *sc_data=status_get_sc_data(bl);
+ int speed = 1000;
+ if(bl->type==BL_MOB && (struct mob_data *)bl) {
+ speed = ((struct mob_data *)bl)->speed;
+ if(battle_config.mobs_level_up) // increase from mobs leveling up [Valaris]
+ speed-=((struct mob_data *)bl)->level - mob_db[((struct mob_data *)bl)->class_].lv;
+ }
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ speed = ((struct pet_data *)bl)->msd->petDB->speed;
+
+ if(sc_data) {
+ //速度増加時は25%減算
+ if(sc_data[SC_INCREASEAGI].timer!=-1)
+ speed -= speed*25/100;
+ //ウィンドウォーク時はLv*2%減算
+ else if(sc_data[SC_WINDWALK].timer!=-1)
+ speed -= (speed*(sc_data[SC_WINDWALK].val1*2))/100;
+ //速度減少時は25%加算
+ if(sc_data[SC_DECREASEAGI].timer!=-1)
+ speed = speed*125/100;
+ //クァグマイア時は50%加算
+ if(sc_data[SC_QUAGMIRE].timer!=-1)
+ speed = speed*3/2;
+ //私を忘れないで…時は加算
+ if(sc_data[SC_DONTFORGETME].timer!=-1)
+ speed = speed*(100+sc_data[SC_DONTFORGETME].val1*2 + sc_data[SC_DONTFORGETME].val2 + (sc_data[SC_DONTFORGETME].val3&0xffff))/100;
+ //金剛時は25%加算
+ if(sc_data[SC_STEELBODY].timer!=-1)
+ speed = speed*125/100;
+ //ディフェンダー時は加算
+ if(sc_data[SC_DEFENDER].timer!=-1)
+ speed = (speed * (155 - sc_data[SC_DEFENDER].val1*5)) / 100;
+ //踊り状態は4倍遅い
+ if(sc_data[SC_DANCING].timer!=-1 )
+ speed *= 6;
+ //呪い時は450加算
+ if(sc_data[SC_CURSE].timer!=-1)
+ speed = speed + 450;
+ if(sc_data[SC_SLOWDOWN].timer!=-1)
+ speed = speed*150/100;
+ if(sc_data[SC_SPEEDUP0].timer!=-1)
+ speed -= speed*25/100;
+ if(sc_data[SC_GOSPEL].timer!=-1 &&
+ sc_data[SC_GOSPEL].val4 == BCT_ENEMY &&
+ sc_data[SC_GOSPEL].val3 == 8)
+ speed = speed*125/100;
+ if(sc_data[SC_JOINTBEAT].timer!=-1) {
+ if (sc_data[SC_JOINTBEAT].val2 == 1)
+ speed = speed*150/100;
+ else if (sc_data[SC_JOINTBEAT].val2 == 3)
+ speed = speed*130/100;
+ }
+ }
+ if(speed < 1) speed = 1;
+ return speed;
+ }
+
+ return 1000;
+}
+/*==========================================
+ * 対象のaDelay(攻撃時ディレイ)を返す(汎用)
+ * aDelayは小さいほうが攻撃速度が速い
+ *------------------------------------------
+ */
+int status_get_adelay(struct block_list *bl)
+{
+ nullpo_retr(4000, bl);
+ if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return (((struct map_session_data *)bl)->aspd<<1);
+ else {
+ struct status_change *sc_data=status_get_sc_data(bl);
+ int adelay=4000,aspd_rate = 100,i;
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ adelay = mob_db[((struct mob_data *)bl)->class_].adelay;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ adelay = mob_db[((struct pet_data *)bl)->class_].adelay;
+
+ if(sc_data) {
+ //ツーハンドクイッケン使用時でクァグマイアでも私を忘れないで…でもない時は3割減算
+ if(sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
+ aspd_rate -= 30;
+ //アドレナリンラッシュ使用時でツーハンドクイッケンでもクァグマイアでも私を忘れないで…でもない時は
+ if(sc_data[SC_ADRENALINE].timer != -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 &&
+ sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) { // アドレナリンラッシュ
+ //使用者とパーティメンバーで格差が出る設定でなければ3割減算
+ if(sc_data[SC_ADRENALINE].val2 || !battle_config.party_skill_penalty)
+ aspd_rate -= 30;
+ //そうでなければ2.5割減算
+ else
+ aspd_rate -= 25;
+ }
+ //スピアクィッケン時は減算
+ if(sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 &&
+ sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // スピアクィッケン
+ aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2;
+ //夕日のアサシンクロス時は減算
+ if(sc_data[SC_ASSNCROS].timer!=-1 && // 夕陽のアサシンクロス
+ sc_data[SC_TWOHANDQUICKEN].timer==-1 && sc_data[SC_ADRENALINE].timer==-1 && sc_data[SC_SPEARSQUICKEN].timer==-1 &&
+ sc_data[SC_DONTFORGETME].timer == -1)
+ aspd_rate -= 5+sc_data[SC_ASSNCROS].val1+sc_data[SC_ASSNCROS].val2+sc_data[SC_ASSNCROS].val3;
+ //私を忘れないで…時は加算
+ if(sc_data[SC_DONTFORGETME].timer!=-1) // 私を忘れないで
+ aspd_rate += sc_data[SC_DONTFORGETME].val1*3 + sc_data[SC_DONTFORGETME].val2 + (sc_data[SC_DONTFORGETME].val3>>16);
+ //金剛時25%加算
+ if(sc_data[SC_STEELBODY].timer!=-1) // 金剛
+ aspd_rate += 25;
+ //増速ポーション使用時は減算
+ if( sc_data[i=SC_SPEEDPOTION3].timer!=-1 || sc_data[i=SC_SPEEDPOTION2].timer!=-1 || sc_data[i=SC_SPEEDPOTION1].timer!=-1 || sc_data[i=SC_SPEEDPOTION0].timer!=-1)
+ aspd_rate -= sc_data[i].val2;
+ //ディフェンダー時は加算
+ if(sc_data[SC_DEFENDER].timer != -1)
+ aspd_rate += (25 - sc_data[SC_DEFENDER].val1*5);
+ //adelay += (1100 - sc_data[SC_DEFENDER].val1*100);
+ if(sc_data[SC_GOSPEL].timer!=-1 &&
+ sc_data[SC_GOSPEL].val4 == BCT_ENEMY &&
+ sc_data[SC_GOSPEL].val3 == 8)
+ aspd_rate = aspd_rate*125/100;
+ if(sc_data[SC_JOINTBEAT].timer!=-1) {
+ if (sc_data[SC_JOINTBEAT].val2 == 2)
+ aspd_rate = aspd_rate*125/100;
+ else if (sc_data[SC_JOINTBEAT].val2 == 3)
+ aspd_rate = aspd_rate*110/100;
+ }
+ }
+ if(aspd_rate != 100)
+ adelay = adelay*aspd_rate/100;
+ if(adelay < battle_config.monster_max_aspd<<1) adelay = battle_config.monster_max_aspd<<1;
+ return adelay;
+ }
+ return 4000;
+}
+int status_get_amotion(struct block_list *bl)
+{
+ nullpo_retr(2000, bl);
+ if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->amotion;
+ else {
+ struct status_change *sc_data=status_get_sc_data(bl);
+ int amotion=2000,aspd_rate = 100,i;
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ amotion = mob_db[((struct mob_data *)bl)->class_].amotion;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ amotion = mob_db[((struct pet_data *)bl)->class_].amotion;
+
+ if(sc_data) {
+ if(sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
+ aspd_rate -= 30;
+ if(sc_data[SC_ADRENALINE].timer != -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 &&
+ sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) { // アドレナリンラッシュ
+ if(sc_data[SC_ADRENALINE].val2 || !battle_config.party_skill_penalty)
+ aspd_rate -= 30;
+ else
+ aspd_rate -= 25;
+ }
+ if(sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 &&
+ sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // スピアクィッケン
+ aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2;
+ if(sc_data[SC_ASSNCROS].timer!=-1 && // 夕陽のアサシンクロス
+ sc_data[SC_TWOHANDQUICKEN].timer==-1 && sc_data[SC_ADRENALINE].timer==-1 && sc_data[SC_SPEARSQUICKEN].timer==-1 &&
+ sc_data[SC_DONTFORGETME].timer == -1)
+ aspd_rate -= 5+sc_data[SC_ASSNCROS].val1+sc_data[SC_ASSNCROS].val2+sc_data[SC_ASSNCROS].val3;
+ if(sc_data[SC_DONTFORGETME].timer!=-1) // 私を忘れないで
+ aspd_rate += sc_data[SC_DONTFORGETME].val1*3 + sc_data[SC_DONTFORGETME].val2 + (sc_data[SC_DONTFORGETME].val3>>16);
+ if(sc_data[SC_STEELBODY].timer!=-1) // 金剛
+ aspd_rate += 25;
+ if( sc_data[i=SC_SPEEDPOTION3].timer!=-1 || sc_data[i=SC_SPEEDPOTION2].timer!=-1 || sc_data[i=SC_SPEEDPOTION1].timer!=-1 || sc_data[i=SC_SPEEDPOTION0].timer!=-1)
+ aspd_rate -= sc_data[i].val2;
+ if(sc_data[SC_DEFENDER].timer != -1)
+ aspd_rate += (25 - sc_data[SC_DEFENDER].val1*5);
+ //amotion += (550 - sc_data[SC_DEFENDER].val1*50);
+ }
+ if(aspd_rate != 100)
+ amotion = amotion*aspd_rate/100;
+ if(amotion < battle_config.monster_max_aspd) amotion = battle_config.monster_max_aspd;
+ return amotion;
+ }
+ return 2000;
+}
+int status_get_dmotion(struct block_list *bl)
+{
+ int ret;
+ struct status_change *sc_data;
+
+ nullpo_retr(0, bl);
+ sc_data = status_get_sc_data(bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl){
+ ret=mob_db[((struct mob_data *)bl)->class_].dmotion;
+ if(battle_config.monster_damage_delay_rate != 100)
+ ret = ret*battle_config.monster_damage_delay_rate/400;
+ }
+ else if(bl->type==BL_PC && (struct map_session_data *)bl){
+ ret=((struct map_session_data *)bl)->dmotion;
+ if(battle_config.pc_damage_delay_rate != 100)
+ ret = ret*battle_config.pc_damage_delay_rate/400;
+ }
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ ret=mob_db[((struct pet_data *)bl)->class_].dmotion;
+ else
+ return 2000;
+
+ if((sc_data && (sc_data[SC_ENDURE].timer!=-1 || sc_data[SC_BERSERK].timer!=-1)) ||
+ (bl->type == BL_PC && ((struct map_session_data *)bl)->special_state.infinite_endure))
+ ret=0;
+
+ return ret;
+}
+int status_get_element(struct block_list *bl)
+{
+ int ret = 20;
+ struct status_change *sc_data;
+
+ nullpo_retr(ret, bl);
+ sc_data = status_get_sc_data(bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl) // 10の位=Lv*2、1の位=属性
+ ret=((struct mob_data *)bl)->def_ele;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ ret=20+((struct map_session_data *)bl)->def_ele; // 防御属性Lv1
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ ret = mob_db[((struct pet_data *)bl)->class_].element;
+
+ if(sc_data) {
+ if( sc_data[SC_BENEDICTIO].timer!=-1 ) // 聖体降福
+ ret=26;
+ if( sc_data[SC_FREEZE].timer!=-1 ) // 凍結
+ ret=21;
+ if( sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0)
+ ret=22;
+ }
+
+ return ret;
+}
+
+int status_get_attack_element(struct block_list *bl)
+{
+ int ret = 0;
+ struct status_change *sc_data=status_get_sc_data(bl);
+
+ nullpo_retr(0, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ ret=0;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ ret=((struct map_session_data *)bl)->atk_ele;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ ret=0;
+
+ if(sc_data) {
+ if( sc_data[SC_FROSTWEAPON].timer!=-1) // フロストウェポン
+ ret=1;
+ if( sc_data[SC_SEISMICWEAPON].timer!=-1) // サイズミックウェポン
+ ret=2;
+ if( sc_data[SC_FLAMELAUNCHER].timer!=-1) // フレームランチャー
+ ret=3;
+ if( sc_data[SC_LIGHTNINGLOADER].timer!=-1) // ライトニングローダー
+ ret=4;
+ if( sc_data[SC_ENCPOISON].timer!=-1) // エンチャントポイズン
+ ret=5;
+ if( sc_data[SC_ASPERSIO].timer!=-1) // アスペルシオ
+ ret=6;
+ }
+
+ return ret;
+}
+int status_get_attack_element2(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_PC && (struct map_session_data *)bl) {
+ int ret = ((struct map_session_data *)bl)->atk_ele_;
+ struct status_change *sc_data = ((struct map_session_data *)bl)->sc_data;
+
+ if(sc_data) {
+ if( sc_data[SC_FROSTWEAPON].timer!=-1) // フロストウェポン
+ ret=1;
+ if( sc_data[SC_SEISMICWEAPON].timer!=-1) // サイズミックウェポン
+ ret=2;
+ if( sc_data[SC_FLAMELAUNCHER].timer!=-1) // フレームランチャー
+ ret=3;
+ if( sc_data[SC_LIGHTNINGLOADER].timer!=-1) // ライトニングローダー
+ ret=4;
+ if( sc_data[SC_ENCPOISON].timer!=-1) // エンチャントポイズン
+ ret=5;
+ if( sc_data[SC_ASPERSIO].timer!=-1) // アスペルシオ
+ ret=6;
+ }
+ return ret;
+ }
+ return 0;
+}
+int status_get_party_id(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->status.party_id;
+ else if(bl->type==BL_MOB && (struct mob_data *)bl){
+ struct mob_data *md=(struct mob_data *)bl;
+ if( md->master_id>0 )
+ return -md->master_id;
+ return -md->bl.id;
+ }
+ else if(bl->type==BL_SKILL && (struct skill_unit *)bl)
+ return ((struct skill_unit *)bl)->group->party_id;
+ else
+ return 0;
+}
+int status_get_guild_id(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data *)bl)->status.guild_id;
+ else if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return ((struct mob_data *)bl)->class_;
+ else if(bl->type==BL_SKILL && (struct skill_unit *)bl)
+ return ((struct skill_unit *)bl)->group->guild_id;
+ else
+ return 0;
+}
+int status_get_race(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return mob_db[((struct mob_data *)bl)->class_].race;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return 7;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ return mob_db[((struct pet_data *)bl)->class_].race;
+ else
+ return 0;
+}
+int status_get_size(struct block_list *bl)
+{
+ nullpo_retr(1, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return mob_db[((struct mob_data *)bl)->class_].size;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ return mob_db[((struct pet_data *)bl)->class_].size;
+ else if(bl->type==BL_PC) {
+ struct map_session_data *sd = (struct map_session_data *)bl;
+ //if (pc_isriding(sd)) // fact or rumour?
+ // return 2;
+ if (pc_calc_upper(sd->status.class_) == 2)
+ return 0;
+ return 1;
+ } else
+ return 1;
+}
+int status_get_mode(struct block_list *bl)
+{
+ nullpo_retr(0x01, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return mob_db[((struct mob_data *)bl)->class_].mode;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ return mob_db[((struct pet_data *)bl)->class_].mode;
+ else
+ return 0x01; // とりあえず動くということで1
+}
+
+int status_get_mexp(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return mob_db[((struct mob_data *)bl)->class_].mexp;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ return mob_db[((struct pet_data *)bl)->class_].mexp;
+ else
+ return 0;
+}
+int status_get_race2(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type == BL_MOB && (struct mob_data *)bl)
+ return mob_db[((struct mob_data *)bl)->class_].race2;
+ else if(bl->type==BL_PET && (struct pet_data *)bl)
+ return mob_db[((struct pet_data *)bl)->class_].race2;
+ else
+ return 0;
+}
+int status_isdead(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type == BL_MOB && (struct mob_data *)bl)
+ return ((struct mob_data *)bl)->state.state == MS_DEAD;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return pc_isdead((struct map_session_data *)bl);
+ else
+ return 0;
+}
+
+// StatusChange系の所得
+struct status_change *status_get_sc_data(struct block_list *bl)
+{
+ nullpo_retr(NULL, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return ((struct mob_data*)bl)->sc_data;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return ((struct map_session_data*)bl)->sc_data;
+ return NULL;
+}
+short *status_get_sc_count(struct block_list *bl)
+{
+ nullpo_retr(NULL, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return &((struct mob_data*)bl)->sc_count;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return &((struct map_session_data*)bl)->sc_count;
+ return NULL;
+}
+short *status_get_opt1(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return &((struct mob_data*)bl)->opt1;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return &((struct map_session_data*)bl)->opt1;
+ else if(bl->type==BL_NPC && (struct npc_data *)bl)
+ return &((struct npc_data*)bl)->opt1;
+ return 0;
+}
+short *status_get_opt2(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return &((struct mob_data*)bl)->opt2;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return &((struct map_session_data*)bl)->opt2;
+ else if(bl->type==BL_NPC && (struct npc_data *)bl)
+ return &((struct npc_data*)bl)->opt2;
+ return 0;
+}
+short *status_get_opt3(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return &((struct mob_data*)bl)->opt3;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return &((struct map_session_data*)bl)->opt3;
+ else if(bl->type==BL_NPC && (struct npc_data *)bl)
+ return &((struct npc_data*)bl)->opt3;
+ return 0;
+}
+short *status_get_option(struct block_list *bl)
+{
+ nullpo_retr(0, bl);
+ if(bl->type==BL_MOB && (struct mob_data *)bl)
+ return &((struct mob_data*)bl)->option;
+ else if(bl->type==BL_PC && (struct map_session_data *)bl)
+ return &((struct map_session_data*)bl)->status.option;
+ else if(bl->type==BL_NPC && (struct npc_data *)bl)
+ return &((struct npc_data*)bl)->option;
+ return 0;
+}
+
+int status_get_sc_def(struct block_list *bl, int type)
+{
+ int sc_def;
+ nullpo_retr(0, bl);
+
+ switch (type)
+ {
+ case SP_MDEF1: // mdef
+ sc_def = 100 - (3 + status_get_mdef(bl) + status_get_luk(bl)/3);
+ break;
+ case SP_MDEF2: // int
+ sc_def = 100 - (3 + status_get_int(bl) + status_get_luk(bl)/3);
+ break;
+ case SP_DEF1: // def
+ sc_def = 100 - (3 + status_get_def(bl) + status_get_luk(bl)/3);
+ break;
+ case SP_DEF2: // vit
+ sc_def = 100 - (3 + status_get_vit(bl) + status_get_luk(bl)/3);
+ break;
+ case SP_LUK: // luck
+ sc_def = 100 - (3 + status_get_luk(bl));
+ break;
+
+ case SC_STONE:
+ case SC_FREEZE:
+ sc_def = 100 - (3 + status_get_mdef(bl) + status_get_luk(bl)/3);
+ break;
+ case SC_STAN:
+ case SC_POISON:
+ case SC_SILENCE:
+ sc_def = 100 - (3 + status_get_vit(bl) + status_get_luk(bl)/3);
+ break;
+ case SC_SLEEP:
+ case SC_CONFUSION:
+ case SC_BLIND:
+ sc_def = 100 - (3 + status_get_int(bl) + status_get_luk(bl)/3);
+ break;
+ case SC_CURSE:
+ sc_def = 100 - (3 + status_get_luk(bl));
+ break;
+
+ default:
+ sc_def = 100;
+ break;
+ }
+
+ if(bl->type == BL_MOB) {
+ struct mob_data *md = (struct mob_data *)bl;
+ if (md && md->class_ == 1288)
+ return 0;
+ if (sc_def < 50)
+ sc_def = 50;
+ } else if(bl->type == BL_PC) {
+ struct status_change* sc_data = status_get_sc_data(bl);
+ if (sc_data && sc_data[SC_GOSPEL].timer != -1 &&
+ sc_data[SC_GOSPEL].val4 == BCT_PARTY &&
+ sc_data[SC_GOSPEL].val3 == 3)
+ sc_def -= 25;
+ }
+
+ return (sc_def < 0) ? 0 : sc_def;
+}
+
+/*==========================================
+ * ステータス異常開始
+ *------------------------------------------
+ */
+int status_change_start(struct block_list *bl,int type,int val1,int val2,int val3,int val4,int tick,int flag)
+{
+ struct map_session_data *sd = NULL;
+ struct status_change* sc_data;
+ short *sc_count, *option, *opt1, *opt2, *opt3;
+ int opt_flag = 0, calc_flag = 0,updateflag = 0, save_flag = 0, race, mode, elem, undead_flag;
+ int scdef = 0;
+ int type2 = type;
+
+ nullpo_retr(0, bl);
+ if(bl->type == BL_SKILL)
+ return 0;
+ if(bl->type == BL_MOB)
+ if (status_isdead(bl)) return 0;
+
+ nullpo_retr(0, sc_data=status_get_sc_data(bl));
+ nullpo_retr(0, sc_count=status_get_sc_count(bl));
+ nullpo_retr(0, option=status_get_option(bl));
+ nullpo_retr(0, opt1=status_get_opt1(bl));
+ nullpo_retr(0, opt2=status_get_opt2(bl));
+ nullpo_retr(0, opt3=status_get_opt3(bl));
+
+
+ race=status_get_race(bl);
+ mode=status_get_mode(bl);
+ elem=status_get_elem_type(bl);
+ undead_flag=battle_check_undead(race,elem);
+
+ if(type == SC_AETERNA && (sc_data[SC_STONE].timer != -1 || sc_data[SC_FREEZE].timer != -1) )
+ return 0;
+
+ switch(type){
+ case SC_STONE:
+ case SC_FREEZE:
+ scdef=3+status_get_mdef(bl)+status_get_luk(bl)/3;
+ break;
+ case SC_STAN:
+ case SC_SILENCE:
+ case SC_POISON:
+ case SC_DPOISON:
+ scdef=3+status_get_vit(bl)+status_get_luk(bl)/3;
+ break;
+ case SC_SLEEP:
+ case SC_BLIND:
+ scdef=3+status_get_int(bl)+status_get_luk(bl)/3;
+ break;
+ case SC_CURSE:
+ scdef=3+status_get_luk(bl);
+ break;
+
+// case SC_CONFUSION:
+ default:
+ scdef=0;
+ }
+ if(scdef>=100)
+ return 0;
+ if(bl->type==BL_PC){
+ sd=(struct map_session_data *)bl;
+ if( sd && type == SC_ADRENALINE && !(skill_get_weapontype(BS_ADRENALINE)&(1<<sd->status.weapon)))
+ return 0;
+
+ if(SC_STONE<=type && type<=SC_BLIND){ /* カ?ドによる耐性 */
+ if( sd && sd->reseff[type-SC_STONE] > 0 && rand()%10000<sd->reseff[type-SC_STONE]){
+ if(battle_config.battle_log)
+ printf("PC %d skill_sc_start: cardによる異常耐性?動\n",sd->bl.id);
+ return 0;
+ }
+ }
+ }
+ else if(bl->type == BL_MOB) {
+ }
+ else {
+ if(battle_config.error_log)
+ printf("status_change_start: neither MOB nor PC !\n");
+ return 0;
+ }
+
+ if(type==SC_FREEZE && undead_flag && !(flag&1))
+ return 0;
+
+ if (type==SC_BLESSING && (bl->type==BL_PC || (!undead_flag && race!=6))) {
+ if (sc_data[SC_CURSE].timer!=-1)
+ status_change_end(bl,SC_CURSE,-1);
+ if (sc_data[SC_STONE].timer!=-1 && sc_data[SC_STONE].val2==0)
+ status_change_end(bl,SC_STONE,-1);
+ }
+
+ if((type == SC_ADRENALINE || type == SC_WEAPONPERFECTION || type == SC_OVERTHRUST) &&
+ sc_data[type].timer != -1 && sc_data[type].val2 && !val2)
+ return 0;
+
+ if(mode & 0x20 && (type==SC_STONE || type==SC_FREEZE ||
+ type==SC_STAN || type==SC_SLEEP || type==SC_SILENCE || type==SC_QUAGMIRE || type == SC_DECREASEAGI || type == SC_SIGNUMCRUCIS || type == SC_PROVOKE ||
+ (type == SC_BLESSING && (undead_flag || race == 6))) && !(flag&1)){
+ /* ボスには?かない(ただしカ?ドによる?果は適用される) */
+ return 0;
+ }
+ if(type==SC_FREEZE || type==SC_STAN || type==SC_SLEEP)
+ battle_stopwalking(bl,1);
+
+ if(sc_data[type].timer != -1){ /* すでに同じ異常になっている場合タイマ解除 */
+ if(sc_data[type].val1 > val1 && type != SC_COMBO && type != SC_DANCING && type != SC_DEVOTION &&
+ type != SC_SPEEDPOTION0 && type != SC_SPEEDPOTION1 && type != SC_SPEEDPOTION2 && type != SC_SPEEDPOTION3
+ && type != SC_ATKPOT && type != SC_MATKPOT) // added atk and matk potions [Valaris]
+ return 0;
+
+ if ((type >=SC_STAN && type <= SC_BLIND) || type == SC_DPOISON)
+ return 0;/* ?ぎ足しができない?態異常である時は?態異常を行わない */
+
+ (*sc_count)--;
+ delete_timer(sc_data[type].timer, status_change_timer);
+ sc_data[type].timer = -1;
+ }
+
+ // クアグマイア/私を忘れないで中は無効なスキル
+ if ((sc_data[SC_QUAGMIRE].timer!=-1 || sc_data[SC_DONTFORGETME].timer!=-1) &&
+ (type==SC_CONCENTRATE || type==SC_INCREASEAGI ||
+ type==SC_TWOHANDQUICKEN || type==SC_SPEARSQUICKEN ||
+ type==SC_ADRENALINE || type==SC_LOUD || type==SC_TRUESIGHT ||
+ type==SC_WINDWALK || type==SC_CARTBOOST || type==SC_ASSNCROS))
+ return 0;
+
+ switch(type){ /* 異常の種類ごとの?理 */
+ case SC_PROVOKE: /* プロボック */
+ calc_flag = 1;
+ if(tick <= 0) tick = 1000; /* (オ?トバ?サ?ク) */
+ break;
+ case SC_ENDURE: /* インデュア */
+ if(tick <= 0) tick = 1000 * 60;
+ calc_flag = 1; // for updating mdef
+#ifdef TWILIGHT
+ val2 = 40; // [Celest]
+#else
+ val2 = 7; // [Celest]
+#endif
+ break;
+ case SC_AUTOBERSERK:
+ {
+ tick = 60*1000;
+ if (bl->type == BL_PC && sd->status.hp<sd->status.max_hp>>2 &&
+ (sc_data[SC_PROVOKE].timer==-1 || sc_data[SC_PROVOKE].val2==0))
+ status_change_start(bl,SC_PROVOKE,10,1,0,0,0,0);
+ }
+ break;
+
+ case SC_CONCENTRATE: /* 集中力向上 */
+ case SC_BLESSING: /* ブレッシング */
+ case SC_ANGELUS: /* アンゼルス */
+ calc_flag = 1;
+ break;
+
+ case SC_INCREASEAGI: /* 速度上昇 */
+ calc_flag = 1;
+ if(sc_data[SC_DECREASEAGI].timer!=-1 )
+ status_change_end(bl,SC_DECREASEAGI,-1);
+ // the effect will still remain [celest]
+// if(sc_data[SC_WINDWALK].timer!=-1 ) /* ウインドウォ?ク */
+// status_change_end(bl,SC_WINDWALK,-1);
+ break;
+ case SC_DECREASEAGI: /* 速度減少 */
+ if (bl->type == BL_PC) // Celest
+ tick>>=1;
+ calc_flag = 1;
+ if(sc_data[SC_INCREASEAGI].timer!=-1 )
+ status_change_end(bl,SC_INCREASEAGI,-1);
+ if(sc_data[SC_ADRENALINE].timer!=-1 )
+ status_change_end(bl,SC_ADRENALINE,-1);
+ if(sc_data[SC_SPEARSQUICKEN].timer!=-1 )
+ status_change_end(bl,SC_SPEARSQUICKEN,-1);
+ if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 )
+ status_change_end(bl,SC_TWOHANDQUICKEN,-1);
+ break;
+ case SC_SIGNUMCRUCIS: /* シグナムクルシス */
+ calc_flag = 1;
+// val2 = 14 + val1;
+ val2 = 10 + val1*2;
+ tick = 600*1000;
+ clif_emotion(bl,4);
+ break;
+ case SC_SLOWPOISON:
+ if (sc_data[SC_POISON].timer == -1 && sc_data[SC_DPOISON].timer == -1)
+ return 0;
+ break;
+ case SC_TWOHANDQUICKEN: /* 2HQ */
+ if(sc_data[SC_DECREASEAGI].timer!=-1)
+ return 0;
+ *opt3 |= 1;
+ calc_flag = 1;
+ break;
+ case SC_ADRENALINE: /* アドレナリンラッシュ */
+ if(sc_data[SC_DECREASEAGI].timer!=-1)
+ return 0;
+ if(bl->type == BL_PC)
+ if(pc_checkskill(sd,BS_HILTBINDING)>0)
+ tick += tick / 10;
+ calc_flag = 1;
+ break;
+ case SC_WEAPONPERFECTION: /* ウェポンパ?フェクション */
+ if(bl->type == BL_PC)
+ if(pc_checkskill(sd,BS_HILTBINDING)>0)
+ tick += tick / 10;
+ break;
+ case SC_OVERTHRUST: /* オ?バ?スラスト */
+ if(bl->type == BL_PC)
+ if(pc_checkskill(sd,BS_HILTBINDING)>0)
+ tick += tick / 10;
+ *opt3 |= 2;
+ break;
+ case SC_MAXIMIZEPOWER: /* マキシマイズパワ?(SPが1減る時間,val2にも) */
+ if(bl->type == BL_PC)
+ val2 = tick;
+ else
+ tick = 5000*val1;
+ break;
+ case SC_ENCPOISON: /* エンチャントポイズン */
+ calc_flag = 1;
+ val2=(((val1 - 1) / 2) + 3)*100; /* 毒付?確率 */
+ skill_enchant_elemental_end(bl,SC_ENCPOISON);
+ break;
+ case SC_EDP: // [Celest]
+ val2 = val1 + 2; /* 猛毒付?確率(%) */
+ calc_flag = 1;
+ break;
+ case SC_POISONREACT: /* ポイズンリアクト */
+ val2=val1/2 + val1%2; // [Celest]
+ break;
+ case SC_IMPOSITIO: /* インポシティオマヌス */
+ calc_flag = 1;
+ break;
+ case SC_ASPERSIO: /* アスペルシオ */
+ skill_enchant_elemental_end(bl,SC_ASPERSIO);
+ break;
+ case SC_SUFFRAGIUM: /* サフラギム */
+ case SC_BENEDICTIO: /* 聖? */
+ case SC_MAGNIFICAT: /* マグニフィカ?ト */
+ case SC_AETERNA: /* エ?テルナ */
+ break;
+ case SC_ENERGYCOAT: /* エナジ?コ?ト */
+ *opt3 |= 4;
+ break;
+ case SC_MAGICROD:
+ val2 = val1*20;
+ break;
+ case SC_KYRIE: /* キリエエレイソン */
+ val2 = status_get_max_hp(bl) * (val1 * 2 + 10) / 100;/* 耐久度 */
+ val3 = (val1 / 2 + 5); /* 回? */
+// -- moonsoul (added to undo assumptio status if target has it)
+ if(sc_data[SC_ASSUMPTIO].timer!=-1 )
+ status_change_end(bl,SC_ASSUMPTIO,-1);
+ break;
+ case SC_MINDBREAKER:
+ calc_flag = 1;
+ if(tick <= 0) tick = 1000; /* (オ?トバ?サ?ク) */
+ case SC_GLORIA: /* グロリア */
+ calc_flag = 1;
+ break;
+ case SC_LOUD: /* ラウドボイス */
+ calc_flag = 1;
+ break;
+ case SC_TRICKDEAD: /* 死んだふり */
+ if (bl->type == BL_PC) {
+ pc_stopattack((struct map_session_data *)sd);
+ }
+ break;
+ case SC_QUAGMIRE: /* クァグマイア */
+ calc_flag = 1;
+ if(sc_data[SC_CONCENTRATE].timer!=-1 ) /* 集中力向上解除 */
+ status_change_end(bl,SC_CONCENTRATE,-1);
+ if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* 速度上昇解除 */
+ status_change_end(bl,SC_INCREASEAGI,-1);
+ if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 )
+ status_change_end(bl,SC_TWOHANDQUICKEN,-1);
+ if(sc_data[SC_SPEARSQUICKEN].timer!=-1 )
+ status_change_end(bl,SC_SPEARSQUICKEN,-1);
+ if(sc_data[SC_ADRENALINE].timer!=-1 )
+ status_change_end(bl,SC_ADRENALINE,-1);
+ if(sc_data[SC_LOUD].timer!=-1 )
+ status_change_end(bl,SC_LOUD,-1);
+ if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* トゥル?サイト */
+ status_change_end(bl,SC_TRUESIGHT,-1);
+ if(sc_data[SC_WINDWALK].timer!=-1 ) /* ウインドウォ?ク */
+ status_change_end(bl,SC_WINDWALK,-1);
+ if(sc_data[SC_CARTBOOST].timer!=-1 ) /* カ?トブ?スト */
+ status_change_end(bl,SC_CARTBOOST,-1);
+ break;
+ case SC_MAGICPOWER:
+ calc_flag = 1;
+ val2 = 1;
+ break;
+ case SC_SACRIFICE:
+ val2 = 5;
+ break;
+ case SC_FLAMELAUNCHER: /* フレ?ムランチャ? */
+ skill_enchant_elemental_end(bl,SC_FLAMELAUNCHER);
+ break;
+ case SC_FROSTWEAPON: /* フロストウェポン */
+ skill_enchant_elemental_end(bl,SC_FROSTWEAPON);
+ break;
+ case SC_LIGHTNINGLOADER: /* ライトニングロ?ダ? */
+ skill_enchant_elemental_end(bl,SC_LIGHTNINGLOADER);
+ break;
+ case SC_SEISMICWEAPON: /* サイズミックウェポン */
+ skill_enchant_elemental_end(bl,SC_SEISMICWEAPON);
+ break;
+ case SC_DEVOTION: /* ディボ?ション */
+ calc_flag = 1;
+ break;
+ case SC_PROVIDENCE: /* プロヴィデンス */
+ calc_flag = 1;
+ val2=val1*5;
+ break;
+ case SC_REFLECTSHIELD:
+ val2=10+val1*3;
+ break;
+ case SC_STRIPWEAPON:
+ if (val2==0) val2=90;
+ break;
+ case SC_STRIPSHIELD:
+ if (val2==0) val2=85;
+ break;
+ case SC_STRIPARMOR:
+ case SC_STRIPHELM:
+ case SC_CP_WEAPON:
+ case SC_CP_SHIELD:
+ case SC_CP_ARMOR:
+ case SC_CP_HELM:
+ break;
+
+ case SC_AUTOSPELL: /* オ?トスペル */
+ val4 = 5 + val1*2;
+ break;
+
+ case SC_VOLCANO:
+ calc_flag = 1;
+ val3 = val1*10;
+ //val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) );
+ break;
+ case SC_DELUGE:
+ calc_flag = 1;
+ //val3 = val1>=5?15: (val1==4?14: (val1==3?12: ( val1==2?9:5 ) ) );
+ //val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) );
+ if (sc_data[SC_FOGWALL].timer != -1 && sc_data[SC_BLIND].timer != -1)
+ status_change_end(bl,SC_BLIND,-1);
+ break;
+ case SC_VIOLENTGALE:
+ calc_flag = 1;
+ val3 = val1*3;
+ //val4 = val1>=5?20: (val1==4?19: (val1==3?17: ( val1==2?14:10 ) ) );
+ break;
+
+ case SC_SPEARSQUICKEN: /* スピアクイッケン */
+ calc_flag = 1;
+ val2 = 20+val1;
+ *opt3 |= 1;
+ break;
+ case SC_COMBO:
+ break;
+ case SC_BLADESTOP_WAIT: /* 白刃取り(待ち) */
+ break;
+ case SC_BLADESTOP: /* 白刃取り */
+ if(val2==2) clif_bladestop((struct block_list *)val3,(struct block_list *)val4,1);
+ *opt3 |= 32;
+ break;
+
+ case SC_LULLABY: /* 子守唄 */
+ val2 = 11;
+ break;
+ case SC_RICHMANKIM:
+ break;
+ case SC_ETERNALCHAOS: /* エタ?ナルカオス */
+ calc_flag = 1;
+ break;
+ case SC_DRUMBATTLE: /* ?太鼓の響き */
+ calc_flag = 1;
+ val2 = (val1+1)*25;
+ val3 = (val1+1)*2;
+ break;
+ case SC_NIBELUNGEN: /* ニ?ベルングの指輪 */
+ calc_flag = 1;
+ //val2 = (val1+2)*50;
+ val3 = (val1+2)*25;
+ break;
+ case SC_ROKISWEIL: /* ロキの叫び */
+ break;
+ case SC_INTOABYSS: /* 深淵の中に */
+ break;
+ case SC_SIEGFRIED: /* 不死身のジ?クフリ?ド */
+ calc_flag = 1;
+ val2 = 55 + val1*5;
+ val3 = val1*10;
+ break;
+ case SC_DISSONANCE: /* 不協和音 */
+ val2 = 10;
+ break;
+ case SC_WHISTLE: /* 口笛 */
+ calc_flag = 1;
+ break;
+ case SC_ASSNCROS: /* 夕陽のアサシンクロス */
+ calc_flag = 1;
+ break;
+ case SC_POEMBRAGI: /* ブラギの詩 */
+ break;
+ case SC_APPLEIDUN: /* イドゥンの林檎 */
+ calc_flag = 1;
+ break;
+ case SC_UGLYDANCE: /* 自分勝手なダンス */
+ val2 = 10;
+ break;
+ case SC_HUMMING: /* ハミング */
+ calc_flag = 1;
+ break;
+ case SC_DONTFORGETME: /* 私を忘れないで */
+ calc_flag = 1;
+ if(sc_data[SC_INCREASEAGI].timer!=-1 ) /* 速度上昇解除 */
+ status_change_end(bl,SC_INCREASEAGI,-1);
+ if(sc_data[SC_TWOHANDQUICKEN].timer!=-1 )
+ status_change_end(bl,SC_TWOHANDQUICKEN,-1);
+ if(sc_data[SC_SPEARSQUICKEN].timer!=-1 )
+ status_change_end(bl,SC_SPEARSQUICKEN,-1);
+ if(sc_data[SC_ADRENALINE].timer!=-1 )
+ status_change_end(bl,SC_ADRENALINE,-1);
+ if(sc_data[SC_ASSNCROS].timer!=-1 )
+ status_change_end(bl,SC_ASSNCROS,-1);
+ if(sc_data[SC_TRUESIGHT].timer!=-1 ) /* トゥル?サイト */
+ status_change_end(bl,SC_TRUESIGHT,-1);
+ if(sc_data[SC_WINDWALK].timer!=-1 ) /* ウインドウォ?ク */
+ status_change_end(bl,SC_WINDWALK,-1);
+ if(sc_data[SC_CARTBOOST].timer!=-1 ) /* カ?トブ?スト */
+ status_change_end(bl,SC_CARTBOOST,-1);
+ break;
+ case SC_FORTUNE: /* 幸運のキス */
+ calc_flag = 1;
+ break;
+ case SC_SERVICE4U: /* サ?ビスフォ?ユ? */
+ calc_flag = 1;
+ break;
+ case SC_MOONLIT:
+ val2 = bl->id;
+ break;
+ case SC_DANCING: /* ダンス/演奏中 */
+ calc_flag = 1;
+ val3= tick / 1000;
+ tick = 1000;
+ break;
+
+ case SC_EXPLOSIONSPIRITS: // 爆裂波動
+ calc_flag = 1;
+ val2 = 75 + 25*val1;
+ *opt3 |= 8;
+ break;
+ case SC_STEELBODY: // 金剛
+ calc_flag = 1;
+ *opt3 |= 16;
+ break;
+ case SC_EXTREMITYFIST: /* 阿修羅覇凰拳 */
+ break;
+ case SC_AUTOCOUNTER:
+ val3 = val4 = 0;
+ break;
+
+ case SC_SPEEDPOTION0: /* ?速ポ?ション */
+ case SC_SPEEDPOTION1:
+ case SC_SPEEDPOTION2:
+ case SC_SPEEDPOTION3:
+ calc_flag = 1;
+ tick = 1000 * tick;
+ val2 = 5*(2+type-SC_SPEEDPOTION0);
+ break;
+
+ /* atk & matk potions [Valaris] */
+ case SC_ATKPOT:
+ case SC_MATKPOT:
+ calc_flag = 1;
+ tick = 1000 * tick;
+ break;
+ case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
+ {
+ time_t timer;
+
+ calc_flag = 1;
+ tick = 10000;
+ if(!val2)
+ val2 = time(&timer);
+ }
+ break;
+ case SC_NOCHAT: //チャット禁止?態
+ {
+ time_t timer;
+
+ if(!battle_config.muting_players)
+ break;
+
+ tick = 60000;
+ if(!val2)
+ val2 = time(&timer);
+ updateflag = SP_MANNER;
+ save_flag = 1; // celest
+ }
+ break;
+ case SC_SELFDESTRUCTION: //自爆
+ clif_skillcasting(bl,bl->id, bl->id,0,0,331,skill_get_time(val2,val1));
+ val3 = tick / 1000;
+ tick = 1000;
+ break;
+
+ /* option1 */
+ case SC_STONE: /* 石化 */
+ if(!(flag&2)) {
+ int sc_def = status_get_mdef(bl)*200;
+ tick = tick - sc_def;
+ }
+ val3 = tick/1000;
+ if(val3 < 1) val3 = 1;
+ tick = 5000;
+ val2 = 1;
+ break;
+ case SC_SLEEP: /* 睡眠 */
+ if(!(flag&2)) {
+// int sc_def = 100 - (status_get_int(bl) + status_get_luk(bl)/3);
+// tick = tick * sc_def / 100;
+// if(tick < 1000) tick = 1000;
+ tick = 30000;//睡眠はステ?タス耐性に?わらず30秒
+ }
+ break;
+ case SC_FREEZE: /* 凍結 */
+ if(!(flag&2)) {
+ int sc_def = 100 - status_get_mdef(bl);
+ tick = tick * sc_def / 100;
+ }
+ break;
+ case SC_STAN: /* スタン(val2にミリ秒セット) */
+ if(!(flag&2)) {
+ int sc_def = status_get_sc_def_vit(bl);
+ tick = tick * sc_def / 100;
+ }
+ break;
+
+ /* option2 */
+ case SC_DPOISON: /* 猛毒 */
+ {
+ int mhp = status_get_max_hp(bl);
+ int hp = status_get_hp(bl);
+ // MHP?1/4????????
+ if (hp > mhp>>2) {
+ if(bl->type == BL_PC) {
+ int diff = mhp*10/100;
+ if (hp - diff < mhp>>2)
+ hp = hp - (mhp>>2);
+ pc_heal((struct map_session_data *)bl, -hp, 0);
+ } else if(bl->type == BL_MOB) {
+ struct mob_data *md = (struct mob_data *)bl;
+ hp -= mhp*15/100;
+ if (hp > mhp>>2)
+ md->hp = hp;
+ else
+ md->hp = mhp>>2;
+ }
+ }
+ } // fall through
+ case SC_POISON: /* 毒 */
+ calc_flag = 1;
+ if(!(flag&2)) {
+ int sc_def = 100 - (status_get_vit(bl) + status_get_luk(bl)/5);
+ tick = tick * sc_def / 100;
+ }
+ val3 = tick/1000;
+ if(val3 < 1) val3 = 1;
+ tick = 1000;
+ break;
+ case SC_SILENCE: /* 沈?(レックスデビ?ナ) */
+ if (sc_data && sc_data[SC_GOSPEL].timer!=-1) {
+ skill_delunitgroup((struct skill_unit_group *)sc_data[SC_GOSPEL].val3);
+ status_change_end(bl,SC_GOSPEL,-1);
+ break;
+ }
+ if(!(flag&2)) {
+ int sc_def = 100 - status_get_vit(bl);
+ tick = tick * sc_def / 100;
+ }
+ break;
+ case SC_CONFUSION:
+ val2 = tick;
+ tick = 100;
+ clif_emotion(bl,1);
+ if (sd) {
+ pc_stop_walking (sd, 0);
+ }
+ break;
+ case SC_BLIND: /* 暗? */
+ calc_flag = 1;
+ if(!(flag&2)) {
+ int sc_def = status_get_lv(bl)/10 + status_get_int(bl)/15;
+ tick = 30000 - sc_def;
+ }
+ break;
+ case SC_CURSE:
+ calc_flag = 1;
+ if(!(flag&2)) {
+ int sc_def = 100 - status_get_vit(bl);
+ tick = tick * sc_def / 100;
+ }
+ break;
+
+ /* option */
+ case SC_HIDING: /* ハイディング */
+ calc_flag = 1;
+ if(bl->type == BL_PC) {
+ val2 = tick / 1000; /* 持?時間 */
+ tick = 1000;
+ }
+ break;
+ case SC_CHASEWALK:
+ case SC_CLOAKING: /* クロ?キング */
+ if(bl->type == BL_PC) {
+ calc_flag = 1; // [Celest]
+ val2 = tick;
+ val3 = type==SC_CLOAKING ? 130-val1*3 : 135-val1*5;
+ }
+ else
+ tick = 5000*val1;
+ break;
+ case SC_SIGHT: /* サイト/ルアフ */
+ case SC_RUWACH:
+ val2 = tick/250;
+ tick = 10;
+ break;
+
+ /* セ?フティウォ?ル、ニュ?マ */
+ case SC_SAFETYWALL: case SC_PNEUMA:
+ tick=((struct skill_unit *)val2)->group->limit;
+ break;
+
+ /* アンクル */
+ case SC_ANKLE:
+ break;
+
+ /* スキルじゃない/時間に?係しない */
+ case SC_RIDING:
+ calc_flag = 1;
+ tick = 600*1000;
+ break;
+ case SC_FALCON:
+ case SC_WEIGHT50:
+ case SC_WEIGHT90:
+ case SC_BROKNWEAPON:
+ case SC_BROKNARMOR:
+ tick=600*1000;
+ break;
+
+ case SC_AUTOGUARD:
+ {
+ int i,t;
+ for(i=val2=0;i<val1;i++) {
+ t = 5-(i>>1);
+ val2 += (t < 0)? 1:t;
+ }
+ }
+ break;
+
+ case SC_DEFENDER:
+ calc_flag = 1;
+ val2 = 5 + val1*15;
+ break;
+
+ case SC_KEEPING:
+ case SC_BARRIER:
+ calc_flag = 1;
+
+ case SC_HALLUCINATION:
+ break;
+
+ case SC_CONCENTRATION: /* コンセントレ?ション */
+ *opt3 |= 1;
+ calc_flag = 1;
+ break;
+
+ case SC_TENSIONRELAX: /* テンションリラックス */
+ if(bl->type == BL_PC) {
+ tick = 10000;
+ } else return 0;
+ break;
+
+ case SC_AURABLADE: /* オ?ラブレ?ド */
+ case SC_PARRYING: /* パリイング */
+// case SC_ASSUMPTIO: /* */
+// case SC_HEADCRUSH: /* ヘッドクラッシュ */
+// case SC_JOINTBEAT: /* ジョイントビ?ト */
+// case SC_MARIONETTE: /* マリオネットコントロ?ル */
+
+ //とりあえず手?き
+ break;
+
+// -- moonsoul (for new upper class related skill status effects)
+/*
+ case SC_AURABLADE:
+ val2 = val1*10;
+ break;
+ case SC_PARRYING:
+ val2=val1*3;
+ break;
+ case SC_CONCENTRATION:
+ calc_flag=1;
+ val2=val1*10;
+ val3=val1*5;
+ break;
+ case SC_TENSIONRELAX:
+// val2 = 10;
+// val3 = 15;
+ break;
+ case SC_BERSERK:
+ calc_flag=1;
+ break;
+ case SC_ASSUMPTIO:
+ if(sc_data[SC_KYRIE].timer!=-1 )
+ status_change_end(bl,SC_KYRIE,-1);
+ break;*/
+
+ case SC_WINDWALK: /* ウインドウォ?ク */
+ calc_flag = 1;
+ val2 = (val1 / 2); //Flee上昇率
+ break;
+
+ case SC_JOINTBEAT: // Random break [DracoRPG]
+ calc_flag = 1;
+ val2 = rand()%6 + 1;
+ if (val2 == 6) status_change_start(bl,SC_BLEEDING,val1,0,0,0,skill_get_time2(type,val1),0);
+ break;
+
+ case SC_BERSERK: /* バ?サ?ク */
+ if(sd){
+ sd->status.hp = sd->status.max_hp * 3;
+ sd->status.sp = 0;
+ clif_updatestatus(sd,SP_HP);
+ clif_updatestatus(sd,SP_SP);
+ clif_status_change(bl,SC_INCREASEAGI,1); /* アイコン表示 */
+ sd->canregen_tick = gettick() + 300000;
+ }
+ *opt3 |= 128;
+ tick = 10000;
+ calc_flag = 1;
+ break;
+
+ case SC_ASSUMPTIO: /* アスムプティオ */
+ if(sc_data[SC_KYRIE].timer!=-1 )
+ status_change_end(bl,SC_KYRIE,-1);
+ break;
+ *opt3 |= 2048;
+ break;
+
+ case SC_BASILICA: // [celest]
+ break;
+
+ case SC_GOSPEL:
+ if (val4 == BCT_SELF) { // self effect
+ int i;
+ if (sd) {
+ sd->canact_tick += tick;
+ sd->canmove_tick += tick;
+ }
+ val2 = tick;
+ tick = 1000;
+ for (i=0; i<=26; i++) {
+ if(sc_data[i].timer!=-1)
+ status_change_end(bl,i,-1);
+ }
+ for (i=58; i<=62; i++) {
+ if(sc_data[i].timer!=-1)
+ status_change_end(bl,i,-1);
+ }
+ for (i=132; i<=136; i++) {
+ if(sc_data[i].timer!=-1)
+ status_change_end(bl,i,-1);
+ }
+ }
+ break;
+
+ case SC_MARIONETTE: /* マリオネットコントロ?ル */
+ case SC_MARIONETTE2:
+ val2 = tick;
+ if (!val3)
+ return 0;
+ tick = 1000;
+ calc_flag = 1;
+ *opt3 |= 1024;
+ break;
+
+ case SC_MELTDOWN: /* メルトダウン */
+ case SC_CARTBOOST: /* カ?トブ?スト */
+ case SC_TRUESIGHT: /* トゥル?サイト */
+ case SC_SPIDERWEB: /* スパイダ?ウェッブ */
+ calc_flag = 1;
+ break;
+
+ case SC_REJECTSWORD: /* リジェクトソ?ド */
+ val2 = 3; //3回攻?を跳ね返す
+ break;
+
+ case SC_MEMORIZE: /* メモライズ */
+ val2 = 5; //回詠唱を1/3にする
+ break;
+
+ case SC_SPLASHER: /* ベナムスプラッシャ? */
+ break;
+
+ case SC_FOGWALL:
+ break;
+
+ case SC_PRESERVE:
+ break;
+
+ case SC_BLEEDING:
+ {
+ // every 1 vit deducts 1 second
+ val3 = tick - status_get_vit(bl) * 1000;
+ // minimum 50 seconds
+ if (val3 < 50000)
+ val3 = 50000;
+ val4 = 10000;
+ tick = 1000;
+ }
+ break;
+
+ case SC_SLOWDOWN:
+ case SC_SPEEDUP0:
+ calc_flag = 1;
+ break;
+
+ case SC_REGENERATION:
+ val1 = 2;
+ case SC_BATTLEORDERS:
+ tick = 60000; // 1 minute
+ calc_flag = 1;
+ break;
+
+ case SC_GUILDAURA:
+ calc_flag = 1;
+ tick = 1000;
+ break;
+
+ case SC_BABY:
+ type2 = _SC_BABY;
+ break;
+
+ default:
+ if(battle_config.error_log)
+ printf("UnknownStatusChange [%d]\n", type);
+ return 0;
+ }
+
+ if(bl->type==BL_PC &&
+ (type<SC_SENDMAX || type==SC_PRESERVE || type==SC_BATTLEORDERS || type==SC_BABY))
+ clif_status_change(bl,type2,1); /* アイコン表示 */
+
+ /* optionの?更 */
+ switch(type){
+ case SC_STONE:
+ case SC_FREEZE:
+ case SC_STAN:
+ case SC_SLEEP:
+ battle_stopattack(bl); /* 攻?停止 */
+ skill_stop_dancing(bl,0); /* 演奏/ダンスの中? */
+ { /* 同時に掛からないステ?タス異常を解除 */
+ int i;
+ for(i = SC_STONE; i <= SC_SLEEP; i++){
+ if(sc_data[i].timer != -1){
+ (*sc_count)--;
+ delete_timer(sc_data[i].timer, status_change_timer);
+ sc_data[i].timer = -1;
+ }
+ }
+ }
+ if(type == SC_STONE)
+ *opt1 = 6;
+ else
+ *opt1 = type - SC_STONE + 1;
+ opt_flag = 1;
+ break;
+ case SC_POISON:
+ case SC_CURSE:
+ case SC_SILENCE:
+ case SC_BLIND:
+ *opt2 |= 1<<(type-SC_POISON);
+ opt_flag = 1;
+ break;
+ case SC_DPOISON: // 暫定で毒のエフェクトを使用
+ *opt2 |= 1;
+ opt_flag = 1;
+ break;
+ case SC_SIGNUMCRUCIS:
+ *opt2 |= 0x40;
+ opt_flag = 1;
+ break;
+ case SC_HIDING:
+ case SC_CLOAKING:
+ battle_stopattack(bl); /* 攻?停止 */
+ *option |= ((type==SC_HIDING)?2:4);
+ opt_flag =1 ;
+ break;
+ case SC_CHASEWALK:
+ battle_stopattack(bl); /* 攻?停止 */
+ *option |= 16388;
+ opt_flag =1 ;
+ break;
+ case SC_SIGHT:
+ *option |= 1;
+ opt_flag = 1;
+ break;
+ case SC_RUWACH:
+ *option |= 8192;
+ opt_flag = 1;
+ break;
+ case SC_WEDDING:
+ *option |= 4096;
+ opt_flag = 1;
+ }
+
+ if(opt_flag) /* optionの?更 */
+ clif_changeoption(bl);
+
+ (*sc_count)++; /* ステ?タス異常の? */
+
+ sc_data[type].val1 = val1;
+ sc_data[type].val2 = val2;
+ sc_data[type].val3 = val3;
+ sc_data[type].val4 = val4;
+ /* タイマ?設定 */
+ sc_data[type].timer = add_timer(
+ gettick() + tick, status_change_timer, bl->id, type);
+
+ if(bl->type==BL_PC && calc_flag)
+ status_calc_pc(sd,0); /* ステ?タス再計算 */
+
+ if(bl->type==BL_PC && save_flag)
+ chrif_save(sd); // save the player status
+
+ if(bl->type==BL_PC && updateflag)
+ clif_updatestatus(sd,updateflag); /* ステ?タスをクライアントに送る */
+
+ return 0;
+}
+/*==========================================
+ * ステータス異常全解除
+ *------------------------------------------
+ */
+int status_change_clear(struct block_list *bl,int type)
+{
+ struct status_change* sc_data;
+ short *sc_count, *option, *opt1, *opt2, *opt3;
+ int i;
+
+ nullpo_retr(0, bl);
+ nullpo_retr(0, sc_data = status_get_sc_data(bl));
+ nullpo_retr(0, sc_count = status_get_sc_count(bl));
+ nullpo_retr(0, option = status_get_option(bl));
+ nullpo_retr(0, opt1 = status_get_opt1(bl));
+ nullpo_retr(0, opt2 = status_get_opt2(bl));
+ nullpo_retr(0, opt3 = status_get_opt3(bl));
+
+ if (*sc_count == 0)
+ return 0;
+ for(i = 0; i < MAX_STATUSCHANGE; i++){
+ if(sc_data[i].timer != -1){ /* 異常があるならタイマ?を削除する */
+ status_change_end(bl, i, -1);
+ }
+ }
+ *sc_count = 0;
+ *opt1 = 0;
+ *opt2 = 0;
+ *opt3 = 0;
+ *option &= OPTION_MASK;
+
+ if (night_flag == 1 && type == BL_PC && !map[bl->m].flag.indoors && // by [Yor]
+ !map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) // [celest]
+ *opt2 |= STATE_BLIND;
+
+ if(!type || type&2)
+ clif_changeoption(bl);
+
+ return 0;
+}
+
+/*==========================================
+ * ステータス異常終了
+ *------------------------------------------
+ */
+int status_change_end( struct block_list* bl , int type,int tid )
+{
+ struct status_change* sc_data;
+ int opt_flag=0, calc_flag = 0;
+ short *sc_count, *option, *opt1, *opt2, *opt3;
+ int type2 = type;
+
+ nullpo_retr(0, bl);
+ if(bl->type!=BL_PC && bl->type!=BL_MOB) {
+ if(battle_config.error_log)
+ printf("status_change_end: neither MOB nor PC !\n");
+ return 0;
+ }
+ nullpo_retr(0, sc_data = status_get_sc_data(bl));
+ nullpo_retr(0, sc_count = status_get_sc_count(bl));
+ nullpo_retr(0, option = status_get_option(bl));
+ nullpo_retr(0, opt1 = status_get_opt1(bl));
+ nullpo_retr(0, opt2 = status_get_opt2(bl));
+ nullpo_retr(0, opt3 = status_get_opt3(bl));
+
+ if ((*sc_count) > 0 && sc_data[type].timer != -1 && (sc_data[type].timer == tid || tid == -1)) {
+
+ if (tid == -1) // タイマから呼ばれていないならタイマ削除をする
+ delete_timer(sc_data[type].timer,status_change_timer);
+
+ /* 該?の異常を正常に?す */
+ sc_data[type].timer=-1;
+ (*sc_count)--;
+
+ switch(type){ /* 異常の種類ごとの?理 */
+ case SC_PROVOKE: /* プロボック */
+ case SC_ENDURE: // celest
+ case SC_CONCENTRATE: /* 集中力向上 */
+ case SC_BLESSING: /* ブレッシング */
+ case SC_ANGELUS: /* アンゼルス */
+ case SC_INCREASEAGI: /* 速度上昇 */
+ case SC_DECREASEAGI: /* 速度減少 */
+ case SC_SIGNUMCRUCIS: /* シグナムクルシス */
+ case SC_HIDING:
+ case SC_TWOHANDQUICKEN: /* 2HQ */
+ case SC_ADRENALINE: /* アドレナリンラッシュ */
+ case SC_ENCPOISON: /* エンチャントポイズン */
+ case SC_IMPOSITIO: /* インポシティオマヌス */
+ case SC_GLORIA: /* グロリア */
+ case SC_LOUD: /* ラウドボイス */
+ case SC_QUAGMIRE: /* クァグマイア */
+ case SC_PROVIDENCE: /* プロヴィデンス */
+ case SC_SPEARSQUICKEN: /* スピアクイッケン */
+ case SC_VOLCANO:
+ case SC_DELUGE:
+ case SC_VIOLENTGALE:
+ case SC_ETERNALCHAOS: /* エタ?ナルカオス */
+ case SC_DRUMBATTLE: /* ?太鼓の響き */
+ case SC_NIBELUNGEN: /* ニ?ベルングの指輪 */
+ case SC_SIEGFRIED: /* 不死身のジ?クフリ?ド */
+ case SC_WHISTLE: /* 口笛 */
+ case SC_ASSNCROS: /* 夕陽のアサシンクロス */
+ case SC_HUMMING: /* ハミング */
+ case SC_DONTFORGETME: /* 私を忘れないで */
+ case SC_FORTUNE: /* 幸運のキス */
+ case SC_SERVICE4U: /* サ?ビスフォ?ユ? */
+ case SC_EXPLOSIONSPIRITS: // 爆裂波動
+ case SC_STEELBODY: // 金剛
+ case SC_DEFENDER:
+ case SC_SPEEDPOTION0: /* ?速ポ?ション */
+ case SC_SPEEDPOTION1:
+ case SC_SPEEDPOTION2:
+ case SC_SPEEDPOTION3:
+ case SC_APPLEIDUN: /* イドゥンの林檎 */
+ case SC_RIDING:
+ case SC_BLADESTOP_WAIT:
+ case SC_CONCENTRATION: /* コンセントレ?ション */
+ case SC_ASSUMPTIO: /* アシャンプティオ */
+ case SC_WINDWALK: /* ウインドウォ?ク */
+ case SC_TRUESIGHT: /* トゥル?サイト */
+ case SC_SPIDERWEB: /* スパイダ?ウェッブ */
+ case SC_MAGICPOWER: /* 魔法力?幅 */
+ case SC_CHASEWALK:
+ case SC_ATKPOT: /* attack potion [Valaris] */
+ case SC_MATKPOT: /* magic attack potion [Valaris] */
+ case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
+ case SC_MELTDOWN: /* メルトダウン */
+ case SC_MINDBREAKER: /* マインドブレーカー */
+ // Celest
+ case SC_EDP:
+ case SC_SLOWDOWN:
+ case SC_SPEEDUP0:
+ case SC_BATTLEORDERS:
+ case SC_REGENERATION:
+ case SC_GUILDAURA:
+ calc_flag = 1;
+ break;
+ case SC_AUTOBERSERK:
+ if (sc_data[SC_PROVOKE].timer != -1)
+ status_change_end(bl,SC_PROVOKE,-1);
+ break;
+ case SC_BERSERK: /* バ?サ?ク */
+ calc_flag = 1;
+ clif_status_change(bl,SC_INCREASEAGI,0); /* アイコン消去 */
+ break;
+ case SC_DEVOTION: /* ディボ?ション */
+ {
+ struct map_session_data *md = map_id2sd(sc_data[type].val1);
+ sc_data[type].val1=sc_data[type].val2=0;
+ skill_devotion(md,bl->id);
+ calc_flag = 1;
+ }
+ break;
+ case SC_BLADESTOP:
+ {
+ struct status_change *t_sc_data = status_get_sc_data((struct block_list *)sc_data[type].val4);
+ //片方が切れたので相手の白刃?態が切れてないのなら解除
+ if(t_sc_data && t_sc_data[SC_BLADESTOP].timer!=-1)
+ status_change_end((struct block_list *)sc_data[type].val4,SC_BLADESTOP,-1);
+
+ if(sc_data[type].val2==2)
+ clif_bladestop((struct block_list *)sc_data[type].val3,(struct block_list *)sc_data[type].val4,0);
+ }
+ break;
+ case SC_DANCING:
+ {
+ struct map_session_data *dsd;
+ struct status_change *d_sc_data;
+ if(sc_data[type].val4 && (dsd=map_id2sd(sc_data[type].val4))){
+ d_sc_data = dsd->sc_data;
+ //合奏で相手がいる場合相手のval4を0にする
+ if(d_sc_data && d_sc_data[type].timer!=-1)
+ d_sc_data[type].val4=0;
+ }
+ }
+ calc_flag = 1;
+ break;
+ case SC_NOCHAT: //チャット禁止?態
+ {
+ struct map_session_data *sd=NULL;
+ if(bl->type == BL_PC && (sd=(struct map_session_data *)bl)){
+ if (sd->status.manner >= 0) // weeee ^^ [celest]
+ sd->status.manner = 0;
+ clif_updatestatus(sd,SP_MANNER);
+ }
+ }
+ break;
+ case SC_SPLASHER: /* ベナムスプラッシャ? */
+ {
+ struct block_list *src=map_id2bl(sc_data[type].val3);
+ if(src && tid!=-1){
+ //自分にダメ?ジ&周?3*3にダメ?ジ
+ skill_castend_damage_id(src, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 );
+ }
+ }
+ break;
+ case SC_SELFDESTRUCTION: /* 自爆 */
+ {
+ //自分のダメ?ジは0にして
+ struct mob_data *md=NULL;
+ if(bl->type == BL_MOB && (md=(struct mob_data*)bl))
+ skill_castend_damage_id(bl, bl,sc_data[type].val2,sc_data[type].val1,gettick(),0 );
+ }
+ break;
+ /* option1 */
+ case SC_FREEZE:
+ sc_data[type].val3 = 0;
+ break;
+
+ /* option2 */
+ case SC_POISON: /* 毒 */
+ case SC_BLIND: /* 暗? */
+ case SC_CURSE:
+ calc_flag = 1;
+ break;
+
+ // celest
+ case SC_CONFUSION:
+ {
+ struct map_session_data *sd=NULL;
+ if(bl->type == BL_PC && (sd=(struct map_session_data *)bl)){
+ sd->next_walktime = -1;
+ }
+ }
+ break;
+
+ case SC_MARIONETTE: /* マリオネットコントロ?ル */
+ case SC_MARIONETTE2: /// Marionette target
+ {
+ // check for partner and end their marionette status as well
+ int type2 = (type == SC_MARIONETTE) ? SC_MARIONETTE2 : SC_MARIONETTE;
+ struct block_list *pbl = map_id2bl(sc_data[type].val3);
+ if (pbl) {
+ struct status_change* sc_data;
+ if (*status_get_sc_count(pbl) > 0 &&
+ (sc_data = status_get_sc_data(pbl)) &&
+ sc_data[type2].timer != -1)
+ status_change_end(pbl, type2, -1);
+ }
+ calc_flag = 1;
+ }
+ break;
+
+ case SC_BABY:
+ type2 = _SC_BABY;
+ break;
+ }
+
+ if(bl->type==BL_PC &&
+ (type<SC_SENDMAX || type==SC_PRESERVE || type==SC_BATTLEORDERS || type==SC_BABY))
+ clif_status_change(bl,type2,0); /* アイコン消去 */
+
+ switch(type){ /* 正常に?るときなにか?理が必要 */
+ case SC_STONE:
+ case SC_FREEZE:
+ case SC_STAN:
+ case SC_SLEEP:
+ *opt1 = 0;
+ opt_flag = 1;
+ break;
+
+ case SC_POISON:
+ if (sc_data[SC_DPOISON].timer != -1) //
+ break; // DPOISON用のオプション
+ *opt2 &= ~1; // が?用に用意された場合には
+ opt_flag = 1; // ここは削除する
+ break; //
+ case SC_CURSE:
+ case SC_SILENCE:
+ case SC_BLIND:
+ *opt2 &= ~(1<<(type-SC_POISON));
+ opt_flag = 1;
+ break;
+ case SC_DPOISON:
+ if (sc_data[SC_POISON].timer != -1) // DPOISON用のオプションが
+ break; // 用意されたら削除
+ *opt2 &= ~1; // 毒?態解除
+ opt_flag = 1;
+ break;
+ case SC_SIGNUMCRUCIS:
+ *opt2 &= ~0x40;
+ opt_flag = 1;
+ break;
+
+ case SC_HIDING:
+ case SC_CLOAKING:
+ *option &= ~((type == SC_HIDING) ? 2 : 4);
+ calc_flag = 1; // orn
+ opt_flag = 1 ;
+ break;
+
+ case SC_CHASEWALK:
+ *option &= ~16388;
+ opt_flag = 1 ;
+ break;
+
+ case SC_SIGHT:
+ *option &= ~1;
+ opt_flag = 1;
+ break;
+ case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
+ *option &= ~4096;
+ opt_flag = 1;
+ break;
+ case SC_RUWACH:
+ *option &= ~8192;
+ opt_flag = 1;
+ break;
+
+ //opt3
+ case SC_TWOHANDQUICKEN: /* 2HQ */
+ case SC_SPEARSQUICKEN: /* スピアクイッケン */
+ case SC_CONCENTRATION: /* コンセントレ?ション */
+ *opt3 &= ~1;
+ break;
+ case SC_OVERTHRUST: /* オ?バ?スラスト */
+ *opt3 &= ~2;
+ break;
+ case SC_ENERGYCOAT: /* エナジ?コ?ト */
+ *opt3 &= ~4;
+ break;
+ case SC_EXPLOSIONSPIRITS: // 爆裂波動
+ *opt3 &= ~8;
+ break;
+ case SC_STEELBODY: // 金剛
+ *opt3 &= ~16;
+ break;
+ case SC_BLADESTOP: /* 白刃取り */
+ *opt3 &= ~32;
+ break;
+ case SC_BERSERK: /* バ?サ?ク */
+ *opt3 &= ~128;
+ break;
+ case SC_MARIONETTE: /* マリオネットコントロ?ル */
+ case SC_MARIONETTE2:
+ *opt3 &= ~1024;
+ break;
+ case SC_ASSUMPTIO: /* アスムプティオ */
+ *opt3 &= ~2048;
+ break;
+ }
+
+ if (night_flag == 1 && (*opt2 & STATE_BLIND) == 0 && bl->type == BL_PC && // by [Yor]
+ !map[bl->m].flag.indoors && battle_config.night_darkness_level <= 0) { // [celest]
+ *opt2 |= STATE_BLIND;
+ opt_flag = 1;
+ }
+
+ if(opt_flag) /* optionの?更を?える */
+ clif_changeoption(bl);
+
+ if (bl->type == BL_PC && calc_flag)
+ status_calc_pc((struct map_session_data *)bl,0); /* ステ?タス再計算 */
+ }
+
+ return 0;
+}
+
+
+/*==========================================
+ * ステータス異常終了タイマー
+ *------------------------------------------
+ */
+int status_change_timer(int tid, unsigned int tick, int id, int data)
+{
+ int type = data;
+ struct block_list *bl;
+ struct map_session_data *sd=NULL;
+ struct status_change *sc_data;
+ //short *sc_count; //使ってない?
+
+// security system to prevent forgetting timer removal
+ int temp_timerid;
+
+ bl=map_id2bl(id);
+#ifndef _WIN32
+ nullpo_retr_f(0, bl, "id=%d data=%d",id,data);
+#endif
+ nullpo_retr(0, sc_data=status_get_sc_data(bl));
+
+ if(bl->type==BL_PC)
+ nullpo_retr(0, sd=(struct map_session_data *)bl);
+
+ //sc_count=status_get_sc_count(bl); //使ってない?
+
+ if(sc_data[type].timer != tid) {
+ if(battle_config.error_log)
+ printf("status_change_timer %d != %d\n",tid,sc_data[type].timer);
+ return 0;
+ }
+
+ // security system to prevent forgetting timer removal
+ // you shouldn't be that careless inside the switch here
+ temp_timerid = sc_data[type].timer;
+ sc_data[type].timer = -1;
+
+ switch(type){ /* 特殊な?理になる場合 */
+ case SC_MAXIMIZEPOWER: /* マキシマイズパワ? */
+ case SC_CLOAKING:
+ if(sd){
+ if( sd->status.sp > 0 ){ /* SP切れるまで持? */
+ sd->status.sp--;
+ clif_updatestatus(sd,SP_SP);
+ sc_data[type].timer=add_timer( /* タイマ?再設定 */
+ sc_data[type].val2+tick, status_change_timer, bl->id, data);
+ return 0;
+ }
+ }
+ break;
+
+ case SC_CHASEWALK:
+ if(sd){
+ int sp = 10+sc_data[SC_CHASEWALK].val1*2;
+ if (map[sd->bl.m].flag.gvg) sp *= 5;
+ if( sd->status.sp > sp){
+ sd->status.sp -= sp; // update sp cost [Celest]
+ clif_updatestatus(sd,SP_SP);
+ sc_data[type].timer=add_timer( /* タイマ?再設定 */
+ sc_data[type].val2+tick, status_change_timer, bl->id, data);
+ sc_data[SC_CHASEWALK].val4++;
+ if (sc_data[SC_CHASEWALK].val4 > 3)
+ sc_data[SC_CHASEWALK].val4 = 0;
+ status_calc_pc (sd, 0);
+ return 0;
+ }
+ }
+ break;
+
+ case SC_HIDING: /* ハイディング */
+ if(sd){ /* SPがあって、時間制限の間は持? */
+ if( sd->status.sp > 0 && (--sc_data[type].val2)>0 ){
+ if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){
+ sd->status.sp--;
+ clif_updatestatus(sd,SP_SP);
+ }
+ sc_data[type].timer=add_timer( /* タイマ?再設定 */
+ 1000+tick, status_change_timer,
+ bl->id, data);
+ return 0;
+ }
+ }
+ break;
+
+ case SC_SIGHT: /* サイト */
+ case SC_RUWACH: /* ルアフ */
+ {
+ int range = 5;
+ if ( type == SC_SIGHT ) range = 7;
+ map_foreachinarea( status_change_timer_sub,
+ bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0,
+ bl,type,tick);
+
+ if( (--sc_data[type].val2)>0 ){
+ sc_data[type].timer=add_timer( /* タイマ?再設定 */
+ 250+tick, status_change_timer,
+ bl->id, data);
+ return 0;
+ }
+ }
+ break;
+
+ case SC_SIGNUMCRUCIS: /* シグナムクルシス */
+ {
+ int race = status_get_race(bl);
+ if(race == 6 || battle_check_undead(race,status_get_elem_type(bl))) {
+ sc_data[type].timer=add_timer(1000*600+tick,status_change_timer, bl->id, data );
+ return 0;
+ }
+ }
+ break;
+
+ case SC_PROVOKE: /* プロボック/オ?トバ?サ?ク */
+ if(sc_data[type].val2!=0){ /* オ?トバ?サ?ク(1秒ごとにHPチェック) */
+ if(sd && sd->status.hp>sd->status.max_hp>>2) /* 停止 */
+ break;
+ sc_data[type].timer=add_timer( 1000+tick,status_change_timer, bl->id, data );
+ return 0;
+ }
+ break;
+
+ case SC_ENDURE: /* インデュア */
+ case SC_AUTOBERSERK: // Celest
+ if(sd && sd->special_state.infinite_endure) {
+#ifdef TWILIGHT
+ sc_data[type].timer=add_timer( 1000*600+tick,status_change_timer, bl->id, data );
+#else
+ sc_data[type].timer=add_timer( 1000*60+tick,status_change_timer, bl->id, data );
+#endif
+ //sc_data[type].val2=1;
+ return 0;
+ }
+ break;
+
+ case SC_DISSONANCE: /* 不協和音 */
+ if( (--sc_data[type].val2)>0){
+ struct skill_unit *unit=
+ (struct skill_unit *)sc_data[type].val4;
+ struct block_list *src;
+ /*if(!unit || !unit->group)
+ break;
+ src=map_id2bl(unit->group->src_id);
+ if(!src)
+ break;*/
+ nullpo_retb(unit);
+ nullpo_retb(unit->group);
+ nullpo_retb(src=map_id2bl(unit->group->src_id));
+ skill_attack(BF_MISC,src,&unit->bl,bl,unit->group->skill_id,sc_data[type].val1,tick,0);
+ if( (bl->type==BL_MOB) && (MS_DEAD==((struct mob_data *)bl)->state.state) )
+ break;
+ sc_data[type].timer=add_timer(skill_get_time2(unit->group->skill_id,unit->group->skill_lv)+tick,
+ status_change_timer, bl->id, data );
+ return 0;
+ }
+ break;
+
+ case SC_LULLABY: /* 子守唄 */
+ if( (--sc_data[type].val2)>0){
+ struct skill_unit *unit=
+ (struct skill_unit *)sc_data[type].val4;
+ nullpo_retb(unit);
+ nullpo_retb(unit->group);
+ if(unit->group->src_id == bl->id)
+ break;
+ skill_additional_effect(bl,bl,unit->group->skill_id,sc_data[type].val1,BF_LONG|BF_SKILL|BF_MISC,tick);
+ if (unit->group != 0)
+ {
+ sc_data[type].timer=add_timer(skill_get_time(unit->group->skill_id,unit->group->skill_lv)/10+tick,
+ status_change_timer, bl->id, data );
+ return 0;
+ }// dont forget the brackets
+ }
+ break;
+
+ case SC_STONE:
+ if(sc_data[type].val2 != 0) {
+ short *opt1 = status_get_opt1(bl);
+ sc_data[type].val2 = 0;
+ sc_data[type].val4 = 0;
+ battle_stopwalking(bl,1);
+ if(opt1) {
+ *opt1 = 1;
+ clif_changeoption(bl);
+ }
+ sc_data[type].timer=add_timer(1000+tick,status_change_timer, bl->id, data );
+ return 0;
+ }
+ else if( (--sc_data[type].val3) > 0) {
+ int hp = status_get_max_hp(bl);
+ if((++sc_data[type].val4)%5 == 0 && status_get_hp(bl) > hp>>2) {
+ hp = hp/100;
+ if(hp < 1) hp = 1;
+ if(sd)
+ pc_heal(sd,-hp,0);
+ else if(bl->type == BL_MOB){
+ struct mob_data *md;
+ if((md=((struct mob_data *)bl)) == NULL)
+ break;
+ md->hp -= hp;
+ }
+ }
+ sc_data[type].timer=add_timer(1000+tick,status_change_timer, bl->id, data );
+ return 0;
+ }
+ break;
+
+ case SC_POISON:
+ case SC_DPOISON:
+ if (sc_data[SC_SLOWPOISON].timer == -1 && (--sc_data[type].val3) > 0) {
+ int hp = status_get_max_hp(bl);
+ if (type == SC_POISON && status_get_hp(bl) < hp>>2)
+ break;
+ if(sd) {
+ hp = (type == SC_DPOISON) ? 3 + hp/50 : 3 + hp*3/200;
+ pc_heal(sd, -hp, 0);
+ } else if (bl->type == BL_MOB) {
+ struct mob_data *md;
+ nullpo_retr(0, md=(struct mob_data *)bl);
+ hp = (type == SC_DPOISON) ? 3 + hp/100 : 3 + hp/200;
+ md->hp -= hp;
+ }
+ }
+ if (sc_data[type].val3 > 0)
+ {
+ sc_data[type].timer=add_timer(1000+tick,status_change_timer, bl->id, data );
+ // hmm setting up a timer and breaking then to call status_change_end just right away?
+ // I think you're missing brackets and a:
+ return 0;
+ }
+ break;
+
+ case SC_TENSIONRELAX: /* テンションリラックス */
+ if(sd){ /* SPがあって、HPが?タンでなければ?? */
+ if( sd->status.sp > 12 && sd->status.max_hp > sd->status.hp ){
+/* if(sc_data[type].val2 % (sc_data[type].val1+3) ==0 ){
+ sd->status.sp -= 12;
+ clif_updatestatus(sd,SP_SP);
+ } */
+ sc_data[type].timer=add_timer( /* タイマ?再設定 */
+ 10000+tick, status_change_timer,
+ bl->id, data);
+ return 0;
+ }
+ if(sd->status.max_hp <= sd->status.hp)
+ {
+ status_change_end(&sd->bl,SC_TENSIONRELAX,-1);
+ // calling status_change_end then break and call it again might not be that what is necessary
+ // or am I wrong?
+ // so I just add brackets and a:
+ return 0;
+ }
+ }
+ break;
+ case SC_BLEEDING: // [celest]
+ // i hope i haven't interpreted it wrong.. which i might ^^;
+ // Source:
+ // - 10ゥェエェネェヒHPェャハ盒
+ // - ェホェ゙ェ゙ォオ?ォミケヤムェ茘ォォーェキェニェ?ヘェマ眈ェィェハェ、
+ if((sc_data[type].val3 -= 1000) > 0) {
+ if((sc_data[type].val4 -= 1000) > 0) {
+ int hp = rand()%300+400;
+ if(sd) {
+ pc_heal(sd,-hp,0);
+ sd->canmove_tick = tick+1000;
+ }
+ else if(bl->type == BL_MOB) {
+ struct mob_data *md;
+ nullpo_retr(0, md=(struct mob_data *)bl);
+ md->hp -= hp;
+ }
+ }
+ if (sd) {
+ sd->canact_tick = tick+1000;
+ }
+
+ sc_data[type].timer=add_timer(1000+tick,status_change_timer, bl->id, data );
+ // hmm setting up a timer and breaking then to call status_change_end just right away?
+ // I think you're missing a:
+ return 0;
+ }
+ break;
+
+ /* 時間切れ無し?? */
+ case SC_AETERNA:
+ case SC_TRICKDEAD:
+ case SC_RIDING:
+ case SC_FALCON:
+ case SC_WEIGHT50:
+ case SC_WEIGHT90:
+ case SC_MAGICPOWER: /* 魔法力?幅 */
+ case SC_REJECTSWORD: /* リジェクトソ?ド */
+ case SC_MEMORIZE: /* メモライズ */
+ case SC_BROKNWEAPON:
+ case SC_BROKNARMOR:
+ case SC_SACRIFICE:
+ sc_data[type].timer=add_timer( 1000*600+tick,status_change_timer, bl->id, data );
+ return 0;
+
+ case SC_DANCING: //ダンススキルの時間SP消費
+ {
+ int s=0;
+ if(sd){
+ if(sd->status.sp > 0 && (--sc_data[type].val3)>0){
+ switch(sc_data[type].val1){
+ case BD_RICHMANKIM: /* ニヨルドの宴 3秒にSP1 */
+ case BD_DRUMBATTLEFIELD: /* ?太鼓の響き 3秒にSP1 */
+ case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 3秒にSP1 */
+ case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド 3秒にSP1 */
+ case BA_DISSONANCE: /* 不協和音 3秒でSP1 */
+ case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス 3秒でSP1 */
+ case DC_UGLYDANCE: /* 自分勝手なダンス 3秒でSP1 */
+ s=3;
+ break;
+ case BD_LULLABY: /* 子守歌 4秒にSP1 */
+ case BD_ETERNALCHAOS: /* 永遠の混沌 4秒にSP1 */
+ case BD_ROKISWEIL: /* ロキの叫び 4秒にSP1 */
+ case DC_FORTUNEKISS: /* 幸運のキス 4秒でSP1 */
+ s=4;
+ break;
+ case BD_INTOABYSS: /* 深淵の中に 5秒にSP1 */
+ case BA_WHISTLE: /* 口笛 5秒でSP1 */
+ case DC_HUMMING: /* ハミング 5秒でSP1 */
+ case BA_POEMBRAGI: /* ブラギの詩 5秒でSP1 */
+ case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? 5秒でSP1 */
+ s=5;
+ break;
+ case BA_APPLEIDUN: /* イドゥンの林檎 6秒でSP1 */
+ s=6;
+ break;
+ case DC_DONTFORGETME: /* 私を忘れないで… 10秒でSP1 */
+ case CG_MOONLIT: /* 月明りの泉に落ちる花びら 10秒でSP1? */
+ s=10;
+ break;
+ }
+ if(s && ((sc_data[type].val3 % s) == 0)){
+ sd->status.sp--;
+ clif_updatestatus(sd,SP_SP);
+ }
+ sc_data[type].timer=add_timer( /* タイマ?再設定 */
+ 1000+tick, status_change_timer,
+ bl->id, data);
+ return 0;
+ }
+ }
+ }
+ break;
+ case SC_BERSERK: /* バ?サ?ク */
+ if(sd){ /* HPが100以上なら?? */
+ if( (sd->status.hp - sd->status.max_hp*5/100) > 100 ){ // 5% every 10 seconds [DracoRPG]
+ sd->status.hp -= sd->status.max_hp*5/100; // changed to max hp [celest]
+ clif_updatestatus(sd,SP_HP);
+ sc_data[type].timer = add_timer( /* タイマ?再設定 */
+ 10000+tick, status_change_timer,
+ bl->id, data);
+ return 0;
+ }
+ }
+ break;
+ case SC_WEDDING: //結婚用(結婚衣裳になって?くのが?いとか)
+ if(sd){
+ time_t timer;
+ if(time(&timer) < ((sc_data[type].val2) + 3600)){ //1時間たっていないので??
+ sc_data[type].timer=add_timer( /* タイマ?再設定 */
+ 10000+tick, status_change_timer,
+ bl->id, data);
+ return 0;
+ }
+ }
+ break;
+ case SC_NOCHAT: //チャット禁止?態
+ if(sd && battle_config.muting_players){
+ time_t timer;
+ if((++sd->status.manner) && time(&timer) < ((sc_data[type].val2) + 60*(0-sd->status.manner))){ //開始からstatus.manner分?ってないので??
+ clif_updatestatus(sd,SP_MANNER);
+ sc_data[type].timer=add_timer( /* タイマ?再設定(60秒) */
+ 60000+tick, status_change_timer,
+ bl->id, data);
+ return 0;
+ }
+ }
+ break;
+ case SC_SELFDESTRUCTION: /* 自爆 */
+ if(--sc_data[type].val3>0){
+ struct mob_data *md;
+ if(bl->type==BL_MOB && (md=(struct mob_data *)bl) && md->speed > 250){
+ md->speed -= 250;
+ md->next_walktime=tick;
+ }
+ sc_data[type].timer=add_timer( /* タイマ?再設定 */
+ 1000+tick, status_change_timer,
+ bl->id, data);
+ return 0;
+ }
+ break;
+
+ case SC_SPLASHER:
+ if (sc_data[type].val4 % 1000 == 0) {
+ char timer[2];
+ sprintf (timer, "%d", sc_data[type].val4/1000);
+ clif_message(bl, timer);
+ }
+ if((sc_data[type].val4 -= 500) > 0) {
+ sc_data[type].timer = add_timer(
+ 500 + tick, status_change_timer,
+ bl->id, data);
+ return 0;
+ }
+ break;
+
+ case SC_MARIONETTE: /* マリオネットコントロ?ル */
+ case SC_MARIONETTE2:
+ {
+ struct block_list *pbl = map_id2bl(sc_data[type].val3);
+ if (pbl && battle_check_range(bl, pbl, 7) &&
+ (sc_data[type].val2 -= 1000)>0) {
+ sc_data[type].timer = add_timer(
+ 1000 + tick, status_change_timer,
+ bl->id, data);
+ return 0;
+ }
+ }
+ break;
+
+ // Celest
+ case SC_CONFUSION:
+ {
+ int i = 3000;
+ //struct mob_data *md;
+ if (sd) {
+ pc_randomwalk (sd, gettick());
+ sd->next_walktime = tick + (i=1000 + rand()%1000);
+ } /*else if (bl->type==BL_MOB && (md=(struct mob_data *)bl) && md->mode&1 && mob_can_move(md)) {
+ md->state.state=MS_WALK;
+ if( DIFF_TICK(md->next_walktime,tick) > + 7000 &&
+ (md->walkpath.path_len==0 || md->walkpath.path_pos>=md->walkpath.path_len) )
+ md->next_walktime = tick + 3000*rand()%2000;
+ mob_randomwalk(md,tick);
+ }*/
+ if ((sc_data[type].val2 -= 1000) > 0) {
+ sc_data[type].timer = add_timer(
+ i + tick, status_change_timer,
+ bl->id, data);
+ return 0;
+ }
+ }
+ break;
+
+ case SC_GOSPEL:
+ {
+ int calc_flag = 0;
+ if (sc_data[type].val3 > 0) {
+ sc_data[type].val3 = 0;
+ calc_flag = 1;
+ }
+ if(sd && sc_data[type].val4 == BCT_SELF){
+ int hp, sp;
+ hp = (sc_data[type].val1 > 5) ? 45 : 30;
+ sp = (sc_data[type].val1 > 5) ? 35 : 20;
+ if(sd->status.hp - hp > 0 &&
+ sd->status.sp - sp > 0){
+ sd->status.hp -= hp;
+ sd->status.sp -= sp;
+ clif_updatestatus(sd,SP_HP);
+ clif_updatestatus(sd,SP_SP);
+ if ((sc_data[type].val2 -= 10000) > 0) {
+ sc_data[type].timer = add_timer(
+ 10000+tick, status_change_timer,
+ bl->id, data);
+ return 0;
+ }
+ }
+ } else if (sd && sc_data[type].val4 == BCT_PARTY) {
+ int i;
+ switch ((i = rand() % 12)) {
+ case 1: // heal between 100-1000
+ {
+ struct block_list tbl;
+ int heal = rand() % 900 + 100;
+ tbl.id = 0;
+ tbl.m = bl->m;
+ tbl.x = bl->x;
+ tbl.y = bl->y;
+ clif_skill_nodamage(&tbl,bl,AL_HEAL,heal,1);
+ battle_heal(NULL,bl,heal,0,0);
+ }
+ break;
+ case 2: // end negative status
+ {
+ int j;
+ for (j=0; j<4; j++)
+ if(sc_data[i + SC_POISON].timer!=-1) {
+ status_change_end(bl,j,-1);
+ break;
+ }
+ }
+ break;
+ case 3: // +25% resistance to negative status
+ case 4: // +25% max hp
+ case 5: // +25% max sp
+ case 6: // +2 to all stats
+ case 11: // +25% armor and vit def
+ case 12: // +8% atk
+ case 13: // +5% flee
+ case 14: // +5% hit
+ sc_data[type].val3 = i;
+ if (i == 6 ||
+ (i >= 11 && i <= 14))
+ calc_flag = 1;
+ break;
+ case 7: // level 5 bless
+ {
+ struct block_list tbl;
+ tbl.id = 0;
+ tbl.m = bl->m;
+ tbl.x = bl->x;
+ tbl.y = bl->y;
+ clif_skill_nodamage(&tbl,bl,AL_BLESSING,5,1);
+ status_change_start(bl,SkillStatusChangeTable[AL_BLESSING],5,0,0,0,10000,0 );
+ }
+ break;
+ case 8: // level 5 increase agility
+ {
+ struct block_list tbl;
+ tbl.id = 0;
+ tbl.m = bl->m;
+ tbl.x = bl->x;
+ tbl.y = bl->y;
+ clif_skill_nodamage(&tbl,bl,AL_INCAGI,5,1);
+ status_change_start(bl,SkillStatusChangeTable[AL_INCAGI],5,0,0,0,10000,0 );
+ }
+ break;
+ case 9: // holy element to weapon
+ {
+ struct block_list tbl;
+ tbl.id = 0;
+ tbl.m = bl->m;
+ tbl.x = bl->x;
+ tbl.y = bl->y;
+ clif_skill_nodamage(&tbl,bl,PR_ASPERSIO,1,1);
+ status_change_start(bl,SkillStatusChangeTable[PR_ASPERSIO],1,0,0,0,10000,0 );
+ }
+ break;
+ case 10: // holy element to armour
+ {
+ struct block_list tbl;
+ tbl.id = 0;
+ tbl.m = bl->m;
+ tbl.x = bl->x;
+ tbl.y = bl->y;
+ clif_skill_nodamage(&tbl,bl,PR_BENEDICTIO,1,1);
+ status_change_start(bl,SkillStatusChangeTable[PR_BENEDICTIO],1,0,0,0,10000,0 );
+ }
+ break;
+ default:
+ break;
+ }
+ } else if (sc_data[type].val4 == BCT_ENEMY) {
+ int i;
+ switch ((i = rand() % 8)) {
+ case 1: // damage between 300-800
+ case 2: // damage between 150-550 (ignore def)
+ battle_damage(NULL, bl, rand() % 500,0); // temporary damage
+ break;
+ case 3: // random status effect
+ {
+ int effect[3] = {
+ SC_CURSE,
+ SC_BLIND,
+ SC_POISON };
+ status_change_start(bl,effect[rand()%3],1,0,0,0,10000,0 );
+ }
+ break;
+ case 4: // level 10 provoke
+ {
+ struct block_list tbl;
+ tbl.id = 0;
+ tbl.m = bl->m;
+ tbl.x = bl->x;
+ tbl.y = bl->y;
+ clif_skill_nodamage(&tbl,bl,SM_PROVOKE,1,1);
+ status_change_start(bl,SkillStatusChangeTable[SM_PROVOKE],10,0,0,0,10000,0 );
+ }
+ break;
+ case 5: // 0 def
+ case 6: // 0 atk
+ case 7: // 0 flee
+ case 8: // -75% move speed and aspd
+ sc_data[type].val3 = i;
+ calc_flag = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ if (sd && calc_flag)
+ status_calc_pc (sd, 0);
+ }
+ break;
+
+ case SC_GUILDAURA:
+ {
+ struct block_list *tbl = map_id2bl(sc_data[type].val2);
+
+ if (tbl && battle_check_range(bl, tbl, 2)){
+ sc_data[type].timer = add_timer(
+ 1000 + tick, status_change_timer,
+ bl->id, data);
+ return 0;
+ }// ugh, don't forget the brackets
+ }
+ break;
+ }
+
+ // default for all non-handled control paths
+ // security system to prevent forgetting timer removal
+
+ // if we reach this point we need the timer for the next call,
+ // so restore it to have status_change_end handle a valid timer
+ sc_data[type].timer = temp_timerid;
+
+ return status_change_end( bl,type,tid );
+}
+
+/*==========================================
+ * ステータス異常タイマー範囲処理
+ *------------------------------------------
+ */
+int status_change_timer_sub(struct block_list *bl, va_list ap )
+{
+ struct block_list *src;
+ int type;
+ unsigned int tick;
+
+ nullpo_retr(0, bl);
+ nullpo_retr(0, ap);
+ nullpo_retr(0, src=va_arg(ap,struct block_list*));
+ type=va_arg(ap,int);
+ tick=va_arg(ap,unsigned int);
+
+ if(bl->type!=BL_PC && bl->type!=BL_MOB)
+ return 0;
+
+ switch( type ){
+ case SC_SIGHT: /* サイト */
+ case SC_CONCENTRATE:
+ if( (*status_get_option(bl))&6 ){
+ status_change_end( bl, SC_HIDING, -1);
+ status_change_end( bl, SC_CLOAKING, -1);
+ }
+ break;
+ case SC_RUWACH: /* ルアフ */
+ if( (*status_get_option(bl))&6 ){
+ struct status_change *sc_data = status_get_sc_data(bl); // check whether the target is hiding/cloaking [celest]
+ if (sc_data && (sc_data[SC_HIDING].timer != -1 || // if the target is using a special hiding, i.e not using normal hiding/cloaking, don't bother
+ sc_data[SC_CLOAKING].timer != -1)) {
+ status_change_end( bl, SC_HIDING, -1);
+ status_change_end( bl, SC_CLOAKING, -1);
+ }
+ if(battle_check_target( src,bl, BCT_ENEMY ) > 0)
+ skill_attack(BF_MAGIC,src,src,bl,AL_RUWACH,sc_data[type].val1,tick,0);
+ }
+ break;
+ }
+ return 0;
+}
+
+
+static int status_calc_sigma(void)
+{
+ int i,j,k;
+
+ for(i=0;i<MAX_PC_CLASS;i++) {
+ memset(hp_sigma_val[i],0,sizeof(hp_sigma_val[i]));
+ for(k=0,j=2;j<=MAX_LEVEL;j++) {
+ k += hp_coefficient[i]*j + 50;
+ k -= k%100;
+ hp_sigma_val[i][j-1] = k;
+ }
+ }
+ return 0;
+}
+
+int status_readdb(void) {
+ int i,j,k;
+ FILE *fp;
+ char line[1024],*p;
+
+ // JOB補正?値1
+ fp=fopen("db/job_db1.txt","r");
+ if(fp==NULL){
+ printf("can't read db/job_db1.txt\n");
+ return 1;
+ }
+ i=0;
+ while(fgets(line, sizeof(line)-1, fp)){
+ char *split[50];
+ if(line[0]=='/' && line[1]=='/')
+ continue;
+ for(j=0,p=line;j<21 && p;j++){
+ split[j]=p;
+ p=strchr(p,',');
+ if(p) *p++=0;
+ }
+ if(j<21)
+ continue;
+ max_weight_base[i]=atoi(split[0]);
+ hp_coefficient[i]=atoi(split[1]);
+ hp_coefficient2[i]=atoi(split[2]);
+ sp_coefficient[i]=atoi(split[3]);
+ for(j=0;j<17;j++)
+ aspd_base[i][j]=atoi(split[j+4]);
+ i++;
+// -- moonsoul (below two lines added to accommodate high numbered new class ids)
+ if(i==24)
+ i=4001;
+ if(i==MAX_PC_CLASS)
+ break;
+ }
+ fclose(fp);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/job_db1.txt");
+ ShowStatus(tmp_output);
+
+ // JOBボ?ナス
+ memset(job_bonus,0,sizeof(job_bonus));
+ fp=fopen("db/job_db2.txt","r");
+ if(fp==NULL){
+ printf("can't read db/job_db2.txt\n");
+ return 1;
+ }
+ i=0;
+ while(fgets(line, sizeof(line)-1, fp)){
+ if(line[0]=='/' && line[1]=='/')
+ continue;
+ for(j=0,p=line;j<MAX_LEVEL && p;j++){
+ if(sscanf(p,"%d",&k)==0)
+ break;
+ job_bonus[0][i][j]=k;
+ job_bonus[2][i][j]=k; //養子職のボ?ナスは分からないので?
+ p=strchr(p,',');
+ if(p) p++;
+ }
+ i++;
+// -- moonsoul (below two lines added to accommodate high numbered new class ids)
+ if(i==24)
+ i=4001;
+ if(i==MAX_PC_CLASS)
+ break;
+ }
+ fclose(fp);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/job_db2.txt");
+ ShowStatus(tmp_output);
+
+ // JOBボ?ナス2 ?生職用
+ fp=fopen("db/job_db2-2.txt","r");
+ if(fp==NULL){
+ printf("can't read db/job_db2-2.txt\n");
+ return 1;
+ }
+ i=0;
+ while(fgets(line, sizeof(line)-1, fp)){
+ if(line[0]=='/' && line[1]=='/')
+ continue;
+ for(j=0,p=line;j<MAX_LEVEL && p;j++){
+ if(sscanf(p,"%d",&k)==0)
+ break;
+ job_bonus[1][i][j]=k;
+ p=strchr(p,',');
+ if(p) p++;
+ }
+ i++;
+ if(i==MAX_PC_CLASS)
+ break;
+ }
+ fclose(fp);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/job_db2-2.txt");
+ ShowStatus(tmp_output);
+
+ // サイズ補正テ?ブル
+ for(i=0;i<3;i++)
+ for(j=0;j<20;j++)
+ atkmods[i][j]=100;
+ fp=fopen("db/size_fix.txt","r");
+ if(fp==NULL){
+ printf("can't read db/size_fix.txt\n");
+ return 1;
+ }
+ i=0;
+ while(fgets(line, sizeof(line)-1, fp)){
+ char *split[20];
+ if(line[0]=='/' && line[1]=='/')
+ continue;
+ if(atoi(line)<=0)
+ continue;
+ memset(split,0,sizeof(split));
+ for(j=0,p=line;j<20 && p;j++){
+ split[j]=p;
+ p=strchr(p,',');
+ if(p) *p++=0;
+ }
+ for(j=0;j<20 && split[j];j++)
+ atkmods[i][j]=atoi(split[j]);
+ i++;
+ }
+ fclose(fp);
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/size_fix.txt");
+ ShowStatus(tmp_output);
+
+ // 精?デ?タテ?ブル
+ for(i=0;i<5;i++){
+ for(j=0;j<10;j++)
+ percentrefinery[i][j]=100;
+ refinebonus[i][0]=0;
+ refinebonus[i][1]=0;
+ refinebonus[i][2]=10;
+ }
+ fp=fopen("db/refine_db.txt","r");
+ if(fp==NULL){
+ printf("can't read db/refine_db.txt\n");
+ return 1;
+ }
+ i=0;
+ while(fgets(line, sizeof(line)-1, fp)){
+ char *split[16];
+ if(line[0]=='/' && line[1]=='/')
+ continue;
+ if(atoi(line)<=0)
+ continue;
+ memset(split,0,sizeof(split));
+ for(j=0,p=line;j<16 && p;j++){
+ split[j]=p;
+ p=strchr(p,',');
+ if(p) *p++=0;
+ }
+ refinebonus[i][0]=atoi(split[0]); // 精?ボ?ナス
+ refinebonus[i][1]=atoi(split[1]); // 過?精?ボ?ナス
+ refinebonus[i][2]=atoi(split[2]); // 安全精?限界
+ for(j=0;j<10 && split[j];j++)
+ percentrefinery[i][j]=atoi(split[j+3]);
+ i++;
+ }
+ fclose(fp); //Lupus. close this file!!!
+ sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/refine_db.txt");
+ ShowStatus(tmp_output);
+
+ return 0;
+}
+
+/*==========================================
+ * スキル関係初期化処理
+ *------------------------------------------
+ */
+int do_init_status(void)
+{
+ add_timer_func_list(status_change_timer,"status_change_timer");
+ status_readdb();
+ status_calc_sigma();
+ return 0;
+}
diff --git a/src/map/status.h b/src/map/status.h
new file mode 100644
index 000000000..a07c47153
--- /dev/null
+++ b/src/map/status.h
@@ -0,0 +1,271 @@
+#ifndef _STATUS_H_
+#define _STATUS_H_
+
+enum { // struct map_session_data の status_changeの番?テ?ブル
+// SC_SENDMAX未?はクライアントへの通知あり。
+// 2-2次職の値はなんかめちゃくちゃっぽいので暫定。たぶん?更されます。
+ SC_SENDMAX = 128, // note: max is now 182, but we'll need to do alot of moving around
+ SC_PROVOKE = 0,
+ SC_ENDURE = 1,
+ SC_TWOHANDQUICKEN = 2,
+ SC_CONCENTRATE = 3,
+ SC_HIDING = 4,
+ SC_CLOAKING = 5,
+ SC_ENCPOISON = 6,
+ SC_POISONREACT = 7,
+ SC_QUAGMIRE = 8,
+ SC_ANGELUS = 9,
+ SC_BLESSING = 10,
+ SC_SIGNUMCRUCIS = 11,
+ SC_INCREASEAGI = 12,
+ SC_DECREASEAGI = 13,
+ SC_SLOWPOISON = 14,
+ SC_IMPOSITIO = 15,
+ SC_SUFFRAGIUM = 16,
+ SC_ASPERSIO = 17,
+ SC_BENEDICTIO = 18,
+ SC_KYRIE = 19,
+ SC_MAGNIFICAT = 20,
+ SC_GLORIA = 21,
+ SC_AETERNA = 22,
+ SC_ADRENALINE = 23,
+ SC_WEAPONPERFECTION = 24,
+ SC_OVERTHRUST = 25,
+ SC_MAXIMIZEPOWER = 26,
+ SC_RIDING = 27,
+ SC_FALCON = 28,
+ SC_TRICKDEAD = 29,
+ SC_LOUD = 30,
+ SC_ENERGYCOAT = 31,
+ SC_BROKNARMOR = 32,
+ SC_BROKNWEAPON = 33,
+ SC_HALLUCINATION = 34,
+ SC_WEIGHT50 = 35,
+ SC_WEIGHT90 = 36,
+ SC_SPEEDPOTION0 = 37,
+ SC_SPEEDPOTION1 = 38,
+ SC_SPEEDPOTION2 = 39,
+ SC_SPEEDPOTION3 = 40,
+ SC_SPEEDUP0 = 41, // for skill speedup
+ SC_SPEEDUP1 = 42, // for skill speedup
+//-- 43-50
+ SC_STRIPWEAPON = 50,
+ SC_STRIPSHIELD = 51,
+ SC_STRIPARMOR = 52,
+ SC_STRIPHELM = 53,
+ SC_CP_WEAPON = 54,
+ SC_CP_SHIELD = 55,
+ SC_CP_ARMOR = 56,
+ SC_CP_HELM = 57,
+ SC_AUTOGUARD = 58,
+ SC_REFLECTSHIELD = 59,
+ SC_DEVOTION = 60,
+ SC_PROVIDENCE = 61,
+ SC_DEFENDER = 62,
+ SC_AUTOSPELL = 65,
+ SC_SPEARSQUICKEN = 68,
+//-- 69-85
+ SC_EXPLOSIONSPIRITS = 86,
+ SC_STEELBODY = 87,
+ SC_COMBO = 89,
+ SC_FLAMELAUNCHER = 90,
+ SC_FROSTWEAPON = 91,
+ SC_LIGHTNINGLOADER = 92,
+ SC_SEISMICWEAPON = 93,
+//-- 94-102
+ SC_AURABLADE = 103, /* オ?ラブレ?ド */
+ SC_PARRYING = 104, /* パリイング */
+ SC_CONCENTRATION = 105, /* コンセントレ?ション */
+ SC_TENSIONRELAX = 106, /* テンションリラックス */
+ SC_BERSERK = 107, /* バ?サ?ク */
+//-- 108, 109
+ SC_ASSUMPTIO = 110, /* アシャンプティオ */
+//-- 111, 112
+ SC_MAGICPOWER = 113, /* 魔法力?幅 */
+ SC_EDP = 114, /* エフェクトが判明したら移動 */
+ SC_TRUESIGHT = 115, /* トゥル?サイト */
+ SC_WINDWALK = 116, /* ウインドウォ?ク */
+ SC_MELTDOWN = 117, /* メルトダウン */
+ SC_CARTBOOST = 118, /* カ?トブ?スト */
+//-- 119
+ SC_REJECTSWORD = 120, /* リジェクトソ?ド */
+ SC_MARIONETTE = 121, /* マリオネットコントロ?ル */
+ SC_MARIONETTE2 = 122, // Marionette target
+//-- 123
+ SC_BLEEDING = 124, /* ヘッドクラッシュ */
+ SC_JOINTBEAT = 125, /* ジョイントビ?ト */
+//-- 126, 127
+
+ SC_STONE = 128,
+ SC_FREEZE = 129,
+// <-- 130 = a baby skill status?
+ SC_STAN = 130,
+ SC_SLEEP = 131,
+// <-- 132 = another baby skill?
+ SC_POISON = 132,
+ SC_CURSE = 133,
+ SC_SILENCE = 134,
+ SC_CONFUSION = 135,
+ SC_BLIND = 136,
+ SC_DIVINA = SC_SILENCE,
+//-- 137-139
+ SC_SAFETYWALL = 140,
+ SC_PNEUMA = 141,
+//-- 142
+ SC_ANKLE = 143,
+ SC_DANCING = 144,
+ SC_KEEPING = 145,
+ SC_BARRIER = 146,
+//-- 147,148
+ SC_MAGICROD = 149,
+ SC_SIGHT = 150,
+ SC_RUWACH = 151,
+ SC_AUTOCOUNTER = 152,
+ SC_VOLCANO = 153,
+ SC_DELUGE = 154,
+ SC_VIOLENTGALE = 155,
+ SC_BLADESTOP_WAIT = 156,
+ SC_BLADESTOP = 157,
+ SC_EXTREMITYFIST = 158,
+//-- 159
+ SC_LULLABY =160,
+ SC_RICHMANKIM =161,
+ SC_ETERNALCHAOS =162,
+ SC_DRUMBATTLE =163,
+ SC_NIBELUNGEN =164,
+ SC_ROKISWEIL =165,
+ SC_INTOABYSS =166,
+ SC_SIEGFRIED =167,
+ SC_DISSONANCE =168,
+ SC_WHISTLE =169,
+ SC_ASSNCROS =170,
+ SC_POEMBRAGI =171,
+ SC_APPLEIDUN =172,
+ SC_UGLYDANCE =173,
+ SC_HUMMING =174,
+ SC_DONTFORGETME =175,
+ SC_FORTUNE =176,
+ SC_SERVICE4U =177,
+ SC_SPIDERWEB =180, /* スパイダ?ウェッブ */
+// <-- 181 = unknown status
+// <-- 182 = unknown status
+ SC_SACRIFICE =184, /* サクリファイス */
+ SC_WEDDING =187, //結婚用(結婚衣裳になって?くのが?いとか)
+ SC_NOCHAT =188, //赤エモ?態
+ SC_SPLASHER =189, /* ベナムスプラッシャ? */
+ SC_SELFDESTRUCTION =190, /* 自爆 */
+ SC_MEMORIZE =197, /* メモライズ */ // changed from 181 to 192
+ SC_DPOISON =198, /* 猛毒 */
+
+// Used by English Team
+ SC_SLOWDOWN =45, // for skill slowdown
+ SC_AUTOBERSERK =46,
+ SC_SIGHTTRASHER =73,
+ SC_BASILICA =102, // temporarily use this before an actual id is found [celest]
+
+ SC_ENSEMBLE =159,
+ SC_FOGWALL =178,
+ SC_GOSPEL =179,
+ SC_PRESERVE =181,
+ SC_BATTLEORDERS =182,
+ SC_MOONLIT =183,
+ SC_ATKPOT =185, // [Valaris]
+ SC_MATKPOT =186, // [Valaris]
+ SC_MINDBREAKER =191,
+ SC_SPELLBREAKER =192,
+ SC_LANDPROTECTOR =193,
+ SC_ADAPTATION =194,
+ SC_CHASEWALK =195,
+ SC_REGENERATION =196,
+ SC_GUILDAURA =199,
+ SC_BABY =200,
+
+// Icons
+ _SC_BABY =200
+};
+extern int SkillStatusChangeTable[];
+
+extern int current_equip_item_index;
+
+// パラメータ所得系 battle.c より移動
+int status_get_class(struct block_list *bl);
+int status_get_dir(struct block_list *bl);
+int status_get_lv(struct block_list *bl);
+int status_get_range(struct block_list *bl);
+int status_get_hp(struct block_list *bl);
+int status_get_max_hp(struct block_list *bl);
+int status_get_str(struct block_list *bl);
+int status_get_agi(struct block_list *bl);
+int status_get_vit(struct block_list *bl);
+int status_get_int(struct block_list *bl);
+int status_get_dex(struct block_list *bl);
+int status_get_luk(struct block_list *bl);
+int status_get_hit(struct block_list *bl);
+int status_get_flee(struct block_list *bl);
+int status_get_def(struct block_list *bl);
+int status_get_mdef(struct block_list *bl);
+int status_get_flee2(struct block_list *bl);
+int status_get_def2(struct block_list *bl);
+int status_get_mdef2(struct block_list *bl);
+int status_get_baseatk(struct block_list *bl);
+int status_get_atk(struct block_list *bl);
+int status_get_atk2(struct block_list *bl);
+int status_get_speed(struct block_list *bl);
+int status_get_adelay(struct block_list *bl);
+int status_get_amotion(struct block_list *bl);
+int status_get_dmotion(struct block_list *bl);
+int status_get_element(struct block_list *bl);
+int status_get_attack_element(struct block_list *bl);
+int status_get_attack_element2(struct block_list *bl); //左手武器属性取得
+#define status_get_elem_type(bl) (status_get_element(bl)%10)
+#define status_get_elem_level(bl) (status_get_element(bl)/10/2)
+int status_get_party_id(struct block_list *bl);
+int status_get_guild_id(struct block_list *bl);
+int status_get_race(struct block_list *bl);
+int status_get_size(struct block_list *bl);
+int status_get_mode(struct block_list *bl);
+int status_get_mexp(struct block_list *bl);
+int status_get_race2(struct block_list *bl);
+
+struct status_change *status_get_sc_data(struct block_list *bl);
+short *status_get_sc_count(struct block_list *bl);
+short *status_get_opt1(struct block_list *bl);
+short *status_get_opt2(struct block_list *bl);
+short *status_get_opt3(struct block_list *bl);
+short *status_get_option(struct block_list *bl);
+
+int status_get_matk1(struct block_list *bl);
+int status_get_matk2(struct block_list *bl);
+int status_get_critical(struct block_list *bl);
+int status_get_atk_(struct block_list *bl);
+int status_get_atk_2(struct block_list *bl);
+int status_get_atk2(struct block_list *bl);
+
+int status_isdead(struct block_list *bl);
+
+int status_get_sc_def(struct block_list *bl, int type);
+#define status_get_sc_def_mdef(bl) (status_get_sc_def(bl, SP_MDEF1))
+#define status_get_sc_def_vit(bl) (status_get_sc_def(bl, SP_DEF2))
+#define status_get_sc_def_int(bl) (status_get_sc_def(bl, SP_MDEF2))
+#define status_get_sc_def_luk(bl) (status_get_sc_def(bl, SP_LUK))
+
+// 状態異常関連 skill.c より移動
+int status_change_start(struct block_list *bl,int type,int val1,int val2,int val3,int val4,int tick,int flag);
+int status_change_end( struct block_list* bl , int type,int tid );
+int status_change_timer(int tid, unsigned int tick, int id, int data);
+int status_change_timer_sub(struct block_list *bl, va_list ap );
+int status_change_clear(struct block_list *bl,int type);
+
+// ステータス計算 pc.c から分離
+// pc_calcstatus
+int status_calc_pc(struct map_session_data* sd,int first);
+int status_calc_speed(struct map_session_data*); // [Celest]
+// int status_calc_skilltree(struct map_session_data *sd);
+int status_getrefinebonus(int lv,int type);
+int status_percentrefinery(struct map_session_data *sd,struct item *item);
+extern int percentrefinery[5][10];
+
+int status_readdb(void);
+int do_init_status(void);
+
+#endif
diff --git a/src/map/storage.c b/src/map/storage.c
index fc6f63cdd..82ecd9321 100644
--- a/src/map/storage.c
+++ b/src/map/storage.c
@@ -3,14 +3,18 @@
#include <stdlib.h>
#include <string.h>
-#include "db.h"
+#include "../common/db.h"
+#include "../common/nullpo.h"
+#include "../common/malloc.h"
+
#include "itemdb.h"
#include "clif.h"
#include "intif.h"
#include "pc.h"
#include "storage.h"
#include "guild.h"
-#include "nullpo.h"
+#include "battle.h"
+#include "atcommand.h"
#ifdef MEMWATCH
#include "memwatch.h"
@@ -42,13 +46,13 @@ struct item *i2=(struct item *)_i2;
void sortage_sortitem(struct storage* stor){
nullpo_retv(stor);
- qsort(stor->storage, MAX_STORAGE, sizeof(struct item), storage_comp_item);
+ qsort(stor->storage_, MAX_STORAGE, sizeof(struct item), storage_comp_item);
}
void sortage_gsortitem(struct guild_storage* gstor){
nullpo_retv(gstor);
- qsort(gstor->storage, MAX_GUILD_STORAGE, sizeof(struct item), storage_comp_item);
+ qsort(gstor->storage_, MAX_GUILD_STORAGE, sizeof(struct item), storage_comp_item);
}
/*==========================================
@@ -61,17 +65,32 @@ int do_init_storage(void) // map.c::do_init()から呼ばれる
guild_storage_db=numdb_init();
return 1;
}
-
-void do_final_storage(void) // map.c::do_final()から呼ばれる
+static int guild_storage_db_final(void *key,void *data,va_list ap)
+{
+ struct guild_storage *gstor=(struct guild_storage *) data;
+ aFree(gstor);
+ return 0;
+}
+static int storage_db_final(void *key,void *data,va_list ap)
{
+ struct storage *stor=(struct storage *) data;
+ aFree(stor);
+ return 0;
+}
+void do_final_storage(void) // by [MC Cameri]
+{
+ if (storage_db)
+ numdb_final(storage_db,storage_db_final);
+ if (guild_storage_db)
+ numdb_final(guild_storage_db,guild_storage_db_final);
}
struct storage *account2storage(int account_id)
{
struct storage *stor;
- stor=numdb_search(storage_db,account_id);
+ stor=(struct storage *) numdb_search(storage_db,account_id);
if(stor == NULL) {
- stor = calloc(sizeof(struct storage), 1);
+ stor = (struct storage *) aCallocA(sizeof(struct storage), 1);
if(stor == NULL){
printf("storage: out of memory!\n");
exit(0);
@@ -85,15 +104,15 @@ struct storage *account2storage(int account_id)
// Just to ask storage, without creation
struct storage *account2storage2(int account_id) {
- return numdb_search(storage_db, account_id);
+ return (struct storage *) numdb_search(storage_db, account_id);
}
int storage_delete(int account_id)
{
- struct storage *stor = numdb_search(storage_db,account_id);
+ struct storage *stor = (struct storage *) numdb_search(storage_db,account_id);
if(stor) {
numdb_erase(storage_db,account_id);
- free(stor);
+ aFree(stor);
}
return 0;
}
@@ -108,38 +127,25 @@ int storage_storageopen(struct map_session_data *sd)
nullpo_retr(0, sd);
- if((stor = numdb_search(storage_db,sd->status.account_id)) != NULL) {
- stor->storage_status = 1;
- sd->state.storage_flag = 0;
- clif_storageitemlist(sd,stor);
- clif_storageequiplist(sd,stor);
- clif_updatestorageamount(sd,stor);
- return 0;
+ if(pc_isGM(sd) && pc_isGM(sd) < battle_config.gm_can_drop_lv) {
+ clif_displaymessage(sd->fd, msg_txt(246));
+ return 1;
+ }
+ if((stor = (struct storage *) numdb_search(storage_db,sd->status.account_id)) != NULL) {
+ if (stor->storage_status == 0) {
+ stor->storage_status = 1;
+ sd->state.storage_flag = 0;
+ clif_storageitemlist(sd,stor);
+ clif_storageequiplist(sd,stor);
+ clif_updatestorageamount(sd,stor);
+ return 0;
+ }
} else
intif_request_storage(sd->status.account_id);
return 1;
}
-int storage_storageopen2(struct map_session_data *sd, struct map_session_data *pl_sd)
-{
- struct storage *stor;
- if(sd == NULL || pl_sd == NULL)
- {
- printf("storage_storageopen nullpo\n");
- return 0;
- }
-
- if((stor = numdb_search(storage_db,pl_sd->status.account_id)) != NULL)
- {
- clif_storageitemlist(sd,stor);
- clif_storageequiplist(sd,stor);
- clif_updatestorageamount(sd,stor);
- return 1;
- }
- return 0;
-}
-
/*==========================================
* カプラ倉庫へアイテム追加
*------------------------------------------
@@ -153,6 +159,8 @@ int storage_additem(struct map_session_data *sd,struct storage *stor,struct item
nullpo_retr(1, stor);
nullpo_retr(1, item_data);
+ stor->dirty = 1;
+
if(item_data->nameid <= 0 || amount <= 0)
return 1;
nullpo_retr(1, data = itemdb_search(item_data->nameid));
@@ -161,12 +169,10 @@ int storage_additem(struct map_session_data *sd,struct storage *stor,struct item
if(!itemdb_isequip2(data)){
// 装備品ではないので、既所有品なら個数のみ変化させる
for(i=0;i<MAX_STORAGE;i++){
- if(stor->storage[i].nameid == item_data->nameid &&
- stor->storage[i].card[0] == item_data->card[0] && stor->storage[i].card[1] == item_data->card[1] &&
- stor->storage[i].card[2] == item_data->card[2] && stor->storage[i].card[3] == item_data->card[3]){
- if(stor->storage[i].amount+amount > MAX_AMOUNT)
+ if( compare_item (&stor->storage_[i], item_data)) {
+ if(stor->storage_[i].amount+amount > MAX_AMOUNT)
return 1;
- stor->storage[i].amount+=amount;
+ stor->storage_[i].amount+=amount;
clif_storageitemadded(sd,stor,i,amount);
break;
}
@@ -175,9 +181,9 @@ int storage_additem(struct map_session_data *sd,struct storage *stor,struct item
if(i>=MAX_STORAGE){
// 装備品か未所有品だったので空き欄へ追加
for(i=0;i<MAX_STORAGE;i++){
- if(stor->storage[i].nameid==0){
- memcpy(&stor->storage[i],item_data,sizeof(stor->storage[0]));
- stor->storage[i].amount=amount;
+ if(stor->storage_[i].nameid==0){
+ memcpy(&stor->storage_[i],item_data,sizeof(stor->storage_[0]));
+ stor->storage_[i].amount=amount;
stor->storage_amount++;
clif_storageitemadded(sd,stor,i,amount);
clif_updatestorageamount(sd,stor);
@@ -187,6 +193,7 @@ int storage_additem(struct map_session_data *sd,struct storage *stor,struct item
if(i>=MAX_STORAGE)
return 1;
}
+
return 0;
}
/*==========================================
@@ -198,17 +205,19 @@ int storage_delitem(struct map_session_data *sd,struct storage *stor,int n,int a
nullpo_retr(1, sd);
nullpo_retr(1, stor);
- if(stor->storage[n].nameid==0 || stor->storage[n].amount<amount)
+ if(stor->storage_[n].nameid==0 || stor->storage_[n].amount<amount)
return 1;
- stor->storage[n].amount-=amount;
- if(stor->storage[n].amount==0){
- memset(&stor->storage[n],0,sizeof(stor->storage[0]));
+ stor->storage_[n].amount-=amount;
+ if(stor->storage_[n].amount==0){
+ memset(&stor->storage_[n],0,sizeof(stor->storage_[0]));
stor->storage_amount--;
clif_updatestorageamount(sd,stor);
}
clif_storageitemremoved(sd,n,amount);
+ stor->dirty = 1;
+
return 0;
}
/*==========================================
@@ -220,15 +229,16 @@ int storage_storageadd(struct map_session_data *sd,int index,int amount)
struct storage *stor;
nullpo_retr(0, sd);
- nullpo_retr(0, stor=account2storage(sd->status.account_id));
+ nullpo_retr(0, stor=account2storage2(sd->status.account_id));
if( (stor->storage_amount <= MAX_STORAGE) && (stor->storage_status == 1) ) { // storage not full & storage open
if(index>=0 && index<MAX_INVENTORY) { // valid index
- if( (amount <= sd->status.inventory[index].amount) && (amount > 0) ) { //valid amount
- if(storage_additem(sd,stor,&sd->status.inventory[index],amount)==0)
- // remove item from inventory
- pc_delitem(sd,index,amount,0);
- } // valid amount
+ if( (amount <= sd->status.inventory[index].amount) && (amount > 0) ) { //valid amount
+// log_tostorage(sd, index, 0);
+ if(storage_additem(sd,stor,&sd->status.inventory[index],amount)==0)
+ // remove item from inventory
+ pc_delitem(sd,index,amount,0);
+ } // valid amount
}// valid index
}// storage not full & storage open
@@ -245,15 +255,16 @@ int storage_storageget(struct map_session_data *sd,int index,int amount)
int flag;
nullpo_retr(0, sd);
- nullpo_retr(0, stor=account2storage(sd->status.account_id));
+ nullpo_retr(0, stor=account2storage2(sd->status.account_id));
if(stor->storage_status == 1) { // storage open
if(index>=0 && index<MAX_STORAGE) { // valid index
- if( (amount <= stor->storage[index].amount) && (amount > 0) ) { //valid amount
- if((flag = pc_additem(sd,&stor->storage[index],amount)) == 0)
+ if( (amount <= stor->storage_[index].amount) && (amount > 0) ) { //valid amount
+ if((flag = pc_additem(sd,&stor->storage_[index],amount)) == 0)
storage_delitem(sd,stor,index,amount);
else
clif_additem(sd,0,0,flag);
+// log_fromstorage(sd, index, 0);
} // valid amount
}// valid index
}// storage open
@@ -269,7 +280,7 @@ int storage_storageaddfromcart(struct map_session_data *sd,int index,int amount)
struct storage *stor;
nullpo_retr(0, sd);
- nullpo_retr(0, stor=account2storage(sd->status.account_id));
+ nullpo_retr(0, stor=account2storage2(sd->status.account_id));
if( (stor->storage_amount <= MAX_STORAGE) && (stor->storage_status == 1) ) { // storage not full & storage open
if(index>=0 && index<MAX_INVENTORY) { // valid index
@@ -292,12 +303,12 @@ int storage_storagegettocart(struct map_session_data *sd,int index,int amount)
struct storage *stor;
nullpo_retr(0, sd);
- nullpo_retr(0, stor=account2storage(sd->status.account_id));
+ nullpo_retr(0, stor=account2storage2(sd->status.account_id));
if(stor->storage_status == 1) { // storage open
if(index>=0 && index<MAX_STORAGE) { // valid index
- if( (amount <= stor->storage[index].amount) && (amount > 0) ) { //valid amount
- if(pc_cart_additem(sd,&stor->storage[index],amount)==0){
+ if( (amount <= stor->storage_[index].amount) && (amount > 0) ) { //valid amount
+ if(pc_cart_additem(sd,&stor->storage_[index],amount)==0){
storage_delitem(sd,stor,index,amount);
}
} // valid amount
@@ -317,12 +328,14 @@ int storage_storageclose(struct map_session_data *sd)
struct storage *stor;
nullpo_retr(0, sd);
- nullpo_retr(0, stor=account2storage(sd->status.account_id));
+ nullpo_retr(0, stor=account2storage2(sd->status.account_id));
stor->storage_status=0;
sd->state.storage_flag = 0;
clif_storageclose(sd);
+ storage_storage_save(sd);
+
sortage_sortitem(stor);
return 0;
}
@@ -337,20 +350,36 @@ int storage_storage_quit(struct map_session_data *sd)
nullpo_retr(0, sd);
- stor = numdb_search(storage_db,sd->status.account_id);
- if(stor) stor->storage_status = 0;
+ stor = (struct storage *) numdb_search(storage_db,sd->status.account_id);
+ if(stor) {
+ stor->storage_status = 0;
+ storage_storage_save(sd);
+ }
return 0;
}
+void storage_storage_dirty(struct map_session_data *sd)
+{
+ struct storage *stor;
+
+ stor=(struct storage *) numdb_search(storage_db,sd->status.account_id);
+
+ if(stor)
+ stor->dirty = 1;
+}
+
int storage_storage_save(struct map_session_data *sd)
{
struct storage *stor;
nullpo_retr(0, sd);
- stor=numdb_search(storage_db,sd->status.account_id);
- if(stor) intif_send_storage(stor);
+ stor=(struct storage *) numdb_search(storage_db,sd->status.account_id);
+ if(stor && stor->dirty) {
+ intif_send_storage(stor);
+ stor->dirty = 0;
+ }
return 0;
}
@@ -359,9 +388,9 @@ struct guild_storage *guild2storage(int guild_id)
{
struct guild_storage *gs = NULL;
if(guild_search(guild_id) != NULL) {
- gs=numdb_search(guild_storage_db,guild_id);
+ gs=(struct guild_storage *) numdb_search(guild_storage_db,guild_id);
if(gs == NULL) {
- gs = calloc(sizeof(struct guild_storage), 1);
+ gs = (struct guild_storage *) aCallocA(sizeof(struct guild_storage), 1);
if(gs==NULL){
printf("storage: out of memory!\n");
exit(0);
@@ -375,10 +404,10 @@ struct guild_storage *guild2storage(int guild_id)
int guild_storage_delete(int guild_id)
{
- struct guild_storage *gstor = numdb_search(guild_storage_db,guild_id);
+ struct guild_storage *gstor = (struct guild_storage *) numdb_search(guild_storage_db,guild_id);
if(gstor) {
numdb_erase(guild_storage_db,guild_id);
- free(gstor);
+ aFree(gstor);
}
return 0;
}
@@ -391,7 +420,7 @@ int storage_guild_storageopen(struct map_session_data *sd)
if(sd->status.guild_id <= 0)
return 2;
- if((gstor = numdb_search(guild_storage_db,sd->status.guild_id)) != NULL) {
+ if((gstor = (struct guild_storage *) numdb_search(guild_storage_db,sd->status.guild_id)) != NULL) {
if(gstor->storage_status)
return 1;
gstor->storage_status = 1;
@@ -427,12 +456,10 @@ int guild_storage_additem(struct map_session_data *sd,struct guild_storage *stor
if(!itemdb_isequip2(data)){
// 装備品ではないので、既所有品なら個数のみ変化させる
for(i=0;i<MAX_GUILD_STORAGE;i++){
- if(stor->storage[i].nameid == item_data->nameid &&
- stor->storage[i].card[0] == item_data->card[0] && stor->storage[i].card[1] == item_data->card[1] &&
- stor->storage[i].card[2] == item_data->card[2] && stor->storage[i].card[3] == item_data->card[3]){
- if(stor->storage[i].amount+amount > MAX_AMOUNT)
+ if(compare_item(&stor->storage_[i], item_data)) {
+ if(stor->storage_[i].amount+amount > MAX_AMOUNT)
return 1;
- stor->storage[i].amount+=amount;
+ stor->storage_[i].amount+=amount;
clif_guildstorageitemadded(sd,stor,i,amount);
break;
}
@@ -441,9 +468,9 @@ int guild_storage_additem(struct map_session_data *sd,struct guild_storage *stor
if(i>=MAX_GUILD_STORAGE){
// 装備品か未所有品だったので空き欄へ追加
for(i=0;i<MAX_GUILD_STORAGE;i++){
- if(stor->storage[i].nameid==0){
- memcpy(&stor->storage[i],item_data,sizeof(stor->storage[0]));
- stor->storage[i].amount=amount;
+ if(stor->storage_[i].nameid==0){
+ memcpy(&stor->storage_[i],item_data,sizeof(stor->storage_[0]));
+ stor->storage_[i].amount=amount;
stor->storage_amount++;
clif_guildstorageitemadded(sd,stor,i,amount);
clif_updateguildstorageamount(sd,stor);
@@ -461,12 +488,12 @@ int guild_storage_delitem(struct map_session_data *sd,struct guild_storage *stor
nullpo_retr(1, sd);
nullpo_retr(1, stor);
- if(stor->storage[n].nameid==0 || stor->storage[n].amount<amount)
+ if(stor->storage_[n].nameid==0 || stor->storage_[n].amount<amount)
return 1;
- stor->storage[n].amount-=amount;
- if(stor->storage[n].amount==0){
- memset(&stor->storage[n],0,sizeof(stor->storage[0]));
+ stor->storage_[n].amount-=amount;
+ if(stor->storage_[n].amount==0){
+ memset(&stor->storage_[n],0,sizeof(stor->storage_[0]));
stor->storage_amount--;
clif_updateguildstorageamount(sd,stor);
}
@@ -485,6 +512,7 @@ int storage_guild_storageadd(struct map_session_data *sd,int index,int amount)
if( (stor->storage_amount <= MAX_GUILD_STORAGE) && (stor->storage_status == 1) ) { // storage not full & storage open
if(index>=0 && index<MAX_INVENTORY) { // valid index
if( (amount <= sd->status.inventory[index].amount) && (amount > 0) ) { //valid amount
+// log_tostorage(sd, index, 1);
if(guild_storage_additem(sd,stor,&sd->status.inventory[index],amount)==0)
// remove item from inventory
pc_delitem(sd,index,amount,0);
@@ -506,11 +534,12 @@ int storage_guild_storageget(struct map_session_data *sd,int index,int amount)
if((stor=guild2storage(sd->status.guild_id)) != NULL) {
if(stor->storage_status == 1) { // storage open
if(index>=0 && index<MAX_GUILD_STORAGE) { // valid index
- if( (amount <= stor->storage[index].amount) && (amount > 0) ) { //valid amount
- if((flag = pc_additem(sd,&stor->storage[index],amount)) == 0)
+ if( (amount <= stor->storage_[index].amount) && (amount > 0) ) { //valid amount
+ if((flag = pc_additem(sd,&stor->storage_[index],amount)) == 0)
guild_storage_delitem(sd,stor,index,amount);
else
clif_additem(sd,0,0,flag);
+// log_fromstorage(sd, index, 1);
} // valid amount
}// valid index
}// storage open
@@ -548,8 +577,8 @@ int storage_guild_storagegettocart(struct map_session_data *sd,int index,int amo
if((stor=guild2storage(sd->status.guild_id)) != NULL) {
if(stor->storage_status == 1) { // storage open
if(index>=0 && index<MAX_GUILD_STORAGE) { // valid index
- if( (amount <= stor->storage[index].amount) && (amount > 0) ) { //valid amount
- if(pc_cart_additem(sd,&stor->storage[index],amount)==0){
+ if( (amount <= stor->storage_[index].amount) && (amount > 0) ) { //valid amount
+ if(pc_cart_additem(sd,&stor->storage_[index],amount)==0){
guild_storage_delitem(sd,stor,index,amount);
}
} // valid amount
@@ -583,7 +612,7 @@ int storage_guild_storage_quit(struct map_session_data *sd,int flag)
nullpo_retr(0, sd);
- stor = numdb_search(guild_storage_db,sd->status.guild_id);
+ stor = (struct guild_storage *) numdb_search(guild_storage_db,sd->status.guild_id);
if(stor) {
if(!flag)
intif_send_guild_storage(sd->status.account_id,stor);
diff --git a/src/map/storage.h b/src/map/storage.h
index 352dee4f0..7b2ac2cbe 100644
--- a/src/map/storage.h
+++ b/src/map/storage.h
@@ -5,7 +5,6 @@
#include "mmo.h"
int storage_storageopen(struct map_session_data *sd);
-int storage_storageopen2(struct map_session_data *sd,struct map_session_data *pl_sd);
int storage_storageadd(struct map_session_data *sd,int index,int amount);
int storage_storageget(struct map_session_data *sd,int index,int amount);
int storage_storageaddfromcart(struct map_session_data *sd,int index,int amount);
@@ -18,6 +17,7 @@ struct storage *account2storage2(int account_id);
int storage_delete(int account_id);
int storage_storage_quit(struct map_session_data *sd);
int storage_storage_save(struct map_session_data *sd);
+void storage_storage_dirty(struct map_session_data *sd);
struct guild_storage *guild2storage(int guild_id);
int guild_storage_delete(int guild_id);
diff --git a/src/map/trade.c b/src/map/trade.c
index 9d2128690..eb1d45ba2 100644
--- a/src/map/trade.c
+++ b/src/map/trade.c
@@ -1,6 +1,10 @@
+// $Id: trade.c 375 2005-03-04 21:33:31Z Yor $
+//#include <config.h>
+
#include <stdio.h>
#include <string.h>
+#include "../common/nullpo.h"
#include "clif.h"
#include "itemdb.h"
#include "map.h"
@@ -8,44 +12,46 @@
#include "pc.h"
#include "npc.h"
#include "battle.h"
-#include "nullpo.h"
+#include "chrif.h"
+#include "storage.h"
+#include "intif.h"
+#include "atcommand.h"
#include "log.h"
/*==========================================
* 取引要請を相手に送る
*------------------------------------------
*/
-void trade_traderequest(struct map_session_data *sd,int target_id)
-{
+void trade_traderequest(struct map_session_data *sd, int target_id) {
struct map_session_data *target_sd;
nullpo_retv(sd);
- if((target_sd = map_id2sd(target_id)) != NULL){
- if(!battle_config.invite_request_check) {
- if(target_sd->guild_invite>0 || target_sd->party_invite>0){
- clif_tradestart(sd,2); // 相手はPT要請中かGuild要請中
+ if ((target_sd = map_id2sd(target_id)) != NULL) {
+ if (!battle_config.invite_request_check) {
+ if (target_sd->guild_invite > 0 || target_sd->party_invite > 0) {
+ clif_tradestart(sd, 2); // 相手はPT要請中かGuild要請中
return;
}
}
- if((target_sd->trade_partner !=0) || (sd->trade_partner !=0)) {
- trade_tradecancel(sd); //person is in another trade
- }
- else{
- if((pc_isGM(sd) < 60) && (sd->bl.m != target_sd->bl.m
- || (sd->bl.x - target_sd->bl.x <= -5 || sd->bl.x - target_sd->bl.x >= 5)
- || (sd->bl.y - target_sd->bl.y <= -5 || sd->bl.y - target_sd->bl.y >= 5))) {
- clif_tradestart(sd,0); //too far
- }
- else if(sd!=target_sd) {
+ if(pc_isGM(sd) && pc_isGM(target_sd) < battle_config.gm_can_drop_lv) {
+ clif_displaymessage(sd->fd, msg_txt(246));
+ trade_tradecancel(sd); // GM is not allowed to trade
+ } else if ((target_sd->trade_partner != 0) || (sd->trade_partner != 0)) {
+ trade_tradecancel(sd); // person is in another trade
+ } else {
+ if (!pc_isGM(sd) && (sd->bl.m != target_sd->bl.m ||
+ (sd->bl.x - target_sd->bl.x <= -5 || sd->bl.x - target_sd->bl.x >= 5) ||
+ (sd->bl.y - target_sd->bl.y <= -5 || sd->bl.y - target_sd->bl.y >= 5))) {
+ clif_tradestart(sd, 0); // too far
+ } else if (sd != target_sd) {
target_sd->trade_partner = sd->status.account_id;
sd->trade_partner = target_sd->status.account_id;
- clif_traderequest(target_sd,sd->status.name);
+ clif_traderequest(target_sd, sd->status.name);
}
}
- }
- else{
- clif_tradestart(sd,1); //character does not exist
+ } else {
+ clif_tradestart(sd, 1); // character does not exist
}
}
@@ -53,34 +59,103 @@ void trade_traderequest(struct map_session_data *sd,int target_id)
* 取引要請
*------------------------------------------
*/
-void trade_tradeack(struct map_session_data *sd,int type)
-{
+void trade_tradeack(struct map_session_data *sd, int type) {
struct map_session_data *target_sd;
-
+ struct storage *stor;
nullpo_retv(sd);
- if((target_sd = map_id2sd(sd->trade_partner)) != NULL){
- clif_tradestart(target_sd,type);
- clif_tradestart(sd,type);
- if(type == 4){ // Cancel
- sd->deal_locked =0;
- sd->trade_partner=0;
- target_sd->deal_locked=0;
- target_sd->trade_partner=0;
+ if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) {
+ clif_tradestart(target_sd, type);
+ clif_tradestart(sd, type);
+ if (type == 4) { // Cancel
+ sd->deal_locked = 0;
+ sd->trade_partner = 0;
+ target_sd->deal_locked = 0;
+ target_sd->trade_partner = 0;
}
- if(sd->npc_id != 0)
+ if (sd->npc_id != 0)
npc_event_dequeue(sd);
- if(target_sd->npc_id != 0)
+ if (target_sd->npc_id != 0)
npc_event_dequeue(target_sd);
+
+ //close STORAGE window if it's open. It protects from spooffing packets [Lupus]
+ stor=account2storage2(sd->status.account_id);
+ if(stor!=NULL && stor->storage_status == 1) {
+ if (sd->state.storage_flag) //is it Guild Storage or Common
+ storage_guild_storageclose(sd);
+ else
+ storage_storageclose(sd);
+ }//END OF STORAGE CLOSE
}
}
/*==========================================
+ * Check here hacker for duplicate item in trade
+ * normal client refuse to have 2 same types of item (except equipment) in same trade window
+ * normal client authorise only no equiped item and only from inventory
+ *------------------------------------------
+ */
+int impossible_trade_check(struct map_session_data *sd) {
+ struct item inventory[MAX_INVENTORY];
+ char message_to_gm[200];
+ int i, index;
+
+ nullpo_retr(0, sd);
+
+ // get inventory of player
+ memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY);
+
+/* remove this part: arrows can be trade and equiped
+ // remove equiped items (they can not be trade)
+ for (i = 0; i < MAX_INVENTORY; i++)
+ if (inventory[i].nameid > 0 && inventory[i].equip)
+ memset(&inventory[i], 0, sizeof(struct item));
+*/
+
+ // check items in player inventory
+ for(i = 0; i < 10; i++)
+ if (sd->deal_item_amount[i] < 0) { // negativ? -> hack
+// printf("Negativ amount in trade, by hack!\n"); // normal client send cancel when we type negativ amount
+ return -1;
+ } else if (sd->deal_item_amount[i] > 0) {
+ index = sd->deal_item_index[i] - 2;
+ inventory[index].amount -= sd->deal_item_amount[i]; // remove item from inventory
+// printf("%d items left\n", inventory[index].amount);
+ if (inventory[index].amount < 0) { // if more than the player have -> hack
+// printf("A player try to trade more items that he has: hack!\n");
+ sprintf(message_to_gm, msg_txt(538), sd->status.name, sd->status.account_id); // Hack on trade: character '%s' (account: %d) try to trade more items that he has.
+ intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm);
+ sprintf(message_to_gm, msg_txt(539), sd->status.inventory[index].amount, sd->status.inventory[index].nameid, sd->status.inventory[index].amount - inventory[index].amount); // This player has %d of a kind of item (id: %d), and try to trade %d of them.
+ intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm);
+ // if we block people
+ if (battle_config.ban_hack_trade < 0) {
+ chrif_char_ask_name(-1, sd->status.name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block
+ clif_setwaitclose(sd->fd); // forced to disconnect because of the hack
+ // message about the ban
+ sprintf(message_to_gm, msg_txt(540), battle_config.ban_spoof_namer); // This player has been definitivly blocked.
+ // if we ban people
+ } else if (battle_config.ban_hack_trade > 0) {
+ chrif_char_ask_name(-1, sd->status.name, 2, 0, 0, 0, 0, battle_config.ban_hack_trade, 0); // type: 2 - ban (year, month, day, hour, minute, second)
+ clif_setwaitclose(sd->fd); // forced to disconnect because of the hack
+ // message about the ban
+ sprintf(message_to_gm, msg_txt(507), battle_config.ban_spoof_namer); // This player has been banned for %d minute(s).
+ } else {
+ // message about the ban
+ sprintf(message_to_gm, msg_txt(508)); // This player hasn't been banned (Ban option is disabled).
+ }
+ intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*==========================================
* アイテム追加
*------------------------------------------
*/
-void trade_tradeadditem(struct map_session_data *sd, int index, int amount)
-{
+void trade_tradeadditem(struct map_session_data *sd, int index, int amount) {
struct map_session_data *target_sd;
int trade_i;
int trade_weight = 0;
@@ -89,7 +164,7 @@ void trade_tradeadditem(struct map_session_data *sd, int index, int amount)
nullpo_retv(sd);
if (((target_sd = map_id2sd(sd->trade_partner)) != NULL) && (sd->deal_locked < 1)){
- if (index < 2 || index >= MAX_INVENTORY + 2){
+ if (index < 2 || index >= MAX_INVENTORY + 2) {
if (index == 0) {
if (amount > 0 && amount <= MAX_ZENY && amount <= sd->status.zeny && // check amount
(target_sd->status.zeny + amount) <= MAX_ZENY) { // fix positiv overflow
@@ -108,7 +183,7 @@ void trade_tradeadditem(struct map_session_data *sd, int index, int amount)
trade_weight += sd->inventory_data[index-2]->weight * amount;
if (target_sd->weight + trade_weight > target_sd->max_weight){
clif_tradeitemok(sd, index, 1); // fail to add item -- the player was over weighted.
- amount = 0; // [MouseJstr]
+ amount = 0;
} else {
for(c = 0; c == trade_i - 1; c++) { // re-deal exploit protection [Valaris]
if (sd->deal_item_index[c] == index) {
@@ -118,6 +193,10 @@ void trade_tradeadditem(struct map_session_data *sd, int index, int amount)
}
sd->deal_item_index[trade_i] = index;
sd->deal_item_amount[trade_i] += amount;
+ if (impossible_trade_check(sd)) { // check exploit (trade more items that you have)
+ trade_tradecancel(sd);
+ return;
+ }
clif_tradeitemok(sd, index, 0); // success to add item
clif_tradeadditem(sd, target_sd, index, amount);
}
@@ -134,27 +213,39 @@ void trade_tradeadditem(struct map_session_data *sd, int index, int amount)
* アイテム追加完了(ok押し)
*------------------------------------------
*/
-void trade_tradeok(struct map_session_data *sd)
-{
+void trade_tradeok(struct map_session_data *sd) {
struct map_session_data *target_sd;
int trade_i;
nullpo_retv(sd);
-
- for(trade_i=0;trade_i<10;trade_i++) {
- if(sd->deal_item_amount[trade_i]>sd->status.inventory[sd->deal_item_index[trade_i]-2].amount ||
- sd->deal_item_amount[trade_i]<0) {
+
+ // check items
+ for(trade_i = 0; trade_i < 10; trade_i++) {
+ if ((((sd->deal_item_index[trade_i]-2) >= 0) &&
+ (sd->deal_item_amount[trade_i] > sd->status.inventory[sd->deal_item_index[trade_i]-2].amount)) ||
+ (sd->deal_item_amount[trade_i] < 0)) {
trade_tradecancel(sd);
return;
}
-
}
-
- if((target_sd = map_id2sd(sd->trade_partner)) != NULL){
- sd->deal_locked=1;
- clif_tradeitemok(sd,0,0);
- clif_tradedeal_lock(sd,0);
- clif_tradedeal_lock(target_sd,1);
+
+ // check exploit (trade more items that you have)
+ if (impossible_trade_check(sd)) {
+ trade_tradecancel(sd);
+ return;
+ }
+
+ // check zeny
+ if (sd->deal_zeny < 0 || sd->deal_zeny > MAX_ZENY || sd->deal_zeny > sd->status.zeny) { // check amount
+ trade_tradecancel(sd);
+ return;
+ }
+
+ if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) {
+ sd->deal_locked = 1;
+ clif_tradeitemok(sd, 0, 0);
+ clif_tradedeal_lock(sd, 0);
+ clif_tradedeal_lock(target_sd, 1);
}
}
@@ -162,38 +253,37 @@ void trade_tradeok(struct map_session_data *sd)
* 取引キャンセル
*------------------------------------------
*/
-void trade_tradecancel(struct map_session_data *sd)
-{
+void trade_tradecancel(struct map_session_data *sd) {
struct map_session_data *target_sd;
int trade_i;
nullpo_retv(sd);
- if((target_sd = map_id2sd(sd->trade_partner)) != NULL){
- for(trade_i=0; trade_i<10;trade_i++) { //give items back (only virtual)
- if(sd->deal_item_amount[trade_i] != 0) {
- clif_additem(sd,sd->deal_item_index[trade_i]-2,sd->deal_item_amount[trade_i],0);
- sd->deal_item_index[trade_i] =0;
- sd->deal_item_amount[trade_i]=0;
+ if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) {
+ for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual)
+ if (sd->deal_item_amount[trade_i] != 0) {
+ clif_additem(sd, sd->deal_item_index[trade_i] - 2, sd->deal_item_amount[trade_i], 0);
+ sd->deal_item_index[trade_i] = 0;
+ sd->deal_item_amount[trade_i] = 0;
}
- if(target_sd->deal_item_amount[trade_i] != 0) {
- clif_additem(target_sd,target_sd->deal_item_index[trade_i]-2,target_sd->deal_item_amount[trade_i],0);
- target_sd->deal_item_index[trade_i] =0;
- target_sd->deal_item_amount[trade_i]=0;
+ if (target_sd->deal_item_amount[trade_i] != 0) {
+ clif_additem(target_sd, target_sd->deal_item_index[trade_i] - 2, target_sd->deal_item_amount[trade_i], 0);
+ target_sd->deal_item_index[trade_i] = 0;
+ target_sd->deal_item_amount[trade_i] = 0;
}
}
- if(sd->deal_zeny) {
- clif_updatestatus(sd,SP_ZENY);
- sd->deal_zeny=0;
+ if (sd->deal_zeny) {
+ clif_updatestatus(sd, SP_ZENY);
+ sd->deal_zeny = 0;
}
- if(target_sd->deal_zeny) {
- clif_updatestatus(target_sd,SP_ZENY);
- target_sd->deal_zeny=0;
+ if (target_sd->deal_zeny) {
+ clif_updatestatus(target_sd, SP_ZENY);
+ target_sd->deal_zeny = 0;
}
- sd->deal_locked =0;
- sd->trade_partner=0;
- target_sd->deal_locked=0;
- target_sd->trade_partner=0;
+ sd->deal_locked = 0;
+ sd->trade_partner = 0;
+ target_sd->deal_locked = 0;
+ target_sd->trade_partner = 0;
clif_tradecancelled(sd);
clif_tradecancelled(target_sd);
}
@@ -203,91 +293,96 @@ void trade_tradecancel(struct map_session_data *sd)
* 取引許諾(trade押し)
*------------------------------------------
*/
-void trade_tradecommit(struct map_session_data *sd)
-{
+void trade_tradecommit(struct map_session_data *sd) {
struct map_session_data *target_sd;
int trade_i;
+ int flag;
nullpo_retv(sd);
- if((target_sd = map_id2sd(sd->trade_partner)) != NULL){
- if( (sd->deal_locked >=1) && (target_sd->deal_locked >=1) ){ // both have pressed 'ok'
- if(sd->deal_locked < 2) {sd->deal_locked=2;} // set locked to 2
- if(target_sd->deal_locked==2) { // the other one pressed 'trade' too
- for(trade_i=0; trade_i<10;trade_i++) {
- if(sd->deal_item_amount[trade_i] != 0) {
- int n=sd->deal_item_index[trade_i]-2;
- int flag;
-
- //Dupe Fix by mark
- if (sd->status.inventory[n].amount < sd->deal_item_amount[trade_i])
- sd->deal_item_amount[trade_i] = sd->status.inventory[n].amount;
- //End Dupe Fix
-
- #ifndef TXT_ONLY
- if(log_config.trade > 0)
- log_trade(sd,target_sd,n,sd->deal_item_amount[trade_i]);
- #endif //USE_SQL
-
- flag = pc_additem(target_sd,&sd->status.inventory[n],sd->deal_item_amount[trade_i]);
- if(flag==0)
- pc_delitem(sd,n,sd->deal_item_amount[trade_i],1);
- else
- clif_additem(sd,n,sd->deal_item_amount[trade_i],0);
- sd->deal_item_index[trade_i] =0;
- sd->deal_item_amount[trade_i]=0;
- }
- if(target_sd->deal_item_amount[trade_i] != 0) {
- int n=target_sd->deal_item_index[trade_i]-2;
- int flag;
-
- //Dupe Fix by mark
- if (target_sd->status.inventory[n].amount < target_sd->deal_item_amount[trade_i])
- target_sd->deal_item_amount[trade_i] = target_sd->status.inventory[n].amount;
- //End Dupe Fix
-
- #ifndef TXT_ONLY
- if(log_config.trade > 0)
- log_trade(target_sd,sd,n,target_sd->deal_item_amount[trade_i]);
- #endif //USE_SQL
-
- flag = pc_additem(sd,&target_sd->status.inventory[n],target_sd->deal_item_amount[trade_i]);
- if(flag==0)
- pc_delitem(target_sd,n,target_sd->deal_item_amount[trade_i],1);
- else
- clif_additem(target_sd,n,target_sd->deal_item_amount[trade_i],0);
- target_sd->deal_item_index[trade_i] =0;
- target_sd->deal_item_amount[trade_i]=0;
- }
+ if ((target_sd = map_id2sd(sd->trade_partner)) != NULL) {
+ if ((sd->deal_locked >= 1) && (target_sd->deal_locked >= 1)) { // both have pressed 'ok'
+ if (sd->deal_locked < 2) { // set locked to 2
+ sd->deal_locked = 2;
+ }
+ if (target_sd->deal_locked == 2) { // the other one pressed 'trade' too
+ // check exploit (trade more items that you have)
+ if (impossible_trade_check(sd)) {
+ trade_tradecancel(sd);
+ return;
}
- if(sd->deal_zeny) {
- #ifndef TXT_ONLY
- if (log_config.trade > 0 && log_config.zeny > 0)
- log_zeny(sd, target_sd, sd->deal_zeny);
- #endif //USE_SQL
- sd->status.zeny -= sd->deal_zeny;
- clif_updatestatus(sd,SP_ZENY);
- target_sd->status.zeny += sd->deal_zeny;
- clif_updatestatus(target_sd,SP_ZENY);
- sd->deal_zeny=0;
+ // check exploit (trade more items that you have)
+ if (impossible_trade_check(target_sd)) {
+ trade_tradecancel(target_sd);
+ return;
}
- if(target_sd->deal_zeny) {
- #ifndef TXT_ONLY
- if (log_config.trade > 0 && log_config.zeny > 0)
- log_zeny(target_sd, sd, target_sd->deal_zeny);
- #endif //USE_SQL
- target_sd->status.zeny -= target_sd->deal_zeny;
- clif_updatestatus(target_sd,SP_ZENY);
- sd->status.zeny += target_sd->deal_zeny;
- clif_updatestatus(sd,SP_ZENY);
- target_sd->deal_zeny=0;
+ // check zenys value against hackers
+ if (sd->deal_zeny >= 0 && sd->deal_zeny <= MAX_ZENY && sd->deal_zeny <= sd->status.zeny && // check amount
+ (target_sd->status.zeny + sd->deal_zeny) <= MAX_ZENY && // fix positiv overflow
+ target_sd->deal_zeny >= 0 && target_sd->deal_zeny <= MAX_ZENY && target_sd->deal_zeny <= target_sd->status.zeny && // check amount
+ (sd->status.zeny + target_sd->deal_zeny) <= MAX_ZENY) { // fix positiv overflow
+
+ // trade is accepted
+ for(trade_i = 0; trade_i < 10; trade_i++) {
+ if (sd->deal_item_amount[trade_i] != 0) {
+ int n = sd->deal_item_index[trade_i] - 2;
+
+ if (sd->status.inventory[n].amount < sd->deal_item_amount[trade_i])
+ sd->deal_item_amount[trade_i] = sd->status.inventory[n].amount;
+ log_trade(sd, target_sd, n, sd->deal_item_amount[trade_i]);
+
+ flag = pc_additem(target_sd, &sd->status.inventory[n], sd->deal_item_amount[trade_i]);
+ if (flag == 0)
+ pc_delitem(sd, n, sd->deal_item_amount[trade_i], 1);
+ else
+ clif_additem(sd, n, sd->deal_item_amount[trade_i], 0);
+ sd->deal_item_index[trade_i] = 0;
+ sd->deal_item_amount[trade_i] = 0;
+
+ }
+ if (target_sd->deal_item_amount[trade_i] != 0) {
+ int n = target_sd->deal_item_index[trade_i] - 2;
+
+ if (target_sd->status.inventory[n].amount < target_sd->deal_item_amount[trade_i])
+ target_sd->deal_item_amount[trade_i] = target_sd->status.inventory[n].amount;
+
+ log_trade(target_sd, sd, n, target_sd->deal_item_amount[trade_i]);
+ flag = pc_additem(sd, &target_sd->status.inventory[n], target_sd->deal_item_amount[trade_i]);
+ if (flag == 0)
+ pc_delitem(target_sd, n, target_sd->deal_item_amount[trade_i], 1);
+ else
+ clif_additem(target_sd, n, target_sd->deal_item_amount[trade_i], 0);
+ target_sd->deal_item_index[trade_i] = 0;
+ target_sd->deal_item_amount[trade_i] = 0;
+ }
+ }
+ if (sd->deal_zeny) {
+ sd->status.zeny -= sd->deal_zeny;
+ target_sd->status.zeny += sd->deal_zeny;
+ }
+ if (target_sd->deal_zeny) {
+ target_sd->status.zeny -= target_sd->deal_zeny;
+ sd->status.zeny += target_sd->deal_zeny;
+ }
+ if (sd->deal_zeny || target_sd->deal_zeny) {
+ clif_updatestatus(sd, SP_ZENY);
+ sd->deal_zeny = 0;
+ clif_updatestatus(target_sd, SP_ZENY);
+ target_sd->deal_zeny = 0;
+ }
+ sd->deal_locked = 0;
+ sd->trade_partner = 0;
+ target_sd->deal_locked = 0;
+ target_sd->trade_partner = 0;
+ clif_tradecompleted(sd, 0);
+ clif_tradecompleted(target_sd, 0);
+ // save both player to avoid crash: they always have no advantage/disadvantage between the 2 players
+ chrif_save(sd); // do pc_makesavestatus and save storage too
+ chrif_save(target_sd); // do pc_makesavestatus and save storage too
+ // zeny value was modified!!!! hacker with packet modified
+ } else {
+ trade_tradecancel(sd);
}
- sd->deal_locked =0;
- sd->trade_partner=0;
- target_sd->deal_locked=0;
- target_sd->trade_partner=0;
- clif_tradecompleted(sd,0);
- clif_tradecompleted(target_sd,0);
}
}
}
diff --git a/src/map/vending.c b/src/map/vending.c
index a7aa708e5..2d3790596 100644
--- a/src/map/vending.c
+++ b/src/map/vending.c
@@ -48,7 +48,7 @@ void vending_vendinglistreq(struct map_session_data *sd,int id)
*/
void vending_purchasereq(struct map_session_data *sd,int len,int id,unsigned char *p)
{
- int i, j, w, z, new = 0, blank, vend_list[12];
+ int i, j, w, z, new_ = 0, blank, vend_list[12];
short amount, index;
struct map_session_data *vsd = map_id2sd(id);
@@ -99,8 +99,8 @@ void vending_purchasereq(struct map_session_data *sd,int len,int id,unsigned cha
case ADDITEM_EXIST:
break;
case ADDITEM_NEW:
- new++;
- if (new > blank)
+ new_++;
+ if (new_ > blank)
return; // 種類数超過
break;
case ADDITEM_OVERAMOUNT:
@@ -112,6 +112,7 @@ void vending_purchasereq(struct map_session_data *sd,int len,int id,unsigned cha
clif_tradecancelled(vsd);
return;
}
+
pc_payzeny(sd, z);
pc_getzeny(vsd, z);
for(i = 0; 8 + 4 * i < len; i++) {
@@ -122,6 +123,13 @@ void vending_purchasereq(struct map_session_data *sd,int len,int id,unsigned cha
vsd->vending[vend_list[i]].amount -= amount;
pc_cart_delitem(vsd, index, amount, 0);
clif_vendingreport(vsd, index, amount);
+
+ //log added by Lupus
+ if(log_config.vend > 0) {
+ log_vend(sd,vsd, index, amount, z); // for Item + Zeny. log.
+ //we log ZENY only with the 1st item. Then zero it for the rest items 8).
+ z = 0;
+ }
}
}
@@ -141,11 +149,14 @@ void vending_openvending(struct map_session_data *sd,int len,char *message,int f
}
if (flag) {
- for(i = 0; 85 + 8 * i < len; i++) {
+ for(i = 0; (85 + 8 * i < len) && (i < MAX_VENDING); i++) {
sd->vending[i].index = *(short*)(p+8*i)-2;
sd->vending[i].amount = *(short*)(p+2+8*i);
sd->vending[i].value = *(int*)(p+4+8*i);
- if(sd->vending[i].value>battle_config.vending_max_value)sd->vending[i].value=battle_config.vending_max_value;
+ if(sd->vending[i].value > battle_config.vending_max_value)
+ sd->vending[i].value=battle_config.vending_max_value;
+ else if(sd->vending[i].value == 0)
+ sd->vending[i].value = 1000000; // auto set to 1 million [celest]
// カート内のアイテム数と販売するアイテム数に相違があったら中止
if(pc_cartitem_amount(sd, sd->vending[i].index, sd->vending[i].amount) < 0 || sd->vending[i].value < 0) { // fixes by Valaris and fritz
clif_skill_fail(sd, MC_VENDING, 0, 0);