Converted elemental_db to YAML (#6102)

* Converts the Elemental Summons Tables file into YAML.
* Includes CSV2YAML converter.

Thanks to @Lemongrass3110, @aleos89, @secretdataz !
This commit is contained in:
Atemo 2021-11-26 00:53:35 +01:00 committed by GitHub
parent ae1135dd2b
commit a205287307
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 1067 additions and 383 deletions

View File

@ -1,25 +0,0 @@
// Elemental Summons Database
//
// Structure of Database:
// ID,Sprite_Name,Name,LV,HP,SP,Range1,ATK1,ATK2,DEF,MDEF,STR,AGI,VIT,INT,DEX,LUK,Range2,Range3,Scale,Race,Element,Speed,aDelay,aMotion,dMotion
//
// Notes:
// Summoned Elementals STATs are affected by the Casters Base Level and STATs.
// In other words, all values specified will be added to (and will not override) the calculated STATs of the summoned elemental.
// Monster Elementals
2114,EL_AGNI_S,Agni,100,0,1,1,0,0,0,0,0,0,0,0,0,0,5,12,0,0,83,200,504,1020,360
2115,EL_AGNI_M,Agni,100,0,1,1,0,0,0,0,0,0,0,0,0,0,5,12,1,0,83,200,504,1020,360
2116,EL_AGNI_L,Agni,100,0,1,1,0,0,0,0,0,0,0,0,0,0,5,12,2,0,83,200,504,1020,360
2117,EL_AQUA_S,Aqua,100,0,1,1,0,0,0,0,0,0,0,0,0,0,5,12,0,0,81,200,504,1020,360
2118,EL_AQUA_M,Aqua,100,0,1,1,0,0,0,0,0,0,0,0,0,0,5,12,1,0,81,200,504,1020,360
2119,EL_AQUA_L,Aqua,100,0,1,1,0,0,0,0,1,1,1,1,1,1,5,12,2,0,81,200,504,1020,360
2120,EL_VENTUS_S,Ventus,100,0,1,1,0,0,0,0,0,0,0,0,0,0,5,12,0,0,84,200,504,1020,360
2121,EL_VENTUS_M,Ventus,100,0,1,1,0,0,0,0,0,0,0,0,0,0,5,12,1,0,84,200,504,1020,360
2122,EL_VENTUS_L,Ventus,100,0,1,1,0,0,0,0,0,0,0,0,0,0,5,12,2,0,84,200,504,1020,360
2123,EL_TERA_S,Tera,100,0,1,1,0,0,0,0,0,0,0,0,0,0,5,12,0,0,82,200,504,1020,360
2124,EL_TERA_M,Tera,100,0,1,1,0,0,0,0,0,0,0,0,0,0,5,12,1,0,82,200,504,1020,360
2125,EL_TERA_L,Tera,100,0,1,1,0,0,0,0,0,0,0,0,0,0,5,12,2,0,82,200,504,1020,360

240
db/elemental_db.yml Normal file
View File

@ -0,0 +1,240 @@
# This file is a part of rAthena.
# Copyright(C) 2021 rAthena Development Team
# https://rathena.org - https://github.com/rathena
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###########################################################################
# Elemental Summons Database
###########################################################################
#
# Elemental Summons Settings
#
###########################################################################
# - Id Elemental ID.
# AegisName Server name to reference the elemental in scripts and lookups, should use no spaces.
# Name Name in English.
# Level Level.
# Hp Additional HP. Base HP depends on caster HP. (Default: 0)
# Sp Additional SP. Base SP depends on caster SP. (Default: 1)
# Attack Additional minimum attack. Base attack depends on caster attack. (Default: 0)
# Attack2 Additional maximum attack. Base attack depends on caster attack. (Default: 0)
# Defense Physical defense of the elemental, reduces melee and ranged physical attack/skill damage. Base defense depends on the caster defense. (Default: 0)
# MagicDefense Magic defense of the elemental, reduces magical skill damage. Base magic defense depends on the caster magic defense. (Default: 0)
# Str Strength which affects attack. (Default: 0)
# Agi Agility which affects flee. (Default: 0)
# Vit Vitality which affects defense. (Default: 0)
# Int Intelligence which affects magic attack. (Default: 0)
# Dex Dexterity which affects hit rate. (Default: 0)
# Luk Luck which affects perfect dodge/lucky flee/perfect flee/lucky dodge rate. (Default: 0)
# AttackRange Attack range. (Default: 1)
# SkillRange Skill cast range. (Default: 5)
# ChaseRange Chase range. (Default: 12)
# Size Size.
# Race Race. (Default: Formless)
# Element Element.
# ElementLevel Level of element.
# WalkSpeed Walk speed. (Default: 200)
# AttackDelay Attack speed. (Default: 504)
# AttackMotion Attack animation speed. Base AttackMotion depends on the caster AttackMotion. (Default: 1020)
# DamageMotion Damage animation speed. (Default: 360)
# Mode: List of elemental skills by mode. (Optional)
# <mode>: Mode name to define the skill available. Available modes are Passive, Assist, and Aggressive.
# Skill Skill name.
# Level Skill level. (Default: 1)
###########################################################################
Header:
Type: ELEMENTAL_DB
Version: 1
Body:
- Id: 2114
AegisName: EL_AGNI_S
Name: Agni
Level: 100
Size: Small
Element: Fire
ElementLevel: 4
Mode:
Passive:
Skill: EL_PYROTECHNIC
Assist:
Skill: EL_CIRCLE_OF_FIRE
Aggressive:
Skill: EL_FIRE_ARROW
- Id: 2115
AegisName: EL_AGNI_M
Name: Agni
Level: 100
Size: Medium
Element: Fire
ElementLevel: 4
Mode:
Passive:
Skill: EL_HEATER
Assist:
Skill: EL_FIRE_CLOAK
Aggressive:
Skill: EL_FIRE_BOMB
- Id: 2116
AegisName: EL_AGNI_L
Name: Agni
Level: 100
Size: Large
Element: Fire
ElementLevel: 4
Mode:
Passive:
Skill: EL_TROPIC
Assist:
Skill: EL_FIRE_MANTLE
Aggressive:
Skill: EL_FIRE_WAVE
- Id: 2117
AegisName: EL_AQUA_S
Name: Aqua
Level: 100
Size: Small
Element: Water
ElementLevel: 4
Mode:
Passive:
Skill: EL_AQUAPLAY
Assist:
Skill: EL_WATER_SCREEN
Aggressive:
Skill: EL_ICE_NEEDLE
- Id: 2118
AegisName: EL_AQUA_M
Name: Aqua
Level: 100
Size: Medium
Element: Water
ElementLevel: 4
Mode:
Passive:
Skill: EL_COOLER
Assist:
Skill: EL_WATER_DROP
Aggressive:
Skill: EL_WATER_SCREW
- Id: 2119
AegisName: EL_AQUA_L
Name: Aqua
Level: 100
Str: 1
Agi: 1
Vit: 1
Int: 1
Dex: 1
Luk: 1
Size: Large
Element: Water
ElementLevel: 4
Mode:
Passive:
Skill: EL_CHILLY_AIR
Assist:
Skill: EL_WATER_BARRIER
Aggressive:
Skill: EL_TIDAL_WEAPON
- Id: 2120
AegisName: EL_VENTUS_S
Name: Ventus
Level: 100
Size: Small
Element: Wind
ElementLevel: 4
Mode:
Passive:
Skill: EL_GUST
Assist:
Skill: EL_WIND_STEP
Aggressive:
Skill: EL_WIND_SLASH
- Id: 2121
AegisName: EL_VENTUS_M
Name: Ventus
Level: 100
Size: Medium
Element: Wind
ElementLevel: 4
Mode:
Passive:
Skill: EL_BLAST
Assist:
Skill: EL_WIND_CURTAIN
Aggressive:
Skill: EL_HURRICANE
- Id: 2122
AegisName: EL_VENTUS_L
Name: Ventus
Level: 100
Size: Large
Element: Wind
ElementLevel: 4
Mode:
Passive:
Skill: EL_WILD_STORM
Assist:
Skill: EL_ZEPHYR
Aggressive:
Skill: EL_TYPOON_MIS
- Id: 2123
AegisName: EL_TERA_S
Name: Tera
Level: 100
Size: Small
Element: Earth
ElementLevel: 4
Mode:
Passive:
Skill: EL_PETROLOGY
Assist:
Skill: EL_SOLID_SKIN
Aggressive:
Skill: EL_STONE_HAMMER
- Id: 2124
AegisName: EL_TERA_M
Name: Tera
Level: 100
Size: Medium
Element: Earth
ElementLevel: 4
Mode:
Passive:
Skill: EL_CURSED_SOIL
Assist:
Skill: EL_STONE_SHIELD
Aggressive:
Skill: EL_ROCK_CRUSHER
- Id: 2125
AegisName: EL_TERA_L
Name: Tera
Level: 100
Size: Large
Element: Earth
ElementLevel: 4
Mode:
Passive:
Skill: EL_UPHEAVAL
Assist:
Skill: EL_POWER_OF_GAIA
Aggressive:
Skill: EL_STONE_RAIN
Footer:
Imports:
- Path: db/import/elemental_db.yml

View File

@ -1,56 +0,0 @@
// Elemental Summons Skill Database
//
// Structure of Database:
// ElementalID,SkillID,SkillLevel,ReqMode
//
// Spirit Modes:
// 1 = Passive, 2 = Defensive, 4 = Aggressive
// EL_AGNI_S
2114,8413,1,1 //EL_PYROTECHNIC,Pyrotechnic
2114,8401,1,2 //EL_CIRCLE_OF_FIRE,Circle of Fire
2114,8425,1,4 //EL_FIRE_ARROW,Fire Arrow
// EL_AGNI_M
2115,8414,1,1 //EL_HEATER,Heater
2115,8402,1,2 //EL_FIRE_CLOAK,Fire Cloak
2115,8426,1,4 //EL_FIRE_BOMB,Fire Bomb
// EL_AGNI_L
2116,8415,1,1 //EL_TROPIC,Tropic
2116,8403,1,2 //EL_FIRE_MANTLE,Fire Mantle
2116,8428,1,4 //EL_FIRE_WAVE,Fire Wave
// EL_AQUA_S
2117,8416,1,1 //EL_AQUAPLAY,Aqua Play
2117,8404,1,2 //EL_WATER_SCREEN,Water Screen
2117,8430,1,4 //EL_ICE_NEEDLE,Ice Needle
// EL_AQUA_M
2118,8417,1,1 //EL_COOLER,Cooler
2118,8405,1,2 //EL_WATER_DROP,Water Drop
2118,8431,1,4 //EL_WATER_SCREW,Water Screw
// EL_AQUA_L
2119,8418,1,1 //EL_CHILLY_AIR,Cool Air
2119,8406,1,2 //EL_WATER_BARRIER,Water Barrier
2119,8433,1,4 //EL_TIDAL_WEAPON,Tidal Weapon
// EL_VENTUS_S
2120,8419,1,1 //EL_GUST,Gust
2120,8407,1,2 //EL_WIND_STEP,Wind Step
2120,8434,1,4 //EL_WIND_SLASH,Wind Slasher
// EL_VENTUS_M
2121,8420,1,1 //EL_BLAST,Blast
2121,8408,1,2 //EL_WIND_CURTAIN,Wind Curtain
2121,8435,1,4 //EL_HURRICANE,Hurricane Rage
// EL_VENTUS_L
2122,8421,1,1 //EL_WILD_STORM,Wild Storm
2122,8409,1,2 //EL_ZEPHYR,Zephyr
2122,8437,1,4 //EL_TYPOON_MIS,Typhoon Missile
// EL_TERA_S
2123,8422,1,1 //EL_PETROLOGY,Petrology
2123,8410,1,2 //EL_SOLID_SKIN,Solid Skin
2123,8439,1,4 //EL_STONE_HAMMER,Stone Hammer
// EL_TERA_M
2124,8423,1,1 //EL_CURSED_SOIL,Cursed Soil
2124,8411,1,2 //EL_STONE_SHIELD,Stone Shield
2124,8440,1,4 //EL_ROCK_CRUSHER,Rock Launcher
// EL_TERA_L
2125,8424,1,1 //EL_UPHEAVAL,Upheaval
2125,8412,1,2 //EL_POWER_OF_GAIA,Power of Gaia
2125,8442,1,4 //EL_STONE_RAIN,Stone Rain

View File

@ -1,9 +0,0 @@
// Elemental Summons Database
//
// Structure of Database:
// ID,Sprite_Name,Name,LV,HP,SP,Range1,ATK1,ATK2,DEF,MDEF,STR,AGI,VIT,INT,DEX,LUK,Range2,Range3,Scale,Race,Element,Speed,aDelay,aMotion,dMotion
//
// Notes:
// Summoned Elementals STATs are affected by the Casters Base Level and STATs.
// In other words, all values specified will be added to (and will not override) the calculated STATs of the summoned elemental.

View File

@ -0,0 +1,43 @@
###########################################################################
# Elemental Summons Database
###########################################################################
#
# Elemental Summons Settings
#
###########################################################################
# - Id Elemental ID.
# AegisName Server name to reference the elemental in scripts and lookups, should use no spaces.
# Name Name in English.
# Level Level.
# Hp Additional HP. Base HP depends on caster HP. (Default: 0)
# Sp Additional SP. Base SP depends on caster SP. (Default: 1)
# Attack Additional minimum attack. Base attack depends on caster attack. (Default: 0)
# Attack2 Additional maximum attack. Base attack depend on caster attack. (Default: 0)
# Defense Physical defense of the elemental, reduces melee and ranged physical attack/skill damage. Base defense depends on the caster defense. (Default: 0)
# MagicDefense Magic defense of the elemental, reduces magical skill damage. Base magic defense depends on the caster magic defense. (Default: 0)
# Str Strength which affects attack. (Default: 0)
# Agi Agility which affects flee. (Default: 0)
# Vit Vitality which affects defense. (Default: 0)
# Int Intelligence which affects magic attack. (Default: 0)
# Dex Dexterity which affects hit rate. (Default: 0)
# Luk Luck which affects perfect dodge/lucky flee/perfect flee/lucky dodge rate. (Default: 0)
# AttackRange Attack range. (Default: 1)
# SkillRange Skill cast range. (Default: 5)
# ChaseRange Chase range. (Default: 12)
# Size Size.
# Race Race. (Default: Formless)
# Element Element.
# ElementLevel Level of element.
# WalkSpeed Walk speed. (Default: 200)
# AttackDelay Attack speed. (Default: 504)
# AttackMotion Attack animation speed. Base AttackMotion depends on the caster AttackMotion. (Default: 1020)
# DamageMotion Damage animation speed. (Default: 360)
# Mode: List of elemental skills by mode. (Optional)
# <mode>: Mode name to define the skill available. Available modes are Passive, Assist, and Aggressive.
# Skill Skill name.
# Level Skill level. (Default: 1)
###########################################################################
Header:
Type: ELEMENTAL_DB
Version: 1

View File

@ -1,7 +0,0 @@
// Elemental Summons Skill Database
//
// Structure of Database:
// ElementalID,SkillID,SkillLevel,ReqMode
//
// Spirit Modes:
// 1 = Passive, 2 = Defensive, 4 = Aggressive

View File

@ -0,0 +1,39 @@
###########################################################################
# Elemental Summons Database
###########################################################################
#
# Elemental Summons Settings
#
###########################################################################
# - Id Elemental ID.
# AegisName Server name to reference the elemental in scripts and lookups, should use no spaces.
# Name Name in English.
# Level Level.
# Hp Additional HP. Base HP depends on caster HP. (Default: 0)
# Sp Additional SP. Base SP depends on caster SP. (Default: 1)
# Attack Additional minimum attack. Base attack depends on caster attack. (Default: 0)
# Attack2 Additional maximum attack. Base attack depend on caster attack. (Default: 0)
# Defense Physical defense of the elemental, reduces melee and ranged physical attack/skill damage. Base defense depends on the caster defense. (Default: 0)
# MagicDefense Magic defense of the elemental, reduces magical skill damage. Base magic defense depends on the caster magic defense. (Default: 0)
# Str Strength which affects attack. (Default: 0)
# Agi Agility which affects flee. (Default: 0)
# Vit Vitality which affects defense. (Default: 0)
# Int Intelligence which affects magic attack. (Default: 0)
# Dex Dexterity which affects hit rate. (Default: 0)
# Luk Luck which affects perfect dodge/lucky flee/perfect flee/lucky dodge rate. (Default: 0)
# AttackRange Attack range. (Default: 1)
# SkillRange Skill cast range. (Default: 5)
# ChaseRange Chase range. (Default: 12)
# Size Size.
# Race Race. (Default: Formless)
# Element Element.
# ElementLevel Level of element.
# WalkSpeed Walk speed. (Default: 200)
# AttackDelay Attack speed. (Default: 504)
# AttackMotion Attack animation speed. Base AttackMotion depends on the caster AttackMotion. (Default: 1020)
# DamageMotion Damage animation speed. (Default: 360)
# Mode: List of elemental skills by mode. (Optional)
# <mode>: Mode name to define the skill available. Available modes are Passive, Assist, and Aggressive.
# Skill Skill name.
# Level Skill level. (Default: 1)
###########################################################################

View File

@ -4038,12 +4038,11 @@ ACMD_FUNC(reload) {
hom_reload();
mercenary_readdb();
mercenary_read_skilldb();
reload_elementaldb();
elemental_db.reload();
clif_displaymessage(fd, msg_txt(sd,98)); // Monster database has been reloaded.
} else if (strstr(command, "skilldb") || strncmp(message, "skilldb", 4) == 0) {
skill_reload();
hom_reload_skill();
reload_elemental_skilldb();
mercenary_read_skilldb();
clif_displaymessage(fd, msg_txt(sd,99)); // Skill database has been reloaded.
} else if (strstr(command, "atcommand") || strncmp(message, "atcommand", 4) == 0) {

View File

@ -125,7 +125,7 @@ int battle_gettarget(struct block_list* bl)
case BL_PET: return ((struct pet_data*)bl)->target_id;
case BL_HOM: return ((struct homun_data*)bl)->ud.target;
case BL_MER: return ((struct mercenary_data*)bl)->ud.target;
case BL_ELEM: return ((struct elemental_data*)bl)->ud.target;
case BL_ELEM: return ((s_elemental_data*)bl)->ud.target;
}
return 0;
@ -8008,7 +8008,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
status_change_end(target, SC_DEVOTION, INVALID_TIMER);
}
if (target->type == BL_PC && (wd.flag&BF_SHORT) && tsc->data[SC_CIRCLE_OF_FIRE_OPTION]) {
struct elemental_data *ed = ((TBL_PC*)target)->ed;
s_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_SINGLE);

