Converted the skill database to YAML (#4531)

* Combines skill_cast_db, skill_castnodex_db, skill_copyable_db, skill_nonearnpc_db, skill_require_db, and skill_unit_db into skill_db.
* Introduces a cached YAML class for quicker lookups.
* General cleanups and optimizations.
* Includes CSV2YAML conversion tool.
Thanks to @Lemongrass3110!
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
This commit is contained in:
Aleos 2020-01-31 14:14:08 -05:00 committed by GitHub
parent de9f667d2f
commit dca3797d44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 74122 additions and 12272 deletions

View File

@ -1,18 +0,0 @@
// Skill Times Database
//
// Structure of Database:
// SkillID,CastingTime,AfterCastActDelay,AfterCastWalkDelay,Duration1,Duration2,Cool Down,Fixed Casting Time
//
// CastingTime: time to cast this skill, in miliseconds
// AfterCastActDelay: "normal" delay, character cannot use skills, in miliseconds
// AfterCastWalkDleay: amount of time before character can move again, in miliseconds
// Duration1/Duration2: usually the durations used by the skill, at special cases it is used to hold special data
// Cool Down: amount of time until character can re-use this skill, in miliseconds
// Fixed Casting Time: the skills fixed casting time (when 0, uses 20% of cast time and less than 0 means no fixed cast time)
//
// On all fields you can use ':' as a delimiter for level-specific values.
// For example:
// - Original: 6,0,0,0,30000,0,1000
// - Modified: 6,0,0,0,30000,0,1000:2500:3000:...
// Gives Level 1 1000ms cool down, Level 2 2500ms, Level 3 3000ms, and so on.

View File

@ -1,16 +0,0 @@
// <Skill id>,<Cast>,<Delay (optional)>
//
// Cast: 0 - everything affects the skill's cast time
// 1 - skill's cast time is not affected by dex
// 2 - skill's cast time is not affected by statuses (Suffragium, etc)
// 4 - skill's cast time is not affected by item bonuses (equip, cards)
//
// Delay: 0 - everything affects the skill's delay
// 1 - skill's delay is not affected by dex
// 2 - skill's delay is not affected by Magic Strings / Bragi
// 4 - skill's delay is not affected by item bonuses (equip, cards)
//
// Note: Values are bit fields, add them up to combine their effects.
// Note: Delay setting '1' only makes sense when delay_dependon_dex is enabled.
// Example: 46,1,1 = Double Strafe's cast time and delay is not affected by dex.

View File

@ -1,52 +0,0 @@
// Copyable Skills Database
// List of skills able to be copied by Intimidate/Plagiarism and Reproduce.
//
// Sources:
// http://irowiki.org/wiki/Intimidate
// -> "Intimidate will copy any 2nd class skill"
// http://irowiki.org/wiki/Reproduce/List_of_reproducible_skills
// -> "Players can reproduce 1-x, 2-x, and 3-x skills and Expanded Class,
// but cannot reproduce transcendent skills"
//
// Structure of Database:
// SkillName,Option{,JobAllowed{,RequirementRemoved}}
//
// Option (bitmask) determines how a skill can be copied.
// 1 = Plagiarism
// 2 = Reproduce
//
// JobAllowed (bitmask) restricts copying the skill to certain classes.
// By default, all jobs can copy the skill (0).
// 1 = Rogue
// 2 = Stalker
// 4 = Shadow Chaser
// 8 = Trans. Shadow Chaser
// 16 = Baby Rouge
// 32 = Baby Shadow Chaser
//
// RequirementRemoved (bitmask) removes requirements when casting a copied skill.
// See 'skill_require_db.txt' for specific skill requirements.
// 0 = uses original requirement(s)
// 1 = hp
// 2 = maxhptrigger
// 4 = sp
// 8 = hprate
// 16 = sprate
// 32 = zeny
// 64 = weapon type
// 128 = ammo (with the amount)
// 256 = state
// 512 = statuses
// 1024 = spirit sphere
// 2048 = items (with the amount)
// 4096 = equipments
//
// Examples:
// AS_SONICBLOW,2,63,64
// Sonic Blow can be copied by all jobs with only Plagiarism.
// To use the copied skill, a Katar is not needed (a Sonic Blow weapon type requirement).
//
// CR_ACIDDEMONSTRATION,3,10
// Acid Demonstration can only be copied by Stalker/Trans. Shadow Chaser with Plagiarism or Reproduce.
// This mode simulates the previous battle config, which allowed only Trans. classes to copy Trans. skills.

View File

@ -1,79 +0,0 @@
//id,range,hit,inf,element,nk,splash,max,list_num,castcancel,cast_defence_rate,inf2,maxcount,skill_type,blow_count,inf3,name,description
// 01 ID
// 02 range (combo skills do not check for range when used,
// if range is < 5, the skill is considered melee-range)
// 03 hit (8- repeated hitting, 6- single-hit)
// 04 inf (0- passive, 1- enemy, 2- place, 4- self, 16- friend, 32- trap)
// 05 element (0 - neutral, 1 - water, 2 - earth, 3 - fire, 4 - wind, 5 - poison,
// 6 - holy, 7 - dark, 8 - ghost, 9 - undead, -1 - use weapon element
// -2 - use endowed element, -3 - use random element.)
// 06 nk (skill damage properties):
// 0x01 - No damage skill
// 0x02 - Has splash area
// 0x04 - Damage should be split among targets
// 0x08 - Skill ignores caster's % damage cards (misc type always ignores)
// 0x10 - Skill ignores elemental adjustments
// 0x20 - Skill ignores target's defense (misc type always ignores)
// 0x40 - Skill ignores target's flee (magic type always ignores)
// 0x80 - Skill ignores target's def cards
// 07 splash/effect range
// -1 - for screen-wide
// 0 - no splash
// all other values follow the formula: value * 2 + 1
// 1 - 3x3
// 2 - 5x5
// 3 - 7x7
// 08 MaxLv
// 09 Number of hits (when positive, damage is increased by hits,
// negative values just show number of hits without increasing total damage)
// 10 Cast interrupted when hit?
// 11 defense-reduction rate during cast.
// 12 inf2 (skill information 2):
// 0x00001 - quest skill
// 0x00002 - npc skill
// 0x00004 - wedding skill
// 0x00008 - spirit skill
// 0x00010 - guild skill
// 0x00020 - song/dance
// 0x00040 - ensemble skill
// 0x00080 - trap
// 0x00100 - skill that damages/targets yourself
// 0x00200 - cannot be casted on self (if inf = 4, auto-select target skill)
// 0x00400 - usable only on party-members (and enemies if skill is offensive)
// 0x00800 - usable only on guild-mates (and enemies if skill is offensive)
// 0x01000 - disable usage on enemies (for non-offensive skills).
// 0x02000 - available skill for SC_AUTOSHADOWSPELL
// 0x04000 - chorus skill
// 0x08000 - skill that ignore bg reduction
// 0x10000 - skill that ignore gvg reduction
// 0x20000 - makes 'self'/'place' skill cannot be casted/placed when near NPC (see 'db/skill_nonearnpc_db.txt' for more options)
// 0x40000 - skill that can hit trap-type skill (inf2 has 0x00080)
// 13 maxcount: max amount of skill instances to place on the ground when
// player_land_skill_limit/monster_land_skill_limit is enabled. For skills
// that attack using a path, this is the path length to be used.
// 14 attack type (none, weapon, magic, misc)
// 15 Blowcount (amount of tiles skill knockbacks)
// 16 inf3 (skill information 3):
// 0x00001 - skill ignores land protector
// 0x00002 - free
// 0x00004 - usable skills while hiding
// 0x00008 - skill that can be use while in dancing state
// 0x00010 - skill that could hit emperium
// 0x00020 - skill ignores SC_STASIS
// 0x00040 - skill blocked by kagehumi
// 0x00080 - skill range affected by AC_VULTURE
// 0x00100 - skill range affected by GS_SNAKEEYE
// 0x00200 - skill range affected by NJ_SHADOWJUMP
// 0x00400 - skill range affected by WL_RADIUS
// 0x00800 - skill range affected by RA_RESEARCHTRAP
// 0x01000 - skill that does not affect user that has NC_HOVERING active
// 0x02000 - skill that can be using while riding warg
// 0x04000 - skill that can be used while on Madogear
// 0x08000 - skill that can be used to target while under SC__MANHOLE effect
// 0x10000 - skill that affects hidden targets
// 0x20000 - skill that affects SC_GLOOMYDAY_SK
// 0x40000 - skill that is affected by SC_DANCEWITHWUG
// 0x80000 - skill blocked by RA_WUGBITE
// 17 Name
// 18 Description

132
db/import-tmpl/skill_db.yml Normal file
View File

@ -0,0 +1,132 @@
# This file is a part of rAthena.
# Copyright(C) 2019 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/>.
#
###########################################################################
# Skill Database
###########################################################################
#
# Skill Settings
#
###########################################################################
# - Id Unique skill ID.
# Name Skill Aegis name.
# Description Skill description.
# MaxLevel Max skill level.
# Type Skill type. (Default: None)
# TargetType Skill target type. (Default: Passive)
# DamageFlags: Skill damage properties.
# Flags: Skill information flags.
# Range: Skill range. (Default: 0)
# - Level Skill level.
# Size Range at specific skill level.
# Hit Skill hit type. (Default: Normal)
# HitCount: Skill hit count. (Default: 0)
# - Level Skill level.
# Count Number of hits at specific skill level.
# Element: Skill element. (Default: Neutral)
# - Level Skill level.
# Element Element at specific skill level.
# SplashArea: Skill splash area of effect. (Default: 0)
# - Level Skill level.
# Area Splash area at specific skill level.
# ActiveInstance: Maximum amount of active skill instances that can be on the ground. (Default: 0)
# - Level Skill level.
# Max Active instances at specific skill level.
# Knockback: Amount of tiles the skill knockbacks. (Default: 0)
# - Level Skill level.
# Amount Knockback count at specific skill level.
# CopyFlags: Determines if the skill is copyable. (Optional)
# Skill: Type of skill that can copy.
# RemoveRequirement: Remove a requirement type. (Optional)
# NoNearNPC: Determines if the skill can be used near a NPC. (Optional)
# AdditionalRange Number of cells from an NPC where the skill can be cast. (Optional)
# Type: Type of NPC.
# CastCancel Cancel cast when hit. (Default: true)
# CastDefenseReduction Defense reduction rate during skill cast. (Default: 0)
# CastTime: Time to cast the skill in milliseconds. (Default: 0)
# - Level Skill level.
# Time Cast time at specific skill level in milliseconds.
# AfterCastActDelay: Time the character cannot use skills in milliseconds. (Default: 0)
# - Level Skill level.
# Time After cast action delay at specific skill level in milliseconds.
# AfterCastWalkDelay: Time before the character can move again in milliseconds. (Default: 0)
# - Level Skill level.
# Time After cast walk delay at specific skill level in milliseconds.
# Duration1: Duration of the skill in milliseconds. (Default: 0)
# - Level Skill level.
# Time Skill duration at specific skill level in milliseconds.
# Duration2: Duration of the skill in milliseconds. (Default: 0)
# - Level Skill level.
# Time Skill duration at specific skill level in milliseconds.
# Cooldown: Time before the character can use the same skill again in milliseconds. (Default: 0)
# - Level Skill level.
# Time Cooldown at specific skill level in milliseconds.
# FixedCastTime: Time that is fixed during cast of the skill in milliseconds. (Default: 0)
# - Level Skill level.
# Time After cast action delay at specific skill level in milliseconds.
# CastTimeFlags: Effects of the skill's cast time. (Optional)
# CastDelayFlags: Effects of the skill's delay. (Optional)
# Requires: List of requirements to cast the skill. (Optional)
# HpCost: HP required to cast. (Default: 0)
# - Level Skill level.
# Amount HP required at specific skill level.
# SpCost: SP required to cast. (Default: 0)
# - Level Skill level.
# Amount SP required at specific skill level.
# HpRateCost: HP rate required to cast. If positive, uses current HP, else uses Max HP. (Default: 0)
# - Level Skill level.
# Amount HP rate required at specific skill level.
# SpRateCost: SP rate required to cast. If positive, uses current SP, else uses Max SP. (Default: 0)
# - Level Skill level.
# Amount SP rate required at specific skill level.
# MaxHpTrigger: Maximum amount of HP to cast the skill. (Default: 0)
# - Level Skill level.
# Amount Maximum HP trigger required at specific skill level.
# ZenyCost: Zeny required to cast. (Default: 0)
# - Level Skill level.
# Amount Zeny required at specific skill level.
# Weapon: Weapon required to cast. (Default: All)
# Ammo: Ammo required to cast. (Default: None)
# AmmoAmount: Ammo amount required to cast. (Default: 0)
# - Level Skill level.
# Amount Ammo amount required at specific skill level.
# State Special state required to cast. (Default: None)
# Status: Status change required to cast. (Default: nullptr)
# SphereCost: Spirit sphere required to cast. (Default: 0)
# - Level Skill level.
# Amount Spirit sphere required at specific skill level.
# ItemCost: Item required to cast. (Default: 0)
# - Item Item name.
# Amount Item amount.
# Equipment: Equipped item required to cast. (Default: nullptr)
# Unit: Skill unit values. (Optional)
# Id Skill unit ID.
# AlternateId: Alternate skill unit ID. (Default: 0)
# Layout: Skill unit layout. (Default: 0)
# - Level Skill level.
# Size Unit layout at specific skill level.
# Range: Skill unit range. (Default: 0)
# - Level Skill level.
# Size Unit range at specific skill level.
# Interval Skill unit interval in milliseconds. (Default: 0)
# Target Skill unit target type. (Default: All)
# Flag: Skill unit flags. (Default: None)
###########################################################################
Header:
Type: SKILL_DB
Version: 1

View File

@ -1,28 +0,0 @@
// Skill Distance-to-NPC Database
// Prevents skills from being used near NPC types using INF2_NO_NEARNPC.
//
// Structure of Database:
// SkillName,AdditionalRange{,NPC Type}
//
// AdditionalRange:
// Number of cells from an NPC where the skill can be cast.
// If zero, this will read the splash range value from skill_db;
// if that is also zero, range+layout's range from skill_unit_db will be used.
//
// NPC Type (bitmask):
// 1 = warp portal, 2 = shop NPC, 4 = normal NPC script, 8 = tomb
//
// Examples:
// MG_SAFETYWALL,2
// Safety Wall can't be placed within 2 ground cells of an NPC.
// (MG_SAFETYWALL doesn't have splash, layout range, and range value,
// so we must add the 'additional_range', or it will be pointless.)
//
// GS_DESPERADO,2
// Desperado can't be casted if the caster is standing within 5 cells of an NPC.
// (Why? GS_DESPERADO has 3 cells of splash range +2 'additional_range' here.)
//
// SC_CHAOSPANIC,0,1
// Chaos Panic can't be placed within 2 ground cells of a warp portal.
// (Because SC_CHAOSPANIC doesn't have splash range, it uses layout range.)

View File

@ -1,33 +0,0 @@
// Skill Requirements Database
//
// Structure of Database:
// SkillID,HPCost,MaxHPTrigger,SPCost,HPRateCost,SPRateCost,ZenyCost,RequiredWeapons,RequiredAmmoTypes,RequiredAmmoAmount,RequiredState,RequiredStatuses,SpiritSphereCost,RequiredItemID1,RequiredItemAmount1,RequiredItemID2,RequiredItemAmount2,RequiredItemID3,RequiredItemAmount3,RequiredItemID4,RequiredItemAmount4,RequiredItemID5,RequiredItemAmount5,RequiredItemID6,RequiredItemAmount6,RequiredItemID7,RequiredItemAmount7,RequiredItemID8,RequiredItemAmount8,RequiredItemID9,RequiredItemAmount9,RequiredItemID10,RequiredItemAmount10,RequiredEquipment
//
// If HP/SPratecost is positive, it is a percent of your current life, otherwise it is a percent of your max life.
//
// Legend for 'RequiredState' field:
// none = Nothing special
// hidden = Requires on hidden status by using Hiding, Cloaking, or maybe Chasewalk
// riding = Requires to ride either a peco or a dragon
// falcon = Requires a Falcon
// cart = Requires a Pushcart (for renewal can replace this state by SC_PUSH_CART in 'RequiredStatuses' field)
// shield = Requires a 0,shield equipped
// recover_weight_rate = Requires to be less than 50% weight
// move_enable = Requires to be able to move
// water = Requires to be standing on a water cell
// dragon = Requires to ride a Dragon
// warg = Requires a Warg
// ridingwarg = Requires to ride a Warg
// mado = Requires to have an active mado
// elementalspirit = Requires to have an Elemental Spirit summoned.
// peco = Requires riding a peco
//
// 'RequiredStatuses'
// Fill the value only with SC_STATUS (see db/const.txt for more details)
// Usage for multiple status requirements: SC_STATUS1:SC_STATUS2:SC_STATUS3
// Max. multiple value is 3 (skill.h: MAX_SKILL_STATUS_REQUIRE)
// Use any number or SC_ALL will disable status requirements
// 'RequiredEquipment'
// Specified equipment to be equipped. For multiple values, use : as delimiter.
// Max. multiple value is 10 (skill.h: MAX_SKILL_EQUIP_REQUIRE)

View File

@ -1,29 +0,0 @@
// Skill Unit Database
//
// Structure of Database:
// ID,unit ID,unit ID 2,layout,range,interval,target,flag
//
// layout = -1:special, 0:1*1, 1:3*3, 2:5*5, up to 5:11*11
// target = friend (party +guildmates +neutral players) / party / guild
// ally (party +guildmates) / all / enemy
// flag 0x0001(UF_DEFNOTENEMY) If 'defunit_not_enemy' is set, the target is changed to 'friend'
// 0x0002(UF_NOREITERRATION) Spell cannot be stacked
// 0x0004(UF_NOFOOTSET) Spell cannot be cast near/on targets
// 0x0008(UF_NOOVERLAP) Spell effects do not overlap
// 0x0010(UF_PATHCHECK) Only cells with a shootable path will be placed
// 0x0020(UF_NOPC) Spell cannot affect players.
// 0x0040(UF_NOMOB) Spell cannot affect mobs.
// 0x0080(UF_SKILL) Spell CAN affect skills.
// 0x0100(UF_DANCE) Dance skill
// 0x0200(UF_ENSEMBLE) Ensemble skill
// 0x0400(UF_SONG) Song skill
// 0x0800(UF_DUALMODE) Spell has effects both at an interval and when you step in/out
// 0x2000(UF_RANGEDSINGLEUNIT) Layout hack, use layout range propriety but only display center.
// Example: 0x006 = 0x002+0x004 -> Cannot be stacked nor cast near targets
//
// Notes:
// 0x89,0x8a,0x8b without indication
//
// u1 u2 lay r intr target flag
//

File diff suppressed because it is too large Load Diff

View File

@ -1,78 +0,0 @@
// <Skill id>,<Cast>,<Delay (optional)>
//
// Cast: 0 - everything affects the skill's cast time
// 1 - skill's cast time is not affected by dex
// 2 - skill's cast time is not affected by statuses (Suffragium, etc)
// 4 - skill's cast time is not affected by item bonuses (equip, cards)
//
// Delay: 0 - everything affects the skill's delay
// 1 - skill's delay is not affected by dex
// 2 - skill's delay is not affected by Magic Strings / Bragi
// 4 - skill's delay is not affected by item bonuses (equip, cards)
//
// Note: Values are bit fields, add them up to combine their effects.
// Note: Delay setting '1' only makes sense when delay_dependon_dex is enabled.
// Example: 46,1,1 = Double Strafe's cast time and delay is not affected by dex.
136,0,2 //AS_SONICBLOW
263,0,2 //MO_TRIPLEATTACK
272,0,2 //MO_CHAINCOMBO
273,0,2 //MO_COMBOFINISH
336,1 //WE_CALLPARTNER
366,7 //HW_MAGICPOWER
370,1 //CH_PALMSTRIKE
371,0,2 //CH_TIGERFIST
372,0,2 //CH_CHAINCRUSH
394,0,2 //CG_ARROWVULCAN
403,3 //PF_MEMORIZE
408,1 //WE_BABY
409,1 //WE_CALLPARENT
410,1 //WE_CALLBABY
482,1 //PF_DOUBLECASTING
462,1 //SL_KAIZEL
496,1 //AM_TWILIGHT1
497,1 //AM_TWILIGHT2
498,1 //AM_TWILIGHT3
512,3 //GS_TRACKING
1014,1 //PR_REDEMPTIO
2012,7 //RK_CRUSHSTRIKE
2013,7 //RK_REFRESH
2014,7 //RK_GIANTGROWTH
2015,7 //RK_STONEHARDSKIN
2022,0,2 //GC_CROSSIMPACT
2032,7 //GC_POISONSMOKE
2234,7 //RA_FEARBREEZE
//2267,7 //NC_SELFDESTRUCTION
2268,7 //NC_SHAPESHIFT
//2270,7 //NC_INFRAREDSCAN
2271,7 //NC_ANALYZE
2281,7 //NC_SILVERSNIPER
2282,7 //NC_MAGICDECOY
2313,7 //LG_FORCEOFVANGUARD
2462,7 //SO_EL_ANALYSIS
2534,7,7 //RETURN_TO_ELDICASTES
2536,7,7 //ALL_GUARDIAN_RECALL
2537,0,7 //ALL_ODINS_POWER
5067,7,7 //ALL_EQSWITCH
// Mercenary Skills
8214,7 //MA_CHARGEARROW
8215,7 //MA_SHARPSHOOTING
8217,7 //ML_BRANDISHSPEAR
8218,7 //ML_SPIRALPIERCE
8221,7 //ML_DEVOTION
8222,7 //MER_MAGNIFICAT
8225,7 //MER_CRASH
8234,7 //MER_DECAGI
8235,7 //MER_SCAPEGOAT
8238,7 //MER_KYRIE
8240,7 //MER_INCAGI
// Guild Skills
10010,3 //GD_BATTLEORDER
10011,3 //GD_REGENERATION
10012,6 //GD_RESTORE
10013,7 //GD_EMERGENCYCALL

File diff suppressed because it is too large Load Diff

33136
db/pre-re/skill_db.yml Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,198 +0,0 @@
// Skill Unit Database
//
// Structure of Database:
// Skill ID,Unit ID,Unit ID 2,Layout,Range,Interval,Target,Flag
//
// layout = -1:special, 0:1*1, 1:3*3, 2:5*5, up to 5:11*11
// target = friend (party +guildmates +neutral players) / party / guild
// ally (party +guildmates) / all / sameguild (guild but no allies) / enemy
// flag 0x00001(UF_DEFNOTENEMY) If 'defunit_not_enemy' is set, the target is changed to 'friend'
// 0x00002(UF_NOREITERATION) Spell cannot be stacked
// 0x00004(UF_NOFOOTSET) Spell cannot be cast near/on targets
// 0x00008(UF_NOOVERLAP) Spell effects do not overlap
// 0x00010(UF_PATHCHECK) Only cells with a shootable path will be placed
// 0x00020(UF_NOPC) Spell cannot affect players.
// 0x00040(UF_NOMOB) Spell cannot affect mobs.
// 0x00080(UF_SKILL) Spell CAN affect skills.
// 0x00100(UF_DANCE) Dance skill
// 0x00200(UF_ENSEMBLE) Ensemble skill
// 0x00400(UF_SONG) Song skill
// 0x00800(UF_DUALMODE) Spell has effects both at an interval and when you step in/out
// 0x01000(UF_NOKNOCKBACK) Cannot be knocked back (only unit that can be damaged)
// 0x02000(UF_RANGEDSINGLEUNIT) Layout hack, use layout range propriety but only display center.
// 0x04000(UF_CRAZYWEED_IMMUNE) Immune to GN_CRAZYWEED removal
// 0x08000(UF_REM_FIRERAIN) Removed if be overlapped by RL_FIRE_RAIN
// 0x10000(UF_KNOCKBACK_GROUP) Knock back a whole skill group (by default, skill unit is knocked back each unit)
// 0x20000(UF_HIDDEN_TRAP) Hidden trap, see 'traps_setting' skill config to enable this flag
// Example: 0x006 = 0x002+0x004 -> Cannot be stacked nor cast near targets
//
// Notes:
// 0x89,0x8a,0x8b without indication
//
// u1 u2 lay r intr target flag
//
12,0x7e, , 0, 0, -1,all, 0x003 //MG_SAFETYWALL
18,0x7f, , -1, 0, 20,enemy, 0x8010 //MG_FIREWALL
21,0x86, , 0, 2:2:2:2:2:2:2:2:2:2:3,1000,enemy, 0x010 //MG_THUNDERSTORM
25,0x85, , 1, 0, -1,all, 0x2003 //AL_PNEUMA
27,0x81,0x80, 0, 0, -1,all, 0x00E //AL_WARP
70,0x83, , -1, 1,1000,all, 0x018 //PR_SANCTUARY
79,0x84, , -1, 1,3000,enemy, 0x8018 //PR_MAGNUS
80,0x87,0x88, 0, 1,2000,enemy, 0x006 //WZ_FIREPILLAR
83,0x86, , 0, 3,1000,enemy, 0x010 //WZ_METEOR
85,0x86, , 5:5:5:5:5:5:5:5:5:5:7, 1,1250,enemy,0x018 //WZ_VERMILION
86,0x86, , 0:1:1:2:2:2:2:2:2:2, 0,-1,noone, 0x010 //WZ_WATERBALL
87,0x8d, , -1, 0,1000,all, 0x9010 //WZ_ICEWALL
89,0x86, , 4, 1, 450,enemy, 0x018 //WZ_STORMGUST
91,0x86, , 2, 0,1000,enemy, 0x010 //WZ_HEAVENDRIVE
92,0x8e, , 2, 0, -1,enemy, 0x8010 //WZ_QUAGMIRE
115,0x90, , 0, 1,1000,enemy, 0x8006 //HT_SKIDTRAP
116,0x93, , 0, 1,1000,enemy, 0x8006 //HT_LANDMINE
117,0x91, , 0, 1,1000,enemy, 0x9006 //HT_ANKLESNARE
118,0x94, , 0, 1,1000,enemy, 0x8006 //HT_SHOCKWAVE
119,0x95, , 0, 1,1000,enemy, 0x8006 //HT_SANDMAN
120,0x96, , 0, 1,1000,enemy, 0x8006 //HT_FLASHER
121,0x97, , 0, 1,1000,enemy, 0x8006 //HT_FREEZINGTRAP
122,0x8f, , 0, 1,1000,enemy, 0x8006 //HT_BLASTMINE
123,0x98, , 0, 1,1000,enemy, 0x8006 //HT_CLAYMORETRAP
125,0x99, , 0, 1,1000,all, 0x8040 //HT_TALKIEBOX
140,0x92, , -1, 1,1000,enemy, 0x8000 //AS_VENOMDUST
220,0xb0, , 0, 0, -1,all, 0x8002 //RG_GRAFFITI
229,0xb1, , 0, 1,1000,enemy, 0x006 //AM_DEMONSTRATION
254,0x86, , -1, 0, 300,enemy, 0x010 //CR_GRANDCROSS
285,0x9a, , 3, 0, -1,all, 0x8010 //SA_VOLCANO
286,0x9b, , 3, 0, -1,all, 0x8010 //SA_DELUGE
287,0x9c, , 3, 0, -1,all, 0x8010 //SA_VIOLENTGALE
288,0x9d, , 3:3:4:4:5,0, -1,all, 0x8010 //SA_LANDPROTECTOR
306,0x9e, , 4, 0,6000,enemy, 0x200 //BD_LULLABY
307,0x9f, , 4, 0, -1,enemy, 0x220 //BD_RICHMANKIM
308,0xa0, , 4, 0, -1,enemy, 0x200 //BD_ETERNALCHAOS
309,0xa1, , 4, 0, -1,party, 0x200 //BD_DRUMBATTLEFIELD
310,0xa2, , 4, 0, -1,party, 0x200 //BD_RINGNIBELUNGEN
311,0xa3, , 4, 0, -1,all, 0x200 //BD_ROKISWEIL
312,0xa4, , 4, 0, -1,party, 0x240 //BD_INTOABYSS
313,0xa5, , 4, 0, -1,party, 0x200 //BD_SIEGFRIED
317,0xa6, , 3, 0,3000,enemy, 0x400 //BA_DISSONANCE
319,0xa7, , 3, 0, -1,all, 0x440 //BA_WHISTLE
320,0xa8, , 3, 0, -1,all, 0x440 //BA_ASSASSINCROSS
321,0xa9, , 3, 0, -1,all, 0x440 //BA_POEMBRAGI
322,0xaa, , 3, 0,6000,all, 0xC40 //BA_APPLEIDUN
325,0xab, , 3, 0,3000,enemy, 0x100 //DC_UGLYDANCE
327,0xac, , 3, 0, -1,all, 0x140 //DC_HUMMING
328,0xad, , 3, 0, -1,enemy, 0x100 //DC_DONTFORGETME
329,0xae, , 3, 0, -1,all, 0x140 //DC_FORTUNEKISS
330,0xaf, , 3, 0, -1,all, 0x140 //DC_SERVICEFORYOU
336,0xb2, , 0,-1, -1,noone, 0x000 //WE_CALLPARTNER
339,0x86, , -1, 0, 300,enemy, 0x000 //NPC_GRANDDARKNESS
362,0xb4, , 2, 0, 300,all, 0x2000 //HP_BASILICA
369,0xb3, , -1, 0,10000,all, 0x008 //PA_GOSPEL
395,0xb5, , 4, 0, -1,all, 0x200 //CG_MOONLIT
404,0xb6, , -1, 0, -1,all, 0x8000 //PF_FOGWALL
405,0xb7, , 0, 0, -1,enemy, 0x8000 //PF_SPIDERWEB
409,0xb2, , 0,-1, -1,noone, 0x000 //WE_CALLBABY
410,0xb2, , 0,-1, -1,noone, 0x000 //WE_CALLPARENT
428,0x86, , 0, 1, 100,enemy, 0x000 //SG_SUN_WARM
429,0x86, , 0, 1, 100,enemy, 0x000 //SG_MOON_WARM
430,0x86, , 0, 1, 100,enemy, 0x000 //SG_STAR_WARM
484,0xb8, , 2, 0,1000,enemy, 0x8818 //HW_GRAVITATION
488,0xb9, , 3, 0, -1,all, 0x200 //CG_HERMODE
516,0x86, , 3, 0, 100,enemy, 0x000 //GS_DESPERADO
521,0xbe, , 0, 1,1000,enemy, 0x000 //GS_GROUNDDRIFT
527,0xbc, , -1, 0,2000,enemy, 0x018 //NJ_TATAMIGAESHI
535,0xbd, , -1, 0, 100,enemy, 0x8010 //NJ_KAENSIN
536,0x86, , 2, 0,1000,enemy, 0x010 //NJ_BAKUENRYU
538,0xbb, , 1:1:1:2:2:2:3:3:3:4,0,-1,all,0x8010 //NJ_SUITON
539,0x86, , 3, 0,1000,enemy, 0x010 //NJ_HYOUSYOURAKU
541,0x86, , 2:2:3:3:4, 0,1000,enemy, 0x010 //NJ_RAIGEKISAI
670,0xc7, , 1, 5:5:5:5:5:5:5:5:5:13,1000,all,0x008 //NPC_EVILLAND
706,0xfd, , 2, 0,1000,enemy, 0x018 //NPC_VENOMFOG
725,0xda, , 0, 0,1000,enemy, 0x1000 //NPC_REVERBERATION
2044,0xca, , 0, 2,1000,all, 0x018 //AB_EPICLESIS
2032,0xe1, , 2, 0,1000,enemy, 0x8018 //GC_POISONSMOKE
2213,0x86, , 0, 9,1000,enemy, 0x018 //WL_COMET
2216,0xcb, , -1, 2,2000,enemy, 0x018 //WL_EARTHSTRAIN
2238,0xd8, , 0, 1,1000,enemy, 0x9006 //RA_ELECTRICSHOCKER
2239,0xd9, , 0, 1,1000,enemy, 0x8006 //RA_CLUSTERBOMB
2249,0xd2, , 0, 1,1000,enemy, 0x8022 //RA_MAGENTATRAP
2250,0xd3, , 0, 1,1000,enemy, 0x8022 //RA_COBALTTRAP
2251,0xd4, , 0, 1,1000,enemy, 0x8022 //RA_MAIZETRAP
2252,0xd5, , 0, 1,1000,enemy, 0x8022 //RA_VERDURETRAP
2253,0xd6, , 0, 1,1000,enemy, 0x8002 //RA_FIRINGTRAP
2254,0xd7, , 0, 1,1000,enemy, 0x8002 //RA_ICEBOUNDTRAP
2273,0xe2, , 2, 0, -1,all, 0x000 //NC_NEUTRALBARRIER
2274,0xe3, , 2, 0, -1,all, 0x000 //NC_STEALTHFIELD
2299,0xcc, , 0, 1,1000,all, 0x8006 //SC_MANHOLE
2300,0xcd, , 0, 0,1000,all, 0x8006 //SC_DIMENSIONDOOR
2301,0xce, , 2, 0,1000,all, 0xA00E //SC_CHAOSPANIC
2302,0xcf, , 2, 0, -1,all, 0xA002 //SC_MAELSTROM
2303,0xd0, , 3, 0, -1,all, 0xA058 //SC_BLOODYLUST
2304,0xd1, , 0, 2, -1,enemy, 0x018 //SC_FEINTBOMB
2319,0xec, , 0, 3,5000,all, 0x000 //LG_BANDING
2414,0xda, , 0, 0,1000,enemy, 0x1000 //WM_REVERBERATION
2418,0xdb, , 0, 5, 300,enemy, 0x800 //WM_SEVERE_RAINSTORM
2419,0xde, , 0, 1,1000,enemy, 0x1014 //WM_POEMOFNETHERWORLD
2443,0xdc, , 0, 0,1000,enemy, 0x00A //SO_FIREWALK
2444,0xdd, , 0, 0,1000,enemy, 0x00A //SO_ELECTRICWALK
2446,0x86, , 0, 3:3:3:4:4,1000,enemy, 0x018 //SO_EARTHGRAVE
2447,0x86, , 0, 3:3:3:4:4,1000,enemy, 0x018 //SO_DIAMONDDUST
2449,0xdf, , 0, 3:3:4:4:5,500,enemy, 0x018 //SO_PSYCHIC_WAVE
2450,0xe0, , 0, 3, 500,enemy, 0x8010 //SO_CLOUD_KILL
2452,0xe4, , 3, 0, -1,all, 0xA010 //SO_WARMER
2453,0xeb, , 0, 1:1:2:2:3,500,enemy,0x8010 //SO_VACUUM_EXTREME
2465,0xf1, , 1, 0, -1,all, 0x2010 //SO_FIRE_INSIGNIA
2466,0xf2, , 1, 0, -1,all, 0x2010 //SO_WATER_INSIGNIA
2467,0xf3, , 1, 0, -1,all, 0x2010 //SO_WIND_INSIGNIA
2468,0xf4, , 1, 0, -1,all, 0x2010 //SO_EARTH_INSIGNIA
2479,0xe5, , 0, 1,1000,enemy, 0x8006 //GN_THORNS_TRAP
2482,0xe6,0x7f, -1, 1, 300,enemy, 0x8000 //GN_WALLOFTHORN
2484,0x86, , 0, 1, 100,enemy, 0x080 //GN_CRAZYWEED_ATK
2485,0xe7, , 0, 2,2000,enemy, 0x8098 //GN_DEMONIC_FIRE
2487,0xe8, , 2, 0, -1,all, 0x2000 //GN_FIRE_EXPANSION_SMOKE_POWDER
2488,0xe9, , 2, 0, -1,all, 0x2000 //GN_FIRE_EXPANSION_TEAR_GAS
2490,0xea, , 0, 1,1000,enemy, 0x8002 //GN_HELLS_PLANT
2555,0x104, , 0, 1:2:2:3:3,500,enemy,0x6 //RL_B_TRAP
2567,0x105, , -1, 0,1000,enemy, 0x98 //RL_FIRE_RAIN
3006,0x86, , 0, 1,1000,enemy, 0x018 //KO_BAKURETSU
3008,0x86, , 0, 1:1:1:1:1:1:1:1:1:2,1000,enemy, 0x018 //KO_MUCHANAGE
3009,0x86, , 0, 3,1000,enemy, 0x018 //KO_HUUMARANKA
3010,0xfc, , 0, 1,5000,enemy, 0x018 //KO_MAKIBISHI
3020,0xf8, , 0, 2, 500,all, 0x018 //KO_ZENKAI
5006,0x101, , 0, 3, 500,enemy, 0x018 //NC_MAGMA_ERUPTION
5010,0x91, , 0, 1,1000,all, 0x002 //SC_ESCAPE
5013,0x102, , 3, 0, -1,all, 0x2002 //LG_KINGS_GRACE
8020,0xf5, , 3, 0,2300:2100:1900:1700:1500,enemy, 0x018 //MH_POISON_MIST
8033,0x7e, , 0, 0, -1,all, 0x003 //MH_STEINWAND
8025,0x86, , 0, 2:2:3:3:4,1000,enemy, 0x018 //MH_XENO_SLASHER
8041,0xf6, , 1:1:2:2:3, 0,2000,enemy, 0x01A //MH_LAVA_SLIDE
8043,0xf7, , 1, 0,-1,all, 0x2018 //MH_VOLCANIC_ASH
8209,0x90, , 0, 1,1000,enemy, 0x006 //MA_SKIDTRAP
8210,0x93, , 0, 0,1000,enemy, 0x006 //MA_LANDMINE
8211,0x95, , 0, 1,1000,enemy, 0x006 //MA_SANDMAN
8212,0x97, , 0, 1,1000,enemy, 0x006 //MA_FREEZINGTRAP
8403,0xed, , -1, 1,1000,enemy, 0x018 //EL_FIRE_MANTLE
8406,0xee, , 1, 0, -1,friend,0x2018 //EL_WATER_BARRIER
8409,0xef, , 1, 0, -1,friend,0x2018 //EL_ZEPHYR
8412,0xf0, , 1, 0, -1,friend,0x2018 //EL_POWER_OF_GAIA
10006,0xc1, , 2, 0, -1,guild, 0x040 //GD_LEADERSHIP
10007,0xc2, , 2, 0, -1,guild, 0x040 //GD_GLORYWOUNDS
10008,0xc3, , 2, 0, -1,guild, 0x040 //GD_SOULCOLD
10009,0xc4, , 2, 0, -1,guild, 0x040 //GD_HAWKEYES

File diff suppressed because it is too large Load Diff

View File

@ -1,83 +0,0 @@
// <Skill id>,<Cast>,<Delay (optional)>
//
// Cast: 0 - everything affects the skill's cast time
// 1 - skill's cast time is not affected by dex
// 2 - skill's cast time is not affected by statuses (Suffragium, etc)
// 4 - skill's cast time is not affected by item bonuses (equip, cards)
//
// Delay: 0 - everything affects the skill's delay
// 1 - skill's delay is not affected by dex
// 2 - skill's delay is not affected by Magic Strings / Bragi
// 4 - skill's delay is not affected by item bonuses (equip, cards)
//
// Note: Values are bit fields, add them up to combine their effects.
// Note: Delay setting '1' only makes sense when delay_dependon_dex is enabled.
// Example: 46,1,1 = Double Strafe's cast time and delay is not affected by dex.
136,0,2 //AS_SONICBLOW
263,0,2 //MO_TRIPLEATTACK
272,0,2 //MO_CHAINCOMBO
273,0,2 //MO_COMBOFINISH
336,1 //WE_CALLPARTNER
366,3 //HW_MAGICPOWER
370,1 //CH_PALMSTRIKE
371,0,2 //CH_TIGERFIST
372,0,2 //CH_CHAINCRUSH
394,0,2 //CG_ARROWVULCAN
403,3 //PF_MEMORIZE
408,1 //WE_BABY
409,1 //WE_CALLPARENT
410,1 //WE_CALLBABY
482,1 //PF_DOUBLECASTING
462,1 //SL_KAIZEL
496,1 //AM_TWILIGHT1
497,1 //AM_TWILIGHT2
498,1 //AM_TWILIGHT3
512,3 //GS_TRACKING
1014,1 //PR_REDEMPTIO
5063,1 //WE_CALLALLFAMILY
5064,1 //WE_ONEFOREVER
5065,1 //WE_CHEERUP
2012,7 //RK_CRUSHSTRIKE
2013,7 //RK_REFRESH
2014,7 //RK_GIANTGROWTH
2015,7 //RK_STONEHARDSKIN
2022,0,2 //GC_CROSSIMPACT
2032,7 //GC_POISONSMOKE
2234,7 //RA_FEARBREEZE
//2267,7 //NC_SELFDESTRUCTION
2268,7 //NC_SHAPESHIFT
//2270,7 //NC_INFRAREDSCAN
2271,7 //NC_ANALYZE
2281,7 //NC_SILVERSNIPER
2282,7 //NC_MAGICDECOY
2313,7 //LG_FORCEOFVANGUARD
2462,7 //SO_EL_ANALYSIS
2534,7,7 //RETURN_TO_ELDICASTES
2536,7,7 //ALL_GUARDIAN_RECALL
2537,0,7 //ALL_ODINS_POWER
3035,7,7 //ECLAGE_RECALL
5067,7,7 //ALL_EQSWITCH
// Mercenary Skills
8214,7 //MA_CHARGEARROW
8215,7 //MA_SHARPSHOOTING
8217,7 //ML_BRANDISHSPEAR
8218,7 //ML_SPIRALPIERCE
8221,7 //ML_DEVOTION
8222,7 //MER_MAGNIFICAT
8225,7 //MER_CRASH
8234,7 //MER_DECAGI
8235,7 //MER_SCAPEGOAT
8238,7 //MER_KYRIE
8240,7 //MER_INCAGI
// Guild Skills
10010,3 //GD_BATTLEORDER
10011,3 //GD_REGENERATION
10012,6 //GD_RESTORE
10013,7 //GD_EMERGENCYCALL

File diff suppressed because it is too large Load Diff

36040
db/re/skill_db.yml Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,206 +0,0 @@
// Skill Unit Database
//
// Structure of Database:
// Skill ID,Unit ID,Unit ID 2,Layout,Range,Interval,Target,Flag
//
// layout = -1:special, 0:1*1, 1:3*3, 2:5*5, up to 5:11*11
// target = friend (party +guildmates +neutral players) / party / guild
// ally (party +guildmates) / all / sameguild (guild but no allies) / enemy
// flag 0x00001(UF_DEFNOTENEMY) If 'defunit_not_enemy' is set, the target is changed to 'friend'
// 0x00002(UF_NOREITERATION) Spell cannot be stacked
// 0x00004(UF_NOFOOTSET) Spell cannot be cast near/on targets
// 0x00008(UF_NOOVERLAP) Spell effects do not overlap
// 0x00010(UF_PATHCHECK) Only cells with a shootable path will be placed
// 0x00020(UF_NOPC) Spell cannot affect players.
// 0x00040(UF_NOMOB) Spell cannot affect mobs.
// 0x00080(UF_SKILL) Spell CAN affect skills.
// 0x00100(UF_DANCE) Dance skill
// 0x00200(UF_ENSEMBLE) Ensemble skill
// 0x00400(UF_SONG) Song skill
// 0x00800(UF_DUALMODE) Spell has effects both at an interval and when you step in/out
// 0x01000(UF_NOKNOCKBACK) Cannot be knocked back (only unit that can be damaged)
// 0x02000(UF_RANGEDSINGLEUNIT) Layout hack, use layout range propriety but only display center.
// 0x04000(UF_CRAZYWEED_IMMUNE) Immune to GN_CRAZYWEED removal
// 0x08000(UF_REM_FIRERAIN) Removed if be overlapped by RL_FIRE_RAIN
// 0x10000(UF_KNOCKBACK_GROUP) Knock back a whole skill group (by default, skill unit is knocked back each unit)
// 0x20000(UF_HIDDEN_TRAP) Hidden trap, see 'traps_setting' skill config to enable this flag
// Example: 0x006 = 0x002+0x004 -> Cannot be stacked nor cast near targets
//
// Notes:
// 0x89,0x8a,0x8b without indication
//
// u1 u2 lay r intr target flag
//
12,0x7e, , 0, 0, -1,all, 0x003 //MG_SAFETYWALL
18,0x7f, , -1, 0, 20,enemy, 0x8010 //MG_FIREWALL
21,0x86, , 0, 2:2:2:2:2:2:2:2:2:2:3,1000,enemy, 0x010 //MG_THUNDERSTORM
25,0x85, , 1, 0, -1,all, 0x2003 //AL_PNEUMA
27,0x81,0x80, 0, 0, -1,all, 0x00E //AL_WARP
70,0x83, , -1, 1,1000,all, 0x018 //PR_SANCTUARY
79,0x84, , -1, 1,3000,enemy, 0x8018 //PR_MAGNUS
80,0x87,0x88, 0, 1,2000,enemy, 0x006 //WZ_FIREPILLAR
83,0x86, , 0, 3,1000,enemy, 0x010 //WZ_METEOR
85,0x86, , 5:5:5:5:5:5:5:5:5:5:7, 1,1250,enemy,0x018 //WZ_VERMILION
86,0x86, , 0:1:1:2:2:2:2:2:2:2, 0,-1,noone, 0x010 //WZ_WATERBALL
87,0x8d, , -1, 0,1000,all, 0x9010 //WZ_ICEWALL
89,0x86, , 4, 1, 450,enemy, 0x018 //WZ_STORMGUST
91,0x86, , 2, 0,1000,enemy, 0x010 //WZ_HEAVENDRIVE
92,0x8e, , 2, 0, -1,enemy, 0x8010 //WZ_QUAGMIRE
115,0x90, , 0, 1,1000,enemy, 0x28006 //HT_SKIDTRAP
116,0x93, , 0, 1,1000,enemy, 0x28006 //HT_LANDMINE
117,0x91, , 0, 1,1000,enemy, 0x29006 //HT_ANKLESNARE
118,0x94, , 0, 1,1000,enemy, 0x28006 //HT_SHOCKWAVE
119,0x95, , 0, 1,1000,enemy, 0x28006 //HT_SANDMAN
120,0x96, , 0, 1,1000,enemy, 0x28006 //HT_FLASHER
121,0x97, , 0, 1,1000,enemy, 0x28006 //HT_FREEZINGTRAP
122,0x8f, , 0, 1,1000,enemy, 0x8006 //HT_BLASTMINE
123,0x98, , 0, 1,1000,enemy, 0x8006 //HT_CLAYMORETRAP
125,0x99, , 0, 1,1000,all, 0x28040 //HT_TALKIEBOX
140,0x92, , -1, 1,1000,enemy, 0x8000 //AS_VENOMDUST
220,0xb0, , 0, 0, -1,all, 0x8002 //RG_GRAFFITI
229,0xb1, , 0, 1, 500,enemy, 0x006 //AM_DEMONSTRATION
254,0x86, , -1, 0, 300,enemy, 0x010 //CR_GRANDCROSS
285,0x9a, , 3, 0, -1,all, 0x8010 //SA_VOLCANO
286,0x9b, , 3, 0, -1,all, 0x8010 //SA_DELUGE
287,0x9c, , 3, 0, -1,all, 0x8010 //SA_VIOLENTGALE
288,0x9d, , 3:3:4:4:5,0, -1,all, 0x8010 //SA_LANDPROTECTOR
306,0x9e, , 4, 0,6000,enemy, 0x200 //BD_LULLABY
307,0x9f, , 4, 0, -1,enemy, 0x220 //BD_RICHMANKIM
308,0xa0, , 4, 0, -1,enemy, 0x8200 //BD_ETERNALCHAOS
309,0xa1, , 4, 0, -1,party, 0x200 //BD_DRUMBATTLEFIELD
310,0xa2, , 4, 0, -1,party, 0x200 //BD_RINGNIBELUNGEN
311,0xa3, , 4, 0, -1,all, 0x8200 //BD_ROKISWEIL
312,0xa4, , 4, 0, -1,party, 0x240 //BD_INTOABYSS
313,0xa5, , 4, 0, -1,party, 0x200 //BD_SIEGFRIED
317,0xa6, , 3, 0,3000,enemy, 0x8400 //BA_DISSONANCE
319,0xa7, , 3, 0, -1,all, 0x440 //BA_WHISTLE
320,0xa8, , 3, 0, -1,all, 0x440 //BA_ASSASSINCROSS
321,0xa9, , 3, 0, -1,all, 0x440 //BA_POEMBRAGI
322,0xaa, , 3, 0,6000,all, 0xC40 //BA_APPLEIDUN
325,0xab, , 3, 0,3000,enemy, 0x100 //DC_UGLYDANCE
327,0xac, , 3, 0, -1,all, 0x140 //DC_HUMMING
328,0xad, , 3, 0, -1,enemy, 0x100 //DC_DONTFORGETME
329,0xae, , 3, 0, -1,all, 0x140 //DC_FORTUNEKISS
330,0xaf, , 3, 0, -1,all, 0x140 //DC_SERVICEFORYOU
336,0xb2, , 0,-1, -1,noone, 0x000 //WE_CALLPARTNER
339,0x86, , -1, 0, 300,enemy, 0x000 //NPC_GRANDDARKNESS
362,0xb4, , 2, 0, 300,all, 0x2000 //HP_BASILICA
369,0xb3, , -1, 0,10000,all, 0x008 //PA_GOSPEL
395,0xb5, , 4, 0, -1,all, 0x200 //CG_MOONLIT
404,0xb6, , -1, 0, -1,all, 0x8000 //PF_FOGWALL
405,0xb7, , 0, 0, -1,enemy, 0x8000 //PF_SPIDERWEB
409,0xb2, , 0,-1, -1,noone, 0x000 //WE_CALLBABY
410,0xb2, , 0,-1, -1,noone, 0x000 //WE_CALLPARENT
428,0x86, , 0, 1, 100,enemy, 0x000 //SG_SUN_WARM
429,0x86, , 0, 1, 100,enemy, 0x000 //SG_MOON_WARM
430,0x86, , 0, 1, 100,enemy, 0x000 //SG_STAR_WARM
484,0xb8, , 2, 0, 500,enemy, 0x8818 //HW_GRAVITATION
488,0xb9, , 3, 0, -1,all, 0x200 //CG_HERMODE
516,0x86, , 3, 0, 100,enemy, 0x000 //GS_DESPERADO
521,0xbe, , 0, 1,1000,enemy, 0x000 //GS_GROUNDDRIFT
527,0xbc, , -1, 0,2000,enemy, 0x018 //NJ_TATAMIGAESHI
535,0xbd, , -1, 0, 100,enemy, 0x8010 //NJ_KAENSIN
536,0x86, , 2, 0,1000,enemy, 0x010 //NJ_BAKUENRYU
538,0xbb, , 1:1:1:2:2:2:3:3:3:4,0,-1,all,0x8010 //NJ_SUITON
539,0x86, , 3, 0,1000,enemy, 0x010 //NJ_HYOUSYOURAKU
541,0x86, , 1:1:2:2:3, 0,1000,enemy, 0x010 //NJ_RAIGEKISAI
670,0xc7, , 1, 5:5:5:5:5:5:5:5:5:13,1000,all,0x008 //NPC_EVILLAND
706,0xfd, , 2, 0,1000,enemy, 0x018 //NPC_VENOMFOG
708,0x86, , 0, 9,1000,enemy, 0x018 //NPC_COMET
709,0xfe, , 0, 3,1000,enemy, 0x8018 //NPC_ICEMINE
711,0xff, , -1, 0,1000,enemy, 0x8018 //NPC_FLAMECROSS
725,0xda, , 0, 0,1000,enemy, 0x1000 //NPC_REVERBERATION
2044,0xca, , 0, 2,1000,all, 0x018 //AB_EPICLESIS
2032,0xe1, , 2, 0,1000,enemy, 0x8018 //GC_POISONSMOKE
2213,0x86, , 0, 9,1000,enemy, 0x018 //WL_COMET
2216,0xcb, , -1, 2,2000,enemy, 0x018 //WL_EARTHSTRAIN
2238,0xd8, , 0, 1,1000,enemy, 0x8006 //RA_ELECTRICSHOCKER
2239,0xd9, , 0, 1,1000,enemy, 0x8006 //RA_CLUSTERBOMB
2249,0xd2, , 0, 1,1000,enemy, 0x8022 //RA_MAGENTATRAP
2250,0xd3, , 0, 1,1000,enemy, 0x8022 //RA_COBALTTRAP
2251,0xd4, , 0, 1,1000,enemy, 0x8022 //RA_MAIZETRAP
2252,0xd5, , 0, 1,1000,enemy, 0x8022 //RA_VERDURETRAP
2253,0xd6, , 0, 1,1000,enemy, 0x8002 //RA_FIRINGTRAP
2254,0xd7, , 0, 1,1000,enemy, 0x8002 //RA_ICEBOUNDTRAP
2273,0xe2, , 2, 0, -1,all, 0x000 //NC_NEUTRALBARRIER
2274,0xe3, , 2, 0, -1,all, 0x000 //NC_STEALTHFIELD
2299,0xcc, , 0, 1,1000,all, 0x8006 //SC_MANHOLE
2300,0xcd, , 0, 0,1000,all, 0x8006 //SC_DIMENSIONDOOR
2301,0xce, , 2, 0,1000,all, 0xA00E //SC_CHAOSPANIC
2302,0xcf, , 2, 0, -1,all, 0xA002 //SC_MAELSTROM
2303,0xd0, , 3, 0, -1,all, 0xA058 //SC_BLOODYLUST
2304,0xd1, , 0, 2, -1,enemy, 0x018 //SC_FEINTBOMB
2319,0xec, , 0, 3,5000,all, 0x000 //LG_BANDING
2414,0xda, , 0, 0,1000,enemy, 0x1000 //WM_REVERBERATION
2418,0xdb, , 0, 5, 300,enemy, 0x800 //WM_SEVERE_RAINSTORM
2419,0xde, , 0, 1,1000,enemy, 0x1014 //WM_POEMOFNETHERWORLD
2443,0xdc, , 0, 0,1000,enemy, 0x00A //SO_FIREWALK
2444,0xdd, , 0, 0,1000,enemy, 0x00A //SO_ELECTRICWALK
2446,0x86, , 0, 3:3:3:4:4,1000,enemy, 0x018 //SO_EARTHGRAVE
2447,0x86, , 0, 3:3:3:4:4,1000,enemy, 0x018 //SO_DIAMONDDUST
2449,0xdf, , 0, 3:3:4:4:5,500,enemy, 0x018 //SO_PSYCHIC_WAVE
2450,0xe0, , 0, 3, 500,enemy, 0x8010 //SO_CLOUD_KILL
2452,0xe4, , 3, 0, -1,all, 0xA010 //SO_WARMER
2453,0xeb, , 0, 1:1:2:2:3,500,enemy,0x8010 //SO_VACUUM_EXTREME
2465,0xf1, , 1, 0, -1,all, 0x2010 //SO_FIRE_INSIGNIA
2466,0xf2, , 1, 0, -1,all, 0x2010 //SO_WATER_INSIGNIA
2467,0xf3, , 1, 0, -1,all, 0x2010 //SO_WIND_INSIGNIA
2468,0xf4, , 1, 0, -1,all, 0x2010 //SO_EARTH_INSIGNIA
2479,0xe5, , 0, 1,1000,enemy, 0x8006 //GN_THORNS_TRAP
2482,0xe6,0x7f, -1, 1, 300,enemy, 0x8000 //GN_WALLOFTHORN
2484,0x86, , 0, 1, 100,enemy, 0x080 //GN_CRAZYWEED_ATK
2485,0xe7, , 0, 2,2000,enemy, 0x8098 //GN_DEMONIC_FIRE
2487,0xe8, , 2, 0, -1,all, 0x2000 //GN_FIRE_EXPANSION_SMOKE_POWDER
2488,0xe9, , 2, 0, -1,all, 0x2000 //GN_FIRE_EXPANSION_TEAR_GAS
2490,0xea, , 0, 1,1000,enemy, 0x8002 //GN_HELLS_PLANT
2555,0x104, , 0, 1:2:2:3:3,500,enemy,0x6 //RL_B_TRAP
2567,0x105, , -1, 0,1000,enemy, 0x98 //RL_FIRE_RAIN
3006,0x86, , 0, 1,1000,enemy, 0x018 //KO_BAKURETSU
3008,0x86, , 0, 1:1:1:1:1:1:1:1:1:2,1000,enemy, 0x018 //KO_MUCHANAGE
3009,0x86, , 0, 3,1000,enemy, 0x018 //KO_HUUMARANKA
3010,0xfc, , 0, 0,5000,enemy, 0x018 //KO_MAKIBISHI
3020,0xf8, , 0, 2, 500,all, 0x018 //KO_ZENKAI
5006,0x101, , 0, 3, 500,enemy, 0x018 //NC_MAGMA_ERUPTION
5010,0x91, , 0, 1,1000,all, 0x002 //SC_ESCAPE
5013,0x102, , 3, 0, -1,all, 0x2002 //LG_KINGS_GRACE
5027,0x106, , 1:1:2:2:3, 0, -1,enemy, 0x2010 // SU_CN_POWDERING
5028,0x86, , 0, 3, 500,enemy, 0x10 // SU_CN_METEOR
5042,0x86, , 0, 3, 500,enemy, 0x10 // SU_CN_METEOR2
5048,0x107, , 2:2:3:3:4, 0, -1, enemy, 0x2010 // SU_NYANGGRASS
8020,0xf5, , 3, 0,2300:2100:1900:1700:1500,enemy, 0x018 //MH_POISON_MIST
8033,0x7e, , 0, 0, -1,all, 0x003 //MH_STEINWAND
8025,0x86, , 0, 2:2:3:3:4,1000,enemy, 0x018 //MH_XENO_SLASHER
8041,0xf6, , 1:1:2:2:3, 0,2000,enemy, 0x01A //MH_LAVA_SLIDE
8043,0xf7, , 1, 0,-1,all, 0x2018 //MH_VOLCANIC_ASH
8209,0x90, , 0, 1,1000,enemy, 0x8006 //MA_SKIDTRAP
8210,0x93, , 0, 0,1000,enemy, 0x8006 //MA_LANDMINE
8211,0x95, , 0, 1,1000,enemy, 0x8006 //MA_SANDMAN
8212,0x97, , 0, 1,1000,enemy, 0x8006 //MA_FREEZINGTRAP
8403,0xed, , -1, 1,1000,enemy, 0x018 //EL_FIRE_MANTLE
8406,0xee, , 1, 0, -1,friend,0x2018 //EL_WATER_BARRIER
8409,0xef, , 1, 0, -1,friend,0x2018 //EL_ZEPHYR
8412,0xf0, , 1, 0, -1,friend,0x2018 //EL_POWER_OF_GAIA
10006,0xc1, , 2, 0, -1,guild, 0x040 //GD_LEADERSHIP
10007,0xc2, , 2, 0, -1,guild, 0x040 //GD_GLORYWOUNDS
10008,0xc3, , 2, 0, -1,guild, 0x040 //GD_SOULCOLD
10009,0xc4, , 2, 0, -1,guild, 0x040 //GD_HAWKEYES

View File

@ -1,282 +0,0 @@
// Copyable Skills Database
// List of skills able to be copied by Intimidate/Plagiarism and Reproduce.
//
// Sources:
// http://irowiki.org/wiki/Intimidate
// -> "Intimidate will copy any 2nd class skill"
// http://irowiki.org/wiki/Reproduce/List_of_reproducible_skills
// -> "Players can reproduce 1-x, 2-x, and 3-x skills and Expanded Class,
// but cannot reproduce transcendent skills"
//
// Structure of Database:
// SkillName,Option{,JobAllowed{,RequirementRemoved}}
//
// Option (bitmask) determines how a skill can be copied.
// 1 = Plagiarism
// 2 = Reproduce
//
// JobAllowed (bitmask) restricts copying the skill to certain classes.
// By default, all jobs can copy the skill (0).
// 1 = Rogue
// 2 = Stalker
// 4 = Shadow Chaser
// 8 = Trans. Shadow Chaser
// 16 = Baby Rouge
// 32 = Baby Shadow Chaser
//
// RequirementRemoved (bitmask) removes requirements when casting a copied skill.
// See 'skill_require_db.txt' for specific skill requirements.
// 0 = uses original requirement(s)
// 1 = hp
// 2 = maxhptrigger
// 4 = sp
// 8 = hprate
// 16 = sprate
// 32 = zeny
// 64 = weapon type
// 128 = ammo (with the amount)
// 256 = state
// 512 = statuses
// 1024 = spirit sphere
// 2048 = items (with the amount)
// 4096 = equipments
//
// Examples:
// AS_SONICBLOW,2,63,64
// Sonic Blow can be copied by all jobs with only Plagiarism.
// To use the copied skill, a Katar is not needed (a Sonic Blow weapon type requirement).
//
// CR_ACIDDEMONSTRATION,3,10
// Acid Demonstration can only be copied by Stalker/Trans. Shadow Chaser with Plagiarism or Reproduce.
// This mode simulates the previous battle config, which allowed only Trans. classes to copy Trans. skills.
// Swordsman
SM_BASH,3 //Bash
SM_MAGNUM,3 //Magnum Break
// Mage
MG_NAPALMBEAT,3 // Napalm Beat
MG_SOULSTRIKE,3 // Soul Strike
MG_COLDBOLT,3 // Cold Bolt
MG_FROSTDIVER,3 // Frost Diver
MG_FIREBALL,3 // Fire Ball
MG_FIREWALL,3 // Fire Wall
MG_FIREBOLT,3 // Fire Bolt
MG_LIGHTNINGBOLT,3 // Lightning Bolt
MG_THUNDERSTORM,3 // Thunderstorm
// Acolyte
AL_RUWACH,3 // Ruwach
AL_HEAL,3 // Heal
// Merchant
MC_MAMMONITE,3 // Mammonite
// Archer
AC_DOUBLE,3 // Double Strafe
AC_SHOWER,3 // Arrow Shower
// Thief
TF_POISON,3 // Envenom
// Resurrection
ALL_RESURRECTION,3 // Resurrection
// Knight
KN_BOWLINGBASH,3 // Bowling Bash
// Priest
PR_ASPERSIO,3 // Asperio
PR_BENEDICTIO,3 // B.S Sacramenti
PR_SANCTUARY,3 // Sanctuary
PR_TURNUNDEAD,3 // Turn Undead
PR_MAGNUS,3 // Magnus Exorcismus
// Wizard
WZ_FIREPILLAR,3 // Fire Pillar
WZ_SIGHTRASHER,3 // Sightrasher
WZ_METEOR,3 // Meteor Storm
WZ_JUPITEL,3 // Jupitel Thunder
WZ_VERMILION,3 // Lord of Vermillion
WZ_WATERBALL,3 // Water Ball
WZ_FROSTNOVA,3 // Frost Nova
WZ_STORMGUST,3 // Storm Gust
WZ_EARTHSPIKE,3 // Earth Spike
WZ_HEAVENDRIVE,3 // Heaven's Drive
// Hunter
HT_LANDMINE,3 // Land Mine
HT_FREEZINGTRAP,3 // Freezing Trap
HT_BLASTMINE,3 // Blast Mine
HT_CLAYMORETRAP,3 // Claymore Trap
// Assassin
AS_SPLASHER,3 // Venom Splasher
// 1st Job Quest Skills
AC_CHARGEARROW,3 // Arrow Repel
TF_THROWSTONE,3 // Stone Fling
AL_HOLYLIGHT,3 // Holy Light
// Rogue
RG_BACKSTAP,3 // Backstab
// Alchemist
AM_DEMONSTRATION,3 // Bomb
AM_ACIDTERROR,3 // Acid Terror
// Crusader
CR_SHIELDCHARGE,3 // Smite
CR_SHIELDBOOMERANG,3 // Shield Boomerang
CR_HOLYCROSS,3 // Holy Cross
CR_GRANDCROSS,3 // Grand Cross
// Monk
MO_TRIPLEATTACK,3 // Raging Trifecta Blow
MO_INVESTIGATE,3 // Occult Impaction
MO_FINGEROFFENSIVE,3 // Throw Spirit Sphere
MO_EXTREMITYFIST,3 // Asura Strike
MO_CHAINCOMBO,3 // Raging Quadruple Blow
// Item Skill
ITM_TOMAHAWK,3 // Throw Tomahawk
// TaeKwon Kid
TK_JUMPKICK,3 // Flying Kick
// Ninja
NJ_ZENYNAGE,3 // Throw Zeny
NJ_TATAMIGAESHI,3 // Improvised Defense
NJ_KASUMIKIRI,3 // Vanishing Slash
NJ_SHADOWJUMP,3 // Shadow Leap
NJ_KIRIKAGE,3 // Shadow Slash
NJ_UTSUSEMI,3 // Cicada Skin Sheeding
NJ_KOUENKA,3 // Crimson Fire Petal
NJ_KAENSIN,3 // Crimson Fire Formation
NJ_BAKUENRYU,3 // Raging Fire Dragon
NJ_HYOUSENSOU,3 // Spear of Ice
NJ_HYOUSYOURAKU,3 // Ice Meteor
NJ_HUUJIN,3 // Wind Blade
NJ_RAIGEKISAI,3 // Lightning Strike of Destruction
NJ_KAMAITACHI,3 // Kamaitachi
// 2nd Job Quest Skills
KN_CHARGEATK,3 // Charge Attack
AS_VENOMKNIFE,3 // Venom Knife
WZ_SIGHTBLASTER,3 // Sight Blaster
HT_PHANTASMIC,3 // Phantasmic Arrow
MO_KITRANSLATION,3 // Excruciating Palm
// Rune Knight
RK_SONICWAVE,2 // Sonic Wave
RK_WINDCUTTER,2 // Wind Cutter
RK_IGNITIONBREAK,2 // Ignition Break
// Guillotine Cross
GC_CROSSIMPACT,2 // Cross Impact
GC_DARKILLUSION,2 // Dark Illusion
GC_PHANTOMMENACE,2 // Phantom Menace
GC_DARKCROW,2 // Dark Claw
// Arch Bishop
AB_JUDEX,2 // Judex
AB_ADORAMUS,2 // Adoramus
AB_RENOVATIO,2 // Renovatio
AB_HIGHNESSHEAL,2 // Highness Heal
AB_DUPLELIGHT,2 // Duple Light
AB_DUPLELIGHT_MELEE,2 // Dummy skill for Duple Light
AB_DUPLELIGHT_MAGIC,2 // Dummy skill for Duple Light
// Warlock
WL_SOULEXPANSION,2 // Soul Expansion
WL_FROSTMISTY,2 // Frosty Misty
WL_JACKFROST,2 // Jack Frost
WL_DRAINLIFE,2 // Drain Life
WL_CRIMSONROCK,2 // Crimson Rock
WL_HELLINFERNO,2 // Hell Inferno
WL_COMET,2 // Comet
WL_CHAINLIGHTNING,2 // Chain Lightning
WL_EARTHSTRAIN,2 // Earth Strain
WL_TETRAVORTEX,2 // Tetra Vortex
WL_SUMMONFB,2 // Summon Fire Ball
WL_SUMMONBL,2 // Summon Lightning Ball
WL_SUMMONWB,2 // Summon Water Ball
WL_SUMMONSTONE,2 // Summon Stone
WL_CHAINLIGHTNING_ATK,2 // Dummy skill for Chain Lightning
WL_TETRAVORTEX_FIRE,2 // Dummy skill for Tetra Vortex
WL_TETRAVORTEX_WATER,2 // Dummy skill for Tetra Vortex
WL_TETRAVORTEX_WIND,2 // Dummy skill for Tetra Vortex
WL_TETRAVORTEX_GROUND,2 // Dummy skill for Tetra Vortex
WL_SUMMON_ATK_FIRE,2 // Dummy skill for Summon Fire Ball
WL_SUMMON_ATK_WIND,2 // Dummy skill for Summon Lightning Ball
WL_SUMMON_ATK_WATER,2 // Dummy skill for Summon Water Ball
WL_SUMMON_ATK_GROUND,2 // Dummy skill for Summon Stone
// Ranger
RA_ARROWSTORM,2 // Arrow Storm
RA_AIMEDBOLT,2 // Aimed Bolt
RA_CLUSTERBOMB,2 // Cluster Bomb
RA_FIRINGTRAP,2 // Firing Trap
RA_ICEBOUNDTRAP,2 // Icebound Trap
// Mechanic
NC_MAGMA_ERUPTION,2 // Magma Eruption
// Shadow Chaser
SC_FATALMENACE,2 // Fatal Menace
SC_TRIANGLESHOT,2 // Triangle Shot
SC_FEINTBOMB,2 // Feint Bomb
// Royal Guard
LG_SHIELDPRESS,2 // Shield Press
LG_SHIELDSPELL,2 // Shield Spell
LG_EXEEDBREAK,2 // Exceed Break
LG_MOONSLASHER,2 // Moon Slasher
LG_EARTHDRIVE,2 // Earth Drive
LG_OVERBRAND_BRANDISH,2 // Dummy skill for Over Brand
LG_OVERBRAND_PLUSATK,2 // Dummy skill for Over Brand
// Sura
SR_DRAGONCOMBO,2 // Dragon Combo
SR_SKYNETBLOW,2 // Sky Net Blow
SR_EARTHSHAKER,2 // Earth Shaker
SR_TIGERCANNON,2 // Tiger Cannon
SR_RAMPAGEBLASTER,2 // Rampage Blaster
SR_KNUCKLEARROW,2 // Knuckle Arrow
SR_WINDMILL,2 // Windmill
SR_GATEOFHELL,2 // Gate of Hell
SR_GENTLETOUCH_QUIET,2 // Gentle Touch - Quiet
SR_HOWLINGOFLION,2 // Howling of Lion
SR_RIDEINLIGHTNING,2 // Riding Lightning
// Minstrel/Wanderer
WM_METALICSOUND,2 // Metallic Sound
WM_REVERBERATION,2 // Reverberation
WM_SEVERE_RAINSTORM,2 // Severe Rainstorm
WM_SEVERE_RAINSTORM_MELEE,2 // Dummy skill for Severe Rainstorm
WM_REVERBERATION_MELEE,2 // Dummy skill for Reverberation
WM_REVERBERATION_MAGIC,2 // Dummy skill for Reverberation
// Sorcerer
SO_FIREWALK,2 // Fire Walk
SO_ELECTRICWALK,2 // Electric Walk
SO_EARTHGRAVE,2 // Earth Grave
SO_DIAMONDDUST,2 // Diamond Dust
SO_POISON_BUSTER,2 // Poison Buster
SO_PSYCHIC_WAVE,2 // Psychic Wave
SO_CLOUD_KILL,2 // Cloud Kill
SO_VARETYR_SPEAR,2 // Varetyr Spear
// Genetic
GN_THORNS_TRAP,2 // Thorn Trap
GN_BLOOD_SUCKER,2 // Blood Sucker
GN_SPORE_EXPLOSION,2 // Spore Explosion
GN_WALLOFTHORN,2 // Wall of Thorns
GN_CRAZYWEED,2 // Crazy Weed
GN_HELLS_PLANT,2 // Hell's Plant
GN_CRAZYWEED_ATK,2 // Dummy skill for Crazy Weed
GN_HELLS_PLANT_ATK,2 // Dummy skil for Hell's Plant
GN_ILLUSIONDOPING,2 // Illusion Doping
// Kagerou/Oboro
KO_MUCHANAGE,3 // Rapid Throw

140
db/skill_db.yml Normal file
View File

@ -0,0 +1,140 @@
# This file is a part of rAthena.
# Copyright(C) 2019 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/>.
#
###########################################################################
# Skill Database
###########################################################################
#
# Skill Settings
#
###########################################################################
# - Id Unique skill ID.
# Name Skill Aegis name.
# Description Skill description.
# MaxLevel Max skill level.
# Type Skill type. (Default: None)
# TargetType Skill target type. (Default: Passive)
# DamageFlags: Skill damage properties.
# Flags: Skill information flags.
# Range: Skill range. (Default: 0)
# - Level Skill level.
# Size Range at specific skill level.
# Hit Skill hit type. (Default: Normal)
# HitCount: Skill hit count. (Default: 0)
# - Level Skill level.
# Count Number of hits at specific skill level.
# Element: Skill element. (Default: Neutral)
# - Level Skill level.
# Element Element at specific skill level.
# SplashArea: Skill splash area of effect. (Default: 0)
# - Level Skill level.
# Area Splash area at specific skill level.
# ActiveInstance: Maximum amount of active skill instances that can be on the ground. (Default: 0)
# - Level Skill level.
# Max Active instances at specific skill level.
# Knockback: Amount of tiles the skill knockbacks. (Default: 0)
# - Level Skill level.
# Amount Knockback count at specific skill level.
# CopyFlags: Determines if the skill is copyable. (Optional)
# Skill: Type of skill that can copy.
# RemoveRequirement: Remove a requirement type. (Optional)
# NoNearNPC: Determines if the skill can be used near a NPC. (Optional)
# AdditionalRange Number of cells from an NPC where the skill can be cast. (Optional)
# Type: Type of NPC.
# CastCancel Cancel cast when hit. (Default: true)
# CastDefenseReduction Defense reduction rate during skill cast. (Default: 0)
# CastTime: Time to cast the skill in milliseconds. (Default: 0)
# - Level Skill level.
# Time Cast time at specific skill level in milliseconds.
# AfterCastActDelay: Time the character cannot use skills in milliseconds. (Default: 0)
# - Level Skill level.
# Time After cast action delay at specific skill level in milliseconds.
# AfterCastWalkDelay: Time before the character can move again in milliseconds. (Default: 0)
# - Level Skill level.
# Time After cast walk delay at specific skill level in milliseconds.
# Duration1: Duration of the skill in milliseconds. (Default: 0)
# - Level Skill level.
# Time Skill duration at specific skill level in milliseconds.
# Duration2: Duration of the skill in milliseconds. (Default: 0)
# - Level Skill level.
# Time Skill duration at specific skill level in milliseconds.
# Cooldown: Time before the character can use the same skill again in milliseconds. (Default: 0)
# - Level Skill level.
# Time Cooldown at specific skill level in milliseconds.
# FixedCastTime: Time that is fixed during cast of the skill in milliseconds. (Default: 0)
# - Level Skill level.
# Time After cast action delay at specific skill level in milliseconds.
# CastTimeFlags: Effects of the skill's cast time. (Optional)
# CastDelayFlags: Effects of the skill's delay. (Optional)
# Requires: List of requirements to cast the skill. (Optional)
# HpCost: HP required to cast. (Default: 0)
# - Level Skill level.
# Amount HP required at specific skill level.
# SpCost: SP required to cast. (Default: 0)
# - Level Skill level.
# Amount SP required at specific skill level.
# HpRateCost: HP rate required to cast. If positive, uses current HP, else uses Max HP. (Default: 0)
# - Level Skill level.
# Amount HP rate required at specific skill level.
# SpRateCost: SP rate required to cast. If positive, uses current SP, else uses Max SP. (Default: 0)
# - Level Skill level.
# Amount SP rate required at specific skill level.
# MaxHpTrigger: Maximum amount of HP to cast the skill. (Default: 0)
# - Level Skill level.
# Amount Maximum HP trigger required at specific skill level.
# ZenyCost: Zeny required to cast. (Default: 0)
# - Level Skill level.
# Amount Zeny required at specific skill level.
# Weapon: Weapon required to cast. (Default: All)
# Ammo: Ammo required to cast. (Default: None)
# AmmoAmount: Ammo amount required to cast. (Default: 0)
# - Level Skill level.
# Amount Ammo amount required at specific skill level.
# State Special state required to cast. (Default: None)
# Status: Status change required to cast. (Default: nullptr)
# SphereCost: Spirit sphere required to cast. (Default: 0)
# - Level Skill level.
# Amount Spirit sphere required at specific skill level.
# ItemCost: Item required to cast. (Default: 0)
# - Item Item name.
# Amount Item amount.
# Equipment: Equipped item required to cast. (Default: nullptr)
# Unit: Skill unit values. (Optional)
# Id Skill unit ID.
# AlternateId: Alternate skill unit ID. (Default: 0)
# Layout: Skill unit layout. (Default: 0)
# - Level Skill level.
# Size Unit layout at specific skill level.
# Range: Skill unit range. (Default: 0)
# - Level Skill level.
# Size Unit range at specific skill level.
# Interval Skill unit interval in milliseconds. (Default: 0)
# Target Skill unit target type. (Default: All)
# Flag: Skill unit flags. (Default: None)
###########################################################################
Header:
Type: SKILL_DB
Version: 1
Footer:
Imports:
- Path: db/pre-re/skill_db.yml
Mode: Prerenewal
- Path: db/re/skill_db.yml
Mode: Renewal
- Path: db/import/skill_db.yml

View File

@ -1,30 +0,0 @@
// Skill Distance-to-NPC Database
// Prevents skills from being used near NPC types using INF2_NO_NEARNPC.
//
// Structure of Database:
// SkillName,AdditionalRange{,NPC Type}
//
// AdditionalRange:
// Number of cells from an NPC where the skill can be cast.
// If zero, this will read the splash range value from skill_db;
// if that is also zero, range+layout's range from skill_unit_db will be used.
//
// NPC Type (bitmask):
// 1 = warp portal, 2 = shop NPC, 4 = normal NPC script, 8 = tomb
//
// Examples:
// MG_SAFETYWALL,2
// Safety Wall can't be placed within 2 ground cells of an NPC.
// (MG_SAFETYWALL doesn't have splash, layout range, and range value,
// so we must add the 'additional_range', or it will be pointless.)
//
// GS_DESPERADO,2
// Desperado can't be casted if the caster is standing within 5 cells of an NPC.
// (Why? GS_DESPERADO has 3 cells of splash range +2 'additional_range' here.)
//
// SC_CHAOSPANIC,0,1
// Chaos Panic can't be placed within 2 ground cells of a warp portal.
// (Because SC_CHAOSPANIC doesn't have splash range, it uses layout range.)
SC_CHAOSPANIC,0,1
SC_MAELSTROM,0,1

836
doc/skill_db.txt Normal file
View File

@ -0,0 +1,836 @@
//===== rAthena Documentation ================================
//= Skill Database Structure
//===== By: ==================================================
//= rAthena Dev Team
//===== Last Updated: ========================================
//= 20191220
//===== Description: =========================================
//= Explanation of the skill_db.yml file and structure.
//============================================================
---------------------------------------
Id: Unique skill ID.
---------------------------------------
Name: Skill Aegis name.
---------------------------------------
Description: Skill description.
---------------------------------------
MaxLevel: Max skill level.
---------------------------------------
Type: Skill type.
None - No specific type. (Default)
Weapon - Weapon type damage.
Magic - Magic type damage.
Misc - Misc type damage.
---------------------------------------
TargetType: Skill target type.
Passive - Passive skill. (Default)
Attack - Damage enemies.
Ground - Ground placement skill.
Self - Self cast skill.
Support - Friendly cast skill.
Trap - Trap cast skill.
---------------------------------------
DamageFlags: Skill damage properties.
NoDamage - No damage skill. (Default)
Splash - Has splash area.
SplashSplit - Damage should be split among targets.
IgnoreAtkCard - Skill ignores caster's % damage cards (Misc type always ignores).
IgnoreElement - Skill ignores elemental adjustments.
IgnoreDefense - Skill ignores target's defense (Misc type always ignores).
IgnoreFlee - Skill ignores target's flee (Magic type always ignores)
IgnoreDefCard - Skill ignores target's defense cards.
Critical - Skill can critical.
---------------------------------------
Flags: Skill information flags.
IsQuest - Quest skill.
IsNpc - NPC skill.
IsWedding - Wedding skill.
IsSpirit - Spirit skill.
IsGuild - Guild skill.
IsSong - Song/Dance skill.
IsEnsemble - Ensemble skill.
IsTrap - Trap skill.
TargetSelf - Damages/targets self.
NoTargetSelf - Cannot target self. If TargetType is Self_Skill, changes to Attack_Skill.
PartyOnly - Usable on party (and enemies if offensive).
GuildOnly - Usable on guild (and enemies if offensive).
NoTargetEnemy - Disable on enemies (for non-offensive).
IsShadowSpell - Make skill available for SC_AUTOSHADOWSPELL.
IsChorus - Chorus skill.
IgnoreBgReduction - Ignore Battleground reduction.
IgnoreGvgReduction - Ignore GvG reduction.
DisableNearNpc - Disable self/ground skills near NPC. In tandem with NoNearNpc node.
TargetTrap - Damage traps. If TargetType is Trap.
IgnoreLandProtector - Ignore SA_LANDPROTECTOR.
AllowWhenHidden - Usable while hiding.
AllowWhenPerforming - Usable while in dancing state.
TargetEmperium - Damages/targets Emperium.
IgnoreStasis - Ignore SC_STASIS.
IgnoreKagehumi - Ignore KG_KAGEHUMI.
AlterRangeVulture - Skill range affected by AC_VULTURE.
AlterRangeSnakeEye - Skill range affected by GS_SNAKEEYE.
AlterRangeShadowJump - Skill range affected by NJ_SHADOWJUMP.
AlterRangeRadius - Skill range affected by WL_RADIUS.
AlterRangeResearchTrap - Skill range affected by RA_RESEARCHTRAP.
IgnoreHovering - Ignore SC_HOVERING.
AllowOnWarg - Usable while riding Warg.
AllowOnMado - Usable while on Madogear.
TargetManHole - Target enemy with SC__MANHOLE.
TargetHidden - Target enemy with OPTION_HIDE.
IncreaseGloomyDayDamage - Increase SC_GLOOMYDAY_SK damage.
IncreaseDanceWithWugDamage - Increase SC_DANCEWITHWUG damage.
IgnoreWugBite - Ignore RA_WUGBITE.
IgnoreAutoGuard - Not blocked by SC_AUTOGUARD (Weapon_Skill only).
IgnoreCicada - Not blocked by SC_UTSUSEMI or SC_BUNSINJYUTSU (Weapon_Skill only).
---------------------------------------
Range: Skill range. Combo skills do not check for range when used. If range is < 5 the skill is considered melee-range.
Can be defined in scalar form or sequence map form:
Scalar Form
Range: 1
Sequence Map Form
Range:
- Level: 1
Size: 1
- Level: 2
Size: 1
- Level: 3
Size: 2
- Level: 4
Size: 2
- Level: 5
Size: 3
---------------------------------------
Hit: Skill hit type.
Normal - Passive/No damage skill. (Default)
Single - Single hit.
Repeat - Multiple hits.
---------------------------------------
HitCount: Skill hit count. When positive the damage is increased by hits. Negative values the number of hits without increasing the total damage.
Can be defined in scalar form or sequence map form:
Scalar Form
HitCount: 1
Sequence Map Form
HitCount:
- Level: 1
Count: 2
- Level: 2
Count: 4
- Level: 3
Count: 6
- Level: 4
Count: 8
- Level: 5
Count: 10
---------------------------------------
Element: Skill element.
Neutral (Default)
Water
Earth
Fire
Wind
Poison
Holy
Dark
Ghost
Undead
Weapon - Uses weapon element.
Endowed - Uses endowed element.
Random - Uses random element.
Can be defined in scalar form or sequence map form:
Scalar Form
Element: Fire
Sequence Map Form
Element:
- Level: 1
Element: Neutral
- Level: 2
Element: Neutral
- Level: 3
Element: Poison
- Level: 4
Element: Poison
- Level: 5
Element: Poison
---------------------------------------
SplashArea: Skill splash area of effect.
-1 - Screen-wide.
0 - No splash.
All other values follow the formula: value * 2 + 1
1 - 3x3
2 - 5x5
3 - 7x7
4 - 9x9
5 - 11x11
6 - 13x13
7 - 15x15
8 - 17x17
9 - 19x19
10 - 21x21
11 - 23x32
12 - 25x25
13 - 27x27
14 - 29x29
15 - 31x31
Can be defined in scalar form or sequence map form:
Scalar Form
SplashArea: 1
Sequence Map Form
SplashArea:
- Level: 1
Area: 1
- Level: 2
Area: 1
- Level: 3
Area: 2
- Level: 4
Area: 2
- Level: 5
Area: 3
---------------------------------------
ActiveInstance: Maximum amount of active skill instances that can be on the ground.
Can be defined in scalar form or sequence map form:
Scalar Form
ActiveInstance: 1
Sequence Map Form
ActiveInstance:
- Level: 1
Max: 1
- Level: 2
Max: 1
- Level: 3
Max: 2
- Level: 4
Max: 2
- Level: 5
Max: 3
---------------------------------------
Knockback: Amount of tiles the skill knockbacks.
Can be defined in scalar form or sequence map form:
Scalar Form
Knockback: 1
Sequence Map Form
Range:
- Level: 1
Amount: 1
- Level: 2
Amount: 1
- Level: 3
Amount: 2
- Level: 4
Amount: 2
- Level: 5
Amount: 3
---------------------------------------
CopyFlags: Determines if the skill is copyable.
Skill - Type of skill that can copy.
Plagiarism
Reproduce
RemoveRequirement - Ability to remove skill cast requirement.
HpCost
SpCost
HpRateCost
SpRateCost
MaxHpTrigger
ZenyCost
Weapon
Ammo
State
Status
SpiritSphereCost
ItemCost
Equipment
---------------------------------------
NoNearNPC: Determines if the skill can be used near a NPC.
AdditionalRange - Number of cells from an NPC where the skill can be cast.
If zero this will read the splash range value.
If that is also zero then Unit Range + Unit Layout Range will be used.
Type - Type of NPC that will block the skill.
WarpPortal
Shop
Npc
Tomb
---------------------------------------
CastCancel: Cancel cast when hit.
---------------------------------------
CastDefenseReduction: Defense reduction rate during skill cast.
---------------------------------------
CastTime: Time to cast the skill in milliseconds.
Can be defined in scalar form or sequence map form:
Scalar Form
CastTime: 1000
Sequence Map Form
CastTime:
- Level: 1
Time: 1000
- Level: 2
Time: 2000
- Level: 3
Time: 3000
- Level: 4
Time: 4000
- Level: 5
Time: 5000
---------------------------------------
AfterCastActDelay: Time the character cannot use skills in milliseconds.
Can be defined in scalar form or sequence map form:
Scalar Form
AfterCastActDelay: 1000
Sequence Map Form
AfterCastActDelay:
- Level: 1
Time: 1000
- Level: 2
Time: 2000
- Level: 3
Time: 3000
- Level: 4
Time: 4000
- Level: 5
Time: 5000
---------------------------------------
AfterCastWalkDelay: Time before the character can move again in milliseconds.
Can be defined in scalar form or sequence map form:
Scalar Form
AfterCastWalkDelay: 1000
Sequence Map Form
AfterCastWalkDelay:
- Level: 1
Time: 1000
- Level: 2
Time: 2000
- Level: 3
Time: 3000
- Level: 4
Time: 4000
- Level: 5
Time: 5000
---------------------------------------
Duration1: Duration of the skill in milliseconds.
Can be defined in scalar form or sequence map form:
Scalar Form
Duration1: 1000
Sequence Map Form
Duration1:
- Level: 1
Time: 1000
- Level: 2
Time: 2000
- Level: 3
Time: 3000
- Level: 4
Time: 4000
- Level: 5
Time: 5000
---------------------------------------
Duration2: Duration of the skill in milliseconds.
Can be defined in scalar form or sequence map form:
Scalar Form
Duration2: 1000
Sequence Map Form
Duration2:
- Level: 1
Time: 1000
- Level: 2
Time: 2000
- Level: 3
Time: 3000
- Level: 4
Time: 4000
- Level: 5
Time: 5000
---------------------------------------
Cooldown: Time before the character can use the same skill again in milliseconds.
Can be defined in scalar form or sequence map form:
Scalar Form
Cooldown: 1000
Sequence Map Form
Cooldown:
- Level: 1
Time: 1000
- Level: 2
Time: 2000
- Level: 3
Time: 3000
- Level: 4
Time: 4000
- Level: 5
Time: 5000
---------------------------------------
FixedCastTime: Time that is fixed during cast of the skill in milliseconds.
Can be defined in scalar form or sequence map form:
Scalar Form
FixedCastTime: 1000
Sequence Map Form
FixedCastTime:
- Level: 1
Time: 1000
- Level: 2
Time: 2000
- Level: 3
Time: 3000
- Level: 4
Time: 4000
- Level: 5
Time: 5000
---------------------------------------
CastTimeFlags: Effects of the skill's cast time.
IgnoreDex - Cast time not affected by DEX.
IgnoreStatus - Cast time not affected by statuses (Suffragium, etc).
IgnoreItemBonus - Cast time not affected by item bonuses.
---------------------------------------
CastDelayFlags: Effects of the skill's delay.
IgnoreDex - Delay not affected by DEX.
IgnoreStatus - Delay not affected by statuses (Suffragium, etc).
IgnoreItemBonus - Delay not affected by item bonuses.
IgnoreDex only makes sense when battle_config::delay_dependon_dex is enabled.
---------------------------------------
Requires: List of requirements to cast the skill.
HpCost: HP required to cast.
Can be defined in scalar form or sequence map form:
Scalar Form
HpCost: 10
Sequence Map Form
HpCost:
- Level: 1
Amount: 10
- Level: 2
Amount: 20
- Level: 3
Amount: 30
- Level: 4
Amount: 40
- Level: 5
Amount: 50
------------------
SpCost: SP required to cast.
Can be defined in scalar form or sequence map form:
Scalar Form
SpCost: 10
Sequence Map Form
SpCost:
- Level: 1
Amount: 10
- Level: 2
Amount: 20
- Level: 3
Amount: 30
- Level: 4
Amount: 40
- Level: 5
Amount: 50
------------------
HpRateCost: HP rate required to cast. If positive, uses current HP, else uses Max HP.
Can be defined in scalar form or sequence map form:
Scalar Form
HpRateCost: 10
Sequence Map Form
HpRateCost:
- Level: 1
Amount: 10
- Level: 2
Amount: 20
- Level: 3
Amount: 30
- Level: 4
Amount: 40
- Level: 5
Amount: 50
------------------
SpRateCost: SP rate required to cast. If positive, uses current SP, else uses Max SP.
Can be defined in scalar form or sequence map form:
Scalar Form
SpRateCost: 10
Sequence Map Form
SpRateCost:
- Level: 1
Amount: 10
- Level: 2
Amount: 20
- Level: 3
Amount: 30
- Level: 4
Amount: 40
- Level: 5
Amount: 50
------------------
MaxHpTrigger: Maximum amount of HP to cast the skill.
Can be defined in scalar form or sequence map form:
Scalar Form
MaxHpTrigger: 10
Sequence Map Form
MaxHpTrigger:
- Level: 1
Amount: 10
- Level: 2
Amount: 20
- Level: 3
Amount: 30
- Level: 4
Amount: 40
- Level: 5
Amount: 50
------------------
ZenyCost: Zeny required to cast.
Can be defined in scalar form or sequence map form:
Scalar Form
ZenyCost: 10
Sequence Map Form
ZenyCost:
- Level: 1
Amount: 10
- Level: 2
Amount: 20
- Level: 3
Amount: 30
- Level: 4
Amount: 40
- Level: 5
Amount: 50
------------------
Weapon: Weapon required to cast.
All (Default)
Fist
Dagger
1hSword
2hSword
1hSpear
2hSpear
1hAxe
2hAxe
Mace
2hMace
Staff
Bow
Knuckle
Musical
Whip
Book
Katar
Revolver
Rifle
Gatling
Shotgun
Grenade
Huuma
2hStaff
------------------
Ammo: Ammo required to cast.
None (Default)
Arrow
Dagger
Bullet
Shell
Grenade
Shuriken
Kunai
Cannonball
Throwweapon
------------------
AmmoAmount: Ammo amount required to cast.
Can be defined in scalar form or sequence map form:
Scalar Form
AmmoAmount: 10
Sequence Map Form
AmmoAmount:
- Level: 1
Amount: 1
- Level: 2
Amount: 2
- Level: 3
Amount: 3
- Level: 4
Amount: 4
- Level: 5
Amount: 5
------------------
State: Special state required to cast.
None - No special state required.
Hidden - Requires OPTION_HIDE, OPTION_CLOAK, or OPTION_CHASEWALK.
Riding - Requires OPTION_RIDING or OPTION_DRAGON.
Falcon - Requires OPTION_FALCON.
Cart - Requires OPTION_CART for pre-renewal or SC_PUSH_CART for renewal.
Shield - Requires a shield to be equipped.
Recover_Weight_Rate - Requires weight to be less than 50% for pre-renewal or 70% for renewal.
Move_Enable - Requires to be able to move.
Water - Requires to be standing in water.
RidingDragon - Requires OPTION_DRAGON.
Wug - Requires OPTION_WUG.
RidingWug - Requires OPTION_WUGRIDER.
Mado - Requires OPTION_MADOGEAR.
ElementalSpirit - Requires an Elemental Spirit to be summoned.
ElementalSpirit2 - Requires an Elemental Spirit to be summoned and will be removed after.
Peco - Requires OPTION_RIDING.
------------------
Status: Status change required to cast.
For a full list, see src/map/status.hpp::sc_type.
------------------
SphereCost: Spirit sphere required to cast.
Can be defined in scalar form or sequence map form:
Scalar Form
SphereCost: 10
Sequence Map Form
SphereCost:
- Level: 1
Amount: 1
- Level: 2
Amount: 2
- Level: 3
Amount: 3
- Level: 4
Amount: 4
- Level: 5
Amount: 5
------------------
ItemCost: Item required to cast.
------------------
Equipment: Equipped item required to cast.
---------------------------------------
Unit: Skill unit values.
Id: Skill unit ID.
For a full list, see src/map/skill.hpp::e_skill_unit_id.
------------------
AlternateId: Alternate skill unit ID.
For a full list, see src/map/skill.hpp::e_skill_unit_id.
------------------
Layout: Skill unit layout.
-1 - Screen-wide.
0 - No splash.
All other values follow the formula: value * 2 + 1
1 - 3x3
2 - 5x5
3 - 7x7
4 - 9x9
5 - 11x11
Can be defined in scalar form or sequence map form:
Scalar Form
Layout: 10
Sequence Map Form
Layout:
- Level: 1
Size: 1
- Level: 2
Size: 2
- Level: 3
Size: 3
- Level: 4
Size: 4
- Level: 5
Size: 5
------------------
Range: Skill unit range.
Can be defined in scalar form or sequence map form:
Scalar Form
Range: 10
Sequence Map Form
Range:
- Level: 1
Size: 1
- Level: 2
Size: 2
- Level: 3
Size: 3
- Level: 4
Size: 4
- Level: 5
Size: 5
------------------
Interval: Skill unit interval in milliseconds.
------------------
Target: Skill unit target type.
Friend - Targets Party, Guild, Guild Allies, and neutral players.
Party - Targets Party.
Ally - Targets Party and Guild and Guild Allies.
Guild - Targets Guild and Guild Allies.
All - Targets all. (Default)
Enemy - Targets enemy.
Self - Targets self.
SameGuild - Targets Guild but not Guild Allies.
------------------
Flag: Skill unit flags.
None - No flags.
NoEnemy - If battle_config::defunit_not_enemy is enabled, the Target is changed to Friend.
NoReiteration - Spell cannot be stacked.
NoFootSet - Spell cannot be cast near/on targets.
NoOverlap - Spell effects do not overlap.
PathCheck - Only cells with a shootable path will be placed.
NoPc - Spell cannot affect players.
NoMob - Spell cannot affect mobs.
Skill - Spell can affect skills.
Dance - Dance unit.
Ensemble - Duet unit.
Song - Song unit.
DualMode - Spell has effects both at an interval and when you step in/out.
NoKnockback - Cannot be knocked back (only unit that can be damaged).
RangedSingleUnit - Layout hack, use layout range property but only display center.
CrazyWeedImmune - Immune to GN_CRAZYWEED.
RemovedByFireRain - Removed by RL_FIRE_RAIN.
KnockbackGroup - Knock back a whole skill group (by default, skill unit is knocked back by each unit).
HiddenTrap - Hidden trap. See battle_config::traps_setting to enable this flag.

View File

@ -1,163 +0,0 @@
//===== rAthena Documentation ================================
//= rAthena Skill Requirement Reference
//===== By: ==================================================
//= rAthena Dev Team
//===== Last Updated: ========================================
//= 20140831
//===== Description: =========================================
//= Explanation of the skill_require_db.txt file and structure.
//============================================================
Structure:
SkillID,HPCost,MaxHPTrigger,SPCost,HPRateCost,SPRateCost,ZenyCost,RequiredWeapons,RequiredAmmoTypes,RequiredAmmoAmount,RequiredState,RequiredStatuses,SpiritSphereCost,RequiredItemID1,RequiredItemAmount1,RequiredItemID2,RequiredItemAmount2,RequiredItemID3,RequiredItemAmount3,RequiredItemID4,RequiredItemAmount4,RequiredItemID5,RequiredItemAmount5,RequiredItemID6,RequiredItemAmount6,RequiredItemID7,RequiredItemAmount7,RequiredItemID8,RequiredItemAmount8,RequiredItemID9,RequiredItemAmount9,RequiredItemID10,RequiredItemAmount10,RequiredEquipment
---------------------------------------
SkillID: The ID of the skill.
See 'db\(pre-)re\skill_db.txt' for more details.
---------------------------------------
HPCost: Amount of HP needed to use the skill.
---------------------------------------
MaxHPTrigger: Player's HP must be below this % of Max HP in order to use the skill.
---------------------------------------
SPCost: Amount of SP needed to use the skill.
---------------------------------------
HPRateCost: If more than 0, the percentage of the player's current HP.
If less than 0, the percentage of the player's Max HP.
---------------------------------------
SPRateCost: If more than 0, the percentage of the player's current SP.
If less than 0, the percentage of the player's Max SP.
---------------------------------------
ZenyCost: Amount of Zeny needed to use the skill.
---------------------------------------
RequiredWeapons: Weapon type needed to use the skill.
0: bare fist
1: Daggers
2: One-handed swords
3: Two-handed swords
4: One-handed spears
5: Two-handed spears
6: One-handed axes
7: Two-handed axes
8: Maces
9: Unused
10: Staves
11: Bows
12: Knuckles
13: Musical Instruments
14: Whips
15: Books
16: Katars
17: Revolvers
18: Rifles
19: Gatling guns
20: Shotguns
21: Grenade launchers
22: Fuuma Shurikens
23: Two-handed staves
24: Max Type
25: Dual-wield Daggers
26: Dual-wield Swords
27: Dual-wield Axes
28: Dagger + Sword
29: Dagger + Axe
30: Sword + Axe
Up to 30 ':'-separated values can be used, e.g.
type1:type2:type3
---------------------------------------
RequiredAmmoTypes: Ammo type needed to use the skill.
1: Arrows
2: Throwable daggers
3: Bullets
4: Shells
5: Grenades
6: Shuriken
7: Kunai
8: Cannonballs
9: Throwable Items (Sling Item)
Up to 9 ':'-separated values can be used, e.g.
type1:type2:type3
---------------------------------------
RequiredAmmoAmount: Amount of ammo needed to use the skill.
---------------------------------------
RequiredState: The active 'State' needed to use the skill.
none = Nothing.
hidden = Requires hidden status by using Hiding, Cloaking, or Chasewalk.
riding = Requires the player to ride either a Peco or a Dragon.
falcon = Requires a Falcon.
cart = Requires a Pushcart.
For renewal, this state can be replaced by SC_PUSH_CART in 'RequiredStatuses' field.
shield = Requires an equipped shield.
recover_weight_rate = Requires to be less than 50% weight.
move_enable = Requires to be able to move.
water = Requires to be standing on a water cell.
dragon = Requires to ride a Dragon.
warg = Requires a Warg.
ridingwarg = Requires to ride a Warg.
mado = Requires to have an active Mado.
elementalspirit = Requires to have an Elemental Spirit summoned.
peco = Requires riding a Peco.
---------------------------------------
RequiredStatuses: The active statuses needed to use the skill.
Up to 3 ':'-separated values can be used, e.g.
SC_STATUS1:SC_STATUS2:SC_STATUS3
See MAX_SKILL_STATUS_REQUIRE in 'src/map/skill.hpp' to modify the max number
of possible values, and 'src/map/script_constants.hpp' for a list of status constants.
Use any number or SC_ALL to disable status requirements.
---------------------------------------
SpiritSphereCost: Amount of Spirit Sphere needed to use the skill.
---------------------------------------
RequiredItemID1..10: Items to be consumed when the skill is used (max 10).
---------------------------------------
RequiredItemAmount1..10: Amount of each item consumed when the skill is used.
If 0, the item is required to be in the inventory but won't be consumed.
---------------------------------------
RequiredEquipment: Specific equipment IDs needed to use the skill.
Up to 10 ':'-separated values can be used, e.g.
item1:item2:item3
See MAX_SKILL_EQUIP_REQUIRE in 'src/map/skill.hpp' to modify the max number
of possible values.
---------------------------------------
NOTE: On some fields, the ':' delimiter means for each skill level, but there
are some level dependent checks. See 'skill_get_requirement()' in
'src/map/skill.cpp'.

111
doc/yaml/db/skill_db.yml Normal file
View File

@ -0,0 +1,111 @@
###########################################################################
# Skill Database
###########################################################################
#
# Skill Settings
#
###########################################################################
# - Id Unique skill ID.
# Name Skill Aegis name.
# Description Skill description.
# MaxLevel Max skill level.
# Type Skill type. (Default: None)
# TargetType Skill target type. (Default: Passive_Skill)
# DamageFlags: Skill damage properties.
# Flags: Skill information flags.
# Range: Skill range. (Default: 0)
# - Level Skill level.
# Size Range at specific skill level.
# Hit Skill hit type. (Default: Normal)
# HitCount: Skill hit count. (Default: 0)
# - Level Skill level.
# Count Number of hits at specific skill level.
# Element: Skill element. (Default: Neutral)
# - Level Skill level.
# Element Element at specific skill level.
# SplashArea: Skill splash area of effect. (Default: 0)
# - Level Skill level.
# Area Splash area at specific skill level.
# ActiveInstance: Maximum amount of active skill instances that can be on the ground. (Default: 0)
# - Level Skill level.
# Max Active instances at specific skill level.
# Knockback: Amount of tiles the skill knockbacks. (Default: 0)
# - Level Skill level.
# Amount Knockback count at specific skill level.
# CopyFlags: Determines if the skill is copyable. (Optional)
# Skill: Type of skill that can copy.
# RemoveRequirement: Remove a requirement type. (Optional)
# NoNearNPC: Determines if the skill can be used near a NPC. (Optional)
# AdditionalRange Number of cells from an NPC where the skill can be cast. (Optional)
# Type: Type of NPC.
# CastCancel Cancel cast when hit. (Default: true)
# CastDefenseReduction Defense reduction rate during skill cast. (Default: 0)
# CastTime: Time to cast the skill in milliseconds. (Default: 0)
# - Level Skill level.
# Time Cast time at specific skill level in milliseconds.
# AfterCastActDelay: Time the character cannot use skills in milliseconds. (Default: 0)
# - Level Skill level.
# Time After cast action delay at specific skill level in milliseconds.
# AfterCastWalkDelay: Time before the character can move again in milliseconds. (Default: 0)
# - Level Skill level.
# Time After cast walk delay at specific skill level in milliseconds.
# Duration1: Duration of the skill in milliseconds. (Default: 0)
# - Level Skill level.
# Time Skill duration at specific skill level in milliseconds.
# Duration2: Duration of the skill in milliseconds. (Default: 0)
# - Level Skill level.
# Time Skill duration at specific skill level in milliseconds.
# Cooldown: Time before the character can use the same skill again in milliseconds. (Default: 0)
# - Level Skill level.
# Time Cooldown at specific skill level in milliseconds.
# FixedCastTime: Time that is fixed during cast of the skill in milliseconds. (Default: 0)
# - Level Skill level.
# Time After cast action delay at specific skill level in milliseconds.
# CastTimeFlags: Effects of the skill's cast time. (Optional)
# CastDelayFlags: Effects of the skill's delay. (Optional)
# Requires: List of requirements to cast the skill. (Optional)
# HpCost: HP required to cast. (Default: 0)
# - Level Skill level.
# Amount HP required at specific skill level.
# SpCost: SP required to cast. (Default: 0)
# - Level Skill level.
# Amount SP required at specific skill level.
# HpRateCost: HP rate required to cast. If positive, uses current HP, else uses Max HP. (Default: 0)
# - Level Skill level.
# Amount HP rate required at specific skill level.
# SpRateCost: SP rate required to cast. If positive, uses current SP, else uses Max SP. (Default: 0)
# - Level Skill level.
# Amount SP rate required at specific skill level.
# MaxHpTrigger: Maximum amount of HP to cast the skill. (Default: 0)
# - Level Skill level.
# Amount Maximum HP trigger required at specific skill level.
# ZenyCost: Zeny required to cast. (Default: 0)
# - Level Skill level.
# Amount Zeny required at specific skill level.
# Weapon: Weapon required to cast. (Default: All)
# Ammo: Ammo required to cast. (Default: None)
# AmmoAmount: Ammo amount required to cast. (Default: 0)
# - Level Skill level.
# Amount Ammo amount required at specific skill level.
# State Special state required to cast. (Default: None)
# Status: Status change required to cast. (Default: nullptr)
# SphereCost: Spirit sphere required to cast. (Default: 0)
# - Level Skill level.
# Amount Spirit sphere required at specific skill level.
# ItemCost: Item required to cast. (Default: 0)
# - Item Item name.
# Amount Item amount.
# Equipment: Equipped item required to cast. (Default: nullptr)
# Unit: Skill unit values. (Optional)
# Id Skill unit ID.
# AlternateId: Alternate skill unit ID. (Default: 0)
# Layout: Skill unit layout. (Default: 0)
# - Level Skill level.
# Size Unit layout at specific skill level.
# Range: Skill unit range. (Default: 0)
# - Level Skill level.
# Size Unit range at specific skill level.
# Interval Skill unit interval in milliseconds. (Default: 0)
# Target Skill unit target type. (Default: All)
# Flag: Skill unit flags. (Default: None)
###########################################################################

View File

@ -125,9 +125,15 @@ bool YamlDatabase::load(const std::string& path) {
this->parseImports( rootNode );
this->loadingFinished();
return true;
}
void YamlDatabase::loadingFinished(){
// Does nothing by default, just for hooking
}
void YamlDatabase::parse( const YAML::Node& rootNode ){
uint64 count = 0;

View File

@ -5,6 +5,7 @@
#define DATABASE_HPP
#include <unordered_map>
#include <vector>
#include <yaml-cpp/yaml.h>
@ -50,6 +51,8 @@ protected:
bool asUInt16Rate(const YAML::Node& node, const std::string& name, uint16& out, uint16 maximum=10000);
bool asUInt32Rate(const YAML::Node& node, const std::string& name, uint32& out, uint32 maximum=10000);
virtual void loadingFinished();
public:
YamlDatabase( const std::string type_, uint16 version_, uint16 minimumVersion_ ){
this->type = type_;
@ -93,7 +96,7 @@ public:
return this->find( key ) != nullptr;
}
std::shared_ptr<datatype> find( keytype key ){
virtual std::shared_ptr<datatype> find( keytype key ){
auto it = this->data.find( key );
if( it != this->data.end() ){
@ -128,4 +131,59 @@ public:
}
};
template <typename keytype, typename datatype> class TypesafeCachedYamlDatabase : public TypesafeYamlDatabase<keytype, datatype>{
private:
std::vector<std::shared_ptr<datatype>> cache;
public:
TypesafeCachedYamlDatabase( const std::string type_, uint16 version_, uint16 minimumVersion_ ) : TypesafeYamlDatabase<keytype, datatype>( type_, version_, minimumVersion_ ){
}
TypesafeCachedYamlDatabase( const std::string& type_, uint16 version_ ) : TypesafeYamlDatabase<keytype, datatype>( type_, version_, version_ ){
}
void clear() override{
TypesafeYamlDatabase<keytype, datatype>::clear();
cache.clear();
}
std::shared_ptr<datatype> find( keytype key ) override{
if( this->cache.empty() || key >= this->cache.capacity() ){
return TypesafeYamlDatabase<keytype, datatype>::find( key );
}else{
return cache[this->calculateCacheKey( key )];
}
}
virtual size_t calculateCacheKey( keytype key ){
return key;
}
void loadingFinished() override{
// Cache all known values
for (auto &pair : *this) {
// Calculate the key that should be used
size_t key = this->calculateCacheKey(pair.first);
// Check if the key fits into the current cache size
if (this->cache.capacity() < key) {
// Double the current size, so we do not have to resize that often
size_t new_size = key * 2;
// Very important => initialize everything to nullptr
this->cache.resize(new_size, nullptr);
}
// Insert the value into the cache
this->cache[key] = pair.second;
}
// Free the memory that was allocated too much
this->cache.shrink_to_fit();
}
};
#endif /* DATABASE_HPP */

View File

@ -4,10 +4,12 @@
#ifndef UTILILITIES_HPP
#define UTILILITIES_HPP
#include <algorithm>
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include "cbasetypes.hpp"
#include "random.hpp"
@ -135,6 +137,31 @@ namespace rathena {
return it->second;
}
/**
* Get an iterator element
* @param vec: Vector to search through
* @param value: Value wanted
* @return Key value iterator on success or vector end iterator on failure
*/
template <typename K, typename V> typename std::vector<K>::iterator vector_get(std::vector<K> &vec, V key) {
return std::find(vec.begin(), vec.end(), key);
}
/**
* Determine if a value exists in the vector
* @param vec: Vector to search through
* @param value: Value wanted
* @return True on success or false on failure
*/
template <typename K, typename V> bool vector_exists(std::vector<K> &vec, V value) {
auto it = std::find(vec.begin(), vec.end(), value);
if (it != vec.end())
return true;
else
return false;
}
bool safe_addition( int64 a, int64 b, int64& result );
bool safe_substraction( int64 a, int64 b, int64& result );
bool safe_multiplication( int64 a, int64 b, int64& result );

View File

@ -3401,7 +3401,7 @@ ACMD_FUNC(questskill)
clif_displaymessage(fd, msg_txt(sd,198)); // This skill number doesn't exist.
return -1;
}
if (!(skill_get_inf2(skill_id) & INF2_QUEST_SKILL)) {
if (!skill_get_inf2(skill_id, INF2_ISQUEST)) {
clif_displaymessage(fd, msg_txt(sd,197)); // This skill number doesn't exist or isn't a quest skill.
return -1;
}
@ -3445,7 +3445,7 @@ ACMD_FUNC(lostskill)
clif_displaymessage(fd, msg_txt(sd,198)); // This skill number doesn't exist.
return -1;
}
if (!(skill_get_inf2(skill_id) & INF2_QUEST_SKILL)) {
if (!skill_get_inf2(skill_id, INF2_ISQUEST)) {
clif_displaymessage(fd, msg_txt(sd,197)); // This skill number doesn't exist or isn't a quest skill.
return -1;
}
@ -5754,9 +5754,6 @@ ACMD_FUNC(clearcart)
#define MAX_SKILLID_PARTIAL_RESULTS_LEN 74 // "skill " (6) + "%d:" (up to 5) + "%s" (up to 30) + " (%s)" (up to 33)
ACMD_FUNC(skillid) {
int skillen, i, found = 0;
DBIterator* iter;
DBKey key;
DBData *data;
char partials[MAX_SKILLID_PARTIAL_RESULTS][MAX_SKILLID_PARTIAL_RESULTS_LEN];
nullpo_retr(-1, sd);
@ -5768,20 +5765,20 @@ ACMD_FUNC(skillid) {
skillen = strlen(message);
iter = db_iterator(skilldb_name2id);
for(const auto & skill : skill_db) {
uint16 skill_id = skill.second->nameid;
uint16 idx = skill_get_index(skill_id);
const char *name = skill.second->name;
const char *desc = skill.second->desc;
for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) {
int idx = skill_get_index(db_data2i(data));
if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill_db[idx]->desc, message, skillen) == 0) {
sprintf(atcmd_output, msg_txt(sd,1164), db_data2i(data), skill_db[idx]->desc, key.str); // skill %d: %s (%s)
if (strnicmp(name, message, skillen) == 0 || strnicmp(desc, message, skillen) == 0) {
sprintf(atcmd_output, msg_txt(sd,1164), skill_id, desc, name); // skill %d: %s (%s)
clif_displaymessage(fd, atcmd_output);
} else if ( found < MAX_SKILLID_PARTIAL_RESULTS && ( stristr(key.str,message) || stristr(skill_db[idx]->desc,message) ) ) {
snprintf(partials[found++], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_txt(sd,1164), db_data2i(data), skill_db[idx]->desc, key.str); // // skill %d: %s (%s)
} else if ( found < MAX_SKILLID_PARTIAL_RESULTS && ( stristr(name,message) || stristr(desc,message) ) ) {
snprintf(partials[found++], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_txt(sd,1164), skill_id, desc, name); // // skill %d: %s (%s)
}
}
dbi_destroy(iter);
if( found ) {
sprintf(atcmd_output, msg_txt(sd,1398), found); // -- Displaying first %d partial matches
clif_displaymessage(fd, atcmd_output);
@ -5912,7 +5909,7 @@ ACMD_FUNC(skilltree)
{
if( ent->need[j].skill_id && pc_checkskill(sd,ent->need[j].skill_id) < ent->need[j].skill_lv)
{
sprintf(atcmd_output, msg_txt(sd,1170), ent->need[j].skill_lv, skill_db[skill_get_index(ent->need[j].skill_id)]->desc); // Player requires level %d of skill %s.
sprintf(atcmd_output, msg_txt(sd,1170), ent->need[j].skill_lv, skill_get_desc(ent->need[j].skill_id)); // Player requires level %d of skill %s.
clif_displaymessage(fd, atcmd_output);
meets = 0;
}

View File

@ -593,7 +593,7 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
* @param attack_type @see enum e_battle_flag
* @param src Attacker
* @param target Target
* @param nk Skill's nk @see enum e_skill_nk [NK_NO_CARDFIX_ATK|NK_NO_ELEFIX|NK_NO_CARDFIX_DEF]
* @param nk Skill's nk @see enum e_skill_nk [NK_IGNOREATKCARD|NK_IGNOREELEMENT|NK_IGNOREDEFCARD]
* @param rh_ele Right-hand weapon element
* @param lh_ele Left-hand weapon element (BF_MAGIC and BF_MISC ignore this value)
* @param damage Original damage
@ -604,7 +604,7 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
* @param flag Misc value of skill & damage flags
* @return damage Damage diff between original damage and after calculation
*/
int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int rh_ele, int lh_ele, int64 damage, int left, int flag){
int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, std::bitset<NK_MAX> nk, int rh_ele, int lh_ele, int64 damage, int left, int flag){
struct map_session_data *sd, ///< Attacker session data if BL_PC
*tsd; ///< Target session data if BL_PC
short cardfix = 1000;
@ -638,9 +638,9 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
switch( attack_type ) {
case BF_MAGIC:
// Affected by attacker ATK bonuses
if( sd && !(nk&NK_NO_CARDFIX_ATK) ) {
if( sd && !nk[NK_IGNOREATKCARD] ) {
cardfix = cardfix * (100 + sd->magic_addrace[tstatus->race] + sd->magic_addrace[RC_ALL] + sd->magic_addrace2[t_race2]) / 100;
if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
if( !nk[NK_IGNOREELEMENT] ) { // Affected by Element modifier bonuses
cardfix = cardfix * (100 + sd->magic_addele[tstatus->def_ele] + sd->magic_addele[ELE_ALL] +
sd->magic_addele_script[tstatus->def_ele] + sd->magic_addele_script[ELE_ALL]) / 100;
cardfix = cardfix * (100 + sd->magic_atk_ele[rh_ele] + sd->magic_atk_ele[ELE_ALL]) / 100;
@ -657,10 +657,10 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
}
// Affected by target DEF bonuses
if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) {
if( tsd && !nk[NK_IGNOREDEFCARD] ) {
cardfix = 1000; // reset var for target
if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
if( !nk[NK_IGNOREELEMENT] ) { // Affected by Element modifier bonuses
int ele_fix = tsd->subele[rh_ele] + tsd->subele[ELE_ALL] + tsd->subele_script[rh_ele] + tsd->subele_script[ELE_ALL];
for (const auto &it : tsd->subele2) {
@ -704,13 +704,13 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
case BF_WEAPON:
// Affected by attacker ATK bonuses
if( sd && !(nk&NK_NO_CARDFIX_ATK) && (left&2) ) {
if( sd && !nk[NK_IGNOREATKCARD] && (left&2) ) {
short cardfix_ = 1000;
if( sd->state.arrow_atk ) { // Ranged attack
cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->arrow_addrace[tstatus->race] +
sd->right_weapon.addrace[RC_ALL] + sd->arrow_addrace[RC_ALL]) / 100;
if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
if( !nk[NK_IGNOREELEMENT] ) { // Affected by Element modifier bonuses
int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele] +
sd->right_weapon.addele[ELE_ALL] + sd->arrow_addele[ELE_ALL];
@ -737,7 +737,7 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
if( !battle_config.left_cardfix_to_right ) {
// Right-handed weapon
cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->right_weapon.addrace[RC_ALL]) / 100;
if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
if( !nk[NK_IGNOREELEMENT] ) { // Affected by Element modifier bonuses
int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->right_weapon.addele[ELE_ALL];
for (const auto &it : sd->right_weapon.addele2) {
@ -757,7 +757,7 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
if( left&1 ) { // Left-handed weapon
cardfix_ = cardfix_ * (100 + sd->left_weapon.addrace[tstatus->race] + sd->left_weapon.addrace[RC_ALL]) / 100;
if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
if( !nk[NK_IGNOREELEMENT] ) { // Affected by Element modifier bonuses
int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[ELE_ALL];
for (const auto &it : sd->left_weapon.addele2) {
@ -778,8 +778,8 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
}
// Calculates right & left hand weapon as unity
else {
//! CHECKME: If 'left_cardfix_to_right' is yes, doesn't need to check NK_NO_ELEFIX?
//if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
//! CHECKME: If 'left_cardfix_to_right' is yes, doesn't need to check NK_IGNOREELEMENT?
//if( !nk[&]K_IGNOREELEMENT) ) { // Affected by Element modifier bonuses
int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele]
+ sd->right_weapon.addele[ELE_ALL] + sd->left_weapon.addele[ELE_ALL];
@ -841,8 +841,8 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
}
}
// Affected by target DEF bonuses
else if( tsd && !(nk&NK_NO_CARDFIX_DEF) && !(left&2) ) {
if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
else if( tsd && !nk[NK_IGNOREDEFCARD] && !(left&2) ) {
if( !nk[NK_IGNOREELEMENT] ) { // Affected by Element modifier bonuses
int ele_fix = tsd->subele[rh_ele] + tsd->subele[ELE_ALL] + tsd->subele_script[rh_ele] + tsd->subele_script[ELE_ALL];
for (const auto &it : tsd->subele2) {
@ -895,8 +895,8 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
case BF_MISC:
// Affected by target DEF bonuses
if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) {
if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
if( tsd && !nk[NK_IGNOREDEFCARD] ) {
if( !nk[NK_IGNOREELEMENT] ) { // Affected by Element modifier bonuses
int ele_fix = tsd->subele[rh_ele] + tsd->subele[ELE_ALL] + tsd->subele_script[rh_ele] + tsd->subele_script[ELE_ALL];
for (const auto &it : tsd->subele2) {
@ -1135,7 +1135,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
return 0;
}
if( (sce = sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill_get_inf3(skill_id)&INF3_NO_EFF_AUTOGUARD) && rnd()%100 < sce->val2) {
if( (sce = sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !skill_get_inf2(skill_id, INF2_IGNOREAUTOGUARD) && rnd()%100 < sce->val2) {
int delay;
struct status_change_entry *sce_d = sc->data[SC_DEVOTION];
struct block_list *d_bl = NULL;
@ -1227,7 +1227,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
return 0;
}
if (((sce = sc->data[SC_UTSUSEMI]) || sc->data[SC_BUNSINJYUTSU]) && flag&BF_WEAPON && !(skill_get_inf3(skill_id)&INF3_NO_EFF_CICADA)) {
if (((sce = sc->data[SC_UTSUSEMI]) || sc->data[SC_BUNSINJYUTSU]) && flag&BF_WEAPON && !skill_get_inf2(skill_id, INF2_IGNORECICADA)) {
skill_additional_effect (src, bl, skill_id, skill_lv, flag, ATK_BLOCK, gettick() );
if (!status_isdead(src))
skill_counter_additional_effect( src, bl, skill_id, skill_lv, flag, gettick() );
@ -1638,7 +1638,7 @@ int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64
if( !damage )
return 0;
if(skill_get_inf2(skill_id)&INF2_NO_BG_DMG)
if(skill_get_inf2(skill_id, INF2_IGNOREBGREDUCTION))
return damage; //skill that ignore bg map reduction
if( flag&BF_SKILL ) { //Skills get a different reduction than non-skills. [Skotlex]
@ -1676,7 +1676,7 @@ bool battle_can_hit_gvg_target(struct block_list *src,struct block_list *bl,uint
if (ud && ud->immune_attack)
return false;
if(md && md->guardian_data) {
if ((status_bl_has_mode(bl,MD_SKILL_IMMUNE) || (class_ == MOBID_EMPERIUM && !(skill_get_inf3(skill_id)&INF3_HIT_EMP))) && flag&BF_SKILL) //Skill immunity.
if ((status_bl_has_mode(bl,MD_SKILL_IMMUNE) || (class_ == MOBID_EMPERIUM && !skill_get_inf2(skill_id, INF2_TARGETEMPERIUM))) && flag&BF_SKILL) //Skill immunity.
return false;
if( src->type != BL_MOB || mob_is_clone( ((struct mob_data*)src)->mob_id ) ){
struct guild *g = src->type == BL_PC ? ((TBL_PC *)src)->guild : guild_search(status_get_guild_id(src));
@ -1708,7 +1708,7 @@ int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64
if (!battle_can_hit_gvg_target(src,bl,skill_id,flag))
return 0;
if (skill_get_inf2(skill_id)&INF2_NO_GVG_DMG) //Skills with no gvg damage reduction.
if (skill_get_inf2(skill_id, INF2_IGNOREGVGREDUCTION)) //Skills with no gvg damage reduction.
return damage;
if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
@ -2112,7 +2112,7 @@ void battle_consume_ammo(struct map_session_data*sd, int skill, int lv)
static int battle_range_type(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv)
{
// [Akinari] , [Xynvaroth]: Traps are always short range.
if( skill_get_inf2( skill_id ) & INF2_TRAP )
if (skill_get_inf2(skill_id, INF2_ISTRAP))
return BF_SHORT;
// When monsters use Arrow Shower or Bomb, it is always short range
@ -2169,13 +2169,14 @@ static enum e_skill_damage_type battle_skill_damage_type( struct block_list* bl
* @return Skill damage rate
*/
static int battle_skill_damage_skill(struct block_list *src, struct block_list *target, uint16 skill_id) {
uint16 idx = skill_get_index(skill_id), m = src->m;
int16 m = src->m;
std::shared_ptr<s_skill_db> skill = skill_db.find(skill_id);
struct s_skill_damage *damage = NULL;
if (!idx || !skill_db[idx]->damage.map)
if (!skill || !skill->damage.map)
return 0;
damage = &skill_db[idx]->damage;
damage = &skill->damage;
//check the adjustment works for specified type
if (!(damage->caster&src->type))
@ -2387,7 +2388,7 @@ static bool is_attack_critical(struct Damage* wd, struct block_list *src, struct
if (skill_id == NPC_CRITICALSLASH || skill_id == LG_PINPOINTATTACK) //Always critical skills
return true;
if( sstatus->cri && ( !skill_id || skill_get_nk(skill_id)&NK_CRITICAL ) )
if( sstatus->cri && ( !skill_id || skill_get_nk(skill_id, NK_CRITICAL) ) )
{
short cri = sstatus->cri;
@ -2485,12 +2486,20 @@ static int is_attack_piercing(struct Damage* wd, struct block_list *src, struct
return 0;
}
static int battle_skill_get_damage_properties(uint16 skill_id, int is_splash)
static std::bitset<NK_MAX> battle_skill_get_damage_properties(uint16 skill_id, int is_splash)
{
int nk = skill_get_nk(skill_id);
if( !skill_id && is_splash ) //If flag, this is splash damage from Baphomet Card and it always hits.
nk |= NK_NO_CARDFIX_ATK|NK_IGNORE_FLEE;
return nk;
if (skill_id == 0) {
if (is_splash) {
std::bitset<NK_MAX> tmp_nk;
tmp_nk.set(NK_IGNOREATKCARD);
tmp_nk.set(NK_IGNOREFLEE);
return tmp_nk;
} else
return 0;
} else
return skill_db.find(skill_id)->nk;
}
/*=============================
@ -2508,7 +2517,7 @@ static bool is_attack_hitting(struct Damage* wd, struct block_list *src, struct
struct status_change *sc = status_get_sc(src);
struct status_change *tsc = status_get_sc(target);
struct map_session_data *sd = BL_CAST(BL_PC, src);
int nk = battle_skill_get_damage_properties(skill_id, wd->miscflag);
std::bitset<NK_MAX> nk = battle_skill_get_damage_properties(skill_id, wd->miscflag);
short flee, hitrate;
if (!first_call)
@ -2525,7 +2534,7 @@ static bool is_attack_hitting(struct Damage* wd, struct block_list *src, struct
return true;
else if (tsc && tsc->opt1 && tsc->opt1 != OPT1_STONEWAIT && tsc->opt1 != OPT1_BURNING)
return true;
else if (nk&NK_IGNORE_FLEE)
else if (nk[NK_IGNOREFLEE])
return true;
if( tsc && tsc->data[SC_NEUTRALBARRIER] && (wd->flag&(BF_LONG|BF_MAGIC)) == BF_LONG )
@ -2671,7 +2680,7 @@ static bool attack_ignores_def(struct Damage* wd, struct block_list *src, struct
struct status_data *tstatus = status_get_status_data(target);
struct status_change *sc = status_get_sc(src);
struct map_session_data *sd = BL_CAST(BL_PC, src);
int nk = battle_skill_get_damage_properties(skill_id, wd->miscflag);
std::bitset<NK_MAX> nk = battle_skill_get_damage_properties(skill_id, wd->miscflag);
#ifndef RENEWAL
if (is_attack_critical(wd, src, target, skill_id, skill_lv, false))
@ -2704,7 +2713,7 @@ static bool attack_ignores_def(struct Damage* wd, struct block_list *src, struct
}
}
return (nk&NK_IGNORE_DEF) != 0;
return nk[NK_IGNOREDEFENSE] != 0;
}
/*================================================
@ -2836,10 +2845,10 @@ static void battle_calc_element_damage(struct Damage* wd, struct block_list *src
int element = skill_get_ele(skill_id, skill_lv);
int left_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_L, true);
int right_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_R, true);
int nk = battle_skill_get_damage_properties(skill_id, wd->miscflag);
std::bitset<NK_MAX> nk = battle_skill_get_damage_properties(skill_id, wd->miscflag);
//Elemental attribute fix
if(!(nk&NK_NO_ELEFIX)) {
if(!nk[NK_IGNOREELEMENT]) {
//Non-pc physical melee attacks (mob, pet, homun) are "non elemental", they deal 100% to all target elements
//However the "non elemental" attacks still get reduced by "Neutral resistance"
//Also non-pc units have only a defending element, but can inflict elemental attacks using skills [exneval]
@ -3065,7 +3074,7 @@ static void battle_calc_skill_base_damage(struct Damage* wd, struct block_list *
struct status_data *tstatus = status_get_status_data(target);
struct map_session_data *sd = BL_CAST(BL_PC, src);
uint16 i;
int nk = battle_skill_get_damage_properties(skill_id, wd->miscflag);
std::bitset<NK_MAX> nk = battle_skill_get_damage_properties(skill_id, wd->miscflag);
switch (skill_id) { //Calc base damage according to skill
case PA_SACRIFICE:
@ -3238,7 +3247,7 @@ static void battle_calc_skill_base_damage(struct Damage* wd, struct block_list *
if (is_attack_left_handed(src, skill_id))
wd->damage2 = battle_calc_base_damage(src, sstatus, &sstatus->lhw, sc, tstatus->size, i);
#endif
if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets
if (nk[NK_SPLASHSPLIT]){ // Divide ATK among targets
if(wd->miscflag > 0) {
wd->damage /= wd->miscflag;
#ifdef RENEWAL
@ -4461,7 +4470,6 @@ static void battle_attack_sc_bonus(struct Damage* wd, struct block_list *src, st
struct status_change *sc = status_get_sc(src);
struct status_data *sstatus = status_get_status_data(src);
struct status_data *tstatus = status_get_status_data(target);
int inf3 = skill_get_inf3(skill_id);
uint8 anger_id = 0; // SLS Anger
// Kagerou/Oboro Earth Charm effect +15% wATK
@ -4553,12 +4561,12 @@ static void battle_attack_sc_bonus(struct Damage* wd, struct block_list *src, st
#endif
}
}
if (sc->data[SC_GLOOMYDAY_SK] && (inf3&INF3_SC_GLOOMYDAY_SK)) {
if (sc->data[SC_GLOOMYDAY_SK] && skill_get_inf2(skill_id, INF2_INCREASEGLOOMYDAYDAMAGE)) {
ATK_ADDRATE(wd->damage, wd->damage2, sc->data[SC_GLOOMYDAY_SK]->val2);
RE_ALLATK_ADDRATE(wd, sc->data[SC_GLOOMYDAY_SK]->val2);
}
if (sc->data[SC_DANCEWITHWUG]) {
if (inf3&INF3_SC_DANCEWITHWUG) {
if (skill_get_inf2(skill_id, INF2_INCREASEDANCEWITHWUGDAMAGE)) {
ATK_ADDRATE(wd->damage, wd->damage2, sc->data[SC_DANCEWITHWUG]->val1 * 10 * battle_calc_chorusbonus(sd));
RE_ALLATK_ADDRATE(wd, sc->data[SC_DANCEWITHWUG]->val1 * 10 * battle_calc_chorusbonus(sd));
}
@ -5122,7 +5130,7 @@ static void battle_calc_weapon_final_atk_modifiers(struct Damage* wd, struct blo
rdamage = (int64)rdamage * ratio / 100 + wd->damage * (10 + tsc->data[SC_CRESCENTELBOW]->val1 * 20 / 10) / 10;
skill_blown(target, src, skill_get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, tsc->data[SC_CRESCENTELBOW]->val1), unit_getdir(src), BLOWN_NONE);
clif_skill_damage(target, src, gettick(), status_get_amotion(src), 0, rdamage,
1, SR_CRESCENTELBOW_AUTOSPELL, tsc->data[SC_CRESCENTELBOW]->val1, DMG_SKILL); // This is how official does
1, SR_CRESCENTELBOW_AUTOSPELL, tsc->data[SC_CRESCENTELBOW]->val1, DMG_SINGLE); // This is how official does
clif_damage(src, target, gettick(), status_get_amotion(src)+1000, 0, rdamage/10, 1, DMG_NORMAL, 0, false);
status_damage(target, src, rdamage, 0, 0, 0);
status_damage(src, target, rdamage/10, 0, 0, 1);
@ -5481,16 +5489,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
}
#endif
#ifndef RENEWAL
if (skill_id == NJ_KUNAI) {
short nk = battle_skill_get_damage_properties(skill_id, wd.miscflag);
ATK_ADD(wd.damage, wd.damage2, 90);
nk |= NK_IGNORE_DEF;
}
#endif
switch (skill_id) {
#ifndef RENEWAL
case NJ_KUNAI:
ATK_ADD(wd.damage, wd.damage2, 90);
break;
#endif
case TK_DOWNKICK:
case TK_STORMKICK:
case TK_TURNKICK:
@ -5677,7 +5681,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
*/
struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag)
{
int i, nk, skill_damage = 0;
int i, skill_damage = 0;
short s_ele = 0;
TBL_PC *sd;
@ -5706,8 +5710,14 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
ad.blewcount = skill_get_blewcount(skill_id, skill_lv);
ad.flag = BF_MAGIC|BF_SKILL;
ad.dmg_lv = ATK_DEF;
nk = skill_get_nk(skill_id);
flag.imdef = (nk&NK_IGNORE_DEF ? 1 : 0);
std::shared_ptr<s_skill_db> skill = skill_db.find(skill_id);
std::bitset<NK_MAX> nk;
if (skill)
nk = skill->nk;
flag.imdef = nk[NK_IGNOREDEFENSE] ? 1 : 0;
sd = BL_CAST(BL_PC, src);
tsd = BL_CAST(BL_PC, target);
@ -5843,7 +5853,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
MATK_ADD(sstatus->matk_min);
}
if (nk&NK_SPLASHSPLIT) { // Divide MATK in case of multiple targets skill
if (nk[NK_SPLASHSPLIT]) { // Divide MATK in case of multiple targets skill
if (mflag>0)
ad.damage /= mflag;
else
@ -6363,7 +6373,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
}
}
if (!(nk&NK_NO_ELEFIX) && skill_id != ASC_BREAKER) // Soul Breaker's magic portion is non-elemental. [Secret]
if (!nk[NK_IGNOREELEMENT] && skill_id != ASC_BREAKER) // Soul Breaker's magic portion is non-elemental. [Secret]
ad.damage = battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
//Apply the physical part of the skill's damage. [Skotlex]
@ -6433,8 +6443,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag)
{
int skill_damage = 0;
short i, nk;
short s_ele;
short i, s_ele;
struct map_session_data *sd, *tsd;
struct Damage md; //DO NOT CONFUSE with md of mob_data!
@ -6457,7 +6466,11 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.dmg_lv = ATK_DEF;
md.flag = BF_MISC|BF_SKILL;
nk = skill_get_nk(skill_id);
std::shared_ptr<s_skill_db> skill = skill_db.find(skill_id);
std::bitset<NK_MAX> nk;
if (skill)
nk = skill->nk;
sd = BL_CAST(BL_PC, src);
tsd = BL_CAST(BL_PC, target);
@ -6512,7 +6525,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
skill = 0;
md.damage = (sstatus->dex / 10 + sstatus->int_ / 2 + skill * 3 + 40) * 2;
if(mflag > 1) //Autocasted Blitz
nk |= NK_SPLASHSPLIT;
nk.set(NK_SPLASHSPLIT);
if (skill_id == SN_FALCONASSAULT) {
//Div fix of Blitzbeat
DAMAGE_DIV_FIX2(md.damage, skill_get_num(HT_BLITZBEAT, 5));
@ -6549,7 +6562,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
struct Damage atk, matk;
atk = battle_calc_weapon_attack(src, target, skill_id, skill_lv, 0);
nk |= NK_NO_ELEFIX; // atk part takes on weapon element, matk part is non-elemental
nk.set(NK_IGNOREELEMENT); // atk part takes on weapon element, matk part is non-elemental
matk = battle_calc_magic_attack(src, target, skill_id, skill_lv, 0);
// (atk + matk) * (3 + (.5 * skill level))
@ -6562,7 +6575,8 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
}
#else
md.damage = 500 + rnd()%500 + 5 * skill_lv * sstatus->int_;
nk |= NK_IGNORE_FLEE|NK_NO_ELEFIX; //These two are not properties of the weapon based part.
nk.set(NK_IGNOREFLEE);
nk.set(NK_IGNOREELEMENT); //These two are not properties of the weapon based part.
#endif
break;
case HW_GRAVITATION:
@ -6670,7 +6684,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage = 0;
} else
md.damage = md.damage * 200 / (skill_id == RA_CLUSTERBOMB ? 50 : 100);
nk |= NK_NO_ELEFIX|NK_IGNORE_FLEE|NK_NO_CARDFIX_DEF;
nk.set(NK_IGNOREELEMENT);
nk.set(NK_IGNOREFLEE);
nk.set(NK_IGNOREDEFCARD);
break;
case NC_MAGMA_ERUPTION_DOTDAMAGE: // 'Eruption' damage
md.damage = 800 + 200 * skill_lv;
@ -6706,14 +6722,14 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
break;
}
if (nk&NK_SPLASHSPLIT) { // Divide ATK among targets
if (nk[NK_SPLASHSPLIT]) { // Divide ATK among targets
if(mflag > 0)
md.damage /= mflag;
else
ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill_get_name(skill_id));
}
if (!(nk&NK_IGNORE_FLEE)) {
if (!nk[NK_IGNOREFLEE]) {
struct status_change *sc = status_get_sc(target);
i = 0; //Temp for "hit or no hit"
@ -6765,7 +6781,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
if (tsd && (i = pc_sub_skillatk_bonus(tsd, skill_id)))
md.damage -= (int64)md.damage*i/100;
if(!(nk&NK_NO_ELEFIX))
if(!nk[NK_IGNOREELEMENT])
md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
//Plant damage
@ -6920,7 +6936,7 @@ int64 battle_calc_return_damage(struct block_list* bl, struct block_list *src, i
return 0; // White Imprison does not reflect any damage
if (flag & BF_SHORT) {//Bounces back part of the damage.
if ( (skill_get_inf2(skill_id)&INF2_TRAP || !status_reflect) && sd && sd->bonus.short_weapon_damage_return ) {
if ( (skill_get_inf2(skill_id, INF2_ISTRAP) || !status_reflect) && sd && sd->bonus.short_weapon_damage_return ) {
rdamage += damage * sd->bonus.short_weapon_damage_return / 100;
rdamage = i64max(rdamage,1);
} else if( status_reflect && sc && sc->count ) {
@ -6937,7 +6953,7 @@ int64 battle_calc_return_damage(struct block_list* bl, struct block_list *src, i
return 0;
}
}
if( sc->data[SC_REFLECTDAMAGE] && !(skill_get_inf2(skill_id)&INF2_TRAP)) {
if( sc->data[SC_REFLECTDAMAGE] && !skill_get_inf2(skill_id, INF2_ISTRAP)) {
if( rnd()%100 <= sc->data[SC_REFLECTDAMAGE]->val1*10 + 30 ){
max_damage = (int64)max_damage * status_get_lv(bl) / 100;
rdamage = (*dmg) * sc->data[SC_REFLECTDAMAGE]->val2 / 100;
@ -6962,7 +6978,7 @@ int64 battle_calc_return_damage(struct block_list* bl, struct block_list *src, i
rd1 = min(damage,status_get_max_hp(bl)) * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage.
*dmg = rd1 * 30 / 100; // Received damage = 30% of amplified damage.
clif_skill_damage(src, bl, gettick(), status_get_amotion(src), 0, -30000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1, DMG_SKILL);
clif_skill_damage(src, bl, gettick(), status_get_amotion(src), 0, -30000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1, DMG_SINGLE);
skill_blown(bl, src, skill_get_blewcount(RK_DEATHBOUND, 1), unit_getdir(src), BLOWN_NONE);
status_change_end(bl, SC_DEATHBOUND, INVALID_TIMER);
rdamage += rd1 * 70 / 100; // Target receives 70% of the amplified damage. [Rytech]
@ -7435,7 +7451,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
struct elemental_data *ed = ((TBL_PC*)target)->ed;
if (ed) {
clif_skill_damage(&ed->bl, target, tick, status_get_amotion(src), 0, -30000, 1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, DMG_SKILL);
clif_skill_damage(&ed->bl, target, tick, status_get_amotion(src), 0, -30000, 1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, DMG_SINGLE);
skill_attack(BF_WEAPON,&ed->bl,&ed->bl,src,EL_CIRCLE_OF_FIRE,tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1,tick,wd.flag);
}
}
@ -7499,13 +7515,12 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
int type;
if( (type = skill_get_casttype(r_skill)) == CAST_GROUND ) {
int maxcount = 0;
std::shared_ptr<s_skill_db> skill = skill_db.find(r_skill);
if( !(BL_PC&battle_config.skill_reiteration) &&
skill_get_unit_flag(r_skill)&UF_NOREITERATION )
if( !(BL_PC&battle_config.skill_reiteration) && skill->unit_flag[UF_NOREITERATION] )
type = -1;
if( BL_PC&battle_config.skill_nofootset &&
skill_get_unit_flag(r_skill)&UF_NOFOOTSET )
if( BL_PC&battle_config.skill_nofootset && skill->unit_flag[UF_NOFOOTSET] )
type = -1;
if( BL_PC&battle_config.land_skill_limit &&
@ -7731,11 +7746,11 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
uint16 skill_id = battle_getcurrentskill(src);
if( !su || !su->group)
return 0;
if( skill_get_inf2(su->group->skill_id)&INF2_TRAP && su->group->unit_id != UNT_USED_TRAPS) {
if( skill_get_inf2(su->group->skill_id, INF2_ISTRAP) && su->group->unit_id != UNT_USED_TRAPS) {
if (!skill_id || su->group->skill_id == WM_REVERBERATION || su->group->skill_id == NPC_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) {
;
}
else if (skill_get_inf2(skill_id)&INF2_HIT_TRAP) { // Only a few skills can target traps
else if (skill_get_inf2(skill_id, INF2_TARGETTRAP)) { // Only a few skills can target traps
switch (skill_id) {
case RK_DRAGONBREATH:
case RK_DRAGONBREATH_WATER:
@ -7768,7 +7783,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
return 0;
default:
// Usually BCT_ALL stands for only hitting chars, but skills specifically set to hit traps also hit icewall
if ((flag&BCT_ALL) == BCT_ALL && !(skill_get_inf2(skill_id)&INF2_HIT_TRAP))
if ((flag&BCT_ALL) == BCT_ALL && !skill_get_inf2(skill_id, INF2_TARGETTRAP))
return -1;
}
state |= BCT_ENEMY;
@ -7832,15 +7847,17 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
struct status_change* sc = status_get_sc(target);
if (!su || !su->group)
return 0;
std::bitset<INF2_MAX> inf2 = skill_db.find(su->group->skill_id)->inf2;
if (su->group->src_id == target->id) {
int inf2 = skill_get_inf2(su->group->skill_id);
if (inf2&INF2_NO_TARGET_SELF)
if (inf2[INF2_NOTARGETSELF])
return -1;
if (inf2&INF2_TARGET_SELF)
if (inf2[INF2_TARGETSELF])
return 1;
}
//Status changes that prevent traps from triggering
if (sc && sc->count && skill_get_inf2(su->group->skill_id)&INF2_TRAP) {
if (sc && sc->count && inf2[INF2_ISTRAP]) {
if( sc->data[SC_SIGHTBLASTER] && sc->data[SC_SIGHTBLASTER]->val2 > 0 && sc->data[SC_SIGHTBLASTER]->val4%2 == 0)
return -1;
}

View File

@ -4,11 +4,14 @@
#ifndef BATTLE_HPP
#define BATTLE_HPP
#include <bitset>
#include "../common/cbasetypes.hpp"
#include "../common/mmo.hpp"
#include "../config/core.hpp"
#include "map.hpp" //ELE_MAX
#include "skill.hpp"
//fwd declaration
struct map_session_data;
@ -29,6 +32,7 @@ enum damage_lv : uint8 {
/// Flag of the final calculation
enum e_battle_flag : uint16 {
BF_NONE = 0x0000, /// None
BF_WEAPON = 0x0001, /// Weapon attack
BF_MAGIC = 0x0002, /// Magic attack
BF_MISC = 0x0004, /// Misc attack
@ -61,6 +65,8 @@ enum e_battle_check_target : uint32 {
BCT_NOGUILD = BCT_ALL&~BCT_GUILD, ///< Except guildmates
BCT_NOPARTY = BCT_ALL&~BCT_PARTY, ///< Except party members
BCT_NOENEMY = BCT_ALL&~BCT_ENEMY, ///< Except enemy
BCT_ALLY = BCT_PARTY|BCT_GUILD,
BCT_FRIEND = BCT_NOENEMY,
};
/// Damage structure
@ -94,7 +100,7 @@ void battle_drain(struct map_session_data *sd, struct block_list *tbl, int64 rda
int battle_attr_ratio(int atk_elem,int def_type, int def_lv);
int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 damage,int atk_elem,int def_type, int def_lv);
int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int left, int flag);
int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, std::bitset<NK_MAX> nk, int s_ele, int s_ele_, int64 damage, int left, int flag);
// Final calculation Damage
int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int64 damage,uint16 skill_id,uint16 skill_lv);

View File

@ -5031,9 +5031,9 @@ void clif_getareachar_skillunit(struct block_list *bl, struct skill_unit *unit,
if (unit->group->state.guildaura)
return;
if (unit->group->state.song_dance&0x1 && unit->val2&UF_ENSEMBLE)
unit_id = unit->val2&UF_SONG ? UNT_DISSONANCE : UNT_UGLYDANCE;
else if (skill_get_unit_flag(unit->group->skill_id) & UF_RANGEDSINGLEUNIT && !(unit->val2 & UF_RANGEDSINGLEUNIT))
if (unit->group->state.song_dance&0x1 && unit->val2&(1 << UF_ENSEMBLE))
unit_id = unit->val2&(1 << UF_SONG) ? UNT_DISSONANCE : UNT_UGLYDANCE;
else if (skill_get_unit_flag(unit->group->skill_id, UF_RANGEDSINGLEUNIT) && !(unit->val2 & (1 << UF_RANGEDSINGLEUNIT)))
unit_id = UNT_DUMMYSKILL; // Use invisible unit id for other case of rangedsingle unit
else
unit_id = unit->group->unit_id;
@ -5622,7 +5622,7 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,t_tick tick,
#if PACKETVER < 20131223
WBUFB(buf,32)=type;
#else
WBUFB(buf,32)=( type == DMG_SKILL ) ? DMG_MULTI_HIT : type;
WBUFB(buf,32)=( type == DMG_SINGLE ) ? DMG_MULTI_HIT : type;
#endif
if (disguised(dst)) {
clif_send(buf,packet_len(0x1de),dst,AREA_WOS);
@ -18500,7 +18500,7 @@ int clif_autoshadowspell_list(struct map_session_data *sd) {
//AEGIS listed the specified skills that available for SC_AUTOSHADOWSPELL
for( i = 0, c = 0; i < MAX_SKILL; i++ )
if( sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].id > 0 &&
(skill_get_inf2(sd->status.skill[i].id)&INF2_AUTOSHADOWSPELL))
skill_get_inf2(sd->status.skill[i].id, INF2_ISAUTOSHADOWSPELL))
{
WFIFOW(fd,8+c*2) = sd->status.skill[i].id;
c++;

View File

@ -542,7 +542,7 @@ enum e_damage_type : uint8_t {
DMG_STAND_UP, /// stand up
DMG_ENDURE, /// damage (endure)
DMG_SPLASH, /// (splash?)
DMG_SKILL, /// (skill?)
DMG_SINGLE, /// (skill?)
DMG_REPEAT, /// (repeat damage?)
DMG_MULTI_HIT, /// multi-hit damage
DMG_MULTI_HIT_ENDURE, /// multi-hit damage (endure)

View File

@ -386,7 +386,7 @@ int elemental_clean_effect(struct elemental_data *ed) {
}
int elemental_action(struct elemental_data *ed, struct block_list *bl, t_tick tick) {
struct skill_condition req;
struct s_skill_condition req;
uint16 skill_id, skill_lv;
int i;
@ -562,19 +562,16 @@ bool elemental_skillnotok(uint16 skill_id, struct elemental_data *ed) {
return idx == 0 ? false : skill_isNotOk(skill_id,ed->master); // return false or check if it,s ok for master as well
}
struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv){
struct skill_condition req;
uint16 idx = skill_get_index(skill_id);
struct s_skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv){
struct s_skill_condition req = {};
std::shared_ptr<s_skill_db> skill = skill_db.find(skill_id);
memset(&req,0,sizeof(req));
if( idx == 0 ) // invalid skill id
if( !skill ) // invalid skill id
return req;
skill_lv = cap_value(skill_lv, 1, MAX_SKILL_LEVEL);
req.hp = skill_db[idx]->require.hp[skill_lv-1];
req.sp = skill_db[idx]->require.sp[skill_lv-1];
req.hp = skill->require.hp[skill_lv - 1];
req.sp = skill->require.sp[skill_lv - 1];
return req;
}

View File

@ -103,7 +103,7 @@ int elemental_set_target( struct map_session_data *sd, struct block_list *bl );
int elemental_clean_single_effect(struct elemental_data *ed, uint16 skill_id);
int elemental_clean_effect(struct elemental_data *ed);
int elemental_action(struct elemental_data *ed, struct block_list *bl, t_tick tick);
struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv);
struct s_skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv);
#define elemental_stop_walking(ed, type) unit_stop_walking(&(ed)->bl, type)
#define elemental_stop_attack(ed) unit_stop_attack(&(ed)->bl)

View File

@ -239,8 +239,10 @@ int hom_vaporize(struct map_session_data *sd, int flag)
//Delete timers when vaporized.
hom_hungry_timer_delete(hd);
hd->homunculus.vaporize = flag ? flag : HOM_ST_REST;
if (battle_config.hom_setting&HOMSET_RESET_REUSESKILL_VAPORIZED)
memset(hd->blockskill, 0, sizeof(hd->blockskill));
if (battle_config.hom_setting&HOMSET_RESET_REUSESKILL_VAPORIZED) {
hd->blockskill.clear();
hd->blockskill.shrink_to_fit();
}
clif_hominfo(sd, sd->hd, 0);
hom_save(hd);
return unit_remove_map(&hd->bl, CLR_OUTSIGHT);

View File

@ -66,7 +66,7 @@ struct homun_data {
struct map_session_data *master; //pointer back to its master
int hungry_timer; //[orn]
unsigned int exp_next;
char blockskill[MAX_SKILL]; // [orn]
std::vector<uint16> blockskill; // [orn]
};
#define MAX_HOM_SKILL_REQUIRE 5

View File

@ -359,17 +359,11 @@
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\quest_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\quest_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\refine_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\refine_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\size_fix.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\size_fix.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_cast_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_cast_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_castnodex_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_castnodex_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_changematerial_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_changematerial_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_copyable_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_copyable_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_damage_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_damage_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_nocast_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_nocast_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_nonearnpc_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_nonearnpc_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_require_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_require_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_tree.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_tree.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_unit_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_unit_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\spellbook_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\spellbook_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\statpoint.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\statpoint.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\status_disabled.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\status_disabled.txt')" />

View File

@ -337,7 +337,10 @@ enum e_element : int8{
ELE_GHOST,
ELE_UNDEAD,
ELE_ALL,
ELE_MAX
ELE_MAX,
ELE_WEAPON,
ELE_ENDOWED,
ELE_RANDOM,
};
#define MAX_ELE_LEVEL 4 /// Maximum Element level

View File

@ -50,7 +50,7 @@ struct mercenary_data {
struct s_mercenary_db *db;
struct s_mercenary mercenary;
char blockskill[MAX_SKILL];
std::vector<uint16> blockskill;
int masterteleport_timer;
struct map_session_data *master;

View File

@ -3907,8 +3907,9 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
for (i=0,j = MAX_SKILL_TREE-1;j>=0 && i< MAX_MOBSKILL ;j--) {
uint16 skill_id = skill_tree[pc_class2idx(sd->status.class_)][j].skill_id;
uint16 sk_idx = 0;
if (!skill_id || !(sk_idx = skill_get_index(skill_id)) || sd->status.skill[sk_idx].lv < 1 ||
(skill_get_inf2(skill_id)&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL)) ||
skill_get_inf2_(skill_id, { INF2_ISWEDDING, INF2_ISGUILD }) ||
mob_clone_disabled_skills(skill_id)
)
continue;
@ -3916,8 +3917,8 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
//against players (those with flags UF_NOMOB and UF_NOPC are specific
//to always aid players!) [Skotlex]
if (!(flag&1) &&
skill_get_unit_id(skill_id, 0) &&
skill_get_unit_flag(skill_id)&(UF_NOMOB|UF_NOPC))
skill_get_unit_id(skill_id) &&
skill_get_unit_flag_(skill_id, { UF_NOMOB, UF_NOPC }))
continue;
/**
* The clone should be able to cast the skill (e.g. have the required weapon) bugreport:5299)
@ -3945,7 +3946,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
else
ms[i].state = MSS_BERSERK;
} else if(inf&INF_GROUND_SKILL) {
if (skill_get_inf2(skill_id)&INF2_TRAP) { //Traps!
if (skill_get_inf2(skill_id, INF2_ISTRAP)) { //Traps!
ms[i].state = MSS_IDLE;
ms[i].target = MST_AROUND2;
ms[i].delay = 60000;
@ -3959,7 +3960,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
ms[i].cond2 = 95;
}
} else if (inf&INF_SELF_SKILL) {
if (skill_get_inf2(skill_id)&INF2_NO_TARGET_SELF) { //auto-select target skill.
if (skill_get_inf2(skill_id, INF2_NOTARGETSELF)) { //auto-select target skill.
ms[i].target = MST_TARGET;
ms[i].cond1 = MSC_ALWAYS;
if (skill_get_range(skill_id, ms[i].skill_lv) > 3) {

View File

@ -138,26 +138,28 @@ struct view_data* npc_get_viewdata(int class_) {
int npc_isnear_sub(struct block_list* bl, va_list args) {
struct npc_data *nd = (struct npc_data*)bl;
if (nd->sc.option & (OPTION_HIDE|OPTION_INVISIBLE))
return 0;
int skill_id = va_arg(args, int);
if (skill_id > 0) { //If skill_id > 0 that means is used for INF2_NO_NEARNPC [Cydh]
uint16 idx = skill_get_index(skill_id);
if (skill_id > 0) { //If skill_id > 0 that means is used for INF2_DISABLENEARNPC [Cydh]
std::shared_ptr<s_skill_db> skill = skill_db.find(skill_id);
if (idx > 0 && skill_db[idx]->unit_nonearnpc_type) {
while (1) {
if (skill_db[idx]->unit_nonearnpc_type&1 && nd->subtype == NPCTYPE_WARP) break;
if (skill_db[idx]->unit_nonearnpc_type&2 && nd->subtype == NPCTYPE_SHOP) break;
if (skill_db[idx]->unit_nonearnpc_type&4 && nd->subtype == NPCTYPE_SCRIPT) break;
if (skill_db[idx]->unit_nonearnpc_type&8 && nd->subtype == NPCTYPE_TOMB) break;
return 0;
}
if (skill && skill->unit_nonearnpc_type) {
if (skill->unit_nonearnpc_type&SKILL_NONEAR_WARPPORTAL && nd->subtype == NPCTYPE_WARP)
return 1;
if (skill->unit_nonearnpc_type&SKILL_NONEAR_SHOP && nd->subtype == NPCTYPE_SHOP)
return 1;
if (skill->unit_nonearnpc_type&SKILL_NONEAR_NPC && nd->subtype == NPCTYPE_SCRIPT)
return 1;
if (skill->unit_nonearnpc_type&SKILL_NONEAR_TOMB && nd->subtype == NPCTYPE_TOMB)
return 1;
}
}
if( nd->sc.option & (OPTION_HIDE|OPTION_INVISIBLE) )
return 0;
return 1;
return 0;
}
bool npc_isnear(struct block_list * bl) {

View File

@ -1755,9 +1755,10 @@ static int pc_calc_skillpoint(struct map_session_data* sd)
for(i = 1; i < MAX_SKILL; i++) {
if( sd->status.skill[i].id && sd->status.skill[i].lv > 0) {
uint16 inf2 = skill_get_inf2(sd->status.skill[i].id);
if ((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) &&
!(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) //Do not count wedding/link skills. [Skotlex]
std::shared_ptr<s_skill_db> skill = skill_db.find(sd->status.skill[i].id);
if ((!skill->inf2[INF2_ISQUEST] || battle_config.quest_skill_learn) &&
(!skill->inf2[INF2_ISWEDDING] || skill->inf2[INF2_ISSPIRIT]) //Do not count wedding/link skills. [Skotlex]
)
{
if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT)
@ -1772,9 +1773,7 @@ static int pc_calc_skillpoint(struct map_session_data* sd)
}
static bool pc_grant_allskills(struct map_session_data *sd, bool addlv) {
uint16 i = 0;
if (!sd || !pc_has_permission(sd, PC_PERM_ALL_SKILL) || !SKILL_MAX_DB())
if (!sd || !pc_has_permission(sd, PC_PERM_ALL_SKILL))
return false;
/**
@ -1783,9 +1782,10 @@ static bool pc_grant_allskills(struct map_session_data *sd, bool addlv) {
* Get ALL skills except npc/guild ones. [Skotlex]
* Don't add SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage]
**/
for( i = 0; i < MAX_SKILL; i++ ) {
uint16 skill_id = skill_idx2id(i);
if (!skill_id || (skill_get_inf2(skill_id)&(INF2_NPC_SKILL|INF2_GUILD_SKILL)))
for (const auto &skill : skill_db) {
uint16 skill_id = skill.second->nameid;
if (skill_id == 0 || skill.second->inf2[INF2_ISNPC]|| skill.second->inf2[INF2_ISGUILD])
continue;
switch (skill_id) {
case SM_SELFPROVOKE:
@ -1811,10 +1811,13 @@ static bool pc_grant_allskills(struct map_session_data *sd, bool addlv) {
default:
{
uint8 lv = (uint8)skill_get_max(skill_id);
if (lv > 0) {
sd->status.skill[i].id = skill_id;
uint16 idx = skill_get_index(skill_id);
sd->status.skill[idx].id = skill_id;
if (addlv)
sd->status.skill[i].lv = lv;
sd->status.skill[idx].lv = lv;
}
}
break;
@ -1829,72 +1832,74 @@ static bool pc_grant_allskills(struct map_session_data *sd, bool addlv) {
*------------------------------------------*/
void pc_calc_skilltree(struct map_session_data *sd)
{
int i, flag;
int c = 0;
nullpo_retv(sd);
i = pc_calc_skilltree_normalize_job(sd);
c = pc_mapid2jobid(i, sd->status.sex);
if( c == -1 )
int job = pc_calc_skilltree_normalize_job(sd);
int class_ = pc_mapid2jobid(job, sd->status.sex);
if( class_ == -1 )
{ //Unable to normalize job??
ShowError("pc_calc_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", i, sd->status.name, sd->status.account_id, sd->status.char_id);
ShowError("pc_calc_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", job, sd->status.name, sd->status.account_id, sd->status.char_id);
return;
}
c = pc_class2idx(c);
class_ = pc_class2idx(class_);
for( i = 0; i < MAX_SKILL; i++ ) {
if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED ) //Don't touch these
sd->status.skill[i].id = 0; //First clear skills.
for (const auto &skill : skill_db) {
uint16 skill_id = skill.second->nameid;
uint16 idx = skill_get_index(skill_id);
if( sd->status.skill[idx].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[idx].flag != SKILL_FLAG_PERM_GRANTED ) //Don't touch these
sd->status.skill[idx].id = 0; //First clear skills.
/* permanent skills that must be re-checked */
if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED ) {
uint16 sk_id = skill_idx2id(i);
if (!sk_id) {
sd->status.skill[i].id = 0;
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
if( sd->status.skill[idx].flag == SKILL_FLAG_PERM_GRANTED ) {
if (skill_id == 0) {
sd->status.skill[idx].id = 0;
sd->status.skill[idx].lv = 0;
sd->status.skill[idx].flag = SKILL_FLAG_PERMANENT;
continue;
}
switch (sk_id) {
switch (skill_id) {
case NV_TRICKDEAD:
if( (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) {
sd->status.skill[i].id = 0;
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
sd->status.skill[idx].id = 0;
sd->status.skill[idx].lv = 0;
sd->status.skill[idx].flag = SKILL_FLAG_PERMANENT;
}
break;
}
}
}
for( i = 0; i < MAX_SKILL; i++ ) {
uint16 skill_id = 0;
for (const auto &skill : skill_db) {
uint16 skill_id = skill.second->nameid;
uint16 idx = skill_get_index(skill_id);
// Restore original level of skills after deleting earned skills.
if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) {
sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
if( sd->status.skill[idx].flag != SKILL_FLAG_PERMANENT && sd->status.skill[idx].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[idx].flag != SKILL_FLAG_PLAGIARIZED ) {
sd->status.skill[idx].lv = (sd->status.skill[idx].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[idx].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[idx].flag = SKILL_FLAG_PERMANENT;
}
//Enable Bard/Dancer spirit linked skills.
if (!(skill_id = skill_idx2id(i)) || skill_id < DC_HUMMING || skill_id > DC_SERVICEFORYOU)
if (skill_id < DC_HUMMING || skill_id > DC_SERVICEFORYOU)
continue;
if( sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER ) {
//Link Dancer skills to bard.
if( sd->status.sex ) {
if( sd->status.skill[i-8].lv < 10 )
if( sd->status.skill[idx - 8].lv < 10 )
continue;
sd->status.skill[i].id = skill_id;
sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill
sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
sd->status.skill[idx].id = skill_id;
sd->status.skill[idx].lv = sd->status.skill[idx - 8].lv; // Set the level to the same as the linking skill
sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
}
//Link Bard skills to dancer.
else {
if( sd->status.skill[i].lv < 10 )
if( sd->status.skill[idx].lv < 10 )
continue;
sd->status.skill[i-8].id = skill_id - 8;
sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill
sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
sd->status.skill[idx - 8].id = skill_id - 8;
sd->status.skill[idx - 8].lv = sd->status.skill[idx].lv; // Set the level to the same as the linking skill
sd->status.skill[idx - 8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
}
}
}
@ -1903,7 +1908,7 @@ void pc_calc_skilltree(struct map_session_data *sd)
if ((sd->class_&MAPID_UPPERMASK) != MAPID_TAEKWON) {
uint16 c_ = pc_class2idx(JOB_TAEKWON);
for (i = 0; i < MAX_SKILL_TREE; i++) {
for (uint16 i = 0; i < MAX_SKILL_TREE; i++) {
uint16 sk_id = skill_tree[c_][i].skill_id;
uint16 sk_idx = 0;
@ -1921,11 +1926,13 @@ void pc_calc_skilltree(struct map_session_data *sd)
// Grant all skills
pc_grant_allskills(sd, false);
int flag;
do {
uint16 skid = 0;
flag = 0;
for (i = 0; i < MAX_SKILL_TREE && (skid = skill_tree[c][i].skill_id) > 0; i++) {
for (uint16 i = 0; i < MAX_SKILL_TREE && (skid = skill_tree[class_][i].skill_id) > 0; i++) {
bool fail = false;
uint16 sk_idx = skill_get_index(skid);
@ -1933,11 +1940,9 @@ void pc_calc_skilltree(struct map_session_data *sd)
continue; //Skill already known.
if (!battle_config.skillfree) {
uint8 j;
// Checking required skills
for(j = 0; j < MAX_PC_SKILL_REQUIRE; j++) {
uint16 sk_need_id = skill_tree[c][i].need[j].skill_id;
for(uint8 j = 0; j < MAX_PC_SKILL_REQUIRE; j++) {
uint16 sk_need_id = skill_tree[class_][i].need[j].skill_id;
uint16 sk_need_idx = 0;
if (sk_need_id && (sk_need_idx = skill_get_index(sk_need_id))) {
@ -1950,40 +1955,42 @@ void pc_calc_skilltree(struct map_session_data *sd)
else
sk_need = pc_checkskill(sd,sk_need_id);
if (sk_need < skill_tree[c][i].need[j].skill_lv) {
if (sk_need < skill_tree[class_][i].need[j].skill_lv) {
fail = true;
break;
}
}
}
if (sd->status.base_level < skill_tree[c][i].baselv) { //We need to get the actual class in this case
int class_ = pc_mapid2jobid(sd->class_, sd->status.sex);
class_ = pc_class2idx(class_);
if (class_ == c || (class_ != c && sd->status.base_level < skill_tree[class_][i].baselv))
if (sd->status.base_level < skill_tree[class_][i].baselv) { //We need to get the actual class in this case
int c_ = pc_mapid2jobid(sd->class_, sd->status.sex);
c_ = pc_class2idx(c_);
if (class_ == c_ || (class_ != c_ && sd->status.base_level < skill_tree[class_][i].baselv))
fail = true; // base level requirement wasn't satisfied
}
if (sd->status.job_level < skill_tree[c][i].joblv) { //We need to get the actual class in this case
int class_ = pc_mapid2jobid(sd->class_, sd->status.sex);
class_ = pc_class2idx(class_);
if (class_ == c || (class_ != c && sd->status.job_level < skill_tree[class_][i].joblv))
if (sd->status.job_level < skill_tree[class_][i].joblv) { //We need to get the actual class in this case
int c_ = pc_mapid2jobid(sd->class_, sd->status.sex);
c_ = pc_class2idx(c_);
if (class_ == c_ || (class_ != c_ && sd->status.job_level < skill_tree[class_][i].joblv))
fail = true; // job level requirement wasn't satisfied
}
}
if (!fail) {
int inf2 = skill_get_inf2(skid);
std::shared_ptr<s_skill_db> skill = skill_db.find(skid);
if (!sd->status.skill[sk_idx].lv && (
(inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
inf2&INF2_WEDDING_SKILL ||
(inf2&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT])
(skill->inf2[INF2_ISQUEST] && !battle_config.quest_skill_learn) ||
skill->inf2[INF2_ISWEDDING] ||
(skill->inf2[INF2_ISSPIRIT] && !sd->sc.data[SC_SPIRIT])
))
continue; //Cannot be learned via normal means. Note this check DOES allows raising already known skills.
sd->status.skill[sk_idx].id = skid;
if(inf2&INF2_SPIRIT_SKILL) { //Spirit skills cannot be learned, they will only show up on your tree when you get buffed.
if(skill->inf2[INF2_ISSPIRIT]) { //Spirit skills cannot be learned, they will only show up on your tree when you get buffed.
sd->status.skill[sk_idx].lv = 1; // need to manually specify a skill level
sd->status.skill[sk_idx].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill.
}
@ -1992,19 +1999,22 @@ void pc_calc_skilltree(struct map_session_data *sd)
}
} while(flag);
if( c > 0 && sd->status.skill_point == 0 && pc_is_taekwon_ranker(sd) ) {
unsigned short skid = 0;
if( class_ > 0 && sd->status.skill_point == 0 && pc_is_taekwon_ranker(sd) ) {
uint16 skid = 0;
/* Taekwon Ranker Bonus Skill Tree
============================================
- Grant All Taekwon Tree, but only as Bonus Skills in case they drop from ranking.
- (c > 0) to avoid grant Novice Skill Tree in case of Skill Reset (need more logic)
- (sd->status.skill_point == 0) to wait until all skill points are assigned to avoid problems with Job Change quest. */
for( i = 0; i < MAX_SKILL_TREE && (skid = skill_tree[c][i].skill_id) > 0; i++ ) {
uint16 sk_idx = 0;
if (!(sk_idx = skill_get_index(skid)))
for( uint16 i = 0; i < MAX_SKILL_TREE && (skid = skill_tree[class_][i].skill_id) > 0; i++ ) {
uint16 sk_idx = skill_get_index(skid);
if (sk_idx == 0)
continue;
if( (skill_get_inf2(skid)&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) )
if( skill_get_inf2_(skid, { INF2_ISQUEST, INF2_ISWEDDING }) )
continue; //Do not include Quest/Wedding skills.
if( sd->status.skill[sk_idx].id == 0 ) {
sd->status.skill[sk_idx].id = skid;
@ -2072,11 +2082,12 @@ static void pc_check_skilltree(struct map_session_data *sd)
if (sd->status.base_level < skill_tree[c][i].baselv || sd->status.job_level < skill_tree[c][i].joblv)
continue;
j = skill_get_inf2(skid);
std::shared_ptr<s_skill_db> skill = skill_db.find(skid);
if( !sd->status.skill[sk_idx].lv && (
(j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
j&INF2_WEDDING_SKILL ||
(j&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT])
(skill->inf2[INF2_ISQUEST] && !battle_config.quest_skill_learn) ||
skill->inf2[INF2_ISWEDDING] ||
(skill->inf2[INF2_ISSPIRIT] && !sd->sc.data[SC_SPIRIT])
) )
continue; //Cannot be learned via normal means.
@ -4106,7 +4117,7 @@ void pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
if(sd->state.lr_flag != 2)
{
int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self.
target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF));
target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !skill_get_inf2(type2, INF2_NOTARGETSELF));
pc_bonus_autospell(sd->autospell, target?-type2:type2, type3, val, 0, current_equip_card_id);
}
break;
@ -4114,7 +4125,7 @@ void pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
if(sd->state.lr_flag != 2)
{
int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self.
target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF));
target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !skill_get_inf2(type2, INF2_NOTARGETSELF));
pc_bonus_autospell(sd->autospell2, target?-type2:type2, type3, val, BF_NORMAL|BF_SKILL, current_equip_card_id);
}
break;
@ -4242,7 +4253,7 @@ void pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type
if(sd->state.lr_flag != 2)
{
int target = skill_get_inf(type3); //Support or Self (non-auto-target) skills should pick self.
target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type3)&INF2_NO_TARGET_SELF));
target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !skill_get_inf2(type3, INF2_NOTARGETSELF));
pc_bonus_autospell_onskill(sd->autospell3, type2, target?-type3:type3, type4, val, current_equip_card_id);
}
@ -6009,12 +6020,11 @@ bool pc_memo(struct map_session_data* sd, int pos)
* @return player skill cooldown
*/
int pc_get_skillcooldown(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv) {
uint16 idx = skill_get_index(skill_id);
int cooldown = 0;
if (!idx) return 0;
if (skill_db[idx]->cooldown[skill_lv - 1])
cooldown = skill_db[idx]->cooldown[skill_lv - 1];
int cooldown = skill_get_cooldown(skill_id, skill_lv);
if (cooldown == 0)
return 0;
if (skill_id == SU_TUNABELLY && pc_checkskill(sd, SU_SPIRITOFSEA))
cooldown -= skill_get_time(SU_TUNABELLY, skill_lv);
@ -7479,14 +7489,16 @@ int pc_allskillup(struct map_session_data *sd)
if (!pc_grant_allskills(sd, true)) {
uint16 sk_id;
for (i = 0; i < MAX_SKILL_TREE && (sk_id = skill_tree[pc_class2idx(sd->status.class_)][i].skill_id) > 0;i++){
int inf2 = 0;
uint16 sk_idx = 0;
if (!sk_id || !(sk_idx = skill_get_index(sk_id)))
uint16 sk_idx = skill_get_index(sk_id);
if (sk_id == 0 || sk_idx == 0)
continue;
inf2 = skill_get_inf2(sk_id);
std::shared_ptr<s_skill_db> skill = skill_db.find(sk_id);
if (
(inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) ||
(skill->inf2[INF2_ISQUEST] && !battle_config.quest_skill_learn) ||
((skill->inf2[INF2_ISWEDDING] || skill->inf2[INF2_ISSPIRIT])) ||
sk_id == SG_DEVIL
)
continue; //Cannot be learned normally.
@ -7708,17 +7720,14 @@ int pc_resetskill(struct map_session_data* sd, int flag)
status_change_end(&sd->bl, SC_SPRITEMABLE, INVALID_TIMER);
}
for( i = 1; i < MAX_SKILL; i++ )
{
for (const auto &skill : skill_db) {
uint8 lv = sd->status.skill[i].lv;
int inf2;
uint16 skill_id = skill_idx2id(i);
uint16 skill_id = skill.second->nameid;
if (lv == 0 || skill_id == 0)
continue;
inf2 = skill_get_inf2(skill_id);
if( inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL) ) //Avoid reseting wedding/linker skills.
if( skill.second->inf2[INF2_ISWEDDING] || skill.second->inf2[INF2_ISSPIRIT] ) //Avoid reseting wedding/linker skills.
continue;
// Don't reset trick dead if not a novice/baby
@ -7739,7 +7748,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
if( flag&4 && !skill_ischangesex(skill_id) )
continue;
if( inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn )
if( skill.second->inf2[INF2_ISQUEST] && !battle_config.quest_skill_learn )
{ //Only handle quest skills in a special way when you can't learn them manually
if( battle_config.quest_skill_reset && !(flag&2) )
{ //Wipe them
@ -9290,7 +9299,7 @@ void pc_setoption(struct map_session_data *sd,int type)
for (uint8 i = 0; i < ARRAYLENGTH(statuses); i++) {
int skill_id = status_sc2skill(statuses[i]);
if (skill_id >= 0 && !(skill_get_inf3(skill_id)&INF3_USABLE_MADO))
if (skill_id > 0 && !skill_get_inf2(skill_id, INF2_ALLOWONMADO))
status_change_end(&sd->bl,statuses[i],INVALID_TIMER);
}
pc_bonus_script_clear(sd,BSF_REM_ON_MADOGEAR);
@ -11510,7 +11519,7 @@ static bool pc_readdb_skilltree(char* fields[], int columns, int current)
idx = pc_class2idx(class_);
if (!skill_get_index(skill_id)) {
ShowWarning("pc_readdb_skilltree: Unable to load skill %hu into job %d's tree.", skill_id, class_);
ShowWarning("pc_readdb_skilltree: Unable to load skill %hu into job %d's tree.\n", skill_id, class_);
return false;
}
if (skill_lv > (skill_lv_max = skill_get_max(skill_id))) {

View File

@ -382,7 +382,7 @@ struct map_session_data {
uint16 skill_id_dance,skill_lv_dance;
short cook_mastery; // range: [0,1999] [Inkfish]
struct skill_cooldown_entry * scd[MAX_SKILLCOOLDOWN]; // Skill Cooldown
short cloneskill_idx, ///Stores index of copied skill by Intimidate/Plagiarism
uint16 cloneskill_idx, ///Stores index of copied skill by Intimidate/Plagiarism
reproduceskill_idx; ///Stores index of copied skill by Reproduce
int menuskill_id, menuskill_val, menuskill_val2;

View File

@ -3504,6 +3504,9 @@
export_constant(ELE_GHOST);
export_constant(ELE_UNDEAD);
export_constant(ELE_ALL);
export_constant(ELE_WEAPON);
export_constant(ELE_ENDOWED);
export_constant(ELE_RANDOM);
/* races */
export_constant(RC_FORMLESS);
@ -3570,6 +3573,7 @@
export_constant(AI_FAW);
/* battle flags */
export_constant(BF_NONE);
export_constant(BF_WEAPON);
export_constant(BF_MAGIC);
export_constant(BF_MISC);
@ -7403,6 +7407,284 @@
export_constant(CPC_CHAR);
export_constant(CPC_ACCOUNT);
/* skill hit */
export_constant(DMG_SINGLE);
export_constant(DMG_MULTI_HIT);
/* skill nk */
export_constant(NK_NODAMAGE);
export_constant(NK_SPLASH);
export_constant(NK_SPLASHSPLIT);
export_constant(NK_IGNOREATKCARD);
export_constant(NK_IGNOREELEMENT);
export_constant(NK_IGNOREDEFENSE);
export_constant(NK_IGNOREFLEE);
export_constant(NK_IGNOREDEFCARD);
export_constant(NK_CRITICAL);
/* skill inf */
export_constant(INF_PASSIVE_SKILL);
export_constant(INF_ATTACK_SKILL);
export_constant(INF_GROUND_SKILL);
export_constant(INF_SELF_SKILL);
export_constant(INF_SUPPORT_SKILL);
export_constant(INF_TRAP_SKILL);
/* skill inf2 */
export_constant(INF2_ISQUEST);
export_constant(INF2_ISNPC);
export_constant(INF2_ISWEDDING);
export_constant(INF2_ISSPIRIT);
export_constant(INF2_ISGUILD);
export_constant(INF2_ISSONG);
export_constant(INF2_ISENSEMBLE);
export_constant(INF2_ISTRAP);
export_constant(INF2_TARGETSELF);
export_constant(INF2_NOTARGETSELF);
export_constant(INF2_PARTYONLY);
export_constant(INF2_GUILDONLY);
export_constant(INF2_NOTARGETENEMY);
export_constant(INF2_ISAUTOSHADOWSPELL);
export_constant(INF2_ISCHORUS);
export_constant(INF2_IGNOREBGREDUCTION);
export_constant(INF2_IGNOREGVGREDUCTION);
export_constant(INF2_DISABLENEARNPC);
export_constant(INF2_TARGETTRAP);
export_constant(INF2_IGNORELANDPROTECTOR);
export_constant(INF2_ALLOWWHENHIDDEN);
export_constant(INF2_ALLOWWHENPERFORMING);
export_constant(INF2_TARGETEMPERIUM);
export_constant(INF2_IGNORESTASIS);
export_constant(INF2_IGNOREKAGEHUMI);
export_constant(INF2_ALTERRANGEVULTURE);
export_constant(INF2_ALTERRANGESNAKEEYE);
export_constant(INF2_ALTERRANGESHADOWJUMP);
export_constant(INF2_ALTERRANGERADIUS);
export_constant(INF2_ALTERRANGERESEARCHTRAP);
export_constant(INF2_IGNOREHOVERING);
export_constant(INF2_ALLOWONWARG);
export_constant(INF2_ALLOWONMADO);
export_constant(INF2_TARGETMANHOLE);
export_constant(INF2_TARGETHIDDEN);
export_constant(INF2_INCREASEGLOOMYDAYDAMAGE);
export_constant(INF2_INCREASEDANCEWITHWUGDAMAGE);
export_constant(INF2_IGNOREWUGBITE);
export_constant(INF2_IGNOREAUTOGUARD);
export_constant(INF2_IGNORECICADA);
/* skill no near npc flags */
export_constant(SKILL_NONEAR_WARPPORTAL);
export_constant(SKILL_NONEAR_SHOP);
export_constant(SKILL_NONEAR_NPC);
export_constant(SKILL_NONEAR_TOMB);
/* skill cast flags */
export_constant(SKILL_CAST_IGNOREDEX);
export_constant(SKILL_CAST_IGNORESTATUS);
export_constant(SKILL_CAST_IGNOREITEMBONUS);
/* skill require cost flags */
export_constant(SKILL_REQ_HPCOST);
export_constant(SKILL_REQ_SPCOST);
export_constant(SKILL_REQ_HPRATECOST);
export_constant(SKILL_REQ_SPRATECOST);
export_constant(SKILL_REQ_MAXHPTRIGGER);
export_constant(SKILL_REQ_ZENYCOST);
export_constant(SKILL_REQ_WEAPON);
export_constant(SKILL_REQ_AMMO);
export_constant(SKILL_REQ_STATE);
export_constant(SKILL_REQ_STATUS);
export_constant(SKILL_REQ_SPIRITSPHERECOST);
export_constant(SKILL_REQ_ITEMCOST);
export_constant(SKILL_REQ_EQUIPMENT);
/* skill require state */
export_constant(ST_NONE);
export_constant(ST_HIDDEN);
export_constant(ST_RIDING);
export_constant(ST_FALCON);
export_constant(ST_CART);
export_constant(ST_SHIELD);
export_constant(ST_RECOVER_WEIGHT_RATE);
export_constant(ST_MOVE_ENABLE);
export_constant(ST_WATER);
export_constant(ST_RIDINGDRAGON);
export_constant(ST_WUG);
export_constant(ST_RIDINGWUG);
export_constant(ST_MADO);
export_constant(ST_ELEMENTALSPIRIT);
export_constant(ST_ELEMENTALSPIRIT2);
export_constant(ST_PECO);
/* skill unit flags */
export_constant(UF_NOENEMY);
export_constant(UF_NOREITERATION);
export_constant(UF_NOFOOTSET);
export_constant(UF_NOOVERLAP);
export_constant(UF_PATHCHECK);
export_constant(UF_NOPC);
export_constant(UF_NOMOB);
export_constant(UF_SKILL);
export_constant(UF_DANCE);
export_constant(UF_ENSEMBLE);
export_constant(UF_SONG);
export_constant(UF_DUALMODE);
export_constant(UF_NOKNOCKBACK);
export_constant(UF_RANGEDSINGLEUNIT);
export_constant(UF_CRAZYWEEDIMMUNE);
export_constant(UF_REMOVEDBYFIRERAIN);
export_constant(UF_KNOCKBACKGROUP);
export_constant(UF_HIDDENTRAP);
/* battle check target */
export_constant(BCT_SELF);
export_constant(BCT_ENEMY);
export_constant(BCT_PARTY);
export_constant(BCT_GUILDALLY);
export_constant(BCT_NEUTRAL);
export_constant(BCT_SAMEGUILD);
export_constant(BCT_ALL);
export_constant(BCT_WOS);
export_constant(BCT_GUILD);
export_constant(BCT_NOGUILD);
export_constant(BCT_NOPARTY);
export_constant(BCT_NOENEMY);
export_constant(BCT_ALLY);
export_constant(BCT_FRIEND);
/* skill unit */
export_constant(UNT_SAFETYWALL);
export_constant(UNT_FIREWALL);
export_constant(UNT_WARP_WAITING);
export_constant(UNT_WARP_ACTIVE);
export_constant(UNT_SANCTUARY);
export_constant(UNT_MAGNUS);
export_constant(UNT_PNEUMA);
export_constant(UNT_DUMMYSKILL);
export_constant(UNT_FIREPILLAR_WAITING);
export_constant(UNT_FIREPILLAR_ACTIVE);
export_constant(UNT_USED_TRAPS);
export_constant(UNT_ICEWALL);
export_constant(UNT_QUAGMIRE);
export_constant(UNT_BLASTMINE);
export_constant(UNT_SKIDTRAP);
export_constant(UNT_ANKLESNARE);
export_constant(UNT_VENOMDUST);
export_constant(UNT_LANDMINE);
export_constant(UNT_SHOCKWAVE);
export_constant(UNT_SANDMAN);
export_constant(UNT_FLASHER);
export_constant(UNT_FREEZINGTRAP);
export_constant(UNT_CLAYMORETRAP);
export_constant(UNT_TALKIEBOX);
export_constant(UNT_VOLCANO);
export_constant(UNT_DELUGE);
export_constant(UNT_VIOLENTGALE);
export_constant(UNT_LANDPROTECTOR);
export_constant(UNT_LULLABY);
export_constant(UNT_RICHMANKIM);
export_constant(UNT_ETERNALCHAOS);
export_constant(UNT_DRUMBATTLEFIELD);
export_constant(UNT_RINGNIBELUNGEN);
export_constant(UNT_ROKISWEIL);
export_constant(UNT_INTOABYSS);
export_constant(UNT_SIEGFRIED);
export_constant(UNT_DISSONANCE);
export_constant(UNT_WHISTLE);
export_constant(UNT_ASSASSINCROSS);
export_constant(UNT_POEMBRAGI);
export_constant(UNT_APPLEIDUN);
export_constant(UNT_UGLYDANCE);
export_constant(UNT_HUMMING);
export_constant(UNT_DONTFORGETME);
export_constant(UNT_FORTUNEKISS);
export_constant(UNT_SERVICEFORYOU);
export_constant(UNT_GRAFFITI);
export_constant(UNT_DEMONSTRATION);
export_constant(UNT_CALLFAMILY);
export_constant(UNT_GOSPEL);
export_constant(UNT_BASILICA);
export_constant(UNT_MOONLIT);
export_constant(UNT_FOGWALL);
export_constant(UNT_SPIDERWEB);
export_constant(UNT_GRAVITATION);
export_constant(UNT_HERMODE);
export_constant(UNT_SUITON);
export_constant(UNT_TATAMIGAESHI);
export_constant(UNT_KAEN);
export_constant(UNT_GROUNDDRIFT_WIND);
export_constant(UNT_GROUNDDRIFT_DARK);
export_constant(UNT_GROUNDDRIFT_POISON);
export_constant(UNT_GROUNDDRIFT_WATER);
export_constant(UNT_GROUNDDRIFT_FIRE);
export_constant(UNT_EVILLAND);
export_constant(UNT_EPICLESIS);
export_constant(UNT_EARTHSTRAIN);
export_constant(UNT_MANHOLE);
export_constant(UNT_DIMENSIONDOOR);
export_constant(UNT_CHAOSPANIC);
export_constant(UNT_MAELSTROM);
export_constant(UNT_BLOODYLUST);
export_constant(UNT_FEINTBOMB);
export_constant(UNT_MAGENTATRAP);
export_constant(UNT_COBALTTRAP);
export_constant(UNT_MAIZETRAP);
export_constant(UNT_VERDURETRAP);
export_constant(UNT_FIRINGTRAP);
export_constant(UNT_ICEBOUNDTRAP);
export_constant(UNT_ELECTRICSHOCKER);
export_constant(UNT_CLUSTERBOMB);
export_constant(UNT_REVERBERATION);
export_constant(UNT_SEVERE_RAINSTORM);
export_constant(UNT_FIREWALK);
export_constant(UNT_ELECTRICWALK);
export_constant(UNT_NETHERWORLD);
export_constant(UNT_PSYCHIC_WAVE);
export_constant(UNT_CLOUD_KILL);
export_constant(UNT_POISONSMOKE);
export_constant(UNT_NEUTRALBARRIER);
export_constant(UNT_STEALTHFIELD);
export_constant(UNT_WARMER);
export_constant(UNT_THORNS_TRAP);
export_constant(UNT_WALLOFTHORN);
export_constant(UNT_DEMONIC_FIRE);
export_constant(UNT_FIRE_EXPANSION_SMOKE_POWDER);
export_constant(UNT_FIRE_EXPANSION_TEAR_GAS);
export_constant(UNT_HELLS_PLANT);
export_constant(UNT_VACUUM_EXTREME);
export_constant(UNT_BANDING);
export_constant(UNT_FIRE_MANTLE);
export_constant(UNT_WATER_BARRIER);
export_constant(UNT_ZEPHYR);
export_constant(UNT_POWER_OF_GAIA);
export_constant(UNT_FIRE_INSIGNIA);
export_constant(UNT_WATER_INSIGNIA);
export_constant(UNT_WIND_INSIGNIA);
export_constant(UNT_EARTH_INSIGNIA);
export_constant(UNT_POISON_MIST);
export_constant(UNT_LAVA_SLIDE);
export_constant(UNT_VOLCANIC_ASH);
export_constant(UNT_ZENKAI_WATER);
export_constant(UNT_ZENKAI_LAND);
export_constant(UNT_ZENKAI_FIRE);
export_constant(UNT_ZENKAI_WIND);
export_constant(UNT_MAKIBISHI);
export_constant(UNT_VENOMFOG);
export_constant(UNT_ICEMINE);
export_constant(UNT_FLAMECROSS);
export_constant(UNT_HELLBURNING);
export_constant(UNT_MAGMA_ERUPTION);
export_constant(UNT_KINGS_GRACE);
export_constant(UNT_GLITTERING_GREED);
export_constant(UNT_B_TRAP);
export_constant(UNT_FIRE_RAIN);
export_constant(UNT_CATNIPPOWDER);
export_constant(UNT_NYANGGRASS);
export_constant(UNT_GD_LEADERSHIP);
export_constant(UNT_GD_GLORYWOUNDS);
export_constant(UNT_GD_SOULCOLD);
export_constant(UNT_GD_HAWKEYES);
#undef export_constant
#undef export_constant2
#undef export_parameter

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@
#define SKILL_HPP
#include <array>
#include <bitset>
#include "../common/cbasetypes.hpp"
#include "../common/database.hpp"
@ -18,6 +19,8 @@ enum damage_lv : uint8;
enum sc_type : int16;
enum send_target : uint8;
enum e_damage_type : uint8;
enum e_battle_flag : uint16;
enum e_battle_check_target : uint32;
struct map_session_data;
struct homun_data;
struct skill_unit;
@ -34,81 +37,138 @@ struct status_change_entry;
#define SKILL_NAME_LENGTH 31 /// Max Skill Name length
#define SKILL_DESC_LENGTH 31 /// Max Skill Desc length
extern DBMap* skilldb_name2id;
/// Constants to identify a skill's nk value (damage properties)
/// The NK value applies only to non INF_GROUND_SKILL skills
/// when determining skill castend function to invoke.
enum e_skill_nk : uint16 {
NK_NO_DAMAGE = 0x01,
NK_SPLASH = 0x02|0x04, // 0x4 = splash & split
NK_SPLASHSPLIT = 0x04,
NK_NO_CARDFIX_ATK = 0x08,
NK_NO_ELEFIX = 0x10,
NK_IGNORE_DEF = 0x20,
NK_IGNORE_FLEE = 0x40,
NK_NO_CARDFIX_DEF = 0x80,
NK_CRITICAL = 0x100,
enum e_skill_nk : uint8 {
NK_NODAMAGE = 0,
NK_SPLASH,
NK_SPLASHSPLIT,
NK_IGNOREATKCARD,
NK_IGNOREELEMENT,
NK_IGNOREDEFENSE,
NK_IGNOREFLEE,
NK_IGNOREDEFCARD,
NK_CRITICAL,
NK_MAX,
};
/// Constants to identify the skill's inf value:
enum e_skill_inf {
/// Constants to identify the skill's inf value.
enum e_skill_inf : uint16 {
INF_PASSIVE_SKILL = 0x00, // Used just for skill_db parsing
INF_ATTACK_SKILL = 0x01,
INF_GROUND_SKILL = 0x02,
INF_SELF_SKILL = 0x04, // Skills casted on self where target is automatically chosen
// 0x08 not assigned
INF_SUPPORT_SKILL = 0x10,
INF_TARGET_TRAP = 0x20,
INF_TRAP_SKILL = 0x20,
};
/// A skill with 3 would be no damage + splash: area of effect.
/// Constants to identify a skill's inf2 value.
enum e_skill_inf2 {
INF2_QUEST_SKILL = 0x00001,
INF2_NPC_SKILL = 0x00002, //NPC skills are those that players can't have in their skill tree.
INF2_WEDDING_SKILL = 0x00004,
INF2_SPIRIT_SKILL = 0x00008,
INF2_GUILD_SKILL = 0x00010,
INF2_SONG_DANCE = 0x00020,
INF2_ENSEMBLE_SKILL = 0x00040,
INF2_TRAP = 0x00080,
INF2_TARGET_SELF = 0x00100, //Refers to ground placed skills that will target the caster as well (like Grandcross)
INF2_NO_TARGET_SELF = 0x00200,
INF2_PARTY_ONLY = 0x00400,
INF2_GUILD_ONLY = 0x00800,
INF2_NO_ENEMY = 0x01000,
INF2_AUTOSHADOWSPELL = 0x02000, // Skill that available for SC_AUTOSHADOWSPELL
INF2_CHORUS_SKILL = 0x04000, // Chorus skill
INF2_NO_BG_DMG = 0x08000, // Skill that ignore bg reduction
INF2_NO_GVG_DMG = 0x10000, // Skill that ignore gvg reduction
INF2_NO_NEARNPC = 0x20000, // disable to cast skill if near with NPC [Cydh]
INF2_HIT_TRAP = 0x40000, // can hit trap-type skill (INF2_TRAP) [Cydh]
/// Constants to identify the skill's inf2 value.
enum e_skill_inf2 : uint8 {
INF2_ISQUEST = 0,
INF2_ISNPC, //NPC skills are those that players can't have in their skill tree.
INF2_ISWEDDING,
INF2_ISSPIRIT,
INF2_ISGUILD,
INF2_ISSONG,
INF2_ISENSEMBLE,
INF2_ISTRAP,
INF2_TARGETSELF, //Refers to ground placed skills that will target the caster as well (like Grandcross)
INF2_NOTARGETSELF,
INF2_PARTYONLY,
INF2_GUILDONLY,
INF2_NOTARGETENEMY,
INF2_ISAUTOSHADOWSPELL, // Skill that available for SC_AUTOSHADOWSPELL
INF2_ISCHORUS, // Chorus skill
INF2_IGNOREBGREDUCTION, // Skill that ignore bg reduction
INF2_IGNOREGVGREDUCTION, // Skill that ignore gvg reduction
INF2_DISABLENEARNPC, // disable to cast skill if near with NPC [Cydh]
INF2_TARGETTRAP, // can hit trap-type skill (INF2_ISTRAP) [Cydh]
INF2_IGNORELANDPROTECTOR, // Skill that can ignore Land Protector
INF2_ALLOWWHENHIDDEN, // Skill that can be use in hiding
INF2_ALLOWWHENPERFORMING, // Skill that can be use while in dancing state
INF2_TARGETEMPERIUM, // Skill that could hit emperium
INF2_IGNORESTASIS, // Skill that can ignore SC_STASIS
INF2_IGNOREKAGEHUMI, // Skill blocked by kagehumi
INF2_ALTERRANGEVULTURE, // Skill range affected by AC_VULTURE
INF2_ALTERRANGESNAKEEYE, // Skill range affected by GS_SNAKEEYE
INF2_ALTERRANGESHADOWJUMP, // Skill range affected by NJ_SHADOWJUMP
INF2_ALTERRANGERADIUS, // Skill range affected by WL_RADIUS
INF2_ALTERRANGERESEARCHTRAP, // Skill range affected by RA_RESEARCHTRAP
INF2_IGNOREHOVERING, // Skill that does not affect user that has SC_HOVERING active
INF2_ALLOWONWARG, // Skill that can be use while riding warg
INF2_ALLOWONMADO, // Skill that can be used while on Madogear
INF2_TARGETMANHOLE, // Skill that can be used to target while under SC__MANHOLE effect
INF2_TARGETHIDDEN, // Skill that affects hidden targets
INF2_INCREASEGLOOMYDAYDAMAGE, // Skill that affects SC_GLOOMYDAY_SK
INF2_INCREASEDANCEWITHWUGDAMAGE, // Skill that is affected by SC_DANCEWITHWUG
INF2_IGNOREWUGBITE, // Skill blocked by RA_WUGBITE
INF2_IGNOREAUTOGUARD , // Skill is not blocked by SC_AUTOGUARD (physical-skill only)
INF2_IGNORECICADA, // Skill is not blocked by SC_UTSUSEMI or SC_BUNSINJYUTSU (physical-skill only)
INF2_MAX,
};
/// Skill info type 3
enum e_skill_inf3 {
INF3_NOLP = 0x000001, // Skill that can ignore Land Protector
INF3_FREE = 0x000002, // Free
INF3_USABLE_HIDING = 0x000004, // Skill that can be use in hiding
INF3_USABLE_DANCE = 0x000008, // Skill that can be use while in dancing state
INF3_HIT_EMP = 0x000010, // Skill that could hit emperium
INF3_STASIS_BL = 0x000020, // Skill that can ignore SC_STASIS
INF3_KAGEHUMI_BL = 0x000040, // Skill blocked by kagehumi
INF3_EFF_VULTURE = 0x000080, // Skill range affected by AC_VULTURE
INF3_EFF_SNAKEEYE = 0x000100, // Skill range affected by GS_SNAKEEYE
INF3_EFF_SHADOWJUMP = 0x000200, // Skill range affected by NJ_SHADOWJUMP
INF3_EFF_RADIUS = 0x000400, // Skill range affected by WL_RADIUS
INF3_EFF_RESEARCHTRAP = 0x000800, // Skill range affected by RA_RESEARCHTRAP
INF3_NO_EFF_HOVERING = 0x001000, // Skill that does not affect user that has SC_HOVERING active
INF3_USABLE_WARG = 0x002000, // Skill that can be use while riding warg
INF3_USABLE_MADO = 0x004000, // Skill that can be used while on Madogear
INF3_USABLE_MANHOLE = 0x008000, // Skill that can be used to target while under SC__MANHOLE effect
INF3_HIT_HIDING = 0x010000, // Skill that affects hidden targets
INF3_SC_GLOOMYDAY_SK = 0x020000, // Skill that affects SC_GLOOMYDAY_SK
INF3_SC_DANCEWITHWUG = 0x040000, // Skill that is affected by SC_DANCEWITHWUG
INF3_BITE_BLOCK = 0x080000, // Skill blocked by RA_WUGBITE
INF3_NO_EFF_AUTOGUARD = 0x100000, // Skill is not blocked by SC_AUTOGUARD (physical-skill only)
INF3_NO_EFF_CICADA = 0x200000, // Skill is not blocked by SC_UTSUSEMI or SC_BUNSINJYUTSU (physical-skill only)
/// Constants for skill requirements
enum e_skill_require : uint16 {
SKILL_REQ_HPCOST = 0x1,
SKILL_REQ_SPCOST = 0x2,
SKILL_REQ_HPRATECOST = 0x4,
SKILL_REQ_SPRATECOST = 0x8,
SKILL_REQ_MAXHPTRIGGER = 0x10,
SKILL_REQ_ZENYCOST = 0x20,
SKILL_REQ_WEAPON = 0x40,
SKILL_REQ_AMMO = 0x80,
SKILL_REQ_STATE = 0x100,
SKILL_REQ_STATUS = 0x200,
SKILL_REQ_SPIRITSPHERECOST = 0x400,
SKILL_REQ_ITEMCOST = 0x800,
SKILL_REQ_EQUIPMENT = 0x1000,
};
/// Constants for skill cast near NPC.
enum e_skill_nonear_npc : uint8 {
SKILL_NONEAR_WARPPORTAL = 0x1,
SKILL_NONEAR_SHOP = 0x2,
SKILL_NONEAR_NPC = 0x4,
SKILL_NONEAR_TOMB = 0x8,
};
/// Constants for skill cast adjustments.
enum e_skill_cast_flags : uint8 {
SKILL_CAST_IGNOREDEX = 0x1,
SKILL_CAST_IGNORESTATUS = 0x2,
SKILL_CAST_IGNOREITEMBONUS = 0x4,
};
/// Constants for skill copyable options.
enum e_skill_copyable_option : uint8 {
SKILL_COPY_PLAGIARISM = 0x1,
SKILL_COPY_REPRODUCE = 0x2,
};
/// Constants for skill unit flags.
enum e_skill_unit_flag : uint8 {
UF_NONE = 0,
UF_NOENEMY, // If 'defunit_not_enemy' is set, the target is changed to 'friend'
UF_NOREITERATION, // Spell cannot be stacked
UF_NOFOOTSET, // Spell cannot be cast near/on targets
UF_NOOVERLAP, // Spell effects do not overlap
UF_PATHCHECK, // Only cells with a shootable path will be placed
UF_NOPC, // May not target players
UF_NOMOB, // May not target mobs
UF_SKILL, // May target skills
UF_DANCE, // Dance
UF_ENSEMBLE, // Duet
UF_SONG, // Song
UF_DUALMODE, // Spells should trigger both ontimer and onplace/onout/onleft effects.
UF_NOKNOCKBACK, // Skill unit cannot be knocked back
UF_RANGEDSINGLEUNIT, // hack for ranged layout, only display center
UF_CRAZYWEEDIMMUNE, // Immune to Crazy Weed removal
UF_REMOVEDBYFIRERAIN, // removed by Fire Rain
UF_KNOCKBACKGROUP, // knockback skill unit with its group instead of single unit
UF_HIDDENTRAP, // Hidden trap [Cydh]
UF_MAX,
};
/// Walk intervals at which chase-skills are attempted to be triggered.
@ -132,112 +192,124 @@ enum e_skill_display {
#define MAX_SKILL_EQUIP_REQUIRE 10 /// Maximum required equipped item
/// Single skill requirement. !TODO: Cleanup the variable types
struct skill_condition {
int32 hp; ///< HP cost
int32 mhp; ///< Max HP to trigger
int32 sp; /// SP cost
int16 hp_rate; /// HP cost (%)
int16 sp_rate; /// SP cost (%)
uint32 zeny; /// Zeny cost
uint32 weapon; /// Weapon type. Combined bitmask of enum weapon_type (1<<weapon)
uint16 ammo; /// Ammo type. Combine bitmask of enum ammo_type (1<<ammo)
int8 ammo_qty; /// Amount of ammo
uint8 state; /// State/condition. @see enum e_require_state
int8 spiritball; /// Spiritball cost
uint16 itemid[MAX_SKILL_ITEM_REQUIRE]; /// Required item
uint16 amount[MAX_SKILL_ITEM_REQUIRE]; /// Amount of item
uint16 *eqItem; /// List of equipped item
enum sc_type *status; /// List of Status required (SC)
uint8 status_count, /// Count of SC
eqItem_count; /// Count of equipped item
struct s_skill_condition {
int32 hp; ///< HP cost
int32 mhp; ///< Max HP to trigger
int32 sp; /// SP cost
int32 hp_rate; /// HP cost (%)
int32 sp_rate; /// SP cost (%)
int32 zeny; /// Zeny cost
int32 weapon; /// Weapon type. Combined bitmask of enum weapon_type (1<<weapon)
int32 ammo; /// Ammo type. Combine bitmask of enum ammo_type (1<<ammo)
int32 ammo_qty; /// Amount of ammo
int32 state; /// State/condition. @see enum e_require_state
int32 spiritball; /// Spiritball cost
int32 itemid[MAX_SKILL_ITEM_REQUIRE]; /// Required item
int32 amount[MAX_SKILL_ITEM_REQUIRE]; /// Amount of item
std::vector<int32> eqItem; /// List of equipped item
std::vector<sc_type> status; /// List of Status required (SC)
};
/// Skill requirement structure. !TODO: Cleanup the variable types that use array [MAX_SKILL_LEVEL]
/// Skill requirement structure.
struct s_skill_require {
int hp[MAX_SKILL_LEVEL]; ///< HP cost
int mhp[MAX_SKILL_LEVEL]; ///< Max HP to trigger
int sp[MAX_SKILL_LEVEL]; /// SP cost
int hp_rate[MAX_SKILL_LEVEL]; /// HP cost (%)
int sp_rate[MAX_SKILL_LEVEL]; /// SP cost (%)
int zeny[MAX_SKILL_LEVEL]; /// Zeny cost
uint32 weapon; /// Weapon type. Combined bitmask of enum weapon_type (1<<weapon)
uint16 ammo; /// Ammo type. Combine bitmask of enum ammo_type (1<<ammo)
int ammo_qty[MAX_SKILL_LEVEL]; /// Amount of ammo
uint8 state; /// State/condition. @see enum e_require_state
int spiritball[MAX_SKILL_LEVEL]; /// Spiritball cost
uint16 itemid[MAX_SKILL_ITEM_REQUIRE]; /// Required item
uint16 amount[MAX_SKILL_ITEM_REQUIRE]; /// Amount of item
uint16 *eqItem; /// List of equipped item
enum sc_type *status; /// List of Status required (SC)
uint8 status_count, /// Count of SC
eqItem_count; /// Count of equipped item
int32 hp[MAX_SKILL_LEVEL]; ///< HP cost
int32 mhp[MAX_SKILL_LEVEL]; ///< Max HP to trigger
int32 sp[MAX_SKILL_LEVEL]; /// SP cost
int32 hp_rate[MAX_SKILL_LEVEL]; /// HP cost (%)
int32 sp_rate[MAX_SKILL_LEVEL]; /// SP cost (%)
int32 zeny[MAX_SKILL_LEVEL]; /// Zeny cost
int32 weapon; /// Weapon type. Combined bitmask of enum weapon_type (1<<weapon)
int32 ammo; /// Ammo type. Combine bitmask of enum ammo_type (1<<ammo)
int32 ammo_qty[MAX_SKILL_LEVEL]; /// Amount of ammo
int32 state; /// State/condition. @see enum e_require_state
int32 spiritball[MAX_SKILL_LEVEL]; /// Spiritball cost
int32 itemid[MAX_SKILL_ITEM_REQUIRE]; /// Required item
int32 amount[MAX_SKILL_ITEM_REQUIRE]; /// Amount of item
std::vector<int32> eqItem; /// List of equipped item
std::vector<sc_type> status; /// List of Status required (SC)
};
/// Database skills. !TODO: Cleanup the variable types that use array [MAX_SKILL_LEVEL]
struct s_skill_db {
// skill_db.txt
uint16 nameid; ///< Skill ID
char name[SKILL_NAME_LENGTH]; ///< AEGIS_Name
char desc[SKILL_DESC_LENGTH]; ///< English Name
int range[MAX_SKILL_LEVEL]; ///< Range
int8 hit; ///< Hit type
uint8 inf; ///< Inf: 0- passive, 1- enemy, 2- place, 4- self, 16- friend, 32- trap
int element[MAX_SKILL_LEVEL]; ///< Element
uint16 nk; ///< Damage properties
int splash[MAX_SKILL_LEVEL]; ///< Splash effect
uint8 max; ///< Max level
int num[MAX_SKILL_LEVEL]; ///< Number of hit
bool castcancel; ///< Cancel cast when being hit
int16 cast_def_rate; ///< Def rate during cast a skill
uint16 skill_type; ///< Skill type
int blewcount[MAX_SKILL_LEVEL]; ///< Blew count
uint32 inf2; ///< Skill flags @see enum e_skill_inf2
uint32 inf3; ///< Skill flags @see enum e_skill_inf3
int maxcount[MAX_SKILL_LEVEL]; ///< Max number skill can be casted in same map
/// Skill Copyable structure.
struct s_skill_copyable { // [Cydh]
uint8 option;
uint16 req_opt;
};
// skill_castnodex_db.txt
uint8 castnodex; ///< 1 - Not affected by dex, 2 - Not affected by SC, 4 - Not affected by item
uint8 delaynodex; ///< 1 - Not affected by dex, 2 - Not affected by SC, 4 - Not affected by item
/// Skill Reading Spellbook structure.
struct s_skill_spellbook {
uint16 nameid, point;
};
/// Database skills
struct s_skill_db {
uint16 nameid; ///< Skill ID
char name[SKILL_NAME_LENGTH]; ///< AEGIS_Name
char desc[SKILL_DESC_LENGTH]; ///< English Name
int32 range[MAX_SKILL_LEVEL]; ///< Range
e_damage_type hit; ///< Hit type
uint16 inf; ///< Inf: 0- passive, 1- enemy, 2- place, 4- self, 16- friend, 32- trap
e_element element[MAX_SKILL_LEVEL]; ///< Element
std::bitset<NK_MAX> nk; ///< Damage properties
int32 splash[MAX_SKILL_LEVEL]; ///< Splash effect
uint16 max; ///< Max level
int32 num[MAX_SKILL_LEVEL]; ///< Number of hit
bool castcancel; ///< Cancel cast when being hit
uint16 cast_def_rate; ///< Def rate during cast a skill
e_battle_flag skill_type; ///< Skill type
int32 blewcount[MAX_SKILL_LEVEL]; ///< Blew count
std::bitset<INF2_MAX> inf2; ///< Skill flags @see enum e_skill_inf2
int32 maxcount[MAX_SKILL_LEVEL]; ///< Max number skill can be casted in same map
uint8 castnodex; ///< 1 - Not affected by dex, 2 - Not affected by SC, 4 - Not affected by item
uint8 delaynodex; ///< 1 - Not affected by dex, 2 - Not affected by SC, 4 - Not affected by item
// skill_nocast_db.txt
uint32 nocast; ///< Skill cannot be casted at this zone
uint32 nocast; ///< Skill cannot be casted at this zone
// skill_unit_db.txt
uint16 unit_id[2]; ///< Unit ID. @see enum s_skill_unit_id
int unit_layout_type[MAX_SKILL_LEVEL]; ///< Layout type. -1 is special layout, others are square with lenght*width: (val*2+1)^2
int unit_range[MAX_SKILL_LEVEL]; ///< Unit cell effect range
int16 unit_interval; ///< Interval
uint32 unit_target; ///< Unit target. @see enum e_battle_check_target
uint32 unit_flag; ///< Unit flags. @see enum e_skill_unit_flag
uint16 unit_id; ///< Unit ID. @see enum e_skill_unit_id
uint16 unit_id2; ///< Alternate unit ID. @see enum e_skill_unit_id
int32 unit_layout_type[MAX_SKILL_LEVEL]; ///< Layout type. -1 is special layout, others are square with lenght*width: (val*2+1)^2
int32 unit_range[MAX_SKILL_LEVEL]; ///< Unit cell effect range
int16 unit_interval; ///< Interval
int32 unit_target; ///< Unit target.
std::bitset<UF_MAX> unit_flag; ///< Unit flags.
// skill_cast_db.txt
int cast[MAX_SKILL_LEVEL]; ///< Variable casttime
int32 cast[MAX_SKILL_LEVEL]; ///< Variable casttime
int32 delay[MAX_SKILL_LEVEL]; ///< Global delay (delay before reusing all skills)
int32 walkdelay[MAX_SKILL_LEVEL]; ///< Delay to walk after casting
int32 upkeep_time[MAX_SKILL_LEVEL]; ///< Duration
int32 upkeep_time2[MAX_SKILL_LEVEL]; ///< Duration2
int32 cooldown[MAX_SKILL_LEVEL]; ///< Cooldown (delay before reusing same skill)
#ifdef RENEWAL_CAST
int fixed_cast[MAX_SKILL_LEVEL]; ///< If -1 means 20% than 'cast'
int32 fixed_cast[MAX_SKILL_LEVEL]; ///< If -1 means 20% than 'cast'
#endif
int walkdelay[MAX_SKILL_LEVEL]; ///< Delay to walk after casting
int delay[MAX_SKILL_LEVEL]; ///< Global delay (delay before reusing all skills)
int cooldown[MAX_SKILL_LEVEL]; ///< Cooldown (delay before reusing same skill)
int upkeep_time[MAX_SKILL_LEVEL]; ///< Duration
int upkeep_time2[MAX_SKILL_LEVEL]; ///< Duration2
// skill_require_db.txt
struct s_skill_require require; ///< Skill requirement
struct s_skill_require require; ///< Skill requirement
// skill_nonearnpc_db.txt
uint8 unit_nonearnpc_range; //additional range for UF_NONEARNPC or INF2_NO_NEARNPC [Cydh]
uint8 unit_nonearnpc_type; //type of NPC [Cydh]
uint16 unit_nonearnpc_range; ///< Additional range for UF_NONEARNPC or INF2_DISABLENEARNPC [Cydh]
uint16 unit_nonearnpc_type; ///< Type of NPC [Cydh]
// skill_damage_db.txt
struct s_skill_damage damage;
struct s_skill_copyable copyable;
// skill_copyable_db.txt
struct s_copyable { // [Cydh]
uint8 option;
uint16 joballowed, req_opt;
} copyable;
int32 abra_probability[MAX_SKILL_LEVEL];
s_skill_spellbook reading_spellbook;
uint16 improvisedsong_rate;
};
extern struct s_skill_db **skill_db;
class SkillDatabase : public TypesafeCachedYamlDatabase <uint16, s_skill_db> {
public:
SkillDatabase() : TypesafeCachedYamlDatabase("SKILL_DB", 1) {
}
const std::string getDefaultLocation();
template<typename T, size_t S> bool parseNode(std::string nodeName, std::string subNodeName, YAML::Node node, T (&arr)[S]);
uint64 parseBodyNode(const YAML::Node &node);
void clear();
};
extern SkillDatabase skill_db;
#define MAX_SQUARE_LAYOUT 7 // 15*15 unit placement maximum
#define MAX_SKILL_UNIT_LAYOUT (48+MAX_SQUARE_LAYOUT) // 47 special ones + the square ones
@ -315,28 +387,6 @@ struct skill_unit_group_tickset {
int id;
};
enum e_skill_unit_flag {
UF_DEFNOTENEMY = 0x00001, // If 'defunit_not_enemy' is set, the target is changed to 'friend'
UF_NOREITERATION = 0x00002, // Spell cannot be stacked
UF_NOFOOTSET = 0x00004, // Spell cannot be cast near/on targets
UF_NOOVERLAP = 0x00008, // Spell effects do not overlap
UF_PATHCHECK = 0x00010, // Only cells with a shootable path will be placed
UF_NOPC = 0x00020, // May not target players
UF_NOMOB = 0x00040, // May not target mobs
UF_SKILL = 0x00080, // May target skills
UF_DANCE = 0x00100, // Dance
UF_ENSEMBLE = 0x00200, // Duet
UF_SONG = 0x00400, // Song
UF_DUALMODE = 0x00800, // Spells should trigger both ontimer and onplace/onout/onleft effects.
UF_NOKNOCKBACK = 0x01000, // Skill unit cannot be knocked back
UF_RANGEDSINGLEUNIT = 0x02000, // hack for ranged layout, only display center
UF_CRAZYWEED_IMMUNE = 0x04000, // Immune to Crazy Weed removal
UF_REM_FIRERAIN = 0x08000, // removed by Fire Rain
UF_KNOCKBACK_GROUP = 0x10000, // knockback skill unit with its group instead of single unit
UF_HIDDEN_TRAP = 0x20000, // Hidden trap [Cydh]
};
/// Enum for skill_blown
enum e_skill_blown {
BLOWN_NONE = 0x00,
@ -410,14 +460,12 @@ const char* skill_get_desc( uint16 skill_id ); // [Skotlex]
int skill_tree_get_max( uint16 skill_id, int b_class ); // Celest
// Accessor to the skills database
int skill_get_index_( uint16 skill_id, bool silent, const char *func, const char *file, int line );
uint16 skill_get_index_(uint16 skill_id, bool silent, const char *func, const char *file, int line);
#define skill_get_index(skill_id) skill_get_index_((skill_id), false, __FUNCTION__, __FILE__, __LINE__) /// Get skill index from skill_id (common usage on source)
#define skill_get_index2(skill_id) skill_get_index_((skill_id), true, __FUNCTION__, __FILE__, __LINE__) /// Get skill index from skill_id (used when reading skill_db files)
int skill_get_type( uint16 skill_id );
enum e_damage_type skill_get_hit( uint16 skill_id );
e_damage_type skill_get_hit( uint16 skill_id );
int skill_get_inf( uint16 skill_id );
int skill_get_ele( uint16 skill_id , uint16 skill_lv );
int skill_get_nk( uint16 skill_id );
int skill_get_max( uint16 skill_id );
int skill_get_range( uint16 skill_id , uint16 skill_lv );
int skill_get_range2(struct block_list *bl, uint16 skill_id, uint16 skill_lv, bool isServer);
@ -431,15 +479,19 @@ int skill_get_time2( uint16 skill_id ,uint16 skill_lv );
int skill_get_castnodex( uint16 skill_id );
int skill_get_castdef( uint16 skill_id );
int skill_get_nocast( uint16 skill_id );
int skill_get_unit_id(uint16 skill_id,int flag);
int skill_get_inf2( uint16 skill_id );
int skill_get_unit_id( uint16 skill_id );
int skill_get_unit_id2( uint16 skill_id );
int skill_get_castcancel( uint16 skill_id );
int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv );
int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv );
int skill_get_unit_flag( uint16 skill_id );
int skill_get_cooldown( uint16 skill_id, uint16 skill_lv );
int skill_get_unit_target( uint16 skill_id );
int skill_get_inf3( uint16 skill_id );
#define skill_get_nk(skill_id, nk) skill_get_nk_(skill_id, { nk })
bool skill_get_nk_(uint16 skill_id, std::vector<e_skill_nk> nk);
#define skill_get_inf2(skill_id, inf2) skill_get_inf2_(skill_id, { inf2 })
bool skill_get_inf2_(uint16 skill_id, std::vector<e_skill_inf2> inf2);
#define skill_get_unit_flag(skill_id, unit) skill_get_unit_flag_(skill_id, { unit })
bool skill_get_unit_flag_(uint16 skill_id, std::vector<e_skill_unit_flag> unit);
// Accessor for skill requirements
int skill_get_hp( uint16 skill_id ,uint16 skill_lv );
int skill_get_mhp( uint16 skill_id ,uint16 skill_lv );
@ -452,15 +504,11 @@ int skill_get_weapontype( uint16 skill_id );
int skill_get_ammotype( uint16 skill_id );
int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv );
int skill_get_state(uint16 skill_id);
//int skill_get_status( uint16 skill_id, int idx );
int skill_get_status_count( uint16 skill_id );
int skill_get_spiritball( uint16 skill_id, uint16 skill_lv );
int skill_get_itemid( uint16 skill_id, int idx );
int skill_get_itemqty( uint16 skill_id, int idx );
unsigned short skill_dummy2skill_id(unsigned short skill_id);
int skill_name2id(const char* name);
uint16 skill_idx2id(uint16 idx);
uint16 skill_name2id(const char* name);
uint16 SKILL_MAX_DB(void);
@ -508,7 +556,7 @@ bool skill_check_condition_castbegin(struct map_session_data *sd, uint16 skill_i
bool skill_check_condition_castend(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
int skill_check_condition_char_sub (struct block_list *bl, va_list ap);
void skill_consume_requirement(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type);
struct skill_condition skill_get_requirement(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
struct s_skill_condition skill_get_requirement(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
int skill_disable_check(struct status_change *sc, uint16 skill_id);
bool skill_pos_maxcount_check(struct block_list *src, int16 x, int16 y, uint16 skill_id, uint16 skill_lv, enum bl_type type, bool display_failure);
@ -565,14 +613,14 @@ int64 skill_attack( int attack_type, struct block_list* src, struct block_list *
void skill_reload(void);
/// List of State Requirements
enum e_require_state {
enum e_require_state : uint8 {
ST_NONE,
ST_HIDDEN,
ST_RIDING,
ST_FALCON,
ST_CART,
ST_SHIELD,
ST_RECOV_WEIGHT_RATE,
ST_RECOVER_WEIGHT_RATE,
ST_MOVE_ENABLE,
ST_WATER,
ST_RIDINGDRAGON,
@ -2019,7 +2067,7 @@ enum e_skill {
};
/// The client view ids for land skills.
enum s_skill_unit_id {
enum e_skill_unit_id : uint16 {
UNT_SAFETYWALL = 0x7e,
UNT_FIREWALL,
UNT_WARP_WAITING,

View File

@ -2184,17 +2184,20 @@ bool status_check_skilluse(struct block_list *src, struct block_list *target, ui
}
if (sc->data[SC_DANCING] && flag!=2) {
std::shared_ptr<s_skill_db> skill = skill_db.find(skill_id);
if (!skill)
return false;
if (src->type == BL_PC && ((skill_id >= WA_SWING_DANCE && skill_id <= WM_UNLIMITED_HUMMING_VOICE ) ||
skill_id == WM_FRIGG_SONG))
{ // Lvl 5 Lesson or higher allow you use 3rd job skills while dancing.
if( pc_checkskill((TBL_PC*)src,WM_LESSON) < 5 )
return false;
} else if(sc->data[SC_LONGING]) { // Allow everything except dancing/re-dancing. [Skotlex]
if (skill_id == BD_ENCORE ||
skill_get_inf2(skill_id)&(INF2_SONG_DANCE|INF2_ENSEMBLE_SKILL)
)
if (skill_id == BD_ENCORE || skill->inf2[INF2_ISSONG] || skill->inf2[INF2_ISENSEMBLE])
return false;
} else if(!(skill_get_inf3(skill_id)&INF3_USABLE_DANCE)) // Skills that can be used in dancing state
} else if(!skill->inf2[INF2_ALLOWWHENPERFORMING]) // Skills that can be used in dancing state
return false;
if ((sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE && skill_id == BD_ADAPTATION)
return false; // Can't amp out of Wand of Hermode :/ [Skotlex]
@ -2226,7 +2229,10 @@ bool status_check_skilluse(struct block_list *src, struct block_list *target, ui
}
if (sc->option) {
if ((sc->option&OPTION_HIDE) && src->type == BL_PC && (!skill_id || !(skill_get_inf3(skill_id)&INF3_USABLE_HIDING))) {
if (skill_id == 0) // Normal attack
return false;
if ((sc->option&OPTION_HIDE) && src->type == BL_PC && !skill_get_inf2(skill_id, INF2_ALLOWWHENHIDDEN)) {
// Non players can use all skills while hidden.
return false;
}
@ -2254,7 +2260,7 @@ bool status_check_skilluse(struct block_list *src, struct block_list *target, ui
return false;
if(skill_id == PR_LEXAETERNA && (tsc->data[SC_FREEZE] || (tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE)))
return false;
if (tsc->data[SC__MANHOLE] && !(skill_get_inf3(skill_id)&INF3_USABLE_MANHOLE))
if (tsc->data[SC__MANHOLE] && !skill_get_inf2(skill_id, INF2_TARGETMANHOLE))
return false;
}
@ -2262,7 +2268,7 @@ bool status_check_skilluse(struct block_list *src, struct block_list *target, ui
hide_flag = flag?OPTION_HIDE:(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK);
// Skill that can hit hidden target
if( skill_get_inf3(skill_id)&INF3_HIT_HIDING )
if( skill_get_inf2(skill_id, INF2_TARGETHIDDEN) )
hide_flag &= ~OPTION_HIDE;
switch( target->type ) {
@ -12628,11 +12634,14 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
if (sce->val3 || status_isdead(bl) || !(caster = map_id2sd(sce->val2)))
break;
if (!itemdb_exists(skill_get_itemid(RL_H_MINE,0)))
std::shared_ptr<s_skill_db> skill = skill_db.find(RL_H_MINE);
if (!itemdb_exists(skill->require.itemid[0]))
break;
memset(&it, 0, sizeof(it));
it.nameid = skill_get_itemid(RL_H_MINE,0);
it.amount = max(skill_get_itemqty(RL_H_MINE,0),1);
it.nameid = skill->require.itemid[0];
it.amount = max(skill->require.amount[0],1);
it.identify = 1;
map_addflooritem(&it, it.amount, bl->m,bl->x, bl->y, caster->status.char_id, 0, 0, 4, 0);
}
@ -13899,7 +13908,7 @@ int status_change_timer_sub(struct block_list* bl, va_list ap)
if(bl->type == BL_SKILL)
su = (struct skill_unit *)bl;
if (skill_attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,sce->val1,tick,0x1000000)
&& (!su || !su->group || !(skill_get_inf2(su->group->skill_id)&INF2_TRAP))) { // The hit is not counted if it's against a trap
&& (!su || !su->group || !skill_get_inf2(su->group->skill_id, INF2_ISTRAP))) { // The hit is not counted if it's against a trap
sce->val2 = 0; // This signals it to end.
} else if((bl->type&BL_SKILL) && sce->val4%2 == 0) {
//Remove trap immunity temporarily so it triggers if you still stand on it

View File

@ -1087,7 +1087,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, enum e_skill_bl
map_foreachinmovearea(clif_outsight, bl, AREA_SIZE, dx, dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl);
if(su) {
if (su->group && skill_get_unit_flag(su->group->skill_id)&UF_KNOCKBACK_GROUP)
if (su->group && skill_get_unit_flag(su->group->skill_id, UF_KNOCKBACKGROUP))
skill_unit_move_unit_group(su->group, bl->m, dx, dy);
else
skill_unit_move_unit(bl, nx, ny);
@ -1159,7 +1159,7 @@ enum e_unit_blown unit_blown_immune(struct block_list* bl, uint8 flag)
case BL_SKILL: {
struct skill_unit* su = (struct skill_unit *)bl;
// Trap cannot be knocked back
if (su && su->group && skill_get_unit_flag(su->group->skill_id)&UF_NOKNOCKBACK)
if (su && su->group && skill_get_unit_flag(su->group->skill_id, UF_NOKNOCKBACK))
return UB_TARGET_TRAP;
}
break;
@ -1375,7 +1375,7 @@ int unit_can_move(struct block_list *bl) {
if (!ud)
return 0;
if (ud->skilltimer != INVALID_TIMER && ud->skill_id != LG_EXEEDBREAK && (!sd || !pc_checkskill(sd, SA_FREECAST) || skill_get_inf2(ud->skill_id)&INF2_GUILD_SKILL))
if (ud->skilltimer != INVALID_TIMER && ud->skill_id != LG_EXEEDBREAK && (!sd || !pc_checkskill(sd, SA_FREECAST) || skill_get_inf2(ud->skill_id, INF2_ISGUILD)))
return 0; // Prevent moving while casting
if (DIFF_TICK(ud->canmove_tick, gettick()) > 0)
@ -1515,8 +1515,6 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
struct block_list * target = NULL;
t_tick tick = gettick();
int combo = 0, range;
uint8 inf = 0;
uint32 inf2 = 0;
nullpo_ret(src);
@ -1537,8 +1535,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if (sc && !sc->count)
sc = NULL; // Unneeded
inf = skill_get_inf(skill_id);
inf2 = skill_get_inf2(skill_id);
int inf = skill_get_inf(skill_id);
std::shared_ptr<s_skill_db> skill = skill_db.find(skill_id);
// temp: used to signal combo-skills right now.
if (sc && sc->data[SC_COMBO] &&
@ -1552,13 +1550,13 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
else if (target_id == src->id || ud->target > 0)
target_id = ud->target;
if (inf&INF_SELF_SKILL && skill_get_nk(skill_id)&NK_NO_DAMAGE)// exploit fix
if (inf&INF_SELF_SKILL && skill->nk[NK_NODAMAGE])// exploit fix
target_id = src->id;
combo = 1;
} else if ( target_id == src->id &&
inf&INF_SELF_SKILL &&
(inf2&INF2_NO_TARGET_SELF ||
(skill->inf2[INF2_NOTARGETSELF] ||
(skill_id == RL_QD_SHOT && sc && sc->data[SC_QD_SHOT_READY])) ) {
target_id = ud->target; // Auto-select target. [Skotlex]
combo = 1;
@ -1632,14 +1630,14 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if(ud->skilltimer != INVALID_TIMER && skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST)
return 0;
if(inf2&INF2_NO_TARGET_SELF && src->id == target_id)
if(skill->inf2[INF2_NOTARGETSELF] && src->id == target_id)
return 0;
if(!status_check_skilluse(src, target, skill_id, 0))
return 0;
// Fail if the targetted skill is near NPC [Cydh]
if(inf2&INF2_NO_NEARNPC && skill_isNotOk_npcRange(src,skill_id,skill_lv,target->x,target->y)) {
if(skill->inf2[INF2_DISABLENEARNPC] && skill_isNotOk_npcRange(src,skill_id,skill_lv,target->x,target->y)) {
if (sd)
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
@ -2016,7 +2014,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
return 0;
// Fail if the targetted skill is near NPC [Cydh]
if(skill_get_inf2(skill_id)&INF2_NO_NEARNPC && skill_isNotOk_npcRange(src,skill_id,skill_lv,skill_x,skill_y)) {
if(skill_get_inf2(skill_id, INF2_DISABLENEARNPC) && skill_isNotOk_npcRange(src,skill_id,skill_lv,skill_x,skill_y)) {
if (sd)
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);

File diff suppressed because it is too large Load Diff