Allow NPC view data modifications (#4385)
* Fixes #4289. * Updated script commands setunitdata and getunitdata to support the modification of NPC view data. * Converted mob_avail database to YAML. Thanks to @Lemongrass3110, @4144, @exneval, @Balferian, @cahya1992 and @teededung! Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
This commit is contained in:
parent
f2a1b6e784
commit
b0119631a4
@ -1,16 +0,0 @@
|
||||
// Mob Availability and Alias Database
|
||||
//
|
||||
// Structure of Database:
|
||||
// MobID,SpriteID{,Equipment}
|
||||
//
|
||||
// 01. MobID Mob ID to change.
|
||||
// 02. SpriteID Mob ID which will be sent to the client instead of MobID.
|
||||
// If 0, the mob becomes unavailable for use.
|
||||
// 03. Equipment Item ID of pet equipment (must be available for pet counterpart, or this will cause problems).
|
||||
//
|
||||
// To disguise a mob as a player:
|
||||
// MobID,SpriteID,Sex,Hair_Style,Hair_Color,Weapon,Shield,Head_Top,Head_Middle,Head_Bottom,Option,Dye_Color
|
||||
//
|
||||
// SpriteID is a job class value.
|
||||
// Weapon and Shield uses Item ID, while Head uses View ID.
|
||||
|
123
db/import-tmpl/mob_avail.yml
Normal file
123
db/import-tmpl/mob_avail.yml
Normal file
@ -0,0 +1,123 @@
|
||||
# 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/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Mob Availability and Alias Database
|
||||
###########################################################################
|
||||
#
|
||||
# Mob Availability and Alias Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Mob Mob to adjust.
|
||||
# Sprite Sprite which will be sent to the client instead of Mob.
|
||||
# Sex Sex (if Sprite is a player). (Default: Female)
|
||||
# HairStyle Hair Style ID (if Sprite is a player). (Default: 0)
|
||||
# HairColor Hair Color ID (if Sprite is a player). (Default: 0)
|
||||
# ClothColor Cloth Color ID (if Sprite is a player). (Default: 0)
|
||||
# Weapon Item name of weapon (if Sprite is a player). (Default: 0)
|
||||
# Shield Item name of shield (if Sprite is a player). (Default: 0)
|
||||
# HeadTop Item name of headgear (if Sprite is a player). (Default: 0)
|
||||
# HeadMid Item name of headgear (if Sprite is a player). (Default: 0)
|
||||
# HeadLow Item name of headgear (if Sprite is a player). (Default: 0)
|
||||
# PetEquip Item name of pet equipment (if Mob is a valid pet). (Default: 0)
|
||||
# Options: Set an option for an object. (Optional)
|
||||
# <Option>: bool
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: MOB_AVAIL_DB
|
||||
Version: 1
|
||||
|
||||
#Body:
|
||||
# Examples
|
||||
# - Mob: PORING
|
||||
# Sprite: BAPHOMET
|
||||
# - Mob: E_OBEAUNE
|
||||
# Sprite: PORING
|
||||
# PetEquip: Backpack
|
||||
|
||||
# Easter Event Monsters
|
||||
# - Mob: MOROCC_3
|
||||
# Sprite: DOPPELGANGER
|
||||
# - Mob: MOROCC_4
|
||||
# Sprite: ECLIPSE
|
||||
|
||||
# rAthena Dev Team
|
||||
# Valaris
|
||||
# - Mob: BOW_GUARDIAN_
|
||||
# Sprite: JOB_ASSASSIN_CROSS
|
||||
# Sex: Male
|
||||
# HairStyle: 1
|
||||
# HairColor: 1
|
||||
# ClothColor: 1
|
||||
# Weapon: Jamadhar
|
||||
# HeadTop: Sahkkat
|
||||
# HeadMid: Sunglasses
|
||||
# HeadLow: Cigar
|
||||
# Options:
|
||||
# Falcon: true
|
||||
# Valaris Worshiper
|
||||
# - Mob: E_CONDOR
|
||||
# Sprite: JOB_THIEF
|
||||
# Sex: Male
|
||||
# HairStyle: 1
|
||||
# HairColor: 1
|
||||
# ClothColor: 1
|
||||
# Weapon: Gladius
|
||||
# Shield: Guard
|
||||
# HeadTop: Sahkkat
|
||||
# HeadMid: Sunglasses
|
||||
# HeadLow: Cigar
|
||||
# MC Cameri
|
||||
# - Mob: E_TREASURE1
|
||||
# Sprite: JOB_CRUSADER
|
||||
# Sex: Male
|
||||
# HairStyle: 6
|
||||
# HairColor: 6
|
||||
# ClothColor: 3
|
||||
# Weapon: Sword
|
||||
# Shield: Shield
|
||||
# Options:
|
||||
# Riding: true
|
||||
# Poki#3
|
||||
# - Mob: E_TREASURE2
|
||||
# Sprite: JOB_SNIPER
|
||||
# Sex: Male
|
||||
# HairStyle: 21
|
||||
# Weapon: Bow_Of_Rudra
|
||||
# HeadTop: Boy's_Cap
|
||||
# HeadMid: Takius_Blindfold
|
||||
# HeadLow: Centimental_Leaf
|
||||
# Options:
|
||||
# Falcon: true
|
||||
# Sentry
|
||||
# - Mob: BOMBPORING
|
||||
# Sprite: KNIGHT_GUARDIAN
|
||||
|
||||
# iRO Halloween Event 2009
|
||||
# - Mob: EP14_MORS_BOSSB
|
||||
# Sprite: ZOMBIE
|
||||
# - Mob: EP14_MORS_MOB1
|
||||
# Sprite: GHOUL
|
||||
# - Mob: EP14_MORS_MOB2
|
||||
# Sprite: ZOMBIE_MASTER
|
||||
|
||||
# iRO Halloween Event 2009
|
||||
# - Mob: EP14_3_DEATH_B_MOB2
|
||||
# Sprite: WHISPER
|
||||
# - Mob: EP14_3_DEATH_B_MOB3
|
||||
# Sprite: DARK_LORD
|
@ -1,44 +0,0 @@
|
||||
// Mob Availability and Alias Database
|
||||
//
|
||||
// Structure of Database:
|
||||
// MobID,SpriteID{,Equipment}
|
||||
//
|
||||
// 01. MobID Mob ID to change.
|
||||
// 02. SpriteID Mob ID which will be sent to the client instead of MobID.
|
||||
// If 0, the mob becomes unavailable for use.
|
||||
// 03. Equipment Item ID of pet equipment (must be available for pet counterpart, or this will cause problems).
|
||||
//
|
||||
// To disguise a mob as a player:
|
||||
// MobID,SpriteID,Sex,Hair_Style,Hair_Color,Weapon,Shield,Head_Top,Head_Middle,Head_Bottom,Option,Dye_Color
|
||||
//
|
||||
// SpriteID is a job class value.
|
||||
// Weapon and Shield uses Item ID, while Head uses View ID.
|
||||
// Option for carts only works if you compiled your server for a packet version before 2012-02-01
|
||||
|
||||
//1002,1039 // Poring - Baphomet
|
||||
//1970,1002,10013 // Displays a Poring with a backpack
|
||||
|
||||
// Easter Event Monsters
|
||||
//1920,1047,0
|
||||
//1921,1093,0
|
||||
|
||||
// rAthena Dev Team
|
||||
// Valaris
|
||||
//1900,4013,1,1,1,1254,0,67,12,54,16,1
|
||||
// Valaris Worshiper
|
||||
//1901,6,1,1,1,1219,2101,67,12,54,0,1
|
||||
// MC Cameri
|
||||
//1902,14,1,6,6,1101,2105,0,0,0,32,3
|
||||
// Poki#3
|
||||
//1903,4012,1,21,0,1720,0,102,184,57,16,0
|
||||
// Sentry
|
||||
//1904,1286,0
|
||||
|
||||
// iRO Halloween Event 2008
|
||||
//3000,1015,0
|
||||
//3001,1036,0
|
||||
//3002,1298,0
|
||||
|
||||
// iRO Halloween Event 2009
|
||||
//3014,1179,0
|
||||
//3015,1272,0
|
108
doc/mob_avail.txt
Normal file
108
doc/mob_avail.txt
Normal file
@ -0,0 +1,108 @@
|
||||
//===== rAthena Documentation ================================
|
||||
//= rAthena Monster Availability Database Reference
|
||||
//===== By: ==================================================
|
||||
//= rAthena Dev Team
|
||||
//===== Last Updated: ========================================
|
||||
//= 20191213
|
||||
//===== Description: =========================================
|
||||
//= Explanation of the mob_avail.yml file and structure.
|
||||
//============================================================
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Mob: The AEGIS name of the monster.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Sprite: The name of the sprite the monster will be changed to.
|
||||
|
||||
This can be another mob, a player (prefixed with 'JOB_'), or an NPC. When using an NPC sprite,
|
||||
the prefix is not required in the mob_avail database as the script engine will strip it.
|
||||
|
||||
Example:
|
||||
- Mob: POPORING
|
||||
Sprite: PORING # This will change the Poporing into a Poring.
|
||||
|
||||
- Mob: PORING
|
||||
Sprite: JOB_STALKER # This will change the Poring into a Stalker.
|
||||
|
||||
- Mob: WOLF
|
||||
Sprite: 4_M_BARBER # This will change the Wolf into the Barber NPC.
|
||||
|
||||
These constants can be found in src/map/script_constants.hpp.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Sex: The sex to be displayed if the Sprite is a player.
|
||||
|
||||
Valid types:
|
||||
Female
|
||||
Male
|
||||
|
||||
---------------------------------------
|
||||
|
||||
HairStyle: The hair style ID to be displayed if the Sprite is a player.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
HairColor: The hair color ID to be displayed if the Sprite is a player.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
ClothColor: The cloth color ID to be displayed if the Sprite is a player.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Weapon: The AEGIS name of the item to be displayed if the Sprite is a player.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Shield: The AEGIS name of the item to be displayed if the Sprite is a player.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
HeadTop: The AEGIS name of the item to be displayed if the Sprite is a player.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
HeadMid: The AEGIS name of the item to be displayed if the Sprite is a player.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
HeadLow: The AEGIS name of the item to be displayed if the Sprite is a player.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
PetEquip: The AEGIS name of the item to be displayed if the Mob is a valid pet.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
Options: The view option to be applied to the Mob.
|
||||
|
||||
Valid types:
|
||||
Sight
|
||||
Cart1
|
||||
Falcon
|
||||
Riding
|
||||
Cart2
|
||||
Cart3
|
||||
Cart4
|
||||
Cart5
|
||||
Orcish
|
||||
Wedding
|
||||
Ruwach
|
||||
Flying
|
||||
Xmas
|
||||
Transform
|
||||
Summer
|
||||
Dragon1
|
||||
Wug
|
||||
WugRider
|
||||
MadoGear
|
||||
Dragon2
|
||||
Dragon3
|
||||
Dragon4
|
||||
Dragon5
|
||||
Hanbok
|
||||
Oktoberfest
|
||||
Summer2
|
@ -7979,6 +7979,8 @@ Parameters (indexes) for monsters are:
|
||||
UMOB_ADELAY
|
||||
UMOB_DMOTION
|
||||
UMOB_TARGETID
|
||||
UMOB_ROBE
|
||||
UMOB_BODY2
|
||||
|
||||
-----
|
||||
|
||||
@ -8152,7 +8154,6 @@ Parameter (indexes) for elementals are:
|
||||
-----
|
||||
|
||||
Parameter (indexes) for NPCs are:
|
||||
UNPC_DISPLAY
|
||||
UNPC_LEVEL
|
||||
UNPC_HP
|
||||
UNPC_MAXHP
|
||||
@ -8185,6 +8186,19 @@ Parameter (indexes) for NPCs are:
|
||||
UNPC_AMOTION
|
||||
UNPC_ADELAY
|
||||
UNPC_DMOTION
|
||||
UNPC_SEX
|
||||
UNPC_CLASS
|
||||
UNPC_HAIRSTYLE
|
||||
UNPC_HAIRCOLOR
|
||||
UNPC_HEADBOTTOM
|
||||
UNPC_HEADMIDDLE
|
||||
UNPC_HEADTOP
|
||||
UNPC_CLOTHCOLOR
|
||||
UNPC_SHIELD
|
||||
UNPC_WEAPON
|
||||
UNPC_ROBE
|
||||
UNPC_BODY2
|
||||
UNPC_DEADSIT
|
||||
|
||||
*Notes:
|
||||
- *_SIZE: small (0); medium (1); large (2)
|
||||
@ -8201,12 +8215,14 @@ Parameter (indexes) for NPCs are:
|
||||
- *_AMOTION: see doc/mob_db.txt
|
||||
- *_ADELAY: see doc/mob_db.txt
|
||||
- *_DMOTION: see doc/mob_db.txt
|
||||
- *_BODY2: enable (1) the alternate display, or disable (0)
|
||||
|
||||
- UMOB_AI: none (0); attack (1); marine sphere (2); flora (3); zanzou (4); legion (5); faw (6)
|
||||
- UMOB_SCOPTION: see the 'Variables' section at the top of this document
|
||||
- UMOB_SLAVECPYMSTRMD: make the slave copy the master's mode (1), or not (0)
|
||||
|
||||
- UNPC_PLUSALLSTAT: same as 'bAllStats'; increases/decreses all stats by given amount
|
||||
- UNPC_PLUSALLSTAT: same as 'bAllStats'; increases/decreases all stats by given amount
|
||||
- UNPC_DEADSIT: stand (0), dead (1), sit (2)
|
||||
|
||||
Example:
|
||||
// Spawn some Porings and save the Game ID.
|
||||
|
22
doc/yaml/db/mob_avail.yml
Normal file
22
doc/yaml/db/mob_avail.yml
Normal file
@ -0,0 +1,22 @@
|
||||
###########################################################################
|
||||
# Mob Availability and Alias Database
|
||||
###########################################################################
|
||||
#
|
||||
# Mob Availability and Alias Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Mob Mob to adjust.
|
||||
# Sprite Sprite which will be sent to the client instead of Mob.
|
||||
# Sex Sex (if Sprite is a player). (Default: Female)
|
||||
# HairStyle Hair Style ID (if Sprite is a player). (Default: 0)
|
||||
# HairColor Hair Color ID (if Sprite is a player). (Default: 0)
|
||||
# ClothColor Cloth Color ID (if Sprite is a player). (Default: 0)
|
||||
# Weapon Item name of weapon (if Sprite is a player). (Default: 0)
|
||||
# Shield Item name of shield (if Sprite is a player). (Default: 0)
|
||||
# HeadTop Item name of headgear (if Sprite is a player). (Default: 0)
|
||||
# HeadMid Item name of headgear (if Sprite is a player). (Default: 0)
|
||||
# HeadLow Item name of headgear (if Sprite is a player). (Default: 0)
|
||||
# PetEquip Item name of pet equipment (if Mob is a valid pet). (Default: 0)
|
||||
# Options: Set an option for an object. (Optional)
|
||||
# <Option>: bool
|
||||
###########################################################################
|
@ -283,7 +283,12 @@ static inline unsigned char clif_bl_type(struct block_list *bl) {
|
||||
case BL_SKILL: return 0x3; //SKILL_TYPE
|
||||
case BL_CHAT: return 0x4; //UNKNOWN_TYPE
|
||||
case BL_MOB: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x5; //NPC_MOB_TYPE
|
||||
case BL_NPC: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x6; //NPC_EVT_TYPE
|
||||
case BL_NPC:
|
||||
#if PACKETVER >= 20170726
|
||||
return 0x6; //NPC_EVT_TYPE
|
||||
#else
|
||||
return (pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x6);
|
||||
#endif
|
||||
case BL_PET: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE
|
||||
case BL_HOM: return 0x8; //NPC_HOM_TYPE
|
||||
case BL_MER: return 0x9; //NPC_MERSOL_TYPE
|
||||
@ -1144,7 +1149,7 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool
|
||||
WBUFW(buf,53) = (sd ? sd->status.font : 0);
|
||||
#endif
|
||||
#if PACKETVER >= 20120221
|
||||
if ( battle_config.monster_hp_bars_info && !map_getmapflag(bl->m, MF_HIDEMOBHPBAR) && bl->type == BL_MOB && (status_get_hp(bl) < status_get_max_hp(bl)) ) {
|
||||
if ( battle_config.monster_hp_bars_info && bl->type == BL_MOB && !map_getmapflag(bl->m, MF_HIDEMOBHPBAR) && (status_get_hp(bl) < status_get_max_hp(bl)) ) {
|
||||
WBUFL(buf,55) = status_get_max_hp(bl); // maxHP
|
||||
WBUFL(buf,59) = status_get_hp(bl); // HP
|
||||
} else {
|
||||
@ -1447,7 +1452,7 @@ int clif_spawn(struct block_list *bl)
|
||||
if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE))
|
||||
return 0;
|
||||
|
||||
len = clif_set_unit_idle(bl, buf,true);
|
||||
len = clif_set_unit_idle(bl, buf, (bl->type == BL_NPC && vd->dead_sit ? false : true));
|
||||
clif_send(buf, len, bl, AREA_WOS);
|
||||
if (disguised(bl))
|
||||
clif_setdisguise(bl, buf, len);
|
||||
@ -3606,7 +3611,7 @@ void clif_changelook(struct block_list *bl, int type, int val) {
|
||||
#if PACKETVER < 20150513
|
||||
return;
|
||||
#else
|
||||
if (val && sd->sc.option&OPTION_COSTUME)
|
||||
if (val && sd && sd->sc.option&OPTION_COSTUME)
|
||||
val = 0;
|
||||
vd->body_style = val;
|
||||
#endif
|
||||
@ -3620,17 +3625,19 @@ void clif_changelook(struct block_list *bl, int type, int val) {
|
||||
#if PACKETVER < 4
|
||||
clif_sprite_change(bl, bl->id, type, val, 0, target);
|
||||
#else
|
||||
if(type == LOOK_WEAPON || type == LOOK_SHIELD) {
|
||||
nullpo_retv(vd);
|
||||
type = LOOK_WEAPON;
|
||||
val = vd->weapon;
|
||||
val2 = vd->shield;
|
||||
}
|
||||
if( disguised(bl) ) {
|
||||
clif_sprite_change(bl, bl->id, type, val, val2, AREA_WOS);
|
||||
clif_sprite_change(bl, -bl->id, type, val, val2, SELF);
|
||||
if (bl->type != BL_NPC) {
|
||||
if (type == LOOK_WEAPON || type == LOOK_SHIELD) {
|
||||
type = LOOK_WEAPON;
|
||||
val = (vd ? vd->weapon : 0);
|
||||
val2 = (vd ? vd->shield : 0);
|
||||
}
|
||||
if (disguised(bl)) {
|
||||
clif_sprite_change(bl, bl->id, type, val, val2, AREA_WOS);
|
||||
clif_sprite_change(bl, -bl->id, type, val, val2, SELF);
|
||||
} else
|
||||
clif_sprite_change(bl, bl->id, type, val, val2, target);
|
||||
} else
|
||||
clif_sprite_change(bl, bl->id, type, val, val2, target);
|
||||
unit_refresh(bl);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -340,7 +340,7 @@
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\map_index.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\map_index.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mercenary_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mercenary_db.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mercenary_skill_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mercenary_skill_db.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mob_avail.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mob_avail.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mob_avail.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mob_avail.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mob_boss.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mob_boss.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mob_branch.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mob_branch.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\mob_chat_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\mob_chat_db.txt')" />
|
||||
|
343
src/map/mob.cpp
343
src/map/mob.cpp
@ -4348,55 +4348,308 @@ static int mob_read_sqldb(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* MOB display graphic change data reading
|
||||
*------------------------------------------*/
|
||||
static bool mob_readdb_mobavail(char* str[], int columns, int current)
|
||||
{
|
||||
int mob_id, sprite_id;
|
||||
struct mob_db *db;
|
||||
const std::string MobAvailDatabase::getDefaultLocation() {
|
||||
return std::string(db_path) + "/" + DBIMPORT + "/mob_avail.yml";
|
||||
}
|
||||
|
||||
mob_id = atoi(str[0]);
|
||||
/**
|
||||
* Reads and parses an entry from the mob_avail.
|
||||
* @param node: YAML node containing the entry.
|
||||
* @return count of successfully parsed rows
|
||||
*/
|
||||
uint64 MobAvailDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
std::string mob_name;
|
||||
|
||||
if( (db=mob_db(mob_id)) == NULL) // invalid class (probably undefined in db)
|
||||
{
|
||||
ShowWarning("mob_readdb_mobavail: Unknown mob id %d.\n", mob_id);
|
||||
return false;
|
||||
if (!this->asString(node, "Mob", mob_name))
|
||||
return 0;
|
||||
|
||||
uint32 mob_id = mobdb_searchname(mob_name.c_str());
|
||||
|
||||
if (mob_id == 0) {
|
||||
this->invalidWarning(node["Mob"], "Unknown mob %s.\n", mob_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
sprite_id = atoi(str[1]);
|
||||
struct mob_db *mob = mob_db(mob_id);
|
||||
|
||||
memset(&db->vd, 0, sizeof(struct view_data));
|
||||
db->vd.class_ = sprite_id;
|
||||
if (this->nodeExists(node, "Sprite")) {
|
||||
std::string sprite;
|
||||
|
||||
//Player sprites
|
||||
if(pcdb_checkid(sprite_id) && columns==12) {
|
||||
db->vd.sex=atoi(str[2]);
|
||||
db->vd.hair_style=atoi(str[3]);
|
||||
db->vd.hair_color=atoi(str[4]);
|
||||
db->vd.weapon=atoi(str[5]);
|
||||
db->vd.shield=atoi(str[6]);
|
||||
db->vd.head_top=atoi(str[7]);
|
||||
db->vd.head_mid=atoi(str[8]);
|
||||
db->vd.head_bottom=atoi(str[9]);
|
||||
db->option=atoi(str[10])&~(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE);
|
||||
db->vd.cloth_color=atoi(str[11]); // Monster player dye option - Valaris
|
||||
if (!this->asString(node, "Sprite", sprite))
|
||||
return 0;
|
||||
|
||||
int constant;
|
||||
|
||||
if (script_get_constant(sprite.c_str(), &constant)) {
|
||||
if (npcdb_checkid(constant) == 0 && pcdb_checkid(constant) == 0) {
|
||||
this->invalidWarning(node["Sprite"], "Unknown sprite constant %s.\n", sprite.c_str());
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
constant = mobdb_searchname(sprite.c_str());
|
||||
|
||||
if (constant == 0) {
|
||||
this->invalidWarning(node["Sprite"], "Unknown mob sprite constant %s.\n", sprite.c_str());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
mob->vd.class_ = constant;
|
||||
} else {
|
||||
this->invalidWarning(node["Sprite"], "Sprite is missing.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "Sex")) {
|
||||
if (pcdb_checkid(mob->vd.class_) == 0) {
|
||||
this->invalidWarning(node["Sex"], "Sex is only applicable to Job sprites.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string sex;
|
||||
|
||||
if (!this->asString(node, "Sex", sex))
|
||||
return 0;
|
||||
|
||||
std::string sex_constant = "SEX_" + sex;
|
||||
|
||||
int constant;
|
||||
|
||||
if (!script_get_constant(sex_constant.c_str(), &constant)) {
|
||||
this->invalidWarning(node["Sex"], "Unknown sex constant %s.\n", sex.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (constant < SEX_FEMALE || constant > SEX_MALE) {
|
||||
this->invalidWarning(node["Sex"], "Sex %s is not valid.\n", sex.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
mob->vd.sex = constant;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "HairStyle")) {
|
||||
if (pcdb_checkid(mob->vd.class_) == 0) {
|
||||
this->invalidWarning(node["HairStyle"], "HairStyle is only applicable to Job sprites.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 hair_style;
|
||||
|
||||
if (!this->asUInt16(node, "HairStyle", hair_style))
|
||||
return 0;
|
||||
|
||||
if (hair_style < MIN_HAIR_STYLE || hair_style > MAX_HAIR_STYLE) {
|
||||
this->invalidWarning(node["HairStyle"], "HairStyle %d is out of range %d~%d. Setting to MIN_HAIR_STYLE.\n", hair_style, MIN_HAIR_STYLE, MAX_HAIR_STYLE);
|
||||
hair_style = MIN_HAIR_STYLE;
|
||||
}
|
||||
|
||||
mob->vd.hair_style = hair_style;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "HairColor")) {
|
||||
if (pcdb_checkid(mob->vd.class_) == 0) {
|
||||
this->invalidWarning(node["HairColor"], "HairColor is only applicable to Job sprites.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 hair_color;
|
||||
|
||||
if (!this->asUInt16(node, "HairColor", hair_color))
|
||||
return 0;
|
||||
|
||||
if (hair_color < MIN_HAIR_COLOR || hair_color > MAX_HAIR_COLOR) {
|
||||
this->invalidWarning(node["HairColor"], "HairColor %d is out of range %d~%d. Setting to MIN_HAIR_COLOR.\n", hair_color, MIN_HAIR_COLOR, MAX_HAIR_COLOR);
|
||||
hair_color = MIN_HAIR_COLOR;
|
||||
}
|
||||
|
||||
mob->vd.hair_color = hair_color;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "ClothColor")) {
|
||||
if (pcdb_checkid(mob->vd.class_) == 0) {
|
||||
this->invalidWarning(node["ClothColor"], "ClothColor is only applicable to Job sprites.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 cloth_color;
|
||||
|
||||
if (!this->asUInt32(node, "ClothColor", cloth_color))
|
||||
return 0;
|
||||
|
||||
if (cloth_color < MIN_CLOTH_COLOR || cloth_color > MAX_CLOTH_COLOR) {
|
||||
this->invalidWarning(node["ClothColor"], "ClothColor %d is out of range %d~%d. Setting to MIN_CLOTH_CLOR.\n", cloth_color, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
|
||||
cloth_color = MIN_CLOTH_COLOR;
|
||||
}
|
||||
|
||||
mob->vd.cloth_color = cloth_color;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "Weapon")) {
|
||||
if (pcdb_checkid(mob->vd.class_) == 0) {
|
||||
this->invalidWarning(node["Weapon"], "Weapon is only applicable to Job sprites.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string weapon;
|
||||
|
||||
if (!this->asString(node, "Weapon", weapon))
|
||||
return 0;
|
||||
|
||||
struct item_data *item = itemdb_searchname(weapon.c_str());
|
||||
|
||||
if (item == nullptr) {
|
||||
this->invalidWarning(node["Weapon"], "Weapon %s is not a valid item.\n", weapon.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
mob->vd.weapon = item->nameid;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "Shield")) {
|
||||
if (pcdb_checkid(mob->vd.class_) == 0) {
|
||||
this->invalidWarning(node["Shield"], "Shield is only applicable to Job sprites.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string shield;
|
||||
|
||||
if (!this->asString(node, "Shield", shield))
|
||||
return 0;
|
||||
|
||||
struct item_data *item = itemdb_searchname(shield.c_str());
|
||||
|
||||
if (item == nullptr) {
|
||||
this->invalidWarning(node["Shield"], "Shield %s is not a valid item.\n", shield.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
mob->vd.shield = item->nameid;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "HeadTop")) {
|
||||
if (pcdb_checkid(mob->vd.class_) == 0) {
|
||||
this->invalidWarning(node["HeadTop"], "HeadTop is only applicable to Job sprites.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string head;
|
||||
|
||||
if (!this->asString(node, "HeadTop", head))
|
||||
return 0;
|
||||
|
||||
struct item_data *item;
|
||||
|
||||
if ((item = itemdb_searchname(head.c_str())) == nullptr) {
|
||||
this->invalidWarning(node["HeadTop"], "HeadTop %s is not a valid item.\n", head.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
mob->vd.head_top = item->look;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "HeadMid")) {
|
||||
if (pcdb_checkid(mob->vd.class_) == 0) {
|
||||
this->invalidWarning(node["HeadMid"], "HeadMid is only applicable to Job sprites.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string head;
|
||||
|
||||
if (!this->asString(node, "HeadMid", head))
|
||||
return 0;
|
||||
|
||||
struct item_data *item = itemdb_searchname(head.c_str());
|
||||
|
||||
if (item == nullptr) {
|
||||
this->invalidWarning(node["HeadMid"], "HeadMid %s is not a valid item.\n", head.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
mob->vd.head_mid = item->look;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "HeadLow")) {
|
||||
if (pcdb_checkid(mob->vd.class_) == 0) {
|
||||
this->invalidWarning(node["HeadLow"], "HeadLow is only applicable to Job sprites.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string head;
|
||||
|
||||
if (!this->asString(node, "HeadLow", head))
|
||||
return 0;
|
||||
|
||||
struct item_data *item = itemdb_searchname(head.c_str());
|
||||
|
||||
if (item == nullptr) {
|
||||
this->invalidWarning(node["HeadLow"], "HeadLow %s is not a valid item.\n", head.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
mob->vd.head_bottom = item->look;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "PetEquip")) {
|
||||
std::shared_ptr<s_pet_db> pet_db_ptr = pet_db.find(mob->vd.class_);
|
||||
|
||||
if (pet_db_ptr == nullptr) {
|
||||
this->invalidWarning(node["PetEquip"], "PetEquip is only applicable to defined pets.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string equipment;
|
||||
|
||||
if (!this->asString(node, "PetEquip", equipment))
|
||||
return 0;
|
||||
|
||||
struct item_data *item = itemdb_searchname(equipment.c_str());
|
||||
|
||||
if (item == nullptr) {
|
||||
this->invalidWarning(node["PetEquip"], "PetEquip %s is not a valid item.\n", equipment.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
mob->vd.head_bottom = item->nameid;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "Options")) {
|
||||
for (const auto &optionNode : node["Options"]) {
|
||||
std::string option = optionNode.first.as<std::string>();
|
||||
std::string option_constant = "OPTION_" + option;
|
||||
int constant;
|
||||
|
||||
if (!script_get_constant(option_constant.c_str(), &constant)) {
|
||||
this->invalidWarning(optionNode, "Unknown option constant %s, skipping.\n", option.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
bool active;
|
||||
|
||||
if (!this->asBool(node, option, active))
|
||||
continue;
|
||||
|
||||
#ifdef NEW_CARTS
|
||||
if( db->option & OPTION_CART ){
|
||||
ShowWarning("mob_readdb_mobavail: You tried to use a cart for mob id %d. This does not work with setting an option anymore.\n", mob_id );
|
||||
db->option &= ~OPTION_CART;
|
||||
}
|
||||
if (constant & OPTION_CART) {
|
||||
this->invalidWarning(optionNode, "OPTION_CART was replace by SC_PUSH_CART, skipping.\n");
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if(columns==3)
|
||||
db->vd.head_bottom=atoi(str[2]); // mob equipment [Valaris]
|
||||
else if( columns != 2 )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
if (active)
|
||||
mob->option |= constant;
|
||||
else
|
||||
mob->option &= ~constant;
|
||||
}
|
||||
|
||||
mob->option &= ~(OPTION_HIDE | OPTION_CLOAK | OPTION_INVISIBLE | OPTION_CHASEWALK); // Remove hiding types
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
MobAvailDatabase mob_avail_db;
|
||||
|
||||
/*==========================================
|
||||
* Reading of random monster data
|
||||
* MobGroup,MobID,DummyName,Rate
|
||||
@ -5282,7 +5535,6 @@ static void mob_load(void)
|
||||
mob_readskilldb(dbsubpath2, silent);
|
||||
}
|
||||
|
||||
sv_readdb(dbsubpath1, "mob_avail.txt", ',', 2, 12, -1, &mob_readdb_mobavail,silent);
|
||||
sv_readdb(dbsubpath2, "mob_race2_db.txt", ',', 2, MAX_RACE2_MOBS, -1, &mob_readdb_race2, silent);
|
||||
sv_readdb(dbsubpath1, "mob_item_ratio.txt", ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, &mob_readdb_itemratio, silent);
|
||||
sv_readdb(dbsubpath1, "mob_chat_db.txt", '#', 3, 3, -1, &mob_parse_row_chatdb, silent);
|
||||
@ -5299,6 +5551,8 @@ static void mob_load(void)
|
||||
aFree(dbsubpath2);
|
||||
}
|
||||
|
||||
mob_avail_db.load();
|
||||
|
||||
mob_drop_ratio_adjust();
|
||||
mob_skill_db_set();
|
||||
}
|
||||
@ -5392,15 +5646,12 @@ static int mob_reload_sub( struct mob_data *md, va_list args ){
|
||||
static int mob_reload_sub_npc( struct npc_data *nd, va_list args ){
|
||||
// If the view data points to a mob
|
||||
if( mobdb_checkid(nd->class_) ){
|
||||
// Get the new view data from the mob database
|
||||
nd->vd = mob_get_viewdata(nd->class_);
|
||||
struct view_data *vd = mob_get_viewdata(nd->class_);
|
||||
|
||||
// If they are spawned right now
|
||||
if( nd->bl.prev != NULL ){
|
||||
// Respawn all NPCs on client side so that they are displayed correctly(if their view id changed)
|
||||
clif_clearunit_area(&nd->bl, CLR_OUTSIGHT);
|
||||
clif_spawn(&nd->bl);
|
||||
}
|
||||
if (vd) // Get the new view data from the mob database
|
||||
memcpy(&nd->vd, vd, sizeof(struct view_data));
|
||||
if (nd->bl.prev) // If they are spawned right now
|
||||
unit_refresh(&nd->bl); // Respawn all NPCs on client side so that they are displayed correctly(if their view id changed)
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "../common/database.hpp"
|
||||
#include "../common/mmo.hpp" // struct item
|
||||
#include "../common/timer.hpp"
|
||||
|
||||
@ -243,6 +244,17 @@ struct mob_data {
|
||||
int tomb_nid;
|
||||
};
|
||||
|
||||
class MobAvailDatabase : public YamlDatabase {
|
||||
public:
|
||||
MobAvailDatabase() : YamlDatabase("MOB_AVAIL_DB", 1) {
|
||||
|
||||
}
|
||||
|
||||
void clear() { };
|
||||
const std::string getDefaultLocation();
|
||||
uint64 parseBodyNode(const YAML::Node& node);
|
||||
};
|
||||
|
||||
enum e_mob_skill_target {
|
||||
MST_TARGET = 0,
|
||||
MST_RANDOM, //Random Target!
|
||||
|
@ -118,8 +118,12 @@ struct script_event_s{
|
||||
// Holds pointers to the commonly executed scripts for speedup. [Skotlex]
|
||||
std::map<enum npce_event, std::vector<struct script_event_s>> script_event;
|
||||
|
||||
struct view_data* npc_get_viewdata(int class_)
|
||||
{ //Returns the viewdata for normal npc classes.
|
||||
/**
|
||||
* Returns the viewdata for normal NPC classes.
|
||||
* @param class_: NPC class ID
|
||||
* @return viewdata or nullptr if the ID is invalid
|
||||
*/
|
||||
struct view_data* npc_get_viewdata(int class_) {
|
||||
if( class_ == JT_INVISIBLE )
|
||||
return &npc_viewdb[0];
|
||||
if (npcdb_checkid(class_)){
|
||||
@ -129,7 +133,7 @@ struct view_data* npc_get_viewdata(int class_)
|
||||
return &npc_viewdb[class_];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int npc_isnear_sub(struct block_list* bl, va_list args) {
|
||||
@ -2556,17 +2560,18 @@ int npc_parseview(const char* w4, const char* start, const char* buffer, const c
|
||||
* @return npc_data
|
||||
*/
|
||||
struct npc_data *npc_create_npc(int16 m, int16 x, int16 y){
|
||||
struct npc_data *nd;
|
||||
struct npc_data *nd = nullptr;
|
||||
|
||||
CREATE(nd, struct npc_data, 1);
|
||||
nd->bl.id = npc_get_new_npc_id();
|
||||
nd->bl.prev = nd->bl.next = NULL;
|
||||
nd->bl.prev = nd->bl.next = nullptr;
|
||||
nd->bl.m = m;
|
||||
nd->bl.x = x;
|
||||
nd->bl.y = y;
|
||||
nd->sc_display = NULL;
|
||||
nd->sc_display = nullptr;
|
||||
nd->sc_display_count = 0;
|
||||
nd->progressbar.timeout = 0;
|
||||
nd->vd = npc_viewdb[0]; // Default to JT_INVISIBLE
|
||||
|
||||
return nd;
|
||||
}
|
||||
@ -3749,14 +3754,9 @@ void npc_setclass(struct npc_data* nd, short class_)
|
||||
if( nd->class_ == class_ )
|
||||
return;
|
||||
|
||||
struct map_data *mapdata = map_getmapdata(nd->bl.m);
|
||||
|
||||
if( mapdata->users )
|
||||
clif_clearunit_area(&nd->bl, CLR_OUTSIGHT);// fade out
|
||||
nd->class_ = class_;
|
||||
status_set_viewdata(&nd->bl, class_);
|
||||
if( mapdata->users )
|
||||
clif_spawn(&nd->bl);// fade in
|
||||
unit_refresh(&nd->bl);
|
||||
}
|
||||
|
||||
// @commands (script based)
|
||||
|
@ -41,8 +41,8 @@ struct s_npc_buy_list {
|
||||
|
||||
struct npc_data {
|
||||
struct block_list bl;
|
||||
struct unit_data ud; //Because they need to be able to move....
|
||||
struct view_data *vd;
|
||||
struct unit_data ud; //Because they need to be able to move....
|
||||
struct view_data vd;
|
||||
struct status_change sc; //They can't have status changes, but.. they want the visual opt values.
|
||||
struct npc_data *master_nd;
|
||||
short class_,speed,instance_id;
|
||||
|
@ -16542,10 +16542,7 @@ BUILDIN_FUNC(setnpcdisplay)
|
||||
if( class_ != JT_FAKENPC && nd->class_ != class_ )
|
||||
npc_setclass(nd, class_);
|
||||
else if( size != -1 )
|
||||
{ // Required to update the visual size
|
||||
clif_clearunit_area(&nd->bl, CLR_OUTSIGHT);
|
||||
clif_spawn(&nd->bl);
|
||||
}
|
||||
unit_refresh(&nd->bl); // Required to update the visual size
|
||||
|
||||
script_pushint(st,0);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
@ -17609,6 +17606,8 @@ BUILDIN_FUNC(getunitdata)
|
||||
getunitdata_sub(UMOB_ADELAY, md->status.adelay);
|
||||
getunitdata_sub(UMOB_DMOTION, md->status.dmotion);
|
||||
getunitdata_sub(UMOB_TARGETID, md->target_id);
|
||||
getunitdata_sub(UMOB_ROBE, md->vd->robe);
|
||||
getunitdata_sub(UMOB_BODY2, md->vd->body_style);
|
||||
break;
|
||||
|
||||
case BL_HOM:
|
||||
@ -17797,7 +17796,6 @@ BUILDIN_FUNC(getunitdata)
|
||||
ShowWarning("buildin_getunitdata: Error in finding object BL_NPC!\n");
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
getunitdata_sub(UNPC_DISPLAY, nd->class_);
|
||||
getunitdata_sub(UNPC_LEVEL, nd->level);
|
||||
getunitdata_sub(UNPC_HP, nd->status.hp);
|
||||
getunitdata_sub(UNPC_MAXHP, nd->status.max_hp);
|
||||
@ -17830,6 +17828,19 @@ BUILDIN_FUNC(getunitdata)
|
||||
getunitdata_sub(UNPC_AMOTION, nd->status.amotion);
|
||||
getunitdata_sub(UNPC_ADELAY, nd->status.adelay);
|
||||
getunitdata_sub(UNPC_DMOTION, nd->status.dmotion);
|
||||
getunitdata_sub(UNPC_SEX, nd->vd.sex);
|
||||
getunitdata_sub(UNPC_CLASS, nd->vd.class_);
|
||||
getunitdata_sub(UNPC_HAIRSTYLE, nd->vd.hair_style);
|
||||
getunitdata_sub(UNPC_HAIRCOLOR, nd->vd.hair_color);
|
||||
getunitdata_sub(UNPC_HEADBOTTOM, nd->vd.head_bottom);
|
||||
getunitdata_sub(UNPC_HEADMIDDLE, nd->vd.head_mid);
|
||||
getunitdata_sub(UNPC_HEADTOP, nd->vd.head_top);
|
||||
getunitdata_sub(UNPC_CLOTHCOLOR, nd->vd.cloth_color);
|
||||
getunitdata_sub(UNPC_SHIELD, nd->vd.shield);
|
||||
getunitdata_sub(UNPC_WEAPON, nd->vd.weapon);
|
||||
getunitdata_sub(UNPC_ROBE, nd->vd.robe);
|
||||
getunitdata_sub(UNPC_BODY2, nd->vd.body_style);
|
||||
getunitdata_sub(UNPC_DEADSIT, nd->vd.dead_sit);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -17912,6 +17923,8 @@ BUILDIN_FUNC(setunitdata)
|
||||
case UMOB_CLOTHCOLOR:
|
||||
case UMOB_SHIELD:
|
||||
case UMOB_WEAPON:
|
||||
case UMOB_ROBE:
|
||||
case UMOB_BODY2:
|
||||
mob_set_dynamic_viewdata( md );
|
||||
break;
|
||||
}
|
||||
@ -17929,8 +17942,8 @@ BUILDIN_FUNC(setunitdata)
|
||||
case UMOB_MODE: md->base_status->mode = (enum e_mode)value; calc_status = true; break;
|
||||
case UMOB_AI: md->special_state.ai = (enum mob_ai)value; break;
|
||||
case UMOB_SCOPTION: md->sc.option = (unsigned short)value; break;
|
||||
case UMOB_SEX: md->vd->sex = (char)value; clif_clearunit_area(bl, CLR_OUTSIGHT); clif_spawn(bl); break;
|
||||
case UMOB_CLASS: status_set_viewdata(bl, (unsigned short)value); clif_clearunit_area(bl, CLR_OUTSIGHT); clif_spawn(bl); break;
|
||||
case UMOB_SEX: md->vd->sex = (char)value; unit_refresh(bl); break;
|
||||
case UMOB_CLASS: status_set_viewdata(bl, (unsigned short)value); unit_refresh(bl); break;
|
||||
case UMOB_HAIRSTYLE: clif_changelook(bl, LOOK_HAIR, (unsigned short)value); break;
|
||||
case UMOB_HAIRCOLOR: clif_changelook(bl, LOOK_HAIR_COLOR, (unsigned short)value); break;
|
||||
case UMOB_HEADBOTTOM: clif_changelook(bl, LOOK_HEAD_BOTTOM, (unsigned short)value); break;
|
||||
@ -17987,6 +18000,8 @@ BUILDIN_FUNC(setunitdata)
|
||||
mob_target(md,target,0);
|
||||
break;
|
||||
}
|
||||
case UMOB_ROBE: clif_changelook(bl, LOOK_ROBE, (unsigned short)value); break;
|
||||
case UMOB_BODY2: clif_changelook(bl, LOOK_BODY2, (unsigned short)value); break;
|
||||
default:
|
||||
ShowError("buildin_setunitdata: Unknown data identifier %d for BL_MOB.\n", type);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
@ -18233,7 +18248,6 @@ BUILDIN_FUNC(setunitdata)
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
switch (type) {
|
||||
case UNPC_DISPLAY: status_set_viewdata(bl, (unsigned short)value); break;
|
||||
case UNPC_LEVEL: nd->level = (unsigned int)value; break;
|
||||
case UNPC_HP: nd->status.hp = (unsigned int)value; status_set_hp(bl, (unsigned int)value, 0); break;
|
||||
case UNPC_MAXHP: nd->status.hp = nd->status.max_hp = (unsigned int)value; status_set_maxhp(bl, (unsigned int)value, 0); break;
|
||||
@ -18265,6 +18279,19 @@ BUILDIN_FUNC(setunitdata)
|
||||
case UNPC_AMOTION: nd->status.amotion = (short)value; break;
|
||||
case UNPC_ADELAY: nd->status.adelay = (short)value; break;
|
||||
case UNPC_DMOTION: nd->status.dmotion = (short)value; break;
|
||||
case UNPC_SEX: nd->vd.sex = (char)value; unit_refresh(bl); break;
|
||||
case UNPC_CLASS: npc_setclass(nd, (short)value); break;
|
||||
case UNPC_HAIRSTYLE: clif_changelook(bl, LOOK_HAIR, (unsigned short)value); break;
|
||||
case UNPC_HAIRCOLOR: clif_changelook(bl, LOOK_HAIR_COLOR, (unsigned short)value); break;
|
||||
case UNPC_HEADBOTTOM: clif_changelook(bl, LOOK_HEAD_BOTTOM, (unsigned short)value); break;
|
||||
case UNPC_HEADMIDDLE: clif_changelook(bl, LOOK_HEAD_MID, (unsigned short)value); break;
|
||||
case UNPC_HEADTOP: clif_changelook(bl, LOOK_HEAD_TOP, (unsigned short)value); break;
|
||||
case UNPC_CLOTHCOLOR: clif_changelook(bl, LOOK_CLOTHES_COLOR, (unsigned short)value); break;
|
||||
case UNPC_SHIELD: clif_changelook(bl, LOOK_SHIELD, (unsigned short)value); break;
|
||||
case UNPC_WEAPON: clif_changelook(bl, LOOK_WEAPON, (unsigned short)value); break;
|
||||
case UNPC_ROBE: clif_changelook(bl, LOOK_ROBE, (unsigned short)value); break;
|
||||
case UNPC_BODY2: clif_changelook(bl, LOOK_BODY2, (unsigned short)value); break;
|
||||
case UNPC_DEADSIT: nd->vd.dead_sit = (char)value; unit_refresh(bl); break;
|
||||
default:
|
||||
ShowError("buildin_setunitdata: Unknown data identifier %d for BL_NPC.\n", type);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
|
@ -476,6 +476,8 @@ enum unitdata_mobtypes {
|
||||
UMOB_ADELAY,
|
||||
UMOB_DMOTION,
|
||||
UMOB_TARGETID,
|
||||
UMOB_ROBE,
|
||||
UMOB_BODY2,
|
||||
};
|
||||
|
||||
enum unitdata_homuntypes {
|
||||
@ -644,8 +646,7 @@ enum unitdata_elemtypes {
|
||||
};
|
||||
|
||||
enum unitdata_npctypes {
|
||||
UNPC_DISPLAY = 0,
|
||||
UNPC_LEVEL,
|
||||
UNPC_LEVEL = 0,
|
||||
UNPC_HP,
|
||||
UNPC_MAXHP,
|
||||
UNPC_MAPID,
|
||||
@ -677,6 +678,19 @@ enum unitdata_npctypes {
|
||||
UNPC_AMOTION,
|
||||
UNPC_ADELAY,
|
||||
UNPC_DMOTION,
|
||||
UNPC_SEX,
|
||||
UNPC_CLASS,
|
||||
UNPC_HAIRSTYLE,
|
||||
UNPC_HAIRCOLOR,
|
||||
UNPC_HEADBOTTOM,
|
||||
UNPC_HEADMIDDLE,
|
||||
UNPC_HEADTOP,
|
||||
UNPC_CLOTHCOLOR,
|
||||
UNPC_SHIELD,
|
||||
UNPC_WEAPON,
|
||||
UNPC_ROBE,
|
||||
UNPC_BODY2,
|
||||
UNPC_DEADSIT,
|
||||
};
|
||||
|
||||
enum navigation_service {
|
||||
|
@ -3964,9 +3964,14 @@
|
||||
export_constant(OPTION_SIGHT);
|
||||
export_constant(OPTION_HIDE);
|
||||
export_constant(OPTION_CLOAK);
|
||||
export_constant(OPTION_CART1);
|
||||
export_constant(OPTION_FALCON);
|
||||
export_constant(OPTION_RIDING);
|
||||
export_constant(OPTION_INVISIBLE);
|
||||
export_constant(OPTION_CART2);
|
||||
export_constant(OPTION_CART3);
|
||||
export_constant(OPTION_CART4);
|
||||
export_constant(OPTION_CART5);
|
||||
export_constant(OPTION_ORCISH);
|
||||
export_constant(OPTION_WEDDING);
|
||||
export_constant(OPTION_RUWACH);
|
||||
@ -3985,6 +3990,7 @@
|
||||
export_constant(OPTION_DRAGON5);
|
||||
export_constant(OPTION_HANBOK);
|
||||
export_constant(OPTION_OKTOBERFEST);
|
||||
export_constant(OPTION_SUMMER2);
|
||||
|
||||
/* status option compounds */
|
||||
export_constant(OPTION_DRAGON);
|
||||
@ -4059,6 +4065,8 @@
|
||||
export_constant(UMOB_ADELAY);
|
||||
export_constant(UMOB_DMOTION);
|
||||
export_constant(UMOB_TARGETID);
|
||||
export_constant(UMOB_ROBE);
|
||||
export_constant(UMOB_BODY2);
|
||||
|
||||
/* unit control - homunculus */
|
||||
export_constant(UHOM_SIZE);
|
||||
@ -4222,7 +4230,7 @@
|
||||
export_constant(UELE_TARGETID);
|
||||
|
||||
/* unit control - NPC */
|
||||
export_constant(UNPC_DISPLAY);
|
||||
export_deprecated_constant3("UNPC_DISPLAY", UNPC_CLASS, "UNPC_CLASS");
|
||||
export_constant(UNPC_LEVEL);
|
||||
export_constant(UNPC_HP);
|
||||
export_constant(UNPC_MAXHP);
|
||||
@ -4255,6 +4263,19 @@
|
||||
export_constant(UNPC_AMOTION);
|
||||
export_constant(UNPC_ADELAY);
|
||||
export_constant(UNPC_DMOTION);
|
||||
export_constant(UNPC_SEX);
|
||||
export_constant(UNPC_CLASS);
|
||||
export_constant(UNPC_HAIRSTYLE);
|
||||
export_constant(UNPC_HAIRCOLOR);
|
||||
export_constant(UNPC_HEADBOTTOM);
|
||||
export_constant(UNPC_HEADMIDDLE);
|
||||
export_constant(UNPC_HEADTOP);
|
||||
export_constant(UNPC_CLOTHCOLOR);
|
||||
export_constant(UNPC_SHIELD);
|
||||
export_constant(UNPC_WEAPON);
|
||||
export_constant(UNPC_ROBE);
|
||||
export_constant(UNPC_BODY2);
|
||||
export_constant(UNPC_DEADSIT);
|
||||
|
||||
export_constant(NAV_NONE);
|
||||
export_constant(NAV_AIRSHIP_ONLY);
|
||||
@ -4954,7 +4975,9 @@
|
||||
|
||||
/* NPC view ids */
|
||||
// Special macro to strip the prefix 'JT_'
|
||||
#define export_constant_npc(a) export_constant_offset(a,3)
|
||||
#if !defined(export_constant_npc)
|
||||
#define export_constant_npc(a) export_constant_offset(a,3)
|
||||
#endif
|
||||
|
||||
export_constant_npc(JT_WARPNPC);
|
||||
export_constant_npc(JT_1_ETC_01);
|
||||
|
@ -7797,7 +7797,7 @@ struct view_data* status_get_viewdata(struct block_list *bl)
|
||||
case BL_PC: return &((TBL_PC*)bl)->vd;
|
||||
case BL_MOB: return ((TBL_MOB*)bl)->vd;
|
||||
case BL_PET: return &((TBL_PET*)bl)->vd;
|
||||
case BL_NPC: return ((TBL_NPC*)bl)->vd;
|
||||
case BL_NPC: return &((TBL_NPC*)bl)->vd;
|
||||
case BL_HOM: return ((TBL_HOM*)bl)->vd;
|
||||
case BL_MER: return ((TBL_MER*)bl)->vd;
|
||||
case BL_ELEM: return ((TBL_ELEM*)bl)->vd;
|
||||
@ -7861,10 +7861,10 @@ void status_set_viewdata(struct block_list *bl, int class_)
|
||||
sd->vd.head_top = sd->status.head_top;
|
||||
sd->vd.head_mid = sd->status.head_mid;
|
||||
sd->vd.head_bottom = sd->status.head_bottom;
|
||||
sd->vd.hair_style = cap_value(sd->status.hair,0,battle_config.max_hair_style);
|
||||
sd->vd.hair_color = cap_value(sd->status.hair_color,0,battle_config.max_hair_color);
|
||||
sd->vd.cloth_color = cap_value(sd->status.clothes_color,0,battle_config.max_cloth_color);
|
||||
sd->vd.body_style = cap_value(sd->status.body,0,battle_config.max_body_style);
|
||||
sd->vd.hair_style = cap_value(sd->status.hair, MIN_HAIR_STYLE, MAX_HAIR_STYLE);
|
||||
sd->vd.hair_color = cap_value(sd->status.hair_color, MIN_HAIR_COLOR, MAX_HAIR_COLOR);
|
||||
sd->vd.cloth_color = cap_value(sd->status.clothes_color, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
|
||||
sd->vd.body_style = cap_value(sd->status.body, MIN_BODY_STYLE, MAX_BODY_STYLE);
|
||||
sd->vd.sex = sd->status.sex;
|
||||
|
||||
if (sd->vd.cloth_color) {
|
||||
@ -7898,6 +7898,8 @@ void status_set_viewdata(struct block_list *bl, int class_)
|
||||
mob_set_dynamic_viewdata( md );
|
||||
|
||||
md->vd->class_ = class_;
|
||||
md->vd->hair_style = cap_value(md->vd->hair_style, MIN_HAIR_STYLE, MAX_HAIR_STYLE);
|
||||
md->vd->hair_color = cap_value(md->vd->hair_color, MIN_HAIR_COLOR, MAX_HAIR_COLOR);
|
||||
}else
|
||||
ShowError("status_set_viewdata (MOB): No view data for class %d\n", class_);
|
||||
}
|
||||
@ -7923,15 +7925,18 @@ void status_set_viewdata(struct block_list *bl, int class_)
|
||||
{
|
||||
TBL_NPC* nd = (TBL_NPC*)bl;
|
||||
if (vd)
|
||||
nd->vd = vd;
|
||||
else {
|
||||
ShowError("status_set_viewdata (NPC): No view data for class %d\n", class_);
|
||||
memcpy(&nd->vd, vd, sizeof(struct view_data));
|
||||
else if (pcdb_checkid(class_)) {
|
||||
memset(&nd->vd, 0, sizeof(struct view_data));
|
||||
nd->vd.class_ = class_;
|
||||
nd->vd.hair_style = cap_value(nd->vd.hair_style, MIN_HAIR_STYLE, MAX_HAIR_STYLE);
|
||||
} else {
|
||||
if (bl->m >= 0)
|
||||
ShowDebug("Source (NPC): %s at %s (%d,%d)\n", nd->name, map_mapid2mapname(bl->m), bl->x, bl->y);
|
||||
else
|
||||
ShowDebug("Source (NPC): %s (invisible/not on a map)\n", nd->name);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BL_HOM:
|
||||
|
@ -3134,6 +3134,26 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the area with a change in display of a unit.
|
||||
* @bl: Object to update
|
||||
*/
|
||||
void unit_refresh(struct block_list *bl) {
|
||||
nullpo_retv(bl);
|
||||
|
||||
if (bl->m < 0)
|
||||
return;
|
||||
|
||||
struct map_data *mapdata = map_getmapdata(bl->m);
|
||||
|
||||
// Using CLR_TRICKDEAD because other flags show effects
|
||||
// Probably need to use another flag or other way to refresh it
|
||||
if (mapdata->users) {
|
||||
clif_clearunit_area(bl, CLR_TRICKDEAD); // Fade out
|
||||
clif_spawn(bl); // Fade in
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes units of a master when the master is removed from map
|
||||
* @param sd: Player
|
||||
|
@ -79,7 +79,7 @@ unsigned short
|
||||
cloth_color,
|
||||
body_style;
|
||||
char sex;
|
||||
unsigned dead_sit : 2;
|
||||
unsigned dead_sit : 2; // 0: Standing, 1: Dead, 2: Sitting
|
||||
};
|
||||
|
||||
/// Enum for unit_blown_immune
|
||||
@ -161,6 +161,7 @@ void unit_dataset(struct block_list *bl);
|
||||
// Remove unit
|
||||
struct unit_data* unit_bl2ud(struct block_list *bl);
|
||||
void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype);
|
||||
void unit_refresh(struct block_list *bl);
|
||||
void unit_free_pc(struct map_session_data *sd);
|
||||
#define unit_remove_map(bl,clrtype) unit_remove_map_(bl,clrtype,__FILE__,__LINE__,__func__)
|
||||
int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, int line, const char* func);
|
||||
|
@ -43,9 +43,9 @@
|
||||
#include "../map/npc.hpp"
|
||||
#include "../map/pc.hpp"
|
||||
#include "../map/pet.hpp"
|
||||
#include "../map/quest.hpp"
|
||||
#include "../map/script.hpp"
|
||||
#include "../map/storage.hpp"
|
||||
#include "../map/quest.hpp"
|
||||
|
||||
using namespace rathena;
|
||||
|
||||
@ -73,9 +73,11 @@ static bool skill_parse_row_magicmushroomdb(char* split[], int column, int curre
|
||||
static bool skill_parse_row_abradb(char* split[], int columns, int current);
|
||||
static bool skill_parse_row_improvisedb(char* split[], int columns, int current);
|
||||
static bool skill_parse_row_spellbookdb(char* split[], int columns, int current);
|
||||
static bool mob_readdb_mobavail(char *str[], int columns, int current);
|
||||
|
||||
// Constants for conversion
|
||||
std::unordered_map<uint16, std::string> aegis_itemnames;
|
||||
std::unordered_map<uint16, uint16> aegis_itemviewid;
|
||||
std::unordered_map<uint16, std::string> aegis_mobnames;
|
||||
std::unordered_map<uint16, std::string> aegis_skillnames;
|
||||
std::unordered_map<const char*, int32> constants;
|
||||
@ -218,6 +220,7 @@ int do_init( int argc, char** argv ){
|
||||
sv_readdb( path_db_import.c_str(), "skill_db.txt", ',', 18, 18, -1, parse_skill_constants, false );
|
||||
|
||||
// Load constants
|
||||
#define export_constant_npc(a) export_constant(a)
|
||||
#include "../map/script_constants.hpp"
|
||||
|
||||
std::vector<std::string> root_paths = {
|
||||
@ -262,6 +265,12 @@ int do_init( int argc, char** argv ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!process("MOB_AVAIL_DB", 1, root_paths, "mob_avail", [](const std::string& path, const std::string& name_ext) -> bool {
|
||||
return sv_readdb(path.c_str(), name_ext.c_str(), ',', 2, 12, -1, &mob_readdb_mobavail, false);
|
||||
})) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: add implementations ;-)
|
||||
|
||||
return 0;
|
||||
@ -419,6 +428,9 @@ static bool parse_item_constants( const char* path ){
|
||||
|
||||
aegis_itemnames[item_id] = std::string(name);
|
||||
|
||||
if (atoi(str[14]) & (EQP_HELM | EQP_COSTUME_HELM) && util::umap_find(aegis_itemviewid, (uint16)atoi(str[18])) == nullptr)
|
||||
aegis_itemviewid[atoi(str[18])] = item_id;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
@ -808,3 +820,233 @@ static bool skill_parse_row_spellbookdb(char* split[], int columns, int current)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Copied and adjusted from mob.cpp
|
||||
static bool mob_readdb_mobavail(char* str[], int columns, int current) {
|
||||
uint16 mob_id = atoi(str[0]);
|
||||
std::string *mob_name = util::umap_find(aegis_mobnames, mob_id);
|
||||
|
||||
if (mob_name == nullptr) {
|
||||
ShowWarning("mob_avail reading: Invalid mob-class %hu, Mob not read.\n", mob_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
body << YAML::Key << "Mob" << YAML::Value << *mob_name;
|
||||
|
||||
uint16 sprite_id = atoi(str[1]);
|
||||
std::string *sprite_name = util::umap_find(aegis_mobnames, sprite_id);
|
||||
|
||||
if (sprite_name == nullptr) {
|
||||
char *sprite = const_cast<char *>(constant_lookup(sprite_id, "JOB_"));
|
||||
|
||||
if (sprite == nullptr) {
|
||||
sprite = const_cast<char *>(constant_lookup(sprite_id, "JT_"));
|
||||
|
||||
if (sprite == nullptr) {
|
||||
ShowError("Sprite name %s is not known.\n", sprite);
|
||||
return false;
|
||||
}
|
||||
|
||||
sprite += 3; // Strip JT_ here because the script engine doesn't send this prefix for NPC.
|
||||
|
||||
body << YAML::Key << "Sprite" << YAML::Value << *sprite;
|
||||
} else
|
||||
body << YAML::Key << "Sprite" << YAML::Value << *sprite;
|
||||
} else
|
||||
body << YAML::Key << "Sprite" << YAML::Value << *sprite_name;
|
||||
|
||||
if (columns == 12) {
|
||||
body << YAML::Key << "Sex" << YAML::Value << (atoi(str[2]) ? "Male" : "Female");
|
||||
if (atoi(str[3]) != 0)
|
||||
body << YAML::Key << "HairStyle" << YAML::Value << atoi(str[3]);
|
||||
if (atoi(str[4]) != 0)
|
||||
body << YAML::Key << "HairColor" << YAML::Value << atoi(str[4]);
|
||||
if (atoi(str[11]) != 0)
|
||||
body << YAML::Key << "ClothColor" << YAML::Value << atoi(str[11]);
|
||||
|
||||
if (atoi(str[5]) != 0) {
|
||||
uint16 weapon_item_id = atoi(str[5]);
|
||||
std::string *weapon_item_name = util::umap_find(aegis_itemnames, weapon_item_id);
|
||||
|
||||
if (weapon_item_name == nullptr) {
|
||||
ShowError("Item name for item ID %hu (weapon) is not known.\n", weapon_item_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
body << YAML::Key << "Weapon" << YAML::Value << *weapon_item_name;
|
||||
}
|
||||
|
||||
if (atoi(str[6]) != 0) {
|
||||
uint16 shield_item_id = atoi(str[6]);
|
||||
std::string *shield_item_name = util::umap_find(aegis_itemnames, shield_item_id);
|
||||
|
||||
if (shield_item_name == nullptr) {
|
||||
ShowError("Item name for item ID %hu (shield) is not known.\n", shield_item_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
body << YAML::Key << "Shield" << YAML::Value << *shield_item_name;
|
||||
}
|
||||
|
||||
if (atoi(str[7]) != 0) {
|
||||
uint16 *headtop_item_id = util::umap_find(aegis_itemviewid, (uint16)atoi(str[7]));
|
||||
|
||||
if (headtop_item_id == nullptr) {
|
||||
ShowError("Item ID for view ID %hu (head top) is not known.\n", atoi(str[7]));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string *headtop_item_name = util::umap_find(aegis_itemnames, *headtop_item_id);
|
||||
|
||||
if (headtop_item_name == nullptr) {
|
||||
ShowError("Item name for item ID %hu (head top) is not known.\n", *headtop_item_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
body << YAML::Key << "HeadTop" << YAML::Value << *headtop_item_name;
|
||||
}
|
||||
|
||||
if (atoi(str[8]) != 0) {
|
||||
uint16 *headmid_item_id = util::umap_find(aegis_itemviewid, (uint16)atoi(str[8]));
|
||||
|
||||
if (headmid_item_id == nullptr) {
|
||||
ShowError("Item ID for view ID %hu (head mid) is not known.\n", atoi(str[8]));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string *headmid_item_name = util::umap_find(aegis_itemnames, *headmid_item_id);
|
||||
|
||||
if (headmid_item_name == nullptr) {
|
||||
ShowError("Item name for item ID %hu (head mid) is not known.\n", *headmid_item_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
body << YAML::Key << "HeadMid" << YAML::Value << *headmid_item_name;
|
||||
}
|
||||
|
||||
if (atoi(str[9]) != 0) {
|
||||
uint16 *headlow_item_id = util::umap_find(aegis_itemviewid, (uint16)atoi(str[9]));
|
||||
|
||||
if (headlow_item_id == nullptr) {
|
||||
ShowError("Item ID for view ID %hu (head low) is not known.\n", atoi(str[9]));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string *headlow_item_name = util::umap_find(aegis_itemnames, *headlow_item_id);
|
||||
|
||||
if (headlow_item_name == nullptr) {
|
||||
ShowError("Item name for item ID %hu (head low) is not known.\n", *headlow_item_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
body << YAML::Key << "HeadLow" << YAML::Value << *headlow_item_name;
|
||||
}
|
||||
|
||||
if (atoi(str[10]) != 0) {
|
||||
uint32 options = atoi(str[10]);
|
||||
|
||||
body << YAML::Key << "Options";
|
||||
body << YAML::BeginMap;
|
||||
|
||||
while (options > OPTION_NOTHING && options <= OPTION_SUMMER2) {
|
||||
if (options & OPTION_SIGHT) {
|
||||
body << YAML::Key << "Sight" << YAML::Value << "true";
|
||||
options &= ~OPTION_SIGHT;
|
||||
} else if (options & OPTION_CART1) {
|
||||
body << YAML::Key << "Cart1" << YAML::Value << "true";
|
||||
options &= ~OPTION_CART1;
|
||||
} else if (options & OPTION_FALCON) {
|
||||
body << YAML::Key << "Falcon" << YAML::Value << "true";
|
||||
options &= ~OPTION_FALCON;
|
||||
} else if (options & OPTION_RIDING) {
|
||||
body << YAML::Key << "Riding" << YAML::Value << "true";
|
||||
options &= ~OPTION_RIDING;
|
||||
} else if (options & OPTION_CART2) {
|
||||
body << YAML::Key << "Cart2" << YAML::Value << "true";
|
||||
options &= ~OPTION_CART2;
|
||||
} else if (options & OPTION_CART3) {
|
||||
body << YAML::Key << "Cart2" << YAML::Value << "true";
|
||||
options &= ~OPTION_CART3;
|
||||
} else if (options & OPTION_CART4) {
|
||||
body << YAML::Key << "Cart4" << YAML::Value << "true";
|
||||
options &= ~OPTION_CART4;
|
||||
} else if (options & OPTION_CART5) {
|
||||
body << YAML::Key << "Cart5" << YAML::Value << "true";
|
||||
options &= ~OPTION_CART5;
|
||||
} else if (options & OPTION_ORCISH) {
|
||||
body << YAML::Key << "Orcish" << YAML::Value << "true";
|
||||
options &= ~OPTION_ORCISH;
|
||||
} else if (options & OPTION_WEDDING) {
|
||||
body << YAML::Key << "Wedding" << YAML::Value << "true";
|
||||
options &= ~OPTION_WEDDING;
|
||||
} else if (options & OPTION_RUWACH) {
|
||||
body << YAML::Key << "Ruwach" << YAML::Value << "true";
|
||||
options &= ~OPTION_RUWACH;
|
||||
} else if (options & OPTION_FLYING) {
|
||||
body << YAML::Key << "Flying" << YAML::Value << "true";
|
||||
options &= ~OPTION_FLYING;
|
||||
} else if (options & OPTION_XMAS) {
|
||||
body << YAML::Key << "Xmas" << YAML::Value << "true";
|
||||
options &= ~OPTION_XMAS;
|
||||
} else if (options & OPTION_TRANSFORM) {
|
||||
body << YAML::Key << "Transform" << YAML::Value << "true";
|
||||
options &= ~OPTION_TRANSFORM;
|
||||
} else if (options & OPTION_SUMMER) {
|
||||
body << YAML::Key << "Summer" << YAML::Value << "true";
|
||||
options &= ~OPTION_SUMMER;
|
||||
} else if (options & OPTION_DRAGON1) {
|
||||
body << YAML::Key << "Dragon1" << YAML::Value << "true";
|
||||
options &= ~OPTION_DRAGON1;
|
||||
} else if (options & OPTION_WUG) {
|
||||
body << YAML::Key << "Wug" << YAML::Value << "true";
|
||||
options &= ~OPTION_WUG;
|
||||
} else if (options & OPTION_WUGRIDER) {
|
||||
body << YAML::Key << "WugRider" << YAML::Value << "true";
|
||||
options &= ~OPTION_WUGRIDER;
|
||||
} else if (options & OPTION_MADOGEAR) {
|
||||
body << YAML::Key << "MadoGear" << YAML::Value << "true";
|
||||
options &= ~OPTION_MADOGEAR;
|
||||
} else if (options & OPTION_DRAGON2) {
|
||||
body << YAML::Key << "Dragon2" << YAML::Value << "true";
|
||||
options &= ~OPTION_DRAGON2;
|
||||
} else if (options & OPTION_DRAGON3) {
|
||||
body << YAML::Key << "Dragon3" << YAML::Value << "true";
|
||||
options &= ~OPTION_DRAGON3;
|
||||
} else if (options & OPTION_DRAGON4) {
|
||||
body << YAML::Key << "Dragon4" << YAML::Value << "true";
|
||||
options &= ~OPTION_DRAGON4;
|
||||
} else if (options & OPTION_DRAGON5) {
|
||||
body << YAML::Key << "Dragon5" << YAML::Value << "true";
|
||||
options &= ~OPTION_DRAGON5;
|
||||
} else if (options & OPTION_HANBOK) {
|
||||
body << YAML::Key << "Hanbok" << YAML::Value << "true";
|
||||
options &= ~OPTION_HANBOK;
|
||||
} else if (options & OPTION_OKTOBERFEST) {
|
||||
body << YAML::Key << "Oktoberfest" << YAML::Value << "true";
|
||||
options &= ~OPTION_OKTOBERFEST;
|
||||
} else if (options & OPTION_SUMMER2) {
|
||||
body << YAML::Key << "Summer2" << YAML::Value << "true";
|
||||
options &= ~OPTION_SUMMER2;
|
||||
}
|
||||
}
|
||||
|
||||
body << YAML::EndMap;
|
||||
}
|
||||
} else if (columns == 3) {
|
||||
if (atoi(str[5]) != 0) {
|
||||
uint16 peteq_item_id = atoi(str[5]);
|
||||
std::string *peteq_item_name = util::umap_find(aegis_itemnames, peteq_item_id);
|
||||
|
||||
if (peteq_item_name == nullptr) {
|
||||
ShowError("Item name for item ID %hu (pet equip) is not known.\n", peteq_item_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
body << YAML::Key << "PetEquip" << YAML::Value << *peteq_item_name;
|
||||
}
|
||||
}
|
||||
|
||||
body << YAML::EndMap;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user