diff options
Diffstat (limited to 'src/map')
81 files changed, 5318 insertions, 4034 deletions
diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c index 3da49c3b9..7600d3d0c 100644 --- a/src/map/HPMmap.c +++ b/src/map/HPMmap.c @@ -5,63 +5,73 @@ #include "HPMmap.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> +#include "common/HPM.h" +#include "common/cbasetypes.h" + +#include "common/HPMi.h" +#include "common/conf.h" +#include "common/console.h" +#include "common/core.h" +#include "common/db.h" +#include "common/des.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/mapindex.h" +#include "common/mmo.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/spinlock.h" +#include "common/sql.h" +#include "common/strlib.h" +#include "common/sysinfo.h" +#include "common/timer.h" +#include "common/utils.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/battleground.h" +#include "map/buyingstore.h" +#include "map/channel.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/date.h" +#include "map/duel.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/irc-bot.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/map.h" +#include "map/mapreg.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/packets_struct.h" +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pc_groups.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/script.h" +#include "map/searchstore.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "map/trade.h" +#include "map/unit.h" +#include "map/vending.h" -#include "atcommand.h" -#include "battle.h" -#include "battleground.h" -#include "channel.h" -#include "chat.h" -#include "chrif.h" -#include "clif.h" -#include "date.h" -#include "duel.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "instance.h" -#include "intif.h" -#include "irc-bot.h" -#include "itemdb.h" -#include "log.h" -#include "mail.h" -#include "map.h" -#include "mapreg.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pc_groups.h" -#include "pet.h" -#include "quest.h" -#include "script.h" -#include "searchstore.h" -#include "skill.h" -#include "status.h" -#include "storage.h" -#include "trade.h" -#include "unit.h" -#include "vending.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/db.h" -#include "../common/des.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/mapindex.h" -#include "../common/mmo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/sysinfo.h" +// HPMDataCheck comes after all the other includes +#include "common/HPMDataCheck.h" -#include "../common/HPMDataCheck.h" +#include <stdio.h> +#include <stdlib.h> struct HPM_atcommand_list { //tracking currently not enabled @@ -114,6 +124,10 @@ bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataType ret->HPDataSRCPtr = (void**)(&((struct item_data *)ptr)->hdata); ret->hdatac = &((struct item_data *)ptr)->hdatac; break; + case HPDT_BGDATA: + ret->HPDataSRCPtr = (void**)(&((struct battleground_data *)ptr)->hdata); + ret->hdatac = &((struct battleground_data *)ptr)->hdatac; + break; default: return false; } diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h index 0c727d017..00a8f43c3 100644 --- a/src/map/HPMmap.h +++ b/src/map/HPMmap.h @@ -8,9 +8,9 @@ #error You should never include HPMmap.h from a plugin. #endif -#include "../common/cbasetypes.h" -#include "../map/atcommand.h" -#include "../common/HPM.h" +#include "map/atcommand.h" +#include "common/cbasetypes.h" +#include "common/HPM.h" struct hplugin; struct map_session_data; diff --git a/src/map/Makefile.in b/src/map/Makefile.in index 90bb55694..ac1b4d837 100644 --- a/src/map/Makefile.in +++ b/src/map/Makefile.in @@ -9,18 +9,20 @@ CONFIG_H = $(wildcard $(CONFIG_D)/*.h) $(wildcard $(CONFIG_D)/*/*.h) COMMON_D = ../common COMMON_H = $(wildcard $(COMMON_D)/*.h) SYSINFO_INC = $(COMMON_D)/sysinfo.inc +COMMON_INCLUDE = -I.. -LIBCONFIG_D = ../../3rdparty/libconfig +THIRDPARTY_D = ../../3rdparty +THIRDPARTY_INCLUDE = -I$(THIRDPARTY_D) + +LIBCONFIG_D = $(THIRDPARTY_D)/libconfig LIBCONFIG_OBJ = $(addprefix $(LIBCONFIG_D)/, libconfig.o grammar.o scanctx.o \ scanner.o strbuf.o) LIBCONFIG_H = $(addprefix $(LIBCONFIG_D)/, libconfig.h grammar.h parsectx.h \ scanctx.h scanner.h strbuf.h wincompat.h) -LIBCONFIG_INCLUDE = -I$(LIBCONFIG_D) -MT19937AR_D = ../../3rdparty/mt19937ar +MT19937AR_D = $(THIRDPARTY_D)/mt19937ar MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o MT19937AR_H = $(MT19937AR_D)/mt19937ar.h -MT19937AR_INCLUDE = -I$(MT19937AR_D) MAP_C = atcommand.c battle.c battleground.c buyingstore.c channel.c chat.c \ chrif.c clif.c date.c duel.c elemental.c guild.c homunculus.c HPMmap.c \ @@ -111,7 +113,7 @@ map-server: ../../map-server@EXEEXT@ obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_sql @echo " CC $<" - @$(CC) @CFLAGS@ @DEFS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + @$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # missing object files $(COMMON_D)/obj_all/common.a: diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 560848c5b..fb0b89381 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -4,59 +4,59 @@ #define HERCULES_CORE -#include "../config/core.h" // AUTOLOOTITEM_SIZE, AUTOTRADE_PERSISTENCY, MAX_SUGGESTIONS, MOB_FLEE(), MOB_HIT(), RENEWAL, RENEWAL_DROP, RENEWAL_EXP +#include "config/core.h" // AUTOLOOTITEM_SIZE, AUTOTRADE_PERSISTENCY, MAX_SUGGESTIONS, MOB_FLEE(), MOB_HIT(), RENEWAL, RENEWAL_DROP, RENEWAL_EXP #include "atcommand.h" +#include "map/HPMmap.h" +#include "map/battle.h" +#include "map/channel.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/duel.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/map.h" +#include "map/mapreg.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pc_groups.h" // groupid2name +#include "map/pet.h" +#include "map/quest.h" +#include "map/script.h" +#include "map/searchstore.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "map/trade.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/core.h" +#include "common/malloc.h" +#include "common/mmo.h" // MAX_CARTS +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/sysinfo.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "HPMmap.h" -#include "battle.h" -#include "channel.h" -#include "chat.h" -#include "chrif.h" -#include "clif.h" -#include "duel.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "mail.h" -#include "map.h" -#include "mapreg.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "pc_groups.h" // groupid2name -#include "pet.h" -#include "quest.h" -#include "script.h" -#include "searchstore.h" -#include "skill.h" -#include "status.h" -#include "storage.h" -#include "trade.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/core.h" -#include "../common/malloc.h" -#include "../common/mmo.h" // MAX_CARTS -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/sysinfo.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct atcommand_interface atcommand_s; static char atcmd_output[CHAT_SIZE_MAX]; @@ -209,9 +209,10 @@ ACMD(send) long num; // read message type as hex number (without the 0x) - if(!message || !*message || - !((sscanf(message, "len %x", &type)==1 && (len=1)) - || sscanf(message, "%x", &type)==1) ) { + if (!message || !*message + || !((sscanf(message, "len %x", &type)==1 && (len=1)) + || sscanf(message, "%x", &type)==1) + ) { clif->message(fd, msg_fd(fd,900)); // Usage: clif->message(fd, msg_fd(fd,901)); // @send len <packet hex number> clif->message(fd, msg_fd(fd,902)); // @send <packet hex number> {<value>}* @@ -663,7 +664,7 @@ ACMD(who) { break; } } - clif->colormes(fd, COLOR_DEFAULT, StrBuf->Value(&buf));/** for whatever reason clif->message crashes with some patterns, see bugreport:8186 **/ + clif->messagecolor_self(fd, COLOR_DEFAULT, StrBuf->Value(&buf));/** for whatever reason clif->message crashes with some patterns, see bugreport:8186 **/ StrBuf->Clear(&buf); count++; } @@ -875,12 +876,12 @@ ACMD(guildstorage) if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading) return false; - if (sd->state.storage_flag == 1) { + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { clif->message(fd, msg_fd(fd,250)); return false; } - if (sd->state.storage_flag == 2) { + if (sd->state.storage_flag == STORAGE_FLAG_GUILD) { clif->message(fd, msg_fd(fd,251)); return false; } @@ -1124,7 +1125,7 @@ ACMD(heal) if ( hp < 0 && sp <= 0 ) { status->damage(NULL, &sd->bl, -hp, -sp, 0, 0); - clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, 4, 0); + clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, BDT_ENDURE, 0); clif->message(fd, msg_fd(fd,156)); // HP or/and SP modified. return true; } @@ -1135,7 +1136,7 @@ ACMD(heal) status->heal(&sd->bl, hp, 0, 0); else { status->damage(NULL, &sd->bl, -hp, 0, 0, 0); - clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, 4, 0); + clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, BDT_ENDURE, 0); } } @@ -1344,7 +1345,7 @@ ACMD(itemreset) for (i = 0; i < MAX_INVENTORY; i++) { if (sd->status.inventory[i].amount && sd->status.inventory[i].equip == 0) { - pc->delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_COMMAND); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_COMMAND); } } clif->message(fd, msg_fd(fd,20)); // All of your items have been removed. @@ -1443,7 +1444,7 @@ ACMD(joblevelup) level = sd->status.job_level-1; sd->status.job_level -= (unsigned int)level; if (sd->status.skill_point < level) - pc->resetskill(sd,0); //Reset skills since we need to subtract more points. + pc->resetskill(sd, PCRESETSKILL_NONE); //Reset skills since we need to subtract more points. if (sd->status.skill_point < level) sd->status.skill_point = 0; else @@ -2086,9 +2087,9 @@ ACMD(refine) if (sd->status.inventory[idx].refine != final_refine) { sd->status.inventory[idx].refine = final_refine; current_position = sd->status.inventory[idx].equip; - pc->unequipitem(sd, idx, 3); + pc->unequipitem(sd, idx, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); clif->refine(fd, 0, idx, sd->status.inventory[idx].refine); - clif->delitem(sd, idx, 1, 3); + clif->delitem(sd, idx, 1, DELITEM_MATERIALCHANGE); clif->additem(sd, idx, 1, 0); pc->equipitem(sd, idx, current_position); clif->misceffect(&sd->bl, 3); @@ -2730,7 +2731,7 @@ ACMD(char_block) return false; } - chrif->char_ask_name(sd->status.account_id, atcmd_player_name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block + chrif->char_ask_name(sd->status.account_id, atcmd_player_name, CHAR_ASK_NAME_BLOCK, 0, 0, 0, 0, 0, 0); clif->message(fd, msg_fd(fd,88)); // Character name sent to char-server to ask it. return true; @@ -2826,7 +2827,8 @@ ACMD(char_ban) return false; } - chrif->char_ask_name(sd->status.account_id, atcmd_player_name, !strcmpi(info->command,"charban") ? 6 : 2, year, month, day, hour, minute, second); // type: 2 - ban; 6 - charban + chrif->char_ask_name(sd->status.account_id, atcmd_player_name, + !strcmpi(info->command,"charban") ? CHAR_ASK_NAME_CHARBAN : CHAR_ASK_NAME_BAN, year, month, day, hour, minute, second); clif->message(fd, msg_fd(fd,88)); // Character name sent to char-server to ask it. return true; @@ -2845,7 +2847,7 @@ ACMD(char_unblock) } // send answer to login server via char-server - chrif->char_ask_name(sd->status.account_id, atcmd_player_name, 3, 0, 0, 0, 0, 0, 0); // type: 3 - unblock + chrif->char_ask_name(sd->status.account_id, atcmd_player_name, CHAR_ASK_NAME_UNBLOCK, 0, 0, 0, 0, 0, 0); clif->message(fd, msg_fd(fd,88)); // Character name sent to char-server to ask it. return true; @@ -2864,7 +2866,8 @@ ACMD(char_unban) } // send answer to login server via char-server - chrif->char_ask_name(sd->status.account_id, atcmd_player_name, !strcmpi(info->command,"charunban") ? 7 : 4, 0, 0, 0, 0, 0, 0); // type: 4 - unban account; type 7 - unban character + chrif->char_ask_name(sd->status.account_id, atcmd_player_name, + !strcmpi(info->command,"charunban") ? CHAR_ASK_NAME_CHARUNBAN : CHAR_ASK_NAME_UNBAN, 0, 0, 0, 0, 0, 0); clif->message(fd, msg_fd(fd,88)); // Character name sent to char-server to ask it. return true; @@ -3101,7 +3104,7 @@ ACMD(questskill) return false; } - pc->skill(sd, skill_id, 1, 0); + pc->skill(sd, skill_id, 1, SKILL_GRANT_PERMANENT); clif->message(fd, msg_fd(fd,70)); // You have learned the skill. return true; @@ -5096,7 +5099,7 @@ ACMD(dropall) for (i = 0; i < MAX_INVENTORY; i++) { if (sd->status.inventory[i].amount) { if(sd->status.inventory[i].equip != 0) - pc->unequipitem(sd, i, 3); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); pc->dropitem(sd, i, sd->status.inventory[i].amount); } } @@ -5111,7 +5114,7 @@ ACMD(storeall) { int i; - if (sd->state.storage_flag != 1) { + if (sd->state.storage_flag != STORAGE_FLAG_NORMAL) { //Open storage. if( storage->open(sd) == 1 ) { clif->message(fd, msg_fd(fd,1161)); // You currently cannot open your storage. @@ -5122,7 +5125,7 @@ ACMD(storeall) for (i = 0; i < MAX_INVENTORY; i++) { if (sd->status.inventory[i].amount) { if(sd->status.inventory[i].equip != 0) - pc->unequipitem(sd, i, 3); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); storage->add(sd, i, sd->status.inventory[i].amount); } } @@ -5136,7 +5139,7 @@ ACMD(clearstorage) { int i, j; - if (sd->state.storage_flag == 1) { + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { clif->message(fd, msg_fd(fd,250)); return false; } @@ -5164,12 +5167,12 @@ ACMD(cleargstorage) return false; } - if (sd->state.storage_flag == 1) { + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { clif->message(fd, msg_fd(fd,250)); return false; } - if (sd->state.storage_flag == 2) { + if (sd->state.storage_flag == STORAGE_FLAG_GUILD) { clif->message(fd, msg_fd(fd,251)); return false; } @@ -5200,7 +5203,7 @@ ACMD(clearcart) return false; } - if( sd->state.vending == 1 ) { + if (sd->state.vending) { clif->message(fd, msg_fd(fd,548)); // You can't clean a cart while vending! return false; } @@ -5241,11 +5244,11 @@ ACMD(skillid) { for (data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key)) { int idx = skill->get_index(DB->data2i(data)); - if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill->db[idx].desc, message, skillen) == 0) { - sprintf(atcmd_output, msg_fd(fd,1164), DB->data2i(data), skill->db[idx].desc, key.str); // skill %d: %s (%s) + if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill->dbs->db[idx].desc, message, skillen) == 0) { + sprintf(atcmd_output, msg_fd(fd,1164), DB->data2i(data), skill->dbs->db[idx].desc, key.str); // skill %d: %s (%s) clif->message(fd, atcmd_output); - } else if ( found < MAX_SKILLID_PARTIAL_RESULTS && ( stristr(key.str,message) || stristr(skill->db[idx].desc,message) ) ) { - snprintf(partials[found], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_fd(fd,1164), DB->data2i(data), skill->db[idx].desc, key.str); + } else if ( found < MAX_SKILLID_PARTIAL_RESULTS && ( stristr(key.str,message) || stristr(skill->dbs->db[idx].desc,message) ) ) { + snprintf(partials[found], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_fd(fd,1164), DB->data2i(data), skill->dbs->db[idx].desc, key.str); found++; } } @@ -5326,7 +5329,7 @@ ACMD(displayskill) { } st = status->get_status_data(&sd->bl); tick = timer->gettick(); - clif->skill_damage(&sd->bl,&sd->bl, tick, st->amotion, st->dmotion, 1, 1, skill_id, skill_lv, 5); + clif->skill_damage(&sd->bl,&sd->bl, tick, st->amotion, st->dmotion, 1, 1, skill_id, skill_lv, BDT_SPLASH); clif->skill_nodamage(&sd->bl, &sd->bl, skill_id, skill_lv, 1); clif->skill_poseffect(&sd->bl, skill_id, skill_lv, sd->bl.x, sd->bl.y, tick); return true; @@ -5373,7 +5376,7 @@ ACMD(skilltree) { { if( ent->need[j].id && pc->checkskill(sd,ent->need[j].id) < ent->need[j].lv) { - sprintf(atcmd_output, msg_fd(fd,1170), ent->need[j].lv, skill->db[ent->need[j].id].desc); // Player requires level %d of skill %s. + sprintf(atcmd_output, msg_fd(fd,1170), ent->need[j].lv, skill->dbs->db[ent->need[j].id].desc); // Player requires level %d of skill %s. clif->message(fd, atcmd_output); meets = 0; } @@ -5603,7 +5606,7 @@ ACMD(partyoption) return false; } - option = (config_switch(w1)?1:0)|(config_switch(w2)?2:0); + option = (config_switch(w1)?1:0)|(config_switch(w2)?2:0); // TODO: Add documentation for these values //Change item share type. if (option != p->party.item) @@ -6075,14 +6078,14 @@ ACMD(cleanmap) { } ACMD(cleanarea) { - int x0 = 0, y0 = 0, x1 = 0, y1 = 0; + int x0 = 0, y0 = 0, x1 = 0, y1 = 0, n = 0; - if (!message || !*message || sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) < 1) { + if (!message || !*message || (n=sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1)) < 1) { map->foreachinrange(atcommand->cleanfloor_sub, &sd->bl, AREA_SIZE * 2, BL_ITEM); - } else if (sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) == 1) { - map->foreachinrange(atcommand->cleanfloor_sub, &sd->bl, x0, BL_ITEM); - } else if (sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) == 4) { + } else if (n == 4) { map->foreachinarea(atcommand->cleanfloor_sub, sd->bl.m, x0, y0, x1, y1, BL_ITEM); + } else { + map->foreachinrange(atcommand->cleanfloor_sub, &sd->bl, x0, BL_ITEM); } clif->message(fd, msg_fd(fd,1221)); // All dropped items have been cleaned up. @@ -6244,10 +6247,9 @@ ACMD(users) /*========================================== * *------------------------------------------*/ -ACMD(reset) -{ +ACMD(reset) { pc->resetstate(sd); - pc->resetskill(sd,1); + pc->resetskill(sd, PCRESETSKILL_RESYNC); sprintf(atcmd_output, msg_fd(fd,208), sd->status.name); // '%s' skill and stats points reseted! clif->message(fd, atcmd_output); return true; @@ -6288,9 +6290,9 @@ ACMD(summon) if(!md) return false; - md->master_id=sd->bl.id; - md->special_state.ai=1; - md->deletetimer=timer->add(tick+(duration*60000),mob->timer_delete,md->bl.id,0); + md->master_id = sd->bl.id; + md->special_state.ai = AI_ATTACK; + md->deletetimer = timer->add(tick+(duration*60000),mob->timer_delete,md->bl.id,0); clif->specialeffect(&md->bl,344,AREA); mob->spawn(md); sc_start4(NULL,&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000); @@ -6423,15 +6425,14 @@ ACMD(uptime) * @changesex <sex> * => Changes one's sex. Argument sex can be 0 or 1, m or f, male or female. *------------------------------------------*/ -ACMD(changesex) -{ +ACMD(changesex) { int i; - pc->resetskill(sd,4); + pc->resetskill(sd, PCRESETSKILL_CHSEX); // to avoid any problem with equipment and invalid sex, equipment is unequipped. for( i=0; i<EQI_MAX; i++ ) - if( sd->equip_index[i] >= 0 ) pc->unequipitem(sd, sd->equip_index[i], 3); - chrif->changesex(sd); + if( sd->equip_index[i] >= 0 ) pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); + chrif->changesex(sd, true); return true; } @@ -6745,7 +6746,7 @@ ACMD(showmobs) continue; if( mob_id != -1 && md->class_ != mob_id ) continue; - if( md->special_state.ai || md->master_id ) + if (md->special_state.ai != AI_NONE || md->master_id) continue; // hide slaves and player summoned mobs if( md->spawn_timer != INVALID_TIMER ) continue; // hide mobs waiting for respawn @@ -7804,13 +7805,15 @@ ACMD(cash) if( !battle_config.cashshop_show_points ){ sprintf(output, msg_fd(fd,505), ret, sd->cashPoints); clif_disp_onlyself(sd, output, strlen(output)); + clif->message(fd, output); } } else clif->message(fd, msg_fd(fd,149)); // Unable to decrease the number/value. } else { if( (ret=pc->paycash(sd, -value, 0)) >= 0){ sprintf(output, msg_fd(fd,410), ret, sd->cashPoints); - clif_disp_onlyself(sd, output, strlen(output)); + clif_disp_onlyself(sd, output, strlen(output)); + clif->message(fd, output); } else clif->message(fd, msg_fd(fd,41)); // Unable to decrease the number/value. } @@ -7821,13 +7824,15 @@ ACMD(cash) if( !battle_config.cashshop_show_points ){ sprintf(output, msg_fd(fd,506), ret, sd->kafraPoints); clif_disp_onlyself(sd, output, strlen(output)); + clif->message(fd, output); } } else clif->message(fd, msg_fd(fd,149)); // Unable to decrease the number/value. } else { if( (ret=pc->paycash(sd, -value, -value)) >= 0){ sprintf(output, msg_fd(fd,411), ret, sd->kafraPoints); - clif_disp_onlyself(sd, output, strlen(output)); + clif_disp_onlyself(sd, output, strlen(output)); + clif->message(fd, output); } else clif->message(fd, msg_fd(fd,41)); // Unable to decrease the number/value. } @@ -7940,10 +7945,10 @@ ACMD(feelreset) /*========================================== * AUCTION SYSTEM *------------------------------------------*/ -ACMD(auction) { - - if( !battle_config.feature_auction ) { - clif->colormes(sd->fd,COLOR_RED,msg_fd(fd,1484)); +ACMD(auction) +{ + if (!battle_config.feature_auction) { + clif->messagecolor_self(sd->fd, COLOR_RED, msg_fd(fd,1484)); return false; } @@ -7955,31 +7960,22 @@ ACMD(auction) { /*========================================== * Kill Steal Protection *------------------------------------------*/ -ACMD(ksprotection) -{ +ACMD(ksprotection) { if( sd->state.noks ) { - sd->state.noks = 0; + sd->state.noks = KSPROTECT_NONE; clif->message(fd, msg_fd(fd,1325)); // [ K.S Protection Inactive ] - } - else - { - if( !message || !*message || !strcmpi(message, "party") ) - { // Default is Party - sd->state.noks = 2; - clif->message(fd, msg_fd(fd,1326)); // [ K.S Protection Active - Option: Party ] - } - else if( !strcmpi(message, "self") ) - { - sd->state.noks = 1; - clif->message(fd, msg_fd(fd,1327)); // [ K.S Protection Active - Option: Self ] - } - else if( !strcmpi(message, "guild") ) - { - sd->state.noks = 3; - clif->message(fd, msg_fd(fd,1328)); // [ K.S Protection Active - Option: Guild ] - } - else - clif->message(fd, msg_fd(fd,1329)); // Usage: @noks <self|party|guild> + } else if( !message || !*message || strcmpi(message, "party") == 0 ) { + // Default is Party + sd->state.noks = KSPROTECT_PARTY; + clif->message(fd, msg_fd(fd,1326)); // [ K.S Protection Active - Option: Party ] + } else if( strcmpi(message, "self") == 0 ) { + sd->state.noks = KSPROTECT_SELF; + clif->message(fd, msg_fd(fd,1327)); // [ K.S Protection Active - Option: Self ] + } else if( strcmpi(message, "guild") == 0 ) { + sd->state.noks = KSPROTECT_GUILD; + clif->message(fd, msg_fd(fd,1328)); // [ K.S Protection Active - Option: Guild ] + } else { + clif->message(fd, msg_fd(fd,1329)); // Usage: @noks <self|party|guild> } return true; } @@ -8008,7 +8004,7 @@ ACMD(resetstat) ACMD(resetskill) { - pc->resetskill(sd,1); + pc->resetskill(sd, PCRESETSKILL_RESYNC); sprintf(atcmd_output, msg_fd(fd,206), sd->status.name); clif->message(fd, atcmd_output); return true; @@ -8255,7 +8251,7 @@ ACMD(delitem) { {// delete pet intif->delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); } - pc->delitem(sd, idx, delamount, 0, 0, LOG_TYPE_COMMAND); + pc->delitem(sd, idx, delamount, 0, DELITEM_NORMAL, LOG_TYPE_COMMAND); amount-= delamount; } @@ -8793,13 +8789,7 @@ ACMD(channel) { unsigned short msg_len = 1; msg_len += sprintf(mout, "[ %s list colors ] : %s", command, channel->config->colors_name[k]); - WFIFOHEAD(fd,msg_len + 12); - WFIFOW(fd,0) = 0x2C1; - WFIFOW(fd,2) = msg_len + 12; - WFIFOL(fd,4) = 0; - WFIFOL(fd,8) = channel->config->colors[k]; - safestrncpy((char*)WFIFOP(fd,12), mout, msg_len); - WFIFOSET(fd, msg_len + 12); + clif->messagecolor_self(fd, channel->config->colors[k], mout); } } else { DBIterator *iter = db_iterator(channel->db); @@ -9153,7 +9143,7 @@ ACMD(channel) { return false; } else { channel->set_options(chan, chan->options | k); - sprintf(atcmd_output, msg_fd(fd,1454), opt_str[k],chan->name);//option '%s' is now enabled for channel '%s' + sprintf(atcmd_output, msg_fd(fd,1450), opt_str[k],chan->name);//option '%s' is now enabled for channel '%s' clif->message(fd, atcmd_output); } } else { @@ -9185,13 +9175,7 @@ ACMD(fontcolor) { for( k = 0; k < channel->config->colors_count; k++ ) { msg_len += sprintf(mout, "[ %s ] : %s", command, channel->config->colors_name[k]); - WFIFOHEAD(fd,msg_len + 12); - WFIFOW(fd,0) = 0x2C1; - WFIFOW(fd,2) = msg_len + 12; - WFIFOL(fd,4) = 0; - WFIFOL(fd,8) = channel->config->colors[k]; - safestrncpy((char*)WFIFOP(fd,12), mout, msg_len); - WFIFOSET(fd, msg_len + 12); + clif->messagecolor_self(fd, channel->config->colors[k], mout); } return false; } @@ -9214,13 +9198,8 @@ ACMD(fontcolor) { sd->fontcolor = k + 1; msg_len += sprintf(mout, "Color changed to '%s'", channel->config->colors_name[k]); - WFIFOHEAD(fd,msg_len + 12); - WFIFOW(fd,0) = 0x2C1; - WFIFOW(fd,2) = msg_len + 12; - WFIFOL(fd,4) = 0; - WFIFOL(fd,8) = channel->config->colors[k]; - safestrncpy((char*)WFIFOP(fd,12), mout, msg_len); - WFIFOSET(fd, msg_len + 12); + clif->messagecolor_self(fd, channel->config->colors[k], mout); + return true; } ACMD(searchstore){ @@ -9327,7 +9306,7 @@ ACMD(cddebug) { const struct TimerData *td = timer->get(cd->entry[i]->timer); if( !td || td->func != skill->blockpc_end ) { - clif->messages(fd,"Found invalid entry in slot %d for skill %s",i,skill->db[cd->entry[i]->skidx].name); + clif->messages(fd,"Found invalid entry in slot %d for skill %s",i,skill->dbs->db[cd->entry[i]->skidx].name); sd->blockskill[cd->entry[i]->skidx] = false; } } @@ -9337,7 +9316,7 @@ ACMD(cddebug) { if( !cd || (message && *message && !strcmpi(message,"reset")) ) { for(i = 0; i < MAX_SKILL; i++) { if( sd->blockskill[i] ) { - clif->messages(fd,"Found skill '%s', unblocking...",skill->db[i].name); + clif->messages(fd,"Found skill '%s', unblocking...",skill->dbs->db[i].name); sd->blockskill[i] = false; } } @@ -9959,11 +9938,12 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa } for(i = 0; i < map->list[sd->bl.m].zone->disabled_commands_count; i++) { if( info->func == map->list[sd->bl.m].zone->disabled_commands[i]->cmd ) { - if( pc_get_group_level(sd) < map->list[sd->bl.m].zone->disabled_commands[i]->group_lv ) { - clif->colormes(sd->fd,COLOR_RED,"This command is disabled in this area"); + if (pc_get_group_level(sd) < map->list[sd->bl.m].zone->disabled_commands[i]->group_lv) { + clif->messagecolor_self(sd->fd, COLOR_RED, "This command is disabled in this area"); return true; - } else + } else { break;/* already found the matching command, no need to keep checking -- just go on */ + } } } } @@ -10263,7 +10243,7 @@ void atcommand_doload(void) { void atcommand_expand_message_table(void) { RECREATE(atcommand->msg_table, char **, ++atcommand->max_message_table); - RECREATE(atcommand->msg_table[atcommand->max_message_table - 1], char *, MAX_MSG); + CREATE(atcommand->msg_table[atcommand->max_message_table - 1], char *, MAX_MSG); } void do_init_atcommand(bool minimal) { diff --git a/src/map/atcommand.h b/src/map/atcommand.h index c1f451ad3..88ddde8c2 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -5,9 +5,12 @@ #ifndef MAP_ATCOMMAND_H #define MAP_ATCOMMAND_H -#include "pc_groups.h" -#include "../common/conf.h" -#include "../common/db.h" +#include "map/pc_groups.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/db.h" + +#include <stdarg.h> /** * Declarations diff --git a/src/map/battle.c b/src/map/battle.c index b2ee9cf1d..3575dea6f 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -4,43 +4,43 @@ #define HERCULES_CORE -#include "../config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, HMAP_ZONE_DAMAGE_CAP_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, RE_LVL_DMOD(), RE_LVL_MDMOD(), RE_LVL_TMDMOD(), RE_SKILL_REDUCTION(), SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, STATS_OPT_OUT +#include "config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, HMAP_ZONE_DAMAGE_CAP_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, RE_LVL_DMOD(), RE_LVL_MDMOD(), RE_LVL_TMDMOD(), RE_SKILL_REDUCTION(), SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, STATS_OPT_OUT #include "battle.h" +#include "map/battleground.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/itemdb.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/skill.h" +#include "map/status.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/sysinfo.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "battleground.h" -#include "chrif.h" -#include "clif.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "itemdb.h" -#include "map.h" -#include "mercenary.h" -#include "mob.h" -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "skill.h" -#include "status.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/sysinfo.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct Battle_Config battle_config; struct battle_interface battle_s; @@ -300,10 +300,10 @@ int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct int battle_attr_ratio(int atk_elem,int def_type, int def_lv) { - if (atk_elem < 0 || atk_elem >= ELE_MAX) + if (atk_elem < ELE_NEUTRAL || atk_elem >= ELE_MAX) return 100; - if (def_type < 0 || def_type >= ELE_MAX || def_lv < 1 || def_lv > 4) + if (def_type < ELE_NEUTRAL || def_type >= ELE_MAX || def_lv < 1 || def_lv > 4) return 100; return battle->attr_fix_table[def_lv-1][atk_elem][def_type]; @@ -322,10 +322,10 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d if (src) sc = status->get_sc(src); if (target) tsc = status->get_sc(target); - if (atk_elem < 0 || atk_elem >= ELE_MAX) + if (atk_elem < ELE_NEUTRAL || atk_elem >= ELE_MAX) atk_elem = rnd()%ELE_MAX; - if (def_type < 0 || def_type >= ELE_MAX || + if (def_type < ELE_NEUTRAL || def_type >= ELE_MAX || def_lv < 1 || def_lv > 4) { ShowError("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",atk_elem,def_type,def_lv); return damage; @@ -407,6 +407,8 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d else return damage + (damage * (ratio - 100) / 100); } + +//FIXME: Missing documentation for flag, flag2 int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, struct weapon_atk *watk, int nk, bool n_ele, short s_ele, short s_ele_, int size, int type, int flag, int flag2){ // [malufett] #ifdef RENEWAL int64 damage, eatk = 0; @@ -421,41 +423,47 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u damage = status->get_weapon_atk(src, watk, flag); - if( sd ){ - if( type == EQI_HAND_R ) - damage = battle->calc_sizefix(sd, damage, EQI_HAND_R, size, flag&8); + if ( sd ) { + if ( type == EQI_HAND_R ) + damage = battle->calc_sizefix(sd, damage, EQI_HAND_R, size, flag & 8); else - damage = battle->calc_sizefix(sd, damage, EQI_HAND_L, size, flag&8); + damage = battle->calc_sizefix(sd, damage, EQI_HAND_L, size, flag & 8); - if( flag&2 && sd->bonus.arrow_atk ) + if ( flag & 2 && sd->bonus.arrow_atk && skill_id != GN_CARTCANNON ) damage += sd->bonus.arrow_atk; - if( sd->battle_status.equip_atk != 0 ) + if ( sd->battle_status.equip_atk != 0 ) eatk = sd->base_status.equip_atk; + + if ( sd->bonus.atk_rate ) + damage += damage * sd->bonus.atk_rate / 100; } if ( skill_id == TF_POISON ) eatk += 15 * skill_lv; + if ( skill_id != ASC_METEORASSAULT ) { + if ( sc && sc->data[SC_SUB_WEAPONPROPERTY] ) // Temporary. [malufett] + damage += damage * sc->data[SC_SUB_WEAPONPROPERTY]->val2 / 100; + } + if( sc && sc->count ){ if( sc->data[SC_ZENKAI] && watk->ele == sc->data[SC_ZENKAI]->val2 ) eatk += 200; + } + #ifdef RENEWAL_EDP - if( sc->data[SC_EDP] && skill_id != AS_GRIMTOOTH && skill_id != AS_VENOMKNIFE && skill_id != ASC_BREAKER ){ - eatk = eatk * (sc->data[SC_EDP]->val4 / 100 - 1); - damage = damage * (sc->data[SC_EDP]->val4 / 100); - } + if ( sc && sc->data[SC_EDP] && skill_id != AS_GRIMTOOTH && skill_id != AS_VENOMKNIFE && skill_id != ASC_BREAKER ) { + struct status_data *tstatus; + tstatus = status->get_status_data(bl); + eatk += damage * 0x19 * battle->attr_fix_table[tstatus->ele_lv - 1][ELE_POISON][tstatus->def_ele] / 10000; + damage += (eatk + damage) * sc->data[SC_EDP]->val3 / 100 + eatk; + } else /* fall through */ #endif - } - - if( skill_id != ASC_METEORASSAULT ){ - if( sc && sc->data[SC_SUB_WEAPONPROPERTY] ) // Temporary. [malufett] - damage += damage * sc->data[SC_SUB_WEAPONPROPERTY]->val2 / 100; - } - - // Temporary. [malufett] - damage = battle->calc_elefix(src, bl, skill_id, skill_lv, damage + eatk, nk, n_ele, s_ele, s_ele_, type == EQI_HAND_L, flag); - + damage += eatk; + + damage = battle->calc_elefix(src, bl, skill_id, skill_lv, damage, nk, n_ele, s_ele, s_ele_, type == EQI_HAND_L, flag); + /** * In RE Shield Boomerang takes weapon element only for damage calculation, * - resist calculation is always against neutral @@ -479,7 +487,7 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u * it calculates nothing extra fancy, is needed for magnum breaks WATK_ELEMENT bonus. [Skotlex] *------------------------------------------ * Pass damage2 as NULL to not calc it. - * Flag values: + * Flag values: // TODO: Check whether these values are correct (the flag parameter seems to be passed through to other functions), and replace them with an enum. * &1: Critical hit * &2: Arrow attack * &4: Skill is Magic Crasher @@ -487,11 +495,23 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u *&16: Arrow attack but BOW, REVOLVER, RIFLE, SHOTGUN, GATLING or GRENADE type weapon not equipped (i.e. shuriken, kunai and venom knives not affected by DEX) */ /* 'battle_calc_base_damage' is used on renewal, 'battle_calc_base_damage2' otherwise. */ +// FIXME: Missing documentation for flag2 int64 battle_calc_base_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2) { int64 damage; struct status_data *st = status->get_status_data(src); struct status_change *sc = status->get_sc(src); - + + if ( !skill_id ) { + s_ele = st->rhw.ele; + s_ele_ = st->lhw.ele; + if ( src->type == BL_PC ) { + if ( ((TBL_PC*)src)->charm_type != CHARM_TYPE_NONE && ((TBL_PC*)src)->charm_count >= MAX_SPIRITCHARM ) { + s_ele = s_ele_ = ((TBL_PC*)src)->charm_type; + } + if ( flag & 2 && ((TBL_PC*)src)->bonus.arrow_ele ) + s_ele = ((TBL_PC*)src)->bonus.arrow_ele; + } + } if (src->type == BL_PC) { int64 batk; // Property from mild wind bypasses it @@ -599,6 +619,7 @@ int64 battle_calc_sizefix(struct map_session_data *sd, int64 damage, int type, i /*========================================== * Passive skill damages increases *------------------------------------------*/ +// FIXME: type is undocumented int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,int64 dmg,int type) { int64 damage; struct status_data *st = status->get_status_data(target); @@ -849,6 +870,7 @@ void battle_calc_masteryfix_unknown(struct block_list *src, struct block_list *t /*========================================== * Elemental attribute fix. *------------------------------------------*/ +// FIXME: flag is undocumented int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag){ struct status_data *tstatus; @@ -869,8 +891,6 @@ int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); if( skill_id == NC_ARMSCANNON ) damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); - if( skill_id == GN_CARTCANNON ) - damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); if( skill_id == GS_GROUNDDRIFT ) //Additional 50*lv Neutral damage. damage += battle->attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); } @@ -896,15 +916,53 @@ int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint #endif return damage; } +int64 battle_calc_cardfix2(struct block_list *src, struct block_list *bl, int64 damage, int s_ele, int nk, int flag) { +#ifdef RENEWAL + struct map_session_data *tsd; + struct status_data *sstatus; + + if ( !damage ) + return 0; + + nullpo_ret(bl); + nullpo_ret(src); + + tsd = BL_CAST(BL_PC, bl); + sstatus = status->get_status_data(src); + + if ( tsd ) { + if ( !(nk&NK_NO_CARDFIX_DEF) ) { + // RaceAddTolerance + damage -= damage * tsd->race_tolerance[sstatus->race] / 100; + damage -= damage * tsd->race_tolerance[is_boss(src) ? RC_BOSS : RC_NONBOSS] / 100; + if ( flag&BF_SHORT ) + damage -= damage * tsd->bonus.near_attack_def_rate / 100; + else // SubRangeAttackDamage or bLongAtkDef + damage -= damage * tsd->bonus.long_attack_def_rate / 100; + } + if ( flag&BF_LONG && tsd->sc.data[SC_GS_ADJUSTMENT] ) { + damage -= 20 * damage / 100; + } + } +#endif + return damage; +} /*========================================== * Calculates card bonuses damage adjustments. * cflag(cardfix flag): * &1 - calc for left hand. * &2 - atker side cardfix(BF_WEAPON) otherwise target side(BF_WEAPON). *------------------------------------------*/ +// FIXME: wflag is undocumented int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int cflag, int wflag){ struct map_session_data *sd, *tsd; - short cardfix = 1000, t_class, s_class, s_race2, t_race2; + short cardfix = +#ifdef RENEWAL + 100; +#else + 1000; +#endif + short t_class, s_class, s_race2, t_race2; struct status_data *sstatus, *tstatus; int i; @@ -937,8 +995,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ break; } } - if (cardfix != 1000) - damage = damage * cardfix / 1000; } if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) @@ -961,8 +1017,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ cardfix = cardfix * (100 - tsd->subrace2[s_race2]) / 100; cardfix = cardfix * (100 - tsd->subrace[sstatus->race]) / 100; cardfix = cardfix * (100 - tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS]) / 100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix = cardfix * (100-tsd->subrace[RC_NONDEMIHUMAN]) / 100; for(i=0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate;i++) { if(tsd->add_mdef[i].class_ == s_class) { @@ -982,16 +1036,25 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ if( tsd->sc.data[SC_PROTECT_MDEF] ) cardfix = cardfix * ( 100 - tsd->sc.data[SC_PROTECT_MDEF]->val1 ) / 100; - - if( cardfix != 1000 ) - damage = damage * cardfix / 1000; } +#ifdef RENEWAL + if ( cardfix != 100 ) + damage += damage * (cardfix - 100) / 100; +#else + if ( cardfix != 1000 ) + damage = damage * cardfix / 1000; +#endif break; case BF_WEAPON: t_race2 = status->get_race2(target); if( cflag&2 ){ if( sd && !(nk&NK_NO_CARDFIX_ATK) ){ - short cardfix_ = 1000; + short cardfix_ = +#ifdef RENEWAL + 100; +#else + 1000; +#endif if( sd->state.arrow_atk ){ cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->arrow_addrace[tstatus->race]) / 100; if( !(nk&NK_NO_ELEFIX) ){ @@ -1009,8 +1072,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ cardfix = cardfix * (100 + sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size]) / 100; cardfix = cardfix * (100 + sd->right_weapon.addrace2[t_race2]) / 100; cardfix = cardfix * (100 + sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS] + sd->arrow_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix = cardfix * (100 + sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->arrow_addrace[RC_NONDEMIHUMAN]) / 100; }else{ // Melee attack if( !battle_config.left_cardfix_to_right ){ cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100; @@ -1029,8 +1090,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ cardfix = cardfix * (100+sd->right_weapon.addsize[tstatus->size]) / 100; cardfix = cardfix * (100+sd->right_weapon.addrace2[t_race2]) / 100; cardfix = cardfix * (100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix = cardfix * (100 + sd->right_weapon.addrace[RC_NONDEMIHUMAN]) / 100; if( cflag&1 ){ cardfix_ = cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100; @@ -1049,8 +1108,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ cardfix_ = cardfix_ * (100+sd->left_weapon.addsize[tstatus->size]) / 100; cardfix_ = cardfix_ * (100+sd->left_weapon.addrace2[t_race2]) / 100; cardfix_ = cardfix_ * (100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix_ = cardfix_*(100+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; } }else{ int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele]; @@ -1076,8 +1133,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ cardfix = cardfix * (100 + sd->right_weapon.addsize[tstatus->size] + sd->left_weapon.addsize[tstatus->size])/100; cardfix = cardfix * (100 + sd->right_weapon.addrace2[t_race2] + sd->left_weapon.addrace2[t_race2])/100; cardfix = cardfix * (100 + sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS] + sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix = cardfix * (100+sd->right_weapon.addrace[RC_NONDEMIHUMAN] + sd->left_weapon.addrace[RC_NONDEMIHUMAN]) / 100; } } @@ -1099,11 +1154,16 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ #ifndef RENEWAL if( wflag&BF_LONG ) cardfix = cardfix * (100 + sd->bonus.long_attack_atk_rate) / 100; -#endif if( (cflag&1) && cardfix_ != 1000 ) damage = damage * cardfix_ / 1000; else if( cardfix != 1000 ) damage = damage * cardfix / 1000; +#else + if ( (cflag & 1) && cardfix_ != 100 ) + damage += damage * (cardfix - 100) / 100; + else if ( cardfix != 100 ) + damage += damage * (cardfix - 100) / 100; +#endif } }else{ // Target side @@ -1137,8 +1197,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ cardfix = cardfix * (100-tsd->subrace2[s_race2]) / 100; cardfix = cardfix * (100-tsd->subrace[sstatus->race]) / 100; cardfix = cardfix * (100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS]) / 100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix = cardfix * (100-tsd->subrace[RC_NONDEMIHUMAN]) / 100; for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++ ){ if( tsd->add_def[i].class_ == s_class ) @@ -1147,52 +1205,59 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ break; } } - +#ifndef RENEWAL if( wflag&BF_SHORT ) cardfix = cardfix * (100 - tsd->bonus.near_attack_def_rate) / 100; else // BF_LONG (there's no other choice) cardfix = cardfix * (100 - tsd->bonus.long_attack_def_rate) / 100; - +#endif if( tsd->sc.data[SC_PROTECT_DEF] ) cardfix = cardfix * (100 - tsd->sc.data[SC_PROTECT_DEF]->val1) / 100; - +#ifdef RENEWAL + if ( cardfix != 100 ) + damage += damage * (cardfix - 100) / 100; +#else if( cardfix != 1000 ) damage = damage * cardfix / 1000; +#endif } } break; case BF_MISC: - if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){ - // misc damage reduction from equipment - if (!(nk&NK_NO_ELEFIX)) + if ( tsd && !(nk&NK_NO_CARDFIX_DEF) ) { + // misc damage reduction from equipment +#ifndef RENEWAL + if ( !(nk&NK_NO_ELEFIX) ) { int ele_fix = tsd->subele[s_ele]; for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) { if(tsd->subele2[i].ele != s_ele) continue; if(!(tsd->subele2[i].flag&wflag&BF_WEAPONMASK && - tsd->subele2[i].flag&wflag&BF_RANGEMASK && - tsd->subele2[i].flag&wflag&BF_SKILLMASK)) + tsd->subele2[i].flag&wflag&BF_RANGEMASK && + tsd->subele2[i].flag&wflag&BF_SKILLMASK)) continue; ele_fix += tsd->subele2[i].rate; } cardfix = cardfix * (100 - ele_fix) / 100; } - cardfix = cardfix*(100-tsd->subsize[sstatus->size]) / 100; - cardfix = cardfix*(100-tsd->subrace2[s_race2]) / 100; cardfix = cardfix*(100-tsd->subrace[sstatus->race]) / 100; cardfix = cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS]) / 100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix = cardfix * (100 - tsd->subrace[RC_NONDEMIHUMAN]) / 100; - - cardfix = cardfix * ( 100 - tsd->bonus.misc_def_rate ) / 100; if( wflag&BF_SHORT ) cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; else // BF_LONG (there's no other choice) cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; - - if (cardfix != 1000) +#endif + cardfix = cardfix*(100 - tsd->subsize[sstatus->size]) / 100; + cardfix = cardfix*(100 - tsd->subrace2[s_race2]) / 100; + cardfix = cardfix * (100 - tsd->bonus.misc_def_rate) / 100; +#ifdef RENEWAL + if ( cardfix != 100 ) + damage += damage * (cardfix - 100) / 100; +#else + if ( cardfix != 1000 ) damage = damage * cardfix / 1000; +#endif } break; } @@ -1207,6 +1272,7 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ * &2 - pdef(Pierce defense) * &4 - tdef(Total defense reduction) *------------------------------------------*/ +// TODO: Add an enum for flag int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int flag, int pdef){ struct status_data *sstatus, *tstatus; struct map_session_data *sd, *tsd; @@ -1244,21 +1310,26 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_ #endif if ( sd ) { + if ( sd->charm_type == CHARM_TYPE_LAND && sd->charm_count > 0 ) // hidden from status window + def1 += 10 * def1 * sd->charm_count / 100; + i = sd->ignore_def[is_boss(target) ? RC_BOSS : RC_NONBOSS]; i += sd->ignore_def[tstatus->race]; if ( i ) { if ( i > 100 ) i = 100; def1 -= def1 * i / 100; +#ifndef RENEWAL def2 -= def2 * i / 100; +#endif } - if (sd->charm_type == CHARM_TYPE_LAND && sd->charm_count > 0 ) // hidden from status window - def1 += 10 * def1 * sd->charm_count / 100; } if( sc && sc->data[SC_EXPIATIO] ){ i = 5 * sc->data[SC_EXPIATIO]->val1; // 5% per level def1 -= def1 * i / 100; +#ifndef RENEWAL def2 -= def2 * i / 100; +#endif } if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) { @@ -1275,7 +1346,9 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_ def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; } } +#ifndef RENEWAL if(skill_id == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex] +#endif if(def2 < 1) def2 = 1; } //Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def @@ -1403,6 +1476,7 @@ int battle_calc_chorusbonus(struct map_session_data *sd) { return members - 2; // Effect bonus from additional Minstrel's/Wanderer's if not above the max possible } +// FIXME: flag is undocumented int battle_calc_skillratio(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int skillratio, int flag){ int i; struct status_change *sc, *tsc; @@ -1927,7 +2001,11 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block skillratio += 20 * skill_lv; break; case AM_ACIDTERROR: +#ifdef RENEWAL + skillratio += 80 * skill_lv + 100; +#else skillratio += 40 * skill_lv; +#endif break; case MO_FINGEROFFENSIVE: skillratio+= 50 * skill_lv; @@ -1935,8 +2013,8 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block case MO_INVESTIGATE: skillratio += 75 * skill_lv; break; - #ifndef RENEWAL case MO_EXTREMITYFIST: + #ifndef RENEWAL { //Overflow check. [Skotlex] unsigned int ratio = skillratio + 100*(8 + st->sp/10); @@ -1944,8 +2022,8 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block if (ratio > 60000) ratio = 60000; //We leave some room here in case skillratio gets further increased. skillratio = (unsigned short)ratio; } +#endif break; - #endif case MO_TRIPLEATTACK: skillratio += 20 * skill_lv; break; @@ -2050,14 +2128,11 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block case GS_TRACKING: skillratio += 100 * (skill_lv+1); break; +#ifndef RENEWAL case GS_PIERCINGSHOT: -#ifdef RENEWAL - if( sd && sd->weapontype1 == W_RIFLE ) - skillratio += 50 + 30 * skill_lv; - else -#endif skillratio += 20 * skill_lv; break; +#endif case GS_RAPIDSHOWER: skillratio += 10 * skill_lv; break; @@ -2456,7 +2531,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block } break; case GN_CARTCANNON: - skillratio = 50 * (sd ? pc->checkskill(sd, GN_REMODELING_CART) : 5) * (st->int_ / 40) + 60 * skill_lv; + skillratio += -100 + (int)(50.0f * (sd ? pc->checkskill(sd, GN_REMODELING_CART) : 5) * (st->int_ / 40.0f) + 60.0f * skill_lv); break; case GN_SPORE_EXPLOSION: skillratio = 100 * skill_lv + (200 + st->int_) * status->get_lv(src) / 100; @@ -2705,6 +2780,8 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam group->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX); } else skill->del_unitgroup(group,ALC_MARK); + if (--group->val3<=0) + skill->del_unitgroup(group,ALC_MARK); #else if (--group->val2<=0) skill->del_unitgroup(group,ALC_MARK); @@ -2920,11 +2997,11 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if(sc->data[SC_DEFENDER] && ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON) || skill_id == CR_ACIDDEMONSTRATION)) damage = damage * ( 100 - sc->data[SC_DEFENDER]->val2 ) / 100; - +#ifndef RENEWAL if(sc->data[SC_GS_ADJUSTMENT] && (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) damage -= damage * 20 / 100; - +#endif if(sc->data[SC_FOGWALL]) { if(flag&BF_SKILL) { //25% reduction if ( !(skill->get_inf(skill_id)&INF_GROUND_SKILL) && !(skill->get_nk(skill_id)&NK_SPLASH) ) @@ -3076,28 +3153,31 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) ) status->change_spread(bl, src); // Deadly infect attacked side + + if ( sd && damage > 0 && (sce = sc->data[SC_GENTLETOUCH_ENERGYGAIN]) ) { + if ( rnd() % 100 < sce->val2 ) + pc->addspiritball(sd, skill->get_time(MO_CALLSPIRITS, 1), pc->getmaxspiritball(sd, 0)); + } } //SC effects from caster side. - sc = status->get_sc(src); - - if (sc && sc->count) { - if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) + if (tsc && tsc->count) { + if( tsc->data[SC_INVINCIBLE] && !tsc->data[SC_INVINCIBLEOFF] ) damage += damage * 75 / 100; // [Epoque] if (bl->type == BL_MOB) { int i; - if ( ((sce=sc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) || - ((sce=sc->data[SC_MANU_MATK]) && (flag&BF_MAGIC)) + if ( ((sce=tsc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) || + ((sce=tsc->data[SC_MANU_MATK]) && (flag&BF_MAGIC)) ) for (i=0;ARRAYLENGTH(mob->manuk)>i;i++) if (((TBL_MOB*)bl)->class_==mob->manuk[i]) { damage += damage * sce->val1 / 100; break; } - if ( ((sce=sc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) || - ((sce=sc->data[SC_SPL_MATK]) && (flag&BF_MAGIC)) + if ( ((sce=tsc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) || + ((sce=tsc->data[SC_SPL_MATK]) && (flag&BF_MAGIC)) ) for (i=0;ARRAYLENGTH(mob->splendide)>i;i++) if (((TBL_MOB*)bl)->class_==mob->splendide[i]) { @@ -3114,14 +3194,19 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam sc_start(src,bl,tsc->data[SC_POISONINGWEAPON]->val2,rate,tsc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000); } } - if( sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) ) + if( tsc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * tsc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) ) status->change_spread(src, bl); - if (sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 1 && damage > 0) + if (tsc->data[SC_SHIELDSPELL_REF] && tsc->data[SC_SHIELDSPELL_REF]->val1 == 1 && damage > 0) skill->break_equip(bl,EQP_ARMOR,10000,BCT_ENEMY ); - if (sc->data[SC_STYLE_CHANGE] && rnd()%2) { + if (tsc->data[SC_STYLE_CHANGE] && rnd()%2) { TBL_HOM *hd = BL_CAST(BL_HOM,bl); if (hd) homun->addspiritball(hd, 10); } + if ( src->type == BL_PC && damage > 0 && (sce = tsc->data[SC_GENTLETOUCH_ENERGYGAIN]) ) { + struct map_session_data *tsd = (struct map_session_data *)src; + if ( tsd && rnd() % 100 < sce->val2 ) + pc->addspiritball(tsd, skill->get_time(MO_CALLSPIRITS, 1), pc->getmaxspiritball(tsd, 0)); + } } /* no data claims these settings affect anything other than players */ if( damage && sd && bl->type == BL_PC ) { @@ -3191,6 +3276,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam /*========================================== * Calculates BG related damage adjustments. *------------------------------------------*/ +// FIXME: flag is undocumented int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag) { if( !damage ) @@ -3209,6 +3295,7 @@ int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64 /*========================================== * Calculates GVG related damage adjustments. *------------------------------------------*/ +// FIXME: flag is undocumented int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64 damage,int div_,uint16 skill_id,uint16 skill_lv,int flag) { struct mob_data* md = BL_CAST(BL_MOB, bl); int class_ = status->get_class(bl); @@ -3285,13 +3372,13 @@ void battle_consume_ammo(TBL_PC*sd, int skill_id, int lv) { if (!battle_config.arrow_decrement) return; - if (skill_id) { + if (skill_id && lv) { qty = skill->get_ammo_qty(skill_id, lv); if (!qty) qty = 1; } if(sd->equip_index[EQI_AMMO]>=0) //Qty check should have been done in skill_check_condition - pc->delitem(sd,sd->equip_index[EQI_AMMO],qty,0,1,LOG_TYPE_CONSUME); + pc->delitem(sd, sd->equip_index[EQI_AMMO], qty, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); sd->state.arrow_atk = 0; } @@ -3345,6 +3432,7 @@ int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) { /*========================================== * battle_calc_magic_attack [DracoRPG] *------------------------------------------*/ +// FIXME: mflag is undocumented struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) { int nk; short s_ele = 0; @@ -3500,7 +3588,10 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list break; default: { MATK_ADD( status->get_matk(src, 2) ); - +#ifdef RENEWAL + ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); + ad.damage = battle->calc_cardfix2(src, target, ad.damage, s_ele, nk, ad.flag); +#endif if (nk&NK_SPLASHSPLIT) { // Divide MATK in case of multiple targets skill if(mflag>0) ad.damage/= mflag; @@ -3520,7 +3611,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list skillratio = sc->data[SC_SPELLFIST]->val2 * 50 + sc->data[SC_SPELLFIST]->val4 * 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech] ad.div_ = 1;// ad mods, to make it work similar to regular hits [Xazax] ad.flag = BF_WEAPON|BF_SHORT; - ad.type = 0; + ad.type = BDT_NORMAL; } /* Fall through */ default: @@ -3536,7 +3627,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list } } #ifndef HMAP_ZONE_DAMAGE_CAP_TYPE - if( target && skill_id ) { + if (skill_id) { for(i = 0; i < map->list[target->m].zone->capped_skills_count; i++) { if( skill_id == map->list[target->m].zone->capped_skills[i]->nameid && (map->list[target->m].zone->capped_skills[i]->type & target->type) ) { if( target->type == BL_MOB && map->list[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { @@ -3554,9 +3645,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list } } #endif -#ifdef RENEWAL - ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); -#endif if(sd) { uint16 rskill;/* redirect skill */ //Damage bonuses @@ -3671,6 +3759,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list /*========================================== * Calculate Misc damage for skill_id *------------------------------------------*/ +// FIXME: mflag is undocumented struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) { int temp; short i, nk; @@ -3789,7 +3878,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * short tdef = status->get_total_def(target); short tmdef = status->get_total_mdef(target); int targetVit = min(120, status_get_vit(target)); - short totaldef = (tmdef + tdef - ((uint64)(tmdef + tdef) >> 32)) >> 1; + short totaldef = (tmdef + tdef - ((uint64)(tmdef + tdef) >> 32)) >> 1; // FIXME: What's the >> 32 supposed to do here? tmdef and tdef are both 16-bit... matk = battle->calc_magic_attack(src, target, skill_id, skill_lv, mflag).damage; atk = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, false, s_ele, ELE_NEUTRAL, EQI_HAND_R, (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), md.flag); @@ -3866,10 +3955,11 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * int ratio = 300 + 50 * skill_lv; int64 matk = battle->calc_magic_attack(src, target, skill_id, skill_lv, mflag).damage; short totaldef = status->get_total_def(target) + status->get_total_mdef(target); - int64 atk = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, false, s_ele, ELE_NEUTRAL, EQI_HAND_R, (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), md.flag); - + int64 atk = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, false, s_ele, ELE_NEUTRAL, EQI_HAND_R, (sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0), md.flag); +#ifdef RENEWAL_EDP if( sc && sc->data[SC_EDP] ) ratio >>= 1; +#endif md.damage = (matk + atk) * ratio / 100; md.damage -= totaldef; #endif @@ -3895,7 +3985,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * case RA_CLUSTERBOMB: case RA_FIRINGTRAP: case RA_ICEBOUNDTRAP: - md.damage = skill_lv * sstatus->dex + sstatus->int_ * 5 ; + md.damage = (int64)skill_lv * sstatus->dex + sstatus->int_ * 5 ; RE_LVL_TMDMOD(); if(sd) { @@ -3909,7 +3999,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * break; case WM_SOUND_OF_DESTRUCTION: - md.damage = 1000 * skill_lv + sstatus->int_ * (sd ? pc->checkskill(sd,WM_LESSON) : 10); + md.damage = 1000 * (int64)skill_lv + sstatus->int_ * (sd ? pc->checkskill(sd,WM_LESSON) : 10); md.damage += md.damage * 10 * battle->calc_chorusbonus(sd) / 100; break; /** @@ -4011,7 +4101,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * } } #ifndef HMAP_ZONE_DAMAGE_CAP_TYPE - if( target && skill_id ) { + if (skill_id) { for(i = 0; i < map->list[target->m].zone->capped_skills_count; i++) { if( skill_id == map->list[target->m].zone->capped_skills[i]->nameid && (map->list[target->m].zone->capped_skills[i]->type & target->type) ) { if( target->type == BL_MOB && map->list[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { @@ -4030,6 +4120,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * } #endif md.damage = battle->calc_cardfix(BF_MISC, src, target, nk, s_ele, 0, md.damage, 0, md.flag); + md.damage = battle->calc_cardfix2(src, target, md.damage, s_ele, nk, md.flag); if(skill_id){ uint16 rskill;/* redirect skill id */ switch(skill_id){ @@ -4100,6 +4191,7 @@ void battle_calc_misc_attack_unknown(struct block_list *src, struct block_list * /*========================================== * battle_calc_weapon_attack (by Skotlex) *------------------------------------------*/ +// FIXME: wflag is undocumented struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag) { unsigned int skillratio = 100; //Skill dmg modifiers. @@ -4128,6 +4220,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list unsigned weapon : 1; ///< It's a weapon attack (consider VVS, and all that) #ifdef RENEWAL unsigned tdef : 1; ///< Total defense reduction + unsigned distinct : 1; ///< Has its own battle calc formula #endif } flag; @@ -4149,13 +4242,13 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list flag.infdef = 1; // Reverberation takes 1 damage //Initial Values - wd.type=0; //Normal attack - wd.div_=skill_id?skill->get_num(skill_id,skill_lv):1; + wd.type = BDT_NORMAL; + wd.div_ = skill_id ? skill->get_num(skill_id,skill_lv) : 1; wd.amotion=(skill_id && skill->get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills. if(skill_id == KN_AUTOCOUNTER) wd.amotion >>= 1; wd.dmotion=tstatus->dmotion; - wd.blewcount=skill->get_blewcount(skill_id,skill_lv); + wd.blewcount = skill_id ? skill->get_blewcount(skill_id,skill_lv) : 0; wd.flag = BF_WEAPON; //Initial Flag wd.flag |= (skill_id||wflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish] wd.dmg_lv=ATK_DEF; //This assumption simplifies the assignation later @@ -4216,7 +4309,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list case TF_DOUBLE: //For NPC used skill. case GS_CHAINACTION: - wd.type = 0x08; + wd.type = BDT_MULTIHIT; break; case GS_GROUNDDRIFT: @@ -4255,13 +4348,28 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if( tsc && (tsc->data[SC_WUGBITE] || tsc->data[SC_ANKLESNARE] || tsc->data[SC_ELECTRICSHOCKER]) ) wd.div_ = tstatus->size + 2 + ( (rnd()%100 < 50-tstatus->size*10) ? 1 : 0 ); break; + + case NPC_EARTHQUAKE: + wd.flag = (wd.flag&~(BF_WEAPON)) | BF_MAGIC; + break; #ifdef RENEWAL + case MO_EXTREMITYFIST: + case GS_PIERCINGSHOT: + case AM_ACIDTERROR: + case AM_DEMONSTRATION: + case NJ_ISSEN: + case PA_SACRIFICE: + flag.distinct = 1; + break; + case GN_CARTCANNON: case PA_SHIELDCHAIN: - case NJ_KUNAI: - case HW_MAGICCRASHER: - case NJ_SYURIKEN: case GS_MAGICALBULLET: + case NJ_SYURIKEN: case KO_BAKURETSU: + flag.distinct = 1; + /* Fall through */ + case NJ_KUNAI: + case HW_MAGICCRASHER: flag.tdef = 1; break; #endif @@ -4270,15 +4378,15 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list wd.flag |= flag.arrow?BF_LONG:BF_SHORT; if ((!skill_id || skill_id == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2) { //Check for Lucky Dodge - wd.type=0x0b; + wd.type = BDT_PDODGE; wd.dmg_lv=ATK_LUCKY; if (wd.div_ < 0) wd.div_*=-1; return wd; } - s_ele = s_ele_ = skill->get_ele(skill_id, skill_lv); - if( !skill_id || s_ele == -1 ) - { //Take weapon's element + s_ele = s_ele_ = skill_id ? skill->get_ele(skill_id, skill_lv) : -1; + if (s_ele == -1) { + //Take weapon's element s_ele = sstatus->rhw.ele; s_ele_ = sstatus->lhw.ele; if (sd && sd->charm_type != CHARM_TYPE_NONE && sd->charm_count >= MAX_SPIRITCHARM) { @@ -4289,13 +4397,14 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list s_ele = sd->bonus.arrow_ele; if( battle_config.attack_attr_none&src->type ) n_ele = true; //Weapon's element is "not elemental" - } - else if( s_ele == -2 ) //Use enchantment's element + } else if (s_ele == -2) { + //Use enchantment's element s_ele = s_ele_ = status_get_attack_sc_element(src,sc); - else if( s_ele == -3 ) //Use random element + } else if (s_ele == -3) { + //Use random element s_ele = s_ele_ = rnd()%ELE_MAX; - switch( skill_id ) - { + } + switch (skill_id) { case GS_GROUNDDRIFT: s_ele = s_ele_ = wflag; //element comes in flag. break; @@ -4337,13 +4446,13 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if( rnd()%100 < ( 5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sc && sc->data[SC_KAGEMUSYA]?sc->data[SC_KAGEMUSYA]->val1*3:sd->bonus.double_rate ) ) { wd.div_ = skill->get_num(TF_DOUBLE,skill_lv?skill_lv:1); - wd.type = 0x08; + wd.type = BDT_MULTIHIT; } } else if( sd->weapontype1 == W_REVOLVER && (skill_lv = pc->checkskill(sd,GS_CHAINACTION)) > 0 && rnd()%100 < 5*skill_lv ) { wd.div_ = skill->get_num(GS_CHAINACTION,skill_lv); - wd.type = 0x08; + wd.type = BDT_MULTIHIT; } else if(sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW && (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1){ @@ -4374,13 +4483,13 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if ( wd.div_ > 1 ) { wd.div_ = min(wd.div_, sd->status.inventory[i].amount); sc->data[SC_FEARBREEZE]->val4 = wd.div_ - 1; - wd.type = 0x08; + wd.type = BDT_MULTIHIT; } } } //Check for critical - if( !flag.cri && !(wd.type&0x08) && sstatus->cri && + if( !flag.cri && wd.type != BDT_MULTIHIT && sstatus->cri && (!skill_id || skill_id == KN_AUTOCOUNTER || skill_id == SN_SHARPSHOOTING || skill_id == MA_SHARPSHOOTING || @@ -4432,7 +4541,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list flag.cri = 1; } if (flag.cri) { - wd.type = 0x0a; + wd.type = BDT_CRIT; #ifndef RENEWAL flag.idef = flag.idef2 = #endif @@ -4590,8 +4699,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list #define ATK_ADD( a ) do { int64 temp__ = (a); wd.damage += temp__; if (flag.lh) wd.damage2 += temp__; } while(0) #define ATK_ADD2( a , b ) do { wd.damage += (a); if (flag.lh) wd.damage2 += (b); } while(0) #ifdef RENEWAL -#define GET_NORMAL_ATTACK( f ) ( wd.damage = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, (f), wd.flag) ) -#define GET_NORMAL_ATTACK2( f ) ( wd.damage2 = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_L, (f), wd.flag) ) +#define GET_NORMAL_ATTACK( f , s ) ( wd.damage = battle->calc_base_damage(src, target, s, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, (f), wd.flag) ) +#define GET_NORMAL_ATTACK2( f , s ) ( wd.damage2 = battle->calc_base_damage(src, target, s, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_L, (f), wd.flag) ) #endif switch (skill_id) { //Calc base damage according to skill @@ -4610,7 +4719,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list { short totaldef = status->get_total_def(target); i = 0; - GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) ); + GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), 0 ); if( sc && sc->data[SC_NJ_BUNSINJYUTSU] && (i=sc->data[SC_NJ_BUNSINJYUTSU]->val2) > 0 ) wd.div_ = ~( i++ + 2 ) + 1; if( wd.damage ){ @@ -4623,18 +4732,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list } break; case NJ_SYURIKEN: // [malufett] - GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) ); - wd.damage += battle->calc_masteryfix(src, target, skill_id, skill_lv, 4 * skill_lv + (sd ? sd->bonus.arrow_atk : 0), wd.div_, 0, flag.weapon); - break; - case MO_EXTREMITYFIST: // [malufett] - { - short totaldef = status->get_total_def(target); - GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|8 ); - if( wd.damage ){ - wd.damage = (250 + 150 * skill_lv) + (10 * (status_get_sp(src)+1) * wd.damage / 100) + (8 * wd.damage); - ATK_ADD(-totaldef); - } - } + GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), 0); + ATK_ADD(battle->calc_masteryfix(src, target, skill_id, skill_lv, 4 * skill_lv + (sd ? sd->bonus.arrow_atk : 0), wd.div_, 0, flag.weapon)); #endif break; #ifndef RENEWAL @@ -4710,11 +4809,13 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list i |= 16; // for ex. shuriken must not be influenced by DEX } #ifdef RENEWAL - GET_NORMAL_ATTACK( i ); + GET_NORMAL_ATTACK( i, skill_id); wd.damage = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage, wd.div_, 0, flag.weapon); + wd.damage = battle->calc_cardfix2(src, target, wd.damage, s_ele, nk, wd.flag); if (flag.lh){ - GET_NORMAL_ATTACK2( i ); + GET_NORMAL_ATTACK2( i, skill_id ); wd.damage2 = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage2, wd.div_, 1, flag.weapon); + wd.damage2 = battle->calc_cardfix2(src, target, wd.damage2, s_ele, nk, wd.flag); } #else wd.damage = battle->calc_base_damage2(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i); @@ -4730,8 +4831,10 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list //Add any bonuses that modify the base baseatk+watk (pre-skills) if(sd) { +#ifndef RENEWAL if (sd->bonus.atk_rate) ATK_ADDRATE(sd->bonus.atk_rate); +#endif if(flag.cri && sd->bonus.crit_atk_rate) ATK_ADDRATE(sd->bonus.crit_atk_rate); if(flag.cri && sc && sc->data[SC_MTF_CRIDAMAGE]) @@ -4775,7 +4878,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list case KO_BAKURETSU: { #ifdef RENEWAL - GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0)); + GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0), skill_id); #endif skillratio = skill_lv * (50 + status_get_dex(src) / 4); skillratio = (int)(skillratio * (sd ? pc->checkskill(sd, NJ_TOBIDOUGU) : 10) * 40.f / 100.0f * status->get_lv(src) / 120); @@ -4784,7 +4887,32 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list break; #ifdef RENEWAL + case GS_MAGICALBULLET: + GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0), skill_id); + ATK_ADD(battle->attr_fix(src, target, + battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, status->get_matk(src, 2), 0, wd.flag), ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv)); + break; + case GS_PIERCINGSHOT: + GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0), 0); + if ( wd.damage ) { + if ( sd && sd->weapontype1 == W_RIFLE ) + ATK_RATE(30 * (skill_lv + 5)); + else + ATK_RATE(20 * (skill_lv + 5)); + } + break; + case MO_EXTREMITYFIST: // [malufett] + { + short totaldef = status->get_total_def(target); + GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | 8, skill_id); + if ( wd.damage ) { + ATK_ADD(250 * (skill_lv + 1) + (10 * (status_get_sp(src) + 1) * wd.damage / 100) + (8 * wd.damage)); + ATK_ADD(-totaldef); + } + } + break; case PA_SHIELDCHAIN: + GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0), skill_id); if ( sd ) { short index = sd->equip_index[EQI_HAND_L]; if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR ) { @@ -4794,6 +4922,32 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list ATK_ADD(sstatus->rhw.atk2); //Else use Atk2 ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag)); break; + case AM_DEMONSTRATION: + case AM_ACIDTERROR: // [malufett/Hercules] + { + int64 matk; + int totaldef = status->get_total_def(target) + status->get_total_mdef(target); + matk = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, status->get_matk(src, 2), 0, wd.flag); + matk = battle->attr_fix(src, target, matk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv); + matk = matk * battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag) / 100; + GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0), 0); + ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag)); + ATK_ADD(matk); + ATK_ADD(-totaldef); + if ( skill_id == AM_ACIDTERROR && is_boss(target) ) + ATK_RATE(50); + if ( skill_id == AM_DEMONSTRATION ) + wd.damage = max(wd.damage, 1); + } + break; + case GN_CARTCANNON: + GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0), skill_id); + ATK_ADD(sd ? sd->bonus.arrow_atk : 0); + wd.damage = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage, wd.div_, 0, flag.weapon); + ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag)); + if ( sd && s_ele != sd->bonus.arrow_ele ) + s_ele = sd->bonus.arrow_ele; + break; case NJ_TATAMIGAESHI: ATK_RATE(200); /* Fall through */ @@ -4801,7 +4955,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list case ML_SPIRALPIERCE: // [malufett] if( skill_id != NJ_TATAMIGAESHI ){ short index = sd?sd->equip_index[EQI_HAND_R]:0; - GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) ); + GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), 0); wd.damage = wd.damage * 70 / 100; //n_ele = true; // FIXME: This is has no effect if it's after GET_NORMAL_ATTACK (was this intended, or was it supposed to be put above?) @@ -4818,6 +4972,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list ATK_RATE(85); } wd.damage = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage, wd.div_, 0, flag.weapon); + wd.damage = battle->calc_cardfix2(src, target, wd.damage, s_ele, nk, wd.flag); } /* Fall through */ #endif @@ -4845,13 +5000,11 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST) ATK_ADD(10*pc->checkskill(sd, TK_RUN)); break; - case GS_MAGICALBULLET: + #ifndef RENEWAL + case GS_MAGICALBULLET: ATK_ADD( status->get_matk(src, 2) ); -#else - ATK_ADD( battle->calc_magic_attack(src, target, skill_id, skill_lv, wflag).damage ); -#endif -#ifndef RENEWAL + break; case NJ_SYURIKEN: ATK_ADD(4*skill_lv); #endif @@ -4886,15 +5039,15 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list } break; case SR_GATEOFHELL: - ATK_ADD (sstatus->max_hp - status_get_hp(src)); - if(sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE) { - ATK_ADD( (sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status->get_lv(src) ); + ATK_ADD(sstatus->max_hp - status_get_hp(src)); + if ( sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE ) { + ATK_ADD((sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status->get_lv(src)); } else { - ATK_ADD( (sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status->get_lv(src) ); + ATK_ADD((sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status->get_lv(src)); } break; case SR_FALLENEMPIRE:// [(Target Size value + Skill Level - 1) x Caster STR] + [(Target current weight x Caster DEX / 120)] - ATK_ADD( ((tstatus->size+1)*2 + skill_lv - 1) * sstatus->str); + ATK_ADD( ((tstatus->size+1)*2 + (int64)skill_lv - 1) * sstatus->str); if( tsd && tsd->weight ){ ATK_ADD( (tsd->weight/10) * sstatus->dex / 120 ); }else{ @@ -5045,7 +5198,11 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list } } - if(!flag.idef || !flag.idef2) { //Defense reduction + if((!flag.idef || !flag.idef2) +#ifdef RENEWAL + && (!flag.distinct || flag.tdef) +#endif + ) { //Defense reduction wd.damage = battle->calc_defense(BF_WEAPON, src, target, skill_id, skill_lv, wd.damage, (flag.idef?1:0)|(flag.pdef?2:0) #ifdef RENEWAL @@ -5062,8 +5219,19 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list } #ifdef RENEWAL + if ( flag.distinct ) { + wd.damage = battle->calc_cardfix2(src, target, wd.damage, s_ele, nk, wd.flag); + if ( flag.lh ) { + wd.damage2 = battle->calc_cardfix2(src, target, wd.damage2, s_ele, nk, wd.flag); + } + } //Div fix. damage_div_fix(wd.damage, wd.div_); + if ( skill_id > 0 && (skill->get_ele(skill_id, skill_lv) == ELE_NEUTRAL || flag.distinct) ) { // re-evaluate forced neutral skills + wd.damage = battle->attr_fix(src, target, wd.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); + if ( flag.lh ) + wd.damage2 = battle->attr_fix(src, target, wd.damage2, s_ele_, tstatus->def_ele, tstatus->ele_lv); + } #endif #if 0 // Can't find any source about this one even in eagis if (skill_id == NPC_EARTHQUAKE) { @@ -5146,7 +5314,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS) return wd; //Enough, rest is not needed. #ifndef HMAP_ZONE_DAMAGE_CAP_TYPE - if( target && skill_id ) { + if (skill_id) { for(i = 0; i < map->list[target->m].zone->capped_skills_count; i++) { if( skill_id == map->list[target->m].zone->capped_skills[i]->nameid && (map->list[target->m].zone->capped_skills[i]->type & target->type) ) { if( target->type == BL_MOB && map->list[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { @@ -5187,11 +5355,12 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list ATK_ADD(10*sd->status.inventory[index].refine); } } -#endif //Card Fix, tsd side - if(tsd){ //if player on player then it was already measured above - wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, (flag.lh?1:0), wd.flag); + if ( tsd ) { //if player on player then it was already measured above + wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, (flag.lh ? 1 : 0), wd.flag); } +#endif + if( flag.infdef ) { //Plants receive 1 damage when hit short class_ = status->get_class(target); if( flag.hit || wd.damage > 0 ) @@ -5370,7 +5539,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list rnd()%100 < tsc->data[SC_SWORDREJECT]->val2 ) { ATK_RATER(50); - status_fix_damage(target,src,wd.damage,clif->damage(target,src,0,0,wd.damage,0,0,0)); + status_fix_damage(target,src,wd.damage,clif->damage(target,src,0,0,wd.damage,0,BDT_NORMAL,0)); clif->skill_nodamage(target,target,ST_REJECTSWORD,tsc->data[SC_SWORDREJECT]->val1,1); if( --(tsc->data[SC_SWORDREJECT]->val3) <= 0 ) status_change_end(target, SC_SWORDREJECT, INVALID_TIMER); @@ -5476,8 +5645,8 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st rdamage = ratio + (damage)* (10 + sc->data[SC_CRESCENTELBOW]->val1 * 20 / 10) / 10; skill->blown(target, src, skill->get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1), unit->getdir(src), 0); clif->skill_damage(target, src, tick, status_get_amotion(src), 0, rdamage, - 1, SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1, 6); // This is how official does - clif->delay_damage(tick + delay, src, target,status_get_amotion(src)+1000,0, rdamage/10, 1, 0); + 1, SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1, BDT_SKILL); // This is how official does + clif->delay_damage(tick + delay, src, target,status_get_amotion(src)+1000,0, rdamage/10, 1, BDT_NORMAL); status->damage(src, target, status->damage(target, src, rdamage, 0, 0, 1)/10, 0, 0, 1); status_change_end(target, SC_CRESCENTELBOW, INVALID_TIMER); /* shouldn't this trigger skill->additional_effect? */ @@ -5495,7 +5664,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st int64 rd1 = damage * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage. trdamage += rdamage = rd1 - (damage = rd1 * 30 / 100); // not normalized as intended. - rdelay = clif->skill_damage(src, target, tick, status_get_amotion(src), status_get_dmotion(src), -3000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1, 6); + rdelay = clif->skill_damage(src, target, tick, status_get_amotion(src), status_get_dmotion(src), -3000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1, BDT_SKILL); skill->blown(target, src, skill->get_blewcount(RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1), unit->getdir(src), 0); if( tsd ) /* is this right? rdamage as both left and right? */ @@ -5522,7 +5691,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st if ( tsd && tsd->bonus.short_weapon_damage_return ) { NORMALIZE_RDAMAGE(damage * tsd->bonus.short_weapon_damage_return / 100); - rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, BDT_ENDURE); /* is this right? rdamage as both left and right? */ battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0); @@ -5547,9 +5716,9 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st NORMALIZE_RDAMAGE(damage * sc->data[SC_REFLECTSHIELD]->val2 / 100); #ifndef RENEWAL - rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, BDT_ENDURE); #else - rdelay = clif->skill_damage(src, src, tick, delay, status_get_dmotion(src), rdamage, 1, CR_REFLECTSHIELD, 1, 4); + rdelay = clif->skill_damage(src, src, tick, delay, status_get_dmotion(src), rdamage, 1, CR_REFLECTSHIELD, 1, BDT_ENDURE); #endif /* is this right? rdamage as both left and right? */ if( tsd ) @@ -5583,7 +5752,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st if( sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 2 ){ NORMALIZE_RDAMAGE(damage * sc->data[SC_SHIELDSPELL_DEF]->val2 / 100); - rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, BDT_ENDURE); /* is this right? rdamage as both left and right? */ if( tsd ) @@ -5597,7 +5766,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st if( ssc->data[SC_INSPIRATION] ) { NORMALIZE_RDAMAGE(damage / 100); - rdelay = clif->delay_damage(tick+delay,target, target, status_get_amotion(target), status_get_dmotion(target), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,target, target, status_get_amotion(target), status_get_dmotion(target), rdamage, 1, BDT_ENDURE); /* is this right? rdamage as both left and right? */ if( sd ) @@ -5612,7 +5781,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st if ( tsd && tsd->bonus.long_weapon_damage_return ) { NORMALIZE_RDAMAGE(damage * tsd->bonus.long_weapon_damage_return / 100); - rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, BDT_ENDURE); /* is this right? rdamage as both left and right? */ battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0); @@ -5707,7 +5876,7 @@ int battle_damage_area(struct block_list *bl, va_list ap) { battle->delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0,true); else status_fix_damage(src,bl,damage,0); - clif->damage(bl,bl,amotion,dmotion,damage,1,ATK_BLOCK,0); + clif->damage(bl,bl,amotion,dmotion,damage,1,BDT_ENDURE,0); if( !(src->type == BL_PC && ((TBL_PC*)src)->state.autocast) ) skill->additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); map->freeblock_unlock(); @@ -5718,6 +5887,7 @@ int battle_damage_area(struct block_list *bl, va_list ap) { /*========================================== * Do a basic physical attack (call trough unit_attack_timer) *------------------------------------------*/ +// FIXME: flag is undocumented enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, int64 tick, int flag) { struct map_session_data *sd = NULL, *tsd = NULL; struct status_data *sstatus, *tstatus; @@ -5753,10 +5923,10 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t { int index = sd->equip_index[EQI_AMMO]; if (index<0) { - if (sd->weapontype1 > W_KATAR && sd->weapontype1 < W_HUUMA) - clif->arrow_fail(sd, 0); - else + if ( sd->weapontype1 > W_KATAR && sd->weapontype1 < W_HUUMA ) clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0); + else + clif->arrow_fail(sd, 0); return ATK_NONE; } //Ammo check by Ishizu-chan @@ -5799,7 +5969,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t if(dist <= 0 || (!map->check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) { uint16 skill_lv = tsc->data[SC_AUTOCOUNTER]->val1; clif->skillcastcancel(target); //Remove the casting bar. [Skotlex] - clif->damage(src, target, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. + clif->damage(src, target, sstatus->amotion, 1, 0, 1, BDT_NORMAL, 0); //Display MISS. status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER); skill->attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skill_lv,tick,0); return ATK_BLOCK; @@ -5812,7 +5982,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER); if(sc_start4(target, src, SC_BLADESTOP, 100, sd?pc->checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration)) { //Target locked. - clif->damage(src, target, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. + clif->damage(src, target, sstatus->amotion, 1, 0, 1, BDT_NORMAL, 0); //Display MISS. clif->bladestop(target, src->id, 1); sc_start4(target, target, SC_BLADESTOP, 100, skill_lv, 0, 0, src->id, duration); return ATK_BLOCK; @@ -5856,18 +6026,6 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t return ATK_DEF; return ATK_MISS; } - if( sc->data[SC_GENTLETOUCH_ENERGYGAIN] ) { - if( sd && rnd()%100 < 10 + 5 * sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1) - pc->addspiritball(sd, - skill->get_time(MO_CALLSPIRITS, sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1), - sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1); - } - if( tsc && tsc->data[SC_GENTLETOUCH_ENERGYGAIN] ) { - if( tsd && rnd()%100 < 10 + 5 * tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1) - pc->addspiritball(tsd, - skill->get_time(MO_CALLSPIRITS, tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1), - tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1); - } if( tsc && tsc->data[SC_MTF_MLEATKED] && rnd()%100 < 20 ) clif->skill_nodamage(target, target, SM_ENDURE, 5, @@ -5890,7 +6048,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } if( sd && sc->data[SC_FEARBREEZE] && sc->data[SC_FEARBREEZE]->val4 > 0 && sd->status.inventory[sd->equip_index[EQI_AMMO]].amount >= sc->data[SC_FEARBREEZE]->val4 && battle_config.arrow_decrement){ - pc->delitem(sd,sd->equip_index[EQI_AMMO],sc->data[SC_FEARBREEZE]->val4,0,1,LOG_TYPE_CONSUME); + pc->delitem(sd, sd->equip_index[EQI_AMMO], sc->data[SC_FEARBREEZE]->val4, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); sc->data[SC_FEARBREEZE]->val4 = 0; } } @@ -5938,7 +6096,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id) ) && check_distance_bl(target, d_bl, sce->val3) ) { - clif->damage(d_bl, d_bl, 0, 0, damage, 0, 0, 0); + clif->damage(d_bl, d_bl, 0, 0, damage, 0, BDT_NORMAL, 0); status_fix_damage(NULL, d_bl, damage, 0); } else @@ -5946,7 +6104,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } else if( tsc->data[SC_CIRCLE_OF_FIRE_OPTION] && (wd.flag&BF_SHORT) && target->type == BL_PC ) { struct elemental_data *ed = ((TBL_PC*)target)->ed; if( ed ) { - clif->skill_damage(&ed->bl, target, tick, status_get_amotion(src), 0, -30000, 1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, 6); + clif->skill_damage(&ed->bl, target, tick, status_get_amotion(src), 0, -30000, 1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, BDT_SKILL); skill->attack(BF_MAGIC,&ed->bl,&ed->bl,src,EL_CIRCLE_OF_FIRE,tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1,tick,wd.flag); } } else if( tsc->data[SC_WATER_SCREEN_OPTION] && tsc->data[SC_WATER_SCREEN_OPTION]->val1 ) { @@ -6215,21 +6373,28 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f } break; case BL_MOB: - if(((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres - (((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras - s_bl->type == BL_PC && src->type != BL_MOB) || (((TBL_MOB*)target)->special_state.ai == 4 && t_bl->id != s_bl->id)) //Zanzoe - { + { + TBL_MOB *md = BL_CAST(BL_MOB, target); + if(( + (md->special_state.ai == AI_SPHERE || (md->special_state.ai == AI_FLORA && battle_config.summon_flora&1)) + && s_bl->type == BL_PC && src->type != BL_MOB + ) + || (md->special_state.ai == AI_ZANZOU && t_bl->id != s_bl->id) + ) { //Targetable by players state |= BCT_ENEMY; strip_enemy = 0; } break; + } case BL_SKILL: { TBL_SKILL *su = (TBL_SKILL*)target; if( !su->group ) return 0; - if( skill->get_inf2(su->group->skill_id)&INF2_TRAP && su->group->unit_id != UNT_USED_TRAPS) { //Only a few skills can target traps... + if( skill->get_inf2(su->group->skill_id)&INF2_TRAP && + su->group->unit_id != UNT_USED_TRAPS && + su->group->unit_id != UNT_NETHERWORLD ) { //Only a few skills can target traps... switch( battle->get_current_skill(src) ) { case RK_DRAGONBREATH:// it can only hit traps in pvp/gvg maps case RK_DRAGONBREATH_WATER: @@ -6367,8 +6532,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f ) { if( t_bl->type == BL_PC && (sd->duel_group == ((TBL_PC*)t_bl)->duel_group) ) return (BCT_ENEMY&flag)?1:-1; // Duel targets can ONLY be your enemy, nothing else. - else - return 0; // You can't target anything out of your duel + else if ( src->type != BL_SKILL || (flag&BCT_ENEMY) ) + return 0; } } if( map_flag_gvg(m) && !sd->status.guild_id && t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->class_ == MOBID_EMPERIUM ) @@ -6384,19 +6549,16 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f && md->guardian_data && (md->guardian_data->g || md->guardian_data->castle->guild_id) ) return 0; // Disable guardians/emperium owned by Guilds on non-woe times. - if( !md->special_state.ai ) - { //Normal mobs - if( - ( target->type == BL_MOB && t_bl->type == BL_PC && ( ((TBL_MOB*)target)->special_state.ai != 4 && ((TBL_MOB*)target)->special_state.ai != 1 ) ) || - ( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai ) - ) + if (md->special_state.ai == AI_NONE) { + //Normal mobs + struct mob_data *target_md = BL_CAST(BL_MOB, target); + if( (target_md && t_bl->type == BL_PC && target_md->special_state.ai != AI_ZANZOU && target_md->special_state.ai != AI_ATTACK) + || (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai) ) state |= BCT_PARTY; //Normal mobs with no ai are friends. else state |= BCT_ENEMY; //However, all else are enemies. - } - else - { - if( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai ) + } else { + if (t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->special_state.ai == AI_NONE) state |= BCT_ENEMY; //Natural enemy for AI mobs are normal mobs. } break; @@ -7287,6 +7449,7 @@ void battle_defaults(void) { battle->attr_ratio = battle_attr_ratio; battle->attr_fix = battle_attr_fix; battle->calc_cardfix = battle_calc_cardfix; + battle->calc_cardfix2 = battle_calc_cardfix2; battle->calc_elefix = battle_calc_elefix; battle->calc_masteryfix = battle_calc_masteryfix; battle->calc_chorusbonus = battle_calc_chorusbonus; diff --git a/src/map/battle.h b/src/map/battle.h index 233c325cf..6bc2659b9 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -5,8 +5,8 @@ #ifndef MAP_BATTLE_H #define MAP_BATTLE_H -#include "map.h" //ELE_MAX -#include "../common/cbasetypes.h" +#include "map/map.h" //ELE_MAX +#include "common/cbasetypes.h" /** * Declarations @@ -77,6 +77,27 @@ enum e_battle_check_target { //New definitions [Skotlex] }; /** + * Values used by (struct Damage).type, as well as clif->damage(type) and clif->skill_damage(type) + * + * Note: some values may not apply in some contexts. + */ +enum battle_dmg_type { + BDT_NORMAL = 0, // Normal attack + //BDT_PICKUP = 1, // Pick up item + //BDT_SITDOWN = 2, // Sit down + //BDT_STANDUP = 3, // Stand up + BDT_ENDURE = 4, // Damage (endure) + BDT_SPLASH = 5, // Splash + BDT_SKILL = 6, // Skill + //BDT_REPEAT = 7, // (repeat damage?) + BDT_MULTIHIT = 8, // Multi-hit damage + BDT_MULTIENDURE = 9, // Multi-hit damage (endure) + BDT_CRIT = 10, // Critical hit + BDT_PDODGE = 11, // Lucky dodge + //BDT_TOUCH = 12, // (touch skill?) +}; + +/** * Structures **/ @@ -558,6 +579,7 @@ struct battle_interface { int64 (*attr_fix) (struct block_list *src, struct block_list *target, int64 damage, int atk_elem, int def_type, int def_lv); /* applies card modifiers */ int64 (*calc_cardfix) (int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int left, int flag); + int64 (*calc_cardfix2) (struct block_list *src, struct block_list *bl, int64 damage, int s_ele, int nk, int flag); /* applies element modifiers */ int64 (*calc_elefix) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag); /* applies mastery modifiers */ diff --git a/src/map/battleground.c b/src/map/battleground.c index 2d4ba6bf1..0fe42110f 100644 --- a/src/map/battleground.c +++ b/src/map/battleground.c @@ -6,29 +6,31 @@ #include "battleground.h" +#include "map/battle.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/map.h" +#include "map/mapreg.h" +#include "map/mercenary.h" +#include "map/mob.h" // struct mob_data +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pet.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/HPM.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" + #include <stdio.h> #include <string.h> -#include "battle.h" -#include "clif.h" -#include "homunculus.h" -#include "map.h" -#include "mapreg.h" -#include "mercenary.h" -#include "mob.h" // struct mob_data -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "pet.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" - struct battleground_interface bg_s; /// Search a BG Team using bg_id @@ -210,7 +212,7 @@ int bg_team_get_id(struct block_list *bl) { { struct map_session_data *msd; struct mob_data *md = (TBL_MOB*)bl; - if( md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL ) + if (md->special_state.ai != AI_NONE && (msd = map->id2sd(md->master_id)) != NULL) return msd->bg_id; return md->bg_id; } @@ -537,11 +539,10 @@ void bg_match_over(struct bg_arena *arena, bool canceled) { bg->team_leave(sd, 0); bg->queue_pc_cleanup(sd); } - if( canceled ) - clif->colormes(sd->fd,COLOR_RED,"BG Match Canceled: not enough players"); - else { + if (canceled) + clif->messagecolor_self(sd->fd, COLOR_RED, "BG Match Canceled: not enough players"); + else pc_setglobalreg(sd, script->add_str(arena->delay_var), (unsigned int)time(NULL)); - } } } @@ -765,7 +766,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_ sprintf(response, "You are a deserter! Wait %d minute(s) before you can apply again",(tick-tsec)/60); else sprintf(response, "You are a deserter! Wait %d seconds before you can apply again",(tick-tsec)); - clif->colormes(sd->fd,COLOR_RED,response); + clif->messagecolor_self(sd->fd, COLOR_RED, response); return BGQA_FAIL_DESERTER; } @@ -775,7 +776,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_ sprintf(response, "You can't reapply to this arena so fast. Apply to the different arena or wait %d minute(s)",(tick-tsec)/60); else sprintf(response, "You can't reapply to this arena so fast. Apply to the different arena or wait %d seconds",(tick-tsec)); - clif->colormes(sd->fd,COLOR_RED,response); + clif->messagecolor_self(sd->fd, COLOR_RED, response); return BGQA_FAIL_COOLDOWN; } @@ -799,7 +800,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_ sprintf(response, "Can't apply: not enough members in your team/guild that have not entered the queue in individual mode, minimum is %d",arena->min_team_players); else sprintf(response, "Can't apply: not enough members in your team/guild, minimum is %d",arena->min_team_players); - clif->colormes(sd->fd,COLOR_RED,response); + clif->messagecolor_self(sd->fd, COLOR_RED, response); return BGQA_FAIL_TEAM_COUNT; } } @@ -831,7 +832,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_ sprintf(response, "Can't apply: not enough members in your team/party that have not entered the queue in individual mode, minimum is %d",arena->min_team_players); else sprintf(response, "Can't apply: not enough members in your team/party, minimum is %d",arena->min_team_players); - clif->colormes(sd->fd,COLOR_RED,response); + clif->messagecolor_self(sd->fd, COLOR_RED, response); return BGQA_FAIL_TEAM_COUNT; } } else @@ -856,9 +857,27 @@ void do_init_battleground(bool minimal) { bg->config_read(); } +/** + * @see DBApply + */ +int bg_team_db_final(DBKey key, DBData *data, va_list ap) { + struct battleground_data* bgd = DB->data2ptr(data); + int i; + for(i = 0; i < bgd->hdatac; i++ ) { + if( bgd->hdata[i]->flag.free ) { + aFree(bgd->hdata[i]->data); + } + aFree(bgd->hdata[i]); + } + if( bgd->hdata ) + aFree(bgd->hdata); + + return 0; +} + void do_final_battleground(void) { - db_destroy(bg->team_db); + bg->team_db->destroy(bg->team_db,bg->team_db_final); if (bg->arena) { int i; @@ -868,6 +887,7 @@ void do_final_battleground(void) } aFree(bg->arena); } + } void battleground_defaults(void) { bg = &bg_s; @@ -911,6 +931,7 @@ void battleground_defaults(void) { bg->send_xy_timer_sub = bg_send_xy_timer_sub; bg->send_xy_timer = bg_send_xy_timer; bg->afk_timer = bg_afk_timer; + bg->team_db_final = bg_team_db_final; /* */ bg->str2teamtype = bg_str2teamtype; /* */ diff --git a/src/map/battleground.h b/src/map/battleground.h index 9878d6be0..a67deb722 100644 --- a/src/map/battleground.h +++ b/src/map/battleground.h @@ -5,9 +5,14 @@ #ifndef MAP_BATTLEGROUND_H #define MAP_BATTLEGROUND_H -#include "clif.h" -#include "guild.h" -#include "../common/mmo.h" // struct party +#include "map/map.h" // EVENT_NAME_LENGTH +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/mmo.h" // struct party + +struct HPluginData; +struct block_list; +struct map_session_data; /** * Defines @@ -48,6 +53,9 @@ struct battleground_data { // Logout Event char logout_event[EVENT_NAME_LENGTH]; char die_event[EVENT_NAME_LENGTH]; + /* HPM Custom Struct */ + struct HPluginData **hdata; + unsigned int hdatac; }; struct bg_arena { @@ -112,6 +120,7 @@ struct battleground_interface { int (*send_xy_timer_sub) (DBKey key, DBData *data, va_list ap); int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data); int (*afk_timer) (int tid, int64 tick, int id, intptr_t data); + int (*team_db_final) (DBKey key, DBData *data, va_list ap); /* */ enum bg_queue_types (*str2teamtype) (const char *str); /* */ diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c index 85fef98aa..d1ce4ba0d 100644 --- a/src/map/buyingstore.c +++ b/src/map/buyingstore.c @@ -4,19 +4,19 @@ #define HERCULES_CORE -#include "buyingstore.h" // struct s_buyingstore - -#include "atcommand.h" // msg_txt -#include "battle.h" // battle_config.* -#include "chrif.h" -#include "clif.h" // clif->buyingstore_* -#include "log.h" // log_pick_pc, log_zeny -#include "pc.h" // struct map_session_data -#include "../common/cbasetypes.h" -#include "../common/db.h" // ARR_FIND -#include "../common/showmsg.h" // ShowWarning -#include "../common/socket.h" // RBUF* -#include "../common/strlib.h" // safestrncpy +#include "buyingstore.h" // struct s_buyingstore + +#include "map/atcommand.h" // msg_txt +#include "map/battle.h" // battle_config.* +#include "map/chrif.h" +#include "map/clif.h" // clif-"buyingstore_* +#include "map/log.h" // log_pick_pc, log_zeny +#include "map/pc.h" // struct map_session_data +#include "common/cbasetypes.h" +#include "common/db.h" // ARR_FIND +#include "common/showmsg.h" // ShowWarning +#include "common/socket.h" // RBUF* +#include "common/strlib.h" // safestrncpy struct buyingstore_interface buyingstore_s; @@ -353,7 +353,7 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int // move item pc->additem(pl_sd, &sd->status.inventory[index], amount, LOG_TYPE_BUYING_STORE); - pc->delitem(sd, index, amount, 1, 0, LOG_TYPE_BUYING_STORE); + pc->delitem(sd, index, amount, 1, DELITEM_NORMAL, LOG_TYPE_BUYING_STORE); pl_sd->buyingstore.items[listidx].amount-= amount; // pay up diff --git a/src/map/buyingstore.h b/src/map/buyingstore.h index 7b8e369d2..f23790459 100644 --- a/src/map/buyingstore.h +++ b/src/map/buyingstore.h @@ -5,8 +5,8 @@ #ifndef MAP_BUYINGSTORE_H #define MAP_BUYINGSTORE_H -#include "../common/cbasetypes.h" -#include "../common/mmo.h" // MAX_SLOTS +#include "common/cbasetypes.h" +#include "common/mmo.h" // MAX_SLOTS struct map_session_data; diff --git a/src/map/channel.c b/src/map/channel.c index 0704bf706..69f7ab872 100644 --- a/src/map/channel.c +++ b/src/map/channel.c @@ -5,28 +5,28 @@ #include "channel.h" +#include "map/atcommand.h" +#include "map/guild.h" +#include "map/instance.h" +#include "map/irc-bot.h" +#include "map/map.h" +#include "map/pc.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/db.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" -#include "guild.h" -#include "instance.h" -#include "irc-bot.h" -#include "map.h" -#include "pc.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct channel_interface channel_s; static struct Channel_Config channel_config; @@ -258,7 +258,7 @@ void channel_send(struct channel_data *chan, struct map_session_data *sd, const if (sd && chan->msg_delay != 0 && DIFF_TICK(sd->hchsysch_tick + chan->msg_delay*1000, timer->gettick()) > 0 && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) { - clif->colormes(sd->fd,COLOR_RED,msg_sd(sd,1455)); + clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd,1455)); return; } else if (sd) { snprintf(message, 150, "[ #%s ] %s : %s",chan->name,sd->status.name, msg); @@ -352,7 +352,7 @@ enum channel_operation_status channel_join(struct channel_data *chan, struct map } else { sprintf(output, msg_sd(sd,1403), chan->name); // You're now in the '%s' channel } - clif->colormes(sd->fd, COLOR_DEFAULT, output); + clif->messagecolor_self(sd->fd, COLOR_DEFAULT, output); } if (chan->type == HCS_TYPE_ALLY) { @@ -477,6 +477,17 @@ void channel_map_join(struct map_session_data *sd) channel->join(map->list[sd->bl.m].channel, sd, NULL, false); } +void channel_irc_join(struct map_session_data *sd) +{ + struct channel_data *chan = ircbot->channel; + if (sd->state.autotrade || sd->state.standalone) + return; + if (channel->config->irc_name[0] == '\0') + return; + if (chan) + channel->join(chan, sd, NULL, false); +} + /** * Lets a guild's members join a newly allied guild's channel. * @@ -574,7 +585,8 @@ void read_channels_config(void) int ally_enabled = 0, local_enabled = 0, local_autojoin = 0, ally_autojoin = 0, allow_user_channel_creation = 0, - irc_enabled = 0; + irc_enabled = 0, + irc_autojoin = 0; if( !libconfig->setting_lookup_string(settings, "map_local_channel_name", &local_name) ) local_name = "map"; @@ -655,11 +667,14 @@ void read_channels_config(void) libconfig->setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin); libconfig->setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin); + libconfig->setting_lookup_bool(settings, "irc_channel_autojoin", &irc_autojoin); if (local_autojoin) channel->config->local_autojoin = true; if (ally_autojoin) channel->config->ally_autojoin = true; + if (irc_autojoin) + channel->config->irc_autojoin = true; libconfig->setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation); @@ -678,7 +693,6 @@ void read_channels_config(void) safestrncpy(channel->config->colors_name[i], config_setting_name(color), HCS_NAME_LENGTH); channel->config->colors[i] = (unsigned int)strtoul(libconfig->setting_get_string_elem(colors,i),NULL,0); - channel->config->colors[i] = (channel->config->colors[i] & 0x0000FF) << 16 | (channel->config->colors[i] & 0x00FF00) | (channel->config->colors[i] & 0xFF0000) >> 16;//RGB to BGR } channel->config->colors_count = color_count; } @@ -768,7 +782,7 @@ int do_init_channel(bool minimal) return 0; channel->db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, HCS_NAME_LENGTH); - channel->config->ally = channel->config->local = channel->config->irc = channel->config->ally_autojoin = channel->config->local_autojoin = false; + channel->config->ally = channel->config->local = channel->config->irc = channel->config->ally_autojoin = channel->config->local_autojoin = channel->config->irc_autojoin = false; channel->config_read(); return 0; @@ -828,6 +842,7 @@ void channel_defaults(void) channel->guild_join_alliance = channel_guild_join_alliance; channel->guild_leave_alliance = channel_guild_leave_alliance; channel->quit_guild = channel_quit_guild; + channel->irc_join = channel_irc_join; channel->config_read = read_channels_config; } diff --git a/src/map/channel.h b/src/map/channel.h index ba6aafc79..de1779d96 100644 --- a/src/map/channel.h +++ b/src/map/channel.h @@ -4,11 +4,9 @@ #ifndef MAP_CHANNEL_H #define MAP_CHANNEL_H -#include <stdarg.h> - -#include "map.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/mmo.h" /** * Declarations @@ -51,7 +49,7 @@ struct Channel_Config { char **colors_name; unsigned char colors_count; bool local, ally, irc; - bool local_autojoin, ally_autojoin; + bool local_autojoin, ally_autojoin, irc_autojoin; char local_name[HCS_NAME_LENGTH], ally_name[HCS_NAME_LENGTH], irc_name[HCS_NAME_LENGTH]; unsigned char local_color, ally_color, irc_color; bool closing; @@ -106,6 +104,7 @@ struct channel_interface { void (*guild_join_alliance) (const struct guild *g_source, const struct guild *g_ally); void (*guild_leave_alliance) (const struct guild *g_source, const struct guild *g_ally); void (*quit_guild) (struct map_session_data *sd); + void (*irc_join) (struct map_session_data *sd); void (*config_read) (void); }; diff --git a/src/map/chat.c b/src/map/chat.c index a232781ca..08c904290 100644 --- a/src/map/chat.c +++ b/src/map/chat.c @@ -6,23 +6,23 @@ #include "chat.h" +#include "map/atcommand.h" // msg_sd(sd,) +#include "map/battle.h" // struct battle_config +#include "map/clif.h" +#include "map/map.h" +#include "map/npc.h" // npc_event_do() +#include "map/pc.h" +#include "map/skill.h" // ext_skill_unit_onplace() +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/mmo.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/strlib.h" + #include <stdio.h> #include <string.h> -#include "atcommand.h" // msg_sd(sd,) -#include "battle.h" // struct battle_config -#include "clif.h" -#include "map.h" -#include "npc.h" // npc_event_do() -#include "pc.h" -#include "skill.h" // ext_skill_unit_onplace() -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/mmo.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" - struct chat_interface chat_s; /// Initializes a chatroom object (common functionality for both pc and npc chatrooms). @@ -93,7 +93,7 @@ bool chat_createpcchat(struct map_session_data* sd, const char* title, const cha return false; } - pc_stop_walking(sd,1); + pc_stop_walking(sd, STOPWALKING_FLAG_FIXPOS); cd = chat->create(&sd->bl, title, pass, limit, pub, 0, "", 0, 1, MAX_LEVEL); if( cd ) { @@ -101,7 +101,7 @@ bool chat_createpcchat(struct map_session_data* sd, const char* title, const cha cd->usersd[0] = sd; pc_setchatid(sd,cd->bl.id); pc_stop_attack(sd); - clif->createchat(sd,0); + clif->createchat(sd,0); // 0 = success clif->dispchat(cd,0); return true; } @@ -150,7 +150,7 @@ bool chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) { return false; } - pc_stop_walking(sd,1); + pc_stop_walking(sd, STOPWALKING_FLAG_FIXPOS); cd->usersd[cd->users] = sd; cd->users++; @@ -339,7 +339,7 @@ bool chat_kickchat(struct map_session_data* sd, const char* kickusername) { idb_iput(cd->kick_list,cd->usersd[i]->status.char_id,1); - chat->leave(cd->usersd[i],1); + chat->leave(cd->usersd[i], true); return true; } @@ -440,7 +440,7 @@ bool chat_npckickall(struct chat_data* cd) nullpo_ret(cd); while( cd->users > 0 ) - chat->leave(cd->usersd[cd->users-1],0); + chat->leave(cd->usersd[cd->users-1], false); return true; } diff --git a/src/map/chat.h b/src/map/chat.h index ced216b41..31048d5dd 100644 --- a/src/map/chat.h +++ b/src/map/chat.h @@ -5,9 +5,9 @@ #ifndef MAP_CHAT_H #define MAP_CHAT_H -#include "map.h" // struct block_list, CHATROOM_TITLE_SIZE -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "map/map.h" // struct block_list, CHATROOM_TITLE_SIZE +#include "common/cbasetypes.h" +#include "common/db.h" struct chat_data; struct map_session_data; diff --git a/src/map/chrif.c b/src/map/chrif.c index da946f050..5bd1e436f 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -4,39 +4,38 @@ #define HERCULES_CORE -#include "../config/core.h" // AUTOTRADE_PERSISTENCY, STATS_OPT_OUT +#include "config/core.h" // AUTOTRADE_PERSISTENCY, STATS_OPT_OUT #include "chrif.h" +#include "map/battle.h" +#include "map/clif.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/npc.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" + #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <sys/types.h> -#include <time.h> - -#include "map.h" -#include "battle.h" -#include "clif.h" -#include "intif.h" -#include "npc.h" -#include "pc.h" -#include "pet.h" -#include "skill.h" -#include "status.h" -#include "homunculus.h" -#include "instance.h" -#include "mercenary.h" -#include "elemental.h" -#include "quest.h" -#include "storage.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" struct chrif_interface chrif_s; @@ -62,7 +61,7 @@ struct chrif_interface chrif_s; //2b0a: Incoming/Outgoing, socket_datasync() //2b0b: Outgoing, update charserv skillid2idx //2b0c: Outgoing, chrif_changeemail -> 'change mail address ...' -//2b0d: Incoming, chrif_changedsex -> 'Change sex of acc XY' +//2b0d: Incoming, chrif_changedsex -> 'Change sex of acc XY' (or char) //2b0e: Outgoing, chrif_char_ask_name -> 'Do some operations (change sex, ban / unban etc)' //2b0f: Incoming, chrif_char_ask_name_answer -> 'answer of the 2b0e' //2b10: Outgoing, chrif_updatefamelist -> 'Update the fame ranking lists and send them' @@ -247,6 +246,7 @@ int chrif_isconnected(void) { * Flag = 1: Character is quitting * Flag = 2: Character is changing map-servers *------------------------------------------*/ +// TODO: Flag enum bool chrif_save(struct map_session_data *sd, int flag) { nullpo_ret(sd); @@ -263,11 +263,11 @@ bool chrif_save(struct map_session_data *sd, int flag) { chrif_check(false); //Character is saved on reconnect. //For data sync - if (sd->state.storage_flag == 2) + if (sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->save(sd->status.account_id, sd->status.guild_id, flag); if (flag) - sd->state.storage_flag = 0; //Force close it. + sd->state.storage_flag = STORAGE_FLAG_CLOSED; //Force close it. //Saving of registry values. if (sd->vars_dirty) @@ -401,7 +401,7 @@ bool chrif_changemapserverack(int account_id, int login_id1, int login_id2, int if ( !login_id1 ) { ShowError("chrif_changemapserverack: map server change failed.\n"); - clif->authfail_fd(node->fd, 0); + clif->authfail_fd(node->fd, 0); // Disconnected from server } else clif->changemapserver(node->sd, map_index, x, y, ntohl(ip), ntohs(port)); @@ -465,7 +465,7 @@ int chrif_reconnect(DBKey key, DBData *data, va_list ap) { if( map->mapname2ipport(sd->mapindex,&ip,&port) == 0 ) chrif->changemapserver(sd, ip, port); else //too much lag/timeout is the closest explanation for this error. - clif->authfail_fd(sd->fd, 3); + clif->authfail_fd(sd->fd, 3); // timeout break; } } @@ -643,7 +643,7 @@ void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used ( node->sex == sex && node->state == ST_LOGIN ) {// found a match - clif->authfail_fd(node->fd, 0); + clif->authfail_fd(node->fd, 0); // Disconnected from server chrif->auth_delete(account_id, char_id, ST_LOGIN); } } @@ -744,10 +744,18 @@ bool chrif_changeemail(int id, const char *actual_email, const char *new_email) } /*========================================== - * S 2b0e <accid>.l <name>.24B <type>.w { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } + * S 2b0e <accid>.l <name>.24B <type>.w { <additional fields>.12B } + * { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } * Send an account modification request to the login server (via char server). - * type of operation: - * 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex (use next function for 5), 6: charban + * type of operation: @see enum zh_char_ask_name + * block { n/a } + * ban { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } + * unblock { n/a } + * unban { n/a } + * changesex { n/a } -- use chrif_changesex + * charban { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w } + * charunban { n/a } + * changecharsex { <sex>.b } -- use chrif_changesex *------------------------------------------*/ bool chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second) { @@ -759,7 +767,7 @@ bool chrif_char_ask_name(int acc, const char* character_name, unsigned short ope safestrncpy((char*)WFIFOP(chrif->fd,6), character_name, NAME_LENGTH); WFIFOW(chrif->fd,30) = operation_type; - if ( operation_type == 2 || operation_type == 6 ) { + if (operation_type == CHAR_ASK_NAME_BAN || operation_type == CHAR_ASK_NAME_CHARBAN) { WFIFOW(chrif->fd,32) = year; WFIFOW(chrif->fd,34) = month; WFIFOW(chrif->fd,36) = day; @@ -772,14 +780,24 @@ bool chrif_char_ask_name(int acc, const char* character_name, unsigned short ope return true; } -bool chrif_changesex(struct map_session_data *sd) { +/** + * Requests a sex change (either per character or per account). + * + * @param sd The character's data. + * @param change_account Whether to change the per-account sex. + * @retval true. + */ +bool chrif_changesex(struct map_session_data *sd, bool change_account) +{ chrif_check(false); WFIFOHEAD(chrif->fd,44); WFIFOW(chrif->fd,0) = 0x2b0e; WFIFOL(chrif->fd,2) = sd->status.account_id; safestrncpy((char*)WFIFOP(chrif->fd,6), sd->status.name, NAME_LENGTH); - WFIFOW(chrif->fd,30) = 5; + WFIFOW(chrif->fd,30) = change_account ? CHAR_ASK_NAME_CHANGESEX : CHAR_ASK_NAME_CHANGECHARSEX; + if (!change_account) + WFIFOB(chrif->fd,32) = sd->status.sex == SEX_MALE ? SEX_FEMALE : SEX_MALE; WFIFOSET(chrif->fd,44); clif->message(sd->fd, msg_sd(sd,408)); //"Disconnecting to perform change-sex request..." @@ -794,19 +812,14 @@ bool chrif_changesex(struct map_session_data *sd) { /*========================================== * R 2b0f <accid>.l <name>.24B <type>.w <answer>.w * Processing a reply to chrif->char_ask_name() (request to modify an account). - * type of operation: - * 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex, 6: charban, 7: charunban - * type of answer: - * 0: login-server request done - * 1: player not found - * 2: gm level too low - * 3: login-server offline + * type of operation: @see chrif_char_ask_name + * type of answer: @see hz_char_ask_name_answer *------------------------------------------*/ bool chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, uint16 answer) { struct map_session_data* sd; char action[25]; char output[256]; - bool charsrv = ( type == 6 || type == 7 ) ? true : false; + bool charsrv = ( type == CHAR_ASK_NAME_CHARBAN || type == CHAR_ASK_NAME_CHARUNBAN ) ? true : false; sd = map->id2sd(acc); @@ -816,19 +829,19 @@ bool chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, u } /* re-use previous msg_number */ - if( type == 6 ) type = 2; - if( type == 7 ) type = 4; + if( type == CHAR_ASK_NAME_CHARBAN ) type = CHAR_ASK_NAME_BAN; + if( type == CHAR_ASK_NAME_CHARUNBAN ) type = CHAR_ASK_NAME_UNBAN; - if( type > 0 && type <= 5 ) + if( type >= CHAR_ASK_NAME_BLOCK && type <= CHAR_ASK_NAME_CHANGESEX ) snprintf(action,25,"%s",msg_sd(sd,427+type)); //block|ban|unblock|unban|change the sex of else snprintf(action,25,"???"); switch( answer ) { - case 0 : sprintf(output, msg_sd(sd,charsrv?434:424), action, NAME_LENGTH, player_name); break; - case 1 : sprintf(output, msg_sd(sd,425), NAME_LENGTH, player_name); break; - case 2 : sprintf(output, msg_sd(sd,426), action, NAME_LENGTH, player_name); break; - case 3 : sprintf(output, msg_sd(sd,427), action, NAME_LENGTH, player_name); break; + case CHAR_ASK_NAME_ANS_DONE: sprintf(output, msg_sd(sd,charsrv?434:424), action, NAME_LENGTH, player_name); break; + case CHAR_ASK_NAME_ANS_NOTFOUND: sprintf(output, msg_sd(sd,425), NAME_LENGTH, player_name); break; + case CHAR_ASK_NAME_ANS_GMLOW: sprintf(output, msg_sd(sd,426), action, NAME_LENGTH, player_name); break; + case CHAR_ASK_NAME_ANS_OFFLINE: sprintf(output, msg_sd(sd,427), action, NAME_LENGTH, player_name); break; default: output[0] = '\0'; break; } @@ -847,8 +860,11 @@ void chrif_changedsex(int fd) { ShowNotice("chrif_changedsex %d.\n", acc); // Path to activate this response: - // Map(start) (0x2b0e) -> Char(0x2727) -> Login + // Map(start) (0x2b0e type 5) -> Char(0x2727) -> Login // Login(0x2723) [ALL] -> Char (0x2b0d)[ALL] -> Map (HERE) + // OR + // Map(start) (0x2b03 type 8) -> Char + // Char(0x2b0d)[ALL] -> Map (HERE) // Char will usually be "logged in" despite being forced to log-out in the beginning // of this process, but there's no need to perform map-server specific response // as everything should been changed through char-server [Panikon] @@ -883,14 +899,14 @@ bool chrif_divorceack(int char_id, int partner_id) { sd->status.partner_id = 0; for(i = 0; i < MAX_INVENTORY; i++) if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F) - pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); } if( ( sd = map->charid2sd(partner_id) ) != NULL && sd->status.partner_id == char_id ) { sd->status.partner_id = 0; for(i = 0; i < MAX_INVENTORY; i++) if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F) - pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); } return true; @@ -1305,8 +1321,8 @@ void chrif_skillid2idx(int fd) { WFIFOHEAD(fd,4 + (MAX_SKILL * 4)); WFIFOW(fd,0) = 0x2b0b; for(i = 0; i < MAX_SKILL; i++) { - if( skill->db[i].nameid ) { - WFIFOW(fd, 4 + (count*4)) = skill->db[i].nameid; + if( skill->dbs->db[i].nameid ) { + WFIFOW(fd, 4 + (count*4)) = skill->dbs->db[i].nameid; WFIFOW(fd, 6 + (count*4)) = i; count++; } diff --git a/src/map/chrif.h b/src/map/chrif.h index 271fc076d..cac965f74 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -5,12 +5,12 @@ #ifndef MAP_CHRIF_H #define MAP_CHRIF_H -#include <time.h> - -#include "map.h" //TBL_stuff -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "map/map.h" //TBL_PC +#include "common/cbasetypes.h" +#include "common/db.h" +struct eri; +struct map_session_data; struct status_change_entry; /** @@ -103,7 +103,7 @@ struct chrif_interface { bool (*char_reset_offline) (void); bool (*send_users_tochar) (void); bool (*char_online) (struct map_session_data *sd); - bool (*changesex) (struct map_session_data *sd); + bool (*changesex) (struct map_session_data *sd, bool change_account); //int (*chardisconnect) (struct map_session_data *sd); // FIXME: Commented out in clif.c, function does not exist bool (*divorce) (int partner_id1, int partner_id2); diff --git a/src/map/clif.c b/src/map/clif.c index 029080958..d00cac0ee 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -4,60 +4,60 @@ #define HERCULES_CORE -#include "../config/core.h" // ANTI_MAYAP_CHEAT, RENEWAL, SECURE_NPCTIMEOUT +#include "config/core.h" // ANTI_MAYAP_CHEAT, RENEWAL, SECURE_NPCTIMEOUT #include "clif.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/battleground.h" +#include "map/channel.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/irc-bot.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "map/trade.h" +#include "map/unit.h" +#include "map/vending.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/ers.h" +#include "common/grfio.h" +#include "common/malloc.h" +#include "common/mmo.h" // NEW_CARTS +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <time.h> -#include "atcommand.h" -#include "battle.h" -#include "battleground.h" -#include "channel.h" -#include "chat.h" -#include "chrif.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "instance.h" -#include "intif.h" -#include "irc-bot.h" -#include "itemdb.h" -#include "log.h" -#include "mail.h" -#include "map.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "pet.h" -#include "quest.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "storage.h" -#include "trade.h" -#include "unit.h" -#include "vending.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/ers.h" -#include "../common/grfio.h" -#include "../common/malloc.h" -#include "../common/mmo.h" // NEW_CARTS -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct clif_interface clif_s; /* re-usable */ @@ -688,6 +688,7 @@ void clif_authrefuse(int fd, uint8 error_code) /// 109 = BAN_INVALID_PWD_CNT /// 110 = BAN_NOT_ALLOWED_JOBCLASS /// ? = disconnected -> MsgStringTable[3] +// TODO: type enum void clif_authfail_fd(int fd, int type) { if (!fd || !session[fd] || session[fd]->func_parse != clif->parse) //clif_authfail should only be invoked on players! @@ -1369,7 +1370,7 @@ bool clif_spawn(struct block_list *bl) if( sd->bg_id && map->list[sd->bl.m].flag.battleground ) clif->sendbgemblem_area(sd); for( i = 0; i < sd->sc_display_count; i++ ) { - clif->sc_load(&sd->bl, sd->bl.id,AREA,status->IconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3); + clif->sc_load(&sd->bl, sd->bl.id,AREA,status->dbs->IconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3); } if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0) clif->spiritcharm(sd); @@ -1520,19 +1521,24 @@ void clif_homskillinfoblock(struct map_session_data *sd) { WFIFOHEAD(fd, 4+37*MAX_HOMUNSKILL); WFIFOW(fd,0)=0x235; - for ( i = 0; i < MAX_HOMUNSKILL; i++){ + for ( i = 0; i < MAX_HOMUNSKILL; i++ ) { int id = hd->homunculus.hskill[i].id; - if (id != 0) { + if ( id != 0 ) { j = id - HM_SKILLBASE; - WFIFOW(fd,len ) = id; - WFIFOW(fd,len+2) = skill->get_inf(id); - WFIFOW(fd,len+4) = 0; - WFIFOW(fd,len+6) = hd->homunculus.hskill[j].lv; - WFIFOW(fd,len+8) = skill->get_sp(id,hd->homunculus.hskill[j].lv); - WFIFOW(fd,len+10)= skill->get_range2(&sd->hd->bl, id,hd->homunculus.hskill[j].lv); - safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); - WFIFOB(fd,len+36) = (hd->homunculus.hskill[j].lv < homun->skill_tree_get_max(id, hd->homunculus.class_))?1:0; - len+=37; + WFIFOW(fd, len) = id; + WFIFOW(fd, len + 2) = skill->get_inf(id); + WFIFOW(fd, len + 4) = 0; + WFIFOW(fd, len + 6) = hd->homunculus.hskill[j].lv; + if ( hd->homunculus.hskill[j].lv ) { + WFIFOW(fd, len + 8) = skill->get_sp(id, hd->homunculus.hskill[j].lv); + WFIFOW(fd, len + 10) = skill->get_range2(&sd->hd->bl, id, hd->homunculus.hskill[j].lv); + } else { + WFIFOW(fd, len + 8) = 0; + WFIFOW(fd, len + 10) = 0; + } + safestrncpy((char*)WFIFOP(fd, len + 12), skill->get_name(id), NAME_LENGTH); + WFIFOB(fd, len + 36) = (hd->homunculus.hskill[j].lv < homun->skill_tree_get_max(id, hd->homunculus.class_)) ? 1 : 0; + len += 37; } } WFIFOW(fd,2)=len; @@ -2292,15 +2298,7 @@ void clif_dropitem(struct map_session_data *sd,int n,int amount) /// Notifies the client, that an inventory item was deleted (ZC_DELETE_ITEM_FROM_BODY). /// 07fa <delete type>.W <index>.W <amount>.W -/// delete type: -/// 0 = Normal -/// 1 = Item used for a skill -/// 2 = Refine failed -/// 3 = Material changed -/// 4 = Moved to storage -/// 5 = Moved to cart -/// 6 = Item sold -/// 7 = Consumed by Four Spirit Analysis (SO_EL_ANALYSIS) skill +/// delete type: @see enum delitem_reason void clif_delitem(struct map_session_data *sd,int n,int amount, short reason) { #if PACKETVER < 20091117 @@ -2976,6 +2974,9 @@ void clif_changelook(struct block_list *bl,int type,int val) case LOOK_BASE: if( !sd ) break; + if ( val == INVISIBLE_CLASS ) /* nothing to change look */ + return; + if( sd->sc.option&OPTION_COSTUME ) vd->weapon = vd->shield = 0; @@ -3226,14 +3227,14 @@ void clif_arrow_create_list(struct map_session_data *sd) for (i = 0, c = 0; i < MAX_SKILL_ARROW_DB; i++) { int j; - if (skill->arrow_db[i].nameid > 0 - && (j = pc->search_inventory(sd, skill->arrow_db[i].nameid)) != INDEX_NOT_FOUND + if (skill->dbs->arrow_db[i].nameid > 0 + && (j = pc->search_inventory(sd, skill->dbs->arrow_db[i].nameid)) != INDEX_NOT_FOUND && !sd->status.inventory[j].equip && sd->status.inventory[j].identify ) { - if ((j = itemdb_viewid(skill->arrow_db[i].nameid)) > 0) + if ((j = itemdb_viewid(skill->dbs->arrow_db[i].nameid)) > 0) WFIFOW(fd,c*2+4) = j; else - WFIFOW(fd,c*2+4) = skill->arrow_db[i].nameid; + WFIFOW(fd,c*2+4) = skill->dbs->arrow_db[i].nameid; c++; } } @@ -3459,6 +3460,7 @@ void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok) /// 0 = Room has been successfully created (opens chat room) /// 1 = Room limit exceeded /// 2 = Same room already exists +// TODO: Flag enum void clif_createchat(struct map_session_data* sd, int flag) { int fd; @@ -4003,7 +4005,7 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds clif->charm_single(sd->fd, dstsd); for( i = 0; i < dstsd->sc_display_count; i++ ) { - clif->sc_load(&sd->bl,dstsd->bl.id,SELF,status->IconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3); + clif->sc_load(&sd->bl,dstsd->bl.id,SELF,status->dbs->IconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3); } if( (sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting. (sd->bg_id && sd->bg_id == dstsd->bg_id) || //BattleGround @@ -4012,11 +4014,11 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds clif->hpmeter_single(sd->fd, dstsd->bl.id, dstsd->battle_status.hp, dstsd->battle_status.max_hp); // display link (sd - dstsd) to sd - ARR_FIND( 0, 5, i, sd->devotion[i] == dstsd->bl.id ); - if( i < 5 ) clif->devotion(&sd->bl, sd); + ARR_FIND( 0, MAX_PC_DEVOTION, i, sd->devotion[i] == dstsd->bl.id ); + if( i < MAX_PC_DEVOTION ) clif->devotion(&sd->bl, sd); // display links (dstsd - devotees) to sd - ARR_FIND( 0, 5, i, dstsd->devotion[i] > 0 ); - if( i < 5 ) clif->devotion(&dstsd->bl, sd); + ARR_FIND( 0, MAX_PC_DEVOTION, i, dstsd->devotion[i] > 0 ); + if( i < MAX_PC_DEVOTION ) clif->devotion(&dstsd->bl, sd); // display link (dstsd - crusader) to sd if( dstsd->sc.data[SC_DEVOTION] && (d_bl = map->id2bl(dstsd->sc.data[SC_DEVOTION]->val1)) != NULL ) clif->devotion(d_bl, sd); @@ -4131,20 +4133,8 @@ int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int damage, i /// Sends a 'damage' packet (src performs action on dst) /// 008a <src ID>.L <dst ID>.L <server tick>.L <src speed>.L <dst speed>.L <damage>.W <div>.W <type>.B <damage2>.W (ZC_NOTIFY_ACT) /// 02e1 <src ID>.L <dst ID>.L <server tick>.L <src speed>.L <dst speed>.L <damage>.L <div>.W <type>.B <damage2>.L (ZC_NOTIFY_ACT2) -/// type: -/// 0 = damage [ damage: total damage, div: amount of hits, damage2: assassin dual-wield damage ] -/// 1 = pick up item -/// 2 = sit down -/// 3 = stand up -/// 4 = damage (endure) -/// 5 = (splash?) -/// 6 = (skill?) -/// 7 = (repeat damage?) -/// 8 = multi-hit damage -/// 9 = multi-hit damage (endure) -/// 10 = critical hit -/// 11 = lucky dodge -/// 12 = (touch skill?) +/// type: @see enum battle_dmg_type +/// for BDT_NORMAL: [ damage: total damage, div: amount of hits, damage2: assassin dual-wield damage ] int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int ddelay, int64 in_damage, short div, unsigned char type, int64 in_damage2) { struct packet_damage p; struct status_change *sc; @@ -4222,7 +4212,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int *------------------------------------------*/ void clif_takeitem(struct block_list* src, struct block_list* dst) { - //clif->damage(src,dst,0,0,0,0,1,0); + //clif->damage(src,dst,0,0,0,0,BDT_PICKUP,0); unsigned char buf[32]; nullpo_retv(src); @@ -4576,15 +4566,23 @@ void clif_skillinfoblock(struct map_session_data *sd) WFIFOW(fd,0) = 0x10f; for ( i = 0, len = 4; i < MAX_SKILL; i++) { if( (id = sd->status.skill[i].id) != 0 ) { + int level; // workaround for bugreport:5348 if (len + 37 > 8192) break; - WFIFOW(fd,len) = id; - WFIFOL(fd,len+2) = skill->get_inf(id); - WFIFOW(fd,len+6) = sd->status.skill[i].lv; - WFIFOW(fd,len+8) = skill->get_sp(id,sd->status.skill[i].lv); - WFIFOW(fd,len+10)= skill->get_range2(&sd->bl, id,sd->status.skill[i].lv); + WFIFOW(fd, len) = id; + WFIFOL(fd, len + 2) = skill->get_inf(id); + level = sd->status.skill[i].lv; + WFIFOW(fd, len + 6) = level; + if (level) { + WFIFOW(fd, len + 8) = skill->get_sp(id, level); + WFIFOW(fd, len + 10)= skill->get_range2(&sd->bl, id, level); + } + else { + WFIFOW(fd, len + 8) = 0; + WFIFOW(fd, len + 10)= 0; + } safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) WFIFOB(fd,len+36) = (sd->status.skill[i].lv < skill->tree_get_max(id, sd->status.class_))? 1:0; @@ -4612,26 +4610,33 @@ void clif_skillinfoblock(struct map_session_data *sd) /// 0111 <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradable>.B void clif_addskill(struct map_session_data *sd, int id) { - int fd, idx = skill->get_index(id); + int fd, skill_lv, idx = skill->get_index(id); nullpo_retv(sd); fd = sd->fd; if (!fd) return; - if( sd->status.skill[idx].id <= 0 ) + if (sd->status.skill[idx].id <= 0) return; + skill_lv = sd->status.skill[idx].lv; + WFIFOHEAD(fd, packet_len(0x111)); WFIFOW(fd,0) = 0x111; WFIFOW(fd,2) = id; WFIFOL(fd,4) = skill->get_inf(id); - WFIFOW(fd,8) = sd->status.skill[idx].lv; - WFIFOW(fd,10) = skill->get_sp(id,sd->status.skill[idx].lv); - WFIFOW(fd,12)= skill->get_range2(&sd->bl, id,sd->status.skill[idx].lv); + WFIFOW(fd,8) = skill_lv; + if (skill_lv > 0) { + WFIFOW(fd,10) = skill->get_sp(id, skill_lv); + WFIFOW(fd,12) = skill->get_range2(&sd->bl, id, skill_lv); + } else { + WFIFOW(fd,10) = 0; + WFIFOW(fd,12) = 0; + } safestrncpy((char*)WFIFOP(fd,14), skill->get_name(id), NAME_LENGTH); - if( sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT ) - WFIFOB(fd,38) = (sd->status.skill[idx].lv < skill->tree_get_max(id, sd->status.class_))? 1:0; + if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) + WFIFOB(fd,38) = (skill_lv < skill->tree_get_max(id, sd->status.class_))? 1:0; else WFIFOB(fd,38) = 0; WFIFOSET(fd,packet_len(0x111)); @@ -4691,16 +4696,22 @@ void clif_skillinfo(struct map_session_data *sd,int skill_id, int inf) { const int fd = sd->fd; int idx = skill->get_index(skill_id); + int skill_lv = sd->status.skill[idx].lv; WFIFOHEAD(fd,packet_len(0x7e1)); WFIFOW(fd,0) = 0x7e1; WFIFOW(fd,2) = skill_id; WFIFOL(fd,4) = inf?inf:skill->get_inf(skill_id); - WFIFOW(fd,8) = sd->status.skill[idx].lv; - WFIFOW(fd,10) = skill->get_sp(skill_id,sd->status.skill[idx].lv); - WFIFOW(fd,12) = skill->get_range2(&sd->bl,skill_id,sd->status.skill[idx].lv); - if( sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT ) - WFIFOB(fd,14) = (sd->status.skill[idx].lv < skill->tree_get_max(skill_id, sd->status.class_))? 1:0; + WFIFOW(fd,8) = skill_lv; + if (skill_lv > 0) { + WFIFOW(fd,10) = skill->get_sp(skill_id, skill_lv); + WFIFOW(fd,12) = skill->get_range2(&sd->bl, skill_id, skill_lv); + } else { + WFIFOW(fd,10) = 0; + WFIFOW(fd,12) = 0; + } + if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) + WFIFOB(fd,14) = (skill_lv < skill->tree_get_max(skill_id, sd->status.class_))? 1:0; else WFIFOB(fd,14) = 0; WFIFOSET(fd,packet_len(0x7e1)); @@ -5179,13 +5190,13 @@ void clif_skill_produce_mix_list(struct map_session_data *sd, int skill_id , int WFIFOW(fd, 0)=0x18d; for(i=0,c=0;i<MAX_SKILL_PRODUCE_DB;i++){ - if( skill->can_produce_mix(sd,skill->produce_db[i].nameid, trigger, 1) && - ( ( skill_id > 0 && skill->produce_db[i].req_skill == skill_id ) || skill_id < 0 ) + if( skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid, trigger, 1) && + ( ( skill_id > 0 && skill->dbs->produce_db[i].req_skill == skill_id ) || skill_id < 0 ) ){ - if((view = itemdb_viewid(skill->produce_db[i].nameid)) > 0) + if((view = itemdb_viewid(skill->dbs->produce_db[i].nameid)) > 0) WFIFOW(fd,c*8+ 4)= view; else - WFIFOW(fd,c*8+ 4)= skill->produce_db[i].nameid; + WFIFOW(fd,c*8+ 4)= skill->dbs->produce_db[i].nameid; WFIFOW(fd,c*8+ 6)= 0; WFIFOW(fd,c*8+ 8)= 0; WFIFOW(fd,c*8+10)= 0; @@ -5226,13 +5237,13 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id c = 0; for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) { - if( !skill->can_produce_mix(sd,skill->produce_db[i].nameid,trigger, qty) ) + if( !skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid,trigger, qty) ) continue; - if( (view = itemdb_viewid(skill->produce_db[i].nameid)) > 0 ) + if( (view = itemdb_viewid(skill->dbs->produce_db[i].nameid)) > 0 ) WFIFOW(fd, 6 + 2 * c) = view; else - WFIFOW(fd, 6 + 2 * c) = skill->produce_db[i].nameid; + WFIFOW(fd, 6 + 2 * c) = skill->dbs->produce_db[i].nameid; c++; } @@ -5256,7 +5267,7 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id if( skill_id != AM_PHARMACY ) { // AM_PHARMACY is used to Cooking. // It fails. #if PACKETVER >= 20090922 - clif->msg_skill(sd,skill_id,0x625); + clif->msgtable_skill(sd, skill_id, MSG_COOKING_LIST_FAIL); #else WFIFOW(fd,2) = 6 + 2 * c; WFIFOSET(fd,WFIFOW(fd,2)); @@ -5338,7 +5349,7 @@ void clif_displaymessage(const int fd, const char* mes) { #if PACKETVER == 20141022 /** for some reason game client crashes depending on message pattern (only for this packet) **/ /** so we redirect to ZC_NPC_CHAT **/ - clif->colormes(fd,COLOR_DEFAULT,mes); + clif->messagecolor_self(fd, COLOR_DEFAULT, mes); #else size_t len; @@ -5558,6 +5569,7 @@ void clif_map_type(struct map_session_data* sd, enum map_type type) { /// Updates PvP ranking (ZC_NOTIFY_RANKING). /// 019a <id>.L <ranking>.L <total>.L +// FIXME: missing documentation for the 'type' parameter void clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type) { if(type == 2) { @@ -5703,54 +5715,30 @@ void clif_solved_charname(int fd, int charid, const char* name) /// 017b <packet len>.W { <name id>.W }* void clif_use_card(struct map_session_data *sd,int idx) { - int i,c,ep; - int fd=sd->fd; + int i, c; + int fd; nullpo_retv(sd); - if (idx < 0 || idx >= MAX_INVENTORY) //Crash-fix from bad packets. + fd = sd->fd; + if (sd->state.trading != 0) + return; + if (!pc->can_insert_card(sd, idx)) return; - if (!sd->inventory_data[idx] || sd->inventory_data[idx]->type != IT_CARD) - return; //Avoid parsing invalid item indexes (no card/no item) - - ep=sd->inventory_data[idx]->equip; - WFIFOHEAD(fd,MAX_INVENTORY * 2 + 4); - WFIFOW(fd,0)=0x17b; - - for(i=c=0;i<MAX_INVENTORY;i++){ - int j; - - if(sd->inventory_data[i] == NULL) - continue; - if(sd->inventory_data[i]->type!=IT_WEAPON && sd->inventory_data[i]->type!=IT_ARMOR) - continue; - if(itemdb_isspecial(sd->status.inventory[i].card[0])) //Can't slot it - continue; - - if (sd->status.inventory[i].identify == 0) //Not identified - continue; - - if ((sd->inventory_data[i]->equip&ep) == 0) //Not equippable on this part. - continue; - - if(sd->inventory_data[i]->type==IT_WEAPON && ep==EQP_SHIELD) //Shield card won't go on left weapon. - continue; - - ARR_FIND( 0, sd->inventory_data[i]->slot, j, sd->status.inventory[i].card[j] == 0 ); - if (j == sd->inventory_data[i]->slot) // No room - continue; + WFIFOHEAD(fd, MAX_INVENTORY * 2 + 4); + WFIFOW(fd, 0) = 0x17b; - if( sd->status.inventory[i].equip > 0 ) // Do not check items that are already equipped + for (i = c = 0; i < MAX_INVENTORY; i++) { + if (!pc->can_insert_card_into(sd, idx, i)) continue; - - WFIFOW(fd,4+c*2)=i+2; + WFIFOW(fd, 4 + c * 2) = i + 2; c++; } - if( !c ) return; // no item is available for card insertion + if (!c) return; // no item is available for card insertion - WFIFOW(fd,2)=4+c*2; - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOW(fd, 2) = 4 + c * 2; + WFIFOSET(fd, WFIFOW(fd, 2)); } @@ -6183,6 +6171,14 @@ void clif_openvending(struct map_session_data* sd, int id, struct s_vending* ven clif->addcards(WFIFOP(fd,22+i*22), &sd->status.cart[index]); } WFIFOSET(fd,WFIFOW(fd,2)); + +#if PACKETVER >= 20141022 + /** should go elsewhere perhaps? it has to be bundled with this however. **/ + WFIFOHEAD(fd, 3); + WFIFOW(fd, 0) = 0xa28; + WFIFOB(fd, 2) = 0;/** 1 is failure. our current responses to failure are working so not yet implemented **/ + WFIFOSET(fd, 3); +#endif } @@ -6877,7 +6873,7 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd) if( sd == NULL ) return; - for( i = 0; i < 5; i++ ) + for( i = 0; i < MAX_PC_DEVOTION; i++ ) WBUFL(buf,6+4*i) = sd->devotion[i]; WBUFW(buf,26) = skill->get_range2(src, CR_DEVOTION, pc->checkskill(sd, CR_DEVOTION)); } @@ -7034,9 +7030,7 @@ void clif_guild_created(struct map_session_data *sd,int flag) /// Notifies the client that it is belonging to a guild (ZC_UPDATE_GDID). /// 016c <guild id>.L <emblem id>.L <mode>.L <ismaster>.B <inter sid>.L <guild name>.24B -/// mode: -/// &0x01 = allow invite -/// &0x10 = allow expel +/// mode: @see enum guild_permission void clif_guild_belonginfo(struct map_session_data *sd, struct guild *g) { int ps,fd; @@ -7286,9 +7280,7 @@ void clif_guild_positionnamelist(struct map_session_data *sd) { /// Guild position information (ZC_POSITION_INFO). /// 0160 <packet len>.W { <position id>.L <mode>.L <ranking>.L <pay rate>.L }* -/// mode: -/// &0x01 = allow invite -/// &0x10 = allow expel +/// mode: @see enum guild_permission /// ranking: /// TODO void clif_guild_positioninfolist(struct map_session_data *sd) { @@ -7316,9 +7308,7 @@ void clif_guild_positioninfolist(struct map_session_data *sd) { /// Notifies clients in a guild about updated position information (ZC_ACK_CHANGE_GUILD_POSITIONINFO). /// 0174 <packet len>.W { <position id>.L <mode>.L <ranking>.L <pay rate>.L <position name>.24B }* -/// mode: -/// &0x01 = allow invite -/// &0x10 = allow expel +/// mode: @see enum guild_permission /// ranking: /// TODO void clif_guild_positionchanged(struct guild *g,int idx) @@ -7432,8 +7422,13 @@ void clif_guild_skillinfo(struct map_session_data* sd) WFIFOW(fd,p+0) = id; WFIFOL(fd,p+2) = skill->get_inf(id); WFIFOW(fd,p+6) = g->skill[i].lv; - WFIFOW(fd,p+8) = skill->get_sp(id, g->skill[i].lv); - WFIFOW(fd,p+10) = skill->get_range(id, g->skill[i].lv); + if ( g->skill[i].lv ) { + WFIFOW(fd, p + 8) = skill->get_sp(id, g->skill[i].lv); + WFIFOW(fd, p + 10) = skill->get_range(id, g->skill[i].lv); + } else { + WFIFOW(fd, p + 8) = 0; + WFIFOW(fd, p + 10) = 0; + } safestrncpy((char*)WFIFOP(fd,p+12), skill->get_name(id), NAME_LENGTH); WFIFOB(fd,p+36)= (g->skill[i].lv < guild->skill_get_max(id) && sd == g->member[0].sd) ? 1 : 0; c++; @@ -8107,28 +8102,41 @@ void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, sen clif->send(buf, packet_len(0x284), bl, SELF); } } -// Modification of clif_messagecolor to send colored messages to players to chat log only (doesn't display overhead) -/// 02c1 <packet len>.W <id>.L <color>.L <message>.?B -int clif_colormes(int fd, enum clif_colors color, const char* msg) { +/** + * Modification of clif_messagecolor to send colored messages to players to chat log only (doesn't display overhead). + * + * 02c1 <packet len>.W <id>.L <color>.L <message>.?B + * + * @param fd Target fd to send the message to + * @param color Message color (RGB format: 0xRRGGBB) + * @param msg Message text + */ +void clif_messagecolor_self(int fd, uint32 color, const char *msg) +{ size_t msg_len = strlen(msg) + 1; WFIFOHEAD(fd,msg_len + 12); WFIFOW(fd,0) = 0x2C1; WFIFOW(fd,2) = msg_len + 12; WFIFOL(fd,4) = 0; - WFIFOL(fd,8) = color_table[color]; + WFIFOL(fd,8) = RGB2BGR(color); safestrncpy((char*)WFIFOP(fd,12), msg, msg_len); WFIFOSET(fd, msg_len + 12); - - return 0; } -/// Monster/NPC color chat [SnakeDrak] (ZC_NPC_CHAT). -/// 02c1 <packet len>.W <id>.L <color>.L <message>.?B -void clif_messagecolor(struct block_list* bl, unsigned int color, const char* msg) { +/** + * Monster/NPC color chat [SnakeDrak] (ZC_NPC_CHAT). + * + * 02c1 <packet len>.W <id>.L <color>.L <message>.?B + * + * @param bl Source block list. + * @param color Message color (RGB format: 0xRRGGBB) + * @param msg Message text + */ +void clif_messagecolor(struct block_list* bl, uint32 color, const char *msg) +{ size_t msg_len = strlen(msg) + 1; uint8 buf[256]; - color = (color & 0x0000FF) << 16 | (color & 0x00FF00) | (color & 0xFF0000) >> 16; // RGB to BGR nullpo_retv(bl); @@ -8140,48 +8148,29 @@ void clif_messagecolor(struct block_list* bl, unsigned int color, const char* ms WBUFW(buf,0) = 0x2C1; WBUFW(buf,2) = msg_len + 12; WBUFL(buf,4) = bl->id; - WBUFL(buf,8) = color; + WBUFL(buf,8) = RGB2BGR(color); memcpy(WBUFP(buf,12), msg, msg_len); clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); } -/// Public chat message [Valaris] (ZC_NOTIFY_CHAT). -/// 008d <packet len>.W <id>.L <message>.?B -void clif_message(struct block_list* bl, const char* msg) { - unsigned short msg_len = strlen(msg) + 1; - uint8 buf[256]; - nullpo_retv(bl); - - if( msg_len > sizeof(buf)-8 ) { - ShowWarning("clif_message: Truncating too long message '%s' (len=%u).\n", msg, msg_len); - msg_len = sizeof(buf)-8; - } - - WBUFW(buf,0) = 0x8d; - WBUFW(buf,2) = msg_len + 8; - WBUFL(buf,4) = bl->id; - safestrncpy((char*)WBUFP(buf,8), msg, msg_len); - - clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); -} - /** * Notifies the client that the storage window is still open * * Should only be used in cases where the client closed the * storage window without server's consent **/ -void clif_refresh_storagewindow( struct map_session_data *sd ) { +void clif_refresh_storagewindow(struct map_session_data *sd) +{ // Notify the client that the storage is open - if( sd->state.storage_flag == 1 ) { + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) { storage->sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); clif->storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); } // Notify the client that the gstorage is open otherwise it will // remain locked forever and nobody will be able to access it - if( sd->state.storage_flag == 2 ) { + if (sd->state.storage_flag == STORAGE_FLAG_GUILD) { struct guild_storage *gstor; if( (gstor = idb_get(gstorage->db,sd->status.guild_id)) == NULL) { // Shouldn't happen... The information should already be at the map-server @@ -8231,7 +8220,7 @@ void clif_refresh(struct map_session_data *sd) map->foreachinrange(clif->getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd); clif->weather_check(sd); if( sd->chatID ) - chat->leave(sd,0); + chat->leave(sd, false); if( sd->state.vending ) clif->openvending(sd, sd->bl.id, sd->vending); if( pc_issit(sd) ) @@ -8712,9 +8701,15 @@ void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* ts } -/// Display msgstringtable.txt string (ZC_MSG). -/// 0291 <message>.W -void clif_msg(struct map_session_data* sd, unsigned short id) +/** + * Displays a string from msgstringtable.txt (ZC_MSG). + * + * 0291 <msg id>.W + * + * @param sd The target character. + * @param msg_id msgstringtable message index, 0-based (@see enum clif_messages) + */ +void clif_msgtable(struct map_session_data* sd, unsigned short msg_id) { int fd; nullpo_retv(sd); @@ -8722,31 +8717,47 @@ void clif_msg(struct map_session_data* sd, unsigned short id) WFIFOHEAD(fd, packet_len(0x291)); WFIFOW(fd, 0) = 0x291; - WFIFOW(fd, 2) = id; // zero-based msgstringtable.txt index + WFIFOW(fd, 2) = msg_id; // zero-based msgstringtable.txt index WFIFOSET(fd, packet_len(0x291)); } - -/// Display msgstringtable.txt string and fill in a valid for %d format (ZC_MSG_VALUE). -/// 0x7e2 <message>.W <value>.L -void clif_msg_value(struct map_session_data* sd, unsigned short id, int value) +/** + * Displays a format string from msgstringtable.txt with a %d value (ZC_MSG_VALUE). + * + * 0x7e2 <msg id>.W <value>.L + * + * @param sd The target character. + * @param msg_id msgstringtable message index, 0-based (@see enum clif_messages) + * @param value The value to fill %d. + */ +void clif_msgtable_num(struct map_session_data *sd, unsigned short msg_id, int value) { - int fd = sd->fd; +#if PACKETVER >= 20090805 + int fd; + nullpo_retv(sd); + fd = sd->fd; WFIFOHEAD(fd, packet_len(0x7e2)); - WFIFOW(fd,0) = 0x7e2; - WFIFOW(fd,2) = id; - WFIFOL(fd,4) = value; + WFIFOW(fd, 0) = 0x7e2; + WFIFOW(fd, 2) = msg_id; + WFIFOL(fd, 4) = value; WFIFOSET(fd, packet_len(0x7e2)); +#endif } - -/// Displays msgstringtable.txt string, prefixed with a skill name. (ZC_MSG_SKILL). -/// 07e6 <skill id>.W <msg id>.L -/// -/// NOTE: Message has following format and is printed in color 0xCDCDFF (purple): -/// "[SkillName] Message" -void clif_msg_skill(struct map_session_data* sd, uint16 skill_id, int msg_id) +/** + * Displays a string from msgstringtable.txt, prefixed with a skill name (ZC_MSG_SKILL). + * + * 07e6 <skill id>.W <msg id>.L + * + * NOTE: Message has following format and is printed in color 0xCDCDFF (purple): + * "[SkillName] Message" + * + * @param sd The target character. + * @param skill_id ID of the skill to display. + * @param msg_id msgstringtable message index, 0-based (@see enum clif_messages) + */ +void clif_msgtable_skill(struct map_session_data* sd, uint16 skill_id, int msg_id) { int fd = sd->fd; @@ -8857,12 +8868,13 @@ void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, ch DBIterator *iter = db_iterator(chan->users); struct map_session_data *user; unsigned short msg_len = strlen(msg) + 1; + uint32 color = channel->config->colors[chan->color]; WFIFOHEAD(sd->fd,msg_len + 12); WFIFOW(sd->fd,0) = 0x2C1; WFIFOW(sd->fd,2) = msg_len + 12; WFIFOL(sd->fd,4) = 0; - WFIFOL(sd->fd,8) = channel->config->colors[chan->color]; + WFIFOL(sd->fd,8) = RGB2BGR(color); safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len); for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) { @@ -8884,11 +8896,12 @@ void clif_channel_msg2(struct channel_data *chan, char *msg) struct map_session_data *user; unsigned char buf[210]; unsigned short msg_len = strlen(msg) + 1; + uint32 color = channel->config->colors[chan->color]; WBUFW(buf,0) = 0x2C1; WBUFW(buf,2) = msg_len + 12; WBUFL(buf,4) = 0; - WBUFL(buf,8) = channel->config->colors[chan->color]; + WBUFL(buf,8) = RGB2BGR(color); safestrncpy((char*)WBUFP(buf,12), msg, msg_len); for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) { @@ -8984,9 +8997,6 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) { /// Notification from the client, that it has finished map loading and is about to display player's character (CZ_NOTIFY_ACTORINIT). /// 007d void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { -#if PACKETVER >= 20090218 - int i; -#endif bool first_time = false; if(sd->bl.prev != NULL) @@ -9171,10 +9181,13 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { //Auron reported that This skill only triggers when you logon on the map o.O [Skotlex] if ((lv = pc->checkskill(sd,SG_KNOWLEDGE)) > 0) { - if(sd->bl.m == sd->feel_map[0].m - || sd->bl.m == sd->feel_map[1].m - || sd->bl.m == sd->feel_map[2].m) - sc_start(NULL,&sd->bl, SC_KNOWLEDGE, 100, lv, skill->get_time(SG_KNOWLEDGE, lv)); + int i; + for (i = 0; i < MAX_PC_FEELHATE; i++) { + if (sd->bl.m == sd->feel_map[i].m) { + sc_start(NULL,&sd->bl, SC_KNOWLEDGE, 100, lv, skill->get_time(SG_KNOWLEDGE, lv)); + break; + } + } } if(sd->pd && sd->pd->pet.intimate > 900) @@ -9202,14 +9215,16 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { clif->updatestatus(sd,SP_DEX); clif->updatestatus(sd,SP_LUK); - // abort currently running script - sd->state.using_fake_npc = 0; - sd->state.menu_or_input = 0; - sd->npc_menu = 0; - - if(sd->npc_id) - npc->event_dequeue(sd); - + if (sd->state.warp_clean) { + // abort currently running script + sd->state.using_fake_npc = 0; + sd->state.menu_or_input = 0; + sd->npc_menu = 0; + if(sd->npc_id) + npc->event_dequeue(sd); + } else { + sd->state.warp_clean = 1; + } if( sd->guild && ( battle_config.guild_notice_changemap == 2 || ( battle_config.guild_notice_changemap == 1 && sd->state.changemap ) ) ) clif->guild_notice(sd,sd->guild); } @@ -9254,6 +9269,9 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { if (channel->config->local && channel->config->local_autojoin) { channel->map_join(sd); } + if (channel->config->irc && channel->config->irc_autojoin) { + channel->irc_join(sd); + } } mail->clear(sd); @@ -9317,14 +9335,17 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { // NPC Quest / Event Icon Check [Kisuka] #if PACKETVER >= 20090218 - for(i = 0; i < map->list[sd->bl.m].qi_count; i++) { - struct questinfo *qi = &map->list[sd->bl.m].qi_data[i]; - if( quest->check(sd, qi->quest_id, HAVEQUEST) == -1 ) {// Check if quest is not started - if( qi->hasJob ) { // Check if quest is job-specific, check is user is said job class. - if( sd->class_ == qi->job ) + { + int i; + for(i = 0; i < map->list[sd->bl.m].qi_count; i++) { + struct questinfo *qi = &map->list[sd->bl.m].qi_data[i]; + if( quest->check(sd, qi->quest_id, HAVEQUEST) == -1 ) {// Check if quest is not started + if( qi->hasJob ) { // Check if quest is job-specific, check is user is said job class. + if( sd->class_ == qi->job ) + clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color); + } else { clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color); - } else { - clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color); + } } } } @@ -9633,6 +9654,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) } else if ( sd->fontcolor && !sd->chatID ) { char mout[200]; unsigned char mylen = 1; + uint32 color = 0; if( sd->disguise == -1 ) { sd->fontcolor_tid = timer->add(timer->gettick()+5000, clif->undisguise_timer, sd->bl.id, 0); @@ -9650,11 +9672,12 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) mylen += snprintf(mout, 200, "%s : %s",sd->fakename[0]?sd->fakename:sd->status.name,message); + color = channel->config->colors[sd->fontcolor - 1]; WFIFOHEAD(fd,mylen + 12); WFIFOW(fd,0) = 0x2C1; WFIFOW(fd,2) = mylen + 12; WFIFOL(fd,4) = sd->bl.id; - WFIFOL(fd,8) = channel->config->colors[sd->fontcolor - 1]; + WFIFOL(fd,8) = RGB2BGR(color); safestrncpy((char*)WFIFOP(fd,12), mout, mylen); clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS); WFIFOL(fd,4) = -sd->bl.id; @@ -9841,7 +9864,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, return; if(action_type != 0x00 && action_type != 0x07) - pc_stop_walking(sd, 1); + pc_stop_walking(sd, STOPWALKING_FLAG_FIXPOS); pc_stop_attack(sd); if(target_id<0 && -target_id == sd->bl.id) // for disguises [Valaris] @@ -10245,7 +10268,7 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) { if( sd->npc_id ) { if ( !sd->npc_item_flag ) return; - } else if ( sd->state.storage_flag || sd->sc.opt1 ) + } else if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->sc.opt1) ; //You can equip/unequip stuff while storage is open/under status changes else if ( pc_cant_act2(sd) || sd->state.prerefining ) return; @@ -10287,7 +10310,7 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd) if( sd->npc_id ) { if ( !sd->npc_item_flag ) return; - } else if ( sd->state.storage_flag || sd->sc.opt1 ) + } else if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->sc.opt1) ; //You can equip/unequip stuff while storage is open/under status changes else if ( pc_cant_act2(sd) || sd->state.prerefining ) return; @@ -10297,7 +10320,7 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd) if( battle_config.idletime_criteria & BCIDLE_USEITEM ) sd->idletime = sockt->last_tick; - pc->unequipitem(sd,index,1); + pc->unequipitem(sd,index, PCUNEQUIPITEM_RECALC); } @@ -10315,7 +10338,7 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd) } if( sd->npc_id || sd->state.workinprogress&2 ){ #ifdef RENEWAL - clif->msg(sd, 0x783); // TODO look for the client date that has this message. + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message. #endif return; } @@ -10330,7 +10353,7 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd) case BL_NPC: if( sd->ud.skill_id < RK_ENCHANTBLADE && sd->ud.skilltimer != INVALID_TIMER ) {// TODO: should only work with none 3rd job skills #ifdef RENEWAL - clif->msg(sd, 0x783); + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); #endif break; } @@ -10525,7 +10548,7 @@ void clif_parse_KickFromChat(int fd,struct map_session_data *sd) /// 00e3 void clif_parse_ChatLeave(int fd, struct map_session_data* sd) { - chat->leave(sd,0); + chat->leave(sd, false); } @@ -10682,7 +10705,7 @@ void clif_parse_ChangeCart(int fd,struct map_session_data *sd) #ifdef RENEWAL if( sd->npc_id || sd->state.workinprogress&1 ){ - clif->msg(sd, 0x783); + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); return; } #endif @@ -10872,7 +10895,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) if( sd->npc_id || sd->state.workinprogress&1 ){ #ifdef RENEWAL - clif->msg(sd, 0x783); // TODO look for the client date that has this message. + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message. #endif return; } @@ -10880,7 +10903,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) if( pc_cant_act(sd) && skill_id != RK_REFRESH && !(skill_id == SR_GENTLETOUCH_CURE && (sd->sc.opt1 == OPT1_STONE || sd->sc.opt1 == OPT1_FREEZE || sd->sc.opt1 == OPT1_STUN)) - && ( sd->state.storage_flag && !(tmp&INF_SELF_SKILL) ) // SELF skills can be used with the storage open, issue: 8027 + && (sd->state.storage_flag != STORAGE_FLAG_CLOSED && !(tmp&INF_SELF_SKILL)) // SELF skills can be used with the storage open, issue: 8027 ) return; @@ -10968,7 +10991,7 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski #ifdef RENEWAL if( sd->state.workinprogress&1 ){ - clif->msg(sd, 0x783); // TODO look for the client date that has this message. + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message. return; } #endif @@ -11085,7 +11108,7 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd) return; // It is possible to use teleport with the storage window open issue:8027 - if( pc_cant_act(sd) && (!sd->state.storage_flag && skill_id != AL_TELEPORT) ) { + if (pc_cant_act(sd) && (sd->state.storage_flag == STORAGE_FLAG_CLOSED && skill_id != AL_TELEPORT)) { clif_menuskill_clear(sd); return; } @@ -11349,8 +11372,6 @@ void clif_parse_AutoSpell(int fd,struct map_session_data *sd) /// 017a <card index>.W void clif_parse_UseCard(int fd,struct map_session_data *sd) { - if (sd->state.trading != 0) - return; clif->use_card(sd,RFIFOW(fd,2)-2); } @@ -11359,8 +11380,6 @@ void clif_parse_UseCard(int fd,struct map_session_data *sd) /// 017c <card index>.W <equip index>.W void clif_parse_InsertCard(int fd,struct map_session_data *sd) { - if (sd->state.trading != 0) - return; pc->insert_card(sd,RFIFOW(fd,2)-2,RFIFOW(fd,4)-2); } @@ -11428,9 +11447,9 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) if (item_index < 0 || item_index >= MAX_INVENTORY || item_amount < 1) return; - if (sd->state.storage_flag == 1) + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) storage->add(sd, item_index, item_amount); - else if (sd->state.storage_flag == 2) + else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->add(sd, item_index, item_amount); } @@ -11446,9 +11465,9 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) item_index = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-1; item_amount = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[1]); - if (sd->state.storage_flag == 1) + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) storage->get(sd, item_index, item_amount); - else if(sd->state.storage_flag == 2) + else if(sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->get(sd, item_index, item_amount); } @@ -11462,9 +11481,9 @@ void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd) if (!pc_iscarton(sd)) return; - if (sd->state.storage_flag == 1) + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) storage->addfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4)); - else if (sd->state.storage_flag == 2) + else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->addfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4)); } @@ -11478,9 +11497,9 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd) if (!pc_iscarton(sd)) return; - if (sd->state.storage_flag == 1) + if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) storage->gettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4)); - else if (sd->state.storage_flag == 2) + else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->gettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4)); } @@ -11489,9 +11508,9 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd) /// 00f7 void clif_parse_CloseKafra(int fd, struct map_session_data *sd) { - if( sd->state.storage_flag == 1 ) + if( sd->state.storage_flag == STORAGE_FLAG_NORMAL ) storage->close(sd); - else if( sd->state.storage_flag == 2 ) + else if( sd->state.storage_flag == STORAGE_FLAG_GUILD ) gstorage->close(sd); } @@ -12701,7 +12720,7 @@ bool clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_sessi return false; } - if ( t_sd && t_sd->state.noask ) {// @noask [LuzZza] + if (t_sd->state.noask) {// @noask [LuzZza] clif->noask_sub(sd, t_sd, 2); return false; } @@ -14142,7 +14161,7 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd) { if (item_position == INDEX_NOT_FOUND) status_change_end(&sd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER); else - pc->delitem(sd, item_position, 1, 0, 1, LOG_TYPE_CONSUME); + pc->delitem(sd, item_position, 1, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); } @@ -14672,7 +14691,7 @@ void clif_Auction_openwindow(struct map_session_data *sd) { int fd = sd->fd; - if( sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading ) + if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->state.vending || sd->state.buyingstore || sd->state.trading) return; if( !battle_config.feature_auction ) @@ -14918,7 +14937,7 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) { int zeny = auction.hours*battle_config.auction_feeperhour; - pc->delitem(sd, sd->auction.index, sd->auction.amount, 1, 6, LOG_TYPE_AUCTION); + pc->delitem(sd, sd->auction.index, sd->auction.amount, 1, DELITEM_SOLD, LOG_TYPE_AUCTION); sd->auction.amount = 0; pc->payzeny(sd, zeny, LOG_TYPE_AUCTION, NULL); @@ -15269,7 +15288,7 @@ void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd) { if( tsd->status.show_equip || pc_has_permission(sd, PC_PERM_VIEW_EQUIPMENT) ) clif->viewequip_ack(sd, tsd); else - clif_viewequip_fail(sd); + clif->msgtable(sd, MSG_EQUIP_NOT_PUBLIC); } @@ -15632,8 +15651,13 @@ void clif_mercenary_skillblock(struct map_session_data *sd) WFIFOW(fd,len) = id; WFIFOL(fd,len+2) = skill->get_inf(id); WFIFOW(fd,len+6) = md->db->skill[j].lv; - WFIFOW(fd,len+8) = skill->get_sp(id, md->db->skill[j].lv); - WFIFOW(fd,len+10) = skill->get_range2(&md->bl, id, md->db->skill[j].lv); + if ( md->db->skill[j].lv ) { + WFIFOW(fd, len + 8) = skill->get_sp(id, md->db->skill[j].lv); + WFIFOW(fd, len + 10) = skill->get_range2(&md->bl, id, md->db->skill[j].lv); + } else { + WFIFOW(fd, len + 8) = 0; + WFIFOW(fd, len + 10) = 0; + } safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); WFIFOB(fd,len+36) = 0; // Skillable for Mercenary? len += 37; @@ -15667,7 +15691,7 @@ void clif_parse_mercenary_action(int fd, struct map_session_data* sd) /// 3 = Your mercenary soldier has ran away. void clif_mercenary_message(struct map_session_data* sd, int message) { - clif->msg(sd, 1266 + message); + clif->msgtable(sd, MSG_MERCENARY_EXPIRED + message); } @@ -16701,11 +16725,11 @@ int clif_elementalconverter_list(struct map_session_data *sd) { WFIFOW(fd, 0)=0x1ad; for(i=0,c=0;i<MAX_SKILL_PRODUCE_DB;i++){ - if( skill->can_produce_mix(sd,skill->produce_db[i].nameid,23, 1) ){ - if((view = itemdb_viewid(skill->produce_db[i].nameid)) > 0) + if( skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid,23, 1) ){ + if((view = itemdb_viewid(skill->dbs->produce_db[i].nameid)) > 0) WFIFOW(fd,c*2+ 4)= view; else - WFIFOW(fd,c*2+ 4)= skill->produce_db[i].nameid; + WFIFOW(fd,c*2+ 4)= skill->dbs->produce_db[i].nameid; c++; } } @@ -16903,26 +16927,6 @@ int clif_skill_itemlistwindow( struct map_session_data *sd, uint16 skill_id, uin return 1; } -// msgstringtable.txt -// 0x291 <line>.W -void clif_msgtable(int fd, int line) { - WFIFOHEAD(fd, packet_len(0x291)); - WFIFOW(fd, 0) = 0x291; - WFIFOW(fd, 2) = line; - WFIFOSET(fd, packet_len(0x291)); -} - -// msgstringtable.txt -// 0x7e2 <line>.W <value>.L -void clif_msgtable_num(int fd, int line, int num) { -#if PACKETVER >= 20090805 - WFIFOHEAD(fd, packet_len(0x7e2)); - WFIFOW(fd, 0) = 0x7e2; - WFIFOW(fd, 2) = line; - WFIFOL(fd, 4) = num; - WFIFOSET(fd, packet_len(0x7e2)); -#endif -} /*========================================== * used by SC_AUTOSHADOWSPELL * RFIFOL(fd,2) - flag (currently not used) @@ -17062,7 +17066,7 @@ void clif_favorite_item(struct map_session_data* sd, unsigned short index) { WFIFOHEAD(fd,packet_len(0x908)); WFIFOW(fd,0) = 0x908; WFIFOW(fd,2) = index+2; - WFIFOL(fd,4) = (sd->status.inventory[index].favorite == 1) ? 0 : 1; + WFIFOB(fd,4) = (sd->status.inventory[index].favorite == 1) ? 0 : 1; WFIFOSET(fd,packet_len(0x908)); } @@ -17093,8 +17097,8 @@ void __attribute__ ((unused)) clif_parse_dull(int fd,struct map_session_data *sd } void clif_parse_CashShopOpen(int fd, struct map_session_data *sd) { - if( map->list[sd->bl.m].flag.nocashshop ) { - clif->colormes(fd,COLOR_RED,msg_fd(fd,1489)); //Cash Shop is disabled in this map + if (map->list[sd->bl.m].flag.nocashshop) { + clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1489)); //Cash Shop is disabled in this map return; } @@ -17134,8 +17138,8 @@ void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) { unsigned short limit = RFIFOW(fd, 4), i, j; unsigned int kafra_pay = RFIFOL(fd, 6);// [Ryuuzaki] - These are free cash points (strangely #CASH = main cash currently for us, confusing) - if( map->list[sd->bl.m].flag.nocashshop ) { - clif->colormes(fd,COLOR_RED,msg_fd(fd,1489)); //Cash Shop is disabled in this map + if (map->list[sd->bl.m].flag.nocashshop) { + clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1489)); //Cash Shop is disabled in this map return; } @@ -17536,8 +17540,8 @@ void clif_parse_BankDeposit(int fd, struct map_session_data* sd) { struct packet_banking_deposit_req *p = P2PTR(fd); int money; - if( !battle_config.feature_banking ) { - clif->colormes(fd,COLOR_RED,msg_fd(fd,1483)); + if (!battle_config.feature_banking) { + clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1483)); return; } @@ -17550,8 +17554,8 @@ void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) { struct packet_banking_withdraw_req *p = P2PTR(fd); int money; - if( !battle_config.feature_banking ) { - clif->colormes(fd,COLOR_RED,msg_fd(fd,1483)); + if (!battle_config.feature_banking) { + clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1483)); return; } @@ -17563,8 +17567,8 @@ void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) { void clif_parse_BankCheck(int fd, struct map_session_data* sd) { struct packet_banking_check p; - if( !battle_config.feature_banking ) { - clif->colormes(fd,COLOR_RED,msg_fd(fd,1483)); + if (!battle_config.feature_banking) { + clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1483)); return; } @@ -17639,7 +17643,7 @@ void clif_parse_GMFullStrip(int fd, struct map_session_data *sd) { for( i = 0; i < EQI_MAX; i++ ) { if( tsd->equip_index[ i ] >= 0 ) - pc->unequipitem( tsd , tsd->equip_index[ i ] , 2 ); + pc->unequipitem(tsd, tsd->equip_index[i], PCUNEQUIPITEM_FORCE); } } /** @@ -18093,6 +18097,157 @@ void clif_roulette_generate_ack(struct map_session_data *sd, unsigned char resul clif->send(&p,sizeof(p), &sd->bl, SELF); } +/** +* Stackable items merger +**/ +void clif_openmergeitem(int fd, struct map_session_data *sd) +{ + int i = 0, n = 0, j = 0; + struct merge_item merge_items[MAX_INVENTORY]; + struct merge_item *merge_items_[MAX_INVENTORY] = {0}; + + memset(&merge_items,'\0',sizeof(merge_items)); + + for (i = 0; i < MAX_INVENTORY; i++) { + struct item *item_data = &sd->status.inventory[i]; + + if (item_data->nameid == 0 || !itemdb->isstackable(item_data->nameid)) + continue; + + merge_items[n].nameid = item_data->nameid; + merge_items[n].position = i + 2; + n++; + + + } + + qsort(merge_items,n,sizeof(struct merge_item),clif->comparemergeitem); + + for (i = 0, j = 0; i < n; i++) { + if (i > 0 && merge_items[i].nameid == merge_items[i-1].nameid) + { + merge_items_[j] = &merge_items[i]; + j++; + continue; + } + + if (i < n - 1 && merge_items[i].nameid == merge_items[i+1].nameid) + { + merge_items_[j] = &merge_items[i]; + j++; + continue; + } + } + + WFIFOHEAD(fd,2*j+4); + WFIFOW(fd,0) = 0x96d; + WFIFOW(fd,2) = 2*j+4; + for ( i = 0; i < j; i++ ) + WFIFOW(fd,i*2+4) = merge_items_[i]->position; + WFIFOSET(fd,2*j+4); +} + +int clif_comparemergeitem(const void *a, const void *b) +{ + const struct merge_item *a_ = a; + const struct merge_item *b_ = b; + + if (a_->nameid == b_->nameid) + return 0; + return a_->nameid > b_->nameid ? -1 : 1; +} + +void clif_ackmergeitems(int fd, struct map_session_data *sd) +{ + int i = 0, n = 0, length = 0, count = 0; + int16 nameid = 0, indexes[MAX_INVENTORY] = {0}, amounts[MAX_INVENTORY] = {0}; + struct item item_data; + + length = (RFIFOW(fd,2) - 4)/2; + + if (length >= MAX_INVENTORY || length < 2) { + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x96f; + WFIFOW(fd,2) = 0; + WFIFOW(fd,4) = 0; + WFIFOB(fd,6) = MERGEITEM_FAILD; + WFIFOSET(fd,7); + return; + } + + for (i = 0, n = 0; i < length; i++) { + int16 idx = RFIFOW(fd,i*2+4) - 2; + struct item *it = NULL; + + if (idx < 0 || idx >= MAX_INVENTORY) + continue; + + it = &sd->status.inventory[idx]; + + if (it->nameid == 0 || !itemdb->isstackable(it->nameid)) + continue; + + if (nameid == 0) + nameid = it->nameid; + + if (nameid != it->nameid) + continue; + + count += it->amount; + indexes[n] = idx; + amounts[n] = it->amount; + n++; + } + + + if (n < 2 || count == 0) { + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x96f; + WFIFOW(fd,2) = 0; + WFIFOW(fd,4) = 0; + WFIFOB(fd,6) = MERGEITEM_FAILD; + WFIFOSET(fd,7); + return; + } + + if (count > MAX_AMOUNT) { + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x96f; + WFIFOW(fd,2) = 0; + WFIFOW(fd,4) = 0; + WFIFOB(fd,6) = MERGEITEM_MAXCOUNTFAILD; + WFIFOSET(fd,7); + return; + } + + for (i = 0; i < n; i++) + pc->delitem(sd,indexes[i],amounts[i],0,DELITEM_NORMAL,LOG_TYPE_NPC); + + + memset(&item_data,'\0',sizeof(item_data)); + + item_data.nameid = nameid; + item_data.identify = 1; + item_data.unique_id = itemdb->unique_id(sd); + pc->additem(sd,&item_data,count,LOG_TYPE_NPC); + + ARR_FIND(0,MAX_INVENTORY,i,item_data.unique_id == sd->status.inventory[i].unique_id); + + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x96f; + WFIFOW(fd,2) = i+2; + WFIFOW(fd,4) = count; + WFIFOB(fd,6) = MERGEITEM_SUCCESS; + WFIFOSET(fd,7); + +} + +void clif_cancelmergeitem (int fd, struct map_session_data *sd) +{ + //Track The merge item cancelation ? + return; +} + /* */ unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) { if( sd ) { @@ -18344,21 +18499,11 @@ void clif_bc_ready(void) { /*========================================== * *------------------------------------------*/ -int do_init_clif(bool minimal) { - const char* colors[COLOR_MAX] = { "0xFF0000", "0x00ff00", "0xffffff" }; - int i; - +int do_init_clif(bool minimal) +{ if (minimal) return 0; - /** - * Setup Color Table (saves unnecessary load of strtoul on every call) - **/ - for(i = 0; i < COLOR_MAX; i++) { - color_table[i] = (unsigned int)strtoul(colors[i],NULL,0); - color_table[i] = (color_table[i] & 0x0000FF) << 16 | (color_table[i] & 0x00FF00) | (color_table[i] & 0xFF0000) >> 16;//RGB to BGR - } - packetdb_loaddb(); set_defaultparse(clif->parse); @@ -18653,17 +18798,15 @@ void clif_defaults(void) { clif->disp_message = clif_disp_message; clif->broadcast = clif_broadcast; clif->broadcast2 = clif_broadcast2; + clif->messagecolor_self = clif_messagecolor_self; clif->messagecolor = clif_messagecolor; clif->disp_overhead = clif_disp_overhead; - clif->msg = clif_msg; - clif->msg_value = clif_msg_value; - clif->msg_skill = clif_msg_skill; + clif->msgtable_skill = clif_msgtable_skill; clif->msgtable = clif_msgtable; clif->msgtable_num = clif_msgtable_num; clif->message = clif_displaymessage; clif->messageln = clif_displaymessage2; clif->messages = clif_displaymessage_sprintf; - clif->colormes = clif_colormes; clif->process_message = clif_process_message; clif->wisexin = clif_wisexin; clif->wisall = clif_wisall; @@ -18894,6 +19037,12 @@ void clif_defaults(void) { /* */ clif->parse_roulette_db = clif_parse_roulette_db; clif->roulette_generate_ack = clif_roulette_generate_ack; + /* Merge Items */ + clif->openmergeitem = clif_openmergeitem; + clif->cancelmergeitem = clif_cancelmergeitem; + clif->comparemergeitem = clif_comparemergeitem; + clif->ackmergeitems = clif_ackmergeitems; + /*------------------------ *- Parse Incoming Packet *------------------------*/ diff --git a/src/map/clif.h b/src/map/clif.h index 5f1a2a899..c827406ca 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -5,40 +5,38 @@ #ifndef MAP_CLIF_H #define MAP_CLIF_H -#include <stdarg.h> +#include "map/map.h" +#include "map/packets_struct.h" +#include "common/cbasetypes.h" +#include "common/mmo.h" -#include "map.h" -#include "packets_struct.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/mmo.h" +#include <stdarg.h> /** * Declarations **/ +struct battleground_data; +struct channel_data; +struct chat_data; +struct eri; +struct flooritem_data; +struct guild; +struct homun_data; struct item; struct item_data; -struct unit_data; struct map_session_data; -struct homun_data; struct mercenary_data; -struct pet_data; struct mob_data; struct npc_data; -struct chat_data; -struct flooritem_data; -struct skill_unit; -struct s_vending; -struct party; +struct party_booking_ad_info; struct party_data; -struct guild; -struct battleground_data; +struct pet_data; struct quest; -struct party_booking_ad_info; -struct view_data; -struct eri; +struct s_vending; struct skill_cd; -struct channel_data; +struct skill_unit; +struct unit_data; +struct view_data; /** * Defines @@ -47,9 +45,14 @@ struct channel_data; #define P2PTR(fd) RFIFO2PTR(fd) #define clif_menuskill_clear(sd) ((sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0) #define clif_disp_onlyself(sd,mes,len) clif->disp_message( &(sd)->bl, (mes), (len), SELF ) -#define clif_viewequip_fail( sd ) clif->msg( (sd), 0x54d ); #define MAX_ROULETTE_LEVEL 7 /** client-defined value **/ #define MAX_ROULETTE_COLUMNS 9 /** client-defined value **/ +#define RGB2BGR(c) ((c & 0x0000FF) << 16 | (c & 0x00FF00) | (c & 0xFF0000) >> 16) + +#define COLOR_RED 0xff0000U +#define COLOR_GREEN 0x00ff00U +#define COLOR_WHITE 0xffffffU +#define COLOR_DEFAULT COLOR_GREEN /** * Enumerations @@ -344,9 +347,30 @@ typedef enum useskill_fail_cause { // clif_skill_fail }useskill_fail_cause; enum clif_messages { - ITEM_CANT_OBTAIN_WEIGHT = 0x34, /* you cannot carry more items because you are overweight. */ - SKILL_CANT_USE_AREA = 0x536, - ITEM_CANT_USE_AREA = 0x537, + MSG_ITEM_CANT_OBTAIN_WEIGHT = 0x034, ///< You cannot carry more items because you are overweight. + MSG_ITEM_NEED_STANDING = 0x297, ///< You cannot use this item while sitting. + MSG_MERCENARY_EXPIRED = 0x4f2, ///< The mercenary contract has expired. + MSG_MERCENARY_DIED = 0x4f3, ///< The mercenary has died. + MSG_MERCENARY_RELEASED = 0x4f4, ///< You have released the mercenary. + MSG_MERCENARY_ESCAPED = 0x4f5, ///< The mercenary has run away. + MSG_SKILL_CANT_USE_AREA = 0x536, ///< This skill cannot be used within this area + MSG_ITEM_CANT_USE_AREA = 0x537, ///< This item cannot be used within this area. + MSG_EQUIP_NOT_PUBLIC = 0x54d, ///< This character's equipment information is not open to the public. + MSG_ITEM_NEED_MADO = 0x59b, ///< Item can only be used when Mado Gear is mounted. + MSG_ITEM_NEED_CART = 0x5ef, ///< Usable only when cart is put on + MSG_RUNE_STONE_MAX_AMOUNT = 0x61b, ///< Cannot create Rune stone more than the maximum amount. + MSG_SKILL_POINTS_LEFT_JOB1 = 0x61e, ///< You must consume all '%d' remaining points in your 1st Job tab. + MSG_SKILL_POINTS_LEFT_JOB2 = 0x61f, ///< You must consume all '%d' remaining points in your 2nd Job tab. 1st Tab is already done. + MSG_SKILL_ITEM_NOT_FOUND = 0x623, // FIXME[Haru]: This seems to be 0x622 in the msgstringtable files I found. + MSG_SKILL_SUCCESS = 0x627, // FIXME[Haru]: This seems to be 0x626 in the msgstringtable files I found. + MSG_SKILL_FAILURE = 0x628, // FIXME[Haru]: This seems to be 0x627 in the msgstringtable files I found. + MSG_SKILL_ITEM_NEED_IDENTIFY = 0x62d, ///< Unable to use unchecked items as materials. + MSG_ITEM_CANT_EQUIP_LVL = 0x6ed, // FIXME[Haru]: This seems to be 0x6ee in the msgstringtable files I found. + MSG_ITEM_CANT_USE_LVL = 0x6ee, // FIXME[Haru]: This seems to be 0x6ef in the msgstringtable files I found. + MSG_COOKING_LIST_FAIL = 0x625, // FIXME[Haru]: This might be a wrong message ID. Not sure what it should be. + MSG_SECONDS_UNTIL_USE = 0x746, ///< %d seconds left until you can use + MSG_NPC_WORK_IN_PROGRESS = 0x783, // FIXME[Haru]: This seems to be 0x784 in the msgstringtable files I found. + MSG_REINS_CANT_USE_MOUNTED = 0x78b, // FIXME[Haru]: This seems to be 0x785 in the msgstringtalbe files I found. }; /** @@ -365,16 +389,6 @@ enum cashshop_error { ERROR_TYPE_NOT_ALL = 8, ///< Some items could not be purchased. (ERROR_TYPE_NOT_ALL) }; -/** - * Color Table - **/ -enum clif_colors { - COLOR_RED, - COLOR_DEFAULT, - COLOR_WHITE, - COLOR_MAX -}; - enum CASH_SHOP_TABS { CASHSHOP_TAB_NEW = 0, CASHSHOP_TAB_POPULAR = 1, @@ -495,6 +509,30 @@ enum CLOSE_ROULETTE_ACK { }; /** + * Reason for item deletion (clif->delitem) + */ +enum delitem_reason { + DELITEM_NORMAL = 0, /// Normal + DELITEM_SKILLUSE = 1, /// Item used for a skill + DELITEM_FAILREFINE = 2, /// Refine failed + DELITEM_MATERIALCHANGE = 3, /// Material changed + DELITEM_TOSTORAGE = 4, /// Moved to storage + DELITEM_TOCART = 5, /// Moved to cart + DELITEM_SOLD = 6, /// Item sold + DELITEM_ANALYSIS = 7, /// Consumed by Four Spirit Analysis (SO_EL_ANALYSIS) skill +}; + +/* +* Merge items reasons +*/ + +enum mergeitem_reason { + MERGEITEM_SUCCESS = 0x0, + MERGEITEM_FAILD = 0x1, + MERGEITEM_MAXCOUNTFAILD = 0x2, +}; + +/** * Structures **/ typedef void (*pFunc)(int, struct map_session_data *); //cant help but put it first @@ -514,11 +552,15 @@ struct cdelayed_damage { struct block_list bl; }; +struct merge_item { + int16 position; + int16 nameid; +}; + /** * Vars **/ struct s_packet_db packet_db[MAX_PACKET_DB + 1]; -unsigned int color_table[COLOR_MAX]; /** * Clif.c Interface @@ -796,18 +838,16 @@ struct clif_interface { void (*disp_message) (struct block_list* src, const char* mes, size_t len, enum send_target target); void (*broadcast) (struct block_list* bl, const char* mes, size_t len, int type, enum send_target target); void (*broadcast2) (struct block_list* bl, const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target); - void (*messagecolor) (struct block_list* bl, unsigned int color, const char* msg); + void (*messagecolor_self) (int fd, uint32 color, const char *msg); + void (*messagecolor) (struct block_list* bl, uint32 color, const char* msg); void (*disp_overhead) (struct block_list *bl, const char* mes); - void (*msg) (struct map_session_data* sd, unsigned short id); - void (*msg_value) (struct map_session_data* sd, unsigned short id, int value); - void (*msg_skill) (struct map_session_data* sd, uint16 skill_id, int msg_id); - void (*msgtable) (int fd, int line); - void (*msgtable_num) (int fd, int line, int num); + void (*msgtable) (struct map_session_data* sd, unsigned short msg_id); + void (*msgtable_num) (struct map_session_data *sd, unsigned short msg_id, int value); + void (*msgtable_skill) (struct map_session_data *sd, uint16 skill_id, int msg_id); void (*message) (const int fd, const char* mes); void (*messageln) (const int fd, const char* mes); /* message+s(printf) */ void (*messages) (const int fd, const char *mes, ...) __attribute__((format(printf, 2, 3))); - int (*colormes) (int fd, enum clif_colors color, const char* msg); bool (*process_message) (struct map_session_data *sd, int format, char **name_, size_t *namelen_, char **message_, size_t *messagelen_); void (*wisexin) (struct map_session_data *sd,int type,int flag); void (*wisall) (struct map_session_data *sd,int type,int flag); @@ -1037,6 +1077,12 @@ struct clif_interface { /* */ bool (*parse_roulette_db) (void); void (*roulette_generate_ack) (struct map_session_data *sd, unsigned char result, short stage, short prizeIdx, short bonusItemID); + /* Merge Items */ + void (*openmergeitem) (int fd, struct map_session_data *sd); + void (*cancelmergeitem) (int fd, struct map_session_data *sd); + int (*comparemergeitem) (const void *a, const void *b); + void (*ackmergeitems) (int fd, struct map_session_data *sd); + /*------------------------ *- Parse Incoming Packet *------------------------*/ diff --git a/src/map/date.c b/src/map/date.c index 975a00c50..e2ad2b179 100644 --- a/src/map/date.c +++ b/src/map/date.c @@ -5,9 +5,9 @@ #include "date.h" -#include <time.h> +#include "common/cbasetypes.h" -#include "../common/cbasetypes.h" +#include <time.h> int date_get_year(void) { diff --git a/src/map/date.h b/src/map/date.h index a57d8132c..e7d06f29d 100644 --- a/src/map/date.h +++ b/src/map/date.h @@ -4,7 +4,7 @@ #ifndef MAP_DATE_H #define MAP_DATE_H -#include "../common/cbasetypes.h" +#include "common/cbasetypes.h" #ifdef HERCULES_CORE // TODO: Interface diff --git a/src/map/duel.c b/src/map/duel.c index 2dae0ae0e..4cd2e276f 100644 --- a/src/map/duel.c +++ b/src/map/duel.c @@ -6,16 +6,16 @@ #include "duel.h" +#include "map/atcommand.h" // msg_txt +#include "map/clif.h" +#include "map/pc.h" +#include "common/cbasetypes.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> -#include "atcommand.h" // msg_txt -#include "clif.h" -#include "pc.h" -#include "../common/cbasetypes.h" - struct duel_interface duel_s; /*========================================== diff --git a/src/map/duel.h b/src/map/duel.h index fa12a4032..0c55c1266 100644 --- a/src/map/duel.h +++ b/src/map/duel.h @@ -5,7 +5,7 @@ #ifndef MAP_DUEL_H #define MAP_DUEL_H -#include "../common/cbasetypes.h" +#include "common/cbasetypes.h" struct map_session_data; diff --git a/src/map/elemental.c b/src/map/elemental.c index a21c128b0..459ce2a39 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -6,41 +6,41 @@ #include "elemental.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/trade.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/mmo.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "guild.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "trade.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/mmo.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct elemental_interface elemental_s; int elemental_search_index(int class_) { @@ -442,9 +442,9 @@ int elemental_action(struct elemental_data *ed, struct block_list *bl, int64 tic ed->ud.skill_lv = skill_lv; if( skill->get_inf(skill_id) & INF_GROUND_SKILL ) - ed->ud.skilltimer = timer->add( tick+status->get_speed(&ed->bl)*walk_dist, skill->castend_pos, ed->bl.id, 0 ); + ed->ud.skilltimer = timer->add(tick+(int64)status->get_speed(&ed->bl)*walk_dist, skill->castend_pos, ed->bl.id, 0); else - ed->ud.skilltimer = timer->add( tick+status->get_speed(&ed->bl)*walk_dist, skill->castend_id, ed->bl.id, 0 ); + ed->ud.skilltimer = timer->add(tick+(int64)status->get_speed(&ed->bl)*walk_dist, skill->castend_id, ed->bl.id, 0); } return 1; @@ -560,7 +560,7 @@ int elemental_unlocktarget(struct elemental_data *ed) { ed->target_id = 0; elemental_stop_attack(ed); - elemental_stop_walking(ed,1); + elemental_stop_walking(ed, STOPWALKING_FLAG_FIXPOS); return 0; } @@ -586,8 +586,8 @@ struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL ) return req; - req.hp = skill->db[idx].hp[skill_lv-1]; - req.sp = skill->db[idx].sp[skill_lv-1]; + req.hp = skill->dbs->db[idx].hp[skill_lv-1]; + req.sp = skill->dbs->db[idx].sp[skill_lv-1]; return req; } diff --git a/src/map/elemental.h b/src/map/elemental.h index 8015f84c0..582e1059c 100644 --- a/src/map/elemental.h +++ b/src/map/elemental.h @@ -5,9 +5,12 @@ #ifndef MAP_ELEMENTAL_H #define MAP_ELEMENTAL_H -#include "status.h" // struct status_data, struct status_change -#include "unit.h" // struct unit_data -#include "../common/mmo.h" // NAME_LENGTH +#include "map/status.h" // struct status_data, struct status_change +#include "map/unit.h" // struct unit_data +#include "common/cbasetypes.h" +#include "common/mmo.h" // NAME_LENGTH + +#include <stdarg.h> /** * Defines diff --git a/src/map/guild.c b/src/map/guild.c index 936b4c900..5f6ce83c6 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -4,37 +4,37 @@ #define HERCULES_CORE -#include "../config/core.h" // GP_BOUND_ITEMS +#include "config/core.h" // GP_BOUND_ITEMS #include "guild.h" +#include "map/battle.h" +#include "map/channel.h" +#include "map/clif.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/pc.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/mapindex.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "battle.h" -#include "channel.h" -#include "clif.h" -#include "instance.h" -#include "intif.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "npc.h" -#include "pc.h" -#include "skill.h" -#include "status.h" -#include "storage.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/mapindex.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct guild_interface guild_s; /*========================================== @@ -343,14 +343,12 @@ int guild_create(struct map_session_data *sd, const char *name) if( !tname[0] ) return 0; // empty name - if( sd->status.guild_id ) - {// already in a guild - clif->guild_created(sd,1); + if( sd->status.guild_id ) { + clif->guild_created(sd,1); // You're already in a guild return 0; } if (battle_config.guild_emperium_check && pc->search_inventory(sd, ITEMID_EMPERIUM) == INDEX_NOT_FOUND) { - // item required - clif->guild_created(sd,3); + clif->guild_created(sd,3); // You need the necessary item to create a guild return 0; } @@ -367,14 +365,14 @@ int guild_created(int account_id,int guild_id) { if(sd==NULL) return 0; if(!guild_id) { - clif->guild_created(sd, 2); // Creation failure (presence of the same name Guild) + clif->guild_created(sd, 2); // Creation failure (The guild name already exists) return 0; } //struct guild *g; sd->status.guild_id=guild_id; - clif->guild_created(sd,0); + clif->guild_created(sd,0); // Success if(battle_config.guild_emperium_check) - pc->delitem(sd,pc->search_inventory(sd,ITEMID_EMPERIUM),1,0,0,LOG_TYPE_CONSUME); //emperium consumption + pc->delitem(sd, pc->search_inventory(sd, ITEMID_EMPERIUM), 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); //emperium consumption return 0; } @@ -615,7 +613,7 @@ int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) { if(tsd==NULL || g==NULL) return 0; - if( (i=guild->getposition(g,sd))<0 || !(g->position[i].mode&0x0001) ) + if( (i=guild->getposition(g,sd)) < 0 || !(g->position[i].mode&GPERM_INVITE) ) return 0; //Invite permission. if(!battle_config.invite_request_check) { @@ -840,7 +838,7 @@ int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, i if(sd->status.guild_id!=guild_id) return 0; - if( (ps=guild->getposition(g,sd))<0 || !(g->position[ps].mode&0x0010) ) + if ((ps=guild->getposition(g,sd))<0 || !(g->position[ps].mode&GPERM_EXPEL)) return 0; //Expulsion permission //Can't leave inside guild castles. @@ -895,7 +893,7 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c // update char, if online if(sd != NULL && sd->status.guild_id == guild_id) { // do stuff that needs the guild_id first, BEFORE we wipe it - if (sd->state.storage_flag == 2) //Close the guild storage. + if (sd->state.storage_flag == STORAGE_FLAG_GUILD) //Close the guild storage. gstorage->close(sd); guild->send_dot_remove(sd); if (channel->config->ally) { @@ -926,7 +924,7 @@ void guild_retrieveitembound(int char_id,int aid,int guild_id) { if(gstor && gstor->storage_status == 1) { //Someone is in guild storage, close them struct s_mapiterator* iter = mapit_getallusers(); for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { - if(sd->status.guild_id == guild_id && sd->state.storage_flag == 2) { + if(sd->status.guild_id == guild_id && sd->state.storage_flag == STORAGE_FLAG_GUILD) { gstorage->close(sd); break; } @@ -1095,9 +1093,7 @@ int guild_change_position(int guild_id,int idx,int mode,int exp_mode,const char struct guild_position p; exp_mode = cap_value(exp_mode, 0, battle_config.guild_exp_limit); - //Mode 0x01 <- Invite - //Mode 0x10 <- Expel. - p.mode=mode&0x11; + p.mode=mode&GPERM_BOTH; // Invite and Expel p.exp_mode=exp_mode; safestrncpy(p.name,name,NAME_LENGTH); return intif->guild_position(guild_id,idx,&p); @@ -1750,7 +1746,7 @@ int guild_broken(int guild_id,int flag) for(i=0;i<g->max_member;i++){ // Destroy all relationships if((sd=g->member[i].sd)!=NULL){ - if(sd->state.storage_flag == 2) + if(sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->pc_quit(sd,1); sd->status.guild_id=0; sd->guild = NULL; @@ -1910,7 +1906,7 @@ int guild_break(struct map_session_data *sd,char *name) { } } - for(i = 0; i < count; i++) { + for(i = 0; i < count; i++) { // FIXME: Why is this not done in the above loop? skill->del_unitgroup(groups[i],ALC_MARK); } } diff --git a/src/map/guild.h b/src/map/guild.h index a75b8a7a5..18a25af58 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -5,10 +5,10 @@ #ifndef MAP_GUILD_H #define MAP_GUILD_H -#include "map.h" // EVENT_NAME_LENGTH, TBL_PC -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/mmo.h" +#include "map/map.h" // EVENT_NAME_LENGTH, TBL_PC +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/mmo.h" /** * Defines diff --git a/src/map/homunculus.c b/src/map/homunculus.c index 51686d3aa..305d60f5b 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -4,50 +4,51 @@ #define HERCULES_CORE -#include "../config/core.h" // DBPATH +#include "config/core.h" // DBPATH #include "homunculus.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/trade.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/mmo.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "guild.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "trade.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/mmo.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct homunculus_interface homunculus_s; +struct homun_dbs homundbs; //Returns the viewdata for homunculus struct view_data* homunculus_get_viewdata(int class_) { if (homdb_checkid(class_)) - return &homun->viewdb[class_-HM_CLASS_BASE]; + return &homun->dbs->viewdb[class_-HM_CLASS_BASE]; return NULL; } @@ -193,13 +194,13 @@ int homunculus_calc_skilltree(struct homun_data *hd, int flag_evolve) { if( hd->homunculus.prev_class != 0 ) { c = hd->homunculus.prev_class - HM_CLASS_BASE; - for( i = 0; i < MAX_SKILL_TREE && ( id = homun->skill_tree[c][i].id ) > 0; i++ ) { + for( i = 0; i < MAX_SKILL_TREE && ( id = homun->dbs->skill_tree[c][i].id ) > 0; i++ ) { if( hd->homunculus.hskill[ id - HM_SKILLBASE ].id ) continue; //Skill already known. if(!battle_config.skillfree) { for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) { - if( homun->skill_tree[c][i].need[j].id && - homun->checkskill(hd,homun->skill_tree[c][i].need[j].id) < homun->skill_tree[c][i].need[j].lv ) { + if( homun->dbs->skill_tree[c][i].need[j].id && + homun->checkskill(hd,homun->dbs->skill_tree[c][i].need[j].id) < homun->dbs->skill_tree[c][i].need[j].lv ) { f = 0; break; } @@ -214,16 +215,16 @@ int homunculus_calc_skilltree(struct homun_data *hd, int flag_evolve) { c = hd->homunculus.class_ - HM_CLASS_BASE; - for( i = 0; i < MAX_SKILL_TREE && ( id = homun->skill_tree[c][i].id ) > 0; i++ ) { + for( i = 0; i < MAX_SKILL_TREE && ( id = homun->dbs->skill_tree[c][i].id ) > 0; i++ ) { if( hd->homunculus.hskill[ id - HM_SKILLBASE ].id ) continue; //Skill already known. j = ( flag_evolve ) ? 10 : hd->homunculus.intimacy; - if( j < homun->skill_tree[c][i].intimacylv ) + if( j < homun->dbs->skill_tree[c][i].intimacylv ) continue; if(!battle_config.skillfree) { for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) { - if( homun->skill_tree[c][i].need[j].id && - homun->checkskill(hd,homun->skill_tree[c][i].need[j].id) < homun->skill_tree[c][i].need[j].lv ) { + if( homun->dbs->skill_tree[c][i].need[j].id && + homun->checkskill(hd,homun->dbs->skill_tree[c][i].need[j].id) < homun->dbs->skill_tree[c][i].need[j].lv ) { f = 0; break; } @@ -252,9 +253,9 @@ int homunculus_checkskill(struct homun_data *hd,uint16 skill_id) { int homunculus_skill_tree_get_max(int id, int b_class) { int i, skill_id; b_class -= HM_CLASS_BASE; - for(i=0;(skill_id=homun->skill_tree[b_class][i].id)>0;i++) + for(i=0;(skill_id=homun->dbs->skill_tree[b_class][i].id)>0;i++) if (id == skill_id) - return homun->skill_tree[b_class][i].max; + return homun->dbs->skill_tree[b_class][i].max; return skill->get_max(id); } @@ -316,7 +317,7 @@ bool homunculus_levelup(struct homun_data *hd) { hom->skillpts++; //1 skillpoint each 3 base level hom->exp -= hd->exp_next; - hd->exp_next = homun->exptable[hom->level - 1]; + hd->exp_next = homun->dbs->exptable[hom->level - 1]; max = &hd->homunculusDB->gmax; min = &hd->homunculusDB->gmin; @@ -366,7 +367,7 @@ int homunculus_change_class(struct homun_data *hd, short class_) { i = homun->db_search(class_,HOMUNCULUS_CLASS); if(i < 0) return 0; - hd->homunculusDB = &homun->db[i]; + hd->homunculusDB = &homun->dbs->db[i]; hd->homunculus.class_ = class_; status->set_viewdata(&hd->bl, class_); homun->calc_skilltree(hd, 1); @@ -584,7 +585,7 @@ bool homunculus_feed(struct map_session_data *sd, struct homun_data *hd) { clif->hom_food(sd,foodID,0); return false; } - pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); if ( hd->homunculus.hunger >= 91 ) { homun->consume_intimacy(hd, 50); @@ -703,16 +704,16 @@ int homunculus_db_search(int key,int type) { int i; for(i=0;i<MAX_HOMUNCULUS_CLASS;i++) { - if(homun->db[i].base_class <= 0) + if(homun->dbs->db[i].base_class <= 0) continue; switch(type) { case HOMUNCULUS_CLASS: - if(homun->db[i].base_class == key || - homun->db[i].evo_class == key) + if(homun->dbs->db[i].base_class == key || + homun->dbs->db[i].evo_class == key) return i; break; case HOMUNCULUS_FOOD: - if(homun->db[i].foodID == key) + if(homun->dbs->db[i].foodID == key) return i; break; default: @@ -729,7 +730,7 @@ bool homunculus_create(struct map_session_data *sd, struct s_homunculus *hom) { nullpo_retr(false, sd); - Assert((sd->status.hom_id == 0 || sd->hd == 0) || sd->hd->master == sd); + Assert_retr(false, sd->status.hom_id == 0 || sd->hd == 0 || sd->hd->master == sd); i = homun->db_search(hom->class_,HOMUNCULUS_CLASS); if(i < 0) { @@ -743,9 +744,9 @@ bool homunculus_create(struct map_session_data *sd, struct s_homunculus *hom) { hd->bl.id = npc->get_new_npc_id(); hd->master = sd; - hd->homunculusDB = &homun->db[i]; + hd->homunculusDB = &homun->dbs->db[i]; memcpy(&hd->homunculus, hom, sizeof(struct s_homunculus)); - hd->exp_next = homun->exptable[hd->homunculus.level - 1]; + hd->exp_next = homun->dbs->exptable[hd->homunculus.level - 1]; status->set_viewdata(&hd->bl, hd->homunculus.class_); status->change_init(&hd->bl); @@ -879,7 +880,7 @@ bool homunculus_creation_request(struct map_session_data *sd, int class_) { memset(&hom, 0, sizeof(struct s_homunculus)); //Initial data - safestrncpy(hom.name, homun->db[i].name, NAME_LENGTH-1); + safestrncpy(hom.name, homun->dbs->db[i].name, NAME_LENGTH-1); hom.class_ = class_; hom.level = 1; hom.hunger = 32; //32% @@ -887,7 +888,7 @@ bool homunculus_creation_request(struct map_session_data *sd, int class_) { hom.char_id = sd->status.char_id; hom.hp = 10 ; - base = &homun->db[i].base; + base = &homun->dbs->db[i].base; hom.max_hp = base->HP; hom.max_sp = base->SP; hom.str = base->str *10; @@ -963,7 +964,7 @@ void homunculus_stat_reset(struct homun_data *hd) { hom->dex = base->dex *10; hom->luk = base->luk *10; hom->exp = 0; - hd->exp_next = homun->exptable[0]; + hd->exp_next = homun->dbs->exptable[0]; memset(&hd->homunculus.hskill, 0, sizeof hd->homunculus.hskill); hd->homunculus.skillpts = 0; } @@ -1026,7 +1027,7 @@ bool homunculus_read_db_sub(char* str[], int columns, int current) { ShowError("homunculus_read_db_sub : Invalid class %d\n", classid); return false; } - db = &homun->db[current]; + db = &homun->dbs->db[current]; db->base_class = classid; classid = atoi(str[1]); if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX) { @@ -1129,8 +1130,7 @@ bool homunculus_read_db_sub(char* str[], int columns, int current) { void homunculus_read_db(void) { int i; const char *filename[]={DBPATH"homunculus_db.txt","homunculus_db2.txt"}; - - memset(homun->db,0,sizeof(homun->db)); + memset(homun->dbs->db, 0, sizeof(homun->dbs->db)); for(i = 0; i<ARRAYLENGTH(filename); i++) { if( i > 0 ) { char filepath[256]; @@ -1165,23 +1165,23 @@ bool homunculus_read_skill_db_sub(char* split[], int columns, int current) { k = atoi(split[1]); //This is to avoid adding two lines for the same skill. [Skotlex] // Search an empty line or a line with the same skill_id (stored in j) - ARR_FIND( 0, MAX_SKILL_TREE, j, !homun->skill_tree[classid][j].id || homun->skill_tree[classid][j].id == k ); + ARR_FIND( 0, MAX_SKILL_TREE, j, !homun->dbs->skill_tree[classid][j].id || homun->dbs->skill_tree[classid][j].id == k ); if (j == MAX_SKILL_TREE) { ShowWarning("Unable to load skill %d into homunculus %d's tree. Maximum number of skills per class has been reached.\n", k, classid); return false; } - homun->skill_tree[classid][j].id = k; - homun->skill_tree[classid][j].max = atoi(split[2]); + homun->dbs->skill_tree[classid][j].id = k; + homun->dbs->skill_tree[classid][j].max = atoi(split[2]); if (minJobLevelPresent) - homun->skill_tree[classid][j].joblv = atoi(split[3]); + homun->dbs->skill_tree[classid][j].joblv = atoi(split[3]); for( k = 0; k < MAX_PC_SKILL_REQUIRE; k++ ) { - homun->skill_tree[classid][j].need[k].id = atoi(split[3+k*2+minJobLevelPresent]); - homun->skill_tree[classid][j].need[k].lv = atoi(split[3+k*2+minJobLevelPresent+1]); + homun->dbs->skill_tree[classid][j].need[k].id = atoi(split[3+k*2+minJobLevelPresent]); + homun->dbs->skill_tree[classid][j].need[k].lv = atoi(split[3+k*2+minJobLevelPresent+1]); } - homun->skill_tree[classid][j].intimacylv = atoi(split[13+minJobLevelPresent]); + homun->dbs->skill_tree[classid][j].intimacylv = atoi(split[13+minJobLevelPresent]); return true; } @@ -1205,9 +1205,8 @@ int8 homunculus_get_intimacy_grade(struct homun_data *hd) { } void homunculus_skill_db_read(void) { - memset(homun->skill_tree,0,sizeof(homun->skill_tree)); + memset(homun->dbs->skill_tree, 0, sizeof(homun->dbs->skill_tree)); sv->readdb(map->db_path, "homun_skill_tree.txt", ',', 13, 15, -1, homun->read_skill_db_sub); - } void homunculus_exp_db_read(void) { @@ -1217,7 +1216,7 @@ void homunculus_exp_db_read(void) { DBPATH"exp_homun.txt", "exp_homun2.txt"}; - memset(homun->exptable,0,sizeof(homun->exptable)); + memset(homun->dbs->exptable, 0, sizeof(homun->dbs->exptable)); for(i = 0; i < 2; i++) { FILE *fp; sprintf(line, "%s/%s", map->db_path, filename[i]); @@ -1231,13 +1230,13 @@ void homunculus_exp_db_read(void) { if(line[0] == '/' && line[1] == '/') continue; - if (!(homun->exptable[j++] = (unsigned int)strtoul(line, NULL, 10))) + if (!(homun->dbs->exptable[j++] = (unsigned int)strtoul(line, NULL, 10))) break; } // Last permitted level have to be 0! - if (homun->exptable[MAX_LEVEL - 1]) { + if (homun->dbs->exptable[MAX_LEVEL - 1]) { ShowWarning("homunculus_exp_db_read: Reached max level in exp_homun [%d]. Remaining lines were not read.\n ", MAX_LEVEL); - homun->exptable[MAX_LEVEL - 1] = 0; + homun->dbs->exptable[MAX_LEVEL - 1] = 0; } fclose(fp); ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' levels in '"CL_WHITE"%s"CL_RESET"'.\n", j, filename[i]); @@ -1266,9 +1265,9 @@ void do_init_homunculus(bool minimal) { timer->add_func_list(homun->hunger_timer, "homunculus_hunger_timer"); //Stock view data for homuncs - memset(&homun->viewdb, 0, sizeof(homun->viewdb)); - for (class_ = 0; class_ < ARRAYLENGTH(homun->viewdb); class_++) - homun->viewdb[class_].class_ = HM_CLASS_BASE+class_; + memset(homun->dbs->viewdb, 0, sizeof(homun->dbs->viewdb)); + for (class_ = 0; class_ < MAX_HOMUNCULUS_CLASS; class_++) + homun->dbs->viewdb[class_].class_ = HM_CLASS_BASE+class_; } void do_final_homunculus(void) { @@ -1277,7 +1276,8 @@ void do_final_homunculus(void) { void homunculus_defaults(void) { homun = &homunculus_s; - + homun->dbs = &homundbs; + homun->init = do_init_homunculus; homun->final = do_final_homunculus; homun->reload = homunculus_reload; diff --git a/src/map/homunculus.h b/src/map/homunculus.h index 18f8728d3..95b613fff 100644 --- a/src/map/homunculus.h +++ b/src/map/homunculus.h @@ -5,10 +5,11 @@ #ifndef MAP_HOMUNCULUS_H #define MAP_HOMUNCULUS_H -#include "pc.h" -#include "status.h" // struct status_data, struct status_change -#include "unit.h" // struct unit_data -#include "../common/mmo.h" +#include "map/status.h" // struct status_data, struct status_change +#include "map/unit.h" // struct unit_data +#include "common/mmo.h" + +struct map_session_data; #define MAX_HOM_SKILL_REQUIRE 5 #define homdb_checkid(id) ((id) >= HM_CLASS_BASE && (id) <= HM_CLASS_MAX) @@ -98,12 +99,16 @@ enum homun_type { HT_INVALID = -1, // Invalid Homunculus }; -/* homunculus.c interface */ -struct homunculus_interface { +struct homun_dbs { unsigned int exptable[MAX_LEVEL]; struct view_data viewdb[MAX_HOMUNCULUS_CLASS]; struct s_homunculus_db db[MAX_HOMUNCULUS_CLASS]; struct homun_skill_tree_entry skill_tree[MAX_HOMUNCULUS_CLASS][MAX_SKILL_TREE]; +}; + +/* homunculus.c interface */ +struct homunculus_interface { + struct homun_dbs *dbs; /* */ void (*init) (bool minimal); void (*final) (void); diff --git a/src/map/instance.c b/src/map/instance.c index dd5709452..f5688d02c 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -4,32 +4,33 @@ #define HERCULES_CORE +#include "config/core.h" // CELL_NOSTACK #include "instance.h" +#include "map/channel.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/map.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> -#include "../config/core.h" // CELL_NOSTACK -#include "channel.h" -#include "clif.h" -#include "map.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct instance_interface instance_s; /// Checks whether given instance id is valid or not. diff --git a/src/map/instance.h b/src/map/instance.h index 80bd1f012..e17d6866f 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -5,10 +5,11 @@ #ifndef MAP_INSTANCE_H #define MAP_INSTANCE_H -#include "script.h" // struct reg_db -#include "../common/cbasetypes.h" -#include "../common/mmo.h" // struct point +#include "map/script.h" // struct reg_db +#include "common/cbasetypes.h" +#include "common/mmo.h" // struct point +struct HPluginData; struct block_list; struct map_session_data; diff --git a/src/map/intif.c b/src/map/intif.c index 50857baa8..26fd1949c 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -3,9 +3,32 @@ #define HERCULES_CORE -#include "../config/core.h" // GP_BOUND_ITEMS +#include "config/core.h" // GP_BOUND_ITEMS #include "intif.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/storage.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" + #include <fcntl.h> #include <signal.h> #include <stdio.h> @@ -13,29 +36,6 @@ #include <string.h> #include <sys/types.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "log.h" -#include "mail.h" -#include "map.h" -#include "mercenary.h" -#include "party.h" -#include "pc.h" -#include "pet.h" -#include "quest.h" -#include "storage.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" - struct intif_interface intif_s; #define inter_fd (chrif->fd) // alias @@ -130,7 +130,7 @@ int intif_rename(struct map_session_data *sd, int type, char *name) // GM Send a message int intif_broadcast(const char* mes, size_t len, int type) { - int lp = (type|BC_COLOR_MASK) ? 4 : 0; + int lp = (type&BC_COLOR_MASK) ? 4 : 0; // Send to the local players clif->broadcast(NULL, mes, len, type, ALL_CLIENT); @@ -149,9 +149,9 @@ int intif_broadcast(const char* mes, size_t len, int type) WFIFOW(inter_fd,10) = 0; // fontSize not used with standard broadcast WFIFOW(inter_fd,12) = 0; // fontAlign not used with standard broadcast WFIFOW(inter_fd,14) = 0; // fontY not used with standard broadcast - if( type|BC_BLUE ) + if (type&BC_BLUE) WFIFOL(inter_fd,16) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow. - else if( type|BC_WOE ) + else if (type&BC_WOE) WFIFOL(inter_fd,16) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'. memcpy(WFIFOP(inter_fd,16 + lp), mes, len); WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); @@ -2152,7 +2152,7 @@ void intif_parse_MessageToFD(int fd) { if( sd && sd->bl.id == aid ) { char msg[512]; safestrncpy(msg, (char*)RFIFOP(fd,12), RFIFOW(fd,2) - 12); - clif->message(u_fd,msg); + clif->messagecolor_self(u_fd, COLOR_DEFAULT ,msg); } } diff --git a/src/map/intif.h b/src/map/intif.h index 52aa32259..3303feb6e 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -5,7 +5,7 @@ #ifndef MAP_INTIF_H #define MAP_INTIF_H -#include "../common/cbasetypes.h" +#include "common/cbasetypes.h" /** * Declarations diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c index d492ad9ca..b0f687c0d 100644 --- a/src/map/irc-bot.c +++ b/src/map/irc-bot.c @@ -1,26 +1,26 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -// Base Author: shennetsind @ http://hercules.ws +// Base Author: shennetsind @ http://herc.ws #define HERCULES_CORE #include "irc-bot.h" +#include "map/channel.h" +#include "map/map.h" +#include "map/pc.h" +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "channel.h" -#include "map.h" -#include "pc.h" -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" - //#define IRCBOT_DEBUG struct irc_bot_interface irc_bot_s; diff --git a/src/map/irc-bot.h b/src/map/irc-bot.h index 8dcfea5bd..b0bfd72f8 100644 --- a/src/map/irc-bot.h +++ b/src/map/irc-bot.h @@ -1,12 +1,12 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -// Base Author: shennetsind @ http://hercules.ws +// Base Author: shennetsind @ http://herc.ws #ifndef MAP_IRC_BOT_H #define MAP_IRC_BOT_H -#include "../common/cbasetypes.h" +#include "common/cbasetypes.h" #define IRC_NICK_LENGTH 40 #define IRC_IDENT_LENGTH 40 diff --git a/src/map/itemdb.c b/src/map/itemdb.c index fb6bcc730..09303978c 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -4,27 +4,27 @@ #define HERCULES_CORE -#include "../config/core.h" // DBPATH, RENEWAL +#include "config/core.h" // DBPATH, RENEWAL #include "itemdb.h" +#include "map/battle.h" // struct battle_config +#include "map/map.h" +#include "map/mob.h" // MAX_MOB_DB +#include "map/pc.h" // W_MUSICAL, W_WHIP +#include "map/script.h" // item script processing +#include "common/HPM.h" +#include "common/conf.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "battle.h" // struct battle_config -#include "map.h" -#include "mob.h" // MAX_MOB_DB -#include "pc.h" // W_MUSICAL, W_WHIP -#include "script.h" // item script processing -#include "../common/HPM.h" -#include "../common/conf.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/utils.h" - struct itemdb_interface itemdb_s; /** @@ -199,6 +199,9 @@ void itemdb_package_item(struct map_session_data *sd, struct item_package *packa if( package->must_items[i].announce ) clif->package_announce(sd,package->must_items[i].id,package->id); + if ( package->must_items[i].force_serial ) + it.unique_id = itemdb->unique_id(sd); + get_count = itemdb->isstackable(package->must_items[i].id) ? package->must_items[i].qty : 1; it.amount = get_count == 1 ? 1 : get_count; @@ -719,7 +722,7 @@ void itemdb_write_cached_packages(const char *config_filename) { //now we loop into must for(c = 0; c < must_qty; c++) { struct item_package_must_entry *entry = &itemdb->packages[i].must_items[c]; - unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0; + unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0, force_serial = entry->force_serial == 1 ? 1 : 0; //first 2 byte = item id hwrite(&entry->id,sizeof(entry->id),1,file); //next 2 byte = qty @@ -729,7 +732,9 @@ void itemdb_write_cached_packages(const char *config_filename) { //next 1 byte = announce (1:0) hwrite(&announce,sizeof(announce),1,file); //next 1 byte = named (1:0) - hwrite(&named,sizeof(announce),1,file); + hwrite(&named,sizeof(named),1,file); + //next 1 byte = ForceSerial (1:0) + hwrite(&force_serial,sizeof(force_serial),1,file); } //now we loop into random groups for(c = 0; c < random_qty; c++) { @@ -741,7 +746,7 @@ void itemdb_write_cached_packages(const char *config_filename) { //now we loop into the group's list for(h = 0; h < group_qty; h++) { struct item_package_rand_entry *entry = &itemdb->packages[i].random_groups[c].random_list[h]; - unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0; + unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0, force_serial = entry->force_serial == 1 ? 1 : 0; //first 2 byte = item id hwrite(&entry->id,sizeof(entry->id),1,file); //next 2 byte = qty @@ -753,7 +758,9 @@ void itemdb_write_cached_packages(const char *config_filename) { //next 1 byte = announce (1:0) hwrite(&announce,sizeof(announce),1,file); //next 1 byte = named (1:0) - hwrite(&named,sizeof(announce),1,file); + hwrite(&named,sizeof(named),1,file); + //next 1 byte = ForceSerial (1:0) + hwrite(&force_serial,sizeof(force_serial),1,file); } } } @@ -807,7 +814,7 @@ bool itemdb_read_cached_packages(const char *config_filename) { for(c = 0; c < package->must_qty; c++) { struct item_package_must_entry *entry = &itemdb->packages[i].must_items[c]; unsigned short mid = 0, qty = 0, hours = 0; - unsigned char announce = 0, named = 0; + unsigned char announce = 0, named = 0, force_serial = 0; struct item_data *data; //first 2 byte = item id hread(&mid,sizeof(mid),1,file); @@ -818,8 +825,10 @@ bool itemdb_read_cached_packages(const char *config_filename) { //next 1 byte = announce (1:0) hread(&announce,sizeof(announce),1,file); //next 1 byte = named (1:0) - hread(&named,sizeof(announce),1,file); - + hread(&named,sizeof(named),1,file); + //next 1 byte = ForceSerial (1:0) + hread(&force_serial,sizeof(force_serial),1,file); + if( !(data = itemdb->exists(mid)) ) ShowWarning("itemdb_read_cached_packages: unknown item '%d' in package '%s'!\n",mid,itemdb_name(package->id)); @@ -828,6 +837,7 @@ bool itemdb_read_cached_packages(const char *config_filename) { entry->qty = qty; entry->announce = announce ? 1 : 0; entry->named = named ? 1 : 0; + entry->force_serial = force_serial ? 1 : 0; } } if( package->random_qty ) { @@ -847,7 +857,7 @@ bool itemdb_read_cached_packages(const char *config_filename) { for(h = 0; h < group_qty; h++) { struct item_package_rand_entry *entry = &itemdb->packages[i].random_groups[c].random_list[h]; unsigned short mid = 0, qty = 0, hours = 0, rate = 0; - unsigned char announce = 0, named = 0; + unsigned char announce = 0, named = 0, force_serial = 0; struct item_data *data; if( prev ) prev->next = entry; @@ -863,8 +873,10 @@ bool itemdb_read_cached_packages(const char *config_filename) { //next 1 byte = announce (1:0) hread(&announce,sizeof(announce),1,file); //next 1 byte = named (1:0) - hread(&named,sizeof(announce),1,file); - + hread(&named,sizeof(named),1,file); + //next 1 byte = ForceSerial (1:0) + hread(&force_serial,sizeof(force_serial),1,file); + if( !(data = itemdb->exists(mid)) ) ShowWarning("itemdb_read_cached_packages: unknown item '%d' in package '%s'!\n",mid,itemdb_name(package->id)); @@ -874,7 +886,7 @@ bool itemdb_read_cached_packages(const char *config_filename) { entry->qty = qty; entry->announce = announce ? 1 : 0; entry->named = named ? 1 : 0; - + entry->force_serial = force_serial ? 1 : 0; prev = entry; } if( prev ) @@ -1020,7 +1032,7 @@ void itemdb_read_packages(void) { c = 0; while( (it = libconfig->setting_get_elem(itg,c++)) ) { int icount = 1, expire = 0, rate = 10000, gid = 0; - bool announce = false, named = false; + bool announce = false, named = false, force_serial = false; itname = config_setting_name(it); @@ -1049,6 +1061,9 @@ void itemdb_read_packages(void) { if( ( t = libconfig->setting_get_member(it, "Named")) && libconfig->setting_get_bool(t) ) named = true; + if( ( t = libconfig->setting_get_member(it, "ForceSerial")) && libconfig->setting_get_bool(t) ) + force_serial = true; + if( !( t = libconfig->setting_get_member(it, "Random") ) ) { ShowWarning("itemdb_read_packages: missing 'Random' field for item '%s' in package '%s', defaulting to must!\n",itname,config_setting_name(itg)); gid = 0; @@ -1061,6 +1076,7 @@ void itemdb_read_packages(void) { itemdb->packages[count].must_items[m].hours = expire; itemdb->packages[count].must_items[m].announce = announce == true ? 1 : 0; itemdb->packages[count].must_items[m].named = named == true ? 1 : 0; + itemdb->packages[count].must_items[m].force_serial = force_serial == true ? 1 : 0; m++; } else { int gidx = gid - 1; @@ -1078,6 +1094,7 @@ void itemdb_read_packages(void) { itemdb->packages[count].random_groups[gidx].random_list[r].hours = expire; itemdb->packages[count].random_groups[gidx].random_list[r].announce = announce == true ? 1 : 0; itemdb->packages[count].random_groups[gidx].random_list[r].named = named == true ? 1 : 0; + itemdb->packages[count].random_groups[gidx].random_list[r].force_serial = force_serial == true ? 1 : 0; itemdb->packages[count].random_groups[gidx].random_qty += 1; prev[gidx] = &itemdb->packages[count].random_groups[gidx].random_list[r]; @@ -1583,14 +1600,15 @@ int itemdb_readdb_sql_sub(Sql *handle, int n, const char *source) { SQL->GetData(handle, 19, &data, NULL); id.flag.no_refine = data && atoi(data) ? 0 : 1; SQL->GetData(handle, 20, &data, NULL); id.look = data ? atoi(data) : 0; SQL->GetData(handle, 21, &data, NULL); id.flag.bindonequip = data && atoi(data) ? 1 : 0; - SQL->GetData(handle, 22, &data, NULL); id.flag.buyingstore = data && atoi(data) ? 1 : 0; - SQL->GetData(handle, 23, &data, NULL); id.delay = data ? atoi(data) : 0; - SQL->GetData(handle, 24, &data, NULL); id.flag.trade_restriction = data ? atoi(data) : ITR_NONE; - SQL->GetData(handle, 25, &data, NULL); id.gm_lv_trade_override = data ? atoi(data) : 0; - SQL->GetData(handle, 26, &data, NULL); id.item_usage.flag = data ? atoi(data) : INR_NONE; - SQL->GetData(handle, 27, &data, NULL); id.item_usage.override = data ? atoi(data) : 0; - SQL->GetData(handle, 28, &data, NULL); id.stack.amount = data ? atoi(data) : 0; - SQL->GetData(handle, 29, &data, NULL); + SQL->GetData(handle, 22, &data, NULL); id.flag.force_serial = data && atoi(data) ? 1 : 0; + SQL->GetData(handle, 23, &data, NULL); id.flag.buyingstore = data && atoi(data) ? 1 : 0; + SQL->GetData(handle, 24, &data, NULL); id.delay = data ? atoi(data) : 0; + SQL->GetData(handle, 25, &data, NULL); id.flag.trade_restriction = data ? atoi(data) : ITR_NONE; + SQL->GetData(handle, 26, &data, NULL); id.gm_lv_trade_override = data ? atoi(data) : 0; + SQL->GetData(handle, 27, &data, NULL); id.item_usage.flag = data ? atoi(data) : INR_NONE; + SQL->GetData(handle, 28, &data, NULL); id.item_usage.override = data ? atoi(data) : 0; + SQL->GetData(handle, 29, &data, NULL); id.stack.amount = data ? atoi(data) : 0; + SQL->GetData(handle, 30, &data, NULL); if (data) { int stack_flag = atoi(data); id.stack.inventory = (stack_flag&1)!=0; @@ -1598,15 +1616,15 @@ int itemdb_readdb_sql_sub(Sql *handle, int n, const char *source) { id.stack.storage = (stack_flag&4)!=0; id.stack.guildstorage = (stack_flag&8)!=0; } - SQL->GetData(handle, 30, &data, NULL); + SQL->GetData(handle, 31, &data, NULL); if (data) { id.view_id = atoi(data); if (id.view_id) id.flag.available = 1; } - SQL->GetData(handle, 31, &data, NULL); id.script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; - SQL->GetData(handle, 32, &data, NULL); id.equip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; - SQL->GetData(handle, 33, &data, NULL); id.unequip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; + SQL->GetData(handle, 32, &data, NULL); id.script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; + SQL->GetData(handle, 33, &data, NULL); id.equip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; + SQL->GetData(handle, 34, &data, NULL); id.unequip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL; return itemdb->validate_entry(&id, n, source); } @@ -1657,6 +1675,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) * BindOnEquip: (true or false) * BuyingStore: (true or false) * Delay: Delay to use item + * ForceSerial: (true or false) * Trade: { * override: Group to override * nodrop: (true or false) @@ -1790,6 +1809,9 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) if( (t = libconfig->setting_get_member(it, "BindOnEquip")) ) id.flag.bindonequip = libconfig->setting_get_bool(t) ? 1 : 0; + + if( (t = libconfig->setting_get_member(it, "ForceSerial")) ) + id.flag.force_serial = libconfig->setting_get_bool(t) ? 1 : 0; if ( (t = libconfig->setting_get_member(it, "BuyingStore")) ) id.flag.buyingstore = libconfig->setting_get_bool(t) ? 1 : 0; @@ -1992,7 +2014,7 @@ int itemdb_readdb_sql(const char *tablename) { " `matk`, `defence`, `range`, `slots`," " `equip_jobs`, `equip_upper`, `equip_genders`, `equip_locations`," " `weapon_level`, `equip_level_min`, `equip_level_max`, `refineable`," - " `view`, `bindonequip`, `buyingstore`, `delay`," + " `view`, `bindonequip`, `forceserial`, `buyingstore`, `delay`," " `trade_flag`, `trade_group`, `nouse_flag`, `nouse_group`," " `stack_amount`, `stack_flag`, `sprite`, `script`," " `equip_script`, `unequip_script`" diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 1d811e3cb..e50ebfd3d 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -5,18 +5,14 @@ #ifndef MAP_ITEMDB_H #define MAP_ITEMDB_H -#include "map.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/db.h" -#include "../common/mmo.h" // ITEM_NAME_LENGTH -#include "../common/sql.h" +/* #include "map/map.h" */ +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/db.h" +#include "common/mmo.h" // ITEM_NAME_LENGTH +#include "common/sql.h" -/** - * Declarations - **/ -struct item_group; -struct item_package; +struct script_code; /** * Defines @@ -371,6 +367,63 @@ enum ItemNouseRestrictions { INR_ALL = 0x1 ///< Sum of all the above values }; +struct item_combo { + struct script_code *script; + unsigned short nameid[MAX_ITEMS_PER_COMBO];/* nameid array */ + unsigned char count; + unsigned short id;/* id of this combo */ +}; + +struct item_group { + unsigned short id; + unsigned short *nameid; + unsigned short qty; +}; + +struct item_chain_entry { + unsigned short id; + unsigned short rate; + struct item_chain_entry *next; +}; + +struct item_chain { + struct item_chain_entry *items; + unsigned short qty; +}; + +struct item_package_rand_entry { + unsigned short id; + unsigned short qty; + unsigned short rate; + unsigned short hours; + unsigned int announce : 1; + unsigned int named : 1; + unsigned int force_serial: 1; + struct item_package_rand_entry *next; +}; + +struct item_package_must_entry { + unsigned short id; + unsigned short qty; + unsigned short hours; + unsigned int announce : 1; + unsigned int named : 1; + unsigned int force_serial : 1; +}; + +struct item_package_rand_group { + struct item_package_rand_entry *random_list; + unsigned short random_qty; +}; + +struct item_package { + unsigned short id; + struct item_package_rand_group *random_groups; + struct item_package_must_entry *must_items; + unsigned short random_qty; + unsigned short must_qty; +}; + struct item_data { uint16 nameid; char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH]; @@ -415,6 +468,7 @@ struct item_data { unsigned buyingstore : 1; unsigned bindonequip : 1; unsigned keepafteruse : 1; + unsigned force_serial : 1; } flag; struct {// item stacking limitation unsigned short amount; @@ -440,61 +494,6 @@ struct item_data { unsigned int hdatac; }; -struct item_combo { - struct script_code *script; - unsigned short nameid[MAX_ITEMS_PER_COMBO];/* nameid array */ - unsigned char count; - unsigned short id;/* id of this combo */ -}; - -struct item_group { - unsigned short id; - unsigned short *nameid; - unsigned short qty; -}; - -struct item_chain_entry { - unsigned short id; - unsigned short rate; - struct item_chain_entry *next; -}; - -struct item_chain { - struct item_chain_entry *items; - unsigned short qty; -}; - -struct item_package_rand_entry { - unsigned short id; - unsigned short qty; - unsigned short rate; - unsigned short hours; - unsigned int announce : 1; - unsigned int named : 1; - struct item_package_rand_entry *next; -}; - -struct item_package_must_entry { - unsigned short id; - unsigned short qty; - unsigned short hours; - unsigned int announce : 1; - unsigned int named : 1; -}; - -struct item_package_rand_group { - struct item_package_rand_entry *random_list; - unsigned short random_qty; -}; - -struct item_package { - unsigned short id; - struct item_package_rand_group *random_groups; - struct item_package_must_entry *must_items; - unsigned short random_qty; - unsigned short must_qty; -}; - #define itemdb_name(n) (itemdb->search(n)->name) #define itemdb_jname(n) (itemdb->search(n)->jname) #define itemdb_type(n) (itemdb->search(n)->type) diff --git a/src/map/log.c b/src/map/log.c index f18efbfb7..0a9b16418 100644 --- a/src/map/log.c +++ b/src/map/log.c @@ -6,22 +6,22 @@ #include "log.h" +#include "map/battle.h" +#include "map/itemdb.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/pc.h" +#include "common/cbasetypes.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/sql.h" // SQL_INNODB +#include "common/strlib.h" +#include "common/HPM.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "battle.h" -#include "itemdb.h" -#include "map.h" -#include "mob.h" -#include "pc.h" -#include "../common/cbasetypes.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/sql.h" // SQL_INNODB -#include "../common/strlib.h" -#include "../common/HPM.h" - struct log_interface log_s; /// obtain log type character for item/zeny logs diff --git a/src/map/log.h b/src/map/log.h index b4b8b84f4..ef654149c 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -5,8 +5,8 @@ #ifndef MAP_LOG_H #define MAP_LOG_H -#include "../common/cbasetypes.h" -#include "../common/sql.h" +#include "common/cbasetypes.h" +#include "common/sql.h" /** * Declarations diff --git a/src/map/mail.c b/src/map/mail.c index 7ba7d7470..184e2be8d 100644 --- a/src/map/mail.c +++ b/src/map/mail.c @@ -6,17 +6,18 @@ #include "mail.h" +#include "map/atcommand.h" +#include "map/clif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/pc.h" +#include "map/storage.h" +#include "common/nullpo.h" +#include "common/showmsg.h" + #include <time.h> #include <string.h> -#include "atcommand.h" -#include "clif.h" -#include "itemdb.h" -#include "log.h" -#include "pc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" - struct mail_interface mail_s; void mail_clear(struct map_session_data *sd) @@ -36,7 +37,7 @@ int mail_removeitem(struct map_session_data *sd, short flag) if( sd->mail.amount ) { if (flag) // Item send - pc->delitem(sd, sd->mail.index, sd->mail.amount, 1, 0, LOG_TYPE_MAIL); + pc->delitem(sd, sd->mail.index, sd->mail.amount, 1, DELITEM_NORMAL, LOG_TYPE_MAIL); else clif->additem(sd, sd->mail.index, sd->mail.amount, 0); } @@ -151,7 +152,7 @@ int mail_openmail(struct map_session_data *sd) { nullpo_ret(sd); - if( sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading ) + if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->state.vending || sd->state.buyingstore || sd->state.trading) return 0; clif->mail_window(sd->fd, 0); diff --git a/src/map/mail.h b/src/map/mail.h index db49ca39e..4f325067d 100644 --- a/src/map/mail.h +++ b/src/map/mail.h @@ -5,7 +5,7 @@ #ifndef MAP_MAIL_H #define MAP_MAIL_H -#include "../common/cbasetypes.h" +#include "common/cbasetypes.h" struct item; struct mail_message; diff --git a/src/map/map.c b/src/map/map.c index c79d49c3e..dc935079a 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -4,65 +4,64 @@ #define HERCULES_CORE -#include "../config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, DBPATH, RENEWAL +#include "config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, DBPATH, RENEWAL #include "map.h" +#include "map/HPMmap.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/battleground.h" +#include "map/channel.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/duel.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/irc-bot.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/mapreg.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/npc.h" // npc_setcells(), npc_unsetcells() +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "map/trade.h" +#include "map/unit.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/console.h" +#include "common/core.h" +#include "common/ers.h" +#include "common/grfio.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" // WFIFO*() +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> - -#include "HPMmap.h" -#include "atcommand.h" -#include "battle.h" -#include "battleground.h" -#include "channel.h" -#include "chat.h" -#include "chrif.h" -#include "clif.h" -#include "duel.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "instance.h" -#include "intif.h" -#include "irc-bot.h" -#include "itemdb.h" -#include "log.h" -#include "mail.h" -#include "mapreg.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "npc.h" // npc_setcells(), npc_unsetcells() -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "quest.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "storage.h" -#include "trade.h" -#include "unit.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/console.h" -#include "../common/core.h" -#include "../common/ers.h" -#include "../common/grfio.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" // WFIFO*() -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - #ifndef _WIN32 #include <unistd.h> #endif @@ -1844,13 +1843,13 @@ int map_quit(struct map_session_data *sd) { for( i = 0; i < EQI_MAX; i++ ) { if( sd->equip_index[ i ] >= 0 ) if( !pc->isequip( sd , sd->equip_index[ i ] ) ) - pc->unequipitem( sd , sd->equip_index[ i ] , 2 ); + pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE); } // Return loot to owner if( sd->pd ) pet->lootitem_drop(sd->pd, sd); - if( sd->state.storage_flag == 1 ) sd->state.storage_flag = 0; // No need to Double Save Storage on Quit. + if( sd->state.storage_flag == STORAGE_FLAG_NORMAL ) sd->state.storage_flag = STORAGE_FLAG_CLOSED; // No need to Double Save Storage on Quit. if( sd->ed ) { elemental->clean_effect(sd->ed); @@ -6140,10 +6139,7 @@ void map_defaults(void) { map->bl_list_size = 0; //all in a big chunk, respects order - memset(&map->bl_head,0,sizeof(map->bl_head) - + sizeof(map->zone_all) - + sizeof(map->zone_pk) - ); + memset(ZEROED_BLOCK_POS(map), 0, ZEROED_BLOCK_SIZE(map)); map->cpsd = NULL; map->list = NULL; diff --git a/src/map/map.h b/src/map/map.h index 26aac7720..8d879cd56 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -5,17 +5,18 @@ #ifndef MAP_MAP_H #define MAP_MAP_H -#include "../config/core.h" +#include "config/core.h" -#include <stdarg.h> +#include "map/atcommand.h" +#include "common/cbasetypes.h" +#include "common/core.h" // CORE_ST_LAST +#include "common/db.h" +#include "common/mapindex.h" +#include "common/mmo.h" +#include "common/sql.h" -#include "atcommand.h" -#include "../common/cbasetypes.h" -#include "../common/core.h" // CORE_ST_LAST -#include "../common/db.h" -#include "../common/mapindex.h" -#include "../common/mmo.h" -#include "../common/sql.h" +#include <stdio.h> +#include <stdarg.h> struct mob_data; struct npc_data; @@ -65,16 +66,6 @@ enum MOBID { MOBID_MAGICDECOY_WIND = 2046, }; -// The following system marks a different job ID system used by the map server, -// which makes a lot more sense than the normal one. [Skotlex] -// These marks the "level" of the job. -#define JOBL_2_1 0x100 //256 -#define JOBL_2_2 0x200 //512 -#define JOBL_2 0x300 -#define JOBL_UPPER 0x1000 //4096 -#define JOBL_BABY 0x2000 //8192 -#define JOBL_THIRD 0x4000 //16384 - // For filtering and quick checking. #define MAPID_BASEMASK 0x00ff #define MAPID_UPPERMASK 0x0fff @@ -266,10 +257,15 @@ enum { RC_DEMIHUMAN, RC_ANGEL, RC_DRAGON, + RC_PLAYER, RC_BOSS, RC_NONBOSS, + RC_MAX, RC_NONDEMIHUMAN, - RC_MAX + RC_NONPLAYER, + RC_DEMIPLAYER, + RC_NONDEMIPLAYER, + RC_ALL = 0xFF }; enum { @@ -280,6 +276,8 @@ enum { RC2_GOLEM, RC2_GUARDIAN, RC2_NINJA, + RC2_SCARABA, + RC2_TURTLE, RC2_MAX }; @@ -294,7 +292,8 @@ enum elements { ELE_DARK, ELE_GHOST, ELE_UNDEAD, - ELE_MAX + ELE_MAX, + ELE_ALL = 0xFF }; /** @@ -425,6 +424,7 @@ enum status_point_types { SP_SKILL_COOLDOWN,SP_SKILL_FIXEDCAST, SP_SKILL_VARIABLECAST, SP_FIXCASTRATE, SP_VARCASTRATE, //2050-2054 SP_SKILL_USE_SP,SP_MAGIC_ATK_ELE, SP_ADD_FIXEDCAST, SP_ADD_VARIABLECAST, //2055-2058 SP_SET_DEF_RACE,SP_SET_MDEF_RACE, //2059-2060 + SP_RACE_TOLERANCE, //2061 /* must be the last, plugins add bonuses from this value onwards */ SP_LAST_KNOWN, @@ -895,15 +895,15 @@ struct map_interface { DBMap* regen_db; // int id -> struct block_list* (status_natural_heal processing) DBMap* zone_db; // string => struct map_zone_data DBMap* iwall_db; - /* order respected by map_defaults() in order to zero */ - /* from block_free until zone_pk */ struct block_list **block_free; int block_free_count, block_free_lock, block_free_list_size; struct block_list **bl_list; int bl_list_count, bl_list_size; +BEGIN_ZEROED_BLOCK; // This block is zeroed in map_defaults() struct block_list bl_head; struct map_zone_data zone_all;/* used as a base on all maps */ struct map_zone_data zone_pk;/* used for (pk_mode) */ +END_ZEROED_BLOCK; /* */ struct map_session_data *cpsd; struct map_data *list; diff --git a/src/map/mapreg.h b/src/map/mapreg.h index 9c9a1acee..cafd25b64 100644 --- a/src/map/mapreg.h +++ b/src/map/mapreg.h @@ -5,9 +5,11 @@ #ifndef MAP_MAPREG_H #define MAP_MAPREG_H -#include "script.h" // struct reg_db -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "map/script.h" // struct reg_db +#include "common/cbasetypes.h" +#include "common/db.h" + +struct eri; /** Container for a mapreg value */ struct mapreg_save { diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c index 0092a6c61..bed40e295 100644 --- a/src/map/mapreg_sql.c +++ b/src/map/mapreg_sql.c @@ -6,20 +6,20 @@ #include "mapreg.h" +#include "map/map.h" // map-"mysql_handle +#include "map/script.h" +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/showmsg.h" +#include "common/sql.h" +#include "common/strlib.h" +#include "common/timer.h" + #include <stdlib.h> #include <string.h> -#include "map.h" // map->mysql_handle -#include "script.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" -#include "../common/sql.h" -#include "../common/strlib.h" -#include "../common/timer.h" - struct mapreg_interface mapreg_s; #define MAPREG_AUTOSAVE_INTERVAL (300*1000) diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 84f6a3c41..c60234d5d 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -6,42 +6,43 @@ #include "mercenary.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/trade.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/mmo.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "guild.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "trade.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/mmo.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct mercenary_interface mercenary_s; +struct s_mercenary_db mercdb[MAX_MERCENARY_CLASS]; int merc_search_index(int class_) { @@ -449,7 +450,7 @@ bool read_mercenarydb_sub(char* str[], int columns, int current) { } int read_mercenarydb(void) { - memset(mercenary->db,0,sizeof(mercenary->db)); + memset(mercenary->db, 0, sizeof(struct s_mercenary_db) * MAX_MERCENARY_CLASS); sv->readdb(map->db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, mercenary->read_db_sub); return 0; @@ -511,7 +512,8 @@ void mercenary_defaults(void) { mercenary = &mercenary_s; /* vars */ - memset(mercenary->db,0,sizeof(mercenary->db)); + mercenary->db = mercdb; + memset(mercenary->db, 0, sizeof(struct s_mercenary_db) * MAX_MERCENARY_CLASS); /* funcs */ diff --git a/src/map/mercenary.h b/src/map/mercenary.h index fbf3603f6..c96b5a5ef 100644 --- a/src/map/mercenary.h +++ b/src/map/mercenary.h @@ -4,9 +4,11 @@ #ifndef MAP_MERCENARY_H #define MAP_MERCENARY_H -#include "status.h" // struct status_data, struct status_change -#include "unit.h" // struct unit_data -#include "../common/cbasetypes.h" +#include "map/status.h" // struct status_data, struct status_change +#include "map/unit.h" // struct unit_data +#include "common/cbasetypes.h" + +struct map_session_data; // number of cells that a mercenary can walk to from it's master before being warped #define MAX_MER_DISTANCE 15 @@ -56,7 +58,7 @@ struct mercenary_interface { /* vars */ - struct s_mercenary_db db[MAX_MERCENARY_CLASS]; + struct s_mercenary_db *db; /* funcs */ diff --git a/src/map/mob.c b/src/map/mob.c index 8a8e96508..8112c208c 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -4,49 +4,49 @@ #define HERCULES_CORE -#include "../config/core.h" // AUTOLOOT_DISTANCE, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, RENEWAL_DROP, RENEWAL_EXP +#include "config/core.h" // AUTOLOOT_DISTANCE, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, RENEWAL_DROP, RENEWAL_EXP #include "mob.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/clif.h" +#include "map/date.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "clif.h" -#include "date.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mercenary.h" -#include "npc.h" -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "quest.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct mob_interface mob_s; #define ACTIVE_AI_RANGE 2 //Distance added on top of 'AREA_SIZE' at which mobs enter active AI mode. @@ -378,14 +378,14 @@ bool mob_ksprotected(struct block_list *src, struct block_list *target) { break; // No KS Protected if( sd->bl.id == sce->val1 || // Same Owner - (sce->val2 == 2 && sd->status.party_id && sd->status.party_id == sce->val3) || // Party KS allowed - (sce->val2 == 3 && sd->status.guild_id && sd->status.guild_id == sce->val4) ) // Guild KS allowed + (sce->val2 == KSPROTECT_PARTY && sd->status.party_id && sd->status.party_id == sce->val3) || // Party KS allowed + (sce->val2 == KSPROTECT_GUILD && sd->status.guild_id && sd->status.guild_id == sce->val4) ) // Guild KS allowed break; if( t_sd && ( - (sce->val2 == 1 && sce->val1 != t_sd->bl.id) || - (sce->val2 == 2 && sce->val3 && sce->val3 != t_sd->status.party_id) || - (sce->val2 == 3 && sce->val4 && sce->val4 != t_sd->status.guild_id)) ) + (sce->val2 == KSPROTECT_SELF && sce->val1 != t_sd->bl.id) || + (sce->val2 == KSPROTECT_PARTY && sce->val3 && sce->val3 != t_sd->status.party_id) || + (sce->val2 == KSPROTECT_GUILD && sce->val4 && sce->val4 != t_sd->status.guild_id)) ) break; if( (pl_sd = map->id2sd(sce->val1)) == NULL || pl_sd->bl.m != md->bl.m ) @@ -1298,7 +1298,7 @@ int mob_unlocktarget(struct mob_data *md, int64 tick) { break; default: mob_stop_attack(md); - mob_stop_walking(md,1); //Stop chasing. + mob_stop_walking(md, STOPWALKING_FLAG_FIXPOS); //Stop chasing. md->state.skillstate = MSS_IDLE; if(battle_config.mob_ai&0x8) //Walk instantly after dropping target md->next_walktime = tick+rnd()%1000; @@ -1975,7 +1975,7 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage) case BL_MOB: { struct mob_data* md2 = (TBL_MOB*)src; - if( md2->special_state.ai && md2->master_id ) { + if (md2->special_state.ai != AI_NONE && md2->master_id) { struct map_session_data* msd = map->id2sd(md2->master_id); if( msd ) char_id = msd->status.char_id; @@ -2170,7 +2170,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { if( !(type&2) //No exp && (!map->list[m].flag.pvp || battle_config.pvp_exp) //Pvp no exp rule [MouseJstr] - && (!md->master_id || !md->special_state.ai) //Only player-summoned mobs do not give exp. [Skotlex] + && (!md->master_id || md->special_state.ai == AI_NONE) //Only player-summoned mobs do not give exp. [Skotlex] && (!map->list[m].flag.nobaseexp || !map->list[m].flag.nojobexp) //Gives Exp ) { //Experience calculation. int bonus = 100; //Bonus on top of your share (common to all attackers). @@ -2298,9 +2298,9 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { } //End EXP giving. if( !(type&1) && !map->list[m].flag.nomobloot && !md->state.rebirth && ( - !md->special_state.ai || //Non special mob + md->special_state.ai == AI_NONE || //Non special mob battle_config.alchemist_summon_reward == 2 || //All summoned give drops - (md->special_state.ai==2 && battle_config.alchemist_summon_reward == 1) //Marine Sphere Drops items. + (md->special_state.ai == AI_SPHERE && battle_config.alchemist_summon_reward == 1) //Marine Sphere Drops items. ) ) { // Item Drop struct item_drop_list *dlist = ers_alloc(item_drop_list_ers, struct item_drop_list); @@ -2473,7 +2473,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { timer->add(tick + (!battle_config.delay_battle_damage?500:0), mob->delay_item_drop, 0, (intptr_t)dlist); } - if(mvp_sd && md->db->mexp > 0 && !md->special_state.ai) { + if(mvp_sd && md->db->mexp > 0 && md->special_state.ai == AI_NONE) { int log_mvp[2] = {0}; unsigned int mexp; double exp; @@ -2746,7 +2746,7 @@ int mob_class_change (struct mob_data *md, int class_) if( mob_is_treasure(md) ) return 0; //Treasure Boxes - if( md->special_state.ai > 1 ) + if( md->special_state.ai > AI_ATTACK ) return 0; //Marine Spheres and Floras. if( mob->is_clone(md->class_) ) @@ -2764,7 +2764,7 @@ int mob_class_change (struct mob_data *md, int class_) memcpy(md->name,md->db->jname,NAME_LENGTH); mob_stop_attack(md); - mob_stop_walking(md, 0); + mob_stop_walking(md, STOPWALKING_FLAG_NONE); unit->skillcastcancel(&md->bl, 0); status->set_viewdata(&md->bl, class_); clif->class_change(&md->bl, md->vd->class_, 1); @@ -3016,7 +3016,7 @@ struct block_list *mob_getfriendhprate(struct mob_data *md,int min_rate,int max_ nullpo_retr(NULL, md); - if (md->special_state.ai) //Summoned creatures. [Skotlex] + if (md->special_state.ai != AI_NONE) //Summoned creatures. [Skotlex] type = BL_PC; map->foreachinrange(mob->getfriendhprate_sub, &md->bl, 8, type,md,min_rate,max_rate,&fr); @@ -3302,7 +3302,7 @@ int mobskill_event(struct mob_data *md, struct block_list *src, int64 tick, int if(md->bl.prev == NULL || md->status.hp <= 0) return 0; - if( md->special_state.ai == 2 ) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex] + if (md->special_state.ai == AI_SPHERE) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex] md->state.alchemist = 1; return mob->skill_use(md, timer->gettick(), MSC_ALCHEMIST); } @@ -3402,7 +3402,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons int idx = pc->skill_tree[pc->class2idx(sd->status.class_)][j].idx; int skill_id = pc->skill_tree[pc->class2idx(sd->status.class_)][j].id; if (!skill_id || sd->status.skill[idx].lv < 1 || - (skill->db[idx].inf2&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL)) + (skill->dbs->db[idx].inf2&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL)) ) continue; for(h = 0; h < map->list[sd->bl.m].zone->disabled_skills_count; h++) { @@ -3435,7 +3435,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons ms[i].casttime = skill->cast_fix(&sd->bl,skill_id, ms[i].skill_lv); ms[i].delay = 5000+skill->delay_fix(&sd->bl,skill_id, ms[i].skill_lv); - inf = skill->db[idx].inf; + inf = skill->dbs->db[idx].inf; if (inf&INF_ATTACK_SKILL) { ms[i].target = MST_TARGET; ms[i].cond1 = MSC_ALWAYS; @@ -4399,13 +4399,13 @@ bool mob_parse_row_mobskilldb(char** str, int columns, int current) if ( skill->get_casttype2(sidx) == CAST_GROUND) {//Ground skill. if (ms->target > MST_AROUND) { ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target for ground skill %d (%s) for %s.\n", - ms->skill_id, skill->db[sidx].name, + ms->skill_id, skill->dbs->db[sidx].name, mob_id < 0?"all mobs":mob->db_data[mob_id]->sprite); ms->target = MST_TARGET; } } else if (ms->target > MST_MASTER) { ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target 'around' for non-ground skill %d (%s) for %s.\n", - ms->skill_id, skill->db[sidx].name, + ms->skill_id, skill->dbs->db[sidx].name, mob_id < 0?"all mobs":mob->db_data[mob_id]->sprite); ms->target = MST_TARGET; } diff --git a/src/map/mob.h b/src/map/mob.h index 02ae1630a..85d2bf9b8 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -5,11 +5,11 @@ #ifndef MAP_MOB_H #define MAP_MOB_H -#include "map.h" // struct status_data, struct view_data, struct mob_skill -#include "status.h" // struct status_data, struct status_change -#include "unit.h" // struct unit_data -#include "../common/cbasetypes.h" -#include "../common/mmo.h" // struct item +#include "map/map.h" // struct block_list +#include "map/status.h" // struct status_data, struct status_change +#include "map/unit.h" // struct unit_data, view_data +#include "common/cbasetypes.h" +#include "common/mmo.h" // struct item #define MAX_RANDOMMONSTER 5 @@ -38,7 +38,7 @@ #define MOB_CLONE_END MAX_MOB_DB //Used to determine default enemy type of mobs (for use in each in range calls) -#define DEFAULT_ENEMY_TYPE(md) ((md)->special_state.ai?BL_CHAR:BL_MOB|BL_PC|BL_HOM|BL_MER) +#define DEFAULT_ENEMY_TYPE(md) ((md)->special_state.ai != AI_NONE ?BL_CHAR:BL_MOB|BL_PC|BL_HOM|BL_MER) #define MAX_MOB_CHAT 250 //Max Skill's messages @@ -79,11 +79,23 @@ enum size { }; enum ai { - AI_NONE = 0, - AI_ATTACK, - AI_SPHERE, - AI_FLORA, - AI_ZANZOU, + AI_NONE = 0, //0: Normal mob. + AI_ATTACK, //1: Standard summon, attacks mobs. + AI_SPHERE, //2: Alchemist Marine Sphere + AI_FLORA, //3: Alchemist Summon Flora + AI_ZANZOU, //4: Summon Zanzou + + AI_MAX +}; + +/** + * Acceptable values for map_session_data.state.noks + */ +enum ksprotection_mode { + KSPROTECT_NONE = 0, + KSPROTECT_SELF = 1, + KSPROTECT_PARTY = 2, + KSPROTECT_GUILD = 3, }; struct mob_skill { @@ -141,13 +153,8 @@ struct mob_data { struct mob_db *db; //For quick data access (saves doing mob_db(md->class_) all the time) [Skotlex] char name[NAME_LENGTH]; struct { - unsigned int size : 2; //Small/Big monsters. - unsigned int ai : 4; //Special AI for summoned monsters. - //0: Normal mob. - //1: Standard summon, attacks mobs. - //2: Alchemist Marine Sphere - //3: Alchemist Summon Flora - //4: Summon Zanzou + unsigned int size : 2; //Small/Big monsters. @see enum size + unsigned int ai : 4; //Special AI for summoned monsters. @see enum ai unsigned int clone : 1;/* is clone? 1:0 */ } special_state; //Special mob information that does not needs to be zero'ed on mob respawn. struct { diff --git a/src/map/npc.c b/src/map/npc.c index 16789b726..a79062c77 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -4,9 +4,37 @@ #define HERCULES_CORE -#include "../config/core.h" // NPC_SECURE_TIMEOUT_INPUT, NPC_SECURE_TIMEOUT_MENU, NPC_SECURE_TIMEOUT_NEXT, SECURE_NPCTIMEOUT, SECURE_NPCTIMEOUT_INTERVAL +#include "config/core.h" // NPC_SECURE_TIMEOUT_INPUT, NPC_SECURE_TIMEOUT_MENU, NPC_SECURE_TIMEOUT_NEXT, SECURE_NPCTIMEOUT, SECURE_NPCTIMEOUT_INTERVAL #include "npc.h" +#include "map/battle.h" +#include "map/chat.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/unit.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <errno.h> #include <math.h> #include <stdio.h> @@ -14,33 +42,6 @@ #include <string.h> #include <time.h> -#include "battle.h" -#include "chat.h" -#include "clif.h" -#include "instance.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "unit.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct npc_interface npc_s; static int npc_id=START_NPC_NUM; @@ -62,34 +63,52 @@ static struct view_data npc_viewdb2[MAX_NPC_CLASS2_END-MAX_NPC_CLASS2_START]; /* for speedup */ unsigned int npc_market_qty[MAX_INVENTORY]; -static struct script_event_s -{ +static struct script_event_s { //Holds pointers to the commonly executed scripts for speedup. [Skotlex] struct event_data *event[UCHAR_MAX]; const char *event_name[UCHAR_MAX]; uint8 event_count; } script_event[NPCE_MAX]; -struct view_data* npc_get_viewdata(int class_) +/** + * Returns the viewdata for normal npc classes. + * @param class_ The NPC class ID. + * @return The viewdata, or NULL if the ID is invalid. + */ +struct view_data *npc_get_viewdata(int class_) { - //Returns the viewdata for normal npc classes. - if( class_ == INVISIBLE_CLASS ) + if (class_ == INVISIBLE_CLASS) return &npc_viewdb[0]; - if (npc->db_checkid(class_) || class_ == WARP_CLASS){ - if( class_ > MAX_NPC_CLASS2_START ){ - return &npc_viewdb2[class_-MAX_NPC_CLASS2_START]; - }else{ + if (npc->db_checkid(class_)) { + if (class_ < MAX_NPC_CLASS) { return &npc_viewdb[class_]; + } else if (class_ >= MAX_NPC_CLASS2_START && class_ < MAX_NPC_CLASS2_END) { + return &npc_viewdb2[class_-MAX_NPC_CLASS2_START]; } } return NULL; } -//Checks if a given id is a valid npc id. [Skotlex] -//Since new npcs are added all the time, the max valid value is the one before the first mob (Scorpion = 1001) +/** + * Checks if a given id is a valid npc id. + * + * Since new npcs are added all the time, the max valid value is the one before the first mob (Scorpion = 1001) + * + * @param id The NPC ID to validate. + * @return Whether the value is a valid ID. + */ bool npc_db_checkid(int id) { - return ((id >= 46 && id <= 125) || id == HIDDEN_WARP_CLASS || (id > 400 && id < MAX_NPC_CLASS) || id == INVISIBLE_CLASS || (id > MAX_NPC_CLASS2_START && id < MAX_NPC_CLASS2_END)); + if (id >= WARP_CLASS && id <= 125) // First subrange + return true; + if (id == HIDDEN_WARP_CLASS || id == INVISIBLE_CLASS) // Special IDs not included in the valid ranges + return true; + if (id > 400 && id < MAX_NPC_CLASS) // Second subrange + return true; + if (id >= MAX_NPC_CLASS2_START && id < MAX_NPC_CLASS2_END) // Second range + return true; + // Anything else is invalid + return false; } /// Returns a new npc id that isn't being used in id_db. @@ -185,7 +204,7 @@ int npc_enable_sub(struct block_list *bl, va_list ap) if (sd->npc_id != 0) return 0; - pc_stop_walking(sd,1); + pc_stop_walking(sd, STOPWALKING_FLAG_FIXPOS); npc->click(sd,nd); } } @@ -1565,8 +1584,8 @@ bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) { } /* nothing to display, no items available */ - if( i == nd->u.scr.shop->items ) { - clif->colormes(sd->fd,COLOR_RED, msg_sd(sd,881)); + if (i == nd->u.scr.shop->items) { + clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd,881)); return false; } @@ -2038,19 +2057,18 @@ int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* item_li script->setarray_pc(sd, "@sold_nameid", i, (void*)(intptr_t)sd->status.inventory[idx].nameid, &key_nameid); script->setarray_pc(sd, "@sold_quantity", i, (void*)(intptr_t)item_list[i*2+1], &key_amount); - - if (itemdb->isequip(sd->status.inventory[idx].nameid)) { - // process equipment based information into the arrays - script->setarray_pc(sd, "@sold_refine", i, (void*)(intptr_t)sd->status.inventory[idx].refine, &key_refine); - script->setarray_pc(sd, "@sold_attribute", i, (void*)(intptr_t)sd->status.inventory[idx].attribute, &key_attribute); - script->setarray_pc(sd, "@sold_identify", i, (void*)(intptr_t)sd->status.inventory[idx].identify, &key_identify); - - for (j = 0; j < MAX_SLOTS; j++) { - // store each of the cards from the equipment in the array - snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1); - script->setarray_pc(sd, card_slot, i, (void*)(intptr_t)sd->status.inventory[idx].card[j], &key_card[j]); - } + + // process item based information into the arrays + script->setarray_pc(sd, "@sold_refine", i, (void*)(intptr_t)sd->status.inventory[idx].refine, &key_refine); + script->setarray_pc(sd, "@sold_attribute", i, (void*)(intptr_t)sd->status.inventory[idx].attribute, &key_attribute); + script->setarray_pc(sd, "@sold_identify", i, (void*)(intptr_t)sd->status.inventory[idx].identify, &key_identify); + + for (j = 0; j < MAX_SLOTS; j++) { + // store each of the cards/special info from the item in the array + snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1); + script->setarray_pc(sd, card_slot, i, (void*)(intptr_t)sd->status.inventory[idx].card[j], &key_card[j]); } + } // invoke event @@ -2127,7 +2145,7 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) } } - pc->delitem(sd, idx, amount, 0, 6, LOG_TYPE_NPC); + pc->delitem(sd, idx, amount, 0, DELITEM_SOLD, LOG_TYPE_NPC); } if( z > MAX_ZENY ) @@ -3537,7 +3555,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st return strchr(start, '\n'); } - if (mobspawn.state.ai > 4 && ai != -1) { + if (mobspawn.state.ai >= AI_MAX && ai != -1) { ShowError("npc_parse_mob: Invalid ai %d for mob ID %d in file '%s', line '%d'.\n", mobspawn.state.ai, class_, filepath, strline(buffer, start - buffer)); if (retval) *retval = EXIT_FAILURE; return strchr(start, '\n'); @@ -3560,7 +3578,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st mobspawn.level = mob_lv; if (size > 0 && size <= 2) mobspawn.state.size = size; - if (ai > 0 && ai <= 4) + if (ai > AI_NONE && ai < AI_MAX) mobspawn.state.ai = ai; if (mobspawn.num > 1 && battle_config.mob_count_rate != 100) { @@ -3812,13 +3830,14 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char } else if (!strcmpi(w3,"battleground")) { struct map_zone_data *zone; - if( state ) { - if( sscanf(w4, "%d", &state) == 1 ) + if (state) { + if (w4 && sscanf(w4, "%d", &state) == 1) map->list[m].flag.battleground = state; else map->list[m].flag.battleground = 1; // Default value - } else + } else { map->list[m].flag.battleground = 0; + } if( map->list[m].flag.battleground && map->list[m].flag.pvp ) { map->list[m].flag.pvp = 0; @@ -4624,6 +4643,7 @@ int do_init_npc(bool minimal) { } if( script->lang_export_fp ) { + ShowInfo("Lang exported to '%s'\n",script->lang_export_file); fclose(script->lang_export_fp); script->lang_export_fp = NULL; } diff --git a/src/map/npc.h b/src/map/npc.h index 68d683847..bc779b56b 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -5,11 +5,11 @@ #ifndef MAP_NPC_H #define MAP_NPC_H -#include "map.h" // struct block_list -#include "status.h" // struct status_change -#include "unit.h" // struct unit_data -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "map/map.h" // struct block_list +#include "map/status.h" // struct status_change +#include "map/unit.h" // struct unit_data +#include "common/cbasetypes.h" +#include "common/db.h" struct HPluginData; struct view_data; @@ -121,7 +121,7 @@ enum actor_classes { // Old NPC range #define MAX_NPC_CLASS 1000 // New NPC range -#define MAX_NPC_CLASS2_START 10000 +#define MAX_NPC_CLASS2_START 10001 #define MAX_NPC_CLASS2_END 10110 //Script NPC events. @@ -288,7 +288,7 @@ void npc_defaults(void); /* comes from npc_chat.c */ #ifdef PCRE_SUPPORT -#include "../../3rdparty/pcre/include/pcre.h" +#include <pcre/include/pcre.h> /* Structure containing all info associated with a single pattern block */ struct pcrematch_entry { struct pcrematch_entry* next; diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c index 8bc246819..3fe379f36 100644 --- a/src/map/npc_chat.c +++ b/src/map/npc_chat.c @@ -8,22 +8,22 @@ #include "npc.h" // struct npc_data +#include "map/mob.h" // struct mob_data +#include "map/pc.h" // struct map_session_data +#include "map/script.h" // set_var() +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "common/timer.h" + +#include <pcre/include/pcre.h> + #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "../../3rdparty/pcre/include/pcre.h" - -#include "mob.h" // struct mob_data -#include "pc.h" // struct map_session_data -#include "script.h" // set_var() -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/timer.h" - /** * interface sources **/ diff --git a/src/map/packets.h b/src/map/packets.h index ccf1c28ef..6623c091c 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -448,6 +448,8 @@ packet(0x020a,10); //packet(0x020b,-1); //packet(0x020c,-1); packet(0x020d,-1); +packet(0x974,2,clif->cancelmergeitem); +packet(0x96e,-1,clif->ackmergeitems); //2004-07-05aSakexe #if PACKETVER >= 20040705 @@ -2802,6 +2804,21 @@ packet(0x020d,-1); packet(0x0a00,269); #endif +/* Roulette System [Yommy/Hercules] */ +#if PACKETVER >= 20141016 + packet(0x0A19,2,clif->pRouletteOpen,0); // HEADER_CZ_REQ_OPEN_ROULETTE + packet(0x0A1A,23); // HEADER_ZC_ACK_OPEN_ROULETTE + packet(0x0A1B,2,clif->pRouletteInfo,0); // HEADER_CZ_REQ_ROULETTE_INFO + packet(0x0A1C,-1); // HEADER_ZC_ACK_ROULEITTE_INFO + packet(0x0A1D,2,clif->pRouletteClose,0); // HEADER_CZ_REQ_CLOSE_ROULETTE + packet(0x0A1E,3); // HEADER_ZC_ACK_CLOSE_ROULETTE + packet(0x0A1F,2,clif->pRouletteGenerate,0); // HEADER_CZ_REQ_GENERATE_ROULETTE + packet(0x0A20,21); // HEADER_ZC_ACK_GENERATE_ROULETTE + packet(0x0A21,3,clif->pRouletteRecvItem,2); // HEADER_CZ_RECV_ROULETTE_ITEM + packet(0x0A22,5); // HEADER_ZC_RECV_ROULETTE_ITEM +#endif + + // 2014-10-22bRagexe - YomRawr #if PACKETVER >= 20141022 packet(0x0369,7,clif->pActionRequest,2,6); @@ -2835,21 +2852,42 @@ packet(0x020d,-1); packet(0x0438,36,clif->pStoragePassword,0); #endif -/* Roulette System [Yommy/Hercules] */ -#if PACKETVER >= 20141016 - packet(0x0A19,2,clif->pRouletteOpen,0); // HEADER_CZ_REQ_OPEN_ROULETTE - packet(0x0A1A,23); // HEADER_ZC_ACK_OPEN_ROULETTE - packet(0x0A1B,2,clif->pRouletteInfo,0); // HEADER_CZ_REQ_ROULETTE_INFO - packet(0x0A1C,-1); // HEADER_ZC_ACK_ROULEITTE_INFO - packet(0x0A1D,2,clif->pRouletteClose,0); // HEADER_CZ_REQ_CLOSE_ROULETTE - packet(0x0A1E,3); // HEADER_ZC_ACK_CLOSE_ROULETTE - packet(0x0A1F,2,clif->pRouletteGenerate,0); // HEADER_CZ_REQ_GENERATE_ROULETTE - packet(0x0A20,21); // HEADER_ZC_ACK_GENERATE_ROULETTE - packet(0x0A21,3,clif->pRouletteRecvItem,2); // HEADER_CZ_RECV_ROULETTE_ITEM - packet(0x0A22,5); // HEADER_ZC_RECV_ROULETTE_ITEM -#endif - -/* PacketKeys: http://hercules.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ */ +// 2015-05-13aRagexe +#if PACKETVER >= 20150513 + packet(0x0369,7,clif->pActionRequest,2,6); + packet(0x083C,10,clif->pUseSkillToId,2,4,6); + packet(0x0437,5,clif->pWalkToXY,2); + packet(0x035F,6,clif->pTickSend,2); + packet(0x0924,5,clif->pChangeDir,2,4); + packet(0x0958,6,clif->pTakeItem,2); + packet(0x0885,6,clif->pDropItem,2,4); + packet(0x0879,8,clif->pMoveToKafra,2,4); + packet(0x0864,8,clif->pMoveFromKafra,2,4); + packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x096A,6,clif->pGetCharNameRequest,2); + packet(0x0368,6,clif->pSolveCharName,2); + packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10); + packet(0x0835,2,clif->pSearchStoreInfoNextPage,0); + packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x0360,6,clif->pReqClickBuyingStore,2); + packet(0x022D,2,clif->pReqCloseBuyingStore,0); + packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); + packet(0x0883,18,clif->pPartyBookingRegisterReq,2,4); + packet(0x02C4,8); // CZ_JOIN_BATTLE_FIELD + packet(0x0960,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x0363,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x094A,26,clif->pPartyInvite2,2); + packet(0x0927,4); // CZ_GANGSI_RANK + packet(0x08A8,26,clif->pFriendsListAdd,2); + packet(0x0817,5,clif->pHomMenu,2,4); + packet(0x0923,36,clif->pStoragePassword,0); + packet(0x09e8,11,clif->pDull); //CZ_OPEN_MAILBOX + packet(0x0a2e,6,clif->pDull); //TITLE +#endif + +/* PacketKeys: http://herc.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ */ #if PACKETVER >= 20110817 packetKeys(0x053D5CED,0x3DED6DED,0x6DED6DED); /* Thanks to Shakto */ #endif @@ -3088,6 +3126,12 @@ packet(0x020d,-1); packetKeys(0x290551EA,0x2B952C75,0x2D67669B); /* YomRawr */ #endif +// 2015 Packet Keys + +#if PACKETVER >= 20150513 + packetKeys(0x62C86D09,0x75944F17,0x112C133D); /* Dastgir */ +#endif + #if defined(OBFUSCATIONKEY1) && defined(OBFUSCATIONKEY2) && defined(OBFUSCATIONKEY3) packetKeys(OBFUSCATIONKEY1,OBFUSCATIONKEY2,OBFUSCATIONKEY3); #endif diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 71471e5c6..231321c88 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -1,13 +1,13 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -/* Hercules Renewal: Phase Two http://hercules.ws/board/topic/383-hercules-renewal-phase-two/ */ +/* Hercules Renewal: Phase Two http://herc.ws/board/topic/383-hercules-renewal-phase-two/ */ #ifndef MAP_PACKETS_STRUCT_H #define MAP_PACKETS_STRUCT_H -#include "../common/cbasetypes.h" -#include "../common/mmo.h" +#include "common/cbasetypes.h" +#include "common/mmo.h" /** * @@ -360,8 +360,8 @@ struct packet_dropflooritem { unsigned char subY; short count; } __attribute__((packed)); -#if PACKETVER < 20091103 struct packet_idle_unit2 { +#if PACKETVER < 20091103 short PacketType; #if PACKETVER >= 20071106 unsigned char objecttype; @@ -392,8 +392,13 @@ struct packet_idle_unit2 { unsigned char ySize; unsigned char state; short clevel; +#else // ! PACKETVER < 20091103 + char UNUSED; +#endif // PACKETVER < 20091103 } __attribute__((packed)); + struct packet_spawn_unit2 { +#if PACKETVER < 20091103 short PacketType; #if PACKETVER >= 20071106 unsigned char objecttype; @@ -418,8 +423,11 @@ struct packet_spawn_unit2 { unsigned char PosDir[3]; unsigned char xSize; unsigned char ySize; +#else // ! PACKETVER < 20091103 + char UNUSED; +#endif // PACKETVER < 20091103 } __attribute__((packed)); -#endif + struct packet_spawn_unit { short PacketType; #if PACKETVER >= 20091103 diff --git a/src/map/party.c b/src/map/party.c index fb738a12b..6b35debe5 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -4,36 +4,36 @@ #define HERCULES_CORE -#include "../config/core.h" // GP_BOUND_ITEMS, RENEWAL_EXP +#include "config/core.h" // GP_BOUND_ITEMS, RENEWAL_EXP #include "party.h" +#include "map/atcommand.h" //msg_txt() +#include "map/battle.h" +#include "map/clif.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" // struct mob_data +#include "map/pc.h" +#include "map/skill.h" +#include "map/status.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" // last_tick +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" //msg_txt() -#include "battle.h" -#include "clif.h" -#include "instance.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" // struct mob_data -#include "pc.h" -#include "skill.h" -#include "status.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" // last_tick -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct party_interface party_s; /*========================================== @@ -640,7 +640,7 @@ int party_optionchanged(int party_id,int account_id,int exp,int item,int flag) { if( (p=party->search(party_id))==NULL) return 0; - //Flag&1: Exp change denied. Flag&2: Item change denied. + //Flag&0x1: Exp change denied. Flag&0x10: Item change denied. if(!(flag&0x01) && p->party.exp != exp) p->party.exp=exp; if(!(flag&0x10) && p->party.item != item) { diff --git a/src/map/party.h b/src/map/party.h index a541d03cb..95faa2213 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -5,12 +5,12 @@ #ifndef MAP_PARTY_H #define MAP_PARTY_H -#include <stdarg.h> +#include "map/map.h" // TBL_PC +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/mmo.h" // struct party -#include "map.h" // TBL_PC -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/mmo.h" // struct party +#include <stdarg.h> #define PARTY_BOOKING_JOBS 6 #define PARTY_BOOKING_RESULTS 10 diff --git a/src/map/path.c b/src/map/path.c index 600dfc082..3ded5423e 100644 --- a/src/map/path.c +++ b/src/map/path.c @@ -4,21 +4,21 @@ #define HERCULES_CORE -#include "../config/core.h" // CELL_NOSTACK, CIRCULAR_AREA +#include "config/core.h" // CELL_NOSTACK, CIRCULAR_AREA #include "path.h" +#include "map/map.h" +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" + +#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <math.h> - -#include "map.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" #define SET_OPEN 0 #define SET_CLOSED 1 diff --git a/src/map/path.h b/src/map/path.h index eb42df6d0..bbd81b8c6 100644 --- a/src/map/path.h +++ b/src/map/path.h @@ -5,8 +5,8 @@ #ifndef MAP_PATH_H #define MAP_PATH_H -#include "map.h" // enum cell_chk -#include "../common/cbasetypes.h" +#include "map/map.h" // enum cell_chk +#include "common/cbasetypes.h" #define MOVE_COST 10 #define MOVE_DIAGONAL_COST 14 diff --git a/src/map/pc.c b/src/map/pc.c index 3d5e240f8..107d656f0 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4,58 +4,58 @@ #define HERCULES_CORE -#include "../config/core.h" // DBPATH, GP_BOUND_ITEMS, MAX_SPIRITBALL, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EXP, SECURE_NPCTIMEOUT +#include "config/core.h" // DBPATH, GP_BOUND_ITEMS, MAX_SPIRITBALL, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EXP, SECURE_NPCTIMEOUT #include "pc.h" +#include "map/atcommand.h" // get_atcommand_level() +#include "map/battle.h" // battle_config +#include "map/battleground.h" +#include "map/channel.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/date.h" // is_day_of_*() +#include "map/duel.h" +#include "map/elemental.h" +#include "map/guild.h" // guild-"search(), guild_request_info() +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/mob.h" // struct mob_data +#include "map/npc.h" // fake_nd +#include "map/party.h" // party-"search() +#include "map/path.h" +#include "map/pc_groups.h" +#include "map/pet.h" // pet_unlocktarget() +#include "map/quest.h" +#include "map/script.h" // script_config +#include "map/skill.h" +#include "map/status.h" // struct status_data +#include "map/storage.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/core.h" // get_svn_revision() +#include "common/malloc.h" +#include "common/mmo.h" // NAME_LENGTH, MAX_CARTS, NEW_CARTS +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" // session[] +#include "common/strlib.h" // safestrncpy() +#include "common/sysinfo.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> -#include "atcommand.h" // get_atcommand_level() -#include "battle.h" // battle_config -#include "battleground.h" -#include "channel.h" -#include "chat.h" -#include "chrif.h" -#include "clif.h" -#include "date.h" // is_day_of_*() -#include "duel.h" -#include "elemental.h" -#include "guild.h" // guild->search(), guild_request_info() -#include "homunculus.h" -#include "instance.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "mail.h" -#include "map.h" -#include "mercenary.h" -#include "mob.h" // struct mob_data -#include "npc.h" // fake_nd -#include "party.h" // party->search() -#include "path.h" -#include "pc_groups.h" -#include "pet.h" // pet_unlocktarget() -#include "quest.h" -#include "script.h" // script_config -#include "skill.h" -#include "status.h" // struct status_data -#include "storage.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/core.h" // get_svn_revision() -#include "../common/malloc.h" -#include "../common/mmo.h" // NAME_LENGTH, MAX_CARTS, NEW_CARTS -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" // session[] -#include "../common/strlib.h" // safestrncpy() -#include "../common/sysinfo.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct pc_interface pc_s; //Converts a class to its array index for CLASS_COUNT defined arrays. @@ -174,6 +174,28 @@ int pc_spiritball_timer(int tid, int64 tick, int id, intptr_t data) { return 0; } +/** +* Get the possible number of spiritball that a player can call. +* @param sd the affected player structure +* @param min the minimum number of spiritball regardless the level of MO_CALLSPIRITS +* @retval total number of spiritball +**/ +int pc_getmaxspiritball(struct map_session_data *sd, int min) { + int result; + + nullpo_ret(sd); + + result = pc->checkskill(sd, MO_CALLSPIRITS); + + if ( min && result < min ) + result = min; + else if ( sd->sc.data[SC_RAISINGDRAGON] ) + result += sd->sc.data[SC_RAISINGDRAGON]->val1; + if ( result > MAX_SPIRITBALL ) + result = MAX_SPIRITBALL; + return result; +} + int pc_addspiritball(struct map_session_data *sd,int interval,int max) { int tid, i; @@ -495,7 +517,7 @@ void pc_rental_expire(struct map_session_data *sd, int i) { } clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid); - pc->delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); } void pc_inventory_rentals(struct map_session_data *sd) { @@ -629,6 +651,7 @@ int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int lo sd->canlog_tick = timer->gettick(); //Required to prevent homunculus copuing a base speed of 0. sd->battle_status.speed = sd->base_status.speed = DEFAULT_WALK_SPEED; + sd->state.warp_clean = 1; return 0; } @@ -861,12 +884,12 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, clif->updatestatus(b_sd, SP_JOBEXP); // Baby Skills - pc->skill(b_sd, WE_BABY, 1, 0); - pc->skill(b_sd, WE_CALLPARENT, 1, 0); + pc->skill(b_sd, WE_BABY, 1, SKILL_GRANT_PERMANENT); + pc->skill(b_sd, WE_CALLPARENT, 1, SKILL_GRANT_PERMANENT); // Parents Skills - pc->skill(p1_sd, WE_CALLBABY, 1, 0); - pc->skill(p2_sd, WE_CALLBABY, 1, 0); + pc->skill(p1_sd, WE_CALLBABY, 1, SKILL_GRANT_PERMANENT); + pc->skill(p2_sd, WE_CALLBABY, 1, SKILL_GRANT_PERMANENT); return true; } @@ -892,12 +915,12 @@ int pc_isequip(struct map_session_data *sd,int n) if(pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT)) return 1; - if(item->elv && sd->status.base_level < (unsigned int)item->elv){ - clif->msg(sd, 0x6ED); + if (item->elv && sd->status.base_level < (unsigned int)item->elv) { + clif->msgtable(sd, MSG_ITEM_CANT_EQUIP_LVL); return 0; } - if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax){ - clif->msg(sd, 0x6ED); + if (item->elvmax && sd->status.base_level > (unsigned int)item->elvmax) { + clif->msgtable(sd, MSG_ITEM_CANT_EQUIP_LVL); return 0; } if(item->sex != 2 && sd->status.sex != item->sex) @@ -906,11 +929,11 @@ int pc_isequip(struct map_session_data *sd,int n) if ( item->equip & EQP_AMMO ) { if ( (sd->state.active && !pc_iscarton(sd)) // check if sc data is already loaded. && (sd->status.class_ == JOB_GENETIC_T || sd->status.class_ == JOB_GENETIC) ) { - clif->msg(sd, 0x5EF); + clif->msgtable(sd, MSG_ITEM_NEED_CART); return 0; } if ( !pc_ismadogear(sd) && (sd->status.class_ == JOB_MECHANIC_T || sd->status.class_ == JOB_MECHANIC) ) { - clif->msg(sd, 0x59B); + clif->msgtable(sd, MSG_ITEM_NEED_MADO); return 0; } } @@ -1119,7 +1142,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim // Rental Timer sd->rental_timer = INVALID_TIMER; - for( i = 0; i < 3; i++ ) + for( i = 0; i < MAX_PC_FEELHATE; i++ ) sd->hate_mob[i] = -1; sd->quest_log = NULL; @@ -1217,7 +1240,7 @@ void pc_authfail(struct map_session_data *sd) int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl) { int class_; - if (!sd || !bl || pos < 0 || pos > 2) + if (!sd || !bl || pos < 0 || pos >= MAX_PC_FEELHATE) return 0; if (sd->hate_mob[pos] != -1) { //Can't change hate targets. @@ -1367,7 +1390,7 @@ int pc_calc_skillpoint(struct map_session_data* sd) { for (i = 1; i < MAX_SKILL; i++) { int skill_lv = pc->checkskill2(sd,i); if (skill_lv > 0) { - inf2 = skill->db[i].inf2; + inf2 = skill->dbs->db[i].inf2; if((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) && !(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL|INF2_GUILD_SKILL)) //Do not count wedding/link skills. [Skotlex] ) { @@ -1406,7 +1429,7 @@ int pc_calc_skilltree(struct map_session_data *sd) sd->status.skill[i].id = 0; //First clear skills. /* permanent skills that must be re-checked */ if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT ) { - switch( skill->db[i].nameid ) { + switch( skill->dbs->db[i].nameid ) { case NV_TRICKDEAD: if( (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE ) { sd->status.skill[i].id = 0; @@ -1425,21 +1448,21 @@ int pc_calc_skilltree(struct map_session_data *sd) sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; } - if( sd->sc.count && sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_BARDDANCER && skill->db[i].nameid >= DC_HUMMING && skill->db[i].nameid <= DC_SERVICEFORYOU ) + if( sd->sc.count && sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_BARDDANCER && skill->dbs->db[i].nameid >= DC_HUMMING && skill->dbs->db[i].nameid <= DC_SERVICEFORYOU ) { //Enable Bard/Dancer spirit linked skills. if( sd->status.sex ) { //Link dancer skills to bard. // i can be < 8? if( sd->status.skill[i-8].lv < 10 ) continue; - sd->status.skill[i].id = skill->db[i].nameid; + sd->status.skill[i].id = skill->dbs->db[i].nameid; sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill } else { //Link bard skills to dancer. if( sd->status.skill[i].lv < 10 ) continue; // i can be < 8? - sd->status.skill[i-8].id = skill->db[i-8].nameid; + sd->status.skill[i-8].id = skill->dbs->db[i-8].nameid; sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill } @@ -1448,7 +1471,7 @@ int pc_calc_skilltree(struct map_session_data *sd) if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) { for( i = 0; i < MAX_SKILL; i++ ) { - switch(skill->db[i].nameid) { + switch(skill->dbs->db[i].nameid) { /** * Dummy skills must be added here otherwise they'll be displayed in the, * skill tree and since they have no icons they'll give resource errors @@ -1471,10 +1494,10 @@ int pc_calc_skilltree(struct map_session_data *sd) default: break; } - if( skill->db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL) ) + if( skill->dbs->db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL) ) continue; //Only skills you can't have are npc/guild ones - if( skill->db[i].max > 0 ) - sd->status.skill[i].id = skill->db[i].nameid; + if( skill->dbs->db[i].max > 0 ) + sd->status.skill[i].id = skill->dbs->db[i].nameid; } return 0; } @@ -1517,7 +1540,7 @@ int pc_calc_skilltree(struct map_session_data *sd) } if( f ) { int inf2; - inf2 = skill->db[idx].inf2; + inf2 = skill->dbs->db[idx].inf2; if(!sd->status.skill[idx].lv && ( (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || @@ -1548,7 +1571,7 @@ int pc_calc_skilltree(struct map_session_data *sd) for( i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[c][i].id) > 0; i++ ) { int idx = pc->skill_tree[c][i].idx; - if( (skill->db[idx].inf2&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) ) + if( (skill->dbs->db[idx].inf2&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) ) continue; //Do not include Quest/Wedding skills. if( sd->status.skill[idx].id == 0 ) { @@ -1618,7 +1641,7 @@ void pc_check_skilltree(struct map_session_data *sd, int skill_id) continue; } - j = skill->db[idx].inf2; + j = skill->dbs->db[idx].inf2; if( !sd->status.skill[idx].lv && ( (j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || j&INF2_WEDDING_SKILL || @@ -1777,7 +1800,7 @@ int pc_disguise(struct map_session_data *sd, int class_) { if( class_ == -1 && sd->disguise == sd->status.class_ ) { clif->clearunit_single(-sd->bl.id,CLR_OUTSIGHT,sd->fd); } else if ( class_ != sd->status.class_ ) { - pc_stop_walking(sd, 0); + pc_stop_walking(sd, STOPWALKING_FLAG_NONE); clif->clearunit_area(&sd->bl, CLR_OUTSIGHT); } } @@ -1877,7 +1900,20 @@ int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_ski return 1; } -int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, short rate, short arrow_rate, unsigned char flag) +/** + * Adds an AddEff/AddEff2/AddEffWhenHit bonus to a character. + * + * @param effect Effects array to append to. + * @param max Size of the effect array. + * @param id Effect ID (@see enum sc_type). + * @param rate Trigger rate. + * @param arrow_rate Trigger rate modifier for ranged attacks (adds to the base rate). + * @param flag Trigger flags (@see enum auto_trigger_flag). + * @param duration Fixed (non-reducible) duration in ms. If 0, uses the default (reducible) duration of the given effect. + * @retval 1 on success. + * @retval 0 on failure. + */ +int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, int16 rate, int16 arrow_rate, uint8 flag, uint16 duration) { int i; if (!(flag&(ATF_SHORT|ATF_LONG))) @@ -1888,8 +1924,8 @@ int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, short flag|=ATF_WEAPON; //Default type: weapon. for (i = 0; i < max && effect[i].flag; i++) { - if (effect[i].id == id && effect[i].flag == flag) - { + // Update existing effect if any. + if (effect[i].id == id && effect[i].flag == flag && effect[i].duration == duration) { effect[i].rate += rate; effect[i].arrow_rate += arrow_rate; return 1; @@ -1903,6 +1939,7 @@ int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, short effect[i].rate = rate; effect[i].arrow_rate = arrow_rate; effect[i].flag = flag; + effect[i].duration = duration; return 1; } @@ -2769,24 +2806,56 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) switch(type){ case SP_ADDELE: - if(type2 >= ELE_MAX) { + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { ShowError("pc_bonus2: SP_ADDELE: Invalid element %d\n", type2); break; } - if(!sd->state.lr_flag) - sd->right_weapon.addele[type2]+=val; - else if(sd->state.lr_flag == 1) - sd->left_weapon.addele[type2]+=val; - else if(sd->state.lr_flag == 2) - sd->arrow_addele[type2]+=val; + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ) { + if ( !sd->state.lr_flag ) + sd->right_weapon.addele[i] += val; + else if ( sd->state.lr_flag == 1 ) + sd->left_weapon.addele[i] += val; + else if ( sd->state.lr_flag == 2 ) + sd->arrow_addele[i] += val; + } + } else { + if(!sd->state.lr_flag) + sd->right_weapon.addele[type2] += val; + else if(sd->state.lr_flag == 1) + sd->left_weapon.addele[type2] += val; + else if(sd->state.lr_flag == 2) + sd->arrow_addele[type2] += val; + } break; case SP_ADDRACE: - if(!sd->state.lr_flag) - sd->right_weapon.addrace[type2]+=val; - else if(sd->state.lr_flag == 1) - sd->left_weapon.addrace[type2]+=val; - else if(sd->state.lr_flag == 2) - sd->arrow_addrace[type2]+=val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_ADDRACE: Invalid Race(%d)\n",type2); + break; + } + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_MAX; i++ ) { + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + if ( !sd->state.lr_flag ) + sd->right_weapon.addrace[i] += val; + else if ( sd->state.lr_flag == 1 ) + sd->left_weapon.addrace[i] += val; + else if ( sd->state.lr_flag == 2 ) + sd->arrow_addrace[i] += val; + } + } else { + if(!sd->state.lr_flag) + sd->right_weapon.addrace[type2] += val; + else if(sd->state.lr_flag == 1) + sd->left_weapon.addrace[type2] += val; + else if(sd->state.lr_flag == 2) + sd->arrow_addrace[type2] += val; + } break; case SP_ADDSIZE: if(!sd->state.lr_flag) @@ -2797,16 +2866,40 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->arrow_addsize[type2]+=val; break; case SP_SUBELE: - if(type2 >= ELE_MAX) { + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { ShowError("pc_bonus2: SP_SUBELE: Invalid element %d\n", type2); break; } - if(sd->state.lr_flag != 2) - sd->subele[type2]+=val; + if(sd->state.lr_flag != 2) { + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ){ + sd->subele[i] += val; + } + } else { + sd->subele[type2] += val; + } + } break; case SP_SUBRACE: - if(sd->state.lr_flag != 2) - sd->subrace[type2]+=val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_SUBRACE: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2) { + if (type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->subrace[i] += val; + } + } else { + sd->subrace[type2]+=val; + } + } break; case SP_ADDEFF: if (type2 > SC_MAX) { @@ -2814,7 +2907,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; } pc->bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, - sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, 0); + sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, 0, 0); break; case SP_ADDEFF2: if (type2 > SC_MAX) { @@ -2822,7 +2915,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; } pc->bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, - sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, ATF_SELF); + sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, ATF_SELF, 0); break; case SP_RESEFF: if (type2 < SC_COMMON_MIN || type2 > SC_COMMON_MAX) { @@ -2835,24 +2928,57 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->reseff[type2-SC_COMMON_MIN]= cap_value(i, 0, 10000); break; case SP_MAGIC_ADDELE: - if(type2 >= ELE_MAX) { + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { ShowError("pc_bonus2: SP_MAGIC_ADDELE: Invalid element %d\n", type2); break; } - if(sd->state.lr_flag != 2) - sd->magic_addele[type2]+=val; + if ( sd->state.lr_flag != 2 ) { + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ) + sd->magic_addele[i] += val; + } else { + sd->magic_addele[type2] += val; + } + } break; case SP_MAGIC_ADDRACE: - if(sd->state.lr_flag != 2) - sd->magic_addrace[type2]+=val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_MAGIC_ADDRACE: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2){ + if ( type2 >= RC_MAX ){ + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->magic_addrace[i] += val; + } + } else { + sd->magic_addrace[type2]+=val; + } + } break; case SP_MAGIC_ADDSIZE: if(sd->state.lr_flag != 2) sd->magic_addsize[type2]+=val; break; case SP_MAGIC_ATK_ELE: - if(sd->state.lr_flag != 2) - sd->magic_atk_ele[type2]+=val; + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { + ShowError("pc_bonus2: SP_MAGIC_ATK_ELE: Invalid element %d\n", type2); + break; + } + if ( sd->state.lr_flag != 2 ) { + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ) + sd->magic_atk_ele[i] += val; + } else { + sd->magic_atk_ele[type2] += val; + } + } break; case SP_ADD_DAMAGE_CLASS: switch (sd->state.lr_flag) { @@ -3001,19 +3127,40 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) } break; case SP_WEAPON_COMA_ELE: - if(type2 >= ELE_MAX) { + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { ShowError("pc_bonus2: SP_WEAPON_COMA_ELE: Invalid element %d\n", type2); break; } if(sd->state.lr_flag == 2) break; - sd->weapon_coma_ele[type2] += val; + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ) + sd->weapon_coma_ele[i] += val; + } else { + sd->weapon_coma_ele[type2] += val; + } sd->special_state.bonus_coma = 1; break; case SP_WEAPON_COMA_RACE: + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_WEAPON_COMA_RACE: Invalid Race(%d)\n",type2); + break; + } if(sd->state.lr_flag == 2) break; - sd->weapon_coma_race[type2] += val; + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->weapon_coma_race[i] += val; + } + } else { + sd->weapon_coma_race[type2] += val; + } sd->special_state.bonus_coma = 1; break; case SP_WEAPON_ATK: @@ -3025,8 +3172,25 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->weapon_atk_rate[type2]+=val; break; case SP_CRITICAL_ADDRACE: - if(sd->state.lr_flag != 2) - sd->critaddrace[type2] += val*10; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_CRITICAL_ADDRACE: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2){ + if ( type2 >= RC_MAX ){ + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->critaddrace[i] += val*10; + } + } else { + sd->critaddrace[type2] += val*10; + } + } break; case SP_ADDEFF_WHENHIT: if (type2 > SC_MAX) { @@ -3034,7 +3198,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; } if(sd->state.lr_flag != 2) - pc->bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, val, 0, 0); + pc->bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, val, 0, 0, 0); break; case SP_SKILL_ATK: if(sd->state.lr_flag == 2) @@ -3197,12 +3361,46 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->itemhealrate[i].rate += val; break; case SP_EXP_ADDRACE: - if(sd->state.lr_flag != 2) - sd->expaddrace[type2]+=val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_EXP_ADDRACE: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2) { + if ( type2 >= RC_MAX ){ + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->expaddrace[i] += val; + } + } else { + sd->expaddrace[type2] += val; + } + } break; case SP_SP_GAIN_RACE: - if(sd->state.lr_flag != 2) - sd->sp_gain_race[type2]+=val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_SP_GAIN_RACE: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2) { + if ( type2 >= RC_MAX ){ + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->sp_gain_race[i] += val; + } + } else { + sd->sp_gain_race[type2] += val; + } + } break; case SP_ADD_MONSTER_DROP_ITEM: if (sd->state.lr_flag != 2) @@ -3221,19 +3419,61 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) } break; case SP_HP_DRAIN_VALUE_RACE: - if(!sd->state.lr_flag) { - sd->right_weapon.hp_drain[type2].value += val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_HP_DRAIN_VALUE_RACE: Invalid Race(%d)\n",type2); + break; } - else if(sd->state.lr_flag == 1) { - sd->left_weapon.hp_drain[type2].value += val; + if ( type2 >= RC_MAX ){ + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + if(!sd->state.lr_flag) { + sd->right_weapon.hp_drain[i].value += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.hp_drain[i].value += val; + } + } + } else { + if(!sd->state.lr_flag) { + sd->right_weapon.hp_drain[type2].value += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.hp_drain[type2].value += val; + } } break; case SP_SP_DRAIN_VALUE_RACE: - if(!sd->state.lr_flag) { - sd->right_weapon.sp_drain[type2].value += val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_SP_DRAIN_VALUE_RACE: Invalid Race(%d)\n",type2); + break; } - else if(sd->state.lr_flag == 1) { - sd->left_weapon.sp_drain[type2].value += val; + if ( type2 >= RC_MAX ){ + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + if(!sd->state.lr_flag) { + sd->right_weapon.sp_drain[i].value += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.sp_drain[i].value += val; + } + } + } else { + if(!sd->state.lr_flag) { + sd->right_weapon.sp_drain[type2].value += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.sp_drain[type2].value += val; + } } break; case SP_IGNORE_MDEF_RATE: @@ -3245,12 +3485,46 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->ignore_def[type2] += val; break; case SP_SP_GAIN_RACE_ATTACK: - if(sd->state.lr_flag != 2) - sd->sp_gain_race_attack[type2] = cap_value(sd->sp_gain_race_attack[type2] + val, 0, INT16_MAX); + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_SP_GAIN_RACE_ATTACK: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2) { + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->sp_gain_race_attack[i] = cap_value(sd->sp_gain_race_attack[i] + val, 0, INT16_MAX); + } + } else { + sd->sp_gain_race_attack[type2] = cap_value(sd->sp_gain_race_attack[type2] + val, 0, INT16_MAX); + } + } break; case SP_HP_GAIN_RACE_ATTACK: - if(sd->state.lr_flag != 2) - sd->hp_gain_race_attack[type2] = cap_value(sd->hp_gain_race_attack[type2] + val, 0, INT16_MAX); + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_HP_GAIN_RACE_ATTACK: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2) { + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->hp_gain_race_attack[i] = cap_value(sd->hp_gain_race_attack[i] + val, 0, INT16_MAX); + } + } else { + sd->hp_gain_race_attack[type2] = cap_value(sd->hp_gain_race_attack[type2] + val, 0, INT16_MAX); + } + } break; case SP_SKILL_USE_SP_RATE: //bonus2 bSkillUseSPrate,n,x; if(sd->state.lr_flag == 2) @@ -3354,6 +3628,29 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) if (sd->state.lr_flag != 2) pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, val, 1<<type2, 10000); break; +#ifdef RENEWAL + case SP_RACE_TOLERANCE: + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus2: SP_RACE_TOLERANCE: Invalid Race(%d)\n",type2); + break; + } + if(sd->state.lr_flag != 2) { + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->race_tolerance[i] += val; + } + } else { + sd->race_tolerance[type2] += val; + } + } + break; +#endif default: ShowWarning("pc_bonus2: unknown type %d %d %d!\n",type,type2,val); break; @@ -3363,6 +3660,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) { + int i; nullpo_ret(sd); switch(type){ @@ -3412,23 +3710,69 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) } break; case SP_HP_DRAIN_RATE_RACE: - if(!sd->state.lr_flag) { - sd->right_weapon.hp_drain[type2].rate += type3; - sd->right_weapon.hp_drain[type2].per += val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus3: SP_HP_DRAIN_RATE_RACE: Invalid Race(%d)\n",type2); + break; } - else if(sd->state.lr_flag == 1) { - sd->left_weapon.hp_drain[type2].rate += type3; - sd->left_weapon.hp_drain[type2].per += val; + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + if(!sd->state.lr_flag) { + sd->right_weapon.hp_drain[i].rate += type3; + sd->right_weapon.hp_drain[i].per += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.hp_drain[i].rate += type3; + sd->left_weapon.hp_drain[i].per += val; + } + } + } else { + if(!sd->state.lr_flag) { + sd->right_weapon.hp_drain[type2].rate += type3; + sd->right_weapon.hp_drain[type2].per += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.hp_drain[type2].rate += type3; + sd->left_weapon.hp_drain[type2].per += val; + } } break; case SP_SP_DRAIN_RATE_RACE: - if(!sd->state.lr_flag) { - sd->right_weapon.sp_drain[type2].rate += type3; - sd->right_weapon.sp_drain[type2].per += val; + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus3: SP_SP_DRAIN_RATE_RACE: Invalid Race(%d)\n",type2); + break; } - else if(sd->state.lr_flag == 1) { - sd->left_weapon.sp_drain[type2].rate += type3; - sd->left_weapon.sp_drain[type2].per += val; + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + if(!sd->state.lr_flag) { + sd->right_weapon.sp_drain[i].rate += type3; + sd->right_weapon.sp_drain[i].per += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.sp_drain[i].rate += type3; + sd->left_weapon.sp_drain[i].per += val; + } + } + } else { + if(!sd->state.lr_flag) { + sd->right_weapon.sp_drain[type2].rate += type3; + sd->right_weapon.sp_drain[type2].per += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.sp_drain[type2].rate += type3; + sd->left_weapon.sp_drain[type2].per += val; + } } break; case SP_ADDEFF: @@ -3437,7 +3781,7 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) break; } pc->bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, - sd->state.lr_flag!=2?type3:0, sd->state.lr_flag==2?type3:0, val); + sd->state.lr_flag!=2?type3:0, sd->state.lr_flag==2?type3:0, val, 0); break; case SP_ADDEFF_WHENHIT: @@ -3446,7 +3790,7 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) break; } if(sd->state.lr_flag != 2) - pc->bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, type3, 0, val); + pc->bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, type3, 0, val, 0); break; case SP_ADDEFF_ONSKILL: @@ -3459,21 +3803,33 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) break; case SP_ADDELE: - if (type2 > ELE_MAX) { - ShowWarning("pc_bonus3 (SP_ADDELE): element %d is out of range.\n", type2); + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { + ShowError("pc_bonus3: SP_ADDELE: Invalid element %d\n", type2); break; } - if (sd->state.lr_flag != 2) - pc_bonus_addele(sd, (unsigned char)type2, type3, val); + if ( sd->state.lr_flag != 2 ) { + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ) + pc_bonus_addele(sd, (unsigned char)i, type3, val); + } else { + pc_bonus_addele(sd, (unsigned char)type2, type3, val); + } + } break; case SP_SUBELE: - if (type2 > ELE_MAX) { - ShowWarning("pc_bonus3 (SP_SUBELE): element %d is out of range.\n", type2); + if( (type2 >= ELE_MAX && type2 != ELE_ALL) || (type2 < ELE_NEUTRAL) ) { + ShowError("pc_bonus3: SP_SUBELE: Invalid element %d\n", type2); break; } - if (sd->state.lr_flag != 2) - pc_bonus_subele(sd, (unsigned char)type2, type3, val); + if ( sd->state.lr_flag != 2 ) { + if ( type2 == ELE_ALL ) { + for ( i = ELE_NEUTRAL; i < ELE_MAX; i++ ) + pc_bonus_subele(sd, (unsigned char)i, type3, val); + } else { + pc_bonus_subele(sd, (unsigned char)type2, type3, val); + } + } break; case SP_SP_VANISH_RATE: if(sd->state.lr_flag != 2) { @@ -3492,6 +3848,7 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) } int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4,int val) { + int i; nullpo_ret(sd); switch(type) { @@ -3524,27 +3881,74 @@ int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4 break; case SP_SET_DEF_RACE: //bonus4 bSetDefRace,n,x,r,y; - if( type2 >= RC_MAX ) { - ShowWarning("pc_bonus4 (DEF_SET): %d is not supported.\n", type2); + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus4: SP_SET_DEF_RACE: Invalid Race(%d)\n",type2); break; } if(sd->state.lr_flag == 2) break; - sd->def_set_race[type2].rate = type3; - sd->def_set_race[type2].tick = type4; - sd->def_set_race[type2].value = val; + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->def_set_race[i].rate = type3; + sd->def_set_race[i].tick = type4; + sd->def_set_race[i].value = val; + } + } else { + sd->def_set_race[type2].rate = type3; + sd->def_set_race[type2].tick = type4; + sd->def_set_race[type2].value = val; + } break; case SP_SET_MDEF_RACE: //bonus4 bSetMDefRace,n,x,r,y; - if( type2 >= RC_MAX ) { - ShowWarning("pc_bonus4 (MDEF_SET): %d is not supported.\n", type2); + if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){ + ShowWarning("pc_bonus4: SP_SET_MDEF_RACE: Invalid Race(%d)\n",type2); break; } if(sd->state.lr_flag == 2) break; - sd->mdef_set_race[type2].rate = type3; - sd->mdef_set_race[type2].tick = type4; - sd->mdef_set_race[type2].value = val; + if ( type2 >= RC_MAX ) { + for ( i = RC_FORMLESS; i < RC_MAX; i++ ){ + if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) || + (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) || + (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) || + (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN)) + ) + continue; + sd->mdef_set_race[i].rate = type3; + sd->mdef_set_race[i].tick = type4; + sd->mdef_set_race[i].value = val; + } + } else { + sd->mdef_set_race[type2].rate = type3; + sd->mdef_set_race[type2].tick = type4; + sd->mdef_set_race[type2].value = val; + } + break; + + case SP_ADDEFF: + { + uint16 duration; + if (type2 > SC_MAX) { + ShowWarning("pc_bonus4 (Add Effect): %d is not supported.\n", type2); + break; + } + if (val < 0 || val > UINT16_MAX) { + ShowWarning("pc_bonus4 (Add Effect): invalid duration %d. Valid range: [0:%d].\n", val, UINT16_MAX); + duration = (val < 0 ? 0 : UINT16_MAX); + } else { + duration = (uint16)val; + } + + pc->bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, + sd->state.lr_flag!=2?type3:0, sd->state.lr_flag==2?type3:0, type4, duration); + } break; default: @@ -3583,13 +3987,11 @@ int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4 } /*========================================== - * Grants a player a given skill. Flag values are: - * 0 - Grant permanent skill to be bound to skill tree - * 1 - Grant an item skill (temporary) - * 2 - Like 1, except the level granted can stack with previously learned level. - * 3 - Grant skill unconditionally and forever (persistent to job changes and skill resets) + * Grants a player a given skill. + * Flag values: @see enum pc_skill_flag *------------------------------------------*/ -int pc_skill(TBL_PC* sd, int id, int level, int flag) { +int pc_skill(TBL_PC* sd, int id, int level, int flag) +{ uint16 index = 0; nullpo_ret(sd); @@ -3601,13 +4003,13 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) { ShowError("pc_skill: Skill level %d too high. Max lv supported is %d\n", level, MAX_SKILL_LEVEL); return 0; } - if( flag == 2 && sd->status.skill[index].lv + level > MAX_SKILL_LEVEL ) { + if( flag == SKILL_GRANT_TEMPSTACK && sd->status.skill[index].lv + level > MAX_SKILL_LEVEL ) { ShowError("pc_skill: Skill level bonus %d too high. Max lv supported is %d. Curr lv is %d\n", level, MAX_SKILL_LEVEL, sd->status.skill[index].lv); return 0; } switch( flag ){ - case 0: //Set skill data overwriting whatever was there before. + case SKILL_GRANT_PERMANENT: //Set skill data overwriting whatever was there before. sd->status.skill[index].id = id; sd->status.skill[index].lv = level; sd->status.skill[index].flag = SKILL_FLAG_PERMANENT; @@ -3616,10 +4018,10 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) { clif->deleteskill(sd,id); } else clif->addskill(sd,id); - if( !skill->db[index].inf ) //Only recalculate for passive skills. + if( !skill->dbs->db[index].inf ) //Only recalculate for passive skills. status_calc_pc(sd, SCO_NONE); break; - case 1: //Item bonus skill. + case SKILL_GRANT_TEMPORARY: //Item bonus skill. if( sd->status.skill[index].id == id ) { if( sd->status.skill[index].lv >= level ) return 0; @@ -3631,7 +4033,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) { } sd->status.skill[index].lv = level; break; - case 2: //Add skill bonus on top of what you had. + case SKILL_GRANT_TEMPSTACK: //Add skill bonus on top of what you had. if( sd->status.skill[index].id == id ) { if( sd->status.skill[index].flag == SKILL_FLAG_PERMANENT ) sd->status.skill[index].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[index].lv; // Store previous level. @@ -3641,7 +4043,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) { } sd->status.skill[index].lv += level; break; - case 3: + case SKILL_GRANT_UNCONDITIONAL: sd->status.skill[index].id = id; sd->status.skill[index].lv = level; sd->status.skill[index].flag = SKILL_FLAG_PERM_GRANTED; @@ -3650,60 +4052,100 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) { clif->deleteskill(sd,id); } else clif->addskill(sd,id); - if( !skill->db[index].inf ) //Only recalculate for passive skills. + if( !skill->dbs->db[index].inf ) //Only recalculate for passive skills. status_calc_pc(sd, SCO_NONE); break; - default: //Unknown flag? - return 0; + default: //Unknown flag? + return 0; } return 1; } + +/** + * Checks if the given card can be inserted into the given equipment piece. + * + * @param sd The current character. + * @param idx_card The card's inventory index (note: it must be a valid index and can be checked by pc_can_insert_card) + * @param idx_equip The target equipment's inventory index. + * @retval true if the card can be inserted. + */ +bool pc_can_insert_card_into(struct map_session_data* sd, int idx_card, int idx_equip) +{ + int i; + + nullpo_ret(sd); + + if (idx_equip < 0 || idx_equip >= MAX_INVENTORY || sd->inventory_data[idx_equip] == NULL) + return false; //Invalid item index. + if (sd->status.inventory[idx_equip].nameid <= 0 || sd->status.inventory[idx_equip].amount < 1) + return false; // target item missing + if (sd->inventory_data[idx_equip]->type != IT_WEAPON && sd->inventory_data[idx_equip]->type != IT_ARMOR) + return false; // only weapons and armor are allowed + if (sd->status.inventory[idx_equip].identify == 0) + return false; // target must be identified + if (itemdb_isspecial(sd->status.inventory[idx_equip].card[0])) + return false; // card slots reserved for other purposes + if (sd->status.inventory[idx_equip].equip != 0) + return false; // item must be unequipped + if ((sd->inventory_data[idx_equip]->equip & sd->inventory_data[idx_card]->equip) == 0) + return false; // card cannot be compounded on this item type + if (sd->inventory_data[idx_equip]->type == IT_WEAPON && sd->inventory_data[idx_card]->equip == EQP_SHIELD) + return false; // attempted to place shield card on left-hand weapon. + + ARR_FIND( 0, sd->inventory_data[idx_equip]->slot, i, sd->status.inventory[idx_equip].card[i] == 0); + if (i == sd->inventory_data[idx_equip]->slot) + return false; // no free slots + return true; +} + +/** + * Checks if the given item is card and it can be inserted into some equipment. + * + * @param sd The current character. + * @param idx_card The card's inventory index. + * @retval true if the card can be inserted. + */ +bool pc_can_insert_card(struct map_session_data* sd, int idx_card) +{ + nullpo_ret(sd); + + if (idx_card < 0 || idx_card >= MAX_INVENTORY || sd->inventory_data[idx_card] == NULL) + return false; //Invalid card index. + if (sd->status.inventory[idx_card].nameid <= 0 || sd->status.inventory[idx_card].amount < 1) + return false; // target card missing + if (sd->inventory_data[idx_card]->type != IT_CARD) + return false; // must be a card + return true; +} + /*========================================== * Append a card to an item ? *------------------------------------------*/ int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip) { - int i; int nameid; nullpo_ret(sd); - if( idx_equip < 0 || idx_equip >= MAX_INVENTORY || sd->inventory_data[idx_equip] == NULL ) - return 0; //Invalid item index. - if( idx_card < 0 || idx_card >= MAX_INVENTORY || sd->inventory_data[idx_card] == NULL ) - return 0; //Invalid card index. - if( sd->status.inventory[idx_equip].nameid <= 0 || sd->status.inventory[idx_equip].amount < 1 ) - return 0; // target item missing - if( sd->status.inventory[idx_card].nameid <= 0 || sd->status.inventory[idx_card].amount < 1 ) - return 0; // target card missing - if( sd->inventory_data[idx_equip]->type != IT_WEAPON && sd->inventory_data[idx_equip]->type != IT_ARMOR ) - return 0; // only weapons and armor are allowed - if( sd->inventory_data[idx_card]->type != IT_CARD ) - return 0; // must be a card - if( sd->status.inventory[idx_equip].identify == 0 ) - return 0; // target must be identified - if( itemdb_isspecial(sd->status.inventory[idx_equip].card[0]) ) - return 0; // card slots reserved for other purposes - if( (sd->inventory_data[idx_equip]->equip & sd->inventory_data[idx_card]->equip) == 0 ) - return 0; // card cannot be compounded on this item type - if( sd->inventory_data[idx_equip]->type == IT_WEAPON && sd->inventory_data[idx_card]->equip == EQP_SHIELD ) - return 0; // attempted to place shield card on left-hand weapon. - if( sd->status.inventory[idx_equip].equip != 0 ) - return 0; // item must be unequipped - - ARR_FIND( 0, sd->inventory_data[idx_equip]->slot, i, sd->status.inventory[idx_equip].card[i] == 0 ); - if( i == sd->inventory_data[idx_equip]->slot ) - return 0; // no free slots + if (sd->state.trading != 0) + return 0; + + if (!pc->can_insert_card(sd, idx_card) || !pc->can_insert_card_into(sd, idx_card, idx_equip)) + return 0; // remember the card id to insert nameid = sd->status.inventory[idx_card].nameid; - if( pc->delitem(sd,idx_card,1,1,0,LOG_TYPE_OTHER) == 1 ) + if( pc->delitem(sd, idx_card, 1, 1, DELITEM_NORMAL, LOG_TYPE_OTHER) == 1 ) {// failed clif->insert_card(sd,idx_equip,idx_card,1); } else {// success + int i; + ARR_FIND( 0, sd->inventory_data[idx_equip]->slot, i, sd->status.inventory[idx_equip].card[i] == 0); + if (i == sd->inventory_data[idx_equip]->slot) + return 0; // no free slots logs->pick_pc(sd, LOG_TYPE_OTHER, -1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]); sd->status.inventory[idx_equip].card[i] = nameid; logs->pick_pc(sd, LOG_TYPE_OTHER, 1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]); @@ -4047,6 +4489,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l if( sd->status.inventory[i].nameid == item_data->nameid && sd->status.inventory[i].bound == item_data->bound && sd->status.inventory[i].expire_time == 0 && + sd->status.inventory[i].unique_id == item_data->unique_id && memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 ) { if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) ) return 5; @@ -4074,8 +4517,8 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l clif->additem(sd,i,amount,0); } - if( !itemdb->isstackable2(data) && !item_data->unique_id ) - sd->status.inventory[i].unique_id = itemdb->unique_id(sd); + if( ( !itemdb->isstackable2(data) || data->flag.force_serial || data->type == IT_CASH) && !item_data->unique_id ) + sd->status.inventory[i].unique_id = itemdb->unique_id(sd); logs->pick_pc(sd, log_type, amount, &sd->status.inventory[i],sd->inventory_data[i]); @@ -4105,6 +4548,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l * @type * 1 : don't notify deletion * 2 : don't notify weight change + * reason: @see enum delitem_reason * Return: * 0 = success * 1 = invalid itemid or negative amount @@ -4122,7 +4566,7 @@ int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reas sd->weight -= sd->inventory_data[n]->weight*amount ; if( sd->status.inventory[n].amount <= 0 ){ if(sd->status.inventory[n].equip) - pc->unequipitem(sd,n,3); + pc->unequipitem(sd, n, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); memset(&sd->status.inventory[n],0,sizeof(sd->status.inventory[0])); sd->inventory_data[n] = NULL; } @@ -4172,7 +4616,7 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount) if (!map->addflooritem(&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 2)) return 0; - pc->delitem(sd, n, amount, 1, 0, LOG_TYPE_PICKDROP_PLAYER); + pc->delitem(sd, n, amount, 1, DELITEM_NORMAL, LOG_TYPE_PICKDROP_PLAYER); clif->dropitem(sd, n, amount); return 1; } @@ -4267,14 +4711,14 @@ int pc_isUseitem(struct map_session_data *sd,int n) if( !item->script ) //if it has no script, you can't really consume it! return 0; - if( (item->item_usage.flag&INR_SITTING) && (pc_issit(sd) == 1) && (pc_get_group_level(sd) < item->item_usage.override) ) { - clif->msgtable(sd->fd,0x297); - //clif->colormes(sd->fd,COLOR_WHITE,msg_txt(1474)); + if ((item->item_usage.flag&INR_SITTING) && (pc_issit(sd) == 1) && (pc_get_group_level(sd) < item->item_usage.override)) { + clif->msgtable(sd, MSG_ITEM_NEED_STANDING); + //clif->messagecolor_self(sd->fd, COLOR_WHITE, msg_txt(1474)); return 0; // You cannot use this item while sitting. } - if (sd->state.storage_flag && item->type != IT_CASH) { - clif->colormes(sd->fd, COLOR_RED, msg_sd(sd,1475)); + if (sd->state.storage_flag != STORAGE_FLAG_CLOSED && item->type != IT_CASH) { + clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd,1475)); return 0; // You cannot use this item while storage is open. } @@ -4373,12 +4817,12 @@ int pc_isUseitem(struct map_session_data *sd,int n) return 0; if( item->package || item->group ) { - if( pc_is90overweight(sd) ) { - clif->msgtable(sd->fd,ITEM_CANT_OBTAIN_WEIGHT); + if (pc_is90overweight(sd)) { + clif->msgtable(sd, MSG_ITEM_CANT_OBTAIN_WEIGHT); return 0; } - if( !pc->inventoryblank(sd) ) { - clif->colormes(sd->fd,COLOR_RED,msg_sd(sd,1477)); + if (!pc->inventoryblank(sd)) { + clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd,1477)); return 0; } } @@ -4387,13 +4831,13 @@ int pc_isUseitem(struct map_session_data *sd,int n) if(item->sex != 2 && sd->status.sex != item->sex) return 0; //Required level check - if(item->elv && sd->status.base_level < (unsigned int)item->elv){ - clif->msg(sd, 0x6EE); + if (item->elv && sd->status.base_level < (unsigned int)item->elv) { + clif->msgtable(sd, MSG_ITEM_CANT_USE_LVL); return 0; } - if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax){ - clif->msg(sd, 0x6EE); + if (item->elvmax && sd->status.base_level > (unsigned int)item->elvmax) { + clif->msgtable(sd, MSG_ITEM_CANT_USE_LVL); return 0; } @@ -4445,7 +4889,7 @@ int pc_useitem(struct map_session_data *sd,int n) { if( sd->npc_id || sd->state.workinprogress&1 ){ /* TODO: add to clif->messages enum */ #ifdef RENEWAL - clif->msg(sd, 0x783); // TODO look for the client date that has this message. + clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message. #endif return 0; } @@ -4508,7 +4952,7 @@ int pc_useitem(struct map_session_data *sd,int n) { if( sd->item_delay[i].nameid ) {// found if( DIFF_TICK(sd->item_delay[i].tick, tick) > 0 ) { int e_tick = (int)(DIFF_TICK(sd->item_delay[i].tick, tick)/1000); - clif->msgtable_num(sd->fd, 0x746, e_tick + 1); // [%d] seconds left until you can use + clif->msgtable_num(sd, MSG_SECONDS_UNTIL_USE, e_tick + 1); // [%d] seconds left until you can use return 0; // Delay has not expired yet } } else {// not yet used item (all slots are initially empty) @@ -4531,10 +4975,10 @@ int pc_useitem(struct map_session_data *sd,int n) { /* on restricted maps the item is consumed but the effect is not used */ for(i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++) { if( map->list[sd->bl.m].zone->disabled_items[i] == nameid ) { - clif->msg(sd, ITEM_CANT_USE_AREA); // This item cannot be used within this area + clif->msgtable(sd, MSG_ITEM_CANT_USE_AREA); // This item cannot be used within this area if( battle_config.item_restricted_consumption_type && sd->status.inventory[n].expire_time == 0 ) { clif->useitemack(sd,n,sd->status.inventory[n].amount-1,true); - pc->delitem(sd,n,1,1,0,LOG_TYPE_CONSUME); + pc->delitem(sd, n, 1, 1, DELITEM_NORMAL, LOG_TYPE_CONSUME); } return 0; } @@ -4552,14 +4996,15 @@ int pc_useitem(struct map_session_data *sd,int n) { amount = sd->status.inventory[n].amount; item_script = sd->inventory_data[n]->script; //Check if the item is to be consumed immediately [Skotlex] - if( sd->inventory_data[n]->flag.delay_consume ) + if (sd->inventory_data[n]->flag.delay_consume || sd->inventory_data[n]->flag.keepafteruse) clif->useitemack(sd,n,amount,true); else { - if (sd->status.inventory[n].expire_time == 0 && !(sd->inventory_data[n]->flag.keepafteruse)) { - clif->useitemack(sd,n,amount-1,true); - pc->delitem(sd,n,1,1,0,LOG_TYPE_CONSUME); // Rental Usable Items are not deleted until expiration - } else - clif->useitemack(sd,n,0,false); + if (sd->status.inventory[n].expire_time == 0) { + clif->useitemack(sd, n, amount - 1, true); + pc->delitem(sd, n, 1, 1, DELITEM_NORMAL, LOG_TYPE_CONSUME); // Rental Usable Items are not deleted until expiration + } else { + clif->useitemack(sd, n, 0, false); + } } if(sd->status.inventory[n].card[0]==CARD0_CREATE && pc->famerank(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST)) @@ -4625,7 +5070,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun sd->status.cart[i].card[2] == item_data->card[2] && sd->status.cart[i].card[3] == item_data->card[3] ); }; - if( i < MAX_CART ) + if( i < MAX_CART && item_data->unique_id == sd->status.cart[i].unique_id) {// item already in cart, stack it if( amount > MAX_AMOUNT - sd->status.cart[i].amount || ( data->stack.cart && amount > data->stack.amount - sd->status.cart[i].amount ) ) return 2; // no room @@ -4704,7 +5149,7 @@ int pc_putitemtocart(struct map_session_data *sd,int idx,int amount) return 1; if( (flag = pc->cart_additem(sd,item_data,amount,LOG_TYPE_NONE)) == 0 ) - return pc->delitem(sd,idx,amount,0,5,LOG_TYPE_NONE); + return pc->delitem(sd, idx, amount, 0, DELITEM_TOCART, LOG_TYPE_NONE); return flag; } @@ -4763,7 +5208,7 @@ void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type) { case IBT_CHARACTER: for( i = 0; i < MAX_INVENTORY; i++ ){ if( sd->status.inventory[i].bound == type ) { - pc->delitem(sd,i,sd->status.inventory[i].amount,0,1,LOG_TYPE_OTHER); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_SKILLUSE, LOG_TYPE_OTHER); // FIXME: is this the correct reason flag? } } break; @@ -4777,7 +5222,7 @@ void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type) { if(sd->status.inventory[i].bound == type) { if( gstor ) gstorage->additem(sd,gstor,&sd->status.inventory[i],sd->status.inventory[i].amount); - pc->delitem(sd,i,sd->status.inventory[i].amount,0,1,gstor?LOG_TYPE_GSTORAGE:LOG_TYPE_OTHER); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_SKILLUSE, gstor ? LOG_TYPE_GSTORAGE : LOG_TYPE_OTHER); // FIXME: is this the correct reason flag? } } if( gstor ) @@ -5046,7 +5491,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int for( i = 0; i < EQI_MAX; i++ ) { if( sd->equip_index[ i ] >= 0 ) if( !pc->isequip( sd , sd->equip_index[ i ] ) ) - pc->unequipitem( sd , sd->equip_index[ i ] , 2 ); + pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE); } if (battle_config.clear_unit_onwarp&BL_PC) skill->clear_unitgroup(&sd->bl); @@ -5262,14 +5707,14 @@ int pc_checkskill2(struct map_session_data *sd,uint16 index) { ShowError("pc_checkskill: Invalid skill index %d (char_id=%d).\n", index, sd->status.char_id); return 0; } - if( skill->db[index].nameid >= GD_SKILLBASE && skill->db[index].nameid < GD_MAX ) { + if( skill->dbs->db[index].nameid >= GD_SKILLBASE && skill->dbs->db[index].nameid < GD_MAX ) { struct guild *g; if( sd->status.guild_id>0 && (g=sd->guild)!=NULL) - return guild->checkskill(g,skill->db[index].nameid); + return guild->checkskill(g,skill->dbs->db[index].nameid); return 0; } - if(sd->status.skill[index].id == skill->db[index].nameid) + if(sd->status.skill[index].id == skill->dbs->db[index].nameid) return (sd->status.skill[index].lv); return 0; @@ -5862,6 +6307,138 @@ const char* job_name(int class_) } } +int pc_check_job_name(const char *name) { + int i, len; + struct { + const char *name; + int id; + } names[] = { + { "Novice", JOB_NOVICE }, + { "Swordsman", JOB_SWORDMAN }, + { "Magician", JOB_MAGE }, + { "Archer", JOB_ARCHER }, + { "Acolyte", JOB_ACOLYTE }, + { "Merchant", JOB_MERCHANT }, + { "Thief", JOB_THIEF }, + { "Knight", JOB_KNIGHT }, + { "Priest", JOB_PRIEST }, + { "Wizard", JOB_WIZARD }, + { "Blacksmith", JOB_BLACKSMITH }, + { "Hunter", JOB_HUNTER }, + { "Assassin", JOB_ASSASSIN }, + { "Crusader", JOB_CRUSADER }, + { "Monk", JOB_MONK }, + { "Sage", JOB_SAGE }, + { "Rogue", JOB_ROGUE }, + { "Alchemist", JOB_ALCHEMIST }, + { "Bard", JOB_BARD }, + { "Dancer", JOB_DANCER }, + { "Super_Novice", JOB_SUPER_NOVICE }, + { "Gunslinger", JOB_GUNSLINGER }, + { "Ninja", JOB_NINJA }, + { "Novice_High", JOB_NOVICE_HIGH }, + { "Swordsman_High", JOB_SWORDMAN_HIGH }, + { "Magician_High", JOB_MAGE_HIGH }, + { "Archer_High", JOB_ARCHER_HIGH }, + { "Acolyte_High", JOB_ACOLYTE_HIGH }, + { "Merchant_High", JOB_MERCHANT_HIGH }, + { "Thief_High", JOB_THIEF_HIGH }, + { "Lord_Knight", JOB_LORD_KNIGHT }, + { "High_Priest", JOB_HIGH_PRIEST }, + { "High_Wizard", JOB_HIGH_WIZARD }, + { "Whitesmith", JOB_WHITESMITH }, + { "Sniper", JOB_SNIPER }, + { "Assassin_Cross", JOB_ASSASSIN_CROSS }, + { "Paladin", JOB_PALADIN }, + { "Champion", JOB_CHAMPION }, + { "Professor", JOB_PROFESSOR }, + { "Stalker", JOB_STALKER }, + { "Creator", JOB_CREATOR }, + { "Clown", JOB_CLOWN }, + { "Gypsy", JOB_GYPSY }, + { "Baby_Novice", JOB_BABY }, + { "Baby_Swordsman", JOB_BABY_SWORDMAN }, + { "Baby_Magician", JOB_BABY_MAGE }, + { "Baby_Archer", JOB_BABY_ARCHER }, + { "Baby_Acolyte", JOB_BABY_ACOLYTE }, + { "Baby_Merchant", JOB_BABY_MERCHANT }, + { "Baby_Thief", JOB_BABY_THIEF }, + { "Baby_Knight", JOB_BABY_KNIGHT }, + { "Baby_Priest", JOB_BABY_PRIEST }, + { "Baby_Wizard", JOB_BABY_WIZARD }, + { "Baby_Blacksmith", JOB_BABY_BLACKSMITH }, + { "Baby_Hunter", JOB_BABY_HUNTER }, + { "Baby_Assassin", JOB_BABY_ASSASSIN }, + { "Baby_Crusader", JOB_BABY_CRUSADER }, + { "Baby_Monk", JOB_BABY_MONK }, + { "Baby_Sage", JOB_BABY_SAGE }, + { "Baby_Rogue", JOB_BABY_ROGUE }, + { "Baby_Alchemist", JOB_BABY_ALCHEMIST }, + { "Baby_Bard", JOB_BABY_BARD }, + { "Baby_Dancer", JOB_BABY_DANCER }, + { "Super_Baby", JOB_SUPER_BABY }, + { "Taekwon", JOB_TAEKWON }, + { "Star_Gladiator", JOB_STAR_GLADIATOR }, + { "Soul_Linker", JOB_SOUL_LINKER }, + { "Gangsi", JOB_GANGSI }, + { "Death_Knight", JOB_DEATH_KNIGHT }, + { "Dark_Collector", JOB_DARK_COLLECTOR }, + { "Rune_Knight", JOB_RUNE_KNIGHT }, + { "Warlock", JOB_WARLOCK }, + { "Ranger", JOB_RANGER }, + { "Arch_Bishop", JOB_ARCH_BISHOP }, + { "Mechanic", JOB_MECHANIC }, + { "Guillotine_Cross", JOB_GUILLOTINE_CROSS }, + { "Rune_Knight_Trans", JOB_RUNE_KNIGHT_T }, + { "Warlock_Trans", JOB_WARLOCK_T }, + { "Ranger_Trans", JOB_RANGER_T }, + { "Arch_Bishop_Trans", JOB_ARCH_BISHOP_T }, + { "Mechanic_Trans", JOB_MECHANIC_T }, + { "Guillotine_Cross_Trans", JOB_GUILLOTINE_CROSS_T }, + { "Royal_Guard", JOB_ROYAL_GUARD }, + { "Sorcerer", JOB_SORCERER }, + { "Minstrel", JOB_MINSTREL }, + { "Wanderer", JOB_WANDERER }, + { "Sura", JOB_SURA }, + { "Genetic", JOB_GENETIC }, + { "Shadow_Chaser", JOB_SHADOW_CHASER }, + { "Royal_Guard_Trans", JOB_ROYAL_GUARD_T }, + { "Sorcerer_Trans", JOB_SORCERER_T }, + { "Minstrel_Trans", JOB_MINSTREL_T }, + { "Wanderer_Trans", JOB_WANDERER_T }, + { "Sura_Trans", JOB_SURA_T }, + { "Genetic_Trans", JOB_GENETIC_T }, + { "Shadow_Chaser_Trans", JOB_SHADOW_CHASER_T }, + { "Baby_Rune_Knight", JOB_BABY_RUNE }, + { "Baby_Warlock", JOB_BABY_WARLOCK }, + { "Baby_Ranger", JOB_BABY_RANGER }, + { "Baby_Arch_Bishop", JOB_BABY_BISHOP }, + { "Baby_Mechanic", JOB_BABY_MECHANIC }, + { "Baby_Guillotine_Cross", JOB_BABY_CROSS }, + { "Baby_Royal_Guard", JOB_BABY_GUARD }, + { "Baby_Sorcerer", JOB_BABY_SORCERER }, + { "Baby_Minstrel", JOB_BABY_MINSTREL }, + { "Baby_Wanderer", JOB_BABY_WANDERER }, + { "Baby_Sura", JOB_BABY_SURA }, + { "Baby_Genetic", JOB_BABY_GENETIC }, + { "Baby_Shadow_Chaser", JOB_BABY_CHASER }, + { "Expanded_Super_Novice", JOB_SUPER_NOVICE_E }, + { "Expanded_Super_Baby", JOB_SUPER_BABY_E }, + { "Kagerou", JOB_KAGEROU }, + { "Oboro", JOB_OBORO }, + { "Rebellion", JOB_REBELLION }, + }; + + len = ARRAYLENGTH(names); + + ARR_FIND(0, len, i, strcmpi(names[i].name, name) == 0); + + if ( i == len ) + return -1; + + return names[i].id; +} + int pc_follow_timer(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd; struct block_list *tbl; @@ -5911,7 +6488,7 @@ int pc_stop_following (struct map_session_data *sd) sd->followtarget = -1; sd->ud.target_to = 0; - unit->stop_walking(&sd->bl, 1); + unit->stop_walking(&sd->bl, STOPWALKING_FLAG_FIXPOS); return 0; } @@ -5984,7 +6561,7 @@ void pc_baselevelchanged(struct map_session_data *sd) { for( i = 0; i < EQI_MAX; i++ ) { if( sd->equip_index[i] >= 0 ) { if( sd->inventory_data[ sd->equip_index[i] ]->elvmax && sd->status.base_level > (unsigned int)sd->inventory_data[ sd->equip_index[i] ]->elvmax ) - pc->unequipitem(sd, sd->equip_index[i], 3); + pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } } } @@ -6439,7 +7016,7 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) { { sd->status.skill[index].lv++; sd->status.skill_point--; - if( !skill->db[index].inf ) + if( !skill->dbs->db[index].inf ) status_calc_pc(sd,SCO_NONE); // Only recalculate for passive skills. else if( sd->status.skill_point == 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) ) pc->calc_skilltree(sd); // Required to grant all TK Ranger skills. @@ -6453,14 +7030,12 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) { if (!pc_has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown clif->skillinfoblock(sd); } else if( battle_config.skillup_limit ){ - if( sd->sktree.second ) - clif->msg_value(sd, 0x61E, sd->sktree.second); - else if( sd->sktree.third ) - clif->msg_value(sd, 0x61F, sd->sktree.third); - else if( pc->calc_skillpoint(sd) < 9 ) { - /* TODO: official response? */ - clif->colormes(sd->fd,COLOR_RED,"You need the basic skills"); - } + if (sd->sktree.second) + clif->msgtable_num(sd, MSG_SKILL_POINTS_LEFT_JOB1, sd->sktree.second); + else if (sd->sktree.third) + clif->msgtable_num(sd, MSG_SKILL_POINTS_LEFT_JOB2, sd->sktree.third); + else if (pc->calc_skillpoint(sd) < 9) /* TODO: official response? */ + clif->messagecolor_self(sd->fd, COLOR_RED, "You need the basic skills"); } return 0; } @@ -6486,22 +7061,22 @@ int pc_allskillup(struct map_session_data *sd) if (pc_has_permission(sd, PC_PERM_ALL_SKILL)) { //Get ALL skills except npc/guild ones. [Skotlex] //and except SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage] for(i=0;i<MAX_SKILL;i++){ - switch( skill->db[i].nameid ) { + switch( skill->dbs->db[i].nameid ) { case SG_DEVIL: case MO_TRIPLEATTACK: case RG_SNATCHER: continue; default: - if( !(skill->db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) ) - if ( ( sd->status.skill[i].lv = skill->db[i].max ) )//Nonexistant skills should return a max of 0 anyway. - sd->status.skill[i].id = skill->db[i].nameid; + if( !(skill->dbs->db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) ) + if ( ( sd->status.skill[i].lv = skill->dbs->db[i].max ) )//Nonexistant skills should return a max of 0 anyway. + sd->status.skill[i].id = skill->dbs->db[i].nameid; } } } else { int id; for (i = 0; i < MAX_SKILL_TREE && (id=pc->skill_tree[pc->class2idx(sd->status.class_)][i].id) > 0; i++) { int idx = pc->skill_tree[pc->class2idx(sd->status.class_)][i].idx; - int inf2 = skill->db[idx].inf2; + int inf2 = skill->dbs->db[idx].inf2; if ( (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || (inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) || @@ -6530,9 +7105,9 @@ int pc_resetlvl(struct map_session_data* sd,int type) nullpo_ret(sd); if (type != 3) //Also reset skills - pc->resetskill(sd, 0); + pc->resetskill(sd, PCRESETSKILL_NONE); - if(type == 1){ + if(type == 1) { sd->status.skill_point=0; sd->status.base_level=1; sd->status.job_level=1; @@ -6550,8 +7125,8 @@ int pc_resetlvl(struct map_session_data* sd,int type) if(sd->status.class_ == JOB_NOVICE_HIGH) { sd->status.status_point=100; // not 88 [celest] // give platinum skills upon changing - pc->skill(sd,142,1,0); - pc->skill(sd,143,1,0); + pc->skill(sd, NV_FIRSTAID, 1, SKILL_GRANT_PERMANENT); + pc->skill(sd, NV_TRICKDEAD, 1, SKILL_GRANT_PERMANENT); } } @@ -6597,7 +7172,7 @@ int pc_resetlvl(struct map_session_data* sd,int type) for(i=0;i<EQI_MAX;i++) { // unequip items that can't be equipped by base 1 [Valaris] if(sd->equip_index[i] >= 0) if(!pc->isequip(sd,sd->equip_index[i])) - pc->unequipitem(sd,sd->equip_index[i],2); + pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE); } if ((type == 1 || type == 2 || type == 3) && sd->status.party_id) @@ -6675,19 +7250,17 @@ int pc_resetstate(struct map_session_data* sd) /*========================================== * /resetskill - * if flag&1, perform block resync and status_calc call. - * if flag&2, just count total amount of skill points used by player, do not really reset. - * if flag&4, just reset the skills if the player class is a bard/dancer type (for changesex.) + * @param flag: @see enum pc_resetskill_flag *------------------------------------------*/ int pc_resetskill(struct map_session_data* sd, int flag) { int i, inf2, skill_point=0; nullpo_ret(sd); - if( flag&4 && (sd->class_&MAPID_UPPERMASK) != MAPID_BARDDANCER ) + if( flag&PCRESETSKILL_CHSEX && (sd->class_&MAPID_UPPERMASK) != MAPID_BARDDANCER ) return 0; - if( !(flag&2) ) { //Remove stuff lost when resetting skills. + if( !(flag&PCRESETSKILL_RECOUNT) ) { //Remove stuff lost when resetting skills. /** * It has been confirmed on official server that when you reset skills with a ranked tweakwon your skills are not reset (because you have all of them anyway) @@ -6726,17 +7299,17 @@ int pc_resetskill(struct map_session_data* sd, int flag) for( i = 1; i < MAX_SKILL; i++ ) { // FIXME: We're looping on i = [1..MAX_SKILL-1] (which makes sense as index for sd->status.skill[]) but then we're using the - // same i to access skill->db[], and especially to check skill_ischangesex(). This is wrong. + // same i to access skill->dbs->db[], and especially to check skill_ischangesex(). This is wrong. uint16 skill_id = 0; int lv = sd->status.skill[i].lv; if (lv < 1) continue; - inf2 = skill->db[i].inf2; + inf2 = skill->dbs->db[i].inf2; if( inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL) ) //Avoid reseting wedding/linker skills. continue; - skill_id = skill->db[i].nameid; + skill_id = skill->dbs->db[i].nameid; // Don't reset trick dead if not a novice/baby if( skill_id == NV_TRICKDEAD && (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE ) { @@ -6752,12 +7325,12 @@ int pc_resetskill(struct map_session_data* sd, int flag) if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED ) continue; - if( flag&4 && !skill_ischangesex(i) ) + if( flag&PCRESETSKILL_CHSEX && !skill_ischangesex(i) ) continue; if( inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn ) { //Only handle quest skills in a special way when you can't learn them manually - if( battle_config.quest_skill_reset && !(flag&2) ) { //Wipe them + if( battle_config.quest_skill_reset && !(flag&PCRESETSKILL_RECOUNT) ) { //Wipe them sd->status.skill[i].lv = 0; sd->status.skill[i].flag = 0; } @@ -6768,18 +7341,18 @@ int pc_resetskill(struct map_session_data* sd, int flag) else if( sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0 ) skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0); - if( !(flag&2) ) {// reset + if( !(flag&PCRESETSKILL_RECOUNT) ) {// reset sd->status.skill[i].lv = 0; sd->status.skill[i].flag = 0; } } - if( flag&2 || !skill_point ) return skill_point; + if( flag&PCRESETSKILL_RECOUNT || !skill_point ) return skill_point; sd->status.skill_point += skill_point; - if( !(flag&2) ) { + if (!(flag&PCRESETSKILL_RECOUNT)) { // Remove all SCs that can't be inactivated without a skill if( sd->sc.data[SC_STORMKICK_READY] ) status_change_end(&sd->bl, SC_STORMKICK_READY, INVALID_TIMER); @@ -6793,7 +7366,7 @@ int pc_resetskill(struct map_session_data* sd, int flag) status_change_end(&sd->bl, SC_DODGE_READY, INVALID_TIMER); } - if( flag&1 ) { + if (flag&PCRESETSKILL_RESYNC) { clif->updatestatus(sd,SP_SKILLPOINT); clif->skillinfoblock(sd); status_calc_pc(sd,SCO_FORCE); @@ -6825,8 +7398,7 @@ int pc_resethate(struct map_session_data* sd) int i; nullpo_ret(sd); - for (i=0; i<3; i++) - { + for (i = 0; i < MAX_PC_FEELHATE; i++) { sd->hate_mob[i] = -1; pc_setglobalreg(sd,script->add_str(pc->sg_info[i].hate_var),0); } @@ -6943,8 +7515,8 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { nullpo_retr(0, sd); - for(j = 0; j < 5; j++) { - if (sd->devotion[j]){ + for (j = 0; j < MAX_PC_DEVOTION; j++) { + if (sd->devotion[j]) { struct map_session_data *devsd = map->id2sd(sd->devotion[j]); if (devsd) status_change_end(&devsd->bl, SC_DEVOTION, INVALID_TIMER); @@ -7048,7 +7620,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { mob->unlocktarget(md,tick); if (battle_config.mobs_level_up && md->status.hp && (unsigned int)md->level < pc->maxbaselv(sd) - && !md->guardian_data && !md->special_state.ai// Guardians/summons should not level. [Skotlex] + && !md->guardian_data && md->special_state.ai == AI_NONE// Guardians/summons should not level. [Skotlex] ) { // monster level up [Valaris] clif->misceffect(&md->bl,0); @@ -7228,7 +7800,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { int n = eq_n[rnd()%eq_num]; if(rnd()%10000 < per){ if(sd->status.inventory[n].equip) - pc->unequipitem(sd,n,3); + pc->unequipitem(sd, n, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); pc->dropitem(sd,n,1); } } @@ -7241,7 +7813,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { || (type == 2 && sd->status.inventory[i].equip) || type == 3) ){ if(sd->status.inventory[i].equip) - pc->unequipitem(sd,i,3); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); pc->dropitem(sd,i,1); break; } @@ -7890,7 +8462,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) for(i=0;i<EQI_MAX;i++) { if(sd->equip_index[i] >= 0) if(!pc->isequip(sd,sd->equip_index[i])) - pc->unequipitem(sd,sd->equip_index[i],2); // unequip invalid item for class + pc->unequipitem(sd,sd->equip_index[i], PCUNEQUIPITEM_FORCE); // unequip invalid item for class } //Change look, if disguised, you need to undisguise @@ -8085,7 +8657,7 @@ int pc_setoption(struct map_session_data *sd,int type) if(pc->checkskill(sd, MC_PUSHCART) < 10) status_calc_pc(sd,SCO_NONE); //Remove speed penalty. if ( sd->equip_index[EQI_AMMO] > 0 ) - pc->unequipitem(sd, sd->equip_index[EQI_AMMO], 2); + pc->unequipitem(sd, sd->equip_index[EQI_AMMO], PCUNEQUIPITEM_FORCE); } #endif @@ -8122,7 +8694,7 @@ int pc_setoption(struct map_session_data *sd,int type) status_change_end(&sd->bl, (sc_type)i, INVALID_TIMER); } if ( sd->equip_index[EQI_AMMO] > 0 ) - pc->unequipitem(sd, sd->equip_index[EQI_AMMO], 2); + pc->unequipitem(sd, sd->equip_index[EQI_AMMO], PCUNEQUIPITEM_FORCE); } if (type&OPTION_FLYING && !(p_type&OPTION_FLYING)) @@ -8176,7 +8748,7 @@ int pc_setcart(struct map_session_data *sd,int type) { clif->clearcart(sd->fd); clif->updatestatus(sd, SP_CARTINFO); if ( sd->equip_index[EQI_AMMO] > 0 ) - pc->unequipitem(sd, sd->equip_index[EQI_AMMO], 2); + pc->unequipitem(sd, sd->equip_index[EQI_AMMO], PCUNEQUIPITEM_FORCE); break; default:/* everything else is an allowed ID so we can move on */ if( !sd->sc.data[SC_PUSH_CART] ) /* first time, so fill cart data */ @@ -8952,6 +9524,9 @@ void pc_equipitem_pos(struct map_session_data *sd, struct item_data *id, int pos /*========================================== * Equip item on player sd at req_pos from inventory index n + * Return: + * 0 = fail + * 1 = success *------------------------------------------*/ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) { @@ -9024,7 +9599,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) for(i=0;i<EQI_MAX;i++) { if(pos & pc->equip_pos[i]) { if(sd->equip_index[i] >= 0) //Slot taken, remove item from there. - pc->unequipitem(sd,sd->equip_index[i],2); + pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE); sd->equip_index[i] = n; } @@ -9083,7 +9658,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) } sd->npc_item_flag = iflag; - return 0; + return 1; } void pc_unequipitem_pos(struct map_session_data *sd, int n, int pos) @@ -9145,12 +9720,13 @@ void pc_unequipitem_pos(struct map_session_data *sd, int n, int pos) /*========================================== * Called when attemting to unequip an item from player - * type: - * 0 - only unequip - * 1 - calculate status after unequipping - * 2 - force unequip + * type: @see enum pc_unequipitem_flag + * Return: + * 0 = fail + * 1 = success *------------------------------------------*/ -int pc_unequipitem(struct map_session_data *sd,int n,int flag) { +int pc_unequipitem(struct map_session_data *sd,int n,int flag) +{ int i,iflag; bool status_cacl = false; int pos; @@ -9162,13 +9738,13 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { } // if player is berserk then cannot unequip - if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_NO_SWITCH_EQUIP]) ) + if (!(flag&PCUNEQUIPITEM_FORCE) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_NO_SWITCH_EQUIP]) ) { clif->unequipitemack(sd,n,0,UIA_FAIL); return 0; } - if( !(flag&2) && sd->sc.count && sd->sc.data[SC_KYOUGAKU] ) + if( !(flag&PCUNEQUIPITEM_FORCE) && sd->sc.count && sd->sc.data[SC_KYOUGAKU] ) { clif->unequipitemack(sd,n,0,UIA_FAIL); return 0; @@ -9229,7 +9805,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { } } - if(flag&1 || status_cacl) { + if(flag&PCUNEQUIPITEM_RECALC || status_cacl) { pc->checkallowskill(sd); status_calc_pc(sd,SCO_NONE); } @@ -9274,7 +9850,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { } sd->npc_item_flag = iflag; - return 0; + return 1; } /*========================================== @@ -9300,7 +9876,7 @@ int pc_checkitem(struct map_session_data *sd) if (!itemdb_available(id)) { ShowWarning("Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", id, sd->status.inventory[i].amount, sd->status.char_id); - pc->delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); continue; } @@ -9374,28 +9950,28 @@ int pc_checkitem(struct map_session_data *sd) continue; if( sd->status.inventory[i].equip&~pc->equippoint(sd,i) ) { - pc->unequipitem(sd, i, 2); + pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); calc_flag = 1; continue; } - if ( battle_config.unequip_restricted_equipment & 1 ) { + if (battle_config.unequip_restricted_equipment&1) { int j; - for ( j = 0; j < map->list[sd->bl.m].zone->disabled_items_count; j++ ) { - if ( map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[i].nameid ) { - pc->unequipitem( sd, i, 2 ); + for (j = 0; j < map->list[sd->bl.m].zone->disabled_items_count; j++) { + if (map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[i].nameid) { + pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); calc_flag = 1; } } } - if ( battle_config.unequip_restricted_equipment & 2 ) { - if ( !itemdb_isspecial( sd->status.inventory[i].card[0] ) ) { + if (battle_config.unequip_restricted_equipment&2) { + if (!itemdb_isspecial(sd->status.inventory[i].card[0])) { int j, slot; - for ( slot = 0; slot < MAX_SLOTS; slot++ ) { - for ( j = 0; j < map->list[sd->bl.m].zone->disabled_items_count; j++ ) { - if ( map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[i].card[slot] ) { - pc->unequipitem( sd, i, 2 ); + for (slot = 0; slot < MAX_SLOTS; slot++) { + for (j = 0; j < map->list[sd->bl.m].zone->disabled_items_count; j++) { + if (map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[i].card[slot]) { + pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); calc_flag = 1; } } @@ -9531,9 +10107,9 @@ int pc_divorce(struct map_session_data *sd) for( i = 0; i < MAX_INVENTORY; i++ ) { if( sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F ) - pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); if( p_sd->status.inventory[i].nameid == WEDDING_RING_M || p_sd->status.inventory[i].nameid == WEDDING_RING_F ) - pc->delitem(p_sd, i, 1, 0, 0, LOG_TYPE_OTHER); + pc->delitem(p_sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); } clif->divorced(sd, p_sd->status.name); @@ -10035,151 +10611,27 @@ void pc_read_skill_tree(void) { #else const char *config_filename = "db/pre-re/skill_tree.conf"; // FIXME hardcoded name #endif - int i = 0, jnamelen = 0; + int i = 0; struct s_mapiterator *iter; struct map_session_data *sd; - struct { - const char *name; - int id; - } jnames[] = { - { "Novice", JOB_NOVICE }, - { "Swordsman", JOB_SWORDMAN }, - { "Magician", JOB_MAGE }, - { "Archer", JOB_ARCHER }, - { "Acolyte", JOB_ACOLYTE }, - { "Merchant", JOB_MERCHANT }, - { "Thief", JOB_THIEF }, - { "Knight", JOB_KNIGHT }, - { "Priest", JOB_PRIEST }, - { "Wizard", JOB_WIZARD }, - { "Blacksmith", JOB_BLACKSMITH }, - { "Hunter", JOB_HUNTER }, - { "Assassin", JOB_ASSASSIN }, - { "Crusader", JOB_CRUSADER }, - { "Monk", JOB_MONK }, - { "Sage", JOB_SAGE }, - { "Rogue", JOB_ROGUE }, - { "Alchemist", JOB_ALCHEMIST }, - { "Bard", JOB_BARD }, - { "Dancer", JOB_DANCER }, - { "Super_Novice", JOB_SUPER_NOVICE }, - { "Gunslinger", JOB_GUNSLINGER }, - { "Ninja", JOB_NINJA }, - { "Novice_High", JOB_NOVICE_HIGH }, - { "Swordsman_High", JOB_SWORDMAN_HIGH }, - { "Magician_High", JOB_MAGE_HIGH }, - { "Archer_High", JOB_ARCHER_HIGH }, - { "Acolyte_High", JOB_ACOLYTE_HIGH }, - { "Merchant_High", JOB_MERCHANT_HIGH }, - { "Thief_High", JOB_THIEF_HIGH }, - { "Lord_Knight", JOB_LORD_KNIGHT }, - { "High_Priest", JOB_HIGH_PRIEST }, - { "High_Wizard", JOB_HIGH_WIZARD }, - { "Whitesmith", JOB_WHITESMITH }, - { "Sniper", JOB_SNIPER }, - { "Assassin_Cross", JOB_ASSASSIN_CROSS }, - { "Paladin", JOB_PALADIN }, - { "Champion", JOB_CHAMPION }, - { "Professor", JOB_PROFESSOR }, - { "Stalker", JOB_STALKER }, - { "Creator", JOB_CREATOR }, - { "Clown", JOB_CLOWN }, - { "Gypsy", JOB_GYPSY }, - { "Baby_Novice", JOB_BABY }, - { "Baby_Swordsman", JOB_BABY_SWORDMAN }, - { "Baby_Magician", JOB_BABY_MAGE }, - { "Baby_Archer", JOB_BABY_ARCHER }, - { "Baby_Acolyte", JOB_BABY_ACOLYTE }, - { "Baby_Merchant", JOB_BABY_MERCHANT }, - { "Baby_Thief", JOB_BABY_THIEF }, - { "Baby_Knight", JOB_BABY_KNIGHT }, - { "Baby_Priest", JOB_BABY_PRIEST }, - { "Baby_Wizard", JOB_BABY_WIZARD }, - { "Baby_Blacksmith", JOB_BABY_BLACKSMITH }, - { "Baby_Hunter", JOB_BABY_HUNTER }, - { "Baby_Assassin", JOB_BABY_ASSASSIN }, - { "Baby_Crusader", JOB_BABY_CRUSADER }, - { "Baby_Monk", JOB_BABY_MONK }, - { "Baby_Sage", JOB_BABY_SAGE }, - { "Baby_Rogue", JOB_BABY_ROGUE }, - { "Baby_Alchemist", JOB_BABY_ALCHEMIST }, - { "Baby_Bard", JOB_BABY_BARD }, - { "Baby_Dancer", JOB_BABY_DANCER }, - { "Super_Baby", JOB_SUPER_BABY }, - { "Taekwon", JOB_TAEKWON }, - { "Star_Gladiator", JOB_STAR_GLADIATOR }, - { "Soul_Linker", JOB_SOUL_LINKER }, - { "Gangsi", JOB_GANGSI }, - { "Death_Knight", JOB_DEATH_KNIGHT }, - { "Dark_Collector", JOB_DARK_COLLECTOR }, - { "Rune_Knight", JOB_RUNE_KNIGHT }, - { "Warlock", JOB_WARLOCK }, - { "Ranger", JOB_RANGER }, - { "Arch_Bishop", JOB_ARCH_BISHOP }, - { "Mechanic", JOB_MECHANIC }, - { "Guillotine_Cross", JOB_GUILLOTINE_CROSS }, - { "Rune_Knight_Trans", JOB_RUNE_KNIGHT_T }, - { "Warlock_Trans", JOB_WARLOCK_T }, - { "Ranger_Trans", JOB_RANGER_T }, - { "Arch_Bishop_Trans", JOB_ARCH_BISHOP_T }, - { "Mechanic_Trans", JOB_MECHANIC_T }, - { "Guillotine_Cross_Trans", JOB_GUILLOTINE_CROSS_T }, - { "Royal_Guard", JOB_ROYAL_GUARD }, - { "Sorcerer", JOB_SORCERER }, - { "Minstrel", JOB_MINSTREL }, - { "Wanderer", JOB_WANDERER }, - { "Sura", JOB_SURA }, - { "Genetic", JOB_GENETIC }, - { "Shadow_Chaser", JOB_SHADOW_CHASER }, - { "Royal_Guard_Trans", JOB_ROYAL_GUARD_T }, - { "Sorcerer_Trans", JOB_SORCERER_T }, - { "Minstrel_Trans", JOB_MINSTREL_T }, - { "Wanderer_Trans", JOB_WANDERER_T }, - { "Sura_Trans", JOB_SURA_T }, - { "Genetic_Trans", JOB_GENETIC_T }, - { "Shadow_Chaser_Trans", JOB_SHADOW_CHASER_T }, - { "Baby_Rune_Knight", JOB_BABY_RUNE }, - { "Baby_Warlock", JOB_BABY_WARLOCK }, - { "Baby_Ranger", JOB_BABY_RANGER }, - { "Baby_Arch_Bishop", JOB_BABY_BISHOP }, - { "Baby_Mechanic", JOB_BABY_MECHANIC }, - { "Baby_Guillotine_Cross", JOB_BABY_CROSS }, - { "Baby_Royal_Guard", JOB_BABY_GUARD }, - { "Baby_Sorcerer", JOB_BABY_SORCERER }, - { "Baby_Minstrel", JOB_BABY_MINSTREL }, - { "Baby_Wanderer", JOB_BABY_WANDERER }, - { "Baby_Sura", JOB_BABY_SURA }, - { "Baby_Genetic", JOB_BABY_GENETIC }, - { "Baby_Shadow_Chaser", JOB_BABY_CHASER }, - { "Expanded_Super_Novice", JOB_SUPER_NOVICE_E }, - { "Expanded_Super_Baby", JOB_SUPER_BABY_E }, - { "Kagerou", JOB_KAGEROU }, - { "Oboro", JOB_OBORO }, - { "Rebellion", JOB_REBELLION }, - }; if (libconfig->read_file(&skill_tree_conf, config_filename)) { ShowError("can't read %s\n", config_filename); return; } - - jnamelen = ARRAYLENGTH(jnames); - + while ((skt = libconfig->setting_get_elem(skill_tree_conf.root,i++))) { int k; const char *name = config_setting_name(skt); - ARR_FIND(0, jnamelen, k, strcmpi(jnames[k].name,name) == 0 ); - - if( k == jnamelen ) { - ShowWarning("pc_read_skill_tree: '%s' unknown job name!\n",name); + if ( (k = pc->check_job_name(name)) == -1 ) { + ShowWarning("pc_read_skill_tree: '%s' unknown job name!\n", name); continue; } - - + if( ( skills = libconfig->setting_get_member(skt,"skills") ) ) { int c = 0; - int idx = pc->class2idx(jnames[k].id); + int idx = pc->class2idx(k); while ((sk = libconfig->setting_get_elem(skills,c++))) { const char *sk_name = config_setting_name(sk); @@ -10193,7 +10645,7 @@ void pc_read_skill_tree(void) { ShowWarning("pc_read_skill_tree: Unable to load skill %d (%s) into '%s's tree. Maximum number of skills per class has been reached.\n", skill_id, sk_name, name); continue; } else if (pc->skill_tree[idx][skidx].id) { - ShowNotice("pc_read_skill_tree: Overwriting %d for '%s' (%d)\n", skill_id, name, jnames[k].id); + ShowNotice("pc_read_skill_tree: Overwriting %d for '%s' (%d)\n", skill_id, name, k); } pc->skill_tree[idx][skidx].id = skill_id; @@ -10237,46 +10689,42 @@ void pc_read_skill_tree(void) { while( (skt = libconfig->setting_get_elem(skill_tree_conf.root,i++)) ) { int k, idx; const char *name = config_setting_name(skt); - - ARR_FIND(0, jnamelen, k, strcmpi(jnames[k].name,name) == 0 ); - - if( k == jnamelen ) { - ShowWarning("pc_read_skill_tree: '%s' unknown job name!\n",name); + if ( (k = pc->check_job_name(name)) == -1 ) { + ShowWarning("pc_read_skill_tree: '%s' unknown job name!\n", name); continue; } - idx = pc->class2idx(jnames[k].id); + + idx = pc->class2idx(k); if( ( inherit = libconfig->setting_get_member(skt,"inherit") ) ) { const char *iname; int v = 0; - while ((iname = libconfig->setting_get_string_elem(inherit, v++))) { + while ( (iname = libconfig->setting_get_string_elem(inherit, v++)) ) { int b = 0, a, d, f, fidx; - ARR_FIND(0, jnamelen, b, strcmpi(jnames[b].name,iname) == 0 ); - - if( b == jnamelen ) { - ShowWarning("pc_read_skill_tree: '%s' trying to inherit unknown '%s'!\n",name,iname); + if ( (b = pc->check_job_name(iname)) == -1 ) { + ShowWarning("pc_read_skill_tree: '%s' trying to inherit unknown '%s'!\n", name, iname); continue; } - - fidx = pc->class2idx(jnames[b].id); - - ARR_FIND( 0, MAX_SKILL_TREE, d, pc->skill_tree[fidx][d].id == 0 ); - for( f = 0; f < d; f++ ) { - - ARR_FIND( 0, MAX_SKILL_TREE, a, pc->skill_tree[idx][a].id == 0 || pc->skill_tree[idx][a].id == pc->skill_tree[fidx][f].id ); + fidx = pc->class2idx(b); + + ARR_FIND(0, MAX_SKILL_TREE, d, pc->skill_tree[fidx][d].id == 0); + + for ( f = 0; f < d; f++ ) { + + ARR_FIND(0, MAX_SKILL_TREE, a, pc->skill_tree[idx][a].id == 0 || pc->skill_tree[idx][a].id == pc->skill_tree[fidx][f].id); - if( a == MAX_SKILL_TREE ) { - ShowWarning("pc_read_skill_tree: '%s' can't inherit '%s', skill tree is full!\n", name,iname); + if ( a == MAX_SKILL_TREE ) { + ShowWarning("pc_read_skill_tree: '%s' can't inherit '%s', skill tree is full!\n", name, iname); break; - } else if ( pc->skill_tree[idx][a].id || ( pc->skill_tree[idx][a].id == NV_TRICKDEAD && ((pc->jobid2mapid(jnames[k].id)&(MAPID_BASEMASK|JOBL_2))!=MAPID_NOVICE) ) ) /* we skip trickdead for non-novices */ + } else if ( pc->skill_tree[idx][a].id || (pc->skill_tree[idx][a].id == NV_TRICKDEAD && ((pc->jobid2mapid(k)&(MAPID_BASEMASK | JOBL_2)) != MAPID_NOVICE)) ) /* we skip trickdead for non-novices */ continue;/* skip */ memcpy(&pc->skill_tree[idx][a], &pc->skill_tree[fidx][f], sizeof(pc->skill_tree[fidx][f])); pc->skill_tree[idx][a].inherited = 1; } - + } } @@ -10427,8 +10875,8 @@ int pc_readdb(void) { // Reset then read attr_fix for(i=0;i<4;i++) - for(j=0;j<ELE_MAX;j++) - for(k=0;k<ELE_MAX;k++) + for ( j = ELE_NEUTRAL; j<ELE_MAX; j++ ) + for ( k = ELE_NEUTRAL; k<ELE_MAX; k++ ) battle->attr_fix_table[i][j][k]=100; sprintf(line, "%s/"DBPATH"attr_fix.txt", map->db_path); @@ -10455,13 +10903,13 @@ int pc_readdb(void) { lv=atoi(split[0]); n=atoi(split[1]); count++; - for(i=0;i<n && i<ELE_MAX;){ + for ( i = ELE_NEUTRAL; i<n && i<ELE_MAX; ) { if( !fgets(line, sizeof(line), fp) ) break; if(line[0]=='/' && line[1]=='/') continue; - for(j=0,p=line;j<n && j<ELE_MAX && p;j++){ + for ( j = ELE_NEUTRAL, p = line; j<n && j<ELE_MAX && p; j++ ) { while(*p==32 && *p>0) p++; battle->attr_fix_table[lv-1][i][j]=atoi(p); @@ -10589,15 +11037,15 @@ void pc_bank_deposit(struct map_session_data *sd, int money) { void pc_bank_withdraw(struct map_session_data *sd, int money) { unsigned int limit_check = money+sd->status.zeny; - if( money <= 0 ) { + if (money <= 0) { clif->bank_withdraw(sd,BWA_UNKNOWN_ERROR); return; - } else if ( money > sd->status.bank_vault ) { + } else if (money > sd->status.bank_vault) { clif->bank_withdraw(sd,BWA_NO_MONEY); return; - } else if ( limit_check > MAX_ZENY ) { + } else if (limit_check > MAX_ZENY) { /* no official response for this scenario exists. */ - clif->colormes(sd->fd,COLOR_RED,msg_sd(sd,1482)); + clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd,1482)); return; } @@ -10997,16 +11445,10 @@ void pc_defaults(void) { /* */ pc->day_timer_tid = INVALID_TIMER; pc->night_timer_tid = INVALID_TIMER; - /* respecting order */ - memset(pc->exp_table, 0, sizeof(pc->exp_table) - + sizeof(pc->max_level) - + sizeof(pc->statp) - + sizeof(pc->level_penalty) - + sizeof(pc->skill_tree) - + sizeof(pc->smith_fame_list) - + sizeof(pc->chemist_fame_list) - + sizeof(pc->taekwon_fame_list) - ); + + // These macros are used instead of a sum of sizeof(), to ensure that padding won't interfere with our size, and code won't rot when adding more fields + memset(ZEROED_BLOCK_POS(pc), 0, ZEROED_BLOCK_SIZE(pc)); + /* */ memcpy(pc->equip_pos, &equip_pos, sizeof(pc->equip_pos)); /* */ @@ -11096,7 +11538,9 @@ void pc_defaults(void) { pc->skill = pc_skill; pc->insert_card = pc_insert_card; - + pc->can_insert_card = pc_can_insert_card; + pc->can_insert_card_into = pc_can_insert_card_into; + pc->steal_item = pc_steal_item; pc->steal_coin = pc_steal_coin; @@ -11203,6 +11647,7 @@ void pc_defaults(void) { pc->addfame = pc_addfame; pc->famerank = pc_famerank; pc->set_hate_mob = pc_set_hate_mob; + pc->getmaxspiritball = pc_getmaxspiritball; pc->readdb = pc_readdb; pc->map_day_timer = map_day_timer; // by [yor] @@ -11281,4 +11726,6 @@ void pc_defaults(void) { pc->autotrade_start = pc_autotrade_start; pc->autotrade_prepare = pc_autotrade_prepare; pc->autotrade_populate = pc_autotrade_populate; + + pc->check_job_name = pc_check_job_name; } diff --git a/src/map/pc.h b/src/map/pc.h index 56380447e..f546d4910 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -5,23 +5,23 @@ #ifndef MAP_PC_H #define MAP_PC_H -#include "../config/core.h" // AUTOLOOTITEM_SIZE, RENEWAL, SECURE_NPCTIMEOUT - -#include "battle.h" // battle -#include "battleground.h" // enum bg_queue_types -#include "buyingstore.h" // struct s_buyingstore -#include "itemdb.h" // MAX_ITEMDELAYS -#include "log.h" // struct e_log_pick_type -#include "map.h" // RC_MAX, ELE_MAX -#include "pc_groups.h" // GroupSettings -#include "script.h" // struct reg_db -#include "searchstore.h" // struct s_search_store_info -#include "status.h" // enum sc_type, OPTION_* -#include "unit.h" // struct unit_data, struct view_data -#include "vending.h" // struct s_vending -#include "../common/cbasetypes.h" -#include "../common/ers.h" // struct eri -#include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus, NEW_CARTS +#include "config/core.h" // AUTOLOOTITEM_SIZE, RENEWAL, SECURE_NPCTIMEOUT + +#include "map/battle.h" // battle +#include "map/battleground.h" // enum bg_queue_types +#include "map/buyingstore.h" // struct s_buyingstore +#include "map/itemdb.h" // MAX_ITEMDELAYS +#include "map/log.h" // struct e_log_pick_type +#include "map/map.h" // RC_MAX, ELE_MAX +#include "map/pc_groups.h" // GroupSettings +#include "map/script.h" // struct reg_db +#include "map/searchstore.h" // struct s_search_store_info +#include "map/status.h" // enum sc_type, OPTION_* +#include "map/unit.h" // struct unit_data, struct view_data +#include "map/vending.h" // struct s_vending +#include "common/cbasetypes.h" +#include "common/ers.h" // struct eri +#include "common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus, NEW_CARTS /** * Defines @@ -29,7 +29,8 @@ #define MAX_PC_BONUS 10 #define MAX_PC_SKILL_REQUIRE 5 #define MAX_PC_FEELHATE 3 -#define PVP_CALCRANK_INTERVAL 1000 // PVP calculation interval +#define MAX_PC_DEVOTION 5 ///< Max amount of devotion targets +#define PVP_CALCRANK_INTERVAL 1000 ///< PVP calculation interval //Equip indexes constants. (eg: sd->equip_index[EQI_AMMO] returns the index //where the arrows are equipped) @@ -57,11 +58,23 @@ enum equip_index { EQI_SHADOW_ACC_L, EQI_MAX }; + +enum pc_unequipitem_flag { + PCUNEQUIPITEM_NONE = 0x0, ///< Just unequip + PCUNEQUIPITEM_RECALC = 0x1, ///< Recalculate status after unequipping + PCUNEQUIPITEM_FORCE = 0x2, ///< Force unequip +}; + +enum pc_resetskill_flag { + PCRESETSKILL_NONE = 0x0, + PCRESETSKILL_RESYNC = 0x1, // perform block resync and status_calc call + PCRESETSKILL_RECOUNT = 0x2, // just count total amount of skill points used by player, do not really reset + PCRESETSKILL_CHSEX = 0x4, // just reset the skills if the player class is a bard/dancer type (for changesex.) +}; + struct weapon_data { int atkmods[3]; - // all the variables except atkmods get zero'ed in each call of status_calc_pc - // NOTE: if you want to add a non-zeroed variable, you need to update the memset call - // in status_calc_pc as well! All the following are automatically zero'ed. [Skotlex] +BEGIN_ZEROED_BLOCK; // all the variables within this block get zero'ed in each call of status_calc_pc int overrefine; int star; int ignore_def_ele; @@ -85,15 +98,20 @@ struct weapon_data { short flag, rate; unsigned char ele; } addele2[MAX_PC_BONUS]; +END_ZEROED_BLOCK; }; struct s_autospell { short id, lv, rate, card_id, flag; bool lock; // bAutoSpellOnSkill: blocks autospell from triggering again, while being executed }; +/// AddEff bonus data struct s_addeffect { - enum sc_type id; - short rate, arrow_rate; - unsigned char flag; + enum sc_type id; ///< Effect ID + int16 rate; ///< Base success rate + int16 arrow_rate; ///< Success rate modifier for ranged attacks (adds to the base rate) + uint8 flag; ///< Trigger flag (@see enum auto_trigger_flag) + uint16 duration; ///< Optional, non-reducible duration in ms. If 0, the default, reducible effect's duration is used. + // TODO[Haru]: Duration is only used in addeff (set through bonus4 bAddEff). The other addeffect types could also use it. }; struct s_addeffectonskill { enum sc_type id; @@ -141,7 +159,7 @@ struct map_session_data { unsigned int arrow_atk : 1; unsigned int gangsterparadise : 1; unsigned int rest : 1; - unsigned int storage_flag : 2; //0: closed, 1: Normal Storage open, 2: guild storage open [Skotlex] + unsigned int storage_flag : 2; // @see enum storage_flag unsigned int snovice_dead_flag : 1; //Explosion spirits on death: 0 off, 1 used. unsigned int abra_flag : 2; // Abracadabra bugfix by Aru unsigned int autocast : 1; // Autospell flag [Inkfish] @@ -188,6 +206,7 @@ struct map_session_data { unsigned int itemcheck : 1; unsigned int standalone : 1;/* [Ind/Hercules <3] */ unsigned int loggingout : 1; + unsigned int warp_clean : 1; } state; struct { unsigned char no_weapon_damage, no_magic_damage, no_misc_damage; @@ -260,7 +279,8 @@ struct map_session_data { short weapontype1,weapontype2; short disguise; // [Valaris] struct weapon_data right_weapon, left_weapon; - // here start arrays to be globally zeroed at the beginning of status_calc_pc() + +BEGIN_ZEROED_BLOCK; // this block will be globally zeroed at the beginning of status_calc_pc() int param_bonus[6],param_equip[6]; //Stores card/equipment bonuses. int subele[ELE_MAX]; int subrace[RC_MAX]; @@ -285,8 +305,9 @@ struct map_session_data { short sp_gain_race[RC_MAX]; short sp_gain_race_attack[RC_MAX]; short hp_gain_race_attack[RC_MAX]; - // zeroed arrays end here. - // zeroed structures start here +#ifdef RENEWAL + int race_tolerance[RC_MAX]; +#endif struct s_autospell autospell[15], autospell2[15], autospell3[15]; struct s_addeffect addeff[MAX_PC_BONUS], addeff2[MAX_PC_BONUS]; struct s_addeffectonskill addeff3[MAX_PC_BONUS]; @@ -315,11 +336,6 @@ struct map_session_data { short value; int rate, tick; } def_set_race[RC_MAX], mdef_set_race[RC_MAX]; - // zeroed structures end here - // manually zeroed structures start here. - struct s_autobonus autobonus[MAX_PC_BONUS], autobonus2[MAX_PC_BONUS], autobonus3[MAX_PC_BONUS]; //Auto script on attack, when attacked, on skill usage - // manually zeroed structures end here. - // zeroed vars start here. struct { int atk_rate; int arrow_atk,arrow_ele,arrow_cri,arrow_hit; @@ -356,7 +372,11 @@ struct map_session_data { int add_fixcast,add_varcast; int ematk; // matk bonus from equipment } bonus; - // zeroed vars end here. +END_ZEROED_BLOCK; + + // The following structures are zeroed manually in status_calc_pc_ + struct s_autobonus autobonus[MAX_PC_BONUS], autobonus2[MAX_PC_BONUS], autobonus3[MAX_PC_BONUS]; //Auto script on attack, when attacked, on skill usage + int castrate,delayrate,hprate,sprate,dsprate; int hprecov_rate,sprecov_rate; int matk_rate; @@ -373,7 +393,7 @@ struct map_session_data { unsigned char mission_count; //Stores the bounty kill count for TK_MISSION short mission_mobid; //Stores the target mob_id for TK_MISSION int die_counter; //Total number of times you've died - int devotion[5]; //Stores the account IDs of chars devoted to. + int devotion[MAX_PC_DEVOTION]; //Stores the account IDs of chars devoted to. int trade_partner; struct { struct { @@ -405,11 +425,11 @@ struct map_session_data { struct mercenary_data *md; struct elemental_data *ed; - struct{ + struct { int m; //-1 - none, other: map index corresponding to map name. unsigned short index; //map index - } feel_map[3];// 0 - Sun; 1 - Moon; 2 - Stars - short hate_mob[3]; + } feel_map[MAX_PC_FEELHATE];// 0 - Sun; 1 - Moon; 2 - Stars + short hate_mob[MAX_PC_FEELHATE]; int pvp_timer; short pvp_point; @@ -723,6 +743,16 @@ enum e_pc_autotrade_update_action { }; /** + * Flag values for pc->skill + */ +enum pc_skill_flag { + SKILL_GRANT_PERMANENT = 0, // Grant permanent skill to be bound to skill tree + SKILL_GRANT_TEMPORARY = 1, // Grant an item skill (temporary) + SKILL_GRANT_TEMPSTACK = 2, // Like 1, except the level granted can stack with previously learned level. + SKILL_GRANT_UNCONDITIONAL = 3, // Grant skill unconditionally and forever (persistent to job changes and skill resets) +}; + +/** * Used to temporarily remember vending data **/ struct autotrade_vending { @@ -746,17 +776,20 @@ struct pc_interface { int day_timer_tid; int night_timer_tid; /* */ + +BEGIN_ZEROED_BLOCK; /* Everything within this block will be memset to 0 when status_defaults() is executed */ unsigned int exp_table[CLASS_COUNT][2][MAX_LEVEL]; unsigned int max_level[CLASS_COUNT][2]; unsigned int statp[MAX_LEVEL+1]; unsigned int level_penalty[3][RC_MAX][MAX_LEVEL*2+1]; - - unsigned int equip_pos[EQI_MAX]; /* */ struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE]; struct fame_list smith_fame_list[MAX_FAME_LIST]; struct fame_list chemist_fame_list[MAX_FAME_LIST]; struct fame_list taekwon_fame_list[MAX_FAME_LIST]; +END_ZEROED_BLOCK; /* End */ + + unsigned int equip_pos[EQI_MAX]; struct sg_data sg_info[MAX_PC_FEELHATE]; /* */ struct eri *sc_display_ers; @@ -848,6 +881,8 @@ struct pc_interface { int (*skill) (struct map_session_data *sd, int id, int level, int flag); int (*insert_card) (struct map_session_data *sd,int idx_card,int idx_equip); + bool (*can_insert_card) (struct map_session_data* sd, int idx_card); + bool (*can_insert_card_into) (struct map_session_data* sd, int idx_card, int idx_equip); int (*steal_item) (struct map_session_data *sd,struct block_list *bl, uint16 skill_lv); int (*steal_coin) (struct map_session_data *sd,struct block_list *bl); @@ -950,6 +985,7 @@ struct pc_interface { int (*addspiritball) (struct map_session_data *sd,int interval,int max); int (*delspiritball) (struct map_session_data *sd,int count,int type); + int (*getmaxspiritball) (struct map_session_data *sd, int min); void (*addfame) (struct map_session_data *sd,int count); unsigned char (*famerank) (int char_id, int job); int (*set_hate_mob) (struct map_session_data *sd, int pos, struct block_list *bl); @@ -987,7 +1023,7 @@ struct pc_interface { void (*check_skilltree) (struct map_session_data *sd, int skill_id); int (*bonus_autospell) (struct s_autospell *spell, int max, short id, short lv, short rate, short flag, short card_id); int (*bonus_autospell_onskill) (struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, short card_id); - int (*bonus_addeff) (struct s_addeffect* effect, int max, enum sc_type id, short rate, short arrow_rate, unsigned char flag); + int (*bonus_addeff) (struct s_addeffect* effect, int max, enum sc_type id, int16 rate, int16 arrow_rate, uint8 flag, uint16 duration); int (*bonus_addeff_onskill) (struct s_addeffectonskill* effect, int max, enum sc_type id, short rate, short skill_id, unsigned char target); int (*bonus_item_drop) (struct s_add_drop *drop, const short max, short id, short group, int race, int rate); void (*calcexp) (struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src); @@ -1032,6 +1068,8 @@ struct pc_interface { void (*autotrade_start) (struct map_session_data *sd); void (*autotrade_prepare) (struct map_session_data *sd); void (*autotrade_populate) (struct map_session_data *sd); + + int (*check_job_name) (const char *name); }; struct pc_interface *pc; diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c index 9cd478b3f..f9a442d97 100644 --- a/src/map/pc_groups.c +++ b/src/map/pc_groups.c @@ -6,17 +6,17 @@ #include "pc_groups.h" -#include "atcommand.h" // atcommand->exists(), atcommand->load_groups() -#include "clif.h" // clif->GM_kick() -#include "map.h" // mapiterator -#include "pc.h" // pc->set_group() -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" // strcmp +#include "map/atcommand.h" // atcommand-"exists(), atcommand-"load_groups() +#include "map/clif.h" // clif-"GM_kick() +#include "map/map.h" // mapiterator +#include "map/pc.h" // pc-"set_group() +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/db.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/showmsg.h" +#include "common/strlib.h" // strcmp static GroupSettings dummy_group; ///< dummy group used in dummy map sessions @see pc_get_dummy_sd() diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h index 8dd95a177..4fee312a4 100644 --- a/src/map/pc_groups.h +++ b/src/map/pc_groups.h @@ -5,9 +5,9 @@ #ifndef MAP_PC_GROUPS_H #define MAP_PC_GROUPS_H -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/db.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/db.h" /// PC permissions enum e_pc_permission { diff --git a/src/map/pet.c b/src/map/pet.c index b37d3c350..2379ec984 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -6,36 +6,36 @@ #include "pet.h" +#include "map/atcommand.h" // msg_txt() +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/unit.h" +#include "common/db.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" // msg_txt() -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "npc.h" -#include "path.h" -#include "pc.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "unit.h" -#include "../common/db.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct pet_interface pet_s; #define MIN_PETTHINKTIME 100 @@ -91,7 +91,7 @@ int pet_unlocktarget(struct pet_data *pd) pd->target_id=0; pet_stop_attack(pd); - pet_stop_walking(pd,1); + pet_stop_walking(pd, STOPWALKING_FLAG_FIXPOS); return 0; } @@ -132,7 +132,7 @@ int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type) pd = sd->pd; - Assert((pd->msd == 0) || (pd->msd->pd == pd)); + Assert_ret(pd->msd == 0 || pd->msd->pd == pd); if( bl == NULL || bl->type != BL_MOB || bl->prev == NULL || pd->pet.intimate < battle_config.pet_support_min_friendly @@ -280,7 +280,7 @@ int pet_performance(struct map_session_data *sd, struct pet_data *pd) else val = 1; - pet_stop_walking(pd,2000<<8); + pet_stop_walking(pd,STOPWALKING_FLAG_NONE | (2000<<8)); // Stop walking for 2000ms clif->send_petdata(NULL, pd, 4, rnd()%val + 1); pet->lootitem_drop(pd,NULL); return 1; @@ -318,8 +318,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo) int i=0,interval=0; nullpo_retr(1, sd); - - Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + Assert_retr(1, sd->status.pet_id == 0 || sd->pd == 0 || sd->pd->msd == sd); if(sd->status.account_id != petinfo->account_id || sd->status.char_id != petinfo->char_id) { sd->status.pet_id = 0; @@ -389,8 +388,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo) int pet_birth_process(struct map_session_data *sd, struct s_pet *petinfo) { nullpo_retr(1, sd); - - Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + Assert_retr(1, sd->status.pet_id == 0 || sd->pd == 0 || sd->pd->msd == sd); if(sd->status.pet_id && petinfo->incubate == 1) { sd->status.pet_id = 0; @@ -418,7 +416,7 @@ int pet_birth_process(struct map_session_data *sd, struct s_pet *petinfo) clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom); clif->send_petstatus(sd); } - Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + Assert_retr(1, sd->status.pet_id == 0 || sd->pd == 0 || sd->pd->msd == sd); return 0; } @@ -447,7 +445,7 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag) { return 1; } if (!pet->birth_process(sd,p)) //Pet hatched. Delete egg. - pc->delitem(sd,i,1,0,0,LOG_TYPE_OTHER); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); } else { pet->data_init(sd,p); if(sd->pd && sd->bl.prev != NULL) { @@ -680,7 +678,7 @@ int pet_equipitem(struct map_session_data *sd,int index) { return 1; } - pc->delitem(sd,index,1,0,0,LOG_TYPE_OTHER); + pc->delitem(sd, index, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); pd->pet.equip = nameid; status->set_viewdata(&pd->bl, pd->pet.class_); //Updates view_data. clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom); @@ -745,7 +743,7 @@ int pet_food(struct map_session_data *sd, struct pet_data *pd) { clif->pet_food(sd, food_id, 0); return 1; } - pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); if (pd->pet.hungry > 90) { pet->set_intimate(pd, pd->pet.intimate - pd->petDB->r_full); @@ -781,10 +779,10 @@ int pet_food(struct map_session_data *sd, struct pet_data *pd) { return 0; } -int pet_randomwalk(struct pet_data *pd, int64 tick) { +int pet_randomwalk(struct pet_data *pd, int64 tick) +{ nullpo_ret(pd); - - Assert((pd->msd == 0) || (pd->msd->pd == pd)); + Assert_ret(pd->msd == 0 || pd->msd->pd == pd); if (DIFF_TICK(pd->next_walktime,tick) < 0 && unit->can_move(&pd->bl)) { const int retrycount=20; @@ -1146,7 +1144,7 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) { } pet_stop_attack(pd); - pet_stop_walking(pd,1); + pet_stop_walking(pd, STOPWALKING_FLAG_FIXPOS); pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000,pet->skill_support_timer,sd->bl.id,0); if (skill->get_inf(pd->s_skill->id) & INF_GROUND_SKILL) unit->skilluse_pos(&pd->bl, sd->bl.x, sd->bl.y, pd->s_skill->id, pd->s_skill->lv); diff --git a/src/map/pet.h b/src/map/pet.h index 0b51bcb16..06302c9b2 100644 --- a/src/map/pet.h +++ b/src/map/pet.h @@ -5,11 +5,11 @@ #ifndef MAP_PET_H #define MAP_PET_H -#include "map.h" // struct block_list -#include "status.h" // enum sc_type -#include "unit.h" // struct unit_data -#include "../common/cbasetypes.h" -#include "../common/mmo.h" // NAME_LENGTH, struct s_pet +#include "map/map.h" // struct block_list +#include "map/status.h" // enum sc_type +#include "map/unit.h" // struct unit_data +#include "common/cbasetypes.h" +#include "common/mmo.h" // NAME_LENGTH, struct s_pet #define MAX_PET_DB 300 #define MAX_PETLOOT_SIZE 30 diff --git a/src/map/quest.c b/src/map/quest.c index 93ec1b04c..463a3395a 100644 --- a/src/map/quest.c +++ b/src/map/quest.c @@ -6,37 +6,38 @@ #include "quest.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/pc.h" +#include "map/script.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "pc.h" -#include "script.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct quest_interface quest_s; +struct quest_db *db_data[MAX_QUEST_DB]; ///< Quest database /** * Searches a quest by ID. @@ -618,6 +619,7 @@ void do_reload_quest(void) { */ void quest_defaults(void) { quest = &quest_s; + quest->db_data = db_data; memset(&quest->db, 0, sizeof(quest->db)); memset(&quest->dummy, 0, sizeof(quest->dummy)); diff --git a/src/map/quest.h b/src/map/quest.h index 36ac69a53..9b5199625 100644 --- a/src/map/quest.h +++ b/src/map/quest.h @@ -5,9 +5,9 @@ #ifndef MAP_QUEST_H #define MAP_QUEST_H -#include "map.h" // TBL_PC -#include "../common/cbasetypes.h" -#include "../common/conf.h" +#include "map/map.h" // TBL_PC +#include "common/cbasetypes.h" +#include "common/conf.h" #define MAX_QUEST_DB (60355+1) // Highest quest ID + 1 @@ -40,7 +40,7 @@ enum quest_check_type { }; struct quest_interface { - struct quest_db *db_data[MAX_QUEST_DB]; ///< Quest database + struct quest_db **db_data; ///< Quest database struct quest_db dummy; ///< Dummy entry for invalid quest lookups /* */ void (*init) (bool minimal); diff --git a/src/map/script.c b/src/map/script.c index d5cf58946..e7a0175c7 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -4,60 +4,59 @@ #define HERCULES_CORE -#include "../config/core.h" // RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, SECURE_NPCTIMEOUT_INTERVAL +#include "config/core.h" // RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, SECURE_NPCTIMEOUT_INTERVAL #include "script.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/battleground.h" +#include "map/channel.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/mail.h" +#include "map/map.h" +#include "map/mapreg.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/pet.h" +#include "map/quest.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/status.h" +#include "map/storage.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/malloc.h" +#include "common/md5calc.h" +#include "common/mmo.h" // NEW_CARTS +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" // usage: getcharip +#include "common/strlib.h" +#include "common/sysinfo.h" +#include "common/timer.h" +#include "common/utils.h" +#include "common/HPM.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> - -#include "atcommand.h" -#include "battle.h" -#include "battleground.h" -#include "channel.h" -#include "chat.h" -#include "chrif.h" -#include "clif.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "instance.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "mail.h" -#include "map.h" -#include "mapreg.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "pet.h" -#include "quest.h" -#include "skill.h" -#include "status.h" -#include "status.h" -#include "storage.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/md5calc.h" -#include "../common/mmo.h" // NEW_CARTS -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" // usage: getcharip -#include "../common/strlib.h" -#include "../common/sysinfo.h" -#include "../common/timer.h" -#include "../common/utils.h" -#include "../common/HPM.h" - #ifndef WIN32 #include <sys/time.h> #endif @@ -406,7 +405,7 @@ unsigned int calc_hash_ci(const char* p) { /// Looks up string using the provided id. const char* script_get_str(int id) { - Assert( id >= LABEL_START && id < script->str_size ); + Assert_retr(NULL, id >= LABEL_START && id < script->str_size); return script->str_buf+script->str_data[id].str; } @@ -462,7 +461,7 @@ const char *script_casecheck_add_str_sub(struct casecheck_data *ccd, const char int i; for (i = ccd->str_hash[h]; ; i = ccd->str_data[i].next) { const char *s = NULL; - Assert( i >= 0 && i < ccd->str_size ); + Assert_retb(i >= 0 && i < ccd->str_size); s = ccd->str_buf+ccd->str_data[i].str; if (strcasecmp(s,p) == 0) { return s; // string already in list @@ -1295,7 +1294,8 @@ const char* parse_simpleexpr(const char *p) const char *line_start = start_point; const char *line_end = start_point; struct script_string_buf *lbuf = &script->lang_export_line_buf; - size_t line_length; + struct script_string_buf *ubuf = &script->lang_export_unescaped_buf; + size_t line_length, cursor; while( line_start > script->parser_current_src ) { if( *line_start != '\n' ) @@ -1319,6 +1319,13 @@ const char* parse_simpleexpr(const char *p) normalize_name(lbuf->ptr, "\r\n\t "); } + for(cursor = 0; cursor < sbuf->pos; cursor++) { + if( sbuf->ptr[cursor] == '"' ) + script_string_buf_addb(ubuf, '\\'); + script_string_buf_addb(ubuf, sbuf->ptr[cursor]); + } + script_string_buf_addb(ubuf, 0); + fprintf(script->lang_export_fp, "#: %s\n" "# %s\n" "msgctxt \"%s\"\n" @@ -1327,10 +1334,11 @@ const char* parse_simpleexpr(const char *p) script->parser_current_file ? script->parser_current_file : "Unknown File", lbuf->ptr, script->parser_current_npc_name ? script->parser_current_npc_name : "Unknown NPC", - sbuf->ptr + ubuf->ptr ); lbuf->pos = 0; + ubuf->pos = 0; } sbuf->pos = 0; @@ -2427,9 +2435,11 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o script->syntax.translation_db = strdb_get(script->translation_db, script->parser_current_npc_name); } - script->buf=(unsigned char *)aMalloc(SCRIPT_BLOCK_SIZE*sizeof(unsigned char)); + if( !script->buf ) { + script->buf = (unsigned char *)aMalloc(SCRIPT_BLOCK_SIZE*sizeof(unsigned char)); + script->size = SCRIPT_BLOCK_SIZE; + } script->pos=0; - script->size=SCRIPT_BLOCK_SIZE; script->parse_nextline(true, NULL); // who called parse_script is responsible for clearing the database after using it, but just in case... lets clear it here @@ -2443,10 +2453,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o if( script->error_report ) script->error(src,file,line,script->error_msg,script->error_pos); aFree( script->error_msg ); - aFree( script->buf ); script->pos = 0; - script->size = 0; - script->buf = NULL; for(i=LABEL_START;i<script->str_num;i++) if(script->str_data[i].type == C_NOP) script->str_data[i].type = C_NAME; for(i=0; i<size; i++) @@ -2468,10 +2475,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o {// does not require brackets around the script if( *p == '\0' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT) ) {// empty script and can return NULL - aFree( script->buf ); script->pos = 0; - script->size = 0; - script->buf = NULL; #ifdef ENABLE_CASE_CHECK script->local_casecheck.clear(); script->parser_current_src = NULL; @@ -2491,10 +2495,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o p = script->skip_space(p+1); if( *p == '}' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT) ) {// empty script and can return NULL - aFree( script->buf ); script->pos = 0; - script->size = 0; - script->buf = NULL; #ifdef ENABLE_CASE_CHECK script->local_casecheck.clear(); script->parser_current_src = NULL; @@ -2543,10 +2544,6 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o script->addc(C_NOP); - // trim code to size - script->size = script->pos; - RECREATE(script->buf,unsigned char,script->pos); - // default unknown references to variables for (i = LABEL_START; i < script->str_num; i++) { if (script->str_data[i].type == C_NOP) { @@ -2611,8 +2608,9 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o #endif CREATE(code,struct script_code,1); - code->script_buf = script->buf; - code->script_size = script->size; + code->script_buf = (unsigned char *)aMalloc(script->pos*sizeof(unsigned char)); + memcpy(code->script_buf, script->buf, script->pos); + code->script_size = script->pos; code->local.vars = NULL; code->local.arrays = NULL; #ifdef ENABLE_CASE_CHECK @@ -3397,15 +3395,13 @@ void script_free_code(struct script_code* code) { nullpo_retv(code); - if( code->instances ) + if (code->instances) script->stop_instances(code); - else { - script->free_vars(code->local.vars); - if( code->local.arrays ) - code->local.arrays->destroy(code->local.arrays,script->array_free_db); - } - aFree( code->script_buf ); - aFree( code ); + script->free_vars(code->local.vars); + if (code->local.arrays) + code->local.arrays->destroy(code->local.arrays,script->array_free_db); + aFree(code->script_buf); + aFree(code); } /// Creates a new script state. @@ -4682,6 +4678,9 @@ void script_load_translations(void) { int i, size; uint32 total = 0; uint8 lang_id = 0, k; + + if (map->minimal) // No translations in minimal mode + return; script->translation_db = strdb_alloc(DB_OPT_DUP_KEY, NAME_LENGTH*2+1); @@ -4815,6 +4814,7 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) { continue; if( strncasecmp(line,"msgctxt \"", 9) == 0 ) { + msgctxt[0] = '\0'; for(i = 9; i < len - 2; i++) { if( line[i] == '\\' && line[i+1] == '"' ) { msgctxt[cursor] = '"'; @@ -4826,6 +4826,7 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) { } msgctxt[cursor] = '\0'; } else if ( strncasecmp(line, "msgid \"", 7) == 0 ) { + msgid.pos = 0; for(i = 7; i < len - 2; i++) { if( line[i] == '\\' && line[i+1] == '"' ) { script_string_buf_addb(&msgid, '"'); @@ -4835,6 +4836,7 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) { } script_string_buf_addb(&msgid,0); } else if ( len > 9 && line[9] != '"' && strncasecmp(line, "msgstr \"",8) == 0 ) { + msgstr.pos = 0; for(i = 8; i < len - 2; i++) { if( line[i] == '\\' && line[i+1] == '"' ) { script_string_buf_addb(&msgstr, '"'); @@ -4886,7 +4888,6 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) { st->translations++; st->len += inner_len; } - msgctxt[0] = '\0'; msgid.pos = msgstr.pos = 0; translations++; @@ -4967,6 +4968,13 @@ int script_translation_db_destroyer(DBKey key, DBData *data, va_list ap) { * **/ void script_parser_clean_leftovers(void) { + + if( script->buf ) + aFree(script->buf); + + script->buf = NULL; + script->size = 0; + if( script->translation_db ) { script->translation_db->destroy(script->translation_db,script->translation_db_destroyer); script->translation_db = NULL; @@ -4979,6 +4987,7 @@ void script_parser_clean_leftovers(void) { script_string_buf_destroy(&script->parse_simpleexpr_str); script_string_buf_destroy(&script->lang_export_line_buf); + script_string_buf_destroy(&script->lang_export_unescaped_buf); } /** @@ -5672,6 +5681,13 @@ BUILDIN(getarg) /// return; /// return <value>; BUILDIN(return) { + st->state = RETFUNC; + + if( st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp-1].type != C_RETINFO ) { + // Incorrect usage of return outside the scope of a function or subroutine. + return true; // No need for further processing, running script is about to be aborted. + } + if( script_hasdata(st,2) ) {// return value struct script_data* data; @@ -5685,16 +5701,19 @@ BUILDIN(return) { script->get_val(st, data);// current scope, convert to value if( data->ref && data->ref->vars == st->stack->stack_data[st->stack->defsp-1].u.ri->scope.vars ) data->ref = NULL; // Reference to the parent scope, remove reference pointer - } else if( name[0] == '.' && !data->ref ) { - // script variable without a reference set, link to current script - data->ref = (struct reg_db *)aCalloc(sizeof(struct reg_db), 1); - script->add_pending_ref(st, data->ref); - data->ref->vars = st->script->local.vars; - if( !st->script->local.arrays ) - st->script->local.arrays = idb_alloc(DB_OPT_BASE); - data->ref->arrays = st->script->local.arrays; - } else if ( name[0] == '.' /* && data->ref != NULL */ ) { - data->ref = NULL; // Reference to the parent scope's script, remove reference pointer. + } else if( name[0] == '.' ) { + // npc variable + if( !data->ref ) { + // npc variable without a reference set, link to current script + data->ref = (struct reg_db *)aCalloc(sizeof(struct reg_db), 1); + script->add_pending_ref(st, data->ref); + data->ref->vars = st->script->local.vars; + if( !st->script->local.arrays ) + st->script->local.arrays = idb_alloc(DB_OPT_BASE); + data->ref->arrays = st->script->local.arrays; + } else if( data->ref->vars == st->stack->stack_data[st->stack->defsp-1].u.ri->script->local.vars ) { + data->ref = NULL; // Reference to the parent scope's script, remove reference pointer. + } } } } @@ -5702,7 +5721,7 @@ BUILDIN(return) { {// no return value script_pushnil(st); } - st->state = RETFUNC; + return true; } @@ -5744,6 +5763,7 @@ BUILDIN(warp) { int ret; int x,y; + int warp_clean = 1; const char* str; TBL_PC* sd; @@ -5755,6 +5775,11 @@ BUILDIN(warp) x = script_getnum(st,3); y = script_getnum(st,4); + if (script_hasdata(st, 5)) { + warp_clean = script_getnum(st, 5); + } + + sd->state.warp_clean = warp_clean; if(strcmp(str,"Random")==0) ret = pc->randomwarp(sd,CLR_TELEPORT); else if(strcmp(str,"SavePoint")==0 || strcmp(str,"Save")==0) @@ -7424,7 +7449,7 @@ void buildin_delitem_delete(struct map_session_data* sd, int idx, int* amount, b {// delete associated pet intif->delete_petdata(MakeDWord(inv->card[1], inv->card[2])); } - pc->delitem(sd, idx, delamount, 0, 0, LOG_TYPE_SCRIPT); + pc->delitem(sd, idx, delamount, 0, DELITEM_NORMAL, LOG_TYPE_SCRIPT); } amount[0]-= delamount; @@ -8085,6 +8110,23 @@ BUILDIN(strnpcinfo) { return true; } +/** + * charid2rid: Returns the RID associated to the given character ID + */ +BUILDIN(charid2rid) +{ + int cid = script_getnum(st, 2); + TBL_PC *sd = map->charid2sd(cid); + + if (sd == NULL) { + script_pushint(st, 0); + return true; + } + + script_pushint(st, sd->status.account_id); + return true; +} + /*========================================== * GetEquipID(Pos); Pos: 1-SCRIPT_EQUIP_TABLE_SIZE *------------------------------------------*/ @@ -8455,10 +8497,10 @@ BUILDIN(successrefitem) sd->status.inventory[i].refine += up; sd->status.inventory[i].refine = cap_value( sd->status.inventory[i].refine, 0, MAX_REFINE); - pc->unequipitem(sd,i,2); // status calc will happen in pc->equipitem() below + pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); // status calc will happen in pc->equipitem() below clif->refine(sd->fd,0,i,sd->status.inventory[i].refine); - clif->delitem(sd,i,1,3); + clif->delitem(sd, i, 1, DELITEM_MATERIALCHANGE); //Logs items, got from (N)PC scripts [Lupus] logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i],sd->inventory_data[i]); @@ -8504,10 +8546,10 @@ BUILDIN(failedrefitem) i=pc->checkequip(sd,script->equip[num-1]); if(i >= 0) { sd->status.inventory[i].refine = 0; - pc->unequipitem(sd,i,3); //recalculate bonus + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); //recalculate bonus clif->refine(sd->fd,1,i,sd->status.inventory[i].refine); //notify client of failure - pc->delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); + pc->delitem(sd, i, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT); clif->misceffect(&sd->bl,2); // display failure effect } @@ -8538,12 +8580,12 @@ BUILDIN(downrefitem) //Logs items, got from (N)PC scripts [Lupus] logs->pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i],sd->inventory_data[i]); - pc->unequipitem(sd,i,2); // status calc will happen in pc->equipitem() below + pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); // status calc will happen in pc->equipitem() below sd->status.inventory[i].refine -= down; sd->status.inventory[i].refine = cap_value( sd->status.inventory[i].refine, 0, MAX_REFINE); clif->refine(sd->fd,2,i,sd->status.inventory[i].refine); - clif->delitem(sd,i,1,3); + clif->delitem(sd, i, 1, DELITEM_MATERIALCHANGE); //Logs items, got from (N)PC scripts [Lupus] logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i],sd->inventory_data[i]); @@ -8572,8 +8614,8 @@ BUILDIN(delequip) if (num > 0 && num <= ARRAYLENGTH(script->equip)) i=pc->checkequip(sd,script->equip[num-1]); if(i >= 0) { - pc->unequipitem(sd,i,3); //recalculate bonus - pc->delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); //recalculate bonus + pc->delitem(sd, i, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT); return true; } @@ -8829,7 +8871,7 @@ BUILDIN(autobonus3) { BUILDIN(skill) { int id; int level; - int flag = 1; + int flag = SKILL_GRANT_TEMPORARY; TBL_PC* sd; sd = script->rid2sd(st); @@ -8857,7 +8899,7 @@ BUILDIN(skill) { BUILDIN(addtoskill) { int id; int level; - int flag = 2; + int flag = SKILL_GRANT_TEMPSTACK; TBL_PC* sd; sd = script->rid2sd(st); @@ -9702,8 +9744,7 @@ BUILDIN(monster) if (script_hasdata(st, 10)) { ai = script_getnum(st, 10); - if (ai > 4) - { + if (ai > AI_FLORA) { ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_); return false; } @@ -9807,7 +9848,7 @@ BUILDIN(areamonster) { if (script_hasdata(st, 12)) { ai = script_getnum(st, 12); - if (ai > 4) { + if (ai > AI_FLORA) { ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_); return false; } @@ -10977,7 +11018,7 @@ BUILDIN(homunculus_mutate) if (m_class == HT_EVO && m_id == HT_S && sd->hd->homunculus.level >= 99 && i != INDEX_NOT_FOUND && - !pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_SCRIPT) ) { + !pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_SCRIPT) ) { sd->hd->homunculus.vaporize = HOM_ST_REST; // Remove morph state. homun->call(sd); // Respawn homunculus. homun->mutate(sd->hd, homun_id); @@ -11158,26 +11199,24 @@ BUILDIN(resetstatus) /*========================================== * script command resetskill *------------------------------------------*/ -BUILDIN(resetskill) -{ +BUILDIN(resetskill) { TBL_PC *sd; sd=script->rid2sd(st); if( sd == NULL ) return false; - pc->resetskill(sd,1); + pc->resetskill(sd, PCRESETSKILL_RESYNC); return true; } /*========================================== * Counts total amount of skill points. *------------------------------------------*/ -BUILDIN(skillpointcount) -{ +BUILDIN(skillpointcount) { TBL_PC *sd; sd=script->rid2sd(st); if( sd == NULL ) return false; - script_pushint(st,sd->status.skill_point + pc->resetskill(sd,2)); + script_pushint(st,sd->status.skill_point + pc->resetskill(sd, PCRESETSKILL_RECOUNT)); return true; } @@ -11219,10 +11258,10 @@ static TBL_PC *prepareChangeSex(struct script_state* st) if (sd == NULL) return NULL; - pc->resetskill(sd, 4); + pc->resetskill(sd, PCRESETSKILL_CHSEX); // to avoid any problem with equipment and invalid sex, equipment is unequiped. for (i=0; i<EQI_MAX; i++) - if (sd->equip_index[i] >= 0) pc->unequipitem(sd, sd->equip_index[i], 3); + if (sd->equip_index[i] >= 0) pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); return sd; } @@ -11234,7 +11273,7 @@ BUILDIN(changesex) TBL_PC *sd = prepareChangeSex(st); if (sd == NULL) return false; - chrif->changesex(sd); + chrif->changesex(sd, true); return true; } @@ -11246,12 +11285,7 @@ BUILDIN(changecharsex) TBL_PC *sd = prepareChangeSex(st); if (sd == NULL) return false; - if (sd->status.sex == 99) - sd->status.sex = 0; - sd->status.sex = sd->status.sex ? 0 : 1; - chrif->save(sd, 0); - if (sd->fd) - clif->authfail_fd(sd->fd, 15); + chrif->changesex(sd, false); return true; } @@ -12280,7 +12314,7 @@ BUILDIN(successremovecards) for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++) item_tmp.card[j]=sd->status.inventory[i].card[j]; - pc->delitem(sd,i,1,0,3,LOG_TYPE_SCRIPT); + pc->delitem(sd, i, 1, 0, DELITEM_MATERIALCHANGE, LOG_TYPE_SCRIPT); if ((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) { //chk if can be spawn in inventory otherwise put on floor clif->additem(sd,0,0,flag); @@ -12342,7 +12376,7 @@ BUILDIN(failedremovecards) if (cardflag == 1) { if (typefail == 0 || typefail == 2) { // destroy the item - pc->delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); + pc->delitem(sd, i, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT); } else if (typefail == 1) { // destroy the card int flag, j; @@ -12360,7 +12394,7 @@ BUILDIN(failedremovecards) for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++) item_tmp.card[j]=sd->status.inventory[i].card[j]; - pc->delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); + pc->delitem(sd, i, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT); if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) { clif->additem(sd,0,0,flag); @@ -13054,7 +13088,7 @@ BUILDIN(clearitem) if(sd==NULL) return true; for (i=0; i<MAX_INVENTORY; i++) { if (sd->status.inventory[i].amount) { - pc->delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_SCRIPT); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_SCRIPT); } } return true; @@ -13483,7 +13517,7 @@ BUILDIN(nude) if( sd->equip_index[ i ] >= 0 ) { if( !calcflag ) calcflag = 1; - pc->unequipitem( sd , sd->equip_index[ i ] , 2); + pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE); } } @@ -13830,7 +13864,7 @@ BUILDIN(npcstop) { if( nd ) { unit->bl2ud2(&nd->bl); // ensure nd->ud is safe to edit - unit->stop_walking(&nd->bl,1|4); + unit->stop_walking(&nd->bl, STOPWALKING_FLAG_FIXPOS|STOPWALKING_FLAG_NEXTCELL); } return true; @@ -14240,11 +14274,6 @@ BUILDIN(isnight) { return true; } -BUILDIN(isday) { - script_pushint(st,(map->night_flag == 0)); - return true; -} - /*================================================ * Check how many items/cards in the list are * equipped - used for 2/15's cards patch [celest] @@ -14460,7 +14489,7 @@ BUILDIN(unequip) if (sd != NULL && num >= 1 && num <= ARRAYLENGTH(script->equip)) { int i = pc->checkequip(sd,script->equip[num-1]); if (i >= 0) - pc->unequipitem(sd,i,1|2); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } return true; } @@ -15466,8 +15495,26 @@ BUILDIN(compare) return true; } -// [zBuffer] List of mathematics commands ---> -BUILDIN(sqrt) +BUILDIN(strcmp) +{ + const char *str1 = script_getstr(st,2); + const char *str2 = script_getstr(st,3); + script_pushint(st,strcmp(str1, str2)); + return true; +} + +// List of mathematics commands ---> + +BUILDIN(log10) +{ + double i, a; + i = script_getnum(st,2); + a = log10(i); + script_pushint(st,(int)a); + return true; +} + +BUILDIN(sqrt) //[zBuffer] { double i, a; i = script_getnum(st,2); @@ -15476,7 +15523,7 @@ BUILDIN(sqrt) return true; } -BUILDIN(pow) +BUILDIN(pow) //[zBuffer] { double i, a, b; a = script_getnum(st,2); @@ -15486,7 +15533,7 @@ BUILDIN(pow) return true; } -BUILDIN(distance) +BUILDIN(distance) //[zBuffer] { int x0, y0, x1, y1; @@ -15499,7 +15546,7 @@ BUILDIN(distance) return true; } -// <--- [zBuffer] List of mathematics commands +// <--- List of mathematics commands BUILDIN(min) { @@ -16432,7 +16479,7 @@ BUILDIN(unitstop) { if( bl != NULL ) { unit->bl2ud2(bl); // ensure ((TBL_NPC*)bl)->ud is safe to edit unit->stop_attack(bl); - unit->stop_walking(bl,4); + unit->stop_walking(bl, STOPWALKING_FLAG_NEXTCELL); if( bl->type == BL_MOB ) ((TBL_MOB*)bl)->target_id = 0; } @@ -17136,18 +17183,27 @@ BUILDIN(changequest) { BUILDIN(questactive) { struct map_session_data *sd = script->rid2sd(st); - int quest_progress = 0; + int qid, i; - if (sd == NULL) + if (sd == NULL) { + ShowError("questactive: no player attached!"); return false; + } + + qid = script_getnum(st, 2); + + ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == qid ); + + if( i >= sd->avail_quests ) { + script_pushint(st, 0); + return true; + } - if (quest->check(sd, script_getnum(st, 2), HAVEQUEST) == Q_ACTIVE) + if(sd->quest_log[i].state == Q_ACTIVE) script_pushint(st, 1); else script_pushint(st, 0); - script_pushint(st, quest_progress); - return true; } @@ -17251,7 +17307,9 @@ BUILDIN(waitingroom2bg) { return true; } + Assert_retr(false, cd->users < MAX_CHAT_USERS); n = cd->users; // This is always < MAX_CHAT_USERS + for (i = 0; i < n && i < MAX_BG_MEMBERS; i++) { struct map_session_data *sd = cd->usersd[i]; if (sd != NULL && bg->team_join(bg_id, sd)) @@ -17356,7 +17414,7 @@ BUILDIN(bg_monster_set_team) { md->bg_id = bg_id; mob_stop_attack(md); - mob_stop_walking(md, 0); + mob_stop_walking(md, STOPWALKING_FLAG_NONE); md->target_id = md->attacked_id = 0; clif->charnameack(0, &md->bl); @@ -18158,7 +18216,7 @@ BUILDIN(setcashmount) if ((sd = script->rid2sd(st)) == NULL) return true; if (pc_hasmount(sd)) { - clif->msgtable(sd->fd, 0X78b); + clif->msgtable(sd, MSG_REINS_CANT_USE_MOUNTED); script_pushint(st,0);//can't mount with one of these } else { if (sd->sc.data[SC_ALL_RIDING]) @@ -19617,6 +19675,48 @@ BUILDIN(channelmes) return true; } + +/** By Cydh +Display script message +showscript "<message>"{,<GID>}; +*/ +BUILDIN(showscript) { + struct block_list *bl = NULL; + const char *msg = script_getstr(st, 2); + int id = 0; + + if (script_hasdata(st, 3)) { + id = script_getnum(st, 3); + bl = map->id2bl(id); + } + else { + bl = st->rid ? map->id2bl(st->rid) : map->id2bl(st->oid); + } + + if (!bl) { + ShowError("buildin_showscript: Script not attached. (id=%d, rid=%d, oid=%d)\n", id, st->rid, st->oid); + script_pushint(st, 0); + return false; + } + + clif->ShowScript(bl, msg); + + script_pushint(st, 1); + + return true; +} + +BUILDIN(mergeitem) +{ + struct map_session_data *sd = script->rid2sd(st); + + if (sd == NULL) + return true; + + clif->openmergeitem(sd->fd, sd); + + return true; +} /** place holder for the translation macro **/ BUILDIN(_) { return true; @@ -19761,7 +19861,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(jobchange,"i?"), BUILDIN_DEF(jobname,"i"), BUILDIN_DEF(input,"r??"), - BUILDIN_DEF(warp,"sii"), + BUILDIN_DEF(warp,"sii?"), BUILDIN_DEF(areawarp,"siiiisii??"), BUILDIN_DEF(warpchar,"siii"), // [LuzZza] BUILDIN_DEF(warpparty,"siii?"), // [Fredzilla] [Paradox924X] @@ -19807,6 +19907,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(getguildmember,"i?"), BUILDIN_DEF(strcharinfo,"i"), BUILDIN_DEF(strnpcinfo,"i"), + BUILDIN_DEF(charid2rid,"i"), BUILDIN_DEF(getequipid,"i"), BUILDIN_DEF(getequipname,"i"), BUILDIN_DEF(getbrokenid,"i"), // [Valaris] @@ -19997,7 +20098,6 @@ void script_parse_builtin(void) { BUILDIN_DEF(logmes,"s"), //this command actls as MES but rints info into LOG file either SQL/TXT [Lupus] BUILDIN_DEF(summon,"si??"), // summons a slave monster [Celest] BUILDIN_DEF(isnight,""), // check whether it is night time [Celest] - BUILDIN_DEF_DEPRECATED(isday,""), // check whether it is day time [Celest] // DEPRECATED 2015-01-21 [Haru] BUILDIN_DEF(isequipped,"i*"), // check whether another item/card has been equipped [Celest] BUILDIN_DEF(isequippedcnt,"i*"), // check how many items/cards are being equipped [Celest] BUILDIN_DEF(cardscnt,"i*"), // check how many items/cards are being equipped in the same arm [Lupus] @@ -20040,14 +20140,16 @@ void script_parse_builtin(void) { BUILDIN_DEF(countstr,"ss?"), BUILDIN_DEF(setnpcdisplay,"sv??"), BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine. + BUILDIN_DEF(strcmp,"ss"), BUILDIN_DEF(getiteminfo,"ii"), //[Lupus] returns Items Buy / sell Price, etc info BUILDIN_DEF(setiteminfo,"iii"), //[Lupus] set Items Buy / sell Price, etc info BUILDIN_DEF(getequipcardid,"ii"), //[Lupus] returns CARD ID or other info from CARD slot N of equipped item - // [zBuffer] List of mathematics commands ---> - BUILDIN_DEF(sqrt,"i"), - BUILDIN_DEF(pow,"ii"), - BUILDIN_DEF(distance,"iiii"), - // <--- [zBuffer] List of mathematics commands + // List of mathematics commands ---> + BUILDIN_DEF(log10,"i"), + BUILDIN_DEF(sqrt,"i"), //[zBuffer] + BUILDIN_DEF(pow,"ii"), //[zBuffer] + BUILDIN_DEF(distance,"iiii"), //[zBuffer] + // <--- List of mathematics commands BUILDIN_DEF(min, "i*"), BUILDIN_DEF(max, "i*"), BUILDIN_DEF(md5,"s"), @@ -20175,7 +20277,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(makerune,"i"), BUILDIN_DEF(hascashmount,""),//[Ind] BUILDIN_DEF(setcashmount,""),//[Ind] - BUILDIN_DEF(checkre,"i"), + BUILDIN_DEF_DEPRECATED(checkre,"i"), // Deprecated 2015-05-08 [Haru] /** * rAthena and beyond! **/ @@ -20252,6 +20354,8 @@ void script_parse_builtin(void) { BUILDIN_DEF(shopcount, "i"), BUILDIN_DEF(channelmes, "ss"), + BUILDIN_DEF(showscript, "s?"), + BUILDIN_DEF(mergeitem,""), BUILDIN_DEF(_,"s"), }; int i, len = ARRAYLENGTH(BUILDIN); @@ -20357,6 +20461,43 @@ void script_hardcoded_constants(void) { script->set_constant("BG_AREA",BG_AREA,false); script->set_constant("BG_AREA_WOS",BG_AREA_WOS,false); script->set_constant("BG_QUEUE",BG_QUEUE,false); + + /* Renewal */ +#ifdef RENEWAL + script->set_constant("RENEWAL", 1, false); +#else + script->set_constant("RENEWAL", 0, false); +#endif +#ifdef RENEWAL_CAST + script->set_constant("RENEWAL_CAST", 1, false); +#else + script->set_constant("RENEWAL_CAST", 0, false); +#endif +#ifdef RENEWAL_DROP + script->set_constant("RENEWAL_DROP", 1, false); +#else + script->set_constant("RENEWAL_DROP", 0, false); +#endif +#ifdef RENEWAL_EXP + script->set_constant("RENEWAL_EXP", 1, false); +#else + script->set_constant("RENEWAL_EXP", 0, false); +#endif +#ifdef RENEWAL_LVDMG + script->set_constant("RENEWAL_LVDMG", 1, false); +#else + script->set_constant("RENEWAL_LVDMG", 0, false); +#endif +#ifdef RENEWAL_EDP + script->set_constant("RENEWAL_EDP", 1, false); +#else + script->set_constant("RENEWAL_EDP", 0, false); +#endif +#ifdef RENEWAL_ASPD + script->set_constant("RENEWAL_ASPD", 1, false); +#else + script->set_constant("RENEWAL_ASPD", 0, false); +#endif } /** diff --git a/src/map/script.h b/src/map/script.h index 51bdf23b5..93d60f416 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -5,16 +5,16 @@ #ifndef MAP_SCRIPT_H #define MAP_SCRIPT_H +#include "map/map.h" //EVENT_NAME_LENGTH +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/mmo.h" // struct item +#include "common/sql.h" // Sql +#include "common/strlib.h" //StringBuf + #include <errno.h> #include <setjmp.h> -#include "map.h" //EVENT_NAME_LENGTH -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/mmo.h" // struct item -#include "../common/sql.h" // Sql -#include "../common/strlib.h" //StringBuf - /** * Declarations **/ @@ -605,6 +605,7 @@ struct script_interface { /* */ struct script_string_buf parse_simpleexpr_str; struct script_string_buf lang_export_line_buf; + struct script_string_buf lang_export_unescaped_buf; /* */ int parse_cleanup_timer_id; /* */ diff --git a/src/map/searchstore.c b/src/map/searchstore.c index 782c14987..b9e23ae82 100644 --- a/src/map/searchstore.c +++ b/src/map/searchstore.c @@ -4,15 +4,15 @@ #define HERCULES_CORE -#include "searchstore.h" // struct s_search_store_info - -#include "battle.h" // battle_config.* -#include "clif.h" // clif->open_search_store_info, clif->search_store_info_* -#include "pc.h" // struct map_session_data -#include "../common/cbasetypes.h" -#include "../common/malloc.h" // aMalloc, aRealloc, aFree -#include "../common/showmsg.h" // ShowError, ShowWarning -#include "../common/strlib.h" // safestrncpy +#include "searchstore.h" // struct s_search_store_info + +#include "map/battle.h" // battle_config.* +#include "map/clif.h" // clif-"open_search_store_info, clif-"search_store_info_* +#include "map/pc.h" // struct map_session_data +#include "common/cbasetypes.h" +#include "common/malloc.h" // aMalloc, aRealloc, aFree +#include "common/showmsg.h" // ShowError, ShowWarning +#include "common/strlib.h" // safestrncpy struct searchstore_interface searchstore_s; diff --git a/src/map/searchstore.h b/src/map/searchstore.h index 6664eddfa..2778740a5 100644 --- a/src/map/searchstore.h +++ b/src/map/searchstore.h @@ -5,11 +5,11 @@ #ifndef MAP_SEARCHSTORE_H #define MAP_SEARCHSTORE_H -#include <time.h> +#include "map/map.h" // MESSAGE_SIZE +#include "common/cbasetypes.h" +#include "common/mmo.h" // MAX_SLOTS -#include "map.h" // MESSAGE_SIZE -#include "../common/cbasetypes.h" -#include "../common/mmo.h" // MAX_SLOTS +#include <time.h> /** * Defines diff --git a/src/map/skill.c b/src/map/skill.c index 96ade3908..f2154aa22 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -4,47 +4,47 @@ #define HERCULES_CORE -#include "../config/core.h" // DBPATH, MAGIC_REFLECTION_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_CAST, VARCAST_REDUCTION() +#include "config/core.h" // DBPATH, MAGIC_REFLECTION_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_CAST, VARCAST_REDUCTION() #include "skill.h" +#include "map/battle.h" +#include "map/battleground.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/date.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/status.h" +#include "map/unit.h" +#include "common/cbasetypes.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> -#include "battle.h" -#include "battleground.h" -#include "chrif.h" -#include "clif.h" -#include "date.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "status.h" -#include "unit.h" -#include "../common/cbasetypes.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - #define SKILLUNITTIMER_INTERVAL 100 // ranges reserved for mapping skill ids to skilldb offsets @@ -62,6 +62,7 @@ #endif struct skill_interface skill_s; +struct s_skill_dbs skilldbs; //Since only mob-casted splash skills can hit ice-walls static inline int splash_target(struct block_list* bl) { @@ -99,7 +100,7 @@ int skill_get_index( uint16 skill_id ) { skill_id = MC_SKILLRANGEMIN + skill_id - MC_SKILLBASE; else if( skill_id >= HM_SKILLBASE ) skill_id = HM_SKILLRANGEMIN + skill_id - HM_SKILLBASE; - //[Ind/Hercules] GO GO GO LESS! - http://hercules.ws/board/topic/512-skill-id-processing-overhaul/ + //[Ind/Hercules] GO GO GO LESS! - http://herc.ws/board/topic/512-skill-id-processing-overhaul/ else if( skill_id > 1019 && skill_id < 8001 ) { if( skill_id < 2058 ) // 1020 - 2000 are empty skill_id = 1020 + skill_id - 2001; @@ -121,11 +122,11 @@ int skill_get_index( uint16 skill_id ) { } const char* skill_get_name( uint16 skill_id ) { - return skill->db[skill->get_index(skill_id)].name; + return skill->dbs->db[skill->get_index(skill_id)].name; } const char* skill_get_desc( uint16 skill_id ) { - return skill->db[skill->get_index(skill_id)].desc; + return skill->dbs->db[skill->get_index(skill_id)].desc; } // out of bounds error checking [celest] @@ -138,58 +139,58 @@ void skill_chk(uint16* skill_id) { skill->chk(&(id)); \ if(!(id)) return 0; \ if( (lv) > MAX_SKILL_LEVEL && (var) > 1 ) { \ - int lv2__ = (lv); (lv) = skill->db[(id)].max; \ + int lv2__ = (lv); (lv) = skill->dbs->db[(id)].max; \ return (var) + ((lv2__-(lv))/2);\ } \ return (var);\ } while(0) #define skill_glv(lv) min((lv),MAX_SKILL_LEVEL-1) // Skill DB -int skill_get_hit( uint16 skill_id ) { skill_get (skill->db[skill_id].hit, skill_id); } -int skill_get_inf( uint16 skill_id ) { skill_get (skill->db[skill_id].inf, skill_id); } -int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { skill_get (skill->db[skill_id].element[skill_glv(skill_lv-1)], skill_id); } -int skill_get_nk( uint16 skill_id ) { skill_get (skill->db[skill_id].nk, skill_id); } -int skill_get_max( uint16 skill_id ) { skill_get (skill->db[skill_id].max, skill_id); } -int skill_get_range( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill->db[skill_id].range[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { skill_get2 ( (skill->db[skill_id].splash[skill_glv(skill_lv-1)]>=0?skill->db[skill_id].splash[skill_glv(skill_lv-1)]:AREA_SIZE), skill_id, skill_lv); } -int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].hp[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].sp[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_hp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].hp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_sp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].sp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_state(uint16 skill_id) { skill_get (skill->db[skill_id].state, skill_id); } -int skill_get_spiritball(uint16 skill_id, uint16 skill_lv) { skill_get2 (skill->db[skill_id].spiritball[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_itemid(uint16 skill_id, int idx) { skill_get (skill->db[skill_id].itemid[idx], skill_id); } -int skill_get_itemqty(uint16 skill_id, int idx) { skill_get (skill->db[skill_id].amount[idx], skill_id); } -int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].zeny[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].num[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].cast[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].delay[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].walkdelay[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].upkeep_time[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].upkeep_time2[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_castdef( uint16 skill_id ) { skill_get (skill->db[skill_id].cast_def_rate, skill_id); } -int skill_get_weapontype( uint16 skill_id ) { skill_get (skill->db[skill_id].weapon, skill_id); } -int skill_get_ammotype( uint16 skill_id ) { skill_get (skill->db[skill_id].ammo, skill_id); } -int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].ammo_qty[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_inf2( uint16 skill_id ) { skill_get (skill->db[skill_id].inf2, skill_id); } -int skill_get_castcancel( uint16 skill_id ) { skill_get (skill->db[skill_id].castcancel, skill_id); } -int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].maxcount[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].blewcount[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].mhp[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].castnodex[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill->db[skill_id].delaynodex[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_type( uint16 skill_id ) { skill_get (skill->db[skill_id].skill_type, skill_id); } -int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get (skill->db[skill_id].unit_id[flag], skill_id); } -int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_interval, skill_id); } -int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].unit_range[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_unit_target( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_target&BCT_ALL, skill_id); } -int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_target&BL_ALL, skill_id); } -int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_flag, skill_id); } -int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill->db[skill_id].unit_layout_type[skill_glv(skill_lv-1)], skill_id, skill_lv); } -int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].cooldown[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_hit( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].hit, skill_id); } +int skill_get_inf( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].inf, skill_id); } +int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get (skill->dbs->db[skill_id].element[skill_glv(skill_lv-1)], skill_id); } +int skill_get_nk( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].nk, skill_id); } +int skill_get_max( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].max, skill_id); } +int skill_get_range( uint16 skill_id , uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].range[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 ( (skill->dbs->db[skill_id].splash[skill_glv(skill_lv-1)]>=0?skill->dbs->db[skill_id].splash[skill_glv(skill_lv-1)]:AREA_SIZE), skill_id, skill_lv); } +int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].hp[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].sp[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_hp_rate(uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].hp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_sp_rate(uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].sp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_state(uint16 skill_id) { skill_get (skill->dbs->db[skill_id].state, skill_id); } +int skill_get_spiritball(uint16 skill_id, uint16 skill_lv) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].spiritball[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_itemid(uint16 skill_id, int idx) { skill_get (skill->dbs->db[skill_id].itemid[idx], skill_id); } +int skill_get_itemqty(uint16 skill_id, int idx) { skill_get (skill->dbs->db[skill_id].amount[idx], skill_id); } +int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].zeny[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].num[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].cast[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].delay[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].walkdelay[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].upkeep_time[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].upkeep_time2[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_castdef( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].cast_def_rate, skill_id); } +int skill_get_weapontype( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].weapon, skill_id); } +int skill_get_ammotype( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].ammo, skill_id); } +int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].ammo_qty[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_inf2( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].inf2, skill_id); } +int skill_get_castcancel( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].castcancel, skill_id); } +int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].maxcount[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].blewcount[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].mhp[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].castnodex[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].delaynodex[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_type( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].skill_type, skill_id); } +int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get (skill->dbs->db[skill_id].unit_id[flag], skill_id); } +int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].unit_interval, skill_id); } +int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].unit_range[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_unit_target( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].unit_target&BCT_ALL, skill_id); } +int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].unit_target&BL_ALL, skill_id); } +int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill->dbs->db[skill_id].unit_flag, skill_id); } +int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].unit_layout_type[skill_glv(skill_lv-1)], skill_id, skill_lv); } +int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].cooldown[skill_glv(skill_lv-1)], skill_id, skill_lv); } int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ) { #ifdef RENEWAL_CAST - skill_get2 (skill->db[skill_id].fixed_cast[skill_glv(skill_lv-1)], skill_id, skill_lv); + Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].fixed_cast[skill_glv(skill_lv-1)], skill_id, skill_lv); #else return 0; #endif @@ -223,17 +224,17 @@ int skill_get_casttype (uint16 skill_id) { } int skill_get_casttype2 (uint16 index) { - int inf = skill->db[index].inf; + int inf = skill->dbs->db[index].inf; if (inf&(INF_GROUND_SKILL)) return CAST_GROUND; if (inf&INF_SUPPORT_SKILL) return CAST_NODAMAGE; if (inf&INF_SELF_SKILL) { - if(skill->db[index].inf2&INF2_NO_TARGET_SELF) + if(skill->dbs->db[index].inf2&INF2_NO_TARGET_SELF) return CAST_DAMAGE; //Combo skill. return CAST_NODAMAGE; } - if (skill->db[index].nk&NK_NO_DAMAGE) + if (skill->dbs->db[index].nk&NK_NO_DAMAGE) return CAST_NODAMAGE; return CAST_DAMAGE; } @@ -438,7 +439,7 @@ int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* b if( !(sd->sc.data[SC__REPRODUCE]) && ((skill_id >= RK_ENCHANTBLADE && skill_id <= LG_OVERBRAND_PLUSATK) || (skill_id >= RL_GLITTERING_GREED && skill_id <= OB_AKAITSUKI) || (skill_id >= GC_DARKCROW && skill_id <= NC_MAGMA_ERUPTION_DOTDAMAGE))) return 0; // Reproduce will only copy skills according on the list. [Jobbie] - else if( sd->sc.data[SC__REPRODUCE] && !skill->reproduce_db[skill->get_index(skill_id)] ) + else if( sd->sc.data[SC__REPRODUCE] && !skill->dbs->reproduce_db[skill->get_index(skill_id)] ) return 0; return 1; @@ -619,19 +620,19 @@ struct s_skill_unit_layout* skill_get_unit_layout (uint16 skill_id, uint16 skill } if (pos != -1) // simple single-definition layout - return &skill->unit_layout[pos]; + return &skill->dbs->unit_layout[pos]; dir = (src->x == x && src->y == y) ? 6 : map->calc_dir(src,x,y); // 6 - default aegis direction if (skill_id == MG_FIREWALL) - return &skill->unit_layout [skill->firewall_unit_pos + dir]; + return &skill->dbs->unit_layout [skill->firewall_unit_pos + dir]; else if (skill_id == WZ_ICEWALL) - return &skill->unit_layout [skill->icewall_unit_pos + dir]; + return &skill->dbs->unit_layout [skill->icewall_unit_pos + dir]; else if( skill_id == WL_EARTHSTRAIN ) //Warlock - return &skill->unit_layout [skill->earthstrain_unit_pos + dir]; + return &skill->dbs->unit_layout [skill->earthstrain_unit_pos + dir]; ShowError("skill_get_unit_layout: unknown unit layout for skill %d (level %d)\n", skill_id, skill_lv); - return &skill->unit_layout[0]; // default 1x1 layout + return &skill->dbs->unit_layout[0]; // default 1x1 layout } /*========================================== @@ -671,7 +672,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 if( skill_id != WS_CARTTERMINATION && skill_id != AM_DEMONSTRATION && skill_id != CR_REFLECTSHIELD && skill_id != MS_REFLECTSHIELD && skill_id != ASC_BREAKER ) { // Trigger status effects enum sc_type type; - int i; + int i, flag; for( i = 0; i < ARRAYLENGTH(sd->addeff) && sd->addeff[i].flag; i++ ) { rate = sd->addeff[i].rate; if( attack_type&BF_LONG ) // Any ranged physical attack takes status arrows into account (Grimtooth...) [DracoRPG] @@ -695,13 +696,22 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 } type = sd->addeff[i].id; - temp = skill->get_time2(status->sc2skill(type),7); + + if (sd->addeff[i].duration > 0) { + // Fixed duration + temp = sd->addeff[i].duration; + flag = SCFLAG_FIXEDRATE|SCFLAG_FIXEDTICK; + } else { + // Default duration + temp = skill->get_time2(status->sc2skill(type),7); + flag = SCFLAG_NONE; + } if (sd->addeff[i].flag&ATF_TARGET) - status->change_start(src,bl,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,SCFLAG_NONE); + status->change_start(src,bl,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,flag); if (sd->addeff[i].flag&ATF_SELF) - status->change_start(src,src,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,SCFLAG_NONE); + status->change_start(src,src,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,flag); } } @@ -912,9 +922,11 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 break; case AM_ACIDTERROR: - sc_start2(src,bl,SC_BLOODING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); - if (skill->break_equip(bl, EQP_ARMOR, 100*skill->get_time(skill_id,skill_lv), BCT_ENEMY)) - clif->emotion(bl,E_OMG); + sc_start2(src, bl, SC_BLOODING, (skill_lv * 3), skill_lv, src->id, skill->get_time2(skill_id, skill_lv)); + if ( bl->type == BL_PC && rnd() % 1000 < 10 * skill->get_time(skill_id, skill_lv) ) { + skill->break_equip(bl, EQP_ARMOR, 10000, BCT_ENEMY); + clif->emotion(bl, E_OMG); // emote icon still shows even there is no armor equip. + } break; case AM_DEMONSTRATION: @@ -1356,7 +1368,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 break; } - if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai) { + if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai != AI_NONE) { //Pass heritage to Master for status causing effects. [Skotlex] sd = map->id2sd(md->master_id); src = sd?&sd->bl:src; @@ -2002,7 +2014,7 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in } if (flag) { sd->status.inventory[j].attribute = 1; - pc->unequipitem(sd, j, 3); + pc->unequipitem(sd, j, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } } clif->equiplist(sd); @@ -2194,7 +2206,12 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr //Trick Dead protects you from damage, but not from buffs and the like, hence it's placed here. if (sc && sc->data[SC_TRICKDEAD]) return 0; - + if ( skill_id != HW_GRAVITATION ) { + struct status_change *csc = status->get_sc(src); + if(csc && csc->data[SC_GRAVITATION] && csc->data[SC_GRAVITATION]->val3 == BCT_SELF ) + return 0; + } + dmg = battle->calc_attack(attack_type,src,bl,skill_id,skill_lv,flag&0xFFF); //Skotlex: Adjusted to the new system @@ -2213,9 +2230,11 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr } } - if( dmg.flag&BF_MAGIC && ( (battle_config.eq_single_target_reflectable && (flag&0xFFF) == 1) ) ) { + if( dmg.flag&BF_MAGIC + && (skill_id != NPC_EARTHQUAKE || (battle_config.eq_single_target_reflectable && (flag & 0xFFF) == 1)) ) { /* Need more info cause NPC_EARTHQUAKE is ground type */ // Earthquake on multiple targets is not counted as a target skill. [Inkfish] - if( (dmg.damage || dmg.damage2) && (type = skill->magic_reflect(src, bl, src==dsrc)) ) { + int reflecttype; + if( (dmg.damage || dmg.damage2) && (reflecttype = skill->magic_reflect(src, bl, src==dsrc)) ) { //Magic reflection, switch caster/target struct block_list *tbl = bl; rmdamage = true; @@ -2232,17 +2251,17 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr /* bugreport:7859 magical reflected zeroes blow count */ dmg.blewcount = 0; //Spirit of Wizard blocks Kaite's reflection - if (type == 2 && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_WIZARD) { + if (reflecttype == 2 && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_WIZARD) { //Consume one Fragment per hit of the casted skill? [Skotlex] - type = tsd ? pc->search_inventory(tsd, ITEMID_FRAGMENT_OF_CRYSTAL) : 0; - if (type != INDEX_NOT_FOUND) { - if ( tsd ) pc->delitem(tsd, type, 1, 0, 1, LOG_TYPE_CONSUME); + int consumeitem = tsd ? pc->search_inventory(tsd, ITEMID_FRAGMENT_OF_CRYSTAL) : 0; + if (consumeitem != INDEX_NOT_FOUND) { + if ( tsd ) pc->delitem(tsd, consumeitem, 1, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); dmg.damage = dmg.damage2 = 0; dmg.dmg_lv = ATK_MISS; sc->data[SC_SOULLINK]->val3 = skill_id; sc->data[SC_SOULLINK]->val4 = dsrc->id; } - } else if( type != 2 ) /* Kaite bypasses */ + } else if( reflecttype != 2 ) /* Kaite bypasses */ additional_effects = false; /** @@ -2255,7 +2274,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr #else // issue:6415 in pre-renewal Kaite reflected the entire damage received // regardless of caster's equipment (Aegis 11.1) - if( dmg.dmg_lv != ATK_MISS && type == 1 ) //Wiz SL canceled and consumed fragment + if( dmg.dmg_lv != ATK_MISS && reflecttype == 1 ) //Wiz SL canceled and consumed fragment #endif { short s_ele = skill->get_ele(skill_id, skill_lv); @@ -2303,14 +2322,13 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr if( damage && sc && sc->data[SC_GENSOU] && dmg.flag&BF_MAGIC ){ struct block_list *nbl; nbl = battle->get_enemy_area(bl,bl->x,bl->y,2,BL_CHAR,bl->id); - if( nbl ){ // Only one target is chosen. - int temp = (int)(damage / (float)(10 / skill_lv)); - clif->skill_damage(bl, nbl, tick, status_get_amotion(src), 0, status_fix_damage(bl,nbl,temp,0), 1, OB_OBOROGENSOU_TRANSITION_ATK, -1, 6); + if (nbl) { // Only one target is chosen. + clif->skill_damage(bl, nbl, tick, status_get_amotion(src), 0, status_fix_damage(bl,nbl,damage * skill_lv / 10,0), 1, OB_OBOROGENSOU_TRANSITION_ATK, -1, BDT_SKILL); } } //Skill hit type - type=(skill_id==0)?5:skill->get_hit(skill_id); + type=(skill_id==0)?BDT_SPLASH:skill->get_hit(skill_id); if(damage < dmg.div_ //Only skills that knockback even when they miss. [Skotlex] @@ -2319,7 +2337,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr if(skill_id == CR_GRANDCROSS||skill_id == NPC_GRANDDARKNESS) { if(battle_config.gx_disptype) dsrc = src; - if(src == bl) type = 4; + if(src == bl) type = BDT_ENDURE; else flag|=SD_ANIMATION; } if(skill_id == NJ_TATAMIGAESHI) { @@ -2425,7 +2443,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr //Display damage. switch( skill_id ) { case PA_GOSPEL: //Should look like Holy Cross [Skotlex] - dmg.dmotion = clif->skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, CR_HOLYCROSS, -1, 5); + dmg.dmotion = clif->skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, CR_HOLYCROSS, -1, BDT_SPLASH); break; //Skills that need be passed as a normal attack for the client to display correctly. case HVAN_EXPLOSION: @@ -2443,13 +2461,13 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr case AS_SPLASHER: if( flag&SD_ANIMATION ) // the surrounding targets - dmg.dmotion = clif->skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, 5); // needs -1 as skill level + dmg.dmotion = clif->skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, BDT_SPLASH); // needs -1 as skill level else // the central target doesn't display an animation - dmg.dmotion = clif->skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -2, 5); // needs -2(!) as skill level + dmg.dmotion = clif->skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -2, BDT_SPLASH); // needs -2(!) as skill level break; case WL_HELLINFERNO: case SR_EARTHSHAKER: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,-2,6); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,-2,BDT_SKILL); break; case KO_MUCHANAGE: if( dmg.dmg_lv == ATK_FLEE ) @@ -2457,17 +2475,17 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr case WL_SOULEXPANSION: case WL_COMET: case NJ_HUUMA: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,skill_lv,8); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,skill_lv,BDT_MULTIHIT); break; case WL_CHAINLIGHTNING_ATK: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING,-2,6); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING,-2,BDT_SKILL); break; case LG_OVERBRAND_BRANDISH: case LG_OVERBRAND: /* Fall through */ dmg.amotion = status_get_amotion(src) * 2; case LG_OVERBRAND_PLUSATK: - dmg.dmotion = clif->skill_damage(dsrc,bl,tick,status_get_amotion(src),dmg.dmotion,damage,dmg.div_,skill_id,-1,5); + dmg.dmotion = clif->skill_damage(dsrc,bl,tick,status_get_amotion(src),dmg.dmotion,damage,dmg.div_,skill_id,-1,BDT_SPLASH); break; case EL_FIRE_BOMB: case EL_FIRE_BOMB_ATK: @@ -2490,29 +2508,29 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr case GN_CRAZYWEED_ATK: case KO_BAKURETSU: case NC_MAGMA_ERUPTION: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,5); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,BDT_SPLASH); break; case GN_SLINGITEM_RANGEMELEEATK: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,GN_SLINGITEM,-2,6); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,GN_SLINGITEM,-2,BDT_SKILL); break; case SC_FEINTBOMB: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,skill_lv,5); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,skill_lv,BDT_SPLASH); break; case EL_STONE_RAIN: - dmg.dmotion = clif->skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,(flag&1)?8:5); + dmg.dmotion = clif->skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,(flag&1)?BDT_MULTIHIT:BDT_SPLASH); break; case WM_SEVERE_RAINSTORM_MELEE: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,-2,6); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,-2,BDT_SPLASH); break; case WM_REVERBERATION_MELEE: case WM_REVERBERATION_MAGIC: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_REVERBERATION,-2,6); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_REVERBERATION,-2,BDT_SKILL); break; case WL_TETRAVORTEX_FIRE: case WL_TETRAVORTEX_WATER: case WL_TETRAVORTEX_WIND: case WL_TETRAVORTEX_GROUND: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_, WL_TETRAVORTEX,-1,5); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_, WL_TETRAVORTEX,-1,BDT_SPLASH); break; case HT_CLAYMORETRAP: case HT_BLASTMINE: @@ -2521,14 +2539,17 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr case RA_CLUSTERBOMB: case RA_FIRINGTRAP: case RA_ICEBOUNDTRAP: - dmg.dmotion = clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, (flag&SD_LEVEL) ? -1 : skill_lv, 5); + dmg.dmotion = clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, (flag&SD_LEVEL) ? -1 : skill_lv, BDT_SPLASH); if( dsrc != src ) // avoid damage display redundancy break; case HT_LANDMINE: dmg.dmotion = clif->skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, type); break; + case HW_GRAVITATION: + dmg.dmotion = clif->damage(bl, bl, 0, 0, damage, 1, BDT_ENDURE, 0); + break; case WZ_SIGHTBLASTER: - dmg.dmotion = clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, (flag&SD_LEVEL) ? -1 : skill_lv, 5); + dmg.dmotion = clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, (flag&SD_LEVEL) ? -1 : skill_lv, BDT_SPLASH); break; case AB_DUPLELIGHT_MELEE: case AB_DUPLELIGHT_MAGIC: @@ -2610,6 +2631,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr tsd->status.skill[cidx].flag = SKILL_FLAG_PLAGIARIZED; clif->addskill(tsd,copy_skill); } else { + int plagiarismlvl; lv = skill_lv; if ( tsd->cloneskill_id ) { idx = skill->get_index(tsd->cloneskill_id); @@ -2621,8 +2643,8 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr } } - if ((type = pc->checkskill(tsd,RG_PLAGIARISM)) < lv) - lv = type; + if ((plagiarismlvl = pc->checkskill(tsd,RG_PLAGIARISM)) < lv) + lv = plagiarismlvl; tsd->cloneskill_id = copy_skill; pc_setglobalreg(tsd, script->add_str("CLONE_SKILL"), copy_skill); @@ -2693,7 +2715,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr } /* monsters with skill lv higher than MAX_SKILL_LEVEL may get this value beyond the max depending on conditions, we cap to the system's limit */ - if( dsrc && dsrc->type == BL_MOB && skill_lv > MAX_SKILL_LEVEL && dmg.blewcount > 25 ) + if (dsrc->type == BL_MOB && skill_lv > MAX_SKILL_LEVEL && dmg.blewcount > 25) dmg.blewcount = 25; //blown-specific handling @@ -2738,12 +2760,12 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr ) && check_distance_bl(bl, d_bl, sce->val3) ) { if(!rmdamage){ - clif->damage(d_bl,d_bl, 0, 0, damage, 0, 0, 0); + clif->damage(d_bl,d_bl, 0, 0, damage, 0, BDT_NORMAL, 0); status_fix_damage(NULL,d_bl, damage, 0); } else{ //Reflected magics are done directly on the target not on paladin //This check is only for magical skill. //For BF_WEAPON skills types track var rdamage and function battle_calc_return_damage - clif->damage(bl,bl, 0, 0, damage, 0, 0, 0); + clif->damage(bl,bl, 0, 0, damage, 0, BDT_NORMAL, 0); status_fix_damage(bl,bl, damage, 0); } } @@ -2837,11 +2859,11 @@ void skill_attack_combo2_unknown(int *attack_type, struct block_list* src, struc void skill_attack_display_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type, struct Damage *dmg, int64 *damage) { if (*flag & SD_ANIMATION && dmg->div_ < 2) //Disabling skill animation doesn't works on multi-hit. - *type = 5; + *type = BDT_SPLASH; if (bl->type == BL_SKILL ) { TBL_SKILL *su = (TBL_SKILL*)bl; if (su->group && skill->get_inf2(su->group->skill_id) & INF2_TRAP) // show damage on trap targets - clif->skill_damage(src, bl, *tick, dmg->amotion, dmg->dmotion, *damage, dmg->div_, *skill_id, (*flag & SD_LEVEL) ? -1 : *skill_lv, 5); + clif->skill_damage(src, bl, *tick, dmg->amotion, dmg->dmotion, *damage, dmg->div_, *skill_id, (*flag & SD_LEVEL) ? -1 : *skill_lv, BDT_SPLASH); } dmg->dmotion = clif->skill_damage(dsrc, bl, *tick, dmg->amotion, dmg->dmotion, *damage, dmg->div_, *skill_id, (*flag & SD_LEVEL) ? -1 : *skill_lv, *type); } @@ -2890,7 +2912,7 @@ int skill_area_sub(struct block_list *bl, va_list ap) { if(battle->check_target(src,bl,flag) > 0) { // several splash skills need this initial dummy packet to display correctly if (flag&SD_PREAMBLE && skill->area_temp[2] == 0) - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if (flag&(SD_SPLASH|SD_PREAMBLE)) skill->area_temp[2]++; @@ -3065,15 +3087,15 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv, // Requirements for( i = 0; i < ARRAYLENGTH(itemid); i++ ) { - itemid[i] = skill->db[idx].itemid[i]; - amount[i] = skill->db[idx].amount[i]; - } - hp = skill->db[idx].hp[lv-1]; - sp = skill->db[idx].sp[lv-1]; - hp_rate = skill->db[idx].hp_rate[lv-1]; - sp_rate = skill->db[idx].sp_rate[lv-1]; - state = skill->db[idx].state; - if( (mhp = skill->db[idx].mhp[lv-1]) > 0 ) + itemid[i] = skill->dbs->db[idx].itemid[i]; + amount[i] = skill->dbs->db[idx].amount[i]; + } + hp = skill->dbs->db[idx].hp[lv-1]; + sp = skill->dbs->db[idx].sp[lv-1]; + hp_rate = skill->dbs->db[idx].hp_rate[lv-1]; + sp_rate = skill->dbs->db[idx].sp_rate[lv-1]; + state = skill->dbs->db[idx].state; + if( (mhp = skill->dbs->db[idx].mhp[lv-1]) > 0 ) hp += (st->max_hp * mhp) / 100; if( hp_rate > 0 ) hp += (st->hp * hp_rate) / 100; @@ -3135,7 +3157,7 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv, // Consume items for (i = 0; i < ARRAYLENGTH(itemid); i++) { if (index[i] != INDEX_NOT_FOUND) - pc->delitem(sd, index[i], amount[i], 0, 1, LOG_TYPE_CONSUME); + pc->delitem(sd, index[i], amount[i], 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); } if( type&2 ) @@ -3315,7 +3337,7 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { break; case SC_ESCAPE: if( skl->type < 4+skl->skill_lv ){ - clif->skill_damage(src,src,tick,0,0,-30000,1,skl->skill_id,skl->skill_lv,5); + clif->skill_damage(src,src,tick,0,0,-30000,1,skl->skill_id,skl->skill_lv,BDT_SPLASH); skill->blown(src,src,1,unit->getdir(src),0); skill->addtimerskill(src,tick+80,src->id,0,0,skl->skill_id,skl->skill_lv,skl->type+1,0); } @@ -3814,9 +3836,16 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 if( dir > 2 && dir < 6 ) y = -i; else if( dir == 7 || dir < 2 ) y = i; else y = 0; - if( (mbl == src || (!map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground) ) // only NJ_ISSEN don't have slide effect in GVG - && unit->movepos(src, mbl->x+x, mbl->y+y, 1, 1) - ) { + if ((mbl == src || (!map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground))) { // only NJ_ISSEN don't have slide effect in GVG + if (!(unit->movepos(src, mbl->x+x, mbl->y+y, 1, 1))) { + // The cell is not reachable (wall, object, ...), move next to the target + if (x > 0) x = -1; + else if (x < 0) x = 1; + if (y > 0) y = -1; + else if (y < 0) y = 1; + + unit->movepos(src, bl->x+x, bl->y+y, 1, 1); + } clif->slide(src, src->x, src->y); clif->fixpos(src); clif->spiritball(src); @@ -3914,7 +3943,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 /* Fall through */ case LG_MOONSLASHER: case MH_XENO_SLASHER: - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); break; default: break; @@ -3946,7 +3975,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case MS_MAGNUM: if( flag&1 ) { //Damage depends on distance, so add it to flag if it is > 1 - skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag|distance_bl(src, bl)); + skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag|SD_ANIMATION|distance_bl(src, bl)); } break; @@ -4069,7 +4098,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 break; case CH_PALMSTRIKE: // Palm Strike takes effect 1sec after casting. [Skotlex] //clif->skill_nodamage(src,bl,skill_id,skill_lv,0); //Can't make this one display the correct attack animation delay :/ - clif->damage(src,bl,status_get_amotion(src),0,-1,1,4,0); //Display an absorbed damage attack. + clif->damage(src,bl,status_get_amotion(src),0,-1,1,BDT_ENDURE,0); //Display an absorbed damage attack. skill->addtimerskill(src, tick + (1000+status_get_amotion(src)), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag); break; @@ -4523,7 +4552,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); // Need confirm it. } else { map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id); - clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if( sd ) pc->overheat(sd,1); } break; @@ -4542,7 +4571,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 skill->area_temp[5] = y; map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id); skill->addtimerskill(src,tick + 800,src->id,x,y,skill_id,skill_lv,0,flag); // To teleport Self - clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); + clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,BDT_SKILL); } break; case LG_PINPOINTATTACK: @@ -4581,14 +4610,12 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER); status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); + status_change_end(bl, SC_NETHERWORLD, INVALID_TIMER); status_change_end(bl, SC_SIREN, INVALID_TIMER); - status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER); - status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER); status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER); status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER); status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER); status_change_end(bl, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER); - status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER); status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER); status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER); @@ -4602,7 +4629,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); } else{ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id); - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); } break; @@ -4669,7 +4696,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 else { int i = skill->get_splash(skill_id,skill_lv); clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); - clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if( rnd()%100 < 30 ) map->foreachinrange(skill->area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); else @@ -4679,7 +4706,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case EL_ROCK_CRUSHER: clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if( rnd()%100 < 50 ) skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); else @@ -4692,7 +4719,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 else { int i = skill->get_splash(skill_id,skill_lv); clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if( rnd()%100 < 30 ) map->foreachinrange(skill->area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); else @@ -4705,7 +4732,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case EL_WIND_SLASH: case EL_STONE_HAMMER: clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); - clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); break; @@ -4718,7 +4745,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 type2 = type-1; clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if( (esc && esc->data[type2]) || (tsc && tsc->data[type]) ) { elemental->clean_single_effect(ele, skill_id); } @@ -4855,7 +4882,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { if( sd && ud->skilltimer != INVALID_TIMER && (pc->checkskill(sd,SA_FREECAST) > 0 || ud->skill_id == LG_EXEEDBREAK) ) {// restore original walk speed ud->skilltimer = INVALID_TIMER; - status_calc_bl(&sd->bl, SCB_SPEED); + status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD); } ud->skilltimer = INVALID_TIMER; @@ -5021,7 +5048,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { } if (ud->walktimer != INVALID_TIMER && ud->skill_id != TK_RUN && ud->skill_id != RA_WUGDASH) - unit->stop_walking(src,1); + unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS); if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) ) ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv); // Tests show wings don't overwrite the delay but skill scrolls do. [Inkfish] @@ -5141,9 +5168,9 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { } } - ud->skill_id = ud->skill_lv = ud->skilltarget = 0; if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) ) ud->canact_tick = tick; + ud->skill_id = ud->skill_lv = ud->skilltarget = 0; //You can't place a skill failed packet here because it would be //sent in ALL cases, even cases where skill_check_condition fails //which would lead to double 'skill failed' messages u.u [Skotlex] @@ -5512,10 +5539,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin int abra_skill_id = 0, abra_skill_lv, abra_idx; do { abra_idx = rnd() % MAX_SKILL_ABRA_DB; - abra_skill_id = skill->abra_db[abra_idx].skill_id; + abra_skill_id = skill->dbs->abra_db[abra_idx].skill_id; } while (abra_skill_id == 0 || - skill->abra_db[abra_idx].req_lv > skill_lv || //Required lv for it to appear - rnd()%10000 >= skill->abra_db[abra_idx].per + skill->dbs->abra_db[abra_idx].req_lv > skill_lv || //Required lv for it to appear + rnd()%10000 >= skill->dbs->abra_db[abra_idx].per ); abra_skill_lv = min(skill_lv, skill->get_max(abra_skill_id)); clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); @@ -6081,7 +6108,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } i = 0; - count = (sd)? min(skill_lv,5) : 1; // Mercenary only can Devote owner + count = (sd)? min(skill_lv,MAX_PC_DEVOTION) : 1; // Mercenary only can Devote owner if( sd ) { // Player Devoting Player ARR_FIND(0, count, i, sd->devotion[i] == bl->id ); @@ -6109,22 +6136,17 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case MO_CALLSPIRITS: if(sd) { - int limit = skill_lv; - if( sd->sc.data[SC_RAISINGDRAGON] ) - limit += sd->sc.data[SC_RAISINGDRAGON]->val1; clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - pc->addspiritball(sd,skill->get_time(skill_id,skill_lv),limit); + pc->addspiritball(sd, skill->get_time(skill_id, skill_lv), pc->getmaxspiritball(sd, 0)); } break; case CH_SOULCOLLECT: if(sd) { - int limit = 5, i; - if( sd->sc.data[SC_RAISINGDRAGON] ) - limit += sd->sc.data[SC_RAISINGDRAGON]->val1; + int i, limit = pc->getmaxspiritball(sd, 5); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - for (i = 0; i < limit; i++) - pc->addspiritball(sd,skill->get_time(skill_id,skill_lv),limit); + for ( i = 0; i < limit; i++ ) + pc->addspiritball(sd, skill->get_time(skill_id, skill_lv), limit); } break; @@ -6146,7 +6168,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin { int sp = 0; if ( dstsd && dstsd->spiritball - && (sd == dstsd || map_flag_vs(src->m) || (sd->duel_group && sd->duel_group == dstsd->duel_group)) + && (sd == dstsd || map_flag_vs(src->m) || (sd && sd->duel_group && sd->duel_group == dstsd->duel_group)) && ((dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK) != MAPID_REBELLION) ) { // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen] @@ -6216,7 +6238,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin count = map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id); if( !count && ( skill_id == NC_AXETORNADO || skill_id == SR_SKYNETBLOW || skill_id == KO_HAPPOKUNAI ) ) - clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); } break; @@ -6268,7 +6290,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin { //Self Destruction hits everyone in range (allies+enemies) //Except for Summoned Marine spheres on non-versus maps, where it's just enemy. - int targetmask = ((!md || md->special_state.ai == 2) && !map_flag_vs(src->m))? + int targetmask = ((!md || md->special_state.ai == AI_SPHERE) && !map_flag_vs(src->m))? BCT_ENEMY:BCT_ALL; clif->skill_nodamage(src, src, skill_id, -1, 1); map->delblock(src); //Required to prevent chain-self-destructions hitting back. @@ -6439,7 +6461,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin // custom hack to make the mob display the skill, because these skills don't show the skill use text themselves //NOTE: mobs don't have the sprite animation that is used when performing this skill (will cause glitches) char temp[70]; - snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill->db[skill_id].desc); + snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill->dbs->db[skill_id].desc); clif->disp_overhead(&md->bl,temp); } break; @@ -6554,6 +6576,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin status_change_end(bl, SC_STUN, INVALID_TIMER); status_change_end(bl, SC_WHITEIMPRISON, INVALID_TIMER); } + status_change_end(bl, SC_NETHERWORLD, INVALID_TIMER); //Is this equation really right? It looks so... special. if( battle->check_undead(tstatus->race,tstatus->def_ele) ) { status->change_start(src, bl, SC_BLIND, @@ -6636,7 +6659,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin return 1; } if( sd->skillitem != skill_id ) - status_zap(src,0,skill->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded + status_zap(src,0,skill->dbs->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded } break; @@ -6814,13 +6837,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( sd ) { int x,bonus=100, potion = min(500+skill_lv,505); x = skill_lv%11 - 1; - i = pc->search_inventory(sd,skill->db[skill_id].itemid[x]); - if (i == INDEX_NOT_FOUND || skill->db[skill_id].itemid[x] <= 0) { + i = pc->search_inventory(sd,skill->dbs->db[skill_id].itemid[x]); + if (i == INDEX_NOT_FOUND || skill->dbs->db[skill_id].itemid[x] <= 0) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); map->freeblock_unlock(); return 1; } - if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill->db[skill_id].amount[x]) { + if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill->dbs->db[skill_id].amount[x]) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); map->freeblock_unlock(); return 1; @@ -6917,44 +6940,24 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } break; case AM_CP_WEAPON: - if(dstsd && dstsd->inventory_data[dstsd->equip_index[EQI_HAND_R]]) - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - else { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case AM_CP_SHIELD: { - int i; - if(dstsd && (i=dstsd->equip_index[EQI_HAND_L])>=0 && dstsd->inventory_data[i] && - dstsd->inventory_data[i]->type==IT_ARMOR) - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - else { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - } - break; + case AM_CP_SHIELD: case AM_CP_ARMOR: - if(dstsd && dstsd->inventory_data[dstsd->equip_index[EQI_ARMOR]]) - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - else { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; case AM_CP_HELM: - if(dstsd && dstsd->inventory_data[dstsd->equip_index[EQI_HEAD_TOP]]) - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - else { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + { + unsigned int equip[] = { EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP }; + int index; + if ( sd && (bl->type != BL_PC || (dstsd && pc->checkequip(dstsd, equip[skill_id - AM_CP_WEAPON]) < 0) || + (dstsd && equip[skill_id - AM_CP_WEAPON] == EQP_SHIELD && pc->checkequip(dstsd, EQP_SHIELD) > 0 + && (index = dstsd->equip_index[EQI_HAND_L]) >= 0 && dstsd->inventory_data[index] + && dstsd->inventory_data[index]->type != IT_ARMOR)) ) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + map->freeblock_unlock(); // Don't consume item requirements return 0; } + clif->skill_nodamage(src, bl, skill_id, skill_lv, + sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); break; + } case AM_TWILIGHT1: if (sd) { clif->skill_nodamage(src,bl,skill_id,skill_lv,1); @@ -7382,14 +7385,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case WE_MALE: { - int hp_rate = (!skill_lv)? 0:skill->db[skill_id].hp_rate[skill_lv-1]; + int hp_rate = (!skill_lv)? 0:skill->dbs->db[skill_id].hp_rate[skill_lv-1]; int gain_hp = tstatus->max_hp*abs(hp_rate)/100; // The earned is the same % of the target HP than it cost the caster. [Skotlex] clif->skill_nodamage(src,bl,skill_id,status->heal(bl, gain_hp, 0, 0),1); } break; case WE_FEMALE: { - int sp_rate = (!skill_lv)? 0:skill->db[skill_id].sp_rate[skill_lv-1]; + int sp_rate = (!skill_lv)? 0:skill->dbs->db[skill_id].sp_rate[skill_lv-1]; int gain_sp = tstatus->max_sp*abs(sp_rate)/100;// The earned is the same % of the target SP than it cost the caster. [Skotlex] clif->skill_nodamage(src,bl,skill_id,status->heal(bl, 0, gain_sp, 0),1); } @@ -7453,15 +7456,15 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin int i; // get back all items used to deploy the trap for( i = 0; i < 10; i++ ) { - if( skill->db[su->group->skill_id].itemid[i] > 0 ) { + if( skill->dbs->db[su->group->skill_id].itemid[i] > 0 ) { int success; struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = skill->db[su->group->skill_id].itemid[i]; + item_tmp.nameid = skill->dbs->db[su->group->skill_id].itemid[i]; item_tmp.identify = 1; - if( item_tmp.nameid && (success=pc->additem(sd,&item_tmp,skill->db[su->group->skill_id].amount[i],LOG_TYPE_OTHER)) ) { + if( item_tmp.nameid && (success=pc->additem(sd,&item_tmp,skill->dbs->db[su->group->skill_id].amount[i],LOG_TYPE_OTHER)) ) { clif->additem(sd,0,0,success); - map->addflooritem(&item_tmp,skill->db[su->group->skill_id].amount[i],sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + map->addflooritem(&item_tmp,skill->dbs->db[su->group->skill_id].amount[i],sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } } } @@ -7638,28 +7641,27 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } break; // Full Chemical Protection - case CR_FULLPROTECTION: { - bool iused=false; - int i; - if(dstsd && dstsd->inventory_data[dstsd->equip_index[EQI_HAND_R]]) { - iused=true; - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,SC_PROTECTWEAPON,100,skill_lv,skill->get_time(skill_id,skill_lv))); - } if(dstsd && (i=dstsd->equip_index[EQI_HAND_L])>=0 && dstsd->inventory_data[i] && - dstsd->inventory_data[i]->type==IT_ARMOR) { - iused=true; - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,SC_PROTECTSHIELD,100,skill_lv,skill->get_time(skill_id,skill_lv))); - } if(dstsd && dstsd->inventory_data[dstsd->equip_index[EQI_ARMOR]]) { - iused=true; - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,SC_PROTECTARMOR,100,skill_lv,skill->get_time(skill_id,skill_lv))); - } if(dstsd && dstsd->inventory_data[dstsd->equip_index[EQI_HEAD_TOP]]) { - iused=true; - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,SC_PROTECTHELM,100,skill_lv,skill->get_time(skill_id,skill_lv))); - } if(iused) - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - else { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + case CR_FULLPROTECTION: + { + unsigned int equip[] = { EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP }; + int i, s = 0, skilltime = skill->get_time(skill_id, skill_lv); + for ( i = 0; i < 4; i++ ) { + if ( bl->type != BL_PC || (dstsd && pc->checkequip(dstsd, equip[i]) < 0) ) + continue; + if ( dstsd && equip[i] == EQP_SHIELD ) { + short index = dstsd->equip_index[EQI_HAND_L]; + if ( index >= 0 && dstsd->inventory_data[index] && dstsd->inventory_data[index]->type != IT_ARMOR ) + continue; + } + sc_start(src, bl, (sc_type)(SC_PROTECTWEAPON + i), 100, skill_lv, skilltime); + s++; + } + if ( sd && !s ) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + map->freeblock_unlock(); // Don't consume item requirements return 0; } + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); } break; @@ -7692,7 +7694,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin map->freeblock_unlock(); return 0; } - status_zap(src,0,skill->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded [Inkfish] + status_zap(src,0,skill->dbs->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded [Inkfish] do { int eff = rnd() % 14; if( eff == 5 ) @@ -7713,7 +7715,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case 3: // 1000 damage, random armor destroyed { status_fix_damage(src, bl, 1000, 0); - clif->damage(src,bl,0,0,1000,0,0,0); + clif->damage(src,bl,0,0,1000,0,BDT_NORMAL,0); if( !status->isdead(bl) ) { int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT }; skill->break_equip(bl, where[rnd()%5], 10000, BCT_ENEMY); @@ -7750,14 +7752,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case 10: // 6666 damage, atk matk halved, cursed status_fix_damage(src, bl, 6666, 0); - clif->damage(src,bl,0,0,6666,0,0,0); + clif->damage(src,bl,0,0,6666,0,BDT_NORMAL,0); sc_start(src,bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); sc_start(src,bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); sc_start(src,bl,SC_CURSE,skill_lv,100,skill->get_time2(skill_id,skill_lv)); break; case 11: // 4444 damage status_fix_damage(src, bl, 4444, 0); - clif->damage(src,bl,0,0,4444,0,0,0); + clif->damage(src,bl,0,0,4444,0,BDT_NORMAL,0); break; case 12: // stun sc_start(src,bl,SC_STUN,100,skill_lv,5000); @@ -8135,7 +8137,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case LG_EARTHDRIVE: { int splash; - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); splash = skill->get_splash(skill_id,skill_lv); if( skill_id == LG_EARTHDRIVE ) { int dummy = 1; @@ -8316,7 +8318,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case GC_PHANTOMMENACE: { int r; - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); r = skill->get_splash(skill_id, skill_lv); map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR, @@ -8612,7 +8614,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin * Ranger **/ case RA_FEARBREEZE: - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); break; @@ -8653,7 +8655,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case RA_SENSITIVEKEEN: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill->castend_damage_id); break; /** @@ -8680,7 +8682,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case NC_ANALYZE: - clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(src,bl,type, 30 + 12 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv))); if( sd ) pc->overheat(sd,1); @@ -8692,7 +8694,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( (failure = sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))) ) { map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill->castend_damage_id);; - clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); + clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,BDT_SKILL); if (sd) pc->overheat(sd,1); } clif->skill_nodamage(src,src,skill_id,skill_lv,failure); @@ -8812,7 +8814,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case LG_TRAMPLE: - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->destroy_trap,bl,skill->get_splash(skill_id,skill_lv),BL_SKILL,tick); break; @@ -8850,7 +8852,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin switch( opt ) { case 1: sc_start(src,bl,SC_SHIELDSPELL_DEF,100,opt,INVALID_TIMER); //Splash AoE ATK - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); status_change_end(bl,SC_SHIELDSPELL_DEF,INVALID_TIMER); break; @@ -8877,13 +8879,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin switch( opt ) { case 1: sc_start(src,bl,SC_SHIELDSPELL_MDEF,100,opt,INVALID_TIMER); //Splash AoE MATK - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); status_change_end(bl,SC_SHIELDSPELL_MDEF,INVALID_TIMER); break; case 2: sc_start(src,bl,SC_SHIELDSPELL_MDEF,100,opt,sd->bonus.shieldmdef * 2000); //Splash AoE Lex Divina - clif->skill_damage(src,bl,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_nodamage_id); break; case 3: @@ -8996,7 +8998,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } } else { int count = 0; - clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); count = map->forcountinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv), (sd)?sd->spiritball_old:15, // Assume 15 spiritballs in non-characters BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); if( sd ) pc->delspiritball(sd, count, 0); @@ -9006,13 +9008,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case SR_RAISINGDRAGON: - if( sd ) { - short max = 5 + skill_lv; - int i; + if ( sd ) { + int i, max; sc_start(src, bl, SC_EXPLOSIONSPIRITS, 100, skill_lv, skill->get_time(skill_id, skill_lv)); - for( i = 0; i < max; i++ ) // Don't call more than max available spheres. - pc->addspiritball(sd, skill->get_time(skill_id, skill_lv), max); - clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv))); + clif->skill_nodamage(src, bl, skill_id, skill_lv, + sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); + max = pc->getmaxspiritball(sd, 0); + for ( i = 0; i < max; i++ ) + pc->addspiritball(sd, skill->get_time(MO_CALLSPIRITS, skill_lv), max); } break; @@ -9030,7 +9033,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin } clif->skill_nodamage(src, bl, skill_id, skill_lv, sp ? 1:0); } else { - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill->castend_nodamage_id); } break; @@ -9038,12 +9041,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case SR_POWERVELOCITY: if( !dstsd ) break; - if( sd && dstsd->spiritball <= 5 ) { - int i; - for(i = 0; i <= 5; i++) { - pc->addspiritball(dstsd, skill->get_time(MO_CALLSPIRITS, pc->checkskill(sd,MO_CALLSPIRITS)), i); - pc->delspiritball(sd, sd->spiritball, 0); + if ( sd && (dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER ) { + int i, max = pc->getmaxspiritball(dstsd, 5); + for ( i = 0; i < max; i++ ) { + pc->addspiritball(dstsd, skill->get_time(MO_CALLSPIRITS, 1), max); } + pc->delspiritball(sd, sd->spiritball, 0); } clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); break; @@ -9199,7 +9202,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin madnesscheck = map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count); sc_start(src, bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv)); if ( madnesscheck >= 8 )//The god of madness deals 9999 fixed unreduceable damage when 8 or more enemy players are affected. - status_fix_damage(src, bl, 9999, clif->damage(src, bl, 0, 0, 9999, 0, 0, 0)); + status_fix_damage(src, bl, 9999, clif->damage(src, bl, 0, 0, 9999, 0, BDT_NORMAL, 0)); //skill->attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);//To renable when I can confirm it deals damage like this. Data shows its dealt as reflected damage which I don't have it coded like that yet. [Rytech] } else if( sd ) { int rate = sstatus->int_ / 6 + (sd? sd->status.job_level:0) / 5 + skill_lv * 4; @@ -9230,8 +9233,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin int improv_skill_id = 0, improv_skill_lv, improv_idx; do { improv_idx = rnd() % MAX_SKILL_IMPROVISE_DB; - improv_skill_id = skill->improvise_db[improv_idx].skill_id; - } while( improv_skill_id == 0 || rnd()%10000 >= skill->improvise_db[improv_idx].per ); + improv_skill_id = skill->dbs->improvise_db[improv_idx].skill_id; + } while( improv_skill_id == 0 || rnd()%10000 >= skill->dbs->improvise_db[improv_idx].per ); improv_skill_lv = 4 + skill_lv; clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); @@ -9335,7 +9338,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; } clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, 0, 1, skill_id, -2, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, 0, 1, skill_id, -2, BDT_SKILL); break; case GM_SANDMAN: @@ -9560,7 +9563,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin elemental->clean_single_effect(ele, skill_id); } else { clif->skill_nodamage(src,src,skill_id,skill_lv,1); - clif->skill_damage(src, ( skill_id == EL_GUST || skill_id == EL_BLAST || skill_id == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, ( skill_id == EL_GUST || skill_id == EL_BLAST || skill_id == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); if( skill_id == EL_WIND_STEP ) // There aren't teleport, just push the master away. skill->blown(src,bl,(rnd()%skill->get_blewcount(skill_id,skill_lv))+1,rnd()%8,0); sc_start(src, src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); @@ -9575,7 +9578,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case EL_ZEPHYR: case EL_POWER_OF_GAIA: clif->skill_nodamage(src,src,skill_id,skill_lv,1); - clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); skill->unitsetting(src,skill_id,skill_lv,bl->x,bl->y,0); break; @@ -9591,7 +9594,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin elemental->clean_single_effect(ele, skill_id); } else { // This not heals at the end. - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); sc_start(src, src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); sc_start(src, bl,type,100,src->id,skill->get_time(skill_id,skill_lv)); } @@ -9668,8 +9671,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin clif->skill_nodamage(src, src, skill_id, skill_lv, 1); clif->slide(src, bl->x, bl->y) ; sc_start(src, src, SC_CONFUSION, 25, skill_lv, skill->get_time(skill_id, skill_lv)); - if ( !is_boss(bl) && unit->stop_walking(&sd->bl, 1) && unit->movepos(bl, x, y, 0, 0) ) - { + if ( !is_boss(bl) && unit->stop_walking(&sd->bl, STOPWALKING_FLAG_FIXPOS) && unit->movepos(bl, x, y, 0, 0) ) { if( dstsd && pc_issit(dstsd) ) pc->setstand(dstsd); clif->slide(bl, x, y) ; @@ -9692,7 +9694,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case KG_KAGEMUSYA: clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(src, bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); break; case KG_KAGEHUMI: @@ -9711,7 +9713,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); } if( skill->area_temp[2] == 1 ){ - clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); sc_start(src, src, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv)); } } else { @@ -9889,7 +9891,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data) if( sd && ud->skilltimer != INVALID_TIMER && ( pc->checkskill(sd,SA_FREECAST) > 0 || ud->skill_id == LG_EXEEDBREAK ) ) {// restore original walk speed ud->skilltimer = INVALID_TIMER; - status_calc_bl(&sd->bl, SCB_SPEED); + status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD); } ud->skilltimer = INVALID_TIMER; @@ -9965,7 +9967,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data) src->type, src->id, ud->skill_id, ud->skill_lv, ud->skillx, ud->skilly); if (ud->walktimer != INVALID_TIMER) - unit->stop_walking(src,1); + unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS); if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) ) ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv); @@ -10527,9 +10529,9 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case CR_SLIMPITCHER: if (sd) { int i = skill_lv%11 - 1; - int j = pc->search_inventory(sd,skill->db[skill_id].itemid[i]); - if (j == INDEX_NOT_FOUND || skill->db[skill_id].itemid[i] <= 0 - || sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < skill->db[skill_id].amount[i] + int j = pc->search_inventory(sd,skill->dbs->db[skill_id].itemid[i]); + if (j == INDEX_NOT_FOUND || skill->dbs->db[skill_id].itemid[i] <= 0 + || sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < skill->dbs->db[skill_id].amount[i] ) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 1; @@ -10558,7 +10560,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui } else { int i = skill_lv%11 - 1; struct item_data *item; - i = skill->db[skill_id].itemid[i]; + i = skill->dbs->db[skill_id].itemid[i]; item = itemdb->search(i); script->potion_flag = 1; script->potion_hp = 0; @@ -10661,7 +10663,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui break; case RK_WINDCUTTER: - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); /* Fall through */ case NC_COLDSLOWER: case RK_DRAGONBREATH: @@ -10701,7 +10703,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui clif->skill_fail(sd,skill_id,USESKILL_FAIL_GC_POISONINGWEAPON,0); return 0; } - clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); + clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,BDT_SKILL); skill->unitsetting(src, skill_id, skill_lv, x, y, flag); //status_change_end(src,SC_POISONINGWEAPON,INVALID_TIMER); // 08/31/2011 - When using poison smoke, you no longer lose the poisoning weapon effect. break; @@ -10738,7 +10740,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case RA_DETONATOR: r = skill->get_splash(skill_id, skill_lv); map->foreachinarea(skill->detonator, src->m, x-r, y-r, x+r, y+r, BL_SKILL, src); - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); break; /** * Mechanic @@ -11074,6 +11076,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ * According to data provided in RE, SW life is equal to 3 times caster's health **/ val2 = status_get_max_hp(src) * 3; + val3 = skill_lv+1; #else val2 = skill_lv+1; #endif @@ -11389,7 +11392,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ } break; case NPC_EARTHQUAKE: - clif->skill_damage(src, src, timer->gettick(), status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src, src, timer->gettick(), status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); break; default: skill->unitsetting1_unknown(src, &skill_id, &skill_lv, &x, &y, &flag, &val1, &val2, &val3); @@ -11785,7 +11788,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 struct skill_unit_group *sg; struct block_list *ss; TBL_PC* tsd; - struct status_data *tstatus; + struct status_data *tstatus, *bst; struct status_change *tsc, *ssc; struct skill_unit_group_tickset *ts; enum sc_type type; @@ -11809,6 +11812,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 return 0; tstatus = status->get_status_data(bl); + bst = status->get_base_status(bl); type = status->skill2sc(sg->skill_id); skill_id = sg->skill_id; @@ -12346,10 +12350,11 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 skill->attack(BF_WEAPON,ss,&src->bl,bl,WM_SEVERE_RAINSTORM_MELEE,sg->skill_lv,tick,0); break; case UNT_NETHERWORLD: - if( !(status_get_mode(bl)&MD_BOSS)) { - if( !(tsc && tsc->data[type]) ){ - sc_start(ss, bl, type, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv)); - } + if ( battle->check_target(&src->bl, bl, BCT_PARTY) == -1 && bl->id != sg->src_id ) { + sc_start(ss, bl, type, 100, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sg->limit = 0; + clif->changetraplook(&src->bl, UNT_USED_TRAPS); + sg->unit_id = UNT_USED_TRAPS; } break; case UNT_THORNS_TRAP: @@ -12420,7 +12425,6 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 hp = tstatus->max_hp * 3 * sg->skill_lv / 100; else hp = tstatus->max_hp * sg->skill_lv / 100; - status->heal(bl, hp, 0, 0); if( tstatus->hp != tstatus->max_hp ) clif->skill_nodamage(&src->bl, bl, AL_HEAL, hp, 0); if( tsc && tsc->data[SC_AKAITSUKI] && hp ) @@ -12457,7 +12461,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 if (tsc && (tsc->data[SC_HALLUCINATIONWALK] || tsc->data[SC_VACUUM_EXTREME])) { return 0; } else { - sg->limit -= 100 * tstatus->str/20; + sg->limit -= 1000 * bst->str/20; sc_start(ss, bl, SC_VACUUM_EXTREME, 100, sg->skill_lv, sg->limit); if ( !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground && !is_boss(bl) ) { @@ -12924,7 +12928,8 @@ int skill_check_condition_mob_master_sub (struct block_list *bl, va_list ap) { mob_class=va_arg(ap,int); skill_id=va_arg(ap,int); c=va_arg(ap,int *); - if( md->master_id != src_id || md->special_state.ai != (unsigned)(skill_id == AM_SPHEREMINE?2:skill_id == KO_ZANZOU?4:skill_id == MH_SUMMON_LEGION?1:3) ) + if( md->master_id != src_id + || md->special_state.ai != (skill_id == AM_SPHEREMINE?AI_SPHERE:skill_id == KO_ZANZOU?AI_ZANZOU:skill_id == MH_SUMMON_LEGION?AI_ATTACK:AI_FLORA) ) return 0; //Non alchemist summoned mobs have nothing to do here. if(md->class_==mob_class) (*c)++; @@ -13038,8 +13043,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id sd->itemid = sd->itemindex = -1; if( skill_id == WZ_EARTHSPIKE && sc && sc->data[SC_EARTHSCROLL] && rnd()%100 > sc->data[SC_EARTHSCROLL]->val2 ) // [marquis007] ; //Do not consume item. - else if( sd->status.inventory[i].expire_time == 0 ) - pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); // Rental usable items are not consumed until expiration + else if( sd->status.inventory[i].expire_time == 0 ) // Rental usable items are not consumed until expiration + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); } return 1; } @@ -13644,7 +13649,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id MOBID_EMPERIUM, MOBID_GUARIDAN_STONE1, MOBID_GUARIDAN_STONE2)) { char output[128]; sprintf(output, "You're too close to a stone or emperium to do this skill"); /* TODO official response? or message.conf it */ - clif->colormes(sd->fd, COLOR_RED, output); + clif->messagecolor_self(sd->fd, COLOR_RED, output); return 0; } } @@ -14078,7 +14083,7 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, skill->get_desc(skill_id), require.ammo_qty, itemdb_jname(sd->status.inventory[i].nameid)); - clif->colormes(sd->fd,COLOR_RED,e_msg); + clif->messagecolor_self(sd->fd, COLOR_RED, e_msg); return 0; } if (!(require.ammo&1<<sd->inventory_data[i]->look)) { //Ammo type check. Send the "wrong weapon type" message @@ -14214,7 +14219,7 @@ int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uin } if ((n = pc->search_inventory(sd,req.itemid[i])) != INDEX_NOT_FOUND) - pc->delitem(sd,n,req.amount[i],0,1,LOG_TYPE_CONSUME); + pc->delitem(sd, n, req.amount[i], 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); } } @@ -14280,17 +14285,17 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 st = &sd->battle_status; - req.hp = skill->db[idx].hp[skill_lv-1]; - hp_rate = skill->db[idx].hp_rate[skill_lv-1]; + req.hp = skill->dbs->db[idx].hp[skill_lv-1]; + hp_rate = skill->dbs->db[idx].hp_rate[skill_lv-1]; if(hp_rate > 0) req.hp += (st->hp * hp_rate)/100; else req.hp += (st->max_hp * (-hp_rate))/100; - req.sp = skill->db[idx].sp[skill_lv-1]; + req.sp = skill->dbs->db[idx].sp[skill_lv-1]; if((sd->skill_id_old == BD_ENCORE) && skill_id == sd->skill_id_dance) req.sp /= 2; - sp_rate = skill->db[idx].sp_rate[skill_lv-1]; + sp_rate = skill->dbs->db[idx].sp_rate[skill_lv-1]; if(sp_rate > 0) req.sp += (st->sp * sp_rate)/100; else @@ -14318,22 +14323,22 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 req.sp -= req.sp * sc->data[SC_TELEKINESIS_INTENSE]->val2 / 100; } - req.zeny = skill->db[idx].zeny[skill_lv-1]; + req.zeny = skill->dbs->db[idx].zeny[skill_lv-1]; if( sc && sc->data[SC__UNLUCKY] ) req.zeny += sc->data[SC__UNLUCKY]->val1 * 500; - req.spiritball = skill->db[idx].spiritball[skill_lv-1]; + req.spiritball = skill->dbs->db[idx].spiritball[skill_lv-1]; - req.state = skill->db[idx].state; + req.state = skill->dbs->db[idx].state; - req.mhp = skill->db[idx].mhp[skill_lv-1]; + req.mhp = skill->dbs->db[idx].mhp[skill_lv-1]; - req.weapon = skill->db[idx].weapon; + req.weapon = skill->dbs->db[idx].weapon; - req.ammo_qty = skill->db[idx].ammo_qty[skill_lv-1]; + req.ammo_qty = skill->dbs->db[idx].ammo_qty[skill_lv-1]; if (req.ammo_qty) - req.ammo = skill->db[idx].ammo; + req.ammo = skill->dbs->db[idx].ammo; if (!req.ammo && skill_id && skill->isammotype(sd, skill_id)) { //Assume this skill is using the weapon, therefore it requires arrows. @@ -14359,11 +14364,11 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 continue; break; case AB_ADORAMUS: - if( itemid_isgemstone(skill->db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 2) ) + if( itemid_isgemstone(skill->dbs->db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 2) ) continue; break; case WL_COMET: - if( itemid_isgemstone(skill->db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 0) ) + if( itemid_isgemstone(skill->dbs->db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 0) ) continue; break; case GN_FIRE_EXPANSION: @@ -14389,8 +14394,8 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 } } - req.itemid[i] = skill->db[idx].itemid[i]; - req.amount[i] = skill->db[idx].amount[i]; + req.itemid[i] = skill->dbs->db[idx].itemid[i]; + req.amount[i] = skill->dbs->db[idx].amount[i]; if (itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN) { if (sd->special_state.no_gemstone) { @@ -14432,8 +14437,8 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 case SO_FIRE_INSIGNIA: case SO_WIND_INSIGNIA: case SO_EARTH_INSIGNIA: - req.itemid[skill_lv-1] = skill->db[idx].itemid[skill_lv-1]; - req.amount[skill_lv-1] = skill->db[idx].amount[skill_lv-1]; + req.itemid[skill_lv-1] = skill->dbs->db[idx].itemid[skill_lv-1]; + req.amount[skill_lv-1] = skill->dbs->db[idx].amount[skill_lv-1]; break; } if (skill_id == NC_REPAIR) { @@ -14737,8 +14742,11 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 fixcast_r = max(fixcast_r, sc->data[SC_DANCE_WITH_WUG]->val4); if( sc->data[SC_SECRAMENT] ) fixcast_r = max(fixcast_r, sc->data[SC_SECRAMENT]->val2); - if( sd && ( skill_lv = pc->checkskill(sd, WL_RADIUS) ) && (skill_id >= WL_WHITEIMPRISON && skill_id < WL_FREEZE_SP) ) - fixcast_r = max(fixcast_r, (status_get_int(bl) + status->get_lv(bl)) / 15 + skill_lv * 5); // [{(Caster?s INT / 15) + (Caster?s Base Level / 15) + (Radius Skill Level x 5)}] % + if (sd && skill_id >= WL_WHITEIMPRISON && skill_id < WL_FREEZE_SP) { + int radius_lv = pc->checkskill(sd, WL_RADIUS); + if (radius_lv) + fixcast_r = max(fixcast_r, (status_get_int(bl) + status->get_lv(bl)) / 15 + radius_lv * 5); // [{(Caster?s INT / 15) + (Caster?s Base Level / 15) + (Radius Skill Level x 5)}] % + } // Fixed cast non percentage bonuses if( sc->data[SC_MANDRAGORA] ) fixed += sc->data[SC_MANDRAGORA]->val1 * 500; @@ -15078,7 +15086,7 @@ void skill_repairweapon (struct map_session_data *sd, int idx) { clif->equiplist(target_sd); - pc->delitem(sd,pc->search_inventory(sd,material),1,0,0,LOG_TYPE_CONSUME); + pc->delitem(sd, pc->search_inventory(sd, material), 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); // FIXME: is this the correct reason flag? clif->item_repaireffect(sd,idx,0); @@ -15147,7 +15155,7 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) else per += 5 * ((signed int)sd->status.job_level - 50); - pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); // FIXME: is this the correct reason flag? if (per > rnd() % 1000) { int ep = 0; logs->pick_pc(sd, LOG_TYPE_OTHER, -1, item, ditem); @@ -15155,9 +15163,9 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) logs->pick_pc(sd, LOG_TYPE_OTHER, 1, item, ditem); if(item->equip) { ep = item->equip; - pc->unequipitem(sd,idx,3); + pc->unequipitem(sd, idx, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } - clif->delitem(sd,idx,1,0); + clif->delitem(sd, idx, 1, DELITEM_NORMAL); clif->upgrademessage(sd->fd, 0,item->nameid); clif->inventorylist(sd); clif->refine(sd->fd,0,idx,item->refine); @@ -15183,9 +15191,9 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) } else { item->refine = 0; if(item->equip) - pc->unequipitem(sd,idx,3); + pc->unequipitem(sd, idx, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); clif->refine(sd->fd,1,idx,item->refine); - pc->delitem(sd,idx,1,0,0, LOG_TYPE_OTHER); + pc->delitem(sd, idx, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); clif->misceffect(&sd->bl,2); clif->emotion(&sd->bl, E_OMG); } @@ -15488,7 +15496,6 @@ int skill_graffitiremover (struct block_list *bl, va_list ap) { struct skill_unit *su=NULL; nullpo_ret(bl); - nullpo_ret(ap); if(bl->type != BL_SKILL) return 0; @@ -15519,7 +15526,6 @@ int skill_detonator(struct block_list *bl, va_list ap) { int unit_id; nullpo_ret(bl); - nullpo_ret(ap); src = va_arg(ap,struct block_list *); if( bl->type != BL_SKILL ) @@ -15725,7 +15731,7 @@ int skill_trap_splash(struct block_list *bl, va_list ap) { skill->blown(src,bl,skill->get_blewcount(sg->skill_id,sg->skill_lv),-1,0); break; case UNT_ELECTRICSHOCKER: - clif->skill_damage(src,bl,tick,0,0,-30000,1,sg->skill_id,sg->skill_lv,5); + clif->skill_damage(src,bl,tick,0,0,-30000,1,sg->skill_id,sg->skill_lv,BDT_SPLASH); break; case UNT_MAGENTATRAP: case UNT_COBALTTRAP: @@ -15912,7 +15918,7 @@ bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit) return false; } - status->damage(bl, src, damage, 0, clif->damage(src, src, 500, 500, damage, hit, (hit > 1 ? 8 : 0), 0), 0); + status->damage(bl, src, damage, 0, clif->damage(src, src, 500, 500, damage, hit, (hit > 1 ? BDT_MULTIHIT : BDT_NORMAL), 0), 0); /* because damage can cancel it */ if( sc->data[SC__SHADOWFORM] && (--sc->data[SC__SHADOWFORM]->val3) <= 0 ) { @@ -15945,7 +15951,8 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int su->group=group; su->alive=1; su->val1=val1; - su->val2=val2; + su->val2 = val2; + su->prev = 0; idb_put(skill->unit_db, su->bl.id, su); map->addiddb(&su->bl); @@ -16539,7 +16546,7 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { dissonance = skill->dance_switch(su, 0); - if( su->range >= 0 && group->interval != -1 ) { + if( su->range >= 0 && group->interval != -1 && su->bl.id != su->prev) { if( battle_config.skill_wall_check ) map->foreachinshootrange(skill->unit_timer_sub_onplace, bl, su->range, group->bl_flag, bl,tick); else @@ -16555,6 +16562,8 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { group->bl_flag= BL_NUL; } } + if ( group->limit == group->interval ) + su->prev = su->bl.id; } if( dissonance ) skill->dance_switch(su, 1); @@ -16795,9 +16804,9 @@ int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger, return 0; for(i=0;i<MAX_SKILL_PRODUCE_DB;i++){ - if(skill->produce_db[i].nameid == nameid ){ - if((j=skill->produce_db[i].req_skill)>0 && - pc->checkskill(sd,j) < skill->produce_db[i].req_skill_lv) + if(skill->dbs->produce_db[i].nameid == nameid ){ + if((j=skill->dbs->produce_db[i].req_skill)>0 && + pc->checkskill(sd,j) < skill->dbs->produce_db[i].req_skill_lv) continue; // must iterate again to check other skills that produce it. [malufett] if( j > 0 && sd->menuskill_id > 0 && sd->menuskill_id != j ) continue; // special case @@ -16815,22 +16824,22 @@ int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger, if(trigger>=0){ if(trigger>20) { // Non-weapon, non-food item (itemlv must match) - if(skill->produce_db[i].itemlv!=trigger) + if(skill->dbs->produce_db[i].itemlv!=trigger) return 0; } else if(trigger>10) { // Food (any item level between 10 and 20 will do) - if(skill->produce_db[i].itemlv<=10 || skill->produce_db[i].itemlv>20) + if(skill->dbs->produce_db[i].itemlv<=10 || skill->dbs->produce_db[i].itemlv>20) return 0; } else { // Weapon (itemlv must be higher or equal) - if(skill->produce_db[i].itemlv>trigger) + if(skill->dbs->produce_db[i].itemlv>trigger) return 0; } } for (j = 0; j < MAX_PRODUCE_RESOURCE; j++) { - int id = skill->produce_db[i].mat_id[j]; + int id = skill->dbs->produce_db[i].mat_id[j]; if (id <= 0) continue; - if (skill->produce_db[i].mat_amount[j] <= 0) { + if (skill->dbs->produce_db[i].mat_amount[j] <= 0) { if (pc->search_inventory(sd,id) == INDEX_NOT_FOUND) return 0; } else { @@ -16838,7 +16847,7 @@ int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger, for(y=0,x=0;y<MAX_INVENTORY;y++) if( sd->status.inventory[y].nameid == id ) x+=sd->status.inventory[y].amount; - if(x<qty*skill->produce_db[i].mat_amount[j]) + if(x<qty*skill->dbs->produce_db[i].mat_amount[j]) return 0; } } @@ -16869,7 +16878,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, qty = 1; if (!skill_id) //A skill can be specified for some override cases. - skill_id = skill->produce_db[idx].req_skill; + skill_id = skill->dbs->produce_db[idx].req_skill; if( skill_id == GC_RESEARCHNEWPOISON ) skill_id = GC_CREATENEWPOISON; @@ -16886,12 +16895,12 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, if (j == INDEX_NOT_FOUND) continue; if( slot[i]==ITEMID_STAR_CRUMB ) { - pc->delitem(sd,j,1,1,0,LOG_TYPE_PRODUCE); + pc->delitem(sd, j, 1, 1, DELITEM_NORMAL, LOG_TYPE_PRODUCE); // FIXME: is this the correct reason flag? sc++; } if( slot[i] >= ITEMID_FLAME_HEART && slot[i] <= ITEMID_GREAT_NATURE && ele == 0 ) { static const int ele_table[4]={3,1,4,2}; - pc->delitem(sd,j,1,1,0,LOG_TYPE_PRODUCE); + pc->delitem(sd, j, 1, 1, DELITEM_NORMAL, LOG_TYPE_PRODUCE); // FIXME: is this the correct reason flag? ele=ele_table[slot[i]-994]; } } @@ -16908,7 +16917,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, for( i = 0; i < MAX_INVENTORY; i++ ) { if( sd->status.inventory[i].nameid == nameid ) { if( sd->status.inventory[i].amount >= data->stack.amount ) { - clif->msgtable(sd->fd,0x61b); + clif->msgtable(sd, MSG_RUNE_STONE_MAX_AMOUNT); return 0; } else { /** @@ -16926,10 +16935,10 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, for(i=0;i<MAX_PRODUCE_RESOURCE;i++){ int j,id,x; - if( (id=skill->produce_db[idx].mat_id[i]) <= 0 ) + if( (id=skill->dbs->produce_db[idx].mat_id[i]) <= 0 ) continue; num++; - x=( skill_id == RK_RUNEMASTERY ? 1 : qty)*skill->produce_db[idx].mat_amount[i]; + x=( skill_id == RK_RUNEMASTERY ? 1 : qty)*skill->dbs->produce_db[idx].mat_amount[i]; do{ int y=0; j = pc->search_inventory(sd,id); @@ -16937,7 +16946,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, if (j != INDEX_NOT_FOUND) { y = sd->status.inventory[j].amount; if(y>x)y=x; - pc->delitem(sd,j,y,0,0,LOG_TYPE_PRODUCE); + pc->delitem(sd, j, y, 0, DELITEM_NORMAL, LOG_TYPE_PRODUCE); // FIXME: is this the correct reason flag? } else ShowError("skill_produce_mix: material item error\n"); @@ -17070,8 +17079,8 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, break; case GN_CHANGEMATERIAL: for(i=0; i<MAX_SKILL_PRODUCE_DB; i++) - if( skill->changematerial_db[i].itemid == nameid ){ - make_per = skill->changematerial_db[i].rate * 10; + if( skill->dbs->changematerial_db[i].itemid == nameid ){ + make_per = skill->dbs->changematerial_db[i].rate * 10; break; } break; @@ -17183,7 +17192,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, + 20 * (sd->status.base_level + 1) + 20 * (st->dex + 1) + 100 * (rnd()%(30+5*(sd->cook_mastery/400) - (6+sd->cook_mastery/80)) + (6+sd->cook_mastery/80)) - - 400 * (skill->produce_db[idx].itemlv - 11 + 1) + - 400 * (skill->dbs->produce_db[idx].itemlv - 11 + 1) - 10 * (100 - st->luk + 1) - 500 * (num - 1) - 100 * (rnd()%4 + 1); @@ -17339,11 +17348,11 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, clif->misceffect(&sd->bl,5); break; default: //Those that don't require a skill? - if( skill->produce_db[idx].itemlv > 10 && skill->produce_db[idx].itemlv <= 20) + if( skill->dbs->produce_db[idx].itemlv > 10 && skill->dbs->produce_db[idx].itemlv <= 20) { //Cooking items. clif->specialeffect(&sd->bl, 608, AREA); if( sd->cook_mastery < 1999 ) - pc_setglobalreg(sd, script->add_str("COOK_MASTERY"),sd->cook_mastery + ( 1 << ( (skill->produce_db[idx].itemlv - 11) / 2 ) ) * 5); + pc_setglobalreg(sd, script->add_str("COOK_MASTERY"),sd->cook_mastery + ( 1 << ( (skill->dbs->produce_db[idx].itemlv - 11) / 2 ) ) * 5); } break; } @@ -17351,10 +17360,10 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, if ( skill_id == GN_CHANGEMATERIAL && tmp_item.amount) { //Success int j, k = 0; for(i=0; i<MAX_SKILL_PRODUCE_DB; i++) - if( skill->changematerial_db[i].itemid == nameid ){ + if( skill->dbs->changematerial_db[i].itemid == nameid ){ for(j=0; j<5; j++){ - if( rnd()%1000 < skill->changematerial_db[i].qty_rate[j] ){ - tmp_item.amount = qty * skill->changematerial_db[i].qty[j]; + if( rnd()%1000 < skill->dbs->changematerial_db[i].qty_rate[j] ){ + tmp_item.amount = qty * skill->dbs->changematerial_db[i].qty[j]; if((flag = pc->additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) { clif->additem(sd,0,0,flag); map->addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); @@ -17365,7 +17374,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, break; } if( k ){ - clif->msg_skill(sd,skill_id,0x627); + clif->msgtable_skill(sd, skill_id, MSG_SKILL_SUCCESS); return 1; } } else if (tmp_item.amount) { //Success @@ -17374,7 +17383,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, map->addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } if( skill_id == GN_MIX_COOKING || skill_id == GN_MAKEBOMB || skill_id == GN_S_PHARMACY ) - clif->msg_skill(sd,skill_id,0x627); + clif->msgtable_skill(sd, skill_id, MSG_SKILL_SUCCESS); return 1; } } @@ -17433,20 +17442,20 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, clif->additem(sd,0,0,flag); map->addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } - clif->msg_skill(sd,skill_id,0x628); + clif->msgtable_skill(sd, skill_id, MSG_SKILL_FAILURE); } break; case GN_MAKEBOMB: case GN_S_PHARMACY: case GN_CHANGEMATERIAL: - clif->msg_skill(sd,skill_id,0x628); + clif->msgtable_skill(sd, skill_id, MSG_SKILL_FAILURE); break; default: - if( skill->produce_db[idx].itemlv > 10 && skill->produce_db[idx].itemlv <= 20 ) + if( skill->dbs->produce_db[idx].itemlv > 10 && skill->dbs->produce_db[idx].itemlv <= 20 ) { //Cooking items. clif->specialeffect(&sd->bl, 609, AREA); if( sd->cook_mastery > 0 ) - pc_setglobalreg(sd, script->add_str("COOK_MASTERY"), sd->cook_mastery - ( 1 << ((skill->produce_db[idx].itemlv - 11) / 2) ) - ( ( ( 1 << ((skill->produce_db[idx].itemlv - 11) / 2) ) >> 1 ) * 3 )); + pc_setglobalreg(sd, script->add_str("COOK_MASTERY"), sd->cook_mastery - ( 1 << ((skill->dbs->produce_db[idx].itemlv - 11) / 2) ) - ( ( ( 1 << ((skill->dbs->produce_db[idx].itemlv - 11) / 2) ) >> 1 ) * 3 )); } } } @@ -17464,7 +17473,7 @@ int skill_arrow_create (struct map_session_data *sd, int nameid) return 1; for(i=0;i<MAX_SKILL_ARROW_DB;i++) - if(nameid == skill->arrow_db[i].nameid) { + if(nameid == skill->dbs->arrow_db[i].nameid) { index = i; break; } @@ -17472,12 +17481,12 @@ int skill_arrow_create (struct map_session_data *sd, int nameid) if(index < 0 || (j = pc->search_inventory(sd,nameid)) == INDEX_NOT_FOUND) return 1; - pc->delitem(sd,j,1,0,0,LOG_TYPE_PRODUCE); + pc->delitem(sd, j, 1, 0, DELITEM_NORMAL, LOG_TYPE_PRODUCE); // FIXME: is this the correct reason flag? for(i=0;i<MAX_ARROW_RESOURCE;i++) { memset(&tmp_item,0,sizeof(tmp_item)); tmp_item.identify = 1; - tmp_item.nameid = skill->arrow_db[index].cre_id[i]; - tmp_item.amount = skill->arrow_db[index].cre_amount[i]; + tmp_item.nameid = skill->dbs->arrow_db[index].cre_id[i]; + tmp_item.amount = skill->dbs->arrow_db[index].cre_amount[i]; if(battle_config.produce_item_name_input&0x4) { tmp_item.card[0]=CARD0_CREATE; tmp_item.card[1]=0; @@ -17498,7 +17507,7 @@ int skill_poisoningweapon( struct map_session_data *sd, int nameid) { sc_type type; int chance, i; nullpo_ret(sd); - if( nameid <= 0 || (i = pc->search_inventory(sd,nameid)) == INDEX_NOT_FOUND || pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME) ) { + if (nameid <= 0 || (i = pc->search_inventory(sd,nameid)) == INDEX_NOT_FOUND || pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME)) { clif->skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0); return 0; } @@ -17555,15 +17564,16 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) { nullpo_ret(sd); skill_id = sd->menuskill_val; - if (nameid <= 0 || !itemdb_is_element(nameid) || (i = pc->search_inventory(sd,nameid)) == INDEX_NOT_FOUND - || !skill_id || pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME) + if (nameid <= 0 || !itemdb_is_element(nameid) || !skill_id + || (i = pc->search_inventory(sd, nameid)) == INDEX_NOT_FOUND + || pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME) != 0 ) { clif->skill_fail(sd,NC_MAGICDECOY,USESKILL_FAIL_LEVEL,0); return 0; } // Spawn Position - pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); // FIXME: is this intended to be there twice? x = sd->sc.comet_x; y = sd->sc.comet_y; sd->sc.comet_x = sd->sc.comet_y = 0; @@ -17603,10 +17613,10 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { return 0; } - ARR_FIND(0,MAX_SKILL_SPELLBOOK_DB,i,skill->spellbook_db[i].nameid == nameid); // Search for information of this item + ARR_FIND(0,MAX_SKILL_SPELLBOOK_DB,i,skill->dbs->spellbook_db[i].nameid == nameid); // Search for information of this item if( i == MAX_SKILL_SPELLBOOK_DB ) return 0; - if( !pc->checkskill(sd, (skill_id = skill->spellbook_db[i].skill_id)) ) + if( !pc->checkskill(sd, (skill_id = skill->dbs->spellbook_db[i].skill_id)) ) { // User don't know the skill sc_start(&sd->bl, &sd->bl, SC_SLEEP, 100, 1, skill->get_time(WL_READING_SB, pc->checkskill(sd,WL_READING_SB))); clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP, 0); @@ -17614,7 +17624,7 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { } max_preserve = 4 * pc->checkskill(sd, WL_FREEZE_SP) + (status_get_int(&sd->bl) + sd->status.base_level) / 10; - point = skill->spellbook_db[i].point; + point = skill->dbs->spellbook_db[i].point; if( sc && sc->data[SC_READING_SB] ) { if( (sc->data[SC_READING_SB]->val2 + point) > max_preserve ) { @@ -17699,7 +17709,7 @@ int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, return 1; } - if( pc->delitem(sd,idx,del_amount,0,1,LOG_TYPE_CONSUME) ) { + if( pc->delitem(sd, idx, del_amount, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME) ) { clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); return 1; } @@ -17737,23 +17747,23 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite // Search for objects that can be created. for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) { - if( skill->produce_db[i].itemlv == 26 ) { + if( skill->dbs->produce_db[i].itemlv == 26 ) { p = 0; do { c = 0; // Verification of overlap between the objects required and the list submitted. for( j = 0; j < MAX_PRODUCE_RESOURCE; j++ ) { - if( skill->produce_db[i].mat_id[j] > 0 ) { + if( skill->dbs->produce_db[i].mat_id[j] > 0 ) { for( k = 0; k < n; k++ ) { int idx = item_list[k*2+0]-2; nameid = sd->status.inventory[idx].nameid; amount = item_list[k*2+1]; if( nameid > 0 && sd->status.inventory[idx].identify == 0 ){ - clif->msg_skill(sd,GN_CHANGEMATERIAL,0x62D); + clif->msgtable_skill(sd, GN_CHANGEMATERIAL, MSG_SKILL_ITEM_NEED_IDENTIFY); return 0; } - if( nameid == skill->produce_db[i].mat_id[j] && (amount-p*skill->produce_db[i].mat_amount[j]) >= skill->produce_db[i].mat_amount[j] - && (amount-p*skill->produce_db[i].mat_amount[j])%skill->produce_db[i].mat_amount[j] == 0 ) // must be in exact amount + if( nameid == skill->dbs->produce_db[i].mat_id[j] && (amount-p*skill->dbs->produce_db[i].mat_amount[j]) >= skill->dbs->produce_db[i].mat_amount[j] + && (amount-p*skill->dbs->produce_db[i].mat_amount[j])%skill->dbs->produce_db[i].mat_amount[j] == 0 ) // must be in exact amount c++; // match } } @@ -17764,14 +17774,14 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite } while(n == j && c == n); p--; if ( p > 0 ) { - skill->produce_mix(sd,GN_CHANGEMATERIAL,skill->produce_db[i].nameid,0,0,0,p); + skill->produce_mix(sd,GN_CHANGEMATERIAL,skill->dbs->produce_db[i].nameid,0,0,0,p); return 1; } } } if( p == 0) - clif->msg_skill(sd,GN_CHANGEMATERIAL,0x623); + clif->msgtable_skill(sd, GN_CHANGEMATERIAL, MSG_SKILL_ITEM_NOT_FOUND); return 0; } @@ -17894,6 +17904,9 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick) } if( i != cd->cursor ) {/* duplicate, update necessary */ + // Don't do anything if there's already a tick longer than the incoming one + if (DIFF_TICK32(cd->entry[i]->started + cd->entry[i]->duration, now) > tick) + return 0; cd->entry[i]->duration = tick; #if PACKETVER >= 20120604 cd->entry[i]->total = tick; @@ -18077,25 +18090,25 @@ void skill_init_unit_layout (void) //when != it was already cleared during skill_defaults() no need to repeat if( runflag == MAPSERVER_ST_RUNNING ) - memset(skill->unit_layout,0,sizeof(skill->unit_layout)); + memset(skill->dbs->unit_layout, 0, sizeof(skill->dbs->unit_layout)); // standard square layouts go first for (i=0; i<=MAX_SQUARE_LAYOUT; i++) { int size = i*2+1; - skill->unit_layout[i].count = size*size; + skill->dbs->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); + skill->dbs->unit_layout[i].dx[j] = (j%size-i); + skill->dbs->unit_layout[i].dy[j] = (j/size-i); } } // afterwards add special ones 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) + if (!skill->dbs->db[i].unit_id[0] || skill->dbs->db[i].unit_layout_type[0] != -1) continue; - switch (skill->db[i].nameid) { + switch (skill->dbs->db[i].nameid) { case MG_FIREWALL: case WZ_ICEWALL: case WL_EARTHSTRAIN://Warlock @@ -18109,9 +18122,9 @@ void skill_init_unit_layout (void) 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)); + skill->dbs->unit_layout[pos].count = 21; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case PR_MAGNUS: { @@ -18123,18 +18136,18 @@ void skill_init_unit_layout (void) -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)); + skill->dbs->unit_layout[pos].count = 33; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case MH_POISON_MIST: 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)); + skill->dbs->unit_layout[pos].count = 5; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case CR_GRANDCROSS: @@ -18147,9 +18160,9 @@ void skill_init_unit_layout (void) -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)); + skill->dbs->unit_layout[pos].count = 29; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case PF_FOGWALL: { @@ -18157,9 +18170,9 @@ void skill_init_unit_layout (void) -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)); + skill->dbs->unit_layout[pos].count = 15; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case PA_GOSPEL: { @@ -18173,17 +18186,17 @@ void skill_init_unit_layout (void) -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)); + skill->dbs->unit_layout[pos].count = 33; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case NJ_KAENSIN: { static const int dx[] = {-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2}; static const int dy[] = { 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2}; - skill->unit_layout[pos].count = 24; - memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy)); + skill->dbs->unit_layout[pos].count = 24; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case NJ_TATAMIGAESHI: { @@ -18198,29 +18211,29 @@ void skill_init_unit_layout (void) static const int dy3[] = { 0, 0, 0, 0, 0, 0,-3,-2,-1, 1, 2, 3}; //lv1 j = 0; - skill->unit_layout[pos].count = 4; - memcpy(skill->unit_layout[pos].dx,dx1,sizeof(dx1)); - memcpy(skill->unit_layout[pos].dy,dy1,sizeof(dy1)); - skill->db[i].unit_layout_type[j] = pos; + skill->dbs->unit_layout[pos].count = 4; + memcpy(skill->dbs->unit_layout[pos].dx,dx1,sizeof(dx1)); + memcpy(skill->dbs->unit_layout[pos].dy,dy1,sizeof(dy1)); + skill->dbs->db[i].unit_layout_type[j] = pos; //lv2/3 j++; pos++; - skill->unit_layout[pos].count = 8; - memcpy(skill->unit_layout[pos].dx,dx2,sizeof(dx2)); - memcpy(skill->unit_layout[pos].dy,dy2,sizeof(dy2)); - skill->db[i].unit_layout_type[j] = pos; - skill->db[i].unit_layout_type[++j] = pos; + skill->dbs->unit_layout[pos].count = 8; + memcpy(skill->dbs->unit_layout[pos].dx,dx2,sizeof(dx2)); + memcpy(skill->dbs->unit_layout[pos].dy,dy2,sizeof(dy2)); + skill->dbs->db[i].unit_layout_type[j] = pos; + skill->dbs->db[i].unit_layout_type[++j] = pos; //lv4/5 j++; pos++; - skill->unit_layout[pos].count = 12; - memcpy(skill->unit_layout[pos].dx,dx3,sizeof(dx3)); - memcpy(skill->unit_layout[pos].dy,dy3,sizeof(dy3)); - skill->db[i].unit_layout_type[j] = pos; - skill->db[i].unit_layout_type[++j] = pos; + skill->dbs->unit_layout[pos].count = 12; + memcpy(skill->dbs->unit_layout[pos].dx,dx3,sizeof(dx3)); + memcpy(skill->dbs->unit_layout[pos].dy,dy3,sizeof(dy3)); + skill->dbs->db[i].unit_layout_type[j] = pos; + skill->dbs->db[i].unit_layout_type[++j] = pos; //Fill in the rest using lv 5. for (;j<MAX_SKILL_LEVEL;j++) - skill->db[i].unit_layout_type[j] = pos; + skill->dbs->db[i].unit_layout_type[j] = pos; //Skip, this way the check below will fail and continue to the next skill. pos++; } @@ -18228,27 +18241,27 @@ void skill_init_unit_layout (void) case GN_WALLOFTHORN: { static const int dx[] = {-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2, 2, 2, 1, 0}; static const int dy[] = { 2, 2, 1, 0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2}; - skill->unit_layout[pos].count = 16; - memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy)); + skill->dbs->unit_layout[pos].count = 16; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case EL_FIRE_MANTLE: { static const int dx[] = {-1, 0, 1, 1, 1, 0,-1,-1}; static const int dy[] = { 1, 1, 1, 0,-1,-1,-1, 0}; - skill->unit_layout[pos].count = 8; - memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy)); + skill->dbs->unit_layout[pos].count = 8; + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; default: ShowError("unknown unit layout at skill %d\n",i); break; } - if (!skill->unit_layout[pos].count) + if (!skill->dbs->unit_layout[pos].count) continue; for (j=0;j<MAX_SKILL_LEVEL;j++) - skill->db[i].unit_layout_type[j] = pos; + skill->dbs->db[i].unit_layout_type[j] = pos; pos++; } @@ -18256,60 +18269,60 @@ void skill_init_unit_layout (void) skill->firewall_unit_pos = pos; for (i=0;i<8;i++) { if (i&1) { - skill->unit_layout[pos].count = 5; + skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } } else { - skill->unit_layout[pos].count = 3; + skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } } pos++; } skill->icewall_unit_pos = pos; for (i=0;i<8;i++) { - skill->unit_layout[pos].count = 5; + skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->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)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } } pos++; @@ -18317,15 +18330,15 @@ void skill_init_unit_layout (void) skill->earthstrain_unit_pos = pos; for( i = 0; i < 8; i++ ) { // For each Direction - skill->unit_layout[pos].count = 15; + skill->dbs->unit_layout[pos].count = 15; switch( i ) { case 0: case 1: case 3: case 4: case 5: case 7: { int dx[] = {-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}; int dy[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; case 2: @@ -18333,8 +18346,8 @@ void skill_init_unit_layout (void) { int dx[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int dy[] = {-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}; - memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy)); + memcpy(skill->dbs->unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill->dbs->unit_layout[pos].dy,dy,sizeof(dy)); } break; } @@ -18581,36 +18594,36 @@ bool skill_parse_row_skilldb(char* split[], int columns, int current) { if( !idx ) // invalid skill id return false; - skill->db[idx].nameid = skill_id; - skill->split_atoi(split[1],skill->db[idx].range); - skill->db[idx].hit = atoi(split[2]); - skill->db[idx].inf = atoi(split[3]); - skill->split_atoi(split[4],skill->db[idx].element); - skill->db[idx].nk = (int)strtol(split[5], NULL, 0); - skill->split_atoi(split[6],skill->db[idx].splash); - skill->db[idx].max = atoi(split[7]); - skill->split_atoi(split[8],skill->db[idx].num); + skill->dbs->db[idx].nameid = skill_id; + skill->split_atoi(split[1],skill->dbs->db[idx].range); + skill->dbs->db[idx].hit = atoi(split[2]); + skill->dbs->db[idx].inf = atoi(split[3]); + skill->split_atoi(split[4],skill->dbs->db[idx].element); + skill->dbs->db[idx].nk = (int)strtol(split[5], NULL, 0); + skill->split_atoi(split[6],skill->dbs->db[idx].splash); + skill->dbs->db[idx].max = atoi(split[7]); + skill->split_atoi(split[8],skill->dbs->db[idx].num); if( strcmpi(split[9],"yes") == 0 ) - skill->db[idx].castcancel = 1; + skill->dbs->db[idx].castcancel = 1; else - skill->db[idx].castcancel = 0; - skill->db[idx].cast_def_rate = atoi(split[10]); - skill->db[idx].inf2 = (int)strtol(split[11], NULL, 0); - skill->split_atoi(split[12],skill->db[idx].maxcount); + skill->dbs->db[idx].castcancel = 0; + skill->dbs->db[idx].cast_def_rate = atoi(split[10]); + skill->dbs->db[idx].inf2 = (int)strtol(split[11], NULL, 0); + skill->split_atoi(split[12],skill->dbs->db[idx].maxcount); if( strcmpi(split[13],"weapon") == 0 ) - skill->db[idx].skill_type = BF_WEAPON; + skill->dbs->db[idx].skill_type = BF_WEAPON; else if( strcmpi(split[13],"magic") == 0 ) - skill->db[idx].skill_type = BF_MAGIC; + skill->dbs->db[idx].skill_type = BF_MAGIC; else if( strcmpi(split[13],"misc") == 0 ) - skill->db[idx].skill_type = BF_MISC; + skill->dbs->db[idx].skill_type = BF_MISC; else - skill->db[idx].skill_type = 0; - skill->split_atoi(split[14],skill->db[idx].blewcount); - safestrncpy(skill->db[idx].name, trim(split[15]), sizeof(skill->db[idx].name)); - safestrncpy(skill->db[idx].desc, trim(split[16]), sizeof(skill->db[idx].desc)); - strdb_iput(skill->name2id_db, skill->db[idx].name, skill_id); - script->set_constant2(skill->db[idx].name,(int)skill_id,0); + skill->dbs->db[idx].skill_type = 0; + skill->split_atoi(split[14],skill->dbs->db[idx].blewcount); + safestrncpy(skill->dbs->db[idx].name, trim(split[15]), sizeof(skill->dbs->db[idx].name)); + safestrncpy(skill->dbs->db[idx].desc, trim(split[16]), sizeof(skill->dbs->db[idx].desc)); + strdb_iput(skill->name2id_db, skill->dbs->db[idx].name, skill_id); + script->set_constant2(skill->dbs->db[idx].name,(int)skill_id,0); return true; } @@ -18625,22 +18638,22 @@ bool skill_parse_row_requiredb(char* split[], int columns, int current) { if( !idx ) // invalid skill id return false; - skill->split_atoi(split[1],skill->db[idx].hp); - skill->split_atoi(split[2],skill->db[idx].mhp); - skill->split_atoi(split[3],skill->db[idx].sp); - skill->split_atoi(split[4],skill->db[idx].hp_rate); - skill->split_atoi(split[5],skill->db[idx].sp_rate); - skill->split_atoi(split[6],skill->db[idx].zeny); + skill->split_atoi(split[1],skill->dbs->db[idx].hp); + skill->split_atoi(split[2],skill->dbs->db[idx].mhp); + skill->split_atoi(split[3],skill->dbs->db[idx].sp); + skill->split_atoi(split[4],skill->dbs->db[idx].hp_rate); + skill->split_atoi(split[5],skill->dbs->db[idx].sp_rate); + skill->split_atoi(split[6],skill->dbs->db[idx].zeny); //Which weapon type are required, see doc/item_db for types p = split[7]; for( j = 0; j < 32; j++ ) { int l = atoi(p); if( l == 99 ) { // Any weapon - skill->db[idx].weapon = 0; + skill->dbs->db[idx].weapon = 0; break; } else - skill->db[idx].weapon |= 1<<l; + skill->dbs->db[idx].weapon |= 1<<l; p = strchr(p,':'); if(!p) break; @@ -18652,49 +18665,49 @@ bool skill_parse_row_requiredb(char* split[], int columns, int current) { for( j = 0; j < 32; j++ ) { int l = atoi(p); if( l == 99 ) { // Any ammo type - skill->db[idx].ammo = 0xFFFFFFFF; + skill->dbs->db[idx].ammo = 0xFFFFFFFF; break; } else if( l ) // 0 stands for no requirement - skill->db[idx].ammo |= 1<<l; + skill->dbs->db[idx].ammo |= 1<<l; p = strchr(p,':'); if( !p ) break; p++; } - skill->split_atoi(split[9],skill->db[idx].ammo_qty); - - if( strcmpi(split[10],"hiding") == 0 ) skill->db[idx].state = ST_HIDING; - else if( strcmpi(split[10],"cloaking") == 0 ) skill->db[idx].state = ST_CLOAKING; - else if( strcmpi(split[10],"hidden") == 0 ) skill->db[idx].state = ST_HIDDEN; - else if( strcmpi(split[10],"riding") == 0 ) skill->db[idx].state = ST_RIDING; - else if( strcmpi(split[10],"falcon") == 0 ) skill->db[idx].state = ST_FALCON; - else if( strcmpi(split[10],"cart") == 0 ) skill->db[idx].state = ST_CART; - else if( strcmpi(split[10],"shield") == 0 ) skill->db[idx].state = ST_SHIELD; - else if( strcmpi(split[10],"sight") == 0 ) skill->db[idx].state = ST_SIGHT; - else if( strcmpi(split[10],"explosionspirits") == 0 ) skill->db[idx].state = ST_EXPLOSIONSPIRITS; - else if( strcmpi(split[10],"cartboost") == 0 ) skill->db[idx].state = ST_CARTBOOST; - else if( strcmpi(split[10],"recover_weight_rate") == 0 ) skill->db[idx].state = ST_RECOV_WEIGHT_RATE; - else if( strcmpi(split[10],"move_enable") == 0 ) skill->db[idx].state = ST_MOVE_ENABLE; - else if( strcmpi(split[10],"water") == 0 ) skill->db[idx].state = ST_WATER; - else if( strcmpi(split[10],"dragon") == 0 ) skill->db[idx].state = ST_RIDINGDRAGON; - else if( strcmpi(split[10],"warg") == 0 ) skill->db[idx].state = ST_WUG; - else if( strcmpi(split[10],"ridingwarg") == 0 ) skill->db[idx].state = ST_RIDINGWUG; - else if( strcmpi(split[10],"mado") == 0 ) skill->db[idx].state = ST_MADO; - else if( strcmpi(split[10],"elementalspirit") == 0 ) skill->db[idx].state = ST_ELEMENTALSPIRIT; - else if( strcmpi(split[10],"poisonweapon") == 0 ) skill->db[idx].state = ST_POISONINGWEAPON; - else if( strcmpi(split[10],"rollingcutter") == 0 ) skill->db[idx].state = ST_ROLLINGCUTTER; - else if( strcmpi(split[10],"mh_fighting") == 0 ) skill->db[idx].state = ST_MH_FIGHTING; - else if( strcmpi(split[10],"mh_grappling") == 0 ) skill->db[idx].state = ST_MH_GRAPPLING; - else if( strcmpi(split[10],"peco") == 0 ) skill->db[idx].state = ST_PECO; + skill->split_atoi(split[9],skill->dbs->db[idx].ammo_qty); + + if( strcmpi(split[10],"hiding") == 0 ) skill->dbs->db[idx].state = ST_HIDING; + else if( strcmpi(split[10],"cloaking") == 0 ) skill->dbs->db[idx].state = ST_CLOAKING; + else if( strcmpi(split[10],"hidden") == 0 ) skill->dbs->db[idx].state = ST_HIDDEN; + else if( strcmpi(split[10],"riding") == 0 ) skill->dbs->db[idx].state = ST_RIDING; + else if( strcmpi(split[10],"falcon") == 0 ) skill->dbs->db[idx].state = ST_FALCON; + else if( strcmpi(split[10],"cart") == 0 ) skill->dbs->db[idx].state = ST_CART; + else if( strcmpi(split[10],"shield") == 0 ) skill->dbs->db[idx].state = ST_SHIELD; + else if( strcmpi(split[10],"sight") == 0 ) skill->dbs->db[idx].state = ST_SIGHT; + else if( strcmpi(split[10],"explosionspirits") == 0 ) skill->dbs->db[idx].state = ST_EXPLOSIONSPIRITS; + else if( strcmpi(split[10],"cartboost") == 0 ) skill->dbs->db[idx].state = ST_CARTBOOST; + else if( strcmpi(split[10],"recover_weight_rate") == 0 ) skill->dbs->db[idx].state = ST_RECOV_WEIGHT_RATE; + else if( strcmpi(split[10],"move_enable") == 0 ) skill->dbs->db[idx].state = ST_MOVE_ENABLE; + else if( strcmpi(split[10],"water") == 0 ) skill->dbs->db[idx].state = ST_WATER; + else if( strcmpi(split[10],"dragon") == 0 ) skill->dbs->db[idx].state = ST_RIDINGDRAGON; + else if( strcmpi(split[10],"warg") == 0 ) skill->dbs->db[idx].state = ST_WUG; + else if( strcmpi(split[10],"ridingwarg") == 0 ) skill->dbs->db[idx].state = ST_RIDINGWUG; + else if( strcmpi(split[10],"mado") == 0 ) skill->dbs->db[idx].state = ST_MADO; + else if( strcmpi(split[10],"elementalspirit") == 0 ) skill->dbs->db[idx].state = ST_ELEMENTALSPIRIT; + else if( strcmpi(split[10],"poisonweapon") == 0 ) skill->dbs->db[idx].state = ST_POISONINGWEAPON; + else if( strcmpi(split[10],"rollingcutter") == 0 ) skill->dbs->db[idx].state = ST_ROLLINGCUTTER; + else if( strcmpi(split[10],"mh_fighting") == 0 ) skill->dbs->db[idx].state = ST_MH_FIGHTING; + else if( strcmpi(split[10],"mh_grappling") == 0 ) skill->dbs->db[idx].state = ST_MH_GRAPPLING; + else if( strcmpi(split[10],"peco") == 0 ) skill->dbs->db[idx].state = ST_PECO; /** * Unknown or no state **/ - else skill->db[idx].state = ST_NONE; + else skill->dbs->db[idx].state = ST_NONE; - skill->split_atoi(split[11],skill->db[idx].spiritball); + skill->split_atoi(split[11],skill->dbs->db[idx].spiritball); for( j = 0; j < MAX_SKILL_ITEM_REQUIRE; j++ ) { - skill->db[idx].itemid[j] = atoi(split[12+ 2*j]); - skill->db[idx].amount[j] = atoi(split[13+ 2*j]); + skill->dbs->db[idx].itemid[j] = atoi(split[12+ 2*j]); + skill->dbs->db[idx].amount[j] = atoi(split[13+ 2*j]); } return true; @@ -18707,14 +18720,14 @@ bool skill_parse_row_castdb(char* split[], int columns, int current) { if( !idx ) // invalid skill id return false; - skill->split_atoi(split[1],skill->db[idx].cast); - skill->split_atoi(split[2],skill->db[idx].delay); - skill->split_atoi(split[3],skill->db[idx].walkdelay); - skill->split_atoi(split[4],skill->db[idx].upkeep_time); - skill->split_atoi(split[5],skill->db[idx].upkeep_time2); - skill->split_atoi(split[6],skill->db[idx].cooldown); + skill->split_atoi(split[1],skill->dbs->db[idx].cast); + skill->split_atoi(split[2],skill->dbs->db[idx].delay); + skill->split_atoi(split[3],skill->dbs->db[idx].walkdelay); + skill->split_atoi(split[4],skill->dbs->db[idx].upkeep_time); + skill->split_atoi(split[5],skill->dbs->db[idx].upkeep_time2); + skill->split_atoi(split[6],skill->dbs->db[idx].cooldown); #ifdef RENEWAL_CAST - skill->split_atoi(split[7],skill->db[idx].fixed_cast); + skill->split_atoi(split[7],skill->dbs->db[idx].fixed_cast); #endif return true; } @@ -18726,9 +18739,9 @@ bool skill_parse_row_castnodexdb(char* split[], int columns, int current) { if( !idx ) // invalid skill id return false; - skill->split_atoi(split[1],skill->db[idx].castnodex); + skill->split_atoi(split[1],skill->dbs->db[idx].castnodex); if( split[2] ) // optional column - skill->split_atoi(split[2],skill->db[idx].delaynodex); + skill->split_atoi(split[2],skill->dbs->db[idx].delaynodex); return true; } @@ -18740,37 +18753,37 @@ bool skill_parse_row_unitdb(char* split[], int columns, int current) { if( !idx ) // invalid skill id return false; - skill->db[idx].unit_id[0] = (int)strtol(split[1],NULL,16); - skill->db[idx].unit_id[1] = (int)strtol(split[2],NULL,16); - skill->split_atoi(split[3],skill->db[idx].unit_layout_type); - skill->split_atoi(split[4],skill->db[idx].unit_range); - skill->db[idx].unit_interval = atoi(split[5]); - - if( strcmpi(split[6],"noenemy")==0 ) skill->db[idx].unit_target = BCT_NOENEMY; - else if( strcmpi(split[6],"friend")==0 ) skill->db[idx].unit_target = BCT_NOENEMY; - else if( strcmpi(split[6],"party")==0 ) skill->db[idx].unit_target = BCT_PARTY; - else if( strcmpi(split[6],"ally")==0 ) skill->db[idx].unit_target = BCT_PARTY|BCT_GUILD; - else if( strcmpi(split[6],"guild")==0 ) skill->db[idx].unit_target = BCT_GUILD; - else if( strcmpi(split[6],"all")==0 ) skill->db[idx].unit_target = BCT_ALL; - else if( strcmpi(split[6],"enemy")==0 ) skill->db[idx].unit_target = BCT_ENEMY; - else if( strcmpi(split[6],"self")==0 ) skill->db[idx].unit_target = BCT_SELF; - else if( strcmpi(split[6],"sameguild")==0 ) skill->db[idx].unit_target = BCT_GUILD|BCT_SAMEGUILD; - else if( strcmpi(split[6],"noone")==0 ) skill->db[idx].unit_target = BCT_NOONE; - else skill->db[idx].unit_target = (int)strtol(split[6],NULL,16); - - skill->db[idx].unit_flag = (int)strtol(split[7],NULL,16); - - if (skill->db[idx].unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy) - skill->db[idx].unit_target = BCT_NOENEMY; + skill->dbs->db[idx].unit_id[0] = (int)strtol(split[1],NULL,16); + skill->dbs->db[idx].unit_id[1] = (int)strtol(split[2],NULL,16); + skill->split_atoi(split[3],skill->dbs->db[idx].unit_layout_type); + skill->split_atoi(split[4],skill->dbs->db[idx].unit_range); + skill->dbs->db[idx].unit_interval = atoi(split[5]); + + if( strcmpi(split[6],"noenemy")==0 ) skill->dbs->db[idx].unit_target = BCT_NOENEMY; + else if( strcmpi(split[6],"friend")==0 ) skill->dbs->db[idx].unit_target = BCT_NOENEMY; + else if( strcmpi(split[6],"party")==0 ) skill->dbs->db[idx].unit_target = BCT_PARTY; + else if( strcmpi(split[6],"ally")==0 ) skill->dbs->db[idx].unit_target = BCT_PARTY|BCT_GUILD; + else if( strcmpi(split[6],"guild")==0 ) skill->dbs->db[idx].unit_target = BCT_GUILD; + else if( strcmpi(split[6],"all")==0 ) skill->dbs->db[idx].unit_target = BCT_ALL; + else if( strcmpi(split[6],"enemy")==0 ) skill->dbs->db[idx].unit_target = BCT_ENEMY; + else if( strcmpi(split[6],"self")==0 ) skill->dbs->db[idx].unit_target = BCT_SELF; + else if( strcmpi(split[6],"sameguild")==0 ) skill->dbs->db[idx].unit_target = BCT_GUILD|BCT_SAMEGUILD; + else if( strcmpi(split[6],"noone")==0 ) skill->dbs->db[idx].unit_target = BCT_NOONE; + else skill->dbs->db[idx].unit_target = (int)strtol(split[6],NULL,16); + + skill->dbs->db[idx].unit_flag = (int)strtol(split[7],NULL,16); + + if (skill->dbs->db[idx].unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy) + skill->dbs->db[idx].unit_target = BCT_NOENEMY; //By default, target just characters. - skill->db[idx].unit_target |= BL_CHAR; - if (skill->db[idx].unit_flag&UF_NOPC) - skill->db[idx].unit_target &= ~BL_PC; - if (skill->db[idx].unit_flag&UF_NOMOB) - skill->db[idx].unit_target &= ~BL_MOB; - if (skill->db[idx].unit_flag&UF_SKILL) - skill->db[idx].unit_target |= BL_SKILL; + skill->dbs->db[idx].unit_target |= BL_CHAR; + if (skill->dbs->db[idx].unit_flag&UF_NOPC) + skill->dbs->db[idx].unit_target &= ~BL_PC; + if (skill->dbs->db[idx].unit_flag&UF_NOMOB) + skill->dbs->db[idx].unit_target &= ~BL_MOB; + if (skill->dbs->db[idx].unit_flag&UF_SKILL) + skill->dbs->db[idx].unit_target |= BL_SKILL; return true; } @@ -18783,14 +18796,14 @@ bool skill_parse_row_producedb(char* split[], int columns, int current) { if( !i ) return false; - skill->produce_db[current].nameid = i; - skill->produce_db[current].itemlv = atoi(split[1]); - skill->produce_db[current].req_skill = atoi(split[2]); - skill->produce_db[current].req_skill_lv = atoi(split[3]); + skill->dbs->produce_db[current].nameid = i; + skill->dbs->produce_db[current].itemlv = atoi(split[1]); + skill->dbs->produce_db[current].req_skill = atoi(split[2]); + skill->dbs->produce_db[current].req_skill_lv = atoi(split[3]); for( x = 4, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_PRODUCE_RESOURCE; x += 2, y++ ) { - skill->produce_db[current].mat_id[y] = atoi(split[x]); - skill->produce_db[current].mat_amount[y] = atoi(split[x+1]); + skill->dbs->produce_db[current].mat_id[y] = atoi(split[x]); + skill->dbs->produce_db[current].mat_amount[y] = atoi(split[x+1]); } return true; @@ -18804,11 +18817,11 @@ bool skill_parse_row_createarrowdb(char* split[], int columns, int current) { if( !i ) return false; - skill->arrow_db[current].nameid = i; + skill->dbs->arrow_db[current].nameid = i; for( x = 1, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_ARROW_RESOURCE; x += 2, y++ ) { - skill->arrow_db[current].cre_id[y] = atoi(split[x]); - skill->arrow_db[current].cre_amount[y] = atoi(split[x+1]); + skill->dbs->arrow_db[current].cre_id[y] = atoi(split[x]); + skill->dbs->arrow_db[current].cre_amount[y] = atoi(split[x+1]); } return true; @@ -18827,9 +18840,9 @@ bool skill_parse_row_spellbookdb(char* split[], int columns, int current) { if( points < 1 ) ShowError("spellbook_db: PreservePoints have to be 1 or above! (%d/%s)\n", skill_id, skill->get_name(skill_id)); else { - skill->spellbook_db[current].skill_id = skill_id; - skill->spellbook_db[current].point = points; - skill->spellbook_db[current].nameid = nameid; + skill->dbs->spellbook_db[current].skill_id = skill_id; + skill->dbs->spellbook_db[current].point = points; + skill->dbs->spellbook_db[current].nameid = nameid; return true; } @@ -18857,8 +18870,8 @@ bool skill_parse_row_improvisedb(char* split[], int columns, int current) { ShowError("skill_improvise_db: Maximum amount of entries reached (%d), increase MAX_SKILL_IMPROVISE_DB\n",MAX_SKILL_IMPROVISE_DB); return false; } - skill->improvise_db[current].skill_id = skill_id; - skill->improvise_db[current].per = j; // Still need confirm it. + skill->dbs->improvise_db[current].skill_id = skill_id; + skill->dbs->improvise_db[current].per = j; // Still need confirm it. return true; } @@ -18875,7 +18888,7 @@ bool skill_parse_row_magicmushroomdb(char* split[], int column, int current) { return false; } - skill->magicmushroom_db[current].skill_id = skill_id; + skill->dbs->magicmushroom_db[current].skill_id = skill_id; return true; } @@ -18886,7 +18899,7 @@ bool skill_parse_row_reproducedb(char* split[], int column, int current) { if( !idx ) return false; - skill->reproduce_db[idx] = true; + skill->dbs->reproduce_db[idx] = true; return true; } @@ -18904,9 +18917,9 @@ bool skill_parse_row_abradb(char* split[], int columns, int current) { return false; } - skill->abra_db[current].skill_id = skill_id; - skill->abra_db[current].req_lv = atoi(split[2]); - skill->abra_db[current].per = atoi(split[3]); + skill->dbs->abra_db[current].skill_id = skill_id; + skill->dbs->abra_db[current].req_lv = atoi(split[2]); + skill->dbs->abra_db[current].per = atoi(split[3]); return true; } @@ -18918,8 +18931,8 @@ bool skill_parse_row_changematerialdb(char* split[], int columns, int current) { int x,y; for(x=0; x<MAX_SKILL_PRODUCE_DB; x++){ - if( skill->produce_db[x].nameid == skill_id ) - if( skill->produce_db[x].req_skill == GN_CHANGEMATERIAL ) + if( skill->dbs->produce_db[x].nameid == skill_id ) + if( skill->dbs->produce_db[x].req_skill == GN_CHANGEMATERIAL ) break; } @@ -18933,12 +18946,12 @@ bool skill_parse_row_changematerialdb(char* split[], int columns, int current) { return false; } - skill->changematerial_db[current].itemid = skill_id; - skill->changematerial_db[current].rate = j; + skill->dbs->changematerial_db[current].itemid = skill_id; + skill->dbs->changematerial_db[current].rate = j; for( x = 2, y = 0; x+1 < columns && split[x] && split[x+1] && y < 5; x += 2, y++ ) { - skill->changematerial_db[current].qty[y] = atoi(split[x]); - skill->changematerial_db[current].qty_rate[y] = atoi(split[x+1]); + skill->dbs->changematerial_db[current].qty[y] = atoi(split[x]); + skill->dbs->changematerial_db[current].qty_rate[y] = atoi(split[x+1]); } return true; @@ -18962,21 +18975,12 @@ void skill_readdb(bool minimal) { /* when != it was called during init and this procedure was already performed by skill_defaults() */ if( runflag == MAPSERVER_ST_RUNNING ) { - memset(skill->db,0,sizeof(skill->db) - + sizeof(skill->produce_db) - + sizeof(skill->arrow_db) - + sizeof(skill->abra_db) - + sizeof(skill->magicmushroom_db) - + sizeof(skill->improvise_db) - + sizeof(skill->changematerial_db) - + sizeof(skill->spellbook_db) - + sizeof(skill->reproduce_db) - ); + memset(ZEROED_BLOCK_POS(skill->dbs), 0, ZEROED_BLOCK_SIZE(skill->dbs)); } // load skill databases - safestrncpy(skill->db[0].name, "UNKNOWN_SKILL", sizeof(skill->db[0].name)); - safestrncpy(skill->db[0].desc, "Unknown Skill", sizeof(skill->db[0].desc)); + safestrncpy(skill->dbs->db[0].name, "UNKNOWN_SKILL", sizeof(skill->dbs->db[0].name)); + safestrncpy(skill->dbs->db[0].desc, "Unknown Skill", sizeof(skill->dbs->db[0].desc)); #ifdef ENABLE_CASE_CHECK script->parser_current_file = DBPATH"skill_db.txt"; @@ -19094,6 +19098,8 @@ void skill_defaults(void) { const int skill_deluge_eff[5] = { 5, 9, 12, 14, 15 }; skill = &skill_s; + skill->dbs = &skilldbs; + skill->init = do_init_skill; skill->final = do_final_skill; skill->reload = skill_reload; @@ -19110,18 +19116,10 @@ void skill_defaults(void) { skill->timer_ers = NULL; skill->cd_ers = NULL; skill->cd_entry_ers = NULL; - /* one huge 0, follows skill.h order */ - memset(skill->db,0,sizeof(skill->db) - + sizeof(skill->produce_db) - + sizeof(skill->arrow_db) - + sizeof(skill->abra_db) - + sizeof(skill->magicmushroom_db) - + sizeof(skill->improvise_db) - + sizeof(skill->changematerial_db) - + sizeof(skill->spellbook_db) - + sizeof(skill->reproduce_db) - + sizeof(skill->unit_layout) - ); + + memset(ZEROED_BLOCK_POS(skill->dbs), 0, ZEROED_BLOCK_SIZE(skill->dbs)); + memset(skill->dbs->unit_layout, 0, sizeof(skill->dbs->unit_layout)); + /* */ memcpy(skill->enchant_eff, skill_enchant_eff, sizeof(skill->enchant_eff)); memcpy(skill->deluge_eff, skill_deluge_eff, sizeof(skill->deluge_eff)); diff --git a/src/map/skill.h b/src/map/skill.h index b598b91c8..aa0188be6 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -5,13 +5,13 @@ #ifndef MAP_SKILL_H #define MAP_SKILL_H -#include "../config/core.h" // RENEWAL_CAST +#include "config/core.h" // RENEWAL_CAST -#include "map.h" // struct block_list -#include "status.h" // enum sc_type -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/mmo.h" // MAX_SKILL, struct square +#include "map/map.h" // struct block_list +#include "map/status.h" // enum sc_type +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/mmo.h" // MAX_SKILL, struct square /** * Declarations @@ -1732,6 +1732,7 @@ struct skill_unit { int limit; int val1,val2; short alive,range; + int prev; }; struct skill_unit_group_tickset { @@ -1813,6 +1814,21 @@ struct s_skill_spellbook_db { typedef int (*SkillFunc)(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 tick, int flag); +struct s_skill_dbs { +BEGIN_ZEROED_BLOCK; // This block will be zeroed in skill_defaults() as well as skill_readdb() + struct s_skill_db db[MAX_SKILL_DB]; + struct s_skill_produce_db produce_db[MAX_SKILL_PRODUCE_DB]; + struct s_skill_arrow_db arrow_db[MAX_SKILL_ARROW_DB]; + struct s_skill_abra_db abra_db[MAX_SKILL_ABRA_DB]; + struct s_skill_magicmushroom_db magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB]; + struct s_skill_improvise_db improvise_db[MAX_SKILL_IMPROVISE_DB]; + struct s_skill_changematerial_db changematerial_db[MAX_SKILL_PRODUCE_DB]; + struct s_skill_spellbook_db spellbook_db[MAX_SKILL_SPELLBOOK_DB]; + bool reproduce_db[MAX_SKILL_DB]; +END_ZEROED_BLOCK; + struct s_skill_unit_layout unit_layout[MAX_SKILL_UNIT_LAYOUT]; +}; + /** * Skill.c Interface **/ @@ -1834,16 +1850,7 @@ struct skill_interface { struct eri *cd_ers; // ERS Storage for skill cool down managers [Ind/Hercules] struct eri *cd_entry_ers; // ERS Storage for skill cool down entries [Ind/Hercules] /* */ - struct s_skill_db db[MAX_SKILL_DB]; - struct s_skill_produce_db produce_db[MAX_SKILL_PRODUCE_DB]; - struct s_skill_arrow_db arrow_db[MAX_SKILL_ARROW_DB]; - struct s_skill_abra_db abra_db[MAX_SKILL_ABRA_DB]; - struct s_skill_magicmushroom_db magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB]; - struct s_skill_improvise_db improvise_db[MAX_SKILL_IMPROVISE_DB]; - struct s_skill_changematerial_db changematerial_db[MAX_SKILL_PRODUCE_DB]; - struct s_skill_spellbook_db spellbook_db[MAX_SKILL_SPELLBOOK_DB]; - bool reproduce_db[MAX_SKILL_DB]; - struct s_skill_unit_layout unit_layout[MAX_SKILL_UNIT_LAYOUT]; + struct s_skill_dbs *dbs; /* */ int enchant_eff[5]; int deluge_eff[5]; diff --git a/src/map/status.c b/src/map/status.c index 16f5f3906..b513c6975 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -4,9 +4,38 @@ #define HERCULES_CORE -#include "../config/core.h" // ANTI_MAYAP_CHEAT, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, DEVOTION_REFLECT_DAMAGE, RENEWAL, RENEWAL_ASPD, RENEWAL_EDP +#include "config/core.h" // ANTI_MAYAP_CHEAT, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, DEVOTION_REFLECT_DAMAGE, RENEWAL, RENEWAL_ASPD, RENEWAL_EDP #include "status.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/itemdb.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/skill.h" +#include "map/unit.h" +#include "map/vending.h" +#include "common/cbasetypes.h" +#include "common/ers.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/strlib.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <memory.h> #include <stdio.h> @@ -14,36 +43,8 @@ #include <string.h> #include <time.h> -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "itemdb.h" -#include "map.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "skill.h" -#include "skill.h" -#include "unit.h" -#include "vending.h" -#include "../common/cbasetypes.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct status_interface status_s; +struct s_status_dbs statusdbs; /** * Returns the status change associated with a skill. @@ -56,7 +57,7 @@ sc_type status_skill2sc(int skill_id) { ShowError("status_skill2sc: Unsupported skill id %d\n", skill_id); return SC_NONE; } - return status->Skill2SCTable[idx]; + return status->dbs->Skill2SCTable[idx]; } /** @@ -72,7 +73,7 @@ int status_sc2skill(sc_type sc) return 0; } - return status->SkillChangeTable[sc]; + return status->dbs->SkillChangeTable[sc]; } /** @@ -87,7 +88,7 @@ unsigned int status_sc2scb_flag(sc_type sc) return SCB_NONE; } - return status->ChangeFlagTable[sc]; + return status->dbs->ChangeFlagTable[sc]; } /** @@ -102,7 +103,7 @@ int status_type2relevant_bl_types(int type) return BL_NUL; } - return status->RelevantBLTypes[type]; + return status->dbs->RelevantBLTypes[type]; } static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) { @@ -116,35 +117,35 @@ static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) { return; } - if( status->SkillChangeTable[sc] == 0 ) - status->SkillChangeTable[sc] = skill_id; - if( status->IconChangeTable[sc] == SI_BLANK ) - status->IconChangeTable[sc] = icon; - status->ChangeFlagTable[sc] |= flag; + if( status->dbs->SkillChangeTable[sc] == 0 ) + status->dbs->SkillChangeTable[sc] = skill_id; + if( status->dbs->IconChangeTable[sc] == SI_BLANK ) + status->dbs->IconChangeTable[sc] = icon; + status->dbs->ChangeFlagTable[sc] |= flag; - if( status->Skill2SCTable[idx] == SC_NONE ) - status->Skill2SCTable[idx] = sc; + if( status->dbs->Skill2SCTable[idx] == SC_NONE ) + status->dbs->Skill2SCTable[idx] = sc; } void initChangeTables(void) { #define add_sc(skill,sc) set_sc((skill),(sc),SI_BLANK,SCB_NONE) // indicates that the status displays a visual effect for the affected unit, and should be sent to the client for all supported units -#define set_sc_with_vfx(skill, sc, icon, flag) do { set_sc((skill), (sc), (icon), (flag)); if((icon) < SI_MAX) status->RelevantBLTypes[(icon)] |= BL_SCEFFECT; } while(0) +#define set_sc_with_vfx(skill, sc, icon, flag) do { set_sc((skill), (sc), (icon), (flag)); if((icon) < SI_MAX) status->dbs->RelevantBLTypes[(icon)] |= BL_SCEFFECT; } while(0) int i; for (i = 0; i < SC_MAX; i++) - status->IconChangeTable[i] = SI_BLANK; + status->dbs->IconChangeTable[i] = SI_BLANK; for (i = 0; i < MAX_SKILL; i++) - status->Skill2SCTable[i] = SC_NONE; + status->dbs->Skill2SCTable[i] = SC_NONE; for (i = 0; i < SI_MAX; i++) - status->RelevantBLTypes[i] = BL_PC; + status->dbs->RelevantBLTypes[i] = BL_PC; - memset(status->SkillChangeTable, 0, sizeof(status->SkillChangeTable)); - memset(status->ChangeFlagTable, 0, sizeof(status->ChangeFlagTable)); - memset(status->DisplayType, 0, sizeof(status->DisplayType)); + memset(status->dbs->SkillChangeTable, 0, sizeof(status->dbs->SkillChangeTable)); + memset(status->dbs->ChangeFlagTable, 0, sizeof(status->dbs->ChangeFlagTable)); + memset(status->dbs->DisplayType, 0, sizeof(status->dbs->DisplayType)); //First we define the skill for common ailments. These are used in skill_additional_effect through sc cards. [Skotlex] set_sc( NPC_PETRIFYATTACK , SC_STONE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF ); @@ -654,7 +655,7 @@ void initChangeTables(void) { set_sc( MI_RUSH_WINDMILL , SC_RUSH_WINDMILL , SI_RUSHWINDMILL , SCB_WATK ); set_sc( MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF2 ); set_sc( MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); - set_sc( WM_POEMOFNETHERWORLD , SC_STOP , SI_NETHERWORLD , SCB_NONE ); + set_sc_with_vfx(WM_POEMOFNETHERWORLD, SC_NETHERWORLD , SI_NETHERWORLD , SCB_NONE); set_sc_with_vfx( WM_VOICEOFSIREN , SC_SIREN , SI_SIREN , SCB_NONE ); set_sc_with_vfx( WM_LULLABY_DEEPSLEEP , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE ); set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SI_SIRCLEOFNATURE , SCB_NONE ); @@ -754,308 +755,303 @@ void initChangeTables(void) { set_sc_with_vfx( GN_ILLUSIONDOPING , SC_ILLUSIONDOPING , SI_ILLUSIONDOPING , SCB_HIT ); // Storing the target job rather than simply SC_SOULLINK simplifies code later on. - status->Skill2SCTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST, - status->Skill2SCTable[SL_MONK] = (sc_type)MAPID_MONK, - status->Skill2SCTable[SL_STAR] = (sc_type)MAPID_STAR_GLADIATOR, - status->Skill2SCTable[SL_SAGE] = (sc_type)MAPID_SAGE, - status->Skill2SCTable[SL_CRUSADER] = (sc_type)MAPID_CRUSADER, - status->Skill2SCTable[SL_SUPERNOVICE] = (sc_type)MAPID_SUPER_NOVICE, - status->Skill2SCTable[SL_KNIGHT] = (sc_type)MAPID_KNIGHT, - status->Skill2SCTable[SL_WIZARD] = (sc_type)MAPID_WIZARD, - status->Skill2SCTable[SL_PRIEST] = (sc_type)MAPID_PRIEST, - status->Skill2SCTable[SL_BARDDANCER] = (sc_type)MAPID_BARDDANCER, - status->Skill2SCTable[SL_ROGUE] = (sc_type)MAPID_ROGUE, - status->Skill2SCTable[SL_ASSASIN] = (sc_type)MAPID_ASSASSIN, - status->Skill2SCTable[SL_BLACKSMITH] = (sc_type)MAPID_BLACKSMITH, - status->Skill2SCTable[SL_HUNTER] = (sc_type)MAPID_HUNTER, - status->Skill2SCTable[SL_SOULLINKER] = (sc_type)MAPID_SOUL_LINKER, + status->dbs->Skill2SCTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST, + status->dbs->Skill2SCTable[SL_MONK] = (sc_type)MAPID_MONK, + status->dbs->Skill2SCTable[SL_STAR] = (sc_type)MAPID_STAR_GLADIATOR, + status->dbs->Skill2SCTable[SL_SAGE] = (sc_type)MAPID_SAGE, + status->dbs->Skill2SCTable[SL_CRUSADER] = (sc_type)MAPID_CRUSADER, + status->dbs->Skill2SCTable[SL_SUPERNOVICE] = (sc_type)MAPID_SUPER_NOVICE, + status->dbs->Skill2SCTable[SL_KNIGHT] = (sc_type)MAPID_KNIGHT, + status->dbs->Skill2SCTable[SL_WIZARD] = (sc_type)MAPID_WIZARD, + status->dbs->Skill2SCTable[SL_PRIEST] = (sc_type)MAPID_PRIEST, + status->dbs->Skill2SCTable[SL_BARDDANCER] = (sc_type)MAPID_BARDDANCER, + status->dbs->Skill2SCTable[SL_ROGUE] = (sc_type)MAPID_ROGUE, + status->dbs->Skill2SCTable[SL_ASSASIN] = (sc_type)MAPID_ASSASSIN, + status->dbs->Skill2SCTable[SL_BLACKSMITH] = (sc_type)MAPID_BLACKSMITH, + status->dbs->Skill2SCTable[SL_HUNTER] = (sc_type)MAPID_HUNTER, + status->dbs->Skill2SCTable[SL_SOULLINKER] = (sc_type)MAPID_SOUL_LINKER, //Status that don't have a skill associated. - status->IconChangeTable[SC_WEIGHTOVER50] = SI_WEIGHTOVER50; - status->IconChangeTable[SC_WEIGHTOVER90] = SI_WEIGHTOVER90; - status->IconChangeTable[SC_ATTHASTE_POTION1] = SI_ATTHASTE_POTION1; - status->IconChangeTable[SC_ATTHASTE_POTION2] = SI_ATTHASTE_POTION2; - status->IconChangeTable[SC_ATTHASTE_POTION3] = SI_ATTHASTE_POTION3; - status->IconChangeTable[SC_ATTHASTE_INFINITY] = SI_ATTHASTE_INFINITY; - status->IconChangeTable[SC_MOVHASTE_HORSE] = SI_MOVHASTE_HORSE; - status->IconChangeTable[SC_MOVHASTE_INFINITY] = SI_MOVHASTE_INFINITY; - status->IconChangeTable[SC_CHASEWALK2] = SI_INCSTR; - status->IconChangeTable[SC_MIRACLE] = SI_SOULLINK; - status->IconChangeTable[SC_CLAIRVOYANCE] = SI_CLAIRVOYANCE; - status->IconChangeTable[SC_FOOD_STR] = SI_FOOD_STR; - status->IconChangeTable[SC_FOOD_AGI] = SI_FOOD_AGI; - status->IconChangeTable[SC_FOOD_VIT] = SI_FOOD_VIT; - status->IconChangeTable[SC_FOOD_INT] = SI_FOOD_INT; - status->IconChangeTable[SC_FOOD_DEX] = SI_FOOD_DEX; - status->IconChangeTable[SC_FOOD_LUK] = SI_FOOD_LUK; - status->IconChangeTable[SC_FOOD_BASICAVOIDANCE]= SI_FOOD_BASICAVOIDANCE; - status->IconChangeTable[SC_FOOD_BASICHIT] = SI_FOOD_BASICHIT; - status->IconChangeTable[SC_MANU_ATK] = SI_MANU_ATK; - status->IconChangeTable[SC_MANU_DEF] = SI_MANU_DEF; - status->IconChangeTable[SC_SPL_ATK] = SI_SPL_ATK; - status->IconChangeTable[SC_SPL_DEF] = SI_SPL_DEF; - status->IconChangeTable[SC_MANU_MATK] = SI_MANU_MATK; - status->IconChangeTable[SC_SPL_MATK] = SI_SPL_MATK; - status->IconChangeTable[SC_PLUSATTACKPOWER] = SI_PLUSATTACKPOWER; - status->IconChangeTable[SC_PLUSMAGICPOWER] = SI_PLUSMAGICPOWER; + status->dbs->IconChangeTable[SC_WEIGHTOVER50] = SI_WEIGHTOVER50; + status->dbs->IconChangeTable[SC_WEIGHTOVER90] = SI_WEIGHTOVER90; + status->dbs->IconChangeTable[SC_ATTHASTE_POTION1] = SI_ATTHASTE_POTION1; + status->dbs->IconChangeTable[SC_ATTHASTE_POTION2] = SI_ATTHASTE_POTION2; + status->dbs->IconChangeTable[SC_ATTHASTE_POTION3] = SI_ATTHASTE_POTION3; + status->dbs->IconChangeTable[SC_ATTHASTE_INFINITY] = SI_ATTHASTE_INFINITY; + status->dbs->IconChangeTable[SC_MOVHASTE_HORSE] = SI_MOVHASTE_HORSE; + status->dbs->IconChangeTable[SC_MOVHASTE_INFINITY] = SI_MOVHASTE_INFINITY; + status->dbs->IconChangeTable[SC_CHASEWALK2] = SI_INCSTR; + status->dbs->IconChangeTable[SC_MIRACLE] = SI_SOULLINK; + status->dbs->IconChangeTable[SC_CLAIRVOYANCE] = SI_CLAIRVOYANCE; + status->dbs->IconChangeTable[SC_FOOD_STR] = SI_FOOD_STR; + status->dbs->IconChangeTable[SC_FOOD_AGI] = SI_FOOD_AGI; + status->dbs->IconChangeTable[SC_FOOD_VIT] = SI_FOOD_VIT; + status->dbs->IconChangeTable[SC_FOOD_INT] = SI_FOOD_INT; + status->dbs->IconChangeTable[SC_FOOD_DEX] = SI_FOOD_DEX; + status->dbs->IconChangeTable[SC_FOOD_LUK] = SI_FOOD_LUK; + status->dbs->IconChangeTable[SC_FOOD_BASICAVOIDANCE]= SI_FOOD_BASICAVOIDANCE; + status->dbs->IconChangeTable[SC_FOOD_BASICHIT] = SI_FOOD_BASICHIT; + status->dbs->IconChangeTable[SC_MANU_ATK] = SI_MANU_ATK; + status->dbs->IconChangeTable[SC_MANU_DEF] = SI_MANU_DEF; + status->dbs->IconChangeTable[SC_SPL_ATK] = SI_SPL_ATK; + status->dbs->IconChangeTable[SC_SPL_DEF] = SI_SPL_DEF; + status->dbs->IconChangeTable[SC_MANU_MATK] = SI_MANU_MATK; + status->dbs->IconChangeTable[SC_SPL_MATK] = SI_SPL_MATK; + status->dbs->IconChangeTable[SC_PLUSATTACKPOWER] = SI_PLUSATTACKPOWER; + status->dbs->IconChangeTable[SC_PLUSMAGICPOWER] = SI_PLUSMAGICPOWER; //Cash Items - status->IconChangeTable[SC_FOOD_STR_CASH] = SI_FOOD_STR_CASH; - status->IconChangeTable[SC_FOOD_AGI_CASH] = SI_FOOD_AGI_CASH; - status->IconChangeTable[SC_FOOD_VIT_CASH] = SI_FOOD_VIT_CASH; - status->IconChangeTable[SC_FOOD_DEX_CASH] = SI_FOOD_DEX_CASH; - status->IconChangeTable[SC_FOOD_INT_CASH] = SI_FOOD_INT_CASH; - status->IconChangeTable[SC_FOOD_LUK_CASH] = SI_FOOD_LUK_CASH; - status->IconChangeTable[SC_CASH_PLUSEXP] = SI_CASH_PLUSEXP; - status->IconChangeTable[SC_CASH_RECEIVEITEM] = SI_CASH_RECEIVEITEM; - status->IconChangeTable[SC_CASH_PLUSONLYJOBEXP] = SI_CASH_PLUSONLYJOBEXP; - status->IconChangeTable[SC_CASH_DEATHPENALTY] = SI_CASH_DEATHPENALTY; - status->IconChangeTable[SC_CASH_BOSS_ALARM] = SI_CASH_BOSS_ALARM; - status->IconChangeTable[SC_PROTECT_DEF] = SI_PROTECT_DEF; - status->IconChangeTable[SC_PROTECT_MDEF] = SI_PROTECT_MDEF; - status->IconChangeTable[SC_CRITICALPERCENT] = SI_CRITICALPERCENT; - status->IconChangeTable[SC_PLUSAVOIDVALUE] = SI_PLUSAVOIDVALUE; - status->IconChangeTable[SC_HEALPLUS] = SI_HEALPLUS; - status->IconChangeTable[SC_S_LIFEPOTION] = SI_S_LIFEPOTION; - status->IconChangeTable[SC_L_LIFEPOTION] = SI_L_LIFEPOTION; - status->IconChangeTable[SC_ATKER_BLOOD] = SI_ATKER_BLOOD; - status->IconChangeTable[SC_TARGET_BLOOD] = SI_TARGET_BLOOD; + status->dbs->IconChangeTable[SC_FOOD_STR_CASH] = SI_FOOD_STR_CASH; + status->dbs->IconChangeTable[SC_FOOD_AGI_CASH] = SI_FOOD_AGI_CASH; + status->dbs->IconChangeTable[SC_FOOD_VIT_CASH] = SI_FOOD_VIT_CASH; + status->dbs->IconChangeTable[SC_FOOD_DEX_CASH] = SI_FOOD_DEX_CASH; + status->dbs->IconChangeTable[SC_FOOD_INT_CASH] = SI_FOOD_INT_CASH; + status->dbs->IconChangeTable[SC_FOOD_LUK_CASH] = SI_FOOD_LUK_CASH; + status->dbs->IconChangeTable[SC_CASH_PLUSEXP] = SI_CASH_PLUSEXP; + status->dbs->IconChangeTable[SC_CASH_RECEIVEITEM] = SI_CASH_RECEIVEITEM; + status->dbs->IconChangeTable[SC_CASH_PLUSONLYJOBEXP] = SI_CASH_PLUSONLYJOBEXP; + status->dbs->IconChangeTable[SC_CASH_DEATHPENALTY] = SI_CASH_DEATHPENALTY; + status->dbs->IconChangeTable[SC_CASH_BOSS_ALARM] = SI_CASH_BOSS_ALARM; + status->dbs->IconChangeTable[SC_PROTECT_DEF] = SI_PROTECT_DEF; + status->dbs->IconChangeTable[SC_PROTECT_MDEF] = SI_PROTECT_MDEF; + status->dbs->IconChangeTable[SC_CRITICALPERCENT] = SI_CRITICALPERCENT; + status->dbs->IconChangeTable[SC_PLUSAVOIDVALUE] = SI_PLUSAVOIDVALUE; + status->dbs->IconChangeTable[SC_HEALPLUS] = SI_HEALPLUS; + status->dbs->IconChangeTable[SC_S_LIFEPOTION] = SI_S_LIFEPOTION; + status->dbs->IconChangeTable[SC_L_LIFEPOTION] = SI_L_LIFEPOTION; + status->dbs->IconChangeTable[SC_ATKER_BLOOD] = SI_ATKER_BLOOD; + status->dbs->IconChangeTable[SC_TARGET_BLOOD] = SI_TARGET_BLOOD; // Mercenary Bonus Effects - status->IconChangeTable[SC_MER_FLEE] = SI_MER_FLEE; - status->IconChangeTable[SC_MER_ATK] = SI_MER_ATK; - status->IconChangeTable[SC_MER_HP] = SI_MER_HP; - status->IconChangeTable[SC_MER_SP] = SI_MER_SP; - status->IconChangeTable[SC_MER_HIT] = SI_MER_HIT; + status->dbs->IconChangeTable[SC_MER_FLEE] = SI_MER_FLEE; + status->dbs->IconChangeTable[SC_MER_ATK] = SI_MER_ATK; + status->dbs->IconChangeTable[SC_MER_HP] = SI_MER_HP; + status->dbs->IconChangeTable[SC_MER_SP] = SI_MER_SP; + status->dbs->IconChangeTable[SC_MER_HIT] = SI_MER_HIT; // Warlock Spheres - status->IconChangeTable[SC_SUMMON1] = SI_SPHERE_1; - status->IconChangeTable[SC_SUMMON2] = SI_SPHERE_2; - status->IconChangeTable[SC_SUMMON3] = SI_SPHERE_3; - status->IconChangeTable[SC_SUMMON4] = SI_SPHERE_4; - status->IconChangeTable[SC_SUMMON5] = SI_SPHERE_5; + status->dbs->IconChangeTable[SC_SUMMON1] = SI_SPHERE_1; + status->dbs->IconChangeTable[SC_SUMMON2] = SI_SPHERE_2; + status->dbs->IconChangeTable[SC_SUMMON3] = SI_SPHERE_3; + status->dbs->IconChangeTable[SC_SUMMON4] = SI_SPHERE_4; + status->dbs->IconChangeTable[SC_SUMMON5] = SI_SPHERE_5; // Warlock Preserved spells - status->IconChangeTable[SC_SPELLBOOK1] = SI_SPELLBOOK1; - status->IconChangeTable[SC_SPELLBOOK2] = SI_SPELLBOOK2; - status->IconChangeTable[SC_SPELLBOOK3] = SI_SPELLBOOK3; - status->IconChangeTable[SC_SPELLBOOK4] = SI_SPELLBOOK4; - status->IconChangeTable[SC_SPELLBOOK5] = SI_SPELLBOOK5; - status->IconChangeTable[SC_SPELLBOOK6] = SI_SPELLBOOK6; - status->IconChangeTable[SC_SPELLBOOK7] = SI_SPELLBOOK7; - - status->IconChangeTable[SC_NEUTRALBARRIER_MASTER] = SI_NEUTRALBARRIER_MASTER; - status->IconChangeTable[SC_STEALTHFIELD_MASTER] = SI_STEALTHFIELD_MASTER; - status->IconChangeTable[SC_OVERHEAT] = SI_OVERHEAT; - status->IconChangeTable[SC_OVERHEAT_LIMITPOINT] = SI_OVERHEAT_LIMITPOINT; - - status->IconChangeTable[SC_HALLUCINATIONWALK_POSTDELAY] = SI_HALLUCINATIONWALK_POSTDELAY; - status->IconChangeTable[SC_TOXIN] = SI_TOXIN; - status->IconChangeTable[SC_PARALYSE] = SI_PARALYSE; - status->IconChangeTable[SC_VENOMBLEED] = SI_VENOMBLEED; - status->IconChangeTable[SC_MAGICMUSHROOM] = SI_MAGICMUSHROOM; - status->IconChangeTable[SC_DEATHHURT] = SI_DEATHHURT; - status->IconChangeTable[SC_PYREXIA] = SI_PYREXIA; - status->IconChangeTable[SC_OBLIVIONCURSE] = SI_OBLIVIONCURSE; - status->IconChangeTable[SC_LEECHESEND] = SI_LEECHESEND; - - status->IconChangeTable[SC_SHIELDSPELL_DEF] = SI_SHIELDSPELL_DEF; - status->IconChangeTable[SC_SHIELDSPELL_MDEF] = SI_SHIELDSPELL_MDEF; - status->IconChangeTable[SC_SHIELDSPELL_REF] = SI_SHIELDSPELL_REF; - status->IconChangeTable[SC_BANDING_DEFENCE] = SI_BANDING_DEFENCE; - - status->IconChangeTable[SC_CURSEDCIRCLE_ATKER] = SI_CURSEDCIRCLE_ATKER; - - status->IconChangeTable[SC_STOMACHACHE] = SI_STOMACHACHE; - status->IconChangeTable[SC_MYSTERIOUS_POWDER] = SI_MYSTERIOUS_POWDER; - status->IconChangeTable[SC_MELON_BOMB] = SI_MELON_BOMB; - status->IconChangeTable[SC_BANANA_BOMB] = SI_BANANA_BOMB; - status->IconChangeTable[SC_BANANA_BOMB_SITDOWN_POSTDELAY] = SI_BANANA_BOMB_SITDOWN_POSTDELAY; + status->dbs->IconChangeTable[SC_SPELLBOOK1] = SI_SPELLBOOK1; + status->dbs->IconChangeTable[SC_SPELLBOOK2] = SI_SPELLBOOK2; + status->dbs->IconChangeTable[SC_SPELLBOOK3] = SI_SPELLBOOK3; + status->dbs->IconChangeTable[SC_SPELLBOOK4] = SI_SPELLBOOK4; + status->dbs->IconChangeTable[SC_SPELLBOOK5] = SI_SPELLBOOK5; + status->dbs->IconChangeTable[SC_SPELLBOOK6] = SI_SPELLBOOK6; + status->dbs->IconChangeTable[SC_SPELLBOOK7] = SI_SPELLBOOK7; + + status->dbs->IconChangeTable[SC_NEUTRALBARRIER_MASTER] = SI_NEUTRALBARRIER_MASTER; + status->dbs->IconChangeTable[SC_STEALTHFIELD_MASTER] = SI_STEALTHFIELD_MASTER; + status->dbs->IconChangeTable[SC_OVERHEAT] = SI_OVERHEAT; + status->dbs->IconChangeTable[SC_OVERHEAT_LIMITPOINT] = SI_OVERHEAT_LIMITPOINT; + + status->dbs->IconChangeTable[SC_HALLUCINATIONWALK_POSTDELAY] = SI_HALLUCINATIONWALK_POSTDELAY; + status->dbs->IconChangeTable[SC_TOXIN] = SI_TOXIN; + status->dbs->IconChangeTable[SC_PARALYSE] = SI_PARALYSE; + status->dbs->IconChangeTable[SC_VENOMBLEED] = SI_VENOMBLEED; + status->dbs->IconChangeTable[SC_MAGICMUSHROOM] = SI_MAGICMUSHROOM; + status->dbs->IconChangeTable[SC_DEATHHURT] = SI_DEATHHURT; + status->dbs->IconChangeTable[SC_PYREXIA] = SI_PYREXIA; + status->dbs->IconChangeTable[SC_OBLIVIONCURSE] = SI_OBLIVIONCURSE; + status->dbs->IconChangeTable[SC_LEECHESEND] = SI_LEECHESEND; + + status->dbs->IconChangeTable[SC_SHIELDSPELL_DEF] = SI_SHIELDSPELL_DEF; + status->dbs->IconChangeTable[SC_SHIELDSPELL_MDEF] = SI_SHIELDSPELL_MDEF; + status->dbs->IconChangeTable[SC_SHIELDSPELL_REF] = SI_SHIELDSPELL_REF; + status->dbs->IconChangeTable[SC_BANDING_DEFENCE] = SI_BANDING_DEFENCE; + + status->dbs->IconChangeTable[SC_CURSEDCIRCLE_ATKER] = SI_CURSEDCIRCLE_ATKER; + + status->dbs->IconChangeTable[SC_STOMACHACHE] = SI_STOMACHACHE; + status->dbs->IconChangeTable[SC_MYSTERIOUS_POWDER] = SI_MYSTERIOUS_POWDER; + status->dbs->IconChangeTable[SC_MELON_BOMB] = SI_MELON_BOMB; + status->dbs->IconChangeTable[SC_BANANA_BOMB] = SI_BANANA_BOMB; + status->dbs->IconChangeTable[SC_BANANA_BOMB_SITDOWN_POSTDELAY] = SI_BANANA_BOMB_SITDOWN_POSTDELAY; //Genetics New Food Items Status Icons - status->IconChangeTable[SC_SAVAGE_STEAK] = SI_SAVAGE_STEAK; - status->IconChangeTable[SC_COCKTAIL_WARG_BLOOD] = SI_COCKTAIL_WARG_BLOOD; - status->IconChangeTable[SC_MINOR_BBQ] = SI_MINOR_BBQ; - status->IconChangeTable[SC_SIROMA_ICE_TEA] = SI_SIROMA_ICE_TEA; - status->IconChangeTable[SC_DROCERA_HERB_STEAMED] = SI_DROCERA_HERB_STEAMED; - status->IconChangeTable[SC_PUTTI_TAILS_NOODLES] = SI_PUTTI_TAILS_NOODLES; - - status->IconChangeTable[SC_BOOST500] |= SI_BOOST500; - status->IconChangeTable[SC_FULL_SWING_K] |= SI_FULL_SWING_K; - status->IconChangeTable[SC_MANA_PLUS] |= SI_MANA_PLUS; - status->IconChangeTable[SC_MUSTLE_M] |= SI_MUSTLE_M; - status->IconChangeTable[SC_LIFE_FORCE_F] |= SI_LIFE_FORCE_F; - status->IconChangeTable[SC_EXTRACT_WHITE_POTION_Z] |= SI_EXTRACT_WHITE_POTION_Z; - status->IconChangeTable[SC_VITATA_500] |= SI_VITATA_500; - status->IconChangeTable[SC_EXTRACT_SALAMINE_JUICE] |= SI_EXTRACT_SALAMINE_JUICE; + status->dbs->IconChangeTable[SC_SAVAGE_STEAK] = SI_SAVAGE_STEAK; + status->dbs->IconChangeTable[SC_COCKTAIL_WARG_BLOOD] = SI_COCKTAIL_WARG_BLOOD; + status->dbs->IconChangeTable[SC_MINOR_BBQ] = SI_MINOR_BBQ; + status->dbs->IconChangeTable[SC_SIROMA_ICE_TEA] = SI_SIROMA_ICE_TEA; + status->dbs->IconChangeTable[SC_DROCERA_HERB_STEAMED] = SI_DROCERA_HERB_STEAMED; + status->dbs->IconChangeTable[SC_PUTTI_TAILS_NOODLES] = SI_PUTTI_TAILS_NOODLES; + + status->dbs->IconChangeTable[SC_BOOST500] |= SI_BOOST500; + status->dbs->IconChangeTable[SC_FULL_SWING_K] |= SI_FULL_SWING_K; + status->dbs->IconChangeTable[SC_MANA_PLUS] |= SI_MANA_PLUS; + status->dbs->IconChangeTable[SC_MUSTLE_M] |= SI_MUSTLE_M; + status->dbs->IconChangeTable[SC_LIFE_FORCE_F] |= SI_LIFE_FORCE_F; + status->dbs->IconChangeTable[SC_EXTRACT_WHITE_POTION_Z] |= SI_EXTRACT_WHITE_POTION_Z; + status->dbs->IconChangeTable[SC_VITATA_500] |= SI_VITATA_500; + status->dbs->IconChangeTable[SC_EXTRACT_SALAMINE_JUICE] |= SI_EXTRACT_SALAMINE_JUICE; // Elemental Spirit's 'side' status change icons. - status->IconChangeTable[SC_CIRCLE_OF_FIRE] = SI_CIRCLE_OF_FIRE; - status->IconChangeTable[SC_FIRE_CLOAK] = SI_FIRE_CLOAK; - status->IconChangeTable[SC_WATER_SCREEN] = SI_WATER_SCREEN; - status->IconChangeTable[SC_WATER_DROP] = SI_WATER_DROP; - status->IconChangeTable[SC_WIND_STEP] = SI_WIND_STEP; - status->IconChangeTable[SC_WIND_CURTAIN] = SI_WIND_CURTAIN; - status->IconChangeTable[SC_SOLID_SKIN] = SI_SOLID_SKIN; - status->IconChangeTable[SC_STONE_SHIELD] = SI_STONE_SHIELD; - status->IconChangeTable[SC_PYROTECHNIC] = SI_PYROTECHNIC; - status->IconChangeTable[SC_HEATER] = SI_HEATER; - status->IconChangeTable[SC_TROPIC] = SI_TROPIC; - status->IconChangeTable[SC_AQUAPLAY] = SI_AQUAPLAY; - status->IconChangeTable[SC_COOLER] = SI_COOLER; - status->IconChangeTable[SC_CHILLY_AIR] = SI_CHILLY_AIR; - status->IconChangeTable[SC_GUST] = SI_GUST; - status->IconChangeTable[SC_BLAST] = SI_BLAST; - status->IconChangeTable[SC_WILD_STORM] = SI_WILD_STORM; - status->IconChangeTable[SC_PETROLOGY] = SI_PETROLOGY; - status->IconChangeTable[SC_CURSED_SOIL] = SI_CURSED_SOIL; - status->IconChangeTable[SC_UPHEAVAL] = SI_UPHEAVAL; - status->IconChangeTable[SC_PUSH_CART] = SI_ON_PUSH_CART; - status->IconChangeTable[SC_REBOUND] = SI_REBOUND; - status->IconChangeTable[SC_ALL_RIDING] = SI_ALL_RIDING; - status->IconChangeTable[SC_MONSTER_TRANSFORM] = SI_MONSTER_TRANSFORM; - status->IconChangeTable[SC_MOONSTAR] = SI_MOONSTAR; - status->IconChangeTable[SC_SUPER_STAR] = SI_SUPER_STAR; - status->IconChangeTable[SC_STRANGELIGHTS] = SI_STRANGELIGHTS; - status->IconChangeTable[SC_DECORATION_OF_MUSIC] = SI_DECORATION_OF_MUSIC; + status->dbs->IconChangeTable[SC_CIRCLE_OF_FIRE] = SI_CIRCLE_OF_FIRE; + status->dbs->IconChangeTable[SC_FIRE_CLOAK] = SI_FIRE_CLOAK; + status->dbs->IconChangeTable[SC_WATER_SCREEN] = SI_WATER_SCREEN; + status->dbs->IconChangeTable[SC_WATER_DROP] = SI_WATER_DROP; + status->dbs->IconChangeTable[SC_WIND_STEP] = SI_WIND_STEP; + status->dbs->IconChangeTable[SC_WIND_CURTAIN] = SI_WIND_CURTAIN; + status->dbs->IconChangeTable[SC_SOLID_SKIN] = SI_SOLID_SKIN; + status->dbs->IconChangeTable[SC_STONE_SHIELD] = SI_STONE_SHIELD; + status->dbs->IconChangeTable[SC_PYROTECHNIC] = SI_PYROTECHNIC; + status->dbs->IconChangeTable[SC_HEATER] = SI_HEATER; + status->dbs->IconChangeTable[SC_TROPIC] = SI_TROPIC; + status->dbs->IconChangeTable[SC_AQUAPLAY] = SI_AQUAPLAY; + status->dbs->IconChangeTable[SC_COOLER] = SI_COOLER; + status->dbs->IconChangeTable[SC_CHILLY_AIR] = SI_CHILLY_AIR; + status->dbs->IconChangeTable[SC_GUST] = SI_GUST; + status->dbs->IconChangeTable[SC_BLAST] = SI_BLAST; + status->dbs->IconChangeTable[SC_WILD_STORM] = SI_WILD_STORM; + status->dbs->IconChangeTable[SC_PETROLOGY] = SI_PETROLOGY; + status->dbs->IconChangeTable[SC_CURSED_SOIL] = SI_CURSED_SOIL; + status->dbs->IconChangeTable[SC_UPHEAVAL] = SI_UPHEAVAL; + status->dbs->IconChangeTable[SC_PUSH_CART] = SI_ON_PUSH_CART; + status->dbs->IconChangeTable[SC_REBOUND] = SI_REBOUND; + status->dbs->IconChangeTable[SC_ALL_RIDING] = SI_ALL_RIDING; + status->dbs->IconChangeTable[SC_MONSTER_TRANSFORM] = SI_MONSTER_TRANSFORM; + status->dbs->IconChangeTable[SC_MOONSTAR] = SI_MOONSTAR; + status->dbs->IconChangeTable[SC_SUPER_STAR] = SI_SUPER_STAR; + status->dbs->IconChangeTable[SC_STRANGELIGHTS] = SI_STRANGELIGHTS; + status->dbs->IconChangeTable[SC_DECORATION_OF_MUSIC] = SI_DECORATION_OF_MUSIC; //Other SC which are not necessarily associated to skills. - status->ChangeFlagTable[SC_ATTHASTE_POTION1] = SCB_ASPD; - status->ChangeFlagTable[SC_ATTHASTE_POTION2] = SCB_ASPD; - status->ChangeFlagTable[SC_ATTHASTE_POTION3] = SCB_ASPD; - status->ChangeFlagTable[SC_ATTHASTE_INFINITY] = SCB_ASPD; - status->ChangeFlagTable[SC_MOVHASTE_HORSE] = SCB_SPEED; - status->ChangeFlagTable[SC_MOVHASTE_INFINITY] = SCB_SPEED; - status->ChangeFlagTable[SC_PLUSATTACKPOWER] = SCB_BATK; - status->ChangeFlagTable[SC_PLUSMAGICPOWER] = SCB_MATK; - status->ChangeFlagTable[SC_INCALLSTATUS] |= SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK; - status->ChangeFlagTable[SC_CHASEWALK2] |= SCB_STR; - status->ChangeFlagTable[SC_INCAGI] |= SCB_AGI; - status->ChangeFlagTable[SC_INCVIT] |= SCB_VIT; - status->ChangeFlagTable[SC_INCINT] |= SCB_INT; - status->ChangeFlagTable[SC_INCDEX] |= SCB_DEX; - status->ChangeFlagTable[SC_INCLUK] |= SCB_LUK; - status->ChangeFlagTable[SC_INCHIT] |= SCB_HIT; - status->ChangeFlagTable[SC_INCHITRATE] |= SCB_HIT; - status->ChangeFlagTable[SC_INCFLEE] |= SCB_FLEE; - status->ChangeFlagTable[SC_INCFLEERATE] |= SCB_FLEE; - status->ChangeFlagTable[SC_MTF_HITFLEE] |= SCB_HIT|SCB_FLEE; - status->ChangeFlagTable[SC_CRITICALPERCENT] |= SCB_CRI; - status->ChangeFlagTable[SC_INCASPDRATE] |= SCB_ASPD; - status->ChangeFlagTable[SC_PLUSAVOIDVALUE] |= SCB_FLEE2; - status->ChangeFlagTable[SC_INCMHPRATE] |= SCB_MAXHP; - status->ChangeFlagTable[SC_INCMSPRATE] |= SCB_MAXSP; - status->ChangeFlagTable[SC_INCMHP] |= SCB_MAXHP; - status->ChangeFlagTable[SC_MTF_MHP] |= SCB_MAXHP; - status->ChangeFlagTable[SC_INCMSP] |= SCB_MAXSP; - status->ChangeFlagTable[SC_MTF_MSP] |= SCB_MAXSP; - status->ChangeFlagTable[SC_INCATKRATE] |= SCB_BATK|SCB_WATK; - status->ChangeFlagTable[SC_INCMATKRATE] |= SCB_MATK; - status->ChangeFlagTable[SC_INCDEFRATE] |= SCB_DEF; - status->ChangeFlagTable[SC_FOOD_STR] |= SCB_STR; - status->ChangeFlagTable[SC_FOOD_AGI] |= SCB_AGI; - status->ChangeFlagTable[SC_FOOD_VIT] |= SCB_VIT; - status->ChangeFlagTable[SC_FOOD_INT] |= SCB_INT; - status->ChangeFlagTable[SC_FOOD_DEX] |= SCB_DEX; - status->ChangeFlagTable[SC_FOOD_LUK] |= SCB_LUK; - status->ChangeFlagTable[SC_FOOD_BASICHIT] |= SCB_HIT; - status->ChangeFlagTable[SC_FOOD_BASICAVOIDANCE] |= SCB_FLEE; - status->ChangeFlagTable[SC_BATKFOOD] |= SCB_BATK; - status->ChangeFlagTable[SC_WATKFOOD] |= SCB_WATK; - status->ChangeFlagTable[SC_MATKFOOD] |= SCB_MATK; - status->ChangeFlagTable[SC_ARMORPROPERTY] |= SCB_ALL; - status->ChangeFlagTable[SC_ARMOR_RESIST] |= SCB_ALL; - status->ChangeFlagTable[SC_ATKER_BLOOD] |= SCB_ALL; - status->ChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED; - status->ChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL; + status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION1] = SCB_ASPD; + status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION2] = SCB_ASPD; + status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION3] = SCB_ASPD; + status->dbs->ChangeFlagTable[SC_ATTHASTE_INFINITY] = SCB_ASPD; + status->dbs->ChangeFlagTable[SC_MOVHASTE_HORSE] = SCB_SPEED; + status->dbs->ChangeFlagTable[SC_MOVHASTE_INFINITY] = SCB_SPEED; + status->dbs->ChangeFlagTable[SC_PLUSATTACKPOWER] = SCB_BATK; + status->dbs->ChangeFlagTable[SC_PLUSMAGICPOWER] = SCB_MATK; + status->dbs->ChangeFlagTable[SC_INCALLSTATUS] |= SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK; + status->dbs->ChangeFlagTable[SC_CHASEWALK2] |= SCB_STR; + status->dbs->ChangeFlagTable[SC_INCAGI] |= SCB_AGI; + status->dbs->ChangeFlagTable[SC_INCVIT] |= SCB_VIT; + status->dbs->ChangeFlagTable[SC_INCINT] |= SCB_INT; + status->dbs->ChangeFlagTable[SC_INCDEX] |= SCB_DEX; + status->dbs->ChangeFlagTable[SC_INCLUK] |= SCB_LUK; + status->dbs->ChangeFlagTable[SC_INCHIT] |= SCB_HIT; + status->dbs->ChangeFlagTable[SC_INCHITRATE] |= SCB_HIT; + status->dbs->ChangeFlagTable[SC_INCFLEE] |= SCB_FLEE; + status->dbs->ChangeFlagTable[SC_INCFLEERATE] |= SCB_FLEE; + status->dbs->ChangeFlagTable[SC_MTF_HITFLEE] |= SCB_HIT|SCB_FLEE; + status->dbs->ChangeFlagTable[SC_CRITICALPERCENT] |= SCB_CRI; + status->dbs->ChangeFlagTable[SC_INCASPDRATE] |= SCB_ASPD; + status->dbs->ChangeFlagTable[SC_PLUSAVOIDVALUE] |= SCB_FLEE2; + status->dbs->ChangeFlagTable[SC_INCMHPRATE] |= SCB_MAXHP; + status->dbs->ChangeFlagTable[SC_INCMSPRATE] |= SCB_MAXSP; + status->dbs->ChangeFlagTable[SC_INCMHP] |= SCB_MAXHP; + status->dbs->ChangeFlagTable[SC_MTF_MHP] |= SCB_MAXHP; + status->dbs->ChangeFlagTable[SC_INCMSP] |= SCB_MAXSP; + status->dbs->ChangeFlagTable[SC_MTF_MSP] |= SCB_MAXSP; + status->dbs->ChangeFlagTable[SC_INCATKRATE] |= SCB_BATK|SCB_WATK; + status->dbs->ChangeFlagTable[SC_INCMATKRATE] |= SCB_MATK; + status->dbs->ChangeFlagTable[SC_INCDEFRATE] |= SCB_DEF; + status->dbs->ChangeFlagTable[SC_FOOD_STR] |= SCB_STR; + status->dbs->ChangeFlagTable[SC_FOOD_AGI] |= SCB_AGI; + status->dbs->ChangeFlagTable[SC_FOOD_VIT] |= SCB_VIT; + status->dbs->ChangeFlagTable[SC_FOOD_INT] |= SCB_INT; + status->dbs->ChangeFlagTable[SC_FOOD_DEX] |= SCB_DEX; + status->dbs->ChangeFlagTable[SC_FOOD_LUK] |= SCB_LUK; + status->dbs->ChangeFlagTable[SC_FOOD_BASICHIT] |= SCB_HIT; + status->dbs->ChangeFlagTable[SC_FOOD_BASICAVOIDANCE] |= SCB_FLEE; + status->dbs->ChangeFlagTable[SC_BATKFOOD] |= SCB_BATK; + status->dbs->ChangeFlagTable[SC_WATKFOOD] |= SCB_WATK; + status->dbs->ChangeFlagTable[SC_MATKFOOD] |= SCB_MATK; + status->dbs->ChangeFlagTable[SC_ARMORPROPERTY] |= SCB_ALL; + status->dbs->ChangeFlagTable[SC_ARMOR_RESIST] |= SCB_ALL; + status->dbs->ChangeFlagTable[SC_ATKER_BLOOD] |= SCB_ALL; + status->dbs->ChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED; + status->dbs->ChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL; // Cash Items - status->ChangeFlagTable[SC_FOOD_STR_CASH] = SCB_STR; - status->ChangeFlagTable[SC_FOOD_AGI_CASH] = SCB_AGI; - status->ChangeFlagTable[SC_FOOD_VIT_CASH] = SCB_VIT; - status->ChangeFlagTable[SC_FOOD_DEX_CASH] = SCB_DEX; - status->ChangeFlagTable[SC_FOOD_INT_CASH] = SCB_INT; - status->ChangeFlagTable[SC_FOOD_LUK_CASH] = SCB_LUK; + status->dbs->ChangeFlagTable[SC_FOOD_STR_CASH] = SCB_STR; + status->dbs->ChangeFlagTable[SC_FOOD_AGI_CASH] = SCB_AGI; + status->dbs->ChangeFlagTable[SC_FOOD_VIT_CASH] = SCB_VIT; + status->dbs->ChangeFlagTable[SC_FOOD_DEX_CASH] = SCB_DEX; + status->dbs->ChangeFlagTable[SC_FOOD_INT_CASH] = SCB_INT; + status->dbs->ChangeFlagTable[SC_FOOD_LUK_CASH] = SCB_LUK; // Mercenary Bonus Effects - status->ChangeFlagTable[SC_MER_FLEE] |= SCB_FLEE; - status->ChangeFlagTable[SC_MER_ATK] |= SCB_WATK; - status->ChangeFlagTable[SC_MER_HP] |= SCB_MAXHP; - status->ChangeFlagTable[SC_MER_SP] |= SCB_MAXSP; - status->ChangeFlagTable[SC_MER_HIT] |= SCB_HIT; + status->dbs->ChangeFlagTable[SC_MER_FLEE] |= SCB_FLEE; + status->dbs->ChangeFlagTable[SC_MER_ATK] |= SCB_WATK; + status->dbs->ChangeFlagTable[SC_MER_HP] |= SCB_MAXHP; + status->dbs->ChangeFlagTable[SC_MER_SP] |= SCB_MAXSP; + status->dbs->ChangeFlagTable[SC_MER_HIT] |= SCB_HIT; // Guillotine Cross Poison Effects - status->ChangeFlagTable[SC_PARALYSE] |= SCB_FLEE|SCB_SPEED|SCB_ASPD; - status->ChangeFlagTable[SC_VENOMBLEED] |= SCB_MAXHP; - status->ChangeFlagTable[SC_MAGICMUSHROOM] |= SCB_REGEN; - status->ChangeFlagTable[SC_DEATHHURT] |= SCB_REGEN; - status->ChangeFlagTable[SC_PYREXIA] |= SCB_HIT|SCB_FLEE; - status->ChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN; + status->dbs->ChangeFlagTable[SC_PARALYSE] |= SCB_FLEE|SCB_SPEED|SCB_ASPD; + status->dbs->ChangeFlagTable[SC_VENOMBLEED] |= SCB_MAXHP; + status->dbs->ChangeFlagTable[SC_MAGICMUSHROOM] |= SCB_REGEN; + status->dbs->ChangeFlagTable[SC_DEATHHURT] |= SCB_REGEN; + status->dbs->ChangeFlagTable[SC_PYREXIA] |= SCB_HIT|SCB_FLEE; + status->dbs->ChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN; // RG status - status->ChangeFlagTable[SC_SHIELDSPELL_DEF] |= SCB_WATK; - status->ChangeFlagTable[SC_SHIELDSPELL_REF] |= SCB_DEF; + status->dbs->ChangeFlagTable[SC_SHIELDSPELL_DEF] |= SCB_WATK; + status->dbs->ChangeFlagTable[SC_SHIELDSPELL_REF] |= SCB_DEF; // Meca status - status->ChangeFlagTable[SC_STEALTHFIELD_MASTER] |= SCB_SPEED; - - status->ChangeFlagTable[SC_SAVAGE_STEAK] |= SCB_STR; - status->ChangeFlagTable[SC_COCKTAIL_WARG_BLOOD] |= SCB_INT; - status->ChangeFlagTable[SC_MINOR_BBQ] |= SCB_VIT; - status->ChangeFlagTable[SC_SIROMA_ICE_TEA] |= SCB_DEX; - status->ChangeFlagTable[SC_DROCERA_HERB_STEAMED] |= SCB_AGI; - status->ChangeFlagTable[SC_PUTTI_TAILS_NOODLES] |= SCB_LUK; - status->ChangeFlagTable[SC_BOOST500] |= SCB_ASPD; - status->ChangeFlagTable[SC_FULL_SWING_K] |= SCB_BATK; - status->ChangeFlagTable[SC_MANA_PLUS] |= SCB_MATK; - status->ChangeFlagTable[SC_MUSTLE_M] |= SCB_MAXHP; - status->ChangeFlagTable[SC_LIFE_FORCE_F] |= SCB_MAXSP; - status->ChangeFlagTable[SC_EXTRACT_WHITE_POTION_Z] |= SCB_REGEN; - status->ChangeFlagTable[SC_VITATA_500] |= SCB_REGEN; - status->ChangeFlagTable[SC_EXTRACT_SALAMINE_JUICE] |= SCB_ASPD; - status->ChangeFlagTable[SC_REBOUND] |= SCB_SPEED|SCB_REGEN; - status->ChangeFlagTable[SC_DEFSET] |= SCB_DEF|SCB_DEF2; - status->ChangeFlagTable[SC_MDEFSET] |= SCB_MDEF|SCB_MDEF2; - status->ChangeFlagTable[SC_MYSTERIOUS_POWDER] |= SCB_MAXHP; - - status->ChangeFlagTable[SC_ALL_RIDING] = SCB_SPEED; - status->ChangeFlagTable[SC_WEDDING] = SCB_SPEED; - - status->ChangeFlagTable[SC_MTF_ASPD] = SCB_ASPD|SCB_HIT; - status->ChangeFlagTable[SC_MTF_MATK] = SCB_MATK; - status->ChangeFlagTable[SC_MTF_MLEATKED] |= SCB_ALL; - - status->ChangeFlagTable[SC_MOONSTAR] |= SCB_NONE; - status->ChangeFlagTable[SC_SUPER_STAR] |= SCB_NONE; - status->ChangeFlagTable[SC_STRANGELIGHTS] |= SCB_NONE; - status->ChangeFlagTable[SC_DECORATION_OF_MUSIC] |= SCB_NONE; - - /* status->DisplayType Table [Ind/Hercules] */ - status->DisplayType[SC_ALL_RIDING] = true; - status->DisplayType[SC_PUSH_CART] = true; - status->DisplayType[SC_SUMMON1] = true; - status->DisplayType[SC_SUMMON2] = true; - status->DisplayType[SC_SUMMON3] = true; - status->DisplayType[SC_SUMMON4] = true; - status->DisplayType[SC_SUMMON5] = true; - status->DisplayType[SC_CAMOUFLAGE] = true; - status->DisplayType[SC_DUPLELIGHT] = true; - status->DisplayType[SC_ORATIO] = true; - status->DisplayType[SC_FROSTMISTY] = true; - status->DisplayType[SC_VENOMIMPRESS] = true; - status->DisplayType[SC_HALLUCINATIONWALK] = true; - status->DisplayType[SC_ROLLINGCUTTER] = true; - status->DisplayType[SC_BANDING] = true; - status->DisplayType[SC_COLD] = true; - status->DisplayType[SC_DEEP_SLEEP] = true; - status->DisplayType[SC_CURSEDCIRCLE_ATKER] = true; - status->DisplayType[SC_CURSEDCIRCLE_TARGET] = true; - status->DisplayType[SC_BLOOD_SUCKER] = true; - status->DisplayType[SC__SHADOWFORM] = true; - status->DisplayType[SC_MONSTER_TRANSFORM] = true; - status->DisplayType[SC_MOONSTAR] = true; - status->DisplayType[SC_SUPER_STAR] = true; - status->DisplayType[SC_STRANGELIGHTS] = true; - status->DisplayType[SC_DECORATION_OF_MUSIC] = true; - -#ifdef RENEWAL_EDP - // renewal EDP increases your weapon atk - status->ChangeFlagTable[SC_EDP] |= SCB_WATK; -#endif + status->dbs->ChangeFlagTable[SC_STEALTHFIELD_MASTER] |= SCB_SPEED; + + status->dbs->ChangeFlagTable[SC_SAVAGE_STEAK] |= SCB_STR; + status->dbs->ChangeFlagTable[SC_COCKTAIL_WARG_BLOOD] |= SCB_INT; + status->dbs->ChangeFlagTable[SC_MINOR_BBQ] |= SCB_VIT; + status->dbs->ChangeFlagTable[SC_SIROMA_ICE_TEA] |= SCB_DEX; + status->dbs->ChangeFlagTable[SC_DROCERA_HERB_STEAMED] |= SCB_AGI; + status->dbs->ChangeFlagTable[SC_PUTTI_TAILS_NOODLES] |= SCB_LUK; + status->dbs->ChangeFlagTable[SC_BOOST500] |= SCB_ASPD; + status->dbs->ChangeFlagTable[SC_FULL_SWING_K] |= SCB_BATK; + status->dbs->ChangeFlagTable[SC_MANA_PLUS] |= SCB_MATK; + status->dbs->ChangeFlagTable[SC_MUSTLE_M] |= SCB_MAXHP; + status->dbs->ChangeFlagTable[SC_LIFE_FORCE_F] |= SCB_MAXSP; + status->dbs->ChangeFlagTable[SC_EXTRACT_WHITE_POTION_Z] |= SCB_REGEN; + status->dbs->ChangeFlagTable[SC_VITATA_500] |= SCB_REGEN; + status->dbs->ChangeFlagTable[SC_EXTRACT_SALAMINE_JUICE] |= SCB_ASPD; + status->dbs->ChangeFlagTable[SC_REBOUND] |= SCB_SPEED|SCB_REGEN; + status->dbs->ChangeFlagTable[SC_DEFSET] |= SCB_DEF|SCB_DEF2; + status->dbs->ChangeFlagTable[SC_MDEFSET] |= SCB_MDEF|SCB_MDEF2; + status->dbs->ChangeFlagTable[SC_MYSTERIOUS_POWDER] |= SCB_MAXHP; + + status->dbs->ChangeFlagTable[SC_ALL_RIDING] = SCB_SPEED; + status->dbs->ChangeFlagTable[SC_WEDDING] = SCB_SPEED; + + status->dbs->ChangeFlagTable[SC_MTF_ASPD] = SCB_ASPD|SCB_HIT; + status->dbs->ChangeFlagTable[SC_MTF_MATK] = SCB_MATK; + status->dbs->ChangeFlagTable[SC_MTF_MLEATKED] |= SCB_ALL; + + status->dbs->ChangeFlagTable[SC_MOONSTAR] |= SCB_NONE; + status->dbs->ChangeFlagTable[SC_SUPER_STAR] |= SCB_NONE; + status->dbs->ChangeFlagTable[SC_STRANGELIGHTS] |= SCB_NONE; + status->dbs->ChangeFlagTable[SC_DECORATION_OF_MUSIC] |= SCB_NONE; + + /* status->dbs->DisplayType Table [Ind/Hercules] */ + status->dbs->DisplayType[SC_ALL_RIDING] = true; + status->dbs->DisplayType[SC_PUSH_CART] = true; + status->dbs->DisplayType[SC_SUMMON1] = true; + status->dbs->DisplayType[SC_SUMMON2] = true; + status->dbs->DisplayType[SC_SUMMON3] = true; + status->dbs->DisplayType[SC_SUMMON4] = true; + status->dbs->DisplayType[SC_SUMMON5] = true; + status->dbs->DisplayType[SC_CAMOUFLAGE] = true; + status->dbs->DisplayType[SC_DUPLELIGHT] = true; + status->dbs->DisplayType[SC_ORATIO] = true; + status->dbs->DisplayType[SC_FROSTMISTY] = true; + status->dbs->DisplayType[SC_VENOMIMPRESS] = true; + status->dbs->DisplayType[SC_HALLUCINATIONWALK] = true; + status->dbs->DisplayType[SC_ROLLINGCUTTER] = true; + status->dbs->DisplayType[SC_BANDING] = true; + status->dbs->DisplayType[SC_COLD] = true; + status->dbs->DisplayType[SC_DEEP_SLEEP] = true; + status->dbs->DisplayType[SC_CURSEDCIRCLE_ATKER] = true; + status->dbs->DisplayType[SC_CURSEDCIRCLE_TARGET] = true; + status->dbs->DisplayType[SC_BLOOD_SUCKER] = true; + status->dbs->DisplayType[SC__SHADOWFORM] = true; + status->dbs->DisplayType[SC_MONSTER_TRANSFORM] = true; + status->dbs->DisplayType[SC_MOONSTAR] = true; + status->dbs->DisplayType[SC_SUPER_STAR] = true; + status->dbs->DisplayType[SC_STRANGELIGHTS] = true; + status->dbs->DisplayType[SC_DECORATION_OF_MUSIC] = true; if( !battle_config.display_hallucination ) //Disable Hallucination. - status->IconChangeTable[SC_ILLUSION] = SI_BLANK; + status->dbs->IconChangeTable[SC_ILLUSION] = SI_BLANK; #undef add_sc #undef set_sc_with_vfx } @@ -1199,7 +1195,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, if(d_bl &&((d_bl->type == BL_MER && ((TBL_MER *)d_bl)->master && ((TBL_MER *)d_bl)->master->bl.id == target->id) || (d_bl->type == BL_PC && ((TBL_PC *)d_bl)->devotion[sce->val2] == target->id)) && check_distance_bl(target, d_bl, sce->val3)) { - clif->damage(d_bl, d_bl, 0, 0, hp, 0, 0, 0); + clif->damage(d_bl, d_bl, 0, 0, hp, 0, BDT_NORMAL, 0); status_fix_damage(NULL, d_bl, hp, 0); return 0; } @@ -1266,7 +1262,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, } if( src && target->type == BL_PC && (((TBL_PC*)target)->disguise) > 0 ) {// stop walking when attacked in disguise to prevent walk-delay bug - unit->stop_walking( target, 1 ); + unit->stop_walking(target, STOPWALKING_FLAG_FIXPOS); } if (st->hp || (flag&8)) { @@ -1349,7 +1345,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, unit->remove_map(target,CLR_DEAD,ALC_MARK); else { //Some death states that would normally be handled by unit_remove_map unit->stop_attack(target); - unit->stop_walking(target,1); + unit->stop_walking(target, STOPWALKING_FLAG_FIXPOS); unit->skillcastcancel(target,0); clif->clearunit_area(target,CLR_DEAD); skill->unit_move(target,timer->gettick(),4); @@ -1601,13 +1597,13 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin for(i = 0; i < map->list[src->m].zone->disabled_skills_count; i++) { if( skill_id == map->list[src->m].zone->disabled_skills[i]->nameid && (map->list[src->m].zone->disabled_skills[i]->type&src->type) ) { - if( src->type == BL_PC ) - clif->msg((TBL_PC*)src, SKILL_CANT_USE_AREA); // This skill cannot be used within this area - else if( src->type == BL_MOB && map->list[src->m].zone->disabled_skills[i]->subtype != MZS_NONE ) { - if( st->mode&MD_BOSS ) { /** is boss **/ + if (src->type == BL_PC) { + clif->msgtable((TBL_PC*)src, MSG_SKILL_CANT_USE_AREA); // This skill cannot be used within this area + } else if (src->type == BL_MOB && map->list[src->m].zone->disabled_skills[i]->subtype != MZS_NONE) { + if( st->mode&MD_BOSS ) { /* is boss */ if( !( map->list[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS ) ) break; - } else { /** is not boss **/ + } else { /* is not boss */ if( map->list[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS ) break; } @@ -1657,15 +1653,19 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin (sc->data[SC_TRICKDEAD] && skill_id != NV_TRICKDEAD) || (sc->data[SC_AUTOCOUNTER] && !flag && skill_id) || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF && skill_id != PA_GOSPEL) - || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF && flag != 2) ) return 0; if (sc->data[SC_DC_WINKCHARM] && target && !flag) { //Prevents skill usage - if( unit->bl2ud(src) && (unit->bl2ud(src))->walktimer == INVALID_TIMER ) - unit->walktobl(src, map->id2bl(sc->data[SC_DC_WINKCHARM]->val2), 3, 1); - clif->emotion(src, E_LV); - return 0; + struct block_list *winkcharm_target = map->id2bl(sc->data[SC_DC_WINKCHARM]->val2); + if (winkcharm_target != NULL) { + if (unit->bl2ud(src) && (unit->bl2ud(src))->walktimer == INVALID_TIMER) + unit->walktobl(src, map->id2bl(sc->data[SC_DC_WINKCHARM]->val2), 3, 1); + clif->emotion(src, E_LV); + return 0; + } else { + status_change_end(src, SC_DC_WINKCHARM, INVALID_TIMER); + } } if (sc->data[SC_BLADESTOP]) { @@ -1880,7 +1880,7 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) { if (battle_config.slaves_inherit_speed && md->master_id) flag|=8; - if (md->master_id && md->special_state.ai>1) + if (md->master_id && md->special_state.ai > AI_ATTACK) flag|=16; if (!flag) @@ -1916,8 +1916,8 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) { //Max HP setting from Summon Flora/marine Sphere struct unit_data *ud = unit->bl2ud(mbl); //Remove special AI when this is used by regular mobs. - if (mbl->type == BL_MOB && !((TBL_MOB*)mbl)->special_state.ai) - md->special_state.ai = 0; + if (mbl->type == BL_MOB && ((TBL_MOB*)mbl)->special_state.ai == AI_NONE) + md->special_state.ai = AI_NONE; if (ud) { // different levels of HP according to skill level if (ud->skill_id == AM_SPHEREMINE) { @@ -2087,64 +2087,42 @@ int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt) return 1; } -/// Helper function for status_base_pc_maxhp(), used to pre-calculate the hp_sigma_val[] array -void status_calc_sigma(void) -{ - int i,j; +unsigned int status_get_base_maxsp(struct map_session_data* sd, struct status_data *st) { + uint64 val = pc->class2idx(sd->status.class_); - for(i = 0; i < CLASS_COUNT; i++) - { - unsigned int k = 0; - status->hp_sigma_val[i][0] = status->hp_sigma_val[i][1] = 0; - for(j = 2; j <= MAX_LEVEL; j++) - { - k += (status->hp_coefficient[i]*j + 50) / 100; - status->hp_sigma_val[i][j] = k; - if (k >= INT_MAX) - break; //Overflow protection. [Skotlex] - } - for(; j <= MAX_LEVEL; j++) - status->hp_sigma_val[i][j] = INT_MAX; - } + val = status->dbs->SP_table[val][sd->status.base_level]; + + if ( sd->class_&JOBL_UPPER ) + val += val * 25 / 100; + else if ( sd->class_&JOBL_BABY ) + val = val * 70 / 100; + if ( (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) ) + val *= 3; //Triple max SP for top ranking Taekwons over level 90. + + val += val * st->int_ / 100; + + return (unsigned int)cap_value(val, 0, UINT_MAX); } -/// Calculates base MaxHP value according to class and base level -/// The recursive equation used to calculate level bonus is (using integer operations) -/// f(0) = 35 | f(x+1) = f(x) + A + (x + B)*C/D -/// which reduces to something close to -/// f(x) = 35 + x*(A + B*C/D) + sum(i=2..x){ i*C/D } -unsigned int status_base_pc_maxhp(struct map_session_data *sd, struct status_data *st) { +unsigned int status_get_base_maxhp(struct map_session_data *sd, struct status_data *st) { uint64 val = pc->class2idx(sd->status.class_); - val = 35 + sd->status.base_level*(int64)status->hp_coefficient2[val]/100 + status->hp_sigma_val[val][sd->status.base_level]; - if((sd->class_&MAPID_UPPERMASK) == MAPID_NINJA || (sd->class_&MAPID_UPPERMASK) == MAPID_GUNSLINGER || (sd->class_&MAPID_UPPERMASK) == MAPID_REBELLION) - val += 100; //Since their HP can't be approximated well enough without this. - if((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON)) - val *= 3; //Triple max HP for top ranking Taekwons over level 90. - if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level >= 99) - val += 2000; //Supernovice lvl99 hp bonus. - - val += val * st->vit/100; // +1% per each point of VIT + val = status->dbs->HP_table[val][sd->status.base_level]; - if (sd->class_&JOBL_UPPER) - val += val * 25/100; //Trans classes get a 25% hp bonus - else if (sd->class_&JOBL_BABY) - val -= val * 30/100; //Baby classes get a 30% hp penalty - return (unsigned int)cap_value(val,0,UINT_MAX); -} + if ( (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level >= 99 ) + val += 2000; //Supernovice lvl99 hp bonus. + if ( (sd->class_&MAPID_THIRDMASK) == MAPID_SUPER_NOVICE_E && sd->status.base_level >= 150 ) + val += 2000; //Extented Supernovice lvl150 hp bonus. -unsigned int status_base_pc_maxsp(struct map_session_data* sd, struct status_data *st) { - uint64 val; + if ( sd->class_&JOBL_UPPER ) + val += val * 25 / 100; //Trans classes get a 25% hp bonus + else if ( sd->class_&JOBL_BABY ) + val = val * 70 / 100; //Baby classes get a 30% hp penalty - val = 10 + sd->status.base_level*(int64)status->sp_coefficient[pc->class2idx(sd->status.class_)]/100; - val += val * st->int_/100; + if ( (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) ) + val *= 3; //Triple max HP for top ranking Taekwons over level 90. - if (sd->class_&JOBL_UPPER) - val += val * 25/100; - else if (sd->class_&JOBL_BABY) - val -= val * 30/100; - if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON)) - val *= 3; //Triple max SP for top ranking Taekwons over level 90. + val += val * st->vit / 100; // +1% per each point of VIT return (unsigned int)cap_value(val,0,UINT_MAX); } @@ -2176,7 +2154,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { pc->calc_skilltree(sd); // SkillTree calculation - sd->max_weight = status->max_weight_base[pc->class2idx(sd->status.class_)]+sd->status.str*300; + sd->max_weight = status->dbs->max_weight_base[pc->class2idx(sd->status.class_)]+sd->status.str*300; if(opt&SCO_FIRST) { //Load Hp/SP from char-received data. @@ -2214,37 +2192,11 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100; sd->regen.state.block = 0; - // zeroed arrays, order follows the order in pc.h. - // add new arrays to the end of zeroed area in pc.h (see comments) and size here. [zzo] - memset (sd->param_bonus, 0, sizeof(sd->param_bonus) - + sizeof(sd->param_equip) - + sizeof(sd->subele) - + sizeof(sd->subrace) - + sizeof(sd->subrace2) - + sizeof(sd->subsize) - + sizeof(sd->reseff) - + sizeof(sd->weapon_coma_ele) - + sizeof(sd->weapon_coma_race) - + sizeof(sd->weapon_atk) - + sizeof(sd->weapon_atk_rate) - + sizeof(sd->arrow_addele) - + sizeof(sd->arrow_addrace) - + sizeof(sd->arrow_addsize) - + sizeof(sd->magic_addele) - + sizeof(sd->magic_addrace) - + sizeof(sd->magic_addsize) - + sizeof(sd->magic_atk_ele) - + sizeof(sd->critaddrace) - + sizeof(sd->expaddrace) - + sizeof(sd->ignore_mdef) - + sizeof(sd->ignore_def) - + sizeof(sd->sp_gain_race) - + sizeof(sd->sp_gain_race_attack) - + sizeof(sd->hp_gain_race_attack) - ); + // zeroed arrays + memset(ZEROED_BLOCK_POS(sd), 0, ZEROED_BLOCK_SIZE(sd)); - memset (&sd->right_weapon.overrefine, 0, sizeof(sd->right_weapon) - sizeof(sd->right_weapon.atkmods)); - memset (&sd->left_weapon.overrefine, 0, sizeof(sd->left_weapon) - sizeof(sd->left_weapon.atkmods)); + memset(ZEROED_BLOCK_POS(&(sd->right_weapon)), 0, ZEROED_BLOCK_SIZE(&(sd->right_weapon))); + memset(ZEROED_BLOCK_POS(&(sd->left_weapon)), 0, ZEROED_BLOCK_SIZE(&(sd->left_weapon))); if (sd->special_state.intravision && !sd->sc.data[SC_CLAIRVOYANCE]) //Clear intravision as long as nothing else is using it clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_CLAIRVOYANCE); @@ -2276,41 +2228,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { } bstatus->aspd_rate = 1000; bstatus->ele_lv = 1; - bstatus->race = RC_DEMIHUMAN; - - //zero up structures... - memset(&sd->autospell,0,sizeof(sd->autospell) - + sizeof(sd->autospell2) - + sizeof(sd->autospell3) - + sizeof(sd->addeff) - + sizeof(sd->addeff2) - + sizeof(sd->addeff3) - + sizeof(sd->skillatk) - + sizeof(sd->skillusesprate) - + sizeof(sd->skillusesp) - + sizeof(sd->skillheal) - + sizeof(sd->skillheal2) - + sizeof(sd->hp_loss) - + sizeof(sd->sp_loss) - + sizeof(sd->hp_regen) - + sizeof(sd->sp_regen) - + sizeof(sd->skillblown) - + sizeof(sd->skillcast) - + sizeof(sd->add_def) - + sizeof(sd->add_mdef) - + sizeof(sd->add_mdmg) - + sizeof(sd->add_drop) - + sizeof(sd->itemhealrate) - + sizeof(sd->subele2) - + sizeof(sd->skillcooldown) - + sizeof(sd->skillfixcast) - + sizeof(sd->skillvarcast) - + sizeof(sd->skillfixcastrate) - + sizeof(sd->def_set_race) - + sizeof(sd->mdef_set_race) - ); - - memset (&sd->bonus, 0,sizeof(sd->bonus)); + bstatus->race = RC_PLAYER; // Autobonus pc->delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),true); @@ -2373,18 +2291,18 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { } wa->atk += sd->inventory_data[index]->atk; if ( (r = sd->status.inventory[index].refine) ) - wa->atk2 = status->refine_info[wlv].bonus[r-1] / 100; + wa->atk2 = status->dbs->refine_info[wlv].bonus[r-1] / 100; #ifdef RENEWAL wa->matk += sd->inventory_data[index]->matk; wa->wlv = wlv; if( r && sd->weapontype1 != W_BOW ) // renewal magic attack refine bonus - wa->matk += status->refine_info[wlv].bonus[r-1] / 100; + wa->matk += status->dbs->refine_info[wlv].bonus[r-1] / 100; #endif //Overrefined bonus. if (r) - wd->overrefine = status->refine_info[wlv].randombonus_max[r-1] / 100; + wd->overrefine = status->dbs->refine_info[wlv].randombonus_max[r-1] / 100; wa->range += sd->inventory_data[index]->range; if(sd->inventory_data[index]->script) { @@ -2412,7 +2330,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { else if(sd->inventory_data[index]->type == IT_ARMOR) { int r; if ( (r = sd->status.inventory[index].refine) ) - refinedef += status->refine_info[REFINE_TYPE_ARMOR].bonus[r-1]; + refinedef += status->dbs->refine_info[REFINE_TYPE_ARMOR].bonus[r-1]; if(sd->inventory_data[index]->script) { if( i == EQI_HAND_L ) //Shield sd->state.lr_flag = 3; @@ -2557,12 +2475,12 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { sd->bonus.splash_range += sd->bonus.splash_add_range; // Damage modifiers from weapon type - sd->right_weapon.atkmods[0] = status->atkmods[0][sd->weapontype1]; - sd->right_weapon.atkmods[1] = status->atkmods[1][sd->weapontype1]; - sd->right_weapon.atkmods[2] = status->atkmods[2][sd->weapontype1]; - sd->left_weapon.atkmods[0] = status->atkmods[0][sd->weapontype2]; - sd->left_weapon.atkmods[1] = status->atkmods[1][sd->weapontype2]; - sd->left_weapon.atkmods[2] = status->atkmods[2][sd->weapontype2]; + sd->right_weapon.atkmods[0] = status->dbs->atkmods[0][sd->weapontype1]; + sd->right_weapon.atkmods[1] = status->dbs->atkmods[1][sd->weapontype1]; + sd->right_weapon.atkmods[2] = status->dbs->atkmods[2][sd->weapontype1]; + sd->left_weapon.atkmods[0] = status->dbs->atkmods[0][sd->weapontype2]; + sd->left_weapon.atkmods[1] = status->dbs->atkmods[1][sd->weapontype2]; + sd->left_weapon.atkmods[2] = status->dbs->atkmods[2][sd->weapontype2]; if ((pc_isridingpeco(sd) || pc_isridingdragon(sd)) && (sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR) @@ -2578,9 +2496,9 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { // Job bonuses index = pc->class2idx(sd->status.class_); for(i=0;i<(int)sd->status.job_level && i<MAX_LEVEL;i++){ - if(!status->job_bonus[index][i]) + if(!status->dbs->job_bonus[index][i]) continue; - switch(status->job_bonus[index][i]) { + switch(status->dbs->job_bonus[index][i]) { case 1: bstatus->str++; break; case 2: bstatus->agi++; break; case 3: bstatus->vit++; break; @@ -2640,7 +2558,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { // Basic MaxHP value //We hold the standard Max HP here to make it faster to recalculate on vit changes. - sd->status.max_hp = status->base_pc_maxhp(sd,bstatus); + sd->status.max_hp = status->get_base_maxhp(sd,bstatus); //This is done to handle underflows from negative Max HP bonuses i64 = sd->status.max_hp + (int)bstatus->max_hp; bstatus->max_hp = (unsigned int)cap_value(i64, 0, INT_MAX); @@ -2665,7 +2583,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { // ----- SP MAX CALCULATION ----- // Basic MaxSP value - sd->status.max_sp = status->base_pc_maxsp(sd,bstatus); + sd->status.max_sp = status->get_base_maxsp(sd,bstatus); //This is done to handle underflows from negative Max SP bonuses i64 = sd->status.max_sp + (int)bstatus->max_sp; bstatus->max_sp = (unsigned int)cap_value(i64, 0, INT_MAX); @@ -2852,17 +2770,12 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { else if (pc_isridingdragon(sd)) bstatus->aspd_rate += 250-50*pc->checkskill(sd,RK_DRAGONTRAINING); #else // needs more info - if((skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK) - bstatus->aspd_rate += 5*skill_lv; - if((skill_lv = pc->checkskill(sd,SG_DEVIL)) > 0 && !pc->nextjobexp(sd)) - bstatus->aspd_rate += 30*skill_lv; - if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 && - (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) - bstatus->aspd_rate += ((skill_lv+1)/2) * 10; - if (pc_isridingpeco(sd)) - bstatus->aspd_rate -= 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY); - else if (pc_isridingdragon(sd)) - bstatus->aspd_rate -= 250-50*pc->checkskill(sd,RK_DRAGONTRAINING); + if ( (skill_lv = pc->checkskill(sd, SG_DEVIL)) > 0 && !pc->nextjobexp(sd) ) + bstatus->aspd_rate += 30 * skill_lv; + if ( pc_isridingpeco(sd) ) + bstatus->aspd_rate -= 500 - 100 * pc->checkskill(sd, KN_CAVALIERMASTERY); + else if ( pc_isridingdragon(sd) ) + bstatus->aspd_rate -= 250 - 50 * pc->checkskill(sd, RK_DRAGONTRAINING); #endif bstatus->adelay = 2*bstatus->amotion; @@ -2937,7 +2850,11 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { sd->right_weapon.addrace[RC_DRAGON]+=skill_lv; sd->left_weapon.addrace[RC_DRAGON]+=skill_lv; sd->magic_addrace[RC_DRAGON]+=skill_lv; +#ifdef RENEWAL + sd->race_tolerance[RC_DRAGON] += skill_lv; +#else sd->subrace[RC_DRAGON]+=skill_lv; +#endif } if( (skill_lv = pc->checkskill(sd, AB_EUCHARISTICA)) > 0 ) { @@ -2947,7 +2864,11 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { sd->left_weapon.addele[ELE_DARK] += skill_lv; sd->magic_addrace[RC_DEMON] += skill_lv; sd->magic_addele[ELE_DARK] += skill_lv; +#ifdef RENEWAL + sd->race_tolerance[RC_DEMON] += skill_lv; +#else sd->subrace[RC_DEMON] += skill_lv; +#endif sd->subele[ELE_DARK] += skill_lv; } @@ -2970,7 +2891,11 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { } if(sc->data[SC_PROVIDENCE]){ sd->subele[ELE_HOLY] += sc->data[SC_PROVIDENCE]->val2; +#ifdef RENEWAL + sd->race_tolerance[RC_DEMON] += sc->data[SC_PROVIDENCE]->val2; +#else sd->subrace[RC_DEMON] += sc->data[SC_PROVIDENCE]->val2; +#endif } if(sc->data[SC_ARMORPROPERTY]) { //This status change should grant card-type elemental resist. @@ -3115,7 +3040,7 @@ int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) { nstatus->def_ele = ELE_NEUTRAL; nstatus->ele_lv = 1; - nstatus->race = RC_DEMIHUMAN; + nstatus->race = RC_PLAYER; nstatus->size = nd->size; nstatus->rhw.range = 1 + nstatus->size; nstatus->mode = (MD_CANMOVE|MD_CANATTACK); @@ -3169,6 +3094,8 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) { hstatus->aspd_rate = 1000; #ifdef RENEWAL + hstatus->def = 0; + amotion = hd->homunculusDB->baseASPD; amotion = amotion - amotion * (hstatus->dex + hom->dex_value) / 1000 - (hstatus->agi + hom->agi_value) * amotion / 250; #else @@ -3183,7 +3110,6 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) { hstatus->amotion = cap_value(amotion, battle_config.max_aspd, 2000); hstatus->adelay = hstatus->amotion; //It seems adelay = amotion for Homunculus. - hstatus->max_hp = hom->max_hp; hstatus->max_sp = hom->max_sp; @@ -3644,7 +3570,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { if (!(st->mode&MD_CANATTACK)) unit->stop_attack(bl); if (!(st->mode&MD_CANMOVE)) - unit->stop_walking(bl,1); + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); } // No status changes alter these yet. @@ -3654,7 +3580,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { if(flag&SCB_MAXHP) { if( bl->type&BL_PC ) { - st->max_hp = status->base_pc_maxhp(sd,st); + st->max_hp = status->get_base_maxhp(sd,st); if (sd) st->max_hp += bst->max_hp - sd->status.max_hp; @@ -3675,7 +3601,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { if(flag&SCB_MAXSP) { if( bl->type&BL_PC ) { - st->max_sp = status->base_pc_maxsp(sd,st); + st->max_sp = status->get_base_maxsp(sd,st); if (sd) st->max_sp += bst->max_sp - sd->status.max_sp; @@ -3742,19 +3668,14 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { amotion = status->base_amotion_pc(sd, st); #ifndef RENEWAL_ASPD st->aspd_rate = status->calc_aspd_rate(bl, sc, bst->aspd_rate); - - if(st->aspd_rate != 1000) - amotion = amotion*st->aspd_rate/1000; -#else - // aspd = baseaspd + floor(sqrt((agi^2/2) + (dex^2/5))/4 + (potskillbonus*agi/200)) - amotion -= (int)(sqrt((pow(st->agi, 2) / 2) + (pow(st->dex, 2) / 5)) / 4 + ((float)status->calc_aspd(bl, sc, 1) * st->agi / 200)) * 10; - - if ( (status->calc_aspd(bl, sc, 2) + st->aspd_rate2) != 0 ) // RE ASPD percertage modifier - amotion -= ((amotion - ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd)) - * (status->calc_aspd(bl, sc, 2) + st->aspd_rate2) / 10 + 5) / 10; - +#endif if ( st->aspd_rate != 1000 ) // absolute percentage modifier - amotion = (200 - (200 - amotion / 10) * st->aspd_rate / 1000) * 10; + amotion = amotion * st->aspd_rate / 1000; + if ( sd && sd->ud.skilltimer != INVALID_TIMER && pc->checkskill(sd, SA_FREECAST) > 0 ) + amotion = amotion * 5 * (pc->checkskill(sd, SA_FREECAST) + 10) / 100; +#ifdef RENEWAL_ASPD + amotion += (max(0xc3 - amotion, 2) * (st->aspd_rate2 + status->calc_aspd(bl, sc, 2))) / 100; + amotion = 10 * (200 - amotion) + sd->bonus.aspd_add; #endif amotion = status->calc_fix_aspd(bl, sc, amotion); st->amotion = cap_value(amotion, ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd), 2000); @@ -4009,46 +3930,46 @@ int status_check_visibility(struct block_list *src, struct block_list *target) { // Basic ASPD value int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) { int amotion; -#ifdef RENEWAL_ASPD - short mod = -1; - - switch ( sd->weapontype2 ) { // adjustment for dual wielding - case W_DAGGER: - mod = 0; - break; // 0, 1, 1 - case W_1HSWORD: - case W_1HAXE: - mod = 1; - if ( (sd->class_&MAPID_THIRDMASK) == MAPID_GUILLOTINE_CROSS ) // 0, 2, 3 - mod = sd->weapontype2 / W_1HSWORD + W_1HSWORD / sd->weapontype2; - } - - amotion = (sd->status.weapon < MAX_WEAPON_TYPE && mod < 0) - ? (status->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon - : ((status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] // dual-wield - + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 6 / 10 + 10 * mod - - status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] - + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1]); - +#ifdef RENEWAL_ASPD /* [malufett/Hercules] */ + float temp; + int skill_lv, val = 0; + amotion = status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1]; + if ( sd->status.weapon > MAX_WEAPON_TYPE ) + amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] / 4; if ( sd->status.shield ) - amotion += (2000 - status->aspd_base[pc->class2idx(sd->status.class_)][W_FIST]) + - (status->aspd_base[pc->class2idx(sd->status.class_)][MAX_WEAPON_TYPE] - 2000); - + amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class_)][MAX_WEAPON_TYPE]; + switch ( sd->status.weapon ) { + case W_BOW: case W_MUSICAL: + case W_WHIP: case W_REVOLVER: + case W_RIFLE: case W_GATLING: + case W_SHOTGUN: case W_GRENADE: + temp = st->dex * st->dex / 7.0f + st->agi * st->agi * 0.5f; + break; + default: + temp = st->dex * st->dex / 5.0f + st->agi * st->agi * 0.5f; + } + temp = (float)(sqrt(temp) * 0.25f) + 0xc4; + if ( (skill_lv = pc->checkskill(sd, SA_ADVANCEDBOOK)) > 0 && sd->status.weapon == W_BOOK ) + val += (skill_lv - 1) / 2 + 1; + if ( (skill_lv = pc->checkskill(sd, GS_SINGLEACTION)) > 0 ) + val += ((skill_lv + 1) / 2); + amotion = ((int)(temp + ((float)(status->calc_aspd(&sd->bl, &sd->sc, 1) + val) * st->agi / 200)) - min(amotion, 200)); #else // base weapon delay amotion = (sd->status.weapon < MAX_WEAPON_TYPE) - ? (status->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon - : (status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1] + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 7 / 10; // dual-wield + ? (status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon + : (status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1] + status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 7 / 10; // dual-wield // percentual delay reduction from stats amotion -= amotion * (4 * st->agi + st->dex) / 1000; -#endif + // raw delay adjustment from bAspd bonus amotion += sd->bonus.aspd_add; /* angra manyu disregards aspd_base and similar */ if ( sd->equip_index[EQI_HAND_R] >= 0 && sd->status.inventory[sd->equip_index[EQI_HAND_R]].nameid == ITEMID_ANGRA_MANYU ) return 0; +#endif return amotion; } @@ -4141,7 +4062,7 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level) if ( bl->type == BL_HOM ) { st->def2 = status_get_homvit(bl) + status_get_homagi(bl) / 2; st->mdef2 = (status_get_homvit(bl) + status_get_homint(bl)) / 2; - st->def += status_get_homvit(bl) + level / 2; + st->def += status_get_homvit(bl) + level / 2; // Increase. Already initialized in status_calc_homunculus_ st->mdef = (int)(((float)status_get_homvit(bl) + level) / 4 + (float)status_get_homint(bl) / 2); st->hit = level + st->dex + 150; st->flee = level + status_get_homagi(bl); @@ -4593,6 +4514,9 @@ unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, #ifndef RENEWAL if(sc->data[SC_LKCONCENTRATION]) batk += batk * sc->data[SC_LKCONCENTRATION]->val2/100; +#else + if ( sc->data[SC_NOEQUIPWEAPON] && bl->type != BL_PC ) + batk -= batk * sc->data[SC_NOEQUIPWEAPON]->val2 / 100; #endif if(sc->data[SC_SKE]) batk += batk * 3; @@ -4672,7 +4596,7 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, if(sc->data[SC_LKCONCENTRATION]) watk += watk * sc->data[SC_LKCONCENTRATION]->val2/100; #endif - if(sc->data[SC_INCATKRATE]) + if(sc->data[SC_INCATKRATE] && bl->type != BL_MOB) watk += watk * sc->data[SC_INCATKRATE]->val1/100; if(sc->data[SC_PROVOKE]) watk += watk * sc->data[SC_PROVOKE]->val3/100; @@ -4682,8 +4606,10 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, watk += watk * sc->data[SC_HLIF_FLEET]->val3/100; if(sc->data[SC_CURSE]) watk -= watk * 25/100; +#ifndef RENEWAL if(sc->data[SC_NOEQUIPWEAPON] && bl->type != BL_PC) watk -= watk * sc->data[SC_NOEQUIPWEAPON]->val2/100; +#endif if(sc->data[SC__ENERVATION]) watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; if(sc->data[SC_RUSH_WINDMILL]) @@ -5227,7 +5153,7 @@ signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, if(sc->data[SC_MINDBREAKER]) mdef2 -= mdef2 * sc->data[SC_MINDBREAKER]->val3/100; #ifdef RENEWAL - if(sc && sc->data[SC_ASSUMPTIO]) + if (sc->data[SC_ASSUMPTIO]) mdef2 <<= 1; return (short)cap_value(mdef2,SHRT_MIN,SHRT_MAX); #else @@ -5508,8 +5434,8 @@ short status_calc_aspd(struct block_list *bl, struct status_change *sc, short fl bonus -= sc->data[SC_DEFENDER]->val4 / 10; if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY) // needs more info bonus -= 25; - if (sc->data[SC_GRAVITATION]) - bonus -= sc->data[SC_GRAVITATION]->val2; // needs more info + if (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 != BCT_SELF) + bonus -= sc->data[SC_GRAVITATION]->val2 / 10; if (sc->data[SC_JOINTBEAT]) { // needs more info if (sc->data[SC_JOINTBEAT]->val2&BREAK_WRIST) bonus -= 25; @@ -5670,7 +5596,7 @@ short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate += sc->data[SC_DEFENDER]->val4; if(sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY) aspd_rate += 250; - if(sc->data[SC_GRAVITATION]) + if(sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 != BCT_SELF) aspd_rate += sc->data[SC_GRAVITATION]->val2; if(sc->data[SC_JOINTBEAT]) { if( sc->data[SC_JOINTBEAT]->val2&BREAK_WRIST ) @@ -6047,7 +5973,7 @@ int status_get_party_id(struct block_list *bl) { struct mob_data *md=(TBL_MOB*)bl; if( md->master_id > 0 ) { struct map_session_data *msd; - if (md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL) + if (md->special_state.ai != AI_NONE && (msd = map->id2sd(md->master_id)) != NULL) return msd->status.party_id; return -md->master_id; } @@ -6090,7 +6016,7 @@ int status_get_guild_id(struct block_list *bl) { // Guardian guild data may not been available yet, castle data is always set return (md->guardian_data->g)?md->guardian_data->g->guild_id:md->guardian_data->castle->guild_id; } - if( md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL ) + if (md->special_state.ai != AI_NONE && (msd = map->id2sd(md->master_id)) != NULL) return msd->status.guild_id; //Alchemist's mobs [Skotlex] break; } @@ -6132,7 +6058,7 @@ int status_get_emblem_id(struct block_list *bl) { struct mob_data *md = (struct mob_data *)bl; if (md->guardian_data) //Guardian's guild [Skotlex] return (md->guardian_data->g) ? md->guardian_data->g->emblem_id:0; - if (md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL) + if (md->special_state.ai != AI_NONE && (msd = map->id2sd(md->master_id)) != NULL) return msd->guild_emblem_id; //Alchemist's mobs [Skotlex] } break; @@ -6315,7 +6241,7 @@ void status_set_viewdata(struct block_list *bl, int class_) if (vd) nd->vd = vd; else - ShowError("status_set_viewdata (NPC): No view data for class %d\n", class_); + ShowError("status_set_viewdata (NPC): No view data for class %d (name=%s)\n", class_, nd->name); } break; case BL_HOM: //[blackhole89] @@ -6604,9 +6530,6 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ case SC_COLD: tick_def2 = bst->vit*100 + status->get_lv(bl)*20; break; - case SC_VACUUM_EXTREME: - tick_def2 = bst->str*50; - break; case SC_MANDRAGORA: sc_def = (st->vit + st->luk)*20; break; @@ -6616,6 +6539,9 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ case SC_NEEDLE_OF_PARALYZE: tick_def2 = (st->vit + st->luk) * 50; break; + case SC_NETHERWORLD: + tick_def2 = 1000 * (((bl->type == BL_PC) ? ((TBL_PC*)bl)->status.job_level : 0) / 10 + status->get_lv(bl) / 50); + break; default: //Effect that cannot be reduced? Likely a buff. if (!(rnd()%10000 < rate)) @@ -6717,6 +6643,9 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ case SC_FROSTMISTY: tick = max(tick, 6000); break; + case SC_NETHERWORLD: + tick = max(tick, 4000); + break; default: //Skills need to trigger even if the duration is reduced below 1ms tick = max(tick, 1); @@ -7055,7 +6984,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t i = sd->equip_index[EQI_HAND_R]; if (i>=0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) { opt_flag|=2; - pc->unequipitem(sd,i,3); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } if (!opt_flag) return 0; } @@ -7071,7 +7000,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t i = sd->equip_index[EQI_HAND_L]; if ( i < 0 || !sd->inventory_data[i] || sd->inventory_data[i]->type != IT_ARMOR ) return 0; - pc->unequipitem(sd,i,3); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; @@ -7083,7 +7012,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t i = sd->equip_index[EQI_ARMOR]; if ( i < 0 || !sd->inventory_data[i] ) return 0; - pc->unequipitem(sd,i,3); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; @@ -7095,7 +7024,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t i = sd->equip_index[EQI_HEAD_TOP]; if ( i < 0 || !sd->inventory_data[i] ) return 0; - pc->unequipitem(sd,i,3); + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; @@ -7165,12 +7094,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if( !(sd->bonus.unstripable_equip&EQP_ACC_L) ) { i = sd->equip_index[EQI_ACC_L]; if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR ) - pc->unequipitem(sd,i,3); //L-Accessory + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); //L-Accessory } if( !(sd->bonus.unstripable_equip&EQP_ACC_R) ) { i = sd->equip_index[EQI_ACC_R]; if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR ) - pc->unequipitem(sd,i,3); //R-Accessory + pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); //R-Accessory } if( i < 0 ) return 0; @@ -7248,6 +7177,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t // Other Effects case SC_VACUUM_EXTREME: + case SC_NETHERWORLD: return 0; } @@ -7400,7 +7330,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER); break; case SC_ENDURE: - if( val4 ) + if( val4 == 1 ) status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); break; case SC_FIGHTINGSPIRIT: @@ -7603,7 +7533,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } vd = status->get_viewdata(bl); - calc_flag = status->ChangeFlagTable[type]; + calc_flag = status->dbs->ChangeFlagTable[type]; if(!(flag&SCFLAG_LOADED)) { // Do not parse val settings when loading SCs switch(type) { case SC_ADORAMUS: @@ -7619,7 +7549,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t struct map_session_data *tsd; if( sd ) { int i; - for( i = 0; i < 5; i++ ) { + for( i = 0; i < MAX_PC_DEVOTION; i++ ) { if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) ) status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, SCFLAG_ALL); } @@ -7646,11 +7576,13 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t tick = -1; // duration sent to the client should be infinite break; case SC_EDP: // [Celest] - val2 = val1 + 2; //Chance to Poison enemies. - val3 = 50*(val1+1); //Damage increase (+50 +50*lv%) - #ifdef RENEWAL_EDP - val4 = 100 * ((val1 + 1)/2 + 2); - #endif + //Chance to Poison enemies. +#ifdef RENEWAL_EDP + val2 = ((val1 + 1) / 2 + 2); +#else + val2 = val1 + 2; +#endif + val3 = 50 * (val1 + 1); //Damage increase (+50 +50*lv%) if( sd )//[Ind] - iROwiki says each level increases its duration by 3 seconds tick += pc->checkskill(sd,GC_RESEARCHNEWPOISON)*3000; break; @@ -7716,7 +7648,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t struct map_session_data *tsd; if( sd ) { int i; - for( i = 0; i < 5; i++ ) { + for( i = 0; i < MAX_PC_DEVOTION; i++ ) { if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) ) status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL); } @@ -7974,7 +7906,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if( bl->type&(BL_PC|BL_MER) ) { if( sd ) { - for( i = 0; i < 5; i++ ) { + for( i = 0; i < MAX_PC_DEVOTION; i++ ) { if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) ) status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL); } @@ -7994,7 +7926,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if (sd) { struct map_session_data *tsd; int i; - for (i = 0; i < 5; i++) { + for (i = 0; i < MAX_PC_DEVOTION; i++) { //See if there are devoted characters, and pass the status to them. [Skotlex] if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i]))) status->change_start(bl, &tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,SCFLAG_NOAVOID); @@ -8030,7 +7962,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_BERSERK: if( val3 == SC__BLOODYLUST ) sc_start(src,bl,(sc_type)val3,100,val1,tick); - if( !val3 && !(!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4) ) + if (!val3 && (!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4)) sc_start4(src, bl, SC_ENDURE, 100,10,0,0,2, tick); //HP healing is performing after the calc_status call. //Val2 holds HP penalty @@ -8887,6 +8819,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t else val2 = val2 / 4 * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level] break; + case SC_GENTLETOUCH_ENERGYGAIN: + val2 = 10 + 5 * val1; + break; case SC_PYROTECHNIC_OPTION: val2 = 60; break; @@ -9129,7 +9064,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val2 = 20+(20*val1); break; default: - if (calc_flag == SCB_NONE && status->SkillChangeTable[type] == 0 && status->IconChangeTable[type] == 0) { + if (calc_flag == SCB_NONE && status->dbs->SkillChangeTable[type] == 0 && status->dbs->IconChangeTable[type] == 0) { //Status change with no calc, no icon, and no skill associated...? ShowError("UnknownStatusChange [%d]\n", type); return 0; @@ -9283,7 +9218,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } /* [Ind/Hercules] */ - if( sd && status->DisplayType[type] ) { + if( sd && status->dbs->DisplayType[type] ) { int dval1 = 0, dval2 = 0, dval3 = 0; switch( type ) { case SC_ALL_RIDING: @@ -9334,11 +9269,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_MEIKYOUSISUI: case SC_NEEDLE_OF_PARALYZE: case SC_DEATHBOUND: - unit->stop_walking(bl,1); + case SC_NETHERWORLD: + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); break; case SC_ANKLESNARE: if( battle_config.skill_trap_type || !map_flag_gvg(bl->m) ) - unit->stop_walking(bl,1); + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); break; case SC_HIDING: case SC_CLOAKING: @@ -9575,8 +9511,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t calc_flag&=~SCB_DYE; } - if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->DisplayType[type])) - clif->status_change(bl,status->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); + if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->dbs->DisplayType[type])) + clif->status_change(bl,status->dbs->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); /** * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first. @@ -9592,14 +9528,18 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t ++(sc->count); sce = sc->data[type] = ers_alloc(status->data_ers, struct status_change_entry); } + sce->val1 = val1; sce->val2 = val2; sce->val3 = val3; sce->val4 = val4; - if (tick >= 0) + + if (tick >= 0) { sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type); - else { + sce->infinite_duration = false; + } else { sce->timer = INVALID_TIMER; //Infinite duration + sce->infinite_duration = true; if( sd ) chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce); } @@ -9629,7 +9569,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } break; case SC_CASH_BOSS_ALARM: - clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message + if( sd ) + clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message break; case SC_MER_HP: status_percent_heal(bl, 100, 0); // Recover Full HP @@ -9773,17 +9714,18 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const nullpo_ret(bl); sc = status->get_sc(bl); - st = status->get_status_data(bl); if(type < 0 || type >= SC_MAX || !sc || !(sce = sc->data[type])) return 0; sd = BL_CAST(BL_PC,bl); - if (sce->timer != tid && tid != INVALID_TIMER) + if (sce->timer != tid && tid != INVALID_TIMER && sce->timer != INVALID_TIMER) return 0; - if( sd && sce->timer == INVALID_TIMER && !sd->state.loggingout ) + st = status->get_status_data(bl); + + if( sd && sce->infinite_duration && !sd->state.loggingout ) chrif->del_scdata_single(sd->status.account_id,sd->status.char_id,type); if (tid == INVALID_TIMER) { @@ -9817,7 +9759,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const sc->data[type] = NULL; - if( sd && status->DisplayType[type] ) { + if( sd && status->dbs->DisplayType[type] ) { status->display_remove(sd,type); } @@ -9827,7 +9769,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const #endif vd = status->get_viewdata(bl); - calc_flag = status->ChangeFlagTable[type]; + calc_flag = status->dbs->ChangeFlagTable[type]; switch(type) { case SC_GRANITIC_ARMOR: { @@ -9854,7 +9796,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const begin_spurt = false; ud->state.running = 0; if (ud->walktimer != INVALID_TIMER) - unit->stop_walking(bl,1); + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); } if (begin_spurt && sce->val1 >= 7 && DIFF_TICK(timer->gettick(), starttick) <= 1000 @@ -9877,7 +9819,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if( bl->type == BL_PC ) { // Clear Status from others int i; - for( i = 0; i < 5; i++ ) { + for( i = 0; i < MAX_PC_DEVOTION; i++ ) { if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) && tsd->sc.data[type] ) status_change_end(&tsd->bl, type, INVALID_TIMER); } @@ -9964,7 +9906,9 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } sce->val2 = 0; - skill->del_unitgroup(group,ALC_MARK); + + if( group ) + skill->del_unitgroup(group,ALC_MARK); } if ((sce->val1&0xFFFF) == CG_MOONLIT) @@ -9996,11 +9940,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if (src && sc2 && sc2->data[SC_RG_CCONFINE_M]) { //If status was already ended, do nothing. //Decrease count - if (--(sc2->data[SC_RG_CCONFINE_M]->val1) <= 0) //No more holds, free him up. + if (--(sc2->data[SC_RG_CCONFINE_M]->val2) <= 0) //No more holds, free him up. status_change_end(src, SC_RG_CCONFINE_M, INVALID_TIMER); } } - /* Fall through */ + break; case SC_RG_CCONFINE_M: if (sce->val2 > 0) { //Caster has been unlocked... nearby chars need to be unlocked. @@ -10067,7 +10011,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if (sce->val3) { //Clear the group. struct skill_unit_group* group = skill->id2group(sce->val3); sce->val3 = 0; - skill->del_unitgroup(group,ALC_MARK); + if( group ) + skill->del_unitgroup(group,ALC_MARK); } break; case SC_HERMODE: @@ -10113,10 +10058,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const break; // Note: vending/buying is closed by unit_remove_map, no // need to do it here. - map->quit(sd); - // Because map->quit calls status_change_end with tid -1 - // from here it's not neccesary to continue - return 1; + if( sd ) { + map->quit(sd); + // Because map->quit calls status_change_end with tid -1 + // from here it's not neccesary to continue + return 1; + } break; case SC_STOP: if( sce->val2 ) { @@ -10128,7 +10075,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } break; case SC_LKCONCENTRATION: - status_change_end(bl, SC_ENDURE, INVALID_TIMER); + if (sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 != 2) + status_change_end(bl, SC_ENDURE, INVALID_TIMER); break; /** * 3rd Stuff @@ -10144,7 +10092,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const struct block_list* src = map->id2bl(sce->val2); if( tid == -1 || !src) break; // Terminated by Damage - status_fix_damage(src,bl,400*sce->val1,clif->damage(bl,bl,0,0,400*sce->val1,0,0,0)); + status_fix_damage(src,bl,400*sce->val1,clif->damage(bl,bl,0,0,400*sce->val1,0,BDT_NORMAL,0)); } break; case SC_WUGDASH: @@ -10153,7 +10101,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if (ud) { ud->state.running = 0; if (ud->walktimer != -1) - unit->stop_walking(bl,1); + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); } } break; @@ -10196,15 +10144,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const map->foreachinrange(status->change_timer_sub, bl, battle_config.area_size,BL_CHAR, bl, sce, SC_CURSEDCIRCLE_TARGET, timer->gettick()); break; case SC_RAISINGDRAGON: - if( sd && sce->val2 && !pc_isdead(sd) ) { + if ( sd && sce->val2 && !pc_isdead(sd) ) { int i; - i = min(sd->spiritball,5); - pc->delspiritball(sd, sd->spiritball, 0); + if ( (i = (sd->spiritball - 5)) > 0 ) + pc->delspiritball(sd, i, 0); status_change_end(bl, SC_EXPLOSIONSPIRITS, INVALID_TIMER); - while( i > 0 ) { - pc->addspiritball(sd, skill->get_time(MO_CALLSPIRITS, pc->checkskill(sd,MO_CALLSPIRITS)), 5); - --i; - } } break; case SC_CURSEDCIRCLE_TARGET: @@ -10222,7 +10166,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const struct block_list *src = map->id2bl(sce->val2); if(src) { struct status_change *ssc = status->get_sc(src); - ssc->bs_counter--; + if( ssc ) + ssc->bs_counter--; } } break; @@ -10468,7 +10413,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } //On Aegis, when turning off a status change, first goes the sc packet, then the option packet. - clif->sc_end(bl,bl->id,AREA,status->IconChangeTable[type]); + clif->sc_end(bl,bl->id,AREA,status->dbs->IconChangeTable[type]); if( opt_flag&8 ) //bugreport:681 clif->changeoption2(bl); @@ -10563,6 +10508,8 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { ShowError("status_change_timer: Mismatch for type %d: %d != %d (bl id %d)\n",type,tid,sce->timer, bl->id); return 0; } + + sce->timer = INVALID_TIMER; sd = BL_CAST(BL_PC, bl); @@ -10593,7 +10540,6 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { } sc_timer_next(sce->val2+tick, status->change_timer, bl->id, data); return 0; - break; case SC_SKA: if(--(sce->val2)>0) { @@ -10641,12 +10587,12 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { case SC_STONE: if(sc->opt1 == OPT1_STONEWAIT && sce->val3) { sce->val4 = 0; - unit->stop_walking(bl,1); + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); unit->stop_attack(bl); sc->opt1 = OPT1_STONE; clif->changeoption(bl); sc_timer_next(1000+tick, status->change_timer, bl->id, data ); - status_calc_bl(bl, status->ChangeFlagTable[type]); + status_calc_bl(bl, status->dbs->ChangeFlagTable[type]); return 0; } if(--(sce->val3) > 0) { @@ -10688,14 +10634,16 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { case SC_KNOWLEDGE: if (!sd) break; - if (bl->m == sd->feel_map[0].m - || bl->m == sd->feel_map[1].m - || bl->m == sd->feel_map[2].m - ) { - //Timeout will be handled by pc->setpos - sce->timer = INVALID_TIMER; - return 0; + { + int i; + for (i = 0; i < MAX_PC_FEELHATE; i++) { + if (bl->m == sd->feel_map[i].m) { + //Timeout will be handled by pc->setpos + sce->timer = INVALID_TIMER; + return 0; + } } + } break; case SC_BLOODING: @@ -10882,7 +10830,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { case SC_PYREXIA: if( --(sce->val4) > 0 ) { map->freeblock_lock(); - clif->damage(bl,bl,status_get_amotion(bl),status_get_dmotion(bl)+500,100,0,0,0); + clif->damage(bl,bl,status_get_amotion(bl),status_get_dmotion(bl)+500,100,0,BDT_NORMAL,0); status_fix_damage(NULL,bl,100,0); if( sc->data[type] ) { sc_timer_next(3000+tick,status->change_timer,bl->id,data); @@ -10898,7 +10846,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { damage += st->vit * (sce->val1 - 3); unit->skillcastcancel(bl,2); map->freeblock_lock(); - status->damage(bl, bl, damage, 0, clif->damage(bl,bl,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,0,0), 1); + status->damage(bl, bl, damage, 0, clif->damage(bl,bl,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,BDT_NORMAL,0), 1); if( sc->data[type] ) { sc_timer_next(1000 + tick, status->change_timer, bl->id, data ); } @@ -10922,13 +10870,15 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { } if( !flag ) { // Random Skill Cast + map->freeblock_lock(); + if (sd && !pc_issit(sd)) { //can't cast if sit int mushroom_skill_id = 0; unit->stop_attack(bl); unit->skillcastcancel(bl,0); do { int i = rnd() % MAX_SKILL_MAGICMUSHROOM_DB; - mushroom_skill_id = skill->magicmushroom_db[i].skill_id; + mushroom_skill_id = skill->dbs->magicmushroom_db[i].skill_id; } while (mushroom_skill_id == 0); switch( skill->get_casttype(mushroom_skill_id) ) { // Magic Mushroom skills are buffs or area damage @@ -10945,7 +10895,10 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { } clif->emotion(bl,E_HEH); - sc_timer_next(4000+tick,status->change_timer,bl->id,data); + if( sc->data[type] ) + sc_timer_next(4000+tick,status->change_timer,bl->id,data); + + map->freeblock_unlock(); } return 0; } @@ -10955,7 +10908,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { if( --(sce->val4) > 0 ) { //Damage is every 10 seconds including 3%sp drain. map->freeblock_lock(); - clif->damage(bl,bl,status_get_amotion(bl),1,1,0,0,0); + clif->damage(bl,bl,status_get_amotion(bl),1,1,0,BDT_NORMAL,0); status->damage(NULL, bl, 1, st->max_sp * 3 / 100, 0, 0); //cancel dmg only if cancelable if( sc->data[type] ) { sc_timer_next(10000 + tick, status->change_timer, bl->id, data ); @@ -10993,8 +10946,15 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { int heal = st->max_hp * 3 / 100; if (sc->count && sc->data[SC_AKAITSUKI] && heal) heal = ~heal + 1; + + map->freeblock_lock(); + status->heal(bl, heal, 0, 2); - sc_timer_next(5000 + tick, status->change_timer, bl->id, data); + if( sc->data[type] ) { + sc_timer_next(5000 + tick, status->change_timer, bl->id, data); + } + map->freeblock_unlock(); + return 0; } break; @@ -11005,7 +10965,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { int damage = 1000 + 3 * status_get_max_hp(bl) / 100; // Deals fixed (1000 + 3%*MaxHP) map->freeblock_lock(); - clif->damage(bl,bl,0,0,damage,1,9,0); //damage is like endure effect with no walk delay + clif->damage(bl,bl,0,0,damage,1,BDT_MULTIENDURE,0); //damage is like endure effect with no walk delay status->damage(src, bl, damage, 0, 0, 1); if( sc->data[type]){ // Target still lives. [LimitLine] @@ -11107,13 +11067,13 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { break; map->freeblock_lock(); damage = sce->val3; - status->damage(src, bl, damage, 0, clif->damage(bl,bl,st->amotion,st->dmotion+200,damage,1,0,0), 1); + status->damage(src, bl, damage, 0, clif->damage(bl,bl,st->amotion,st->dmotion+200,damage,1,BDT_NORMAL,0), 1); unit->skillcastcancel(bl,1); if ( sc->data[type] ) { sc_timer_next(1000 + tick, status->change_timer, bl->id, data); } - map->freeblock_unlock(); status->heal(src, damage*(5 + 5 * sce->val1)/100, 0, 0); // 5 + 5% per level + map->freeblock_unlock(); return 0; } break; @@ -11215,11 +11175,12 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { int damage = st->max_hp / 100; // Suggestion 1% each second if( damage >= st->hp ) damage = st->hp - 1; // Do not kill, just keep you with 1 hp minimum map->freeblock_lock(); - status_fix_damage(NULL,bl,damage,clif->damage(bl,bl,0,0,damage,0,0,0)); + status_fix_damage(NULL,bl,damage,clif->damage(bl,bl,0,0,damage,0,BDT_NORMAL,0)); if( sc->data[type] ) { sc_timer_next(1000 + tick, status->change_timer, bl->id, data); } map->freeblock_unlock(); + return 0; } break; @@ -11300,18 +11261,19 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { case SC_WATER_DROP: case SC_WIND_CURTAIN: case SC_STONE_SHIELD: - if(status->charge(bl, 0, sce->val2) && (sce->val4==-1 || (sce->val4-=sce->val3)>=0)) + if(status->charge(bl, 0, sce->val2) && (sce->val4==-1 || (sce->val4-=sce->val3)>=0)) { sc_timer_next(sce->val3 + tick, status->change_timer, bl->id, data); - else + return 0; + } else if (bl->type == BL_ELEM) elemental->change_mode(BL_CAST(BL_ELEM,bl),MAX_ELESKILLTREE); - return 0; + break; case SC_STOMACHACHE: if( --(sce->val4) > 0 ) { status->charge(bl,0,sce->val2); // Reduce 8 every 10 seconds. if( sd && !pc_issit(sd) ) { // Force to sit every 10 seconds. - pc_stop_walking(sd,1|4); + pc_stop_walking(sd, STOPWALKING_FLAG_FIXPOS|STOPWALKING_FLAG_NEXTCELL); pc_stop_attack(sd); pc_setsit(sd); clif->sitting(bl); @@ -11495,7 +11457,7 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl short index = sd->equip_index[EQI_HAND_R], refine; if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON && (refine = sd->status.inventory[index].refine) < 16 && refine ) { - int r = status->refine_info[watk->wlv].randombonus_max[refine + (4 - watk->wlv)] / 100; + int r = status->dbs->refine_info[watk->wlv].randombonus_max[refine + (4 - watk->wlv)] / 100; if ( r ) max += (rnd() % 100) % r + 1; } @@ -11594,7 +11556,7 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m short index = sd->equip_index[EQI_HAND_R], refine; if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON && (refine = sd->status.inventory[index].refine) < 16 && refine ) { - int r = status->refine_info[sd->inventory_data[index]->wlv].randombonus_max[refine + (4 - sd->inventory_data[index]->wlv)] / 100; + int r = status->dbs->refine_info[sd->inventory_data[index]->wlv].randombonus_max[refine + (4 - sd->inventory_data[index]->wlv)] / 100; if ( r ) *matk_max += (rnd() % 100) % r + 1; } @@ -11691,6 +11653,8 @@ int status_change_clear_buffs (struct block_list* bl, int type) { if (!sc || !sc->count) return 0; + map->freeblock_lock(); + if (type&6) //Debuffs for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) status_change_end(bl, (sc_type)i, INVALID_TIMER); @@ -11737,6 +11701,9 @@ int status_change_clear_buffs (struct block_list* bl, int type) { } status_change_end(bl, (sc_type)i, INVALID_TIMER); } + + map->freeblock_unlock(); + return 0; } @@ -12032,7 +11999,7 @@ int status_get_refine_chance(enum refine_type wlv, int refine) { if ( refine < 0 || refine >= MAX_REFINE) return 0; - return status->refine_info[wlv].chance[refine]; + return status->dbs->refine_info[wlv].chance[refine]; } int status_get_sc_type(sc_type type) { @@ -12040,43 +12007,206 @@ int status_get_sc_type(sc_type type) { if( type <= SC_NONE || type >= SC_MAX ) return 0; - return status->sc_conf[type]; + return status->dbs->sc_conf[type]; +} + +void status_read_job_db_sub(int idx, const char *name, config_setting_t *jdb) +{ + config_setting_t *temp = NULL; + int i32 = 0; + + struct { + const char *name; + int id; + } wnames[] = { + { "Fist", W_FIST }, + { "Dagger", W_DAGGER }, + { "Sword", W_1HSWORD }, + { "TwoHandSword", W_2HSWORD }, + { "Spear", W_1HSPEAR }, + { "TwoHandSpear", W_2HSPEAR }, + { "Axe", W_1HAXE }, + { "TwoHandAxe", W_2HAXE }, + { "Mace", W_MACE }, + { "TwoHandMace", W_2HMACE }, + { "Rod", W_STAFF }, + { "Bow", W_BOW }, + { "Knuckle", W_KNUCKLE }, + { "Instrument", W_MUSICAL }, + { "Whip", W_WHIP }, + { "Book", W_BOOK }, + { "Katar", W_KATAR }, + { "Revolver", W_REVOLVER }, + { "Rifle", W_RIFLE }, + { "GatlingGun", W_GATLING }, + { "Shotgun", W_SHOTGUN }, + { "GrenadeLauncher", W_GRENADE }, + { "FuumaShuriken", W_HUUMA }, + { "TwoHandRod", W_2HSTAFF }, +#ifdef RENEWAL_ASPD + { "Shield", MAX_WEAPON_TYPE } +#endif + }; + + if ((temp = libconfig->setting_get_member(jdb, "Inherit"))) { + int nidx = 0; + const char *iname; + while ((iname = libconfig->setting_get_string_elem(temp, nidx++))) { + int i, iidx, iclass, avg_increment, base; + if ((iclass = pc->check_job_name(iname)) == -1) { + ShowWarning("status_read_job_db: '%s' trying to inherit unknown '%s'!\n", name, iname); + continue; + } + iidx = pc->class2idx(iclass); + status->dbs->max_weight_base[idx] = status->dbs->max_weight_base[iidx]; + memcpy(&status->dbs->aspd_base[idx], &status->dbs->aspd_base[iidx], sizeof(status->dbs->aspd_base[iidx])); + + for (i = 1; i <= MAX_LEVEL && status->dbs->HP_table[iidx][i]; i++) { + status->dbs->HP_table[idx][i] = status->dbs->HP_table[iidx][i]; + } + base = (i > 1 ? status->dbs->HP_table[idx][1] : 35); // Safe value if none are specified + avg_increment = (i > 2 ? (status->dbs->HP_table[idx][i] - base) / (i-1) : 5); // Safe value if none are specified + for ( ; i <= pc->max_level[idx][0]; i++) { + status->dbs->HP_table[idx][i] = min(base + avg_increment * i, battle_config.max_hp); + } + + for (i = 1; i <= MAX_LEVEL && status->dbs->SP_table[iidx][i]; i++) { + status->dbs->SP_table[idx][i] = status->dbs->SP_table[iidx][i]; + } + base = (i > 1 ? status->dbs->SP_table[idx][1] : 10); // Safe value if none are specified + avg_increment = (i > 2 ? (status->dbs->SP_table[idx][i] - base) / (i-1) : 1); // Safe value if none are specified + for ( ; i <= pc->max_level[idx][0]; i++) { + status->dbs->SP_table[idx][i] = min(base + avg_increment * i, battle_config.max_sp); + } + } + } + if ((temp = libconfig->setting_get_member(jdb, "InheritHP"))) { + int nidx = 0; + const char *iname; + while ((iname = libconfig->setting_get_string_elem(temp, nidx++))) { + int i, iidx, iclass, avg_increment, base; + if ((iclass = pc->check_job_name(iname)) == -1) { + ShowWarning("status_read_job_db: '%s' trying to inherit unknown '%s' HP!\n", name, iname); + continue; + } + iidx = pc->class2idx(iclass); + for (i = 1; i <= MAX_LEVEL && status->dbs->HP_table[iidx][i]; i++) { + status->dbs->HP_table[idx][i] = status->dbs->HP_table[iidx][i]; + } + base = (i > 1 ? status->dbs->HP_table[idx][1] : 35); // Safe value if none are specified + avg_increment = (i > 2 ? (status->dbs->HP_table[idx][i] - base) / (i-1) : 5); // Safe value if none are specified + for ( ; i <= pc->max_level[idx][0]; i++) { + status->dbs->HP_table[idx][i] = min(base + avg_increment * i, battle_config.max_hp); + } + } + } + if ((temp = libconfig->setting_get_member(jdb, "InheritSP"))) { + int nidx = 0; + const char *iname; + while ((iname = libconfig->setting_get_string_elem(temp, nidx++))) { + int i, iidx, iclass, avg_increment, base; + if ((iclass = pc->check_job_name(iname)) == -1) { + ShowWarning("status_read_job_db: '%s' trying to inherit unknown '%s' SP!\n", name, iname); + continue; + } + iidx = pc->class2idx(iclass); + for (i = 1; i <= MAX_LEVEL && status->dbs->SP_table[iidx][i]; i++) { + status->dbs->SP_table[idx][i] = status->dbs->SP_table[iidx][i]; + } + base = (i > 1 ? status->dbs->SP_table[idx][1] : 10); // Safe value if none are specified + avg_increment = (i > 2 ? (status->dbs->SP_table[idx][i] - base) / (i-1) : 1); // Safe value if none are specified + for ( ; i <= pc->max_level[idx][0]; i++) { + status->dbs->SP_table[idx][i] = min(avg_increment * i, battle_config.max_sp); + } + } + } + + if (libconfig->setting_lookup_int(jdb, "Weight", &i32)) + status->dbs->max_weight_base[idx] = i32; + else if (!status->dbs->max_weight_base[idx]) + status->dbs->max_weight_base[idx] = 20000; + + if ((temp = libconfig->setting_get_member(jdb, "BaseASPD"))) { + int widx = 0; + config_setting_t *wpn = NULL; + while ((wpn = libconfig->setting_get_elem(temp, widx++))) { + int w, wlen = ARRAYLENGTH(wnames); + const char *wname = config_setting_name(wpn); + + ARR_FIND(0, wlen, w, strcmp(wnames[w].name, wname) == 0); + if (w != wlen) { + status->dbs->aspd_base[idx][wnames[w].id] = libconfig->setting_get_int(wpn); + } else { + ShowWarning("status_read_job_db: unknown weapon type '%s'!\n", wname); + } + } + } + + if ((temp = libconfig->setting_get_member(jdb, "HPTable"))) { + int level = 0, avg_increment, base; + config_setting_t *hp = NULL; + while (level <= MAX_LEVEL && (hp = libconfig->setting_get_elem(temp, level))) { + i32 = libconfig->setting_get_int(hp); + status->dbs->HP_table[idx][++level] = min(i32, battle_config.max_hp); + } + base = (level > 0 ? status->dbs->HP_table[idx][1] : 35); // Safe value if none are specified + avg_increment = (level > 1 ? (status->dbs->HP_table[idx][level] - base) / level : 5); // Safe value if none are specified + for (++level; level <= pc->max_level[idx][0]; ++level) { /* limit only to possible maximum level of the given class */ + status->dbs->HP_table[idx][level] = min(base + avg_increment * level, battle_config.max_hp); /* some are still empty? then let's use the average increase */ + } + } + + if ((temp = libconfig->setting_get_member(jdb, "SPTable"))) { + int level = 0, avg_increment, base; + config_setting_t *sp = NULL; + while (level <= MAX_LEVEL && (sp = libconfig->setting_get_elem(temp, level))) { + i32 = libconfig->setting_get_int(sp); + status->dbs->SP_table[idx][++level] = min(i32, battle_config.max_sp); + } + base = (level > 0 ? status->dbs->SP_table[idx][1] : 10); // Safe value if none are specified + avg_increment = (level > 1 ? (status->dbs->SP_table[idx][level] - base) / level : 1); + for ( ; level <= pc->max_level[idx][0]; level++ ) { + status->dbs->SP_table[idx][level] = min(base + avg_increment * level, battle_config.max_sp); + } + } } /*------------------------------------------ * DB reading. -* job_db1.txt - weight, hp, sp, aspd +* job_db.conf - weight, hp, sp, aspd * job_db2.txt - job level stat bonuses * size_fix.txt - size adjustment table for weapons * refine_db.txt - refining data table *------------------------------------------*/ -bool status_readdb_job1(char* fields[], int columns, int current) -{// Job-specific values (weight, HP, SP, ASPD) - int idx, class_; - unsigned int i; - - class_ = atoi(fields[0]); - - if(!pc->db_checkid(class_)) - { - ShowWarning("status_readdb_job1: Invalid job class %d specified.\n", class_); - return false; - } - idx = pc->class2idx(class_); - - status->max_weight_base[idx] = atoi(fields[1]); - status->hp_coefficient[idx] = atoi(fields[2]); - status->hp_coefficient2[idx] = atoi(fields[3]); - status->sp_coefficient[idx] = atoi(fields[4]); +void status_read_job_db(void) { /* [malufett/Hercules] */ + int i = 0; + config_t job_db_conf; + config_setting_t *jdb = NULL; + const char *config_filename = #ifdef RENEWAL_ASPD - for(i = 0; i <= MAX_WEAPON_TYPE; i++) + "db/re/job_db.conf"; #else - for(i = 0; i < MAX_WEAPON_TYPE; i++) + "db/pre-re/job_db.conf"; #endif - { - status->aspd_base[idx][i] = atoi(fields[i+5]); + + if ( libconfig->read_file(&job_db_conf, config_filename) ) { + ShowError("can't read %s\n", config_filename); + return; } - return true; + while ( (jdb = libconfig->setting_get_elem(job_db_conf.root, i++)) ) { + int class_, idx; + const char *name = config_setting_name(jdb); + + if ( (class_ = pc->check_job_name(name)) == -1 ) { + ShowWarning("pc_read_job_db: '%s' unknown job name!\n", name); + continue; + } + + idx = pc->class2idx(class_); + status->read_job_db_sub(idx, name, jdb); + } + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, config_filename); + libconfig->destroy(&job_db_conf); } bool status_readdb_job2(char* fields[], int columns, int current) @@ -12094,7 +12224,7 @@ bool status_readdb_job2(char* fields[], int columns, int current) for(i = 1; i < columns; i++) { - status->job_bonus[idx][i-1] = atoi(fields[i]); + status->dbs->job_bonus[idx][i-1] = atoi(fields[i]); } return true; } @@ -12105,7 +12235,7 @@ bool status_readdb_sizefix(char* fields[], int columns, int current) for(i = 0; i < MAX_WEAPON_TYPE; i++) { - status->atkmods[current][i] = atoi(fields[i]); + status->dbs->atkmods[current][i] = atoi(fields[i]); } return true; } @@ -12132,14 +12262,14 @@ bool status_readdb_refine(char* fields[], int columns, int current) *delim = '\0'; - status->refine_info[current].chance[i] = atoi(fields[4+i]); + status->dbs->refine_info[current].chance[i] = atoi(fields[4+i]); if (i >= random_bonus_start_level - 1) - status->refine_info[current].randombonus_max[i] = random_bonus * (i - random_bonus_start_level + 2); + status->dbs->refine_info[current].randombonus_max[i] = random_bonus * (i - random_bonus_start_level + 2); - status->refine_info[current].bonus[i] = bonus_per_level + atoi(delim+1); + status->dbs->refine_info[current].bonus[i] = bonus_per_level + atoi(delim+1); if (i > 0) - status->refine_info[current].bonus[i] += status->refine_info[current].bonus[i-1]; + status->dbs->refine_info[current].bonus[i] += status->dbs->refine_info[current].bonus[i-1]; } return true; } @@ -12153,7 +12283,7 @@ bool status_readdb_scconfig(char* fields[], int columns, int current) { return false; } - status->sc_conf[val] = (int)strtol(fields[1], NULL, 0); + status->dbs->sc_conf[val] = (int)strtol(fields[1], NULL, 0); return true; } @@ -12171,42 +12301,42 @@ int status_readdb(void) // initialize databases to default // if( runflag == MAPSERVER_ST_RUNNING ) {//not necessary during boot - // reset job_db1.txt data - memset(status->max_weight_base, 0, sizeof(status->max_weight_base)); - memset(status->hp_coefficient, 0, sizeof(status->hp_coefficient)); - memset(status->hp_coefficient2, 0, sizeof(status->hp_coefficient2)); - memset(status->sp_coefficient, 0, sizeof(status->sp_coefficient)); - memset(status->aspd_base, 0, sizeof(status->aspd_base)); + // reset job_db.conf data + memset(status->dbs->max_weight_base, 0, sizeof(status->dbs->max_weight_base)); + memset(status->dbs->HP_table, 0, sizeof(status->dbs->HP_table)); + memset(status->dbs->SP_table, 0, sizeof(status->dbs->SP_table)); // reset job_db2.txt data - memset(status->job_bonus,0,sizeof(status->job_bonus)); // Job-specific stats bonus + memset(status->dbs->job_bonus,0,sizeof(status->dbs->job_bonus)); // Job-specific stats bonus + } + for ( i = 0; i < CLASS_COUNT; i++ ) { + for ( j = 0; j < MAX_WEAPON_TYPE; j++ ) + status->dbs->aspd_base[i][j] = 2000; +#ifdef RENEWAL_ASPD + status->dbs->aspd_base[i][MAX_WEAPON_TYPE] = 0; +#endif } + // size_fix.txt - for(i = 0; i < ARRAYLENGTH(status->atkmods); i++) + for(i = 0; i < ARRAYLENGTH(status->dbs->atkmods); i++) for(j = 0; j < MAX_WEAPON_TYPE; j++) - status->atkmods[i][j] = 100; + status->dbs->atkmods[i][j] = 100; // refine_db.txt - for(i=0;i<ARRAYLENGTH(status->refine_info);i++) { + for(i=0;i<ARRAYLENGTH(status->dbs->refine_info);i++) { for(j=0;j<MAX_REFINE; j++) { - status->refine_info[i].chance[j] = 100; - status->refine_info[i].bonus[j] = 0; - status->refine_info[i].randombonus_max[j] = 0; + status->dbs->refine_info[i].chance[j] = 100; + status->dbs->refine_info[i].bonus[j] = 0; + status->dbs->refine_info[i].randombonus_max[j] = 0; } } // read databases // - - -#ifdef RENEWAL_ASPD - sv->readdb(map->db_path, "re/job_db1.txt", ',', 6+MAX_WEAPON_TYPE, 6+MAX_WEAPON_TYPE, -1, status->readdb_job1); -#else - sv->readdb(map->db_path, "pre-re/job_db1.txt", ',', 5+MAX_WEAPON_TYPE, 5+MAX_WEAPON_TYPE, -1, status->readdb_job1); -#endif sv->readdb(map->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, status->readdb_job2); - sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(status->atkmods), status->readdb_sizefix); - sv->readdb(map->db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(status->refine_info), status->readdb_refine); + sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(status->dbs->atkmods), status->readdb_sizefix); + sv->readdb(map->db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(status->dbs->refine_info), status->readdb_refine); sv->readdb(map->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, status->readdb_scconfig); + status->read_job_db(); return 0; } @@ -12224,7 +12354,6 @@ int do_init_status(bool minimal) { status->initChangeTables(); status->initDummyData(); status->readdb(); - status->calc_sigma(); status->natural_heal_prev_tick = timer->gettick(); status->data_ers = ers_new(sizeof(struct status_change_entry),"status.c::data_ers",ERS_OPT_NONE); timer->add_interval(status->natural_heal_prev_tick + NATURAL_HEAL_INTERVAL, status->natural_heal_timer, 0, 0, NATURAL_HEAL_INTERVAL); @@ -12241,6 +12370,7 @@ void do_final_status(void) { *-------------------------------------*/ void status_defaults(void) { status = &status_s; + status->dbs = &statusdbs; /* vars */ //we need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only @@ -12248,23 +12378,8 @@ void status_defaults(void) { status->current_equip_item_index = 0; //Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus] status->current_equip_card_id = 0; //To prevent card-stacking (from jA) [Skotlex] - memset(status->max_weight_base,0,sizeof(status->max_weight_base) - + sizeof(status->hp_coefficient) - + sizeof(status->hp_coefficient2) - + sizeof(status->hp_sigma_val) - + sizeof(status->sp_coefficient) - + sizeof(status->aspd_base) - + sizeof(status->Skill2SCTable) - + sizeof(status->IconChangeTable) - + sizeof(status->ChangeFlagTable) - + sizeof(status->SkillChangeTable) - + sizeof(status->RelevantBLTypes) - + sizeof(status->DisplayType) - + sizeof(status->refine_info) - + sizeof(status->atkmods) - + sizeof(status->job_bonus) - + sizeof(status->sc_conf) - ); + // These macros are used instead of a sum of sizeof(), to ensure that padding won't interfere with our size, and code won't rot when adding more fields + memset(ZEROED_BLOCK_POS(status->dbs), 0, ZEROED_BLOCK_SIZE(status->dbs)); status->data_ers = NULL; memset(&status->dummy, 0, sizeof(status->dummy)); @@ -12361,9 +12476,8 @@ void status_defaults(void) { status->initDummyData = initDummyData; status->base_amotion_pc = status_base_amotion_pc; status->base_atk = status_base_atk; - status->calc_sigma = status_calc_sigma; - status->base_pc_maxhp = status_base_pc_maxhp; - status->base_pc_maxsp = status_base_pc_maxsp; + status->get_base_maxhp = status_get_base_maxhp; + status->get_base_maxsp = status_get_base_maxsp; status->calc_npc_ = status_calc_npc_; status->calc_str = status_calc_str; status->calc_agi = status_calc_agi; @@ -12393,9 +12507,10 @@ void status_defaults(void) { status->display_remove = status_display_remove; status->natural_heal = status_natural_heal; status->natural_heal_timer = status_natural_heal_timer; - status->readdb_job1 = status_readdb_job1; status->readdb_job2 = status_readdb_job2; status->readdb_sizefix = status_readdb_sizefix; status->readdb_refine = status_readdb_refine; status->readdb_scconfig = status_readdb_scconfig; + status->read_job_db = status_read_job_db; + status->read_job_db_sub = status_read_job_db_sub; } diff --git a/src/map/status.h b/src/map/status.h index 1a8d7ef51..45a1300a0 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -5,10 +5,11 @@ #ifndef MAP_STATUS_H #define MAP_STATUS_H -#include "../config/core.h" // defType, RENEWAL, RENEWAL_ASPD +#include "config/core.h" // defType, RENEWAL, RENEWAL_ASPD -#include "../common/cbasetypes.h" -#include "../common/mmo.h" // NEW_CARTS +#include "common/conf.h" +#include "common/cbasetypes.h" +#include "common/mmo.h" // NEW_CARTS struct block_list; struct elemental_data; @@ -527,7 +528,7 @@ typedef enum sc_type { SC_BEYOND_OF_WARCRY, SC_UNLIMITED_HUMMING_VOICE, // 410 SC_SITDOWN_FORCE, - //SC_NETHERWORLD, + SC_NETHERWORLD, /** * Sura **/ @@ -1655,49 +1656,6 @@ enum { OPT3_CONTRACT = 0x00020000, }; -enum { - OPTION_NOTHING = 0x00000000, - OPTION_SIGHT = 0x00000001, - OPTION_HIDE = 0x00000002, - OPTION_CLOAK = 0x00000004, - OPTION_FALCON = 0x00000010, - OPTION_RIDING = 0x00000020, - OPTION_INVISIBLE = 0x00000040, - OPTION_ORCISH = 0x00000800, - OPTION_WEDDING = 0x00001000, - OPTION_RUWACH = 0x00002000, - OPTION_CHASEWALK = 0x00004000, - OPTION_FLYING = 0x00008000, //Note that clientside Flying and Xmas are 0x8000 for clients prior to 2007. - OPTION_XMAS = 0x00010000, - OPTION_TRANSFORM = 0x00020000, - OPTION_SUMMER = 0x00040000, - OPTION_DRAGON1 = 0x00080000, - OPTION_WUG = 0x00100000, - OPTION_WUGRIDER = 0x00200000, - OPTION_MADOGEAR = 0x00400000, - OPTION_DRAGON2 = 0x00800000, - OPTION_DRAGON3 = 0x01000000, - OPTION_DRAGON4 = 0x02000000, - OPTION_DRAGON5 = 0x04000000, - OPTION_HANBOK = 0x08000000, - OPTION_OKTOBERFEST = 0x10000000, - -#ifndef NEW_CARTS - OPTION_CART1 = 0x00000008, - OPTION_CART2 = 0x00000080, - OPTION_CART3 = 0x00000100, - OPTION_CART4 = 0x00000200, - OPTION_CART5 = 0x00000400, - - /* compound constant for older carts */ - OPTION_CART = OPTION_CART1|OPTION_CART2|OPTION_CART3|OPTION_CART4|OPTION_CART5, -#endif - - // compound constants - OPTION_DRAGON = OPTION_DRAGON1|OPTION_DRAGON2|OPTION_DRAGON3|OPTION_DRAGON4|OPTION_DRAGON5, - OPTION_COSTUME = OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK|OPTION_OKTOBERFEST, -}; - //Defines for the manner system [Skotlex] enum manner_flags { @@ -1868,6 +1826,7 @@ struct sc_display_entry { struct status_change_entry { int timer; int val1,val2,val3,val4; + bool infinite_duration; }; struct status_change { @@ -1969,22 +1928,11 @@ struct s_refine_info { int randombonus_max[MAX_REFINE]; // cumulative maximum random bonus damage }; -/*===================================== -* Interface : status.h -* Generated by HerculesInterfaceMaker -* created by Susu -*-------------------------------------*/ -struct status_interface { - - /* vars */ - int current_equip_item_index; - int current_equip_card_id; - /* */ +struct s_status_dbs { +BEGIN_ZEROED_BLOCK; /* Everything within this block will be memset to 0 when status_defaults() is executed */ int max_weight_base[CLASS_COUNT]; - int hp_coefficient[CLASS_COUNT]; - int hp_coefficient2[CLASS_COUNT]; - int hp_sigma_val[CLASS_COUNT][MAX_LEVEL+1]; - int sp_coefficient[CLASS_COUNT]; + int HP_table[CLASS_COUNT][MAX_LEVEL + 1]; + int SP_table[CLASS_COUNT][MAX_LEVEL + 1]; int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE+1]; // +1 for RENEWAL_ASPD sc_type Skill2SCTable[MAX_SKILL]; // skill -> status int IconChangeTable[SC_MAX]; // status -> "icon" (icon is a bit of a misnomer, since there exist values with no icon associated) @@ -1998,6 +1946,22 @@ struct status_interface { int atkmods[3][MAX_WEAPON_TYPE];//ATK weapon modification for size (size_fix.txt) char job_bonus[CLASS_COUNT][MAX_LEVEL]; sc_conf_type sc_conf[SC_MAX]; +END_ZEROED_BLOCK; /* End */ +}; + +/*===================================== +* Interface : status.h +* Generated by HerculesInterfaceMaker +* created by Susu +*-------------------------------------*/ +struct status_interface { + + /* vars */ + int current_equip_item_index; + int current_equip_card_id; + + struct s_status_dbs *dbs; + struct eri *data_ers; //For sc_data entries struct status_data dummy; int64 natural_heal_prev_tick; @@ -2082,9 +2046,8 @@ struct status_interface { void (*initDummyData) (void); int (*base_amotion_pc) (struct map_session_data *sd, struct status_data *st); unsigned short (*base_atk) (const struct block_list *bl, const struct status_data *st); - void (*calc_sigma) (void); - unsigned int (*base_pc_maxhp) (struct map_session_data *sd, struct status_data *st); - unsigned int (*base_pc_maxsp) (struct map_session_data *sd, struct status_data *st); + unsigned int (*get_base_maxhp) (struct map_session_data *sd, struct status_data *st); + unsigned int (*get_base_maxsp) (struct map_session_data *sd, struct status_data *st); int (*calc_npc_) (struct npc_data *nd, enum e_status_calc_opt opt); unsigned short (*calc_str) (struct block_list *bl, struct status_change *sc, int str); unsigned short (*calc_agi) (struct block_list *bl, struct status_change *sc, int agi); @@ -2114,11 +2077,12 @@ struct status_interface { void (*display_remove) (struct map_session_data *sd, enum sc_type type); int (*natural_heal) (struct block_list *bl, va_list args); int (*natural_heal_timer) (int tid, int64 tick, int id, intptr_t data); - bool (*readdb_job1) (char *fields[], int columns, int current); bool (*readdb_job2) (char *fields[], int columns, int current); bool (*readdb_sizefix) (char *fields[], int columns, int current); bool (*readdb_refine) (char *fields[], int columns, int current); bool (*readdb_scconfig) (char *fields[], int columns, int current); + void (*read_job_db) (void); + void (*read_job_db_sub) (int idx, const char *name, config_setting_t *jdb); }; struct status_interface *status; diff --git a/src/map/storage.c b/src/map/storage.c index 79a5ad52d..95194bc47 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -6,25 +6,25 @@ #include "storage.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/guild.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" // struct map_session_data +#include "map/pc.h" +#include "common/cbasetypes.h" +#include "common/db.h" +#include "common/malloc.h" +#include "common/nullpo.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "guild.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" // struct map_session_data -#include "pc.h" -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" - struct storage_interface storage_s; struct guild_storage_interface gstorage_s; @@ -83,7 +83,7 @@ int storage_storageopen(struct map_session_data *sd) { nullpo_ret(sd); - if(sd->state.storage_flag) + if (sd->state.storage_flag != STORAGE_FLAG_CLOSED) return 1; //Already open? if( !pc_can_give_items(sd) ) { @@ -92,7 +92,7 @@ int storage_storageopen(struct map_session_data *sd) return 1; } - sd->state.storage_flag = 1; + sd->state.storage_flag = STORAGE_FLAG_NORMAL; storage->sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); clif->storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); @@ -109,7 +109,8 @@ int compare_item(struct item *a, struct item *b) a->refine == b->refine && a->attribute == b->attribute && a->expire_time == b->expire_time && - a->bound == b->bound ) + a->bound == b->bound && + a->unique_id == b->unique_id) { int i; for (i = 0; i < MAX_SLOTS && (a->card[i] == b->card[i]); i++); @@ -155,6 +156,7 @@ int storage_additem(struct map_session_data* sd, struct item* item_data, int amo {// existing items found, stack them if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->items[i].amount ) ) return 1; + stor->items[i].amount += amount; clif->storageitemadded(sd,&stor->items[i],i,amount); return 0; @@ -190,9 +192,11 @@ int storage_delitem(struct map_session_data* sd, int n, int amount) { memset(&sd->status.storage.items[n],0,sizeof(sd->status.storage.items[0])); sd->status.storage.storage_amount--; - if( sd->state.storage_flag == 1 ) clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); + if( sd->state.storage_flag == STORAGE_FLAG_NORMAL ) + clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); } - if( sd->state.storage_flag == 1 ) clif->storageitemremoved(sd,n,amount); + if( sd->state.storage_flag == STORAGE_FLAG_NORMAL ) + clif->storageitemremoved(sd,n,amount); return 0; } @@ -219,9 +223,9 @@ int storage_storageadd(struct map_session_data* sd, int index, int amount) { return 0; if( storage->additem(sd,&sd->status.inventory[index],amount) == 0 ) - pc->delitem(sd,index,amount,0,4,LOG_TYPE_STORAGE); + pc->delitem(sd, index, amount, 0, DELITEM_TOSTORAGE, LOG_TYPE_STORAGE); else - clif->dropitem(sd, index,0); + clif->dropitem(sd, index, 0); return 1; } @@ -325,7 +329,7 @@ void storage_storageclose(struct map_session_data* sd) { if( map->save_settings&4 ) chrif->save(sd,0); //Invokes the storage saving as well. - sd->state.storage_flag = 0; + sd->state.storage_flag = STORAGE_FLAG_CLOSED; } /*========================================== @@ -337,7 +341,7 @@ void storage_storage_quit(struct map_session_data* sd, int flag) { if (map->save_settings&4) chrif->save(sd, flag); //Invokes the storage saving as well. - sd->state.storage_flag = 0; + sd->state.storage_flag = STORAGE_FLAG_CLOSED; } /** @@ -380,7 +384,7 @@ int storage_guild_storageopen(struct map_session_data* sd) if(sd->status.guild_id <= 0) return 2; - if(sd->state.storage_flag) + if (sd->state.storage_flag != STORAGE_FLAG_CLOSED) return 1; //Can't open both storages at a time. if( !pc_can_give_items(sd) ) { //check is this GM level can open guild storage and store items [Lupus] @@ -399,7 +403,7 @@ int storage_guild_storageopen(struct map_session_data* sd) return 1; gstor->storage_status = 1; - sd->state.storage_flag = 2; + sd->state.storage_flag = STORAGE_FLAG_GUILD; storage->sortitem(gstor->items, ARRAYLENGTH(gstor->items)); clif->storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items)); clif->updatestorageamount(sd, gstor->storage_amount, MAX_GUILD_STORAGE); @@ -525,10 +529,10 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount) return 0; } - if(gstorage->additem(sd,stor,&sd->status.inventory[index],amount)==0) - pc->delitem(sd,index,amount,0,4,LOG_TYPE_GSTORAGE); + if( gstorage->additem(sd,stor,&sd->status.inventory[index],amount) == 0 ) + pc->delitem(sd, index, amount, 0, DELITEM_TOSTORAGE, LOG_TYPE_GSTORAGE); else - clif->dropitem(sd, index,0); + clif->dropitem(sd, index, 0); return 1; } @@ -694,7 +698,7 @@ int storage_guild_storageclose(struct map_session_data* sd) { gstorage->save(sd->status.account_id, sd->status.guild_id,0); stor->storage_status=0; } - sd->state.storage_flag = 0; + sd->state.storage_flag = STORAGE_FLAG_CLOSED; return 0; } @@ -707,7 +711,7 @@ int storage_guild_storage_quit(struct map_session_data* sd, int flag) { if(flag) { //Only during a guild break flag is 1 (don't save storage) - sd->state.storage_flag = 0; + sd->state.storage_flag = STORAGE_FLAG_CLOSED; stor->storage_status = 0; clif->storageclose(sd); if (map->save_settings&4) @@ -721,7 +725,7 @@ int storage_guild_storage_quit(struct map_session_data* sd, int flag) { else gstorage->save(sd->status.account_id,sd->status.guild_id,1); } - sd->state.storage_flag = 0; + sd->state.storage_flag = STORAGE_FLAG_CLOSED; stor->storage_status = 0; return 0; diff --git a/src/map/storage.h b/src/map/storage.h index 6393e124a..5f2c69f56 100644 --- a/src/map/storage.h +++ b/src/map/storage.h @@ -5,13 +5,22 @@ #ifndef MAP_STORAGE_H #define MAP_STORAGE_H -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "common/cbasetypes.h" +#include "common/db.h" struct guild_storage; struct item; struct map_session_data; +/** + * Acceptable values for map_session_data.state.storage_flag + */ +enum storage_flag { + STORAGE_FLAG_CLOSED = 0, // Closed + STORAGE_FLAG_NORMAL = 1, // Normal Storage open + STORAGE_FLAG_GUILD = 2, // Guild Storage open +}; + struct storage_interface { /* */ void (*reconnect) (void); diff --git a/src/map/trade.c b/src/map/trade.c index 7417f05af..4dd6ffafa 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -6,24 +6,24 @@ #include "trade.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/intif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/npc.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/storage.h" +#include "common/nullpo.h" +#include "common/socket.h" + #include <stdio.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "intif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "npc.h" -#include "path.h" -#include "pc.h" -#include "storage.h" -#include "../common/nullpo.h" -#include "../common/socket.h" - struct trade_interface trade_s; /*========================================== @@ -145,8 +145,8 @@ void trade_tradeack(struct map_session_data *sd, int type) { } //Check if you can start trade. - if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.storage_flag - || tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag + if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.storage_flag != STORAGE_FLAG_CLOSED + || tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag != STORAGE_FLAG_CLOSED ) { //Fail clif->tradestart(sd, 2); @@ -208,13 +208,13 @@ int impossible_trade_check(struct map_session_data *sd) intif->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); // if we block people if (battle_config.ban_hack_trade < 0) { - chrif->char_ask_name(-1, sd->status.name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block + chrif->char_ask_name(-1, sd->status.name, CHAR_ASK_NAME_BLOCK, 0, 0, 0, 0, 0, 0); set_eof(sd->fd); // forced to disconnect because of the hack // message about the ban safestrncpy(message_to_gm, msg_txt(540), sizeof(message_to_gm)); // This player has been definitively blocked. // if we ban people } else if (battle_config.ban_hack_trade > 0) { - chrif->char_ask_name(-1, sd->status.name, 2, 0, 0, 0, 0, battle_config.ban_hack_trade, 0); // type: 2 - ban (year, month, day, hour, minute, second) + chrif->char_ask_name(-1, sd->status.name, CHAR_ASK_NAME_BAN, 0, 0, 0, 0, battle_config.ban_hack_trade, 0); // type: 2 - ban (year, month, day, hour, minute, second) set_eof(sd->fd); // forced to disconnect because of the hack // message about the ban sprintf(message_to_gm, msg_txt(507), battle_config.ban_hack_trade); // This player has been banned for %d minute(s). @@ -561,7 +561,7 @@ void trade_tradecommit(struct map_session_data *sd) { flag = pc->additem(tsd, &sd->status.inventory[n], sd->deal.item[trade_i].amount,LOG_TYPE_TRADE); if (flag == 0) - pc->delitem(sd, n, sd->deal.item[trade_i].amount, 1, 6, LOG_TYPE_TRADE); + pc->delitem(sd, n, sd->deal.item[trade_i].amount, 1, DELITEM_SOLD, LOG_TYPE_TRADE); else clif->additem(sd, n, sd->deal.item[trade_i].amount, 0); sd->deal.item[trade_i].index = 0; @@ -573,7 +573,7 @@ void trade_tradecommit(struct map_session_data *sd) { flag = pc->additem(sd, &tsd->status.inventory[n], tsd->deal.item[trade_i].amount,LOG_TYPE_TRADE); if (flag == 0) - pc->delitem(tsd, n, tsd->deal.item[trade_i].amount, 1, 6, LOG_TYPE_TRADE); + pc->delitem(tsd, n, tsd->deal.item[trade_i].amount, 1, DELITEM_SOLD, LOG_TYPE_TRADE); else clif->additem(tsd, n, tsd->deal.item[trade_i].amount, 0); tsd->deal.item[trade_i].index = 0; diff --git a/src/map/unit.c b/src/map/unit.c index 2e96e9c20..60911b85a 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -4,47 +4,47 @@ #define HERCULES_CORE -#include "../config/core.h" // RENEWAL_CAST +#include "config/core.h" // RENEWAL_CAST #include "unit.h" +#include "map/battle.h" +#include "map/battleground.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/duel.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/instance.h" +#include "map/intif.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/npc.h" +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/script.h" +#include "map/skill.h" +#include "map/status.h" +#include "map/storage.h" +#include "map/trade.h" +#include "map/vending.h" +#include "common/HPM.h" +#include "common/db.h" +#include "common/malloc.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/timer.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "battle.h" -#include "battleground.h" -#include "chat.h" -#include "chrif.h" -#include "clif.h" -#include "duel.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "instance.h" -#include "intif.h" -#include "map.h" -#include "mercenary.h" -#include "mob.h" -#include "npc.h" -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "script.h" -#include "skill.h" -#include "status.h" -#include "storage.h" -#include "trade.h" -#include "vending.h" -#include "../common/HPM.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/timer.h" - const short dirx[8]={0,-1,-1,-1,0,1,1,1}; const short diry[8]={1,1,0,-1,-1,-1,0,1}; @@ -737,7 +737,7 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool if( ud == NULL) return 0; - unit->stop_walking(bl,1); + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); unit->stop_attack(bl); if( checkpath && (map->getcell(bl->m,dst_x,dst_y,CELL_CHKNOPASS) || !path->search(NULL,bl->m,bl->x,bl->y,dst_x,dst_y,easy,CELL_CHKNOREACH)) ) @@ -834,7 +834,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag) ny = result&0xffff; if(!su) { - unit->stop_walking(bl, 0); + unit->stop_walking(bl, STOPWALKING_FLAG_NONE); } if( sd ) { @@ -952,14 +952,10 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type) /*========================================== * Caused the target object to stop moving. - * Flag values: - * &0x1: Issue a fixpos packet afterwards - * &0x2: Force the unit to move one cell if it hasn't yet - * &0x4: Enable moving to the next cell when unit was already half-way there - * (may cause on-touch/place side-effects, such as a scripted map change) + * Flag values: @see unit_stopwalking_flag. + * Upper bytes may be used for other purposes depending on the unit type. *------------------------------------------*/ -int unit_stop_walking(struct block_list *bl,int type) -{ +int unit_stop_walking(struct block_list *bl, int flag) { struct unit_data *ud; const struct TimerData* td; int64 tick; @@ -976,22 +972,22 @@ int unit_stop_walking(struct block_list *bl,int type) ud->walktimer = INVALID_TIMER; ud->state.change_walk_target = 0; tick = timer->gettick(); - if( (type&0x02 && !ud->walkpath.path_pos) //Force moving at least one cell. - || (type&0x04 && td && DIFF_TICK(td->tick, tick) <= td->data/2) //Enough time has passed to cover half-cell + if( (flag&STOPWALKING_FLAG_ONESTEP && !ud->walkpath.path_pos) //Force moving at least one cell. + || (flag&STOPWALKING_FLAG_NEXTCELL && td && DIFF_TICK(td->tick, tick) <= td->data/2) //Enough time has passed to cover half-cell ) { ud->walkpath.path_len = ud->walkpath.path_pos+1; unit->walktoxy_timer(INVALID_TIMER, tick, bl->id, ud->walkpath.path_pos); } - if(type&0x01) + if(flag&STOPWALKING_FLAG_FIXPOS) clif->fixpos(bl); ud->walkpath.path_len = 0; ud->walkpath.path_pos = 0; ud->to_x = bl->x; ud->to_y = bl->y; - if(bl->type == BL_PET && type&~0xff) - ud->canmove_tick = timer->gettick() + (type>>8); + if(bl->type == BL_PET && flag&~STOPWALKING_FLAG_MASK) + ud->canmove_tick = timer->gettick() + (flag>>8); //Read, the check in unit_set_walkdelay means dmg during running won't fall through to this place in code [Kevin] if (ud->state.running) { @@ -1081,6 +1077,7 @@ int unit_can_move(struct block_list *bl) { || sc->data[SC_NEEDLE_OF_PARALYZE] || sc->data[SC_VACUUM_EXTREME] || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0) + || sc->data[SC_NETHERWORLD] || (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) || (sc->data[SC_CLOAKING] && sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1)) //Need wall at level 1-2 || ( @@ -1168,17 +1165,14 @@ int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type) { //Stop walking, if chasing, readjust timers. if (delay == 1) { //Minimal delay (walk-delay) disabled. Just stop walking. - unit->stop_walking(bl,4); + unit->stop_walking(bl, STOPWALKING_FLAG_NEXTCELL); } else { //Resume running after can move again [Kevin] - if(ud->state.running) - { + if (ud->state.running) { timer->add(ud->canmove_tick, unit->resume_running, bl->id, (intptr_t)ud); - } - else - { - unit->stop_walking(bl,4); - if(ud->target) + } else { + unit->stop_walking(bl, STOPWALKING_FLAG_NEXTCELL); + if (ud->target) timer->add(ud->canmove_tick+1, unit->walktobl_sub, bl->id, ud->target); } } @@ -1353,18 +1347,21 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui } } - if (sd || src->type == BL_HOM){ - if (!sd && (target = battle->get_master(src))) - sd = map->id2sd(target->id); - if (sd){ - /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ + if (src->type == BL_HOM) { + // In case of homunuculus, set the sd to the homunculus' master, as needed below + struct block_list *master = battle->get_master(src); + if (master) + sd = map->id2sd(master->id); + } + + if (sd) { + /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ #if 0 - if (sd->skillitem != skill_id && !skill->check_condition_castbegin(sd, skill_id, skill_lv)) + if (sd->skillitem != skill_id && !skill->check_condition_castbegin(sd, skill_id, skill_lv)) #else - if (!skill->check_condition_castbegin(sd, skill_id, skill_lv)) + if (!skill->check_condition_castbegin(sd, skill_id, skill_lv)) #endif - return 0; - } + return 0; } if( src->type == BL_MOB ) @@ -1372,7 +1369,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui case NPC_SUMMONSLAVE: case NPC_SUMMONMONSTER: case AL_TELEPORT: - if( ((TBL_MOB*)src)->master_id && ((TBL_MOB*)src)->special_state.ai ) + if (((TBL_MOB*)src)->master_id && ((TBL_MOB*)src)->special_state.ai != AI_NONE) return 0; } @@ -1543,8 +1540,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui } } - if(!ud->state.running) //need TK_RUN or WUGDASH handler to be done before that, see bugreport:6026 - unit->stop_walking(src,1);// even though this is not how official works but this will do the trick. bugreport:6829 + if (!ud->state.running) //need TK_RUN or WUGDASH handler to be done before that, see bugreport:6026 + unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS);// even though this is not how official works but this will do the trick. bugreport:6829 // in official this is triggered even if no cast time. clif->skillcasting(src, src->id, target_id, 0,0, skill_id, skill->get_ele(skill_id, skill_lv), casttime); @@ -1604,7 +1601,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui unit->setdir(src, map->calc_dir(src, target->x, target->y)); ud->skilltimer = timer->add( tick+casttime, skill->castend_id, src->id, 0 ); if( sd && (pc->checkskill(sd,SA_FREECAST) > 0 || skill_id == LG_EXEEDBREAK) ) - status_calc_bl(&sd->bl, SCB_SPEED); + status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD); } else skill->castend_id(ud->skilltimer,tick,src->id,0); @@ -1741,14 +1738,15 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui } } - unit->stop_walking(src,1); + unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS); // in official this is triggered even if no cast time. clif->skillcasting(src, src->id, 0, skill_x, skill_y, skill_id, skill->get_ele(skill_id, skill_lv), casttime); if( casttime > 0 ) { unit->setdir(src, map->calc_dir(src, skill_x, skill_y)); ud->skilltimer = timer->add( tick+casttime, skill->castend_pos, src->id, 0 ); - if( (sd && pc->checkskill(sd,SA_FREECAST) > 0) || skill_id == LG_EXEEDBREAK) - status_calc_bl(&sd->bl, SCB_SPEED); + if ( (sd && pc->checkskill(sd, SA_FREECAST) > 0) || skill_id == LG_EXEEDBREAK ) { + status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD); + } } else { ud->skilltimer = INVALID_TIMER; skill->castend_pos(ud->skilltimer,tick,src->id,0); @@ -2129,7 +2127,7 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) { ud->dir = map->calc_dir(src, target->x,target->y ); } if(ud->walktimer != INVALID_TIMER) - unit->stop_walking(src,1); + unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS); if(md) { //First attack is always a normal attack if(md->state.skillstate == MSS_ANGRY || md->state.skillstate == MSS_BERSERK) { @@ -2231,7 +2229,7 @@ int unit_skillcastcancel(struct block_list *bl,int type) ud->skilltimer = INVALID_TIMER; if( sd && pc->checkskill(sd,SA_FREECAST) > 0 ) - status_calc_bl(&sd->bl, SCB_SPEED); + status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD); if( sd ) { switch( skill_id ) { @@ -2324,7 +2322,7 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i map->freeblock_lock(); if (ud->walktimer != INVALID_TIMER) - unit->stop_walking(bl,0); + unit->stop_walking(bl, STOPWALKING_FLAG_NONE); if (ud->skilltimer != INVALID_TIMER) unit->skillcastcancel(bl,0); @@ -2374,6 +2372,7 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i status_change_end(bl, SC__MANHOLE, INVALID_TIMER); status_change_end(bl, SC_VACUUM_EXTREME, INVALID_TIMER); status_change_end(bl, SC_CURSEDCIRCLE_ATKER, INVALID_TIMER); //callme before warp + status_change_end(bl, SC_NETHERWORLD, INVALID_TIMER); } if (bl->type&(BL_CHAR|BL_PET)) { @@ -2392,18 +2391,18 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i } //Leave/reject all invitations. if(sd->chatID) - chat->leave(sd,0); + chat->leave(sd, false); if(sd->trade_partner) trade->cancel(sd); buyingstore->close(sd); searchstore->close(sd); if( sd->menuskill_id != AL_TELEPORT ) { // issue: 8027 - if(sd->state.storage_flag == 1) + if(sd->state.storage_flag == STORAGE_FLAG_NORMAL) storage->pc_quit(sd,0); - else if (sd->state.storage_flag == 2) + else if (sd->state.storage_flag == STORAGE_FLAG_GUILD) gstorage->pc_quit(sd,0); - sd->state.storage_flag = 0; //Force close it when being warped. + sd->state.storage_flag = STORAGE_FLAG_CLOSED; //Force close it when being warped. } if(sd->party_invite>0) party->reply_invite(sd,sd->party_invite,0); diff --git a/src/map/unit.h b/src/map/unit.h index 881fa16f4..00fff5981 100644 --- a/src/map/unit.h +++ b/src/map/unit.h @@ -5,14 +5,27 @@ #ifndef MAP_UNIT_H #define MAP_UNIT_H -#include "clif.h" // clr_type -#include "path.h" // struct walkpath_data -#include "skill.h" // 'MAX_SKILLTIMERSKILL, struct skill_timerskill, struct skill_unit_group, struct skill_unit_group_tickset -#include "../common/cbasetypes.h" +#include "map/clif.h" // clr_type +#include "map/path.h" // struct walkpath_data +#include "map/skill.h" // 'MAX_SKILLTIMERSKILL, struct skill_timerskill, struct skill_unit_group, struct skill_unit_group_tickset +#include "common/cbasetypes.h" struct map_session_data; struct block_list; +/** + * Bitmask values usable as a flag in unit_stopwalking + */ +enum unit_stopwalking_flag { + STOPWALKING_FLAG_NONE = 0x00, + STOPWALKING_FLAG_FIXPOS = 0x01, ///< Issue a fixpos packet afterwards + STOPWALKING_FLAG_ONESTEP = 0x02, ///< Force the unit to move one cell if it hasn't yet + STOPWALKING_FLAG_NEXTCELL = 0x04, ///< Enable moving to the next cell when unit was already half-way there + /// (may cause on-touch/place side-effects, such as a scripted map change) + STOPWALKING_FLAG_MASK = 0xff, ///< Mask all of the above + // Note: Upper bytes are reserved for duration. +}; + struct unit_data { struct block_list *bl; struct walkpath_data walkpath; diff --git a/src/map/vending.c b/src/map/vending.c index 8ae3f36a4..d0f0dee00 100644 --- a/src/map/vending.c +++ b/src/map/vending.c @@ -6,24 +6,24 @@ #include "vending.h" +#include "map/atcommand.h" +#include "map/battle.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/itemdb.h" +#include "map/log.h" +#include "map/map.h" +#include "map/npc.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/skill.h" +#include "common/nullpo.h" +#include "common/strlib.h" +#include "common/utils.h" + #include <stdio.h> #include <string.h> -#include "atcommand.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "itemdb.h" -#include "log.h" -#include "map.h" -#include "npc.h" -#include "path.h" -#include "pc.h" -#include "skill.h" -#include "../common/nullpo.h" -#include "../common/strlib.h" -#include "../common/utils.h" - struct vending_interface vending_s; /// Returns an unique vending shop id. @@ -38,7 +38,7 @@ void vending_closevending(struct map_session_data* sd) { nullpo_retv(sd); if( sd->state.vending ) { - sd->state.vending = false; + sd->state.vending = 0; clif->closevendingboard(&sd->bl, 0); idb_remove(vending->db, sd->status.char_id); } diff --git a/src/map/vending.h b/src/map/vending.h index 00d3eefff..189189227 100644 --- a/src/map/vending.h +++ b/src/map/vending.h @@ -5,8 +5,8 @@ #ifndef MAP_VENDING_H #define MAP_VENDING_H -#include "../common/cbasetypes.h" -#include "../common/db.h" +#include "common/cbasetypes.h" +#include "common/db.h" struct map_session_data; struct s_search_store_search; |