summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/map/battle/feature.conf8
-rw-r--r--conf/map/battle/items.conf4
-rw-r--r--conf/messages.conf9
-rw-r--r--db/attendance_db.conf119
-rw-r--r--db/constants.conf58
-rw-r--r--db/pet_db2.conf64
-rw-r--r--db/pet_db2.txt52
-rw-r--r--db/pre-re/item_db.conf16
-rw-r--r--db/pre-re/pet_db.conf1544
-rw-r--r--db/pre-re/pet_db.txt124
-rw-r--r--db/re/item_db.conf4
-rw-r--r--db/re/pet_db.conf1649
-rw-r--r--db/re/pet_db.txt133
-rw-r--r--doc/constants.md59
-rw-r--r--doc/script_commands.txt7
-rw-r--r--npc/mapflag/noteleport.txt1
-rw-r--r--sql-files/item_db.sql1
-rw-r--r--sql-files/item_db_re.sql2
-rw-r--r--sql-files/main.sql3
-rw-r--r--sql-files/upgrades/2018-03-10--04-06.sql24
-rw-r--r--sql-files/upgrades/index.txt1
-rw-r--r--src/char/char.c13
-rw-r--r--src/char/int_guild.c11
-rw-r--r--src/char/int_rodex.c8
-rw-r--r--src/common/HPMDataCheck.h12
-rw-r--r--src/common/mmo.h20
-rw-r--r--src/map/battle.c3
-rw-r--r--src/map/battle.h5
-rw-r--r--src/map/clif.c471
-rw-r--r--src/map/clif.h37
-rw-r--r--src/map/guild.c4
-rw-r--r--src/map/guild.h2
-rw-r--r--src/map/intif.c4
-rw-r--r--src/map/itemdb.c5
-rw-r--r--src/map/itemdb.h3
-rw-r--r--src/map/packets.h47
-rw-r--r--src/map/packets_keys_main.h13
-rw-r--r--src/map/packets_keys_zero.h12
-rw-r--r--src/map/packets_shuffle_main.h106
-rw-r--r--src/map/packets_shuffle_zero.h40
-rw-r--r--src/map/packets_struct.h141
-rw-r--r--src/map/pc.c56
-rw-r--r--src/map/pc.h3
-rw-r--r--src/map/pet.c312
-rw-r--r--src/map/pet.h7
-rw-r--r--src/map/quest.c8
-rw-r--r--src/map/rodex.c2
-rw-r--r--src/map/script.c43
-rw-r--r--src/map/skill.c14
-rw-r--r--src/map/status.c6
-rw-r--r--src/map/unit.c1
-rw-r--r--src/plugins/HPMHooking/HPMHooking.Defs.inc42
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc68
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc17
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc477
-rw-r--r--tools/petdbconverter.py214
56 files changed, 5532 insertions, 577 deletions
diff --git a/conf/map/battle/feature.conf b/conf/map/battle/feature.conf
index e01c7f93d..c0c60e475 100644
--- a/conf/map/battle/feature.conf
+++ b/conf/map/battle/feature.conf
@@ -70,4 +70,12 @@ features: {
// true: enable (Default)
// false: disable
enable_homun_autofeed: true
+
+ // Enable Attendance System for clients >= 2018-03-07bRagexeRE or 2018-04-04bRagexe
+ // true: enable (Default)
+ // false: disable
+ enable_attendance_system: true
+
+ // Attendance End time in the format YearMonthDay
+ feature_attendance_endtime: 20180331
}
diff --git a/conf/map/battle/items.conf b/conf/map/battle/items.conf
index f7ffd3f32..135df7107 100644
--- a/conf/map/battle/items.conf
+++ b/conf/map/battle/items.conf
@@ -119,3 +119,7 @@ bow_unequip_arrow: true
// How much should rental mounts increase a player's movement speed? (Note 2)
// Official: 25 (Default)
boarding_halter_speed: 25
+
+// Allow to use items when the storage is open?
+// Official: false (Default)
+storage_use_item: false
diff --git a/conf/messages.conf b/conf/messages.conf
index 3f395ab5e..7adff9dff 100644
--- a/conf/messages.conf
+++ b/conf/messages.conf
@@ -74,7 +74,10 @@
46: %s recalled!
47: Base level can't go any higher.
48: Any work in progress (NPC dialog, manufacturing ...) quit and try again.
-//49-52 FREE
+49: Unable to Teleport in this area
+50: This skill cannot be used within this area.
+51: This item cannot be used within this area.
+//52 FREE
53: '%s' stats:
54: No player found in map '%s'.
55: 1 player found in map '%s'.
@@ -475,7 +478,9 @@
538: Hack on trade: character '%s' (account: %d) try to trade more items that he has.
539: This player has %d of a kind of item (id: %d), and tried to trade %d of them.
540: This player has been definitively blocked.
-//541-545 FREE
+//541-543 FREE
+544: <MSG>3455</MSG>
+545: <MSG>3456,%d</MSG>
// @showmobs
546: Please enter a mob name/id (usage: @showmobs <mob name/id>)
547: Invalid mob name %s!
diff --git a/db/attendance_db.conf b/db/attendance_db.conf
new file mode 100644
index 000000000..f63ceed53
--- /dev/null
+++ b/db/attendance_db.conf
@@ -0,0 +1,119 @@
+//================= Hercules Database =====================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2018 Hercules Dev Team
+//= Copyright (C) 2018 Asheraf
+//=
+//= Hercules 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/>.
+//=========================================================================
+
+attendance_db:(
+/**************************************************************************
+ ************* Entry structure ********************************************
+ **************************************************************************
+{
+ // ================ Mandatory fields ==============================
+ ItemID: Item Constant (string)
+ Amount: Item Amount (int)
+},
+**************************************************************************/
+{
+ ItemID: "Red_Potion"
+ Amount: 10
+},
+{
+ ItemID: "Orange_Potion"
+ Amount: 10
+},
+{
+ ItemID: "Yellow_Potion"
+ Amount: 10
+},
+{
+ ItemID: "White_Potion"
+ Amount: 10
+},
+{
+ ItemID: "Blue_Potion"
+ Amount: 10
+},
+{
+ ItemID: "Red_Potion"
+ Amount: 20
+},
+{
+ ItemID: "Orange_Potion"
+ Amount: 20
+},
+{
+ ItemID: "Yellow_Potion"
+ Amount: 20
+},
+{
+ ItemID: "White_Potion"
+ Amount: 20
+},
+{
+ ItemID: "Blue_Potion"
+ Amount: 20
+},
+{
+ ItemID: "Red_Potion"
+ Amount: 30
+},
+{
+ ItemID: "Orange_Potion"
+ Amount: 30
+},
+{
+ ItemID: "Yellow_Potion"
+ Amount: 30
+},
+{
+ ItemID: "White_Potion"
+ Amount: 30
+},
+{
+ ItemID: "Blue_Potion"
+ Amount: 30
+},
+{
+ ItemID: "Red_Potion"
+ Amount: 40
+},
+{
+ ItemID: "Orange_Potion"
+ Amount: 40
+},
+{
+ ItemID: "Yellow_Potion"
+ Amount: 40
+},
+{
+ ItemID: "White_Potion"
+ Amount: 40
+},
+{
+ ItemID: "Blue_Potion"
+ Amount: 40
+}
+)
diff --git a/db/constants.conf b/db/constants.conf
index 8c3336f79..cc0fb3104 100644
--- a/db/constants.conf
+++ b/db/constants.conf
@@ -3877,4 +3877,62 @@ constants_db: {
UDT_STATADD: 54
UDT_ROBE: 55
UDT_BODY2: 56
+
+ comment__: "HatEffect Constants"
+ HAT_EF_BLOSSOM_FLUTTERING: 1
+ HAT_EF_MERMAID_LONGING: 2
+ HAT_EF_RL_BANISHING_BUSTER: 3
+ HAT_EF_LJOSALFAR: 4
+ HAT_EF_CLOCKING: 5
+ HAT_EF_SNOW: 6
+ HAT_EF_MAKEBLUR: 7
+ HAT_EF_SLEEPATTACK: 8
+ HAT_EF_GUMGANG: 9
+ HAT_EF_TALK_FROSTJOKE: 10
+ HAT_EF_DEMONSTRATION: 11
+ HAT_EF_FLUTTER_BUTTERFLY: 12
+ HAT_EF_ANGEL_FLUTTERING: 13
+ HAT_EF_BLESSING_OF_ANGELS: 14
+ HAT_EF_ELECTRIC: 15
+ HAT_EF_GREEN_FLOOR: 16
+ HAT_EF_SHRINK: 17
+ HAT_EF_VALHALLA_IDOL: 18
+ HAT_EF_ANGEL_STAIRS: 19
+ HAT_EF_GLOW_OF_NEW_YEAR: 20
+ HAT_EF_BOTTOM_FORTUNEKISS: 21
+ HAT_EF_PINKBODY: 22
+ HAT_EF_DOUBLEGUMGANG: 23
+ HAT_EF_GIANTBODY: 24
+ HAT_EF_GREEN99_6: 25
+ HAT_EF_CIRCLEPOWER: 26
+ HAT_EF_BOTTOM_BLOODYLUST: 27
+ HAT_EF_WATER_BELOW: 28
+ HAT_EF_LEVEL99_150: 29
+ HAT_EF_YELLOWFLY3: 30
+ HAT_EF_KAGEMUSYA: 31
+ HAT_EF_CHERRYBLOSSOM: 32
+ HAT_EF_STRANGELIGHTS: 33
+ HAT_EF_WL_TELEKINESIS_INTENSE: 34
+ HAT_EF_AB_OFFERTORIUM_RING: 35
+ HAT_EF_WHITEBODY2: 36
+ HAT_EF_SAKURA: 37
+ HAT_EF_CLOUD2: 38
+ HAT_EF_FEATHER_FLUTTERING: 39
+ HAT_EF_CAMELLIA_HAIR_PIN: 40
+ HAT_EF_JP_EV_EFFECT01: 41
+ HAT_EF_JP_EV_EFFECT02: 42
+ HAT_EF_JP_EV_EFFECT03: 43
+ HAT_EF_FLORAL_WALTZ: 44
+ HAT_EF_MAGICAL_FEATHER: 45
+ HAT_EF_HAT_EFFECT: 46
+ HAT_EF_BAKURETSU_HADOU: 47
+ HAT_EF_GOLD_SHOWER: 48
+ HAT_EF_WHITEBODY: 49
+ HAT_EF_WATER_BELOW2: 50
+ HAT_EF_FIREWORK: 51
+ HAT_EF_RETURN_TW_1ST_HAT: 52
+ HAT_EF_C_FLUTTERBUTTERFLY_BL: 53
+ HAT_EF_QSCARABA: 54
+ HAT_EF_FSTONE: 55
+ HAT_EF_MAGICCIRCLE: 56
}
diff --git a/db/pet_db2.conf b/db/pet_db2.conf
new file mode 100644
index 000000000..34a6130e4
--- /dev/null
+++ b/db/pet_db2.conf
@@ -0,0 +1,64 @@
+//================= Hercules Database =====================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2018 Hercules Dev Team
+//=
+//= Hercules 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/>.
+//=========================================================================
+//= Pets Database
+//=========================================================================
+
+pet_db:(
+/**************************************************************************
+ ************* Entry structure ********************************************
+ **************************************************************************
+{
+ // ================ Mandatory fields ==============================
+ Id: ID (int)
+ SpriteName: "Sprite_Name" (string)
+ Name: "Pet Name" (string)
+ // ================ Optional fields ===============================
+ TamingItem: Taming Item (string, defaults to 0)
+ EggItem: Egg Id (string, defaults to 0)
+ AccessoryItem: Equipment Id (string, defaults to 0)
+ FoodItem: Food Id (string, defaults to 0)
+ FoodEffectiveness: hunger points (int, defaults to 0)
+ HungerDelay: hunger time (int, defaults to 0)
+ Intimacy: {
+ Initial: start intimacy (int, defaults to 0)
+ FeedIncrement: feeding intimacy (int, defaults to 0)
+ OverFeedDecrement: overfeeding intimacy (int, defaults to 0)
+ OwnerDeathDecrement: owner die intimacy (int, defaults to 0)
+ }
+ CaptureRate: capture rate (int, defaults to 0)
+ Speed: speed (int, defaults to 0)
+ SpecialPerformance: true/false (boolean, defaults to false)
+ TalkWithEmotes: convert talk (boolean, defaults to false)
+ AttackRate: attack rate (int, defaults to 0)
+ DefendRate: Defence attack (int, defaults to 0)
+ ChangeTargetRate: change target (int, defaults to 0)
+ PetScript: <" Pet Script (can also be multi-line) ">
+ EquipScript: <" Equip Script (can also be multi-line) ">
+},
+**************************************************************************/
+ // entries in this file will override the ones in /(pre-)re/pet_db.conf
+)
diff --git a/db/pet_db2.txt b/db/pet_db2.txt
deleted file mode 100644
index 4e9b26fd9..000000000
--- a/db/pet_db2.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-// Pet Additional Database
-//
-// Structure of Database:
-// MobID,Name,JName,LureID,EggID,EquipID,FoodID,Fullness,HungryDelay,R_Hungry,R_Full,Intimate,Die,Capture,Speed,S_Performance,talk_convert_class,attack_rate,defence_attack_rate,change_target_rate,pet_script,loyal_script
-//
-// 01. MobID Monster ID of the pet.
-// 02. Name Name of the monster as defined in the database.
-// 03. JName The display name of the monster when hatched.
-// 04. LureID Pet Tame Item ID.
-// 05. EggID Pet Egg ID.
-// 06. EquipID Pet Accessory ID.
-// 07. FoodID Pet Food ID.
-// 08. Fullness The amount of hunger points increasing with each feeding.
-// 09. HungryDelay The amount of time it takes for hunger to decrease after feeding. (Default: 60 seconds)
-// 10. R_Hungry Amount of Intimacy that is increased when fed.
-// 11. R_Full Amount of Intimacy that is decreased when over-fed.
-// 12. Intimate Amount of Intimacy the pet starts with.
-// 13. Die Amount of Intimacy that is decreased when the pet owner dies.
-// 14. Capture Capture succes rate (10000 = 100%)
-// 15. Speed Pet's walk speed. (Defaul: 150)
-// 16. S_Performance Special Performance. (Yes = 1, No = 0)
-// 17. talk_convert_class Disables pet talk (instead of talking they emote with /!.)
-// 18. attack_rate Rate of which the pet will attack (requires at least pet_support_min_friendly intimacy).
-// 19. defence_attack_rate Rate of which the pet will retaliate when master is being attacked (requires at least pet_support_min_friendly intimacy).
-// 20. change_target_rate Rate of which the pet will change its attack target.
-// 21. pet_script Script to execute when the pet is hatched.
-// 22. loyal_script Script to execute when the pet is hatched (requires at least pet_equip_min_friendly intimacy, independent of pet_script).
-//NOTE: The max value (100%) of attack_rate, defense_rate & change_target_rate is 10000.
-
-//In theory you can use any valid script, but it is run only once upon pet
-//loading, so it is recommended you use the specific pet scripts:
-
-//petskillattack skillid, skilllv, hits, rate, bonusrate
-//Skill attack that triggers while the pet is attacking. Rate is the base
-//chance of execution per attack. Bonusrate is an additional success rate when
-//intimacy reaches max. If hits is specified and different than 0, it will make
-//the pet cast the skill with a fixed amount of damage inflicted and the
-//specified number of hits. A value of zero uses the skill's defaults.
-
-//petskillsupport skillid, skilllv, delay, hp%, sp%
-//Casts a support skill when the health levels are below the specified hp% and
-//sp%. Delay is the minimum time in seconds before the skill can be cast again
-
-//petrecovery type, delay: Cures the "type" status effect after "delay" seconds
-
-//petskillbonus type, value, duration, delay
-//Gives bonus stats. Type is the stat to increase (bStr, bLuk), value is the
-//amount by which it is increased, duration signals how long the bonus lasts
-//delay is the time elapsed after the bonus ends and before it starts again.
-
-//A single pet can have petloot, petskillbonus, petskillattack and
-//petskillsupport at the same time, but only one of each.
diff --git a/db/pre-re/item_db.conf b/db/pre-re/item_db.conf
index a98495eee..d62bbf19c 100644
--- a/db/pre-re/item_db.conf
+++ b/db/pre-re/item_db.conf
@@ -64561,7 +64561,21 @@ item_db: (
Type: "IT_PETEGG"
Buy: 20
},
-
+{
+ Id: 9058
+ AegisName: "Snow_Rabbit_Egg"
+ Name: "Christmas Snow Rabbit Egg"
+ Type: "IT_PETEGG"
+ Buy: 20
+ Trade: {
+ nodrop: true
+ notrade: true
+ nocart: true
+ nogstorage: true
+ nomail: true
+ noauction: true
+ }
+},
//== Pet Accessories =======================================
{
Id: 10001
diff --git a/db/pre-re/pet_db.conf b/db/pre-re/pet_db.conf
new file mode 100644
index 000000000..3ce78e546
--- /dev/null
+++ b/db/pre-re/pet_db.conf
@@ -0,0 +1,1544 @@
+//================= Hercules Database =====================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2018 Hercules Dev Team
+//=
+//= Hercules 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/>.
+//=========================================================================
+//= Pets Database
+//=========================================================================
+
+pet_db:(
+/**************************************************************************
+ ************* Entry structure ********************************************
+ **************************************************************************
+{
+ // ================ Mandatory fields ==============================
+ Id: ID (int)
+ SpriteName: "Sprite_Name" (string)
+ Name: "Pet Name" (string)
+ // ================ Optional fields ===============================
+ TamingItem: Taming Item (string, defaults to 0)
+ EggItem: Egg Id (string, defaults to 0)
+ AccessoryItem: Equipment Id (string, defaults to 0)
+ FoodItem: Food Id (string, defaults to 0)
+ FoodEffectiveness: hunger points (int, defaults to 0)
+ HungerDelay: hunger time (int, defaults to 0)
+ Intimacy: {
+ Initial: start intimacy (int, defaults to 0)
+ FeedIncrement: feeding intimacy (int, defaults to 0)
+ OverFeedDecrement: overfeeding intimacy (int, defaults to 0)
+ OwnerDeathDecrement: owner die intimacy (int, defaults to 0)
+ }
+ CaptureRate: capture rate (int, defaults to 0)
+ Speed: speed (int, defaults to 0)
+ SpecialPerformance: true/false (boolean, defaults to false)
+ TalkWithEmotes: convert talk (boolean, defaults to false)
+ AttackRate: attack rate (int, defaults to 0)
+ DefendRate: Defence attack (int, defaults to 0)
+ ChangeTargetRate: change target (int, defaults to 0)
+ PetScript: <" Pet Script (can also be multi-line) ">
+ EquipScript: <" Equip Script (can also be multi-line) ">
+},
+**************************************************************************/
+{
+ Id: 1002
+ SpriteName: "PORING"
+ Name: "Poring"
+ TamingItem: "Unripe_Apple"
+ EggItem: "Poring_Egg"
+ AccessoryItem: "Backpack"
+ FoodItem: "Apple_Juice"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 350
+ DefendRate: 400
+ ChangeTargetRate: 800
+ PetScript: <" petloot(10); ">
+ EquipScript: <"
+ bonus(bLuk, 2);
+ bonus(bCritical, 1);
+ ">
+},
+{
+ Id: 1011
+ SpriteName: "CHONCHON"
+ Name: "ChonChon"
+ TamingItem: "Rotten_Fish"
+ EggItem: "Chonchon_Egg"
+ AccessoryItem: "Monster_Oxygen_Mask"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1500
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 500
+ DefendRate: 500
+ ChangeTargetRate: 250
+ PetScript: <" petskillbonus(bAgi, 4, 10, 50); ">
+ EquipScript: <"
+ bonus(bAgi, 1);
+ bonus(bFlee, 2);
+ ">
+},
+{
+ Id: 1014
+ SpriteName: "SPORE"
+ Name: "Spore"
+ TamingItem: "Dew_Laden_Moss"
+ EggItem: "Spore_Egg"
+ AccessoryItem: "Bark_Shorts"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1500
+ Speed: 150
+ AttackRate: 350
+ DefendRate: 500
+ ChangeTargetRate: 500
+ PetScript: <" petrecovery(SC_POISON, 60); ">
+ EquipScript: <"
+ bonus(bHit, 5);
+ bonus(bAtk, -2);
+ ">
+},
+{
+ Id: 1019
+ SpriteName: "PECOPECO"
+ Name: "PecoPeco"
+ TamingItem: "Fatty_Chubby_Earthworm"
+ EggItem: "PecoPeco_Egg"
+ AccessoryItem: "Battered_Pot"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 400
+ DefendRate: 500
+ ChangeTargetRate: 800
+ PetScript: <" petskillbonus(bSpeedRate, 25, 20, 20); ">
+ EquipScript: <"
+ bonus(bMaxHP, 150);
+ bonus(bMaxSP, -10);
+ ">
+},
+{
+ Id: 1023
+ SpriteName: "ORK_WARRIOR"
+ Name: "Orc Warrior"
+ TamingItem: "Horror_Of_Tribe"
+ EggItem: "Orc_Warrior_Egg"
+ AccessoryItem: "Wild_Flower"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 600
+ DefendRate: 200
+ ChangeTargetRate: 300
+ PetScript: <" petskillattack("NPC_PIERCINGATT", 100, 1, 0, 10); ">
+ EquipScript: <"
+ bonus(bAtk, 10);
+ bonus(bDef, -3);
+ ">
+},
+{
+ Id: 1026
+ SpriteName: "MUNAK"
+ Name: "Munak"
+ TamingItem: "No_Recipient"
+ EggItem: "Munak_Egg"
+ AccessoryItem: "Punisher"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 750
+ ChangeTargetRate: 300
+ PetScript: <" petskillattack("NPC_DARKNESSATTACK", 444, 1, 0, 10); ">
+ EquipScript: <"
+ bonus(bInt, 1);
+ bonus(bDef, 1);
+ ">
+},
+{
+ Id: 1029
+ SpriteName: "ISIS"
+ Name: "Isis"
+ TamingItem: "Armlet_Of_Obedience"
+ EggItem: "Isis_Egg"
+ AccessoryItem: "Queens_Hair_Ornament"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 650
+ DefendRate: 450
+ ChangeTargetRate: 150
+ PetScript: <" petskillsupport("PR_MAGNIFICAT", 2, 60, 50, 50); ">
+ EquipScript: <"
+ bonus(bMatkRate, -1);
+ bonus(bAtkRate, 1);
+ ">
+},
+{
+ Id: 1031
+ SpriteName: "POPORING"
+ Name: "Poporing"
+ TamingItem: "Bitter_Herb"
+ EggItem: "Poporing_Egg"
+ AccessoryItem: "Backpack"
+ FoodItem: "Green_Herb"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 300
+ DefendRate: 500
+ ChangeTargetRate: 400
+ PetScript: <" petloot(15); ">
+ EquipScript: <"
+ bonus(bLuk, 2);
+ bonus2(bSubEle, Ele_Poison, 10);
+ ">
+},
+{
+ Id: 1035
+ SpriteName: "HUNTER_FLY"
+ Name: "Hunter Fly"
+ TamingItem: "Monster_Juice"
+ EggItem: "Hunter_Fly_Egg"
+ AccessoryItem: "Monster_Oxygen_Mask"
+ FoodItem: "Red_Gemstone"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 500
+ DefendRate: 500
+ ChangeTargetRate: 200
+ PetScript: <" petskillattack("NPC_WINDATTACK", 888, 2, 0, 10); ">
+ EquipScript: <"
+ bonus(bFlee, -5);
+ bonus(bFlee2, 2);
+ ">
+},
+{
+ Id: 1042
+ SpriteName: "STEEL_CHONCHON"
+ Name: "Steel ChonChon"
+ TamingItem: "Lusty_Iron"
+ EggItem: "Steel_Chonchon_Egg"
+ AccessoryItem: "Monster_Oxygen_Mask"
+ FoodItem: "Iron_Ore"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 500
+ DefendRate: 500
+ ChangeTargetRate: 200
+ PetScript: <" petskillbonus(bAgiVit, 4, 20, 40); ">
+ EquipScript: <"
+ bonus(bFlee, 6);
+ bonus(bAgi, -1);
+ ">
+},
+{
+ Id: 1049
+ SpriteName: "PICKY"
+ Name: "Picky"
+ TamingItem: "Earthworm_The_Dude"
+ EggItem: "Picky_Egg"
+ AccessoryItem: "Tiny_Egg_Shell"
+ FoodItem: "Red_Herb"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 40
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 500
+ DefendRate: 600
+ ChangeTargetRate: 50
+ PetScript: <" petskillbonus(bStr, 3, 10, 50); ">
+ EquipScript: <"
+ bonus(bStr, 1);
+ bonus(bAtk, 5);
+ ">
+},
+{
+ Id: 1052
+ SpriteName: "ROCKER"
+ Name: "Rocker"
+ TamingItem: "Singing_Flower"
+ EggItem: "Rocker_Egg"
+ AccessoryItem: "Rocker_Glasses"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1500
+ Speed: 150
+ AttackRate: 350
+ DefendRate: 350
+ ChangeTargetRate: 600
+ PetScript: <" petskillbonus(bAllStats, 1, 10, 50); ">
+ EquipScript: <"
+ bonus(bHPrecovRate, 5);
+ bonus(bMaxHP, 25);
+ ">
+},
+{
+ Id: 1056
+ SpriteName: "SMOKIE"
+ Name: "Smokie"
+ TamingItem: "Baked_Yam"
+ EggItem: "Smokie_Egg"
+ AccessoryItem: "Red_Muffler"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 600
+ DefendRate: 600
+ ChangeTargetRate: 100
+ PetScript: <" petskillbonus(bPerfectHide, 1, 3600, 0); ">
+ EquipScript: <"
+ bonus(bAgi, 1);
+ bonus(bFlee2, 1);
+ ">
+},
+{
+ Id: 1057
+ SpriteName: "YOYO"
+ Name: "Yoyo"
+ TamingItem: "Tropical_Banana"
+ EggItem: "Yoyo_Egg"
+ AccessoryItem: "Monkey_Circlet"
+ FoodItem: "Banana_Juice"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 300
+ DefendRate: 800
+ ChangeTargetRate: 400
+ PetScript: <" petloot(20); ">
+ EquipScript: <"
+ bonus(bCritical, 3);
+ bonus(bLuk, -1);
+ ">
+},
+{
+ Id: 1063
+ SpriteName: "LUNATIC"
+ Name: "Lunatic"
+ TamingItem: "Rainbow_Carrot"
+ EggItem: "Lunatic_Egg"
+ AccessoryItem: "Silk_Ribbon"
+ FoodItem: "Carrot_Juice"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 40
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 1000
+ PetScript: <" petskillbonus(bLuk, 3, 10, 50); ">
+ EquipScript: <"
+ bonus(bCritical, 2);
+ bonus(bAtk, 2);
+ ">
+},
+{
+ Id: 1077
+ SpriteName: "POISON_SPORE"
+ Name: "Poison Spore"
+ TamingItem: "Deadly_Noxious_Herb"
+ EggItem: "Poison_Spore_Egg"
+ AccessoryItem: "Bark_Shorts"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ AttackRate: 600
+ DefendRate: 200
+ ChangeTargetRate: 400
+ PetScript: <" petskillattack("NPC_POISON", 20, 0, 0, 10); ">
+ EquipScript: <"
+ bonus(bStr, 1);
+ bonus(bInt, 1);
+ ">
+},
+{
+ Id: 1101
+ SpriteName: "BAPHOMET_"
+ Name: "Baphomet Jr."
+ TamingItem: "Book_Of_Devil"
+ EggItem: "Bapho_Jr_Egg"
+ AccessoryItem: "Skull_Helm"
+ FoodItem: "Honey"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 1000
+ DefendRate: 100
+ ChangeTargetRate: 200
+ PetScript: <" petskillattack("NPC_DARKNESSATTACK", 1776, 4, 0, 5); ">
+ EquipScript: <"
+ bonus(bDef, 1);
+ bonus(bMdef, 1);
+ bonus2(bResEff, Eff_Stun, -100);
+ ">
+},
+{
+ Id: 1107
+ SpriteName: "DESERT_WOLF_B"
+ Name: "Baby Desert Wolf"
+ TamingItem: "Well_Dried_Bone"
+ EggItem: "Baby_Desert_Wolf_Egg"
+ AccessoryItem: "Transparent_Headgear"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 40
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ AttackRate: 400
+ DefendRate: 400
+ ChangeTargetRate: 400
+ PetScript: <" petskillattack("SM_PROVOKE", 1, 0, 0, 5);">
+ EquipScript: <"
+ bonus(bInt, 1);
+ bonus(bMaxSP, 50);
+ ">
+},
+{
+ Id: 1109
+ SpriteName: "DEVIRUCHI"
+ Name: "Deviruchi"
+ TamingItem: "Contracts_In_Shadow"
+ EggItem: "Deviruchi_Egg"
+ AccessoryItem: "Pacifier"
+ FoodItem: "Shoot"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 800
+ DefendRate: 200
+ ChangeTargetRate: 100
+ PetScript: <" petskillbonus(bAgiDexStr, 6, 20, 40); ">
+ EquipScript: <"
+ bonus(bMatkRate, 1);
+ bonus(bAtkRate, 1);
+ bonus(bMaxHPrate, -3);
+ bonus(bMaxSPrate, -3);
+ ">
+},
+{
+ Id: 1110
+ SpriteName: "DOKEBI"
+ Name: "Dokebi"
+ TamingItem: "Old_Broom"
+ EggItem: "Dokkaebi_Egg"
+ AccessoryItem: "Wig"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("BS_HAMMERFALL", 1, 0, 0, 10); ">
+ EquipScript: <"
+ bonus(bMatkRate, 1);
+ bonus(bAtkRate, -1);
+ ">
+},
+{
+ Id: 1113
+ SpriteName: "DROPS"
+ Name: "Drops"
+ TamingItem: "Orange_Juice"
+ EggItem: "Drops_Egg"
+ AccessoryItem: "Backpack"
+ FoodItem: "Yellow_Herb"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 40
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1500
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 300
+ DefendRate: 400
+ ChangeTargetRate: 500
+ PetScript: <" petloot(10); ">
+ EquipScript: <"
+ bonus(bHit, 3);
+ bonus(bAtk, 3);
+ ">
+},
+{
+ Id: 1155
+ SpriteName: "PETIT"
+ Name: "Petite"
+ TamingItem: "Shining_Stone"
+ EggItem: "Green_Petite_Egg"
+ AccessoryItem: "Stellar_Hairpin"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 800
+ DefendRate: 400
+ ChangeTargetRate: 100
+ PetScript: <" petskillattack("WZ_HEAVENDRIVE", 500, 1, 0, 10); ">
+ EquipScript: <"
+ bonus(bDef, -2);
+ bonus(bMdef, -2);
+ bonus(bAspdRate, 1);
+ ">
+},
+{
+ Id: 1167
+ SpriteName: "SAVAGE_BABE"
+ Name: "Savage Babe"
+ TamingItem: "Sweet_Milk"
+ EggItem: "Savage_Bebe_Egg"
+ AccessoryItem: "Green_Lace"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 40
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1500
+ Speed: 150
+ AttackRate: 500
+ DefendRate: 500
+ ChangeTargetRate: 200
+ PetScript: <" petskillbonus(bVit, 4, 10, 50); ">
+ EquipScript: <"
+ bonus(bVit, 1);
+ bonus(bMaxHP, 50);
+ ">
+},
+{
+ Id: 1170
+ SpriteName: "SOHEE"
+ Name: "Sohee"
+ TamingItem: "Silver_Knife_Of_Chaste"
+ EggItem: "Sohee_Egg"
+ AccessoryItem: "Golden_Bell"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 100
+ DefendRate: 1000
+ ChangeTargetRate: 200
+ PetScript: <" petskillsupport(AL_HEAL, 10, 60, 33, 100); ">
+ EquipScript: <"
+ bonus(bStr, 1);
+ bonus(bDex, 1);
+ ">
+},
+{
+ Id: 1188
+ SpriteName: "BON_GUN"
+ Name: "Bon Gun"
+ TamingItem: "Heart_Of_Her"
+ EggItem: "Bongun_Egg"
+ AccessoryItem: "Sword_Of_Grave_Keeper"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 600
+ DefendRate: 200
+ ChangeTargetRate: 400
+ PetScript: <" petskillattack("NPC_DARKNESSATTACK", 555, 1, 1, 1); ">
+ EquipScript: <"
+ bonus(bVit, 1);
+ bonus2(bResEff, Eff_Stun, 100);
+ ">
+},
+{
+ Id: 1200
+ SpriteName: "ZHERLTHSH"
+ Name: "Zealotus"
+ TamingItem: "Prohibition_Red_Candle"
+ EggItem: "Zherlthsh_Egg"
+ FoodItem: "Immortal_Heart"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 300
+ Speed: 150
+ AttackRate: 1000
+ DefendRate: 100
+ ChangeTargetRate: 500
+ PetScript: <" petskillattack("AS_SONICBLOW", 1, 0, 0, 3); ">
+ EquipScript: <"
+ bonus2(bAddRace, RC_DemiPlayer, 2);
+ bonus2(bMagicAddRace, RC_DemiPlayer, 2);
+ ">
+},
+{
+ Id: 1245
+ SpriteName: "GOBLINE_XMAS"
+ Name: "Christmas Goblin"
+ TamingItem: "Sweet_Candy_Striper"
+ EggItem: "Santa_Goblin_Egg"
+ FoodItem: "Scell"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("MG_SIGHT", 5, 0, 5, 5); ">
+ EquipScript: <"
+ bonus(bMaxHP, 30);
+ bonus2(bSubEle, Ele_Water, 1);
+ ">
+},
+{
+ Id: 1275
+ SpriteName: "ALICE"
+ Name: "Alice"
+ TamingItem: "Sway_Apron"
+ EggItem: "Alice_Egg"
+ FoodItem: "White_Potion"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 100
+ DefendRate: 1000
+ ChangeTargetRate: 200
+ PetScript: <" petskillsupport("AL_HEAL", 5, 60, 25, 100); ">
+ EquipScript: <"
+ bonus(bMdef, 1);
+ bonus2(bSubRace, RC_DemiPlayer, 1);
+ ">
+},
+// New Pets
+{
+ Id: 1122
+ SpriteName: "GOBLIN_1"
+ Name: "Goblin"
+ TamingItem: "Knife_Goblin_Ring"
+ EggItem: "Knife_Goblin_Egg"
+ FoodItem: "Green_Apple"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("NPC_WINDATTACK", 5, 0, 5, 5); ">
+
+},
+{
+ Id: 1123
+ SpriteName: "GOBLIN_2"
+ Name: "Goblin"
+ TamingItem: "Flail_Goblin_Ring"
+ EggItem: "Flail_Goblin_Egg"
+ FoodItem: "Green_Apple"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("NPC_FIREATTACK", 5, 0, 5, 5); ">
+
+},
+{
+ Id: 1125
+ SpriteName: "GOBLIN_4"
+ Name: "Goblin"
+ TamingItem: "Hammer_Goblin_Ring"
+ EggItem: "Hammer_Goblin_Egg"
+ FoodItem: "Green_Apple"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("NPC_GROUNDATTACK", 5, 0, 5, 5); ">
+},
+{
+ Id: 1208
+ SpriteName: "WANDER_MAN"
+ Name: "Wanderer"
+ TamingItem: "Skull_Of_Vagabond"
+ EggItem: "Wanderer_Egg"
+ FoodItem: "Spirit_Liquor"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("NPC_UNDEADATTACK", 5, 0, 5, 5); ">
+},
+{
+ Id: 1382
+ SpriteName: "DIABOLIC"
+ Name: "Diabolic"
+ TamingItem: "Red_Burning_Stone"
+ EggItem: "Diabolic_Egg"
+ FoodItem: "Meat_Veg_Skewer"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("WZ_METEOR", 2, 0, 5, 5); ">
+},
+{
+ Id: 1385
+ SpriteName: "DELETER_"
+ Name: "Deleter"
+ TamingItem: "Holy_Marble"
+ EggItem: "Red_Deleter_Egg"
+ FoodItem: "Whole_Barbecue"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("SM_MAGNUM", 5, 0, 5, 5); ">
+},
+{
+ Id: 1879
+ SpriteName: "ECLIPSE_P"
+ Name: "Spring Rabbit"
+ EggItem: "Spring_Rabbit_Egg"
+ FoodItem: "Bok_Choy"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("TF_THROWSTONE", 1, 0, 5, 5); ">
+},
+// Episode 12
+{
+ Id: 1963
+ SpriteName: "P_CHUNG_E"
+ Name: "New Year Doll"
+ EggItem: "New_Year_Doll_Egg"
+ FoodItem: "Mojji"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("CR_SHIELDCHARGE", 5, 0, 5, 5); ">
+},
+// Episode 13
+{
+ Id: 1815
+ SpriteName: "EVENT_RICECAKE"
+ Name: "Rice Cake"
+ EggItem: "Rice_Cake_Egg"
+ FoodItem: "Green_Herb"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 500
+ DefendRate: 500
+ ChangeTargetRate: 200
+ PetScript: <" petskillsupport("CR_DEFENDER", 3, 240, 50, 100); ">
+ EquipScript: <"
+ bonus2(bSubEle, Ele_Neutral, 1);
+ bonus(bMaxHPrate, -1);
+ ">
+},
+{
+ Id: 2210
+ SpriteName: "XMAS_LUNATIC"
+ Name: "Christmas Snow Rabbit"
+ EggItem: "Snow_Rabbit_Egg"
+ FoodItem: "Candy"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus2(bExpAddRace, RC_All, 5); ">
+},
+// Episode 13.2
+{
+ Id: 1040
+ SpriteName: "GOLEM"
+ Name: "Golem"
+ TamingItem: "Magical_Lithography"
+ EggItem: "Golem_Egg"
+ AccessoryItem: "Windup_Spring"
+ FoodItem: "Mystic_Stone"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus(bMaxHP, 100);
+ bonus(bFlee, -5);
+ ">
+},
+{
+ Id: 1143
+ SpriteName: "MARIONETTE"
+ Name: "Marionette"
+ TamingItem: "Delicious_Shaved_Ice"
+ EggItem: "Marionette_Egg"
+ AccessoryItem: "Star_Hairband"
+ FoodItem: "Small_Snow_Flower"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus(bSPrecovRate, 3); ">
+},
+{
+ Id: 1148
+ SpriteName: "MEDUSA"
+ Name: "Medusa"
+ TamingItem: "Splendid_Mirror"
+ EggItem: "Medusa_Egg"
+ AccessoryItem: "Queens_Coronet"
+ FoodItem: "Apple_Pudding"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus(bVit, 1);
+ bonus2(bResEff, Eff_Stone, 500);
+ ">
+},
+{
+ Id: 1179
+ SpriteName: "WHISPER"
+ Name: "Whisper"
+ TamingItem: "Fit_Pipe"
+ EggItem: "Whisper_Egg"
+ AccessoryItem: "Spirit_Chain_"
+ FoodItem: "Damp_Darkness"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus(bFlee, 7);
+ bonus(bDef, -3);
+ ">
+},
+{
+ Id: 1299
+ SpriteName: "GOBLIN_LEADER"
+ Name: "Goblin Leader"
+ TamingItem: "Staff_Of_Leader"
+ EggItem: "Goblin_Leader_Egg"
+ AccessoryItem: "Nice_Badge"
+ FoodItem: "Big_Cell"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 50
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus2(bAddRace, RC_DemiPlayer, 3); ">
+},
+{
+ Id: 1370
+ SpriteName: "SUCCUBUS"
+ Name: "Succubus"
+ TamingItem: "Boys_Naivety"
+ EggItem: "Succubus_Egg"
+ AccessoryItem: "Black_Butterfly_Mask"
+ FoodItem: "Vital_Flower_"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus2(bHPDrainRate, 50, 5); ">
+},
+{
+ Id: 1374
+ SpriteName: "INCUBUS"
+ Name: "Incubus"
+ TamingItem: "Grils_Naivety"
+ EggItem: "Incubus_Egg"
+ AccessoryItem: "Ball_Mask"
+ FoodItem: "Vital_Flower"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 50
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus(bMaxSPrate, 3); ">
+},
+{
+ Id: 1379
+ SpriteName: "NIGHTMARE_TERROR"
+ Name: "Nightmare Terror"
+ TamingItem: "Hell_Contract"
+ EggItem: "Nightmare_Terror_Egg"
+ AccessoryItem: "Hell_Horn"
+ FoodItem: "Fresh_Plant"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus2(bResEff, Eff_Sleep, 10000); ">
+},
+{
+ Id: 1401
+ SpriteName: "SHINOBI"
+ Name: "Shinobi"
+ TamingItem: "Kuloren"
+ EggItem: "Shinobi_Egg"
+ AccessoryItem: "Wine_On_Sleeve"
+ FoodItem: "Grilled_Rice_Cake"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus(bAgi, 2); ">
+},
+{
+ Id: 1404
+ SpriteName: "MIYABI_NINGYO"
+ Name: "Miyabi Doll"
+ TamingItem: "Gril_Doll"
+ EggItem: "Miyabi_Ningyo_Egg"
+ AccessoryItem: "Summer_Fan"
+ FoodItem: "Well_Ripened_Berry"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 15
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus(bInt, 1);
+ bonus(bCastrate, -3);
+ ">
+},
+{
+ Id: 1416
+ SpriteName: "WICKED_NYMPH"
+ Name: "Evil Nymph"
+ TamingItem: "Charming_Lotus"
+ EggItem: "Wicked_Nymph_Egg"
+ AccessoryItem: "Jade_Trinket"
+ FoodItem: "Morning_Dew"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 15
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus(bMaxSP, 30);
+ bonus(bSPrecovRate, 5);
+ ">
+},
+{
+ Id: 1495
+ SpriteName: "STONE_SHOOTER"
+ Name: "Stone Shooter"
+ TamingItem: "Oilpalm_Coconut"
+ EggItem: "Stone_Shooter_Egg"
+ AccessoryItem: "Apro_Hair"
+ FoodItem: "Plant_Neutrient"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus2(bSubEle, Ele_Fire, 3); ">
+},
+{
+ Id: 1504
+ SpriteName: "DULLAHAN"
+ Name: "Dullahan"
+ TamingItem: "Luxury_Whisky_Bottle"
+ EggItem: "Dullahan_Egg"
+ AccessoryItem: "Death_Coil"
+ FoodItem: "Sunset_On_The_Rock"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus(bCritAtkRate, 5); ">
+},
+{
+ Id: 1505
+ SpriteName: "LOLI_RURI"
+ Name: "Loli Ruri"
+ TamingItem: "Very_Red_Juice"
+ EggItem: "Loli_Ruri_Egg"
+ AccessoryItem: "Fashionable_Glasses"
+ FoodItem: "Pumpkin_Pie_"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 15
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus(bMaxHPrate, 3);
+ bonus3(bAutoSpellWhenHit, "AL_HEAL", 1, 50);
+ ">
+},
+{
+ Id: 1513
+ SpriteName: "CIVIL_SERVANT"
+ Name: "Mao Guai"
+ TamingItem: "Fan_Of_Wind"
+ EggItem: "Civil_Servant_Egg"
+ AccessoryItem: "Golden_Earing"
+ FoodItem: "Flavored_Alcohol"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus(bMaxSP, 10); ">
+},
+{
+ Id: 1519
+ SpriteName: "CHUNG_E"
+ Name: "Green Maiden"
+ TamingItem: "Tantanmen"
+ EggItem: "Chung_E_Egg"
+ FoodItem: "Bun_"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("CR_SHIELDCHARGE", 5, 0, 5, 5); ">
+ EquipScript: <"
+ bonus(bDef, 1);
+ bonus2(bSubRace, RC_DemiPlayer, 1);
+ ">
+},
+{
+ Id: 1586
+ SpriteName: "LEAF_CAT"
+ Name: "Leaf Cat"
+ TamingItem: "Very_Soft_Plant"
+ EggItem: "Leaf_Cat_Egg"
+ AccessoryItem: "Green_Lucky_Bag"
+ FoodItem: "Fish_With_Blue_Back"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus2(bSubRace, RC_Brute, 3);
+ ">
+},
+{
+ Id: 1630
+ SpriteName: "BACSOJIN_"
+ Name: "White Lady"
+ TamingItem: "Shiny_Wing_Gown"
+ EggItem: "Bacsojin_Egg"
+ AccessoryItem: "Round_Hair_Ornament"
+ FoodItem: "Traditional_Cookie"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+},
+{
+ Id: 1837
+ SpriteName: "IMP"
+ Name: "Fire Imp"
+ TamingItem: "Flaming_Ice"
+ EggItem: "Imp_Egg"
+ AccessoryItem: "Horn_Protector"
+ FoodItem: "Flame_Gemstone"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus2(bSubEle, Ele_Fire, 2);
+ bonus2(bAddEle, Ele_Fire, 2);
+ ">
+},
+// Episode 13.2 Brasilis
+{
+ Id: 2057
+ SpriteName: "E_CRAMP"
+ Name: "Strange Cramp"
+ TamingItem: "Leaf_Cat_Ball"
+ EggItem: "Mystic_Leaf_Cat_Ball"
+ CaptureRate: 50
+ AttackRate: 350
+ DefendRate: 400
+ ChangeTargetRate: 800
+},
+{
+ Id: 2081
+ SpriteName: "E_HYDRA"
+ Name: "Strange Hydra"
+ TamingItem: "Leaf_Cat_Ball"
+ EggItem: "Mystic_Leaf_Cat_Ball"
+ CaptureRate: 50
+ AttackRate: 350
+ DefendRate: 400
+ ChangeTargetRate: 800
+},
+)
diff --git a/db/pre-re/pet_db.txt b/db/pre-re/pet_db.txt
deleted file mode 100644
index c0f3a3e91..000000000
--- a/db/pre-re/pet_db.txt
+++ /dev/null
@@ -1,124 +0,0 @@
-// Pet Database
-//
-// Structure of Database:
-// MobID,Name,JName,LureID,EggID,EquipID,FoodID,Fullness,HungryDelay,R_Hungry,R_Full,Intimate,Die,Capture,Speed,S_Performance,talk_convert_class,attack_rate,defence_attack_rate,change_target_rate,pet_script,loyal_script
-//
-// 01. MobID Monster ID of the pet.
-// 02. Name Name of the monster as defined in the database.
-// 03. JName The display name of the monster when hatched.
-// 04. LureID Pet Tame Item ID.
-// 05. EggID Pet Egg ID.
-// 06. EquipID Pet Accessory ID.
-// 07. FoodID Pet Food ID.
-// 08. Fullness The amount of hunger points increasing with each feeding.
-// 09. HungryDelay The amount of time it takes for hunger to decrease after feeding. (Default: 60 seconds)
-// 10. R_Hungry Amount of Intimacy that is increased when fed.
-// 11. R_Full Amount of Intimacy that is decreased when over-fed.
-// 12. Intimate Amount of Intimacy the pet starts with.
-// 13. Die Amount of Intimacy that is decreased when the pet owner dies.
-// 14. Capture Capture succes rate (10000 = 100%)
-// 15. Speed Pet's walk speed. (Defaul: 150)
-// 16. S_Performance Special Performance. (Yes = 1, No = 0)
-// 17. talk_convert_class Disables pet talk (instead of talking they emote with /!.)
-// 18. attack_rate Rate of which the pet will attack (requires at least pet_support_min_friendly intimacy).
-// 19. defence_attack_rate Rate of which the pet will retaliate when master is being attacked (requires at least pet_support_min_friendly intimacy).
-// 20. change_target_rate Rate of which the pet will change its attack target.
-// 21. pet_script Script to execute when the pet is hatched.
-// 22. loyal_script Script to execute when the pet is hatched (requires at least pet_equip_min_friendly intimacy, independent of pet_script).
-// NOTE: The max value (100%) of attack_rate, defense_rate & change_target_rate is 10000.
-
-// In theory you can use any valid script, but it is run only once upon pet
-// loading, so it is recommended you use the specific pet scripts:
-
-// petskillattack skillid, skilllv, hits, rate, bonusrate Skill attack that
-// triggers while the pet is attacking. Rate is the base chance of execution
-// per attack. Bonusrate is an additional success rate when intimacy reaches
-// max. If hits is specified and different than 0, it will make the pet cast
-// the skill with a fixed amount of damage inflicted and the specified number
-// of hits. A value of zero uses the skill's defaults.
-
-// petskillsupport skillid, skilllv, delay, hp%, sp% Casts a support skill when
-// the health levels are below the specified hp% and sp%. Delay is the minimum
-// time in seconds before the skill can be cast again
-
-// petrecovery type, delay: Cures the "type" status effect after "delay"
-// seconds
-
-// petskillbonus type, value, duration, delay Gives bonus stats. Type is the
-// stat to increase (bStr, bLuk), value is the amount by which it is increased,
-// duration signals how long the bonus lasts delay is the time elapsed after
-// the bonus ends and before it starts again.
-
-// A single pet can have petloot, petskillbonus, petskillattack and
-// petskillsupport at the same time, but only one of each.
-
-// Core
-1002,PORING,Poring,619,9001,10013,531,80,60,50,100,250,20,2000,150,1,0,350,400,800,{ petloot 10; },{ bonus bLuk,2; bonus bCritical,1; }
-1011,CHONCHON,ChonChon,624,9006,10002,537,80,60,30,100,250,20,1500,150,1,0,500,500,250,{ petskillbonus bAgi,4,10,50; },{ bonus bAgi,1; bonus bFlee,2; }
-1014,SPORE,Spore,630,9012,10017,537,80,60,30,100,250,20,1500,150,0,0,350,500,500,{ petrecovery SC_POISON,60; },{ bonus bHit,5; bonus bAtk,-2; }
-1019,PECOPECO,PecoPeco,632,9014,10010,537,80,60,30,100,250,20,1000,150,1,0,400,500,800,{ petskillbonus bSpeedRate,25,20,20; },{ bonus bMaxHP,150; bonus bMaxSP,-10; }
-1023,ORK_WARRIOR,Orc Warrior,635,9017,10009,537,80,60,20,100,250,20,500,150,1,0,600,200,300,{ petskillattack "NPC_PIERCINGATT",100,1,0,10; },{ bonus bAtk,10; bonus bDef,-3; }
-1026,MUNAK,Munak,636,9018,10008,537,80,60,20,100,250,20,500,150,0,0,300,750,300,{ petskillattack "NPC_DARKNESSATTACK",444,1,0,10; },{ bonus bInt,1; bonus bDef,1; }
-1029,ISIS,Isis,639,9021,10006,537,80,60,10,100,250,20,500,150,0,0,650,450,150,{ petskillsupport "PR_MAGNIFICAT",2,60,50,50; },{ bonus bMatkRate,-1; bonus bAtkRate,1; }
-1031,POPORING,Poporing,621,9003,10013,511,80,60,30,100,250,20,1000,150,1,0,300,500,400,{ petloot 15; },{ bonus bLuk,2; bonus2 bSubEle,Ele_Poison,10; }
-1035,HUNTER_FLY,Hunter Fly,626,9008,10002,716,80,60,10,100,250,20,500,150,1,0,500,500,200,{ petskillattack "NPC_WINDATTACK",888,2,0,10; },{ bonus bFlee,-5; bonus bFlee2,2; }
-1042,STEEL_CHONCHON,Steel ChonChon,625,9007,10002,1002,80,60,20,100,250,20,1000,150,1,0,500,500,200,{ petskillbonus bAgiVit,4,20,40; },{ bonus bFlee,6; bonus bAgi,-1; }
-1049,PICKY,Picky,623,9005,10012,507,80,60,40,100,250,20,2000,150,1,0,500,600,50,{ petskillbonus bStr,3,10,50;},{ bonus bStr,1; bonus bAtk,5; }
-1052,ROCKER,Rocker,629,9011,10014,537,80,60,30,100,250,20,1500,150,0,0,350,350,600,{ petskillbonus bAllStats,1,10,50; },{ bonus bHPrecovRate,5; bonus bMaxHP,25; }
-1056,SMOKIE,Smokie,633,9015,10019,537,80,60,30,100,250,20,1000,150,1,0,600,600,100,{ petskillbonus bPerfectHide,1,3600,0; },{ bonus bAgi,1; bonus bFlee2,1; }
-1057,YOYO,Yoyo,634,9016,10018,532,80,60,20,100,250,20,1000,150,1,0,300,800,400,{ petloot 20; },{ bonus bCritical,3; bonus bLuk,-1; }
-1063,LUNATIC,Lunatic,622,9004,10007,534,80,60,40,100,250,20,1500,150,0,0,300,300,1000,{ petskillbonus bLuk,3,10,50; },{ bonus bCritical,2; bonus bAtk,2; }
-1077,POISON_SPORE,Poison Spore,631,9013,10017,537,80,60,20,100,250,20,1000,150,0,0,600,200,400,{ petskillattack "NPC_POISON",20,0,0,10; },{ bonus bStr,1; bonus bInt,1; }
-1101,BAPHOMET_,Baphomet Jr.,642,9024,10001,518,80,60,10,100,250,20,200,150,0,0,1000,100,200,{ petskillattack "NPC_DARKNESSATTACK",1776,4,0,5; },{ bonus bDef,1; bonus bMdef,1; bonus2 bResEff,Eff_Stun,-100; }
-1107,DESERT_WOLF_B,Baby Desert Wolf,628,9010,10003,537,80,60,40,100,250,20,1000,150,0,0,400,400,400,{ petskillattack "SM_PROVOKE",1,0,0,5;},{ bonus bInt,1; bonus bMaxSP,50; }
-1109,DEVIRUCHI,Deviruchi,641,9023,10004,711,80,60,10,100,250,20,500,150,0,0,800,200,100,{ petskillbonus bAgiDexStr,6,20,40; },{ bonus bMatkRate,1; bonus bAtkRate,1; bonus bMaxHPrate,-3; bonus bMaxSPrate,-3; }
-1110,DOKEBI,Dokebi,637,9019,10005,537,80,60,20,100,250,20,500,150,0,0,300,300,800,{ petskillattack "BS_HAMMERFALL",1,0,0,10; },{ bonus bMatkRate,1; bonus bAtkRate,-1; }
-1113,DROPS,Drops,620,9002,10013,508,80,60,40,100,250,20,1500,150,1,0,300,400,500,{ petloot 10; },{ bonus bHit,3; bonus bAtk,3; }
-1155,PETIT,Petite,640,9022,10011,537,80,60,20,100,250,20,500,150,0,0,800,400,100,{ petskillattack "WZ_HEAVENDRIVE",500,1,0,10; },{ bonus bDef,-2; bonus bMdef,-2; bonus bAspdRate,1; }
-1167,SAVAGE_BABE,Savage Babe,627,9009,10015,537,80,60,40,100,250,20,1500,150,0,0,500,500,200,{ petskillbonus bVit,4,10,50; },{ bonus bVit,1; bonus bMaxHP,50; }
-1170,SOHEE,Sohee,638,9020,10016,537,80,60,10,100,250,20,500,150,0,0,100,1000,200,{ petskillsupport AL_HEAL,10,60,33,100; },{ bonus bStr,1; bonus bDex,1; }
-1188,BON_GUN,Bon Gun,659,9025,10020,537,80,60,30,100,250,20,500,150,1,0,600,200,400,{ petskillattack "NPC_DARKNESSATTACK",555,1,1,1; },{ bonus bVit,1; bonus2 bResEff,Eff_Stun,100; }
-1200,ZHERLTHSH,Zealotus,660,9026,0,929,80,60,10,100,250,20,300,150,0,0,1000,100,500,{ petskillattack "AS_SONICBLOW",1,0,0,3; },{ bonus2 bAddRace,RC_DemiPlayer,2; bonus2 bMagicAddRace,RC_DemiPlayer,2; }
-1245,GOBLINE_XMAS,Christmas Goblin,12225,9029,0,911,80,60,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "MG_SIGHT",5,0,5,5; },{ bonus bMaxHP,30; bonus2 bSubEle,Ele_Water,1; }
-1275,ALICE,Alice,661,9027,0,504,80,60,20,100,250,20,800,150,0,0,100,1000,200,{ petskillsupport "AL_HEAL",5,60,25,100; },{ bonus bMdef,1; bonus2 bSubRace,RC_DemiPlayer,1; }
-
-// New Pets
-1122,GOBLIN_1,Goblin,14569,9032,0,7821,80,60,50,100,250,20,800,150,0,0,300,300,800,{ petskillattack "NPC_WINDATTACK",5,0,5,5; },{}
-1123,GOBLIN_2,Goblin,14570,9033,0,7821,80,60,50,100,250,20,800,150,0,0,300,300,800,{ petskillattack "NPC_FIREATTACK",5,0,5,5; },{}
-1125,GOBLIN_4,Goblin,14571,9034,0,7821,80,60,50,100,250,20,800,150,0,0,300,300,800,{ petskillattack "NPC_GROUNDATTACK",5,0,5,5; },{}
-1208,WANDER_MAN,Wanderer,14574,9037,0,7824,80,60,20,100,250,20,800,150,0,0,300,300,800,{ petskillattack "NPC_UNDEADATTACK",5,0,5,5; },{}
-1382,DIABOLIC,Diabolic,14573,9036,0,7823,80,60,10,100,250,20,800,150,0,0,300,300,800,{ petskillattack "WZ_METEOR",2,0,5,5; },{}
-1385,DELETER_,Deleter,14572,9035,0,7822,80,60,20,100,250,20,800,150,0,0,300,300,800,{ petskillattack "SM_MAGNUM",5,0,5,5; },{}
-1879,ECLIPSE_P,Spring Rabbit,0,9031,0,7766,80,60,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "TF_THROWSTONE",1,0,5,5; },{}
-
-// Episode 12
-1963,P_CHUNG_E,New Year Doll,0,9038,0,554,80,60,30,100,250,20,800,150,0,0,300,300,800,{ petskillattack "CR_SHIELDCHARGE",5,0,5,5; },{}
-
-// Episode 13
-1815,EVENT_RICECAKE,Rice Cake,0,9028,0,511,80,60,50,100,250,20,2000,150,1,0,500,500,200,{ petskillsupport "CR_DEFENDER",3,240,50,100; },{ bonus2 bSubEle,Ele_Neutral,1; bonus bMaxHPrate,-1; }
-2210,XMAS_LUNATIC,Christmas Snow Rabbit,0,9058,0,529,80,60,10,100,250,20,0,150,1,0,300,300,800,{},{ bonus2 bExpAddRace,RC_All,5; }
-
-// Episode 13.2
-1040,GOLEM,Golem,12371,9053,10035,6111,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus bMaxHP,100; bonus bFlee,-5; }
-1143,MARIONETTE,Marionette,12361,9043,10025,6098,80,60,10,100,250,20,500,150,0,0,300,300,800,{},{ bonus bSPrecovRate,3; }
-1148,MEDUSA,Medusa,12368,9050,10032,6108,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus bVit,1; bonus2 bResEff,Eff_Stone,500; }
-1179,WHISPER,Whisper,12363,9045,10027,6100,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus bFlee,7; bonus bDef,-3; }
-1299,GOBLIN_LEADER,Goblin Leader,12364,9046,10028,6104,80,60,10,100,250,20,50,150,0,0,300,300,800,{},{ bonus2 bAddRace,RC_DemiPlayer,3; }
-1370,SUCCUBUS,Succubus,12373,9055,10037,6113,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus2 bHPDrainRate,50,5; }
-1374,INCUBUS,Incubus,12370,9052,10034,6110,80,60,10,100,250,20,50,150,0,0,300,300,800,{},{ bonus bMaxSPrate,3; }
-1379,NIGHTMARE_TERROR,Nightmare Terror,12372,9054,10036,6112,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus2 bResEff,Eff_Sleep,10000; }
-1401,SHINOBI,Shinobi,12362,9044,10026,6099,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus bAgi,2; }
-1404,MIYABI_NINGYO,Miyabi Doll,12366,9048,10030,6106,80,60,15,100,250,20,200,150,0,0,300,300,800,{},{ bonus bInt,1; bonus bCastrate,-3; }
-1416,WICKED_NYMPH,Evil Nymph,12365,9047,10029,6105,80,60,15,100,250,20,500,150,0,0,300,300,800,{},{ bonus bMaxSP,30; bonus bSPrecovRate,5; }
-1495,STONE_SHOOTER,Stone Shooter,12369,9051,10033,6109,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus2 bSubEle,Ele_Fire,3; }
-1504,DULLAHAN,Dullahan,12367,9049,10031,6107,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus bCritAtkRate,5; }
-1505,LOLI_RURI,Loli Ruri,12360,9042,10024,6097,80,60,15,100,250,20,200,150,0,0,300,300,800,{},{ bonus bMaxHPrate,3; bonus3 bAutoSpellWhenHit,"AL_HEAL",1,50; }
-1513,CIVIL_SERVANT,Mao Guai,12358,9040,10022,6095,80,60,10,100,250,20,500,150,0,0,300,300,800,{},{ bonus bMaxSP,10; }
-1519,CHUNG_E,Green Maiden,12395,9030,0,6115,80,60,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "CR_SHIELDCHARGE",5,0,5,5; },{ bonus bDef,1; bonus2 bSubRace,RC_DemiPlayer,1; }
-1586,LEAF_CAT,Leaf Cat,12359,9041,10023,6096,80,60,20,100,250,20,200,150,0,0,300,300,800,{},{ bonus2 bSubRace,RC_Brute,3; }
-1630,BACSOJIN_,White Lady,12357,9039,10021,6094,80,60,10,100,250,20,2000,150,0,0,300,300,800,{},{}
-1837,IMP,Fire Imp,12374,9056,10038,6114,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus2 bSubEle,Ele_Fire,2; bonus2 bAddEle,Ele_Fire,2; }
-
-// Episode 13.2 Brasilis
-2057,E_CRAMP,Strange Cramp,12408,6221,0,0,0,0,0,0,0,0,50,0,0,0,350,400,800,{},{} // kRO version
-2081,E_HYDRA,Strange Hydra,12408,6221,0,0,0,0,0,0,0,0,50,0,0,0,350,400,800,{},{} // iRO/cRO version
diff --git a/db/re/item_db.conf b/db/re/item_db.conf
index 80baad89f..6c4e820e8 100644
--- a/db/re/item_db.conf
+++ b/db/re/item_db.conf
@@ -144605,8 +144605,8 @@ item_db: (
Type: "IT_ARMOR"
Loc: "EQP_COSTUME_HEAD_LOW"
ViewSprite: 1331
- OnEquipScript: <" sc_start SC_BLOSSOM_FLUTTERING, -1, 0; ">
- OnUnequipScript: <" sc_end SC_BLOSSOM_FLUTTERING; ">
+ OnEquipScript: <" hateffect(HAT_EF_BLOSSOM_FLUTTERING, true); ">
+ OnUnequipScript: <" hateffect(HAT_EF_BLOSSOM_FLUTTERING, false); ">
},
{
Id: 20286
diff --git a/db/re/pet_db.conf b/db/re/pet_db.conf
new file mode 100644
index 000000000..6d6083e59
--- /dev/null
+++ b/db/re/pet_db.conf
@@ -0,0 +1,1649 @@
+//================= Hercules Database =====================================
+//= _ _ _
+//= | | | | | |
+//= | |_| | ___ _ __ ___ _ _| | ___ ___
+//= | _ |/ _ \ '__/ __| | | | |/ _ \/ __|
+//= | | | | __/ | | (__| |_| | | __/\__ \
+//= \_| |_/\___|_| \___|\__,_|_|\___||___/
+//================= License ===============================================
+//= This file is part of Hercules.
+//= http://herc.ws - http://github.com/HerculesWS/Hercules
+//=
+//= Copyright (C) 2018 Hercules Dev Team
+//=
+//= Hercules 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/>.
+//=========================================================================
+//= Pets Database
+//=========================================================================
+
+pet_db:(
+/**************************************************************************
+ ************* Entry structure ********************************************
+ **************************************************************************
+{
+ // ================ Mandatory fields ==============================
+ Id: ID (int)
+ SpriteName: "Sprite_Name" (string)
+ Name: "Pet Name" (string)
+ // ================ Optional fields ===============================
+ TamingItem: Taming Item (string, defaults to 0)
+ EggItem: Egg Id (string, defaults to 0)
+ AccessoryItem: Equipment Id (string, defaults to 0)
+ FoodItem: Food Id (string, defaults to 0)
+ FoodEffectiveness: hunger points (int, defaults to 0)
+ HungerDelay: hunger time (int, defaults to 0)
+ Intimacy: {
+ Initial: start intimacy (int, defaults to 0)
+ FeedIncrement: feeding intimacy (int, defaults to 0)
+ OverFeedDecrement: overfeeding intimacy (int, defaults to 0)
+ OwnerDeathDecrement: owner die intimacy (int, defaults to 0)
+ }
+ CaptureRate: capture rate (int, defaults to 0)
+ Speed: speed (int, defaults to 0)
+ SpecialPerformance: true/false (boolean, defaults to false)
+ TalkWithEmotes: convert talk (boolean, defaults to false)
+ AttackRate: attack rate (int, defaults to 0)
+ DefendRate: Defence attack (int, defaults to 0)
+ ChangeTargetRate: change target (int, defaults to 0)
+ PetScript: <" Pet Script (can also be multi-line) ">
+ EquipScript: <" Equip Script (can also be multi-line) ">
+},
+**************************************************************************/
+{
+ Id: 1002
+ SpriteName: "PORING"
+ Name: "Poring"
+ TamingItem: "Unripe_Apple"
+ EggItem: "Poring_Egg"
+ AccessoryItem: "Backpack"
+ FoodItem: "Apple_Juice"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 350
+ DefendRate: 400
+ ChangeTargetRate: 800
+ PetScript: <" petloot(10); ">
+ EquipScript: <"
+ bonus(bLuk, 2);
+ bonus(bCritical, 1);
+ ">
+},
+{
+ Id: 1011
+ SpriteName: "CHONCHON"
+ Name: "ChonChon"
+ TamingItem: "Rotten_Fish"
+ EggItem: "Chonchon_Egg"
+ AccessoryItem: "Monster_Oxygen_Mask"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1500
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 500
+ DefendRate: 500
+ ChangeTargetRate: 250
+ PetScript: <" petskillbonus(bAgi, 4, 10, 50); ">
+ EquipScript: <"
+ bonus(bAgi, 1);
+ bonus(bFlee, 2);
+ ">
+},
+{
+ Id: 1014
+ SpriteName: "SPORE"
+ Name: "Spore"
+ TamingItem: "Dew_Laden_Moss"
+ EggItem: "Spore_Egg"
+ AccessoryItem: "Bark_Shorts"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1500
+ Speed: 150
+ AttackRate: 350
+ DefendRate: 500
+ ChangeTargetRate: 500
+ PetScript: <" petrecovery(SC_POISON, 60); ">
+ EquipScript: <"
+ bonus(bHit, 5);
+ bonus(bAtk, -2);
+ ">
+},
+{
+ Id: 1019
+ SpriteName: "PECOPECO"
+ Name: "PecoPeco"
+ TamingItem: "Fatty_Chubby_Earthworm"
+ EggItem: "PecoPeco_Egg"
+ AccessoryItem: "Battered_Pot"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 400
+ DefendRate: 500
+ ChangeTargetRate: 800
+ PetScript: <" petskillbonus(bSpeedRate, 25, 20, 20); ">
+ EquipScript: <"
+ bonus(bMaxHP, 150);
+ bonus(bMaxSP, -10);
+ ">
+},
+{
+ Id: 1023
+ SpriteName: "ORK_WARRIOR"
+ Name: "Orc Warrior"
+ TamingItem: "Horror_Of_Tribe"
+ EggItem: "Orc_Warrior_Egg"
+ AccessoryItem: "Wild_Flower"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 600
+ DefendRate: 200
+ ChangeTargetRate: 300
+ PetScript: <" petskillattack("NPC_PIERCINGATT", 100, 1, 0, 10); ">
+ EquipScript: <"
+ bonus(bAtk, 10);
+ bonus(bDef, -3);
+ ">
+},
+{
+ Id: 1026
+ SpriteName: "MUNAK"
+ Name: "Munak"
+ TamingItem: "No_Recipient"
+ EggItem: "Munak_Egg"
+ AccessoryItem: "Punisher"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 750
+ ChangeTargetRate: 300
+ PetScript: <" petskillattack("NPC_DARKNESSATTACK", 444, 1, 0, 10); ">
+ EquipScript: <"
+ bonus(bInt, 1);
+ bonus(bDef, 1);
+ ">
+},
+{
+ Id: 1029
+ SpriteName: "ISIS"
+ Name: "Isis"
+ TamingItem: "Armlet_Of_Obedience"
+ EggItem: "Isis_Egg"
+ AccessoryItem: "Queens_Hair_Ornament"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 650
+ DefendRate: 450
+ ChangeTargetRate: 150
+ PetScript: <" petskillsupport("PR_MAGNIFICAT", 2, 60, 50, 50); ">
+ EquipScript: <"
+ bonus(bMatkRate, -1);
+ bonus(bAtkRate, 1);
+ ">
+},
+{
+ Id: 1031
+ SpriteName: "POPORING"
+ Name: "Poporing"
+ TamingItem: "Bitter_Herb"
+ EggItem: "Poporing_Egg"
+ AccessoryItem: "Backpack"
+ FoodItem: "Green_Herb"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 300
+ DefendRate: 500
+ ChangeTargetRate: 400
+ PetScript: <" petloot(15); ">
+ EquipScript: <"
+ bonus(bLuk, 2);
+ bonus2(bSubEle, Ele_Poison, 10);
+ ">
+},
+{
+ Id: 1035
+ SpriteName: "HUNTER_FLY"
+ Name: "Hunter Fly"
+ TamingItem: "Monster_Juice"
+ EggItem: "Hunter_Fly_Egg"
+ AccessoryItem: "Monster_Oxygen_Mask"
+ FoodItem: "Red_Gemstone"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 500
+ DefendRate: 500
+ ChangeTargetRate: 200
+ PetScript: <" petskillattack("NPC_WINDATTACK", 888, 2, 0, 10); ">
+ EquipScript: <"
+ bonus(bFlee, -5);
+ bonus(bFlee2, 2);
+ ">
+},
+{
+ Id: 1042
+ SpriteName: "STEEL_CHONCHON"
+ Name: "Steel ChonChon"
+ TamingItem: "Lusty_Iron"
+ EggItem: "Steel_Chonchon_Egg"
+ AccessoryItem: "Monster_Oxygen_Mask"
+ FoodItem: "Iron_Ore"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 500
+ DefendRate: 500
+ ChangeTargetRate: 200
+ PetScript: <" petskillbonus(bAgiVit, 4, 20, 40); ">
+ EquipScript: <"
+ bonus(bFlee, 6);
+ bonus(bAgi, -1);
+ ">
+},
+{
+ Id: 1049
+ SpriteName: "PICKY"
+ Name: "Picky"
+ TamingItem: "Earthworm_The_Dude"
+ EggItem: "Picky_Egg"
+ AccessoryItem: "Tiny_Egg_Shell"
+ FoodItem: "Red_Herb"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 40
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 500
+ DefendRate: 600
+ ChangeTargetRate: 50
+ PetScript: <" petskillbonus(bStr, 3, 10, 50); ">
+ EquipScript: <"
+ bonus(bStr, 1);
+ bonus(bAtk, 5);
+ ">
+},
+{
+ Id: 1052
+ SpriteName: "ROCKER"
+ Name: "Rocker"
+ TamingItem: "Singing_Flower"
+ EggItem: "Rocker_Egg"
+ AccessoryItem: "Rocker_Glasses"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1500
+ Speed: 150
+ AttackRate: 350
+ DefendRate: 350
+ ChangeTargetRate: 600
+ PetScript: <" petskillbonus(bAllStats, 1, 10, 50); ">
+ EquipScript: <"
+ bonus(bHPrecovRate, 5);
+ bonus(bMaxHP, 25);
+ ">
+},
+{
+ Id: 1056
+ SpriteName: "SMOKIE"
+ Name: "Smokie"
+ TamingItem: "Baked_Yam"
+ EggItem: "Smokie_Egg"
+ AccessoryItem: "Red_Muffler"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 600
+ DefendRate: 600
+ ChangeTargetRate: 100
+ PetScript: <" petskillbonus(bPerfectHide, 1, 3600, 0); ">
+ EquipScript: <"
+ bonus(bAgi, 1);
+ bonus(bFlee2, 1);
+ ">
+},
+{
+ Id: 1057
+ SpriteName: "YOYO"
+ Name: "Yoyo"
+ TamingItem: "Tropical_Banana"
+ EggItem: "Yoyo_Egg"
+ AccessoryItem: "Monkey_Circlet"
+ FoodItem: "Banana_Juice"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 300
+ DefendRate: 800
+ ChangeTargetRate: 400
+ PetScript: <" petloot(20); ">
+ EquipScript: <"
+ bonus(bCritical, 3);
+ bonus(bLuk, -1);
+ ">
+},
+{
+ Id: 1063
+ SpriteName: "LUNATIC"
+ Name: "Lunatic"
+ TamingItem: "Rainbow_Carrot"
+ EggItem: "Lunatic_Egg"
+ AccessoryItem: "Silk_Ribbon"
+ FoodItem: "Carrot_Juice"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 40
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 1000
+ PetScript: <" petskillbonus(bLuk, 3, 10, 50); ">
+ EquipScript: <"
+ bonus(bCritical, 2);
+ bonus(bAtk, 2);
+ ">
+},
+{
+ Id: 1077
+ SpriteName: "POISON_SPORE"
+ Name: "Poison Spore"
+ TamingItem: "Deadly_Noxious_Herb"
+ EggItem: "Poison_Spore_Egg"
+ AccessoryItem: "Bark_Shorts"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ AttackRate: 600
+ DefendRate: 200
+ ChangeTargetRate: 400
+ PetScript: <" petskillattack("NPC_POISON", 20, 0, 0, 10); ">
+ EquipScript: <"
+ bonus(bStr, 1);
+ bonus(bInt, 1);
+ ">
+},
+{
+ Id: 1101
+ SpriteName: "BAPHOMET_"
+ Name: "Baphomet Jr."
+ TamingItem: "Book_Of_Devil"
+ EggItem: "Bapho_Jr_Egg"
+ AccessoryItem: "Skull_Helm"
+ FoodItem: "Honey"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 1000
+ DefendRate: 100
+ ChangeTargetRate: 200
+ PetScript: <" petskillattack("NPC_DARKNESSATTACK", 1776, 4, 0, 5); ">
+ EquipScript: <"
+ bonus(bDef, 1);
+ bonus(bMdef, 1);
+ bonus2(bResEff, Eff_Stun, -100);
+ ">
+},
+{
+ Id: 1107
+ SpriteName: "DESERT_WOLF_B"
+ Name: "Baby Desert Wolf"
+ TamingItem: "Well_Dried_Bone"
+ EggItem: "Baby_Desert_Wolf_Egg"
+ AccessoryItem: "Transparent_Headgear"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 40
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ AttackRate: 400
+ DefendRate: 400
+ ChangeTargetRate: 400
+ PetScript: <" petskillattack("SM_PROVOKE", 1, 0, 0, 5);">
+ EquipScript: <"
+ bonus(bInt, 1);
+ bonus(bMaxSP, 50);
+ ">
+},
+{
+ Id: 1109
+ SpriteName: "DEVIRUCHI"
+ Name: "Deviruchi"
+ TamingItem: "Contracts_In_Shadow"
+ EggItem: "Deviruchi_Egg"
+ AccessoryItem: "Pacifier"
+ FoodItem: "Shoot"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 800
+ DefendRate: 200
+ ChangeTargetRate: 100
+ PetScript: <" petskillbonus(bAgiDexStr, 6, 20, 40); ">
+ EquipScript: <"
+ bonus(bMatkRate, 1);
+ bonus(bAtkRate, 1);
+ bonus(bMaxHPrate, -3);
+ bonus(bMaxSPrate, -3);
+ ">
+},
+{
+ Id: 1110
+ SpriteName: "DOKEBI"
+ Name: "Dokebi"
+ TamingItem: "Old_Broom"
+ EggItem: "Dokkaebi_Egg"
+ AccessoryItem: "Wig"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("BS_HAMMERFALL", 1, 0, 0, 10); ">
+ EquipScript: <"
+ bonus(bMatkRate, 1);
+ bonus(bAtkRate, -1);
+ ">
+},
+{
+ Id: 1113
+ SpriteName: "DROPS"
+ Name: "Drops"
+ TamingItem: "Orange_Juice"
+ EggItem: "Drops_Egg"
+ AccessoryItem: "Backpack"
+ FoodItem: "Yellow_Herb"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 40
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1500
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 300
+ DefendRate: 400
+ ChangeTargetRate: 500
+ PetScript: <" petloot(10); ">
+ EquipScript: <"
+ bonus(bHit, 3);
+ bonus(bAtk, 3);
+ ">
+},
+{
+ Id: 1155
+ SpriteName: "PETIT"
+ Name: "Petite"
+ TamingItem: "Shining_Stone"
+ EggItem: "Green_Petite_Egg"
+ AccessoryItem: "Stellar_Hairpin"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 800
+ DefendRate: 400
+ ChangeTargetRate: 100
+ PetScript: <" petskillattack("WZ_HEAVENDRIVE", 500, 1, 0, 10); ">
+ EquipScript: <"
+ bonus(bDef, -2);
+ bonus(bMdef, -2);
+ bonus(bAspdRate, 1);
+ ">
+},
+{
+ Id: 1167
+ SpriteName: "SAVAGE_BABE"
+ Name: "Savage Babe"
+ TamingItem: "Sweet_Milk"
+ EggItem: "Savage_Bebe_Egg"
+ AccessoryItem: "Green_Lace"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 40
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1500
+ Speed: 150
+ AttackRate: 500
+ DefendRate: 500
+ ChangeTargetRate: 200
+ PetScript: <" petskillbonus(bVit, 4, 10, 50); ">
+ EquipScript: <"
+ bonus(bVit, 1);
+ bonus(bMaxHP, 50);
+ ">
+},
+{
+ Id: 1170
+ SpriteName: "SOHEE"
+ Name: "Sohee"
+ TamingItem: "Silver_Knife_Of_Chaste"
+ EggItem: "Sohee_Egg"
+ AccessoryItem: "Golden_Bell"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 100
+ DefendRate: 1000
+ ChangeTargetRate: 200
+ PetScript: <" petskillsupport(AL_HEAL, 10, 60, 33, 100); ">
+ EquipScript: <"
+ bonus(bStr, 1);
+ bonus(bDex, 1);
+ ">
+},
+{
+ Id: 1188
+ SpriteName: "BON_GUN"
+ Name: "Bon Gun"
+ TamingItem: "Heart_Of_Her"
+ EggItem: "Bongun_Egg"
+ AccessoryItem: "Sword_Of_Grave_Keeper"
+ FoodItem: "Pet_Food"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 600
+ DefendRate: 200
+ ChangeTargetRate: 400
+ PetScript: <" petskillattack("NPC_DARKNESSATTACK", 555, 1, 1, 1); ">
+ EquipScript: <"
+ bonus(bVit, 1);
+ bonus2(bResEff, Eff_Stun, 100);
+ ">
+},
+{
+ Id: 1200
+ SpriteName: "ZHERLTHSH"
+ Name: "Zealotus"
+ TamingItem: "Prohibition_Red_Candle"
+ EggItem: "Zherlthsh_Egg"
+ FoodItem: "Immortal_Heart"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 300
+ Speed: 150
+ AttackRate: 1000
+ DefendRate: 100
+ ChangeTargetRate: 500
+ PetScript: <" petskillattack("AS_SONICBLOW", 1, 0, 0, 3); ">
+ EquipScript: <"
+ bonus2(bAddRace, RC_DemiPlayer, 2);
+ bonus2(bMagicAddRace, RC_DemiPlayer, 2);
+ ">
+},
+{
+ Id: 1245
+ SpriteName: "GOBLINE_XMAS"
+ Name: "Christmas Goblin"
+ TamingItem: "Sweet_Candy_Striper"
+ EggItem: "Santa_Goblin_Egg"
+ FoodItem: "Scell"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("MG_SIGHT", 5, 0, 5, 5); ">
+ EquipScript: <"
+ bonus(bMaxHP, 30);
+ bonus2(bSubEle, Ele_Water, 1);
+ ">
+},
+{
+ Id: 1275
+ SpriteName: "ALICE"
+ Name: "Alice"
+ TamingItem: "Sway_Apron"
+ EggItem: "Alice_Egg"
+ FoodItem: "White_Potion"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 100
+ DefendRate: 1000
+ ChangeTargetRate: 200
+ PetScript: <" petskillsupport("AL_HEAL", 5, 60, 25, 100); ">
+ EquipScript: <"
+ bonus(bMdef, 1);
+ bonus2(bAddRaceTolerance, RC_DemiPlayer, 1);
+ ">
+},
+// New Pets
+{
+ Id: 1122
+ SpriteName: "GOBLIN_1"
+ Name: "Goblin"
+ TamingItem: "Knife_Goblin_Ring"
+ EggItem: "Knife_Goblin_Egg"
+ FoodItem: "Green_Apple"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("NPC_WINDATTACK", 5, 0, 5, 5); ">
+},
+{
+ Id: 1123
+ SpriteName: "GOBLIN_2"
+ Name: "Goblin"
+ TamingItem: "Flail_Goblin_Ring"
+ EggItem: "Flail_Goblin_Egg"
+ FoodItem: "Green_Apple"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("NPC_FIREATTACK", 5, 0, 5, 5); ">
+},
+{
+ Id: 1125
+ SpriteName: "GOBLIN_4"
+ Name: "Goblin"
+ TamingItem: "Hammer_Goblin_Ring"
+ EggItem: "Hammer_Goblin_Egg"
+ FoodItem: "Green_Apple"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("NPC_GROUNDATTACK", 5, 0, 5, 5); ">
+},
+{
+ Id: 1208
+ SpriteName: "WANDER_MAN"
+ Name: "Wanderer"
+ TamingItem: "Skull_Of_Vagabond"
+ EggItem: "Wanderer_Egg"
+ FoodItem: "Spirit_Liquor"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("NPC_UNDEADATTACK", 5, 0, 5, 5); ">
+},
+{
+ Id: 1382
+ SpriteName: "DIABOLIC"
+ Name: "Diabolic"
+ TamingItem: "Red_Burning_Stone"
+ EggItem: "Diabolic_Egg"
+ FoodItem: "Meat_Veg_Skewer"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("WZ_METEOR", 2, 0, 5, 5); ">
+},
+{
+ Id: 1385
+ SpriteName: "DELETER_"
+ Name: "Deleter"
+ TamingItem: "Holy_Marble"
+ EggItem: "Red_Deleter_Egg"
+ FoodItem: "Whole_Barbecue"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("SM_MAGNUM", 5, 0, 5, 5); ">
+},
+{
+ Id: 1879
+ SpriteName: "ECLIPSE_P"
+ Name: "Spring Rabbit"
+ EggItem: "Spring_Rabbit_Egg"
+ FoodItem: "Bok_Choy"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("TF_THROWSTONE", 1, 0, 5, 5); ">
+},
+// Episode 12
+{
+ Id: 1963
+ SpriteName: "P_CHUNG_E"
+ Name: "New Year Doll"
+ EggItem: "New_Year_Doll_Egg"
+ FoodItem: "Mojji"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 30
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 800
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("CR_SHIELDCHARGE", 5, 0, 5, 5); ">
+},
+// Episode 13
+{
+ Id: 1815
+ SpriteName: "EVENT_RICECAKE"
+ Name: "Rice Cake"
+ EggItem: "Rice_Cake_Egg"
+ FoodItem: "Green_Herb"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 500
+ DefendRate: 500
+ ChangeTargetRate: 200
+ PetScript: <" petskillsupport("CR_DEFENDER", 3, 240, 50, 100); ">
+ EquipScript: <"
+ bonus2(bSubEle, Ele_Neutral, 1);
+ bonus(bMaxHPrate, -1);
+ ">
+},
+{
+ Id: 2210
+ SpriteName: "XMAS_LUNATIC"
+ Name: "Christmas Snow Rabbit"
+ EggItem: "Snow_Rabbit_Egg"
+ FoodItem: "Candy"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus2(bExpAddRace, RC_All, 5); ">
+},
+// Episode 13.2
+{
+ Id: 1040
+ SpriteName: "GOLEM"
+ Name: "Golem"
+ TamingItem: "Magical_Lithography"
+ EggItem: "Golem_Egg"
+ AccessoryItem: "Windup_Spring"
+ FoodItem: "Mystic_Stone"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus(bMaxHP, 100);
+ bonus(bFlee, -5);
+ ">
+},
+{
+ Id: 1143
+ SpriteName: "MARIONETTE"
+ Name: "Marionette"
+ TamingItem: "Delicious_Shaved_Ice"
+ EggItem: "Marionette_Egg"
+ AccessoryItem: "Star_Hairband"
+ FoodItem: "Small_Snow_Flower"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus(bSPrecovRate, 3); ">
+},
+{
+ Id: 1148
+ SpriteName: "MEDUSA"
+ Name: "Medusa"
+ TamingItem: "Splendid_Mirror"
+ EggItem: "Medusa_Egg"
+ AccessoryItem: "Queens_Coronet"
+ FoodItem: "Apple_Pudding"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus(bVit, 1);
+ bonus2(bResEff, Eff_Stone, 500);
+ ">
+},
+{
+ Id: 1179
+ SpriteName: "WHISPER"
+ Name: "Whisper"
+ TamingItem: "Fit_Pipe"
+ EggItem: "Whisper_Egg"
+ AccessoryItem: "Spirit_Chain_"
+ FoodItem: "Damp_Darkness"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus(bFlee, 7);
+ bonus(bDef, -3);
+ ">
+},
+{
+ Id: 1299
+ SpriteName: "GOBLIN_LEADER"
+ Name: "Goblin Leader"
+ TamingItem: "Staff_Of_Leader"
+ EggItem: "Goblin_Leader_Egg"
+ AccessoryItem: "Nice_Badge"
+ FoodItem: "Big_Cell"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 50
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus2(bAddRace, RC_DemiPlayer, 3); ">
+},
+{
+ Id: 1370
+ SpriteName: "SUCCUBUS"
+ Name: "Succubus"
+ TamingItem: "Boys_Naivety"
+ EggItem: "Succubus_Egg"
+ AccessoryItem: "Black_Butterfly_Mask"
+ FoodItem: "Vital_Flower_"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus2(bHPDrainRate, 50, 5); ">
+},
+{
+ Id: 1374
+ SpriteName: "INCUBUS"
+ Name: "Incubus"
+ TamingItem: "Grils_Naivety"
+ EggItem: "Incubus_Egg"
+ AccessoryItem: "Ball_Mask"
+ FoodItem: "Vital_Flower"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 50
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus(bMaxSPrate, 3); ">
+},
+{
+ Id: 1379
+ SpriteName: "NIGHTMARE_TERROR"
+ Name: "Nightmare Terror"
+ TamingItem: "Hell_Contract"
+ EggItem: "Nightmare_Terror_Egg"
+ AccessoryItem: "Hell_Horn"
+ FoodItem: "Fresh_Plant"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus2(bResEff, Eff_Sleep, 10000); ">
+},
+{
+ Id: 1401
+ SpriteName: "SHINOBI"
+ Name: "Shinobi"
+ TamingItem: "Kuloren"
+ EggItem: "Shinobi_Egg"
+ AccessoryItem: "Wine_On_Sleeve"
+ FoodItem: "Grilled_Rice_Cake"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus(bAgi, 2); ">
+},
+{
+ Id: 1404
+ SpriteName: "MIYABI_NINGYO"
+ Name: "Miyabi Doll"
+ TamingItem: "Gril_Doll"
+ EggItem: "Miyabi_Ningyo_Egg"
+ AccessoryItem: "Summer_Fan"
+ FoodItem: "Well_Ripened_Berry"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 15
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus(bInt, 1);
+ bonus(bCastrate, -3);
+ ">
+},
+{
+ Id: 1416
+ SpriteName: "WICKED_NYMPH"
+ Name: "Evil Nymph"
+ TamingItem: "Charming_Lotus"
+ EggItem: "Wicked_Nymph_Egg"
+ AccessoryItem: "Jade_Trinket"
+ FoodItem: "Morning_Dew"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 15
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus(bMaxSP, 30);
+ bonus(bSPrecovRate, 5);
+ ">
+},
+{
+ Id: 1495
+ SpriteName: "STONE_SHOOTER"
+ Name: "Stone Shooter"
+ TamingItem: "Oilpalm_Coconut"
+ EggItem: "Stone_Shooter_Egg"
+ AccessoryItem: "Apro_Hair"
+ FoodItem: "Plant_Neutrient"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus2(bSubEle, Ele_Fire, 3); ">
+},
+{
+ Id: 1504
+ SpriteName: "DULLAHAN"
+ Name: "Dullahan"
+ TamingItem: "Luxury_Whisky_Bottle"
+ EggItem: "Dullahan_Egg"
+ AccessoryItem: "Death_Coil"
+ FoodItem: "Sunset_On_The_Rock"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus(bCritAtkRate, 5); ">
+},
+{
+ Id: 1505
+ SpriteName: "LOLI_RURI"
+ Name: "Loli Ruri"
+ TamingItem: "Very_Red_Juice"
+ EggItem: "Loli_Ruri_Egg"
+ AccessoryItem: "Fashionable_Glasses"
+ FoodItem: "Pumpkin_Pie_"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 15
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus(bMaxHPrate, 3);
+ bonus3(bAutoSpellWhenHit, "AL_HEAL", 1, 50);
+ ">
+},
+{
+ Id: 1513
+ SpriteName: "CIVIL_SERVANT"
+ Name: "Mao Guai"
+ TamingItem: "Fan_Of_Wind"
+ EggItem: "Civil_Servant_Egg"
+ AccessoryItem: "Golden_Earing"
+ FoodItem: "Flavored_Alcohol"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 500
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <" bonus(bMaxSP, 10); ">
+},
+{
+ Id: 1519
+ SpriteName: "CHUNG_E"
+ Name: "Green Maiden"
+ TamingItem: "Tantanmen"
+ EggItem: "Chung_E_Egg"
+ FoodItem: "Bun_"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ PetScript: <" petskillattack("CR_SHIELDCHARGE", 5, 0, 5, 5); ">
+ EquipScript: <"
+ bonus(bDef, 1);
+ bonus2(bAddRaceTolerance, RC_DemiPlayer, 1);
+ ">
+},
+{
+ Id: 1586
+ SpriteName: "LEAF_CAT"
+ Name: "Leaf Cat"
+ TamingItem: "Very_Soft_Plant"
+ EggItem: "Leaf_Cat_Egg"
+ AccessoryItem: "Green_Lucky_Bag"
+ FoodItem: "Fish_With_Blue_Back"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 20
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus2(bAddRaceTolerance, RC_Brute, 3);
+ ">
+},
+{
+ Id: 1630
+ SpriteName: "BACSOJIN_"
+ Name: "White Lady"
+ TamingItem: "Shiny_Wing_Gown"
+ EggItem: "Bacsojin_Egg"
+ AccessoryItem: "Round_Hair_Ornament"
+ FoodItem: "Traditional_Cookie"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+},
+{
+ Id: 1837
+ SpriteName: "IMP"
+ Name: "Fire Imp"
+ TamingItem: "Flaming_Ice"
+ EggItem: "Imp_Egg"
+ AccessoryItem: "Horn_Protector"
+ FoodItem: "Flame_Gemstone"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 200
+ Speed: 150
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus2(bSubEle, Ele_Fire, 2);
+ bonus2(bAddEle, Ele_Fire, 2);
+ ">
+},
+// Episode 13.2 Brasilis
+{
+ Id: 2057
+ SpriteName: "E_CRAMP"
+ Name: "Strange Cramp"
+ TamingItem: "Leaf_Cat_Ball"
+ EggItem: "Mystic_Leaf_Cat_Ball"
+ CaptureRate: 50
+ AttackRate: 350
+ DefendRate: 400
+ ChangeTargetRate: 800
+},
+{
+ Id: 2081
+ SpriteName: "E_HYDRA"
+ Name: "Strange Hydra"
+ TamingItem: "Leaf_Cat_Ball"
+ EggItem: "Mystic_Leaf_Cat_Ball"
+ CaptureRate: 50
+ AttackRate: 350
+ DefendRate: 400
+ ChangeTargetRate: 800
+},
+// Episode 14.1
+{
+ Id: 2313
+ SpriteName: "TIKBALANG"
+ Name: "Tikbalang"
+ TamingItem: "Tikbalang_Belt"
+ EggItem: "Tikbalang_Pet"
+ FoodItem: "Monsters_Feed"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 1000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+ EquipScript: <"
+ bonus2(bAddDamageClass, 2320, 10);
+ bonus2(bAddDamageClass, 2321, 10);
+ bonus2(bAddDamageClass, 2322, 10);
+ bonus2(bAddDamageClass, 2317, 10);
+ bonus2(bAddDamageClass, 2318, 10);
+ bonus2(bAddDamageClass, 2327, 10);
+ bonus2(bAddDamageClass, 2319, 10);
+ bonus2(bAddDamageClass, 2333, 10);
+ bonus2(bAddDamageClass, 2332, 10);
+ ">
+},
+// New Pets
+{
+ Id: 1242
+ SpriteName: "MARIN"
+ Name: "Marin"
+ TamingItem: "Juicy_Fruit"
+ EggItem: "Marin_Egg"
+ AccessoryItem: "Tw_Backpack"
+ FoodItem: "Fruit_Sundae"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+},
+{
+ Id: 2200
+ SpriteName: "J_TAINI"
+ Name: "Tiny"
+ EggItem: "Egg_Of_Tiny"
+ FoodItem: "Apple"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 10
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 300
+ DefendRate: 300
+ ChangeTargetRate: 800
+},
+// Episode 14.2
+{
+ Id: 2398
+ SpriteName: "LITTLE_PORING"
+ Name: "Little Poring"
+ TamingItem: "Unripe_Apple2"
+ EggItem: "Novice_Poring_Egg"
+ AccessoryItem: "Backpack"
+ FoodItem: "Apple_Juice"
+ FoodEffectiveness: 80
+ HungerDelay: 60
+ Intimacy: {
+ Initial: 250
+ FeedIncrement: 50
+ OverFeedDecrement: 100
+ OwnerDeathDecrement: 20
+ }
+ CaptureRate: 2000
+ Speed: 150
+ SpecialPerformance: true
+ AttackRate: 350
+ DefendRate: 400
+ ChangeTargetRate: 800
+ PetScript: <" petloot(10); ">
+ EquipScript: <"
+ bonus(bLuk, 2);
+ bonus(bCritical, 1);
+ ">
+},
+)
diff --git a/db/re/pet_db.txt b/db/re/pet_db.txt
deleted file mode 100644
index 42d758cb9..000000000
--- a/db/re/pet_db.txt
+++ /dev/null
@@ -1,133 +0,0 @@
-// Pet Database
-//
-// Structure of Database:
-// MobID,Name,JName,LureID,EggID,EquipID,FoodID,Fullness,HungryDelay,R_Hungry,R_Full,Intimate,Die,Capture,Speed,S_Performance,talk_convert_class,attack_rate,defence_attack_rate,change_target_rate,pet_script,loyal_script
-//
-// 01. MobID Monster ID of the pet.
-// 02. Name Name of the monster as defined in the database.
-// 03. JName The display name of the monster when hatched.
-// 04. LureID Pet Tame Item ID.
-// 05. EggID Pet Egg ID.
-// 06. EquipID Pet Accessory ID.
-// 07. FoodID Pet Food ID.
-// 08. Fullness The amount of hunger points increasing with each feeding.
-// 09. HungryDelay The amount of time it takes for hunger to decrease after feeding. (Default: 60 seconds)
-// 10. R_Hungry Amount of Intimacy that is increased when fed.
-// 11. R_Full Amount of Intimacy that is decreased when over-fed.
-// 12. Intimate Amount of Intimacy the pet starts with.
-// 13. Die Amount of Intimacy that is decreased when the pet owner dies.
-// 14. Capture Capture succes rate (10000 = 100%)
-// 15. Speed Pet's walk speed. (Defaul: 150)
-// 16. S_Performance Special Performance. (Yes = 1, No = 0)
-// 17. talk_convert_class Disables pet talk (instead of talking they emote with /!.)
-// 18. attack_rate Rate of which the pet will attack (requires at least pet_support_min_friendly intimacy).
-// 19. defence_attack_rate Rate of which the pet will retaliate when master is being attacked (requires at least pet_support_min_friendly intimacy).
-// 20. change_target_rate Rate of which the pet will change its attack target.
-// 21. pet_script Script to execute when the pet is hatched.
-// 22. loyal_script Script to execute when the pet is hatched (requires at least pet_equip_min_friendly intimacy, independent of pet_script).
-//NOTE: The max value (100%) of attack_rate, defense_rate & change_target_rate is 10000.
-
-//In theory you can use any valid script, but it is run only once upon pet
-//loading, so it is recommended you use the specific pet scripts:
-
-//petskillattack skillid, skilllv, hits, rate, bonusrate
-//Skill attack that triggers while the pet is attacking. Rate is the base
-//chance of execution per attack. Bonusrate is an additional success rate when
-//intimacy reaches max. If hits is specified and different than 0, it will make
-//the pet cast the skill with a fixed amount of damage inflicted and the
-//specified number of hits. A value of zero uses the skill's defaults.
-
-//petskillsupport skillid, skilllv, delay, hp%, sp%
-//Casts a support skill when the health levels are below the specified hp% and
-//sp%. Delay is the minimum time in seconds before the skill can be cast again
-
-//petrecovery type, delay: Cures the "type" status effect after "delay" seconds
-
-//petskillbonus type, value, duration, delay
-//Gives bonus stats. Type is the stat to increase (bStr, bLuk), value is the
-//amount by which it is increased, duration signals how long the bonus lasts
-//delay is the time elapsed after the bonus ends and before it starts again.
-
-//A single pet can have petloot, petskillbonus, petskillattack and
-//petskillsupport at the same time, but only one of each.
-
-// Core
-1002,PORING,Poring,619,9001,10013,531,80,60,50,100,250,20,2000,150,1,0,350,400,800,{ petloot 10; },{ bonus bLuk,2; bonus bCritical,1; }
-1011,CHONCHON,ChonChon,624,9006,10002,537,80,60,30,100,250,20,1500,150,1,0,500,500,250,{ petskillbonus bAgi,4,10,50; },{ bonus bAgi,1; bonus bFlee,2; }
-1014,SPORE,Spore,630,9012,10017,537,80,60,30,100,250,20,1500,150,0,0,350,500,500,{ petrecovery SC_POISON,60; },{ bonus bHit,5; bonus bAtk,-2; }
-1019,PECOPECO,PecoPeco,632,9014,10010,537,80,60,30,100,250,20,1000,150,1,0,400,500,800,{ petskillbonus bSpeedRate,25,20,20; },{ bonus bMaxHP,150; bonus bMaxSP,-10; }
-1023,ORK_WARRIOR,Orc Warrior,635,9017,10009,537,80,60,20,100,250,20,500,150,1,0,600,200,300,{ petskillattack "NPC_PIERCINGATT",100,1,0,10; },{ bonus bAtk,10; bonus bDef,-3; }
-1026,MUNAK,Munak,636,9018,10008,537,80,60,20,100,250,20,500,150,0,0,300,750,300,{ petskillattack "NPC_DARKNESSATTACK",444,1,0,10; },{ bonus bInt,1; bonus bDef,1; }
-1029,ISIS,Isis,639,9021,10006,537,80,60,10,100,250,20,500,150,0,0,650,450,150,{ petskillsupport "PR_MAGNIFICAT",2,60,50,50; },{ bonus bMatkRate,-1; bonus bAtkRate,1; }
-1031,POPORING,Poporing,621,9003,10013,511,80,60,30,100,250,20,1000,150,1,0,300,500,400,{ petloot 15; },{ bonus bLuk,2; bonus2 bSubEle,Ele_Poison,10; }
-1035,HUNTER_FLY,Hunter Fly,626,9008,10002,716,80,60,10,100,250,20,500,150,1,0,500,500,200,{ petskillattack "NPC_WINDATTACK",888,2,0,10; },{ bonus bFlee,-5; bonus bFlee2,2; }
-1042,STEEL_CHONCHON,Steel ChonChon,625,9007,10002,1002,80,60,20,100,250,20,1000,150,1,0,500,500,200,{ petskillbonus bAgiVit,4,20,40; },{ bonus bFlee,6; bonus bAgi,-1; }
-1049,PICKY,Picky,623,9005,10012,507,80,60,40,100,250,20,2000,150,1,0,500,600,50,{ petskillbonus bStr,3,10,50;},{ bonus bStr,1; bonus bAtk,5; }
-1052,ROCKER,Rocker,629,9011,10014,537,80,60,30,100,250,20,1500,150,0,0,350,350,600,{ petskillbonus bAllStats,1,10,50; },{ bonus bHPrecovRate,5; bonus bMaxHP,25; }
-1056,SMOKIE,Smokie,633,9015,10019,537,80,60,30,100,250,20,1000,150,1,0,600,600,100,{ petskillbonus bPerfectHide,1,3600,0; },{ bonus bAgi,1; bonus bFlee2,1; }
-1057,YOYO,Yoyo,634,9016,10018,532,80,60,20,100,250,20,1000,150,1,0,300,800,400,{ petloot 20; },{ bonus bCritical,3; bonus bLuk,-1; }
-1063,LUNATIC,Lunatic,622,9004,10007,534,80,60,40,100,250,20,1500,150,0,0,300,300,1000,{ petskillbonus bLuk,3,10,50; },{ bonus bCritical,2; bonus bAtk,2; }
-1077,POISON_SPORE,Poison Spore,631,9013,10017,537,80,60,20,100,250,20,1000,150,0,0,600,200,400,{ petskillattack "NPC_POISON",20,0,0,10; },{ bonus bStr,1; bonus bInt,1; }
-1101,BAPHOMET_,Baphomet Jr.,642,9024,10001,518,80,60,10,100,250,20,200,150,0,0,1000,100,200,{ petskillattack "NPC_DARKNESSATTACK",1776,4,0,5; },{ bonus bDef,1; bonus bMdef,1; bonus2 bResEff,Eff_Stun,-100; }
-1107,DESERT_WOLF_B,Baby Desert Wolf,628,9010,10003,537,80,60,40,100,250,20,1000,150,0,0,400,400,400,{ petskillattack "SM_PROVOKE",1,0,0,5;},{ bonus bInt,1; bonus bMaxSP,50; }
-1109,DEVIRUCHI,Deviruchi,641,9023,10004,711,80,60,10,100,250,20,500,150,0,0,800,200,100,{ petskillbonus bAgiDexStr,6,20,40; },{ bonus bMatkRate,1; bonus bAtkRate,1; bonus bMaxHPrate,-3; bonus bMaxSPrate,-3; }
-1110,DOKEBI,Dokebi,637,9019,10005,537,80,60,20,100,250,20,500,150,0,0,300,300,800,{ petskillattack "BS_HAMMERFALL",1,0,0,10; },{ bonus bMatkRate,1; bonus bAtkRate,-1; }
-1113,DROPS,Drops,620,9002,10013,508,80,60,40,100,250,20,1500,150,1,0,300,400,500,{ petloot 10; },{ bonus bHit,3; bonus bAtk,3; }
-1155,PETIT,Petite,640,9022,10011,537,80,60,20,100,250,20,500,150,0,0,800,400,100,{ petskillattack "WZ_HEAVENDRIVE",500,1,0,10; },{ bonus bDef,-2; bonus bMdef,-2; bonus bAspdRate,1; }
-1167,SAVAGE_BABE,Savage Babe,627,9009,10015,537,80,60,40,100,250,20,1500,150,0,0,500,500,200,{ petskillbonus bVit,4,10,50; },{ bonus bVit,1; bonus bMaxHP,50; }
-1170,SOHEE,Sohee,638,9020,10016,537,80,60,10,100,250,20,500,150,0,0,100,1000,200,{ petskillsupport AL_HEAL,10,60,33,100; },{ bonus bStr,1; bonus bDex,1; }
-1188,BON_GUN,Bon Gun,659,9025,10020,537,80,60,30,100,250,20,500,150,1,0,600,200,400,{ petskillattack "NPC_DARKNESSATTACK",555,1,1,1; },{ bonus bVit,1; bonus2 bResEff,Eff_Stun,100; }
-1200,ZHERLTHSH,Zealotus,660,9026,0,929,80,60,10,100,250,20,300,150,0,0,1000,100,500,{ petskillattack "AS_SONICBLOW",1,0,0,3; },{ bonus2 bAddRace,RC_DemiPlayer,2; bonus2 bMagicAddRace,RC_DemiPlayer,2; }
-1245,GOBLINE_XMAS,Christmas Goblin,12225,9029,0,911,80,60,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "MG_SIGHT",5,0,5,5; },{ bonus bMaxHP,30; bonus2 bSubEle,Ele_Water,1; }
-1275,ALICE,Alice,661,9027,0,504,80,60,20,100,250,20,800,150,0,0,100,1000,200,{ petskillsupport "AL_HEAL",5,60,25,100; },{ bonus bMdef,1; bonus2 bAddRaceTolerance,RC_DemiPlayer,1; }
-
-// New Pets
-1122,GOBLIN_1,Goblin,14569,9032,0,7821,80,60,50,100,250,20,800,150,0,0,300,300,800,{ petskillattack "NPC_WINDATTACK",5,0,5,5; },{}
-1123,GOBLIN_2,Goblin,14570,9033,0,7821,80,60,50,100,250,20,800,150,0,0,300,300,800,{ petskillattack "NPC_FIREATTACK",5,0,5,5; },{}
-1125,GOBLIN_4,Goblin,14571,9034,0,7821,80,60,50,100,250,20,800,150,0,0,300,300,800,{ petskillattack "NPC_GROUNDATTACK",5,0,5,5; },{}
-1208,WANDER_MAN,Wanderer,14574,9037,0,7824,80,60,20,100,250,20,800,150,0,0,300,300,800,{ petskillattack "NPC_UNDEADATTACK",5,0,5,5; },{}
-1382,DIABOLIC,Diabolic,14573,9036,0,7823,80,60,10,100,250,20,800,150,0,0,300,300,800,{ petskillattack "WZ_METEOR",2,0,5,5; },{}
-1385,DELETER_,Deleter,14572,9035,0,7822,80,60,20,100,250,20,800,150,0,0,300,300,800,{ petskillattack "SM_MAGNUM",5,0,5,5; },{}
-1879,ECLIPSE_P,Spring Rabbit,0,9031,0,7766,80,60,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "TF_THROWSTONE",1,0,5,5; },{}
-
-// Episode 12
-1963,P_CHUNG_E,New Year Doll,0,9038,0,554,80,60,30,100,250,20,800,150,0,0,300,300,800,{ petskillattack "CR_SHIELDCHARGE",5,0,5,5; },{}
-
-// Episode 13
-1815,EVENT_RICECAKE,Rice Cake,0,9028,0,511,80,60,50,100,250,20,2000,150,1,0,500,500,200,{ petskillsupport "CR_DEFENDER",3,240,50,100; },{ bonus2 bSubEle,Ele_Neutral,1; bonus bMaxHPrate,-1; }
-2210,XMAS_LUNATIC,Christmas Snow Rabbit,0,9058,0,529,80,60,10,100,250,20,0,150,1,0,300,300,800,{},{ bonus2 bExpAddRace,RC_All,5; }
-
-// Episode 13.2
-1040,GOLEM,Golem,12371,9053,10035,6111,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus bMaxHP,100; bonus bFlee,-5; }
-1143,MARIONETTE,Marionette,12361,9043,10025,6098,80,60,10,100,250,20,500,150,0,0,300,300,800,{},{ bonus bSPrecovRate,3; }
-1148,MEDUSA,Medusa,12368,9050,10032,6108,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus bVit,1; bonus2 bResEff,Eff_Stone,500; }
-1179,WHISPER,Whisper,12363,9045,10027,6100,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus bFlee,7; bonus bDef,-3; }
-1299,GOBLIN_LEADER,Goblin Leader,12364,9046,10028,6104,80,60,10,100,250,20,50,150,0,0,300,300,800,{},{ bonus2 bAddRace,RC_DemiPlayer,3; }
-1370,SUCCUBUS,Succubus,12373,9055,10037,6113,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus2 bHPDrainRate,50,5; }
-1374,INCUBUS,Incubus,12370,9052,10034,6110,80,60,10,100,250,20,50,150,0,0,300,300,800,{},{ bonus bMaxSPrate,3; }
-1379,NIGHTMARE_TERROR,Nightmare Terror,12372,9054,10036,6112,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus2 bResEff,Eff_Sleep,10000; }
-1401,SHINOBI,Shinobi,12362,9044,10026,6099,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus bAgi,2; }
-1404,MIYABI_NINGYO,Miyabi Doll,12366,9048,10030,6106,80,60,15,100,250,20,200,150,0,0,300,300,800,{},{ bonus bInt,1; bonus bCastrate,-3; }
-1416,WICKED_NYMPH,Evil Nymph,12365,9047,10029,6105,80,60,15,100,250,20,500,150,0,0,300,300,800,{},{ bonus bMaxSP,30; bonus bSPrecovRate,5; }
-1495,STONE_SHOOTER,Stone Shooter,12369,9051,10033,6109,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus2 bSubEle,Ele_Fire,3; }
-1504,DULLAHAN,Dullahan,12367,9049,10031,6107,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus bCritAtkRate,5; }
-1505,LOLI_RURI,Loli Ruri,12360,9042,10024,6097,80,60,15,100,250,20,200,150,0,0,300,300,800,{},{ bonus bMaxHPrate,3; bonus3 bAutoSpellWhenHit,"AL_HEAL",1,50; }
-1513,CIVIL_SERVANT,Mao Guai,12358,9040,10022,6095,80,60,10,100,250,20,500,150,0,0,300,300,800,{},{ bonus bMaxSP,10; }
-1519,CHUNG_E,Green Maiden,12395,9030,0,6115,80,60,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "CR_SHIELDCHARGE",5,0,5,5; },{ bonus bDef,1; bonus2 bAddRaceTolerance,RC_DemiPlayer,1; }
-1586,LEAF_CAT,Leaf Cat,12359,9041,10023,6096,80,60,20,100,250,20,200,150,0,0,300,300,800,{},{ bonus2 bAddRaceTolerance,RC_Brute,2; }
-1630,BACSOJIN_,White Lady,12357,9039,10021,6094,80,60,10,100,250,20,2000,150,0,0,300,300,800,{},{}
-1837,IMP,Fire Imp,12374,9056,10038,6114,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus2 bSubEle,Ele_Fire,2; bonus2 bAddEle,Ele_Fire,2; }
-
-// Episode 13.2 Brasilis
-2057,E_CRAMP,Strange Cramp,12408,6221,0,0,0,0,0,0,0,0,50,0,0,0,350,400,800,{},{} // kRO version
-2081,E_HYDRA,Strange Hydra,12408,6221,0,0,0,0,0,0,0,0,50,0,0,0,350,400,800,{},{} // iRO/cRO version
-
-// Episode 14.1
-2313,TIKBALANG,Tikbalang,12699,9059,0,528,80,60,10,100,250,20,1000,150,1,0,300,300,800,{},{ bonus2 bAddDamageClass,2320,10; bonus2 bAddDamageClass,2321,10; bonus2 bAddDamageClass,2322,10; bonus2 bAddDamageClass,2317,10; bonus2 bAddDamageClass,2318,10; bonus2 bAddDamageClass,2327,10; bonus2 bAddDamageClass,2319,10; bonus2 bAddDamageClass,2333,10; bonus2 bAddDamageClass,2332,10; }
-
-// New Pets
-1242,MARIN,Marin,12789,9061,10039,6534,80,60,50,100,250,20,2000,150,1,0,300,300,800,{},{}
-2200,J_TAINI,Tiny,0,9057,0,512,80,60,10,100,250,20,0,150,1,0,300,300,800,{},{}
-
-// Episode 14.2
-2398,LITTLE_PORING,Little Poring,12846,9062,10013,531,80,60,50,100,250,20,2000,150,1,0,350,400,800,{ petloot 10; },{ bonus bLuk,2; bonus bCritical,1; }
diff --git a/doc/constants.md b/doc/constants.md
index cd5417471..978cc7ecd 100644
--- a/doc/constants.md
+++ b/doc/constants.md
@@ -3793,6 +3793,65 @@
- `UDT_ROBE`: 55
- `UDT_BODY2`: 56
+### HatEffect Constants
+
+- `HAT_EF_BLOSSOM_FLUTTERING`: 1
+- `HAT_EF_MERMAID_LONGING`: 2
+- `HAT_EF_RL_BANISHING_BUSTER`: 3
+- `HAT_EF_LJOSALFAR`: 4
+- `HAT_EF_CLOCKING`: 5
+- `HAT_EF_SNOW`: 6
+- `HAT_EF_MAKEBLUR`: 7
+- `HAT_EF_SLEEPATTACK`: 8
+- `HAT_EF_GUMGANG`: 9
+- `HAT_EF_TALK_FROSTJOKE`: 10
+- `HAT_EF_DEMONSTRATION`: 11
+- `HAT_EF_FLUTTER_BUTTERFLY`: 12
+- `HAT_EF_ANGEL_FLUTTERING`: 13
+- `HAT_EF_BLESSING_OF_ANGELS`: 14
+- `HAT_EF_ELECTRIC`: 15
+- `HAT_EF_GREEN_FLOOR`: 16
+- `HAT_EF_SHRINK`: 17
+- `HAT_EF_VALHALLA_IDOL`: 18
+- `HAT_EF_ANGEL_STAIRS`: 19
+- `HAT_EF_GLOW_OF_NEW_YEAR`: 20
+- `HAT_EF_BOTTOM_FORTUNEKISS`: 21
+- `HAT_EF_PINKBODY`: 22
+- `HAT_EF_DOUBLEGUMGANG`: 23
+- `HAT_EF_GIANTBODY`: 24
+- `HAT_EF_GREEN99_6`: 25
+- `HAT_EF_CIRCLEPOWER`: 26
+- `HAT_EF_BOTTOM_BLOODYLUST`: 27
+- `HAT_EF_WATER_BELOW`: 28
+- `HAT_EF_LEVEL99_150`: 29
+- `HAT_EF_YELLOWFLY3`: 30
+- `HAT_EF_KAGEMUSYA`: 31
+- `HAT_EF_CHERRYBLOSSOM`: 32
+- `HAT_EF_STRANGELIGHTS`: 33
+- `HAT_EF_WL_TELEKINESIS_INTENSE`: 34
+- `HAT_EF_AB_OFFERTORIUM_RING`: 35
+- `HAT_EF_WHITEBODY2`: 36
+- `HAT_EF_SAKURA`: 37
+- `HAT_EF_CLOUD2`: 38
+- `HAT_EF_FEATHER_FLUTTERING`: 39
+- `HAT_EF_CAMELLIA_HAIR_PIN`: 40
+- `HAT_EF_JP_EV_EFFECT01`: 41
+- `HAT_EF_JP_EV_EFFECT02`: 42
+- `HAT_EF_JP_EV_EFFECT03`: 43
+- `HAT_EF_FLORAL_WALTZ`: 44
+- `HAT_EF_MAGICAL_FEATHER`: 45
+- `HAT_EF_HAT_EFFECT`: 46
+- `HAT_EF_BAKURETSU_HADOU`: 47
+- `HAT_EF_GOLD_SHOWER`: 48
+- `HAT_EF_WHITEBODY`: 49
+- `HAT_EF_WATER_BELOW2`: 50
+- `HAT_EF_FIREWORK`: 51
+- `HAT_EF_RETURN_TW_1ST_HAT`: 52
+- `HAT_EF_C_FLUTTERBUTTERFLY_BL`: 53
+- `HAT_EF_QSCARABA`: 54
+- `HAT_EF_FSTONE`: 55
+- `HAT_EF_MAGICCIRCLE`: 56
+
## Hardcoded Constants (source)
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index e14e80444..d69322745 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -3271,6 +3271,13 @@ produced). It's useful for when you want to check whether an item contains
cards or if it's signed.
---------------------------------------
+
+*hateffect(<Hat Effect ID>, <State>)
+
+This will set a Hat Effect onto the player. The state field allows you to
+enable (true) or disable (false) the effect on the player.
+
+---------------------------------------
//=====================================
2.1 - End of Item-Related Commands
//=====================================
diff --git a/npc/mapflag/noteleport.txt b/npc/mapflag/noteleport.txt
index 700964da4..b80498f89 100644
--- a/npc/mapflag/noteleport.txt
+++ b/npc/mapflag/noteleport.txt
@@ -154,6 +154,7 @@ thor_camp mapflag noteleport
moc_para01 mapflag noteleport
// Job Quests ====================
+pay_arche mapflag noteleport
job_sword1 mapflag noteleport
job_thief1 mapflag noteleport
// 2-1 -----------------------
diff --git a/sql-files/item_db.sql b/sql-files/item_db.sql
index 3a045faf0..08b1be3cd 100644
--- a/sql-files/item_db.sql
+++ b/sql-files/item_db.sql
@@ -4202,6 +4202,7 @@ REPLACE INTO `item_db` VALUES ('9053','Golem_Egg','Golem Egg','7','0','20','10',
REPLACE INTO `item_db` VALUES ('9054','Nightmare_Terror_Egg','Nightmare Terror Egg','7','0','20','10','0','0','0','0','0','0','18446744073709551615','63','2','0','0','0',NULL,'0','1','0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','','');
REPLACE INTO `item_db` VALUES ('9055','Succubus_Egg','Succubus Egg','7','0','20','10','0','0','0','0','0','0','18446744073709551615','63','2','0','0','0',NULL,'0','1','0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','','');
REPLACE INTO `item_db` VALUES ('9056','Imp_Egg','Imp Egg','7','0','20','10','0','0','0','0','0','0','18446744073709551615','63','2','0','0','0',NULL,'0','1','0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','','');
+REPLACE INTO `item_db` VALUES ('9058','Snow_Rabbit_Egg','Christmas Snow Rabbit Egg','7','0','20','10','0','0','0','0','0','0','18446744073709551615','63','2','0','0','0',NULL,'0','1','0','0','0','0','0','467',NULL,'0',NULL,'0',NULL,'0','','','');
REPLACE INTO `item_db` VALUES ('10001','Skull_Helm','Skull Helm','8','0','20','10','0','0','0','0','0','0','18446744073709551615','63','2','0','0','0',NULL,'0','1','0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','','');
REPLACE INTO `item_db` VALUES ('10002','Monster_Oxygen_Mask','Monster Oxygen Mask','8','0','20','10','0','0','0','0','0','0','18446744073709551615','63','2','0','0','0',NULL,'0','1','0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','','');
REPLACE INTO `item_db` VALUES ('10003','Transparent_Headgear','Transparent Head Protector','8','0','20','10','0','0','0','0','0','0','18446744073709551615','63','2','0','0','0',NULL,'0','1','0','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','','');
diff --git a/sql-files/item_db_re.sql b/sql-files/item_db_re.sql
index 4c762b8e8..072895142 100644
--- a/sql-files/item_db_re.sql
+++ b/sql-files/item_db_re.sql
@@ -9638,7 +9638,7 @@ REPLACE INTO `item_db` VALUES ('20281','C_Kindergarten_Hat','Costume Kindergarte
REPLACE INTO `item_db` VALUES ('20282','C_White_Student_Cap','Costume White Student Cap','5','0','0','0','0','0','0','0','0','0','18446744073709551615','63','2','1024','0','0',NULL,'1','0','877','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','','');
REPLACE INTO `item_db` VALUES ('20283','C_Over_Protector','Costume Over Protector','5','0','0','0','0','0','0','0','0','0','18446744073709551615','63','2','1024','0','0',NULL,'1','0','1329','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','','');
REPLACE INTO `item_db` VALUES ('20284','C_Cherry_Blossom_Hat','Costume Sakura Hat','5','0','0','0','0','0','0','0','0','0','18446744073709551615','63','2','1024','0','0',NULL,'1','0','1330','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','','');
-REPLACE INTO `item_db` VALUES ('20285','C_Blossom_Fluttering','Costume Dancing Fallen Sakura','5','0','0','0','0','0','0','0','0','0','18446744073709551615','63','2','4096','0','0',NULL,'1','0','1331','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','sc_start SC_BLOSSOM_FLUTTERING, -1, 0;','sc_end SC_BLOSSOM_FLUTTERING;');
+REPLACE INTO `item_db` VALUES ('20285','C_Blossom_Fluttering','Costume Dancing Fallen Sakura','5','0','0','0','0','0','0','0','0','0','18446744073709551615','63','2','4096','0','0',NULL,'1','0','1331','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','hateffect(HAT_EF_BLOSSOM_FLUTTERING, true);','hateffect(HAT_EF_BLOSSOM_FLUTTERING, false);');
REPLACE INTO `item_db` VALUES ('20286','C_Under_Rim_Glasses_Red','Costume Under Rim Glasses Red','5','0','0','0','0','0','0','0','0','0','18446744073709551615','63','2','2048','0','0',NULL,'1','0','1332','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','','');
REPLACE INTO `item_db` VALUES ('20287','C_Mans_Medal_','Costume Man\'s Medal(Gold)','5','0','0','0','0','0','0','0','0','0','18446744073709551615','63','2','1024','0','0',NULL,'1','0','1333','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','','');
REPLACE INTO `item_db` VALUES ('20288','C_Bijou_Hat','Costume Bijou Hat','5','0','0','0','0','0','0','0','0','0','18446744073709551615','63','2','1024','0','0',NULL,'1','0','1334','0','0','0','0','0',NULL,'0',NULL,'0',NULL,'0','','','');
diff --git a/sql-files/main.sql b/sql-files/main.sql
index 5546c0271..2e51d6a12 100644
--- a/sql-files/main.sql
+++ b/sql-files/main.sql
@@ -219,6 +219,8 @@ CREATE TABLE IF NOT EXISTS `char` (
`uniqueitem_counter` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
`sex` ENUM('M','F','U') NOT NULL DEFAULT 'U',
`hotkey_rowshift` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
+ `attendance_count` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
+ `attendance_timer` BIGINT(20) NULL DEFAULT '0',
PRIMARY KEY (`char_id`),
UNIQUE KEY `name_key` (`name`),
KEY `account_id` (`account_id`),
@@ -890,6 +892,7 @@ INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1496588640); -- 2017-06-0
INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1496588700); -- 2017-06-04--15-05.sql
INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1509835214); -- 2017-11-04--10-39.sql
INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1519671456); -- 2018-02-26--15-57.sql
+INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1520654809); -- 2018-03-10--04-06.sql
--
-- Table structure for table `storage`
--
diff --git a/sql-files/upgrades/2018-03-10--04-06.sql b/sql-files/upgrades/2018-03-10--04-06.sql
new file mode 100644
index 000000000..ee827735d
--- /dev/null
+++ b/sql-files/upgrades/2018-03-10--04-06.sql
@@ -0,0 +1,24 @@
+#1520654809
+
+-- This file is part of Hercules.
+-- http://herc.ws - http://github.com/HerculesWS/Hercules
+--
+-- Copyright (C) 2017 Hercules Dev Team
+--
+-- Hercules 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/>.
+
+ALTER TABLE `char` ADD COLUMN `attendance_count` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `hotkey_rowshift`;
+ALTER TABLE `char` ADD COLUMN `attendance_timer` BIGINT(20) NULL DEFAULT '0' AFTER `attendance_count`;
+
+INSERT INTO `sql_updates` (`timestamp`, `ignored`) VALUES (1520654809 , 'No');
diff --git a/sql-files/upgrades/index.txt b/sql-files/upgrades/index.txt
index a2d0c5171..dac60b6aa 100644
--- a/sql-files/upgrades/index.txt
+++ b/sql-files/upgrades/index.txt
@@ -44,3 +44,4 @@
2017-06-04--15-05.sql
2017-11-04--10-39.sql
2018-02-26--15-57.sql
+2018-03-10--04-06.sql
diff --git a/src/char/char.c b/src/char/char.c
index 0069e7f1d..84cc1b688 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -467,7 +467,8 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
(p->rename != cp->rename) || (p->slotchange != cp->slotchange) || (p->look.robe != cp->look.robe) ||
(p->show_equip != cp->show_equip) || (p->allow_party != cp->allow_party) || (p->font != cp->font) ||
(p->uniqueitem_counter != cp->uniqueitem_counter) || (p->hotkey_rowshift != cp->hotkey_rowshift) ||
- (p->clan_id != cp->clan_id) || (p->last_login != cp->last_login)
+ (p->clan_id != cp->clan_id) || (p->last_login != cp->last_login) || (p->attendance_count != cp->attendance_count) ||
+ (p->attendance_timer != cp->attendance_timer)
) {
//Save status
unsigned int opt = 0;
@@ -485,7 +486,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
"`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d',"
"`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d',"
"`delete_date`='%lu',`robe`='%d',`slotchange`='%d', `char_opt`='%u', `font`='%u', `uniqueitem_counter` ='%u',"
- "`hotkey_rowshift`='%d',`clan_id`='%d',`last_login`='%"PRId64"'"
+ "`hotkey_rowshift`='%d',`clan_id`='%d',`last_login`='%"PRId64"',`attendance_count`='%d',`attendance_timer`='%"PRId64"'"
" WHERE `account_id`='%d' AND `char_id` = '%d'",
char_db, p->base_level, p->job_level,
p->base_exp, p->job_exp, p->zeny,
@@ -497,7 +498,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename,
(unsigned long)p->delete_date, // FIXME: platform-dependent size
p->look.robe,p->slotchange,opt,p->font,p->uniqueitem_counter,
- p->hotkey_rowshift,p->clan_id,p->last_login,
+ p->hotkey_rowshift,p->clan_id,p->last_login, p->attendance_count, p->attendance_timer,
p->account_id, p->char_id) )
{
Sql_ShowDebug(inter->sql_handle);
@@ -1175,7 +1176,7 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
"`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`,"
"`hair_color`,`clothes_color`,`body`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`,"
"`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`,`slotchange`,"
- "`char_opt`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`,`clan_id`,`last_login`"
+ "`char_opt`,`font`,`uniqueitem_counter`,`sex`,`hotkey_rowshift`,`clan_id`,`last_login`, `attendance_count`, `attendance_timer`"
" FROM `%s` WHERE `char_id`=? LIMIT 1", char_db)
|| SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, sizeof char_id)
|| SQL_ERROR == SQL->StmtExecute(stmt)
@@ -1240,6 +1241,8 @@ int char_mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_every
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 58, SQLDT_UCHAR, &p->hotkey_rowshift, sizeof p->hotkey_rowshift, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 59, SQLDT_INT, &p->clan_id, sizeof p->clan_id, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 60, SQLDT_INT64, &p->last_login, sizeof p->last_login, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 61, SQLDT_SHORT, &p->attendance_count, sizeof p->attendance_count, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 62, SQLDT_INT64, &p->attendance_timer, sizeof p->attendance_timer, NULL, NULL)
) {
SqlStmt_ShowDebug(stmt);
SQL->StmtFree(stmt);
@@ -3328,7 +3331,7 @@ void char_char_name_ack(int fd, int char_id)
WFIFOHEAD(fd,30);
WFIFOW(fd,0) = 0x2b09;
WFIFOL(fd,2) = char_id;
-#if !defined(PACKETVER_ZERO) && (PACKETVER >= 20180307 || (defined(PACKETVER_RE) && PACKETVER >= 20180221))
+#if PACKETVER_MAIN_NUM >= 20180307 || PACKETVER_RE_NUM >= 20180221 || PACKETVER_ZERO_NUM >= 20180328
if (chr->loadName(char_id, WFIFOP(fd,6)) == 0)
WFIFOL(fd, 6) = 0;
#else
diff --git a/src/char/int_guild.c b/src/char/int_guild.c
index 0102f11a0..3f34e883b 100644
--- a/src/char/int_guild.c
+++ b/src/char/int_guild.c
@@ -417,8 +417,8 @@ struct guild * inter_guild_fromsql(int guild_id)
}
// load guild member info
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name` "
- "FROM `%s` WHERE `guild_id`='%d' ORDER BY `position`", guild_member_db, guild_id) )
+ if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT g.`account_id`,g.`char_id`,g.`hair`,g.`hair_color`,g.`gender`,g.`class`,g.`lv`,g.`exp`,g.`exp_payper`,g.`online`,g.`position`,g.`name`,c.`last_login`"
+ "FROM `%s` g LEFT JOIN `%s` c ON c.`char_id` = g.`char_id` WHERE g.`guild_id`='%d' ORDER BY `position`", guild_member_db, char_db, guild_id) )
{
Sql_ShowDebug(inter->sql_handle);
aFree(g);
@@ -442,6 +442,7 @@ struct guild * inter_guild_fromsql(int guild_id)
if( m->position >= MAX_GUILDPOSITION ) // Fix reduction of MAX_GUILDPOSITION [PoW]
m->position = MAX_GUILDPOSITION - 1;
SQL->GetData(inter->sql_handle, 11, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH));
+ SQL->GetData(inter->sql_handle, 12, &data, NULL); m->last_login = atoi(data);
m->modified = GS_MEMBER_UNMODIFIED;
}
@@ -975,7 +976,7 @@ int mapif_guild_withdraw(int guild_id,int account_id,int char_id,int flag, const
// Send short member's info
int mapif_guild_memberinfoshort(struct guild *g, int idx)
{
- unsigned char buf[19];
+ unsigned char buf[23];
nullpo_ret(g);
Assert_ret(idx >= 0 && idx < MAX_GUILD);
WBUFW(buf, 0)=0x3835;
@@ -985,7 +986,8 @@ int mapif_guild_memberinfoshort(struct guild *g, int idx)
WBUFB(buf,14)=(unsigned char)g->member[idx].online;
WBUFW(buf,15)=g->member[idx].lv;
WBUFW(buf,17)=g->member[idx].class;
- mapif->sendall(buf,19);
+ WBUFL(buf,19)=g->member[idx].last_login;
+ mapif->sendall(buf,23);
return 0;
}
@@ -1366,6 +1368,7 @@ int mapif_parse_GuildChangeMemberInfoShort(int fd, int guild_id, int account_id,
g->member[i].online = online;
g->member[i].lv = lv;
g->member[i].class = class;
+ g->member[i].last_login = (uint32)time(NULL);
g->member[i].modified = GS_MEMBER_MODIFIED;
mapif->guild_memberinfoshort(g,i);
}
diff --git a/src/char/int_rodex.c b/src/char/int_rodex.c
index 2001ddc43..0dab66f61 100644
--- a/src/char/int_rodex.c
+++ b/src/char/int_rodex.c
@@ -83,8 +83,8 @@ static int inter_rodex_fromsql(int char_id, int account_id, int8 opentype, int64
if (SQL_ERROR == SQL->StmtPrepare(stmt,
"SELECT `mail_id`, `sender_name`, `sender_id`, `receiver_name`, `receiver_id`, `receiver_accountid`,"
"`title`, `body`, `zeny`, `type`, `is_read`, `sender_read`, `send_date`, `expire_date`, `weight`"
- "FROM `%s` WHERE (`is_read` = 0 AND `sender_id` = '%d' AND `expire_date` <= '%d' AND `send_date` + '%d' > '%d' AND `mail_id` > '%"PRId64"')"
- "ORDER BY `mail_id` ASC", rodex_db, char_id, (int)time(NULL), 2 * RODEX_EXPIRE, (int)time(NULL), mail_id)
+ "FROM `%s` WHERE (`is_read` = 0 AND `sender_id` = '%d' AND `expire_date` <= '%d' AND `expire_date` + '%d' > '%d' AND `mail_id` > '%"PRId64"')"
+ "ORDER BY `mail_id` ASC", rodex_db, char_id, (int)time(NULL), RODEX_EXPIRE, (int)time(NULL), mail_id)
) {
SqlStmt_ShowDebug(stmt);
SQL->StmtFree(stmt);
@@ -98,8 +98,8 @@ static int inter_rodex_fromsql(int char_id, int account_id, int8 opentype, int64
"`title`, `body`, `zeny`, `type`, `is_read`, `sender_read`, `send_date`, `expire_date`, `weight`"
"FROM `%s` WHERE "
"((`expire_date` > '%d' AND (`receiver_id` = '%d' OR `receiver_accountid` = '%d'))"
- "OR (`is_read` = 0 AND `sender_id` = '%d' AND `expire_date` <= '%d' AND `send_date` + '%d' > '%d'))"
- "ORDER BY `mail_id` ASC", rodex_db, (int)time(NULL), char_id, account_id, char_id, (int)time(NULL), 2 * RODEX_EXPIRE, (int)time(NULL))
+ "OR (`is_read` = 0 AND `sender_id` = '%d' AND `expire_date` <= '%d' AND `expire_date` + '%d' > '%d'))"
+ "ORDER BY `mail_id` ASC", rodex_db, (int)time(NULL), char_id, account_id, char_id, (int)time(NULL), RODEX_EXPIRE, (int)time(NULL))
) {
SqlStmt_ShowDebug(stmt);
SQL->StmtFree(stmt);
diff --git a/src/common/HPMDataCheck.h b/src/common/HPMDataCheck.h
index 4bcb33e23..f8a55218e 100644
--- a/src/common/HPMDataCheck.h
+++ b/src/common/HPMDataCheck.h
@@ -426,6 +426,7 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = {
#define MAP_CLAN_H
#endif // MAP_CLAN_H
#ifdef MAP_CLIF_H
+ { "attendance_entry", sizeof(struct attendance_entry), SERVER_TYPE_MAP },
{ "cdelayed_damage", sizeof(struct cdelayed_damage), SERVER_TYPE_MAP },
{ "clif_interface", sizeof(struct clif_interface), SERVER_TYPE_MAP },
{ "hCSData", sizeof(struct hCSData), SERVER_TYPE_MAP },
@@ -585,6 +586,7 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = {
{ "NORMALITEM_INFO", sizeof(struct NORMALITEM_INFO), SERVER_TYPE_MAP },
{ "PACKET_CZ_ADD_ITEM_TO_MAIL", sizeof(struct PACKET_CZ_ADD_ITEM_TO_MAIL), SERVER_TYPE_MAP },
{ "PACKET_CZ_CHECKNAME", sizeof(struct PACKET_CZ_CHECKNAME), SERVER_TYPE_MAP },
+ { "PACKET_CZ_OPEN_UI", sizeof(struct PACKET_CZ_OPEN_UI), SERVER_TYPE_MAP },
{ "PACKET_CZ_REQ_DELETE_MAIL", sizeof(struct PACKET_CZ_REQ_DELETE_MAIL), SERVER_TYPE_MAP },
{ "PACKET_CZ_REQ_ITEM_FROM_MAIL", sizeof(struct PACKET_CZ_REQ_ITEM_FROM_MAIL), SERVER_TYPE_MAP },
{ "PACKET_CZ_REQ_NEXT_MAIL_LIST", sizeof(struct PACKET_CZ_REQ_NEXT_MAIL_LIST), SERVER_TYPE_MAP },
@@ -605,14 +607,18 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = {
{ "PACKET_ZC_ADD_MEMBER_TO_GROUP", sizeof(struct PACKET_ZC_ADD_MEMBER_TO_GROUP), SERVER_TYPE_MAP },
{ "PACKET_ZC_CHECKNAME", sizeof(struct PACKET_ZC_CHECKNAME), SERVER_TYPE_MAP },
{ "PACKET_ZC_CLANINFO", sizeof(struct PACKET_ZC_CLANINFO), SERVER_TYPE_MAP },
+ { "PACKET_ZC_FORMATSTRING_MSG", sizeof(struct PACKET_ZC_FORMATSTRING_MSG), SERVER_TYPE_MAP },
{ "PACKET_ZC_GROUP_LIST", sizeof(struct PACKET_ZC_GROUP_LIST), SERVER_TYPE_MAP },
{ "PACKET_ZC_GROUP_LIST_SUB", sizeof(struct PACKET_ZC_GROUP_LIST_SUB), SERVER_TYPE_MAP },
{ "PACKET_ZC_MAIL_LIST", sizeof(struct PACKET_ZC_MAIL_LIST), SERVER_TYPE_MAP },
+ { "PACKET_ZC_MSG_COLOR", sizeof(struct PACKET_ZC_MSG_COLOR), SERVER_TYPE_MAP },
{ "PACKET_ZC_NOTIFY_CLAN_CHAT", sizeof(struct PACKET_ZC_NOTIFY_CLAN_CHAT), SERVER_TYPE_MAP },
{ "PACKET_ZC_NOTIFY_CLAN_CONNECTINFO", sizeof(struct PACKET_ZC_NOTIFY_CLAN_CONNECTINFO), SERVER_TYPE_MAP },
{ "PACKET_ZC_NOTIFY_UNREADMAIL", sizeof(struct PACKET_ZC_NOTIFY_UNREADMAIL), SERVER_TYPE_MAP },
+ { "PACKET_ZC_OPEN_UI", sizeof(struct PACKET_ZC_OPEN_UI), SERVER_TYPE_MAP },
{ "PACKET_ZC_READ_MAIL", sizeof(struct PACKET_ZC_READ_MAIL), SERVER_TYPE_MAP },
{ "PACKET_ZC_SKILL_SCALE", sizeof(struct PACKET_ZC_SKILL_SCALE), SERVER_TYPE_MAP },
+ { "PACKET_ZC_UI_ACTION", sizeof(struct PACKET_ZC_UI_ACTION), SERVER_TYPE_MAP },
{ "PACKET_ZC_WRITE_MAIL_RESULT", sizeof(struct PACKET_ZC_WRITE_MAIL_RESULT), SERVER_TYPE_MAP },
{ "ZC_PROGRESS_ACTOR", sizeof(struct ZC_PROGRESS_ACTOR), SERVER_TYPE_MAP },
{ "mail_item", sizeof(struct mail_item), SERVER_TYPE_MAP },
@@ -656,8 +662,14 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = {
{ "packet_npc_market_result_ack", sizeof(struct packet_npc_market_result_ack), SERVER_TYPE_MAP },
{ "packet_package_item_announce", sizeof(struct packet_package_item_announce), SERVER_TYPE_MAP },
{ "packet_party_leader_changed", sizeof(struct packet_party_leader_changed), SERVER_TYPE_MAP },
+ { "packet_quest_add_header", sizeof(struct packet_quest_add_header), SERVER_TYPE_MAP },
+ { "packet_quest_hunt_info", sizeof(struct packet_quest_hunt_info), SERVER_TYPE_MAP },
+ { "packet_quest_hunt_info_sub", sizeof(struct packet_quest_hunt_info_sub), SERVER_TYPE_MAP },
+ { "packet_quest_hunt_sub", sizeof(struct packet_quest_hunt_sub), SERVER_TYPE_MAP },
{ "packet_quest_list_header", sizeof(struct packet_quest_list_header), SERVER_TYPE_MAP },
{ "packet_quest_list_info", sizeof(struct packet_quest_list_info), SERVER_TYPE_MAP },
+ { "packet_quest_update_header", sizeof(struct packet_quest_update_header), SERVER_TYPE_MAP },
+ { "packet_quest_update_hunt", sizeof(struct packet_quest_update_hunt), SERVER_TYPE_MAP },
{ "packet_roulette_close_ack", sizeof(struct packet_roulette_close_ack), SERVER_TYPE_MAP },
{ "packet_roulette_generate_ack", sizeof(struct packet_roulette_generate_ack), SERVER_TYPE_MAP },
{ "packet_roulette_info_ack", sizeof(struct packet_roulette_info_ack), SERVER_TYPE_MAP },
diff --git a/src/common/mmo.h b/src/common/mmo.h
index f9cbc57de..1110fa8f5 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -81,6 +81,22 @@
#undef ENABLE_PACKETVER_ZERO
#endif // DISABLE_PACKETVER_ZERO
+#if !defined(PACKETVER_RE) && !defined(PACKETVER_ZERO)
+ #define PACKETVER_MAIN_NUM PACKETVER
+#else
+ #define PACKETVER_MAIN_NUM 0
+#endif
+#ifdef PACKETVER_RE
+ #define PACKETVER_RE_NUM PACKETVER
+#else
+ #define PACKETVER_RE_NUM 0
+#endif
+#ifdef PACKETVER_ZERO
+ #define PACKETVER_ZERO_NUM PACKETVER
+#else
+ #define PACKETVER_ZERO_NUM 0
+#endif
+
// Client support for experimental RagexeRE UI present in 2012-04-10 and 2012-04-18
#if defined(PACKETVER_RE) && ( PACKETVER == 20120410 || PACKETVER == 20120418 )
#define PARTY_RECRUIT
@@ -664,6 +680,9 @@ struct mmo_charstatus {
uint32 uniqueitem_counter;
+ int64 attendance_timer;
+ short attendance_count;
+
unsigned char hotkey_rowshift;
};
@@ -746,6 +765,7 @@ struct guild_member {
char name[NAME_LENGTH];
struct map_session_data *sd;
unsigned char modified;
+ uint32 last_login;
};
struct guild_position {
diff --git a/src/map/battle.c b/src/map/battle.c
index b2490ed23..5f56599d7 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -7320,6 +7320,9 @@ static const struct battle_data {
{ "features/rodex", &battle_config.feature_rodex, 1, 0, 1, },
{ "features/rodex_use_accountmail", &battle_config.feature_rodex_use_accountmail, 0, 0, 1, },
{ "features/enable_homun_autofeed", &battle_config.feature_enable_homun_autofeed, 1, 0, 1, },
+ { "storage_use_item", &battle_config.storage_use_item, 0, 0, 1, },
+ { "features/enable_attendance_system", &battle_config.feature_enable_attendance_system,1, 0, 1, },
+ { "features/feature_attendance_endtime",&battle_config.feature_attendance_endtime, 1, 0, 99999999, },
};
#ifndef STATS_OPT_OUT
/**
diff --git a/src/map/battle.h b/src/map/battle.h
index 9eb7557f8..998c0b011 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -563,6 +563,11 @@ struct Battle_Config {
int feature_rodex_use_accountmail;
int feature_enable_homun_autofeed;
+
+ int storage_use_item;
+
+ int feature_enable_attendance_system;
+ int feature_attendance_endtime;
};
/* criteria for battle_config.idletime_critera */
diff --git a/src/map/clif.c b/src/map/clif.c
index cf5edd0e0..60f4b18c0 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -1539,6 +1539,7 @@ bool clif_spawn(struct block_list *bl)
clif->spiritcharm(sd);
if (sd->status.look.robe != 0)
clif->refreshlook(bl, bl->id, LOOK_ROBE, sd->status.look.robe, AREA);
+ clif->hat_effect(bl, NULL, AREA);
}
break;
case BL_MOB:
@@ -4395,6 +4396,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
clif->sendbgemblem_single(sd->fd,tsd);
if (tsd->status.look.robe != 0)
clif->refreshlook(&sd->bl, bl->id, LOOK_ROBE, tsd->status.look.robe, SELF);
+ clif->hat_effect(bl, &sd->bl, SELF);
}
break;
case BL_MER: // Devotion Effects
@@ -5466,6 +5468,7 @@ void clif_skill_warppoint(struct map_session_data* sd, uint16 skill_id, uint16 s
/// 0 = "Saved location as a Memo Point for Warp skill." in color 0xFFFF00 (cyan)
/// 1 = "Skill Level is not high enough." in color 0x0000FF (red)
/// 2 = "You haven't learned Warp." in color 0x0000FF (red)
+/// 3 = "Cannot save location as a Memo Point at current location." in color 0x0000FF (red)
///
/// @param sd Who receives the message
/// @param type What message
@@ -5488,6 +5491,7 @@ void clif_skill_memomessage(struct map_session_data* sd, int type)
/// 0 = "Unable to Teleport in this area" in color 0xFFFF00 (cyan)
/// 1 = "Saved point cannot be memorized." in color 0x0000FF (red)
/// 2 = "This skill cannot be used within this area." in color 0xFFFF00 (cyan)
+/// 3 = "This item cannot be used within this area." in color 0xFFFF00 (cyan)
///
/// @param sd Who receives the message
/// @param type What message
@@ -6092,7 +6096,7 @@ void clif_wis_end(int fd, int flag) {
void clif_solved_charname(int fd, int charid, const char* name)
{
nullpo_retv(name);
-#if !defined(PACKETVER_ZERO) && (PACKETVER >= 20180307 || (defined(PACKETVER_RE) && PACKETVER >= 20180221))
+#if PACKETVER_MAIN_NUM >= 20180307 || PACKETVER_RE_NUM >= 20180221 || PACKETVER_ZERO_NUM >= 20180328
WFIFOHEAD(fd, packet_len(0x0af7));
WFIFOW(fd, 0) = 0xaf7;
if (*name == 0) {
@@ -7715,7 +7719,7 @@ void clif_guild_memberlist(struct map_session_data *sd)
memset(WFIFOP(fd, c * size + 34), 0, 50); //[Ind] - This is displayed in the 'note' column but being you can't edit it it's sent empty.
memcpy(WFIFOP(fd, c * size + 84), m->name, NAME_LENGTH);
#else
- WFIFOL(fd, c * size + 34) = 0; // [4144] this is member last login time. But in hercules it not present.
+ WFIFOL(fd, c * size + 34) = m->last_login; // [Megasantos] - Shows last date online
#endif
c++;
}
@@ -9230,6 +9234,56 @@ void clif_msgtable_skill(struct map_session_data* sd, uint16 skill_id, int msg_i
}
/**
+* Displays a format string from msgstringtable.txt with a %s value (ZC_FORMATSTRING_MSG).
+*
+* @param sd The target character.
+* @param msg_id msgstringtable message index, 0-based (@see enum clif_messages)
+* @param value The value to fill %s.
+*/
+void clif_msgtable_str(struct map_session_data *sd, uint16 msg_id, const char *value)
+{
+ int message_len;
+ int len;
+ struct PACKET_ZC_FORMATSTRING_MSG *p;
+
+ nullpo_retv(sd);
+ nullpo_retv(value);
+
+ message_len = (int)strlen(value) + 1;
+ len = sizeof(*p) + message_len + 1;
+
+ p = (struct PACKET_ZC_FORMATSTRING_MSG *)aMalloc(len);
+ p->PacketType = 0x2c2;
+ p->PacketLength = len;
+ p->MessageId = msg_id;
+ safestrncpy(p->MessageString, value, message_len);
+ p->MessageString[message_len] = 0;
+
+ clif->send(p, p->PacketLength, &sd->bl, SELF);
+ aFree(p);
+}
+
+/**
+* Displays a format string from msgstringtable.txt with a color (ZC_MSG_COLOR).
+*
+* @param sd The target character.
+* @param msg_id msgstringtable message index, 0-based (@see enum clif_messages)
+* @param color The color to use
+*/
+void clif_msgtable_color(struct map_session_data *sd, uint16 msg_id, uint32 color)
+{
+ struct PACKET_ZC_MSG_COLOR p;
+
+ nullpo_retv(sd);
+
+ p.PacketType = 0x9cd;
+ p.MessageId = msg_id;
+ p.MessageColor = RGB2BGR(color);
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+}
+
+/**
* Validates and processes a global/guild/party message packet.
*
* @param[in] sd The source character.
@@ -9756,6 +9810,13 @@ void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) {
clif->partyinvitationstate(sd);
clif->equpcheckbox(sd);
#endif
+
+#if PACKETVER_MAIN_NUM >= 20171025 || PACKETVER_RE_NUM >= 20170920
+ if (sd->hd != NULL)
+ clif->zc_config(sd, CZ_CONFIG_HOMUNCULUS_AUTOFEEDING, sd->hd->homunculus.autofeed);
+ else
+ clif->zc_config(sd, CZ_CONFIG_HOMUNCULUS_AUTOFEEDING, false);
+#endif
if( (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100)
&& (map_flag_gvg2(sd->state.pmap) || map_flag_gvg2(sd->bl.m)
|| map->list[sd->state.pmap].flag.battleground || map->list[sd->bl.m].flag.battleground) )
@@ -14218,10 +14279,8 @@ void clif_friendslist_toggle(struct map_session_data *sd,int account_id, int cha
WFIFOL(fd, 2) = sd->status.friends[i].account_id;
WFIFOL(fd, 6) = sd->status.friends[i].char_id;
WFIFOB(fd, 10) = !online; //Yeah, a 1 here means "logged off", go figure...
-#ifndef PACKETVER_ZERO
-#if PACKETVER >= 20180307 || (defined(PACKETVER_RE) && PACKETVER >= 20180221)
+#if PACKETVER_MAIN_NUM >= 20180307 || PACKETVER_RE_NUM >= 20180221
memcpy(WFIFOP(fd, 11), sd->status.friends[i].name, NAME_LENGTH);
-#endif
#endif // PACKETVER_ZERO
WFIFOSET(fd, packet_len(0x206));
@@ -14245,7 +14304,7 @@ void clif_friendslist_send(struct map_session_data *sd)
{
int i = 0, n, fd = sd->fd;
-#if !defined(PACKETVER_ZERO) && (PACKETVER >= 20180307 || (defined(PACKETVER_RE) && PACKETVER >= 20180221))
+#if PACKETVER_MAIN_NUM >= 20180307 || PACKETVER_RE_NUM >= 20180221
const int offset = 8;
#else
const int offset = 32;
@@ -14257,7 +14316,7 @@ void clif_friendslist_send(struct map_session_data *sd)
for(i = 0; i < MAX_FRIENDS && sd->status.friends[i].char_id; i++) {
WFIFOL(fd, 4 + offset * i + 0) = sd->status.friends[i].account_id;
WFIFOL(fd, 4 + offset * i + 4) = sd->status.friends[i].char_id;
-#if !(!defined(PACKETVER_ZERO) && (PACKETVER >= 20180307 || (defined(PACKETVER_RE) && PACKETVER >= 20180221)))
+#if !(PACKETVER_MAIN_NUM >= 20180307 || PACKETVER_RE_NUM >= 20180221)
memcpy(WFIFOP(fd, 4 + offset * i + 8), &sd->status.friends[i].name, NAME_LENGTH);
#endif
}
@@ -16126,6 +16185,7 @@ void clif_parse_PartyTick(int fd, struct map_session_data* sd)
/// Sends list of all quest states (ZC_ALL_QUEST_LIST).
/// 02b1 <packet len>.W <num>.L { <quest id>.L <active>.B }*num
/// 097a <packet len>.W <num>.L { <quest id>.L <active>.B <remaining time>.L <time>.L <count>.W { <mob_id>.L <killed>.W <total>.W <mob name>.24B }*count }*num
+/// 09f8 <packet len>.W <num>.L { <quest id>.L <active>.B <remaining time>.L <time>.L <count>.W { <hunt identification>.L <mob type>.L <mob_id>.L <min level>.L <max level>.L <killed>.W <total>.W <mob name>.24B }*count }*num
void clif_quest_send_list(struct map_session_data *sd)
{
int i, len, real_len;
@@ -16164,8 +16224,16 @@ void clif_quest_send_list(struct map_session_data *sd)
real_len += sizeof(info->objectives[j]);
mob_data = mob->db(qi->objectives[j].mob);
-
+#if PACKETVER >= 20150513
+ info->objectives[j].huntIdent = (sd->quest_log[i].quest_id * 1000) + j;
+ info->objectives[j].mobType = 0; // Info Needed
+#endif
info->objectives[j].mob_id = qi->objectives[j].mob;
+#if PACKETVER >= 20150513
+ // Info Needed
+ info->objectives[j].levelMin = 0;
+ info->objectives[j].levelMax = 0;
+#endif
info->objectives[j].huntCount = sd->quest_log[i].count[j];
info->objectives[j].maxCount = qi->objectives[j].count;
safestrncpy(info->objectives[j].mobName, mob_data->jname, sizeof(info->objectives[j].mobName));
@@ -16213,33 +16281,53 @@ void clif_quest_send_mission(struct map_session_data *sd)
/// Notification about a new quest (ZC_ADD_QUEST).
/// 02b3 <quest id>.L <active>.B <start time>.L <expire time>.L <mobs>.W { <mob id>.L <mob count>.W <mob name>.24B }*3
+/// 09f9 <quest id>.L <active>.B <start time>.L <expire time>.L <mobs>.W { <hunt identification>.L <mob type>.L <mob id>.L <min level>.L <max level>.L <mob count>.W <mob name>.24B }*3
void clif_quest_add(struct map_session_data *sd, struct quest *qd)
{
- int fd;
- int i;
+ int i, len;
+ uint8 *buf = NULL;
+ struct packet_quest_add_header *packet = NULL;
struct quest_db *qi;
nullpo_retv(sd);
nullpo_retv(qd);
- fd = sd->fd;
+
qi = quest->db(qd->quest_id);
- WFIFOHEAD(fd, packet_len(0x2b3));
- WFIFOW(fd, 0) = 0x2b3;
- WFIFOL(fd, 2) = qd->quest_id;
- WFIFOB(fd, 6) = qd->state;
- WFIFOB(fd, 7) = qd->time - qi->time;
- WFIFOL(fd, 11) = qd->time;
- WFIFOW(fd, 15) = qi->objectives_count;
+ Assert_retv(qi->objectives_count < MAX_QUEST_OBJECTIVES);
+
+ len = sizeof(struct packet_quest_add_header)
+ + MAX_QUEST_OBJECTIVES * sizeof(struct packet_quest_hunt_sub); // >= than the actual length
+
+ buf = aCalloc(1, len);
+ packet = (struct packet_quest_add_header *)WBUFP(buf, 0);
+
+ packet->PacketType = questAddType;
+ packet->questID = qd->quest_id;
+ packet->active = qd->state;
+ packet->quest_svrTime = qd->time - qi->time;
+ packet->quest_endTime = qd->time;
+ packet->count = qi->objectives_count;
for (i = 0; i < qi->objectives_count; i++) {
struct mob_db *monster;
- WFIFOL(fd, i*30+17) = qi->objectives[i].mob;
- WFIFOW(fd, i*30+21) = qd->count[i];
+
monster = mob->db(qi->objectives[i].mob);
- memcpy(WFIFOP(fd, i*30+23), monster->jname, NAME_LENGTH);
- }
- WFIFOSET(fd, packet_len(0x2b3));
+#if PACKETVER >= 20150513
+ packet->objectives[i].huntIdent = (qd->quest_id * 1000) + i;
+ packet->objectives[i].mobType = 0; // Info Needed
+#endif
+ packet->objectives[i].mob_id = qi->objectives[i].mob;
+#if PACKETVER >= 20150513
+ // Info Needed
+ packet->objectives[i].levelMin = 0;
+ packet->objectives[i].levelMax = 0;
+#endif
+ packet->objectives[i].huntCount = qd->count[i];
+ memcpy(packet->objectives[i].mobName, monster->jname, NAME_LENGTH);
+ }
+ clif->send(buf, len, &sd->bl, SELF);
+ aFree(buf);
}
/// Notification about a quest being removed (ZC_DEL_QUEST).
@@ -16257,32 +16345,84 @@ void clif_quest_delete(struct map_session_data *sd, int quest_id) {
/// Notification of an update to the hunting mission counter (ZC_UPDATE_MISSION_HUNT).
/// 02b5 <packet len>.W <mobs>.W { <quest id>.L <mob id>.L <total count>.W <current count>.W }*3
+/// 09fa <packet len>.W <mobs>.W { <quest id>.L <hunt identification>.L <total count>.W <current count>.W }*3
void clif_quest_update_objective(struct map_session_data *sd, struct quest *qd)
{
- int fd;
- int i;
+ int i, len, real_len;
+ uint8 *buf = NULL;
+ struct packet_quest_update_header *packet = NULL;
struct quest_db *qi;
- int len;
nullpo_retv(sd);
nullpo_retv(qd);
- fd = sd->fd;
+
qi = quest->db(qd->quest_id);
- len = qi->objectives_count * 12 + 6;
+ Assert_retv(qi->objectives_count < MAX_QUEST_OBJECTIVES);
+
+ len = sizeof(struct packet_quest_update_header)
+ + MAX_QUEST_OBJECTIVES * sizeof(struct packet_quest_update_hunt); // >= than the actual length
- WFIFOHEAD(fd, len);
- WFIFOW(fd, 0) = 0x2b5;
- WFIFOW(fd, 2) = len;
- WFIFOW(fd, 4) = qi->objectives_count;
+ buf = aCalloc(1, len);
+ packet = (struct packet_quest_update_header *)WBUFP(buf, 0);
+ real_len = sizeof(*packet);
+
+ packet->PacketType = questUpdateType;
+ packet->count = qi->objectives_count;
for (i = 0; i < qi->objectives_count; i++) {
- WFIFOL(fd, i*12+6) = qd->quest_id;
- WFIFOL(fd, i*12+10) = qi->objectives[i].mob;
- WFIFOW(fd, i*12+14) = qi->objectives[i].count;
- WFIFOW(fd, i*12+16) = qd->count[i];
+ real_len += sizeof(packet->objectives[i]);
+
+ packet->objectives[i].questID = qd->quest_id;
+#if PACKETVER >= 20150513
+ packet->objectives[i].huntIdent = (qd->quest_id * 1000) + i;
+#else
+ packet->objectives[i].mob_id = qi->objectives[i].mob;
+#endif
+ packet->objectives[i].maxCount = qi->objectives[i].count;
+ packet->objectives[i].count = qd->count[i];
}
+ packet->PacketLength = real_len;
+ clif->send(buf, real_len, &sd->bl, SELF);
+ aFree(buf);
+}
- WFIFOSET(fd, len);
+/// Notification of an hunting mission counter just after quest is added (ZC_HUNTING_QUEST_INFO).
+/// 08fe <packet len>.W { <quest id>.L <mob id>.L <total count>.W <current count>.W }*3
+void clif_quest_notify_objective(struct map_session_data *sd, struct quest *qd)
+{
+#if PACKETVER >= 20150513
+ int i, len, real_len;
+ uint8 *buf = NULL;
+ struct packet_quest_hunt_info *packet = NULL;
+ struct quest_db *qi;
+
+ nullpo_retv(sd);
+ nullpo_retv(qd);
+
+ qi = quest->db(qd->quest_id);
+ Assert_retv(qi->objectives_count < MAX_QUEST_OBJECTIVES);
+
+ len = sizeof(struct packet_quest_hunt_info)
+ + MAX_QUEST_OBJECTIVES * sizeof(struct packet_quest_hunt_info_sub); // >= than the actual length
+
+ buf = aCalloc(1, len);
+ packet = (struct packet_quest_hunt_info *)WBUFP(buf, 0);
+ real_len = sizeof(*packet);
+
+ packet->PacketType = questUpdateType2;
+
+ for (i = 0; i < qi->objectives_count; i++) {
+ real_len += sizeof(packet->info[i]);
+
+ packet->info[i].questID = qd->quest_id;
+ packet->info[i].mob_id = qi->objectives[i].mob;
+ packet->info[i].maxCount = qi->objectives[i].count;
+ packet->info[i].count = qd->count[i];
+ }
+ packet->PacketLength = real_len;
+ clif->send(buf, real_len, &sd->bl, SELF);
+ aFree(buf);
+#endif
}
void clif_parse_questStateAck(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
@@ -20228,6 +20368,248 @@ void clif_skill_scale(struct block_list *bl, int src_id, int x, int y, uint16 sk
#endif
}
+/// Send hat effects to the client (ZC_HAT_EFFECT).
+/// 0A3B <Length>.W <AID>.L <Status>.B { <HatEffectId>.W }
+void clif_hat_effect(struct block_list *bl, struct block_list *tbl, enum send_target target)
+{
+#if PACKETVER >= 20150422
+ unsigned char *buf;
+ int len, i;
+ struct map_session_data *sd;
+
+ nullpo_retv(bl);
+
+ sd = BL_CAST(BL_PC, bl);
+
+ nullpo_retv(sd);
+
+ len = 9 + VECTOR_LENGTH(sd->hatEffectId) * 2;
+
+ buf = (unsigned char*)aMalloc(len);
+
+ WBUFW(buf, 0) = 0xa3b;
+ WBUFW(buf, 2) = len;
+ WBUFL(buf, 4) = bl->id;
+ WBUFB(buf, 8) = 1;
+
+ for( i = 0; i < VECTOR_LENGTH(sd->hatEffectId); i++ ){
+ WBUFW(buf, 9 + i * 2) = VECTOR_INDEX(sd->hatEffectId, i);
+ }
+
+ if (tbl != NULL) {
+ clif->send(buf, len, tbl, target);
+ } else {
+ clif->send(buf, len, bl, target);
+ }
+
+ aFree(buf);
+#endif
+}
+
+void clif_hat_effect_single(struct block_list *bl, uint16 effectId, bool enable){
+#if PACKETVER >= 20150422
+ unsigned char buf[13];
+
+ nullpo_retv(bl);
+
+ WBUFW(buf,0) = 0xa3b;
+ WBUFW(buf,2) = 13;
+ WBUFL(buf,4) = bl->id;
+ WBUFB(buf,8) = enable;
+ WBUFL(buf,9) = effectId;
+
+ clif_send(buf, 13, bl, AREA);
+#endif
+}
+
+bool clif_parse_attendance_db(void)
+{
+ struct config_t attendance_conf;
+ struct config_setting_t *attendance = NULL, *it = NULL;
+ const char *config_filename = "db/attendance_db.conf"; // FIXME hardcoded name
+ int i = 0;
+
+ if (!libconfig->load_file(&attendance_conf, config_filename))
+ return false;
+ attendance = libconfig->lookup(&attendance_conf, "attendance_db");
+
+ VECTOR_CLEAR(clif->attendance_data);
+
+ while ((it = libconfig->setting_get_elem(attendance, i++))) {
+ clif->attendancedb_libconfig_sub(it, i, config_filename);
+ }
+
+ libconfig->destroy(&attendance_conf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, config_filename);
+ return true;
+}
+
+bool clif_attendancedb_libconfig_sub(struct config_setting_t *it, int n, const char *source)
+{
+ struct attendance_entry entry = { 0 };
+ int i32 = 0;
+
+ nullpo_ret(it);
+ nullpo_ret(source);
+
+ if (!itemdb->lookup_const(it, "ItemID", &i32) || i32 < 0) {
+ ShowWarning("clif_attendancedb_libconfig_sub: unknown item %d, entry #%d, skipping.\n", i32, n);
+ return false;
+ }
+ entry.nameid = i32;
+
+ if (!libconfig->setting_lookup_int(it, "Amount", &i32) || i32 < 1) {
+ ShowWarning("clif_attendancedb_libconfig_sub: invalid amount %d, entry #%d, skipping.\n", i32, n);
+ return false;
+ }
+ entry.qty = i32;
+
+ VECTOR_ENSURE(clif->attendance_data, 1, 1);
+ VECTOR_PUSH(clif->attendance_data, entry);
+ return true;
+}
+
+bool clif_attendance_timediff(struct map_session_data *sd)
+{
+ int64 timediff;
+
+ nullpo_retr(false, sd);
+
+ timediff = (time(NULL) / (60 * 60 * 24)) - (sd->status.attendance_timer / (60 * 60 * 24));
+
+ if (timediff <= 0)
+ return false;
+ return true;
+}
+time_t clif_attendance_getendtime(void)
+{
+ time_t timestamp;
+ struct tm tmtime = { 0 };
+ int year = 0, month = 0, day = 0;
+ char timestring[9];
+
+ sprintf(timestring, "%8d", battle_config.feature_attendance_endtime);
+ sscanf(timestring, "%4d%2d%2d", &year, &month, &day);
+
+ tmtime.tm_year = year - 1900;
+ tmtime.tm_mon = month - 1;
+ tmtime.tm_mday = day;
+
+ timestamp = mktime(&tmtime);
+
+ return timestamp;
+}
+
+void clif_parse_open_ui_request(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+void clif_parse_open_ui_request(int fd, struct map_session_data *sd)
+{
+
+ const struct PACKET_CZ_OPEN_UI *p = RP2PTR(fd);
+
+ if (clif->attendance_getendtime() < time(NULL)) {
+ clif->msgtable_color(sd, MSG_ATTENDANCE_UNAVAILABLE, COLOR_RED);
+ return;
+ }
+
+ if (battle_config.feature_enable_attendance_system != 1)
+ return;
+
+ clif->open_ui(sd, p->UIType);
+}
+
+void clif_open_ui(struct map_session_data *sd, int8 UIType)
+{
+#if PACKETVER_RE_NUM >= 20180307 || PACKETVER_MAIN_NUM >= 20180404
+ int claimed = 0;
+ struct PACKET_ZC_OPEN_UI p;
+
+ nullpo_retv(sd);
+
+ p.PacketType = 0xAE2;
+ switch (UIType) {
+ case 5: // client will send 5 for the request but requires to receive ATTENDANCE_UI (7) to open the correct ui.
+ if (clif->attendance_timediff(sd) != true)
+ ++claimed;
+ else if (sd->status.attendance_count >= VECTOR_LENGTH(clif->attendance_data))
+ sd->status.attendance_count = 0;
+ p.UIType = ATTENDANCE_UI;
+ p.data = sd->status.attendance_count * 10 + claimed;
+ break;
+ default:
+ ShowWarning("clif_open_ui: Requested UI (%d) is not implemented yet.\n", UIType);
+ return;
+ }
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+#else
+ ShowWarning("Attendance System available only for PACKETVER_RE_NUM >= 20180307 || PACKETVER_MAIN_NUM >= 20180404.\n");
+#endif
+}
+
+void clif_parse_attendance_reward_request(int fd, struct map_session_data *sd) __attribute__((nonnull(2)));
+void clif_parse_attendance_reward_request(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_RE_NUM >= 20180307 || PACKETVER_MAIN_NUM >= 20180404
+
+ struct rodex_message msg = { 0 };
+ struct attendance_entry *entry;
+ int attendance_count;
+ char title[RODEX_TITLE_LENGTH], body[MAIL_BODY_LENGTH];
+
+ if (clif->attendance_getendtime() < time(NULL)) {
+ clif->msgtable_color(sd, MSG_ATTENDANCE_UNAVAILABLE, COLOR_RED);
+ return;
+ }
+
+ if (battle_config.feature_enable_attendance_system != 1)
+ return;
+
+ if (clif->attendance_timediff(sd) != true)
+ return;
+
+ if (sd->status.attendance_count >= VECTOR_LENGTH(clif->attendance_data))
+ sd->status.attendance_count = 0;
+
+ attendance_count = sd->status.attendance_count;
+ ++sd->status.attendance_count;
+ sd->status.attendance_timer = time(NULL);
+
+ msg.receiver_id = sd->status.char_id;
+ sprintf(title, msg_txt(545), attendance_count + 1);
+ sprintf(body, msg_txt(545), attendance_count + 1);
+
+ entry = &VECTOR_INDEX(clif->attendance_data, attendance_count);
+ msg.items[0].item.nameid = entry->nameid;
+ msg.items[0].item.amount = entry->qty;
+ msg.items[0].item.identify = 1;
+ msg.type = MAIL_TYPE_NPC | MAIL_TYPE_ITEM;
+
+ safestrncpy(msg.sender_name, msg_txt(544), NAME_LENGTH);
+ safestrncpy(msg.title, title, RODEX_TITLE_LENGTH);
+ safestrncpy(msg.body, body, MAIL_BODY_LENGTH);
+ msg.send_date = (int)time(NULL);
+ msg.expire_date = (int)time(NULL) + RODEX_EXPIRE;
+
+ intif->rodex_sendmail(&msg);
+ clif->ui_action(sd, 0, sd->status.attendance_count);
+#else
+ ShowWarning("Attendance System available only for PACKETVER_RE_NUM >= 20180307 || PACKETVER_MAIN_NUM >= 20180404.\n");
+#endif
+}
+
+void clif_ui_action(struct map_session_data *sd, int32 UIType, int32 data)
+{
+
+ struct PACKET_ZC_UI_ACTION p;
+
+ nullpo_retv(sd);
+
+ p.PacketType = 0xAF0;
+ p.UIType = UIType;
+ p.data = data;
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+}
/*==========================================
* Main client packet processing function
*------------------------------------------*/
@@ -20790,6 +21172,8 @@ void clif_defaults(void) {
clif->msgtable_skill = clif_msgtable_skill;
clif->msgtable = clif_msgtable;
clif->msgtable_num = clif_msgtable_num;
+ clif->msgtable_str = clif_msgtable_str;
+ clif->msgtable_color = clif_msgtable_color;
clif->message = clif_displaymessage;
clif->messageln = clif_displaymessage2;
clif->messages = clif_displaymessage_sprintf;
@@ -20924,6 +21308,7 @@ void clif_defaults(void) {
clif->quest_delete = clif_quest_delete;
clif->quest_update_status = clif_quest_update_status;
clif->quest_update_objective = clif_quest_update_objective;
+ clif->quest_notify_objective = clif_quest_notify_objective;
clif->quest_show_event = clif_quest_show_event;
/* mail-related */
clif->mail_window = clif_Mail_window;
@@ -21318,4 +21703,16 @@ void clif_defaults(void) {
clif->clan_leave = clif_clan_leave;
clif->clan_message = clif_clan_message;
clif->pClanMessage = clif_parse_ClanMessage;
+ // -- Hat Effect
+ clif->hat_effect = clif_hat_effect;
+ clif->hat_effect_single = clif_hat_effect_single;
+
+ clif->pAttendanceDB = clif_parse_attendance_db;
+ clif->attendancedb_libconfig_sub = clif_attendancedb_libconfig_sub;
+ clif->attendance_timediff = clif_attendance_timediff;
+ clif->attendance_getendtime = clif_attendance_getendtime;
+ clif->pOpenUIRequest = clif_parse_open_ui_request;
+ clif->open_ui = clif_open_ui;
+ clif->pAttendanceRewardRequest = clif_parse_attendance_reward_request;
+ clif->ui_action = clif_ui_action;
}
diff --git a/src/map/clif.h b/src/map/clif.h
index acf79c373..f0eaaf6eb 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -388,6 +388,7 @@ enum clif_messages {
MSG_NPC_WORK_IN_PROGRESS = 0x783, // FIXME[Haru]: This seems to be 0x784 in the msgstringtable files I found.
MSG_REINS_CANT_USE_MOUNTED = 0x78b, // FIXME[Haru]: This seems to be 0x785 in the msgstringtalbe files I found.
MSG_PARTY_LEADER_SAMEMAP = 0x82e, //< It is only possible to change the party leader while on the same map.
+ MSG_ATTENDANCE_UNAVAILABLE = 0xd92, ///< Attendance Check failed. Please try again later.
};
/**
@@ -575,6 +576,19 @@ enum CZ_CONFIG {
CZ_CONFIG_HOMUNCULUS_AUTOFEEDING = 3,
};
/**
+* Client UI types
+* used with packet 0xAE2 to request the client to open a specific ui
+**/
+enum ui_types {
+ BANK_UI = 0,
+ STYLIST_UI,
+ CAPTCHA_UI,
+ MACRO_UI,
+ TIPBOX_UI = 5,
+ RENEWQUEST_UI,
+ ATTENDANCE_UI
+};
+/**
* Structures
**/
typedef void (*pFunc)(int, struct map_session_data *); //cant help but put it first
@@ -599,6 +613,12 @@ struct merge_item {
int16 nameid;
};
+/* attendance data */
+struct attendance_entry {
+ int nameid;
+ int qty;
+};
+
/**
* Clif.c Interface
**/
@@ -628,6 +648,8 @@ struct clif_interface {
bool ally_only;
/* */
struct eri *delayed_damage_ers;
+ /* */
+ VECTOR_DECL(struct attendance_entry) attendance_data;
/* core */
int (*init) (bool minimal);
void (*final) (void);
@@ -886,6 +908,8 @@ struct clif_interface {
void (*msgtable) (struct map_session_data* sd, unsigned short msg_id);
void (*msgtable_num) (struct map_session_data *sd, unsigned short msg_id, int value);
void (*msgtable_skill) (struct map_session_data *sd, uint16 skill_id, int msg_id);
+ void (*msgtable_str) (struct map_session_data *sd, uint16 msg_id, const char *value);
+ void (*msgtable_color) (struct map_session_data *sd, uint16 msg_id, uint32 color);
void (*message) (const int fd, const char* mes);
void (*messageln) (const int fd, const char* mes);
/* message+s(printf) */
@@ -1021,6 +1045,7 @@ struct clif_interface {
void (*quest_delete) (struct map_session_data *sd, int quest_id);
void (*quest_update_status) (struct map_session_data *sd, int quest_id, bool active);
void (*quest_update_objective) (struct map_session_data *sd, struct quest *qd);
+ void (*quest_notify_objective) (struct map_session_data *sd, struct quest *qd);
void (*quest_show_event) (struct map_session_data *sd, struct block_list *bl, short state, short color);
/* mail-related */
void (*mail_window) (int fd, int flag);
@@ -1413,6 +1438,18 @@ struct clif_interface {
void (*clan_leave) (struct map_session_data *sd);
void (*clan_message) (struct clan *c, const char *mes, int len);
void (*pClanMessage) (int fd, struct map_session_data* sd);
+ /* Hat Effect */
+ void (*hat_effect) (struct block_list *bl, struct block_list *tbl, enum send_target target);
+ void (*hat_effect_single) (struct block_list *bl, uint16 effectId, bool enable);
+
+ bool (*pAttendanceDB) (void);
+ bool (*attendancedb_libconfig_sub) (struct config_setting_t *it, int n, const char *source);
+ bool (*attendance_timediff) (struct map_session_data *sd);
+ time_t (*attendance_getendtime) (void);
+ void (*pOpenUIRequest) (int fd, struct map_session_data *sd);
+ void (*open_ui) (struct map_session_data *sd, int8 UIType);
+ void (*pAttendanceRewardRequest) (int fd, struct map_session_data *sd);
+ void (*ui_action) (struct map_session_data *sd, int32 UIType, int32 data);
};
#ifdef HERCULES_CORE
diff --git a/src/map/guild.c b/src/map/guild.c
index 11609ec81..d33df5e08 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -275,6 +275,7 @@ void guild_makemember(struct guild_member *m,struct map_session_data *sd)
m->online = 1;
m->position = MAX_GUILDPOSITION-1;
memcpy(m->name,sd->status.name,NAME_LENGTH);
+ m->last_login = (uint32)time(NULL); // When player create or join a guild the date is updated
return;
}
@@ -1001,7 +1002,7 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online)
return 0;
}
-int guild_recv_memberinfoshort(int guild_id, int account_id, int char_id, int online, int lv, int16 class)
+int guild_recv_memberinfoshort(int guild_id, int account_id, int char_id, int online, int lv, int16 class, uint32 last_login)
{ // cleaned up [LuzZza]
int i, alv, c, idx = INDEX_NOT_FOUND, om = 0, oldonline = -1;
struct guild *g = guild->search(guild_id);
@@ -1017,6 +1018,7 @@ int guild_recv_memberinfoshort(int guild_id, int account_id, int char_id, int on
m->online=online;
m->lv=lv;
m->class = class;
+ m->last_login = last_login;
idx=i;
}
alv+=m->lv;
diff --git a/src/map/guild.h b/src/map/guild.h
index 9296f9ec0..d6bba2a56 100644
--- a/src/map/guild.h
+++ b/src/map/guild.h
@@ -126,7 +126,7 @@ struct guild_interface {
int (*check_alliance) (int guild_id1, int guild_id2, int flag);
/* */
int (*send_memberinfoshort) (struct map_session_data *sd,int online);
- int (*recv_memberinfoshort) (int guild_id, int account_id, int char_id, int online, int lv, int16 class);
+ int (*recv_memberinfoshort) (int guild_id, int account_id, int char_id, int online, int lv, int16 class, uint32 last_login);
int (*change_memberposition) (int guild_id,int account_id,int char_id,short idx);
int (*memberposition_changed) (struct guild *g,int idx,int pos);
int (*change_position) (int guild_id,int idx,int mode,int exp_mode,const char *name);
diff --git a/src/map/intif.c b/src/map/intif.c
index f656a0df9..e9bf0e96b 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -1494,7 +1494,7 @@ void intif_parse_GuildMemberWithdraw(int fd) {
// ACK guild member basic info
void intif_parse_GuildMemberInfoShort(int fd) {
- guild->recv_memberinfoshort(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17));
+ guild->recv_memberinfoshort(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17),RFIFOL(fd,19));
}
// ACK guild break
@@ -2846,7 +2846,7 @@ void intif_defaults(void) {
-1,-1,27,-1, -1,-1,37,-1, 7, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f
0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810
39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820
- 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830
+ 10,-1,15, 0, 79,23, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830
-1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840
-1,-1, 7, 7, 7,11, 8, 0, 10, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] itembound[Akinari] Clan System[Murilo BiO]
-1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish]
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 17a73400a..7f0ebb39c 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -2387,6 +2387,8 @@ void itemdb_read(bool minimal) {
if (minimal)
return;
+ itemdb->name_constants();
+
itemdb->read_combos();
itemdb->read_groups();
itemdb->read_chains();
@@ -2619,6 +2621,7 @@ void do_final_itemdb(void) {
itemdb->options->destroy(itemdb->options, itemdb->options_final_sub);
itemdb->destroy_item_data(&itemdb->dummy, 0);
db_destroy(itemdb->names);
+ VECTOR_CLEAR(clif->attendance_data);
}
void do_init_itemdb(bool minimal) {
@@ -2637,6 +2640,8 @@ void do_init_itemdb(bool minimal) {
/** it failed? we disable it **/
if (battle_config.feature_roulette == 1 && !clif->parse_roulette_db())
battle_config.feature_roulette = 0;
+ VECTOR_INIT(clif->attendance_data);
+ clif->pAttendanceDB();
}
void itemdb_defaults(void) {
itemdb = &itemdb_s;
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index 5344a7cd6..b170059ca 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -137,6 +137,8 @@ enum item_itemid {
ITEMID_MAGIC_CASTLE = 12308,
ITEMID_BULGING_HEAD = 12309,
ITEMID_THICK_MANUAL50 = 12312,
+ ITEMID_N_FLY_WING = 12323,
+ ITEMID_N_BUTTERFLY_WING = 12324,
ITEMID_N_MAGNIFIER = 12325,
ITEMID_ANSILA = 12333,
ITEMID_REPAIRA = 12392,
@@ -162,6 +164,7 @@ enum item_itemid {
ITEMID_THURISAZ = 12731,
ITEMID_WYRD = 12732,
ITEMID_HAGALAZ = 12733,
+ ITEMID_C_WING_OF_FLY = 12887,
ITEMID_DUN_TELE_SCROLL1 = 14527,
ITEMID_BATTLE_MANUAL25 = 14532,
ITEMID_BATTLE_MANUAL100 = 14533,
diff --git a/src/map/packets.h b/src/map/packets.h
index 462efd31b..db98cdc28 100644
--- a/src/map/packets.h
+++ b/src/map/packets.h
@@ -3427,7 +3427,7 @@ packet(0x96e,-1,clif->ackmergeitems);
// 2016-03-23aRagexeRE
#if PACKETVER >= 20160323
// new packets
- packet(0x0a68,3);
+ packet(0x0a68,3,clif->pOpenUIRequest);
packet(0x0a69,6);
packet(0x0a6a,12);
packet(0x0a6b,-1);
@@ -3970,7 +3970,7 @@ packet(0x96e,-1,clif->ackmergeitems);
#if PACKETVER >= 20180117
// new packets
- packet(0x0aef,2);
+ packet(0x0aef,2,clif->pAttendanceRewardRequest);
packet(0x0af0,10);
// changed packet sizes
packet(0x0ae9,13);
@@ -4044,4 +4044,47 @@ packet(0x96e,-1,clif->ackmergeitems);
#endif
#endif // PACKETVER_ZERO
+#ifndef PACKETVER_ZERO
+// 2018-03-21aRagexe, 2018-03-21aRagexeRE
+#if PACKETVER >= 20180321
+// new packets
+ packet(0x0af8,11,clif->pDull/*,XXX*/);
+// changed packet sizes
+ packet(0x0ae7,34,clif->pDull/*,XXX*/);
+#endif
+#endif // PACKETVER_ZERO
+
+#ifdef PACKETVER_ZERO
+// 2018-03-28_1aRagexe_zero
+#if PACKETVER >= 20180328
+// new packets
+ packet(0x0af8,11,clif->pDull/*,XXX*/);
+ packet(0x0af9,6,clif->pDull/*,XXX*/);
+ packet(0x0afa,54,clif->pDull/*,XXX*/);
+// changed packet sizes
+ packet(0x0206,35); // ZC_FRIENDS_STATE
+ packet(0x0ae7,38,clif->pDull/*,XXX*/);
+#endif
+#endif // PACKETVER_ZERO
+
+
+#ifndef PACKETVER_ZERO
+// 2018-04-04bRagexe, 2018-04-04cRagexeRE
+#if PACKETVER >= 20180404
+// new packets
+ packet(0x0af9,6,clif->pDull/*,XXX*/);
+ packet(0x0afa,54,clif->pDull/*,XXX*/);
+// changed packet sizes
+ packet(0x0ae7,38,clif->pDull/*,XXX*/);
+#endif
+#endif // PACKETVER_ZERO
+
+#ifdef PACKETVER_RE
+// 2018-04-04cRagexeRE
+#if PACKETVER >= 20180404
+// changed packet sizes
+ packet(0x0821,102,clif->pDull/*,XXX*/); // AC_OTP_USER
+#endif
+#endif
+
#endif /* MAP_PACKETS_H */
diff --git a/src/map/packets_keys_main.h b/src/map/packets_keys_main.h
index 066e7d2c3..150fb486a 100644
--- a/src/map/packets_keys_main.h
+++ b/src/map/packets_keys_main.h
@@ -874,11 +874,15 @@
packetKeys(0x6A596301,0x76866D0E,0x32294A45);
#endif
-// 2013-12-23aRagexeRE, 2014-05-08aRagexe, 2014-05-08aRagexeRE, 2014-06-11eRagexe, 2015-02-25hRagexe
+// 2013-12-23aRagexeRE, 2014-05-08aRagexe, 2014-05-08aRagexeRE, 2014-06-11eRagexe, 2015-02-25hRagexe, 2018-03-15aRagexe, 2018-03-21aRagexe, 2018-03-21aRagexeRE, 2018-03-28bRagexe, 2018-03-28bRagexeRE, 2018-04-04bRagexe, 2018-04-04cRagexeRE
#if PACKETVER == 20131223 || \
PACKETVER == 20140508 || \
PACKETVER == 20140611 || \
- PACKETVER == 20150225
+ PACKETVER == 20150225 || \
+ PACKETVER == 20180315 || \
+ PACKETVER == 20180321 || \
+ PACKETVER == 20180328 || \
+ PACKETVER >= 20180404
packetKeys(0x00000000,0x00000000,0x00000000);
#endif
@@ -1976,5 +1980,10 @@
packetKeys(0x47DA10EB,0x4B922CCF,0x765C5055);
#endif
+// 2018-03-14nRagexe
+#if PACKETVER == 20180314
+ packetKeys(0x2FF07149,0x00596EA3,0x2B853026);
+#endif
+
#endif /* MAP_PACKETS_MAIN_KEYS_H */
diff --git a/src/map/packets_keys_zero.h b/src/map/packets_keys_zero.h
index 75196e6b4..2bd6f1604 100644
--- a/src/map/packets_keys_zero.h
+++ b/src/map/packets_keys_zero.h
@@ -29,7 +29,7 @@
/* This file is autogenerated, please do not commit manual changes */
-// 2017-10-19aRagexe_zero, 2017-10-23aRagexe_zero, 2017-10-23bRagexe_zero, 2017-10-23cRagexe_zero, 2017-10-24aRagexe_2_zero, 2017-10-24aRagexe_zero, 2017-10-25bRagexe_zero, 2017-10-27aRagexe_zero, 2017-10-27bRagexe_zero, 2017-10-30aRagexe_zero, 2017-10-31aRagexe_zero, 2017-11-09aRagexe_zero, 2017-11-13aRagexe_zero, 2017-11-13bRagexe_zero
+// 2017-10-19aRagexe_zero, 2017-10-23aRagexe_zero, 2017-10-23bRagexe_zero, 2017-10-23cRagexe_zero, 2017-10-24aRagexe_2_zero, 2017-10-24aRagexe_zero, 2017-10-25bRagexe_zero, 2017-10-27aRagexe_zero, 2017-10-27bRagexe_zero, 2017-10-30aRagexe_zero, 2017-10-31aRagexe_zero, 2017-11-09aRagexe_zero, 2017-11-13aRagexe_zero, 2017-11-13bRagexe_zero, 2018-03-15aRagexe_zero, 2018-03-21aRagexe_zero, 2018-03-21bRagexe_zero, 2018-03-28_1aRagexe_zero, 2018-03-28cRagexe_zero
#if PACKETVER == 20171019 || \
PACKETVER == 20171023 || \
PACKETVER == 20171024 || \
@@ -38,7 +38,10 @@
PACKETVER == 20171030 || \
PACKETVER == 20171031 || \
PACKETVER == 20171109 || \
- PACKETVER == 20171113
+ PACKETVER == 20171113 || \
+ PACKETVER == 20180315 || \
+ PACKETVER == 20180321 || \
+ PACKETVER == 20180328
packetKeys(0x00000000,0x00000000,0x00000000);
#endif
@@ -141,5 +144,10 @@
packetKeys(0x56C82ABE,0x61AE2B2E,0x472E272E);
#endif
+// 2018-03-14nRagexe_zero
+#if PACKETVER == 20180314
+ packetKeys(0x2FC330DD,0x01C04E1F,0x4D914DE2);
+#endif
+
#endif /* MAP_PACKETS_ZERO_KEYS_H */
diff --git a/src/map/packets_shuffle_main.h b/src/map/packets_shuffle_main.h
index aabf9c3f3..16d480893 100644
--- a/src/map/packets_shuffle_main.h
+++ b/src/map/packets_shuffle_main.h
@@ -3178,41 +3178,6 @@
packet(0x096a,18,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
#endif
-// 2014-05-08aRagexe, 2014-05-08aRagexeRE, 2014-06-11eRagexe, 2015-02-25hRagexe
-#if PACKETVER == 20140508 || \
- PACKETVER == 20140611 || \
- PACKETVER == 20150225
- packet(0x0202,26,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
- packet(0x022d,5,clif->pHomMenu,2,4); // CZ_COMMAND_MER
- packet(0x023b,36,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
- packet(0x0281,4,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK
- packet(0x02c4,26,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
- packet(0x035f,5,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
- packet(0x0360,6,clif->pTickSend,2); // CZ_REQUEST_TIME
- packet(0x0361,5,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
- packet(0x0362,6,clif->pTakeItem,2); // CZ_ITEM_PICKUP
- packet(0x0363,6,clif->pDropItem,2,4); // CZ_ITEM_THROW
- packet(0x0364,8,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
- packet(0x0365,8,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
- packet(0x0366,10,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
- packet(0x0367,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
- packet(0x0368,6,clif->pGetCharNameRequest,2); // CZ_REQNAME
- packet(0x0369,6,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
- packet(0x0436,19,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
- packet(0x0437,7,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
- packet(0x0438,10,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
- packet(0x07e4,-1,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
- packet(0x07ec,8,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD
- packet(0x0802,18,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
- packet(0x0811,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
- packet(0x0815,2,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
- packet(0x0817,6,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
- packet(0x0819,-1,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
- packet(0x0835,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
- packet(0x0838,2,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
- packet(0x083c,12,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
-#endif
-
// 2014-05-14bRagexe, 2014-05-14bRagexeRE, 2014-05-14cRagexeRE
#if PACKETVER == 20140514
packet(0x0437,12,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
@@ -3380,6 +3345,44 @@
packet(0x0969,2,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
#endif
+// 2014-06-11eRagexe, 2015-02-25hRagexe, 2018-03-15aRagexe, 2018-03-21aRagexe, 2018-03-21aRagexeRE, 2018-03-28bRagexe, 2018-03-28bRagexeRE, 2018-04-04bRagexe, 2018-04-04cRagexeRE
+#if PACKETVER == 20140611 || \
+ PACKETVER == 20150225 || \
+ PACKETVER == 20180315 || \
+ PACKETVER == 20180321 || \
+ PACKETVER == 20180328 || \
+ PACKETVER >= 20180404
+ packet(0x0202,26,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x022d,5,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x023b,36,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0281,4,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK
+ packet(0x02c4,26,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x035f,5,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0360,6,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0361,5,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x0362,6,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0363,6,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x0364,8,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0365,8,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0366,10,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0367,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x0368,6,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0369,6,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0436,19,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0437,7,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x0438,10,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x07e4,-1,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x07ec,8,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0802,18,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
+ packet(0x0811,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
+ packet(0x0815,2,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x0817,6,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x0819,-1,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x0835,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0838,2,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x083c,12,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+#endif
+
// 2014-06-18aRagexe, 2014-06-18cRagexeRE
#if PACKETVER == 20140618
packet(0x085d,8,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
@@ -9667,5 +9670,38 @@
packet(0x0969,7,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
#endif
+// 2018-03-14nRagexe
+#if PACKETVER == 20180314
+ packet(0x0361,12,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0366,10,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x0369,5,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0436,6,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x085a,6,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0862,6,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0863,-1,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x0868,8,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD
+ packet(0x086e,8,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0874,-1,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+ packet(0x087a,19,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0888,5,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x088a,10,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x088d,36,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0894,2,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x089b,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x0921,7,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x0927,2,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x092f,5,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0933,8,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x0935,26,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x0945,18,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
+ packet(0x094d,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
+ packet(0x094e,26,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x0956,4,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK
+ packet(0x0959,6,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x095f,6,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0962,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0967,6,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+#endif
+
#endif /* MAP_PACKETS_SHUFFLE_MAIN_H */
diff --git a/src/map/packets_shuffle_zero.h b/src/map/packets_shuffle_zero.h
index 463ab1679..7cd52d971 100644
--- a/src/map/packets_shuffle_zero.h
+++ b/src/map/packets_shuffle_zero.h
@@ -36,7 +36,7 @@
/* This file is autogenerated, please do not commit manual changes */
-// 2017-10-19aRagexe_zero, 2017-10-23aRagexe_zero, 2017-10-23bRagexe_zero, 2017-10-23cRagexe_zero, 2017-10-24aRagexe_2_zero, 2017-10-24aRagexe_zero, 2017-10-25bRagexe_zero, 2017-10-27aRagexe_zero, 2017-10-27bRagexe_zero, 2017-10-30aRagexe_zero, 2017-10-31aRagexe_zero, 2017-11-09aRagexe_zero, 2017-11-13aRagexe_zero, 2017-11-13bRagexe_zero
+// 2017-10-19aRagexe_zero, 2017-10-23aRagexe_zero, 2017-10-23bRagexe_zero, 2017-10-23cRagexe_zero, 2017-10-24aRagexe_2_zero, 2017-10-24aRagexe_zero, 2017-10-25bRagexe_zero, 2017-10-27aRagexe_zero, 2017-10-27bRagexe_zero, 2017-10-30aRagexe_zero, 2017-10-31aRagexe_zero, 2017-11-09aRagexe_zero, 2017-11-13aRagexe_zero, 2017-11-13bRagexe_zero, 2018-03-15aRagexe_zero, 2018-03-21aRagexe_zero, 2018-03-21bRagexe_zero, 2018-03-28_1aRagexe_zero, 2018-03-28cRagexe_zero
#if PACKETVER == 20171019 || \
PACKETVER == 20171023 || \
PACKETVER == 20171024 || \
@@ -45,7 +45,10 @@
PACKETVER == 20171030 || \
PACKETVER == 20171031 || \
PACKETVER == 20171109 || \
- PACKETVER == 20171113
+ PACKETVER == 20171113 || \
+ PACKETVER == 20180315 || \
+ PACKETVER == 20180321 || \
+ PACKETVER == 20180328
packet(0x0202,26,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
packet(0x022d,5,clif->pHomMenu,2,4); // CZ_COMMAND_MER
packet(0x023b,36,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
@@ -652,5 +655,38 @@
packet(0x096a,6,clif->pGetCharNameRequest,2); // CZ_REQNAME
#endif
+// 2018-03-14nRagexe_zero
+#if PACKETVER == 20180314
+ packet(0x023b,26,clif->pPartyInvite2,2); // CZ_PARTY_JOIN_REQ
+ packet(0x0438,2,clif->pSearchStoreInfoNextPage,0); // CZ_SEARCH_STORE_INFO_NEXT_PAGE
+ packet(0x07ec,19,clif->pWantToConnection,2,6,10,14,18); // CZ_ENTER
+ packet(0x0817,2,clif->pReqCloseBuyingStore,0); // CZ_REQ_CLOSE_BUYING_STORE
+ packet(0x083c,5,clif->pChangeDir,2,4); // CZ_CHANGE_DIRECTION
+ packet(0x085d,26,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS
+ packet(0x085f,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); // CZ_REQ_OPEN_BUYING_STORE
+ packet(0x0866,5,clif->pHomMenu,2,4); // CZ_COMMAND_MER
+ packet(0x0878,8,clif->pDull/*,XXX*/); // CZ_JOIN_BATTLE_FIELD
+ packet(0x088d,36,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD
+ packet(0x0891,8,clif->pMoveFromKafra,2,4); // CZ_MOVE_ITEM_FROM_STORE_TO_BODY
+ packet(0x0897,6,clif->pTakeItem,2); // CZ_ITEM_PICKUP
+ packet(0x0899,8,clif->pMoveToKafra,2,4); // CZ_MOVE_ITEM_FROM_BODY_TO_STORE
+ packet(0x089e,-1,clif->pItemListWindowSelected,2,4,8); // CZ_ITEMLISTWIN_RES
+ packet(0x08a1,4,clif->pDull/*,XXX*/); // CZ_GANGSI_RANK
+ packet(0x0917,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); // CZ_SEARCH_STORE_INFO
+ packet(0x0918,7,clif->pActionRequest,2,6); // CZ_REQUEST_ACT
+ packet(0x091f,10,clif->pUseSkillToPos,2,4,6,8); // CZ_USE_SKILL_TOGROUND
+ packet(0x0920,6,clif->pTickSend,2); // CZ_REQUEST_TIME
+ packet(0x0923,12,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK
+ packet(0x0930,6,clif->pDropItem,2,4); // CZ_ITEM_THROW
+ packet(0x0931,6,clif->pReqClickBuyingStore,2); // CZ_REQ_CLICK_TO_BUYING_STORE
+ packet(0x093f,6,clif->pSolveCharName,2); // CZ_REQNAME_BYGID
+ packet(0x0946,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); // CZ_USE_SKILL_TOGROUND_WITHTALKBOX
+ packet(0x094a,10,clif->pUseSkillToId,2,4,6); // CZ_USE_SKILL
+ packet(0x094e,5,clif->pWalkToXY,2); // CZ_REQUEST_MOVE
+ packet(0x0954,18,clif->pPartyBookingRegisterReq,2,4); // CZ_PARTY_BOOKING_REQ_REGISTER
+ packet(0x0956,6,clif->pGetCharNameRequest,2); // CZ_REQNAME
+ packet(0x0958,-1,clif->pReqTradeBuyingStore,2,4,8,12); // CZ_REQ_TRADE_BUYING_STORE
+#endif
+
#endif /* MAP_PACKETS_SHUFFLE_ZERO_H */
diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h
index 2a65eb6cf..438084778 100644
--- a/src/map/packets_struct.h
+++ b/src/map/packets_struct.h
@@ -302,7 +302,7 @@ enum packet_headers {
rouletteinfoackType = 0xa1c,
roulettgenerateackType = 0xa20,
roulettercvitemackType = 0xa22,
-#if 0 // Unknown
+#if PACKETVER >= 20150513 // [4144] 0x09f8 handling in client from 2014-10-29aRagexe and 2014-03-26cRagexeRE
questListType = 0x9f8, ///< ZC_ALL_QUEST_LIST3
#elif PACKETVER >= 20141022
questListType = 0x97a, ///< ZC_ALL_QUEST_LIST2
@@ -357,6 +357,17 @@ enum packet_headers {
clanLeave = 0x0989, ///< ZC_ACK_CLAN_LEAVE
clanMessage = 0x098E, ///< ZC_NOTIFY_CLAN_CHAT
#endif
+#if PACKETVER >= 20150513 // [4144] 0x09f9 handled in client from 2014-10-29aRagexe and 2014-03-26cRagexeRE
+ questAddType = 0x9f9,
+#else
+ questAddType = 0x2b3,
+#endif // PACKETVER < 20150513
+#if PACKETVER >= 20150513
+ questUpdateType = 0x9fa,
+#else
+ questUpdateType = 0x2b5,
+#endif // PACKETVER < 20150513
+ questUpdateType2 = 0x8fe,
};
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
@@ -1248,10 +1259,19 @@ struct packet_hotkey {
} __attribute__((packed));
/**
- * MISSION_HUNT_INFO
+ * MISSION_HUNT_INFO (PACKETVER >= 20141022)
+ * MISSION_HUNT_INFO_EX (PACKETVER >= 20150513)
*/
struct packet_mission_info_sub {
- int32 mob_id;
+#if PACKETVER >= 20150513
+ uint32 huntIdent;
+ uint32 mobType;
+#endif
+ uint32 mob_id;
+#if PACKETVER >= 20150513
+ int16 levelMin;
+ int16 levelMax;
+#endif
int16 huntCount;
int16 maxCount;
char mobName[NAME_LENGTH];
@@ -1259,7 +1279,7 @@ struct packet_mission_info_sub {
/**
* PACKET_ZC_ALL_QUEST_LIST2_INFO (PACKETVER >= 20141022)
- * PACKET_ZC_ALL_QUEST_LIST3_INFO (PACKETVER Unknown) / unused
+ * PACKET_ZC_ALL_QUEST_LIST3_INFO (PACKETVER >= 20150513)
*/
struct packet_quest_list_info {
int32 questID;
@@ -1276,7 +1296,7 @@ struct packet_quest_list_info {
* Header for:
* PACKET_ZC_ALL_QUEST_LIST (PACKETVER < 20141022)
* PACKET_ZC_ALL_QUEST_LIST2 (PACKETVER >= 20141022)
- * PACKET_ZC_ALL_QUEST_LIST3 (PACKETVER Unknown) / unused
+ * PACKET_ZC_ALL_QUEST_LIST3 (PACKETVER >= 20150513)
*
* @remark
* Contains (is followed by) a variable-length array of packet_quest_list_info
@@ -1598,6 +1618,117 @@ struct PACKET_ZC_NOTIFY_CLAN_CHAT {
char Message[];
} __attribute__((packed));
+/**
+ * PACKET_ZC_MISSION_HUNT (PACKETVER < 20150513)
+ * PACKET_ZC_MISSION_HUNT_EX (PACKETVER >= 20150513)
+ */
+struct packet_quest_hunt_sub {
+#if PACKETVER >= 20150513
+ uint32 huntIdent;
+ uint32 mobType;
+#endif
+ uint32 mob_id;
+#if PACKETVER >= 20150513
+ int16 levelMin;
+ int16 levelMax;
+#endif
+ int16 huntCount;
+ char mobName[NAME_LENGTH];
+} __attribute__((packed));
+
+/**
+ * Header for:
+ * PACKET_ZC_ADD_QUEST (PACKETVER < 20150513)
+ * PACKET_ZC_ADD_QUEST_EX (PACKETVER >= 20150513)
+ */
+struct packet_quest_add_header {
+ uint16 PacketType;
+ uint32 questID;
+ uint8 active;
+ int32 quest_svrTime;
+ int32 quest_endTime;
+ int16 count;
+ struct packet_quest_hunt_sub objectives[];
+} __attribute__((packed));
+
+/**
+ * PACKET_MOB_HUNTING (PACKETVER < 20150513)
+ * PACKET_MOB_HUNTING_EX (PACKETVER >= 20150513)
+ */
+struct packet_quest_update_hunt {
+ uint32 questID;
+#if PACKETVER >= 20150513
+ uint32 huntIdent;
+#else
+ uint32 mob_id;
+#endif // PACKETVER < 20150513
+ int16 maxCount;
+ int16 count;
+} __attribute__((packed));
+
+/**
+ * Header for:
+ * PACKET_ZC_UPDATE_MISSION_HUNT (PACKETVER < 20150513)
+ * PACKET_ZC_UPDATE_MISSION_HUNT_EX (PACKETVER >= 20150513)
+ */
+struct packet_quest_update_header {
+ uint16 PacketType;
+ uint16 PacketLength;
+ int16 count;
+ struct packet_quest_update_hunt objectives[];
+} __attribute__((packed));
+
+/**
+ * Header for:
+ * PACKET_MOB_HUNTING (PACKETVER >= 20150513)
+ */
+struct packet_quest_hunt_info_sub {
+ uint32 questID;
+ uint32 mob_id;
+ int16 maxCount;
+ int16 count;
+} __attribute__((packed));
+
+/**
+ * Header for:
+ * ZC_HUNTING_QUEST_INFO (PACKETVER >= 20150513)
+ */
+struct packet_quest_hunt_info {
+ uint16 PacketType;
+ uint16 PacketLength;
+ struct packet_quest_hunt_info_sub info[];
+} __attribute__((packed));
+
+struct PACKET_ZC_FORMATSTRING_MSG {
+ uint16 PacketType;
+ uint16 PacketLength;
+ uint16 MessageId;
+ char MessageString[];
+} __attribute__((packed));
+
+struct PACKET_ZC_MSG_COLOR {
+ uint16 PacketType;
+ uint16 MessageId;
+ uint32 MessageColor;
+} __attribute__((packed));
+
+struct PACKET_CZ_OPEN_UI {
+ int16 PacketType;
+ int8 UIType;
+} __attribute__((packed));
+
+struct PACKET_ZC_OPEN_UI {
+ int16 PacketType;
+ int8 UIType;
+ int32 data;
+} __attribute__((packed));
+
+struct PACKET_ZC_UI_ACTION {
+ int16 PacketType;
+ int32 UIType;
+ int32 data;
+} __attribute__((packed));
+
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
#pragma pack(pop)
#endif // not NetBSD < 6 / Solaris
diff --git a/src/map/pc.c b/src/map/pc.c
index cd4b2a54f..ee1fcd7da 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -1293,6 +1293,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
VECTOR_INIT(sd->script_queues);
VECTOR_INIT(sd->storage.item); // initialize storage item vector.
+ VECTOR_INIT(sd->hatEffectId);
sd->state.dialog = 0;
@@ -4901,15 +4902,16 @@ int pc_isUseitem(struct map_session_data *sd,int n)
return 0; // You cannot use this item while sitting.
}
- if (sd->state.storage_flag != STORAGE_FLAG_CLOSED && item->type != IT_CASH) {
- clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd,1475));
- return 0; // You cannot use this item while storage is open.
- }
-
switch( nameid ) { // TODO: Is there no better way to handle this, other than hardcoding item IDs?
case ITEMID_ANODYNE:
- if (map_flag_gvg2(sd->bl.m))
+ if (map_flag_gvg2(sd->bl.m)) {
+#if PACKETVER >= 20080311
+ clif->skill_mapinfomessage(sd, 3);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_CYAN, msg_sd(sd, 51));
+#endif
return 0;
+ }
break;
case ITEMID_GIANT_FLY_WING: {
@@ -4943,12 +4945,19 @@ int pc_isUseitem(struct map_session_data *sd,int n)
}
FALLTHROUGH
case ITEMID_WING_OF_FLY:
+ case ITEMID_N_FLY_WING:
+ case ITEMID_C_WING_OF_FLY:
if (map->list[sd->bl.m].flag.noteleport || map_flag_gvg2(sd->bl.m)) {
+#if PACKETVER >= 20080311
clif->skill_mapinfomessage(sd, 0);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd, 49));
+#endif
return 0;
}
/* Fall through */
case ITEMID_WING_OF_BUTTERFLY:
+ case ITEMID_N_BUTTERFLY_WING:
case ITEMID_DUN_TELE_SCROLL1:
case ITEMID_DUN_TELE_SCROLL2:
case ITEMID_WOB_RUNE: // Yellow Butterfly Wing
@@ -4960,15 +4969,27 @@ int pc_isUseitem(struct map_session_data *sd,int n)
clif->message(sd->fd, msg_sd(sd,863)); // "Duel: Can't use this item in duel."
return 0;
}
- if( nameid != ITEMID_WING_OF_FLY && nameid != ITEMID_GIANT_FLY_WING && map->list[sd->bl.m].flag.noreturn )
+ if (nameid != ITEMID_WING_OF_FLY && nameid != ITEMID_GIANT_FLY_WING && map->list[sd->bl.m].flag.noreturn) {
+#if PACKETVER >= 20080311
+ clif->skill_mapinfomessage(sd, 0);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd, 49));
+#endif
return 0;
+ }
break;
case ITEMID_BRANCH_OF_DEAD_TREE:
case ITEMID_RED_POUCH_OF_SURPRISE:
case ITEMID_BLOODY_DEAD_BRANCH:
case ITEMID_PORING_BOX:
- if( map->list[sd->bl.m].flag.nobranch || map_flag_gvg2(sd->bl.m) )
+ if (map->list[sd->bl.m].flag.nobranch || map_flag_gvg2(sd->bl.m)) {
+#if PACKETVER >= 20080311
+ clif->skill_mapinfomessage(sd, 3);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_CYAN, msg_sd(sd, 51));
+#endif
return 0;
+ }
break;
// Mercenary Items
@@ -4988,8 +5009,14 @@ int pc_isUseitem(struct map_session_data *sd,int n)
break;
case ITEMID_NEURALIZER:
- if( !map->list[sd->bl.m].flag.reset )
+ if (!map->list[sd->bl.m].flag.reset) {
+#if PACKETVER >= 20080311
+ clif->skill_mapinfomessage(sd, 3);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_CYAN, msg_sd(sd, 51));
+#endif
return 0;
+ }
break;
}
@@ -5092,6 +5119,11 @@ int pc_useitem(struct map_session_data *sd,int n) {
return 0;
}
+ if (battle_config.storage_use_item == 1 && sd->state.storage_flag != STORAGE_FLAG_CLOSED) {
+ clif->messagecolor_self(sd->fd, COLOR_RED, msg_sd(sd, 1475));
+ return 0; // You cannot use this item while storage is open.
+ }
+
if( sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount <= 0 )
return 0;
@@ -5178,7 +5210,11 @@ int pc_useitem(struct map_session_data *sd,int n) {
/* on restricted maps the item is consumed but the effect is not used */
for(i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++) {
if( map->list[sd->bl.m].zone->disabled_items[i] == nameid ) {
- clif->msgtable(sd, MSG_ITEM_CANT_USE_AREA); // This item cannot be used within this area
+#if PACKETVER >= 20080311
+ clif->skill_mapinfomessage(sd, 3);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_CYAN, msg_sd(sd, 50));
+#endif
if( battle_config.item_restricted_consumption_type && sd->status.inventory[n].expire_time == 0 ) {
clif->useitemack(sd,n,sd->status.inventory[n].amount-1,true);
pc->delitem(sd, n, 1, 1, DELITEM_NORMAL, LOG_TYPE_CONSUME);
diff --git a/src/map/pc.h b/src/map/pc.h
index a01152df5..e699e5750 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -618,6 +618,9 @@ END_ZEROED_BLOCK;
const char* delunit_prevfile;
int delunit_prevline;
+ // HatEffect
+ VECTOR_DECL(int) hatEffectId;
+
};
#define EQP_WEAPON EQP_HAND_R
diff --git a/src/map/pet.c b/src/map/pet.c
index 2997a4b5a..57800dc0a 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -39,6 +39,7 @@
#include "map/skill.h"
#include "map/status.h"
#include "map/unit.h"
+#include "common/conf.h"
#include "common/db.h"
#include "common/ers.h"
#include "common/memmgr.h"
@@ -1199,145 +1200,213 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-/**
- * Loads (or reloads) the pet database.
- */
-int read_petdb(void)
+void pet_read_db(void)
{
const char *filename[] = {
- DBPATH"pet_db.txt",
- "pet_db2.txt",
+ DBPATH"pet_db.conf",
+ "pet_db2.conf"
};
- int i,j;
+ int i;
- // Remove any previous scripts in case reloaddb was invoked.
- for (j = 0; j < MAX_PET_DB; j++) {
- if (pet->db[j].pet_script) {
- script->free_code(pet->db[j].pet_script);
- pet->db[j].pet_script = NULL;
- }
- if (pet->db[j].equip_script) {
- script->free_code(pet->db[j].equip_script);
- pet->db[j].equip_script = NULL;
+ pet->read_db_clear();
+
+ for (i = 0; i < ARRAYLENGTH(filename); ++i) {
+ pet->read_db_libconfig(filename[i], i > 0 ? true : false);
+ }
+}
+
+int pet_read_db_libconfig(const char *filename, bool ignore_missing)
+{
+ struct config_t pet_db_conf;
+ struct config_setting_t *pdb;
+ struct config_setting_t *t;
+ char filepath[256];
+ bool duplicate[MAX_MOB_DB] = { 0 };
+ int i = 0, count = 0;
+
+ nullpo_ret(filename);
+
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, filename);
+
+ if (!exists(filepath)) {
+ if (!ignore_missing) {
+ ShowError("pet_read_db_libconfig: can't find file %s\n", filepath);
}
+ return 0;
}
- // clear database
- memset(pet->db,0,sizeof(pet->db));
+ if (!libconfig->load_file(&pet_db_conf, filepath))
+ return 0;
- j = 0; // entry counter
- for (i = 0; i < ARRAYLENGTH(filename); i++) {
- char line[1024];
- int lines, entries;
- FILE *fp;
-
- sprintf(line, "%s/%s", map->db_path, filename[i]);
- fp=fopen(line,"r");
- if (fp == NULL) {
- if (i == 0)
- ShowError("can't read %s\n",line);
+ if ((pdb = libconfig->setting_get_member(pet_db_conf.root, "pet_db")) == NULL) {
+ ShowError("can't read %s\n", filepath);
+ return 0;
+ }
+
+ while ((t = libconfig->setting_get_elem(pdb, i++))) {
+ int pet_id = pet->read_db_sub(t, i - 1, filename);
+
+ if (pet_id <= 0 || pet_id >= MAX_MOB_DB)
continue;
+
+ if (duplicate[pet_id]) {
+ ShowWarning("pet_read_db_libconfig:%s: duplicate entry of ID #%d\n", filename, pet_id);
+ } else {
+ duplicate[pet_id] = true;
}
- lines = entries = 0;
- while (fgets(line, sizeof(line), fp) && j < MAX_PET_DB) {
- char *str[22], *p;
- int nameid, k;
- lines++;
-
- if (line[0] == '/' && line[1] == '/')
- continue;
- memset(str, 0, sizeof(str));
- p = line;
- while (ISSPACE(*p))
- ++p;
- if (*p == '\0')
- continue; // empty line
- for (k = 0; k < 20; ++k) {
- str[k] = p;
- p = strchr(p,',');
- if (p == NULL)
- break; // comma not found
- *p = '\0';
- ++p;
- }
+ count++;
+ }
+ libconfig->destroy(&pet_db_conf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename);
- if (p == NULL) {
- ShowError("read_petdb: Insufficient columns in line %d, skipping.\n", lines);
- continue;
- }
+ return count;
+}
- // Pet Script
- if (*p != '{') {
- ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines);
- continue;
- }
+int pet_read_db_sub(struct config_setting_t *it, int n, const char *source)
+{
+ struct config_setting_t *t = NULL;
+ struct item_data *data = NULL;
+ const char *str = NULL;
+ int i32 = 0;
- str[20] = p;
- p = strstr(p+1,"},");
- if (p == NULL) {
- ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines);
- continue;
- }
- p[1] = '\0';
- p += 2;
+ nullpo_ret(it);
+ nullpo_ret(source);
+ Assert_ret(n >= 0 && n < MAX_PET_DB);
- // Equip Script
- if (*p != '{') {
- ShowError("read_petdb: Invalid format (Equip Script column) in line %d, skipping.\n", lines);
- continue;
- }
- str[21] = p;
+ if (!libconfig->setting_lookup_int(it, "Id", &i32)) {
+ ShowWarning("pet_read_db_sub: Missing Id in \"%s\", entry #%d, skipping.\n", source, n);
+ return 0;
+ }
+ pet->db[n].class_ = i32;
- nameid = atoi(str[0]);
- if (nameid <= 0)
- continue;
+ if (!libconfig->setting_lookup_string(it, "SpriteName", &str) || !*str ) {
+ ShowWarning("pet_read_db_sub: Missing SpriteName in pet %d of \"%s\", skipping.\n", pet->db[n].class_, source);
+ return 0;
+ }
+ safestrncpy(pet->db[n].name, str, sizeof(pet->db[n].name));
- if (!mob->db_checkid(nameid)) {
- ShowWarning("pet_db reading: Invalid mob-class %d, pet not read.\n", nameid);
- continue;
- }
+ if (!libconfig->setting_lookup_string(it, "Name", &str) || !*str) {
+ ShowWarning("pet_read_db_sub: Missing Name in pet %d of \"%s\", skipping.\n", pet->db[n].class_, source);
+ return 0;
+ }
+ safestrncpy(pet->db[n].jname, str, sizeof(pet->db[n].jname));
- pet->db[j].class_ = nameid;
- safestrncpy(pet->db[j].name,str[1],NAME_LENGTH);
- safestrncpy(pet->db[j].jname,str[2],NAME_LENGTH);
- pet->db[j].itemID=atoi(str[3]);
- pet->db[j].EggID=atoi(str[4]);
- pet->db[j].AcceID=atoi(str[5]);
- pet->db[j].FoodID=atoi(str[6]);
- pet->db[j].fullness=atoi(str[7]);
- pet->db[j].hungry_delay=atoi(str[8])*1000;
- pet->db[j].r_hungry=atoi(str[9]);
- if (pet->db[j].r_hungry <= 0)
- pet->db[j].r_hungry=1;
- pet->db[j].r_full=atoi(str[10]);
- pet->db[j].intimate=atoi(str[11]);
- pet->db[j].die=atoi(str[12]);
- pet->db[j].capture=atoi(str[13]);
- pet->db[j].speed=atoi(str[14]);
- pet->db[j].s_perfor=(char)atoi(str[15]);
- pet->db[j].talk_convert_class=atoi(str[16]);
- pet->db[j].attack_rate=atoi(str[17]);
- pet->db[j].defence_attack_rate=atoi(str[18]);
- pet->db[j].change_target_rate=atoi(str[19]);
- pet->db[j].pet_script = NULL;
- pet->db[j].equip_script = NULL;
-
- if (*str[20])
- pet->db[j].pet_script = script->parse(str[20], filename[i], lines, 0, NULL);
- if (*str[21])
- pet->db[j].equip_script = script->parse(str[21], filename[i], lines, 0, NULL);
-
- j++;
- entries++;
+ if (libconfig->setting_lookup_string(it, "TamingItem", &str)) {
+ if (!(data = itemdb->name2id(str))) {
+ ShowWarning("pet_read_db_sub: Invalid item '%s' in pet %d of \"%s\", defaulting to 0.\n", str, pet->db[n].class_, source);
+ } else {
+ pet->db[n].itemID = (uint16)data->nameid;
}
+ }
- if (j >= MAX_PET_DB)
- ShowWarning("read_petdb: Reached max number of pets [%d]. Remaining pets were not read.\n ", MAX_PET_DB);
- fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' pets in '"CL_WHITE"%s"CL_RESET"'.\n", entries, filename[i]);
+ if (libconfig->setting_lookup_string(it, "EggItem", &str)) {
+ if (!(data = itemdb->name2id(str))) {
+ ShowWarning("pet_read_db_sub: Invalid item '%s' in pet %d of \"%s\", defaulting to 0.\n", str, pet->db[n].class_, source);
+ } else {
+ pet->db[n].EggID = (uint16)data->nameid;
+ }
}
- return 0;
+
+ if (libconfig->setting_lookup_string(it, "AccessoryItem", &str)) {
+ if (!(data = itemdb->name2id(str))) {
+ ShowWarning("pet_read_db_sub: Invalid item '%s' in pet %d of \"%s\", defaulting to 0.\n", str, pet->db[n].class_, source);
+ } else {
+ pet->db[n].AcceID = (uint16)data->nameid;
+ }
+ }
+
+ if (libconfig->setting_lookup_string(it, "FoodItem", &str)) {
+ if (!(data = itemdb->name2id(str))) {
+ ShowWarning("pet_read_db_sub: Invalid item '%s' in pet %d of \"%s\", defaulting to 0.\n", str, pet->db[n].class_, source);
+ } else {
+ pet->db[n].FoodID = (uint16)data->nameid;
+ }
+ }
+
+ if (libconfig->setting_lookup_int(it, "FoodEffectiveness", &i32))
+ pet->db[n].fullness = i32;
+
+ if (libconfig->setting_lookup_int(it, "HungerDelay", &i32))
+ pet->db[n].hungry_delay = i32 * 1000;
+
+ if ((t = libconfig->setting_get_member(it, "Intimacy"))) {
+ if (config_setting_is_group(t)) {
+ pet->read_db_sub_intimacy(n, t);
+ }
+ }
+ if (pet->db[n].r_hungry <= 0)
+ pet->db[n].r_hungry = 1;
+
+ if (libconfig->setting_lookup_int(it, "CaptureRate", &i32))
+ pet->db[n].capture = i32;
+
+ if (libconfig->setting_lookup_int(it, "Speed", &i32))
+ pet->db[n].speed = i32;
+
+ if ((t = libconfig->setting_get_member(it, "SpecialPerformance")) && (i32 = libconfig->setting_get_bool(t)))
+ pet->db[n].s_perfor = (char)i32;
+
+ if ((t = libconfig->setting_get_member(it, "TalkWithEmotes")) && (i32 = libconfig->setting_get_bool(t)))
+ pet->db[n].talk_convert_class = i32;
+
+ if (libconfig->setting_lookup_int(it, "AttackRate", &i32))
+ pet->db[n].attack_rate = i32;
+
+ if (libconfig->setting_lookup_int(it, "DefendRate", &i32))
+ pet->db[n].defence_attack_rate = i32;
+
+ if (libconfig->setting_lookup_int(it, "ChangeTargetRate", &i32))
+ pet->db[n].change_target_rate = i32;
+
+ if (libconfig->setting_lookup_string(it, "PetScript", &str))
+ pet->db[n].pet_script = *str ? script->parse(str, source, -pet->db[n].class_, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+
+ if (libconfig->setting_lookup_string(it, "EquipScript", &str))
+ pet->db[n].equip_script = *str ? script->parse(str, source, -pet->db[n].class_, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+
+ return pet->db[n].class_;
+}
+
+bool pet_read_db_sub_intimacy(int idx, struct config_setting_t *t)
+{
+ int i32 = 0;
+
+ nullpo_retr(false, t);
+ Assert_ret(idx >= 0 && idx < MAX_PET_DB);
+
+ if (libconfig->setting_lookup_int(t, "Initial", &i32))
+ pet->db[idx].intimate = i32;
+
+ if (libconfig->setting_lookup_int(t, "FeedIncrement", &i32))
+ pet->db[idx].r_hungry = i32;
+
+ if (libconfig->setting_lookup_int(t, "OverFeedDecrement", &i32))
+ pet->db[idx].r_full = i32;
+
+ if (libconfig->setting_lookup_int(t, "OwnerDeathDecrement", &i32))
+ pet->db[idx].die = i32;
+
+ return true;
+}
+
+void pet_read_db_clear(void)
+{
+ int i;
+
+ // Remove any previous scripts in case reloaddb was invoked.
+ for (i = 0; i < MAX_PET_DB; i++) {
+ if (pet->db[i].pet_script) {
+ script->free_code(pet->db[i].pet_script);
+ pet->db[i].pet_script = NULL;
+ }
+ if (pet->db[i].equip_script) {
+ script->free_code(pet->db[i].equip_script);
+ pet->db[i].equip_script = NULL;
+ }
+ }
+ memset(pet->db, 0, sizeof(pet->db));
+ return;
}
/*==========================================
@@ -1428,5 +1497,10 @@ void pet_defaults(void) {
pet->skill_bonus_timer = pet_skill_bonus_timer;
pet->recovery_timer = pet_recovery_timer;
pet->skill_support_timer = pet_skill_support_timer;
- pet->read_db = read_petdb;
+
+ pet->read_db = pet_read_db;
+ pet->read_db_libconfig = pet_read_db_libconfig;
+ pet->read_db_sub = pet_read_db_sub;
+ pet->read_db_sub_intimacy = pet_read_db_sub_intimacy;
+ pet->read_db_clear = pet_read_db_clear;
}
diff --git a/src/map/pet.h b/src/map/pet.h
index 9a0287b42..19e524c16 100644
--- a/src/map/pet.h
+++ b/src/map/pet.h
@@ -166,7 +166,12 @@ struct pet_interface {
int (*skill_bonus_timer) (int tid, int64 tick, int id, intptr_t data);
int (*recovery_timer) (int tid, int64 tick, int id, intptr_t data);
int (*skill_support_timer) (int tid, int64 tick, int id, intptr_t data);
- int (*read_db) (void);
+
+ void (*read_db) (void);
+ int (*read_db_libconfig) (const char *filename, bool ignore_missing);
+ int (*read_db_sub) (struct config_setting_t *it, int n, const char *source);
+ bool (*read_db_sub_intimacy) (int idx, struct config_setting_t *t);
+ void (*read_db_clear) (void);
};
#ifdef HERCULES_CORE
diff --git a/src/map/quest.c b/src/map/quest.c
index 4c5dcb59f..581ecf45e 100644
--- a/src/map/quest.c
+++ b/src/map/quest.c
@@ -148,7 +148,11 @@ int quest_add(struct map_session_data *sd, int quest_id, unsigned int time_limit
sd->save_quest = true;
clif->quest_add(sd, &sd->quest_log[n]);
+#if PACKETVER >= 20150513
+ clif->quest_notify_objective(sd, &sd->quest_log[n]);
+#else
clif->quest_update_objective(sd, &sd->quest_log[n]);
+#endif
if ((map->save_settings & 64) != 0)
chrif->save(sd, 0);
@@ -201,7 +205,11 @@ int quest_change(struct map_session_data *sd, int qid1, int qid2)
clif->quest_delete(sd, qid1);
clif->quest_add(sd, &sd->quest_log[i]);
+#if PACKETVER >= 20150513
+ clif->quest_notify_objective(sd, &sd->quest_log[i]);
+#else
clif->quest_update_objective(sd, &sd->quest_log[i]);
+#endif
if( map->save_settings&64 )
chrif->save(sd,0);
diff --git a/src/map/rodex.c b/src/map/rodex.c
index 0e9e4ee2a..d1b0191ac 100644
--- a/src/map/rodex.c
+++ b/src/map/rodex.c
@@ -383,7 +383,7 @@ struct rodex_message *rodex_get_mail(struct map_session_data *sd, int64 mail_id)
if ((msg->is_deleted == true)
|| (msg->expire_date < time(NULL) && ((msg->receiver_accountid > 0) || (msg->receiver_id == char_id && msg->sender_id != char_id)))
- || ((msg->send_date + 2 * RODEX_EXPIRE) < time(NULL))
+ || (msg->expire_date + RODEX_EXPIRE < time(NULL))
)
return NULL;
diff --git a/src/map/script.c b/src/map/script.c
index d653800cc..275601dcc 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -12815,12 +12815,12 @@ enum mapinfo_info {
BUILDIN(getmapinfo)
{
enum mapinfo_info mode = script_getnum(st, 2);
- int16 m;
+ int16 m = -1;
if (script_hasdata(st, 3)) {
if (script_isstringtype(st, 3)) {
const char *str = script_getstr(st, 3);
- m = map->mapname2mapid(str);
+ m = map->mapindex2mapid(strdb_iget(mapindex->db, str));
} else {
m = script_getnum(st, 3);
}
@@ -23965,6 +23965,42 @@ BUILDIN(clan_master)
}
/**
+ * hateffect(EffectID, Enable_State)
+ */
+BUILDIN(hateffect)
+{
+#if PACKETVER >= 20150422
+ struct map_session_data *sd = script_rid2sd(st);
+ int effectId, enabled = 0;
+ int i;
+
+ if (sd == NULL)
+ return false;
+
+ effectId = script_getnum(st, 2);
+ enabled = script_getnum(st, 3);
+
+ for (i = 0; i < VECTOR_LENGTH(sd->hatEffectId); ++i) {
+ if (VECTOR_INDEX(sd->hatEffectId, i) == effectId) {
+ if (enabled == 1) { // Already Enabled
+ return true;
+ } else { // Remove
+ VECTOR_ERASE(sd->hatEffectId, i);
+ clif->hat_effect_single(&sd->bl, effectId, enabled);
+ return true;
+ }
+ }
+ }
+
+ VECTOR_ENSURE(sd->hatEffectId, 1, 1);
+ VECTOR_PUSH(sd->hatEffectId, effectId);
+
+ clif->hat_effect_single(&sd->bl, effectId, enabled);
+#endif
+ return true;
+}
+
+/**
* Adds a built-in script function.
*
* @param buildin Script function data
@@ -24679,6 +24715,9 @@ void script_parse_builtin(void) {
BUILDIN_DEF2(rodex_sendmail2, "rodex_sendmail_acc2", "isss?????????????????????????????????????????"),
BUILDIN_DEF(_,"s"),
BUILDIN_DEF2(_, "_$", "s"),
+
+ // -- HatEffect
+ BUILDIN_DEF(hateffect, "ii"),
};
int i, len = ARRAYLENGTH(BUILDIN);
RECREATE(script->buildin, char *, script->buildin_count + len); // Pre-alloc to speed up
diff --git a/src/map/skill.c b/src/map/skill.c
index 3d541bf76..9108b6575 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -6503,16 +6503,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case TK_JUMPKICK:
/* Check if the target is an enemy; if not, skill should fail so the character doesn't unit->movepos (exploitable) */
- if( battle->check_target(src, bl, BCT_ENEMY) > 0 )
- {
- if( unit->movepos(src, bl->x, bl->y, 1, 1) )
- {
- skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
- clif->slide(src,bl->x,bl->y);
+ if (battle->check_target(src, bl, BCT_ENEMY) > 0) {
+ if (unit->movepos(src, bl->x, bl->y, 1, 1)) {
+ skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
+ clif->slide(src, bl->x, bl->y);
}
+ } else if (sd != NULL) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL, 0);
}
- else
- clif->skill_fail(sd,skill_id,USESKILL_FAIL,0);
break;
case AL_INCAGI:
diff --git a/src/map/status.c b/src/map/status.c
index 3e4b4a45c..b2f67735b 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -1780,7 +1780,11 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
for(i = 0; i < map->list[src->m].zone->disabled_skills_count; i++) {
if( skill_id == map->list[src->m].zone->disabled_skills[i]->nameid && (map->list[src->m].zone->disabled_skills[i]->type&src->type) ) {
if (src->type == BL_PC) {
- clif->msgtable(sd, MSG_SKILL_CANT_USE_AREA); // This skill cannot be used within this area
+#if PACKETVER >= 20080311
+ clif->skill_mapinfomessage(sd, 2);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_CYAN, msg_sd(sd, 50));
+#endif
} else if (src->type == BL_MOB && map->list[src->m].zone->disabled_skills[i]->subtype != MZS_NONE) {
if( st->mode&MD_BOSS ) { /* is boss */
if( !( map->list[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS ) )
diff --git a/src/map/unit.c b/src/map/unit.c
index c40aa7000..64bd17edc 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -2766,6 +2766,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
}
VECTOR_CLEAR(sd->script_queues);
VECTOR_CLEAR(sd->storage.item);
+ VECTOR_CLEAR(sd->hatEffectId);
sd->storage.received = false;
if( sd->quest_log != NULL ) {
aFree(sd->quest_log);
diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc
index bd17dc7fe..4bd77f588 100644
--- a/src/plugins/HPMHooking/HPMHooking.Defs.inc
+++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc
@@ -1452,6 +1452,10 @@ typedef void (*HPMHOOK_pre_clif_msgtable_num) (struct map_session_data **sd, uns
typedef void (*HPMHOOK_post_clif_msgtable_num) (struct map_session_data *sd, unsigned short msg_id, int value);
typedef void (*HPMHOOK_pre_clif_msgtable_skill) (struct map_session_data **sd, uint16 *skill_id, int *msg_id);
typedef void (*HPMHOOK_post_clif_msgtable_skill) (struct map_session_data *sd, uint16 skill_id, int msg_id);
+typedef void (*HPMHOOK_pre_clif_msgtable_str) (struct map_session_data **sd, uint16 *msg_id, const char **value);
+typedef void (*HPMHOOK_post_clif_msgtable_str) (struct map_session_data *sd, uint16 msg_id, const char *value);
+typedef void (*HPMHOOK_pre_clif_msgtable_color) (struct map_session_data **sd, uint16 *msg_id, uint32 *color);
+typedef void (*HPMHOOK_post_clif_msgtable_color) (struct map_session_data *sd, uint16 msg_id, uint32 color);
typedef void (*HPMHOOK_pre_clif_message) (const int *fd, const char **mes);
typedef void (*HPMHOOK_post_clif_message) (const int fd, const char *mes);
typedef void (*HPMHOOK_pre_clif_messageln) (const int *fd, const char **mes);
@@ -1692,6 +1696,8 @@ typedef void (*HPMHOOK_pre_clif_quest_update_status) (struct map_session_data **
typedef void (*HPMHOOK_post_clif_quest_update_status) (struct map_session_data *sd, int quest_id, bool active);
typedef void (*HPMHOOK_pre_clif_quest_update_objective) (struct map_session_data **sd, struct quest **qd);
typedef void (*HPMHOOK_post_clif_quest_update_objective) (struct map_session_data *sd, struct quest *qd);
+typedef void (*HPMHOOK_pre_clif_quest_notify_objective) (struct map_session_data **sd, struct quest **qd);
+typedef void (*HPMHOOK_post_clif_quest_notify_objective) (struct map_session_data *sd, struct quest *qd);
typedef void (*HPMHOOK_pre_clif_quest_show_event) (struct map_session_data **sd, struct block_list **bl, short *state, short *color);
typedef void (*HPMHOOK_post_clif_quest_show_event) (struct map_session_data *sd, struct block_list *bl, short state, short color);
typedef void (*HPMHOOK_pre_clif_mail_window) (int *fd, int *flag);
@@ -2404,6 +2410,26 @@ typedef void (*HPMHOOK_pre_clif_clan_message) (struct clan **c, const char **mes
typedef void (*HPMHOOK_post_clif_clan_message) (struct clan *c, const char *mes, int len);
typedef void (*HPMHOOK_pre_clif_pClanMessage) (int *fd, struct map_session_data **sd);
typedef void (*HPMHOOK_post_clif_pClanMessage) (int fd, struct map_session_data *sd);
+typedef void (*HPMHOOK_pre_clif_hat_effect) (struct block_list **bl, struct block_list **tbl, enum send_target *target);
+typedef void (*HPMHOOK_post_clif_hat_effect) (struct block_list *bl, struct block_list *tbl, enum send_target target);
+typedef void (*HPMHOOK_pre_clif_hat_effect_single) (struct block_list **bl, uint16 *effectId, bool *enable);
+typedef void (*HPMHOOK_post_clif_hat_effect_single) (struct block_list *bl, uint16 effectId, bool enable);
+typedef bool (*HPMHOOK_pre_clif_pAttendanceDB) (void);
+typedef bool (*HPMHOOK_post_clif_pAttendanceDB) (bool retVal___);
+typedef bool (*HPMHOOK_pre_clif_attendancedb_libconfig_sub) (struct config_setting_t **it, int *n, const char **source);
+typedef bool (*HPMHOOK_post_clif_attendancedb_libconfig_sub) (bool retVal___, struct config_setting_t *it, int n, const char *source);
+typedef bool (*HPMHOOK_pre_clif_attendance_timediff) (struct map_session_data **sd);
+typedef bool (*HPMHOOK_post_clif_attendance_timediff) (bool retVal___, struct map_session_data *sd);
+typedef time_t (*HPMHOOK_pre_clif_attendance_getendtime) (void);
+typedef time_t (*HPMHOOK_post_clif_attendance_getendtime) (time_t retVal___);
+typedef void (*HPMHOOK_pre_clif_pOpenUIRequest) (int *fd, struct map_session_data **sd);
+typedef void (*HPMHOOK_post_clif_pOpenUIRequest) (int fd, struct map_session_data *sd);
+typedef void (*HPMHOOK_pre_clif_open_ui) (struct map_session_data **sd, int8 *UIType);
+typedef void (*HPMHOOK_post_clif_open_ui) (struct map_session_data *sd, int8 UIType);
+typedef void (*HPMHOOK_pre_clif_pAttendanceRewardRequest) (int *fd, struct map_session_data **sd);
+typedef void (*HPMHOOK_post_clif_pAttendanceRewardRequest) (int fd, struct map_session_data *sd);
+typedef void (*HPMHOOK_pre_clif_ui_action) (struct map_session_data **sd, int32 *UIType, int32 *data);
+typedef void (*HPMHOOK_post_clif_ui_action) (struct map_session_data *sd, int32 UIType, int32 data);
#endif // MAP_CLIF_H
#ifdef COMMON_CORE_H /* cmdline */
typedef void (*HPMHOOK_pre_cmdline_init) (void);
@@ -2668,8 +2694,8 @@ typedef int (*HPMHOOK_pre_guild_check_alliance) (int *guild_id1, int *guild_id2,
typedef int (*HPMHOOK_post_guild_check_alliance) (int retVal___, int guild_id1, int guild_id2, int flag);
typedef int (*HPMHOOK_pre_guild_send_memberinfoshort) (struct map_session_data **sd, int *online);
typedef int (*HPMHOOK_post_guild_send_memberinfoshort) (int retVal___, struct map_session_data *sd, int online);
-typedef int (*HPMHOOK_pre_guild_recv_memberinfoshort) (int *guild_id, int *account_id, int *char_id, int *online, int *lv, int16 *class);
-typedef int (*HPMHOOK_post_guild_recv_memberinfoshort) (int retVal___, int guild_id, int account_id, int char_id, int online, int lv, int16 class);
+typedef int (*HPMHOOK_pre_guild_recv_memberinfoshort) (int *guild_id, int *account_id, int *char_id, int *online, int *lv, int16 *class, uint32 *last_login);
+typedef int (*HPMHOOK_post_guild_recv_memberinfoshort) (int retVal___, int guild_id, int account_id, int char_id, int online, int lv, int16 class, uint32 last_login);
typedef int (*HPMHOOK_pre_guild_change_memberposition) (int *guild_id, int *account_id, int *char_id, short *idx);
typedef int (*HPMHOOK_post_guild_change_memberposition) (int retVal___, int guild_id, int account_id, int char_id, short idx);
typedef int (*HPMHOOK_pre_guild_memberposition_changed) (struct guild **g, int *idx, int *pos);
@@ -6018,8 +6044,16 @@ typedef int (*HPMHOOK_pre_pet_recovery_timer) (int *tid, int64 *tick, int *id, i
typedef int (*HPMHOOK_post_pet_recovery_timer) (int retVal___, int tid, int64 tick, int id, intptr_t data);
typedef int (*HPMHOOK_pre_pet_skill_support_timer) (int *tid, int64 *tick, int *id, intptr_t *data);
typedef int (*HPMHOOK_post_pet_skill_support_timer) (int retVal___, int tid, int64 tick, int id, intptr_t data);
-typedef int (*HPMHOOK_pre_pet_read_db) (void);
-typedef int (*HPMHOOK_post_pet_read_db) (int retVal___);
+typedef void (*HPMHOOK_pre_pet_read_db) (void);
+typedef void (*HPMHOOK_post_pet_read_db) (void);
+typedef int (*HPMHOOK_pre_pet_read_db_libconfig) (const char **filename, bool *ignore_missing);
+typedef int (*HPMHOOK_post_pet_read_db_libconfig) (int retVal___, const char *filename, bool ignore_missing);
+typedef int (*HPMHOOK_pre_pet_read_db_sub) (struct config_setting_t **it, int *n, const char **source);
+typedef int (*HPMHOOK_post_pet_read_db_sub) (int retVal___, struct config_setting_t *it, int n, const char *source);
+typedef bool (*HPMHOOK_pre_pet_read_db_sub_intimacy) (int *idx, struct config_setting_t **t);
+typedef bool (*HPMHOOK_post_pet_read_db_sub_intimacy) (bool retVal___, int idx, struct config_setting_t *t);
+typedef void (*HPMHOOK_pre_pet_read_db_clear) (void);
+typedef void (*HPMHOOK_post_pet_read_db_clear) (void);
#endif // MAP_PET_H
#ifdef CHAR_PINCODE_H /* pincode */
typedef void (*HPMHOOK_pre_pincode_handle) (int *fd, struct char_session_data **sd);
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
index 9d531e370..c01f8000c 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
@@ -1046,6 +1046,10 @@ struct {
struct HPMHookPoint *HP_clif_msgtable_num_post;
struct HPMHookPoint *HP_clif_msgtable_skill_pre;
struct HPMHookPoint *HP_clif_msgtable_skill_post;
+ struct HPMHookPoint *HP_clif_msgtable_str_pre;
+ struct HPMHookPoint *HP_clif_msgtable_str_post;
+ struct HPMHookPoint *HP_clif_msgtable_color_pre;
+ struct HPMHookPoint *HP_clif_msgtable_color_post;
struct HPMHookPoint *HP_clif_message_pre;
struct HPMHookPoint *HP_clif_message_post;
struct HPMHookPoint *HP_clif_messageln_pre;
@@ -1286,6 +1290,8 @@ struct {
struct HPMHookPoint *HP_clif_quest_update_status_post;
struct HPMHookPoint *HP_clif_quest_update_objective_pre;
struct HPMHookPoint *HP_clif_quest_update_objective_post;
+ struct HPMHookPoint *HP_clif_quest_notify_objective_pre;
+ struct HPMHookPoint *HP_clif_quest_notify_objective_post;
struct HPMHookPoint *HP_clif_quest_show_event_pre;
struct HPMHookPoint *HP_clif_quest_show_event_post;
struct HPMHookPoint *HP_clif_mail_window_pre;
@@ -1998,6 +2004,26 @@ struct {
struct HPMHookPoint *HP_clif_clan_message_post;
struct HPMHookPoint *HP_clif_pClanMessage_pre;
struct HPMHookPoint *HP_clif_pClanMessage_post;
+ struct HPMHookPoint *HP_clif_hat_effect_pre;
+ struct HPMHookPoint *HP_clif_hat_effect_post;
+ struct HPMHookPoint *HP_clif_hat_effect_single_pre;
+ struct HPMHookPoint *HP_clif_hat_effect_single_post;
+ struct HPMHookPoint *HP_clif_pAttendanceDB_pre;
+ struct HPMHookPoint *HP_clif_pAttendanceDB_post;
+ struct HPMHookPoint *HP_clif_attendancedb_libconfig_sub_pre;
+ struct HPMHookPoint *HP_clif_attendancedb_libconfig_sub_post;
+ struct HPMHookPoint *HP_clif_attendance_timediff_pre;
+ struct HPMHookPoint *HP_clif_attendance_timediff_post;
+ struct HPMHookPoint *HP_clif_attendance_getendtime_pre;
+ struct HPMHookPoint *HP_clif_attendance_getendtime_post;
+ struct HPMHookPoint *HP_clif_pOpenUIRequest_pre;
+ struct HPMHookPoint *HP_clif_pOpenUIRequest_post;
+ struct HPMHookPoint *HP_clif_open_ui_pre;
+ struct HPMHookPoint *HP_clif_open_ui_post;
+ struct HPMHookPoint *HP_clif_pAttendanceRewardRequest_pre;
+ struct HPMHookPoint *HP_clif_pAttendanceRewardRequest_post;
+ struct HPMHookPoint *HP_clif_ui_action_pre;
+ struct HPMHookPoint *HP_clif_ui_action_post;
struct HPMHookPoint *HP_cmdline_init_pre;
struct HPMHookPoint *HP_cmdline_init_post;
struct HPMHookPoint *HP_cmdline_final_pre;
@@ -4670,6 +4696,14 @@ struct {
struct HPMHookPoint *HP_pet_skill_support_timer_post;
struct HPMHookPoint *HP_pet_read_db_pre;
struct HPMHookPoint *HP_pet_read_db_post;
+ struct HPMHookPoint *HP_pet_read_db_libconfig_pre;
+ struct HPMHookPoint *HP_pet_read_db_libconfig_post;
+ struct HPMHookPoint *HP_pet_read_db_sub_pre;
+ struct HPMHookPoint *HP_pet_read_db_sub_post;
+ struct HPMHookPoint *HP_pet_read_db_sub_intimacy_pre;
+ struct HPMHookPoint *HP_pet_read_db_sub_intimacy_post;
+ struct HPMHookPoint *HP_pet_read_db_clear_pre;
+ struct HPMHookPoint *HP_pet_read_db_clear_post;
struct HPMHookPoint *HP_quest_init_pre;
struct HPMHookPoint *HP_quest_init_post;
struct HPMHookPoint *HP_quest_final_pre;
@@ -7327,6 +7361,10 @@ struct {
int HP_clif_msgtable_num_post;
int HP_clif_msgtable_skill_pre;
int HP_clif_msgtable_skill_post;
+ int HP_clif_msgtable_str_pre;
+ int HP_clif_msgtable_str_post;
+ int HP_clif_msgtable_color_pre;
+ int HP_clif_msgtable_color_post;
int HP_clif_message_pre;
int HP_clif_message_post;
int HP_clif_messageln_pre;
@@ -7567,6 +7605,8 @@ struct {
int HP_clif_quest_update_status_post;
int HP_clif_quest_update_objective_pre;
int HP_clif_quest_update_objective_post;
+ int HP_clif_quest_notify_objective_pre;
+ int HP_clif_quest_notify_objective_post;
int HP_clif_quest_show_event_pre;
int HP_clif_quest_show_event_post;
int HP_clif_mail_window_pre;
@@ -8279,6 +8319,26 @@ struct {
int HP_clif_clan_message_post;
int HP_clif_pClanMessage_pre;
int HP_clif_pClanMessage_post;
+ int HP_clif_hat_effect_pre;
+ int HP_clif_hat_effect_post;
+ int HP_clif_hat_effect_single_pre;
+ int HP_clif_hat_effect_single_post;
+ int HP_clif_pAttendanceDB_pre;
+ int HP_clif_pAttendanceDB_post;
+ int HP_clif_attendancedb_libconfig_sub_pre;
+ int HP_clif_attendancedb_libconfig_sub_post;
+ int HP_clif_attendance_timediff_pre;
+ int HP_clif_attendance_timediff_post;
+ int HP_clif_attendance_getendtime_pre;
+ int HP_clif_attendance_getendtime_post;
+ int HP_clif_pOpenUIRequest_pre;
+ int HP_clif_pOpenUIRequest_post;
+ int HP_clif_open_ui_pre;
+ int HP_clif_open_ui_post;
+ int HP_clif_pAttendanceRewardRequest_pre;
+ int HP_clif_pAttendanceRewardRequest_post;
+ int HP_clif_ui_action_pre;
+ int HP_clif_ui_action_post;
int HP_cmdline_init_pre;
int HP_cmdline_init_post;
int HP_cmdline_final_pre;
@@ -10951,6 +11011,14 @@ struct {
int HP_pet_skill_support_timer_post;
int HP_pet_read_db_pre;
int HP_pet_read_db_post;
+ int HP_pet_read_db_libconfig_pre;
+ int HP_pet_read_db_libconfig_post;
+ int HP_pet_read_db_sub_pre;
+ int HP_pet_read_db_sub_post;
+ int HP_pet_read_db_sub_intimacy_pre;
+ int HP_pet_read_db_sub_intimacy_post;
+ int HP_pet_read_db_clear_pre;
+ int HP_pet_read_db_clear_post;
int HP_quest_init_pre;
int HP_quest_init_post;
int HP_quest_final_pre;
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
index 5551668d2..2e762a231 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
@@ -546,6 +546,8 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(clif->msgtable, HP_clif_msgtable) },
{ HP_POP(clif->msgtable_num, HP_clif_msgtable_num) },
{ HP_POP(clif->msgtable_skill, HP_clif_msgtable_skill) },
+ { HP_POP(clif->msgtable_str, HP_clif_msgtable_str) },
+ { HP_POP(clif->msgtable_color, HP_clif_msgtable_color) },
{ HP_POP(clif->message, HP_clif_message) },
{ HP_POP(clif->messageln, HP_clif_messageln) },
{ HP_POP(clif->process_chat_message, HP_clif_process_chat_message) },
@@ -666,6 +668,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(clif->quest_delete, HP_clif_quest_delete) },
{ HP_POP(clif->quest_update_status, HP_clif_quest_update_status) },
{ HP_POP(clif->quest_update_objective, HP_clif_quest_update_objective) },
+ { HP_POP(clif->quest_notify_objective, HP_clif_quest_notify_objective) },
{ HP_POP(clif->quest_show_event, HP_clif_quest_show_event) },
{ HP_POP(clif->mail_window, HP_clif_mail_window) },
{ HP_POP(clif->mail_read, HP_clif_mail_read) },
@@ -1022,6 +1025,16 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(clif->clan_leave, HP_clif_clan_leave) },
{ HP_POP(clif->clan_message, HP_clif_clan_message) },
{ HP_POP(clif->pClanMessage, HP_clif_pClanMessage) },
+ { HP_POP(clif->hat_effect, HP_clif_hat_effect) },
+ { HP_POP(clif->hat_effect_single, HP_clif_hat_effect_single) },
+ { HP_POP(clif->pAttendanceDB, HP_clif_pAttendanceDB) },
+ { HP_POP(clif->attendancedb_libconfig_sub, HP_clif_attendancedb_libconfig_sub) },
+ { HP_POP(clif->attendance_timediff, HP_clif_attendance_timediff) },
+ { HP_POP(clif->attendance_getendtime, HP_clif_attendance_getendtime) },
+ { HP_POP(clif->pOpenUIRequest, HP_clif_pOpenUIRequest) },
+ { HP_POP(clif->open_ui, HP_clif_open_ui) },
+ { HP_POP(clif->pAttendanceRewardRequest, HP_clif_pAttendanceRewardRequest) },
+ { HP_POP(clif->ui_action, HP_clif_ui_action) },
/* cmdline_interface */
{ HP_POP(cmdline->init, HP_cmdline_init) },
{ HP_POP(cmdline->final, HP_cmdline_final) },
@@ -2393,6 +2406,10 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(pet->recovery_timer, HP_pet_recovery_timer) },
{ HP_POP(pet->skill_support_timer, HP_pet_skill_support_timer) },
{ HP_POP(pet->read_db, HP_pet_read_db) },
+ { HP_POP(pet->read_db_libconfig, HP_pet_read_db_libconfig) },
+ { HP_POP(pet->read_db_sub, HP_pet_read_db_sub) },
+ { HP_POP(pet->read_db_sub_intimacy, HP_pet_read_db_sub_intimacy) },
+ { HP_POP(pet->read_db_clear, HP_pet_read_db_clear) },
/* quest_interface */
{ HP_POP(quest->init, HP_quest_init) },
{ HP_POP(quest->final, HP_quest_final) },
diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index 2e20ab157..6b89e4f65 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -13622,6 +13622,58 @@ void HP_clif_msgtable_skill(struct map_session_data *sd, uint16 skill_id, int ms
}
return;
}
+void HP_clif_msgtable_str(struct map_session_data *sd, uint16 msg_id, const char *value) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_clif_msgtable_str_pre > 0) {
+ void (*preHookFunc) (struct map_session_data **sd, uint16 *msg_id, const char **value);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_msgtable_str_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_msgtable_str_pre[hIndex].func;
+ preHookFunc(&sd, &msg_id, &value);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.msgtable_str(sd, msg_id, value);
+ }
+ if (HPMHooks.count.HP_clif_msgtable_str_post > 0) {
+ void (*postHookFunc) (struct map_session_data *sd, uint16 msg_id, const char *value);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_msgtable_str_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_msgtable_str_post[hIndex].func;
+ postHookFunc(sd, msg_id, value);
+ }
+ }
+ return;
+}
+void HP_clif_msgtable_color(struct map_session_data *sd, uint16 msg_id, uint32 color) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_clif_msgtable_color_pre > 0) {
+ void (*preHookFunc) (struct map_session_data **sd, uint16 *msg_id, uint32 *color);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_msgtable_color_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_msgtable_color_pre[hIndex].func;
+ preHookFunc(&sd, &msg_id, &color);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.msgtable_color(sd, msg_id, color);
+ }
+ if (HPMHooks.count.HP_clif_msgtable_color_post > 0) {
+ void (*postHookFunc) (struct map_session_data *sd, uint16 msg_id, uint32 color);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_msgtable_color_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_msgtable_color_post[hIndex].func;
+ postHookFunc(sd, msg_id, color);
+ }
+ }
+ return;
+}
void HP_clif_message(const int fd, const char *mes) {
int hIndex = 0;
if (HPMHooks.count.HP_clif_message_pre > 0) {
@@ -16753,6 +16805,32 @@ void HP_clif_quest_update_objective(struct map_session_data *sd, struct quest *q
}
return;
}
+void HP_clif_quest_notify_objective(struct map_session_data *sd, struct quest *qd) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_clif_quest_notify_objective_pre > 0) {
+ void (*preHookFunc) (struct map_session_data **sd, struct quest **qd);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_quest_notify_objective_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_quest_notify_objective_pre[hIndex].func;
+ preHookFunc(&sd, &qd);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.quest_notify_objective(sd, qd);
+ }
+ if (HPMHooks.count.HP_clif_quest_notify_objective_post > 0) {
+ void (*postHookFunc) (struct map_session_data *sd, struct quest *qd);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_quest_notify_objective_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_quest_notify_objective_post[hIndex].func;
+ postHookFunc(sd, qd);
+ }
+ }
+ return;
+}
void HP_clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, short state, short color) {
int hIndex = 0;
if (HPMHooks.count.HP_clif_quest_show_event_pre > 0) {
@@ -26018,6 +26096,271 @@ void HP_clif_pClanMessage(int fd, struct map_session_data *sd) {
}
return;
}
+void HP_clif_hat_effect(struct block_list *bl, struct block_list *tbl, enum send_target target) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_clif_hat_effect_pre > 0) {
+ void (*preHookFunc) (struct block_list **bl, struct block_list **tbl, enum send_target *target);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_hat_effect_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_hat_effect_pre[hIndex].func;
+ preHookFunc(&bl, &tbl, &target);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.hat_effect(bl, tbl, target);
+ }
+ if (HPMHooks.count.HP_clif_hat_effect_post > 0) {
+ void (*postHookFunc) (struct block_list *bl, struct block_list *tbl, enum send_target target);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_hat_effect_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_hat_effect_post[hIndex].func;
+ postHookFunc(bl, tbl, target);
+ }
+ }
+ return;
+}
+void HP_clif_hat_effect_single(struct block_list *bl, uint16 effectId, bool enable) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_clif_hat_effect_single_pre > 0) {
+ void (*preHookFunc) (struct block_list **bl, uint16 *effectId, bool *enable);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_hat_effect_single_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_hat_effect_single_pre[hIndex].func;
+ preHookFunc(&bl, &effectId, &enable);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.hat_effect_single(bl, effectId, enable);
+ }
+ if (HPMHooks.count.HP_clif_hat_effect_single_post > 0) {
+ void (*postHookFunc) (struct block_list *bl, uint16 effectId, bool enable);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_hat_effect_single_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_hat_effect_single_post[hIndex].func;
+ postHookFunc(bl, effectId, enable);
+ }
+ }
+ return;
+}
+bool HP_clif_pAttendanceDB(void) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if (HPMHooks.count.HP_clif_pAttendanceDB_pre > 0) {
+ bool (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_pAttendanceDB_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_pAttendanceDB_pre[hIndex].func;
+ retVal___ = preHookFunc();
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.clif.pAttendanceDB();
+ }
+ if (HPMHooks.count.HP_clif_pAttendanceDB_post > 0) {
+ bool (*postHookFunc) (bool retVal___);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_pAttendanceDB_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_pAttendanceDB_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___);
+ }
+ }
+ return retVal___;
+}
+bool HP_clif_attendancedb_libconfig_sub(struct config_setting_t *it, int n, const char *source) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if (HPMHooks.count.HP_clif_attendancedb_libconfig_sub_pre > 0) {
+ bool (*preHookFunc) (struct config_setting_t **it, int *n, const char **source);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_attendancedb_libconfig_sub_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_attendancedb_libconfig_sub_pre[hIndex].func;
+ retVal___ = preHookFunc(&it, &n, &source);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.clif.attendancedb_libconfig_sub(it, n, source);
+ }
+ if (HPMHooks.count.HP_clif_attendancedb_libconfig_sub_post > 0) {
+ bool (*postHookFunc) (bool retVal___, struct config_setting_t *it, int n, const char *source);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_attendancedb_libconfig_sub_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_attendancedb_libconfig_sub_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, it, n, source);
+ }
+ }
+ return retVal___;
+}
+bool HP_clif_attendance_timediff(struct map_session_data *sd) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if (HPMHooks.count.HP_clif_attendance_timediff_pre > 0) {
+ bool (*preHookFunc) (struct map_session_data **sd);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_attendance_timediff_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_attendance_timediff_pre[hIndex].func;
+ retVal___ = preHookFunc(&sd);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.clif.attendance_timediff(sd);
+ }
+ if (HPMHooks.count.HP_clif_attendance_timediff_post > 0) {
+ bool (*postHookFunc) (bool retVal___, struct map_session_data *sd);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_attendance_timediff_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_attendance_timediff_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, sd);
+ }
+ }
+ return retVal___;
+}
+time_t HP_clif_attendance_getendtime(void) {
+/* Unknown return type 'time_t'. Initializing to '0'. */
+ int hIndex = 0;
+ time_t retVal___ = 0;
+ if (HPMHooks.count.HP_clif_attendance_getendtime_pre > 0) {
+ time_t (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_attendance_getendtime_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_attendance_getendtime_pre[hIndex].func;
+ retVal___ = preHookFunc();
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.clif.attendance_getendtime();
+ }
+ if (HPMHooks.count.HP_clif_attendance_getendtime_post > 0) {
+ time_t (*postHookFunc) (time_t retVal___);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_attendance_getendtime_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_attendance_getendtime_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___);
+ }
+ }
+ return retVal___;
+}
+void HP_clif_pOpenUIRequest(int fd, struct map_session_data *sd) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_clif_pOpenUIRequest_pre > 0) {
+ void (*preHookFunc) (int *fd, struct map_session_data **sd);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_pOpenUIRequest_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_pOpenUIRequest_pre[hIndex].func;
+ preHookFunc(&fd, &sd);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.pOpenUIRequest(fd, sd);
+ }
+ if (HPMHooks.count.HP_clif_pOpenUIRequest_post > 0) {
+ void (*postHookFunc) (int fd, struct map_session_data *sd);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_pOpenUIRequest_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_pOpenUIRequest_post[hIndex].func;
+ postHookFunc(fd, sd);
+ }
+ }
+ return;
+}
+void HP_clif_open_ui(struct map_session_data *sd, int8 UIType) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_clif_open_ui_pre > 0) {
+ void (*preHookFunc) (struct map_session_data **sd, int8 *UIType);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_open_ui_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_open_ui_pre[hIndex].func;
+ preHookFunc(&sd, &UIType);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.open_ui(sd, UIType);
+ }
+ if (HPMHooks.count.HP_clif_open_ui_post > 0) {
+ void (*postHookFunc) (struct map_session_data *sd, int8 UIType);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_open_ui_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_open_ui_post[hIndex].func;
+ postHookFunc(sd, UIType);
+ }
+ }
+ return;
+}
+void HP_clif_pAttendanceRewardRequest(int fd, struct map_session_data *sd) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_clif_pAttendanceRewardRequest_pre > 0) {
+ void (*preHookFunc) (int *fd, struct map_session_data **sd);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_pAttendanceRewardRequest_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_pAttendanceRewardRequest_pre[hIndex].func;
+ preHookFunc(&fd, &sd);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.pAttendanceRewardRequest(fd, sd);
+ }
+ if (HPMHooks.count.HP_clif_pAttendanceRewardRequest_post > 0) {
+ void (*postHookFunc) (int fd, struct map_session_data *sd);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_pAttendanceRewardRequest_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_pAttendanceRewardRequest_post[hIndex].func;
+ postHookFunc(fd, sd);
+ }
+ }
+ return;
+}
+void HP_clif_ui_action(struct map_session_data *sd, int32 UIType, int32 data) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_clif_ui_action_pre > 0) {
+ void (*preHookFunc) (struct map_session_data **sd, int32 *UIType, int32 *data);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_ui_action_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_ui_action_pre[hIndex].func;
+ preHookFunc(&sd, &UIType, &data);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.ui_action(sd, UIType, data);
+ }
+ if (HPMHooks.count.HP_clif_ui_action_post > 0) {
+ void (*postHookFunc) (struct map_session_data *sd, int32 UIType, int32 data);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_ui_action_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_ui_action_post[hIndex].func;
+ postHookFunc(sd, UIType, data);
+ }
+ }
+ return;
+}
/* cmdline_interface */
void HP_cmdline_init(void) {
int hIndex = 0;
@@ -29222,15 +29565,15 @@ int HP_guild_send_memberinfoshort(struct map_session_data *sd, int online) {
}
return retVal___;
}
-int HP_guild_recv_memberinfoshort(int guild_id, int account_id, int char_id, int online, int lv, int16 class) {
+int HP_guild_recv_memberinfoshort(int guild_id, int account_id, int char_id, int online, int lv, int16 class, uint32 last_login) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_guild_recv_memberinfoshort_pre > 0) {
- int (*preHookFunc) (int *guild_id, int *account_id, int *char_id, int *online, int *lv, int16 *class);
+ int (*preHookFunc) (int *guild_id, int *account_id, int *char_id, int *online, int *lv, int16 *class, uint32 *last_login);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_guild_recv_memberinfoshort_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_guild_recv_memberinfoshort_pre[hIndex].func;
- retVal___ = preHookFunc(&guild_id, &account_id, &char_id, &online, &lv, &class);
+ retVal___ = preHookFunc(&guild_id, &account_id, &char_id, &online, &lv, &class, &last_login);
}
if (*HPMforce_return) {
*HPMforce_return = false;
@@ -29238,13 +29581,13 @@ int HP_guild_recv_memberinfoshort(int guild_id, int account_id, int char_id, int
}
}
{
- retVal___ = HPMHooks.source.guild.recv_memberinfoshort(guild_id, account_id, char_id, online, lv, class);
+ retVal___ = HPMHooks.source.guild.recv_memberinfoshort(guild_id, account_id, char_id, online, lv, class, last_login);
}
if (HPMHooks.count.HP_guild_recv_memberinfoshort_post > 0) {
- int (*postHookFunc) (int retVal___, int guild_id, int account_id, int char_id, int online, int lv, int16 class);
+ int (*postHookFunc) (int retVal___, int guild_id, int account_id, int char_id, int online, int lv, int16 class, uint32 last_login);
for (hIndex = 0; hIndex < HPMHooks.count.HP_guild_recv_memberinfoshort_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_guild_recv_memberinfoshort_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, guild_id, account_id, char_id, online, lv, class);
+ retVal___ = postHookFunc(retVal___, guild_id, account_id, char_id, online, lv, class, last_login);
}
}
return retVal___;
@@ -62202,33 +62545,139 @@ int HP_pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) {
}
return retVal___;
}
-int HP_pet_read_db(void) {
+void HP_pet_read_db(void) {
int hIndex = 0;
- int retVal___ = 0;
if (HPMHooks.count.HP_pet_read_db_pre > 0) {
- int (*preHookFunc) (void);
+ void (*preHookFunc) (void);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_read_db_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_pet_read_db_pre[hIndex].func;
- retVal___ = preHookFunc();
+ preHookFunc();
}
if (*HPMforce_return) {
*HPMforce_return = false;
- return retVal___;
+ return;
}
}
{
- retVal___ = HPMHooks.source.pet.read_db();
+ HPMHooks.source.pet.read_db();
}
if (HPMHooks.count.HP_pet_read_db_post > 0) {
- int (*postHookFunc) (int retVal___);
+ void (*postHookFunc) (void);
for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_read_db_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_pet_read_db_post[hIndex].func;
- retVal___ = postHookFunc(retVal___);
+ postHookFunc();
+ }
+ }
+ return;
+}
+int HP_pet_read_db_libconfig(const char *filename, bool ignore_missing) {
+ int hIndex = 0;
+ int retVal___ = 0;
+ if (HPMHooks.count.HP_pet_read_db_libconfig_pre > 0) {
+ int (*preHookFunc) (const char **filename, bool *ignore_missing);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_read_db_libconfig_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_pet_read_db_libconfig_pre[hIndex].func;
+ retVal___ = preHookFunc(&filename, &ignore_missing);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.pet.read_db_libconfig(filename, ignore_missing);
+ }
+ if (HPMHooks.count.HP_pet_read_db_libconfig_post > 0) {
+ int (*postHookFunc) (int retVal___, const char *filename, bool ignore_missing);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_read_db_libconfig_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_pet_read_db_libconfig_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, filename, ignore_missing);
+ }
+ }
+ return retVal___;
+}
+int HP_pet_read_db_sub(struct config_setting_t *it, int n, const char *source) {
+ int hIndex = 0;
+ int retVal___ = 0;
+ if (HPMHooks.count.HP_pet_read_db_sub_pre > 0) {
+ int (*preHookFunc) (struct config_setting_t **it, int *n, const char **source);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_read_db_sub_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_pet_read_db_sub_pre[hIndex].func;
+ retVal___ = preHookFunc(&it, &n, &source);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.pet.read_db_sub(it, n, source);
+ }
+ if (HPMHooks.count.HP_pet_read_db_sub_post > 0) {
+ int (*postHookFunc) (int retVal___, struct config_setting_t *it, int n, const char *source);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_read_db_sub_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_pet_read_db_sub_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, it, n, source);
+ }
+ }
+ return retVal___;
+}
+bool HP_pet_read_db_sub_intimacy(int idx, struct config_setting_t *t) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if (HPMHooks.count.HP_pet_read_db_sub_intimacy_pre > 0) {
+ bool (*preHookFunc) (int *idx, struct config_setting_t **t);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_read_db_sub_intimacy_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_pet_read_db_sub_intimacy_pre[hIndex].func;
+ retVal___ = preHookFunc(&idx, &t);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.pet.read_db_sub_intimacy(idx, t);
+ }
+ if (HPMHooks.count.HP_pet_read_db_sub_intimacy_post > 0) {
+ bool (*postHookFunc) (bool retVal___, int idx, struct config_setting_t *t);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_read_db_sub_intimacy_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_pet_read_db_sub_intimacy_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, idx, t);
}
}
return retVal___;
}
+void HP_pet_read_db_clear(void) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_pet_read_db_clear_pre > 0) {
+ void (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_read_db_clear_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_pet_read_db_clear_pre[hIndex].func;
+ preHookFunc();
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pet.read_db_clear();
+ }
+ if (HPMHooks.count.HP_pet_read_db_clear_post > 0) {
+ void (*postHookFunc) (void);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_read_db_clear_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_pet_read_db_clear_post[hIndex].func;
+ postHookFunc();
+ }
+ }
+ return;
+}
/* quest_interface */
void HP_quest_init(bool minimal) {
int hIndex = 0;
diff --git a/tools/petdbconverter.py b/tools/petdbconverter.py
new file mode 100644
index 000000000..261c1e6ad
--- /dev/null
+++ b/tools/petdbconverter.py
@@ -0,0 +1,214 @@
+#! /usr/bin/env python
+# -*- coding: utf8 -*-
+#
+# This file is part of Hercules.
+# http://herc.ws - http://github.com/HerculesWS/Hercules
+#
+# Copyright (C) 2018 Hercules Dev Team
+# Copyright (C) 2018 Asheraf
+# Copyright (C) 2015 Andrei Karas (4144)
+#
+# Hercules 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/>.
+
+import os
+import re
+import sys
+
+def isValidEntry(line):
+ if re.match('^[0-9]+,.*', line):
+ return True
+ return False
+
+def curlSplit(line):
+ return re.split('[{}]|},', line)
+
+def commaSplit(line):
+ return line.split(',')
+
+def printIntField(name, value):
+ if int(value) != 0:
+ print('\t{0}: {1}'.format(name, value))
+
+def printIntField2(name, value):
+ if int(value) != 0:
+ print('\t\t{0}: {1}'.format(name, value))
+
+def printStrField(name, value):
+ if value != '':
+ print('\t{0}: \"{1}\"'.format(name, value))
+
+def printBool(name, value):
+ if int(value) != 0:
+ print('\t{0}: true'.format(name))
+
+def printIntimacy(arr):
+ if int(arr[9]) == 0 or int(arr[10]) == 0 or int(arr[11]) == 0 or int(arr[12]) == 0:
+ return
+ print('\tIntimacy: {')
+ printIntField2('Initial', arr[11])
+ printIntField2('FeedIncrement', arr[9])
+ printIntField2('OverFeedDecrement', arr[10])
+ printIntField2('OwnerDeathDecrement', arr[12])
+ print('\t}')
+
+def printScript(name, value):
+ if re.match('.*[a-zA-Z0-9,]+.*', value):
+ print('\t{0}: <\"{1}\">'.format(name, value))
+
+def printItemName(fieldname, itemid, itemDb):
+ value = int(itemid)
+ if value != 0:
+ if value not in itemDb:
+ print("// Error: pet item with id {0} not found in item_db.conf".format(value))
+ else:
+ printStrField(fieldname, itemDb[value])
+
+
+def printHeader():
+ print("""
+pet_db:(
+/**************************************************************************
+ ************* Entry structure ********************************************
+ **************************************************************************
+{
+ // ================ Mandatory fields ==============================
+ Id: ID (int)
+ SpriteName: "Sprite_Name" (string)
+ Name: "Pet Name" (string)
+ // ================ Optional fields ===============================
+ TamingItem: Taming Item (string, defaults to 0)
+ EggItem: Egg Id (string, defaults to 0)
+ AccessoryItem: Equipment Id (string, defaults to 0)
+ FoodItem: Food Id (string, defaults to 0)
+ FoodEffectiveness: hunger points (int, defaults to 0)
+ HungerDelay: hunger time (int, defaults to 0)
+ Intimacy: {
+ Initial: start intimacy (int, defaults to 0)
+ FeedIncrement: feeding intimacy (int, defaults to 0)
+ OverFeedDecrement: overfeeding intimacy (int, defaults to 0)
+ OwnerDeathDecrement: owner die intimacy (int, defaults to 0)
+ }
+ CaptureRate: capture rate (int, defaults to 0)
+ Speed: speed (int, defaults to 0)
+ SpecialPerformance: true/false (boolean, defaults to false)
+ TalkWithEmotes: convert talk (boolean, defaults to false)
+ AttackRate: attack rate (int, defaults to 0)
+ DefendRate: Defence attack (int, defaults to 0)
+ ChangeTargetRate: change target (int, defaults to 0)
+ PetScript: <" Pet Script (can also be multi-line) ">
+ EquipScript: <" Equip Script (can also be multi-line) ">
+},
+**************************************************************************/
+ """)
+
+def printFooter():
+ print(')\n')
+
+def convertFile(inFile, itemDb):
+ if inFile != "" and not os.path.exists(inFile):
+ return
+
+ if inFile == "":
+ r = sys.stdin
+ else:
+ r = open(inFile, "r")
+
+ printHeader()
+ for line in r:
+ if isValidEntry(line) == True:
+ print('{')
+ firstsplit = curlSplit(line)
+ secondsplit = commaSplit(firstsplit[0])
+ printIntField('Id', secondsplit[0])
+ printStrField('SpriteName', secondsplit[1])
+ printStrField('Name', secondsplit[2])
+ printItemName('TamingItem', secondsplit[3], itemDb)
+ printItemName('EggItem', secondsplit[4], itemDb)
+ printItemName('AccessoryItem', secondsplit[5], itemDb)
+ printItemName('FoodItem', secondsplit[6], itemDb)
+ printIntField('FoodEffectiveness', secondsplit[7])
+ printIntField('HungerDelay', secondsplit[8])
+ printIntimacy(secondsplit)
+ printIntField('CaptureRate', secondsplit[13])
+ printIntField('Speed', secondsplit[14])
+ printBool('SpecialPerformance', secondsplit[15])
+ printBool('TalkWithEmotes', secondsplit[16])
+ printIntField('AttackRate', secondsplit[17])
+ printIntField('DefendRate', secondsplit[18])
+ printIntField('ChangeTargetRate', secondsplit[19])
+ printScript('PetScript', firstsplit[1])
+ printScript('EquipScript', firstsplit[3])
+ print('},')
+ printFooter()
+
+def printHelp():
+ print("PetDB converter from txt to conf format")
+ print("Usage:")
+ print(" petdbconverter.py re serverpath dbfilepath")
+ print(" petdbconverter.py pre-re serverpath dbfilepath")
+ print("Usage for read from stdin:")
+ print(" petdbconverter.py re dbfilepath")
+
+def readItemDB(inFile, itemDb):
+ itemId = 0
+ itemName = ""
+ started = False
+ with open(inFile, "r") as r:
+ for line in r:
+ line = line.strip()
+ if started == True:
+ if line == "},":
+ started = False
+ elif line[:10] == "AegisName:":
+ itemName = line[12:-1]
+ elif line[:3] == "Id:":
+ try:
+ itemId = int(line[4:])
+ except:
+ started = False
+ if itemId != 0 and itemName != "":
+# was need for remove wrong characters
+# itemName = itemName.replace(".", "")
+# if itemName[0] >= "0" and itemName[0] <= "9":
+# itemName = "Num" + itemName
+ itemDb[itemId] = itemName
+ started = False
+ else:
+ if line == "{":
+ started = True
+ itemId = 0
+ itemName = ""
+ return itemDb
+
+if len(sys.argv) != 4 and len(sys.argv) != 3:
+ printHelp();
+ exit(1)
+startPath = sys.argv[2]
+if len(sys.argv) == 4:
+ sourceFile = sys.argv[3]
+else:
+ sourceFile = "";
+
+itemDb = dict()
+if sys.argv[1] == "re":
+ itemDb = readItemDB(startPath + "/db/re/item_db.conf", itemDb)
+ itemDb = readItemDB(startPath + "/db/item_db2.conf", itemDb)
+elif sys.argv[1] == "pre-re":
+ itemDb = readItemDB(startPath + "/db/pre-re/item_db.conf", itemDb)
+ itemDb = readItemDB(startPath + "/db/item_db2.conf", itemDb)
+else:
+ printHelp();
+ exit(1)
+
+convertFile(sourceFile, itemDb) \ No newline at end of file