summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/atcommand.c17
-rw-r--r--src/map/battle.c1
-rw-r--r--src/map/battle.h3
-rw-r--r--src/map/chrif.c6
-rw-r--r--src/map/clif.c135
-rw-r--r--src/map/clif.h15
-rw-r--r--src/map/elemental.c2
-rw-r--r--src/map/homunculus.c7
-rw-r--r--src/map/homunculus.h2
-rw-r--r--src/map/map.c2
-rw-r--r--src/map/map.h2
-rw-r--r--src/map/mapreg_sql.c6
-rw-r--r--src/map/mercenary.c2
-rw-r--r--src/map/mercenary.h2
-rw-r--r--src/map/mob.c4
-rw-r--r--src/map/mob.h8
-rw-r--r--src/map/npc.c32
-rw-r--r--src/map/npc.h3
-rw-r--r--src/map/packets.h76
-rw-r--r--src/map/packets_keys.h14
-rw-r--r--src/map/packets_struct.h13
-rw-r--r--src/map/pc.c50
-rw-r--r--src/map/pc.h2
-rw-r--r--src/map/script.c302
-rw-r--r--src/map/script.h27
-rw-r--r--src/map/skill.c810
-rw-r--r--src/map/skill.h108
-rw-r--r--src/map/status.c16
-rw-r--r--src/map/status.h2
29 files changed, 1275 insertions, 394 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index d9f4810ee..1590c3f0c 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -5296,12 +5296,13 @@ ACMD(skillid)
iter = db_iterator(skill->name2id_db);
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->dbs->db[idx].desc, message, skillen) == 0) {
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1164), DB->data2i(data), skill->dbs->db[idx].desc, key.str); // skill %d: %s (%s)
+ int skill_id = DB->data2i(data);
+ const char *skill_desc = skill->get_desc(skill_id);
+ if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill_desc, message, skillen) == 0) {
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd, 1164), skill_id, skill_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->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);
+ } else if (found < MAX_SKILLID_PARTIAL_RESULTS && (stristr(key.str, message) != NULL || stristr(skill_desc, message) != NULL)) {
+ snprintf(partials[found], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_fd(fd, 1164), skill_id, skill_desc, key.str);
found++;
}
}
@@ -5428,7 +5429,7 @@ ACMD(skilltree)
for (j = 0; j < VECTOR_LENGTH(entry->need); j++) {
struct skill_tree_requirement *req = &VECTOR_INDEX(entry->need, j);
if (pc->checkskill(sd, req->id) < req->lv) {
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1170), req->lv, skill->dbs->db[req->id].desc); // Player requires level %d of skill %s.
+ safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1170), req->lv, skill->get_desc(req->id)); // Player requires level %d of skill %s.
clif->message(fd, atcmd_output);
meets = 0;
}
@@ -8686,7 +8687,7 @@ ACMD(cart) {
int val = atoi(message);
bool need_skill = pc->checkskill(sd, MC_PUSHCART) ? false : true;
- unsigned int index = skill->get_index(MC_PUSHCART);
+ int index = skill->get_index(MC_PUSHCART);
if (!*message || val < 0 || val > MAX_CARTS) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1390),command,MAX_CARTS); // Unknown Cart (usage: %s <0-%d>).
@@ -9394,7 +9395,7 @@ ACMD(cddebug) {
}
if (!cd || (*message && !strcmpi(message,"reset"))) {
- for(i = 0; i < MAX_SKILL; i++) {
+ for (i = 0; i < MAX_SKILL_DB; i++) {
if( sd->blockskill[i] ) {
clif->messages(fd,"Found skill '%s', unblocking...",skill->dbs->db[i].name);
sd->blockskill[i] = false;
diff --git a/src/map/battle.c b/src/map/battle.c
index 8983e93c9..70ebc4a08 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -7308,6 +7308,7 @@ static const struct battle_data {
{ "boarding_halter_speed", &battle_config.boarding_halter_speed, 25, 0, 100, },
{ "features/rodex", &battle_config.feature_rodex, 1, 0, 1, },
{ "features/rodex_use_accountmail", &battle_config.feature_rodex_use_accountmail, 0, 0, 1, },
+ { "features/enable_homun_autofeed", &battle_config.feature_enable_homun_autofeed, 1, 0, 1, },
};
#ifndef STATS_OPT_OUT
/**
diff --git a/src/map/battle.h b/src/map/battle.h
index 4a63887c4..429249dca 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -54,6 +54,7 @@ struct status_data;
enum {
// Flag of the final calculation
+ BF_NONE = 0x0000,
BF_WEAPON = 0x0001,
BF_MAGIC = 0x0002,
BF_MISC = 0x0004,
@@ -559,6 +560,8 @@ struct Battle_Config {
int feature_rodex;
int feature_rodex_use_accountmail;
+
+ int feature_enable_homun_autofeed;
};
/* criteria for battle_config.idletime_critera */
diff --git a/src/map/chrif.c b/src/map/chrif.c
index 39aa046d7..96f144523 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -1360,10 +1360,10 @@ void chrif_skillid2idx(int fd) {
if (!sockt->session_is_valid(fd))
return;
- WFIFOHEAD(fd,4 + (MAX_SKILL * 4));
+ WFIFOHEAD(fd,4 + (MAX_SKILL_DB * 4));
WFIFOW(fd,0) = 0x2b0b;
- for(i = 0; i < MAX_SKILL; i++) {
- if( skill->dbs->db[i].nameid ) {
+ for (i = 0; i < MAX_SKILL_DB; i++) {
+ if (skill->dbs->db[i].nameid != 0) {
WFIFOW(fd, 4 + (count*4)) = skill->dbs->db[i].nameid;
WFIFOW(fd, 6 + (count*4)) = i;
count++;
diff --git a/src/map/clif.c b/src/map/clif.c
index 088c92ea8..5f7cf3b5d 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -293,7 +293,11 @@ unsigned char clif_bl_type(struct block_list *bl)
case BL_NPC:
vd = status->get_viewdata(bl);
nullpo_retr(CLUT_NPC, vd);
+#if PACKETVER >= 20170726
+ return CLUT_EVENT;
+#else
return pc->db_checkid(vd->class) ? CLUT_PC : CLUT_EVENT;
+#endif
case BL_PET:
vd = status->get_viewdata(bl);
nullpo_retr(CLUT_NPC, vd);
@@ -1067,14 +1071,17 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu
#endif
#if PACKETVER >= 20120221
if (battle_config.show_monster_hp_bar && bl->type == BL_MOB && status_get_hp(bl) < status_get_max_hp(bl)) {
- const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
p.maxHP = status_get_max_hp(bl);
p.HP = status_get_hp(bl);
- p.isBoss = (md->spawn != NULL && md->spawn->state.boss) ? 1 : 0;
} else {
p.maxHP = -1;
p.HP = -1;
- p.isBoss = 0;
+ }
+ if (bl->type == BL_MOB) {
+ const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
+ p.isBoss = (md->spawn != NULL) ? md->spawn->state.boss : BTYPE_NONE;
+ } else {
+ p.isBoss = BTYPE_NONE;
}
#endif
#if PACKETVER >= 20150513
@@ -1216,14 +1223,17 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) {
#endif
#if PACKETVER >= 20120221
if (battle_config.show_monster_hp_bar && bl->type == BL_MOB && status_get_hp(bl) < status_get_max_hp(bl)) {
- const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
p.maxHP = status_get_max_hp(bl);
p.HP = status_get_hp(bl);
- p.isBoss = (md->spawn != NULL && md->spawn->state.boss) ? 1 : 0;
} else {
p.maxHP = -1;
p.HP = -1;
- p.isBoss = 0;
+ }
+ if (bl->type == BL_MOB) {
+ const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
+ p.isBoss = (md->spawn != NULL) ? md->spawn->state.boss : BTYPE_NONE;
+ } else {
+ p.isBoss = BTYPE_NONE;
}
#endif
#if PACKETVER >= 20150513
@@ -1315,14 +1325,17 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd,
#endif
#if PACKETVER >= 20120221
if (battle_config.show_monster_hp_bar && bl->type == BL_MOB && status_get_hp(bl) < status_get_max_hp(bl)) {
- const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
p.maxHP = status_get_max_hp(bl);
p.HP = status_get_hp(bl);
- p.isBoss = (md->spawn != NULL && md->spawn->state.boss) ? 1 : 0;
} else {
p.maxHP = -1;
p.HP = -1;
- p.isBoss = 0;
+ }
+ if (bl->type == BL_MOB) {
+ const struct mob_data *md = BL_UCCAST(BL_MOB, bl);
+ p.isBoss = (md->spawn != NULL) ? md->spawn->state.boss : BTYPE_NONE;
+ } else {
+ p.isBoss = BTYPE_NONE;
}
#endif
#if PACKETVER >= 20150513
@@ -3332,17 +3345,22 @@ void clif_changelook(struct block_list *bl,int type,int val)
#if PACKETVER < 4
clif->sendlook(bl, bl->id, type, val, 0, target);
#else
- if(type == LOOK_WEAPON || type == LOOK_SHIELD) {
- nullpo_retv(vd);
- type = LOOK_WEAPON;
- val = vd->weapon;
- val2 = vd->shield;
- }
- if (clif->isdisguised(bl)) {
- clif->sendlook(bl, bl->id, type, val, val2, AREA_WOS);
- clif->sendlook(bl, -bl->id, type, val, val2, SELF);
+ if (bl->type != BL_NPC) {
+ if(type == LOOK_WEAPON || type == LOOK_SHIELD) {
+ nullpo_retv(vd);
+ type = LOOK_WEAPON;
+ val = vd->weapon;
+ val2 = vd->shield;
+ }
+ if (clif->isdisguised(bl)) {
+ clif->sendlook(bl, bl->id, type, val, val2, AREA_WOS);
+ clif->sendlook(bl, -bl->id, type, val, val2, SELF);
+ } else {
+ clif->sendlook(bl, bl->id, type, val, val2, target);
+ }
} else {
- clif->sendlook(bl, bl->id, type, val, val2, target);
+ struct npc_data *nd = BL_UCAST(BL_NPC, bl);
+ npc->refresh(nd);
}
#endif
}
@@ -4848,9 +4866,9 @@ void clif_skillinfoblock(struct map_session_data *sd)
fd=sd->fd;
if (!fd) return;
- WFIFOHEAD(fd, MAX_SKILL * 37 + 4);
+ WFIFOHEAD(fd, MAX_SKILL_DB * 37 + 4);
WFIFOW(fd,0) = 0x10f;
- for ( i = 0, len = 4; i < MAX_SKILL; i++) {
+ for ( i = 0, len = 4; i < MAX_SKILL_DB; i++) {
if( (id = sd->status.skill[i].id) != 0 ) {
int level;
// workaround for bugreport:5348
@@ -4881,7 +4899,7 @@ void clif_skillinfoblock(struct map_session_data *sd)
WFIFOSET(fd,len);
// workaround for bugreport:5348; send the remaining skills one by one to bypass packet size limit
- for ( ; i < MAX_SKILL; i++) {
+ for ( ; i < MAX_SKILL_DB; i++) {
if( (id = sd->status.skill[i].id) != 0 ) {
clif->addskill(sd, id);
clif->skillinfo(sd, id, 0);
@@ -4983,7 +5001,7 @@ void clif_skillinfo(struct map_session_data *sd,int skill_id, int inf)
int skill_lv;
nullpo_retv(sd);
- Assert_retv(idx >= 0 && idx < MAX_SKILL);
+ Assert_retv(idx >= 0 && idx < MAX_SKILL_DB);
skill_lv = sd->status.skill[idx].lv;
@@ -5050,6 +5068,10 @@ void clif_useskill(struct block_list* bl, int src_id, int dst_id, int dst_x, int
} else {
clif->send(buf,packet_len(cmd), bl, AREA);
}
+#if PACKETVER >= 20151223
+ if ((skill->get_inf2(skill_id) & INF2_SHOW_SKILL_SCALE) != 0)
+ clif->skill_scale(bl, src_id, bl->x, bl->y, skill_id, skill_lv, casttime);
+#endif
}
/// Notifies clients in area, that an object canceled casting (ZC_DISPEL).
@@ -9021,14 +9043,15 @@ void clif_feel_hate_reset(struct map_session_data *sd)
clif->starskill(sd, "", 0, 0, 30);
}
-/// Equip window (un)tick ack (ZC_CONFIG).
+/// Send configurations (ZC_CONFIG).
/// 02d9 <type>.L <value>.L
/// type:
/// 0 = open equip window
+/// 3 = homunculus autofeeding
/// value:
/// 0 = disabled
/// 1 = enabled
-void clif_equiptickack(struct map_session_data* sd, int flag)
+void clif_zc_config(struct map_session_data* sd, int type, int flag)
{
int fd;
nullpo_retv(sd);
@@ -9036,7 +9059,7 @@ void clif_equiptickack(struct map_session_data* sd, int flag)
WFIFOHEAD(fd, packet_len(0x2d9));
WFIFOW(fd, 0) = 0x2d9;
- WFIFOL(fd, 2) = 0;
+ WFIFOL(fd, 2) = type;
WFIFOL(fd, 6) = flag;
WFIFOSET(fd, packet_len(0x2d9));
}
@@ -15920,19 +15943,32 @@ void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd) {
clif->msgtable(sd, MSG_EQUIP_NOT_PUBLIC);
}
-void clif_parse_EquipTick(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Request to change equip window tick (CZ_CONFIG).
+void clif_parse_cz_config(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+/// Receive configurations (CZ_CONFIG).
/// 02d8 <type>.L <value>.L
/// type:
/// 0 = open equip window
+/// 3 = homunculus autofeeding
/// value:
/// 0 = disabled
/// 1 = enabled
-void clif_parse_EquipTick(int fd, struct map_session_data* sd)
-{
- bool flag = (RFIFOL(fd,6) != 0) ? true : false;
- sd->status.show_equip = flag;
- clif->equiptickack(sd, flag);
+void clif_parse_cz_config(int fd, struct map_session_data *sd)
+{
+ int type = RFIFOL(fd, 2);
+ int flag = RFIFOL(fd, 6);
+
+ if (type == CZ_CONFIG_OPEN_EQUIPMENT_WINDOW) {
+ sd->status.show_equip = flag;
+ } else if (type == CZ_CONFIG_HOMUNCULUS_AUTOFEEDING) {
+ struct homun_data *hd;
+ hd = sd->hd;
+ nullpo_retv(hd);
+ hd->homunculus.autofeed = flag;
+ } else {
+ ShowWarning("clif_parse_cz_config: Unsupported type has been received (%d).", type);
+ return;
+ }
+ clif->zc_config(sd, type, flag);
}
void clif_parse_PartyTick(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
@@ -17624,7 +17660,7 @@ int clif_autoshadowspell_list(struct map_session_data *sd) {
WFIFOHEAD(fd, 2 * 6 + 4);
WFIFOW(fd,0) = 0x442;
- for( i = 0, c = 0; i < MAX_SKILL; i++ )
+ for (i = 0, c = 0; i < MAX_SKILL_DB; i++)
if( sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].id > 0 &&
sd->status.skill[i].id < GS_GLITTERING && skill->get_type(sd->status.skill[i].id) == BF_MAGIC )
{ // Can't auto cast both Extended class and 3rd class skills.
@@ -19842,6 +19878,32 @@ void clif_parse_rodex_cancel_write_mail(int fd, struct map_session_data *sd)
rodex->clean(sd, 1);
}
+void clif_skill_scale(struct block_list *bl, int src_id, int x, int y, uint16 skill_id, uint16 skill_lv, int casttime)
+{
+#if PACKETVER >= 20151223
+ struct PACKET_ZC_SKILL_SCALE p;
+
+ p.PacketType = skillscale;
+ p.AID = src_id;
+ p.skill_id = skill_id;
+ p.skill_lv = skill_lv;
+ p.x = x;
+ p.y = y;
+ p.casttime = casttime;
+
+ if (clif->isdisguised(bl)) {
+ clif->send(&p, sizeof(p), bl, AREA_WOS);
+ p.AID = -src_id;
+ clif->send(&p, sizeof(p), bl, SELF);
+ } else {
+ clif->send(&p, sizeof(p), bl, AREA);
+ }
+#else
+ ShowWarning("clif_skill_scale: showing skill scale available only for clients >= 20151223.");
+ return;
+#endif
+}
+
/*==========================================
* Main client packet processing function
*------------------------------------------*/
@@ -20296,7 +20358,7 @@ void clif_defaults(void) {
clif->mission_info = clif_mission_info;
clif->feel_hate_reset = clif_feel_hate_reset;
clif->partytickack = clif_partytickack;
- clif->equiptickack = clif_equiptickack;
+ clif->zc_config = clif_zc_config;
clif->viewequip_ack = clif_viewequip_ack;
clif->equpcheckbox = clif_equpcheckbox;
clif->displayexp = clif_displayexp;
@@ -20821,7 +20883,7 @@ void clif_defaults(void) {
clif->pAdopt_request = clif_parse_Adopt_request;
clif->pAdopt_reply = clif_parse_Adopt_reply;
clif->pViewPlayerEquip = clif_parse_ViewPlayerEquip;
- clif->pEquipTick = clif_parse_EquipTick;
+ clif->p_cz_config = clif_parse_cz_config;
clif->pquestStateAck = clif_parse_questStateAck;
clif->pmercenary_action = clif_parse_mercenary_action;
clif->pBattleChat = clif_parse_BattleChat;
@@ -20911,4 +20973,5 @@ void clif_defaults(void) {
clif->rodex_request_items = clif_rodex_request_items;
clif->rodex_icon = clif_rodex_icon;
clif->rodex_send_mails_all = clif_rodex_send_mails_all;
+ clif->skill_scale = clif_skill_scale;
}
diff --git a/src/map/clif.h b/src/map/clif.h
index 851c823ea..e348bbb08 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -563,7 +563,15 @@ enum clif_unittype {
CLUT_MERCNARY = 0x9,
CLUT_ELEMENTAL = 0xa,
};
-
+/**
+* Receive configuration types
+**/
+enum CZ_CONFIG {
+ CZ_CONFIG_OPEN_EQUIPMENT_WINDOW = 0,
+ // Unknown = 1,
+ CZ_CONFIG_PET_AUTOFEEDING = 2,
+ CZ_CONFIG_HOMUNCULUS_AUTOFEEDING = 3,
+};
/**
* Structures
**/
@@ -781,7 +789,7 @@ struct clif_interface {
void (*mission_info) (struct map_session_data *sd, int mob_id, unsigned char progress);
void (*feel_hate_reset) (struct map_session_data *sd);
void (*partytickack) (struct map_session_data* sd, bool flag);
- void (*equiptickack) (struct map_session_data* sd, int flag);
+ void (*zc_config) (struct map_session_data *sd, int type, int flag);
void (*viewequip_ack) (struct map_session_data* sd, struct map_session_data* tsd);
void (*equpcheckbox) (struct map_session_data* sd);
void (*displayexp) (struct map_session_data *sd, uint64 exp, char type, bool is_quest);
@@ -1302,7 +1310,7 @@ struct clif_interface {
void (*pAdopt_request) (int fd, struct map_session_data *sd);
void (*pAdopt_reply) (int fd, struct map_session_data *sd);
void (*pViewPlayerEquip) (int fd, struct map_session_data* sd);
- void (*pEquipTick) (int fd, struct map_session_data* sd);
+ void (*p_cz_config) (int fd, struct map_session_data *sd);
void (*pquestStateAck) (int fd, struct map_session_data * sd);
void (*pmercenary_action) (int fd, struct map_session_data* sd);
void (*pBattleChat) (int fd, struct map_session_data* sd);
@@ -1395,6 +1403,7 @@ struct clif_interface {
void (*pRodexRequestItems) (int fd, struct map_session_data *sd);
void (*rodex_request_items) (struct map_session_data *sd, int8 opentype, int64 mail_id, int8 result);
void (*rodex_icon) (int fd, bool show);
+ void (*skill_scale) (struct block_list *bl, int src_id, int x, int y, uint16 skill_id, uint16 skill_lv, int casttime);
};
#ifdef HERCULES_CORE
diff --git a/src/map/elemental.c b/src/map/elemental.c
index ae1fda0a2..cf1d485e1 100644
--- a/src/map/elemental.c
+++ b/src/map/elemental.c
@@ -885,7 +885,7 @@ int read_elementaldb(void) {
estatus->race = atoi(str[20]);
ele = atoi(str[21]);
- estatus->def_ele = ele%10;
+ estatus->def_ele = ele % ELE_MAX;
estatus->ele_lv = ele/20;
if( estatus->def_ele >= ELE_MAX ) {
ShowWarning("Elemental %d has invalid element type %d (max element is %d)\n", db->class_, estatus->def_ele, ELE_MAX - 1);
diff --git a/src/map/homunculus.c b/src/map/homunculus.c
index ddaf3443a..9f5756885 100644
--- a/src/map/homunculus.c
+++ b/src/map/homunculus.c
@@ -683,7 +683,12 @@ int homunculus_hunger_timer(int tid, int64 tick, int id, intptr_t data) {
} else if(hd->homunculus.hunger == 75) {
clif->emotion(&hd->bl, E_OK);
}
-
+ if (battle_config.feature_enable_homun_autofeed != 0) {
+ if (hd->homunculus.autofeed) {
+ if (hd->homunculus.hunger < 30)
+ homun->feed(sd, hd);
+ }
+ }
if(hd->homunculus.hunger < 0) {
hd->homunculus.hunger = 0;
// Delete the homunculus if intimacy <= 100
diff --git a/src/map/homunculus.h b/src/map/homunculus.h
index a80392cf6..f3b10fc19 100644
--- a/src/map/homunculus.h
+++ b/src/map/homunculus.h
@@ -124,7 +124,7 @@ struct homun_data {
struct map_session_data *master; //pointer back to its master
int hungry_timer; //[orn]
unsigned int exp_next;
- char blockskill[MAX_SKILL]; // [orn]
+ char blockskill[MAX_SKILL_DB]; // [orn]
int64 masterteleport_timer;
};
diff --git a/src/map/map.c b/src/map/map.c
index ff5c2aafd..5a647625f 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -1840,7 +1840,7 @@ void map_addiddb(struct block_list *bl)
struct mob_data *md = BL_UCAST(BL_MOB, bl);
idb_put(map->mobid_db,bl->id,bl);
- if( md->state.boss )
+ if (md->state.boss == BTYPE_MVP)
idb_put(map->bossid_db, bl->id, bl);
}
diff --git a/src/map/map.h b/src/map/map.h
index 3221c73cd..5835b5abc 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -519,7 +519,7 @@ struct spawn_data {
//0: Normal mob | 1: Standard summon, attacks mobs
//2: Alchemist Marine Sphere | 3: Alchemist Summon Flora | 4: Summon Zanzou
unsigned int dynamic : 1; ///< Whether this data is indexed by a map's dynamic mob list
- unsigned int boss : 1; ///< 0: Non-boss monster | 1: Boss monster
+ uint8 boss; ///< 0: Non-boss monster | 1: Boss monster | 2: MVP
} state;
char name[NAME_LENGTH], eventname[EVENT_NAME_LENGTH]; //Name/event
};
diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c
index 4cdb91b21..02015e011 100644
--- a/src/map/mapreg_sql.c
+++ b/src/map/mapreg_sql.c
@@ -211,9 +211,9 @@ void script_load_mapreg(void) {
mapreg->skip_insert = true;
- SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &varname[0], sizeof(varname), &length, NULL);
- SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &index, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 2, SQLDT_STRING, &value[0], sizeof(value), NULL, NULL);
+ SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &varname, sizeof varname, &length, NULL);
+ SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &index, sizeof index, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 2, SQLDT_STRING, &value, sizeof value, NULL, NULL);
while ( SQL_SUCCESS == SQL->StmtNextRow(stmt) ) {
int s = script->add_str(varname);
diff --git a/src/map/mercenary.c b/src/map/mercenary.c
index f5d3fe11c..c4b692008 100644
--- a/src/map/mercenary.c
+++ b/src/map/mercenary.c
@@ -465,7 +465,7 @@ bool read_mercenarydb_sub(char* str[], int columns, int current) {
mstatus->race = atoi(str[20]);
ele = atoi(str[21]);
- mstatus->def_ele = ele%10;
+ mstatus->def_ele = ele % ELE_MAX;
mstatus->ele_lv = ele/20;
if( mstatus->def_ele >= ELE_MAX ) {
ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, mstatus->def_ele, ELE_MAX - 1);
diff --git a/src/map/mercenary.h b/src/map/mercenary.h
index 0af75e8a2..f3773f191 100644
--- a/src/map/mercenary.h
+++ b/src/map/mercenary.h
@@ -92,7 +92,7 @@ struct mercenary_data {
struct regen_data regen;
struct s_mercenary_db *db;
struct s_mercenary mercenary;
- char blockskill[MAX_SKILL];
+ char blockskill[MAX_SKILL_DB];
struct map_session_data *master;
int contract_timer;
diff --git a/src/map/mob.c b/src/map/mob.c
index 822b84bf4..f509ecace 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -2686,7 +2686,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
return 5; // Note: Actually, it's 4. Oh well...
// MvP tomb [GreenBox]
- if (battle_config.mvp_tomb_enabled && md->spawn->state.boss && map->list[md->bl.m].flag.notomb != 1)
+ if (battle_config.mvp_tomb_enabled && md->spawn->state.boss == BTYPE_MVP && map->list[md->bl.m].flag.notomb != 1)
mob->mvptomb_create(md, mvp_sd ? mvp_sd->status.name : NULL, time(NULL));
if( !rebirth ) {
@@ -4846,7 +4846,7 @@ bool mob_parse_row_mobskilldb(char** str, int columns, int current)
struct mob_skill *ms, gms;
int mob_id;
int i =0, j, tmp;
- uint16 sidx = 0;
+ int sidx = 0;
nullpo_retr(false, str);
mob_id = atoi(str[0]);
diff --git a/src/map/mob.h b/src/map/mob.h
index 7f2accedf..83e022899 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -69,6 +69,12 @@ struct hplugin_data_store;
// Disable this to make monsters not do any path search when looking for a target (old behavior).
#define ACTIVEPATHSEARCH
+enum e_bosstype {
+ BTYPE_NONE = 0,
+ BTYPE_BOSS = 1,
+ BTYPE_MVP = 2,
+};
+
//Mob skill states.
enum MobSkillState {
MSS_ANY = -1,
@@ -181,10 +187,10 @@ struct mob_data {
unsigned int spotted: 1;
unsigned int npc_killmonster: 1; //for new killmonster behavior
unsigned int rebirth: 1; // NPC_Rebirth used
- unsigned int boss : 1;
enum MobSkillState skillstate;
unsigned char steal_flag; //number of steal tries (to prevent steal exploit on mobs with few items) [Lupus]
unsigned char attacked_count; //For rude attacked.
+ uint8 boss;
int provoke_flag; // Celest
} state;
struct guardian_data* guardian_data;
diff --git a/src/map/npc.c b/src/map/npc.c
index ecf7f878f..d3dfb39d2 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -114,6 +114,8 @@ bool npc_db_checkid(int id)
return true;
if (id >= MAX_NPC_CLASS2_START && id < MAX_NPC_CLASS2_END) // Second range
return true;
+ if (pc->db_checkid(id))
+ return true;
// Anything else is invalid
return false;
}
@@ -1558,9 +1560,9 @@ void npc_market_fromsql(void)
return;
}
- SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &name[0], sizeof(name), NULL, NULL);
- SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &itemid, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 2, SQLDT_INT, &amount, 0, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &name, sizeof name, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &itemid, sizeof itemid, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 2, SQLDT_INT, &amount, sizeof amount, NULL, NULL);
while ( SQL_SUCCESS == SQL->StmtNextRow(stmt) ) {
struct npc_data *nd = NULL;
@@ -2706,6 +2708,7 @@ struct npc_data *npc_create_npc(enum npc_subtype subtype, int m, int x, int y, u
nd->area_size = AREA_SIZE + 1;
nd->class_ = class_;
nd->speed = 200;
+ nd->vd = npc_viewdb[0]; // Copy INVISIBLE_CLASS view data. Actual view data is set by npc->add_to_location() later.
return nd;
}
@@ -3656,6 +3659,18 @@ void npc_setclass(struct npc_data* nd, short class_) {
clif->spawn(&nd->bl);// fade in
}
+void npc_refresh(struct npc_data* nd)
+{
+ nullpo_retv(nd);
+
+ if (map->list[nd->bl.m].users) {
+ // using here CLR_TRICKDEAD because other flags show effects.
+ // probably need use other flag or other way to refresh npc.
+ clif->clearunit_area(&nd->bl, CLR_TRICKDEAD); // fade out
+ clif->spawn(&nd->bl); // fade in
+ }
+}
+
// @commands (script based)
int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const char* message, const char* eventname)
{
@@ -3843,7 +3858,12 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const
memset(&mobspawn, 0, sizeof(struct spawn_data));
- mobspawn.state.boss = (strcmp(w2,"boss_monster") == 0 ? 1 : 0);
+ if (strcmp(w2, "boss_monster") == 0)
+ mobspawn.state.boss = BTYPE_MVP;
+ else if (strcmp(w2, "miniboss_monster") == 0)
+ mobspawn.state.boss = BTYPE_BOSS;
+ else
+ mobspawn.state.boss = BTYPE_NONE;
// w1=<map name>,<x>,<y>,<xs>,<ys>
// w3=<mob name>{,<mob level>}
@@ -4662,7 +4682,7 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
{
p = npc->parse_duplicate(w1,w2,w3,w4, p, buffer, filepath, (runOnInit?NPO_ONINIT:NPO_NONE), &success);
}
- else if( (strcmp(w2,"monster") == 0 || strcmp(w2,"boss_monster") == 0) )
+ else if (strcmp(w2,"monster") == 0 || strcmp(w2,"boss_monster") == 0 || strcmp(w2,"miniboss_monster") == 0)
{
p = npc->parse_mob(w1, w2, w3, w4, p, buffer, filepath, &success);
}
@@ -4994,7 +5014,6 @@ int do_init_npc(bool minimal) {
npc_viewdb[i].class = i;
for( i = MAX_NPC_CLASS2_START; i < MAX_NPC_CLASS2_END; i++ )
npc_viewdb2[i - MAX_NPC_CLASS2_START].class = i;
-
npc->ev_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, EVENT_NAME_LENGTH);
npc->ev_label_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, NAME_LENGTH);
npc->name_db = strdb_alloc(DB_OPT_BASE, NAME_LENGTH);
@@ -5189,4 +5208,5 @@ void npc_defaults(void) {
npc->market_delfromsql = npc_market_delfromsql;
npc->market_delfromsql_sub = npc_market_delfromsql_sub;
npc->db_checkid = npc_db_checkid;
+ npc->refresh = npc_refresh;
}
diff --git a/src/map/npc.h b/src/map/npc.h
index 3bd11d536..8bb38f252 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -70,7 +70,7 @@ struct npc_parse;
struct npc_data {
struct block_list bl;
struct unit_data *ud;
- struct view_data *vd;
+ struct view_data vd;
unsigned int option;
struct npc_data *master_nd;
short class_;
@@ -309,6 +309,7 @@ struct npc_interface {
void (*market_delfromsql) (struct npc_data *nd, unsigned short index);
void (*market_delfromsql_sub) (const char *npcname, unsigned short index);
bool (*db_checkid) (const int id);
+ void (*refresh) (struct npc_data* nd);
/**
* For the Secure NPC Timeout option (check config/Secure.h) [RR]
**/
diff --git a/src/map/packets.h b/src/map/packets.h
index e9d895440..b95ae65cf 100644
--- a/src/map/packets.h
+++ b/src/map/packets.h
@@ -1151,7 +1151,7 @@ packet(0x96e,-1,clif->ackmergeitems);
packet(0x02d5,2);
packet(0x02d6,6,clif->pViewPlayerEquip,2);
packet(0x02d7,-1);
- packet(0x02d8,10,clif->pEquipTick,6);
+ packet(0x02d8,10,clif->p_cz_config,6);
packet(0x02d9,10);
packet(0x02da,3);
packet(0x02db,-1,clif->pBattleChat,2,4);
@@ -10669,4 +10669,78 @@ packet(0x96e,-1,clif->ackmergeitems);
packet(0x096a,6,clif->pGetCharNameRequest,2); // CZ_REQNAME
#endif
+// 2017-10-25eRagexeRE
+#if PACKETVER == 20171025
+// shuffle packets
+ packet(0x0202,5,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x022d,19,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x023b,26,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x035f,6,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0360,6,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0361,5,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0362,6,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x0363,8,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0364,8,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
+ packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x0368,6,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0369,7,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x0436,4,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK
+ packet(0x0437,5,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x07e4,6,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x07ec,8,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0802,26,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
+ packet(0x0817,2,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0835,2,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x083c,10,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x08a2,36,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x096a,6,clif->pGetCharNameRequest,2); // CZ_REQNAME
+#endif
+
+// 2017-11-01bRagexeRE
+#if PACKETVER == 20171101
+// shuffle packets
+ packet(0x022d,36,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0368,19,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0369,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0438,6,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0835,6,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x085b,5,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0860,6,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x086c,10,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0872,26,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0876,5,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x0886,8,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD
+ packet(0x088e,6,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0890,2,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x0895,4,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK
+ packet(0x0899,26,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x089b,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
+ packet(0x089c,18,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
+ packet(0x08a0,8,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x08ab,-1,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x08ad,12,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x091b,8,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0939,5,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x094a,2,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x094d,6,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0952,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x0957,7,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x095a,-1,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0962,6,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0966,10,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+#endif
+
+// 2017-11-01bRagexeRE
+#if PACKETVER >= 20171101
+// new packets
+ packet(0x0ae1,28);
+#endif
+
#endif /* MAP_PACKETS_H */
diff --git a/src/map/packets_keys.h b/src/map/packets_keys.h
index 85796813a..005c3790b 100644
--- a/src/map/packets_keys.h
+++ b/src/map/packets_keys.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2015 Hercules Dev Team
+ * Copyright (C) 2013-2017 Hercules Dev Team
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -2057,7 +2057,7 @@
packetKeys(0x03FA5A97,0x20B802D5,0x339F1977);
#endif
-// 2017-06-07bRagexeRE
+// 2017-06-07bRagexeRE, 2017-06-07cRagexeRE
#if PACKETVER == 20170607
packetKeys(0x50564ACD,0x79CA4E15,0x405F4894);
#endif
@@ -2152,6 +2152,16 @@
packetKeys(0x2CAA109C,0x158C1EC2,0x7A5E58F3);
#endif
+// 2017-10-25bRagexeRE, 2017-10-25cRagexeRE, 2017-10-25dRagexeRE, 2017-10-25eRagexeRE
+#if PACKETVER == 20171025
+ packetKeys(0x165C565C,0x565C565C,0x565C565C);
+#endif
+
+// 2017-11-01bRagexeRE
+#if PACKETVER == 20171101
+ packetKeys(0x7056317F,0x7EEE0589,0x02672373);
+#endif
+
#if defined(OBFUSCATIONKEY1) && defined(OBFUSCATIONKEY2) && defined(OBFUSCATIONKEY3)
packetKeys(OBFUSCATIONKEY1,OBFUSCATIONKEY2,OBFUSCATIONKEY3);
diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h
index 03b555e2b..e1395e949 100644
--- a/src/map/packets_struct.h
+++ b/src/map/packets_struct.h
@@ -330,6 +330,9 @@ enum packet_headers {
#else // PACKETVER >= 20160316
rodexcheckplayer = 0x0A51,
#endif
+#if PACKETVER >= 20151223
+ skillscale = 0xA41,
+#endif
};
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
@@ -1478,6 +1481,16 @@ struct PACKET_ZC_ACK_ITEM_FROM_MAIL {
int8 result;
} __attribute__((packed));
+struct PACKET_ZC_SKILL_SCALE {
+ int16 PacketType;
+ uint32 AID;
+ int16 skill_id;
+ int16 skill_lv;
+ int16 x;
+ int16 y;
+ uint32 casttime;
+} __attribute__((packed));
+
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
#pragma pack(pop)
#endif // not NetBSD < 6 / Solaris
diff --git a/src/map/pc.c b/src/map/pc.c
index 0636ebafa..d5d359557 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -1560,7 +1560,7 @@ int pc_calc_skillpoint(struct map_session_data* sd) {
nullpo_ret(sd);
- for (i = 1; i < MAX_SKILL; i++) {
+ for (i = 1; i < MAX_SKILL_DB; i++) {
int skill_lv = pc->checkskill2(sd,i);
if (skill_lv > 0) {
inf2 = skill->dbs->db[i].inf2;
@@ -1596,7 +1596,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
}
classidx = pc->class2idx(class);
- for( i = 0; i < MAX_SKILL; i++ ) {
+ for (i = 0; i < MAX_SKILL_DB; i++) {
if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED ) //Don't touch these
sd->status.skill[i].id = 0; //First clear skills.
/* permanent skills that must be re-checked */
@@ -1613,7 +1613,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
}
}
- for( i = 0; i < MAX_SKILL; i++ ) {
+ for (i = 0; i < MAX_SKILL_DB; i++) {
if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED )
{ // Restore original level of skills after deleting earned skills.
sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
@@ -1622,18 +1622,25 @@ int pc_calc_skilltree(struct map_session_data *sd)
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 )
+ if (sd->status.sex) {
+ // Link dancer skills to bard.
+ if (i < 8) {
+ Assert_report(i >= 8);
+ continue;
+ }
+ if (sd->status.skill[i-8].lv < 10)
continue;
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 )
+ } else {
+ // Link bard skills to dancer.
+ if (i < 8) {
+ Assert_report(i >= 8);
+ continue;
+ }
+ if (sd->status.skill[i].lv < 10)
continue;
- // i can be < 8?
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
@@ -1642,7 +1649,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++ ) {
+ for (i = 0; i < MAX_SKILL_DB; i++) {
switch(skill->dbs->db[i].nameid) {
/**
* Dummy skills must be added here otherwise they'll be displayed in the,
@@ -1836,7 +1843,7 @@ int pc_clean_skilltree(struct map_session_data *sd)
{
int i;
nullpo_ret(sd);
- for (i = 0; i < MAX_SKILL; i++){
+ for (i = 0; i < MAX_SKILL_DB; i++) {
if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED) {
sd->status.skill[i].id = 0;
sd->status.skill[i].lv = 0;
@@ -4143,7 +4150,7 @@ int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4
*------------------------------------------*/
int pc_skill(struct map_session_data *sd, int id, int level, int flag)
{
- uint16 index = 0;
+ int index = 0;
nullpo_ret(sd);
if (!(index = skill->get_index(id))) {
@@ -5869,7 +5876,7 @@ int pc_memo(struct map_session_data* sd, int pos) {
* Return player sd skill_lv learned for given skill
*------------------------------------------*/
int pc_checkskill(struct map_session_data *sd,uint16 skill_id) {
- uint16 index = 0;
+ int index = 0;
if(sd == NULL) return 0;
if( skill_id >= GD_SKILLBASE && skill_id < GD_MAX ) {
struct guild *g;
@@ -5888,8 +5895,9 @@ int pc_checkskill(struct map_session_data *sd,uint16 skill_id) {
return 0;
}
int pc_checkskill2(struct map_session_data *sd,uint16 index) {
- if(sd == NULL) return 0;
- if(index >= ARRAYLENGTH(sd->status.skill) ) {
+ if (sd == NULL)
+ return 0;
+ if (index >= MAX_SKILL_DB) {
ShowError("pc_checkskill: Invalid skill index %d (char_id=%d).\n", index, sd->status.char_id);
return 0;
}
@@ -7229,7 +7237,7 @@ int pc_statusup2(struct map_session_data* sd, int type, int val)
* Skill point allocation
*------------------------------------------*/
int pc_skillup(struct map_session_data *sd,uint16 skill_id) {
- uint16 index = 0;
+ int index = 0;
nullpo_ret(sd);
if( skill_id >= GD_SKILLBASE && skill_id < GD_SKILLBASE+MAX_GUILDSKILL ) {
@@ -7286,7 +7294,7 @@ int pc_allskillup(struct map_session_data *sd)
nullpo_ret(sd);
- for(i=0;i<MAX_SKILL;i++){
+ for (i = 0; i < MAX_SKILL_DB; i++) {
if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) {
sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
@@ -7297,7 +7305,7 @@ 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++){
+ for (i = 0; i < MAX_SKILL_DB; i++) {
switch( skill->dbs->db[i].nameid ) {
case SG_DEVIL:
case MO_TRIPLEATTACK:
@@ -7537,9 +7545,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
status_change_end(&sd->bl, SC_SPRITEMABLE, INVALID_TIMER);
}
- 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->dbs->db[], and especially to check skill_ischangesex(). This is wrong.
+ for (i = 1; i < MAX_SKILL_DB; i++) {
uint16 skill_id = 0;
int lv = sd->status.skill[i].lv;
if (lv < 1) continue;
diff --git a/src/map/pc.h b/src/map/pc.h
index 50cb1b68e..df0df979d 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -292,7 +292,7 @@ struct map_session_data {
uint16 skill_id_old,skill_lv_old;
uint16 skill_id_dance,skill_lv_dance;
short cook_mastery; // range: [0,1999] [Inkfish]
- bool blockskill[MAX_SKILL];
+ bool blockskill[MAX_SKILL_DB];
int cloneskill_id, reproduceskill_id;
int menuskill_id, menuskill_val, menuskill_val2;
int invincible_timer;
diff --git a/src/map/script.c b/src/map/script.c
index d2101d21f..7f7aba183 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -12190,7 +12190,7 @@ BUILDIN(homunculus_mutate)
if (script_hasdata(st,2))
homun_id = script_getnum(st,2);
else
- homun_id = 6048 + (rnd() % 4);
+ homun_id = HOMID_EIRA + (rnd() % 4);
m_class = homun->class2type(sd->hd->homunculus.class_);
m_id = homun->class2type(homun_id);
@@ -14081,53 +14081,61 @@ BUILDIN(getiteminfo)
}
switch (n) {
- case 0:
+ case ITEMINFO_BUYPRICE:
script_pushint(st, it->value_buy);
break;
- case 1:
+ case ITEMINFO_SELLPRICE:
script_pushint(st, it->value_sell);
break;
- case 2:
+ case ITEMINFO_TYPE:
script_pushint(st, it->type);
break;
- case 3:
+ case ITEMINFO_MAXCHANCE:
script_pushint(st, it->maxchance);
break;
- case 4:
+ case ITEMINFO_SEX:
script_pushint(st, it->sex);
break;
- case 5:
+ case ITEMINFO_LOC:
script_pushint(st, it->equip);
break;
- case 6:
+ case ITEMINFO_WEIGHT:
script_pushint(st, it->weight);
break;
- case 7:
+ case ITEMINFO_ATK:
script_pushint(st, it->atk);
break;
- case 8:
+ case ITEMINFO_DEF:
script_pushint(st, it->def);
break;
- case 9:
+ case ITEMINFO_RANGE:
script_pushint(st, it->range);
break;
- case 10:
+ case ITEMINFO_SLOTS:
script_pushint(st, it->slot);
break;
- case 11:
+ case ITEMINFO_SUBTYPE:
script_pushint(st, it->subtype);
break;
- case 12:
+ case ITEMINFO_ELV:
script_pushint(st, it->elv);
break;
- case 13:
+ case ITEMINFO_WLV:
script_pushint(st, it->wlv);
break;
- case 14:
+ case ITEMINFO_VIEWID:
script_pushint(st, it->view_id);
break;
+ case ITEMINFO_MATK:
+ script_pushint(st, it->matk);
+ break;
+ case ITEMINFO_VIEWSPRITE:
+ script_pushint(st, it->view_sprite);
+ break;
default:
+ ShowError("buildin_getiteminfo: Invalid item type %d.\n", n);
script_pushint(st,-1);
+ return false;
}
return true;
}
@@ -14270,31 +14278,36 @@ BUILDIN(setequipoption)
if (equip_index > 0 && equip_index <= ARRAYLENGTH(script->equip)) {
if ((i = pc->checkequip(sd, script->equip[equip_index - 1])) == -1) {
- ShowError("buildin_setequipoptioninfo: No equipment is equipped in the given index %d.\n", equip_index);
+ ShowError("buildin_setequipoption: No equipment is equipped in the given index %d.\n", equip_index);
script_pushint(st, 0);
return false;
}
} else {
- ShowError("buildin_setequipoptioninfo: Invalid equipment index %d provided.\n", equip_index);
+ ShowError("buildin_setequipoption: Invalid equipment index %d provided.\n", equip_index);
script_pushint(st, 0);
return false;
}
if (sd->status.inventory[i].nameid != 0) {
-
- if ((ito = itemdb->option_exists(opt_index)) == NULL) {
- script_pushint(st, 0);
- ShowError("buildin_setequipotion: Option index %d does not exist!\n", opt_index);
- return false;
- } else if (value < -INT16_MAX || value > INT16_MAX) {
- script_pushint(st, 0);
- ShowError("buildin_setequipotion: Option value %d exceeds maximum limit (%d to %d) for type!\n", value, -INT16_MAX, INT16_MAX);
- return false;
+ if (opt_index == 0) {
+ // Remove the option
+ sd->status.inventory[i].option[slot-1].index = 0;
+ sd->status.inventory[i].option[slot-1].value = 0;
+ } else {
+ if ((ito = itemdb->option_exists(opt_index)) == NULL) {
+ script_pushint(st, 0);
+ ShowError("buildin_setequipotion: Option index %d does not exist!\n", opt_index);
+ return false;
+ } else if (value < -INT16_MAX || value > INT16_MAX) {
+ script_pushint(st, 0);
+ ShowError("buildin_setequipotion: Option value %d exceeds maximum limit (%d to %d) for type!\n", value, -INT16_MAX, INT16_MAX);
+ return false;
+ }
+ /* Add Option Index */
+ sd->status.inventory[i].option[slot-1].index = ito->index;
+ /* Add Option Value */
+ sd->status.inventory[i].option[slot-1].value = value;
}
- /* Add Option Index */
- sd->status.inventory[i].option[slot-1].index = ito->index;
- /* Add Option Value */
- sd->status.inventory[i].option[slot-1].value = value;
/* Unequip and simulate deletion of the item. */
pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); // status calc will happen in pc->equipitem() below
@@ -14334,54 +14347,61 @@ BUILDIN(setiteminfo)
}
switch (n) {
- case 0:
+ case ITEMINFO_BUYPRICE:
it->value_buy = value;
break;
- case 1:
+ case ITEMINFO_SELLPRICE:
it->value_sell = value;
break;
- case 2:
+ case ITEMINFO_TYPE:
it->type = value;
break;
- case 3:
+ case ITEMINFO_MAXCHANCE:
it->maxchance = value;
break;
- case 4:
+ case ITEMINFO_SEX:
it->sex = value;
break;
- case 5:
+ case ITEMINFO_LOC:
it->equip = value;
break;
- case 6:
+ case ITEMINFO_WEIGHT:
it->weight = value;
break;
- case 7:
+ case ITEMINFO_ATK:
it->atk = value;
break;
- case 8:
+ case ITEMINFO_DEF:
it->def = value;
break;
- case 9:
+ case ITEMINFO_RANGE:
it->range = value;
break;
- case 10:
+ case ITEMINFO_SLOTS:
it->slot = value;
break;
- case 11:
+ case ITEMINFO_SUBTYPE:
it->subtype = value;
break;
- case 12:
+ case ITEMINFO_ELV:
it->elv = value;
break;
- case 13:
+ case ITEMINFO_WLV:
it->wlv = value;
break;
- case 14:
+ case ITEMINFO_VIEWID:
it->view_id = value;
break;
+ case ITEMINFO_MATK:
+ it->matk = value;
+ break;
+ case ITEMINFO_VIEWSPRITE:
+ it->view_sprite = value;
+ break;
default:
+ ShowError("buildin_setiteminfo: invalid type %d.\n", n);
script_pushint(st,-1);
- return true;
+ return false;
}
script_pushint(st,value);
return true;
@@ -14585,7 +14605,7 @@ BUILDIN(getskilllist)
int i,j=0;
if (sd == NULL)
return true;
- for(i=0;i<MAX_SKILL;i++) {
+ for (i = 0; i < MAX_SKILL_DB; i++) {
if(sd->status.skill[i].id > 0 && sd->status.skill[i].lv > 0) {
pc->setreg(sd,reference_uid(script->add_str("@skilllist_id"), j),sd->status.skill[i].id);
pc->setreg(sd,reference_uid(script->add_str("@skilllist_lv"), j),sd->status.skill[i].lv);
@@ -15866,11 +15886,12 @@ enum logmes_type {
/*==========================================
* Allows player to write logs (i.e. Bank NPC, etc) [Lupus]
*------------------------------------------*/
-BUILDIN(logmes) {
+BUILDIN(logmes)
+{
const char *str = script_getstr(st, 2);
struct map_session_data *sd = script->rid2sd(st);
enum logmes_type type = LOGMES_NPC;
- nullpo_retr(sd, false);
+ nullpo_retr(false, sd);
if (script_hasdata(st, 3)) {
type = script_getnum(st, 3);
@@ -18211,6 +18232,8 @@ BUILDIN(setunitdata)
case UDT_INTIMACY:
case UDT_LIFETIME:
case UDT_MERC_KILLCOUNT:
+ case UDT_ROBE:
+ case UDT_BODY2:
setunitdata_check_min(4, 0);
break;
case UDT_MASTERAID:
@@ -19149,6 +19172,40 @@ BUILDIN(setunitdata)
case UDT_DMOTION:
nd->status.dmotion = (unsigned short) val;
break;
+ case UDT_SEX:
+ nd->vd.sex = (char)val;
+ npc->refresh(nd);
+ break;
+ case UDT_HAIRSTYLE:
+ clif->changelook(bl, LOOK_HAIR, val);
+ break;
+ case UDT_HAIRCOLOR:
+ clif->changelook(bl, LOOK_HAIR_COLOR, val);
+ break;
+ case UDT_HEADBOTTOM:
+ clif->changelook(bl, LOOK_HEAD_BOTTOM, val);
+ break;
+ case UDT_HEADMIDDLE:
+ clif->changelook(bl, LOOK_HEAD_MID, val);
+ break;
+ case UDT_HEADTOP:
+ clif->changelook(bl, LOOK_HEAD_TOP, val);
+ break;
+ case UDT_CLOTHCOLOR:
+ clif->changelook(bl, LOOK_CLOTHES_COLOR, val);
+ break;
+ case UDT_SHIELD:
+ clif->changelook(bl, LOOK_SHIELD, val);
+ break;
+ case UDT_WEAPON:
+ clif->changelook(bl, LOOK_WEAPON, val);
+ break;
+ case UDT_ROBE:
+ clif->changelook(bl, LOOK_ROBE, val);
+ break;
+ case UDT_BODY2:
+ clif->changelook(bl, LOOK_BODY2, val);
+ break;
default:
ShowWarning("buildin_setunitdata: Invalid data type '%s' for NPC unit.\n", udtype);
script_pushint(st, 0);
@@ -19559,6 +19616,18 @@ BUILDIN(getunitdata)
case UDT_AMOTION: script_pushint(st, nd->status.amotion); break;
case UDT_ADELAY: script_pushint(st, nd->status.adelay); break;
case UDT_DMOTION: script_pushint(st, nd->status.dmotion); break;
+ case UDT_SEX: script_pushint(st, nd->vd.sex); break;
+ case UDT_CLASS: script_pushint(st, nd->vd.class); break;
+ case UDT_HAIRSTYLE: script_pushint(st, nd->vd.hair_style); break;
+ case UDT_HAIRCOLOR: script_pushint(st, nd->vd.hair_color); break;
+ case UDT_HEADBOTTOM: script_pushint(st, nd->vd.head_bottom); break;
+ case UDT_HEADMIDDLE: script_pushint(st, nd->vd.head_mid); break;
+ case UDT_HEADTOP: script_pushint(st, nd->vd.head_top); break;
+ case UDT_CLOTHCOLOR: script_pushint(st, nd->vd.cloth_color); break;
+ case UDT_SHIELD: script_pushint(st, nd->vd.shield); break;
+ case UDT_WEAPON: script_pushint(st, nd->vd.weapon); break;
+ case UDT_ROBE: script_pushint(st, nd->vd.robe); break;
+ case UDT_BODY2: script_pushint(st, nd->vd.body_style); break;
default:
ShowWarning("buildin_getunitdata: Invalid data type '%s' for NPC unit.\n", udtype);
script_pushint(st, 0);
@@ -20446,15 +20515,18 @@ BUILDIN(questinfo)
quest_id = script_getnum(st, 2);
icon = script_getnum(st, 3);
- #if PACKETVER >= 20120410
- if(icon < 0 || (icon > 8 && icon != 9999) || icon == 7)
- icon = 9999; // Default to nothing if icon id is invalid.
- #else
- if(icon < 0 || icon > 7)
- icon = 0;
- else
- icon = icon + 1;
- #endif
+#if PACKETVER >= 20170315
+ if (icon < 0 || (icon > 10 && icon != 9999))
+ icon = 9999;
+#elif PACKETVER >= 20120410
+ if (icon < 0 || (icon > 8 && icon != 9999) || icon == 7)
+ icon = 9999; // Default to nothing if icon id is invalid.
+#else
+ if (icon < 0 || icon > 7)
+ icon = 0;
+ else
+ icon = icon + 1;
+#endif
qi.quest_id = quest_id;
qi.icon = (unsigned char)icon;
@@ -20648,15 +20720,18 @@ BUILDIN(showevent)
}
}
- #if PACKETVER >= 20120410
- if(icon < 0 || (icon > 8 && icon != 9999) || icon == 7)
- icon = 9999; // Default to nothing if icon id is invalid.
- #else
- if(icon < 0 || icon > 7)
- icon = 0;
- else
- icon = icon + 1;
- #endif
+#if PACKETVER >= 20170315
+ if (icon < 0 || (icon > 10 && icon != 9999))
+ icon = 9999;
+#elif PACKETVER >= 20120410
+ if (icon < 0 || (icon > 8 && icon != 9999) || icon == 7)
+ icon = 9999; // Default to nothing if icon id is invalid.
+#else
+ if (icon < 0 || icon > 7)
+ icon = 0;
+ else
+ icon = icon + 1;
+#endif
clif->quest_show_event(sd, &nd->bl, icon, color);
return true;
@@ -21128,72 +21203,90 @@ BUILDIN(has_instance)
const char *str;
int16 m;
int instance_id = -1;
+ int i = 0, j = 0;
bool type = strcmp(script->getfuncname(st),"has_instance2") == 0 ? true : false;
str = script_getstr(st, 2);
- if( (m = map->mapname2mapid(str)) < 0 ) {
- if( type )
+ if ((m = map->mapname2mapid(str)) < 0) {
+ if (type) {
script_pushint(st, -1);
- else
+ } else {
script_pushconststr(st, "");
+ }
return true;
}
- if( script_hasdata(st, 3) )
+ if (script_hasdata(st, 3))
instance_id = script_getnum(st, 3);
- else if( st->instance_id >= 0 )
+ else if (st->instance_id >= 0)
instance_id = st->instance_id;
- else if( (sd = script->rid2sd(st)) != NULL ) {
+ else if ((sd = script->rid2sd(st)) != NULL) {
struct party_data *p;
- int i = 0, j = 0;
- if( sd->instances ) {
- for( i = 0; i < sd->instances; i++ ) {
- if( sd->instance[i] >= 0 ) {
+ if (sd->instances) {
+ for (i = 0; i < sd->instances; i++) {
+ if (sd->instance[i] >= 0) {
ARR_FIND(0, instance->list[sd->instance[i]].num_map, j, map->list[instance->list[sd->instance[i]].map[j]].instance_src_map == m);
- if( j != instance->list[sd->instance[i]].num_map )
+ if (j != instance->list[sd->instance[i]].num_map)
break;
}
}
- if( i != sd->instances )
+ if (i != sd->instances) {
instance_id = sd->instance[i];
+ }
}
if (instance_id == -1 && sd->status.party_id && (p = party->search(sd->status.party_id)) != NULL && p->instances) {
- for( i = 0; i < p->instances; i++ ) {
- if( p->instance[i] >= 0 ) {
+ for (i = 0; i < p->instances; i++) {
+ if (p->instance[i] >= 0) {
ARR_FIND(0, instance->list[p->instance[i]].num_map, j, map->list[instance->list[p->instance[i]].map[j]].instance_src_map == m);
- if( j != instance->list[p->instance[i]].num_map )
+ if (j != instance->list[p->instance[i]].num_map)
break;
}
}
- if( i != p->instances )
+ if (i != p->instances) {
instance_id = p->instance[i];
+ }
}
- if( instance_id == -1 && sd->guild && sd->guild->instances ) {
- for( i = 0; i < sd->guild->instances; i++ ) {
- if( sd->guild->instance[i] >= 0 ) {
+ if (instance_id == -1 && sd->guild && sd->guild->instances) {
+ for (i = 0; i < sd->guild->instances; i++) {
+ if (sd->guild->instance[i] >= 0) {
ARR_FIND(0, instance->list[sd->guild->instance[i]].num_map, j, map->list[instance->list[sd->guild->instance[i]].map[j]].instance_src_map == m);
- if( j != instance->list[sd->guild->instance[i]].num_map )
+ if (j != instance->list[sd->guild->instance[i]].num_map)
break;
}
}
- if( i != sd->guild->instances )
+ if (i != sd->guild->instances)
instance_id = sd->guild->instance[i];
}
}
- if( !instance->valid(instance_id) || (m = instance->map2imap(m, instance_id)) < 0 ) {
- if( type )
+ if (instance_id == -1) {
+ for (i = 0; i < instance->instances; i++) {
+ if (instance->list[i].state != INSTANCE_FREE && instance->list[i].owner_type == IOT_NONE && instance->list[i].num_map > 0) {
+ ARR_FIND(0, instance->list[i].num_map, j, map->list[instance->list[i].map[j]].instance_src_map == m);
+ if (j != instance->list[i].num_map)
+ break;
+ }
+ }
+ if (i != instance->instances) {
+ instance_id = instance->list[i].id;
+ }
+ }
+
+ if (!instance->valid(instance_id) || (m = instance->map2imap(m, instance_id)) < 0) {
+ if (type) {
script_pushint(st, -1);
- else
+ } else {
script_pushconststr(st, "");
+ }
return true;
}
- if( type )
+ if (type) {
script_pushint(st, instance_id);
- else
+ } else {
script_pushconststr(st, map->list[m].name);
+ }
return true;
}
@@ -23505,7 +23598,7 @@ BUILDIN(dressroom)
clif->dressroom_open(sd, 0);
break;
default:
- ShowWarning("script:dressroom: unknown mode (%i).\n", mode);
+ ShowWarning("script:dressroom: unknown mode (%u).\n", mode);
script_pushint(st, 0);
return false;
}
@@ -24751,6 +24844,25 @@ void script_hardcoded_constants(void)
script->set_constant("MAPINFO_SIZE_Y", MAPINFO_SIZE_Y, false, false);
script->set_constant("MAPINFO_ZONE", MAPINFO_ZONE, false, false);
+ script->constdb_comment("set/getiteminfo options");
+ script->set_constant("ITEMINFO_BUYPRICE", ITEMINFO_BUYPRICE, false, false);
+ script->set_constant("ITEMINFO_SELLPRICE", ITEMINFO_SELLPRICE, false, false);
+ script->set_constant("ITEMINFO_TYPE", ITEMINFO_TYPE, false, false);
+ script->set_constant("ITEMINFO_MAXCHANCE", ITEMINFO_MAXCHANCE, false, false);
+ script->set_constant("ITEMINFO_SEX", ITEMINFO_SEX, false, false);
+ script->set_constant("ITEMINFO_LOC", ITEMINFO_LOC, false, false);
+ script->set_constant("ITEMINFO_WEIGHT", ITEMINFO_WEIGHT, false, false);
+ script->set_constant("ITEMINFO_ATK", ITEMINFO_ATK, false, false);
+ script->set_constant("ITEMINFO_DEF", ITEMINFO_DEF, false, false);
+ script->set_constant("ITEMINFO_RANGE", ITEMINFO_RANGE, false, false);
+ script->set_constant("ITEMINFO_SLOTS", ITEMINFO_SLOTS, false, false);
+ script->set_constant("ITEMINFO_SUBTYPE", ITEMINFO_SUBTYPE, false, false);
+ script->set_constant("ITEMINFO_ELV", ITEMINFO_ELV, false, false);
+ script->set_constant("ITEMINFO_WLV", ITEMINFO_WLV, false, false);
+ script->set_constant("ITEMINFO_VIEWID", ITEMINFO_VIEWID, false, false);
+ script->set_constant("ITEMINFO_MATK", ITEMINFO_MATK, false, false);
+ script->set_constant("ITEMINFO_VIEWSPRITE", ITEMINFO_VIEWSPRITE, false, false);
+
script->constdb_comment("Renewal");
#ifdef RENEWAL
script->set_constant("RENEWAL", 1, false, false);
diff --git a/src/map/script.h b/src/map/script.h
index 283afa496..14d20838d 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -423,10 +423,37 @@ enum script_unit_data_types {
UDT_LIFETIME,
UDT_MERC_KILLCOUNT,
UDT_STATPOINT,
+ UDT_ROBE,
+ UDT_BODY2,
UDT_MAX
};
/**
+ * Item Info types.
+ */
+enum script_iteminfo_types {
+ ITEMINFO_BUYPRICE = 0,
+ ITEMINFO_SELLPRICE,
+ ITEMINFO_TYPE,
+ ITEMINFO_MAXCHANCE,
+ ITEMINFO_SEX,
+ ITEMINFO_LOC,
+ ITEMINFO_WEIGHT,
+ ITEMINFO_ATK,
+ ITEMINFO_DEF,
+ ITEMINFO_RANGE,
+ ITEMINFO_SLOTS,
+ ITEMINFO_SUBTYPE,
+ ITEMINFO_ELV,
+ ITEMINFO_WLV,
+ ITEMINFO_VIEWID,
+ ITEMINFO_MATK,
+ ITEMINFO_VIEWSPRITE,
+
+ ITEMINFO_MAX
+};
+
+/**
* Structures
**/
diff --git a/src/map/skill.c b/src/map/skill.c
index 726deaa9a..88a29b9a8 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -105,7 +105,7 @@ int skill_name2id(const char* name)
/// Maps skill ids to skill db offsets.
/// Returns the skill's array index, or 0 (Unknown Skill).
-int skill_get_index (uint16 skill_id)
+int skill_get_index(int skill_id)
{
// avoid ranges reserved for mapping guild/homun/mercenary skills
if( (skill_id >= GD_SKILLRANGEMIN && skill_id <= GD_SKILLRANGEMAX)
@@ -138,88 +138,593 @@ int skill_get_index (uint16 skill_id)
}
// validate result
- if( !skill_id || skill_id >= MAX_SKILL_DB )
+ if (skill_id <= 0|| skill_id >= MAX_SKILL_DB)
return 0;
return skill_id;
}
-const char* skill_get_name( uint16 skill_id ) {
+const char *skill_get_name(int skill_id)
+{
return skill->dbs->db[skill->get_index(skill_id)].name;
}
-const char* skill_get_desc( uint16 skill_id ) {
+const char *skill_get_desc(int skill_id)
+{
return skill->dbs->db[skill->get_index(skill_id)].desc;
}
-// out of bounds error checking [celest]
-void skill_chk(uint16* skill_id) {
- *skill_id = skill->get_index(*skill_id); // checks/adjusts id
-}
+#define skill_get_lvl_idx(lv) (min((lv), MAX_SKILL_LEVEL) - 1)
+#define skill_adjust_over_level(val, lv, max_lv) ((val) > 1 ? ((val) + ((lv) - (max_lv)) / 2) : (val))
-#define skill_get(var,id) do { skill->chk(&(id)); if(!(id)) return 0; return (var); } while(0)
-#define skill_get2(var,id,lv) do { \
- skill->chk(&(id)); \
- if(!(id)) return 0; \
- if( (lv) > MAX_SKILL_LEVEL && (var) > 1 ) { \
- 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->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 ) {
+
+int skill_get_hit(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].hit;
+}
+
+int skill_get_inf(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return INF_NONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(INF_NONE, idx != 0);
+ return skill->dbs->db[idx].inf;
+}
+
+int skill_get_ele(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return ELE_NEUTRAL;
+ idx = skill->get_index(skill_id);
+ Assert_retr(ELE_NEUTRAL, idx != 0);
+ Assert_retr(ELE_NEUTRAL, skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].element[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].element[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_nk(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return NK_NONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(NK_NONE, idx != 0);
+ return skill->dbs->db[idx].nk;
+}
+
+int skill_get_max(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].max;
+}
+
+int skill_get_range(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].range[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].range[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_splash(int skill_id, int skill_lv)
+{
+ int idx, val;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ val = skill->dbs->db[idx].splash[skill_get_lvl_idx(skill_lv)];
+ if (val < 0) {
+ val = AREA_SIZE;
+ }
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return val;
+}
+
+int skill_get_hp(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].hp[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].hp[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_sp(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].sp[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].sp[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_hp_rate(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].hp_rate[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].hp_rate[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_sp_rate(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].sp_rate[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].sp_rate[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_state(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return ST_NONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(ST_NONE, idx != 0);
+ return skill->dbs->db[idx].state;
+}
+
+int skill_get_spiritball(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].spiritball[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].spiritball[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_itemid(int skill_id, int item_idx)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(item_idx >= 0 && item_idx < MAX_SKILL_ITEM_REQUIRE);
+ return skill->dbs->db[idx].itemid[item_idx];
+}
+
+int skill_get_itemqty(int skill_id, int item_idx)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(item_idx >= 0 && item_idx < MAX_SKILL_ITEM_REQUIRE);
+ return skill->dbs->db[idx].amount[item_idx];
+}
+
+int skill_get_zeny(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].zeny[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].zeny[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_num(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].num[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].num[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_cast(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].cast[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].cast[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_delay(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].delay[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].delay[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_walkdelay(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].walkdelay[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].walkdelay[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_time(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].upkeep_time[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].upkeep_time[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_time2(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].upkeep_time2[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].upkeep_time2[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_castdef(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].cast_def_rate;
+}
+
+int skill_get_weapontype(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].weapon;
+}
+
+int skill_get_ammotype(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].ammo;
+}
+
+int skill_get_ammo_qty(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].ammo_qty[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].ammo_qty[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_inf2(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return INF2_NONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(INF2_NONE, idx != 0);
+ return skill->dbs->db[idx].inf2;
+}
+
+int skill_get_castcancel(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].castcancel;
+}
+
+int skill_get_maxcount(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].maxcount[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].maxcount[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_blewcount(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].blewcount[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].blewcount[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_mhp(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].mhp[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].mhp[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_castnodex(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].castnodex[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].castnodex[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_delaynodex(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].delaynodex[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].delaynodex[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_type(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return BF_NONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(BF_NONE, idx != 0);
+ return skill->dbs->db[idx].skill_type;
+}
+
+int skill_get_unit_id(int skill_id, int flag)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(flag >= 0 && flag < ARRAYLENGTH(skill->dbs->db[0].unit_id));
+ return skill->dbs->db[idx].unit_id[flag];
+}
+
+int skill_get_unit_interval(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ return skill->dbs->db[idx].unit_interval;
+}
+
+int skill_get_unit_range(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].unit_range[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].unit_range[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_unit_target(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return BCT_NOONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(BCT_NOONE, idx != 0);
+ return skill->dbs->db[idx].unit_target & BCT_ALL;
+}
+
+int skill_get_unit_bl_target(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return BL_NUL;
+ idx = skill->get_index(skill_id);
+ Assert_retr(BL_NUL, idx != 0);
+ return skill->dbs->db[idx].unit_target & BL_ALL;
+}
+
+int skill_get_unit_flag(int skill_id)
+{
+ int idx;
+ if (skill_id == 0)
+ return UF_NONE;
+ idx = skill->get_index(skill_id);
+ Assert_retr(UF_NONE, idx != 0);
+ return skill->dbs->db[idx].unit_flag;
+}
+
+int skill_get_unit_layout_type(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].unit_layout_type[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].unit_layout_type[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_cooldown(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].cooldown[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].cooldown[skill_get_lvl_idx(skill_lv)];
+}
+
+int skill_get_fixed_cast(int skill_id, int skill_lv)
+{
+ int idx;
+ if (skill_id == 0)
+ return 0;
+ idx = skill->get_index(skill_id);
+ Assert_ret(idx != 0);
+ Assert_ret(skill_lv > 0);
#ifdef RENEWAL_CAST
- Assert_ret(skill_lv > 0); skill_get2 (skill->dbs->db[skill_id].fixed_cast[skill_glv(skill_lv-1)], skill_id, skill_lv);
+ if (skill_lv > MAX_SKILL_LEVEL) {
+ int val = skill->dbs->db[idx].fixed_cast[skill_get_lvl_idx(skill_lv)];
+ return skill_adjust_over_level(val, skill_lv, skill->dbs->db[idx].max);
+ }
+ return skill->dbs->db[idx].fixed_cast[skill_get_lvl_idx(skill_lv)];
#else
return 0;
#endif
}
-int skill_tree_get_max(uint16 skill_id, int class)
+int skill_tree_get_max(int skill_id, int class)
{
int i;
int class_idx = pc->class2idx(class);
@@ -231,7 +736,7 @@ int skill_tree_get_max(uint16 skill_id, int class)
return skill->get_max(skill_id);
}
-int skill_get_casttype(uint16 skill_id)
+int skill_get_casttype(int skill_id)
{
int inf = skill->get_inf(skill_id);
if (inf&(INF_GROUND_SKILL))
@@ -248,7 +753,7 @@ int skill_get_casttype(uint16 skill_id)
return CAST_DAMAGE;
}
-int skill_get_casttype2(uint16 index)
+int skill_get_casttype2(int index)
{
int inf;
Assert_retr(CAST_NODAMAGE, index < MAX_SKILL_DB);
@@ -268,7 +773,7 @@ int skill_get_casttype2(uint16 index)
}
//Returns actual skill range taking into account attack range and AC_OWL [Skotlex]
-int skill_get_range2(struct block_list *bl, uint16 skill_id, uint16 skill_lv)
+int skill_get_range2(struct block_list *bl, int skill_id, int skill_lv)
{
int range;
struct map_session_data *sd = BL_CAST(BL_PC, bl);
@@ -3175,8 +3680,8 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv,
struct status_data *st;
struct map_session_data *sd = NULL;
int i, hp, sp, hp_rate, sp_rate, state, mhp;
- uint16 idx;
- int itemid[MAX_SKILL_ITEM_REQUIRE],amount[ARRAYLENGTH(itemid)],index[ARRAYLENGTH(itemid)];
+ int idx;
+ int itemid[MAX_SKILL_ITEM_REQUIRE], amount[MAX_SKILL_ITEM_REQUIRE], index[MAX_SKILL_ITEM_REQUIRE];
if( lv < 1 || lv > MAX_SKILL_LEVEL )
return 0;
@@ -3192,8 +3697,7 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv,
return 0;
// Requirements
- for( i = 0; i < ARRAYLENGTH(itemid); i++ )
- {
+ for (i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++) {
itemid[i] = skill->dbs->db[idx].itemid[i];
amount[i] = skill->dbs->db[idx].amount[i];
}
@@ -6666,7 +7170,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->dbs->db[skill_id].desc);
+ snprintf(temp, sizeof(temp), "%s : %s !!", md->name, skill->get_desc(skill_id));
clif->disp_overhead(&md->bl,temp);
}
break;
@@ -6865,7 +7369,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->dbs->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded
+ status_zap(src, 0, skill->get_sp(skill_id, skill_lv)); // consume sp only if succeeded
}
break;
@@ -7041,21 +7545,22 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
return 1;
}
if( sd ) {
- int x,bonus=100, potion = min(500+skill_lv,505);
- x = skill_lv%11 - 1;
- 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) {
+ int bonus = 100, potion = min(500+skill_lv,505);
+ int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ int item_id = skill->get_itemid(skill_id, item_idx);
+ int inventory_idx = pc->search_inventory(sd, item_id);
+ if (inventory_idx == INDEX_NOT_FOUND || item_id <= 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->dbs->db[skill_id].amount[x]) {
+ if (sd->inventory_data[inventory_idx] == NULL || sd->status.inventory[inventory_idx].amount < skill->get_itemqty(skill_id, item_idx)) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
map->freeblock_unlock();
return 1;
}
if( skill_id == AM_BERSERKPITCHER ) {
- if (dstsd && dstsd->status.base_level < sd->inventory_data[i]->elv) {
+ if (dstsd != NULL && dstsd->status.base_level < sd->inventory_data[inventory_idx]->elv) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
map->freeblock_unlock();
return 1;
@@ -7064,7 +7569,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
script->potion_flag = 1;
script->potion_hp = script->potion_sp = script->potion_per_hp = script->potion_per_sp = 0;
script->potion_target = bl->id;
- script->run_use_script(sd, sd->inventory_data[i], 0);
+ script->run_use_script(sd, sd->inventory_data[inventory_idx], 0);
script->potion_flag = script->potion_target = 0;
if( sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_ALCHEMIST )
bonus += sd->status.base_level;
@@ -7384,7 +7889,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
maxlv = skill_lv - 4;
}
else if(skill_lv >=2) {
- int i = rnd()%3;
+ int i = rnd() % ARRAYLENGTH(spellarray);
spellid = spellarray[i];
maxlv = skill_lv - 1;
}
@@ -7591,14 +8096,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->dbs->db[skill_id].hp_rate[skill_lv-1];
+ int hp_rate = skill_lv == 0 ? 0 : skill->get_hp_rate(skill_id, skill_lv);
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->dbs->db[skill_id].sp_rate[skill_lv-1];
+ int sp_rate = skill_lv == 0 ? 0 : skill->get_sp_rate(skill_id, skill_lv);
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);
}
@@ -7661,16 +8166,17 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( battle_config.skill_removetrap_type ) {
int i;
// get back all items used to deploy the trap
- for( i = 0; i < 10; i++ ) {
- if( skill->dbs->db[su->group->skill_id].itemid[i] > 0 ) {
+ for (i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++) {
+ int nameid = skill->get_itemid(su->group->skill_id, i);
+ if (nameid > 0) {
int success;
- struct item item_tmp;
- memset(&item_tmp,0,sizeof(item_tmp));
- item_tmp.nameid = skill->dbs->db[su->group->skill_id].itemid[i];
+ struct item item_tmp = { 0 };
+ int amount = skill->get_itemqty(su->group->skill_id, i);
+ item_tmp.nameid = nameid;
item_tmp.identify = 1;
- if (item_tmp.nameid && (success=pc->additem(sd,&item_tmp,skill->dbs->db[su->group->skill_id].amount[i],LOG_TYPE_SKILL)) != 0) {
+ if ((success = pc->additem(sd, &item_tmp, amount, LOG_TYPE_SKILL)) != 0) {
clif->additem(sd,0,0,success);
- map->addflooritem(&sd->bl, &item_tmp, skill->dbs->db[su->group->skill_id].amount[i], sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
+ map->addflooritem(&sd->bl, &item_tmp, amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
}
}
}
@@ -7902,7 +8408,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->dbs->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded [Inkfish]
+ status_zap(src, 0, skill->get_sp(skill_id, skill_lv)); // consume sp only if succeeded [Inkfish]
do {
int eff = rnd() % 14;
if( eff == 5 )
@@ -7926,7 +8432,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
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);
+ skill->break_equip(bl, where[rnd() % ARRAYLENGTH(where)], 10000, BCT_ENEMY);
}
}
break;
@@ -7947,7 +8453,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case 7: // stop freeze or stoned
{
enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE };
- sc_start(src,bl,sc[rnd()%3],100,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,sc[rnd() % ARRAYLENGTH(sc)],100,skill_lv,skill->get_time2(skill_id,skill_lv));
}
break;
case 8: // curse coma and poison
@@ -10837,10 +11343,13 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
// Slim Pitcher [Celest]
case CR_SLIMPITCHER:
if (sd) {
- int i = skill_lv%11 - 1;
- 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]
+ int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ int item_id = skill->get_itemid(skill_id, item_idx);
+ int inventory_idx = pc->search_inventory(sd, item_id);
+ int bonus;
+ if (inventory_idx == INDEX_NOT_FOUND || item_id <= 0
+ || sd->inventory_data[inventory_idx] == NULL
+ || sd->status.inventory[inventory_idx].amount < skill->get_itemqty(skill_id, item_idx)
) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 1;
@@ -10848,44 +11357,44 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
script->potion_flag = 1;
script->potion_hp = 0;
script->potion_sp = 0;
- script->run_use_script(sd, sd->inventory_data[j], 0);
+ script->run_use_script(sd, sd->inventory_data[inventory_idx], 0);
script->potion_flag = 0;
//Apply skill bonuses
- i = pc->checkskill(sd,CR_SLIMPITCHER)*10
+ bonus = pc->checkskill(sd,CR_SLIMPITCHER)*10
+ pc->checkskill(sd,AM_POTIONPITCHER)*10
+ pc->checkskill(sd,AM_LEARNINGPOTION)*5
+ pc->skillheal_bonus(sd, skill_id);
- script->potion_hp = script->potion_hp * (100+i)/100;
- script->potion_sp = script->potion_sp * (100+i)/100;
+ script->potion_hp = script->potion_hp * (100 + bonus) / 100;
+ script->potion_sp = script->potion_sp * (100 + bonus) / 100;
- if(script->potion_hp > 0 || script->potion_sp > 0) {
- i = skill->get_splash(skill_id, skill_lv);
+ if (script->potion_hp > 0 || script->potion_sp > 0) {
+ r = skill->get_splash(skill_id, skill_lv);
map->foreachinarea(skill->area_sub,
- src->m,x-i,y-i,x+i,y+i,BL_CHAR,
- src,skill_id,skill_lv,tick,flag|BCT_PARTY|BCT_GUILD|1,
+ src->m, x - r, y - r, x + r, y + r, BL_CHAR,
+ src, skill_id, skill_lv, tick, flag|BCT_PARTY|BCT_GUILD|1,
skill->castend_nodamage_id);
}
} else {
- int i = skill_lv%11 - 1;
- struct item_data *item;
- i = skill->dbs->db[skill_id].itemid[i];
- item = itemdb->search(i);
+ int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ int item_id = skill->get_itemid(skill_id, item_idx);
+ struct item_data *item = itemdb->search(item_id);
+ int bonus;
script->potion_flag = 1;
script->potion_hp = 0;
script->potion_sp = 0;
script->run(item->script,0,src->id,0);
script->potion_flag = 0;
- i = skill->get_max(CR_SLIMPITCHER)*10;
+ bonus = skill->get_max(CR_SLIMPITCHER)*10;
- script->potion_hp = script->potion_hp * (100+i)/100;
- script->potion_sp = script->potion_sp * (100+i)/100;
+ script->potion_hp = script->potion_hp * (100 + bonus)/100;
+ script->potion_sp = script->potion_sp * (100 + bonus)/100;
- if(script->potion_hp > 0 || script->potion_sp > 0) {
- i = skill->get_splash(skill_id, skill_lv);
+ if (script->potion_hp > 0 || script->potion_sp > 0) {
+ r = skill->get_splash(skill_id, skill_lv);
map->foreachinarea(skill->area_sub,
- src->m,x-i,y-i,x+i,y+i,BL_CHAR,
- src,skill_id,skill_lv,tick,flag|BCT_PARTY|BCT_GUILD|1,
+ src->m, x - r, y - r, x + r, y + r, BL_CHAR,
+ src, skill_id, skill_lv, tick, flag|BCT_PARTY|BCT_GUILD|1,
skill->castend_nodamage_id);
}
}
@@ -11636,27 +12145,27 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
int element[5]={ELE_WIND,ELE_DARK,ELE_POISON,ELE_WATER,ELE_FIRE};
val1 = st->rhw.ele;
- if (!val1)
- val1=element[rnd()%5];
+ if (val1 == ELE_NEUTRAL)
+ val1 = element[rnd() % ARRAYLENGTH(element)];
- switch (val1)
- {
+ switch (val1) {
case ELE_FIRE:
- subunt++;
- FALLTHROUGH
+ subunt = 4;
+ break;
case ELE_WATER:
- subunt++;
- FALLTHROUGH
+ subunt = 3;
+ break;
case ELE_POISON:
- subunt++;
- FALLTHROUGH
+ subunt = 2;
+ break;
case ELE_DARK:
- subunt++;
- FALLTHROUGH
+ subunt = 1;
+ break;
case ELE_WIND:
+ subunt = 0;
break;
default:
- subunt=rnd()%5;
+ subunt = rnd() % 5;
break;
}
@@ -14824,7 +15333,8 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
}
for( i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++ ) {
- if( (skill_id == AM_POTIONPITCHER || skill_id == CR_SLIMPITCHER || skill_id == CR_CULTIVATION) && i != skill_lv%11 - 1 )
+ int item_idx = (skill_lv - 1) % MAX_SKILL_ITEM_REQUIRE;
+ if ((skill_id == AM_POTIONPITCHER || skill_id == CR_SLIMPITCHER || skill_id == CR_CULTIVATION) && i != item_idx)
continue;
switch( skill_id ) {
@@ -16618,15 +17128,16 @@ struct skill_unit_group* skill_id2group(int group_id)
/// Fatal error if nothing is available.
int skill_get_new_group_id(void)
{
- if( skill->unit_group_newid >= MAX_SKILL_DB && skill->id2group(skill->unit_group_newid) == NULL )
+ if (skill->unit_group_newid > MAX_SKILL_ID && skill->id2group(skill->unit_group_newid) == NULL)
return skill->unit_group_newid++;// available
- {// find next id
+
+ {
+ // find next id
int base_id = skill->unit_group_newid;
- while( base_id != ++skill->unit_group_newid )
- {
- if( skill->unit_group_newid < MAX_SKILL_DB )
- skill->unit_group_newid = MAX_SKILL_DB;
- if( skill->id2group(skill->unit_group_newid) == NULL )
+ while (base_id != ++skill->unit_group_newid) {
+ if (skill->unit_group_newid <= MAX_SKILL_ID)
+ skill->unit_group_newid = MAX_SKILL_ID + 1;
+ if (skill->id2group(skill->unit_group_newid) == NULL)
return skill->unit_group_newid++;// available
}
// full loop, nothing available
@@ -17719,7 +18230,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
int difficulty = 30 + rnd()%120; // Random number between (30 ~ 150)
make_per = sd->status.job_level / 4 + st->luk / 2 + st->dex / 3; // (Caster?s Job Level / 4) + (Caster?s LUK / 2) + (Caster?s DEX / 3)
- qty = ~(5 + rnd()%5) + 1;
+ qty = ~(5 + rnd()%5) + 1; // FIXME[Haru]: This smells, if anyone knows the intent, please rewrite the expression in a more clear form.
switch(nameid){// difficulty factor
case ITEMID_APPLE_BOMB:
@@ -17755,7 +18266,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
qty = 5;
if( qty < 0 || (skill_lv == 1 && make_per < difficulty)){
- qty = ~qty + 1;
+ qty = ~qty + 1; // FIXME[Haru]: This smells. If anyone knows the intent, please rewrite the expression in a more clear form.
make_per = 0;
}else
make_per = 10000;
@@ -18012,7 +18523,7 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
int rate = rnd()%500;
memset(&tmp_item,0,sizeof(tmp_item));
if( rate < 50) i = 4;
- else if( rate < 100) i = 2+rnd()%1;
+ else if( rate < 100) i = 2+rnd()%1; // FIXME[Haru]: This '%1' is certainly not intended. If anyone knows the purpose, please rewrite this code.
else if( rate < 250 ) i = 1;
else if( rate < 500 ) i = 0;
tmp_item.nameid = compensation[i];
@@ -18435,7 +18946,7 @@ int skill_blockpc_end(int tid, int64 tick, int id, intptr_t data)
struct map_session_data *sd = map->id2sd(id);
struct skill_cd * cd = NULL;
- if (data <= 0 || data >= MAX_SKILL)
+ if (data <= 0 || data >= MAX_SKILL_DB)
return 0;
if (!sd || !sd->blockskill[data])
return 0;
@@ -18571,7 +19082,7 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick)
int skill_blockhomun_end(int tid, int64 tick, int id, intptr_t data)
{
struct homun_data *hd = map->id2hd(id);
- if (data <= 0 || data >= MAX_SKILL)
+ if (data <= 0 || data >= MAX_SKILL_DB)
return 0;
if (hd != NULL)
hd->blockskill[data] = 0;
@@ -18600,7 +19111,7 @@ int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick)
int skill_blockmerc_end(int tid, int64 tick, int id, intptr_t data)
{
struct mercenary_data *md = map->id2mc(id);
- if (data <= 0 || data >= MAX_SKILL)
+ if (data <= 0 || data >= MAX_SKILL_DB)
return 0;
if (md != NULL)
md->blockskill[data] = 0;
@@ -19651,6 +20162,12 @@ void skill_validate_skillinfo(struct config_setting_t *conf, struct s_skill_db *
} else {
sk->inf2 &= ~INF2_FREE_CAST_REDUCED;
}
+ } else if (strcmpi(type, "ShowSkillScale") == 0) {
+ if (on) {
+ sk->inf2 |= INF2_SHOW_SKILL_SCALE;
+ } else {
+ sk->inf2 &= ~INF2_SHOW_SKILL_SCALE;
+ }
} else if (strcmpi(type, "None") != 0) {
skilldb_invalid_error(type, config_setting_name(t), sk->nameid);
}
@@ -20477,7 +20994,7 @@ bool skill_read_skilldb(const char *filename)
struct config_setting_t *sk, *conf;
char filepath[256];
int count=0, index=0;
- bool duplicate[MAX_SKILL] = {0};
+ bool duplicate[MAX_SKILL_DB] = {0};
nullpo_retr(false, filename);
@@ -20902,8 +21419,12 @@ void skill_defaults(void)
skill->get_hp = skill_get_hp;
skill->get_mhp = skill_get_mhp;
skill->get_sp = skill_get_sp;
+ skill->get_hp_rate = skill_get_hp_rate;
+ skill->get_sp_rate = skill_get_sp_rate;
skill->get_state = skill_get_state;
skill->get_spiritball = skill_get_spiritball;
+ skill->get_itemid = skill_get_itemid;
+ skill->get_itemqty = skill_get_itemqty;
skill->get_zeny = skill_get_zeny;
skill->get_num = skill_get_num;
skill->get_cast = skill_get_cast;
@@ -20932,7 +21453,6 @@ void skill_defaults(void)
skill->tree_get_max = skill_tree_get_max;
skill->get_name = skill_get_name;
skill->get_desc = skill_get_desc;
- skill->chk = skill_chk;
skill->get_casttype = skill_get_casttype;
skill->get_casttype2 = skill_get_casttype2;
skill->is_combo = skill_is_combo;
diff --git a/src/map/skill.h b/src/map/skill.h
index bba440107..1e00e488f 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -25,7 +25,7 @@
#include "map/status.h" // enum sc_type
#include "common/hercules.h"
#include "common/db.h"
-#include "common/mmo.h" // MAX_SKILL, struct square
+#include "common/mmo.h" // MAX_SKILL_DB, struct square
/**
* Declarations
@@ -43,7 +43,6 @@ struct status_change_entry;
/**
* Defines
**/
-#define MAX_SKILL_DB MAX_SKILL
#define MAX_SKILL_PRODUCE_DB 270
#define MAX_PRODUCE_RESOURCE 10
#define MAX_SKILL_ARROW_DB 140
@@ -77,6 +76,7 @@ struct status_change_entry;
//Constants to identify the skill's inf value:
enum e_skill_inf {
+ INF_NONE = 0x00,
INF_ATTACK_SKILL = 0x01,
INF_GROUND_SKILL = 0x02,
INF_SELF_SKILL = 0x04, // Skills casted on self where target is automatically chosen
@@ -89,6 +89,7 @@ enum e_skill_inf {
//The NK value applies only to non INF_GROUND_SKILL skills
//when determining skill castend function to invoke.
enum e_skill_nk {
+ NK_NONE = 0x00,
NK_NO_DAMAGE = 0x01,
NK_SPLASH = 0x02|0x04, // 0x4 = splash & split
NK_SPLASH_ONLY = 0x02,
@@ -103,6 +104,7 @@ enum e_skill_nk {
//A skill with 3 would be no damage + splash: area of effect.
//Constants to identify a skill's inf2 value.
enum e_skill_inf2 {
+ INF2_NONE = 0x00000,
INF2_QUEST_SKILL = 0x00001,
INF2_NPC_SKILL = 0x00002, // NPC skills are those that players can't have in their skill tree.
INF2_WEDDING_SKILL = 0x00004,
@@ -120,6 +122,7 @@ enum e_skill_inf2 {
INF2_CHORUS_SKILL = 0x04000, // Chorus skill
INF2_FREE_CAST_NORMAL = 0x08000,
INF2_FREE_CAST_REDUCED = 0x10000,
+ INF2_SHOW_SKILL_SCALE = 0x20000,
};
@@ -132,6 +135,7 @@ enum e_skill_display {
};
enum {
+ UF_NONE = 0x0000,
UF_DEFNOTENEMY = 0x0001, // If 'defunit_not_enemy' is set, the target is changed to 'friend'
UF_NOREITERATION = 0x0002, // Spell cannot be stacked
UF_NOFOOTSET = 0x0004, // Spell cannot be cast near/on targets
@@ -158,7 +162,7 @@ enum wl_spheres {
};
enum {
- ST_NONE,
+ ST_NONE = 0,
ST_HIDING,
ST_CLOAKING,
ST_HIDDEN,
@@ -1930,54 +1934,56 @@ struct skill_interface {
int unit_temp[20]; // temporary storage for tracking skill unit skill ids as players move in/out of them
int unit_group_newid;
/* accesssors */
- int (*get_index) ( uint16 skill_id );
- int (*get_type) ( uint16 skill_id );
- int (*get_hit) ( uint16 skill_id );
- int (*get_inf) ( uint16 skill_id );
- int (*get_ele) ( uint16 skill_id, uint16 skill_lv );
- int (*get_nk) ( uint16 skill_id );
- int (*get_max) ( uint16 skill_id );
- int (*get_range) ( uint16 skill_id, uint16 skill_lv );
- int (*get_range2) (struct block_list *bl, uint16 skill_id, uint16 skill_lv);
- int (*get_splash) ( uint16 skill_id, uint16 skill_lv );
- int (*get_hp) ( uint16 skill_id, uint16 skill_lv );
- int (*get_mhp) ( uint16 skill_id, uint16 skill_lv );
- int (*get_sp) ( uint16 skill_id, uint16 skill_lv );
- int (*get_state) (uint16 skill_id);
- int (*get_spiritball) (uint16 skill_id, uint16 skill_lv);
- int (*get_zeny) ( uint16 skill_id, uint16 skill_lv );
- int (*get_num) ( uint16 skill_id, uint16 skill_lv );
- int (*get_cast) ( uint16 skill_id, uint16 skill_lv );
- int (*get_delay) ( uint16 skill_id, uint16 skill_lv );
- int (*get_walkdelay) ( uint16 skill_id, uint16 skill_lv );
- int (*get_time) ( uint16 skill_id, uint16 skill_lv );
- int (*get_time2) ( uint16 skill_id, uint16 skill_lv );
- int (*get_castnodex) ( uint16 skill_id, uint16 skill_lv );
- int (*get_delaynodex) ( uint16 skill_id ,uint16 skill_lv );
- int (*get_castdef) ( uint16 skill_id );
- int (*get_weapontype) ( uint16 skill_id );
- int (*get_ammotype) ( uint16 skill_id );
- int (*get_ammo_qty) ( uint16 skill_id, uint16 skill_lv );
- int (*get_unit_id) (uint16 skill_id,int flag);
- int (*get_inf2) ( uint16 skill_id );
- int (*get_castcancel) ( uint16 skill_id );
- int (*get_maxcount) ( uint16 skill_id, uint16 skill_lv );
- int (*get_blewcount) ( uint16 skill_id, uint16 skill_lv );
- int (*get_unit_flag) ( uint16 skill_id );
- int (*get_unit_target) ( uint16 skill_id );
- int (*get_unit_interval) ( uint16 skill_id );
- int (*get_unit_bl_target) ( uint16 skill_id );
- int (*get_unit_layout_type) ( uint16 skill_id ,uint16 skill_lv );
- int (*get_unit_range) ( uint16 skill_id, uint16 skill_lv );
- int (*get_cooldown) ( uint16 skill_id, uint16 skill_lv );
- int (*tree_get_max) (uint16 skill_id, int class);
- const char *(*get_name) ( uint16 skill_id );
- const char *(*get_desc) ( uint16 skill_id );
- /* check */
- void (*chk) (uint16* skill_id);
+ int (*get_index) (int skill_id);
+ int (*get_type) (int skill_id);
+ int (*get_hit) (int skill_id);
+ int (*get_inf) (int skill_id);
+ int (*get_ele) (int skill_id, int skill_lv);
+ int (*get_nk) (int skill_id);
+ int (*get_max) (int skill_id);
+ int (*get_range) (int skill_id, int skill_lv);
+ int (*get_range2) (struct block_list *bl, int skill_id, int skill_lv);
+ int (*get_splash) (int skill_id, int skill_lv);
+ int (*get_hp) (int skill_id, int skill_lv);
+ int (*get_mhp) (int skill_id, int skill_lv);
+ int (*get_sp) (int skill_id, int skill_lv);
+ int (*get_hp_rate) (int skill_id, int skill_lv);
+ int (*get_sp_rate) (int skill_id, int skill_lv);
+ int (*get_state) (int skill_id);
+ int (*get_spiritball) (int skill_id, int skill_lv);
+ int (*get_itemid) (int skill_id, int item_idx);
+ int (*get_itemqty) (int skill_id, int item_idx);
+ int (*get_zeny) (int skill_id, int skill_lv);
+ int (*get_num) (int skill_id, int skill_lv);
+ int (*get_cast) (int skill_id, int skill_lv);
+ int (*get_delay) (int skill_id, int skill_lv);
+ int (*get_walkdelay) (int skill_id, int skill_lv);
+ int (*get_time) (int skill_id, int skill_lv);
+ int (*get_time2) (int skill_id, int skill_lv);
+ int (*get_castnodex) (int skill_id, int skill_lv);
+ int (*get_delaynodex) (int skill_id, int skill_lv);
+ int (*get_castdef) (int skill_id);
+ int (*get_weapontype) (int skill_id);
+ int (*get_ammotype) (int skill_id);
+ int (*get_ammo_qty) (int skill_id, int skill_lv);
+ int (*get_unit_id) (int skill_id, int flag);
+ int (*get_inf2) (int skill_id);
+ int (*get_castcancel) (int skill_id);
+ int (*get_maxcount) (int skill_id, int skill_lv);
+ int (*get_blewcount) (int skill_id, int skill_lv);
+ int (*get_unit_flag) (int skill_id);
+ int (*get_unit_target) (int skill_id);
+ int (*get_unit_interval) (int skill_id);
+ int (*get_unit_bl_target) (int skill_id);
+ int (*get_unit_layout_type) (int skill_id, int skill_lv);
+ int (*get_unit_range) (int skill_id, int skill_lv);
+ int (*get_cooldown) (int skill_id, int skill_lv);
+ int (*tree_get_max) (int skill_id, int class);
+ const char *(*get_name) (int skill_id);
+ const char *(*get_desc) (int skill_id);
/* whether its CAST_GROUND, CAST_DAMAGE or CAST_NODAMAGE */
- int (*get_casttype) (uint16 skill_id);
- int (*get_casttype2) (uint16 index);
+ int (*get_casttype) (int skill_id);
+ int (*get_casttype2) (int index);
bool (*is_combo) (int skill_id);
int (*name2id) (const char* name);
int (*isammotype) (struct map_session_data *sd, int skill_id);
@@ -2071,7 +2077,7 @@ struct skill_interface {
int (*check_condition_mob_master_sub) (struct block_list *bl, va_list ap);
void (*brandishspear_first) (struct square *tc, uint8 dir, int16 x, int16 y);
void (*brandishspear_dir) (struct square* tc, uint8 dir, int are);
- int (*get_fixed_cast) ( uint16 skill_id ,uint16 skill_lv );
+ int (*get_fixed_cast) (int skill_id, int skill_lv);
int (*sit_count) (struct block_list *bl, va_list ap);
int (*sit_in) (struct block_list *bl, va_list ap);
int (*sit_out) (struct block_list *bl, va_list ap);
diff --git a/src/map/status.c b/src/map/status.c
index e0893aa36..ddb8c7e6a 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -159,7 +159,7 @@ void initChangeTables(void)
for (i = 0; i < SC_MAX; i++)
status->dbs->IconChangeTable[i] = SI_BLANK;
- for (i = 0; i < MAX_SKILL; i++)
+ for (i = 0; i < MAX_SKILL_DB; i++)
status->dbs->Skill2SCTable[i] = SC_NONE;
for (i = 0; i < SI_MAX; i++)
@@ -2329,7 +2329,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
static int calculating = 0; //Check for recursive call preemption. [Skotlex]
struct status_data *bstatus; // pointer to the player's base status
const struct status_change *sc;
- struct s_skill b_skill[MAX_SKILL]; // previous skill tree
+ struct s_skill b_skill[MAX_SKILL_DB]; // previous skill tree
int b_weight, b_max_weight, b_cart_weight_max, // previous weight
i, k, index, skill_lv,refinedef=0;
int64 i64;
@@ -6809,7 +6809,7 @@ struct view_data *status_get_viewdata(struct block_list *bl)
case BL_PC: return &BL_UCAST(BL_PC, bl)->vd;
case BL_MOB: return BL_UCAST(BL_MOB, bl)->vd;
case BL_PET: return &BL_UCAST(BL_PET, bl)->vd;
- case BL_NPC: return BL_UCAST(BL_NPC, bl)->vd;
+ case BL_NPC: return &BL_UCAST(BL_NPC, bl)->vd;
case BL_HOM: return BL_UCAST(BL_HOM, bl)->vd;
case BL_MER: return BL_UCAST(BL_MER, bl)->vd;
case BL_ELEM: return BL_UCAST(BL_ELEM, bl)->vd;
@@ -6927,10 +6927,14 @@ void status_set_viewdata(struct block_list *bl, int class_)
case BL_NPC:
{
struct npc_data *nd = BL_UCAST(BL_NPC, bl);
- if (vd != NULL)
- nd->vd = vd;
- else
+ if (vd != NULL) {
+ memcpy(&nd->vd, vd, sizeof(struct view_data));
+ } else if (pc->db_checkid(class_)) {
+ memset(&nd->vd, 0, sizeof(struct view_data));
+ nd->vd.class = class_;
+ } else {
ShowError("status_set_viewdata (NPC): No view data for class %d (name=%s)\n", class_, nd->name);
+ }
}
break;
case BL_HOM: //[blackhole89]
diff --git a/src/map/status.h b/src/map/status.h
index a104c66ab..e9c2218e8 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -2257,7 +2257,7 @@ BEGIN_ZEROED_BLOCK; /* Everything within this block will be memset to 0 when sta
int HP_table[CLASS_COUNT][MAX_LEVEL + 1];
int SP_table[CLASS_COUNT][MAX_LEVEL + 1];
int aspd_base[CLASS_COUNT][MAX_SINGLE_WEAPON_TYPE+1]; // +1 for RENEWAL_ASPD
- sc_type Skill2SCTable[MAX_SKILL]; // skill -> status
+ sc_type Skill2SCTable[MAX_SKILL_DB]; // skill -> status
int IconChangeTable[SC_MAX]; // status -> "icon" (icon is a bit of a misnomer, since there exist values with no icon associated)
unsigned int ChangeFlagTable[SC_MAX]; // status -> flags
int SkillChangeTable[SC_MAX]; // status -> skill