From 4a778815a344a5555209dc79fa80b8fff11fbad9 Mon Sep 17 00:00:00 2001 From: Atemo Date: Tue, 7 Dec 2021 00:49:44 +0100 Subject: [PATCH] Converted mercenary_db to YAML format (#6101) * Converts the Mercenary Tables file into YAML. * Includes CSV2YAML converter. * Fixed mercenary name not properly displayed after moving Co-authored-by: Aleos Co-authored-by: Lemongrass3110 --- db/import-tmpl/mercenary_db.txt | 5 - db/import-tmpl/mercenary_db.yml | 59 + db/import-tmpl/mercenary_skill_db.txt | 5 - db/mercenary_db.txt | 71 -- db/mercenary_db.yml | 1438 +++++++++++++++++++++++++ db/mercenary_skill_db.txt | 219 ---- db/pre-re/mercenary_db.yml | 59 + db/re/mercenary_db.yml | 613 +++++++++++ db/re/mob_db.yml | 386 +++---- doc/yaml/db/mercenary_db.yml | 38 + src/map/atcommand.cpp | 4 +- src/map/battle.cpp | 2 +- src/map/clif.cpp | 37 +- src/map/map-server.vcxproj | 3 +- src/map/map.cpp | 2 +- src/map/map.hpp | 4 +- src/map/mercenary.cpp | 672 ++++++++---- src/map/mercenary.hpp | 86 +- src/map/mob.cpp | 2 +- src/map/pc.hpp | 2 +- src/map/script.cpp | 8 +- src/map/skill.cpp | 8 +- src/map/skill.hpp | 4 +- src/map/status.cpp | 10 +- src/map/status.hpp | 4 +- src/map/unit.cpp | 6 +- src/tool/csv2yaml.cpp | 122 +++ src/tool/csv2yaml.hpp | 9 + 28 files changed, 3107 insertions(+), 771 deletions(-) delete mode 100644 db/import-tmpl/mercenary_db.txt create mode 100644 db/import-tmpl/mercenary_db.yml delete mode 100644 db/import-tmpl/mercenary_skill_db.txt delete mode 100644 db/mercenary_db.txt create mode 100644 db/mercenary_db.yml delete mode 100644 db/mercenary_skill_db.txt create mode 100644 db/pre-re/mercenary_db.yml create mode 100644 db/re/mercenary_db.yml create mode 100644 doc/yaml/db/mercenary_db.yml diff --git a/db/import-tmpl/mercenary_db.txt b/db/import-tmpl/mercenary_db.txt deleted file mode 100644 index 88d543e364..0000000000 --- a/db/import-tmpl/mercenary_db.txt +++ /dev/null @@ -1,5 +0,0 @@ -// Mercenary Database -// -// Structure of Database: -// ID,Sprite_Name,Name,LV,HP,SP,Range1,ATK1,ATK2,DEF,MDEF,STR,AGI,VIT,INT,DEX,LUK,Range2,Range3,Scale,Race,Element,Speed,aDelay,aMotion,dMotion - diff --git a/db/import-tmpl/mercenary_db.yml b/db/import-tmpl/mercenary_db.yml new file mode 100644 index 0000000000..d42e464344 --- /dev/null +++ b/db/import-tmpl/mercenary_db.yml @@ -0,0 +1,59 @@ +# This file is a part of rAthena. +# Copyright(C) 2021 rAthena Development Team +# https://rathena.org - https://github.com/rathena +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +########################################################################### +# Mercenary Database +########################################################################### +# +# Mercenary Settings +# +########################################################################### +# - Id Mercenary ID. +# AegisName Server name to reference the mercenary in scripts and lookups, should use no spaces. +# Name Name in English. +# Level Level. (Default: 1) +# Hp Total HP. (Default: 1) +# Sp Total SP. (Default: 1) +# Attack Minimum attack. (Default: 0) +# Attack2 Maximum attack. (Default: 0) +# Defense Physical defense of the mercenary, reduces melee and ranged physical attack/skill damage. (Default: 0) +# MagicDefense Magic defense of the mercenary, reduces magical skill damage. (Default: 0) +# Str Strength which affects attack. (Default: 1) +# Agi Agility which affects flee. (Default: 1) +# Vit Vitality which affects defense. (Default: 1) +# Int Intelligence which affects magic attack. (Default: 1) +# Dex Dexterity which affects hit rate. (Default: 1) +# Luk Luck which affects perfect dodge/lucky flee/perfect flee/lucky dodge rate. (Default: 1) +# AttackRange Attack range. (Default: 0) +# SkillRange Skill cast range. (Default: 0) +# ChaseRange Chase range. (Default: 0) +# Size Size. (Default: Small) +# Race Race. (Default: Formless) +# Element Element. (Default: Neutral) +# ElementLevel Level of element. (Default: 1) +# WalkSpeed Walk speed. (Default: DEFAULT_WALK_SPEED) +# AttackDelay Attack speed. (Default: 4000) +# AttackMotion Attack animation speed. (Default: 2000) +# DamageMotion Damage animation speed. (Default: 0) +# Skills: List of mercenary skills. (Optional) +# - Name Skill name. +# MaxLevel Max skill level. +########################################################################### + +Header: + Type: MERCENARY_DB + Version: 1 diff --git a/db/import-tmpl/mercenary_skill_db.txt b/db/import-tmpl/mercenary_skill_db.txt deleted file mode 100644 index dceb55b863..0000000000 --- a/db/import-tmpl/mercenary_skill_db.txt +++ /dev/null @@ -1,5 +0,0 @@ -// Mercenary Skill Database -// -// Structure of Database: -// MercenryID,SkillID,SkillLevel - diff --git a/db/mercenary_db.txt b/db/mercenary_db.txt deleted file mode 100644 index 8056def27d..0000000000 --- a/db/mercenary_db.txt +++ /dev/null @@ -1,71 +0,0 @@ -// Mercenary Database -// -// Structure of Database: -// ID,Sprite_Name,Name,LV,HP,SP,Range1,ATK1,ATK2,DEF,MDEF,STR,AGI,VIT,INT,DEX,LUK,Range2,Range3,Scale,Race,Element,Speed,aDelay,aMotion,dMotion - -// Monster Mercenaries -1191,MIMIC,Mimic,51,6120,187,2,150,900,10,40,44,121,1,60,75,110,10,12,1,0,60,100,972,500,288 -1506,DISGUISE,Disguise,55,7543,180,2,279,546,18,29,0,72,45,35,48,65,10,12,1,6,82,147,516,768,384 -1275,ALICE,Alice,62,10000,221,2,550,700,5,5,64,64,42,85,100,130,10,12,1,7,60,200,502,2304,480 -1965,M_WILD_ROSE,Wild Rose,38,2980,130,2,315,360,0,15,65,85,15,35,65,80,10,12,0,2,24,100,964,864,288 -1966,M_DOPPELGANGER,Doppelganger,72,7800,200,2,1340,1590,60,35,88,90,30,35,125,65,10,12,1,6,67,100,480,480,288 -1967,M_YGNIZEM,Egnigem Cenia,58,11200,320,2,823,1212,35,8,60,35,52,18,79,20,10,12,1,7,43,145,576,432,288 -2000,M_GAMEMASTER,Male Game Master,50,7000,250,2,100,50,6,17,1,109,1,60,215,111,10,0,0,7,20,150,450,432,300 -2001,F_GAMEMASTER,Female Game Master,50,7000,250,2,100,50,6,17,1,109,1,60,215,111,10,0,0,7,20,150,450,432,300 -2034,M_DESERT_WOLF_B,Baby Desert Wolf,9,164,15,1,500,600,0,0,1,9,9,5,40,40,10,12,0,2,23,100,1600,900,240 -2037,VALKYRIE_A,Valkyrie Randgris,90,5000,15,1,10,160,10,20,1,20,40,0,20,20,10,12,1,8,66,100,576,576,480 -2038,VALKYRIE_B,Valkyrie Randgris,90,10000,15,1,300,450,10,40,1,20,80,0,80,20,10,12,1,8,66,100,576,576,480 -2058,M_MIMIC,Mimic,51,6120,182,1,800,950,10,40,44,121,1,60,75,110,10,12,1,0,60,100,972,500,288 -2059,M_DISGUISE,Disguise,55,7543,180,2,526,693,18,29,0,72,45,35,48,65,10,12,1,6,82,147,516,768,384 -2060,M_ALICE,Alice,62,10000,221,1,700,850,5,5,64,64,42,85,100,130,10,12,1,7,60,200,502,1999,480 -2213,M_WANDER_MAN,Wander Man,81,8614,220,2,1100,1300,60,20,80,110,63,51,85,90,10,12,1,6,24,100,672,500,192 -2214,M_WICKED_NYMPH,Wicked Nymph,85,6157,256,2,420,620,30,45,40,50,40,92,60,110,10,12,1,6,67,200,637,1008,360 -2215,M_KASA,Kasa,83,9815,234,2,1100,1300,60,60,85,90,71,43,85,105,10,12,2,0,63,150,800,600,288 -2216,M_SALAMANDER,Salamander,87,9517,260,2,900,1100,60,68,90,80,65,45,87,95,10,12,2,0,63,160,140,384,288 -2217,M_TEDDY_BEAR,Teddy Bear,85,14493,243,1,600,800,100,70,60,20,85,50,75,130,10,12,0,0,60,200,512,780,504 -2325,M_BAPHOMET_,Baphomet,57,7510,204,1,810,955,70,40,52,60,36,17,57,25,10,12,0,6,27,100,868,480,120 -2326,M_GALAPAGO,Galapago,45,7513,201,1,760,915,70,40,30,28,29,18,30,16,10,12,0,2,22,165,1430,1080,1080 -2342,MER_DIABOLIC,Diabolic,83,9815,234,2,1100,1300,60,60,85,90,71,43,85,105,10,12,0,6,47,150,1080,780,180 -2344,MER_WISH_MAIDEN,Wish Maiden,83,9815,234,2,1100,1300,60,60,85,90,71,43,85,105,10,12,0,6,47,150,1080,780,180 -2345,MER_ZHERLTHSH,Zherlthsh,83,9815,234,2,1100,1300,60,60,85,90,71,43,85,105,10,12,0,6,47,150,1080,780,180 -2346,MER_KTULLANUX,Ktullanux,83,9815,234,2,1100,1300,60,60,85,90,71,43,85,105,10,12,0,6,47,150,1080,780,180 -2347,MER_EDDGA,Eddga,83,9815,234,2,1100,1300,60,60,85,90,71,43,85,105,10,12,0,6,47,150,1080,780,180 -2348,MER_CIVIL_SERVANT,Civil Servant,83,9815,234,2,1100,1300,60,60,85,90,71,43,85,105,10,12,0,6,47,150,1080,780,180 -2349,MER_LOLI_RURI,Loli Ruri,83,9815,234,2,1100,1300,60,60,85,90,71,43,85,105,10,12,0,6,47,150,1080,780,180 -2350,MER_SEDORA,Sedora,83,9815,234,2,1100,1300,60,60,85,90,71,43,85,105,10,12,0,6,47,150,1080,780,180 -2351,MER_CHEPET,Chepet,83,9815,234,2,1100,1300,60,60,85,90,71,43,85,105,10,12,0,6,47,150,1080,780,180 -2378,MER_ANTLER_SCARABA,Antler Scaraba,136,30000,1,1,1418,1828,155,102,23,99,59,129,137,45,10,12,1,4,42,200,504,624,360 -2937,M_LOKI,Loki's Shadow,145,1215600,1,2,1835,2279,15,89,76,66,90,55,189,22,10,12,1,7,20,175,800,750,300 -3087,M_NYDHOG,Guardian's Alter Ego,160,215000,1,2,1835,444,15,89,76,66,90,55,189,22,10,12,1,7,20,175,800,750,300 - -// Normal Mercenaries -6017,MER_ARCHER01,Mina,20,256,200,10,170,85,7,5,1,16,5,1,28,8,10,0,0,7,20,150,700,432,300 -6018,MER_ARCHER02,Dororu,30,457,70,10,228,114,11,7,1,18,8,1,40,11,10,0,0,7,20,150,700,432,300 -6019,MER_ARCHER03,Nami,40,732,93,10,260,130,15,9,3,21,12,4,52,17,10,0,0,7,20,150,700,432,300 -6020,MER_ARCHER04,Elfin,50,1092,116,10,310,155,18,11,5,33,17,6,60,23,10,0,0,7,20,150,575,432,300 -6021,MER_ARCHER05,Clara,60,2212,280,10,360,180,20,13,5,41,17,12,75,30,10,0,0,7,20,150,575,432,300 -6022,MER_ARCHER06,Dali,70,3098,353,10,424,212,21,15,11,46,24,22,83,37,10,0,0,7,20,150,575,432,300 -6023,MER_ARCHER07,Karaya,80,4051,415,10,468,234,22,16,14,55,27,26,91,44,10,0,0,7,20,150,450,432,300 -6024,MER_ARCHER08,Hiyori,90,5039,469,10,482,241,24,18,19,65,27,27,103,49,10,0,0,7,20,150,450,432,300 -6025,MER_ARCHER09,Kero,95,5572,499,10,500,250,25,20,20,71,27,28,110,51,10,0,0,7,20,150,450,432,300 -6026,MER_ARCHER10,Sukye,99,7381,642,10,816,308,49,49,21,83,27,28,123,52,10,0,0,7,20,150,450,432,300 -6027,MER_LANCER01,Rodin,22,2071,100,2,168,84,30,1,27,1,4,1,30,2,10,0,0,7,20,150,700,432,300 -6028,MER_LANCER02,Lancer,34,2523,131,2,208,104,33,1,37,1,4,1,37,4,10,0,0,7,20,150,700,432,300 -6029,MER_LANCER03,Nathan,41,3397,161,2,248,124,36,5,45,1,22,1,40,6,10,0,0,7,20,150,700,432,300 -6030,MER_LANCER04,Roan,55,4580,191,2,300,150,39,5,55,2,35,1,50,8,10,0,0,7,20,150,575,432,300 -6031,MER_LANCER05,Orizaro,60,5899,221,2,350,160,42,10,65,2,39,1,60,10,10,0,0,7,20,150,575,432,300 -6032,MER_LANCER06,Thyla,72,7874,252,2,370,185,46,10,75,3,15,77,61,12,10,0,0,7,20,150,575,432,300 -6033,MER_LANCER07,Ben,81,10260,330,2,380,190,50,15,85,3,63,20,61,14,10,0,0,7,20,150,450,432,300 -6034,MER_LANCER08,Pinaka,90,13167,366,2,400,200,55,20,95,20,74,20,63,16,10,0,0,7,20,150,450,432,300 -6035,MER_LANCER09,Kuhlmann,95,14648,398,2,440,220,60,25,100,25,77,25,63,18,10,0,0,7,20,150,450,432,300 -6036,MER_LANCER10,Roux,99,18000,413,2,700,250,70,30,120,30,90,30,70,30,10,0,0,7,20,150,450,432,300 -6037,MER_SWORDMAN01,David,20,502,70,2,174,87,26,0,21,27,5,1,30,3,10,0,0,7,20,150,700,432,300 -6038,MER_SWORDMAN02,Ellen,30,979,99,2,258,129,31,0,26,38,6,1,35,3,10,0,0,7,20,150,700,432,300 -6039,MER_SWORDMAN03,Luise,40,1555,134,2,326,163,36,3,31,45,7,6,40,6,10,0,0,7,20,150,700,432,300 -6040,MER_SWORDMAN04,Frank,50,2397,162,2,382,191,39,5,37,59,8,6,40,6,10,0,0,7,20,150,575,432,300 -6041,MER_SWORDMAN05,Ryan,60,3387,195,2,406,203,42,7,48,68,9,6,45,9,10,0,0,7,20,150,575,432,300 -6042,MER_SWORDMAN06,Paolo,70,4495,241,2,436,218,45,12,53,79,10,12,50,9,10,0,0,7,20,150,575,432,300 -6043,MER_SWORDMAN07,Jens,80,5889,279,2,468,234,47,15,59,88,11,12,55,12,10,0,0,7,20,150,450,432,300 -6044,MER_SWORDMAN08,Thierry,90,7520,325,2,500,250,49,18,70,95,12,18,60,15,10,0,0,7,20,150,450,432,300 -6045,MER_SWORDMAN09,Steven,95,9052,348,2,524,262,51,22,80,95,18,18,60,15,10,0,0,7,20,150,450,432,300 -6046,MER_SWORDMAN10,Wayne,99,12355,451,2,760,280,64,30,99,105,30,30,60,30,10,0,0,7,20,150,450,432,300 diff --git a/db/mercenary_db.yml b/db/mercenary_db.yml new file mode 100644 index 0000000000..db58c6e3dd --- /dev/null +++ b/db/mercenary_db.yml @@ -0,0 +1,1438 @@ +# This file is a part of rAthena. +# Copyright(C) 2021 rAthena Development Team +# https://rathena.org - https://github.com/rathena +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +########################################################################### +# Mercenary Database +########################################################################### +# +# Mercenary Settings +# +########################################################################### +# - Id Mercenary ID. +# AegisName Server name to reference the mercenary in scripts and lookups, should use no spaces. +# Name Name in English. +# Level Level. (Default: 1) +# Hp Total HP. (Default: 1) +# Sp Total SP. (Default: 1) +# Attack Minimum attack. (Default: 0) +# Attack2 Maximum attack. (Default: 0) +# Defense Physical defense of the mercenary, reduces melee and ranged physical attack/skill damage. (Default: 0) +# MagicDefense Magic defense of the mercenary, reduces magical skill damage. (Default: 0) +# Str Strength which affects attack. (Default: 1) +# Agi Agility which affects flee. (Default: 1) +# Vit Vitality which affects defense. (Default: 1) +# Int Intelligence which affects magic attack. (Default: 1) +# Dex Dexterity which affects hit rate. (Default: 1) +# Luk Luck which affects perfect dodge/lucky flee/perfect flee/lucky dodge rate. (Default: 1) +# AttackRange Attack range. (Default: 0) +# SkillRange Skill cast range. (Default: 0) +# ChaseRange Chase range. (Default: 0) +# Size Size. (Default: Small) +# Race Race. (Default: Formless) +# Element Element. (Default: Neutral) +# ElementLevel Level of element. (Default: 1) +# WalkSpeed Walk speed. (Default: DEFAULT_WALK_SPEED) +# AttackDelay Attack speed. (Default: 4000) +# AttackMotion Attack animation speed. (Default: 2000) +# DamageMotion Damage animation speed. (Default: 0) +# Skills: List of mercenary skills. (Optional) +# - Name Skill name. +# MaxLevel Max skill level. +########################################################################### + +Header: + Type: MERCENARY_DB + Version: 1 + +Body: + - Id: 1191 + AegisName: MIMIC + Name: Mimic + Level: 51 + Hp: 6120 + Sp: 187 + Attack: 150 + Attack2: 900 + Defense: 10 + MagicDefense: 40 + Str: 44 + Agi: 121 + Int: 60 + Dex: 75 + Luk: 110 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Element: Neutral + ElementLevel: 3 + WalkSpeed: 100 + AttackDelay: 972 + AttackMotion: 500 + DamageMotion: 288 + Skills: + - Name: MER_AUTOBERSERK + MaxLevel: 1 + - Name: ML_AUTOGUARD + MaxLevel: 5 + - Name: MS_BASH + MaxLevel: 5 + - Id: 1506 + AegisName: DISGUISE + Name: Disguise + Level: 55 + Hp: 7543 + Sp: 180 + Attack: 279 + Attack2: 546 + Defense: 18 + MagicDefense: 29 + Str: 0 + Agi: 72 + Vit: 45 + Int: 35 + Dex: 48 + Luk: 65 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Demon + Element: Earth + ElementLevel: 4 + WalkSpeed: 147 + AttackDelay: 516 + AttackMotion: 768 + DamageMotion: 384 + Skills: + - Name: MER_QUICKEN + MaxLevel: 2 + - Name: MER_CRASH + MaxLevel: 5 + - Name: MER_LEXDIVINA + MaxLevel: 3 + - Id: 1275 + AegisName: ALICE + Name: Alice + Level: 62 + Hp: 10000 + Sp: 221 + Attack: 550 + Attack2: 700 + Defense: 5 + MagicDefense: 5 + Str: 64 + Agi: 64 + Vit: 42 + Int: 85 + Dex: 100 + Luk: 130 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Demihuman + Element: Neutral + ElementLevel: 3 + WalkSpeed: 200 + AttackDelay: 502 + AttackMotion: 2304 + DamageMotion: 480 + Skills: + - Name: MER_PROVOKE + MaxLevel: 5 + - Name: MS_MAGNUM + MaxLevel: 5 + - Name: ML_BRANDISH + MaxLevel: 5 + - Name: MER_REGAIN + MaxLevel: 1 + - Id: 1965 + AegisName: M_WILD_ROSE + Name: Wild Rose + Level: 38 + Hp: 2980 + Sp: 130 + Attack: 315 + Attack2: 360 + MagicDefense: 15 + Str: 65 + Agi: 85 + Vit: 15 + Int: 35 + Dex: 65 + Luk: 80 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Race: Brute + Element: Wind + ElementLevel: 1 + WalkSpeed: 100 + AttackDelay: 964 + AttackMotion: 864 + DamageMotion: 288 + Skills: + - Name: MS_BASH + MaxLevel: 5 + - Id: 1966 + AegisName: M_DOPPELGANGER + Name: Doppelganger + Level: 72 + Hp: 7800 + Sp: 200 + Attack: 1340 + Attack2: 1590 + Defense: 60 + MagicDefense: 35 + Str: 88 + Agi: 90 + Vit: 30 + Int: 35 + Dex: 125 + Luk: 65 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Demon + Element: Dark + ElementLevel: 3 + WalkSpeed: 100 + AttackDelay: 480 + AttackMotion: 480 + DamageMotion: 288 + Skills: + - Name: MER_QUICKEN + MaxLevel: 5 + - Name: MS_BASH + MaxLevel: 5 + - Name: ML_DEVOTION + MaxLevel: 3 + - Id: 1967 + AegisName: M_YGNIZEM + Name: Egnigem Cenia + Level: 58 + Hp: 11200 + Sp: 320 + Attack: 823 + Attack2: 1212 + Defense: 35 + MagicDefense: 8 + Str: 60 + Agi: 35 + Vit: 52 + Int: 18 + Dex: 79 + Luk: 20 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Demihuman + Element: Fire + ElementLevel: 2 + WalkSpeed: 145 + AttackDelay: 576 + AttackMotion: 432 + DamageMotion: 288 + Skills: + - Name: MER_QUICKEN + MaxLevel: 5 + - Name: MS_BASH + MaxLevel: 5 + - Name: ML_DEVOTION + MaxLevel: 3 + - Id: 2000 + AegisName: M_GAMEMASTER + Name: Male Game Master + Level: 50 + Hp: 7000 + Sp: 250 + Attack: 100 + Attack2: 50 + Defense: 6 + MagicDefense: 17 + Agi: 109 + Int: 60 + Dex: 215 + Luk: 111 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MER_REGAIN + MaxLevel: 1 + - Name: MER_TENDER + MaxLevel: 1 + - Name: MER_KYRIE + MaxLevel: 5 + - Name: MER_BLESSING + MaxLevel: 5 + - Name: MER_INCAGI + MaxLevel: 5 + - Id: 2001 + AegisName: F_GAMEMASTER + Name: Female Game Master + Level: 50 + Hp: 7000 + Sp: 250 + Attack: 100 + Attack2: 50 + Defense: 6 + MagicDefense: 17 + Agi: 109 + Int: 60 + Dex: 215 + Luk: 111 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MER_REGAIN + MaxLevel: 1 + - Name: MER_TENDER + MaxLevel: 1 + - Name: MER_KYRIE + MaxLevel: 5 + - Name: MER_BLESSING + MaxLevel: 5 + - Name: MER_INCAGI + MaxLevel: 5 + - Id: 2034 + AegisName: M_DESERT_WOLF_B + Name: Baby Desert Wolf + Level: 9 + Hp: 164 + Sp: 15 + Attack: 500 + Attack2: 600 + Agi: 9 + Vit: 9 + Int: 5 + Dex: 40 + Luk: 40 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Race: Brute + Element: Fire + ElementLevel: 1 + WalkSpeed: 100 + AttackDelay: 1600 + AttackMotion: 900 + DamageMotion: 240 + - Id: 2037 + AegisName: VALKYRIE_A + Name: Valkyrie Randgris + Level: 90 + Hp: 5000 + Sp: 15 + Attack: 10 + Attack2: 160 + Defense: 10 + MagicDefense: 20 + Agi: 20 + Vit: 40 + Int: 0 + Dex: 20 + Luk: 20 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Angel + Element: Holy + ElementLevel: 3 + WalkSpeed: 100 + AttackDelay: 576 + AttackMotion: 576 + DamageMotion: 480 + - Id: 2038 + AegisName: VALKYRIE_B + Name: Valkyrie Randgris + Level: 90 + Hp: 10000 + Sp: 15 + Attack: 300 + Attack2: 450 + Defense: 10 + MagicDefense: 40 + Agi: 20 + Vit: 80 + Int: 0 + Dex: 80 + Luk: 20 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Angel + Element: Holy + ElementLevel: 3 + WalkSpeed: 100 + AttackDelay: 576 + AttackMotion: 576 + DamageMotion: 480 + - Id: 2058 + AegisName: M_MIMIC + Name: Mimic + Level: 51 + Hp: 6120 + Sp: 182 + Attack: 800 + Attack2: 950 + Defense: 10 + MagicDefense: 40 + Str: 44 + Agi: 121 + Int: 60 + Dex: 75 + Luk: 110 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Element: Neutral + ElementLevel: 3 + WalkSpeed: 100 + AttackDelay: 972 + AttackMotion: 500 + DamageMotion: 288 + Skills: + - Name: MER_AUTOBERSERK + MaxLevel: 1 + - Name: ML_AUTOGUARD + MaxLevel: 5 + - Name: MS_BASH + MaxLevel: 5 + - Id: 2059 + AegisName: M_DISGUISE + Name: Disguise + Level: 55 + Hp: 7543 + Sp: 180 + Attack: 526 + Attack2: 693 + Defense: 18 + MagicDefense: 29 + Str: 0 + Agi: 72 + Vit: 45 + Int: 35 + Dex: 48 + Luk: 65 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Demon + Element: Earth + ElementLevel: 4 + WalkSpeed: 147 + AttackDelay: 516 + AttackMotion: 768 + DamageMotion: 384 + Skills: + - Name: MER_QUICKEN + MaxLevel: 2 + - Name: MER_CRASH + MaxLevel: 5 + - Name: MER_LEXDIVINA + MaxLevel: 3 + - Id: 2060 + AegisName: M_ALICE + Name: Alice + Level: 62 + Hp: 10000 + Sp: 221 + Attack: 700 + Attack2: 850 + Defense: 5 + MagicDefense: 5 + Str: 64 + Agi: 64 + Vit: 42 + Int: 85 + Dex: 100 + Luk: 130 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Demihuman + Element: Neutral + ElementLevel: 3 + WalkSpeed: 200 + AttackDelay: 502 + AttackMotion: 1999 + DamageMotion: 480 + Skills: + - Name: MER_PROVOKE + MaxLevel: 5 + - Name: MS_MAGNUM + MaxLevel: 5 + - Name: ML_BRANDISH + MaxLevel: 5 + - Name: MER_REGAIN + MaxLevel: 1 + - Id: 6017 + AegisName: MER_ARCHER01 + Name: Mina + Level: 20 + Hp: 256 + Sp: 200 + Attack: 170 + Attack2: 85 + Defense: 7 + MagicDefense: 5 + Agi: 16 + Vit: 5 + Dex: 28 + Luk: 8 + AttackRange: 10 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 700 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MA_DOUBLE + MaxLevel: 2 + - Name: MER_AUTOBERSERK + MaxLevel: 1 + - Id: 6018 + AegisName: MER_ARCHER02 + Name: Dororu + Level: 30 + Hp: 457 + Sp: 70 + Attack: 228 + Attack2: 114 + Defense: 11 + MagicDefense: 7 + Agi: 18 + Vit: 8 + Dex: 40 + Luk: 11 + AttackRange: 10 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 700 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MA_SHOWER + MaxLevel: 2 + - Name: MER_SIGHT + MaxLevel: 1 + - Id: 6019 + AegisName: MER_ARCHER03 + Name: Nami + Level: 40 + Hp: 732 + Sp: 93 + Attack: 260 + Attack2: 130 + Defense: 15 + MagicDefense: 9 + Str: 3 + Agi: 21 + Vit: 12 + Int: 4 + Dex: 52 + Luk: 17 + AttackRange: 10 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 700 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MA_CHARGEARROW + MaxLevel: 1 + - Name: MER_QUICKEN + MaxLevel: 1 + - Id: 6020 + AegisName: MER_ARCHER04 + Name: Elfin + Level: 50 + Hp: 1092 + Sp: 116 + Attack: 310 + Attack2: 155 + Defense: 18 + MagicDefense: 11 + Str: 5 + Agi: 33 + Vit: 17 + Int: 6 + Dex: 60 + Luk: 23 + AttackRange: 10 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 575 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MER_ESTIMATION + MaxLevel: 1 + - Name: MER_MAGNIFICAT + MaxLevel: 1 + - Name: MER_TENDER + MaxLevel: 1 + - Id: 6021 + AegisName: MER_ARCHER05 + Name: Clara + Level: 60 + Hp: 2212 + Sp: 280 + Attack: 360 + Attack2: 180 + Defense: 20 + MagicDefense: 13 + Str: 5 + Agi: 41 + Vit: 17 + Int: 12 + Dex: 75 + Luk: 30 + AttackRange: 10 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 575 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MA_DOUBLE + MaxLevel: 5 + - Name: MER_PROVOKE + MaxLevel: 1 + - Name: MA_REMOVETRAP + MaxLevel: 1 + - Id: 6022 + AegisName: MER_ARCHER06 + Name: Dali + Level: 70 + Hp: 3098 + Sp: 353 + Attack: 424 + Attack2: 212 + Defense: 21 + MagicDefense: 15 + Str: 11 + Agi: 46 + Vit: 24 + Int: 22 + Dex: 83 + Luk: 37 + AttackRange: 10 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 575 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MA_DOUBLE + MaxLevel: 7 + - Name: MA_SKIDTRAP + MaxLevel: 3 + - Name: MER_DECAGI + MaxLevel: 1 + - Id: 6023 + AegisName: MER_ARCHER07 + Name: Karaya + Level: 80 + Hp: 4051 + Sp: 415 + Attack: 468 + Attack2: 234 + Defense: 22 + MagicDefense: 16 + Str: 14 + Agi: 55 + Vit: 27 + Int: 26 + Dex: 91 + Luk: 44 + AttackRange: 10 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MA_SHOWER + MaxLevel: 10 + - Name: MER_MENTALCURE + MaxLevel: 1 + - Name: MA_FREEZINGTRAP + MaxLevel: 2 + - Id: 6024 + AegisName: MER_ARCHER08 + Name: Hiyori + Level: 90 + Hp: 5039 + Sp: 469 + Attack: 482 + Attack2: 241 + Defense: 24 + MagicDefense: 18 + Str: 19 + Agi: 65 + Vit: 27 + Int: 27 + Dex: 103 + Luk: 49 + AttackRange: 10 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MER_QUICKEN + MaxLevel: 2 + - Name: MER_PROVOKE + MaxLevel: 3 + - Name: MA_SANDMAN + MaxLevel: 3 + - Id: 6025 + AegisName: MER_ARCHER09 + Name: Kero + Level: 95 + Hp: 5572 + Sp: 499 + Attack: 500 + Attack2: 250 + Defense: 25 + MagicDefense: 20 + Str: 20 + Agi: 71 + Vit: 27 + Int: 28 + Dex: 110 + Luk: 51 + AttackRange: 10 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MA_DOUBLE + MaxLevel: 10 + - Name: MA_CHARGEARROW + MaxLevel: 1 + - Name: MA_LANDMINE + MaxLevel: 5 + - Id: 6026 + AegisName: MER_ARCHER10 + Name: Sukye + Level: 99 + Hp: 7381 + Sp: 642 + Attack: 816 + Attack2: 308 + Defense: 49 + MagicDefense: 49 + Str: 21 + Agi: 83 + Vit: 27 + Int: 28 + Dex: 123 + Luk: 52 + AttackRange: 10 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MA_CHARGEARROW + MaxLevel: 1 + - Name: MA_SHARPSHOOTING + MaxLevel: 5 + - Name: MER_QUICKEN + MaxLevel: 5 + - Name: MER_AUTOBERSERK + MaxLevel: 1 + - Id: 6027 + AegisName: MER_LANCER01 + Name: Rodin + Level: 22 + Hp: 2071 + Sp: 100 + Attack: 168 + Attack2: 84 + Defense: 30 + MagicDefense: 1 + Str: 27 + Vit: 4 + Dex: 30 + Luk: 2 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 700 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: ML_PIERCE + MaxLevel: 1 + - Name: MER_REGAIN + MaxLevel: 1 + - Id: 6028 + AegisName: MER_LANCER02 + Name: Lancer + Level: 34 + Hp: 2523 + Sp: 131 + Attack: 208 + Attack2: 104 + Defense: 33 + MagicDefense: 1 + Str: 37 + Vit: 4 + Dex: 37 + Luk: 4 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 700 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: ML_BRANDISH + MaxLevel: 2 + - Name: MER_LEXDIVINA + MaxLevel: 1 + - Id: 6029 + AegisName: MER_LANCER03 + Name: Nathan + Level: 41 + Hp: 3397 + Sp: 161 + Attack: 248 + Attack2: 124 + Defense: 36 + MagicDefense: 5 + Str: 45 + Vit: 22 + Dex: 40 + Luk: 6 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 700 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: ML_PIERCE + MaxLevel: 2 + - Name: ML_DEVOTION + MaxLevel: 1 + - Name: MER_RECUPERATE + MaxLevel: 1 + - Id: 6030 + AegisName: MER_LANCER04 + Name: Roan + Level: 55 + Hp: 4580 + Sp: 191 + Attack: 300 + Attack2: 150 + Defense: 39 + MagicDefense: 5 + Str: 55 + Agi: 2 + Vit: 35 + Dex: 50 + Luk: 8 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 575 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: ML_DEFENDER + MaxLevel: 1 + - Name: MER_CRASH + MaxLevel: 4 + - Id: 6031 + AegisName: MER_LANCER05 + Name: Orizaro + Level: 60 + Hp: 5899 + Sp: 221 + Attack: 350 + Attack2: 160 + Defense: 42 + MagicDefense: 10 + Str: 65 + Agi: 2 + Vit: 39 + Dex: 60 + Luk: 10 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 575 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: ML_PIERCE + MaxLevel: 5 + - Name: ML_AUTOGUARD + MaxLevel: 3 + - Id: 6032 + AegisName: MER_LANCER06 + Name: Thyla + Level: 72 + Hp: 7874 + Sp: 252 + Attack: 370 + Attack2: 185 + Defense: 46 + MagicDefense: 10 + Str: 75 + Agi: 3 + Vit: 15 + Int: 77 + Dex: 61 + Luk: 12 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 575 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MER_QUICKEN + MaxLevel: 2 + - Name: ML_BRANDISH + MaxLevel: 5 + - Id: 6033 + AegisName: MER_LANCER07 + Name: Ben + Level: 81 + Hp: 10260 + Sp: 330 + Attack: 380 + Attack2: 190 + Defense: 50 + MagicDefense: 15 + Str: 85 + Agi: 3 + Vit: 63 + Int: 20 + Dex: 61 + Luk: 14 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: ML_DEVOTION + MaxLevel: 1 + - Name: MER_AUTOBERSERK + MaxLevel: 1 + - Id: 6034 + AegisName: MER_LANCER08 + Name: Pinaka + Level: 90 + Hp: 13167 + Sp: 366 + Attack: 400 + Attack2: 200 + Defense: 55 + MagicDefense: 20 + Str: 95 + Agi: 20 + Vit: 74 + Int: 20 + Dex: 63 + Luk: 16 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MER_SCAPEGOAT + MaxLevel: 1 + - Name: ML_PIERCE + MaxLevel: 10 + - Name: MER_PROVOKE + MaxLevel: 5 + - Id: 6035 + AegisName: MER_LANCER09 + Name: Kuhlmann + Level: 95 + Hp: 14648 + Sp: 398 + Attack: 440 + Attack2: 220 + Defense: 60 + MagicDefense: 25 + Str: 100 + Agi: 25 + Vit: 77 + Int: 25 + Dex: 63 + Luk: 18 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: ML_BRANDISH + MaxLevel: 10 + - Name: ML_AUTOGUARD + MaxLevel: 7 + - Name: ML_DEFENDER + MaxLevel: 3 + - Id: 6036 + AegisName: MER_LANCER10 + Name: Roux + Level: 99 + Hp: 18000 + Sp: 413 + Attack: 700 + Attack2: 250 + Defense: 70 + MagicDefense: 30 + Str: 120 + Agi: 30 + Vit: 90 + Int: 30 + Dex: 70 + Luk: 30 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MER_QUICKEN + MaxLevel: 5 + - Name: ML_AUTOGUARD + MaxLevel: 10 + - Name: ML_DEVOTION + MaxLevel: 3 + - Name: ML_SPIRALPIERCE + MaxLevel: 5 + - Id: 6037 + AegisName: MER_SWORDMAN01 + Name: David + Level: 20 + Hp: 502 + Sp: 70 + Attack: 174 + Attack2: 87 + Defense: 26 + Str: 21 + Agi: 27 + Vit: 5 + Dex: 30 + Luk: 3 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 700 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MS_BASH + MaxLevel: 1 + - Name: MER_DECAGI + MaxLevel: 1 + - Id: 6038 + AegisName: MER_SWORDMAN02 + Name: Ellen + Level: 30 + Hp: 979 + Sp: 99 + Attack: 258 + Attack2: 129 + Defense: 31 + Str: 26 + Agi: 38 + Vit: 6 + Dex: 35 + Luk: 3 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 700 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MER_PROVOKE + MaxLevel: 5 + - Name: MS_MAGNUM + MaxLevel: 3 + - Id: 6039 + AegisName: MER_SWORDMAN03 + Name: Luise + Level: 40 + Hp: 1555 + Sp: 134 + Attack: 326 + Attack2: 163 + Defense: 36 + MagicDefense: 3 + Str: 31 + Agi: 45 + Vit: 7 + Int: 6 + Dex: 40 + Luk: 6 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 700 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MER_QUICKEN + MaxLevel: 1 + - Name: MER_BENEDICTION + MaxLevel: 1 + - Id: 6040 + AegisName: MER_SWORDMAN04 + Name: Frank + Level: 50 + Hp: 2397 + Sp: 162 + Attack: 382 + Attack2: 191 + Defense: 39 + MagicDefense: 5 + Str: 37 + Agi: 59 + Vit: 8 + Int: 6 + Dex: 40 + Luk: 6 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 575 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MER_CRASH + MaxLevel: 1 + - Name: MS_MAGNUM + MaxLevel: 5 + - Id: 6041 + AegisName: MER_SWORDMAN05 + Name: Ryan + Level: 60 + Hp: 3387 + Sp: 195 + Attack: 406 + Attack2: 203 + Defense: 42 + MagicDefense: 7 + Str: 48 + Agi: 68 + Vit: 9 + Int: 6 + Dex: 45 + Luk: 9 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 575 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MS_BASH + MaxLevel: 5 + - Name: MER_CRASH + MaxLevel: 4 + - Name: MER_BENEDICTION + MaxLevel: 1 + - Id: 6042 + AegisName: MER_SWORDMAN06 + Name: Paolo + Level: 70 + Hp: 4495 + Sp: 241 + Attack: 436 + Attack2: 218 + Defense: 45 + MagicDefense: 12 + Str: 53 + Agi: 79 + Vit: 10 + Int: 12 + Dex: 50 + Luk: 9 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 575 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MER_QUICKEN + MaxLevel: 5 + - Name: MER_ESTIMATION + MaxLevel: 1 + - Name: MER_DECAGI + MaxLevel: 3 + - Id: 6043 + AegisName: MER_SWORDMAN07 + Name: Jens + Level: 80 + Hp: 5889 + Sp: 279 + Attack: 468 + Attack2: 234 + Defense: 47 + MagicDefense: 15 + Str: 59 + Agi: 88 + Vit: 11 + Int: 12 + Dex: 55 + Luk: 12 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MS_BASH + MaxLevel: 10 + - Name: MER_AUTOBERSERK + MaxLevel: 1 + - Name: MER_SCAPEGOAT + MaxLevel: 1 + - Id: 6044 + AegisName: MER_SWORDMAN08 + Name: Thierry + Level: 90 + Hp: 7520 + Sp: 325 + Attack: 500 + Attack2: 250 + Defense: 49 + MagicDefense: 18 + Str: 70 + Agi: 95 + Vit: 12 + Int: 18 + Dex: 60 + Luk: 15 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MER_QUICKEN + MaxLevel: 10 + - Name: MS_BOWLINGBASH + MaxLevel: 5 + - Name: MER_COMPRESS + MaxLevel: 1 + - Name: MS_PARRYING + MaxLevel: 4 + - Id: 6045 + AegisName: MER_SWORDMAN09 + Name: Steven + Level: 95 + Hp: 9052 + Sp: 348 + Attack: 524 + Attack2: 262 + Defense: 51 + MagicDefense: 22 + Str: 80 + Agi: 95 + Vit: 18 + Int: 18 + Dex: 60 + Luk: 15 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MS_BOWLINGBASH + MaxLevel: 8 + - Name: MER_CRASH + MaxLevel: 3 + - Name: MS_REFLECTSHIELD + MaxLevel: 5 + - Id: 6046 + AegisName: MER_SWORDMAN10 + Name: Wayne + Level: 99 + Hp: 12355 + Sp: 451 + Attack: 760 + Attack2: 280 + Defense: 64 + MagicDefense: 30 + Str: 99 + Agi: 105 + Vit: 30 + Int: 30 + Dex: 60 + Luk: 30 + AttackRange: 2 + SkillRange: 10 + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 150 + AttackDelay: 450 + AttackMotion: 432 + DamageMotion: 300 + Skills: + - Name: MER_QUICKEN + MaxLevel: 10 + - Name: MS_BOWLINGBASH + MaxLevel: 10 + - Name: MS_BASH + MaxLevel: 10 + - Name: MS_BERSERK + MaxLevel: 1 + +Footer: + Imports: + - Path: db/pre-re/mercenary_db.yml + Mode: Prerenewal + - Path: db/re/mercenary_db.yml + Mode: Renewal + - Path: db/import/mercenary_db.yml diff --git a/db/mercenary_skill_db.txt b/db/mercenary_skill_db.txt deleted file mode 100644 index 8e378769e1..0000000000 --- a/db/mercenary_skill_db.txt +++ /dev/null @@ -1,219 +0,0 @@ -// Mercenary Skill Database -// -// Structure of Database: -// MercenryID,SkillID,SkillLevel - -// Archer Mercenaries Level 1-10. -// MER_ARCHER01 -6017,8207,2 //MA_DOUBLE -6017,8233,1 //MER_AUTOBERSERK -// MER_ARCHER02 -6018,8208,2 //MA_SHOWER -6018,8224,1 //MER_SIGHT -// MER_ARCHER03 -6019,8214,1 //MA_CHARGEARROW -6019,8223,1 //MER_QUICKEN -// MER_ARCHER04 -6020,8237,1 //MER_ESTIMATION -6020,8222,1 //MER_MAGNIFICAT -6020,8227,1 //MER_TENDER -// MER_ARCHER05 -6021,8207,5 //MA_DOUBLE -6021,8232,1 //MER_PROVOKE -6021,8213,1 //MA_REMOVETRAP -// MER_ARCHER06 -6022,8207,7 //MA_DOUBLE -6022,8209,3 //MA_SKIDTRAP -6022,8234,1 //MER_DECAGI -// MER_ARCHER07 -6023,8208,10 //MA_SHOWER -6023,8230,1 //MER_MENTALCURE -6023,8212,2 //MA_FREEZINGTRAP -// MER_ARCHER08 -6024,8223,2 //MER_QUICKEN -6024,8232,3 //MER_PROVOKE -6024,8211,3 //MA_SANDMAN -// MER_ARCHER09 -6025,8207,10 //MA_DOUBLE -6025,8214,1 //MA_CHARGEARROW -6025,8210,5 //MA_LANDMINE -// MER_ARCHER10 -6026,8214,1 //MA_CHARGEARROW -6026,8215,5 //MA_SHARPSHOOTING -6026,8223,5 //MER_QUICKEN -6026,8233,1 //MER_AUTOBERSERK - -// Lancer Mercenaries Level 1-10. -// MER_LANCER01 -6027,8216,1 //ML_PIERCE -6027,8226,1 //MER_REGAIN -// MER_LANCER02 -6028,8217,2 //ML_BRANDISH -6028,8236,1 //MER_LEXDIVINA -// MER_LANCER03 -6029,8216,2 //ML_PIERCE -6029,8221,1 //ML_DEVOTION -6029,8229,1 //MER_RECUPERATE -// MER_LANCER04 -6030,8219,1 //ML_DEFENDER -6030,8225,4 //MER_CRASH -// MER_LANCER05 -6031,8216,5 //ML_PIERCE -6031,8220,3 //ML_AUTOGUARD -// MER_LANCER06 -6032,8223,2 //MER_QUICKEN -6032,8217,5 //ML_BRANDISH -// MER_LANCER07 -6033,8221,1 //ML_DEVOTION -6033,8233,1 //MER_AUTOBERSERK -// MER_LANCER08 -6034,8235,1 //MER_SCAPEGOAT -6034,8216,10 //ML_PIERCE -6034,8232,5 //MER_PROVOKE -// MER_LANCER09 -6035,8217,10 //ML_BRANDISH -6035,8220,7 //ML_AUTOGUARD -6035,8219,3 //ML_DEFENDER -// MER_LANCER10 -6036,8223,5 //MER_QUICKEN -6036,8220,10 //ML_AUTOGUARD -6036,8221,3 //ML_DEVOTION -6036,8218,5 //ML_SPIRALPIERCE - -// Swordman Mercenaries Level 1-10. -// MER_SWORDMAN01 -6037,8201,1 //MS_BASH -6037,8234,1 //MER_DECAGI -// MER_SWORDMAN02 -6038,8232,5 //MER_PROVOKE -6038,8202,3 //MS_MAGNUM -// MER_SWORDMAN03 -6039,8223,1 //MER_QUICKEN -6039,8228,1 //MER_BENEDICTION -// MER_SWORDMAN04 -6040,8225,1 //MER_CRASH -6040,8202,5 //MS_MAGNUM -// MER_SWORDMAN05 -6041,8201,5 //MS_BASH -6041,8225,4 //MER_CRASH -6041,8228,1 //MER_BENEDICTION -// MER_SWORDMAN06 -6042,8223,5 //MER_QUICKEN -6042,8237,1 //MER_ESTIMATION -6042,8234,3 //MER_DECAGI -// MER_SWORDMAN07 -6043,8201,10 //MS_BASH -6043,8233,1 //MER_AUTOBERSERK -6043,8235,1 //MER_SCAPEGOAT -// MER_SWORDMAN08 -6044,8223,10 //MER_QUICKEN -6044,8203,5 //MS_BOWLINGABASH -6044,8231,1 //MER_COMPRESS -6044,8204,4 //MS_PARRYING -// MER_SWORDMAN09 -6045,8203,8 //MS_BOWLINGABASH -6045,8225,3 //MER_CRASH -6045,8205,5 //MS_REFLECTSHIELD -// MER_SWORDMAN10 -6046,8223,10 //MER_QUICKEN -6046,8203,10 //MS_BOWLINGABASH -6046,8201,10 //MS_BASH -6046,8206,1 //MS_BERSERK - -// Monster Mercenaries -// MIMIC -1191,8233,1 //MER_AUTOBERSERK -1191,8220,5 //ML_AUTOGUARD -1191,8201,5 //MS_BASH -// DISGUISE -1506,8223,2 //MER_QUICKEN -1506,8225,5 //MER_CRASH -1506,8236,3 //MER_LEXDIVINA -// ALICE -1275,8232,5 //MER_PROVOKE -1275,8202,5 //MS_MAGNUM -1275,8217,5 //ML_BRANDISH -1275,8226,1 //MER_REGAIN -// M_WILD_ROSE -1965,8201,5 //MS_BASH -// M_DOPPELGANGER -1966,8223,5 //MER_QUICKEN -1966,8201,5 //MS_BASH -1966,8221,3 //ML_DEVOTION -// M_YGNIZEM -1967,8223,5 //MER_QUICKEN -1967,8201,5 //MS_BASH -1967,8221,3 //ML_DEVOTION -// M_GAMEMASTER -2000,8226,1 //MER_REGAIN -2000,8227,1 //MER_TENDER -2000,8238,5 //MER_KYRIE -2000,8239,5 //MER_BLESSING -2000,8240,5 //MER_INCAGI -// F_GAMEMASTER -2001,8226,1 //MER_REGAIN -2001,8227,1 //MER_TENDER -2001,8238,5 //MER_KYRIE -2001,8239,5 //MER_BLESSING -2001,8240,5 //MER_INCAGI -// M_MIMIC -2058,8233,1 //MER_AUTOBERSERK -2058,8220,5 //ML_AUTOGUARD -2058,8201,5 //MS_BASH -// M_DISGUISE -2059,8223,2 //MER_QUICKEN -2059,8225,5 //MER_CRASH -2059,8236,3 //MER_LEXDIVINA -// M_ALICE -2060,8232,5 //MER_PROVOKE -2060,8202,5 //MS_MAGNUM -2060,8217,5 //ML_BRANDISH -2060,8226,1 //MER_REGAIN -// M_WANDER_MAN -2213,8223,10 //MER_QUICKEN -2213,8204,4 //MS_PARRYING -2213,8233,1 //MER_AUTOBERSERK -2213,8203,5 //MS_BOWLINGBASH -// M_WICKED_NYMPH -2214,8236,3 //MER_LEXDIVINA -2214,8239,5 //MER_BLESSING -2214,8227,1 //MER_TENDER -2214,8222,1 //MER_MAGNIFICAT -// M_KASA -2215,8225,5 //MER_CRASH -2215,8202,5 //MS_MAGNUM -2215,8226,1 //MER_REGAIN -2215,8233,1 //MER_AUTOBERSERK -// M_SALAMANDER -2216,8201,5 //MS_BASH -2216,8217,5 //ML_BRANDISH -2216,8233,1 //MER_AUTOBERSERK -2216,8228,1 //MER_BENEDICTION -// M_TEDDY_BEAR -2217,8221,3 //ML_DEVOTION -2217,8226,1 //MER_REGAIN -2217,8219,1 //ML_DEFENDER -2217,8235,1 //MER_SCAPEGOAT -// M_BAPHOMET_ -2325,8201,5 //MS_BASH -2325,8223,10 //MER_QUICKEN -// M_GALAPAGO -2326,8239,5 //MER_BLESSING -//2326,28,5 //AL_HEAL -// MER_DIABOLIC -2342,8225,5 //MER_CRASH -2342,8202,5 //MS_MAGNUM -2342,8226,1 //MER_REGAIN -2342,8233,1 //MER_AUTOBERSERK -// MER_ZHERLTHSH -2345,8225,5 //MER_CRASH -2345,8202,5 //MS_MAGNUM -2345,8226,1 //MER_REGAIN -2345,8233,1 //MER_AUTOBERSERK -// MER_EDDGA -2347,8225,5 //MER_CRASH -2347,8202,5 //MS_MAGNUM -2347,8226,1 //MER_REGAIN -2347,8233,1 //MER_AUTOBERSERK -// M_LOKI -2937,8241,1 //MER_INVINCIBLEOFF2 diff --git a/db/pre-re/mercenary_db.yml b/db/pre-re/mercenary_db.yml new file mode 100644 index 0000000000..d42e464344 --- /dev/null +++ b/db/pre-re/mercenary_db.yml @@ -0,0 +1,59 @@ +# This file is a part of rAthena. +# Copyright(C) 2021 rAthena Development Team +# https://rathena.org - https://github.com/rathena +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +########################################################################### +# Mercenary Database +########################################################################### +# +# Mercenary Settings +# +########################################################################### +# - Id Mercenary ID. +# AegisName Server name to reference the mercenary in scripts and lookups, should use no spaces. +# Name Name in English. +# Level Level. (Default: 1) +# Hp Total HP. (Default: 1) +# Sp Total SP. (Default: 1) +# Attack Minimum attack. (Default: 0) +# Attack2 Maximum attack. (Default: 0) +# Defense Physical defense of the mercenary, reduces melee and ranged physical attack/skill damage. (Default: 0) +# MagicDefense Magic defense of the mercenary, reduces magical skill damage. (Default: 0) +# Str Strength which affects attack. (Default: 1) +# Agi Agility which affects flee. (Default: 1) +# Vit Vitality which affects defense. (Default: 1) +# Int Intelligence which affects magic attack. (Default: 1) +# Dex Dexterity which affects hit rate. (Default: 1) +# Luk Luck which affects perfect dodge/lucky flee/perfect flee/lucky dodge rate. (Default: 1) +# AttackRange Attack range. (Default: 0) +# SkillRange Skill cast range. (Default: 0) +# ChaseRange Chase range. (Default: 0) +# Size Size. (Default: Small) +# Race Race. (Default: Formless) +# Element Element. (Default: Neutral) +# ElementLevel Level of element. (Default: 1) +# WalkSpeed Walk speed. (Default: DEFAULT_WALK_SPEED) +# AttackDelay Attack speed. (Default: 4000) +# AttackMotion Attack animation speed. (Default: 2000) +# DamageMotion Damage animation speed. (Default: 0) +# Skills: List of mercenary skills. (Optional) +# - Name Skill name. +# MaxLevel Max skill level. +########################################################################### + +Header: + Type: MERCENARY_DB + Version: 1 diff --git a/db/re/mercenary_db.yml b/db/re/mercenary_db.yml new file mode 100644 index 0000000000..d77fa3c988 --- /dev/null +++ b/db/re/mercenary_db.yml @@ -0,0 +1,613 @@ +# This file is a part of rAthena. +# Copyright(C) 2021 rAthena Development Team +# https://rathena.org - https://github.com/rathena +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +########################################################################### +# Mercenary Database +########################################################################### +# +# Mercenary Settings +# +########################################################################### +# - Id Mercenary ID. +# AegisName Server name to reference the mercenary in scripts and lookups, should use no spaces. +# Name Name in English. +# Level Level. (Default: 1) +# Hp Total HP. (Default: 1) +# Sp Total SP. (Default: 1) +# Attack Minimum attack. (Default: 0) +# Attack2 Maximum attack. (Default: 0) +# Defense Physical defense of the mercenary, reduces melee and ranged physical attack/skill damage. (Default: 0) +# MagicDefense Magic defense of the mercenary, reduces magical skill damage. (Default: 0) +# Str Strength which affects attack. (Default: 1) +# Agi Agility which affects flee. (Default: 1) +# Vit Vitality which affects defense. (Default: 1) +# Int Intelligence which affects magic attack. (Default: 1) +# Dex Dexterity which affects hit rate. (Default: 1) +# Luk Luck which affects perfect dodge/lucky flee/perfect flee/lucky dodge rate. (Default: 1) +# AttackRange Attack range. (Default: 0) +# SkillRange Skill cast range. (Default: 0) +# ChaseRange Chase range. (Default: 0) +# Size Size. (Default: Small) +# Race Race. (Default: Formless) +# Element Element. (Default: Neutral) +# ElementLevel Level of element. (Default: 1) +# WalkSpeed Walk speed. (Default: DEFAULT_WALK_SPEED) +# AttackDelay Attack speed. (Default: 4000) +# AttackMotion Attack animation speed. (Default: 2000) +# DamageMotion Damage animation speed. (Default: 0) +# Skills: List of mercenary skills. (Optional) +# - Name Skill name. +# MaxLevel Max skill level. +########################################################################### + +Header: + Type: MERCENARY_DB + Version: 1 + +Body: + - Id: 2213 + AegisName: M_WANDER_MAN + Name: Wander Man + Level: 81 + Hp: 8614 + Sp: 220 + Attack: 1100 + Attack2: 1300 + Defense: 60 + MagicDefense: 20 + Str: 80 + Agi: 110 + Vit: 63 + Int: 51 + Dex: 85 + Luk: 90 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Demon + Element: Wind + ElementLevel: 1 + WalkSpeed: 100 + AttackDelay: 672 + AttackMotion: 500 + DamageMotion: 192 + Skills: + - Name: MER_QUICKEN + MaxLevel: 10 + - Name: MS_PARRYING + MaxLevel: 4 + - Name: MER_AUTOBERSERK + MaxLevel: 1 + - Name: MS_BOWLINGBASH + MaxLevel: 5 + - Id: 2214 + AegisName: M_WICKED_NYMPH + Name: Wicked Nymph + Level: 85 + Hp: 6157 + Sp: 256 + Attack: 420 + Attack2: 620 + Defense: 30 + MagicDefense: 45 + Str: 40 + Agi: 50 + Vit: 40 + Int: 92 + Dex: 60 + Luk: 110 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Demon + Element: Dark + ElementLevel: 3 + WalkSpeed: 200 + AttackDelay: 637 + AttackMotion: 1008 + DamageMotion: 360 + Skills: + - Name: MER_LEXDIVINA + MaxLevel: 3 + - Name: MER_BLESSING + MaxLevel: 5 + - Name: MER_TENDER + MaxLevel: 1 + - Name: MER_MAGNIFICAT + MaxLevel: 1 + - Id: 2215 + AegisName: M_KASA + Name: Kasa + Level: 83 + Hp: 9815 + Sp: 234 + Attack: 1100 + Attack2: 1300 + Defense: 60 + MagicDefense: 60 + Str: 85 + Agi: 90 + Vit: 71 + Int: 43 + Dex: 85 + Luk: 105 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Size: Large + Element: Fire + ElementLevel: 3 + WalkSpeed: 150 + AttackDelay: 800 + AttackMotion: 600 + DamageMotion: 288 + Skills: + - Name: MER_CRASH + MaxLevel: 5 + - Name: MS_MAGNUM + MaxLevel: 5 + - Name: MER_REGAIN + MaxLevel: 1 + - Name: MER_AUTOBERSERK + MaxLevel: 1 + - Id: 2216 + AegisName: M_SALAMANDER + Name: Salamander + Level: 87 + Hp: 9517 + Sp: 260 + Attack: 900 + Attack2: 1100 + Defense: 60 + MagicDefense: 68 + Str: 90 + Agi: 80 + Vit: 65 + Int: 45 + Dex: 87 + Luk: 95 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Size: Large + Element: Fire + ElementLevel: 3 + WalkSpeed: 160 + AttackDelay: 140 + AttackMotion: 384 + DamageMotion: 288 + Skills: + - Name: MS_BASH + MaxLevel: 5 + - Name: ML_BRANDISH + MaxLevel: 5 + - Name: MER_AUTOBERSERK + MaxLevel: 1 + - Name: MER_BENEDICTION + MaxLevel: 1 + - Id: 2217 + AegisName: M_TEDDY_BEAR + Name: Teddy Bear + Level: 85 + Hp: 14493 + Sp: 243 + Attack: 600 + Attack2: 800 + Defense: 100 + MagicDefense: 70 + Str: 60 + Agi: 20 + Vit: 85 + Int: 50 + Dex: 75 + Luk: 130 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Element: Neutral + ElementLevel: 3 + WalkSpeed: 200 + AttackDelay: 512 + AttackMotion: 780 + DamageMotion: 504 + Skills: + - Name: ML_DEVOTION + MaxLevel: 3 + - Name: MER_REGAIN + MaxLevel: 1 + - Name: ML_DEFENDER + MaxLevel: 1 + - Name: MER_SCAPEGOAT + MaxLevel: 1 + - Id: 2325 + AegisName: M_BAPHOMET_ + Name: Baphomet + Level: 57 + Hp: 7510 + Sp: 204 + Attack: 810 + Attack2: 955 + Defense: 70 + MagicDefense: 40 + Str: 52 + Agi: 60 + Vit: 36 + Int: 17 + Dex: 57 + Luk: 25 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Race: Demon + Element: Dark + ElementLevel: 1 + WalkSpeed: 100 + AttackDelay: 868 + AttackMotion: 480 + DamageMotion: 120 + Skills: + - Name: MS_BASH + MaxLevel: 5 + - Name: MER_QUICKEN + MaxLevel: 10 + - Id: 2326 + AegisName: M_GALAPAGO + Name: Galapago + Level: 45 + Hp: 7513 + Sp: 201 + Attack: 760 + Attack2: 915 + Defense: 70 + MagicDefense: 40 + Str: 30 + Agi: 28 + Vit: 29 + Int: 18 + Dex: 30 + Luk: 16 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Race: Brute + Element: Earth + ElementLevel: 1 + WalkSpeed: 165 + AttackDelay: 1430 + AttackMotion: 1080 + DamageMotion: 1080 + Skills: + - Name: MER_BLESSING + MaxLevel: 5 + - Id: 2342 + AegisName: MER_DIABOLIC + Name: Diabolic + Level: 83 + Hp: 9815 + Sp: 234 + Attack: 1100 + Attack2: 1300 + Defense: 60 + MagicDefense: 60 + Str: 85 + Agi: 90 + Vit: 71 + Int: 43 + Dex: 85 + Luk: 105 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Race: Demon + Element: Dark + ElementLevel: 2 + WalkSpeed: 150 + AttackDelay: 1080 + AttackMotion: 780 + DamageMotion: 180 + Skills: + - Name: MER_CRASH + MaxLevel: 5 + - Name: MS_MAGNUM + MaxLevel: 5 + - Name: MER_REGAIN + MaxLevel: 1 + - Name: MER_AUTOBERSERK + MaxLevel: 1 + - Id: 2344 + AegisName: MER_WISH_MAIDEN + Name: Wish Maiden + Level: 83 + Hp: 9815 + Sp: 234 + Attack: 1100 + Attack2: 1300 + Defense: 60 + MagicDefense: 60 + Str: 85 + Agi: 90 + Vit: 71 + Int: 43 + Dex: 85 + Luk: 105 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Race: Demon + Element: Dark + ElementLevel: 2 + WalkSpeed: 150 + AttackDelay: 1080 + AttackMotion: 780 + DamageMotion: 180 + - Id: 2345 + AegisName: MER_ZHERLTHSH + Name: Zherlthsh + Level: 83 + Hp: 9815 + Sp: 234 + Attack: 1100 + Attack2: 1300 + Defense: 60 + MagicDefense: 60 + Str: 85 + Agi: 90 + Vit: 71 + Int: 43 + Dex: 85 + Luk: 105 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Race: Demon + Element: Dark + ElementLevel: 2 + WalkSpeed: 150 + AttackDelay: 1080 + AttackMotion: 780 + DamageMotion: 180 + Skills: + - Name: MER_CRASH + MaxLevel: 5 + - Name: MS_MAGNUM + MaxLevel: 5 + - Name: MER_REGAIN + MaxLevel: 1 + - Name: MER_AUTOBERSERK + MaxLevel: 1 + - Id: 2346 + AegisName: MER_KTULLANUX + Name: Ktullanux + Level: 83 + Hp: 9815 + Sp: 234 + Attack: 1100 + Attack2: 1300 + Defense: 60 + MagicDefense: 60 + Str: 85 + Agi: 90 + Vit: 71 + Int: 43 + Dex: 85 + Luk: 105 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Race: Demon + Element: Dark + ElementLevel: 2 + WalkSpeed: 150 + AttackDelay: 1080 + AttackMotion: 780 + DamageMotion: 180 + - Id: 2347 + AegisName: MER_EDDGA + Name: Eddga + Level: 83 + Hp: 9815 + Sp: 234 + Attack: 1100 + Attack2: 1300 + Defense: 60 + MagicDefense: 60 + Str: 85 + Agi: 90 + Vit: 71 + Int: 43 + Dex: 85 + Luk: 105 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Race: Demon + Element: Dark + ElementLevel: 2 + WalkSpeed: 150 + AttackDelay: 1080 + AttackMotion: 780 + DamageMotion: 180 + Skills: + - Name: MER_CRASH + MaxLevel: 5 + - Name: MS_MAGNUM + MaxLevel: 5 + - Name: MER_REGAIN + MaxLevel: 1 + - Name: MER_AUTOBERSERK + MaxLevel: 1 + - Id: 2348 + AegisName: MER_CIVIL_SERVANT + Name: Civil Servant + Level: 83 + Hp: 9815 + Sp: 234 + Attack: 1100 + Attack2: 1300 + Defense: 60 + MagicDefense: 60 + Str: 85 + Agi: 90 + Vit: 71 + Int: 43 + Dex: 85 + Luk: 105 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Race: Demon + Element: Dark + ElementLevel: 2 + WalkSpeed: 150 + AttackDelay: 1080 + AttackMotion: 780 + DamageMotion: 180 + - Id: 2349 + AegisName: MER_LOLI_RURI + Name: Loli Ruri + Level: 83 + Hp: 9815 + Sp: 234 + Attack: 1100 + Attack2: 1300 + Defense: 60 + MagicDefense: 60 + Str: 85 + Agi: 90 + Vit: 71 + Int: 43 + Dex: 85 + Luk: 105 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Race: Demon + Element: Dark + ElementLevel: 2 + WalkSpeed: 150 + AttackDelay: 1080 + AttackMotion: 780 + DamageMotion: 180 + - Id: 2350 + AegisName: MER_SEDORA + Name: Sedora + Level: 83 + Hp: 9815 + Sp: 234 + Attack: 1100 + Attack2: 1300 + Defense: 60 + MagicDefense: 60 + Str: 85 + Agi: 90 + Vit: 71 + Int: 43 + Dex: 85 + Luk: 105 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Race: Demon + Element: Dark + ElementLevel: 2 + WalkSpeed: 150 + AttackDelay: 1080 + AttackMotion: 780 + DamageMotion: 180 + - Id: 2351 + AegisName: MER_CHEPET + Name: Chepet + Level: 83 + Hp: 9815 + Sp: 234 + Attack: 1100 + Attack2: 1300 + Defense: 60 + MagicDefense: 60 + Str: 85 + Agi: 90 + Vit: 71 + Int: 43 + Dex: 85 + Luk: 105 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Race: Demon + Element: Dark + ElementLevel: 2 + WalkSpeed: 150 + AttackDelay: 1080 + AttackMotion: 780 + DamageMotion: 180 + - Id: 2378 + AegisName: MER_ANTLER_SCARABA + Name: Antler Scaraba + Level: 136 + Hp: 30000 + Attack: 1418 + Attack2: 1828 + Defense: 155 + MagicDefense: 102 + Str: 23 + Agi: 99 + Vit: 59 + Int: 129 + Dex: 137 + Luk: 45 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Insect + Element: Earth + ElementLevel: 2 + WalkSpeed: 200 + AttackDelay: 504 + AttackMotion: 624 + DamageMotion: 360 + - Id: 2937 + AegisName: M_LOKI + Name: Loki's Shadow + Level: 145 + Hp: 1215600 + Attack: 1835 + Attack2: 2279 + Defense: 15 + MagicDefense: 89 + Str: 76 + Agi: 66 + Vit: 90 + Int: 55 + Dex: 189 + Luk: 22 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 175 + AttackDelay: 800 + AttackMotion: 750 + DamageMotion: 300 + Skills: + - Name: MER_INVINCIBLEOFF2 + MaxLevel: 1 diff --git a/db/re/mob_db.yml b/db/re/mob_db.yml index de9ccc1733..b94ef11bce 100644 --- a/db/re/mob_db.yml +++ b/db/re/mob_db.yml @@ -40946,32 +40946,32 @@ Body: Drops: - Item: Gold_Tulip Rate: 10000 -# - Id: 2034 -# AegisName: M_DESERT_WOLF_B -# Name: Baby Desert Wolf -# Level: 9 -# Hp: 164 -# Sp: 15 -# Attack: 500 -# Attack2: 600 -# Agi: 9 -# Vit: 9 -# Int: 5 -# Dex: 40 -# Luk: 40 -# AttackRange: 1 -# SkillRange: 10 -# ChaseRange: 12 -# Size: Small -# Race: Brute -# Element: Fire -# ElementLevel: 1 -# WalkSpeed: 100 -# AttackDelay: 1600 -# AttackMotion: 900 -# DamageMotion: 240 -# Modes: -# NoRandomWalk: true + - Id: 2034 + AegisName: M_DESERT_WOLF_B + Name: Baby Desert Wolf + Level: 9 + Hp: 164 + Sp: 15 + Attack: 500 + Attack2: 600 + Agi: 9 + Vit: 9 + Int: 5 + Dex: 40 + Luk: 40 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Size: Small + Race: Brute + Element: Fire + ElementLevel: 1 + WalkSpeed: 100 + AttackDelay: 1600 + AttackMotion: 900 + DamageMotion: 240 + Modes: + NoRandomWalk: true - Id: 2035 AegisName: NIHILITY_ZEM Name: Nihility Zem @@ -41026,60 +41026,60 @@ Body: - Item: Broken_Horn_Pipe Rate: 2500 StealProtected: true -# - Id: 2037 -# AegisName: VALKYRIE_A -# Name: Valkyrie Randgris -# Level: 90 -# Hp: 5500 -# Sp: 15 -# Attack: 10 -# Attack2: 160 -# Defense: 16 -# MagicDefense: 20 -# Agi: 20 -# Vit: 40 -# Dex: 20 -# Luk: 20 -# AttackRange: 1 -# SkillRange: 10 -# ChaseRange: 12 -# Size: Medium -# Race: Angel -# Element: Holy -# ElementLevel: 3 -# WalkSpeed: 100 -# AttackDelay: 576 -# AttackMotion: 576 -# DamageMotion: 480 -# Modes: -# NoRandomWalk: true -# - Id: 2038 -# AegisName: VALKYRIE_B -# Name: Valkyrie Randgris -# Level: 90 -# Hp: 10500 -# Sp: 15 -# Attack: 300 -# Attack2: 450 -# Defense: 16 -# MagicDefense: 40 -# Agi: 20 -# Vit: 80 -# Dex: 80 -# Luk: 20 -# AttackRange: 1 -# SkillRange: 10 -# ChaseRange: 12 -# Size: Medium -# Race: Angel -# Element: Holy -# ElementLevel: 3 -# WalkSpeed: 100 -# AttackDelay: 576 -# AttackMotion: 576 -# DamageMotion: 480 -# Modes: -# NoRandomWalk: true + - Id: 2037 + AegisName: VALKYRIE_A + Name: Valkyrie Randgris + Level: 90 + Hp: 5500 + Sp: 15 + Attack: 10 + Attack2: 160 + Defense: 16 + MagicDefense: 20 + Agi: 20 + Vit: 40 + Dex: 20 + Luk: 20 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Angel + Element: Holy + ElementLevel: 3 + WalkSpeed: 100 + AttackDelay: 576 + AttackMotion: 576 + DamageMotion: 480 + Modes: + NoRandomWalk: true + - Id: 2038 + AegisName: VALKYRIE_B + Name: Valkyrie Randgris + Level: 90 + Hp: 10500 + Sp: 15 + Attack: 300 + Attack2: 450 + Defense: 16 + MagicDefense: 40 + Agi: 20 + Vit: 80 + Dex: 80 + Luk: 20 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Angel + Element: Holy + ElementLevel: 3 + WalkSpeed: 100 + AttackDelay: 576 + AttackMotion: 576 + DamageMotion: 480 + Modes: + NoRandomWalk: true - Id: 2039 AegisName: EXECUTIONER_R Name: Executioner @@ -41661,91 +41661,91 @@ Body: AttackMotion: 500 DamageMotion: 1000 Ai: 09 -# - Id: 2058 -# AegisName: M_MIMIC -# Name: Mimic -# Level: 51 -# Hp: 6120 -# Sp: 182 -# Attack: 800 -# Attack2: 950 -# Defense: 10 -# MagicDefense: 40 -# Str: 44 -# Agi: 121 -# Int: 60 -# Dex: 75 -# Luk: 110 -# AttackRange: 1 -# SkillRange: 10 -# ChaseRange: 12 -# Size: Medium -# Race: Formless -# Element: Neutral -# ElementLevel: 3 -# WalkSpeed: 100 -# AttackDelay: 972 -# AttackMotion: 500 -# DamageMotion: 288 -# Modes: -# NoRandomWalk: true -# - Id: 2059 -# AegisName: M_DISGUISE -# Name: Disguise -# Level: 55 -# Hp: 7543 -# Sp: 180 -# Attack: 526 -# Attack2: 693 -# Defense: 18 -# MagicDefense: 29 -# Agi: 72 -# Vit: 45 -# Int: 35 -# Dex: 48 -# Luk: 65 -# AttackRange: 2 -# SkillRange: 10 -# ChaseRange: 12 -# Size: Medium -# Race: Demon -# Element: Earth -# ElementLevel: 4 -# WalkSpeed: 147 -# AttackDelay: 516 -# AttackMotion: 768 -# DamageMotion: 384 -# Modes: -# NoRandomWalk: true -# - Id: 2060 -# AegisName: M_ALICE -# Name: Alice -# Level: 62 -# Hp: 10000 -# Sp: 221 -# Attack: 700 -# Attack2: 850 -# Defense: 5 -# MagicDefense: 5 -# Str: 64 -# Agi: 64 -# Vit: 42 -# Int: 85 -# Dex: 100 -# Luk: 130 -# AttackRange: 1 -# SkillRange: 10 -# ChaseRange: 12 -# Size: Medium -# Race: Demihuman -# Element: Neutral -# ElementLevel: 3 -# WalkSpeed: 200 -# AttackDelay: 502 -# AttackMotion: 1999 -# DamageMotion: 480 -# Modes: -# NoRandomWalk: true + - Id: 2058 + AegisName: M_MIMIC + Name: Mimic + Level: 51 + Hp: 6120 + Sp: 182 + Attack: 800 + Attack2: 950 + Defense: 10 + MagicDefense: 40 + Str: 44 + Agi: 121 + Int: 60 + Dex: 75 + Luk: 110 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Formless + Element: Neutral + ElementLevel: 3 + WalkSpeed: 100 + AttackDelay: 972 + AttackMotion: 500 + DamageMotion: 288 + Modes: + NoRandomWalk: true + - Id: 2059 + AegisName: M_DISGUISE + Name: Disguise + Level: 55 + Hp: 7543 + Sp: 180 + Attack: 526 + Attack2: 693 + Defense: 18 + MagicDefense: 29 + Agi: 72 + Vit: 45 + Int: 35 + Dex: 48 + Luk: 65 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Demon + Element: Earth + ElementLevel: 4 + WalkSpeed: 147 + AttackDelay: 516 + AttackMotion: 768 + DamageMotion: 384 + Modes: + NoRandomWalk: true + - Id: 2060 + AegisName: M_ALICE + Name: Alice + Level: 62 + Hp: 10000 + Sp: 221 + Attack: 700 + Attack2: 850 + Defense: 5 + MagicDefense: 5 + Str: 64 + Agi: 64 + Vit: 42 + Int: 85 + Dex: 100 + Luk: 130 + AttackRange: 1 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Demihuman + Element: Neutral + ElementLevel: 3 + WalkSpeed: 200 + AttackDelay: 502 + AttackMotion: 1999 + DamageMotion: 480 + Modes: + NoRandomWalk: true # - Id: 2061 # AegisName: E_STAPO # Name: Stapo @@ -74745,34 +74745,34 @@ Body: - Item: Halloween_Coin Rate: 10000 StealProtected: true -# - Id: 2937 -# AegisName: M_LOKI -# Name: M Loki -# Level: 145 -# Hp: 1215600 -# BaseExp: 1 -# JobExp: 1 -# Attack: 1835 -# Attack2: 444 -# Defense: 15 -# MagicDefense: 89 -# Str: 76 -# Agi: 66 -# Vit: 90 -# Int: 55 -# Dex: 189 -# Luk: 22 -# AttackRange: 2 -# SkillRange: 10 -# ChaseRange: 12 -# Size: Medium -# Race: Demihuman -# Element: Neutral -# ElementLevel: 1 -# WalkSpeed: 175 -# AttackDelay: 800 -# AttackMotion: 750 -# DamageMotion: 300 + - Id: 2937 + AegisName: M_LOKI + Name: M Loki + Level: 145 + Hp: 1215600 + BaseExp: 1 + JobExp: 1 + Attack: 1835 + Attack2: 444 + Defense: 15 + MagicDefense: 89 + Str: 76 + Agi: 66 + Vit: 90 + Int: 55 + Dex: 189 + Luk: 22 + AttackRange: 2 + SkillRange: 10 + ChaseRange: 12 + Size: Medium + Race: Demihuman + Element: Neutral + ElementLevel: 1 + WalkSpeed: 175 + AttackDelay: 800 + AttackMotion: 750 + DamageMotion: 300 - Id: 2938 AegisName: MM_MAGIC_SEAL Name: Magic Seal diff --git a/doc/yaml/db/mercenary_db.yml b/doc/yaml/db/mercenary_db.yml new file mode 100644 index 0000000000..bbdb5ea141 --- /dev/null +++ b/doc/yaml/db/mercenary_db.yml @@ -0,0 +1,38 @@ +########################################################################### +# Mercenary Database +########################################################################### +# +# Mercenary Settings +# +########################################################################### +# - Id Mercenary ID. +# AegisName Server name to reference the mercenary in scripts and lookups, should use no spaces. +# Name Name in English. +# Level Level. (Default: 1) +# Hp Total HP. (Default: 1) +# Sp Total SP. (Default: 1) +# Attack Minimum attack. (Default: 0) +# Attack2 Maximum attack. (Default: 0) +# Defense Physical defense of the mercenary, reduces melee and ranged physical attack/skill damage. (Default: 0) +# MagicDefense Magic defense of the mercenary, reduces magical skill damage. (Default: 0) +# Str Strength which affects attack. (Default: 1) +# Agi Agility which affects flee. (Default: 1) +# Vit Vitality which affects defense. (Default: 1) +# Int Intelligence which affects magic attack. (Default: 1) +# Dex Dexterity which affects hit rate. (Default: 1) +# Luk Luck which affects perfect dodge/lucky flee/perfect flee/lucky dodge rate. (Default: 1) +# AttackRange Attack range. (Default: 0) +# SkillRange Skill cast range. (Default: 0) +# ChaseRange Chase range. (Default: 0) +# Size Size. (Default: Small) +# Race Race. (Default: Formless) +# Element Element. (Default: Neutral) +# ElementLevel Level of element. (Default: 1) +# WalkSpeed Walk speed. (Default: DEFAULT_WALK_SPEED) +# AttackDelay Attack speed. (Default: 4000) +# AttackMotion Attack animation speed. (Default: 2000) +# DamageMotion Damage animation speed. (Default: 0) +# Skills: List of mercenary skills. (Optional) +# - Name Skill name. +# MaxLevel Max skill level. +########################################################################### diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 1a01ef3108..d43c650df9 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -4036,14 +4036,12 @@ ACMD_FUNC(reload) { mob_reload(); pet_db.reload(); hom_reload(); - mercenary_readdb(); - mercenary_read_skilldb(); + mercenary_db.reload(); elemental_db.reload(); clif_displaymessage(fd, msg_txt(sd,98)); // Monster database has been reloaded. } else if (strstr(command, "skilldb") || strncmp(message, "skilldb", 4) == 0) { skill_reload(); hom_reload_skill(); - mercenary_read_skilldb(); clif_displaymessage(fd, msg_txt(sd,99)); // Skill database has been reloaded. } else if (strstr(command, "atcommand") || strncmp(message, "atcommand", 4) == 0) { config_t run_test; diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 8e874a6b81..4134659a64 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -124,7 +124,7 @@ int battle_gettarget(struct block_list* bl) case BL_MOB: return ((struct mob_data*)bl)->target_id; case BL_PET: return ((struct pet_data*)bl)->target_id; case BL_HOM: return ((struct homun_data*)bl)->ud.target; - case BL_MER: return ((struct mercenary_data*)bl)->ud.target; + case BL_MER: return ((s_mercenary_data*)bl)->ud.target; case BL_ELEM: return ((s_elemental_data*)bl)->ud.target; } diff --git a/src/map/clif.cpp b/src/map/clif.cpp index ca81aaa69d..2e8805ca6f 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -8309,7 +8309,7 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd) WBUFL(buf,2) = src->id; if( src->type == BL_MER ) { - struct mercenary_data *md = BL_CAST(BL_MER,src); + s_mercenary_data *md = BL_CAST(BL_MER,src); if( md && md->master && md->devotion_flag ) WBUFL(buf,6) = md->master->bl.id; @@ -9836,7 +9836,7 @@ void clif_name( struct block_list* src, struct block_list *bl, send_target targe memcpy(packet.name, ((TBL_HOM *)bl)->homunculus.name, NAME_LENGTH); break; case BL_MER: - memcpy(packet.name, ((TBL_MER *)bl)->db->name, NAME_LENGTH); + memcpy(packet.name, ((TBL_MER *)bl)->db->name.c_str(), NAME_LENGTH); break; case BL_PET: safestrncpy(packet.name, ((TBL_PET *)bl)->pet.name, NAME_LENGTH); @@ -12542,7 +12542,7 @@ static void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_ses unit_skilluse_pos(&hd->bl, x, y, skill_id, skill_lv); } -static void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_session_data *sd, t_tick tick, uint16 skill_id, uint16 skill_lv, int target_id) +static void clif_parse_UseSkillToId_mercenary(s_mercenary_data *md, struct map_session_data *sd, t_tick tick, uint16 skill_id, uint16 skill_lv, int target_id) { int lv; @@ -12566,7 +12566,7 @@ static void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct unit_skilluse_id(&md->bl, target_id, skill_id, skill_lv); } -static void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_session_data *sd, t_tick tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) +static void clif_parse_UseSkillToPos_mercenary(s_mercenary_data *md, struct map_session_data *sd, t_tick tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) { int lv; if( !md ) @@ -17696,7 +17696,7 @@ void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, e /// 02a2 .W .L void clif_mercenary_updatestatus(struct map_session_data *sd, int type) { - struct mercenary_data *md; + s_mercenary_data *md; struct status_data *status; int fd; if( !clif_session_isValid(sd) || (md = sd->md) == NULL ) @@ -17765,7 +17765,7 @@ void clif_mercenary_updatestatus(struct map_session_data *sd, int type) void clif_mercenary_info(struct map_session_data *sd) { int fd; - struct mercenary_data *md; + s_mercenary_data *md; struct status_data *status; int atk; @@ -17789,7 +17789,7 @@ void clif_mercenary_info(struct map_session_data *sd) WFIFOW(fd,16) = status->mdef; WFIFOW(fd,18) = status->flee; WFIFOW(fd,20) = status->amotion; - safestrncpy(WFIFOCP(fd,22), md->db->name, NAME_LENGTH); + safestrncpy(WFIFOCP(fd,22), md->db->name.c_str(), NAME_LENGTH); WFIFOW(fd,46) = md->db->lv; WFIFOL(fd,48) = status->hp; WFIFOL(fd,52) = status->max_hp; @@ -17808,8 +17808,8 @@ void clif_mercenary_info(struct map_session_data *sd) /// 029d .W { .W .L .W .W .W .24B .B }* void clif_mercenary_skillblock(struct map_session_data *sd) { - struct mercenary_data *md; - int fd, i, len = 4; + s_mercenary_data *md; + int fd, len = 4; if( sd == NULL || (md = sd->md) == NULL ) return; @@ -17817,20 +17817,19 @@ void clif_mercenary_skillblock(struct map_session_data *sd) fd = sd->fd; WFIFOHEAD(fd,4+37*MAX_MERCSKILL); WFIFOW(fd,0) = 0x29d; - for( i = 0; i < MAX_MERCSKILL; i++ ) - { - uint16 id; - short idx = -1; - if( (id = md->db->skill[i].id) == 0 ) - continue; - if ((idx = mercenary_skill_get_index(id)) == -1) + for (const auto &it : md->db->skill) { + uint16 id = it.first; + + if (!SKILL_CHK_MERC(id)) continue; + uint16 lv = it.second; + WFIFOW(fd,len) = id; WFIFOL(fd,len+2) = skill_get_inf(id); - WFIFOW(fd,len+6) = md->db->skill[idx].lv; - WFIFOW(fd,len+8) = skill_get_sp(id, md->db->skill[idx].lv); - WFIFOW(fd,len+10) = skill_get_range2(&md->bl, id, md->db->skill[idx].lv, false); + WFIFOW(fd,len+6) = lv; + WFIFOW(fd,len+8) = skill_get_sp(id, lv); + WFIFOW(fd,len+10) = skill_get_range2(&md->bl, id, lv, false); safestrncpy(WFIFOCP(fd,len+12), skill_get_name(id), NAME_LENGTH); WFIFOB(fd,len+36) = 0; // Skillable for Mercenary? len += 37; diff --git a/src/map/map-server.vcxproj b/src/map/map-server.vcxproj index 9fa64b73c0..10e3cb558a 100644 --- a/src/map/map-server.vcxproj +++ b/src/map/map-server.vcxproj @@ -323,8 +323,7 @@ - - + diff --git a/src/map/map.cpp b/src/map/map.cpp index 899ee0e8a8..e9ecc29101 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -2239,7 +2239,7 @@ struct homun_data* map_id2hd(int id){ return BL_CAST(BL_HOM, bl); } -struct mercenary_data* map_id2mc(int id){ +struct s_mercenary_data* map_id2mc(int id){ struct block_list* bl = map_id2bl(id); return BL_CAST(BL_MER, bl); } diff --git a/src/map/map.hpp b/src/map/map.hpp index 832a56d809..3ebdf4aebc 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -1087,7 +1087,7 @@ struct map_session_data * map_id2sd(int id); struct mob_data * map_id2md(int id); struct npc_data * map_id2nd(int id); struct homun_data* map_id2hd(int id); -struct mercenary_data* map_id2mc(int id); +struct s_mercenary_data* map_id2mc(int id); struct pet_data* map_id2pd(int id); struct s_elemental_data* map_id2ed(int id); struct chat_data* map_id2cd(int id); @@ -1195,7 +1195,7 @@ typedef struct chat_data TBL_CHAT; typedef struct skill_unit TBL_SKILL; typedef struct pet_data TBL_PET; typedef struct homun_data TBL_HOM; -typedef struct mercenary_data TBL_MER; +typedef struct s_mercenary_data TBL_MER; typedef struct s_elemental_data TBL_ELEM; #define BL_CAST(type_, bl) \ diff --git a/src/map/mercenary.cpp b/src/map/mercenary.cpp index 169adef8eb..8594f4228c 100644 --- a/src/map/mercenary.cpp +++ b/src/map/mercenary.cpp @@ -29,16 +29,7 @@ using namespace rathena; -std::map mercenary_db_data; - -/** - * Search Mercenary by class - * @param class_ Class ID of Mercenary - * @return A pointer to the mercenary db entry or nullptr if not found - **/ -struct s_mercenary_db *mercenary_db( uint16 class_ ){ - return util::map_find( mercenary_db_data, class_ ); -} +MercenaryDatabase mercenary_db; /** * Get View Data of Mercenary by Class ID @@ -46,7 +37,7 @@ struct s_mercenary_db *mercenary_db( uint16 class_ ){ * @return View Data of Mercenary **/ struct view_data *mercenary_get_viewdata( uint16 class_ ){ - struct s_mercenary_db *db = mercenary_db(class_); + std::shared_ptr db = mercenary_db.find(class_); if( db ){ return &db->vd; @@ -55,20 +46,6 @@ struct view_data *mercenary_get_viewdata( uint16 class_ ){ } } -/** - * Get mercenary skill index for mercenary skill tree - * @param skill_id - * @return Index in skill_tree or -1 - **/ -short mercenary_skill_get_index(uint16 skill_id) { - if (!SKILL_CHK_MERC(skill_id)) - return -1; - skill_id -= MC_SKILLBASE; - if (skill_id >= MAX_MERCSKILL) - return -1; - return skill_id; -} - /** * Create a new Mercenary for Player * @param sd The Player @@ -76,18 +53,17 @@ short mercenary_skill_get_index(uint16 skill_id) { * @param lifetime Contract duration * @return false if failed, true otherwise **/ -bool mercenary_create(struct map_session_data *sd, uint16 class_, unsigned int lifetime) { - struct s_mercenary merc; - struct s_mercenary_db *db; +bool mercenary_create(map_session_data *sd, uint16 class_, unsigned int lifetime) { nullpo_retr(false,sd); - db = mercenary_db(class_); + std::shared_ptr db = mercenary_db.find(class_); - if( !db ){ + if (db == nullptr) { + ShowError("mercenary_create: Unknown mercenary class %d.\n", class_); return false; } - memset(&merc,0,sizeof(struct s_mercenary)); + s_mercenary merc = {}; merc.char_id = sd->status.char_id; merc.class_ = class_; @@ -106,12 +82,11 @@ bool mercenary_create(struct map_session_data *sd, uint16 class_, unsigned int l * @param md The Mercenary * @return The Lifetime **/ -t_tick mercenary_get_lifetime(struct mercenary_data *md) { - const struct TimerData * td; +t_tick mercenary_get_lifetime(s_mercenary_data *md) { if( md == NULL || md->contract_timer == INVALID_TIMER ) return 0; - td = get_timer(md->contract_timer); + const struct TimerData *td = get_timer(md->contract_timer); return (td != NULL) ? DIFF_TICK(td->tick, gettick()) : 0; } @@ -120,13 +95,11 @@ t_tick mercenary_get_lifetime(struct mercenary_data *md) { * @param md Mercenary * @return enum e_MercGuildType **/ -enum e_MercGuildType mercenary_get_guild(struct mercenary_data *md){ - uint16 class_; - +e_MercGuildType mercenary_get_guild(s_mercenary_data *md){ if( md == NULL || md->db == NULL ) return NONE_MERC_GUILD; - class_ = md->db->class_; + uint16 class_ = md->db->class_; if( class_ >= MERID_MER_ARCHER01 && class_ <= MERID_MER_ARCHER10 ) return ARCH_MERC_GUILD; @@ -143,14 +116,13 @@ enum e_MercGuildType mercenary_get_guild(struct mercenary_data *md){ * @param md Mercenary * @return the Faith value **/ -int mercenary_get_faith(struct mercenary_data *md) { - struct map_session_data *sd; - enum e_MercGuildType guild; +int mercenary_get_faith(s_mercenary_data *md) { + map_session_data *sd; if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) return 0; - guild = mercenary_get_guild(md); + e_MercGuildType guild = mercenary_get_guild(md); switch( guild ){ case ARCH_MERC_GUILD: @@ -170,15 +142,14 @@ int mercenary_get_faith(struct mercenary_data *md) { * @param md The Mercenary * @param value Faith Value **/ -void mercenary_set_faith(struct mercenary_data *md, int value) { - struct map_session_data *sd; - enum e_MercGuildType guild; - int *faith; +void mercenary_set_faith(s_mercenary_data *md, int value) { + map_session_data *sd; if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) return; - guild = mercenary_get_guild(md); + e_MercGuildType guild = mercenary_get_guild(md); + int *faith = nullptr; switch( guild ){ case ARCH_MERC_GUILD: @@ -204,14 +175,13 @@ void mercenary_set_faith(struct mercenary_data *md, int value) { * @param md Mercenary * @return Number of calls **/ -int mercenary_get_calls(struct mercenary_data *md) { - struct map_session_data *sd; - enum e_MercGuildType guild; +int mercenary_get_calls(s_mercenary_data *md) { + map_session_data *sd; if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) return 0; - guild = mercenary_get_guild(md); + e_MercGuildType guild = mercenary_get_guild(md); switch( guild ){ case ARCH_MERC_GUILD: @@ -231,15 +201,14 @@ int mercenary_get_calls(struct mercenary_data *md) { * @param md Mercenary * @param value **/ -void mercenary_set_calls(struct mercenary_data *md, int value) { - struct map_session_data *sd; - enum e_MercGuildType guild; - int *calls; +void mercenary_set_calls(s_mercenary_data *md, int value) { + map_session_data *sd; if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) return; - guild = mercenary_get_guild(md); + e_MercGuildType guild = mercenary_get_guild(md); + int *calls = nullptr; switch( guild ){ case ARCH_MERC_GUILD: @@ -263,7 +232,7 @@ void mercenary_set_calls(struct mercenary_data *md, int value) { * Save Mercenary data * @param md Mercenary **/ -void mercenary_save(struct mercenary_data *md) { +void mercenary_save(s_mercenary_data *md) { md->mercenary.hp = md->battle_status.hp; md->mercenary.sp = md->battle_status.sp; md->mercenary.life_time = mercenary_get_lifetime(md); @@ -275,8 +244,8 @@ void mercenary_save(struct mercenary_data *md) { * Ends contract of Mercenary **/ static TIMER_FUNC(merc_contract_end){ - struct map_session_data *sd; - struct mercenary_data *md; + map_session_data *sd; + s_mercenary_data *md; if( (sd = map_id2sd(id)) == NULL ) return 1; @@ -300,8 +269,8 @@ static TIMER_FUNC(merc_contract_end){ * @param md Mercenary * @param reply **/ -int mercenary_delete(struct mercenary_data *md, int reply) { - struct map_session_data *sd = md->master; +int mercenary_delete(s_mercenary_data *md, int reply) { + map_session_data *sd = md->master; md->mercenary.life_time = 0; mercenary_contract_stop(md); @@ -329,7 +298,7 @@ int mercenary_delete(struct mercenary_data *md, int reply) { * Stop contract of Mercenary * @param md Mercenary **/ -void mercenary_contract_stop(struct mercenary_data *md) { +void mercenary_contract_stop(s_mercenary_data *md) { nullpo_retv(md); if( md->contract_timer != INVALID_TIMER ) delete_timer(md->contract_timer, merc_contract_end); @@ -340,7 +309,7 @@ void mercenary_contract_stop(struct mercenary_data *md) { * Init contract of Mercenary * @param md Mercenary **/ -void merc_contract_init(struct mercenary_data *md) { +void merc_contract_init(s_mercenary_data *md) { if( md->contract_timer == INVALID_TIMER ) md->contract_timer = add_timer(gettick() + md->mercenary.life_time, merc_contract_end, md->master->bl.id, 0); @@ -353,30 +322,31 @@ void merc_contract_init(struct mercenary_data *md) { * @param flag : if inter-serv request was sucessfull * @return false:failure, true:sucess */ -bool mercenary_recv_data(struct s_mercenary *merc, bool flag) +bool mercenary_recv_data(s_mercenary *merc, bool flag) { - struct map_session_data *sd; - struct mercenary_data *md; - struct s_mercenary_db *db; - - db = mercenary_db(merc->class_); + map_session_data *sd; if( (sd = map_charid2sd(merc->char_id)) == NULL ) return false; + + std::shared_ptr db = mercenary_db.find(merc->class_); + if( !flag || !db ){ // Not created - loaded - DB info sd->status.mer_id = 0; return false; } + s_mercenary_data *md; + if( !sd->md ) { - sd->md = md = (struct mercenary_data*)aCalloc(1,sizeof(struct mercenary_data)); + sd->md = md = (s_mercenary_data*)aCalloc(1,sizeof(s_mercenary_data)); md->bl.type = BL_MER; md->bl.id = npc_get_new_npc_id(); md->devotion_flag = 0; md->master = sd; md->db = db; - memcpy(&md->mercenary, merc, sizeof(struct s_mercenary)); + memcpy(&md->mercenary, merc, sizeof(s_mercenary)); status_set_viewdata(&md->bl, md->mercenary.class_); status_change_init(&md->bl); unit_dataset(&md->bl); @@ -395,7 +365,7 @@ bool mercenary_recv_data(struct s_mercenary *merc, bool flag) md->masterteleport_timer = INVALID_TIMER; merc_contract_init(md); } else { - memcpy(&sd->md->mercenary, merc, sizeof(struct s_mercenary)); + memcpy(&sd->md->mercenary, merc, sizeof(s_mercenary)); md = sd->md; } @@ -420,7 +390,7 @@ bool mercenary_recv_data(struct s_mercenary *merc, bool flag) * @param hp HP amount * @param sp SP amount **/ -void mercenary_heal(struct mercenary_data *md, int hp, int sp) { +void mercenary_heal(s_mercenary_data *md, int hp, int sp) { if (md->master == NULL) return; if( hp ) @@ -434,7 +404,7 @@ void mercenary_heal(struct mercenary_data *md, int hp, int sp) { * @param md: Mercenary * @return false for status_damage */ -bool mercenary_dead(struct mercenary_data *md) { +bool mercenary_dead(s_mercenary_data *md) { mercenary_delete(md, 1); return false; } @@ -443,18 +413,17 @@ bool mercenary_dead(struct mercenary_data *md) { * Gives bonus to Mercenary * @param md Mercenary **/ -void mercenary_killbonus(struct mercenary_data *md) { - const enum sc_type scs[] = { SC_MERC_FLEEUP, SC_MERC_ATKUP, SC_MERC_HPUP, SC_MERC_SPUP, SC_MERC_HITUP }; - uint8 index = rnd() % ARRAYLENGTH(scs); +void mercenary_killbonus(s_mercenary_data *md) { + std::vector scs = { SC_MERC_FLEEUP, SC_MERC_ATKUP, SC_MERC_HPUP, SC_MERC_SPUP, SC_MERC_HITUP }; - sc_start(&md->bl,&md->bl, scs[index], 100, rnd() % 5, 600000); + sc_start(&md->bl,&md->bl, util::vector_random(scs), 100, rnd() % 5, 600000); } /** * Mercenary does kill * @param md Mercenary **/ -void mercenary_kills(struct mercenary_data *md){ +void mercenary_kills(s_mercenary_data *md){ if(md->mercenary.kill_count <= (INT_MAX-1)) //safe cap to INT_MAX md->mercenary.kill_count++; @@ -474,144 +443,475 @@ void mercenary_kills(struct mercenary_data *md){ * @param skill_id The skill * @return Skill Level or 0 if Mercenary doesn't have the skill **/ -int mercenary_checkskill(struct mercenary_data *md, uint16 skill_id) { - short idx = mercenary_skill_get_index(skill_id); - - if( !md || !md->db || idx == -1) +uint16 mercenary_checkskill(s_mercenary_data *md, uint16 skill_id) { + if (!md || !md->db) return 0; - return md->db->skill[idx].lv; + auto skill_level = util::umap_find(md->db->skill, skill_id); + return skill_level ? *skill_level : 0; } -/** -* Read each line of Mercenary's database -**/ -static bool mercenary_readdb_sub(char* str[], int columns, int current) -{ - int ele; - uint16 class_ = atoi(str[0]); - struct s_mercenary_db *db; - struct status_data *status; +const std::string MercenaryDatabase::getDefaultLocation() { + return std::string(db_path) + "/mercenary_db.yml"; +} - db = &mercenary_db_data[class_]; +/* + * Reads and parses an entry from the mercenary_db. + * @param node: YAML node containing the entry. + * @return count of successfully parsed rows + */ +uint64 MercenaryDatabase::parseBodyNode(const YAML::Node &node) { + uint32 id; - db->class_ = class_; - safestrncpy(db->sprite, str[1], NAME_LENGTH); - safestrncpy(db->name, str[2], NAME_LENGTH); - db->lv = atoi(str[3]); + if (!this->asUInt32(node, "Id", id)) + return 0; - status = &db->status; - db->vd.class_ = db->class_; + std::shared_ptr mercenary = this->find(id); + bool exists = mercenary != nullptr; - status->max_hp = atoi(str[4]); - status->max_sp = atoi(str[5]); - status->rhw.range = atoi(str[6]); - status->rhw.atk = atoi(str[7]); - status->rhw.atk2 = status->rhw.atk + atoi(str[8]); - status->def = atoi(str[9]); - status->mdef = atoi(str[10]); - status->str = atoi(str[11]); - status->agi = atoi(str[12]); - status->vit = atoi(str[13]); - status->int_ = atoi(str[14]); - status->dex = atoi(str[15]); - status->luk = atoi(str[16]); - db->range2 = atoi(str[17]); - db->range3 = atoi(str[18]); - status->size = atoi(str[19]); - status->race = atoi(str[20]); + if (!exists) { + if (!this->nodesExist(node, { "AegisName", "Name" })) + return 0; - ele = atoi(str[21]); - status->def_ele = ele%20; - status->ele_lv = (unsigned char)floor(ele/20.); - if( !CHK_ELEMENT(status->def_ele) ) - { - ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_ALL - 1); - status->def_ele = ELE_NEUTRAL; - } - if( !CHK_ELEMENT_LEVEL(status->ele_lv) ) - { - ShowWarning("Mercenary %d has invalid element level %d (max is %d)\n", db->class_, status->ele_lv, MAX_ELE_LEVEL); - status->ele_lv = 1; + mercenary = std::make_shared(); + mercenary->class_ = id; } - status->aspd_rate = 1000; - status->speed = atoi(str[22]); - status->adelay = atoi(str[23]); - status->amotion = atoi(str[24]); - status->dmotion = atoi(str[25]); + if (this->nodeExists(node, "AegisName")) { + std::string name; + + if (!this->asString(node, "AegisName", name)) + return 0; + + if (name.size() > NAME_LENGTH) { + this->invalidWarning(node["AegisName"], "AegisName \"%s\" exceeds maximum of %d characters, capping...\n", name.c_str(), NAME_LENGTH - 1); + } + + name.resize(NAME_LENGTH); + mercenary->sprite = name; + } + + if (this->nodeExists(node, "Name")) { + std::string name; + + if (!this->asString(node, "Name", name)) + return 0; + + if (name.size() > NAME_LENGTH) { + this->invalidWarning(node["Name"], "Name \"%s\" exceeds maximum of %d characters, capping...\n", name.c_str(), NAME_LENGTH - 1); + } + + name.resize(NAME_LENGTH); + mercenary->name = name; + } + + if (this->nodeExists(node, "Level")) { + uint16 level; + + if (!this->asUInt16(node, "Level", level)) + return 0; + + if (level > MAX_LEVEL) { + this->invalidWarning(node["Level"], "Level %d exceeds MAX_LEVEL, capping to %d.\n", level, MAX_LEVEL); + level = MAX_LEVEL; + } + + mercenary->lv = level; + } else { + if (!exists) + mercenary->lv = 1; + } + + if (this->nodeExists(node, "Hp")) { + uint32 hp; + + if (!this->asUInt32(node, "Hp", hp)) + return 0; + + mercenary->status.max_hp = hp; + } else { + if (!exists) + mercenary->status.max_hp = 1; + } - return true; -} + if (this->nodeExists(node, "Sp")) { + uint32 sp; -/** -* Load Mercenary's database -**/ -void mercenary_readdb(void) { - const char *filename[]={ "mercenary_db.txt",DBIMPORT"/mercenary_db.txt"}; - uint8 i; + if (!this->asUInt32(node, "Sp", sp)) + return 0; - mercenary_db_data.clear(); - - for(i = 0; i 0); - } -} - -/** -* Read each line of Mercenary's skill -**/ -static bool mercenary_read_skilldb_sub(char* str[], int columns, int current) -{// ,, - struct s_mercenary_db *db; - uint16 class_, skill_id, skill_lv; - short idx = -1; - - class_ = atoi(str[0]); - db = mercenary_db(class_); - if( !db ){ - ShowError("read_mercenary_skilldb : Class %d not found in mercenary_db for skill entry.\n", class_); - return false; + mercenary->status.max_sp = sp; + } else { + if (!exists) + mercenary->status.max_sp = 1; } - skill_id = atoi(str[1]); - if( (idx = mercenary_skill_get_index(skill_id)) == -1 ) { - ShowError("read_mercenary_skilldb: Invalid Mercenary skill '%s'.\n", str[1]); - return false; + if (this->nodeExists(node, "Attack")) { + uint16 atk; + + if (!this->asUInt16(node, "Attack", atk)) + return 0; + + mercenary->status.rhw.atk = atk; + } else { + if (!exists) + mercenary->status.rhw.atk = 0; + } + + if (this->nodeExists(node, "Attack2")) { + uint16 atk; + + if (!this->asUInt16(node, "Attack2", atk)) + return 0; + + mercenary->status.rhw.atk2 = mercenary->status.rhw.atk + atk; + } else { + if (!exists) + mercenary->status.rhw.atk2 = mercenary->status.rhw.atk; } - skill_lv = atoi(str[2]); + if (this->nodeExists(node, "Defense")) { + int32 def; - db->skill[idx].id = skill_id; - db->skill[idx].lv = skill_lv; + if (!this->asInt32(node, "Defense", def)) + return 0; + + if (def < DEFTYPE_MIN || def > DEFTYPE_MAX) { + this->invalidWarning(node["Defense"], "Invalid defense %d, capping...\n", def); + def = cap_value(def, DEFTYPE_MIN, DEFTYPE_MAX); + } + + mercenary->status.def = static_cast(def); + } else { + if (!exists) + mercenary->status.def = 0; + } + + if (this->nodeExists(node, "MagicDefense")) { + int32 def; + + if (!this->asInt32(node, "MagicDefense", def)) + return 0; + + if (def < DEFTYPE_MIN || def > DEFTYPE_MAX) { + this->invalidWarning(node["MagicDefense"], "Invalid magic defense %d, capping...\n", def); + def = cap_value(def, DEFTYPE_MIN, DEFTYPE_MAX); + } + + mercenary->status.mdef = static_cast(def); + } else { + if (!exists) + mercenary->status.mdef = 0; + } + + if (this->nodeExists(node, "Str")) { + uint16 stat; + + if (!this->asUInt16(node, "Str", stat)) + return 0; + + mercenary->status.str = stat; + } else { + if (!exists) + mercenary->status.str = 1; + } + + if (this->nodeExists(node, "Agi")) { + uint16 stat; + + if (!this->asUInt16(node, "Agi", stat)) + return 0; + + mercenary->status.agi = stat; + } else { + if (!exists) + mercenary->status.agi = 1; + } + + if (this->nodeExists(node, "Vit")) { + uint16 stat; + + if (!this->asUInt16(node, "Vit", stat)) + return 0; + + mercenary->status.vit = stat; + } else { + if (!exists) + mercenary->status.vit = 1; + } + + if (this->nodeExists(node, "Int")) { + uint16 stat; + + if (!this->asUInt16(node, "Int", stat)) + return 0; + + mercenary->status.int_ = stat; + } else { + if (!exists) + mercenary->status.int_ = 1; + } + + if (this->nodeExists(node, "Dex")) { + uint16 stat; + + if (!this->asUInt16(node, "Dex", stat)) + return 0; + + mercenary->status.dex = stat; + } else { + if (!exists) + mercenary->status.dex = 1; + } + + if (this->nodeExists(node, "Luk")) { + uint16 stat; + + if (!this->asUInt16(node, "Luk", stat)) + return 0; + + mercenary->status.luk = stat; + } else { + if (!exists) + mercenary->status.luk = 1; + } + + if (this->nodeExists(node, "AttackRange")) { + uint16 range; + + if (!this->asUInt16(node, "AttackRange", range)) + return 0; + + mercenary->status.rhw.range = range; + } else { + if (!exists) + mercenary->status.rhw.range = 0; + } + + if (this->nodeExists(node, "SkillRange")) { + uint16 range; + + if (!this->asUInt16(node, "SkillRange", range)) + return 0; + + mercenary->range2 = range; + } else { + if (!exists) + mercenary->range2 = 0; + } + + if (this->nodeExists(node, "ChaseRange")) { + uint16 range; + + if (!this->asUInt16(node, "ChaseRange", range)) + return 0; + + mercenary->range3 = range; + } else { + if (!exists) + mercenary->range3 = 0; + } + + if (this->nodeExists(node, "Size")) { + std::string size; + + if (!this->asString(node, "Size", size)) + return 0; + + std::string size_constant = "Size_" + size; + int64 constant; + + if (!script_get_constant(size_constant.c_str(), &constant)) { + this->invalidWarning(node["Size"], "Unknown mercenary size %s, defaulting to Small.\n", size.c_str()); + constant = SZ_SMALL; + } + + if (constant < SZ_SMALL || constant > SZ_BIG) { + this->invalidWarning(node["Size"], "Invalid mercenary size %s, defaulting to Small.\n", size.c_str()); + constant = SZ_SMALL; + } + + mercenary->status.size = static_cast(constant); + } else { + if (!exists) + mercenary->status.size = SZ_SMALL; + } + + if (this->nodeExists(node, "Race")) { + std::string race; + + if (!this->asString(node, "Race", race)) + return 0; + + std::string race_constant = "RC_" + race; + int64 constant; + + if (!script_get_constant(race_constant.c_str(), &constant)) { + this->invalidWarning(node["Race"], "Unknown mercenary race %s, defaulting to Formless.\n", race.c_str()); + constant = RC_FORMLESS; + } + + if (!CHK_RACE(constant)) { + this->invalidWarning(node["Race"], "Invalid mercenary race %s, defaulting to Formless.\n", race.c_str()); + constant = RC_FORMLESS; + } + + mercenary->status.race = static_cast(constant); + } else { + if (!exists) + mercenary->status.race = RC_FORMLESS; + } + + if (this->nodeExists(node, "Element")) { + std::string ele; + + if (!this->asString(node, "Element", ele)) + return 0; + + std::string ele_constant = "ELE_" + ele; + int64 constant; + + if (!script_get_constant(ele_constant.c_str(), &constant)) { + this->invalidWarning(node["Element"], "Unknown mercenary element %s, defaulting to Neutral.\n", ele.c_str()); + constant = ELE_NEUTRAL; + } + + if (!CHK_ELEMENT(constant)) { + this->invalidWarning(node["Element"], "Invalid mercenary element %s, defaulting to Neutral.\n", ele.c_str()); + constant = ELE_NEUTRAL; + } + + mercenary->status.def_ele = static_cast(constant); + } else { + if (!exists) + mercenary->status.def_ele = ELE_NEUTRAL; + } + + if (this->nodeExists(node, "ElementLevel")) { + uint16 level; + + if (!this->asUInt16(node, "ElementLevel", level)) + return 0; + + if (!CHK_ELEMENT_LEVEL(level)) { + this->invalidWarning(node["ElementLevel"], "Invalid mercenary element level %hu, defaulting to 1.\n", level); + level = 1; + } + + mercenary->status.ele_lv = static_cast(level); + } else { + if (!exists) + mercenary->status.ele_lv = 1; + } + + if (this->nodeExists(node, "WalkSpeed")) { + uint16 speed; + + if (!this->asUInt16(node, "WalkSpeed", speed)) + return 0; + + if (speed < MIN_WALK_SPEED || speed > MAX_WALK_SPEED) { + this->invalidWarning(node["WalkSpeed"], "Invalid mercenary walk speed %hu, capping...\n", speed); + speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED); + } + + mercenary->status.speed = speed; + } else { + if (!exists) + mercenary->status.speed = DEFAULT_WALK_SPEED; + } + + if (this->nodeExists(node, "AttackDelay")) { + uint16 speed; + + if (!this->asUInt16(node, "AttackDelay", speed)) + return 0; + + mercenary->status.adelay = cap_value(speed, 0, 4000); + } else { + if (!exists) + mercenary->status.adelay = 4000; + } + + if (this->nodeExists(node, "AttackMotion")) { + uint16 speed; + + if (!this->asUInt16(node, "AttackMotion", speed)) + return 0; + + mercenary->status.amotion = cap_value(speed, 0, 2000); + } else { + if (!exists) + mercenary->status.amotion = 2000; + } + + if (this->nodeExists(node, "DamageMotion")) { + uint16 speed; + + if (!this->asUInt16(node, "DamageMotion", speed)) + return 0; + + mercenary->status.dmotion = speed; + } else { + if (!exists) + mercenary->status.dmotion = 0; + } + + mercenary->status.aspd_rate = 1000; + + if (this->nodeExists(node, "Skills")) { + const YAML::Node &skillsNode = node["Skills"]; + + for (const YAML::Node &skill : skillsNode) { + std::string skill_name; + + if (!this->asString(skill, "Name", skill_name)) + return 0; + + uint16 skill_id = skill_name2id(skill_name.c_str()); + + if (skill_id == 0) { + this->invalidWarning(skill["Name"], "Invalid skill %s, skipping.\n", skill_name.c_str()); + return 0; + } + + if (!SKILL_CHK_MERC(skill_id)) { + this->invalidWarning(skill["Name"], "Skill %s (%u) is out of the mercenary skill range [%u-%u], skipping.\n", skill_name.c_str(), skill_id, MC_SKILLBASE, MC_SKILLBASE + MAX_MERCSKILL - 1); + return 0; + } + + uint16 level; + + if (!this->asUInt16(skill, "MaxLevel", level)) + return 0; + + if (level == 0) { + if (mercenary->skill.erase(skill_id) == 0) + this->invalidWarning(skill["Name"], "Failed to remove %s, the skill doesn't exist for mercenary %hu.\n", skill_name.c_str(), id); + continue; + } + + mercenary->skill[skill_id] = level; + } + } + + if (!exists) + this->put(id, mercenary); return true; } -/** -* Load Mercenary's skill database -**/ -void mercenary_read_skilldb(void){ - const char *filename[]={ "mercenary_skill_db.txt",DBIMPORT"/mercenary_skill_db.txt"}; - uint8 i; - - for(i = 0; i 0); - } -} - /** * Init Mercenary datas **/ void do_init_mercenary(void){ - mercenary_readdb(); - mercenary_read_skilldb(); + mercenary_db.load(); - //add_timer_func_list(mercenary_contract, "mercenary_contract"); + add_timer_func_list(merc_contract_end, "merc_contract_end"); } /** * Do Final Mercenary datas **/ void do_final_mercenary(void){ - mercenary_db_data.clear(); + mercenary_db.clear(); } diff --git a/src/map/mercenary.hpp b/src/map/mercenary.hpp index b2eedc6a49..ba74c41b79 100644 --- a/src/map/mercenary.hpp +++ b/src/map/mercenary.hpp @@ -19,7 +19,7 @@ enum e_MercGuildType { SWORD_MERC_GUILD, }; -enum MERID { +enum e_MERID { MERID_MER_ARCHER01 = 6017, MERID_MER_ARCHER10 = 6026, MERID_MER_LANCER01, @@ -29,65 +29,67 @@ enum MERID { }; struct s_mercenary_db { - int class_; - char sprite[NAME_LENGTH], name[NAME_LENGTH]; - unsigned short lv; - short range2, range3; - struct status_data status; - struct view_data vd; - struct { - unsigned short id, lv; - } skill[MAX_MERCSKILL]; + int32 class_; + std::string sprite, name; + uint16 lv; + uint16 range2, range3; + status_data status; + view_data vd; + std::unordered_map skill; }; -struct mercenary_data { - struct block_list bl; - struct unit_data ud; - struct view_data *vd; - struct status_data base_status, battle_status; - struct status_change sc; - struct regen_data regen; +struct s_mercenary_data { + block_list bl; + unit_data ud; + view_data *vd; + status_data base_status, battle_status; + status_change sc; + regen_data regen; - struct s_mercenary_db *db; - struct s_mercenary mercenary; + std::shared_ptr db; + s_mercenary mercenary; std::vector blockskill; int masterteleport_timer; - struct map_session_data *master; + map_session_data *master; int contract_timer; unsigned devotion_flag : 1; }; -struct s_mercenary_db *mercenary_db(uint16 class_); struct view_data * mercenary_get_viewdata(uint16 class_); -bool mercenary_create(struct map_session_data *sd, uint16 class_, unsigned int lifetime); -bool mercenary_recv_data(struct s_mercenary *merc, bool flag); -void mercenary_save(struct mercenary_data *md); +class MercenaryDatabase : public TypesafeYamlDatabase { +public: + MercenaryDatabase() : TypesafeYamlDatabase("MERCENARY_DB", 1) { -void mercenary_heal(struct mercenary_data *md, int hp, int sp); -bool mercenary_dead(struct mercenary_data *md); + } -int mercenary_delete(struct mercenary_data *md, int reply); -void mercenary_contract_stop(struct mercenary_data *md); + const std::string getDefaultLocation(); + uint64 parseBodyNode(const YAML::Node& node); +}; -t_tick mercenary_get_lifetime(struct mercenary_data *md); -enum e_MercGuildType mercenary_get_guild(struct mercenary_data *md); -int mercenary_get_faith(struct mercenary_data *md); -void mercenary_set_faith(struct mercenary_data *md, int value); -int mercenary_get_calls(struct mercenary_data *md); -void mercenary_set_calls(struct mercenary_data *md, int value); -void mercenary_kills(struct mercenary_data *md); +extern MercenaryDatabase mercenary_db; -int mercenary_checkskill(struct mercenary_data *md, uint16 skill_id); -short mercenary_skill_get_index(uint16 skill_id); +bool mercenary_create(map_session_data *sd, uint16 class_, unsigned int lifetime); +bool mercenary_recv_data(s_mercenary *merc, bool flag); +void mercenary_save(s_mercenary_data *md); -/** - * atcommand.cpp required - **/ -void mercenary_readdb(void); -void mercenary_read_skilldb(void); +void mercenary_heal(s_mercenary_data *md, int hp, int sp); +bool mercenary_dead(s_mercenary_data *md); + +int mercenary_delete(s_mercenary_data *md, int reply); +void mercenary_contract_stop(s_mercenary_data *md); + +t_tick mercenary_get_lifetime(s_mercenary_data *md); +e_MercGuildType mercenary_get_guild(s_mercenary_data *md); +int mercenary_get_faith(s_mercenary_data *md); +void mercenary_set_faith(s_mercenary_data *md, int value); +int mercenary_get_calls(s_mercenary_data *md); +void mercenary_set_calls(s_mercenary_data *md, int value); +void mercenary_kills(s_mercenary_data *md); + +uint16 mercenary_checkskill(s_mercenary_data *md, uint16 skill_id); void do_init_mercenary(void); void do_final_mercenary(void); diff --git a/src/map/mob.cpp b/src/map/mob.cpp index 75e8ae6e1c..59f00fd074 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -2351,7 +2351,7 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage) } case BL_MER: { - struct mercenary_data *mer = (TBL_MER*)src; + s_mercenary_data *mer = (TBL_MER*)src; if( mer->master ) char_id = mer->master->status.char_id; if( damage ) diff --git a/src/map/pc.hpp b/src/map/pc.hpp index 5d17654726..9a73f2d879 100644 --- a/src/map/pc.hpp +++ b/src/map/pc.hpp @@ -660,7 +660,7 @@ struct map_session_data { struct pet_data *pd; struct homun_data *hd; // [blackhole89] - struct mercenary_data *md; + s_mercenary_data *md; s_elemental_data *ed; struct s_hate_mob { diff --git a/src/map/script.cpp b/src/map/script.cpp index 1bf95ab83b..3aba3f2030 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -15363,7 +15363,7 @@ BUILDIN_FUNC(getmercinfo) { int type; struct map_session_data* sd; - struct mercenary_data* md; + s_mercenary_data* md; if( !script_charid2sd(3,sd) ){ script_pushnil(st); @@ -15385,7 +15385,7 @@ BUILDIN_FUNC(getmercinfo) { case 0: script_pushint(st,md->mercenary.mercenary_id); break; case 1: script_pushint(st,md->mercenary.class_); break; - case 2: script_pushstrcopy(st,md->db->name); break; + case 2: script_pushstrcopy(st,md->db->name.c_str()); break; case 3: script_pushint(st,mercenary_get_faith(md)); break; case 4: script_pushint(st,mercenary_get_calls(md)); break; case 5: script_pushint(st,md->mercenary.kill_count); break; @@ -17995,7 +17995,7 @@ BUILDIN_FUNC(rid2name) case BL_NPC: script_pushstrcopy(st,((TBL_NPC*)bl)->exname); break; case BL_PET: script_pushstrcopy(st,((TBL_PET*)bl)->pet.name); break; case BL_HOM: script_pushstrcopy(st,((TBL_HOM*)bl)->homunculus.name); break; - case BL_MER: script_pushstrcopy(st,((TBL_MER*)bl)->db->name); break; + case BL_MER: script_pushstrcopy(st,((TBL_MER*)bl)->db->name.c_str()); break; default: ShowError("buildin_rid2name: BL type unknown.\n"); script_pushconststr(st,""); @@ -19877,7 +19877,7 @@ BUILDIN_FUNC(mercenary_create) class_ = script_getnum(st,2); - if( !mercenary_db(class_) ) + if( !mercenary_db.exists(class_) ) return SCRIPT_CMD_SUCCESS; contract_time = script_getnum(st,3); diff --git a/src/map/skill.cpp b/src/map/skill.cpp index d461cd021c..fbc43bb4fa 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -1068,7 +1068,7 @@ bool skill_isNotOk_hom(struct homun_data *hd, uint16 skill_id, uint16 skill_lv) * @param md: Mercenary who casted * @return true: Skill cannot be used, false: otherwise */ -bool skill_isNotOk_mercenary(uint16 skill_id, struct mercenary_data *md) +bool skill_isNotOk_mercenary(uint16 skill_id, s_mercenary_data *md) { nullpo_retr(1, md); @@ -6511,7 +6511,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui struct map_session_data *sd, *dstsd; struct mob_data *md, *dstmd; struct homun_data *hd; - struct mercenary_data *mer; + s_mercenary_data *mer; struct status_data *sstatus, *tstatus; struct status_change *tsc; struct status_change_entry *tsce; @@ -21128,7 +21128,7 @@ int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) //[ } TIMER_FUNC(skill_blockmerc_end){ - struct mercenary_data *md = (TBL_MER*)map_id2bl(id); + s_mercenary_data *md = (TBL_MER*)map_id2bl(id); if (md) { auto skill = util::vector_get(md->blockskill, (uint16)data); @@ -21140,7 +21140,7 @@ TIMER_FUNC(skill_blockmerc_end){ return 1; } -int skill_blockmerc_start(struct mercenary_data *md, uint16 skill_id, int tick) +int skill_blockmerc_start(s_mercenary_data *md, uint16 skill_id, int tick) { nullpo_retr(-1, md); diff --git a/src/map/skill.hpp b/src/map/skill.hpp index 8abcdd1378..f55c58ba98 100644 --- a/src/map/skill.hpp +++ b/src/map/skill.hpp @@ -613,7 +613,7 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce void skill_enchant_elemental_end(struct block_list *bl, int type); bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd); bool skill_isNotOk_hom(struct homun_data *hd, uint16 skill_id, uint16 skill_lv); -bool skill_isNotOk_mercenary(uint16 skill_id, struct mercenary_data *md); +bool skill_isNotOk_mercenary(uint16 skill_id, s_mercenary_data *md); bool skill_isNotOk_npcRange(struct block_list *src, uint16 skill_id, uint16 skill_lv, int pos_x, int pos_y); @@ -633,7 +633,7 @@ int skill_blockpc_get(struct map_session_data *sd, int skillid); int skill_blockpc_clear(struct map_session_data *sd); TIMER_FUNC(skill_blockpc_end); int skill_blockhomun_start (struct homun_data*,uint16 skill_id,int); -int skill_blockmerc_start (struct mercenary_data*,uint16 skill_id,int); +int skill_blockmerc_start (s_mercenary_data*,uint16 skill_id,int); // (Epoque:) To-do: replace this macro with some sort of skill tree check (rather than hard-coded skill names) diff --git a/src/map/status.cpp b/src/map/status.cpp index 5e2fba14bf..ec0a85d0e6 100644 --- a/src/map/status.cpp +++ b/src/map/status.cpp @@ -5140,10 +5140,10 @@ int status_calc_pc_( struct map_session_data* sd, enum e_status_calc_opt opt ){ * @param opt: Whether it is first calc or not (0 on level up or status) * @return 0 */ -int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt) +int status_calc_mercenary_(s_mercenary_data *md, enum e_status_calc_opt opt) { struct status_data *status = &md->base_status; - struct s_mercenary *merc = &md->mercenary; + s_mercenary *merc = &md->mercenary; if (opt&SCO_FIRST) { memcpy(status, &md->db->status, sizeof(struct status_data)); @@ -8453,7 +8453,7 @@ const char* status_get_name(struct block_list *bl) case BL_MOB: return ((TBL_MOB*)bl)->name; case BL_PET: return ((TBL_PET*)bl)->pet.name; case BL_HOM: return ((TBL_HOM*)bl)->homunculus.name; - //case BL_MER: // They only have database names which are global, not specific to GID. + case BL_MER: return ((TBL_MER *)bl)->db->name.c_str(); // They only have database names which are global, not specific to GID. case BL_NPC: return ((TBL_NPC*)bl)->name; case BL_ELEM: return ((TBL_ELEM *)bl)->db->name.c_str(); // They only have database names which are global, not specific to GID. } @@ -8813,7 +8813,7 @@ void status_set_viewdata(struct block_list *bl, int class_) vd = npc_get_viewdata(class_); else if (homdb_checkid(class_)) vd = hom_get_viewdata(class_); - else if (mercenary_db(class_)) + else if (mercenary_db.exists(class_)) vd = mercenary_get_viewdata(class_); else if (elemental_db.exists(class_)) vd = elemental_get_viewdata(class_); @@ -8943,7 +8943,7 @@ void status_set_viewdata(struct block_list *bl, int class_) break; case BL_MER: { - struct mercenary_data *md = (struct mercenary_data*)bl; + s_mercenary_data *md = (s_mercenary_data*)bl; if (vd) md->vd = vd; else diff --git a/src/map/status.hpp b/src/map/status.hpp index 44345ccc0b..5f0425b309 100644 --- a/src/map/status.hpp +++ b/src/map/status.hpp @@ -17,7 +17,7 @@ struct block_list; struct mob_data; struct pet_data; struct homun_data; -struct mercenary_data; +struct s_mercenary_data; struct s_elemental_data; struct npc_data; struct status_change; @@ -2881,7 +2881,7 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt); void status_calc_pet_(struct pet_data* pd, enum e_status_calc_opt opt); int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt); int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt); -int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt); +int status_calc_mercenary_(s_mercenary_data *md, e_status_calc_opt opt); int status_calc_elemental_(s_elemental_data *ed, e_status_calc_opt opt); int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt); diff --git a/src/map/unit.cpp b/src/map/unit.cpp index 6c160b46b1..48e59d3c2f 100644 --- a/src/map/unit.cpp +++ b/src/map/unit.cpp @@ -65,7 +65,7 @@ struct unit_data* unit_bl2ud(struct block_list *bl) case BL_PET: return &((struct pet_data*)bl)->ud; case BL_NPC: return &((struct npc_data*)bl)->ud; case BL_HOM: return &((struct homun_data*)bl)->ud; - case BL_MER: return &((struct mercenary_data*)bl)->ud; + case BL_MER: return &((s_mercenary_data*)bl)->ud; case BL_ELEM: return &((s_elemental_data*)bl)->ud; default : return NULL; } @@ -3216,7 +3216,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, break; } case BL_MER: { - struct mercenary_data *md = (struct mercenary_data *)bl; + s_mercenary_data *md = (s_mercenary_data *)bl; ud->canact_tick = ud->canmove_tick; @@ -3557,7 +3557,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) break; } case BL_MER: { - struct mercenary_data *md = (TBL_MER*)bl; + s_mercenary_data *md = (TBL_MER*)bl; struct map_session_data *sd = md->master; if( mercenary_get_lifetime(md) > 0 ) diff --git a/src/tool/csv2yaml.cpp b/src/tool/csv2yaml.cpp index d15cef497e..a10d26ed08 100644 --- a/src/tool/csv2yaml.cpp +++ b/src/tool/csv2yaml.cpp @@ -130,6 +130,14 @@ static void elemental_skill_txt_data(const std::string& modePath, const std::str sv_readdb(fixedPath.c_str(), "elemental_skill_db.txt", ',', 4, 4, -1, read_elemental_skilldb, false); } +// Mercenary's Skill Database data to memory +static void mercenary_skill_txt_data(const std::string& modePath, const std::string& fixedPath) { + mercenary_skill_tree.clear(); + + if (fileExists(fixedPath + "/mercenary_skill_db.txt")) + sv_readdb(fixedPath.c_str(), "mercenary_skill_db.txt", ',', 3, 3, -1, mercenary_read_skilldb, false); +} + template bool process( const std::string& type, uint32 version, const std::vector& paths, const std::string& name, Func lambda, const std::string& rename = "" ){ for( const std::string& path : paths ){ @@ -489,6 +497,12 @@ int do_init( int argc, char** argv ){ return 0; } + mercenary_skill_txt_data(path_db_mode, path_db); + if (!process("MERCENARY_DB", 1, root_paths, "mercenary_db", [](const std::string &path, const std::string &name_ext) -> bool { + return sv_readdb(path.c_str(), name_ext.c_str(), ',', 26, 26, -1, &mercenary_readdb, false); + })) { + return 0; + } // TODO: add implementations ;-) return 0; @@ -4528,3 +4542,111 @@ static bool read_elementaldb(char* str[], int columns, int current) { return true; } + +// mercenary_db.yml function +//--------------------------- +static bool mercenary_read_skilldb(char* str[], int columns, int current) { + uint16 skill_id = atoi(str[1]); + std::string *skill_name = util::umap_find(aegis_skillnames, skill_id); + + if (skill_name == nullptr) { + ShowError("mercenary_read_skilldb: Invalid skill '%hu'.\n", skill_id); + return false; + } + + s_mercenary_skill_csv entry = {}; + + entry.skill_name = *skill_name; + entry.max_lv = atoi(str[2]); + + uint16 class_ = atoi(str[0]); + + if (util::umap_find(mercenary_skill_tree, class_)) + mercenary_skill_tree[class_].push_back(entry); + else { + mercenary_skill_tree[class_] = std::vector(); + mercenary_skill_tree[class_].push_back(entry); + } + + return true; +} + +// Copied and adjusted from mercenary.cpp +static bool mercenary_readdb(char* str[], int columns, int current) { + body << YAML::BeginMap; + body << YAML::Key << "Id" << YAML::Value << str[0]; + body << YAML::Key << "AegisName" << YAML::Value << str[1]; + body << YAML::Key << "Name" << YAML::Value << str[2]; + if (atoi(str[3]) != 1) + body << YAML::Key << "Level" << YAML::Value << str[3]; + if (atoi(str[4]) != 1) + body << YAML::Key << "Hp" << YAML::Value << str[4]; + if (atoi(str[5]) != 1) + body << YAML::Key << "Sp" << YAML::Value << str[5]; + if (atoi(str[7]) != 0) + body << YAML::Key << "Attack" << YAML::Value << str[7]; + if (atoi(str[8]) != 0) + body << YAML::Key << "Attack2" << YAML::Value << str[8]; + if (atoi(str[9]) != 0) + body << YAML::Key << "Defense" << YAML::Value << str[9]; + if (atoi(str[10]) != 0) + body << YAML::Key << "MagicDefense" << YAML::Value << str[10]; + if (atoi(str[11]) != 1) + body << YAML::Key << "Str" << YAML::Value << str[11]; + if (atoi(str[12]) != 1) + body << YAML::Key << "Agi" << YAML::Value << str[12]; + if (atoi(str[13]) != 1) + body << YAML::Key << "Vit" << YAML::Value << str[13]; + if (atoi(str[14]) != 1) + body << YAML::Key << "Int" << YAML::Value << str[14]; + if (atoi(str[15]) != 1) + body << YAML::Key << "Dex" << YAML::Value << str[15]; + if (atoi(str[16]) != 1) + body << YAML::Key << "Luk" << YAML::Value << str[16]; + if (atoi(str[6]) != 0) + body << YAML::Key << "AttackRange" << YAML::Value << str[6]; + if (atoi(str[17]) != 0) + body << YAML::Key << "SkillRange" << YAML::Value << str[17]; + if (atoi(str[18]) != 0) + body << YAML::Key << "ChaseRange" << YAML::Value << str[18]; + if (atoi(str[19]) != 0) + body << YAML::Key << "Size" << YAML::Value << constant_lookup(strtol(str[19], nullptr, 10), "Size_") + 5; + if (atoi(str[20]) != 0) + body << YAML::Key << "Race" << YAML::Value << name2Upper(constant_lookup(atoi(str[20]), "RC_") + 3); + + int ele = strtol(str[21], nullptr, 10); + if (atoi(str[21]) != 0) + body << YAML::Key << "Element" << YAML::Value << name2Upper(constant_lookup(ele % 20, "ELE_") + 4); + if (atoi(str[21]) != 1) + body << YAML::Key << "ElementLevel" << YAML::Value << floor(ele / 20.); + + if (atoi(str[22]) != 0) + body << YAML::Key << "WalkSpeed" << YAML::Value << cap_value(std::stoi(str[22]), MIN_WALK_SPEED, MAX_WALK_SPEED); + if (atoi(str[23]) != 0) + body << YAML::Key << "AttackDelay" << YAML::Value << str[23]; + if (atoi(str[24]) != 0) + body << YAML::Key << "AttackMotion" << YAML::Value << str[24]; + if (atoi(str[25]) != 0) + body << YAML::Key << "DamageMotion" << YAML::Value << str[25]; + + for (const auto &skillit : mercenary_skill_tree) { + if (skillit.first != atoi(str[0])) + continue; + + body << YAML::Key << "Skills"; + body << YAML::BeginSeq; + + for (const auto &it : skillit.second) { + body << YAML::BeginMap; + body << YAML::Key << "Name" << YAML::Value << it.skill_name; + body << YAML::Key << "MaxLevel" << YAML::Value << it.max_lv; + body << YAML::EndMap; + } + + body << YAML::EndSeq; + } + + body << YAML::EndMap; + + return true; +} diff --git a/src/tool/csv2yaml.hpp b/src/tool/csv2yaml.hpp index cd2d1675fc..abda1463d3 100644 --- a/src/tool/csv2yaml.hpp +++ b/src/tool/csv2yaml.hpp @@ -128,6 +128,13 @@ struct s_elemental_skill_csv { std::unordered_map> elemental_skill_tree; +struct s_mercenary_skill_csv { + std::string skill_name; + uint16 max_lv; +}; + +std::unordered_map> mercenary_skill_tree; + static std::map um_mapid2jobname { { "Novice", JOB_NOVICE }, // Novice and Super Novice share the same value { "SuperNovice", JOB_NOVICE }, @@ -486,5 +493,7 @@ static bool pc_readdb_job_basehpsp(char *fields[], int columns, int current); static bool pc_readdb_job1(char *fields[], int columns, int current); static bool read_elemental_skilldb(char* str[], int columns, int current); static bool read_elementaldb(char* str[], int columns, int current); +static bool mercenary_read_skilldb(char* str[], int columns, int current); +static bool mercenary_readdb(char* str[], int columns, int current); #endif /* CSV2YAML_HPP */