summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/mapserver-logging67
-rw-r--r--doc/script_ref.txt22
-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
24 files changed, 844 insertions, 203 deletions
diff --git a/doc/mapserver-logging b/doc/mapserver-logging
new file mode 100644
index 0000000..e7088eb
--- /dev/null
+++ b/doc/mapserver-logging
@@ -0,0 +1,67 @@
+Log format:
+
+LOGLINE ::= int'.'int <MESSAGE>
+
+MESSAGE ::= 'log-start'
+ | 'log-start v2'
+ | 'log-start v3'
+ | <PC> <COORD> <PC-MESSAGE>
+ | <MOB> <MOB-MESSAGE>
+
+COORD ::= int':'int','int
+
+PC ::= 'PC'int
+
+MOB ::= 'MOB'int
+
+TARGET ::= <PC> | <MOB>
+
+SPELLRESULT ::= 'SUCCESS' | 'FAILURE'
+
+STATPLACE ::= 'LOGIN' | 'STATUP' | 'STATUP2' | 'STATRESET'
+
+XPPLACE ::= 'LOGIN' | 'LEVELUP'
+
+XPREASON ::= 'SCRIPTXP' 'HEALXP' 'KILLXP'
+
+ZEROTARGET ::= 'null' | <TARGET>
+
+MOB-MESSAGE ::= 'DEAD'
+
+PC-MESSAGE ::= 'WPNDMG' <TARGET> int 'FOR' int WPN int # "WPNDMG MOB01 type FOR damage WPN weapon-item"
+ | 'WPNINJURY' <TARGET> int 'FOR' int
+ | 'SPELLHEAL-INSTA' <PC> FOR int
+ | 'SPELLDMG' <MOB> FOR int BY spell-id
+ | 'CAST' spell-id <SPELLRESULT>
+ | 'STAT' int int int int int int <STATPLACE> # str agi vit int dex luk
+ | 'XP' int int ZENY int '+' int <XPPLACE> # level xp zeny bank-zeny
+ | 'MAGIC' int int int int int int 'EXP' int int 'LOGIN' # magic life war transmute nature ether magic-xp healer-xp
+ | 'SKILL-ACTIVATE' int int int # skillid skilllvl skillpower
+ | 'SKILL-UP' int int int # skillid skilllvl skillpower
+ | 'SKILL-DEACTIVATE' int
+ | 'MAGIC-ABSORB-DMG' int
+ | 'GAINXP' int <XPREASON>
+ | 'PICKUP' int int # item-id count
+ | 'INJURED-BY' <ZEROTARGET> 'FOR' int
+ | 'DEAD'
+ | 'LOGOUT'
+ | 'TRADECOMMIT' 'WITH' int 'GIVE' int 'GET' int # pc-id give-zeny get-zeny
+ | 'TRADECANCEL'
+ | 'TRADEOK'
+
+
+
+NOTES:
+------
+1. Any PICKUP between TRADECOMMIT and TRADEOK is part of the trade.
+2. TRADECOMMIT is issued for both participants in a trade.
+3. INJURED-BY seems to only duplicate information we already have.
+
+
+Illegal items
+
+645, 668, 659, 731, 734, 744, 745, 755, 756, 757, 747, 748, 721, 722
+
+Restricted access
+
+725, 726, 647, 646 \ No newline at end of file
diff --git a/doc/script_ref.txt b/doc/script_ref.txt
index 6c9f3f9..c24ac57 100644
--- a/doc/script_ref.txt
+++ b/doc/script_ref.txt
@@ -1257,6 +1257,28 @@ AthenaNPCScript
misceffect <id> <name>
Shows the effect with id on name. if name is omitted show on NPC.
+
+ getskilllist
+ Computes the set of all skills that the player has access to.
+ Results are written into @skilllist_id[], @skilllist_lv[], @skilllist_flag[],
+ which have a total of @skilllist_count entries.
+
+ getpoolskilllist
+ Same as getskilllist, but only list pool skills, and also set set
+ @skilllist_name$[] to the skills' names.
+ Note that flag & 1 here indicates that the spell is activated.
+
+ getactivatedpoolskilllist
+ Same as getpoolskilllist, but only list activated pool skills.
+
+ poolskill (skill_nr)
+ Moves the specified skill into the skill pool, if possible
+
+ unpoolskill (skill_nr)
+ Moves the specified skill out of the skill pool, if possible
+
+ checkpoolskill (skill_nr)
+ Checks whether the specified skill is in the skill pool (returns nonzero if so)
*定数ラベル
-ラベル
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 0b006c3..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) (int) (mt_random() % 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) //XpC_[EFu
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) //RZg[V
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) //RZg[V
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;
+ }
+}
+
+
// StatusChangen̏
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̕ɂU
@@ -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Ȍ̂ŏô͕ݕύX
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; //vZ
- { // [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){ /* }WbNNbV[MATKʼn */
damage = damage2 = battle_get_matk1(src); //damega,damega2oAbase_atk̎擾
}else{
damage = damage2 = battle_get_baseatk(&sd->bl); //damega,damega2oAbase_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; //ŒATKDEXŏH
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,
// ep[^𓾂
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) // `bgo
@@ -1012,13 +1010,6 @@ int map_quit(struct map_session_data *sd) {
pc_setrestartvalue(sd,2);
pc_makesavestatus(sd);
//N[XLŊoXL͏
- 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)
+
+
// ACe֘A
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 ){ // ̏mF
clif_party_inviteack(sd,tsd->status.name,0);
return 0;
}
+ printf("\tC\n");
for(i=0;i<MAX_PARTY;i++){ // AJEgmF
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�ẴX�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�����̂Ńp�[�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 ; //�]���ȊO�͒ʏ��̃X�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�ẴX�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;
/* XLf[^x[X */
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);
}
}
+*/
/* _[WȂljʔ */
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
* n
*/
+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
+
/*==========================================
* XL֌Wt@Cǂݍ
* skill_db.txt XLf[^
@@ -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)
// XLf[^x[X
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̔ԍe[u
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