Converted item_combo_db txt to yml (#6162)
* Converts item_combo_db.txt into YAML. * Includes CSV2YAML converter. Thanks to @llchrisll and @Everade Co-authored-by: Lemongrass3110 <lemongrass@kstp.at> Co-authored-by: Aleos <aleos89@users.noreply.github.com>
This commit is contained in:
parent
0fa79030e7
commit
c8d1d1ea1e
@ -1,5 +0,0 @@
|
||||
// Item Combos Database
|
||||
//
|
||||
// Structure of Database:
|
||||
// ID:ID:ID:ID,{ Script }
|
||||
|
34
db/import-tmpl/item_combos.yml
Normal file
34
db/import-tmpl/item_combos.yml
Normal file
@ -0,0 +1,34 @@
|
||||
# This file is a part of rAthena.
|
||||
# Copyright(C) 2022 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/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Item Combo Database
|
||||
###########################################################################
|
||||
#
|
||||
# Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Combos: List of combo sets.
|
||||
# - Combo: Sequence of items to define a combo (minimum of 2 items).
|
||||
# - <item name> AEGIS name of the item
|
||||
# Script Script to execute when one of the combos is equipped. (Default: null)
|
||||
# Clear Remove the defined combos from database. (Default: false)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: COMBO_DB
|
||||
Version: 1
|
42
db/item_combos.yml
Normal file
42
db/item_combos.yml
Normal file
@ -0,0 +1,42 @@
|
||||
# This file is a part of rAthena.
|
||||
# Copyright(C) 2022 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/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Item Combo Database
|
||||
###########################################################################
|
||||
#
|
||||
# Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Combos: List of combo sets.
|
||||
# - Combo: Sequence of items to define a combo (minimum of 2 items).
|
||||
# - <item name> AEGIS name of the item
|
||||
# Script Script to execute when one of the combos is equipped. (Default: null)
|
||||
# Clear Remove the defined combos from database. (Default: false)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: COMBO_DB
|
||||
Version: 1
|
||||
|
||||
Footer:
|
||||
Imports:
|
||||
- Path: db/pre-re/item_combos.yml
|
||||
Mode: Prerenewal
|
||||
- Path: db/re/item_combos.yml
|
||||
Mode: Renewal
|
||||
- Path: db/import/item_combos.yml
|
@ -1,167 +0,0 @@
|
||||
// Item Combos Database
|
||||
//
|
||||
// Structure of Database:
|
||||
// ID:ID:ID:ID,{ Script }
|
||||
|
||||
1166:2527,{ bonus2 bAddRace,RC_Dragon,5; }
|
||||
1420:2115,{ bonus3 bAutoSpellWhenHit,"HP_ASSUMPTIO",2,5; }
|
||||
1420:2133,{ bonus2 bAddClass,Class_All,4; bonus bDef,2; }
|
||||
1421:2133,{ bonus2 bAddClass,Class_All,4; bonus bDef,2; }
|
||||
1422:2133,{ bonus2 bAddClass,Class_All,4; bonus bDef,2; }
|
||||
1428:2115,{ bonus3 bAutoSpellWhenHit,"HP_ASSUMPTIO",2,5; }
|
||||
1472:2677,{ bonus bMatkRate,6; bonus bDex,2; bonus bCastrate,-getequiprefinerycnt(EQI_HEAD_TOP); }
|
||||
1472:2711,{ bonus bMatkRate,6; bonus bDex,2; bonus bCastrate,-getequiprefinerycnt(EQI_HAND_R); }
|
||||
1473:2677,{ bonus bMatkRate,6; bonus bDex,2; bonus bCastrate,-getequiprefinerycnt(EQI_HEAD_TOP); }
|
||||
1473:2711,{ bonus bMatkRate,6; bonus bDex,2; bonus bCastrate,-getequiprefinerycnt(EQI_HAND_R); }
|
||||
1474:2527,{ bonus2 bAddRace,RC_Dragon,5; }
|
||||
1477:2700,{ bonus2 bResEff,Eff_Confusion,9500; }
|
||||
1479:2700,{ bonus2 bResEff,Eff_Confusion,9500; }
|
||||
1535:4361,{ bonus bBreakArmorRate,900; bonus bBreakWeaponRate,900; }
|
||||
1572:2716:2717,{ bonus bInt,5; bonus bMaxHP,700; bonus bAspdRate,5; }
|
||||
1573:2334,{ bonus bMdef,8; bonus bMaxSPRate,10; bonus bInt,4; }
|
||||
1573:2372,{ bonus bMdef,8; bonus bMaxSPRate,10; bonus bInt,4; }
|
||||
1573:2716:2717,{ bonus bInt,5; bonus bMaxHP,700; bonus bAspdRate,5; }
|
||||
1615:18539,{ bonus bMatk,10*getequiprefinerycnt(EQI_HAND_R); bonus bCastRate,-10; }
|
||||
1616:2515,{ bonus bSpeedRate,25; }
|
||||
1618:2509,{ bonus bMaxHP,300; bonus bMatkRate,min(5, getequiprefinerycnt(EQI_HAND_R)-5); bonus2 bSubEle,Ele_Neutral,min(30, getequiprefinerycnt(EQI_GARMENT)*3); }
|
||||
1618:2535,{ bonus bMatkRate,5; bonus2 bSubEle,Ele_Neutral,25; }
|
||||
1620:2509,{ bonus bMaxHP,300; bonus bMatkRate,getequiprefinerycnt(EQI_HAND_R)-5; if(getequiprefinerycnt(EQI_GARMENT) > 10) { bonus2 bSubEle,Ele_Neutral,30; } else { bonus2 bSubEle,Ele_Neutral,getequiprefinerycnt(EQI_GARMENT)*3; } }
|
||||
1620:2535,{ bonus bMatkRate,5; bonus2 bSubEle,Ele_Neutral,25; }
|
||||
1629:5045,{ bonus bDex,2; bonus bInt,2; bonus bSPrecovRate,5; bonus bMatkRate,getequiprefinerycnt(EQI_HAND_R); }
|
||||
1631:2129,{ bonus2 bSkillAtk,"PR_MAGNUS",20; bonus3 bAutoSpellWhenHit,"PR_TURNUNDEAD",1,20; }
|
||||
1636:18539,{ bonus bMatk,10*getequiprefinerycnt(EQI_HAND_R); bonus bCastRate,-10; }
|
||||
1723:2718,{ bonus bDex,1; bonus bMaxSP,50; bonus bSPrecovRate,10; }
|
||||
1730:1752,{ bonus bLongAtkRate,25; }
|
||||
1731:1754,{ bonus bLongAtkRate,25; }
|
||||
1732:1756,{ bonus bLongAtkRate,25; bonus2 bAddEff,Eff_Stone,1000; }
|
||||
1733:1755,{ bonus bLongAtkRate,25; bonus3 bAutoSpell,"NJ_HUUJIN",5,100; if(readparam(bInt)>39) bonus3 bAutoSpell,"NJ_HUUJIN",5,200; }
|
||||
1734:1753,{ bonus bLongAtkRate,50; }
|
||||
1741:2748,{ bonus bAtk,25; bonus3 bAddEff,Eff_Curse,200,ATF_WEAPON|ATF_LONG|ATF_TARGET; }
|
||||
2001:2677,{ bonus bMatkRate,10; bonus bDex,2; bonus2 bSubRace,RC_Demon,10; bonus2 bSubRace,RC_Undead,10; }
|
||||
2001:2711,{ bonus bMatkRate,10; bonus bDex,2; bonus2 bSubRace,RC_Demon,10; bonus2 bSubRace,RC_Undead,10; }
|
||||
2109:2717:2239,{ bonus bHPrecovRate,15; bonus bSPrecovRate,15; bonus bMatkRate,7; }
|
||||
2114:2353:5122,{ bonus bStr,2; bonus bDef,5; bonus bMdef,5; if(BaseClass==Job_Swordman) bonus bDef,6; }
|
||||
2115:2353:5124,{ bonus bDef,2-getequiprefinerycnt(EQI_HAND_L)-getequiprefinerycnt(EQI_HEAD_TOP); bonus bMdef,5+getequiprefinerycnt(EQI_HAND_L)+getequiprefinerycnt(EQI_HEAD_TOP); }
|
||||
2116:2355:2420:2521:5125,{ bonus bMaxHP,900; bonus bMaxSP,100; bonus3 bAutoSpellWhenHit,"HP_ASSUMPTIO",1,30; }
|
||||
2121:2717:2239,{ bonus bHPrecovRate,15; bonus bSPrecovRate,15; bonus bMatkRate,7; }
|
||||
2123:2701,{ bonus bCastrate,-10; }
|
||||
2124:2702,{ bonus bAspdRate,10; bonus bShortWeaponDamageReturn,5; }
|
||||
2135:2426,{ bonus2 bAddEff,Eff_Blind,500; autobonus "{ bonus bFlee,20; }",200,10000,BF_WEAPON,"{ specialeffect2 EF_INCAGILITY; }"; }
|
||||
2137:2353:5124,{ bonus bDef,2-getequiprefinerycnt(EQI_HAND_L)-getequiprefinerycnt(EQI_HEAD_TOP); bonus bMdef,5+getequiprefinerycnt(EQI_HAND_L)+getequiprefinerycnt(EQI_HEAD_TOP); }
|
||||
//2269:5768,{ bonus bInt,1; if(getequiprefinerycnt(EQI_HEAD_TOP) > 6) bonus bMaxSPrate,getequiprefinerycnt(EQI_HEAD_TOP)-6; }
|
||||
//2270:5768,{ bonus bStr,1; if(getequiprefinerycnt(EQI_HEAD_TOP) > 2) bonus bUseSPrate,2-getequiprefinerycnt(EQI_HEAD_TOP); }
|
||||
2278:18656,{ bonus2 bAddMonsterDropItem,12192,1; }
|
||||
2281:18656,{ bonus bFlee,10; bonus2 bAddEff,Eff_Stun,1000; }
|
||||
2286:18539,{ bonus bUseSPrate,-3; }
|
||||
2312:2656,{ bonus bDef,5; bonus bMaxHP,150; }
|
||||
2313:2656,{ bonus bDef,5; bonus bMaxHP,150; }
|
||||
2337:2654,{ bonus bUseSPrate,-20; bonus bMaxHP,300; }
|
||||
2339:2522,{ bonus bAgi,5; bonus bFlee,10; }
|
||||
2339:2523,{ bonus bAgi,5; bonus bFlee,10; }
|
||||
2353:2417:2516,{ bonus bAgi,3; bonus bMaxHPrate,5; bonus bMaxSPrate,5; }
|
||||
2353:2418:2517,{ bonus bVit,5; bonus bHPrecovRate,10; bonus bSPrecovRate,10; }
|
||||
2353:5123,{ if(readparam(bDex)>69) bonus bUseSPrate,-10; }
|
||||
2353:5493,{ if(readparam(bDex)>69) bonus bUseSPrate,-10; }
|
||||
2354:2419:2520:5128,{ bonus bVit,5; bonus bMaxHPrate,15; bonus bMaxSPrate,5; bonus bDef,5; bonus bMdef,15; bonus2 bSubEle,Ele_Water,10; bonus2 bSubEle,Ele_Earth,10; bonus2 bSubEle,Ele_Fire,10; bonus2 bSubEle,Ele_Wind,10; }
|
||||
2357:2421:2524:5171,{ bonus bAllStats,1; }
|
||||
2358:5153,{ bonus bLuk,6; bonus bFlee,5; bonus bInt,2; }
|
||||
2359:2654,{ bonus bUseSPrate,-20; bonus bMaxHP,300; }
|
||||
2369:2428:2533:5306,{ bonus2 bSubRace,RC_DemiHuman,10; bonus2 bSubRace,RC_Player_Human,10; bonus bMaxHPrate,20; bonus2 bResEff,Eff_Freeze,10000; skill "WZ_FROSTNOVA",10; }
|
||||
2371:2522,{ bonus bAgi,5; bonus bFlee,10; }
|
||||
2371:2523,{ bonus bAgi,5; bonus bFlee,10; }
|
||||
2374:2729,{ bonus2 bAddClass,Class_All,3; bonus bMatkRate,3; }
|
||||
2375:2729,{ bonus2 bAddClass,Class_All,3; bonus bMatkRate,3; }
|
||||
2376:2435:2538,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player_Human,300; bonus bVit,3; bonus bMaxHPRate,12; bonus bHealpower2,10; bonus bAddItemHealRate,10; autobonus2 "{ bonus2 bHPRegenRate,600,1000; }",5,10000,BF_WEAPON,"{ specialeffect2 EF_HEAL; }"; }
|
||||
2377:2435:2538,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player_Human,300; bonus bStr,3; bonus bMaxHPRate,12; bonus2 bSkillAtk,"MC_MAMMONITE",20; bonus2 bSkillHeal,"AM_POTIONPITCHER",10; bonus2 bSkillHeal2,"AM_POTIONPITCHER",10; bonus2 bSkillHeal2,"AL_HEAL",10; bonus bUnbreakableArmor; }
|
||||
2378:2435:2538,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player_Human,300; bonus bAgi,3; bonus bMaxHPRate,12; bonus bCritical,5; bonus bAspdRate,5; autobonus "{ bonus2 bHPRegenRate,300,1000; }",10,10000,BF_WEAPON,"{ specialeffect2 EF_HEAL; }"; }
|
||||
2379:2436:2539,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player_Human,300; bonus bInt,3; bonus bMaxHPRate,12; bonus2 bResEff,Eff_Stun,2000; autobonus2 "{ bonus bDefEle,Ele_Ghost; }",30,10000,BF_WEAPON,"{ specialeffect2 EF_ENERGYCOAT; }"; }
|
||||
2380:2436:2539,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player_Human,300; bonus bInt,3; bonus bMaxHPRate,12; bonus2 bCastrate,"AL_HOLYLIGHT",-50; bonus bHealPower,6; autobonus2 "{ bonus bDefEle,Ele_Ghost; }",30,10000,BF_WEAPON,"{ specialeffect2 EF_ENERGYCOAT; }"; }
|
||||
2381:2436:2539,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player_Human,300; bonus bDex,3; bonus bMaxHPRate,12; bonus bLongAtkDef,10; bonus bDelayRate,-25; }
|
||||
2382:2437:2540,{ bonus2 bSubRace,RC_All,-300; bonus2 bSubRace,RC_DemiHuman,300; bonus2 bSubRace,RC_Player_Human,300; bonus bDex,3; bonus bMaxHPRate,12; bonus bLongAtkDef,10; bonus bDelayRate,-25; }
|
||||
2387:2440:2744,{ bonus bMaxHPrate,7; bonus bMaxSPrate,7; bonus bCastrate,-3; bonus bDelayrate,-15; }
|
||||
2390:2749,{ bonus bFlee2,5; }
|
||||
2394:2444:2549,{ bonus2 bAddClass,Class_All,5; bonus bMatkRate,5; bonus2 bResEff,Eff_Freeze,10000; bonus2 bSkillHeal2,"AM_POTIONPITCHER",3; bonus2 bSkillHeal2,"AL_HEAL",3; bonus2 bSkillHeal2,"PR_SANCTUARY",3; }
|
||||
2399:2553,{ bonus bAgi,5; bonus bFlee,15; }
|
||||
2408:2655,{ bonus bBaseAtk,50; bonus2 bAddDefMonster,1196,20; bonus2 bAddDefMonster,1197,20; }
|
||||
2424:2528,{ bonus bHPrecovRate,5; bonus bMaxHPrate,10; }
|
||||
2425:2529,{ bonus bFlee,10; }
|
||||
2425:2530,{ bonus bFlee,10; }
|
||||
2425:2551,{ bonus bFlee,10; }
|
||||
2433:2537,{ bonus bMaxHPRate,6; }
|
||||
2434:2529,{ bonus bFlee,10; }
|
||||
2434:2530,{ bonus bFlee,10; }
|
||||
2434:2551,{ bonus bFlee,10; }
|
||||
2441:2546,{ bonus bFlee,5; }
|
||||
2518:2648:2649:5126,{ bonus bInt,5; bonus bMdef,11; bonus bMaxSPrate,20; bonus bNoCastCancel; bonus bCastrate,25; }
|
||||
2519:2650:2651:5127,{ bonus bStr,2; bonus bLuk,9; bonus bCritical,13; bonus bBaseAtk,18; bonus bFlee2,13; }
|
||||
2527:13001,{ bonus2 bAddRace,RC_Dragon,5; }
|
||||
2607:2677,{ bonus2 bSkillAtk,"AL_HEAL",50; bonus2 bSkillAtk,"PR_MAGNUS",30; bonus bSPrecovRate,9; }
|
||||
2607:2711,{ bonus2 bSkillAtk,"AL_HEAL",50; bonus2 bSkillAtk,"PR_MAGNUS",30; bonus bSPrecovRate,9; }
|
||||
2607:2786,{ bonus2 bSkillAtk,"AL_HEAL",50; bonus2 bSkillAtk,"PR_MAGNUS",30; bonus bSPrecovRate,9; }
|
||||
2608:2677,{ bonus2 bSkillAtk,"AL_HEAL",50; bonus2 bSkillAtk,"PR_MAGNUS",30; bonus bSPrecovRate,9; }
|
||||
2608:2711,{ bonus2 bSkillAtk,"AL_HEAL",50; bonus2 bSkillAtk,"PR_MAGNUS",30; bonus bSPrecovRate,9; }
|
||||
2608:2786,{ bonus2 bSkillAtk,"AL_HEAL",50; bonus2 bSkillAtk,"PR_MAGNUS",30; bonus bSPrecovRate,9; }
|
||||
2620:2746,{ bonus2 bAddSize,Size_Medium,8; bonus bAspdRate,getequiprefinerycnt(EQI_HAND_R)/2; }
|
||||
2620:2747,{ bonus2 bAddSize,Size_Large,8; bonus bHit,getequiprefinerycnt(EQI_HAND_R)/2; bonus bCastrate,-getequiprefinerycnt(EQI_HAND_R)/2; }
|
||||
2626:2677,{ bonus2 bSkillAtk,"AL_HEAL",50; bonus2 bSkillAtk,"PR_MAGNUS",30; bonus bSPrecovRate,9; }
|
||||
2626:2711,{ bonus2 bSkillAtk,"AL_HEAL",50; bonus2 bSkillAtk,"PR_MAGNUS",30; bonus bSPrecovRate,9; }
|
||||
2626:2786,{ bonus2 bSkillAtk,"AL_HEAL",50; bonus2 bSkillAtk,"PR_MAGNUS",30; bonus bSPrecovRate,9; }
|
||||
2678:2679,{ bonus4 bAutoSpell,"MO_EXTREMITYFIST",1,3,1; bonus3 bAutoSpell,"PR_LEXAETERNA",1,20; bonus3 bAutoSpell,"AS_SONICBLOW",5,50; bonus3 bAutoSpell,"MO_INVESTIGATE",5,20; bonus3 bAutoSpell,"ASC_METEORASSAULT",2,50; }
|
||||
//2679:2792,{ bonus4 bAutoSpell,"MO_EXTREMITYFIST",1,3,1; bonus3 bAutoSpell,"PR_LEXAETERNA",1,20; bonus3 bAutoSpell,"AS_SONICBLOW",5,50; bonus3 bAutoSpell,"MO_INVESTIGATE",5,20; bonus3 bAutoSpell,"ASC_METEORASSAULT",2,50; }
|
||||
2720:2772,{ bonus2 bAddClass,Class_All,5; bonus bMatkRate,3; bonus bHealPower,5; }
|
||||
2721:2772,{ bonus2 bAddClass,Class_All,5; bonus bMatkRate,3; bonus bHealPower,5; }
|
||||
2722:2772,{ bonus2 bAddClass,Class_All,5; bonus bMatkRate,3; bonus bHealPower,5; }
|
||||
2723:2772,{ bonus2 bAddClass,Class_All,5; bonus bMatkRate,3; bonus bHealPower,5; }
|
||||
2724:2772,{ bonus2 bAddClass,Class_All,5; bonus bMatkRate,3; bonus bHealPower,5; }
|
||||
2725:2772,{ bonus2 bAddClass,Class_All,5; bonus bMatkRate,3; bonus bHealPower,5; }
|
||||
2726:2727,{ bonus bUseSPrate,-25; }
|
||||
2733:2772,{ bonus2 bAddClass,Class_All,5; bonus bMatkRate,3; bonus bHealPower,5; }
|
||||
2777:2778:5479,{ bonus bMaxHP,300; bonus bMatkRate,5; bonus2 bSubEle,Ele_Neutral,5; }
|
||||
2779:2780:5482,{ bonus bMatkRate,10; bonus bInt,5; bonus2 bSubRace,RC_Angel,10; }
|
||||
2779:2780:5577,{ bonus bMatkRate,10; bonus bInt,5; bonus2 bSubRace,RC_Angel,10; }
|
||||
4001:4197,{ bonus bFlee,18; }
|
||||
4006:4266,{ bonus bFlee,18; }
|
||||
4009:4179,{ bonus bFlee,18; }
|
||||
4014:4306,{ bonus bFlee,18; }
|
||||
4021:4211,{ bonus bFlee,18; }
|
||||
4025:4222,{ bonus2 bAddEffWhenHit,Eff_Sleep,600; }
|
||||
4028:4296,{ bonus bStr,3; }
|
||||
4029:4183,{ bonus bFlee,18; }
|
||||
4031:4161,{ bonus bDef,3; bonus bVit,3; }
|
||||
4036:4186:4233:4281:4343,{ bonus bStr,4; bonus bMaxHPrate,7; bonus bMaxSPrate,7; bonus2 bSkillAtk,"MC_MAMMONITE",20; bonus bSPDrainValue,1; if(BaseJob==Job_Alchemist) { bonus3 bAutoSpell,"BS_ADRENALINE",1,10; bonus2 bAddMonsterDropItem,7139,3; bonus2 bAddMonsterDropItem,905,10; } }
|
||||
4039:4210:4230:4257:4348,{ bonus bStr,6; bonus bAgi,4; bonus2 bSkillAtk,"RG_BACKSTAP",10; if(getskilllv("RG_STRIPARMOR")==5) bonus3 bAutoSpell,"RG_STRIPARMOR",5,50; if(BaseJob==Job_Rogue) { bonus bUseSPrate,-20; bonus3 bAutoSpell,"RG_INTIMIDATE",1,-20; } }
|
||||
4074:4162,{ bonus2 bAddEffWhenHit,Eff_Blind,600; }
|
||||
4090:4212:4328,{ bonus bAllStats,1; }
|
||||
4106:4248,{ bonus bPerfectHitAddRate,20; }
|
||||
4127:4166,{ bonus2 bAddEffWhenHit,Eff_Curse,600; }
|
||||
4153:4247:4273,{ bonus3 bAddMonsterDropItem,544,RC_Fish,3000; bonus2 bAddEle,Ele_Water,30; }
|
||||
4168:4169,{ bonus bMaxHPrate,20; bonus bMaxSPrate,20; bonus bCastrate,-10; }
|
||||
4172:4210:4230:4257:4272,{ bonus bAgi,5; bonus bStr,5; bonus bAspdRate,5; bonus bSpeedRate,25; bonus bSPDrainValue,1; if(BaseClass==Job_Thief) bonus bNoGemStone; }
|
||||
4178:4199:4234:4252:4297,{ bonus bAgi,5; bonus bDex,3; bonus bLongAtkRate,20; bonus bPerfectHitAddRate,20; if(BaseClass==Job_Archer) { bonus2 bExpAddRace,RC_Brute,5; bonus2 bComaRace,RC_Brute,100; bonus2 bComaRace,RC_Player_Doram,100; } }
|
||||
4178:4234:4252:4297:4381,{ bonus bDex,5; bonus2 bSkillAtk,"CG_ARROWVULCAN",5; bonus2 bSkillAtk,"DC_THROWARROW",10; bonus2 bSkillAtk,"BA_MUSICALSTRIKE",10; if(BaseJob==Job_Bard||BaseJob==Job_Dancer) bonus3 bAutoSpellWhenHit,"CG_TAROTCARD",2,50; }
|
||||
4185:4217:4280:4293:4312,{ bonus bVit,10; bonus bCastrate,-10; bonus bUseSPRate,-10; if(BaseClass==Job_Acolyte) { bonus2 bExpAddRace,RC_Undead,5; bonus2 bExpAddRace,RC_Demon,5; bonus2 bSubRace,RC_Undead,30; bonus2 bSubRace,RC_Demon,30; } }
|
||||
4185:4293:4312:4332,{ bonus bStr,3; bonus bMaxSP,80; bonus bBaseAtk,25; bonus3 bAutoSpell,"AL_CRUCIS",5,10; bonus2 bSkillAtk,"MO_EXTREMITYFIST",10; if(BaseJob==Job_Monk) { bonus bUseSPrate,-10; bonus bNoCastCancel; } }
|
||||
4186:4206:4233:4281:4321,{ bonus bLuk,10; bonus bSPDrainValue,2; bonus2 bSkillAtk,42,20; if(BaseClass==Job_Merchant) { bonus2 bAddMonsterDropItem,617,5; bonus bMagicDamageReturn,20; } }
|
||||
4191:4208:4258:4309:4325:4327,{ bonus bMaxHP,500; bonus bDef,5; bonus bMdef,5; bonus2 bSkillAtk,14,10; bonus2 bSkillAtk,19,10; bonus2 bSkillAtk,20,10; if(BaseClass==Job_Mage) { bonus bMatkRate,3; bonus bCastrate,-15; } }
|
||||
4193:4294,{ bonus bMaxHP,300; bonus bMaxSP,60; }
|
||||
4208:4258:4325:4327:4382,{ bonus bInt,3; bonus2 bSkillAtk,"WZ_HEAVENDRIVE",10; bonus2 bSkillAtk,"MG_THUNDERSTORM",10; if(BaseJob==Job_Sage) { bonus bMagicDamageReturn,20; bonus2 bAddMonsterDropItem,716,100; bonus2 bAddMonsterDropItem,715,100; bonus bCastrate,-20; } }
|
||||
4218:4269,{ bonus bHPrecovRate,30; bonus bSPrecovRate,30; bonus bVit,4; bonus bInt,4; }
|
||||
4220:4246:4311:4319:4331,{ bonus bStr,10; bonus bMaxHPrate,20; bonus bHPrecovRate,50; bonus3 bAutoSpell,"BS_WEAPONPERFECT",1,3; bonus2 bAddMonsterDropItem,501,500; if(BaseClass==Job_Swordman) bonus2 bAddItemGroupHealRate,IG_Potion,50; }
|
||||
4229:4244:4299:4313,{ bonus bDef,3; bonus bMdef,3; }
|
||||
4237:4238,{ bonus3 bAutoSpell,"MG_LIGHTNINGBOLT",5,20; }
|
||||
4268:4277,{ bonus bBaseAtk,20; bonus bLuk,3; }
|
||||
4311:4319:4331:4371,{ bonus bInt,1; bonus bStr,1; bonus bDef,2; bonus bSPrecovRate,10; bonus2 bSkillAtk,"PA_SHIELDCHAIN",10; bonus2 bSkillAtk,"PA_SACRIFICE",10; bonus bCastrate,-10; if(BaseJob==Job_Crusader) bonus bDefEle,Ele_Holy; }
|
||||
4323:4324,{ bonus3 bAutoSpell,"MG_FROSTDIVER",3,250; }
|
||||
4435:4436,{ bonus2 bSPGainRace,RC_DemiHuman,2; bonus2 bSPGainRace,RC_Player_Human,2; }
|
||||
5040:5442,{ bonus bAspdRate,3; bonus bCastrate,3; }
|
||||
5068:5653,{ bonus bStr,1; bonus bAtkRate,5; }
|
||||
5074:5653,{ bonus bStr,1; bonus bAspdRate,2; }
|
||||
5086:18656,{ bonus2 bAddMonsterDropItem,12192,1; bonus2 bAddMonsterDropItem,538,1; bonus2 bAddItemHealRate,12192,100; bonus2 bAddItemHealRate,538,100; }
|
||||
5176:18656,{ bonus bAspdRate,5; autobonus "{ bonus bAtk,50; }",5,10000,0,"{ specialeffect2 EF_POTION_BERSERK; }"; }
|
||||
//5206:5768,{ bonus bDex,1; if(getequiprefinerycnt(EQI_HEAD_TOP) > 4) bonus bDelayRate,4-getequiprefinerycnt(EQI_HEAD_TOP); }
|
||||
5358:5653,{ bonus bAgi,1; bonus bFlee,3; }
|
||||
//5359:5657,{ bonus bLongAtkRate,getequiprefinerycnt(EQI_HEAD_TOP); }
|
||||
5401:5653,{ bonus bInt,1; bonus bMatkRate,2; }
|
||||
//5470:5653,{ bonus bDex,1; bonus bLongAtkRate,3; }
|
||||
13034:13035,{ bonus bMaxSP,20; bonus bMaxHPRate,5; bonus bHit,10; bonus2 bAddSize,Size_Large,30; autobonus "{ bonus bAspdRate,100; }",1,7000,BF_WEAPON,"{ specialeffect2 EF_POTION_BERSERK; }"; }
|
||||
18507:18539,{ bonus bUseSPrate,-3; }
|
1152
db/pre-re/item_combos.yml
Normal file
1152
db/pre-re/item_combos.yml
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
22716
db/re/item_combos.yml
Normal file
22716
db/re/item_combos.yml
Normal file
File diff suppressed because it is too large
Load Diff
@ -1421,11 +1421,11 @@ Affected files:
|
||||
-- atcommand: atcommands.yml, groups.conf
|
||||
-- battleconf: battle_athena.conf, battle_conf.txt
|
||||
-- instancedb: instance_db.yml
|
||||
-- itemdb: item_db.yml, item_group_db.yml, item_noequip.txt, item_combo_db.txt, item_randomopt_db.yml, item_randomopt_group.yml
|
||||
-- mobdb: mob_db.yml, mob_item_ratio.yml, mob_chat_db.yml, mob_avail.yml, mob_summon.yml, pet_db.yml, homunculus_db.txt, homun_skill_tree.txt, exp_homun.yml, mercenary_db.txt, mercenary_skill_db.txt, elemental_db.txt, elemental_skill_db.txt
|
||||
-- itemdb: item_db.yml, item_group_db.yml, item_noequip.txt, item_combos.yml, item_randomopt_db.yml, item_randomopt_group.yml
|
||||
-- mobdb: mob_db.yml, mob_item_ratio.yml, mob_chat_db.yml, mob_avail.yml, mob_summon.yml, pet_db.yml, homunculus_db.txt, homun_skill_tree.txt, exp_homun.yml, mercenary_db.yml, elemental_db.yml
|
||||
-- motd: motd.txt
|
||||
-- msgconf: atcommands.yml
|
||||
-- pcdb: statpoint.yml, job_exp.yml, skill_tree.txt, attr_fix.yml, job_stats.yml, job_basepoints.yml, level_penalty.yml
|
||||
-- pcdb: statpoint.yml, job_exp.yml, skill_tree.yml, attr_fix.yml, job_stats.yml, job_basepoints.yml, level_penalty.yml
|
||||
-- questdb: quest_db.yml
|
||||
-- script: /npc/*.txt, /npc/*.conf
|
||||
-- skilldb: skill_db.yml, skill_nocast_db.txt, skill_changematerial_db.txt, skill_damage_db.txt, abra_db.yml, create_arrow_db.yml, produce_db.txt, spellbook_db.yml, magicmushroom_db.yml
|
||||
|
13
doc/yaml/db/item_combos.yml
Normal file
13
doc/yaml/db/item_combos.yml
Normal file
@ -0,0 +1,13 @@
|
||||
###########################################################################
|
||||
# Item Combo Database
|
||||
###########################################################################
|
||||
#
|
||||
# Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Combos: List of combo sets.
|
||||
# - Combo: Sequence of items to define a combo (minimum of 2 items).
|
||||
# - <item name> AEGIS name of the item
|
||||
# Script Script to execute when one of the combos is equipped. (Default: null)
|
||||
# Clear Remove the defined combos from database. (Default: false)
|
||||
###########################################################################
|
@ -24,8 +24,8 @@
|
||||
|
||||
using namespace rathena;
|
||||
|
||||
static std::map<uint32, std::shared_ptr<s_item_combo>> itemdb_combo; /// Item Combo DB
|
||||
|
||||
ComboDatabase itemdb_combo;
|
||||
ItemGroupDatabase itemdb_group;
|
||||
|
||||
struct s_roulette_db rd;
|
||||
@ -1206,21 +1206,6 @@ std::shared_ptr<item_data> ItemDatabase::searchname( const char *name ){
|
||||
|
||||
ItemDatabase item_db;
|
||||
|
||||
/**
|
||||
* Check if combo exists
|
||||
* @param combo_id
|
||||
* @return s_item_combo or nullptr if it does not exist
|
||||
*/
|
||||
s_item_combo *itemdb_combo_exists(uint32 combo_id) {
|
||||
auto item = util::map_find(itemdb_combo, combo_id);
|
||||
|
||||
if( item == nullptr ){
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return item.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an item exists in a group
|
||||
* @param group_id: Item Group ID
|
||||
@ -1932,142 +1917,154 @@ static bool itemdb_read_noequip(char* str[], int columns, int current) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return: amount of retrieved entries.
|
||||
**/
|
||||
static int itemdb_combo_split_atoi (char *str, t_itemid *val) {
|
||||
int i;
|
||||
const std::string ComboDatabase::getDefaultLocation() {
|
||||
return std::string(db_path) + "/item_combos.yml";
|
||||
}
|
||||
|
||||
for (i=0; i<MAX_ITEMS_PER_COMBO; i++) {
|
||||
if (!str) break;
|
||||
|
||||
val[i] = strtoul(str, nullptr, 10);
|
||||
|
||||
str = strchr(str,':');
|
||||
|
||||
if (str)
|
||||
*str++=0;
|
||||
uint16 ComboDatabase::find_combo_id( const std::vector<t_itemid>& items ){
|
||||
for (const auto &it : *this) {
|
||||
if (it.second->nameid == items) {
|
||||
return it.first;
|
||||
}
|
||||
}
|
||||
|
||||
if( i == 0 ) //No data found.
|
||||
return 0;
|
||||
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* <combo{:combo{:combo:{..}}}>,<{ script }>
|
||||
**/
|
||||
static void itemdb_read_combos(const char* basedir, bool silent) {
|
||||
uint32 lines = 0, count = 0;
|
||||
char line[1024];
|
||||
* Reads and parses an entry from the item_combos.
|
||||
* @param node: YAML node containing the entry.
|
||||
* @return count of successfully parsed rows
|
||||
*/
|
||||
uint64 ComboDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
std::vector<std::vector<t_itemid>> items_list;
|
||||
|
||||
char path[256];
|
||||
FILE* fp;
|
||||
|
||||
sprintf(path, "%s/%s", basedir, "item_combo_db.txt");
|
||||
|
||||
if ((fp = fopen(path, "r")) == NULL) {
|
||||
if(silent==0) ShowError("itemdb_read_combos: File not found \"%s\".\n", path);
|
||||
return;
|
||||
if( !this->nodesExist( node, { "Combos" } ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
// process rows one by one
|
||||
while(fgets(line, sizeof(line), fp)) {
|
||||
char *str[2], *p;
|
||||
const YAML::Node &combosNode = node["Combos"];
|
||||
|
||||
lines++;
|
||||
for (const auto &comboit : combosNode) {
|
||||
static const std::string nodeName = "Combo";
|
||||
|
||||
if (line[0] == '/' && line[1] == '/')
|
||||
continue;
|
||||
|
||||
memset(str, 0, sizeof(str));
|
||||
|
||||
p = line;
|
||||
|
||||
p = trim(p);
|
||||
|
||||
if (*p == '\0')
|
||||
continue;// empty line
|
||||
|
||||
if (!strchr(p,','))
|
||||
{
|
||||
/* is there even a single column? */
|
||||
ShowError("itemdb_read_combos: Insufficient columns in line %d of \"%s\", skipping.\n", lines, path);
|
||||
continue;
|
||||
if (!this->nodesExist(comboit, { nodeName })) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
str[0] = p;
|
||||
p = strchr(p,',');
|
||||
*p = '\0';
|
||||
p++;
|
||||
const YAML::Node &comboNode = comboit[nodeName];
|
||||
|
||||
str[1] = p;
|
||||
p = strchr(p,',');
|
||||
p++;
|
||||
|
||||
if (str[1][0] != '{') {
|
||||
ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
|
||||
continue;
|
||||
if (!comboNode.IsSequence()) {
|
||||
this->invalidWarning(comboNode, "%s should be a sequence.\n", nodeName.c_str());
|
||||
return 0;
|
||||
}
|
||||
/* no ending key anywhere (missing \}\) */
|
||||
if ( str[1][strlen(str[1])-1] != '}' ) {
|
||||
ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
|
||||
continue;
|
||||
} else {
|
||||
t_itemid items[MAX_ITEMS_PER_COMBO];
|
||||
int v = 0, retcount = 0;
|
||||
|
||||
if((retcount = itemdb_combo_split_atoi(str[0], items)) < 2) {
|
||||
ShowError("itemdb_read_combos: line %d of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, path);
|
||||
continue;
|
||||
std::vector<t_itemid> items = {};
|
||||
|
||||
for (const auto &it : comboNode) {
|
||||
std::string item_name = it.as<std::string>();
|
||||
|
||||
std::shared_ptr<item_data> item = item_db.search_aegisname(item_name.c_str());
|
||||
|
||||
if (item == nullptr) {
|
||||
this->invalidWarning(it, "Invalid item %s, skipping.\n", item_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
/* validate */
|
||||
for(v = 0; v < retcount; v++) {
|
||||
if( !itemdb_exists(items[v]) ) {
|
||||
ShowError("itemdb_read_combos: line %d of \"%s\" contains unknown item ID %" PRIu32 ", skipping.\n", lines, path,items[v]);
|
||||
break;
|
||||
|
||||
items.push_back(item->nameid);
|
||||
}
|
||||
|
||||
if (items.empty()) {
|
||||
this->invalidWarning(comboNode, "Empty combo, skipping.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (items.size() < 2) {
|
||||
this->invalidWarning(comboNode, "Not enough item to make a combo (need at least 2). Skipping.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::sort(items.begin(), items.end());
|
||||
items_list.push_back(items);
|
||||
}
|
||||
|
||||
if (items_list.empty()) {
|
||||
this->invalidWarning(combosNode, "No combos defined, skipping.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "Clear")) {
|
||||
bool clear = false;
|
||||
|
||||
if (!this->asBool(node, "Clear", clear))
|
||||
return 0;
|
||||
|
||||
// Remove the combo (if exists)
|
||||
if (clear) {
|
||||
for (const auto& itemsit : items_list) {
|
||||
uint16 id = this->find_combo_id(itemsit);
|
||||
|
||||
if (id == 0) {
|
||||
this->invalidWarning(node["Clear"], "Unable to clear the combo.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* failed at some item */
|
||||
if( v < retcount )
|
||||
continue;
|
||||
|
||||
// Create combo data
|
||||
auto entry = std::make_shared<s_item_combo>();
|
||||
|
||||
entry->nameid = {};
|
||||
entry->script = parse_script(str[1], path, lines, 0);
|
||||
entry->id = count;
|
||||
|
||||
// Store into first item
|
||||
item_data *id = itemdb_exists(items[0]);
|
||||
|
||||
id->combos.push_back(entry);
|
||||
|
||||
size_t idx = id->combos.size() - 1;
|
||||
|
||||
// Populate nameid field
|
||||
for (v = 0; v < retcount; v++)
|
||||
id->combos[idx]->nameid.push_back(items[v]);
|
||||
|
||||
// Populate the children to refer to this combo
|
||||
for (v = 1; v < retcount; v++) {
|
||||
item_data *it = itemdb_exists(items[v]);
|
||||
|
||||
// Copy to other combos in list
|
||||
it->combos.push_back(id->combos[idx]);
|
||||
this->erase(id);
|
||||
}
|
||||
|
||||
itemdb_combo.insert({ id->combos[idx]->id, id->combos[idx] });
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint64 count = 0;
|
||||
|
||||
for (const auto &itemsit : items_list) {
|
||||
// Find the id when the combo exists
|
||||
uint16 id = this->find_combo_id(itemsit);
|
||||
std::shared_ptr<s_item_combo> combo = this->find(id);
|
||||
bool exists = combo != nullptr;
|
||||
|
||||
if (!exists) {
|
||||
combo = std::make_shared<s_item_combo>();
|
||||
|
||||
combo->nameid.insert(combo->nameid.begin(), itemsit.begin(), itemsit.end());
|
||||
combo->id = ++this->combo_num;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "Script")) {
|
||||
std::string script;
|
||||
|
||||
if (!this->asString(node, "Script", script))
|
||||
return 0;
|
||||
|
||||
if (exists) {
|
||||
script_free_code(combo->script);
|
||||
combo->script = nullptr;
|
||||
}
|
||||
combo->script = parse_script(script.c_str(), this->getCurrentFile().c_str(), node["Script"].Mark().line + 1, SCRIPT_IGNORE_EXTERNAL_BRACKETS);
|
||||
} else {
|
||||
if (!exists) {
|
||||
combo->script = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists)
|
||||
this->put( combo->id, combo );
|
||||
|
||||
count++;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
ShowStatus("Done reading '" CL_WHITE "%u" CL_RESET "' entries in '" CL_WHITE "%s" CL_RESET "'.\n",count,path);
|
||||
return count;
|
||||
}
|
||||
|
||||
return;
|
||||
void ComboDatabase::loadingFinished() {
|
||||
// Populate item_data to refer to the combo
|
||||
for (const auto &combo : *this) {
|
||||
for (const auto &itm : combo.second->nameid) {
|
||||
item_data *it = itemdb_exists(itm);
|
||||
it->combos.push_back(combo.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2898,13 +2895,13 @@ static void itemdb_read(void) {
|
||||
safesnprintf(dbsubpath2,n1,"%s%s",db_path,dbsubpath[i]);
|
||||
}
|
||||
|
||||
itemdb_read_combos(dbsubpath2,i > 0); //TODO change this to sv_read ? id#script ?
|
||||
sv_readdb(dbsubpath2, "item_noequip.txt", ',', 2, 2, -1, &itemdb_read_noequip, i > 0);
|
||||
aFree(dbsubpath1);
|
||||
aFree(dbsubpath2);
|
||||
}
|
||||
|
||||
itemdb_group.load();
|
||||
itemdb_combo.load();
|
||||
random_option_db.load();
|
||||
random_option_group.load();
|
||||
}
|
||||
|
@ -23,8 +23,6 @@ const t_itemid UNKNOWN_ITEM_ID = 512;
|
||||
#define MAX_ITEMDELAYS 10
|
||||
///Designed for search functions, species max number of matches to display.
|
||||
#define MAX_SEARCH 5
|
||||
///Maximum amount of items a combo may require
|
||||
#define MAX_ITEMS_PER_COMBO 6
|
||||
|
||||
#define MAX_ROULETTE_LEVEL 7 /** client-defined value **/
|
||||
#define MAX_ROULETTE_COLUMNS 9 /** client-defined value **/
|
||||
@ -818,7 +816,7 @@ enum e_delay_consume : uint8 {
|
||||
struct s_item_combo {
|
||||
std::vector<t_itemid> nameid;
|
||||
script_code *script;
|
||||
uint32 id;
|
||||
uint16 id;
|
||||
|
||||
~s_item_combo() {
|
||||
if (this->script) {
|
||||
@ -830,6 +828,27 @@ struct s_item_combo {
|
||||
}
|
||||
};
|
||||
|
||||
class ComboDatabase : public TypesafeYamlDatabase<uint16, s_item_combo> {
|
||||
private:
|
||||
uint16 combo_num;
|
||||
uint16 find_combo_id( const std::vector<t_itemid>& items );
|
||||
|
||||
public:
|
||||
ComboDatabase() : TypesafeYamlDatabase("COMBO_DB", 1) {
|
||||
|
||||
}
|
||||
|
||||
void clear() {
|
||||
TypesafeYamlDatabase::clear();
|
||||
this->combo_num = 0;
|
||||
}
|
||||
const std::string getDefaultLocation();
|
||||
uint64 parseBodyNode(const YAML::Node& node);
|
||||
void loadingFinished();
|
||||
};
|
||||
|
||||
extern ComboDatabase itemdb_combo;
|
||||
|
||||
/// Struct of item group entry
|
||||
struct s_item_group_entry
|
||||
{
|
||||
@ -1133,8 +1152,6 @@ bool itemdb_isstackable2(struct item_data *id);
|
||||
#define itemdb_isstackable(nameid) itemdb_isstackable2(itemdb_search(nameid))
|
||||
bool itemdb_isNoEquip(struct item_data *id, uint16 m);
|
||||
|
||||
s_item_combo *itemdb_combo_exists(uint32 combo_id);
|
||||
|
||||
bool itemdb_parse_roulette_db(void);
|
||||
|
||||
void itemdb_reload(void);
|
||||
|
@ -311,7 +311,7 @@
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\homunculus_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\homunculus_db.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\instance_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\instance_db.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\item_cash_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\item_cash_db.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\item_combo_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\item_combo_db.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\item_combos.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\item_combos.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\item_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\item_db.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\item_group_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\item_group_db.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\item_noequip.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\item_noequip.txt')" />
|
||||
|
@ -5017,12 +5017,12 @@ int status_calc_pc_sub(struct map_session_data* sd, enum e_status_calc_opt opt)
|
||||
// Process and check item combos
|
||||
if (!sd->combos.empty()) {
|
||||
for (const auto &combo : sd->combos) {
|
||||
s_item_combo *item_combo;
|
||||
std::shared_ptr<s_item_combo> item_combo;
|
||||
|
||||
current_equip_item_index = -1;
|
||||
current_equip_combo_pos = combo->pos;
|
||||
|
||||
if (combo->bonus == nullptr || !(item_combo = itemdb_combo_exists(combo->id)))
|
||||
if (combo->bonus == nullptr || !(item_combo = itemdb_combo.find(combo->id)))
|
||||
continue;
|
||||
|
||||
bool no_run = false;
|
||||
|
@ -526,6 +526,18 @@ int do_init( int argc, char** argv ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!process("COMBO_DB", 1, { path_db_mode }, "item_combo_db", [](const std::string& path, const std::string& name_ext) -> bool {
|
||||
return itemdb_read_combos((path + name_ext).c_str());
|
||||
}, "item_combos")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!process("COMBO_DB", 1, { path_db_import }, "item_combo_db", [](const std::string& path, const std::string& name_ext) -> bool {
|
||||
return itemdb_read_combos((path + name_ext).c_str());
|
||||
}, "item_combos")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: add implementations ;-)
|
||||
|
||||
return 0;
|
||||
@ -4783,3 +4795,124 @@ static bool pc_readdb_skilltree_yaml(void) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Copied and adjusted from itemdb.cpp
|
||||
static int itemdb_combo_split_atoi (char *str, t_itemid *val) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_ITEMS_PER_COMBO; i++) {
|
||||
if (!str)
|
||||
break;
|
||||
val[i] = strtoul(str, nullptr, 10);
|
||||
str = strchr(str,':');
|
||||
if (str)
|
||||
*str++=0;
|
||||
}
|
||||
if (i == 0) //No data found.
|
||||
return 0;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// Copied and adjusted from itemdb.cpp
|
||||
static bool itemdb_read_combos(const char* file) {
|
||||
FILE* fp = fopen( file, "r" );
|
||||
|
||||
if( fp == nullptr ){
|
||||
ShowError( "Can't read %s\n", file );
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 lines = 0, count = 0;
|
||||
char line[1024];
|
||||
char path[256];
|
||||
|
||||
// process rows one by one
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
char *str[2], *p;
|
||||
|
||||
lines++;
|
||||
|
||||
if (line[0] == '/' && line[1] == '/')
|
||||
continue;
|
||||
|
||||
memset(str, 0, sizeof(str));
|
||||
|
||||
p = line;
|
||||
|
||||
p = trim(p);
|
||||
|
||||
if (*p == '\0')
|
||||
continue;// empty line
|
||||
|
||||
if (!strchr(p,',')) {
|
||||
ShowError("itemdb_read_combos: Insufficient columns in line %d of \"%s\", skipping.\n", lines, path);
|
||||
continue;
|
||||
}
|
||||
|
||||
str[0] = p;
|
||||
p = strchr(p,',');
|
||||
*p = '\0';
|
||||
p++;
|
||||
|
||||
str[1] = p;
|
||||
p = strchr(p,',');
|
||||
p++;
|
||||
|
||||
if (str[1][0] != '{') {
|
||||
ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
|
||||
continue;
|
||||
}
|
||||
if ( str[1][strlen(str[1])-1] != '}' ) {
|
||||
ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
|
||||
continue;
|
||||
}
|
||||
t_itemid items[MAX_ITEMS_PER_COMBO];
|
||||
int v = 0, retcount = 0;
|
||||
|
||||
if ((retcount = itemdb_combo_split_atoi(str[0], items)) < 2) {
|
||||
ShowError("itemdb_read_combos: line %d of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, path);
|
||||
continue;
|
||||
}
|
||||
for (v = 0; v < retcount; v++) {
|
||||
std::string *item_name = util::umap_find(aegis_itemnames, items[v]);
|
||||
|
||||
if (item_name == nullptr) {
|
||||
ShowWarning("itemdb_read_combos: Invalid item ID %" PRIu32 ".\n", items[v]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (v < retcount)
|
||||
continue;
|
||||
|
||||
body << YAML::BeginMap;
|
||||
body << YAML::Key << "Combos";
|
||||
body << YAML::BeginSeq;
|
||||
|
||||
body << YAML::BeginMap;
|
||||
body << YAML::Key << "Combo";
|
||||
body << YAML::BeginSeq;
|
||||
|
||||
for (v = 0; v < retcount; v++) {
|
||||
body << YAML::BeginMap;
|
||||
std::string *item_name = util::umap_find(aegis_itemnames, items[v]);
|
||||
body << YAML::Key << *item_name;
|
||||
body << YAML::EndMap;
|
||||
}
|
||||
body << YAML::EndSeq;
|
||||
body << YAML::EndMap;
|
||||
|
||||
str[1] = str[1] + 1; //skip the first left curly
|
||||
str[1][strlen(str[1])-1] = '\0'; //null the last right curly
|
||||
|
||||
body << YAML::EndSeq;
|
||||
body << YAML::Key << "Script" << YAML::Literal << trim(str[1]);
|
||||
body << YAML::EndMap;
|
||||
|
||||
count++;
|
||||
}
|
||||
fclose(fp);
|
||||
ShowStatus("Done reading '" CL_WHITE "%d" CL_RESET "' entries in '" CL_WHITE "%s" CL_RESET "'.\n", count, file);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
//Raised to 105 since Expanded Super Baby needs it.
|
||||
#define MAX_SKILL_TREE 105
|
||||
#define MAX_PC_SKILL_REQUIRE 5 /// Max skill tree requirement
|
||||
///Maximum amount of items a combo may require
|
||||
#define MAX_ITEMS_PER_COMBO 6
|
||||
|
||||
struct s_skill_tree_entry_csv {
|
||||
std::string skill_name;
|
||||
@ -508,5 +510,6 @@ static bool mercenary_read_skilldb(char* str[], int columns, int current);
|
||||
static bool mercenary_readdb(char* str[], int columns, int current);
|
||||
static bool pc_readdb_skilltree(char* str[], int columns, int current);
|
||||
static bool pc_readdb_skilltree_yaml(void);
|
||||
static bool itemdb_read_combos(const char* file);
|
||||
|
||||
#endif /* CSV2YAML_HPP */
|
||||
|
Loading…
x
Reference in New Issue
Block a user