diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/Makefile | 102 | ||||
-rw-r--r-- | src/map/atcommand.c | 52 | ||||
-rw-r--r-- | src/map/atcommand.h | 2 | ||||
-rw-r--r-- | src/map/battle.c | 16 | ||||
-rw-r--r-- | src/map/chrif.c | 11 | ||||
-rw-r--r-- | src/map/chrif.h | 1 | ||||
-rw-r--r-- | src/map/guild.c | 10 | ||||
-rw-r--r-- | src/map/itemdb.c | 18 | ||||
-rw-r--r-- | src/map/map.c | 152 | ||||
-rw-r--r-- | src/map/map.h | 39 | ||||
-rw-r--r-- | src/map/mob.c | 98 | ||||
-rw-r--r-- | src/map/path.c | 2 | ||||
-rw-r--r-- | src/map/pc.c | 93 | ||||
-rw-r--r-- | src/map/skill.c | 2820 | ||||
-rw-r--r-- | src/map/skill.h | 36 | ||||
-rw-r--r-- | src/map/status.c | 31 | ||||
-rw-r--r-- | src/map/status.h | 2 |
17 files changed, 1564 insertions, 1921 deletions
diff --git a/src/map/Makefile b/src/map/Makefile index 884e8b902..b413c8a62 100644 --- a/src/map/Makefile +++ b/src/map/Makefile @@ -10,7 +10,9 @@ txtobj: sqlobj: mkdir sqlobj -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/grfio.o ../common/db.o ../common/lock.o ../common/nullpo.o ../common/malloc.o ../common/showmsg.o ../common/utils.o ../common/strlib.o +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/grfio.o ../common/obj/db.o ../common/obj/lock.o ../common/obj/nullpo.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o ../common/obj/strlib.o + +COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/grfio.h ../common/db.h ../common/lock.h ../common/nullpo.h ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h LIBS = -lz -lm map-server: txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/status.o txtobj/npc.o txtobj/npc_chat.o txtobj/chat.o txtobj/path.o txtobj/itemdb.o txtobj/mob.o txtobj/script.o txtobj/storage.o txtobj/skill.o txtobj/atcommand.o txtobj/charcommand.o txtobj/battle.o txtobj/intif.o txtobj/trade.o txtobj/party.o txtobj/vending.o txtobj/guild.o txtobj/pet.o txtobj/log.o $(COMMON_OBJ) @@ -25,56 +27,56 @@ txtobj/%.o: %.c sqlobj/%.o: %.c $(COMPILE.c) $(OUTPUT_OPTION) $< -txtobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h ../common/core.h ../common/timer.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -txtobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/showmsg.h -txtobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h -txtobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h -txtobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h -txtobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h -txtobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -txtobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h ../common/timer.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -txtobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h ../common/timer.h ../common/socket.h ../common/db.h ../common/mmo.h ../common/lock.h ../common/showmsg.h -txtobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h ../common/mmo.h ../common/db.h ../common/showmsg.h -txtobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -txtobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h ../common/mmo.h ../common/showmsg.h -txtobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h ../common/mmo.h ../common/showmsg.h -txtobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/log.o: log.c log.h map.h ../common/nullpo.h -txtobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h +txtobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h $(COMMON_H) +txtobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h $(COMMON_H) +txtobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h $(COMMON_H) +txtobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h $(COMMON_H) +txtobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h $(COMMON_H) +txtobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +txtobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +txtobj/chat.o: chat.c map.h clif.h pc.h chat.h $(COMMON_H) +txtobj/path.o: path.c map.h battle.h $(COMMON_H) +txtobj/itemdb.o: itemdb.c map.h battle.h itemdb.h $(COMMON_H) +txtobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h $(COMMON_H) +txtobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h $(COMMON_H) +txtobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h $(COMMON_H) +txtobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h $(COMMON_H) +txtobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) +txtobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h $(COMMON_H) +txtobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h $(COMMON_H) +txtobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h $(COMMON_H) +txtobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h $(COMMON_H) +txtobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h $(COMMON_H) +txtobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h $(COMMON_H) +txtobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h $(COMMON_H) +txtobj/log.o: log.c log.h map.h $(COMMON_H) +txtobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) -sqlobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h log.h ../common/core.h ../common/timer.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -sqlobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/showmsg.h -sqlobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h log.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h -sqlobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h -sqlobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h -sqlobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h -sqlobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -sqlobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h log.h ../common/timer.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -sqlobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h ../common/timer.h ../common/socket.h ../common/db.h ../common/mmo.h ../common/lock.h ../common/showmsg.h -sqlobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h ../common/mmo.h ../common/db.h ../common/showmsg.h -sqlobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h log.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -sqlobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h log.h ../common/mmo.h ../common/showmsg.h -sqlobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h log.h ../common/mmo.h ../common/showmsg.h -sqlobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/mail.o: mail.c mail.h ../common/showmsg.h ../common/strlib.h ../common/utils.h -sqlobj/log.o: log.c log.h map.h ../common/nullpo.h -sqlobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h +sqlobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h log.h $(COMMON_H) +sqlobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h $(COMMON_H) +sqlobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h $(COMMON_H) +sqlobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h log.h $(COMMON_H) +sqlobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h $(COMMON_H) +sqlobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +sqlobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +sqlobj/chat.o: chat.c map.h clif.h pc.h chat.h $(COMMON_H) +sqlobj/path.o: path.c map.h battle.h $(COMMON_H) +sqlobj/itemdb.o: itemdb.c map.h battle.h itemdb.h $(COMMON_H) +sqlobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h log.h $(COMMON_H) +sqlobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h $(COMMON_H) +sqlobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h $(COMMON_H) +sqlobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h log.h $(COMMON_H) +sqlobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) +sqlobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h $(COMMON_H) +sqlobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h $(COMMON_H) +sqlobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h log.h $(COMMON_H) +sqlobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h $(COMMON_H) +sqlobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h log.h $(COMMON_H) +sqlobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h $(COMMON_H) +sqlobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h $(COMMON_H) +sqlobj/mail.o: mail.c mail.h $(COMMON_H) +sqlobj/log.o: log.c log.h map.h $(COMMON_H) +sqlobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) clean: rm -rf *.o ../../map-server ../../map-server_sql sqlobj txtobj diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 12e6c2306..3169c75ab 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -9,6 +9,7 @@ #include "../common/timer.h" #include "../common/nullpo.h" #include "../common/mmo.h" +#include "../common/db.h" #include "log.h" #include "clif.h" @@ -210,6 +211,8 @@ ACMD_FUNC(gmotd); // Added by MC Cameri, created by davidsiaw ACMD_FUNC(misceffect); // by MC Cameri ACMD_FUNC(mobsearch); ACMD_FUNC(cleanmap); +ACMD_FUNC(npctalk); +ACMD_FUNC(pettalk); ACMD_FUNC(autoloot); // by Upa-Kun #ifndef TXT_ONLY @@ -484,6 +487,8 @@ static AtCommandInfo atcommand_info[] = { { AtCommand_MiscEffect, "@misceffect", 50, atcommand_misceffect }, // by MC Cameri { AtCommand_MobSearch, "@mobsearch", 0, atcommand_mobsearch }, { AtCommand_CleanMap, "@cleanmap", 0, atcommand_cleanmap }, + { AtCommand_NpcTalk, "@npctalk", 0, atcommand_npctalk }, + { AtCommand_PetTalk, "@pettalk", 0, atcommand_pettalk }, #ifndef TXT_ONLY // sql-only commands { AtCommand_CheckMail, "@checkmail", 1, atcommand_listmail }, // [Valaris] @@ -1743,8 +1748,8 @@ int atcommand_whozeny( clif_displaymessage(fd, output); } - free(zeny); - free(counted); + aFree(zeny); + aFree(counted); return 0; } @@ -7790,6 +7795,49 @@ atcommand_cleanmap( } /*========================================== + * NPC/PETに話させる + *------------------------------------------ + */ +int +atcommand_npctalk( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char name[100],mes[100]; + struct npc_data *nd; + + if (sscanf(message, "%s %99[^\n]", name, mes) < 2) + return -1; + + if (!(nd = npc_name2id(name))) + return -1; + + clif_message(&nd->bl, mes); + return 0; +} +int +atcommand_pettalk( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char mes[100],temp[100]; + struct pet_data *pd; + + nullpo_retr(-1, sd); + + if(!sd->status.pet_id || !(pd=sd->pd)) + return -1; + + if (sscanf(message, "%99[^\n]", mes) < 1) + return -1; + + snprintf(temp, sizeof temp ,"%s : %s",sd->pet.name,mes); + clif_message(&pd->bl, temp); + + return 0; +} + +/*========================================== * *------------------------------------------ */ diff --git a/src/map/atcommand.h b/src/map/atcommand.h index cb260db19..ea6849476 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -196,6 +196,8 @@ enum AtCommandType { AtCommand_MiscEffect, // by MC Cameri AtCommand_MobSearch, AtCommand_CleanMap, + AtCommand_NpcTalk, + AtCommand_PetTalk, // SQL-only commands start #ifndef TXT_ONLY diff --git a/src/map/battle.c b/src/map/battle.c index 707362f7f..605fd30e0 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -59,15 +59,17 @@ int battle_counttargeted(struct block_list *bl,struct block_list *src,int target // ダメージの遅延 struct battle_delay_damage_ { - struct block_list *src,*target; + struct block_list *src; + int target; int damage; int flag; }; int battle_delay_damage_sub(int tid,unsigned int tick,int id,int data) { struct battle_delay_damage_ *dat=(struct battle_delay_damage_ *)data; - if( dat && map_id2bl(id)==dat->src && dat->target->prev!=NULL) - battle_damage(dat->src,dat->target,dat->damage,dat->flag); + struct block_list *target=map_id2bl(dat->target); + if( dat && map_id2bl(id)==dat->src && target && target->prev!=NULL) + battle_damage(dat->src,target,dat->damage,dat->flag); aFree(dat); return 0; } @@ -80,7 +82,7 @@ int battle_delay_damage(unsigned int tick,struct block_list *src,struct block_li dat->src=src; - dat->target=target; + dat->target=target->id; dat->damage=damage; dat->flag=flag; add_timer(tick,battle_delay_damage_sub,src->id,(int)dat); @@ -256,7 +258,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i flag&BF_SHORT && skill_num != NPC_GUIDEDATTACK) { // セーフティウォール struct skill_unit *unit; - unit = map_find_skill_unit_oncell(bl->m,bl->x,bl->y,MG_SAFETYWALL); + unit = (struct skill_unit *)sc_data[SC_SAFETYWALL].val2; if (unit) { if (unit->group && (--unit->group->val2)<=0) skill_delunit(unit); @@ -3501,7 +3503,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, if(sd && sd->splash_range > 0 && (wd.damage > 0 || wd.damage2 > 0) ) skill_castend_damage_id(src,target,0,-1,tick,0); map_freeblock_lock(); - battle_damage(src,target,(wd.damage+wd.damage2),0); + battle_delay_damage(tick+wd.amotion,src,target,(wd.damage+wd.damage2),0); if(target->prev != NULL && (target->type != BL_PC || (target->type == BL_PC && !pc_isdead((struct map_session_data *)target) ) ) ) { if(wd.damage > 0 || wd.damage2 > 0) { @@ -3652,7 +3654,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, } if(rdamage > 0) - battle_damage(target,src,rdamage,0); + battle_delay_damage(tick+wd.amotion,src,target,rdamage,0); if(t_sc_data && t_sc_data[SC_AUTOCOUNTER].timer != -1 && t_sc_data[SC_AUTOCOUNTER].val4 > 0) { if(t_sc_data[SC_AUTOCOUNTER].val3 == src->id) battle_weapon_attack(target,src,tick,0x8000|t_sc_data[SC_AUTOCOUNTER].val1); diff --git a/src/map/chrif.c b/src/map/chrif.c index a04c483d5..bbc6a51e5 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -1011,6 +1011,8 @@ int chrif_disconnect(int fd) { ShowWarning(tmp_output); clif_foreachclient(chrif_disconnect_sub); chrif_connected = 0; + // 他のmap 鯖のデータを消す + map_eraseallipport(); } close(fd); return 0; @@ -1146,6 +1148,15 @@ int check_connect_char_server(int tid, unsigned int tick, int id, int data) { if (chrif_isconnect()) displayed = 0; return 0; } +/*========================================== + * 終了 + *------------------------------------------ + */ +int do_final_chrif(void) +{ + delete_session(char_fd); + return 0; +} /*========================================== * diff --git a/src/map/chrif.h b/src/map/chrif.h index 7f55d23d6..03ff83f6a 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -31,6 +31,7 @@ int chrif_changesex(int id, int sex); int chrif_chardisconnect(struct map_session_data *sd); int check_connect_char_server(int tid, unsigned int tick, int id, int data); +int do_final_chrif(void); int do_init_chrif(void); int chrif_flush_fifo(void); diff --git a/src/map/guild.c b/src/map/guild.c index d0d7f14dd..ea9c3795f 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -477,8 +477,11 @@ int guild_recv_info(struct guild *sg) // イベントの発生 if( (ev=numdb_search(guild_infoevent_db,sg->guild_id))!=NULL ){ numdb_erase(guild_infoevent_db,sg->guild_id); - for(;ev;ev2=ev->next,aFree(ev),ev=ev2){ + while(ev){ npc_event_do(ev->name); + ev2=ev->next; + aFree(ev); + ev=ev2; } } @@ -1400,8 +1403,11 @@ int guild_castledataloadack(int castle_id,int index,int value) } if( (ev=numdb_search(guild_castleinfoevent_db,code))!=NULL ){ numdb_erase(guild_castleinfoevent_db,code); - for(;ev;ev2=ev->next,aFree(ev),ev=ev2){ + while(ev){ npc_event_do(ev->name); + ev2=ev->next; + aFree(ev); + ev=ev2; } } return 1; diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 41e2e2a75..82149946d 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -379,8 +379,10 @@ static int itemdb_readdb(void) id->equip_script = parse_script((unsigned char *) p,lines); } fclose(fp); - sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,filename[i]); - ShowStatus(tmp_output); + if (ln > 0) { + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,filename[i]); + ShowStatus(tmp_output); + } ln=0; // reset to 0 } return 0; @@ -456,8 +458,10 @@ static int itemdb_read_randomitem() ln++; } fclose(fp); - sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",*pc,fn); - ShowStatus(tmp_output); + if (*pc > 0) { + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",*pc,fn); + ShowStatus(tmp_output); + } } return 0; @@ -699,8 +703,10 @@ static int itemdb_read_noequip(void) } fclose(fp); - sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/item_noequip.txt"); - ShowStatus(tmp_output); + if (ln > 0) { + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/item_noequip.txt"); + ShowStatus(tmp_output); + } return 0; } diff --git a/src/map/map.c b/src/map/map.c index ee597789c..d402ac06c 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -403,12 +403,13 @@ int map_count_oncell(int m, int x, int y) { /* * ォサォ・セェホフェヒフクェトェアェソォケォュォ・讚ヒォテォネェレェケ */ -struct skill_unit *map_find_skill_unit_oncell(int m,int x,int y,int skill_id) +struct skill_unit *map_find_skill_unit_oncell(struct block_list *target,int x,int y,int skill_id,struct skill_unit *out_unit) { - int bx,by; + int m,bx,by; struct block_list *bl; int i,c; struct skill_unit *unit; + m = target->m; if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys)) return NULL; @@ -421,7 +422,10 @@ struct skill_unit *map_find_skill_unit_oncell(int m,int x,int y,int skill_id) if (bl->x != x || bl->y != y || bl->type != BL_SKILL) continue; unit = (struct skill_unit *) bl; - if (unit->alive && unit->group->skill_id == skill_id) + if (unit==out_unit || !unit->alive || + !unit->group || unit->group->skill_id!=skill_id) + continue; + if (battle_check_target(&unit->bl,target,unit->group->target_flag)>0) return unit; } return NULL; @@ -1622,7 +1626,7 @@ struct map_session_data * map_nick2sd(char *nick) { struct block_list * map_id2bl(int id) { struct block_list *bl=NULL; - if(id<sizeof(objects)/sizeof(objects[0])) + if(id >= 0 && id < sizeof(objects)/sizeof(objects[0])) bl = objects[id]; else bl = (struct block_list*)numdb_search(id_db,id); @@ -1826,7 +1830,7 @@ int map_getcell(int m,int x,int y,cell_t cellchk) int map_getcellp(struct map_data* m,int x,int y,cell_t cellchk) { - int j; + int type; nullpo_ret(m); if(x<0 || x>=m->xs-1 || y<0 || y>=m->ys-1) @@ -1834,24 +1838,28 @@ int map_getcellp(struct map_data* m,int x,int y,cell_t cellchk) if(cellchk==CELL_CHKNOPASS) return 1; return 0; } - j=x+y*m->xs; + type = m->gat[x+y*m->xs]; + if (cellchk<0x10) + type &= CELL_MASK; switch(cellchk) { case CELL_CHKPASS: - return (m->gat[j] != 1 && m->gat[j] != 5); + return (type!=1 && type!=5); case CELL_CHKNOPASS: - return (m->gat[j] == 1 || m->gat[j] == 5); + return (type==1 || type==5); case CELL_CHKWALL: - return (m->gat[j] == 1); - case CELL_CHKNPC: - return (m->gat[j]&0x80); + return (type==1); case CELL_CHKWATER: - return (m->gat[j] == 3); + return (type==3); case CELL_CHKGROUND: - return (m->gat[j] == 5); + return (type==5); case CELL_GETTYPE: - return m->gat[j]; + return type; + case CELL_CHKNPC: + return (type&CELL_NPC); + case CELL_CHKBASILICA: + return (type&CELL_BASILICA); default: return 0; } @@ -1868,10 +1876,20 @@ void map_setcell(int m,int x,int y,int cell) return; j=x+y*map[m].xs; - if (cell == CELL_SETNPC) - map[m].gat[j] |= 0x80; - else - map[m].gat[j] = cell; + switch (cell) { + case CELL_SETNPC: + map[m].gat[j] |= CELL_NPC; + break; + case CELL_SETBASILICA: + map[m].gat[j] |= CELL_BASILICA; + break; + case CELL_CLRBASILICA: + map[m].gat[j] &= ~CELL_BASILICA; + break; + default: + map[m].gat[j] = (map[m].gat[j]&~CELL_MASK) + cell; + break; + } } /*========================================== @@ -1889,15 +1907,39 @@ int map_setipport(char *name,unsigned long ip,int port) { mdos->gat = NULL; mdos->ip = ip; mdos->port = port; + mdos->map = NULL; strdb_insert(map_db,mdos->name,mdos); + } else if(md->gat){ + if(ip!=clif_getip() || port!=clif_getport()){ + // 読み込んでいたけど、担当外になったマップ + mdos=(struct map_data_other_server *)aCalloc(1,sizeof(struct map_data_other_server)); + memcpy(mdos->name,name,24); + mdos->gat = NULL; + mdos->ip = ip; + mdos->port = port; + mdos->map = md; + strdb_insert(map_db,mdos->name,mdos); + // printf("from char server : %s -> %08lx:%d\n",name,ip,port); + } else { + // 読み込んでいて、担当になったマップ(何もしない) + ; + } } else { - if(md->gat){ // local -> check data - if(ip!=clif_getip() || port!=clif_getport()){ - printf("from char server : %s -> %08lx:%d\n",name,ip,port); - return 1; + mdos=(struct map_data_other_server *)md; + if(ip == clif_getip() && port == clif_getport()) { + // 自分の担当になったマップ + if(mdos->map == NULL) { + // 読み込んでいないので終了する + printf("map_setipport : %s is not loaded.\n",name); + exit(1); + } else { + // 読み込んでいるので置き換える + md = mdos->map; + free(mdos); + strdb_insert(map_db,md->name,md); } - } else { // update - mdos=(struct map_data_other_server *)md; + } else { + // 他の鯖の担当マップなので置き換えるだけ mdos->ip = ip; mdos->port = port; } @@ -1905,6 +1947,56 @@ int map_setipport(char *name,unsigned long ip,int port) { return 0; } +/*========================================== + * 他鯖管理のマップを全て削除 + *------------------------------------------ + */ +int map_eraseallipport_sub(void *key,void *data,va_list va) { + struct map_data_other_server *mdos = (struct map_data_other_server*)data; + if(mdos->gat == NULL && mdos->map == NULL) { + strdb_erase(map_db,key); + free(mdos); + } + return 0; +} + +int map_eraseallipport(void) { + strdb_foreach(map_db,map_eraseallipport_sub); + return 1; +} + +/*========================================== + * 他鯖管理のマップをdbから削除 + *------------------------------------------ + */ +int map_eraseipport(char *name,unsigned long ip,int port) +{ + struct map_data *md; + struct map_data_other_server *mdos; +// unsigned char *p=(unsigned char *)&ip; + + md=strdb_search(map_db,name); + if(md){ + if(md->gat) // local -> check data + return 0; + else { + mdos=(struct map_data_other_server *)md; + if(mdos->ip==ip && mdos->port == port) { + if(mdos->map) { + // このマップ鯖でも読み込んでいるので移動できる + return 1; // 呼び出し元で chrif_sendmap() をする + } else { + strdb_erase(map_db,name); + free(mdos); + } +// if(battle_config.etc_log) +// printf("erase map %s %d.%d.%d.%d:%d\n",name,p[0],p[1],p[2],p[3],port); + } + } + } + return 0; +} + // 初期化周り /*========================================== * 水場高さ設定 @@ -2043,7 +2135,7 @@ static void map_cache_close(void) fwrite(map_cache.map,map_cache.head.nmaps,sizeof(struct map_cache_info),map_cache.fp); } fclose(map_cache.fp); - free(map_cache.map); + aFree(map_cache.map); map_cache.fp = NULL; return; } @@ -2085,16 +2177,16 @@ int map_cache_read(struct map_data *m) if(fread(buf,1,size_compress,map_cache.fp) != size_compress) { // なぜかファイル後半が欠けてるので読み直し printf("fread error\n"); - m->xs = 0; m->ys = 0; m->gat = NULL; - free(m->gat); free(buf); + free(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL; + free(buf); return 0; } dest_len = m->xs * m->ys; decode_zip(m->gat,&dest_len,buf,size_compress); if(dest_len != map_cache.map[i].xs * map_cache.map[i].ys) { // 正常に解凍が出来てない - m->xs = 0; m->ys = 0; m->gat = NULL; - free(m->gat); free(buf); + free(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL; + free(buf); return 0; } free(buf); @@ -3069,7 +3161,7 @@ void do_final(void) { strdb_final(nick_db, nick_db_final); numdb_final(charid_db, charid_db_final); - + do_final_chrif(); // この内部でキャラを全て切断する do_final_script(); do_final_itemdb(); do_final_storage(); diff --git a/src/map/map.h b/src/map/map.h index 2963a316e..96cbc9fb3 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -20,7 +20,7 @@ #define MAX_STATUSCHANGE 210 #define MAX_SKILLUNITGROUP 32 #define MAX_MOBSKILLUNITGROUP 8 -#define MAX_SKILLUNITGROUPTICKSET 128 +#define MAX_SKILLUNITGROUPTICKSET 32 #define MAX_SKILLTIMERSKILL 32 #define MAX_MOBSKILLTIMERSKILL 10 #define MAX_MOBSKILL 32 @@ -85,13 +85,13 @@ struct skill_unit_group { int src_id; int party_id; int guild_id; - int map,range; + int map; int target_flag; unsigned int tick; int limit,interval; int skill_id,skill_lv; - int val1,val2; + int val1,val2,val3; char *valstr; int unit_id; int group_id; @@ -582,6 +582,7 @@ struct map_data_other_server { unsigned char *gat; // NULL固定にして判断 unsigned long ip; unsigned int port; + struct map_data* map; }; struct flooritem_data { @@ -646,20 +647,29 @@ enum { LOOK_BASE,LOOK_HAIR,LOOK_WEAPON,LOOK_HEAD_BOTTOM,LOOK_HEAD_TOP,LOOK_HEAD_MID,LOOK_HAIR_COLOR,LOOK_CLOTHES_COLOR,LOOK_SHIELD,LOOK_SHOES }; +// CELL +#define CELL_MASK 0x0f +#define CELL_NPC 0x80 // NPCセル +#define CELL_BASILICA 0x40 // BASILICAセル /* - * map_getcell()ェヌ゙ナ鯑ェオェェォユォ鬮ー + * map_getcell()で使用されるフラグ */ typedef enum { - CELL_CHKWALL=1, // ロ(ォサォォソォ、ォラ1) - CELL_CHKWATER=3, // 筰゙(ォサォォソォ、ォラ3) - CELL_CHKGROUND=5, // 「リ。ェレェ(ォサォォソォ、ォラ5) - CELL_CHKNPC=0x80, // ォソォテォチォソォ、ォラェホNPC(ォサォォソォ、ォラ0x80ォユォ鬮ー) - CELL_CHKPASS, // ラホヲハヲメ(ォサォォソォ、ォラ1,5、鞣) - CELL_CHKNOPASS, // ラホヲワハヲ(ォサォォソォ、ォラ1,5) - CELL_GETTYPE // ォサォォソォ、ォラェレェケ + CELL_CHKWALL=0, // 壁(セルタイプ1) + CELL_CHKWATER, // 水場(セルタイプ3) + CELL_CHKGROUND, // 地面障害物(セルタイプ5) + CELL_CHKPASS, // 通過可能(セルタイプ1,5以外) + CELL_CHKNOPASS, // 通過不可(セルタイプ1,5) + CELL_GETTYPE, // セルタイプを返す + CELL_CHKNPC=0x10, // タッチタイプのNPC(セルタイプ0x80フラグ) + CELL_CHKBASILICA, // バジリカ(セルタイプ0x40フラグ) } cell_t; -// map_setcell()ェヌ゙ナ鯑ェオェェォユォ鬮ー -#define CELL_SETNPC 0x80 // ォソォテォチォソォ、ォラェホNPCェォサォテォネ +// map_setcell()で使用されるフラグ +enum { + CELL_SETNPC=0x10, // タッチタイプのNPCをセット + CELL_SETBASILICA, // バジリカをセット + CELL_CLRBASILICA, // バジリカをクリア +}; struct chat_data { struct block_list bl; @@ -718,7 +728,7 @@ void map_foreachinpath(int (*func)(struct block_list*,va_list),int m,int x0,int int map_countnearpc(int,int,int); //block関連に追加 int map_count_oncell(int m,int x,int y); -struct skill_unit *map_find_skill_unit_oncell(int m,int x,int y,int skill_id); +struct skill_unit *map_find_skill_unit_oncell(struct block_list *,int x,int y,int skill_id,struct skill_unit *); // 一時的object関連 int map_addobject(struct block_list *); int map_delobject(int); @@ -747,6 +757,7 @@ int map_mapname2mapid(char*); int map_mapname2ipport(char*,int*,int*); int map_setipport(char *name,unsigned long ip,int port); int map_eraseipport(char *name,unsigned long ip,int port); +int map_eraseallipport(void); void map_addiddb(struct block_list *); void map_deliddb(struct block_list *bl); int map_foreachiddb(int (*)(void*,void*,va_list),...); diff --git a/src/map/mob.c b/src/map/mob.c index 74a1c5889..9b2f91da1 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -496,10 +496,16 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data) dx = dirx[md->dir]; dy = diry[md->dir]; - if(map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKNOPASS)) { + if (map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKBASILICA) && !(status_get_mode(&md->bl)&0x20)) { + mob_stop_walking(md,1); + return 0; + } + + if (map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKNOPASS)) { mob_walktoxy_sub(md); return 0; } + if (skill_check_basilica (&md->bl,x+dx,y+dy) || skill_check_moonlit (&md->bl,x+dx,y+dy)) { mob_walktoxy_sub(md); @@ -515,18 +521,18 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data) if(md->min_chase>13) md->min_chase--; + skill_unit_move(&md->bl,tick,0); if(moveblock) map_delblock(&md->bl); md->bl.x = x; md->bl.y = y; if(moveblock) map_addblock(&md->bl); + skill_unit_move(&md->bl,tick,1); map_foreachinmovearea(clif_mobinsight,md->bl.m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,-dx,-dy,BL_PC,md); md->state.state=MS_IDLE; if(md->option&4) skill_check_cloaking(&md->bl); - - skill_unit_move(&md->bl,tick,1); // スキルユニットの検査 } if((i=calc_next_walk_step(md))>0){ i = i>>1; @@ -712,7 +718,7 @@ int mob_changestate(struct mob_data *md,int state,int type) md->last_deadtime=gettick(); // Since it died, all aggressors' attack to this mob is stopped. clif_foreachclient(mob_stopattacked,md->bl.id); - skill_unit_out_all(&md->bl,gettick(),1); + skill_unit_move(&md->bl,gettick(),0); status_change_clear(&md->bl,2); // ステータス異常を解除する skill_clear_unitgroup(&md->bl); // 全てのスキルユニットグループを削除する skill_cleartimerskill(&md->bl); @@ -789,11 +795,21 @@ static int mob_timer(int tid,unsigned int tick,int id,int data) static int mob_walktoxy_sub(struct mob_data *md) { struct walkpath_data wpd; + int x,y; + static int dirx[8]={0,-1,-1,-1,0,1,1,1}; + static int diry[8]={1,1,0,-1,-1,-1,0,1}; nullpo_retr(0, md); if(path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,md->to_x,md->to_y,md->state.walk_easy)) return 1; + x = md->bl.x+dirx[wpd.path[0]]; + y = md->bl.y+diry[wpd.path[0]]; + if (map_getcell(md->bl.m,x,y,CELL_CHKBASILICA) && !(status_get_mode(&md->bl)&0x20)) { + md->state.change_walk_target=0; + return 1; + } + memcpy(&md->walkpath,&wpd,sizeof(wpd)); md->state.change_walk_target=0; @@ -909,7 +925,7 @@ int mob_spawn(int id) md->last_spawntime=tick; if( md->bl.prev!=NULL ){ // clif_clearchar_area(&md->bl,3); - skill_unit_out_all(&md->bl,gettick(),1); +// skill_unit_move(&md->bl,tick,0); map_delblock(&md->bl); } else @@ -939,8 +955,6 @@ int mob_spawn(int id) md->dir=0; md->target_dir=0; - map_addblock(&md->bl); - memset(&md->state,0,sizeof(md->state)); md->attacked_id = 0; md->target_id = 0; @@ -1003,6 +1017,9 @@ int mob_spawn(int id) md->hp = status_get_max_hp(&md->bl); } + map_addblock(&md->bl); + skill_unit_move(&md->bl,tick,1); + clif_spawnmob(md); return 0; @@ -2876,6 +2893,7 @@ int mob_warpslave(struct mob_data *md,int x, int y) int mob_warp(struct mob_data *md,int m,int x,int y,int type) { int i=0,xs=0,ys=0,bx=x,by=y; + int tick = gettick(); nullpo_retr(0, md); @@ -2889,7 +2907,7 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type) return 0; clif_clearchar_area(&md->bl,type); } - skill_unit_out_all(&md->bl,gettick(),1); + skill_unit_move(&md->bl,tick,0); map_delblock(&md->bl); if(bx>0 && by>0){ // 位置指定の場合周囲9セルを探索 @@ -2928,6 +2946,7 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type) } map_addblock(&md->bl); + skill_unit_move(&md->bl,tick,1); if(type>0) { clif_spawnmob(md); @@ -3241,59 +3260,16 @@ int mobskill_castend_pos( int tid, unsigned int tick, int id,int data ) return 0; } - if(battle_config.monster_skill_reiteration == 0) { - range = -1; - switch(md->skillid) { - case MG_SAFETYWALL: - case WZ_FIREPILLAR: - case HT_SKIDTRAP: - case HT_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case PF_SPIDERWEB: /* スパイダーウェッブ */ - range = 0; - break; - case AL_PNEUMA: - case AL_WARP: - range = 1; - break; - } - if(range >= 0) { - if(skill_check_unit_range(md->bl.m,md->skillx,md->skilly,range,md->skillid) > 0) - return 0; - } - } - if(battle_config.monster_skill_nofootset) { - range = -1; - switch(md->skillid) { - case WZ_FIREPILLAR: - case HT_SKIDTRAP: - case HT_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case AM_DEMONSTRATION: - case PF_SPIDERWEB: /* スパイダーウェッブ */ - range = 1; - break; - case AL_WARP: - range = 0; - break; - } - if(range >= 0) { - if(skill_check_unit_range2(md->bl.m,md->skillx,md->skilly,range) > 0) - return 0; - } - } + if (!battle_config.monster_skill_reiteration && + skill_get_unit_flag(md->skillid)&UF_NOREITERATION && + skill_check_unit_range(md->bl.m,md->skillx,md->skilly,md->skillid,md->skilllv)) + return 0; + + if(battle_config.monster_skill_nofootset && + skill_get_unit_flag(md->skillid)&UF_NOFOOTSET && + skill_check_unit_range2(md->bl.m,md->skillx,md->skilly,md->skillid,md->skilllv)) + return 0; + if(battle_config.monster_land_skill_limit) { maxcount = skill_get_maxcount(md->skillid); diff --git a/src/map/path.c b/src/map/path.c index dae7fc59a..92ea4941e 100644 --- a/src/map/path.c +++ b/src/map/path.c @@ -273,7 +273,7 @@ int path_search_long(int m,int x0,int y0,int x1,int y1) else weight = abs(y1 - y0); - while (x0 != x1 && y0 != y1) { + while (x0 != x1 || y0 != y1) { if (map_getcellp(md,x0,y0,CELL_CHKWALL)) return 0; wx += dx; diff --git a/src/map/pc.c b/src/map/pc.c index 416e05f97..0a5ef8a67 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -140,6 +140,7 @@ static int pc_invincible_timer(int tid,unsigned int tick,int id,int data) { return 0; } sd->invincible_timer=-1; + skill_unit_move(&sd->bl,tick,1); return 0; } @@ -160,6 +161,7 @@ int pc_delinvincibletimer(struct map_session_data *sd) { delete_timer(sd->invincible_timer,pc_invincible_timer); sd->invincible_timer = -1; } + skill_unit_move(&sd->bl,gettick(),1); return 0; } @@ -2244,7 +2246,12 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount) i = pc_search_inventory(sd,0); if(i >= 0) { memcpy(&sd->status.inventory[i],item_data,sizeof(sd->status.inventory[0])); - sd->status.inventory[i].amount=amount; + if(itemdb_isequip2(data)){ + sd->status.inventory[i].amount=1; + amount=1; + } else { + sd->status.inventory[i].amount=amount; + } sd->inventory_data[i]=data; clif_additem(sd,i,amount,0); } @@ -2480,7 +2487,12 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun for(i=0;i<MAX_CART;i++){ if(sd->status.cart[i].nameid==0){ memcpy(&sd->status.cart[i],item_data,sizeof(sd->status.cart[0])); - sd->status.cart[i].amount=amount; + if(itemdb_isequip2(data)){ + sd->status.inventory[i].amount=1; + amount=1; + } else { + sd->status.inventory[i].amount=amount; + } sd->cart_num++; clif_cart_additem(sd,i,amount,0); break; @@ -2877,6 +2889,13 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt status_change_end(&sd->bl,SC_BLADESTOP,-1); if(sd->sc_data[SC_DANCING].timer!=-1) // clear dance effect when warping [Valaris] skill_stop_dancing(&sd->bl,0); + if (sd->sc_data[SC_BASILICA].timer!=-1) { + int i; + for (i=0;i<MAX_SKILLUNITGROUP;i++) + if (sd->skillunit[i].skill_id==HP_BASILICA) + skill_delunitgroup(&sd->skillunit[i]); + status_change_end(&sd->bl,SC_BASILICA,-1); + } } if(sd->status.option&2) @@ -2910,7 +2929,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt int ip,port; if(map_mapname2ipport(mapname,&ip,&port)==0){ skill_stop_dancing(&sd->bl,1); - skill_unit_out_all(&sd->bl,gettick(),1); + skill_unit_move(&sd->bl,gettick(),0); clif_clearchar_area(&sd->bl,clrtype&0xffff); skill_gangsterparadise(sd,0); map_delblock(&sd->bl); @@ -2966,7 +2985,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt } if(sd->mapname[0] && sd->bl.prev != NULL){ - skill_unit_out_all(&sd->bl,gettick(),1); + skill_unit_move(&sd->bl,gettick(),0); clif_clearchar_area(&sd->bl,clrtype&0xffff); skill_gangsterparadise(sd,0); map_delblock(&sd->bl); @@ -3199,10 +3218,12 @@ static int pc_walk(int tid,unsigned int tick,int id,int data) x += dx; y += dy; + skill_unit_move(&sd->bl,tick,0); if(moveblock) map_delblock(&sd->bl); sd->bl.x = x; sd->bl.y = y; if(moveblock) map_addblock(&sd->bl); + skill_unit_move(&sd->bl,tick,1); #if 0 if (sd->status.guild_id > 0) { @@ -3250,20 +3271,15 @@ static int pc_walk(int tid,unsigned int tick,int id,int data) if (sd->sc_data[SC_DEVOTION].val1) skill_devotion2(&sd->bl,sd->sc_data[SC_DEVOTION].val1); - if (sd->sc_data[SC_BASILICA].timer != -1) { // Basilica cancels if caster moves [celest] - struct skill_unit *su; - if ((su = (struct skill_unit *)sd->sc_data[SC_BASILICA].val4)) { - struct skill_unit_group *sg; - if ((sg = su->group) && sg->src_id == sd->bl.id) { - status_change_end(&sd->bl,SC_BASILICA,-1); - skill_delunitgroup (sg); - } - } + if (sd->sc_data[SC_BASILICA].timer!=-1) { // Basilica cancels if caster moves [celest] + int i; + for (i=0;i<MAX_SKILLUNITGROUP;i++) + if (sd->skillunit[i].skill_id==HP_BASILICA) + skill_delunitgroup(&sd->skillunit[i]); + status_change_end(&sd->bl,SC_BASILICA,-1); } } - skill_unit_move(&sd->bl,tick,1); // スキルユニットの?査 - if(map_getcell(sd->bl.m,x,y,CELL_CHKNPC)) npc_touch_areanpc(sd,sd->bl.m,x,y); else @@ -3420,7 +3436,8 @@ int pc_randomwalk(struct map_session_data *sd,int tick) int pc_movepos(struct map_session_data *sd,int dst_x,int dst_y) { int moveblock; - int dx,dy,dist; + int dx,dy; + int tick = gettick(); struct walkpath_data wpd; @@ -3433,16 +3450,17 @@ int pc_movepos(struct map_session_data *sd,int dst_x,int dst_y) dx = dst_x - sd->bl.x; dy = dst_y - sd->bl.y; - dist = distance(sd->bl.x,sd->bl.y,dst_x,dst_y); moveblock = ( sd->bl.x/BLOCK_SIZE != dst_x/BLOCK_SIZE || sd->bl.y/BLOCK_SIZE != dst_y/BLOCK_SIZE); map_foreachinmovearea(clif_pcoutsight,sd->bl.m,sd->bl.x-AREA_SIZE,sd->bl.y-AREA_SIZE,sd->bl.x+AREA_SIZE,sd->bl.y+AREA_SIZE,dx,dy,0,sd); + skill_unit_move(&sd->bl,tick,0); if(moveblock) map_delblock(&sd->bl); sd->bl.x = dst_x; sd->bl.y = dst_y; if(moveblock) map_addblock(&sd->bl); + skill_unit_move(&sd->bl,tick,1); map_foreachinmovearea(clif_pcinsight,sd->bl.m,sd->bl.x-AREA_SIZE,sd->bl.y-AREA_SIZE,sd->bl.x+AREA_SIZE,sd->bl.y+AREA_SIZE,-dx,-dy,0,sd); @@ -3459,8 +3477,6 @@ int pc_movepos(struct map_session_data *sd,int dst_x,int dst_y) if(sd->status.option&4) // クロ?キングの消滅?査 skill_check_cloaking(&sd->bl); - skill_unit_move(&sd->bl,gettick(),dist+7); // スキルユニットの?査 - if(map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNPC)) npc_touch_areanpc(sd,sd->bl.m,sd->bl.x,sd->bl.y); else @@ -3781,7 +3797,7 @@ int pc_attack(struct map_session_data *sd,int target_id,int type) return 0; } - if(!battle_check_target(&sd->bl,bl,BCT_ENEMY)) + if(battle_check_target(&sd->bl,bl,BCT_ENEMY) <= 0) return 1; if(sd->attacktimer != -1) pc_stopattack(sd); @@ -4612,7 +4628,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage) skill_castcancel(&sd->bl,0); // 詠唱の中止 clif_clearchar_area(&sd->bl,1); pc_setdead(sd); - skill_unit_out_all(&sd->bl,gettick(),1); + skill_unit_move(&sd->bl,gettick(),0); if(sd->sc_data[SC_BLADESTOP].timer!=-1)//白刃は事前に解除 status_change_end(&sd->bl,SC_BLADESTOP,-1); pc_setglobalreg(sd,"PC_DIE_COUNTER",++sd->die_counter); //死にカウンタ?書き?み @@ -4967,7 +4983,21 @@ int pc_setparam(struct map_session_data *sd,int type,int val) sd->status.status_point = val; break; case SP_ZENY: - sd->status.zeny = val; + if(val <= MAX_ZENY) { + // MAX_ZENY 以下なら代入 + sd->status.zeny = val; + } else { + if(sd->status.zeny > val) { + // Zeny が減少しているなら代入 + sd->status.zeny = val; + } else if(sd->status.zeny <= MAX_ZENY) { + // Zeny が増加していて、現在の値がMAX_ZENY 以下ならMAX_ZENY + sd->status.zeny = MAX_ZENY; + } else { + // Zeny が増加していて、現在の値がMAX_ZENY より下なら増加分を無視 + ; + } + } break; case SP_BASEEXP: if(pc_nextbaseexp(sd) > 0) { @@ -5761,6 +5791,7 @@ int pc_setaccountreg2(struct map_session_data *sd,char *reg,int val) int pc_eventtimer(int tid,unsigned int tick,int id,int data) { struct map_session_data *sd=map_id2sd(id); + char *p = (char *)data; int i; if(sd==NULL) return 0; @@ -5768,11 +5799,11 @@ int pc_eventtimer(int tid,unsigned int tick,int id,int data) for(i=0;i<MAX_EVENTTIMER;i++){ if( sd->eventtimer[i]==tid ){ sd->eventtimer[i]=-1; - npc_event(sd,(const char *)data,0); + npc_event(sd,p,0); break; } } - aFree((void *)data); + aFree(p); if(i==MAX_EVENTTIMER) { if(battle_config.error_log) printf("pc_eventtimer: no such event timer\n"); @@ -5795,8 +5826,9 @@ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name) if( sd->eventtimer[i]==-1 ) break; if(i<MAX_EVENTTIMER){ - char *evname=(char *)aMallocA((strlen(name)+1)*sizeof(char)); - memcpy(evname,name,(strlen(name)+1)); + char *evname=strdup(name); + //char *evname=(char *)aMallocA((strlen(name)+1)*sizeof(char)); + //memcpy(evname,name,(strlen(name)+1)); sd->eventtimer[i]=add_timer(gettick()+tick, pc_eventtimer,sd->bl.id,(int)evname); sd->eventcount++; @@ -5819,12 +5851,15 @@ int pc_deleventtimer(struct map_session_data *sd,const char *name) return 0; for(i=0;i<MAX_EVENTTIMER;i++) - if( sd->eventtimer[i]!=-1 && strcmp( - (char *)(get_timer(sd->eventtimer[i])->data), name)==0 ){ + if( sd->eventtimer[i]!=-1 ) { + char *p = (char *)(get_timer(sd->eventtimer[i])->data); + if(strcmp(p, name)==0) { delete_timer(sd->eventtimer[i],pc_eventtimer); sd->eventtimer[i]=-1; sd->eventcount--; + free(p); break; + } } return 0; @@ -5865,8 +5900,10 @@ int pc_cleareventtimer(struct map_session_data *sd) for(i=0;i<MAX_EVENTTIMER;i++) if( sd->eventtimer[i]!=-1 ){ + char *p = (char *)(get_timer(sd->eventtimer[i])->data); delete_timer(sd->eventtimer[i],pc_eventtimer); sd->eventtimer[i]=-1; + free(p); } return 0; diff --git a/src/map/skill.c b/src/map/skill.c index 9ae3e2ba4..3d3411b16 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -556,6 +556,12 @@ int skill_get_mhp( int id ,int lv ){ skill_get (skill_db[id].mhp[lv-1], id, lv); int skill_get_castnodex( int id ,int lv ){ skill_get (skill_db[id].castnodex[lv-1], id, lv); } int skill_get_delaynodex( int id ,int lv ){ skill_get (skill_db[id].delaynodex[lv-1], id, lv); } int skill_get_nocast ( int id ){ skill_get (skill_db[id].nocast, id, 1); } +int skill_get_unit_id ( int id, int flag ){ skill_get (skill_db[id].unit_id[flag], id, 1); } +int skill_get_unit_layout_type( int id ,int lv ){ skill_get (skill_db[id].unit_layout_type[lv-1], id, lv); } +int skill_get_unit_interval( int id ){ skill_get (skill_db[id].unit_interval, id, 1); } +int skill_get_unit_range( int id ){ skill_get (skill_db[id].unit_range, id, 1); } +int skill_get_unit_target( int id ){ skill_get (skill_db[id].unit_target, id, 1); } +int skill_get_unit_flag( int id ){ skill_get (skill_db[id].unit_flag, id, 1); } int skill_tree_get_max(int id, int b_class){ struct pc_base_job s_class = pc_calc_base_job(b_class); @@ -577,6 +583,9 @@ int skill_clear_element_field(struct block_list *bl); int skill_landprotector(struct block_list *bl, va_list ap ); int skill_trap_splash(struct block_list *bl, va_list ap ); int skill_count_target(struct block_list *bl, va_list ap ); +struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl,struct skill_unit_group *sg,int tick); +int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int tick); +int skill_unit_effect(struct block_list *bl,va_list ap); // [MouseJstr] - skill ok to cast? and when? int skillnotok(int skillid, struct map_session_data *sd) @@ -635,96 +644,53 @@ static int distance(int x0,int y0,int x1,int y1) return dx>dy ? dx : dy; } -/* スキルユニットIDを返す(これもデ?タベ?スに入れたいな) */ -int skill_get_unit_id(int id,int flag) +/* スキルユニットの配置情報を返す */ +struct skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT]; +int firewall_unit_pos; +int icewall_unit_pos; + +struct skill_unit_layout *skill_get_unit_layout(int skillid,int skilllv,struct block_list *src,int x,int y) { + + int pos = skill_get_unit_layout_type(skillid,skilllv); + int dir; - switch(id){ - case MG_SAFETYWALL: return 0x7e; /* セイフティウォ?ル */ - case MG_FIREWALL: return 0x7f; /* ファイア?ウォ?ル */ - case AL_WARP: return (flag==0)?0x81:0x80; /* ワ?プポ?タル */ - case PR_BENEDICTIO: return 0x82; /* 聖?降福 */ - case PR_SANCTUARY: return 0x83; /* サンクチュアリ */ - case PR_MAGNUS: return 0x84; /* マグヌスエクソシズム */ - case AL_PNEUMA: return 0x85; /* ニュ?マ */ - case MG_THUNDERSTORM: return 0x86; /* サンダ?スト?ム */ - case WZ_HEAVENDRIVE: return 0x86; /* ヘヴンズドライブ */ - case WZ_SIGHTRASHER: return 0x86; /* サイトラッシャ? */ - case WZ_METEOR: return 0x86; /* メテオスト?ム */ - case WZ_VERMILION: return 0x86; /* ロ?ドオブヴァ?ミリオン */ - //case WZ_FROSTNOVA: return 0x86; /* フロストノヴァ */ - case WZ_STORMGUST: return 0x86; /* スト?ムガスト(とりあえずLoVと同じで?理) */ - case CR_GRANDCROSS: return 0x86; /* グランドクロス */ - case NPC_DARKGRANDCROSS: return 0x86; /*闇グランドクロス*/ - case WZ_FIREPILLAR: return (flag==0)?0x87:0x88; /* ファイア?ピラ? */ - case HT_TALKIEBOX: return 0x99; /* ト?キ?ボックス */ - case WZ_ICEWALL: return 0x8d; /* アイスウォ?ル */ - case WZ_QUAGMIRE: return 0x8e; /* クァグマイア */ - case HT_BLASTMINE: return 0x8f; /* ブラストマイン */ - case HT_SKIDTRAP: return 0x90; /* スキッドトラップ */ - case HT_ANKLESNARE: return 0x91; /* アンクルスネア */ - case AS_VENOMDUST: return 0x92; /* ベノムダスト */ - case HT_LANDMINE: return 0x93; /* ランドマイン */ - case HT_SHOCKWAVE: return 0x94; /* ショックウェ?ブトラップ */ - case HT_SANDMAN: return 0x95; /* サンドマン */ - case HT_FLASHER: return 0x96; /* フラッシャ? */ - case HT_FREEZINGTRAP: return 0x97; /* フリ?ジングトラップ */ - case HT_CLAYMORETRAP: return 0x98; /* クレイモア?トラップ */ - case SA_VOLCANO: return 0x9a; /* ボルケ?ノ */ - case SA_DELUGE: return 0x9b; /* デリュ?ジ */ - case SA_VIOLENTGALE: return 0x9c; /* バイオレントゲイル */ - case SA_LANDPROTECTOR: return 0x9d; /* ランドプロテクタ? */ - case BD_LULLABY: return 0x9e; /* 子守歌 */ - case BD_RICHMANKIM: return 0x9f; /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: return 0xa0; /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD:return 0xa1; /* ?太鼓の響き */ - case BD_RINGNIBELUNGEN: return 0xa2; /* ニ?ベルングの指輪 */ - case BD_ROKISWEIL: return 0xa3; /* ロキの叫び */ - case BD_INTOABYSS: return 0xa4; /* 深淵の中に */ - case BD_SIEGFRIED: return 0xa5; /* 不死身のジ?クフリ?ド */ - case BA_DISSONANCE: return 0xa6; /* 不協和音 */ - case BA_WHISTLE: return 0xa7; /* 口笛 */ - case BA_ASSASSINCROSS: return 0xa8; /* 夕陽のアサシンクロス */ - case BA_POEMBRAGI: return 0xa9; /* ブラギの詩 */ - case BA_APPLEIDUN: return 0xaa; /* イドゥンの林檎 */ - case DC_UGLYDANCE: return 0xab; /* 自分勝手なダンス */ - case DC_HUMMING: return 0xac; /* ハミング */ - case DC_DONTFORGETME: return 0xad; /* 私を忘れないで… */ - case DC_FORTUNEKISS: return 0xae; /* 幸運のキス */ - case DC_SERVICEFORYOU: return 0xaf; /* サ?ビスフォ?ユ? */ - case RG_GRAFFITI: return 0xb0; /* グラフィティ */ - case AM_DEMONSTRATION: return 0xb1; /* デモンストレ?ション */ - case WE_CALLPARTNER: return 0xb2; /* あなたに逢いたい */ - case PA_GOSPEL: return 0xb3; /* ゴスペル */ - case HP_BASILICA: return 0xb4; /* バジリカ */ -// case CG_MOONLIT: return 0xb5; - case PF_FOGWALL: return 0xb6; /* フォグウォ?ル */ - case PF_SPIDERWEB: return 0xb7; /* スパイダ?ウェッブ */ - // temporary unit ID's [Celest] - case GD_LEADERSHIP: return 0xc1; - case GD_GLORYWOUNDS: return 0xc2; - case GD_SOULCOLD: return 0xc3; - case GD_HAWKEYES: return 0xc4; - } - return 0; - /* - 0x89,0x8a,0x8b 表示無し - 0x9a 炎?性の詠唱みたいなエフェクト - 0x9b 水?性の詠唱みたいなエフェクト - 0x9c 風?性の詠唱みたいなエフェクト - 0x9d 白い小さなエフェクト - 0xb1 Alchemist Demonstration - 0xb2 = Pink Warp Portal - 0xb3 = Gospel For Paladin - 0xb4 = Basilica - 0xb5 = Empty - 0xb6 = Fog Wall for Professor - 0xb7 = Spider Web for Professor - 0xb8 = Empty - 0xb9 = - */ + if (pos!=-1) + return &skill_unit_layout[pos]; + + if (src->x==x && src->y==y) + dir = 2; + else + dir = map_calc_dir(src,x,y); + + if (skillid==MG_FIREWALL) + return &skill_unit_layout[firewall_unit_pos+dir]; + else if (skillid==WZ_ICEWALL) + return &skill_unit_layout[icewall_unit_pos+dir]; + + printf("unknown unit layout for skill %d, %d\n",skillid,skilllv); + return &skill_unit_layout[0]; } +// case GD_LEADERSHIP: return 0xc1; +// case GD_GLORYWOUNDS: return 0xc2; +// case GD_SOULCOLD: return 0xc3; +// case GD_HAWKEYES: return 0xc4; +// 0x89,0x8a,0x8b 表示無し +// 0x9a 炎?性の詠唱みたいなエフェクト +// 0x9b 水?性の詠唱みたいなエフェクト +// 0x9c 風?性の詠唱みたいなエフェクト +// 0x9d 白い小さなエフェクト +// 0xb1 Alchemist Demonstration +// 0xb2 = Pink Warp Portal +// 0xb3 = Gospel For Paladin +// 0xb4 = Basilica +// 0xb5 = Empty +// 0xb6 = Fog Wall for Professor +// 0xb7 = Spider Web for Professor +// 0xb8 = Empty +// 0xb9 = + /*========================================== * スキル追加?果 *------------------------------------------ @@ -1162,16 +1128,16 @@ int skill_blown( struct block_list *src, struct block_list *target,int count) nullpo_retr(0, target); if(target->type==BL_PC){ - nullpo_retr(0, sd=(struct map_session_data *)target); + sd=(struct map_session_data *)target; }else if(target->type==BL_MOB){ - nullpo_retr(0, md=(struct mob_data *)target); + md=(struct mob_data *)target; }else if(target->type==BL_PET){ - nullpo_retr(0, pd=(struct pet_data *)target); + pd=(struct pet_data *)target; }else if(target->type==BL_SKILL){ - nullpo_retr(0, su=(struct skill_unit *)target); + su=(struct skill_unit *)target; }else return 0; - if(!(count&0x10000 && (sd||md||pd||su))){ /* 指定なしなら位置?係から方向を求める */ + if(!(count&0x10000)){ /* 指定なしなら位置関係から方向を求める */ dx=target->x-src->x; dx=(dx>0)?1:((dx<0)?-1: 0); dy=target->y-src->y; dy=(dy>0)?1:((dy<0)?-1: 0); } @@ -1228,18 +1194,13 @@ int skill_blown( struct block_list *src, struct block_list *target,int count) if(su){ skill_unit_move_unit_group(su->group,target->m,dx,dy); }else{ -// struct status_change *sc_data=status_get_sc_data(target); - if(moveblock) map_delblock(target); - target->x=nx; - target->y=ny; - if(moveblock) map_addblock(target); -/*ダンス中にエフェクトは移動しないらしい - if(sc_data && sc_data[SC_DANCING].timer!=-1){ //?象がダンス中なのでエフェクトも移動 - struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[SC_DANCING].val2; - if(sg) - skill_unit_move_unit_group(sg,target->m,dx,dy); - } -*/ + int tick = gettick(); + skill_unit_move(target,tick,0); + if(moveblock) map_delblock(target); + target->x=nx; + target->y=ny; + if(moveblock) map_addblock(target); + skill_unit_move(target,tick,1); } if(sd) { /* ?面?に入ってきたので表示 */ @@ -1258,8 +1219,6 @@ int skill_blown( struct block_list *src, struct block_list *target,int count) pd->state.state = prev_state; } - skill_unit_move(target,gettick(),(count&0xffff)+7); /* スキルユニットの判定 */ - return 0; } @@ -1480,9 +1439,6 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds //武器スキル?ここまで switch(skillid){ - case WZ_SIGHTRASHER: - clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, 5); - break; case AS_SPLASHER: clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, -1, 5); break; @@ -1495,11 +1451,9 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds default: clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, (skillid==0)? 5:type ); } - if(dmg.blewcount > 0 && !map[src->m].flag.gvg) { /* 吹き飛ばし?理とそのパケット */ - if(skillid == WZ_SIGHTRASHER) - skill_blown(src,bl,dmg.blewcount); - else - skill_blown(dsrc,bl,dmg.blewcount); + /* 吹き飛ばし処理とそのパケット */ + if (dmg.blewcount > 0 && bl->type!=BL_SKILL && !map[src->m].flag.gvg) { + skill_blown(dsrc,bl,dmg.blewcount); if(bl->type == BL_MOB) clif_fixmobpos((struct mob_data *)bl); else if(bl->type == BL_PET) @@ -1510,8 +1464,12 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds map_freeblock_lock(); /* ?際にダメ?ジ?理を行う */ - if(skillid || flag) - battle_damage(src,bl,damage,0); + if (skillid || flag) { + if (attack_type&BF_WEAPON) + battle_delay_damage(tick+dmg.amotion,src,bl,damage,0); + else + battle_damage(src,bl,damage,0); + } if(skillid == RG_INTIMIDATE && damage > 0 && !(status_get_mode(bl)&0x20) && !map[src->m].flag.gvg ) { int s_lv = status_get_lv(src),t_lv = status_get_lv(bl); int rate = 50 + skilllv * 5; @@ -1594,8 +1552,12 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds battle_heal(NULL,bl,0,-sp,0); } - if((skillid || flag) && rdamage > 0) - battle_damage(bl,src,rdamage,0); + if ((skillid || flag) && rdamage>0) { + if (attack_type&BF_WEAPON) + battle_delay_damage(tick+dmg.amotion,bl,src,rdamage,0); + else + battle_damage(bl,src,rdamage,0); + } if(attack_type&BF_WEAPON && sc_data && sc_data[SC_AUTOCOUNTER].timer != -1 && sc_data[SC_AUTOCOUNTER].val4 > 0) { if(sc_data[SC_AUTOCOUNTER].val3 == dsrc->id) @@ -1647,9 +1609,8 @@ int skill_area_sub( struct block_list *bl,va_list ap ) static int skill_check_unit_range_sub( struct block_list *bl,va_list ap ) { struct skill_unit *unit; - int *c,x,y,range,sx[4],sy[4]; - int t_range,tx[4],ty[4]; - int i,r_flag,skillid; + int *c; + int skillid,unit_id; nullpo_retr(0, bl); nullpo_retr(0, ap); @@ -1662,57 +1623,46 @@ static int skill_check_unit_range_sub( struct block_list *bl,va_list ap ) if(!unit->alive) return 0; - x = va_arg(ap,int); - y = va_arg(ap,int); - range = va_arg(ap,int); skillid = va_arg(ap,int); + unit_id = unit->group->unit_id; - if(skillid == MG_SAFETYWALL || skillid == AL_PNEUMA) { - if(unit->group->unit_id != 0x7e && unit->group->unit_id != 0x85) + if (skillid==MG_SAFETYWALL || skillid==AL_PNEUMA) { + if(unit_id != 0x7e && unit_id != 0x85) return 0; - } - else if(skillid == AL_WARP) { - if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92) + } else if (skillid==AL_WARP) { + if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92) return 0; - } - else if((skillid >= HT_SKIDTRAP && skillid <= HT_CLAYMORETRAP) || skillid == HT_TALKIEBOX) { - if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92) + } else if ((skillid>=HT_SKIDTRAP && skillid<=HT_CLAYMORETRAP) || skillid==HT_TALKIEBOX) { + if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92) return 0; - } - else if(skillid == WZ_FIREPILLAR) { - if(unit->group->unit_id != 0x87) + } else if (skillid==WZ_FIREPILLAR) { + if (unit_id!=0x87) return 0; - } - else return 0; - t_range=(unit->range!=0)? unit->range:unit->group->range; - tx[0] = tx[3] = unit->bl.x - t_range; - tx[1] = tx[2] = unit->bl.x + t_range; - ty[0] = ty[1] = unit->bl.y - t_range; - ty[2] = ty[3] = unit->bl.y + t_range; - sx[0] = sx[3] = x - range; - sx[1] = sx[2] = x + range; - sy[0] = sy[1] = y - range; - sy[2] = sy[3] = y + range; - for(i=r_flag=0;i<4;i++) { - if(sx[i] >= tx[0] && sx[i] <= tx[1] && sy[i] >= ty[0] && sy[i] <= ty[2]) { - r_flag = 1; - break; - } - if(tx[i] >= sx[0] && tx[i] <= sx[1] && ty[i] >= sy[0] && ty[i] <= sy[2]) { - r_flag = 1; - break; - } - } - if(r_flag) (*c)++; + } else if (skillid==HP_BASILICA) { + if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92 && unit_id!=0x83) + return 0; + } else + return 0; + + (*c)++; return 0; } -int skill_check_unit_range(int m,int x,int y,int range,int skillid) +int skill_check_unit_range(int m,int x,int y,int skillid,int skilllv) { int c = 0; + int range = skill_get_unit_range(skillid); + int layout_type = skill_get_unit_layout_type(skillid,skilllv); + if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) { + printf("skill_check_unit_range: unsupported layout type %d for skill %d\n",layout_type,skillid); + return 0; + } - map_foreachinarea(skill_check_unit_range_sub,m,x-10,y-10,x+10,y+10,BL_SKILL,&c,x,y,range,skillid); + // とりあえず正方形のユニットレイアウトのみ対応 + range += layout_type; + map_foreachinarea(skill_check_unit_range_sub,m, + x-range,y-range,x+range,y+range,BL_SKILL,&c,skillid); return c; } @@ -1720,6 +1670,8 @@ int skill_check_unit_range(int m,int x,int y,int range,int skillid) static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap ) { int *c; + int skillid; + nullpo_retr(0, bl); nullpo_retr(0, ap); @@ -1731,16 +1683,29 @@ static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap ) if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)) return 0; + skillid = va_arg(ap,int); + if (skillid==HP_BASILICA && bl->type==BL_PC) + return 0; + (*c)++; return 0; } -int skill_check_unit_range2(int m,int x,int y,int range) +int skill_check_unit_range2(int m,int x,int y,int skillid, int skilllv) { int c = 0; + int range = skill_get_unit_range(skillid); + int layout_type = skill_get_unit_layout_type(skillid,skilllv); + if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) { + printf("skill_check_unit_range2: unsupported layout type %d for skill %d\n",layout_type,skillid); + return 0; + } - map_foreachinarea(skill_check_unit_range2_sub,m,x-range,y-range,x+range,y+range,0,&c); + // とりあえず正方形のユニットレイアウトのみ対応 + range += layout_type; + map_foreachinarea(skill_check_unit_range2_sub,m, + x-range,y-range,x+range,y+range,0,&c,skillid); return c; } @@ -1758,6 +1723,27 @@ int skill_area_sub_count(struct block_list *src,struct block_list *target,int sk return 0; } +int skill_count_water(struct block_list *src,int range) +{ + int i,x,y,cnt = 0,size = range*2+1; + struct skill_unit *unit; + + for (i=0;i<size*size;i++) { + x = src->x+(i%size-range); + y = src->y+(i/size-range); + if (map_getcell(src->m,x,y,CELL_CHKWATER)) { + cnt++; + continue; + } + unit = map_find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL); + if (unit) { + cnt++; + skill_delunit(unit); + } + } + return cnt; +} + /*========================================== * *------------------------------------------ @@ -1877,6 +1863,14 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data ) src->x+range,src->y+range,0,src,skl->skill_id,skl->skill_lv,tick); break; + case WZ_WATERBALL: + if (skl->type>1) { + skl->timer = 0; // skill_addtimerskillで使用されないように + skill_addtimerskill(src,tick+150,target->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag); + skl->timer = -1; + } + skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); + break; default: skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); break; @@ -2047,7 +2041,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s if(sd && pc_isdead(sd)) return 1; - if((skillid == WZ_SIGHTRASHER || skillid == CR_GRANDCROSS || skillid == NPC_DARKGRANDCROSS) && src != bl) + if((skillid == CR_GRANDCROSS || skillid == NPC_DARKGRANDCROSS) && src != bl) bl = src; if(bl->prev == NULL) return 1; @@ -2445,8 +2439,17 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s case WZ_WATERBALL: /* ウォ?タ?ボ?ル */ skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - if(skilllv>1) - status_change_start(src,SC_WATERBALL,skilllv,bl->id,0,0,0,0); + if (skilllv>1) { + int cnt,range; + range = skilllv>5?2:skilllv/2; + if (sd) + cnt = skill_count_water(src,range)-1; + else + cnt = skill_get_num(skillid,skilllv)-1; + if (cnt>0) + skill_addtimerskill(src,tick+150,bl->id,0,0, + skillid,skilllv,cnt,flag); + } break; case PR_BENEDICTIO: /* 聖?降福 */ @@ -2457,6 +2460,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s /* 魔法系範?攻?スキル */ case MG_NAPALMBEAT: /* ナパ?ムビ?ト */ case MG_FIREBALL: /* ファイヤ?ボ?ル */ + case WZ_SIGHTRASHER: /* サイトラッシャー */ if(flag&1){ /* 個別にダメ?ジを?える */ if(bl->id!=skill_area_temp[1]){ @@ -2469,27 +2473,46 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s skill_area_temp[0]| 0x0500); } }else{ - int ar=(skillid==MG_NAPALMBEAT)?1:2; + int ar; + skill_area_temp[0]=0; skill_area_temp[1]=bl->id; - if(skillid==MG_NAPALMBEAT){ /* ナパ?ムでは先に?える */ - skill_area_temp[0]=0; - map_foreachinarea(skill_area_sub, - bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY , - skill_area_sub_count); - }else{ - skill_area_temp[0]=0; - skill_area_temp[2]=bl->x; - skill_area_temp[3]=bl->y; + switch (skillid) { + case MG_NAPALMBEAT: + ar = 1; + /* ナパームビートは分散ダメージなので敵の数を数える */ + map_foreachinarea(skill_area_sub, + bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0, + src,skillid,skilllv,tick,flag|BCT_ENEMY, + skill_area_sub_count); + break; + case MG_FIREBALL: + ar = 2; + skill_area_temp[2]=bl->x; + skill_area_temp[3]=bl->y; + /* ターゲットに攻撃を加える(スキルエフェクト表示) */ + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick, + skill_area_temp[0]); + break; + case WZ_SIGHTRASHER: + default: + ar = 3; + bl = src; + status_change_end(src,SC_SIGHT,-1); + break; } - /* まずタ?ゲットに攻?を加える */ - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick, - skill_area_temp[0] ); - /* その後タ?ゲット以外の範??の敵全?に?理を行う */ + if (skillid==WZ_SIGHTRASHER) { + /* スキルエフェクト表示 */ + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } else { + /* ターゲットに攻撃を加える(スキルエフェクト表示) */ + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick, + skill_area_temp[0]); + } + /* ターゲット以外の範囲内の敵全体に処理を行う */ map_foreachinarea(skill_area_sub, - bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); + bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0, + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_damage_id); } break; @@ -2528,12 +2551,6 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s map_foreachinarea(skill_attack_area,src->m,src->x-5,bl->y-5,bl->x+5,bl->y+5,0,BF_MAGIC,src,src,skillid,skilllv,tick,flag,BCT_ENEMY); break; - case WZ_SIGHTRASHER: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0); - status_change_end(src,SC_SIGHT,-1); - break; - /* その他 */ case HT_BLITZBEAT: /* ブリッツビ?ト */ if(flag&1){ @@ -4688,7 +4705,6 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil nullpo_retr(0, sd=(struct map_session_data *)src); } if( skillid != WZ_METEOR && - skillid != WZ_SIGHTRASHER && skillid != AM_CANNIBALIZE && skillid != AM_SPHEREMINE) clif_skill_poseffect(src,skillid,skilllv,x,y,tick); @@ -4739,7 +4755,6 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil case AL_PNEUMA: /* ニュ?マ */ case WZ_ICEWALL: /* アイスウォ?ル */ case WZ_FIREPILLAR: /* ファイアピラ? */ - case WZ_SIGHTRASHER: case WZ_QUAGMIRE: /* クァグマイア */ case WZ_VERMILION: /* ロ?ドオブヴァ?ミリオン */ //case WZ_FROSTNOVA: /* フロストノヴァ */ @@ -5007,349 +5022,137 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag) { struct skill_unit_group *group; - int i,count=1,limit=10000,val1=0,val2=0; - int target=BCT_ENEMY,interval=1000,range=0; - int dir=0,aoe_diameter=0; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills + int i,limit,val1=0,val2=0,val3=0; + int count=0; + int target,interval,range,unit_flag; + struct skill_unit_layout *layout; struct status_change *sc_data; nullpo_retr(0, src); + limit = skill_get_time(skillid,skilllv); + range = skill_get_unit_range(skillid); + interval = skill_get_unit_interval(skillid); + target = skill_get_unit_target(skillid); + unit_flag = skill_get_unit_flag(skillid); + layout = skill_get_unit_layout(skillid,skilllv,src,x,y); + + if (unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy) + target = BCT_NOENEMY; + sc_data = status_get_sc_data(src); // for firewall and fogwall - celest switch(skillid){ /* 設定 */ case MG_SAFETYWALL: /* セイフティウォ?ル */ - limit=skill_get_time(skillid,skilllv); val2=skilllv+1; - interval = -1; - target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL; break; - case MG_FIREWALL: /* ファイヤ?ウォ?ル */ - if(src->x == x && src->y == y) - dir = 2; - else - dir=map_calc_dir(src,x,y); - if(dir&1) count=5; - else count=3; - limit=skill_get_time(skillid,skilllv); - if(sc_data) { - if (sc_data[SC_VIOLENTGALE].timer!=-1) limit = limit*3/2; - } - // check for sc_data first - Celest - // if (((struct map_session_data *)src)->sc_data[SC_VIOLENTGALE].timer!=-1) - // limit *= 1.5; + if(sc_data && sc_data[SC_VIOLENTGALE].timer!=-1) + limit = limit*3/2; val2=4+skilllv; - interval=1; - break; - - case AL_PNEUMA: /* ニュ?マ */ - limit=skill_get_time(skillid,skilllv); - interval = -1; - target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL; - count = 9; break; case AL_WARP: /* ワ?プポ?タル */ - target=BCT_ALL; val1=skilllv+6; if(flag==0) limit=2000; - else - limit=skill_get_time(skillid,skilllv); break; case PR_SANCTUARY: /* サンクチュアリ */ - count=21; - limit=skill_get_time(skillid,skilllv); val1=(skilllv+3)*2; val2=(skilllv>6)?777:skilllv*100; - target=BCT_ALL; - range=1; - break; - - case PR_MAGNUS: /* マグヌスエクソシズム */ - count=33; - limit=skill_get_time(skillid,skilllv); - interval=3000; + interval += 500; break; case WZ_FIREPILLAR: /* ファイア?ピラ? */ - if(flag==0) - limit=skill_get_time(skillid,skilllv); - else + if(flag!=0) limit=1000; - interval=2000; val1=skilllv+2; - if(skilllv < 6) - range=1; - else + if(skilllv >= 6) range=2; break; - case MG_THUNDERSTORM: /* サンダ?スト?ム */ - limit=500; - range=1; - break; - - //case WZ_FROSTNOVA: /* フロストノヴァ */ - // limit=500; - // range=5; - // break; - - case WZ_HEAVENDRIVE: /* ヘヴンズドライブ */ - limit=500; - range=2; - break; - - case WZ_METEOR: /* メテオスト?ム */ - limit=500; - range=3; - break; - - case WZ_SIGHTRASHER: - limit=500; - count=41; - break; - - case WZ_VERMILION: /* ロ?ドオブヴァ?ミリオン */ - limit=4100; - interval=1000; - range=6; - break; - - case WZ_ICEWALL: /* アイスウォ?ル */ - limit=skill_get_time(skillid,skilllv); - count=5; - break; - - case WZ_STORMGUST: /* スト?ムガスト */ - limit=4600; - interval=450; - range=5; - break; - - case WZ_QUAGMIRE: /* クァグマイア */ - limit=skill_get_time(skillid,skilllv); - interval=200; - count=25; - break; - case HT_SANDMAN: /* サンドマン */ case HT_CLAYMORETRAP: /* クレイモア?トラップ */ - limit=skill_get_time(skillid,skilllv); - // longer trap times in WOE [celest] - if (map[src->m].flag.gvg) limit *= 4; - range=2; - break; case HT_SKIDTRAP: /* スキッドトラップ */ case HT_LANDMINE: /* ランドマイン */ case HT_ANKLESNARE: /* アンクルスネア */ - case PF_SPIDERWEB: /* スパイダ?ウェッブ */ case HT_FLASHER: /* フラッシャ? */ case HT_FREEZINGTRAP: /* フリ?ジングトラップ */ case HT_BLASTMINE: /* ブラストマイン */ - limit=skill_get_time(skillid,skilllv); // longer trap times in WOE [celest] - if (skillid != PF_SPIDERWEB && map[src->m].flag.gvg) - limit *= 4; - range=1; - break; - - case HT_TALKIEBOX: /* ト?キ?ボックス */ - limit=skill_get_time(skillid,skilllv); - range=1; - target=BCT_ALL; + if (map[src->m].flag.gvg) limit *= 4; break; - case HT_SHOCKWAVE: /* ショックウェ?ブトラップ */ - limit=skill_get_time(skillid,skilllv); - range=1; val1=skilllv*15+10; break; - case AS_VENOMDUST: /* ベノムダスト */ - limit=skill_get_time(skillid,skilllv); - interval=1000; - count=5; - break; - - case CR_GRANDCROSS: /* グランドクロス */ - case NPC_DARKGRANDCROSS: /*闇グランドクロス*/ - count=29; - limit=1000; - interval=300; - break; - - case SA_VOLCANO: /* ボルケ?ノ */ - case SA_DELUGE: /* デリュ?ジ */ - case SA_VIOLENTGALE: /* バイオレントゲイル */ - limit=skill_get_time(skillid,skilllv); - //count=skilllv<=2?25:(skilllv<=4?49:81); - count=49; - target=BCT_ALL; - break; - case SA_LANDPROTECTOR: /* グランドクロス */ - limit=skill_get_time(skillid,skilllv); // changed to get duration from cast_db (moonsoul) - val1=skilllv*15+10; - aoe_diameter=skilllv+skilllv%2+5; - target=BCT_ALL; - count=aoe_diameter*aoe_diameter; // -- this will not function if changed to ^2 (moonsoul) - break; - - case BD_LULLABY: /* 子守唄 */ - case BD_ETERNALCHAOS: /* エタ?ナルカオス */ - case BD_ROKISWEIL: /* ロキの叫び */ - count=81; - limit=skill_get_time(skillid,skilllv); - range=5; - target=(skillid==BD_ETERNALCHAOS ? BCT_ENEMY : BCT_ALL); - break; - case BD_RICHMANKIM: - case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */ - count=81; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_PARTY; + { + int aoe_diameter; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills + val1=skilllv*15+10; + aoe_diameter=skilllv+skilllv%2+5; + count=aoe_diameter*aoe_diameter; // -- this will not function if changed to ^2 (moonsoul) + } break; case BA_WHISTLE: /* 口笛 */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1; val2 = ((status_get_agi(src)/10)&0xffff)<<16; val2 |= (status_get_luk(src)/10)&0xffff; break; case DC_HUMMING: /* ハミング */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; val2 = status_get_dex(src)/10; break; - - case BA_DISSONANCE: /* 不協和音 */ - case DC_UGLYDANCE: /* 自分勝手なダンス */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_ENEMY; - break; - case DC_DONTFORGETME: /* 私を忘れないで… */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_ENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; val2 = ((status_get_str(src)/20)&0xffff)<<16; val2 |= (status_get_agi(src)/10)&0xffff; break; case BA_POEMBRAGI: /* ブラギの詩 */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON); val2 = ((status_get_dex(src)/10)&0xffff)<<16; val2 |= (status_get_int(src)/5)&0xffff; break; case BA_APPLEIDUN: /* イドゥンの林檎 */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = ((pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON))&0xffff)<<16; - else - val1 = 0; - val1 |= (status_get_vit(src))&0xffff; - val2 = 0;//回復用タイムカウンタ(6秒?に1?加) + val2 |= (status_get_vit(src))&0xffff; + val3 = 0;//回復用タイムカウンタ(6秒?に1?加) break; case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_PARTY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; val2 = status_get_int(src)/10; break; case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1; val2 = status_get_agi(src)/20; break; case DC_FORTUNEKISS: /* 幸運のキス */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; val2 = status_get_luk(src)/10; break; - case AM_DEMONSTRATION: /* デモンストレ?ション */ - limit=skill_get_time(skillid,skilllv); - interval=1000; - range=1; - target=BCT_ENEMY; - break; - - case WE_CALLPARTNER: /* あなたに逢いたい */ - limit=skill_get_time(skillid,skilllv); - range=-1; - break; - case HP_BASILICA: /* バジリカ */ - limit=skill_get_time(skillid,skilllv); - target=BCT_ALL; - range=3; //Fix to prevent the priest from walking while Basilica is up. battle_stopwalking(src,1); - //status_change_start(src,SC_ANKLE,skilllv,0,0,0,limit,0); - //sd->canmove_tick = gettick() + limit; // added later [celest] - break; - - case PA_GOSPEL: /* ゴスペル */ - count=49; - target=BCT_PARTY; - limit=skill_get_time(skillid,skilllv); break; -/* case CG_MOONLIT: - range=1; - target=BCT_ALL; - limit=skill_get_time(skillid,skilllv); - break;*/ - case PF_FOGWALL: /* フォグウォ?ル */ - count=15; - limit=skill_get_time(skillid,skilllv); - if(sc_data) { - if (sc_data[SC_DELUGE].timer!=-1) limit *= 2; - } + if(sc_data && sc_data[SC_DELUGE].timer!=-1) limit *= 2; break; case RG_GRAFFITI: /* Graffiti */ count=1; // Leave this at 1 [Valaris] - limit=600000; // Time length [Valaris] break; case GD_LEADERSHIP: @@ -5360,20 +5163,16 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid, target=BCT_ALL; limit=300000; break; - - default: - if(battle_config.error_log) - printf ("skill_unitsetting: Unknown skill id = %d\n",skillid); - return 0; } - nullpo_retr(NULL, group=skill_initunitgroup(src,count,skillid,skilllv,skill_get_unit_id(skillid,flag&1))); + nullpo_retr(NULL, group=skill_initunitgroup(src,(count > 0 ? count : layout->count), + skillid,skilllv,skill_get_unit_id(skillid,flag&1))); group->limit=limit; group->val1=val1; group->val2=val2; + group->val3=val3; group->target_flag=target; group->interval=interval; - group->range=range; if(skillid==HT_TALKIEBOX || skillid==RG_GRAFFITI){ group->valstr=aCallocA(80, 1); @@ -5383,200 +5182,20 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid, } memcpy(group->valstr,talkie_mes,80); } - for(i=0;i<count;i++){ + for(i=0;i<layout->count;i++){ struct skill_unit *unit; - int ux=x,uy=y,val1=skilllv,val2=0,limit=group->limit,alive=1; - int range=group->range; - switch(skillid){ /* 設定 */ - case AL_PNEUMA: /* ニュ?マ */ - { - static const int dx[9]={-1, 0, 1,-1, 0, 1,-1, 0, 1}; - static const int dy[9]={-1,-1,-1, 0, 0, 0, 1, 1, 1}; - ux+=dx[i]; - uy+=dy[i]; - } - break; + int ux,uy,val1=skilllv,val2=0,limit=group->limit,alive=1; + ux = x + layout->dx[i]; + uy = y + layout->dy[i]; + switch (skillid) { case MG_FIREWALL: /* ファイヤ?ウォ?ル */ - { - if(dir&1){ /* 斜め配置 */ - static const int dx[][5]={ - { 1,1,0,0,-1 }, { -1,-1,0,0,1 }, - },dy[][5]={ - { 1,0,0,-1,-1 }, { 1,0,0,-1,-1 }, - }; - ux+=dx[(dir>>1)&1][i]; - uy+=dy[(dir>>1)&1][i]; - }else{ /* 上下配置 */ - if(dir%4==0) /* 上下 */ - ux+=i-1; - else /* 左右 */ - uy+=i-1; - } - val2=group->val2; - } - break; - - case PR_SANCTUARY: /* サンクチュアリ */ - { - static const int dx[]={ - -1,0,1, -2,-1,0,1,2, -2,-1,0,1,2, -2,-1,0,1,2, -1,0,1 }; - static const int dy[]={ - -2,-2,-2, -1,-1,-1,-1,-1, 0,0,0,0,0, 1,1,1,1,1, 2,2,2, }; - ux+=dx[i]; - uy+=dy[i]; - } - break; - - case PR_MAGNUS: /* マグヌスエクソシズム */ - { - static const int dx[]={ -1,0,1, -1,0,1, -3,-2,-1,0,1,2,3, - -3,-2,-1,0,1,2,3, -3,-2,-1,0,1,2,3, -1,0,1, -1,0,1, }; - static const int dy[]={ - -3,-3,-3, -2,-2,-2, -1,-1,-1,-1,-1,-1,-1, - 0,0,0,0,0,0,0, 1,1,1,1,1,1,1, 2,2,2, 3,3,3 }; - ux+=dx[i]; - uy+=dy[i]; - } + val2=group->val2; break; - - case WZ_SIGHTRASHER: - { - static const int dx[]={ - -5, 0, 5, -4, 0, 4, -3, 0, 3, -2, 0, 2, -1, 0, 1, -5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, -1, 0, 1, -2, 0, 2, -3, 0, 3, -4, 0, 4, -5, 0, 5 }; - static const int dy[]={ - -5,-5,-5, -4,-4,-4, -3,-3,-3, -2,-2,-2, -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 }; - ux+=dx[i]; - uy+=dy[i]; - } - break; - case WZ_ICEWALL: /* アイスウォ?ル */ - { - static const int dirx[8]={0,-1,-1,-1,0,1,1,1}; - static const int diry[8]={1,1,0,-1,-1,-1,0,1}; if(skilllv <= 1) val1 = 500; else val1 = 200 + 200*skilllv; - if(src->x == x && src->y == y) - dir = 2; - else - dir=map_calc_dir(src,x,y); - ux+=(2-i)*diry[dir]; - uy+=(i-2)*dirx[dir]; - } - break; - - case WZ_QUAGMIRE: /* クァグマイア */ - ux+=(i%5-2); - uy+=(i/5-2); - if(i==12) - range=2; - else - range=-1; - - break; - - case AS_VENOMDUST: /* ベノムダスト */ - { - static const int dx[]={-1,0,0,0,1}; - static const int dy[]={0,-1,0,1,0}; - ux+=dx[i]; - uy+=dy[i]; - } - break; - - case CR_GRANDCROSS: /* グランドクロス */ - case NPC_DARKGRANDCROSS: /*闇グランドクロス*/ - { - static const int dx[]={ - 0, 0, -1,0,1, -2,-1,0,1,2, -4,-3,-2,-1,0,1,2,3,4, -2,-1,0,1,2, -1,0,1, 0, 0, }; - static const int dy[]={ - -4, -3, -2,-2,-2, -1,-1,-1,-1,-1, 0,0,0,0,0,0,0,0,0, 1,1,1,1,1, 2,2,2, 3, 4, }; - ux+=dx[i]; - uy+=dy[i]; - } - break; - case SA_VOLCANO: /* ボルケ?ノ */ - case SA_DELUGE: /* デリュ?ジ */ - case SA_VIOLENTGALE: /* バイオレントゲイル */ - { - int u_range=0,central=0; - if(skilllv<=2){ - u_range=2; - central=12; - }else if(skilllv<=4){ - u_range=3; - central=24; - }else if(skilllv>=5){ - u_range=4; - central=40; - } - ux+=(i%(u_range*2+1)-u_range); - uy+=(i/(u_range*2+1)-u_range); - - if(i==central) - range=u_range;//中央のユニットの?果範?は全範? - else - range=-1;//中央以外のユニットは飾り - } - break; - case SA_LANDPROTECTOR: /* ランドプロテクタ? */ - { - int u_range=0; - - if(skilllv<=2) u_range=3; - else if(skilllv<=4) u_range=4; - else if(skilllv>=5) u_range=5; - - ux+=(i%(u_range*2+1)-u_range); - uy+=(i/(u_range*2+1)-u_range); - - range=0; - } - break; - - /* ダンスなど */ - case BD_LULLABY: /* 子守歌 */ - case BD_RICHMANKIM: /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD:/* ?太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */ - case BD_ROKISWEIL: /* ロキの叫び */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */ - ux+=(i%9-4); - uy+=(i/9-4); - if(i==40) - range=4; /* 中心の場合は範?を4にオ?バ?ライド */ - else - range=-1; /* 中心じゃない場合は範?を-1にオ?バ?ライド */ - break; - case BA_DISSONANCE: /* 不協和音 */ - case BA_WHISTLE: /* 口笛 */ - case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ - case BA_POEMBRAGI: /* ブラギの詩 */ - case BA_APPLEIDUN: /* イドゥンの林檎 */ - case DC_UGLYDANCE: /* 自分勝手なダンス */ - case DC_HUMMING: /* ハミング */ - case DC_DONTFORGETME: /* 私を忘れないで… */ - case DC_FORTUNEKISS: /* 幸運のキス */ - case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */ -// case CG_MOONLIT: - ux+=(i%7-3); - uy+=(i/7-3); - if(i==40) - range=4; /* 中心の場合は範?を4にオ?バ?ライド */ - else - range=-1; /* 中心じゃない場合は範?を-1にオ?バ?ライド */ - break; - case PA_GOSPEL: /* ゴスペル */ - ux+=(i%7-3); - uy+=(i/7-3); - break; - case PF_FOGWALL: /* フォグウォ?ル */ - ux+=(i%5-2); - uy+=(i/5-1); break; case RG_GRAFFITI: /* Graffiti [Valaris] */ ux+=(i%5-2); @@ -5603,7 +5222,7 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid, unit->val2=val2; unit->limit=limit; unit->range=range; - + // [celest] if (sc_data) { // attach the unit's id to the caster @@ -5642,6 +5261,10 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid, break; } } + if (range==0) + map_foreachinarea(skill_unit_effect,unit->bl.m + ,unit->bl.x,unit->bl.y,unit->bl.x,unit->bl.y + ,0,&unit->bl,gettick(),1); } } return group; @@ -5655,123 +5278,284 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int { struct skill_unit_group *sg; struct block_list *ss; - struct skill_unit_group_tickset *ts; - struct map_session_data *srcsd=NULL; - int diff,goflag,splash_count=0; + struct skill_unit *unit2; struct status_change *sc_data; + int type; nullpo_retr(0, src); nullpo_retr(0, bl); - sc_data = status_get_sc_data(bl); - - if( bl->prev==NULL || !src->alive || (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl) ) ) + + if(bl->prev==NULL || !src->alive || + (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))) return 0; nullpo_retr(0, sg=src->group); nullpo_retr(0, ss=map_id2bl(sg->src_id)); + + sc_data = status_get_sc_data(bl); + type = SkillStatusChangeTable[sg->skill_id]; - if(ss->type == BL_PC) - nullpo_retr(0, srcsd=(struct map_session_data *)ss); - if(srcsd && srcsd->chatID) + if (battle_check_target(&src->bl,bl,sg->target_flag)<=0) return 0; - if( bl->type != BL_PC && bl->type != BL_MOB ) + // 対象がLP上に居る場合は無効 + if (map_find_skill_unit_oncell(bl,bl->x,bl->y,SA_LANDPROTECTOR,NULL)) return 0; - nullpo_retr(0, ts = skill_unitgrouptickset_search(bl, sg)); - diff=DIFF_TICK(tick,ts->tick); - goflag=(diff>sg->interval || diff<0); - if (sg->skill_id == CR_GRANDCROSS && !battle_config.gx_allhit) // 重なっていたら3HITしない - goflag = (diff>sg->interval*map_count_oncell(bl->m,bl->x,bl->y) || diff<0); - //?象がLP上に居る場合は無? - map_foreachinarea(skill_landprotector,bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,0,&goflag); + switch (sg->unit_id) { + case 0x85: /* ニューマ */ + case 0x7e: /* セイフティウォール */ + if (sc_data && sc_data[type].timer == -1) + status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); + break; - if(!goflag) - return 0; - ts->tick=tick; + case 0x80: /* ワープポータル(発動後) */ + if(bl->type==BL_PC){ + struct map_session_data *sd = (struct map_session_data *)bl; + if(sd && src->bl.m == bl->m && src->bl.x == bl->x && src->bl.y == bl->y && + src->bl.x == sd->to_x && src->bl.y == sd->to_y) { + if( battle_config.chat_warpportal || !sd->chatID ){ + pc_setpos(sd,sg->valstr,sg->val2>>16,sg->val2&0xffff,3); + if(sg->src_id == bl->id || (strcmp(map[src->bl.m].name,sg->valstr) == 0 && + src->bl.x == (sg->val2>>16) && src->bl.y == (sg->val2&0xffff) )) + skill_delunitgroup(sg); + if (--sg->val1<=0) + skill_delunitgroup(sg); + } + } + } else if(bl->type==BL_MOB && battle_config.mob_warpportal){ + int m = map_mapname2mapid(sg->valstr); + mob_warp((struct mob_data *)bl,m,sg->val2>>16,sg->val2&0xffff,3); + } + break; - switch(sg->unit_id){ - case 0x83: /* サンクチュアリ */ - { - int race=status_get_race(bl); - int damage_flag = (battle_check_undead(race,status_get_elem_type(bl)) || race == 6)? 1:0; + case 0x8e: /* クァグマイア */ + if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + break; + if(sc_data && sc_data[type].timer==-1) + status_change_start(bl,type,sg->skill_lv,(int)src,0,0, + skill_get_time2(sg->skill_id,sg->skill_lv),0); + break; - if( status_get_hp(bl)>=status_get_max_hp(bl) && !damage_flag) + case 0x9a: /* ボルケ?ノ */ + case 0x9b: /* デリュ?ジ */ + case 0x9c: /* バイオレントゲイル */ + if (sc_data && sc_data[type].timer!=-1) { + unit2 = (struct skill_unit *)sc_data[type].val4; + if (unit2 && unit2->group && + (unit2==src || DIFF_TICK(sg->tick,unit2->group->tick)<=0)) break; - - if((sg->val1--)<=0){ - skill_delunitgroup(sg); - return 0; - } - if(!damage_flag) { - int heal=sg->val2; - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage) - heal=0; /* ?金蟲カ?ド(ヒ?ル量0) */ - clif_skill_nodamage(&src->bl,bl,AL_HEAL,heal,1); - battle_heal(NULL,bl,heal,0,0); - } - else { - // reduce healing count if this was meant for damaging [celest] - sg->val1 /= 2; - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - } } + status_change_start(bl,type,sg->skill_lv,(int)src,0,0, + skill_get_time2(sg->skill_id,sg->skill_lv),0); break; - case 0x84: /* マグヌスエクソシズム */ - { - int race=status_get_race(bl); - int damage_flag = (battle_check_undead(race,status_get_elem_type(bl)) || race == 6)? 1:0; + case 0x9e: /* 子守唄 */ + case 0x9f: /* ニヨルドの宴 */ + case 0xa0: /* 永遠の混沌 */ + case 0xa1: /* ?太鼓の響き */ + case 0xa2: /* ニ?ベルングの指輪 */ + case 0xa3: /* ロキの叫び */ + case 0xa4: /* 深淵の中に */ + case 0xa5: /* 不死身のジ?クフリ?ド */ + case 0xa6: /* 不協和音 */ + case 0xa7: /* 口笛 */ + case 0xa8: /* 夕陽のアサシンクロス */ + case 0xa9: /* ブラギの詩 */ + case 0xaa: /* イドゥンの林檎 */ + case 0xab: /* 自分勝手なダンス */ + case 0xac: /* ハミング */ + case 0xad: /* 私を忘れないで… */ + case 0xae: /* 幸運のキス */ + case 0xaf: /* サ?ビスフォ?ユ? */ + case 0xb4: + if (sg->src_id==bl->id) + break; + if (sc_data && sc_data[type].timer!=-1) { + unit2 = (struct skill_unit *)sc_data[type].val4; + if (unit2 && unit2->group && + (unit2 == src || DIFF_TICK(sg->tick,unit2->group->tick)<=0)) + break; + } + status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, + (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); + break; - if(!damage_flag) - return 0; - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + case 0xb6: /* フォグウォ?ル */ + if (sc_data && sc_data[type].timer!=-1) { + unit2 = (struct skill_unit *)sc_data[type].val4; + if (unit2 && unit2->group && + (unit2 == src || DIFF_TICK(sg->tick,unit2->group->tick)<=0)) + break; } + status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, + (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); + skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick); break; - case 0x85: /* ニュ?マ */ + // New guild skills [Celest] + case 0xc1: // GD_LEADERSHIP { - struct skill_unit *unit2; - int type=SC_PNEUMA; - if(sc_data) { - if (sc_data[type].timer==-1) - status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); - else if((unit2 = (struct skill_unit *)sc_data[type].val2) && unit2 != src){ - if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick) > 0) - status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); - ts->tick-=sg->interval; + struct map_session_data *sd, *tsd; + tsd=(struct map_session_data *)ss; + if (tsd && (sd=(struct map_session_data *)bl) && + sd->status.guild_id == tsd->status.guild_id && + sd != tsd) { + sd->state.leadership_flag = (int)src; + status_calc_pc (sd, 0); } - } } break; - case 0x7e: /* セイフティウォ?ル */ - if (sc_data) { - status_change_start(bl,SC_SAFETYWALL,sg->skill_lv,(int)src,0,0,0,0); - ts->tick-=sg->interval; + case 0xc2: // GD_GLORYWOUNDS + { + struct map_session_data *sd, *tsd; + tsd=(struct map_session_data *)ss; + if (tsd && (sd=(struct map_session_data *)bl) && + sd->status.guild_id == tsd->status.guild_id && + sd != tsd) { + sd->state.glorywounds_flag = (int)src; + status_calc_pc (sd, 0); + } + } + break; + case 0xc3: // GD_SOULCOLD + { + struct map_session_data *sd, *tsd; + tsd=(struct map_session_data *)ss; + if (tsd && (sd=(struct map_session_data *)bl) && + sd->status.guild_id == tsd->status.guild_id && + sd != tsd) { + sd->state.soulcold_flag = (int)src; + status_calc_pc (sd, 0); + } + } + break; + case 0xc4: // GD_HAWKEYES + { + struct map_session_data *sd, *tsd; + tsd=(struct map_session_data *)ss; + if (tsd && (sd=(struct map_session_data *)bl) && + sd->status.guild_id == tsd->status.guild_id && + sd != tsd) { + sd->state.hawkeyes_flag = (int)src; + status_calc_pc (sd, 0); + } } break; - case 0x86: /* ロ?ドオブヴァ?ミリオン(&スト?ムガスト &グランドクロス) */ - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + case 0xb2: /* あなたを_?いたいです */ + case 0xb3: /* ゴスペル */ + //case 0xb6: /* フォグウォ?ル */ - moved [celest] + //とりあえず何もしない break; + /* default: + if(battle_config.error_log) + printf("skill_unit_onplace: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); + break;*/ + } + + return 0; +} + +/*========================================== + * スキルユニットの発動イベント(タイマー発動) + *------------------------------------------ + */ +int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsigned int tick) +{ + struct skill_unit_group *sg; + struct block_list *ss; + int splash_count=0; + struct status_change *sc_data; + struct skill_unit_group_tickset *ts; + int type; + int diff=0; + + nullpo_retr(0, src); + nullpo_retr(0, bl); + + if (bl->type!=BL_PC && bl->type!=BL_MOB) + return 0; + + if (bl->prev==NULL || !src->alive || + (bl->type==BL_PC && pc_isdead((struct map_session_data *)bl))) + return 0; + + nullpo_retr(0, sg=src->group); + nullpo_retr(0, ss=map_id2bl(sg->src_id)); + sc_data = status_get_sc_data(bl); + type = SkillStatusChangeTable[sg->skill_id]; + + // 対象がLP上に居る場合は無効 + if (map_find_skill_unit_oncell(bl,bl->x,bl->y,SA_LANDPROTECTOR,NULL)) + return 0; + + // 前に影響を受けてからintervalの間は影響を受けない + nullpo_retr(0,ts = skill_unitgrouptickset_search(bl,sg,tick)); + diff = DIFF_TICK(tick,ts->tick); + if (sg->skill_id == PR_SANCTUARY) + diff += 500; // 新規に回復したユニットだけカウントするための仕掛け + if (diff < 0) + return 0; + ts->tick = tick+sg->interval; + // GXは重なっていたら3HITしない + if (sg->skill_id==CR_GRANDCROSS && !battle_config.gx_allhit) + ts->tick += sg->interval*(map_count_oncell(bl->m,bl->x,bl->y)-1); + + switch (sg->unit_id) { + case 0x83: /* サンクチュアリ */ + { + int race=status_get_race(bl); - case 0x7f: /* ファイヤ?ウォ?ル */ - if( (src->val2--)>0) - skill_attack(BF_MAGIC,ss,&src->bl,bl, - sg->skill_id,sg->skill_lv,tick,0); - if( src->val2<=0 ) + if (battle_check_undead(race,status_get_elem_type(bl)) || race==6) { + if (skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0)) { + // reduce healing count if this was meant for damaging [celest] + // sg->val1 /= 2; + sg->val1--; // チャットキャンセルに対応 + } + } else { + int heal = sg->val2; + if (status_get_hp(bl)>=status_get_max_hp(bl)) + break; + if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage) + heal=0; /* 黄金蟲カード(ヒール量0) */ + clif_skill_nodamage(&src->bl,bl,AL_HEAL,heal,1); + battle_heal(NULL,bl,heal,0,0); + if (diff>=500) + sg->val1--; // 新規に入ったユニットだけカウント + } + if (sg->val1<=0) + skill_delunitgroup(sg); + break; + } + + case 0x84: /* マグヌスエクソシズム */ + { + int race = status_get_race(bl); + if (!battle_check_undead(race,status_get_elem_type(bl)) && race!=6) + return 0; + skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + src->val2++; + break; + } + + case 0x7f: /* ファイヤーウォール */ + skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + if (--src->val2<=0) skill_delunit(src); break; - - case 0x87: /* ファイア?ピラ?(?動前) */ + case 0x86: /* ロードオブヴァーミリオン(TS,MS,FN,SG,HD,GX,闇GX) */ + skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + break; + case 0x87: /* ファイアーピラー(発動前) */ skill_delunit(src); skill_unitsetting(ss,sg->skill_id,sg->skill_lv,src->bl.x,src->bl.y,1); break; - case 0x88: /* ファイア?ピラ?(?動後) */ - if(DIFF_TICK(tick,sg->tick) < 150) - //skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - map_foreachinarea(skill_attack_area,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,BF_MAGIC,ss,&src->bl,sg->skill_id,sg->skill_lv,tick,0,BCT_ENEMY); // area damage [Celest] + case 0x88: /* ファイアーピラー(発動後) */ + map_foreachinarea(skill_attack_area,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0, + BF_MAGIC,ss,&src->bl,sg->skill_id,sg->skill_lv,tick,0,BCT_ENEMY); // area damage [Celest] + //skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; case 0x90: /* スキッドトラップ */ @@ -5784,7 +5568,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int clif_changelook(&src->bl,LOOK_BASE,sg->unit_id); sg->limit=DIFF_TICK(tick,sg->tick)+1500; } - break; + break; case 0x93: /* ランドマイン */ skill_attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); @@ -5813,22 +5597,22 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int break; case 0x91: /* アンクルスネア */ - { - struct status_change *sc_data=status_get_sc_data(bl); - if(sg->val2==0 && sc_data && sc_data[SC_ANKLE].timer==-1){ - int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE); - int sec = skill_get_time2(sg->skill_id,sg->skill_lv) - status_get_agi(bl)*100; - if(status_get_mode(bl)&0x20) - sec = sec/5; - if (sec < 3000) // minimum time of 3 seconds [celest] - sec = 3000; - battle_stopwalking(bl,1); - status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0); - + if(sg->val2==0 && sc_data && sc_data[SC_ANKLE].timer==-1){ + int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE); + int sec = skill_get_time2(sg->skill_id,sg->skill_lv) - status_get_agi(bl)*100; + if(status_get_mode(bl)&0x20) + sec = sec/5; + if (sec < 3000) // minimum time of 3 seconds [celest] + sec = 3000; + battle_stopwalking(bl,1); + status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0); + + skill_unit_move(bl,tick,0); if(moveblock) map_delblock(bl); bl->x = src->bl.x; bl->y = src->bl.y; if(moveblock) map_addblock(bl); + skill_unit_move(bl,tick,1); if(bl->type == BL_MOB) clif_fixmobpos((struct mob_data *)bl); else if(bl->type == BL_PET) @@ -5836,156 +5620,26 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int else clif_fixpos(bl); clif_01ac(&src->bl); - sg->limit=DIFF_TICK(tick,sg->tick) + sec; + sg->limit=DIFF_TICK(tick,sg->tick) + sec; sg->val2=bl->id; - } - } - break; - - case 0x80: /* ワ?プポ?タル(?動後) */ - if(bl->type==BL_PC){ - struct map_session_data *sd = (struct map_session_data *)bl; - if(sd && src->bl.m == bl->m && src->bl.x == bl->x && src->bl.y == bl->y && src->bl.x == sd->to_x && src->bl.y == sd->to_y) { - if( battle_config.chat_warpportal || !sd->chatID ){ - if((sg->val1--)>0){ - pc_setpos(sd,sg->valstr,sg->val2>>16,sg->val2&0xffff,3); - if(sg->src_id == bl->id ||( strcmp(map[src->bl.m].name,sg->valstr) == 0 && src->bl.x == (sg->val2>>16) && src->bl.y == (sg->val2&0xffff) )) - skill_delunitgroup(sg); - }else - skill_delunitgroup(sg); - } - } - }else if(bl->type==BL_MOB && battle_config.mob_warpportal){ - int m=map_mapname2mapid(sg->valstr); - struct mob_data *md; - md=(struct mob_data *)bl; - mob_warp((struct mob_data *)bl,m,sg->val2>>16,sg->val2&0xffff,3); + sg->interval = -1; + src->range = 0; } break; - case 0x8e: /* クァグマイア */ - { - struct status_change *sc_data=status_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if(sc_data && sc_data[type].timer==-1) - status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - } - break; case 0x92: /* ベノムダスト */ - { - struct status_change *sc_data=status_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sc_data && sc_data[type].timer==-1 ) - status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - } + if(sc_data && sc_data[type].timer==-1 ) + status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); break; - case 0x9a: /* ボルケ?ノ */ - case 0x9b: /* デリュ?ジ */ - case 0x9c: /* バイオレントゲイル */ - { - struct skill_unit *unit2; - struct status_change *sc_data=status_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sc_data) { - if (sc_data[type].timer==-1) - status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){ - if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - ts->tick-=sg->interval; - } - } - } break; - - case 0x9e: /* 子守唄 */ - case 0x9f: /* ニヨルドの宴 */ - case 0xa0: /* 永遠の混沌 */ - case 0xa1: /* ?太鼓の響き */ - case 0xa2: /* ニ?ベルングの指輪 */ - case 0xa3: /* ロキの叫び */ - case 0xa4: /* 深淵の中に */ - case 0xa5: /* 不死身のジ?クフリ?ド */ - case 0xa6: /* 不協和音 */ - case 0xa7: /* 口笛 */ - case 0xa8: /* 夕陽のアサシンクロス */ - case 0xa9: /* ブラギの詩 */ - case 0xab: /* 自分勝手なダンス */ - case 0xac: /* ハミング */ - case 0xad: /* 私を忘れないで… */ - case 0xae: /* 幸運のキス */ - case 0xaf: /* サ?ビスフォ?ユ? */ - case 0xb4: -// case 0xb6: /* フォグウォ?ル */ - { - struct skill_unit *unit2; - struct status_change *sc_data=status_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sg->src_id == bl->id) - break; - if(sc_data) { - if (sc_data[type].timer==-1) - status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - else if( (unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){ - if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - ts->tick-=sg->interval; - } - } - } break; - - case 0xaa: /* イドゥンの林檎 */ - { - struct skill_unit *unit2; - struct status_change *sc_data=status_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sg->src_id == bl->id) - break; - if(sc_data) { - if (sc_data[type].timer==-1) - status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - else if((unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){ - if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - ts->tick-=sg->interval; - } - } - } break; - - case 0xb6: /* フォグウォ?ル */ - { - struct skill_unit *unit2; - struct status_change *sc_data=status_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sc_data) { - if (sc_data[type].timer==-1) { - status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick); - } - else if( (unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){ - if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 ) { - status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick); - } -// ts->tick-=sg->interval; - } - } - } break; case 0xb1: /* デモンストレ?ション */ skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); if(bl->type == BL_PC && rand()%100 < sg->skill_lv && battle_config.equipment_breaking) pc_breakweapon((struct map_session_data *)bl); break; - case 0x99: /* ト?キ?ボックス */ - if(sg->src_id == bl->id) //自分が踏んでも?動しない + + case 0x99: /* トーキーボックス */ + if(sg->src_id == bl->id) //自分が踏んでも発動しない break; if(sg->val2==0){ clif_talkiebox(&src->bl,sg->valstr); @@ -5994,76 +5648,41 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int sg->limit=DIFF_TICK(tick,sg->tick)+5000; sg->val2=-1; //踏んだ } - break; - case 0xb2: /* あなたを_?いたいです */ - case 0xb3: /* ゴスペル */ - //case 0xb6: /* フォグウォ?ル */ - moved [celest] - //とりあえず何もしない - break; + break; + + //case 0xb4: /* バジリカ */ + /*if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0 && + !(status_get_mode(bl)&0x20)) + skill_blown(&src->bl,bl,1); + if (sg->src_id==bl->id) + break; + if (battle_check_target(&src->bl,bl,BCT_NOENEMY)>0) { + type = SkillStatusChangeTable[sg->skill_id]; + status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, + (int)src,sg->interval+100,0); + } + break;*/ case 0xb7: /* スパイダ?ウェッブ */ if(sg->val2==0){ int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE); skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick); + skill_unit_move(bl,tick,0); if(moveblock) map_delblock(bl); - bl->x = (&src->bl)->x; - bl->y = (&src->bl)->y; + bl->x = src->bl.x; + bl->y = src->bl.y; if(moveblock) map_addblock(bl); - if(bl->type == BL_MOB) - clif_fixmobpos((struct mob_data *)bl); - else if(bl->type == BL_PET) - clif_fixpetpos((struct pet_data *)bl); - else - clif_fixpos(bl); - clif_01ac(&src->bl); - sg->limit=DIFF_TICK(tick,sg->tick) + skill_get_time2(sg->skill_id,sg->skill_lv); + skill_unit_move(bl,tick,1); + if(bl->type == BL_MOB) + clif_fixmobpos((struct mob_data *)bl); + else if(bl->type == BL_PET) + clif_fixpetpos((struct pet_data *)bl); + else + clif_fixpos(bl); + sg->limit = DIFF_TICK(tick,sg->tick)+skill_get_time2(sg->skill_id,sg->skill_lv); sg->val2=bl->id; - } - break; - - // New guild skills [Celest] - case 0xc1: // GD_LEADERSHIP - { - struct map_session_data *sd; - if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) && - sd->status.guild_id == srcsd->status.guild_id && - sd != srcsd) { - sd->state.leadership_flag = (int)src; - status_calc_pc (sd, 0); - } - } - break; - case 0xc2: // GD_GLORYWOUNDS - { - struct map_session_data *sd; - if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) && - sd->status.guild_id == srcsd->status.guild_id && - sd != srcsd) { - sd->state.glorywounds_flag = (int)src; - status_calc_pc (sd, 0); - } - } - break; - case 0xc3: // GD_SOULCOLD - { - struct map_session_data *sd; - if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) && - sd->status.guild_id == srcsd->status.guild_id && - sd != srcsd) { - sd->state.soulcold_flag = (int)src; - status_calc_pc (sd, 0); - } - } - break; - case 0xc4: // GD_HAWKEYES - { - struct map_session_data *sd; - if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) && - sd->status.guild_id == srcsd->status.guild_id && - sd != srcsd) { - sd->state.hawkeyes_flag = (int)src; - status_calc_pc (sd, 0); - } + sg->interval = -1; + src->range = 0; } break; @@ -6072,6 +5691,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int printf("skill_unit_onplace: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); break;*/ } + if(bl->type==BL_MOB && ss!=bl) /* スキル使用?件のMOBスキル */ { if(battle_config.mob_changetarget_byskill == 1) @@ -6095,77 +5715,41 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int tick) { struct skill_unit_group *sg; + struct status_change *sc_data; + int type; nullpo_retr(0, src); nullpo_retr(0, bl); nullpo_retr(0, sg=src->group); + sc_data = status_get_sc_data(bl); + type = SkillStatusChangeTable[sg->skill_id]; - if( bl->prev==NULL || !src->alive ) - return 0; - - if( bl->type!=BL_PC && bl->type!=BL_MOB ) + if (bl->prev==NULL || !src->alive || + (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))) return 0; switch(sg->unit_id){ - case 0x7e: /* セイフティウォ?ル */ - case 0x85: /* ニュ?マ */ + case 0x7e: /* セイフティウォール */ + case 0x85: /* ニューマ */ case 0x8e: /* クァグマイア */ - { - struct status_change *sc_data=status_get_sc_data(bl); - int type= - (sg->unit_id==0x85)?SC_PNEUMA: - ((sg->unit_id==0x7e)?SC_SAFETYWALL: - SC_QUAGMIRE); - if((type != SC_QUAGMIRE || bl->type != BL_MOB) && - sc_data && sc_data[type].timer!=-1 && ((struct skill_unit *)sc_data[type].val2)==src){ - status_change_end(bl,type,-1); - } - } break; - - case 0x91: /* アンクルスネア */ - { - struct block_list *target=map_id2bl(sg->val2); - if( target && target==bl ){ - status_change_end(bl,SC_ANKLE,-1); - sg->limit=DIFF_TICK(tick,sg->tick)+1000; - } + case 0x9a: /* ボルケーノ */ + case 0x9b: /* デリュージ */ + case 0x9c: /* バイオレントゲイル */ + if (type==SC_QUAGMIRE && bl->type==BL_MOB) + break; + if (sc_data && sc_data[type].timer!=-1 && sc_data[type].val2==(int)src) { + status_change_end(bl,type,-1); } break; -// case 0xb5: - case 0xb8: - { - struct block_list *target=map_id2bl(sg->val2); - if( target==bl ) - status_change_end(bl,SC_SPIDERWEB,-1); + case 0x91: /* アンクルスネア */ + { + struct block_list *target = map_id2bl(sg->val2); + if(target && target == bl){ + status_change_end(bl,SC_ANKLE,-1); sg->limit=DIFF_TICK(tick,sg->tick)+1000; } break; - case 0xb6: - { - struct block_list *target=map_id2bl(sg->val2); - struct status_change *sc_data=status_get_sc_data(bl); - if( target==bl ) { - status_change_end(bl,SC_FOGWALL,-1); - if (sc_data && sc_data[SC_BLIND].timer!=-1) - sc_data[SC_BLIND].timer = add_timer( - gettick() + 30000, status_change_timer, bl->id, 0); - } - //sg->limit=DIFF_TICK(tick,sg->tick)+1000; - } - break; - case 0x9a: /* ボルケ?ノ */ - case 0x9b: /* デリュ?ジ */ - case 0x9c: /* バイオレントゲイル */ - { - struct status_change *sc_data=status_get_sc_data(bl); - struct skill_unit *su; - int type=SkillStatusChangeTable[sg->skill_id]; - if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val2)) && su == src ){ - status_change_end(bl,type,-1); - } - } - break; - + } case 0x9e: /* 子守唄 */ case 0x9f: /* ニヨルドの宴 */ case 0xa0: /* 永遠の混沌 */ @@ -6185,24 +5769,32 @@ int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int t case 0xae: /* 幸運のキス */ case 0xaf: /* サ?ビスフォ?ユ? */ case 0xb4: - { - struct status_change *sc_data=status_get_sc_data(bl); - struct skill_unit *su; - int type=SkillStatusChangeTable[sg->skill_id]; - if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val4)) && su == src ){ - status_change_end(bl,type,-1); - } + if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)src) { + status_change_end(bl,type,-1); } break; + + case 0xb6: + { + struct block_list *target = map_id2bl(sg->val2); + if(target && target==bl) { + status_change_end(bl,SC_FOGWALL,-1); + if (sc_data && sc_data[SC_BLIND].timer!=-1) + sc_data[SC_BLIND].timer = add_timer( + gettick() + 30000, status_change_timer, bl->id, 0); + } + break; + } + case 0xb7: /* スパイダ?ウェッブ */ { - struct block_list *target=map_id2bl(sg->val2); - if( target && target==bl ) + struct block_list *target = map_id2bl(sg->val2); + if (target && target==bl) status_change_end(bl,SC_SPIDERWEB,-1); - sg->limit=DIFF_TICK(tick,sg->tick)+1000; + sg->limit = DIFF_TICK(tick,sg->tick)+1000; + break; } - break; - // New guild skills [Celest] + // New guild skills [Celest] case 0xc1: // GD_LEADERSHIP { struct map_session_data *sd; @@ -6231,73 +5823,53 @@ int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int t sd->state.hawkeyes_flag = 0; } break; - /* default: if(battle_config.error_log) printf("skill_unit_onout: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); break;*/ } - skill_unitgrouptickset_delete(bl,sg); + return 0; } + /*========================================== - * スキルユニットの削除イベント + * スキルユニット効果発動/離脱処理(foreachinarea) + * bl: ユニット(BL_PC/BL_MOB) *------------------------------------------ */ -int skill_unit_ondelete(struct skill_unit *src,struct block_list *bl,unsigned int tick) +int skill_unit_effect(struct block_list *bl,va_list ap) { - struct skill_unit_group *sg; + struct skill_unit *unit; + struct skill_unit_group *group; + int flag; + unsigned int tick; - nullpo_retr(0, src); nullpo_retr(0, bl); - nullpo_retr(0, sg = src->group); + nullpo_retr(0, ap); + nullpo_retr(0, unit=va_arg(ap,struct skill_unit*)); + tick = va_arg(ap,unsigned int); + flag = va_arg(ap,unsigned int); - if( bl->prev==NULL || !src->alive ) + if (bl->type!=BL_PC && bl->type!=BL_MOB) return 0; - if( bl->type!=BL_PC && bl->type!=BL_MOB ) + if (!unit->alive || bl->prev==NULL) return 0; - switch(sg->unit_id){ - case 0x85: /* ニュ?マ */ - case 0x7e: /* セイフティウォ?ル */ - case 0x8e: /* クァグマイヤ */ - case 0x9a: /* ボルケ?ノ */ - case 0x9b: /* デリュ?ジ */ - case 0x9c: /* バイオレントゲイル */ - case 0x9e: /* 子守唄 */ - case 0x9f: /* ニヨルドの宴 */ - case 0xa0: /* 永遠の混沌 */ - case 0xa1: /* ?太鼓の響き */ - case 0xa2: /* ニ?ベルングの指輪 */ - case 0xa3: /* ロキの叫び */ - case 0xa4: /* 深淵の中に */ - case 0xa5: /* 不死身のジ?クフリ?ド */ - case 0xa6: /* 不協和音 */ - case 0xa7: /* 口笛 */ - case 0xa8: /* 夕陽のアサシンクロス */ - case 0xa9: /* ブラギの詩 */ - case 0xaa: /* イドゥンの林檎 */ - case 0xab: /* 自分勝手なダンス */ - case 0xac: /* ハミング */ - case 0xad: /* 私を忘れないで… */ - case 0xae: /* 幸運のキス */ - case 0xaf: /* サ?ビスフォ?ユ? */ - case 0xb4: - case 0xc1: - case 0xc2: - case 0xc3: - case 0xc4: - return skill_unit_onout(src,bl,tick); + nullpo_retr(0, group=unit->group); -/* default: - if(battle_config.error_log) - printf("skill_unit_ondelete: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); - break;*/ + if (flag) + skill_unit_onplace(unit,bl,tick); + else { + skill_unit_onout(unit,bl,tick); + unit = map_find_skill_unit_oncell(bl,bl->x,bl->y,group->skill_id,unit); + if (unit) + skill_unit_onplace(unit,bl,tick); } - skill_unitgrouptickset_delete(bl,sg); + return 0; } + /*========================================== * スキルユニットの限界イベント *------------------------------------------ @@ -6435,10 +6007,7 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) return 0; } - if(battle_config.pc_skill_reiteration == 0) { - range = -1; - switch(sd->skillid) { - case MG_SAFETYWALL: + /*case MG_SAFETYWALL: case WZ_FIREPILLAR: case HT_SKIDTRAP: case HT_LANDMINE: @@ -6451,28 +6020,23 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) case HT_CLAYMORETRAP: case HT_TALKIEBOX: case AL_WARP: - case PF_SPIDERWEB: /* スパイダ?ウェッブ */ - case RG_GRAFFITI: /* グラフィティ */ + case PF_SPIDERWEB: + case RG_GRAFFITI: range = 0; break; case AL_PNEUMA: range = 1; - break; - } - if(range >= 0) { - if(skill_check_unit_range(sd->bl.m,sd->skillx,sd->skilly,range,sd->skillid) > 0) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } + break;*/ + if (!battle_config.pc_skill_reiteration && + skill_get_unit_flag(sd->skillid)&UF_NOREITERATION && + skill_check_unit_range(sd->bl.m,sd->skillx,sd->skilly,sd->skillid,sd->skilllv)) { + clif_skill_fail(sd,sd->skillid,0,0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; } - if(battle_config.pc_skill_nofootset) { - range = -1; - switch(sd->skillid) { - case WZ_FIREPILLAR: + /*case WZ_FIREPILLAR: case HT_SKIDTRAP: case HT_LANDMINE: case HT_ANKLESNARE: @@ -6483,25 +6047,22 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) case HT_BLASTMINE: case HT_CLAYMORETRAP: case HT_TALKIEBOX: - case PF_SPIDERWEB: /* スパイダ?ウェッブ */ + case PF_SPIDERWEB: case WZ_ICEWALL: range = 2; break; case AL_WARP: range = 0; - break; - } - if(range >= 0) { - if(skill_check_unit_range2(sd->bl.m,sd->skillx,sd->skilly,range) > 0) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } + break;*/ + if (battle_config.pc_skill_nofootset && + skill_get_unit_flag(sd->skillid)&UF_NOFOOTSET && + skill_check_unit_range2(sd->bl.m,sd->skillx,sd->skilly,sd->skillid,sd->skilllv)) { + clif_skill_fail(sd,sd->skillid,0,0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; } - if(battle_config.pc_land_skill_limit) { maxcount = skill_get_maxcount(sd->skillid); if(maxcount > 0) { @@ -7523,22 +7084,22 @@ int skill_use_id( struct map_session_data *sd, int target_id, return 0; } break; - // removed on 12/14's patch [celest] - //case AS_SPLASHER: /* ベナムスプラッシャ? */ - /* { - struct status_change *t_sc_data = status_get_sc_data(bl); - if(t_sc_data && t_sc_data[SC_POISON].timer==-1){ - clif_skill_fail(sd,skill_num,0,10); - return 0; - } - } - break;*/ case PF_MEMORIZE: /* メモライズ */ casttime = 12000; break; case HW_MAGICPOWER: casttime = 700; break; + case HP_BASILICA: /* バジリカ */ + if (skill_check_unit_range(sd->bl.m,sd->bl.x,sd->bl.y,sd->skillid,sd->skilllv)) { + clif_skill_fail(sd,sd->skillid,0,0); + return 0; + } + if (skill_check_unit_range2(sd->bl.m,sd->bl.x,sd->bl.y,sd->skillid,sd->skilllv)) { + clif_skill_fail(sd,sd->skillid,0,0); + return 0; + } + break; case GD_BATTLEORDER: case GD_REGENERATION: case GD_RESTORE: @@ -7991,13 +7552,14 @@ int skill_devotion3(struct block_list *bl,int target) int n,r=0; nullpo_retr(1, bl); + md = (struct map_session_data *)bl; - if( (md = (struct map_session_data *)bl) == NULL || (sd = map_id2sd(target)) == NULL ) + if ((sd = map_id2sd(target))==NULL) return 1; else r = distance(bl->x,bl->y,sd->bl.x,sd->bl.y); - if(pc_checkskill(sd,CR_DEVOTION)+6 < r){ // 許容範?を超えてた + if(pc_checkskill(md,CR_DEVOTION)+6 < r){ // 許容範?を超えてた for(n=0;n<5;n++) if(md->dev.val1[n]==target) md->dev.val2[n]=0; // 離れた時は、?を切るだけ @@ -8249,12 +7811,28 @@ int skill_abra_dataset(int skilllv) //NPCスキルはダメ if(skill >= NPC_PIERCINGATT && skill <= NPC_SUMMONMONSTER) return 0; //演奏スキルはダメ - if(skill_is_danceskill(skill)) return 0; + if (skill_get_unit_flag(skill)&UF_DANCE) return 0; return skill; } /*========================================== + * バジリカのセルを設定する + *------------------------------------------ + */ +void skill_basilica_cell(struct skill_unit *unit,int flag) +{ + int i,x,y,range = skill_get_unit_range(HP_BASILICA); + int size = range*2+1; + + for (i=0;i<size*size;i++) { + x = unit->bl.x+(i%size-range); + y = unit->bl.y+(i/size-range); + map_setcell(unit->bl.m,x,y,flag); + } +} + +/*========================================== * *------------------------------------------ */ @@ -8293,16 +7871,20 @@ int skill_clear_element_field(struct block_list *bl) { struct mob_data *md=NULL; struct map_session_data *sd=NULL; - int i,skillid; + int i,max,skillid; nullpo_retr(0, bl); - if(bl->type==BL_MOB) - md=(struct mob_data *)bl; - if(bl->type==BL_PC) - sd=(struct map_session_data *)bl; + if (bl->type==BL_MOB) { + max = MAX_MOBSKILLUNITGROUP; + md = (struct mob_data *)bl; + } else if(bl->type==BL_PC) { + max = MAX_SKILLUNITGROUP; + sd = (struct map_session_data *)bl; + } else + return 0; - for(i=0;i<MAX_MOBSKILLUNITGROUP;i++){ + for (i=0;i<max;i++) { if(sd){ skillid=sd->skillunit[i].skill_id; if(skillid==SA_DELUGE||skillid==SA_VOLCANO||skillid==SA_VIOLENTGALE||skillid==SA_LANDPROTECTOR) @@ -8372,7 +7954,8 @@ int skill_idun_heal(struct block_list *bl, va_list ap ) * 指定範??でsrcに?して有?なタ?ゲットのblの?を?える(foreachinarea) *------------------------------------------ */ -int skill_count_target(struct block_list *bl, va_list ap ){ +int skill_count_target(struct block_list *bl, va_list ap) +{ struct block_list *src; int *c; @@ -8528,48 +8111,6 @@ int skill_type_cloaking(struct block_list *bl) */ /*========================================== - * 演奏/ダンススキルかどうか判定 - * 引? スキルID - * ?り ダンスじゃない=0 合奏=2 それ以外のダンス=1 - *------------------------------------------ - */ -int skill_is_danceskill(int id) -{ - int i; - switch(id){ - case BD_LULLABY: /* 子守歌 */ - case BD_RICHMANKIM: /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */ - case BD_ROKISWEIL: /* ロキの叫び */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */ - case BD_RAGNAROK: /* 神?の?昏 */ - case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ - i=2; - break; - case BA_DISSONANCE: /* 不協和音 */ - case BA_FROSTJOKE: /* 寒いジョ?ク */ - case BA_WHISTLE: /* 口笛 */ - case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ - case BA_POEMBRAGI: /* ブラギの詩 */ - case BA_APPLEIDUN: /* イドゥンの林檎 */ - case DC_UGLYDANCE: /* 自分勝手なダンス */ - case DC_SCREAM: /* スクリ?ム */ - case DC_HUMMING: /* ハミング */ - case DC_DONTFORGETME: /* 私を忘れないで… */ - case DC_FORTUNEKISS: /* 幸運のキス */ - case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */ - i=1; - break; - default: - i=0; - } - return i; -} - -/*========================================== * 演奏/ダンスをやめる * flag 1で合奏中なら相方にユニットを任せる * @@ -8650,10 +8191,13 @@ struct skill_unit *skill_initunit(struct skill_unit_group *group,int idx,int x,i map_addblock(&unit->bl); clif_skill_setunit(unit); + +// if (group->skill_id==HP_BASILICA) +// skill_basilica_cell(unit,CELL_SETBASILICA); + return unit; } -int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap ); /*========================================== * スキルユニット削除 *------------------------------------------ @@ -8661,7 +8205,6 @@ int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap ); int skill_delunit(struct skill_unit *unit) { struct skill_unit_group *group; - int range; nullpo_retr(0, unit); if(!unit->alive) @@ -8671,11 +8214,15 @@ int skill_delunit(struct skill_unit *unit) /* onlimitイベント呼び出し */ skill_unit_onlimit( unit,gettick() ); - /* ondeleteイベント呼び出し */ - range=group->range; - map_foreachinarea( skill_unit_timer_sub_ondelete, unit->bl.m, - unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0, - &unit->bl,gettick() ); + /* onoutイベント呼び出し */ + if (!unit->range) { + map_foreachinarea(skill_unit_effect,unit->bl.m, + unit->bl.x,unit->bl.y,unit->bl.x,unit->bl.y,0, + &unit->bl,gettick(),0); + } + +// if (group->skill_id==HP_BASILICA) +// skill_basilica_cell(unit,CELL_CLRBASILICA); clif_skill_delunit(unit); @@ -8691,7 +8238,7 @@ int skill_delunit(struct skill_unit *unit) * スキルユニットグル?プ初期化 *------------------------------------------ */ -static int skill_unit_group_newid=10; +static int skill_unit_group_newid = MAX_SKILL_DB; struct skill_unit_group *skill_initunitgroup(struct block_list *src, int count,int skillid,int skilllv,int unit_id) { @@ -8743,7 +8290,7 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src, group->guild_id=status_get_guild_id(src); group->group_id=skill_unit_group_newid++; if(skill_unit_group_newid<=0) - skill_unit_group_newid=10; + skill_unit_group_newid = MAX_SKILL_DB; group->unit=(struct skill_unit *)aCalloc(count,sizeof(struct skill_unit)); group->unit_count=count; group->val1=group->val2=0; @@ -8751,39 +8298,23 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src, group->skill_lv=skilllv; group->unit_id=unit_id; group->map=src->m; - group->range=0; group->limit=10000; group->interval=1000; group->tick=gettick(); group->valstr=NULL; - if( skill_is_danceskill(skillid) ){ + if (skill_get_unit_flag(skillid)&UF_DANCE) { struct map_session_data *sd = NULL; if(src->type==BL_PC && (sd=(struct map_session_data *)src) ){ sd->skillid_dance=skillid; sd->skilllv_dance=skilllv; } status_change_start(src,SC_DANCING,skillid,(int)group,0,0,skill_get_time(skillid,skilllv)+1000,0); - switch(skillid){ //合奏スキルは相方をダンス?態にする - case BD_LULLABY: /* 子守歌 */ - case BD_RICHMANKIM: /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */ - case BD_ROKISWEIL: /* ロキの叫び */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */ - case BD_RAGNAROK: /* 神?の?昏 */ - case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ - { - int range=1; - int c=0; - if(sd){ - map_foreachinarea(skill_check_condition_use_sub,sd->bl.m, - sd->bl.x-range,sd->bl.y-range, - sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c); - } - } + //合奏スキルは相方をダンス状態にする + if (sd && skill_get_unit_flag(skillid)&UF_ENSEMBLE) { + int c=0; + map_foreachinarea(skill_check_condition_use_sub,sd->bl.m, + sd->bl.x-1,sd->bl.y-1,sd->bl.x+1,sd->bl.y+1,BL_PC,&sd->bl,&c); } } return group; @@ -8803,7 +8334,8 @@ int skill_delunitgroup(struct skill_unit_group *group) return 0; src=map_id2bl(group->src_id); - if( skill_is_danceskill(group->skill_id) ){ //ダンススキルはダンス?態を解除する + //ダンススキルはダンス状態を解除する + if (skill_get_unit_flag(group->skill_id)&UF_DANCE) { if(src) status_change_end(src,SC_DANCING,-1); } @@ -8841,13 +8373,14 @@ int skill_clear_unitgroup(struct block_list *src) if(src->type==BL_PC){ group=((struct map_session_data *)src)->skillunit; maxsug=MAX_SKILLUNITGROUP; - }else if(src->type==BL_MOB){ + } else if(src->type==BL_MOB){ group=((struct mob_data *)src)->skillunit; maxsug=MAX_MOBSKILLUNITGROUP; - }else if(src->type==BL_PET){ // [Valaris] + } else if(src->type==BL_PET){ // [Valaris] group=((struct pet_data *)src)->skillunit; maxsug=MAX_MOBSKILLUNITGROUP; - } + } else + return 0; if(group){ int i; for(i=0;i<maxsug;i++) @@ -8857,31 +8390,19 @@ int skill_clear_unitgroup(struct block_list *src) return 0; } -/* - * 珞ヌォケォュォェェヘヌェュェキェゾェホヤムツ - */ -int skill_unit_overlap_type(int skill_id) -{ - switch (skill_id) { - case WZ_STORMGUST: - case WZ_VERMILION: - return 1; // ェノェチェ鬪ォ鰥ーェォェ鬮タォ?ォクェ磑ェアェ - default: - return 0; // ?ローェォェ鬮タォ?ォクェ磑ェアェ - } -} - /*========================================== * スキルユニットグル?プの被影響tick?索 *------------------------------------------ */ struct skill_unit_group_tickset *skill_unitgrouptickset_search( - struct block_list *bl, struct skill_unit_group *sg) + struct block_list *bl,struct skill_unit_group *group,int tick) { int i,j=-1,k,s,id; struct skill_unit_group_tickset *set; nullpo_retr(0, bl); + if (group->interval==-1) + return NULL; if (bl->type == BL_PC) set = ((struct map_session_data *)bl)->skillunittick; @@ -8890,16 +8411,16 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search( else return 0; - if (skill_unit_overlap_type(sg->skill_id)) - id = s = sg->skill_id; + if (skill_get_unit_flag(group->skill_id)&UF_NOOVERLAP) + id = s = group->skill_id; else - id = s = sg->group_id; + id = s = group->group_id; for (i=0; i<MAX_SKILLUNITGROUPTICKSET; i++) { k = (i+s) % MAX_SKILLUNITGROUPTICKSET; if (set[k].id == id) return &set[k]; - else if (j == -1 && set[k].id == 0) + else if (j==-1 && (DIFF_TICK(tick,set[k].tick)>0 || set[k].id==0)) j=k; } @@ -8908,101 +8429,41 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search( sprintf (tmp_output, "skill_unitgrouptickset_search: tickset is full\n"); ShowWarning (tmp_output); } - for (i = 0; i<MAX_SKILLUNITGROUPTICKSET; i++) - set[k].id = 0; j = id % MAX_SKILLUNITGROUPTICKSET; } set[j].id = id; + set[j].tick = tick; return &set[j]; } /*========================================== - * スキルユニットグル?プの被影響tick削除 - *------------------------------------------ - */ -int skill_unitgrouptickset_delete( - struct block_list *bl, struct skill_unit_group *sg) -{ - int i, k, s, id; - struct skill_unit_group_tickset *set=NULL; - - nullpo_retr(0, bl); - if (bl->type == BL_PC) - set=((struct map_session_data *)bl)->skillunittick; - else if (bl->type == BL_MOB) - set=((struct mob_data *)bl)->skillunittick; - else - return 0; - - if (skill_unit_overlap_type(sg->skill_id)) - id = s = sg->skill_id; - else - id = s = sg->group_id; - - for(i=0; i<MAX_SKILLUNITGROUPTICKSET; i++) { - k = (i+s) % MAX_SKILLUNITGROUPTICKSET; - if (set[k].id == id) { - set[k].id = 0; - break; - } - } -// if (i == MAX_SKILLUNITGROUPTICKSET && battle_config.error_log) { -// printf("skill_unitgrouptickset_delete: tickset not found\n"); -// } - - return 0; -} - -/*========================================== * スキルユニットタイマ??動?理用(foreachinarea) *------------------------------------------ */ int skill_unit_timer_sub_onplace( struct block_list *bl, va_list ap ) { - struct block_list *src; - struct skill_unit *su; + struct skill_unit *unit; + struct skill_unit_group *group; unsigned int tick; nullpo_retr(0, bl); nullpo_retr(0, ap); - src=va_arg(ap,struct block_list*); + unit = va_arg(ap,struct skill_unit *); + tick = va_arg(ap,unsigned int); - tick=va_arg(ap,unsigned int); - su = (struct skill_unit *)src; - - if( su && su->alive ) { - struct skill_unit_group *sg; - sg = su->group; - if(sg && battle_check_target(src,bl,sg->target_flag )>0) - skill_unit_onplace( su, bl, tick ); - } - return 0; -} + if (bl->type!=BL_PC && bl->type!=BL_MOB) + return 0; + if (!unit->alive || bl->prev==NULL) + return 0; -/*========================================== - * スキルユニットタイマ?削除?理用(foreachinarea) - *------------------------------------------ - */ -int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap ) -{ - struct block_list *src; - struct skill_unit *su; - unsigned int tick; + nullpo_retr(0, group=unit->group); - nullpo_retr(0, bl); - nullpo_retr(0, ap); - src=va_arg(ap,struct block_list*); + if (battle_check_target(&unit->bl,bl,group->target_flag)<=0) + return 0; - tick=va_arg(ap,unsigned int); - su = (struct skill_unit *)src; + skill_unit_onplace_timer(unit,bl,tick); - if( su && su->alive ){ - struct skill_unit_group *sg; - sg = su->group; - if( sg && battle_check_target(src,bl,sg->target_flag )>0 ) - skill_unit_ondelete( su, bl, tick ); - } return 0; } @@ -9020,28 +8481,37 @@ int skill_unit_timer_sub( struct block_list *bl, va_list ap ) nullpo_retr(0, bl); nullpo_retr(0, ap); nullpo_retr(0, unit=(struct skill_unit *)bl); - nullpo_retr(0, group=unit->group); tick=va_arg(ap,unsigned int); if(!unit->alive) return 0; - range=(unit->range!=0)?unit->range:group->range; + nullpo_retr(0, group=unit->group); + range = unit->range; - /* onplaceイベント呼び出し */ - if(unit->alive && unit->range>=0){ - map_foreachinarea( skill_unit_timer_sub_onplace, bl->m, - bl->x-range,bl->y-range,bl->x+range,bl->y+range,0, - bl,tick); - if(group->unit_id == 0xaa && DIFF_TICK(tick,group->tick)>=6000*group->val2){ - map_foreachinarea( skill_idun_heal, bl->m, - bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,unit); - group->val2++; + /* onplace_timerイベント呼び出し */ + if (range>=0 && group->interval!=-1) { + map_foreachinarea(skill_unit_timer_sub_onplace, bl->m, + bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,bl,tick); + if (!unit->alive) + return 0; + // マグヌスは発動したユニットは削除する + if (group->skill_id==PR_MAGNUS && unit->val2) { + skill_delunit(unit); + return 0; } } + // イドゥンの林檎による回復 + if (group->unit_id==0xaa && DIFF_TICK(tick,group->tick)>=6000*group->val3) { + struct block_list *src = map_id2bl(group->src_id); + int range = skill_get_unit_layout_type(group->skill_id,group->skill_lv); + nullpo_retr(0, src); + map_foreachinarea(skill_idun_heal,src->m, + src->x-range,src->y-range,src->x+range,src->y+range,0,unit); + group->val3++; + } /* 時間切れ削除 */ - if(unit->alive && - (DIFF_TICK(tick,group->tick)>=group->limit || DIFF_TICK(tick,group->tick)>=unit->limit) ){ + if((DIFF_TICK(tick,group->tick)>=group->limit || DIFF_TICK(tick,group->tick)>=unit->limit)){ switch(group->unit_id){ case 0x8f: /* ブラストマイン */ group->unit_id = 0x8c; @@ -9117,92 +8587,33 @@ int skill_unit_timer( int tid,unsigned int tick,int id,int data) * スキルユニット移動時?理用(foreachinarea) *------------------------------------------ */ -int skill_unit_out_all_sub( struct block_list *bl, va_list ap ) -{ - struct skill_unit *unit; - struct skill_unit_group *group; - struct block_list *src; - int range; - unsigned int tick; - - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); - nullpo_retr(0, unit=(struct skill_unit *)bl); - nullpo_retr(0, group=unit->group); - - tick=va_arg(ap,unsigned int); - - if(!unit->alive || src->prev==NULL) - return 0; - - range=(unit->range!=0)?unit->range:group->range; - - if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 ) - return 0; - - if( src->x >= bl->x-range && src->x <= bl->x+range && - src->y >= bl->y-range && src->y <= bl->y+range ) - skill_unit_onout( unit, src, tick ); - - return 0; -} - - -/*========================================== - * スキルユニット移動時?理 - *------------------------------------------ - */ -int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range) -{ - nullpo_retr(0, bl); - - if( bl->prev==NULL ) - return 0; - - if(range<7) - range=7; - map_foreachinarea( skill_unit_out_all_sub, - bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL, - bl,tick ); - - return 0; -} - -/*========================================== - * スキルユニット移動時?理用(foreachinarea) - *------------------------------------------ - */ int skill_unit_move_sub( struct block_list *bl, va_list ap ) { - struct skill_unit *unit; + struct skill_unit *unit = (struct skill_unit *)bl; struct skill_unit_group *group; - struct block_list *src; - int range; - unsigned int tick; + struct block_list *target; + unsigned int tick,flag; nullpo_retr(0, bl); nullpo_retr(0, ap); - nullpo_retr(0, unit=(struct skill_unit *)bl); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); - - tick=va_arg(ap,unsigned int); + nullpo_retr(0, target=va_arg(ap,struct block_list*)); + tick = va_arg(ap,unsigned int); + flag = va_arg(ap,int); - if(!unit->alive || src->prev==NULL) + if (target->type!=BL_PC && target->type!=BL_MOB) return 0; - if((group=unit->group) == NULL) + nullpo_retr(0, group=unit->group); + if (group->interval!=-1) return 0; - range=(unit->range!=0)?unit->range:group->range; - if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 ) + if (!unit->alive || target->prev==NULL) return 0; - if( src->x >= bl->x-range && src->x <= bl->x+range && - src->y >= bl->y-range && src->y <= bl->y+range ) - skill_unit_onplace( unit, src, tick ); + if (flag) + skill_unit_onplace(unit,target,tick); else - skill_unit_onout( unit, src, tick ); + skill_unit_onout(unit,target,tick); return 0; } @@ -9211,54 +8622,16 @@ int skill_unit_move_sub( struct block_list *bl, va_list ap ) * スキルユニット移動時?理 *------------------------------------------ */ -int skill_unit_move( struct block_list *bl,unsigned int tick,int range) +int skill_unit_move(struct block_list *bl,unsigned int tick,int flag) { nullpo_retr(0, bl); - if( bl->prev==NULL ) + if(bl->prev==NULL ) return 0; - if(range<7) - range=7; - map_foreachinarea( skill_unit_move_sub, - bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL, - bl,tick ); - - return 0; -} + map_foreachinarea(skill_unit_move_sub, + bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,bl,tick,flag); -/*========================================== - * スキルユニット自?の移動時?理(foreachinarea) - *------------------------------------------ - */ -int skill_unit_move_unit_group_sub( struct block_list *bl, va_list ap ) -{ - struct skill_unit *unit; - struct skill_unit_group *group; - struct block_list *src; - int range; - unsigned int tick; - - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); - nullpo_retr(0, unit=(struct skill_unit *)src); - nullpo_retr(0, group=unit->group); - - tick=va_arg(ap,unsigned int); - - if(!unit->alive || bl->prev==NULL) - return 0; - - range=(unit->range!=0)?unit->range:group->range; - - if( range<0 || battle_check_target(src,bl,group->target_flag )<=0 ) - return 0; - if( bl->x >= src->x-range && bl->x <= src->x+range && - bl->y >= src->y-range && bl->y <= src->y+range ) - skill_unit_onplace( unit, bl, tick ); - else - skill_unit_onout( unit, bl, tick ); return 0; } @@ -9269,115 +8642,97 @@ int skill_unit_move_unit_group_sub( struct block_list *bl, va_list ap ) */ int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int dy) { + int i,j; + int tick = gettick(); + int *m_flag; + struct skill_unit *unit1; + struct skill_unit *unit2; + nullpo_retr(0, group); + if (group->unit_count<=0) + return 0; + if (group->unit==NULL) + return 0; - if( group->unit_count<=0) + // 移動可能なスキルはダンス系と、ブラストマイン、クレイモアートラップのみ + if (!(skill_get_unit_flag(group->skill_id)&UF_DANCE) && + group->skill_id!=HT_CLAYMORETRAP && group->skill_id!=HT_BLASTMINE) return 0; - if(group->unit!=NULL){ - if(!battle_config.unit_movement_type){ - int i; - for(i=0;i<group->unit_count;i++){ - struct skill_unit *unit=&group->unit[i]; - if(unit->alive && !(m==unit->bl.m && dx==0 && dy==0)){ - int range=unit->range; - map_delblock(&unit->bl); - unit->bl.m = m; - unit->bl.x += dx; - unit->bl.y += dy; - map_addblock(&unit->bl); - clif_skill_setunit(unit); - if(range>0){ - if(range<7) - range=7; - map_foreachinarea( skill_unit_move_unit_group_sub, unit->bl.m, - unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0, - &unit->bl,gettick() ); - } - } + m_flag = malloc(sizeof(int)*group->unit_count); + memset(m_flag,0,sizeof(int)*group->unit_count);// 移動フラグ + // 先にフラグを全部決める + // m_flag + // 0: 単純移動 + // 1: ユニットを移動する(現位置からユニットがなくなる) + // 2: 残留&新位置が移動先となる(移動先にユニットが存在しない) + // 3: 残留 + for(i=0;i<group->unit_count;i++){ + unit1=&group->unit[i]; + if (!unit1->alive || unit1->bl.m!=m) + continue; + for(j=0;j<group->unit_count;j++){ + unit2=&group->unit[j]; + if (!unit2->alive) + continue; + if (unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){ + // 移動先にユニットがかぶっている + m_flag[i] |= 0x1; } - }else{ - int i,j, *r_flag, *s_flag, *m_flag; - struct skill_unit *unit1; - struct skill_unit *unit2; - r_flag = (int *) aMallocA(sizeof(int) * group->unit_count); - s_flag = (int *) aMallocA(sizeof(int) * group->unit_count); - m_flag = (int *) aMallocA(sizeof(int) * group->unit_count); - memset(r_flag,0, sizeof(int) * group->unit_count);// ?承フラグ - memset(s_flag,0, sizeof(int) * group->unit_count);// ?承フラグ - memset(m_flag,0, sizeof(int) * group->unit_count);// ?承フラグ - - //先にフラグを全部決める - for(i=0;i<group->unit_count;i++){ - int move_check=0;// かぶりフラグ - unit1=&group->unit[i]; - for(j=0;j<group->unit_count;j++){ - unit2=&group->unit[j]; - if(unit1->bl.m==m && unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){ - //移動先にユニットがかぶってたら - s_flag[i]=1;// 移動前のユニットナンバ?の?承フラグon - r_flag[j]=1;// かぶるユニットナンバ?の?留フラグon - move_check=1;//ユニットがかぶった。 - break; - } - } - if(!move_check)// ユニットがかぶってなかったら - m_flag[i]=1;// 移動前ユニットナンバ?の移動フラグon - } - - //フラグに基づいてユニット移動 - for(i=0;i<group->unit_count;i++){ - unit1=&group->unit[i]; - if(m_flag[i]){// 移動フラグがonで - if(!r_flag[i]){// ?留フラグがoffなら - //?純移動(rangeも?承の必要無し) - int range=unit1->range; - map_delblock(&unit1->bl); - unit1->bl.m = m; - unit1->bl.x += dx; - unit1->bl.y += dy; - map_addblock(&unit1->bl); - clif_skill_setunit(unit1); - if(range > 0){ - if(range < 7) - range = 7; - map_foreachinarea( skill_unit_move_unit_group_sub, unit1->bl.m, - unit1->bl.x-range,unit1->bl.y-range,unit1->bl.x+range,unit1->bl.y+range,0, - &unit1->bl,gettick() ); - } - }else{// ?留フラグがonなら - //空ユニットになるので、?承可能なユニットを探す - for(j=0;j<group->unit_count;j++){ - unit2=&group->unit[j]; - if(s_flag[j] && !r_flag[j]){ - // ?承移動(range?承付き) - int range=unit1->range; - map_delblock(&unit2->bl); - unit2->bl.m = m; - unit2->bl.x = unit1->bl.x + dx; - unit2->bl.y = unit1->bl.y + dy; - unit2->range = unit1->range; - map_addblock(&unit2->bl); - clif_skill_setunit(unit2); - if(range > 0){ - if(range < 7) - range = 7; - map_foreachinarea( skill_unit_move_unit_group_sub, unit2->bl.m, - unit2->bl.x-range,unit2->bl.y-range,unit2->bl.x+range,unit2->bl.y+range,0, - &unit2->bl,gettick() ); - } - s_flag[j]=0;// ?承完了したのでoff - break; - } - } - } + if (unit1->bl.x-dx==unit2->bl.x && unit1->bl.y-dy==unit2->bl.y){ + // ユニットがこの場所にやってくる + m_flag[i] |= 0x2; + } + } + } + // フラグに基づいてユニット移動 + // フラグが1のunitを探し、フラグが2のunitの移動先に移す + j = 0; + for (i=0;i<group->unit_count;i++) { + unit1=&group->unit[i]; + if (!unit1->alive) + continue; + if (!(m_flag[i]&0x2)) { + // ユニットがなくなる場所でスキルユニット影響を消す + map_foreachinarea(skill_unit_effect,unit1->bl.m, + unit1->bl.x,unit1->bl.y,unit1->bl.x,unit1->bl.y,0, + &unit1->bl,tick,0); + } + if (m_flag[i]==0) { + // 単純移動 + map_delblock(&unit1->bl); + unit1->bl.m = m; + unit1->bl.x += dx; + unit1->bl.y += dy; + map_addblock(&unit1->bl); + clif_skill_setunit(unit1); + } else if (m_flag[i]==1) { + // フラグが2のものを探してそのユニットの移動先に移動 + for(;j<group->unit_count;j++) { + if (m_flag[j]==2) { + // 継承移動 + unit2 = &group->unit[j]; + if (!unit2->alive) + continue; + map_delblock(&unit1->bl); + unit1->bl.m = m; + unit1->bl.x = unit2->bl.x+dx; + unit1->bl.y = unit2->bl.y+dy; + map_addblock(&unit1->bl); + clif_skill_setunit(unit1); + j++; + break; } } - aFree(r_flag); - aFree(s_flag); - aFree(m_flag); + } + if (!(m_flag[i]&0x2)) { + // 移動後の場所でスキルユニットを発動 + map_foreachinarea(skill_unit_effect,unit1->bl.m, + unit1->bl.x,unit1->bl.y,unit1->bl.x,unit1->bl.y,0, + &unit1->bl,tick,1); } } + free(m_flag); return 0; } @@ -9505,25 +8860,29 @@ int skill_produce_mix( struct map_session_data *sd, if(!equip) { // Corrected rates [DracoRPG] --------------------------// if(skill_produce_db[idx].req_skill==AM_PHARMACY) { + make_per = pc_checkskill(sd,AM_LEARNINGPOTION)*100 + + pc_checkskill(sd,AM_PHARMACY)*300 + sd->status.job_level*20 + + sd->status.dex*10+sd->status.int_*5; + if(nameid >= 501 && nameid <= 505) // Normal potions - make_per = 2000 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_POTIONPITCHER)*100; - if(nameid >= 605 && nameid <= 606) // Anodyne & Aloevera (not sure of the formula, I put the same base value as normal pots but without the Aid Potion bonus since they are not throwable pots ^^) - make_per = 2000 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300; + make_per += 2000 + pc_checkskill(sd,AM_POTIONPITCHER)*100; + else if(nameid >= 605 && nameid <= 606) // Anodyne & Aloevera (not sure of the formula, I put the same base value as normal pots but without the Aid Potion bonus since they are not throwable pots ^^) + make_per += 2000; else if(nameid >= 545 && nameid <= 547) // Concentrated potions - make_per = sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300; + ; else if(nameid == 970) // Alcohol - make_per = 1000 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300; + make_per += 1000; else if(nameid == 7135) // Bottle Grenade - make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_DEMONSTRATION)*100; + make_per += 500 + pc_checkskill(sd,AM_DEMONSTRATION)*100; else if(nameid == 7136) // Acid Bottle - make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_ACIDTERROR)*100; + make_per += 500 + pc_checkskill(sd,AM_ACIDTERROR)*100; else if(nameid == 7137) // Plant Bottle - make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CANNIBALIZE)*100; + make_per += 500 + pc_checkskill(sd,AM_CANNIBALIZE)*100; else if(nameid == 7138) // Marine Sphere Bottle - make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_SPHEREMINE)*100; + make_per += 500 + pc_checkskill(sd,AM_SPHEREMINE)*100; else if(nameid == 7139) // Glistening Coat - make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CP_WEAPON)*100 + - pc_checkskill(sd,AM_CP_SHIELD)*100 + pc_checkskill(sd,AM_CP_ARMOR)*100 + pc_checkskill(sd,AM_CP_HELM)*100; + make_per += 500 + pc_checkskill(sd,AM_CP_WEAPON)*100 + pc_checkskill(sd,AM_CP_SHIELD)*100 + + pc_checkskill(sd,AM_CP_ARMOR)*100 + pc_checkskill(sd,AM_CP_HELM)*100; else make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300; } else if (skill_produce_db[idx].req_skill == ASC_CDP) { @@ -9604,8 +8963,7 @@ int skill_produce_mix( struct map_session_data *sd, clif_additem(sd,0,0,flag); map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0); } - } - else { + } else { if(log_config.produce > 0) log_produce(sd,nameid,slot1,slot2,slot3,0); @@ -9675,6 +9033,213 @@ int skill_arrow_create( struct map_session_data *sd,int nameid) * 初期化系 */ +/*---------------------------------------------------------------------------- + * 初期化系 + */ + +/* + * 文字列処理 + * ',' で区切って val に戻す + */ +int skill_split_str(char *str,char **val,int num) +{ + int i; + + for (i=0; i<num && str; i++){ + val[i] = str; + str = strchr(str,','); + if (str) + *str++=0; + } + return i; +} +/* + * 文字列処理 + * ':' で区切ってatoiしてvalに戻す + */ +int skill_split_atoi(char *str,int *val) +{ + int i, max = 0; + + for (i=0; i<MAX_SKILL_LEVEL; i++) { + if (str) { + val[i] = max = atoi(str); + str = strchr(str,':'); + if (str) + *str++=0; + } else { + val[i] = max; + } + } + return i; +} + +/* + * スキルユニットの配置情報作成 + */ +void skill_init_unit_layout() +{ + int i,j,size,pos = 0; + + memset(skill_unit_layout,0,sizeof(skill_unit_layout)); + // 矩形のユニット配置を作成する + for (i=0; i<=MAX_SQUARE_LAYOUT; i++) { + size = i*2+1; + skill_unit_layout[i].count = size*size; + for (j=0; j<size*size; j++) { + skill_unit_layout[i].dx[j] = (j%size-i); + skill_unit_layout[i].dy[j] = (j/size-i); + } + } + pos = i; + // 矩形以外のユニット配置を作成する + for (i=0;i<MAX_SKILL_DB;i++) { + if (!skill_db[i].unit_id[0] || skill_db[i].unit_layout_type[0] != -1) + continue; + switch (i) { + case MG_FIREWALL: + case WZ_ICEWALL: + // ファイアーウォール、アイスウォールは方向で変わるので別処理 + break; + case PR_SANCTUARY: + { + static const int dx[] = { + -1, 0, 1,-2,-1, 0, 1, 2,-2,-1, + 0, 1, 2,-2,-1, 0, 1, 2,-1, 0, 1}; + static const int dy[]={ + -2,-2,-2,-1,-1,-1,-1,-1, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2}; + skill_unit_layout[pos].count = 21; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + case PR_MAGNUS: + { + static const int dx[] = { + -1, 0, 1,-1, 0, 1,-3,-2,-1, 0, + 1, 2, 3,-3,-2,-1, 0, 1, 2, 3, + -3,-2,-1, 0, 1, 2, 3,-1, 0, 1,-1, 0, 1}; + static const int dy[] = { + -3,-3,-3,-2,-2,-2,-1,-1,-1,-1, + -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3}; + skill_unit_layout[pos].count = 33; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + case AS_VENOMDUST: + { + static const int dx[] = {-1, 0, 0, 0, 1}; + static const int dy[] = { 0,-1, 0, 1, 0}; + skill_unit_layout[pos].count = 5; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + case CR_GRANDCROSS: + case NPC_DARKGRANDCROSS: + { + static const int dx[] = { + 0, 0,-1, 0, 1,-2,-1, 0, 1, 2, + -4,-3,-2,-1, 0, 1, 2, 3, 4,-2, + -1, 0, 1, 2,-1, 0, 1, 0, 0}; + static const int dy[] = { + -4,-3,-2,-2,-2,-1,-1,-1,-1,-1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 2, 2, 2, 3, 4}; + skill_unit_layout[pos].count = 29; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + case PF_FOGWALL: + { + static const int dx[] = { + -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2}; + static const int dy[] = { + -1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}; + skill_unit_layout[pos].count = 15; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + default: + printf("unknown unit layout at skill %d\n",i); + break; + } + if (!skill_unit_layout[pos].count) + continue; + for (j=0;j<MAX_SKILL_LEVEL;j++) + skill_db[i].unit_layout_type[j] = pos; + pos++; + } + // ファイヤーウォール + firewall_unit_pos = pos; + for (i=0;i<8;i++) { + if (i&1) { /* 斜め配置 */ + skill_unit_layout[pos].count = 5; + if (i&0x2) { + int dx[] = {-1,-1, 0, 0, 1}; + int dy[] = { 1, 0, 0,-1,-1}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } else { + int dx[] = { 1, 1 ,0, 0,-1}; + int dy[] = { 1, 0, 0,-1,-1}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + } else { /* 縦横配置 */ + skill_unit_layout[pos].count = 3; + if (i%4==0) { /* 上下 */ + int dx[] = {-1, 0, 1}; + int dy[] = { 0, 0, 0}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } else { /* 左右 */ + int dx[] = { 0, 0, 0}; + int dy[] = {-1, 0, 1}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + } + pos++; + } + // アイスウォール + icewall_unit_pos = pos; + for (i=0;i<8;i++) { + skill_unit_layout[pos].count = 5; + if (i&1) { /* 斜め配置 */ + if (i&0x2) { + int dx[] = {-2,-1, 0, 1, 2}; + int dy[] = { 2,-1, 0,-1,-2}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } else { + int dx[] = { 2, 1 ,0,-1,-2}; + int dy[] = { 2, 1, 0,-1,-2}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + } else { /* 縦横配置 */ + if (i%4==0) { /* 上下 */ + int dx[] = {-2,-1, 0, 1, 2}; + int dy[] = { 0, 0, 0, 0, 0}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } else { /* 左右 */ + int dx[] = { 0, 0, 0, 0, 0}; + int dy[] = {-2,-1, 0, 1, 2}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + } + pos++; + } +} + /*========================================== * スキル?係ファイル?み?み * skill_db.txt スキルデ?タ @@ -9699,14 +9264,10 @@ int skill_readdb(void) return 1; } while(fgets(line,1020,fp)){ - char *split[50], *split2[MAX_SKILL_LEVEL]; + char *split[50]; if(line[0]=='/' && line[1]=='/') continue; - for(j=0,p=line;j<14 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,14); if(split[13]==NULL || j<14) continue; @@ -9717,28 +9278,13 @@ int skill_readdb(void) continue; /* printf("skill id=%d\n",i); */ - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].range[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[1],skill_db[i].range); skill_db[i].hit=atoi(split[2]); skill_db[i].inf=atoi(split[3]); skill_db[i].pl=atoi(split[4]); skill_db[i].nk=atoi(split[5]); skill_db[i].max=atoi(split[6]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[7];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].num[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[1],skill_db[i].num); if(strcmpi(split[8],"yes") == 0) skill_db[i].castcancel=1; @@ -9755,14 +9301,7 @@ int skill_readdb(void) skill_db[i].skill_type=BF_MISC; else skill_db[i].skill_type=0; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[13];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].blewcount[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[13],skill_db[i].blewcount); } fclose(fp); sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_db.txt"); @@ -9774,14 +9313,10 @@ int skill_readdb(void) return 1; } while(fgets(line,1020,fp)){ - char *split[51], *split2[MAX_SKILL_LEVEL]; + char *split[50]; if(line[0]=='/' && line[1]=='/') continue; - for(j=0,p=line;j<30 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,30); if(split[29]==NULL || j<30) continue; @@ -9791,74 +9326,26 @@ int skill_readdb(void) else if(i<=0 || i>MAX_SKILL_DB) continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].hp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].mhp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].sp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].hp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[5];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].sp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[6];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].zeny[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[7];j<32 && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<32 && split2[k];k++) { - l = atoi(split2[k]); - if(l == 99) { + skill_split_atoi(split[1],skill_db[i].hp); + skill_split_atoi(split[2],skill_db[i].mhp); + skill_split_atoi(split[3],skill_db[i].sp); + skill_split_atoi(split[4],skill_db[i].hp_rate); + skill_split_atoi(split[5],skill_db[i].sp_rate); + skill_split_atoi(split[6],skill_db[i].zeny); + + p = split[7]; + for(j=0;j<32;j++){ + l = atoi(p); + if (l==99) { skill_db[i].weapon = 0xffffffff; break; } else skill_db[i].weapon |= 1<<l; + p=strchr(p,':'); + if(!p) + break; + p++; } if( strcmpi(split[8],"hiding")==0 ) skill_db[i].state=ST_HIDING; @@ -9875,14 +9362,7 @@ int skill_readdb(void) else if( strcmpi(split[8],"water")==0 ) skill_db[i].state=ST_WATER; else skill_db[i].state=ST_NONE; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[9];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].spiritball[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[9],skill_db[i].spiritball); skill_db[i].itemid[0]=atoi(split[10]); skill_db[i].amount[0]=atoi(split[11]); skill_db[i].itemid[1]=atoi(split[12]); @@ -9915,15 +9395,11 @@ int skill_readdb(void) return 1; } while(fgets(line,1020,fp)){ - char *split[50], *split2[MAX_SKILL_LEVEL]; + char *split[50]; memset(split,0,sizeof(split)); // [Valaris] thanks to fov if(line[0]=='/' && line[1]=='/') continue; - for(j=0,p=line;j<5 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,5); if(split[4]==NULL || j<5) continue; @@ -9933,45 +9409,55 @@ int skill_readdb(void) else if(i<=0 || i>MAX_SKILL_DB) continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].cast[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].delay[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[1],skill_db[i].cast); + skill_split_atoi(split[2],skill_db[i].delay); + skill_split_atoi(split[3],skill_db[i].upkeep_time); + skill_split_atoi(split[4],skill_db[i].upkeep_time2); + } + fclose(fp); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_cast_db.txt"); + ShowStatus(tmp_output); - memset(split2,0,sizeof(split2)); - for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].upkeep_time[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + /* スキルユニットデータベース */ + fp = fopen("db/skill_unit_db.txt","r"); + if (fp==NULL) { + printf("can't read db/skill_unit_db.txt\n"); + return 1; + } + while (fgets(line,1020,fp)) { + char *split[50]; + if (line[0]=='/' && line[1]=='/') + continue; + j = skill_split_str(line,split,8); + if (split[7]==NULL || j<8) + continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].upkeep_time2[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + i=atoi(split[0]); + if (i>=10000 && i<10015) // for guild skills [Celest] + i -= 9500; + else if(i<=0 || i>MAX_SKILL_DB) + continue; + skill_db[i].unit_id[0] = strtol(split[1],NULL,16); + skill_db[i].unit_id[1] = strtol(split[2],NULL,16); + skill_split_atoi(split[3],skill_db[i].unit_layout_type); + skill_db[i].unit_range = atoi(split[4]); + skill_db[i].unit_interval = atoi(split[5]); + + if( strcmpi(split[6],"noenemy")==0 ) skill_db[i].unit_target=BCT_NOENEMY; + else if( strcmpi(split[6],"friend")==0 ) skill_db[i].unit_target=BCT_NOENEMY; + else if( strcmpi(split[6],"party")==0 ) skill_db[i].unit_target=BCT_PARTY; + else if( strcmpi(split[6],"all")==0 ) skill_db[i].unit_target=BCT_ALL; + else if( strcmpi(split[6],"enemy")==0 ) skill_db[i].unit_target=BCT_ENEMY; + else if( strcmpi(split[6],"self")==0 ) skill_db[i].unit_target=BCT_SELF; + else skill_db[i].unit_target = strtol(split[6],NULL,16); + + skill_db[i].unit_flag = strtol(split[7],NULL,16); + k++; } fclose(fp); - sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_cast_db.txt"); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_unit_db.txt"); ShowStatus(tmp_output); + skill_init_unit_layout(); /* 製造系スキルデ?タベ?ス */ memset(skill_produce_db,0,sizeof(skill_produce_db)); @@ -9990,16 +9476,11 @@ int skill_readdb(void) if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<3 + MAX_PRODUCE_RESOURCE * 2 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,(3 + MAX_PRODUCE_RESOURCE * 2)); if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); - if(i<=0) - continue; + if(i<=0) continue; skill_produce_db[k].nameid=i; skill_produce_db[k].itemlv=atoi(split[1]); @@ -10031,11 +9512,7 @@ int skill_readdb(void) if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<13 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,13); if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); @@ -10068,11 +9545,7 @@ int skill_readdb(void) if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<13 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,13); if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); @@ -10096,15 +9569,11 @@ int skill_readdb(void) return 1; } while(fgets(line,1020,fp)){ - char *split[50], *split2[MAX_SKILL_LEVEL]; + char *split[50]; if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<3 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,3); if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); @@ -10113,25 +9582,10 @@ int skill_readdb(void) else if(i<=0 || i>MAX_SKILL_DB) continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].castnodex[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - + skill_split_atoi(split[1],skill_db[i].castnodex); if (!split[2]) continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].delaynodex[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[2],skill_db[i].delaynodex); } fclose(fp); sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_castnodex_db.txt"); @@ -10148,11 +9602,7 @@ int skill_readdb(void) if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<2 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,2); if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); diff --git a/src/map/skill.h b/src/map/skill.h index dc789aa4a..72653e9a9 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -25,6 +25,12 @@ struct skill_db { int castnodex[MAX_SKILL_LEVEL]; int delaynodex[MAX_SKILL_LEVEL]; int nocast; + int unit_id[2]; + int unit_layout_type[MAX_SKILL_LEVEL]; + int unit_range; + int unit_interval; + int unit_target; + int unit_flag; }; extern struct skill_db skill_db[MAX_SKILL_DB]; @@ -35,6 +41,24 @@ struct skill_name_db { }; extern const struct skill_name_db skill_names[]; +#define MAX_SKILL_UNIT_LAYOUT 50 +#define MAX_SQUARE_LAYOUT 5 // 11*11のユニット配置が最大 +#define MAX_SKILL_UNIT_COUNT ((MAX_SQUARE_LAYOUT*2+1)*(MAX_SQUARE_LAYOUT*2+1)) +struct skill_unit_layout { + int count; + int dx[MAX_SKILL_UNIT_COUNT]; + int dy[MAX_SKILL_UNIT_COUNT]; +}; + +enum { + UF_DEFNOTENEMY = 0x0001, // defnotenemy 設定でBCT_NOENEMYに切り替え + UF_NOREITERATION = 0x0002, // 重複置き禁止 + UF_NOFOOTSET = 0x0004, // 足元置き禁止 + UF_NOOVERLAP = 0x0008, // ユニット効果が重複しない + UF_DANCE = 0x0100, // ダンススキル + UF_ENSEMBLE = 0x0200, // 合奏スキル +}; + // アイテム作成デ?タベ?ス struct skill_produce_db { int nameid, trigger; @@ -87,6 +111,7 @@ int skill_get_unit_id(int id,int flag); int skill_get_inf2( int id ); int skill_get_maxcount( int id ); int skill_get_blewcount( int id ,int lv ); +int skill_get_unit_flag( int id ); int skill_tree_get_max( int id, int b_class ); // Celest // スキルの使用 @@ -110,10 +135,6 @@ int skill_delunit(struct skill_unit *unit); struct skill_unit_group *skill_initunitgroup(struct block_list *src, int count,int skillid,int skilllv,int unit_id); int skill_delunitgroup(struct skill_unit_group *group); - -struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl,struct skill_unit_group *sg); -int skill_unitgrouptickset_delete(struct block_list *bl,struct skill_unit_group *sg); - int skill_clear_unitgroup(struct block_list *src); int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl, @@ -121,12 +142,12 @@ int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl, int skill_castfix( struct block_list *bl, int time ); int skill_delayfix( struct block_list *bl, int time ); -int skill_check_unit_range(int m,int x,int y,int range,int skillid); -int skill_check_unit_range2(int m,int x,int y,int range); +int skill_check_unit_range(int m,int x,int y,int skillid, int skilllv); +int skill_check_unit_range2(int m,int x,int y,int skillid, int skilllv); // -- moonsoul (added skill_check_unit_cell) int skill_check_unit_cell(int skillid,int m,int x,int y,int unit_id); int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range); -int skill_unit_move( struct block_list *bl,unsigned int tick,int range); +int skill_unit_move(struct block_list *bl,unsigned int tick,int flag); int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int dy); struct skill_unit_group *skill_check_dancing( struct block_list *src ); @@ -151,7 +172,6 @@ void skill_devotion_end(struct map_session_data *md,struct map_session_data *sd, // その他 int skill_check_cloaking(struct block_list *bl); int skill_type_cloaking(struct block_list *bl); -int skill_is_danceskill(int id); // ステ?タス異常 int skill_encchant_eremental_end(struct block_list *bl, int type); diff --git a/src/map/status.c b/src/map/status.c index 0d35572d0..5275be42a 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -31,14 +31,17 @@ int SkillStatusChangeTable[]={ /* status.hのenumのSC_***とあわせること */ -1, 1,-1, /* 10- */ SC_SIGHT, /* サイト */ - -1,-1,-1,-1, + -1, + SC_SAFETYWALL, /* セーフティーウォール */ + -1,-1,-1, SC_FREEZE, /* フロストダイバ? */ SC_STONE, /* スト?ンカ?ス */ -1,-1,-1, /* 20- */ -1,-1,-1,-1, SC_RUWACH, /* ルアフ */ - -1,-1,-1,-1, + SC_PNEUMA, /* ニューマ */ + -1,-1,-1, SC_INCREASEAGI, /* 速度?加 */ /* 30- */ SC_DECREASEAGI, /* 速度減少 */ @@ -3585,15 +3588,6 @@ int status_change_start(struct block_list *bl,int type,int val1,int val2,int val case SC_ANKLE: break; - /* ウォ?タ?ボ?ル */ - case SC_WATERBALL: - tick=150; - if(val1>5) //レベルが5以上の場合は25?に制限(1?目はすでに打ってるので-1) - val3=5*5-1; - else - val3= (val1|1)*(val1|1)-1; - break; - /* スキルじゃない/時間に?係しない */ case SC_RIDING: calc_flag = 1; @@ -4361,21 +4355,6 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) } break; - case SC_WATERBALL: /* ウォ?タ?ボ?ル */ - { - struct block_list *target=map_id2bl(sc_data[type].val2); - if (!target || !target->prev) - break; // target has been killed in previous hits, no need to raise an alarm ^^; - // nullpo_retb(target); - // nullpo_retb(target->prev); - skill_attack(BF_MAGIC,bl,bl,target,WZ_WATERBALL,sc_data[type].val1,tick,0); - if((--sc_data[type].val3)>0) { - sc_data[type].timer=add_timer( 150+tick,status_change_timer, bl->id, data ); - return 0; - } - } - break; - case SC_ENDURE: /* インデュア */ case SC_AUTOBERSERK: // Celest if(sd && sd->special_state.infinite_endure) { diff --git a/src/map/status.h b/src/map/status.h index d788c7b50..fbeee7300 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -111,7 +111,7 @@ enum { // struct map_session_data の status_changeの番?テ?ブル //-- 137-139 SC_SAFETYWALL = 140, SC_PNEUMA = 141, - SC_WATERBALL = 142, +//-- 142 SC_ANKLE = 143, SC_DANCING = 144, SC_KEEPING = 145, |