View File

@ -9845,7 +9845,7 @@ void clif_name( struct block_list* src, struct block_list *bl, send_target targe
safestrncpy(packet.name, ((TBL_NPC *)bl)->name, NAME_LENGTH);
break;
case BL_ELEM:
safestrncpy(packet.name, ((TBL_ELEM *)bl)->db->name, NAME_LENGTH);
safestrncpy(packet.name, ((TBL_ELEM *)bl)->db->name.c_str(), NAME_LENGTH);
break;
}
@ -18552,7 +18552,7 @@ void clif_parse_ItemListWindowSelected(int fd, struct map_session_data* sd) {
* Elemental System
*==========================================*/
void clif_elemental_updatestatus(struct map_session_data *sd, int type) {
struct elemental_data *ed;
s_elemental_data *ed;
struct status_data *status;
int fd;
@ -18583,7 +18583,7 @@ void clif_elemental_updatestatus(struct map_session_data *sd, int type) {
void clif_elemental_info(struct map_session_data *sd) {
int fd;
struct elemental_data *ed;
s_elemental_data *ed;
struct status_data *status;
if( !clif_session_isValid(sd) || (ed = sd->ed) == NULL )

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,7 @@
#ifndef ELEMENTAL_HPP
#define ELEMENTAL_HPP
#include "../common/database.hpp"
#include "../common/mmo.hpp"
#include "../common/timer.hpp"
@ -19,7 +20,7 @@ const t_tick MIN_ELETHINKTIME = 100;
#define EL_MODE_PASSIVE MD_CANMOVE
///Enum of Elemental Skill Mode
enum elemental_skillmode : uint8 {
enum e_elemental_skillmode : uint8 {
EL_SKILLMODE_PASSIVE = 0x1,
EL_SKILLMODE_ASSIST = 0x2,
EL_SKILLMODE_AGGRESSIVE = 0x4,
@ -41,36 +42,33 @@ enum elemental_elementalid : uint16 {
ELEMENTALID_TERA_L,
};
struct elemental_skill {
unsigned short id, lv;
short mode;
struct s_elemental_skill {
uint16 id, lv;
};
struct s_elemental_db {
int class_;
char sprite[NAME_LENGTH], name[NAME_LENGTH];
unsigned short lv;
short range2, range3;
struct status_data status;
struct view_data vd;
struct elemental_skill skill[MAX_ELESKILLTREE];
int32 class_;
std::string sprite, name;
uint16 lv;
uint16 range2, range3;
status_data status;
view_data vd;
std::unordered_map<e_elemental_skillmode, std::shared_ptr<s_elemental_skill>> skill; /// mode, skill
};
extern struct s_elemental_db elemental_db[MAX_ELEMENTAL_CLASS];
struct s_elemental_data {
block_list bl;
unit_data ud;
view_data *vd;
status_data base_status, battle_status;
status_change sc;
regen_data regen;
struct elemental_data {
struct block_list bl;
struct unit_data ud;
struct view_data *vd;
struct status_data base_status, battle_status;
struct status_change sc;
struct regen_data regen;
struct s_elemental_db *db;
struct s_elemental elemental;
std::shared_ptr<s_elemental_db> db;
s_elemental elemental;
int masterteleport_timer;
struct map_session_data *master;
map_session_data *master;
int summon_timer;
int skill_timer;
@ -79,38 +77,47 @@ struct elemental_data {
int target_id, attacked_id;
};
bool elemental_class(int class_);
class ElementalDatabase : public TypesafeYamlDatabase<int32, s_elemental_db> {
public:
ElementalDatabase() : TypesafeYamlDatabase("ELEMENTAL_DB", 1) {
}
const std::string getDefaultLocation();
uint64 parseBodyNode(const YAML::Node& node);
};
extern ElementalDatabase elemental_db;
struct view_data * elemental_get_viewdata(int class_);
int elemental_create(struct map_session_data *sd, int class_, unsigned int lifetime);
int elemental_data_received(struct s_elemental *ele, bool flag);
int elemental_save(struct elemental_data *ed);
int elemental_create(map_session_data *sd, int class_, unsigned int lifetime);
int elemental_data_received(s_elemental *ele, bool flag);
int elemental_save(s_elemental_data *ed);
int elemental_change_mode_ack(struct elemental_data *ed, enum elemental_skillmode skill_mode);
int elemental_change_mode(struct elemental_data *ed, enum e_mode mode);
int elemental_change_mode_ack(s_elemental_data *ed, e_elemental_skillmode skill_mode);
int elemental_change_mode(s_elemental_data *ed, e_mode mode);
void elemental_heal(struct elemental_data *ed, int hp, int sp);
int elemental_dead(struct elemental_data *ed);
void elemental_heal(s_elemental_data *ed, int hp, int sp);
int elemental_dead(s_elemental_data *ed);
int elemental_delete(struct elemental_data *ed);
void elemental_summon_stop(struct elemental_data *ed);
int elemental_delete(s_elemental_data *ed);
void elemental_summon_stop(s_elemental_data *ed);
t_tick elemental_get_lifetime(struct elemental_data *ed);
t_tick elemental_get_lifetime(s_elemental_data *ed);
int elemental_unlocktarget(struct elemental_data *ed);
bool elemental_skillnotok(uint16 skill_id, struct elemental_data *ed);
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);
int elemental_unlocktarget(s_elemental_data *ed);
bool elemental_skillnotok(uint16 skill_id, s_elemental_data *ed);
int elemental_set_target( map_session_data *sd, block_list *bl );
int elemental_clean_single_effect(s_elemental_data *ed, uint16 skill_id);
int elemental_clean_effect(s_elemental_data *ed);
int elemental_action(s_elemental_data *ed, block_list *bl, t_tick tick);
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)
void read_elemental_skilldb(void);
void reload_elementaldb(void);
void reload_elemental_skilldb(void);
void do_init_elemental(void);
void do_final_elemental(void);

View File

@ -303,8 +303,7 @@
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\castle_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\castle_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\const.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\const.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\create_arrow_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\create_arrow_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\elemental_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\elemental_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\elemental_skill_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\elemental_skill_db.txt')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\elemental_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\elemental_db.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\exp_homun.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\exp_homun.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\exp_guild.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\exp_guild.yml')" />
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\guild_skill_tree.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\guild_skill_tree.yml')" />

View File

@ -2249,7 +2249,7 @@ struct pet_data* map_id2pd(int id){
return BL_CAST(BL_PET, bl);
}
struct elemental_data* map_id2ed(int id) {
struct s_elemental_data* map_id2ed(int id) {
struct block_list* bl = map_id2bl(id);
return BL_CAST(BL_ELEM, bl);
}

View File

@ -1089,7 +1089,7 @@ struct npc_data * map_id2nd(int id);
struct homun_data* map_id2hd(int id);
struct mercenary_data* map_id2mc(int id);
struct pet_data* map_id2pd(int id);
struct elemental_data* map_id2ed(int id);
struct s_elemental_data* map_id2ed(int id);
struct chat_data* map_id2cd(int id);
struct block_list * map_id2bl(int id);
bool map_blid_exists( int id );
@ -1196,7 +1196,7 @@ typedef struct skill_unit TBL_SKILL;
typedef struct pet_data TBL_PET;
typedef struct homun_data TBL_HOM;
typedef struct mercenary_data TBL_MER;
typedef struct elemental_data TBL_ELEM;
typedef struct s_elemental_data TBL_ELEM;
#define BL_CAST(type_, bl) \
( ((bl) == (struct block_list*)NULL || (bl)->type != (type_)) ? (T ## type_ *)NULL : (T ## type_ *)(bl) )

View File

@ -2390,7 +2390,7 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
}
case BL_ELEM:
{
struct elemental_data *ele = (TBL_ELEM*)src;
s_elemental_data *ele = (TBL_ELEM*)src;
if( ele->master )
char_id = ele->master->status.char_id;
if( damage )

View File

@ -661,7 +661,7 @@ struct map_session_data {
struct pet_data *pd;
struct homun_data *hd; // [blackhole89]
struct mercenary_data *md;
struct elemental_data *ed;
s_elemental_data *ed;
struct s_hate_mob {
int m; //-1 - none, other: map index corresponding to map name.

View File

@ -8245,6 +8245,11 @@
export_constant(PARAM_CON);
export_constant(PARAM_CRT);
/* Elemental Skill Mode */
export_constant(EL_SKILLMODE_PASSIVE);
export_constant(EL_SKILLMODE_ASSIST);
export_constant(EL_SKILLMODE_AGGRESSIVE);
#undef export_constant
#undef export_constant2
#undef export_parameter

View File

@ -6166,7 +6166,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case EL_TIDAL_WEAPON:
if( src->type == BL_ELEM ) {
struct elemental_data *ele = BL_CAST(BL_ELEM,src);
s_elemental_data *ele = BL_CAST(BL_ELEM,src);
struct status_change *tsc_ele = status_get_sc(&ele->bl);
sc_type type = status_skill2sc(skill_id), type2;
@ -11010,7 +11010,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SO_EL_CURE:
if( sd ) {
struct elemental_data *ed = sd->ed;
s_elemental_data *ed = sd->ed;
int s_hp, s_sp;
if( !ed )
@ -11145,7 +11145,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case EL_SOLID_SKIN:
case EL_STONE_SHIELD:
case EL_WIND_STEP: {
struct elemental_data *ele = BL_CAST(BL_ELEM, src);
s_elemental_data *ele = BL_CAST(BL_ELEM, src);
if( ele ) {
sc_type type2 = (sc_type)(type-1);
struct status_change *sc = status_get_sc(&ele->bl);
@ -11171,7 +11171,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
skill_unitsetting(src,skill_id,skill_lv,bl->x,bl->y,0);
break;
case EL_WATER_SCREEN: {
struct elemental_data *ele = BL_CAST(BL_ELEM, src);
s_elemental_data *ele = BL_CAST(BL_ELEM, src);
if( ele ) {
struct status_change *sc = status_get_sc(&ele->bl);
sc_type type2 = (sc_type)(type-1);

View File

@ -5264,10 +5264,10 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt)
* @param opt: Whether it is first calc or not (0 on status change)
* @return 0
*/
int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt)
int status_calc_elemental_(s_elemental_data *ed, e_status_calc_opt opt)
{
struct status_data *status = &ed->base_status;
struct s_elemental *ele = &ed->elemental;
s_elemental *ele = &ed->elemental;
struct map_session_data *sd = ed->master;
if( !sd )
@ -8455,7 +8455,7 @@ const char* status_get_name(struct block_list *bl)
case BL_HOM: return ((TBL_HOM*)bl)->homunculus.name;
//case BL_MER: // They only have database names which are global, not specific to GID.
case BL_NPC: return ((TBL_NPC*)bl)->name;
//case BL_ELEM: // They only have database names which are global, not specific to GID.
case BL_ELEM: return ((TBL_ELEM *)bl)->db->name.c_str(); // They only have database names which are global, not specific to GID.
}
return "Unknown";
}
@ -8815,7 +8815,7 @@ void status_set_viewdata(struct block_list *bl, int class_)
vd = hom_get_viewdata(class_);
else if (mercenary_db(class_))
vd = mercenary_get_viewdata(class_);
else if (elemental_class(class_))
else if (elemental_db.exists(class_))
vd = elemental_get_viewdata(class_);
else
vd = NULL;
@ -8952,7 +8952,7 @@ void status_set_viewdata(struct block_list *bl, int class_)
break;
case BL_ELEM:
{
struct elemental_data *ed = (struct elemental_data*)bl;
s_elemental_data *ed = (s_elemental_data*)bl;
if (vd)
ed->vd = vd;
else

View File

@ -18,7 +18,7 @@ struct mob_data;
struct pet_data;
struct homun_data;
struct mercenary_data;
struct elemental_data;
struct s_elemental_data;
struct npc_data;
struct status_change;
@ -2882,7 +2882,7 @@ void status_calc_pet_(struct pet_data* pd, enum e_status_calc_opt opt);
int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt);
int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt);
int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt);
int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt);
int status_calc_elemental_(s_elemental_data *ed, e_status_calc_opt opt);
int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt);
void status_calc_misc(struct block_list *bl, struct status_data *status, int level);

View File

@ -66,7 +66,7 @@ struct unit_data* unit_bl2ud(struct block_list *bl)
case BL_NPC: return &((struct npc_data*)bl)->ud;
case BL_HOM: return &((struct homun_data*)bl)->ud;
case BL_MER: return &((struct mercenary_data*)bl)->ud;
case BL_ELEM: return &((struct elemental_data*)bl)->ud;
case BL_ELEM: return &((s_elemental_data*)bl)->ud;
default : return NULL;
}
}
@ -3222,7 +3222,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
break;
}
case BL_ELEM: {
struct elemental_data *ed = (struct elemental_data *)bl;
s_elemental_data *ed = (s_elemental_data *)bl;
ud->canact_tick = ud->canmove_tick;
@ -3571,7 +3571,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
break;
}
case BL_ELEM: {
struct elemental_data *ed = (TBL_ELEM*)bl;
s_elemental_data *ed = (TBL_ELEM*)bl;
struct map_session_data *sd = ed->master;
if( elemental_get_lifetime(ed) > 0 )

View File

@ -122,6 +122,14 @@ static void job_txt_data(const std::string &modePath, const std::string &fixedPa
sv_readdb(modePath.c_str(), "job_param_db.txt", ',', 2, PARAM_MAX + 1, CLASS_COUNT, &pc_readdb_job_param, false);
}
// Elemental Summons Skill Database data to memory
static void elemental_skill_txt_data(const std::string& modePath, const std::string& fixedPath) {
elemental_skill_tree.clear();
if (fileExists(fixedPath + "/elemental_skill_db.txt"))
sv_readdb(fixedPath.c_str(), "elemental_skill_db.txt", ',', 4, 4, -1, read_elemental_skilldb, false);
}
template<typename Func>
bool process( const std::string& type, uint32 version, const std::vector<std::string>& paths, const std::string& name, Func lambda, const std::string& rename = "" ){
for( const std::string& path : paths ){
@ -474,6 +482,13 @@ int do_init( int argc, char** argv ){
return 0;
}
elemental_skill_txt_data(path_db_mode, path_db);
if (!process("ELEMENTAL_DB", 1, root_paths, "elemental_db", [](const std::string &path, const std::string &name_ext) -> bool {
return sv_readdb(path.c_str(), name_ext.c_str(), ',', 26, 26, -1, &read_elementaldb, false);
})) {
return 0;
}
// TODO: add implementations ;-)
return 0;
@ -4403,3 +4418,113 @@ static bool pc_readdb_job1(char* fields[], int columns, int current) {
return true;
}
// elemental_db.yml function
//---------------------------
static bool read_elemental_skilldb(char* str[], int columns, int current) {
uint16 skill_id = atoi(str[1]);
std::string *skill_name = util::umap_find(aegis_skillnames, skill_id);
if (skill_name == nullptr) {
ShowError("read_elemental_skilldb: Invalid skill '%hu'.\n", skill_id);
return false;
}
uint16 skillmode = atoi(str[3]);
std::string constant = constant_lookup(skillmode, "EL_SKILLMODE_");
constant.erase(0, 13);
std::string mode_name = name2Upper(constant);
s_elemental_skill_csv entry = {};
entry.skill_name = *skill_name;
entry.lv = atoi(str[2]);
entry.mode_name = mode_name;
uint16 class_ = atoi(str[0]);
if (util::umap_find(elemental_skill_tree, class_))
elemental_skill_tree[class_].push_back(entry);
else {
elemental_skill_tree[class_] = std::vector<s_elemental_skill_csv>();
elemental_skill_tree[class_].push_back(entry);
}
return true;
}
// Copied and adjusted from elemental.cpp
static bool read_elementaldb(char* str[], int columns, int current) {
body << YAML::BeginMap;
body << YAML::Key << "Id" << YAML::Value << str[0];
body << YAML::Key << "AegisName" << YAML::Value << str[1];
body << YAML::Key << "Name" << YAML::Value << str[2];
body << YAML::Key << "Level" << YAML::Value << str[3];
if (atoi(str[4]) != 0)
body << YAML::Key << "Hp" << YAML::Value << str[4];
if (atoi(str[5]) != 1)
body << YAML::Key << "Sp" << YAML::Value << str[5];
if (atoi(str[7]) != 0)
body << YAML::Key << "Attack" << YAML::Value << str[7];
if (atoi(str[8]) != 0)
body << YAML::Key << "Attack2" << YAML::Value << str[8];
if (atoi(str[9]) != 0)
body << YAML::Key << "Defense" << YAML::Value << str[9];
if (atoi(str[10]) != 0)
body << YAML::Key << "MagicDefense" << YAML::Value << str[10];
if (atoi(str[11]) != 0)
body << YAML::Key << "Str" << YAML::Value << str[11];
if (atoi(str[12]) != 0)
body << YAML::Key << "Agi" << YAML::Value << str[12];
if (atoi(str[13]) != 0)
body << YAML::Key << "Vit" << YAML::Value << str[13];
if (atoi(str[14]) != 0)
body << YAML::Key << "Int" << YAML::Value << str[14];
if (atoi(str[15]) != 0)
body << YAML::Key << "Dex" << YAML::Value << str[15];
if (atoi(str[16]) != 0)
body << YAML::Key << "Luk" << YAML::Value << str[16];
if (atoi(str[6]) != 1)
body << YAML::Key << "AttackRange" << YAML::Value << str[6];
if (atoi(str[17]) != 5)
body << YAML::Key << "SkillRange" << YAML::Value << str[17];
if (atoi(str[18]) != 12)
body << YAML::Key << "ChaseRange" << YAML::Value << str[18];
body << YAML::Key << "Size" << YAML::Value << constant_lookup(strtol(str[19], nullptr, 10), "Size_") + 5;
if (atoi(str[20]) != 0)
body << YAML::Key << "Race" << YAML::Value << name2Upper(constant_lookup(atoi(str[20]), "RC_") + 3);
int ele = strtol(str[21], nullptr, 10);
body << YAML::Key << "Element" << YAML::Value << name2Upper(constant_lookup(ele % 20, "ELE_") + 4);
body << YAML::Key << "ElementLevel" << YAML::Value << floor(ele / 20.);
if (atoi(str[22]) != 200)
body << YAML::Key << "WalkSpeed" << YAML::Value << str[22];
if (atoi(str[23]) != 504)
body << YAML::Key << "AttackDelay" << YAML::Value << str[23];
if (atoi(str[24]) != 1020)
body << YAML::Key << "AttackMotion" << YAML::Value << str[24];
if (atoi(str[25]) != 360)
body << YAML::Key << "DamageMotion" << YAML::Value << str[25];
auto list = elemental_skill_tree.find( atoi(str[0]) );
if (list != elemental_skill_tree.end()) {
body << YAML::Key << "Mode";
body << YAML::BeginMap;
for (const auto &it : list->second) {
body << YAML::Key << it.mode_name;
body << YAML::BeginMap;
body << YAML::Key << "Skill" << YAML::Value << it.skill_name;
if (it.lv != 1)
body << YAML::Key << "Level" << YAML::Value << it.lv;
body << YAML::EndMap;
}
body << YAML::EndMap;
}
body << YAML::EndMap;
return true;
}

View File

@ -120,6 +120,14 @@ std::unordered_map<int, std::vector<int64>> job_hp, job_sp;
std::unordered_map<int, s_job_param> job_param;
std::unordered_map<int, int> exp_base_level, exp_job_level;
struct s_elemental_skill_csv {
std::string skill_name,
mode_name;
uint16 lv;
};
std::unordered_map<uint16, std::vector<s_elemental_skill_csv>> elemental_skill_tree;
static std::map<std::string, int> um_mapid2jobname {
{ "Novice", JOB_NOVICE }, // Novice and Super Novice share the same value
{ "SuperNovice", JOB_NOVICE },
@ -476,5 +484,7 @@ static bool pc_readdb_job_exp(char *fields[], int columns, int current);
static bool pc_readdb_job_exp_sub(char *fields[], int columns, int current);
static bool pc_readdb_job_basehpsp(char *fields[], int columns, int current);
static bool pc_readdb_job1(char *fields[], int columns, int current);
static bool read_elemental_skilldb(char* str[], int columns, int current);
static bool read_elementaldb(char* str[], int columns, int current);
#endif /* CSV2YAML_HPP */

View File

@ -42,6 +42,7 @@
#include "../map/chat.hpp"
#include "../map/date.hpp"
#include "../map/instance.hpp"
#include "../map/elemental.hpp"
#include "../map/mercenary.hpp"
#include "../map/mob.hpp"
#include "../map/npc.hpp"

View File

@ -38,6 +38,7 @@
#include "../map/channel.hpp"
#include "../map/chat.hpp"
#include "../map/date.hpp"
#include "../map/elemental.hpp"
#include "../map/instance.hpp"
#include "../map/mercenary.hpp"
#include "../map/mob.hpp"