summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/char.c23
-rw-r--r--src/common/mmo.h2
-rw-r--r--src/common/utils.h2
-rw-r--r--src/map/Makefile3
-rw-r--r--src/map/atcommand.c163
-rw-r--r--src/map/atcommand.h1
-rw-r--r--src/map/battle.c85
-rw-r--r--src/map/battle.h2
-rw-r--r--src/map/chrif.c17
-rw-r--r--src/map/clif.c52
-rw-r--r--src/map/magic-stmt.c27
-rw-r--r--src/map/magic.c10
-rw-r--r--src/map/map.c13
-rw-r--r--src/map/map.h9
-rw-r--r--src/map/mob.c2
-rw-r--r--src/map/npc.c19
-rw-r--r--src/map/party.c10
-rw-r--r--src/map/pc.c102
-rw-r--r--src/map/script.c110
-rw-r--r--src/map/skill-pools.c165
-rw-r--r--src/map/skill.c77
-rw-r--r--src/map/skill.h64
22 files changed, 755 insertions, 203 deletions
diff --git a/src/char/char.c b/src/char/char.c
index fbf512e..98321ec 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -269,8 +269,8 @@ int mmo_char_tostr(char *str, struct mmo_charstatus *p) {
*(str_p++) = '\t';
for(i = 0; i < MAX_SKILL; i++)
- if (p->skill[i].id && p->skill[i].flag != 1) {
- str_p += sprintf(str_p, "%d,%d ", p->skill[i].id, (p->skill[i].flag == 0) ? p->skill[i].lv : p->skill[i].flag-2);
+ if (p->skill[i].id) {
+ str_p += sprintf(str_p, "%d,%d ", p->skill[i].id, p->skill[i].lv | (p->skill[i].flags << 16));
}
*(str_p++) = '\t';
@@ -506,7 +506,8 @@ int mmo_char_fromstr(char *str, struct mmo_charstatus *p) {
if (sscanf(str + next, "%d,%d%n", &tmp_int[0], &tmp_int[1], &len) != 2)
return -6;
p->skill[tmp_int[0]].id = tmp_int[0];
- p->skill[tmp_int[0]].lv = tmp_int[1];
+ p->skill[tmp_int[0]].lv = tmp_int[1] & 0xffff;
+ p->skill[tmp_int[0]].flags = ((tmp_int[1] >> 16) & 0xffff);
next += len;
if (str[next] == ' ')
next++;
@@ -1660,22 +1661,6 @@ int parse_tologin(int fd) {
} else if (jobclass == 4042 || jobclass == 4043) {
char_dat[i].class = (sex) ? 4042 : 4043;
}
- // remove specifical skills of classes 19, 4020 and 4042
- for(j = 315; j <= 322; j++) {
- if (char_dat[i].skill[j].id > 0 && !char_dat[i].skill[j].flag) {
- char_dat[i].skill_point += char_dat[i].skill[j].lv;
- char_dat[i].skill[j].id = 0;
- char_dat[i].skill[j].lv = 0;
- }
- }
- // remove specifical skills of classes 20, 4021 and 4043
- for(j = 323; j <= 330; j++) {
- if (char_dat[i].skill[j].id > 0 && !char_dat[i].skill[j].flag) {
- char_dat[i].skill_point += char_dat[i].skill[j].lv;
- char_dat[i].skill[j].id = 0;
- char_dat[i].skill[j].lv = 0;
- }
- }
}
// to avoid any problem with equipment and invalid sex, equipment is unequiped.
for (j = 0; j < MAX_INVENTORY; j++) {
diff --git a/src/common/mmo.h b/src/common/mmo.h
index e958f81..1ba3ee4 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -83,7 +83,7 @@ struct point{
};
struct skill {
- unsigned short id,lv,flag;
+ unsigned short id,lv,flags;
};
struct global_reg {
diff --git a/src/common/utils.h b/src/common/utils.h
index 3493808..88d1027 100644
--- a/src/common/utils.h
+++ b/src/common/utils.h
@@ -38,5 +38,5 @@
* MRAND(10), returns 0-9.
* MPRAND(5,10) returns 5-14.
*/
-#define MRAND(mod) (mt_rand() % mod)
+#define MRAND(mod) (int) (mt_random() % (mod))
#define MPRAND(add, mod) add + MRAND(mod)
diff --git a/src/map/Makefile b/src/map/Makefile
index 7fe6876..5e80410 100644
--- a/src/map/Makefile
+++ b/src/map/Makefile
@@ -11,7 +11,7 @@ obj:
COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/grfio.o ../common/db.o ../common/lock.o ../common/nullpo.o ../common/malloc.o ../common/mt_rand.o
LIBS = -lz -lm
-map-server: obj/tmw.o obj/magic-interpreter-lexer.o obj/magic-interpreter-parser.o obj/magic-interpreter-base.o obj/magic-expr.o obj/magic-stmt.o obj/magic.o obj/map.o obj/chrif.o obj/clif.o obj/pc.o obj/npc.o obj/chat.o obj/path.o obj/itemdb.o obj/mob.o obj/script.o obj/storage.o obj/skill.o obj/atcommand.o obj/battle.o obj/intif.o obj/trade.o obj/party.o obj/guild.o $(COMMON_OBJ)
+map-server: obj/tmw.o obj/magic-interpreter-lexer.o obj/magic-interpreter-parser.o obj/magic-interpreter-base.o obj/magic-expr.o obj/magic-stmt.o obj/magic.o obj/map.o obj/chrif.o obj/clif.o obj/pc.o obj/npc.o obj/chat.o obj/path.o obj/itemdb.o obj/mob.o obj/script.o obj/storage.o obj/skill.o obj/skill-pools.o obj/atcommand.o obj/battle.o obj/intif.o obj/trade.o obj/party.o obj/guild.o $(COMMON_OBJ)
$(CC) -o ../../$@ $> $(LIBS)
obj/%.o: %.c
@@ -41,6 +41,7 @@ obj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h
obj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h battle.h ../common/timer.h ../common/socket.h ../common/db.h ../common/mmo.h ../common/lock.h
obj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h ../common/mmo.h ../common/db.h
obj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h ../common/timer.h ../common/mmo.h
+obj/skill-pools.o: skill-pools.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h ../common/timer.h ../common/mmo.h
obj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h ../common/socket.h ../common/timer.h ../common/mmo.h
obj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h guild.h ../common/timer.h ../common/mmo.h
obj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h ../common/socket.h ../common/mmo.h
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index ed213b2..510026b 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -201,8 +201,13 @@ ATCOMMAND_FUNC(log); // [Fate]
ATCOMMAND_FUNC(tee); // [Fate]
ATCOMMAND_FUNC(invisible); // [Fate]
ATCOMMAND_FUNC(visible); // [Fate]
+ATCOMMAND_FUNC(list_nearby); // [Fate]
ATCOMMAND_FUNC(iterate_forward_over_players); // [Fate]
ATCOMMAND_FUNC(iterate_backwards_over_players); // [Fate]
+ATCOMMAND_FUNC(skillpool_info); // [Fate]
+ATCOMMAND_FUNC(skillpool_focus); // [Fate]
+ATCOMMAND_FUNC(skillpool_unfocus); // [Fate]
+ATCOMMAND_FUNC(skill_learn); // [Fate]
ATCOMMAND_FUNC(wgm);
/*==========================================
@@ -334,6 +339,7 @@ static AtCommandInfo atcommand_info[] = {
{ AtCommand_Disablenpc, "@disablenpc", 80, atcommand_disablenpc }, // []
{ AtCommand_ServerTime, "@servertime", 0, atcommand_servertime }, // by Yor
{ AtCommand_CharDelItem, "@chardelitem", 60, atcommand_chardelitem }, // by Yor
+ { AtCommand_ListNearby, "@listnearby", 40, atcommand_list_nearby }, // by Yor
{ AtCommand_Jail, "@jail", 60, atcommand_jail }, // by Yor
{ AtCommand_UnJail, "@unjail", 60, atcommand_unjail }, // by Yor
{ AtCommand_Disguise, "@disguise", 20, atcommand_disguise }, // [Valaris]
@@ -391,6 +397,10 @@ static AtCommandInfo atcommand_info[] = {
{ AtCommand_Visible, "@visible", 60, atcommand_visible }, // [Fate]
{ AtCommand_IterateForward, "@hugo", 60, atcommand_iterate_forward_over_players }, // [Fate]
{ AtCommand_IterateBackward, "@linus", 60, atcommand_iterate_backwards_over_players }, // [Fate]
+ { AtCommand_IterateBackward, "@sp-info", 40, atcommand_skillpool_info }, // [Fate]
+ { AtCommand_IterateBackward, "@sp-focus", 80, atcommand_skillpool_focus }, // [Fate]
+ { AtCommand_IterateBackward, "@sp-unfocus", 80, atcommand_skillpool_unfocus }, // [Fate]
+ { AtCommand_IterateBackward, "@skill-learn", 80, atcommand_skill_learn }, // [Fate]
{ AtCommand_Wgm, "@wgm", 0, atcommand_wgm },
// add new commands before this line
@@ -2606,6 +2616,37 @@ int atcommand_killmonster(
return 0;
}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int atlist_nearby_sub(struct block_list *bl, va_list ap) {
+ char buf[32];
+ int fd = va_arg(ap, int);
+ nullpo_retr(0, bl);
+
+ sprintf (buf, " - \"%s\"", ((struct map_session_data *)bl)->status.name);
+ clif_displaymessage(fd, buf);
+
+ return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_list_nearby(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ clif_displaymessage(fd, "Nearby players:");
+ map_foreachinarea(atlist_nearby_sub, sd->bl.m, sd->bl.x-1, sd->bl.y-1, sd->bl.x+1, sd->bl.x+1, BL_PC, fd);
+
+ return 0;
+}
+
+
/*==========================================
*
*------------------------------------------
@@ -4055,7 +4096,7 @@ int atcommand_lostskill(
if (skill_get_inf2(skill_id) & 0x01) {
if (pc_checkskill(sd, skill_id) > 0) {
sd->status.skill[skill_id].lv = 0;
- sd->status.skill[skill_id].flag = 0;
+ sd->status.skill[skill_id].flags = 0;
clif_skillinfoblock(sd);
clif_displaymessage(fd, msg_table[71]); // You have forgotten the skill.
} else {
@@ -4098,7 +4139,7 @@ int atcommand_charlostskill(
if ((pl_sd = map_nick2sd(character)) != NULL) {
if (pc_checkskill(pl_sd, skill_id) > 0) {
pl_sd->status.skill[skill_id].lv = 0;
- pl_sd->status.skill[skill_id].flag = 0;
+ pl_sd->status.skill[skill_id].flags = 0;
clif_skillinfoblock(pl_sd);
clif_displaymessage(fd, msg_table[202]); // This player has forgotten the skill.
} else {
@@ -6969,7 +7010,7 @@ atcommand_magic_info(const int fd, struct map_session_data* sd,
memset(character, '\0', sizeof(character));
- if (!message || !*message || sscanf(message, "%99[^\n]", character) < 1) {
+ if (!message || !*message || sscanf(message, "%99s", character) < 1) {
clif_displaymessage(fd, "Usage: @magicinfo <char_name>");
return -1;
}
@@ -6998,7 +7039,6 @@ set_skill(struct map_session_data* sd, int i, int level)
{
sd->status.skill[i].id = level? i : 0;
sd->status.skill[i].lv = level;
- sd->status.skill[i].flag = 0;
}
int
@@ -7161,3 +7201,118 @@ int atcommand_wgm(
return 0;
}
+
+int atcommand_skillpool_info(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ char character[100];
+ struct map_session_data *pl_sd;
+
+ if (!message || !*message || sscanf(message, "%99s", character) < 1) {
+ clif_displaymessage(fd, "Usage: @sp-info <char_name>");
+ return -1;
+ }
+
+ if ((pl_sd = map_nick2sd(character)) != NULL) {
+ char buf[200];
+ int pool_skills[MAX_SKILL_POOL];
+ int pool_skills_nr = skill_pool(pl_sd, pool_skills);
+ int i;
+
+ sprintf(buf, "Active skills %d out of %d for %s:", pool_skills_nr, skill_pool_max(pl_sd), character);
+ clif_displaymessage(fd, buf);
+ for (i = 0; i < pool_skills_nr; ++i) {
+ sprintf(buf, " - %s [%d]: power %d", skill_name(pool_skills[i]), pool_skills[i], skill_power(pl_sd, pool_skills[i]));
+ clif_displaymessage(fd, buf);
+ }
+
+ sprintf(buf, "Learned skills out of %d for %s:", skill_pool_skills_size, character);
+ clif_displaymessage(fd, buf);
+
+ for (i = 0; i < skill_pool_skills_size; ++i) {
+ char *name = skill_name(skill_pool_skills[i]);
+ int lvl = pl_sd->status.skill[skill_pool_skills[i]].lv;
+
+ if (lvl) {
+ sprintf(buf, " - %s [%d]: lvl %d", name, skill_pool_skills[i], lvl);
+ clif_displaymessage(fd, buf);
+ }
+ }
+
+ } else
+ clif_displaymessage(fd, "Character not found.");
+
+
+ return 0;
+}
+
+int atcommand_skillpool_focus(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ char character[100];
+ int skill;
+ struct map_session_data *pl_sd;
+
+ if (!message || !*message || sscanf(message, "%d %99[^\n]", &skill, character) < 1) {
+ clif_displaymessage(fd, "Usage: @sp-focus <skill-nr> <char_name>");
+ return -1;
+ }
+
+ if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if (skill_pool_activate(pl_sd, skill))
+ clif_displaymessage(fd, "Activation failed.");
+ else
+ clif_displaymessage(fd, "Activation successful.");
+ } else
+ clif_displaymessage(fd, "Character not found.");
+
+ return 0;
+}
+
+int atcommand_skillpool_unfocus(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ char character[100];
+ int skill;
+ struct map_session_data *pl_sd;
+
+ if (!message || !*message || sscanf(message, "%d %99[^\n]", &skill, character) < 1) {
+ clif_displaymessage(fd, "Usage: @sp-unfocus <skill-nr> <char_name>");
+ return -1;
+ }
+
+ if ((pl_sd = map_nick2sd(character)) != NULL) {
+ if (skill_pool_deactivate(pl_sd, skill))
+ clif_displaymessage(fd, "Deactivation failed.");
+ else
+ clif_displaymessage(fd, "Deactivation successful.");
+ } else
+ clif_displaymessage(fd, "Character not found.");
+
+ return 0;
+}
+
+int atcommand_skill_learn(
+ const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ char character[100];
+ int skill, level;
+ struct map_session_data *pl_sd;
+
+ if (!message || !*message || sscanf(message, "%d %d %99[^\n]", &skill, &level, character) < 1) {
+ clif_displaymessage(fd, "Usage: @skill-learn <skill-nr> <level> <char_name>");
+ return -1;
+ }
+
+ if ((pl_sd = map_nick2sd(character)) != NULL) {
+ set_skill(pl_sd, skill, level);
+ clif_skillinfoblock(pl_sd);
+ } else
+ clif_displaymessage(fd, "Character not found.");
+
+ return 0;
+}
diff --git a/src/map/atcommand.h b/src/map/atcommand.h
index df996b6..5e72b1f 100644
--- a/src/map/atcommand.h
+++ b/src/map/atcommand.h
@@ -182,6 +182,7 @@ enum AtCommandType {
AtCommand_IterateForward,
AtCommand_IterateBackward,
AtCommand_Wgm,
+ AtCommand_ListNearby, // [fate]
// end
AtCommand_Unknown,
AtCommand_MAX
diff --git a/src/map/battle.c b/src/map/battle.c
index ebc395d..177c63e 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -381,6 +381,10 @@ int battle_get_flee(struct block_list *bl)
flee += flee*(sc_data[SC_WINDWALK].val2)/100;
if(sc_data[SC_SPIDERWEB].timer!=-1 && bl->type != BL_PC) //スパイダーウェブ
flee -= flee*50/100;
+
+ if (battle_is_unarmed(bl))
+ flee += (skill_power_bl(bl, TMW_BRAWLING) >> 3); // +25 for 200
+ flee += skill_power_bl(bl, TMW_SPEED) >> 3;
}
if(flee < 1) flee = 1;
return flee;
@@ -412,6 +416,9 @@ int battle_get_hit(struct block_list *bl)
hit += 3*(sc_data[SC_TRUESIGHT].val1);
if(sc_data[SC_CONCENTRATION].timer!=-1 && bl->type != BL_PC) //コンセントレーション
hit += (hit*(10*(sc_data[SC_CONCENTRATION].val1)))/100;
+
+ if (battle_is_unarmed(bl))
+ hit += (skill_power_bl(bl, TMW_BRAWLING) >> 4); // +12 for 200
}
if(hit < 1) hit = 1;
return hit;
@@ -439,6 +446,10 @@ int battle_get_flee2(struct block_list *bl)
if(sc_data[SC_WHISTLE].timer!=-1 && bl->type != BL_PC)
flee2 += (sc_data[SC_WHISTLE].val1+sc_data[SC_WHISTLE].val2
+(sc_data[SC_WHISTLE].val3&0xffff))*10;
+
+ if (battle_is_unarmed(bl))
+ flee2 += (skill_power_bl(bl, TMW_BRAWLING) >> 3); // +25 for 200
+ flee2 += skill_power_bl(bl, TMW_SPEED) >> 3;
}
if(flee2 < 1) flee2 = 1;
return flee2;
@@ -582,6 +593,7 @@ int battle_get_atk2(struct block_list *bl)
if(sc_data[SC_CONCENTRATION].timer!=-1) //コンセントレーション
atk2 += atk2*(5*sc_data[SC_CONCENTRATION].val1)/100;
}
+
if(atk2 < 0) atk2 = 0;
return atk2;
}
@@ -595,8 +607,8 @@ int battle_get_atk2(struct block_list *bl)
int battle_get_atk_2(struct block_list *bl)
{
nullpo_retr(0, bl);
- if(bl->type==BL_PC && (struct map_session_data *)bl)
- return ((struct map_session_data*)bl)->watk_2;
+ if(bl->type==BL_PC)
+ return ((struct map_session_data*)bl)->watk_2;
else
return 0;
}
@@ -1134,6 +1146,21 @@ int battle_get_mexp(struct block_list *bl)
return 0;
}
+int battle_get_stat(int stat_id /* SP_VIT or similar */, struct block_list *bl)
+{
+ switch (stat_id) {
+ case SP_STR: return battle_get_str(bl);
+ case SP_AGI: return battle_get_agi(bl);
+ case SP_DEX: return battle_get_dex(bl);
+ case SP_VIT: return battle_get_vit(bl);
+ case SP_INT: return battle_get_int(bl);
+ case SP_LUK: return battle_get_luk(bl);
+ default:
+ return 0;
+ }
+}
+
+
// StatusChange系の所得
struct status_change *battle_get_sc_data(struct block_list *bl)
{
@@ -2213,6 +2240,23 @@ static struct Damage battle_calc_mob_weapon_attack(
wd.dmg_lv=dmg_lv;
return wd;
}
+
+
+int
+battle_is_unarmed(struct block_list *bl)
+{
+ if (!bl)
+ return 0;
+ if (bl->type == BL_PC) {
+ struct map_session_data *sd = (struct map_session_data *) bl;
+
+ return (sd->equip_index[EQUIP_SHIELD] == -1
+ && sd->equip_index[EQUIP_WEAPON] == -1);
+ } else
+ return 0;
+}
+
+
/*
* =========================================================================
* PCの武器による攻撃
@@ -2239,6 +2283,7 @@ static struct Damage battle_calc_pc_weapon_attack(
int watk,watk_,cardfix,t_ele;
int da=0,i,t_class,ac_flag = 0;
int idef_flag=0,idef_flag_=0;
+ int target_distance;
//return前の処理があるので情報出力部のみ変更
if( src == NULL || target == NULL || sd == NULL ){
@@ -2310,26 +2355,36 @@ static struct Damage battle_calc_pc_weapon_attack(
}
}
hitrate=battle_get_hit(src) - flee + 80; //命中率計算
- { // [Fate] Reduce hit chance by distance
+
+ { // [fate] Reduce hit chance by distance
int dx = abs(src->x - target->x);
int dy = abs(src->y - target->y);
- int dist = MAX(dx, dy);
- hitrate -= (dist * (dist + 1));
- }
+ int malus_dist;
- type=0; // normal
- div_ = 1; // single attack
+ target_distance = MAX(dx, dy);
+ malus_dist = MAX(0, target_distance - (skill_power(sd, AC_OWL) / 75));
+ hitrate -= (malus_dist * (malus_dist + 1));
+ }
dex=battle_get_dex(src); //DEX
luk=battle_get_luk(src); //LUK
watk = battle_get_atk(src); //ATK
watk_ = battle_get_atk_(src); //ATK左手
+ type=0; // normal
+ div_ = 1; // single attack
+
if(skill_num==HW_MAGICCRASHER){ /* マジッククラッシャーはMATKで殴る */
damage = damage2 = battle_get_matk1(src); //damega,damega2初登場、base_atkの取得
}else{
damage = damage2 = battle_get_baseatk(&sd->bl); //damega,damega2初登場、base_atkの取得
}
+ if (sd->attackrange > 2) { // [fate] ranged weapon?
+ const int range_damage_bonus = 80; // up to 31.25% bonus for long-range hit
+ damage = damage * (256 + ((range_damage_bonus * target_distance) / sd->attackrange)) >> 8;
+ damage2 = damage2 * (256 + ((range_damage_bonus * target_distance) / sd->attackrange)) >> 8;
+ }
+
atkmin = atkmin_ = dex; //最低ATKはDEXで初期化?
sd->state.arrow_atk = 0; //arrow_atk初期化
if(sd->equip_index[9] >= 0 && sd->inventory_data[sd->equip_index[9]])
@@ -3875,13 +3930,17 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
// significantly increase injuries for hasted characters
if (wd.damage > 0
&& (t_sc_data[SC_HASTE].timer != -1)) {
- wd.damage = (wd.damage * (16 + t_sc_data[SC_HASTE].val1)) >> 4;
+ wd.damage = (wd.damage * (16 + t_sc_data[SC_HASTE].val1)) >> 4;
}
- if (t_sc_data[SC_PHYS_SHIELD].timer != -1 && target->type == BL_PC) {
- wd.damage -= t_sc_data[SC_PHYS_SHIELD].val1;
- if (wd.damage < 0)
- wd.damage = 0;
+ if (wd.damage > 0
+ && t_sc_data[SC_PHYS_SHIELD].timer != -1 && target->type == BL_PC) {
+ int reduction = t_sc_data[SC_PHYS_SHIELD].val1;
+ if (reduction > wd.damage)
+ reduction = wd.damage;
+
+ wd.damage -= reduction;
+ MAP_LOG_PC(((struct map_session_data *)target), "MAGIC-ABSORB-DMG %d", reduction);
}
if((damage = wd.damage + wd.damage2) > 0 && src != target) {
diff --git a/src/map/battle.h b/src/map/battle.h
index b58e80c..6b4860d 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -63,6 +63,7 @@ int battle_weapon_attack( struct block_list *bl,struct block_list *target,
// 各種パラメータを得る
int battle_counttargeted(struct block_list *bl,struct block_list *src,int target_lv);
+int battle_is_unarmed(struct block_list *bl);
int battle_get_class(struct block_list *bl);
int battle_get_dir(struct block_list *bl);
int battle_get_lv(struct block_list *bl);
@@ -100,6 +101,7 @@ int battle_get_race(struct block_list *bl);
int battle_get_size(struct block_list *bl);
int battle_get_mode(struct block_list *bl);
int battle_get_mexp(struct block_list *bl);
+int battle_get_stat(int stat_id /* SP_VIT or similar */, struct block_list *bl);
struct status_change *battle_get_sc_data(struct block_list *bl);
short *battle_get_sc_count(struct block_list *bl);
diff --git a/src/map/chrif.c b/src/map/chrif.c
index 4318d1a..3152866 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -595,22 +595,7 @@ int chrif_changedsex(int fd)
// reset skill of some job
if (s_class.job == 19 || s_class.job == 4020 || s_class.job == 4042 ||
s_class.job == 20 || s_class.job == 4021 || s_class.job == 4043) {
- // remove specifical skills of classes 19, 4020 and 4042
- for(i = 315; i <= 322; i++) {
- if (sd->status.skill[i].id > 0 && !sd->status.skill[i].flag) {
- sd->status.skill_point += sd->status.skill[i].lv;
- sd->status.skill[i].id = 0;
- sd->status.skill[i].lv = 0;
- }
- }
- // remove specifical skills of classes 20, 4021 and 4043
- for(i = 323; i <= 330; i++) {
- if (sd->status.skill[i].id > 0 && !sd->status.skill[i].flag) {
- sd->status.skill_point += sd->status.skill[i].lv;
- sd->status.skill[i].id = 0;
- sd->status.skill[i].lv = 0;
- }
- }
+
clif_updatestatus(sd, SP_SKILLPOINT);
// change job if necessary
if (s_class.job == 20 || s_class.job == 4021 || s_class.job == 4043)
diff --git a/src/map/clif.c b/src/map/clif.c
index 401f6cc..76c38e5 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -3741,10 +3741,7 @@ int clif_skillinfo(struct map_session_data *sd,int skillid,int type,int range)
} else
WFIFOW(fd,12)= range;
memset(WFIFOP(fd,14),0,24);
- if(!(skill_get_inf2(id)&0x01) || battle_config.quest_skill_learn == 1 || (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill) )
- WFIFOB(fd,38)= (sd->status.skill[skillid].lv < skill_get_max(id) && sd->status.skill[skillid].flag ==0 )? 1:0;
- else
- WFIFOB(fd,38) = 0;
+ WFIFOB(fd,38)= (sd->status.skill[skillid].lv < skill_get_max_raise(id))? 1:0;
WFIFOSET(fd,packet_len_table[0x147]);
return 0;
@@ -3765,11 +3762,10 @@ int clif_skillinfoblock(struct map_session_data *sd)
WFIFOW(fd,0)=0x10f;
for ( i = c = 0; i < MAX_SKILL; i++){
if( (id=sd->status.skill[i].id)!=0
- && (sd->tmw_version >= 1 // [Fate] Version 1 and later don't crash because of bad skill IDs anymore
- || !QUEST_SKILL(i))){ // [Fate] Hack: Prevent killing the client
+ && (sd->tmw_version >= 1)){ // [Fate] Version 1 and later don't crash because of bad skill IDs anymore
WFIFOW(fd,len ) = id;
WFIFOW(fd,len+2) = skill_get_inf(id);
- WFIFOW(fd,len+4) = 0;
+ WFIFOW(fd,len+4) = skill_db[i].poolflags | (sd->status.skill[i].flags & (SKILL_POOL_ACTIVATED));
WFIFOW(fd,len+6) = sd->status.skill[i].lv;
WFIFOW(fd,len+8) = skill_get_sp(id,sd->status.skill[i].lv);
range = skill_get_range(id,sd->status.skill[i].lv);
@@ -3777,10 +3773,7 @@ int clif_skillinfoblock(struct map_session_data *sd)
range = battle_get_range(&sd->bl) - (range + 1);
WFIFOW(fd,len+10)= range;
memset(WFIFOP(fd,len+12),0,24);
- if(!(skill_get_inf2(id)&0x01) || battle_config.quest_skill_learn == 1 || (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill) )
- WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_get_max(id) && sd->status.skill[i].flag ==0 )? 1:0;
- else
- WFIFOB(fd,len+36) = 0;
+ WFIFOB(fd,len+36)= (sd->status.skill[i].lv < skill_get_max_raise(id))? 1:0;
len+=37;
c++;
}
@@ -3810,7 +3803,7 @@ int clif_skillup(struct map_session_data *sd,int skill_num)
if(range < 0)
range = battle_get_range(&sd->bl) - (range + 1);
WFIFOW(fd,8) = range;
- WFIFOB(fd,10) = (sd->status.skill[skill_num].lv < skill_get_max(sd->status.skill[skill_num].id)) ? 1 : 0;
+ WFIFOB(fd,10) = (sd->status.skill[skill_num].lv < skill_get_max_raise(sd->status.skill[skill_num].id)) ? 1 : 0;
WFIFOSET(fd,packet_len_table[0x10e]);
return 0;
@@ -6648,7 +6641,7 @@ void clif_parse_Emotion(int fd, struct map_session_data *sd) {
nullpo_retv(sd);
- if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, NV_BASIC) >= 2) {
+ if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, NV_EMOTE) >= 1) {
WBUFW(buf,0) = 0xc0;
WBUFL(buf,2) = sd->bl.id;
WBUFB(buf,6) = RFIFOB(fd,2);
@@ -6700,7 +6693,7 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) {
switch(action_type) {
case 0x00: // once attack
case 0x07: // continuous attack
- if(sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class==22)
+ if(sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class==22 || sd->status.option & OPTION_HIDE)
return;
if (!battle_config.sdelay_attack_enable && pc_checkskill(sd, SA_FREECAST) <= 0) {
if (DIFF_TICK(tick, sd->canact_tick) < 0) {
@@ -6715,15 +6708,12 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) {
pc_attack(sd, target_id, action_type != 0);
break;
case 0x02: // sitdown
- if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, NV_BASIC) >= 3) {
- if (tmw_CheckSitSpam(sd))
- break;
- pc_stop_walking(sd, 1);
- skill_gangsterparadise(sd, 1); // ソスMソスソスソスソスソスOソスXソス^ソス[ソスpソスソスソス_ソスCソスXソスン抵ソス
- pc_setsit(sd);
- clif_sitting(fd, sd);
- } else
- clif_skill_fail(sd, 1, 0, 2);
+ if (tmw_CheckSitSpam(sd))
+ break;
+ pc_stop_walking(sd, 1);
+ skill_gangsterparadise(sd, 1); // ソスMソスソスソスソスソスOソスXソス^ソス[ソスpソスソスソス_ソスCソスXソスン抵ソス
+ pc_setsit(sd);
+ clif_sitting(fd, sd);
break;
case 0x03: // standup
skill_gangsterparadise(sd, 0); // ソスMソスソスソスソスソスOソスXソス^ソス[ソスpソスソスソス_ソスCソスXソスソスソスソス
@@ -6906,7 +6896,7 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd) {
clif_clearchar_area(&sd->bl, 1);
return;
}
- if (sd->npc_id != 0 || sd->opt1 > 0 ||
+ if (sd->npc_id != 0 || sd->opt1 > 0 || map[sd->bl.m].flag.no_player_drops ||
(sd->sc_data && (sd->sc_data[SC_AUTOCOUNTER].timer != -1 || //ソスIソス[ソスgソスJソスEソスソスソス^ソス[
sd->sc_data[SC_BLADESTOP].timer != -1 || //ソスソスソスnソスソスソスソス
sd->sc_data[SC_BERSERK].timer != -1)) ) //ソスoソス[ソスTソス[ソスN
@@ -7072,10 +7062,7 @@ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd)
*/
void clif_parse_CreateChatRoom(int fd,struct map_session_data *sd)
{
- if(battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_BASIC) >= 4){
- chat_createchat(sd,RFIFOW(fd,4),RFIFOB(fd,6),RFIFOP(fd,7),RFIFOP(fd,15),RFIFOW(fd,2)-15);
- } else
- clif_skill_fail(sd,1,0,3);
+ chat_createchat(sd,RFIFOW(fd,4),RFIFOB(fd,6),RFIFOP(fd,7),RFIFOP(fd,15),RFIFOW(fd,2)-15);
}
/*==========================================
@@ -7131,7 +7118,7 @@ void clif_parse_TradeRequest(int fd,struct map_session_data *sd)
{
nullpo_retv(sd);
- if(battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_BASIC) >= 1){
+ if(battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_TRADE) >= 1){
if (tmw_CheckTradeSpam(sd))
return;
trade_traderequest(sd,RFIFOL(sd->fd,2));
@@ -7664,7 +7651,7 @@ void clif_parse_CloseKafra(int fd, struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_CreateParty(int fd, struct map_session_data *sd) {
- if (battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_BASIC) >= 7) {
+ if (battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_PARTY) >= 2) {
party_create(sd,RFIFOP(fd,2));
} else
clif_skill_fail(sd,1,0,4);
@@ -7675,7 +7662,7 @@ void clif_parse_CreateParty(int fd, struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_CreateParty2(int fd, struct map_session_data *sd) {
- if (battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_BASIC) >= 7){
+ if (battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_PARTY) >= 2){
party_create(sd, RFIFOP(fd,2));
} else
clif_skill_fail(sd, 1, 0, 4);
@@ -7686,6 +7673,7 @@ void clif_parse_CreateParty2(int fd, struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_PartyInvite(int fd, struct map_session_data *sd) {
+ printf("Party Invite!\n");
party_invite(sd, RFIFOL(fd,2));
}
@@ -7694,7 +7682,7 @@ void clif_parse_PartyInvite(int fd, struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_ReplyPartyInvite(int fd,struct map_session_data *sd) {
- if(battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_BASIC) >= 5){
+ if (battle_config.basic_skill_check == 0 || pc_checkskill(sd,NV_PARTY) >= 1){
party_reply_invite(sd,RFIFOL(fd,2),RFIFOL(fd,6));
} else {
party_reply_invite(sd,RFIFOL(fd,2),-1);
diff --git a/src/map/magic-stmt.c b/src/map/magic-stmt.c
index 55e6133..65e0202 100644
--- a/src/map/magic-stmt.c
+++ b/src/map/magic-stmt.c
@@ -292,9 +292,8 @@ op_instaheal(env_t *env, int args_nr, val_t *args)
if (caster->type == BL_PC && subject->type == BL_PC) {
character_t *caster_pc = (character_t *) caster;
character_t *subject_pc = (character_t *) subject;
- MAP_LOG("PC%d %d:%d,%d SPELLHEAL-INSTA PC%d FOR %d",
- caster_pc->status.char_id, caster->m, caster->x, caster->y,
- subject_pc->status.char_id, ARGINT(1));
+ MAP_LOG_PC(caster_pc, "SPELLHEAL-INSTA PC%d FOR %d",
+ subject_pc->status.char_id, ARGINT(1));
}
battle_heal(caster, subject, ARGINT(1), ARGINT(2), 0);
@@ -677,6 +676,22 @@ op_spawn(env_t *env, int args_nr, val_t *args)
}
+static char *
+get_invocation_name(env_t *env)
+{
+ invocation_t *invocation;
+
+ if (VAR(VAR_INVOCATION).ty != TY_INVOCATION)
+ return "?";
+ invocation = (invocation_t *)map_id2bl(VAR(VAR_INVOCATION).v.v_int);
+
+ if (invocation)
+ return invocation->spell->name;
+ else
+ return "??";
+}
+
+
static int
op_injure(env_t *env, int args_nr, val_t *args)
{
@@ -711,9 +726,9 @@ op_injure(env_t *env, int args_nr, val_t *args)
if (target->type == BL_MOB) {
struct mob_data *mob = (struct mob_data *) target;
- MAP_LOG("PC%d %d:%d,%d SPELLDMG MOB%d %d FOR %d",
- caster_pc->status.char_id, caster->m, caster->x, caster->y,
- mob->bl.id, mob->class, damage_caused);
+ MAP_LOG_PC(caster_pc, "SPELLDMG MOB%d %d FOR %d BY %s",
+ mob->bl.id, mob->class, damage_caused,
+ get_invocation_name(env));
}
}
battle_damage(caster, target, damage_caused, mp_damage);
diff --git a/src/map/magic.c b/src/map/magic.c
index 674da89..f70d9a6 100644
--- a/src/map/magic.c
+++ b/src/map/magic.c
@@ -92,12 +92,12 @@ magic_message(character_t *caster,
#ifdef DEBUG
fprintf(stderr, "Found spell `%s', triggered = %d\n", spell_, effects != NULL);
#endif
+ if (caster->status.option & OPTION_HIDE)
+ return 0; // No spellcasting while hidden
- MAP_LOG("PC%d %d:%d,%d CAST %s %s",
- caster->status.char_id, caster->bl.m, caster->bl.x, caster->bl.y,
- spell->name,
- effects? "SUCCESS" : "FAILURE");
-
+ MAP_LOG_PC(caster, "CAST %s %s",
+ spell->name,
+ effects? "SUCCESS" : "FAILURE");
if (effects) {
invocation_t *invocation = spell_instantiate(effects, env);
diff --git a/src/map/map.c b/src/map/map.c
index 31f269d..f5d6d33 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -965,8 +965,6 @@ void map_addnickdb(struct map_session_data *sd) {
*------------------------------------------
*/
int map_quit(struct map_session_data *sd) {
- int i;
-
nullpo_retr(0, sd);
if(sd->chatID) // チャットから出る
@@ -1012,13 +1010,6 @@ int map_quit(struct map_session_data *sd) {
pc_setrestartvalue(sd,2);
pc_makesavestatus(sd);
//クローンスキルで覚えたスキルは消す
- for(i=0;i<MAX_SKILL;i++){
- if(sd->status.skill[i].flag == 13){
- sd->status.skill[i].id=0;
- sd->status.skill[i].lv=0;
- sd->status.skill[i].flag=0;
- }
- }
//The storage closing routines will save the char if needed. [Skotlex]
if (!sd->state.storage_flag)
@@ -1668,7 +1659,7 @@ map_close_logfile()
{
if (map_logfile) {
char *filenameop_buf = malloc(strlen(map_logfile_name) + 50);
- sprintf(filenameop_buf, "gzip %s.%ld", map_logfile_name, map_logfile_index);
+ sprintf(filenameop_buf, "gzip -f %s.%ld", map_logfile_name, map_logfile_index);
fclose(map_logfile);
@@ -1704,7 +1695,7 @@ map_set_logfile(char *filename)
map_start_logfile(tv.tv_sec);
atexit(map_close_logfile);
- MAP_LOG("log-start v2");
+ MAP_LOG("log-start v3");
}
diff --git a/src/map/map.h b/src/map/map.h
index 5e77d89..9a6b3ef 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -546,6 +546,7 @@ struct map_data {
unsigned sakura : 1; // [Valaris]
unsigned leaves : 1; // [Valaris]
unsigned rain : 1; // [Valaris]
+ unsigned no_player_drops : 1; // [Jaxad0127]
} flag;
struct point save;
struct npc_data *npc[MAX_NPC_PER_MAP];
@@ -630,6 +631,11 @@ enum {
LOOK_MISC2
};
+enum {
+ EQUIP_SHIELD = 8,
+ EQUIP_WEAPON = 9
+};
+
#define LOOK_LAST LOOK_MISC2
struct chat_data {
@@ -692,6 +698,9 @@ extern FILE *map_logfile;
void map_write_log(char *format, ...);
#define MAP_LOG(format, args...) {if (map_logfile) map_write_log(format, ##args);}
+#define MAP_LOG_PC(sd, fmt, args...) MAP_LOG("PC%d %d:%d,%d " fmt, sd->status.char_id, sd->bl.m, sd->bl.x, sd->bl.y, ## args)
+
+
// 床アイテム関連
int map_clearflooritem_timer(int,unsigned int,int,int);
#define map_clearflooritem(id) map_clearflooritem_timer(0,0,id,1)
diff --git a/src/map/mob.c b/src/map/mob.c
index c2a2955..b4753da 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -267,7 +267,7 @@ mob_gen_exp(struct mob_db *mob)
double mod_def = 100 - mob->def;
if (mod_def == 0) mod_def = 1;
double effective_hp = ((50 - mob->luk) * mob->max_hp / 50.0) + (2 * mob->luk * mob->max_hp / mod_def);
- double attack_factor = (mob->atk1 + mob->atk2 + mob->str / 3.0 + mob->dex / 2.0 + mob->luk) * (1872 / mob->adelay) / 4;
+ double attack_factor = (mob->atk1 + mob->atk2 + mob->str / 3.0 + mob->dex / 2.0 + mob->luk) * (1872.0 / mob->adelay) / 4;
double dodge_factor = pow(mob->lv + mob->agi + mob->luk / 2.0, 4.0 / 3.0);
double persuit_factor = (3 + mob->range) * (mob->mode % 2) * 1000 / mob->speed;
double aggression_factor = (mob->mode & 4) == 4 ? 10.0 / 9.0 : 1.0;
diff --git a/src/map/npc.c b/src/map/npc.c
index 10d64db..0c6c922 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -996,8 +996,6 @@ int npc_buylist(struct map_session_data *sd,int n,unsigned short *item_list)
pc_gainexp(sd,0,z);
}*/
if (battle_config.shop_exp > 0 && z > 0 && (skill = pc_checkskill(sd,MC_DISCOUNT)) > 0) {
- if (sd->status.skill[MC_DISCOUNT].flag != 0)
- skill = sd->status.skill[MC_DISCOUNT].flag - 2;
if (skill > 0) {
z = (log(z * (double)skill) * (double)battle_config.shop_exp/100.);
if (z < 1)
@@ -1053,8 +1051,6 @@ int npc_selllist(struct map_session_data *sd,int n,unsigned short *item_list)
pc_gainexp(sd,0,z);
}*/
if (battle_config.shop_exp > 0 && z > 0 && (skill = pc_checkskill(sd,MC_OVERCHARGE)) > 0) {
- if (sd->status.skill[MC_OVERCHARGE].flag != 0)
- skill = sd->status.skill[MC_OVERCHARGE].flag - 2;
if (skill > 0) {
z = (log(z * (double)skill) * (double)battle_config.shop_exp/100.);
if (z < 1)
@@ -1837,22 +1833,25 @@ static int npc_parse_mapflag(char *w1,char *w2,char *w3,char *w4)
}
else if (strcmpi(w3,"noicewall")==0) { // noicewall [Valaris]
map[m].flag.noicewall=1;
- }
+ }
else if (strcmpi(w3,"snow")==0) { // snow [Valaris]
map[m].flag.snow=1;
- }
+ }
else if (strcmpi(w3,"fog")==0) { // fog [Valaris]
map[m].flag.fog=1;
- }
+ }
else if (strcmpi(w3,"sakura")==0) { // sakura [Valaris]
map[m].flag.sakura=1;
- }
+ }
else if (strcmpi(w3,"leaves")==0) { // leaves [Valaris]
map[m].flag.leaves=1;
- }
+ }
else if (strcmpi(w3,"rain")==0) { // rain [Valaris]
map[m].flag.rain=1;
- }
+ }
+ else if (strcmpi(w3,"no_player_drops")==0) { // rain [Valaris]
+ map[m].flag.no_player_drops=1;
+ }
return 0;
}
diff --git a/src/map/party.c b/src/map/party.c
index feacc25..62b30d8 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -14,6 +14,7 @@
#include "battle.h"
#include "intif.h"
#include "clif.h"
+#include "skill.h"
#ifdef MEMWATCH
#include "memwatch.h"
@@ -203,23 +204,28 @@ int party_invite(struct map_session_data *sd,int account_id)
if(tsd==NULL || p==NULL)
return 0;
+
+ printf("\tA\n");
+
if(!battle_config.invite_request_check) {
- if (tsd->guild_invite>0 || tsd->trade_partner) { // 相手が取引中かどうか
+ if (tsd->guild_invite>0 || tsd->trade_partner || tsd->npc_id || tsd->npc_shopid || pc_checkskill(tsd,NV_PARTY) < 1) {
clif_party_inviteack(sd,tsd->status.name,0);
return 0;
}
}
+ printf("\tB\n");
if( tsd->status.party_id>0 || tsd->party_invite>0 ){ // 相手の所属確認
clif_party_inviteack(sd,tsd->status.name,0);
return 0;
}
+ printf("\tC\n");
for(i=0;i<MAX_PARTY;i++){ // 同アカウント確認
if(p->member[i].account_id==account_id){
clif_party_inviteack(sd,tsd->status.name,0);
return 0;
}
}
-
+ printf("\tD\n");
tsd->party_invite=sd->status.party_id;
tsd->party_invite_account=sd->status.account_id;
diff --git a/src/map/pc.c b/src/map/pc.c
index acec322..e2f8eec 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -38,8 +38,6 @@
#define STATE_BLIND 0x10
-#define MAP_LOG_PC(sd, fmt, args...) MAP_LOG("PC%d %d:%d,%d " fmt, sd->status.char_id, sd->bl.m, sd->bl.x, sd->bl.y, ## args)
-
#define MAP_LOG_STATS(sd, suffix) \
MAP_LOG_PC(sd, "STAT %d %d %d %d %d %d " suffix, \
sd->status.str, sd->status.agi, sd->status.vit, sd->status.int_, sd->status.dex, sd->status.luk)
@@ -853,6 +851,7 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, short tmw_versio
strftime(tmpstr, sizeof(tmpstr) - 1, msg_txt(501), gmtime(&connect_until_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S."
clif_wis_message(sd->fd, wisp_server_name, tmpstr, strlen(tmpstr)+1);
}
+ pc_calcstatus(sd,1);
return 0;
}
@@ -875,23 +874,17 @@ int pc_authfail(int id) {
static int pc_calc_skillpoint(struct map_session_data* sd)
{
- int i,skill,skill_point=0;
+ int i, skill_points = 0;
nullpo_retr(0, sd);
- for(i=1;i<MAX_SKILL;i++){
- if( (skill = pc_checkskill(sd,i)) > 0) {
- if(!(skill_get_inf2(i)&0x01) || battle_config.quest_skill_learn) {
- if(!sd->status.skill[i].flag)
- skill_point += skill;
- else if(sd->status.skill[i].flag > 2 && sd->status.skill[i].flag != 13) {
- skill_point += (sd->status.skill[i].flag - 2);
- }
- }
- }
- }
+ for (i = 0; i < skill_pool_skills_size; i++) {
+ int lv = sd->status.skill[skill_pool_skills[i]].lv;
+ if (lv)
+ skill_points += ((lv * (lv + 1)) >> 1) - 1;
+ }
- return skill_point;
+ return skill_points;
}
/*==========================================
@@ -997,6 +990,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
}
}
+ /*Comment this out for now, as we manage skills differently
for(i=0;i<MAX_SKILL;i++)
if (i < TMW_MAGIC || i > TMW_MAGIC_END){ // [Fate] This hack gets TMW magic working and persisted without bothering about the skill tree.
if (sd->status.skill[i].flag != 13) sd->status.skill[i].id=0;
@@ -1005,6 +999,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
sd->status.skill[i].flag=0; // flagソスソス0ソスノゑソスソストゑソスソスソス
}
}
+ */
if (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill){
// ソスSソストのスソスLソスソス
@@ -1379,6 +1374,13 @@ int pc_calcstatus(struct map_session_data* sd,int first)
}
}
+ if (battle_is_unarmed(&sd->bl)) {
+ sd->watk += skill_power(sd, TMW_BRAWLING) / 3; // +66 for 200
+ sd->watk2 += skill_power(sd, TMW_BRAWLING) >> 3; // +25 for 200
+ sd->watk_ += skill_power(sd, TMW_BRAWLING) / 3; // +66 for 200
+ sd->watk_2 += skill_power(sd, TMW_BRAWLING) >> 3; // +25 for 200
+ }
+
if(sd->equip_index[10] >= 0){ // ソスソス
index = sd->equip_index[10];
if(sd->inventory_data[index]){ //ソスワゑソスソスソスソスソスソスソスソスソスソスソストゑソスソスネゑソス
@@ -1429,9 +1431,6 @@ int pc_calcstatus(struct map_session_data* sd,int first)
if( (skill=pc_checkskill(sd,MC_INCCARRY))>0 ) // skill can be used with an item now, thanks to orn [Valaris]
sd->max_weight += skill*1000;
- if( (skill=pc_checkskill(sd,AC_OWL))>0 ) // ソスモゑソスソスうソスフ厄ソス
- sd->paramb[4] += skill;
-
// ソスXソスeソス[ソス^ソスXソスマ会ソスソスノゑソスソスソスソスソスソス{ソスpソスソスソスソスソス[ソス^ソス竦ウ
if(sd->sc_count){
if(sd->sc_data[SC_CONCENTRATE].timer!=-1 && sd->sc_data[SC_QUAGMIRE].timer == -1){ // ソスWソスソスソスヘ鯉ソスソスソス
@@ -1469,6 +1468,10 @@ int pc_calcstatus(struct map_session_data* sd,int first)
sd->paramb[5]+= 5;
}
}
+ sd->speed -= skill_power(sd, TMW_SPEED) >> 3;
+ sd->aspd_rate -= skill_power(sd, TMW_SPEED) / 10;
+ if (sd->aspd_rate < 20)
+ sd->aspd_rate = 20;
//1ソスxソスソスソスソスソスナなゑソスJob70ソスXソスpソスmソスrソスソス+10
if(s_class.job == 23 && sd->die_counter == 0 && sd->status.job_level >= 70){
@@ -1562,10 +1565,15 @@ int pc_calcstatus(struct map_session_data* sd,int first)
if( (skill=pc_checkskill(sd,AC_VULTURE))>0){ // ソスソスソスVソスフ厄ソス
sd->hit += skill;
- if(sd->status.weapon == 11)
+ if (sd->status.weapon == 11)
sd->attackrange += skill;
}
+ if (sd->attackrange > 2) { // [fate] ranged weapon?
+ sd->attackrange += MIN(skill_power(sd, AC_OWL) / 60, 3);
+ sd->hit += skill_power(sd, AC_OWL) / 10; // 20 for 200
+ }
+
if( (skill=pc_checkskill(sd,BS_WEAPONRESEARCH))>0) // ソスソスソス研ソスソスソスフ厄ソスソスソスソスソスソスソスソスソス
sd->hit += skill*2;
if(sd->status.option&2 && (skill = pc_checkskill(sd,RG_TUNNELDRIVE))>0 ) // ソスgソスソスソスlソスソスソスhソスソスソスCソスu // ソスgソスソスソスlソスソスソスhソスソスソスCソスu
@@ -2652,12 +2660,7 @@ int pc_skill(struct map_session_data *sd,int id,int level,int flag)
clif_skillinfoblock(sd);
}
else if(sd->status.skill[id].lv < level){ // ソスoソスソスソスソスソスソスソス驍ェlvソスソスソスソスソスソスソスソスソスネゑソス
- if(sd->status.skill[id].id==id)
- sd->status.skill[id].flag=sd->status.skill[id].lv+2; // lvソスソスソスLソスソス
- else {
- sd->status.skill[id].id=id;
- sd->status.skill[id].flag=1; // cardソスXソスLソスソスソスニゑソスソスソス
- }
+ sd->status.skill[id].id=id;
sd->status.skill[id].lv=level;
}
@@ -4356,6 +4359,7 @@ int pc_checkbaselevelup(struct map_session_data *sd)
//ソスソスソスxソスソスソスAソスbソスvソスソスソスソスソスフでパソス[ソスeソスBソス[ソスソスソスソスソスソスソスXソスVソスソスソスソス
//(ソスソスヘ囲チソスFソスbソスN)
party_send_movemap(sd);
+ MAP_LOG_XP(sd, "LEVELUP")
return 1;
}
@@ -4754,22 +4758,18 @@ int pc_skillup(struct map_session_data *sd,int skill_num)
{
nullpo_retr(0, sd);
- if( skill_num>=10000 ){
- guild_skillup(sd,skill_num);
- return 0;
- }
-
- if( sd->status.skill_point>0 &&
- sd->status.skill[skill_num].id!=0 &&
- sd->status.skill[skill_num].lv < skill_get_max(skill_num)
- && (skill_num < TMW_MAGIC || skill_num > TMW_MAGIC_END)) // [Fate] Hack: Prevent exploit for raising magic levels
- {
+ if (sd->status.skill[skill_num].id !=0
+ && sd->status.skill_point > sd->status.skill[skill_num].lv
+ && sd->status.skill[skill_num].lv < skill_db[skill_num].max_raise) {
sd->status.skill[skill_num].lv++;
- sd->status.skill_point--;
+ sd->status.skill_point -= sd->status.skill[skill_num].lv;
+
pc_calcstatus(sd,0);
clif_skillup(sd,skill_num);
clif_updatestatus(sd,SP_SKILLPOINT);
clif_skillinfoblock(sd);
+ MAP_LOG_PC(sd, "SKILLUP %d %d %d",
+ skill_num, sd->status.skill[skill_num].lv, skill_power(sd, skill_num));
}
return 0;
@@ -4792,13 +4792,8 @@ int pc_allskillup(struct map_session_data *sd)
c = s_class.job;
s = (s_class.upper==1) ? 1 : 0 ; //ソス]ソスソスソスネ外ソスヘ通擾ソスソスフスソスLソスソスソスH
- for(i=0;i<MAX_SKILL;i++){
+ for(i=0;i<MAX_SKILL;i++)
sd->status.skill[i].id=0;
- if (sd->status.skill[i].flag && sd->status.skill[i].flag != 13){ // cardソスXソスLソスソスソスネゑソスソスA
- sd->status.skill[i].lv=(sd->status.skill[i].flag==1)?0:sd->status.skill[i].flag-2; // ソス{ソスソスソスソスlvソスソス
- sd->status.skill[i].flag=0; // flagソスソス0ソスノゑソスソストゑソスソスソス
- }
- }
if (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill){
// ソスSソストのスソスLソスソス
@@ -4811,7 +4806,7 @@ int pc_allskillup(struct map_session_data *sd)
}
else {
for(i=0;(id=skill_tree[s][c][i].id)>0;i++){
- if(sd->status.skill[id].id==0 && (!(skill_get_inf2(id)&0x01) || battle_config.quest_skill_learn) )
+ if(sd->status.skill[id].id==0 && skill_get_inf2(id)&0x01 )
sd->status.skill[id].lv=skill_get_max(id);
}
}
@@ -4967,23 +4962,14 @@ int pc_resetskill(struct map_session_data* sd)
nullpo_retr(0, sd);
- for(i=1;i<MAX_SKILL;i++){
+ sd->status.skill_point += pc_calc_skillpoint(sd);
+
+ for(i=1;i<MAX_SKILL;i++)
if( (skill = pc_checkskill(sd,i)) > 0) {
- if(!(skill_get_inf2(i)&0x01) || battle_config.quest_skill_learn) {
- if(!sd->status.skill[i].flag && !QUEST_SKILL(i))
- sd->status.skill_point += skill;
- else if(sd->status.skill[i].flag > 2 && sd->status.skill[i].flag != 13) {
- sd->status.skill_point += (sd->status.skill[i].flag - 2);
- }
- sd->status.skill[i].lv = 0;
- }
- else if(battle_config.quest_skill_reset)
- sd->status.skill[i].lv = 0;
- sd->status.skill[i].flag = 0;
- }
- else
sd->status.skill[i].lv = 0;
- }
+ sd->status.skill[i].flags = 0;
+ }
+
clif_updatestatus(sd,SP_SKILLPOINT);
clif_skillinfoblock(sd);
pc_calcstatus(sd,0);
diff --git a/src/map/script.c b/src/map/script.c
index 8d9abe8..9310b6d 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -255,6 +255,13 @@ int buildin_getanchorinvocation(struct script_state *st); // [Fate]
int buildin_getexp(struct script_state *st);
int buildin_getinventorylist(struct script_state *st);
int buildin_getskilllist(struct script_state *st);
+int buildin_get_pool_skills(struct script_state *st); // [fate]
+int buildin_get_activated_pool_skills(struct script_state *st); // [fate]
+int buildin_activate_pool_skill(struct script_state *st); // [fate]
+int buildin_deactivate_pool_skill(struct script_state *st); // [fate]
+int buildin_check_pool_skill(struct script_state *st); // [fate]
+int buildin_getskilllist(struct script_state *st);
+int buildin_getskilllist(struct script_state *st);
int buildin_clearitem(struct script_state *st);
int buildin_classchange(struct script_state *st);
int buildin_misceffect(struct script_state *st);
@@ -464,6 +471,11 @@ struct {
{buildin_getexp,"getexp","ii"},
{buildin_getinventorylist,"getinventorylist",""},
{buildin_getskilllist,"getskilllist",""},
+ {buildin_get_activated_pool_skills,"getpoolskilllist",""},
+ {buildin_get_pool_skills,"getactivatedpoolskilllist",""},
+ {buildin_activate_pool_skill,"poolskill","i"},
+ {buildin_deactivate_pool_skill,"unpoolskill","i"},
+ {buildin_check_pool_skill,"checkpoolskill","i"},
{buildin_clearitem,"clearitem",""},
{buildin_classchange,"classchange","ii"},
{buildin_misceffect,"misceffect","i*"},
@@ -3193,7 +3205,6 @@ int buildin_setskill(struct script_state *st)
sd->status.skill[id].id = level? id : 0;
sd->status.skill[id].lv = level;
- sd->status.skill[id].flag = 0;
clif_skillinfoblock(sd);
return 0;
}
@@ -5512,7 +5523,7 @@ int buildin_getskilllist(struct script_state *st)
if(sd->status.skill[i].id > 0 && sd->status.skill[i].lv > 0){
pc_setreg(sd,add_str("@skilllist_id")+(j<<24),sd->status.skill[i].id);
pc_setreg(sd,add_str("@skilllist_lv")+(j<<24),sd->status.skill[i].lv);
- pc_setreg(sd,add_str("@skilllist_flag")+(j<<24),sd->status.skill[i].flag);
+ pc_setreg(sd,add_str("@skilllist_flag")+(j<<24),sd->status.skill[i].flags);
j++;
}
}
@@ -5520,6 +5531,101 @@ int buildin_getskilllist(struct script_state *st)
return 0;
}
+
+
+int
+buildin_get_activated_pool_skills(struct script_state *st)
+{
+ struct map_session_data *sd=script_rid2sd(st);
+ int pool_skills[MAX_SKILL_POOL];
+ int skill_pool_size = skill_pool(sd, pool_skills);
+ int i, count = 0;
+
+ if (!sd)
+ return 0;
+
+ for (i = 0; i < skill_pool_size; i++) {
+ int skill_id = pool_skills[i];
+
+ if (sd->status.skill[skill_id].id == skill_id) {
+ pc_setreg(sd,add_str("@skilllist_id")+(count<<24),sd->status.skill[skill_id].id);
+ pc_setreg(sd,add_str("@skilllist_lv")+(count<<24),sd->status.skill[skill_id].lv);
+ pc_setreg(sd,add_str("@skilllist_flag")+(count<<24),sd->status.skill[skill_id].flags);
+ pc_setregstr(sd, add_str("@skilllist_name$")+(count<<24), skill_name(skill_id));
+ ++count;
+ }
+ }
+ pc_setreg(sd,add_str("@skilllist_count"),count);
+
+ return 0;
+}
+
+extern int skill_pool_skills[];
+extern int skill_pool_skills_size;
+
+int
+buildin_get_pool_skills(struct script_state *st)
+{
+ struct map_session_data *sd=script_rid2sd(st);
+ int i, count = 0;
+
+ if (!sd)
+ return 0;
+
+ for (i = 0; i < skill_pool_skills_size; i++) {
+ int skill_id = skill_pool_skills[i];
+
+ if (sd->status.skill[skill_id].id == skill_id) {
+ pc_setreg(sd,add_str("@skilllist_id")+(count<<24),sd->status.skill[skill_id].id);
+ pc_setreg(sd,add_str("@skilllist_lv")+(count<<24),sd->status.skill[skill_id].lv);
+ pc_setreg(sd,add_str("@skilllist_flag")+(count<<24),sd->status.skill[skill_id].flags);
+ pc_setregstr(sd, add_str("@skilllist_name$")+(count<<24), skill_name(skill_id));
+ ++count;
+ }
+ }
+ pc_setreg(sd,add_str("@skilllist_count"),count);
+
+ return 0;
+}
+
+int
+buildin_activate_pool_skill(struct script_state *st)
+{
+ struct map_session_data *sd=script_rid2sd(st);
+ int skill_id = conv_num(st,& (st->stack->stack_data[st->start+2]));
+
+ skill_pool_activate(sd, skill_id);
+ clif_skillinfoblock(sd);
+
+ return 0;
+}
+
+
+int
+buildin_deactivate_pool_skill(struct script_state *st)
+{
+ struct map_session_data *sd=script_rid2sd(st);
+ int skill_id = conv_num(st,& (st->stack->stack_data[st->start+2]));
+
+ skill_pool_deactivate(sd, skill_id);
+ clif_skillinfoblock(sd);
+
+ return 0;
+}
+
+
+int
+buildin_check_pool_skill(struct script_state *st)
+{
+ struct map_session_data *sd=script_rid2sd(st);
+ int skill_id = conv_num(st,& (st->stack->stack_data[st->start+2]));
+
+ push_val(st->stack, C_INT, skill_pool_is_activated(sd, skill_id));
+
+ return 0;
+}
+
+
int buildin_clearitem(struct script_state *st)
{
struct map_session_data *sd=script_rid2sd(st);
diff --git a/src/map/skill-pools.c b/src/map/skill-pools.c
new file mode 100644
index 0000000..177a6a2
--- /dev/null
+++ b/src/map/skill-pools.c
@@ -0,0 +1,165 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "timer.h"
+#include "nullpo.h"
+#include "malloc.h"
+#include "magic.h"
+
+#include "battle.h"
+#include "clif.h"
+#include "intif.h"
+#include "itemdb.h"
+#include "map.h"
+#include "mob.h"
+#include "party.h"
+#include "pc.h"
+#include "script.h"
+#include "skill.h"
+#include "../common/socket.h"
+
+#ifdef MEMWATCH
+#include "memwatch.h"
+#endif
+
+int skill_pool_skills[MAX_POOL_SKILLS];
+int skill_pool_skills_size = 0;
+
+extern void
+skill_pool_register(int id)
+{
+ if (skill_pool_skills_size + 1 >= MAX_POOL_SKILLS) {
+ fprintf(stderr, "Too many pool skills! Increase MAX_POOL_SKILLS and recompile.");
+ return;
+ }
+
+ skill_pool_skills[skill_pool_skills_size++] = id;
+}
+
+
+char *
+skill_name(int skill)
+{
+ if (skill > 0 && skill < MAX_SKILL_DB)
+ return skill_names[skill].desc;
+ else
+ return NULL;
+}
+
+int
+skill_pool(struct map_session_data *sd, int *skills)
+{
+ int i, count = 0;
+
+ for (i = 0; count < MAX_SKILL_POOL && i < skill_pool_skills_size; i++) {
+ int skill_id = skill_pool_skills[i];
+ if (sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED) {
+ if (skills)
+ skills[count] = skill_id;
+ ++count;
+ }
+ }
+
+ return count;
+}
+
+void
+skill_pool_empty(struct map_session_data *sd)
+{
+ int i;
+
+ for (i = 0; i < skill_pool_skills_size; i++) {
+ int skill_id = skill_pool_skills[i];
+ sd->status.skill[skill_id].flags = 0;
+ }
+}
+
+int skill_pool_size(struct map_session_data *sd)
+{
+ return skill_pool(sd, NULL);
+}
+
+int
+skill_pool_max(struct map_session_data *sd)
+{
+ return sd->status.skill[TMW_SKILLPOOL].lv;
+}
+
+
+int
+skill_pool_activate(struct map_session_data *sd, int skill_id)
+{
+ if (sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED)
+ return 0; // Already there
+ else if (sd->status.skill[skill_id].id == skill_id // knows the skill
+ && (skill_pool_size(sd) < skill_pool_max(sd))) {
+ sd->status.skill[skill_id].flags |= SKILL_POOL_ACTIVATED;
+ pc_calcstatus(sd, 0);
+ MAP_LOG_PC(sd, "SKILL-ACTIVATE %d %d %d", skill_id, sd->status.skill[skill_id].lv, skill_power(sd, skill_id));
+ return 0;
+ }
+
+ return 1; // failed
+}
+
+int
+skill_pool_is_activated(struct map_session_data *sd, int skill_id)
+{
+ return sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED;
+}
+
+int
+skill_pool_deactivate(struct map_session_data *sd, int skill_id)
+{
+ if (sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED) {
+ sd->status.skill[skill_id].flags &= ~SKILL_POOL_ACTIVATED;
+ MAP_LOG_PC(sd, "SKILL-DEACTIVATE %d", skill_id);
+ pc_calcstatus(sd, 0);
+ return 0;
+ }
+
+ return 1;
+}
+
+
+int
+skill_stat(int skill_id)
+{
+ return skill_db[skill_id].stat;
+}
+
+int
+skill_power(struct map_session_data *sd, int skill_id)
+{
+ int stat = skill_stat(skill_id);
+ int stat_value, skill_value;
+ int result;
+
+ if (stat == 0
+ || !skill_pool_is_activated(sd, skill_id))
+ return 0;
+
+ stat_value = battle_get_stat(stat, &(sd->bl));
+ skill_value = sd->status.skill[skill_id].lv;
+
+ if ((skill_value * 10) - 1 > stat_value)
+ skill_value += (stat_value / 10);
+ else
+ skill_value *= 2;
+
+ result = (skill_value * stat_value) / 10;
+
+ return result;
+}
+
+
+int
+skill_power_bl(struct block_list *bl, int skill)
+{
+ if (bl->type == BL_PC)
+ return skill_power((struct map_session_data *) bl, skill);
+ else
+ return 0;
+}
diff --git a/src/map/skill.c b/src/map/skill.c
index 778acea..5f0092a 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -524,7 +524,9 @@ struct skill_name_db skill_names[] = {
{ NPC_TRANSFORMATION, "TRANSFORMATION", "NPC_TRANSFORMATION" } ,
{ NPC_WATERATTACK, "WATERATTACK", "NPC_WATERATTACK" } ,
{ NPC_WINDATTACK, "WINDATTACK", "NPC_WINDATTACK" } ,
- { NV_BASIC, "BASIC", "Basic_Skill" } ,
+ { NV_EMOTE, "EMOTE", "Emote_Skill" } ,
+ { NV_TRADE, "TRADE", "Trade_Skill" } ,
+ { NV_PARTY, "PARTY", "Party_Skill" } ,
{ NV_FIRSTAID, "FIRSTAID", "First Aid" } ,
{ NV_TRICKDEAD, "TRICKDEAD", "Play_Dead" } ,
{ PA_GOSPEL, "GOSPEL", "Gospel" } ,
@@ -720,11 +722,16 @@ static int rdamage;
/* スキルデータベース */
struct skill_db skill_db[MAX_SKILL_DB];
+#define UNARMED_PLAYER_DAMAGE_MIN(bl) (skill_power_bl((bl), TMW_BRAWLING) >> 4) // +50 for 200
+#define UNARMED_PLAYER_DAMAGE_MAX(bl) (skill_power_bl((bl), TMW_BRAWLING)) // +200 for 200
+
+
int skill_get_hit( int id ){ return skill_db[id].hit; }
int skill_get_inf( int id ){ return skill_db[id].inf; }
int skill_get_pl( int id ){ return skill_db[id].pl; }
int skill_get_nk( int id ){ return skill_db[id].nk; }
int skill_get_max( int id ){ return skill_db[id].max; }
+int skill_get_max_raise( int id ){ return skill_db[id].max_raise; }
int skill_get_range( int id , int lv ){ return (lv <= 0) ? 0:skill_db[id].range[lv-1]; }
int skill_get_hp( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].hp[lv-1]; }
int skill_get_sp( int id ,int lv ){ return (lv <= 0) ? 0:skill_db[id].sp[lv-1]; }
@@ -1567,6 +1574,7 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
if(MRAND(100) < rate)
skill_addtimerskill(src,tick + 800,bl->id,0,0,skillid,skilllv,0,flag);
}
+/*
if(damage > 0 && dmg.flag&BF_SKILL && bl->type==BL_PC && pc_checkskill((struct map_session_data *)bl,RG_PLAGIARISM)){
struct map_session_data *tsd = (struct map_session_data *)bl;
nullpo_retr(0, tsd);
@@ -1587,6 +1595,7 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
clif_skillinfoblock(tsd);
}
}
+*/
/* ダメージがあるなら追加効果判定 */
if(bl->prev != NULL){
struct map_session_data *sd = (struct map_session_data *)bl;
@@ -8020,6 +8029,10 @@ int skill_status_change_timer(int tid, unsigned int tick, int id, int data)
break;
case SC_POISON:
if(sc_data[SC_SLOWPOISON].timer == -1) {
+ const int resist_poison = skill_power_bl(bl, TMW_RESIST_POISON) >> 3;
+ if (resist_poison)
+ sc_data[type].val1 -= MRAND(resist_poison + 1);
+
if( (--sc_data[type].val1) > 0) {
int hp = battle_get_max_hp(bl);
@@ -9877,6 +9890,31 @@ int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int
* 初期化系
*/
+static int
+scan_stat(char *statname)
+{
+ if (!strcmpi(statname, "str"))
+ return SP_STR;
+ if (!strcmpi(statname, "dex"))
+ return SP_DEX;
+ if (!strcmpi(statname, "agi"))
+ return SP_AGI;
+ if (!strcmpi(statname, "vit"))
+ return SP_VIT;
+ if (!strcmpi(statname, "int"))
+ return SP_INT;
+ if (!strcmpi(statname, "luk"))
+ return SP_LUK;
+ if (!strcmpi(statname, "none"))
+ return 0;
+
+ else fprintf(stderr, "Unknown stat `%s'\n", statname);
+ return 0;
+}
+
+extern void
+skill_pool_register(int id); // [Fate] Remember that a certain skill ID belongs to a pool skill
+
/*==========================================
* スキル関係ファイル読み込み
* skill_db.txt スキルデータ
@@ -9900,14 +9938,16 @@ int skill_readdb(void)
char *split[50], *split2[MAX_SKILL_LEVEL];
if(line[0]=='/' && line[1]=='/')
continue;
- for(j=0,p=line;j<14 && p;j++){
+ for(j=0,p=line;j<18 && p;j++){
while (*p == '\t' || *p == ' ') p++;
split[j]=p;
p=strchr(p,',');
if(p) *p++=0;
}
- if(split[13]==NULL || j<14)
+ if(split[17]==NULL || j<18) {
+ fprintf(stderr, "Incomplete skill db data online (%d entries)\n", j);
continue;
+ }
i=atoi(split[0]);
if(i<0 || i>MAX_SKILL_DB)
@@ -9925,10 +9965,11 @@ int skill_readdb(void)
skill_db[i].inf=atoi(split[3]);
skill_db[i].pl=atoi(split[4]);
skill_db[i].nk=atoi(split[5]);
- skill_db[i].max=atoi(split[6]);
+ skill_db[i].max_raise=atoi(split[6]);
+ skill_db[i].max=atoi(split[7]);
memset(split2,0,sizeof(split2));
- for(j=0,p=split[7];j<MAX_SKILL_LEVEL && p;j++){
+ for(j=0,p=split[8];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
@@ -9936,14 +9977,14 @@ int skill_readdb(void)
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].num[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
- if(strcmpi(split[8],"yes") == 0)
+ if(strcmpi(split[9],"yes") == 0)
skill_db[i].castcancel=1;
else
skill_db[i].castcancel=0;
skill_db[i].cast_def_rate=atoi(split[9]);
skill_db[i].inf2=atoi(split[10]);
skill_db[i].maxcount=atoi(split[11]);
- if(strcmpi(split[12],"weapon") == 0)
+ if(strcmpi(split[13],"weapon") == 0)
skill_db[i].skill_type=BF_WEAPON;
else if(strcmpi(split[12],"magic") == 0)
skill_db[i].skill_type=BF_MAGIC;
@@ -9952,13 +9993,33 @@ int skill_readdb(void)
else
skill_db[i].skill_type=0;
memset(split2,0,sizeof(split2));
- for(j=0,p=split[13];j<MAX_SKILL_LEVEL && p;j++){
+ for(j=0,p=split[14];j<MAX_SKILL_LEVEL && p;j++){
split2[j]=p;
p=strchr(p,':');
if(p) *p++=0;
}
for(k=0;k<MAX_SKILL_LEVEL;k++)
skill_db[i].blewcount[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]);
+
+ if (!strcmpi(split[15], "passive")) {
+ skill_pool_register(i);
+ skill_db[i].poolflags = SKILL_POOL_FLAG;
+ } else if (!strcmpi(split[15], "active")) {
+ skill_pool_register(i);
+ skill_db[i].poolflags = SKILL_POOL_FLAG | SKILL_POOL_ACTIVE;
+ } else
+ skill_db[i].poolflags = 0;
+
+ skill_db[i].stat = scan_stat(split[16]);
+
+ skill_names[i].desc = strdup(split[17]);
+ { // replace "_" by " "
+ char *s = skill_names[i].desc;
+ while ((s = strchr(s, '_')))
+ *s = ' ';
+ if ((s = strchr(skill_names[i].desc, '\t')) || (s = strchr (skill_names[i].desc, ' ')) || (s = strchr (skill_names[i].desc, '\n')))
+ *s = '\000';
+ }
}
fclose_(fp);
printf("read db/skill_db.txt done\n");
diff --git a/src/map/skill.h b/src/map/skill.h
index fdbe799..0f7b369 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -10,12 +10,13 @@
#define MAX_SKILL_ARROW_DB 150
#define MAX_SKILL_ABRA_DB 350
-#define QUEST_SKILL(i) ((i) >= TMW_MAGIC && (i) < TMW_MAGIC_END)
-// [Fate] A `quest skill' is a skill handled via quests, i.e., one that can't be modified via skill points.
+#define SKILL_POOL_FLAG 0x1 // is a pool skill
+#define SKILL_POOL_ACTIVE 0x2 // is an active pool skill
+#define SKILL_POOL_ACTIVATED 0x4 // pool skill has been activated (used for clif)
// スキルデータベース
struct skill_db {
- int range[MAX_SKILL_LEVEL],hit,inf,pl,nk,max;
+ int range[MAX_SKILL_LEVEL],hit,inf,pl,nk,max, stat, poolflags, max_raise; // `max' is the global max, `max_raise' is the maximum attainable via skill-ups
int num[MAX_SKILL_LEVEL];
int cast[MAX_SKILL_LEVEL],delay[MAX_SKILL_LEVEL];
int upkeep_time[MAX_SKILL_LEVEL],upkeep_time2[MAX_SKILL_LEVEL];
@@ -49,6 +50,7 @@ int skill_get_inf( int id );
int skill_get_pl( int id );
int skill_get_nk( int id );
int skill_get_max( int id );
+int skill_get_max_raise( int id );
int skill_get_range( int id , int lv );
int skill_get_hp( int id ,int lv );
int skill_get_mhp( int id ,int lv );
@@ -323,7 +325,9 @@ enum { // struct map_session_data の status_changeの番号テーブル
extern int SkillStatusChangeTable[];
enum {
- NV_BASIC = 1,
+ NV_EMOTE = 1,
+ NV_TRADE,
+ NV_PARTY,
SM_SWORD,
SM_TWOHAND,
@@ -370,7 +374,7 @@ enum {
MC_VENDING,
MC_MAMMONITE,
- AC_OWL,
+ AC_OWL = 45,
AC_VULTURE,
AC_CONCENTRATION,
AC_DOUBLE,
@@ -380,7 +384,7 @@ enum {
TF_MISS,
TF_STEAL,
TF_HIDING,
- TF_POISON, // 52
+ TF_POISON,
TF_DETOXIFY,
ALL_RESURRECTION,
@@ -677,7 +681,7 @@ enum {
DC_FORTUNEKISS,
DC_SERVICEFORYOU,
- NPC_SELFDESTRUCTION2 = 331,
+ NPC_SELFDESTRUCTION2 = 333,
WE_MALE = 334,
WE_FEMALE,
@@ -685,13 +689,22 @@ enum {
NPC_DARKCROSS = 338,
+ TMW_SKILLPOOL = 339, // skill pool size
+
TMW_MAGIC = 340,
- TMW_MAGIC_LIFE,
- TMW_MAGIC_WAR,
- TMW_MAGIC_TRANSMUTE,
- TMW_MAGIC_NATURE,
- TMW_MAGIC_ETHER,
- TMW_MAGIC_END,
+ TMW_MAGIC_LIFE = 341,
+ TMW_MAGIC_WAR = 342,
+ TMW_MAGIC_TRANSMUTE = 343,
+ TMW_MAGIC_NATURE = 344,
+ TMW_MAGIC_ETHER = 345,
+ TMW_MAGIC_DARK = 346,
+ TMW_MAGIC_LIGHT = 347,
+
+ TMW_BRAWLING = 350,
+ TMW_LUCKY_COUNTER = 351,
+ TMW_SPEED = 352,
+ TMW_RESIST_POISON = 353,
+ TMW_ASTRAL_SOUL = 354,
LK_AURABLADE = 355,
LK_PARRYING,
@@ -819,5 +832,30 @@ enum {
GD_EXTENSION,
};
+
+// [Fate] Skill pools API
+
+// Max. # of active entries in the skill pool
+#define MAX_SKILL_POOL 3
+// Max. # of skills that may be classified as pool skills in db/skill_db.txt
+#define MAX_POOL_SKILLS 128
+
+extern int skill_pool_skills[MAX_POOL_SKILLS]; // All pool skills
+extern int skill_pool_skills_size; // Number of entries in skill_pool_skills
+
+int skill_pool(struct map_session_data *sd, int *skills); // Yields all active skills in the skill pool; no more than MAX_SKILL_POOL. Return is number of skills.
+int skill_pool_size(struct map_session_data *sd);
+int skill_pool_max(struct map_session_data *sd); // Max. number of pool skills
+void skill_pool_empty(struct map_session_data *sd); // Deactivate all pool skills
+int skill_pool_activate(struct map_session_data *sd, int skill); // Skill into skill pool. Return is zero iff okay.
+int skill_pool_is_activated(struct map_session_data *sd, int skill); // Skill into skill pool. Return is zero when activated.
+int skill_pool_deactivate(struct map_session_data *sd, int skill); // Skill out of skill pool. Return is zero iff okay.
+char *skill_name(int skill); // Yield configurable skill name
+int skill_stat(int skill); // Yields the stat associated with a skill. Returns zero if none, or SP_STR, SP_VIT, ... otherwise
+int skill_power(struct map_session_data *sd, int skill); // Yields the power of a skill. This is zero if the skill is unknown or if it's a pool skill that is outside of the skill pool,
+ // otherwise a value from 0 to 255 (with 200 being the `normal maximum')
+int skill_power_bl(struct block_list *bl, int skill); // Yields the power of a skill. This is zero if the skill is unknown or if it's a pool skill that is outside of the skill pool,
+ // otherwise a value from 0 to 255 (with 200 being the `normal maximum')
+
#endif