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 <aleos89@users.noreply.github.com>
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
This commit is contained in:
Atemo 2021-12-07 00:49:44 +01:00 committed by GitHub
parent 9b05754071
commit 4a778815a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 3107 additions and 771 deletions

View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/>.
#
###########################################################################
# 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

View File

@ -1,5 +0,0 @@
// Mercenary Skill Database
//
// Structure of Database:
// MercenryID,SkillID,SkillLevel

View File

@ -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

1438
db/mercenary_db.yml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/>.
#
###########################################################################
# 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

613
db/re/mercenary_db.yml Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
#
###########################################################################
# 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

View File

@ -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

View File

@ -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.
###########################################################################

View File

@ -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;

View File

@ -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;
}

View File

@ -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 <var id>.W <value>.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 <packet len>.W { <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradable>.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;

View File

@ -323,8 +323,7 @@
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\magicmushroom_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\magicmushroom_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\map_cache.dat" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\map_cache.dat')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\map_index.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\map_index.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mercenary_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mercenary_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mercenary_skill_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mercenary_skill_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mercenary_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mercenary_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mob_avail.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mob_avail.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mob_summon.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mob_summon.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mob_chat_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mob_chat_db.yml')" />

View File

@ -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);
}

View File

@ -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) \

View File

@ -29,16 +29,7 @@
using namespace rathena;
std::map<uint16, struct s_mercenary_db> 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<s_mercenary_db> 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<s_mercenary_db> 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<s_mercenary_db> 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<sc_type> 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<s_mercenary_db> 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<s_mercenary_db>();
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<ARRAYLENGTH(filename); i++){
sv_readdb(db_path, filename[i], ',', 26, 26, -1, &mercenary_readdb_sub, i > 0);
}
}
/**
* Read each line of Mercenary's skill
**/
static bool mercenary_read_skilldb_sub(char* str[], int columns, int current)
{// <merc id>,<skill id>,<skill level>
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<defType>(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<defType>(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<e_size>(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<e_race>(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<e_element>(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<uint8>(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<ARRAYLENGTH(filename); i++){
sv_readdb(db_path, filename[i], ',', 3, 3, -1, &mercenary_read_skilldb_sub, 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();
}

View File

@ -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<uint16, uint16> 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<s_mercenary_db> db;
s_mercenary mercenary;
std::vector<uint16> 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<int32, s_mercenary_db> {
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);

View File

@ -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 )

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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 )

View File

@ -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<typename Func>
bool process( const std::string& type, uint32 version, const std::vector<std::string>& 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<s_mercenary_skill_csv>();
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;
}

View File

@ -128,6 +128,13 @@ struct s_elemental_skill_csv {
std::unordered_map<uint16, std::vector<s_elemental_skill_csv>> elemental_skill_tree;
struct s_mercenary_skill_csv {
std::string skill_name;
uint16 max_lv;
};
std::unordered_map<uint16, std::vector<s_mercenary_skill_csv>> mercenary_skill_tree;
static std::map<std::string, int> 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 */