diff options
50 files changed, 1749 insertions, 348 deletions
diff --git a/conf/map/battle/feature.conf b/conf/map/battle/feature.conf index 8d19539b4..285633209 100644 --- a/conf/map/battle/feature.conf +++ b/conf/map/battle/feature.conf @@ -71,6 +71,11 @@ features: { // false: disable enable_homun_autofeed: true + // Allow Pet autofeeding + // true: enable (Default) + // false: disable + enable_pet_autofeed: true + // Enable Attendance System for clients >= 2018-03-07bRagexeRE or 2018-04-04bRagexe or 2018-04-11aRagexe_zero // true: enable (Default) // false: disable diff --git a/db/pre-re/pet_db.conf b/db/pre-re/pet_db.conf index 3ce78e546..91f9cb8e8 100644 --- a/db/pre-re/pet_db.conf +++ b/db/pre-re/pet_db.conf @@ -56,6 +56,13 @@ pet_db:( AttackRate: attack rate (int, defaults to 0) DefendRate: Defence attack (int, defaults to 0) ChangeTargetRate: change target (int, defaults to 0) + Evolve: { + EggID: { (string, Evolved Pet EggID) + Name: Amount (items required to perform evolution) + ... + } + } + AutoFeed: true/false (boolean, defaults to false) PetScript: <" Pet Script (can also be multi-line) "> EquipScript: <" Equip Script (can also be multi-line) "> }, diff --git a/db/re/item_db.conf b/db/re/item_db.conf index bc3470fd9..3974a911e 100644 --- a/db/re/item_db.conf +++ b/db/re/item_db.conf @@ -83540,6 +83540,209 @@ item_db: ( Type: "IT_PETEGG" Buy: 20 }, +{ + Id: 9069 + AegisName: "Mastering_Egg" + Name: "Mastering Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9070 + AegisName: "Savage_Egg" + Name: "Savage Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9071 + AegisName: "Grand_Peco_Peco_Egg" + Name: "Grand Peco Peco Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9087 + AegisName: "High_Orc_Egg" + Name: "High Orc Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9088 + AegisName: "Angeling_Egg" + Name: "Angeling Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9089 + AegisName: "Am_Mut_Egg" + Name: "Am Mut Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9090 + AegisName: "Little_Isis_Egg" + Name: "Little Isis Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9091 + AegisName: "Choco_Egg" + Name: "Choco Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9092 + AegisName: "Eggring_Egg" + Name: "Eggring Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9093 + AegisName: "Hyegun_Egg" + Name: "Hyegun Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9094 + AegisName: "Leaf_Lunatic_Egg" + Name: "Leaf Lunatic Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9095 + AegisName: "Nine_Tails_Egg" + Name: "Nine Tails Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9096 + AegisName: "Cat_o_Nine_Tails_Egg" + Name: "Cat o' Nine Tails Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9097 + AegisName: "Diabolic_Egg_" + Name: "Diabolic Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9098 + AegisName: "Earth_Deleter_Egg" + Name: "Earth Deleter Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9099 + AegisName: "Teddy_Bear_Egg" + Name: "Teddy Bear Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9100 + AegisName: "Gremlin_Egg" + Name: "Gremlin Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9101 + AegisName: "Scatelon_Egg" + Name: "Scatleton Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9102 + AegisName: "Mummy_Egg" + Name: "Mummy Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9103 + AegisName: "Willow_Egg" + Name: "Willow Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9104 + AegisName: "Roween_Egg" + Name: "Roween Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9105 + AegisName: "Hodremlin_Egg" + Name: "Hodremlin Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9106 + AegisName: "Metaller_Egg" + Name: "Metaller Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9107 + AegisName: "Ancient_Mummy_Egg" + Name: "Ancient Mummy Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9108 + AegisName: "Abandoned_Teddy_Bear_Egg" + Name: "Abandoned Teddy Bear Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9109 + AegisName: "Sweet_Drops_Egg" + Name: "Sweet Drops Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9111 + AegisName: "Phreeoni_Egg" + Name: "Phreeoni Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9112 + AegisName: "Moonlight_Flower_Egg" + Name: "Moonlight Flower Egg" + Type: "IT_PETEGG" + Buy: 20 +}, +{ + Id: 9113 + AegisName: "Skelion_Egg" + Name: "Skelion Egg" + Type: "IT_PETEGG" + Buy: 20 +}, //== Pet Accessories ======================================= { diff --git a/db/re/pet_db.conf b/db/re/pet_db.conf index 6d6083e59..a28da61ff 100644 --- a/db/re/pet_db.conf +++ b/db/re/pet_db.conf @@ -56,6 +56,13 @@ pet_db:( AttackRate: attack rate (int, defaults to 0) DefendRate: Defence attack (int, defaults to 0) ChangeTargetRate: change target (int, defaults to 0) + Evolve: { + EggID: { (string, Evolved Pet EggID) + Name: Amount (items required to perform evolution) + ... + } + } + AutoFeed: true/false (boolean, defaults to false) PetScript: <" Pet Script (can also be multi-line) "> EquipScript: <" Equip Script (can also be multi-line) "> }, @@ -87,6 +94,12 @@ pet_db:( bonus(bLuk, 2); bonus(bCritical, 1); "> + Evolve: { + Mastering_Egg: { + Leaf_Of_Yggdrasil: 10 + Unripe_Apple: 3 + } + } }, { Id: 1011 @@ -170,6 +183,15 @@ pet_db:( bonus(bMaxHP, 150); bonus(bMaxSP, -10); "> + Evolve: { + Grand_Peco_Peco_Egg: { + Pet_Food: 10 + Fatty_Chubby_Earthworm: 3 + Peco_Wing_Feather: 300 + Pecopeco_Card: 1 + Fruit_Of_Mastela: 10 + } + } }, { Id: 1023 @@ -198,6 +220,15 @@ pet_db:( bonus(bAtk, 10); bonus(bDef, -3); "> + Evolve: { + High_Orc_Egg: { + Horror_Of_Tribe: 3 + Orcish_Sword: 1 + Orcish_Voucher: 500 + Cigar: 1 + Orc_Warrior_Card: 1 + } + } }, { Id: 1026 @@ -252,6 +283,14 @@ pet_db:( bonus(bMatkRate, -1); bonus(bAtkRate, 1); "> + Evolve: { + Little_Isis_Egg: { + Armlet_Of_Obedience: 3 + Queens_Hair_Ornament: 1 + Shining_Scales: 300 + Crystal_Jewel__: 6 + } + } }, { Id: 1031 @@ -391,6 +430,14 @@ pet_db:( bonus(bHPrecovRate, 5); bonus(bMaxHP, 25); "> + Evolve: { + Metaller_Egg: { + Singing_Plant: 3 + Grasshoppers_Leg: 777 + Yellow_Herb: 200 + Metaller_Card: 1 + } + } }, { Id: 1056 @@ -447,6 +494,14 @@ pet_db:( bonus(bCritical, 3); bonus(bLuk, -1); "> + Evolve: { + Choco_Egg: { + Tropical_Banana: 3 + Monkey_Doll: 2 + Cacao: 300 + Yoyo_Card: 1 + } + } }, { Id: 1063 @@ -474,6 +529,14 @@ pet_db:( bonus(bCritical, 2); bonus(bAtk, 2); "> + Evolve: { + Leaf_Lunatic_Egg: { + Great_Leaf: 100 + Clover: 250 + Four_Leaf_Clover: 30 + Leaf_Lunatic_Card: 1 + } + } }, { Id: 1077 @@ -585,6 +648,14 @@ pet_db:( bonus(bMaxHPrate, -3); bonus(bMaxSPrate, -3); "> + Evolve: { + Diabolic_Egg_: { + Contracts_In_Shadow: 3 + Petite_DiablOfs_Wing: 250 + Sacred_Marks: 30 + Deviruchi_Card: 1 + } + } }, { Id: 1110 @@ -612,6 +683,14 @@ pet_db:( bonus(bMatkRate, 1); bonus(bAtkRate, -1); "> + Evolve: { + Am_Mut_Egg: { + Old_Broom: 3 + Violet_Dyestuffs: 3 + Dokkaebi_Horn: 300 + Gold: 3 + } + } }, { Id: 1113 @@ -640,6 +719,22 @@ pet_db:( bonus(bHit, 3); bonus(bAtk, 3); "> + Evolve: { + Eggring_Egg: { + Piece_Of_Egg_Shell: 20 + Old_Frying_Pan: 10 + Apple_Juice: 3 + Eggring_Card: 1 + } +/* + Sweet_Drops_Egg: { + 25290: 500 + Candy: 50 + Candy_Striper: 50 + Drops_Card: 1 + } +*/ + } }, { Id: 1155 @@ -668,6 +763,14 @@ pet_db:( bonus(bMdef, -2); bonus(bAspdRate, 1); "> + Evolve: { + Earth_Deleter_Egg: { + Shining_Stone: 3 + Petti_Tail: 100 + Aloebera: 150 + Deleter_Card: 1 + } + } }, { Id: 1167 @@ -695,6 +798,14 @@ pet_db:( bonus(bVit, 1); bonus(bMaxHP, 50); "> + Evolve: { + Savage_Egg: { + Pet_Food: 10 + Sweet_Milk: 3 + Meat: 100 + Feather: 50 + } + } }, { Id: 1170 @@ -750,6 +861,14 @@ pet_db:( bonus(bVit, 1); bonus2(bResEff, Eff_Stun, 100); "> + Evolve: { + Hyegun_Egg: { + Hyegun_Hat: 1 + Munak_Doll: 100 + Old_Portrait: 50 + Hyegun_Card: 1 + } + } }, { Id: 1200 @@ -1646,4 +1765,262 @@ pet_db:( bonus(bCritical, 1); "> }, +// New Pets [Need Info] +{ + Id: 1090 + SpriteName: "MASTERING" + Name: "Mastering" + EggItem: "Mastering_Egg" + AutoFeed: true + Evolve: { + Angeling_Egg: { + Yellow_Potion: 20 + Spirit_Chain: 1 + White_Herb: 50 + Jellopy: 200 + } + } +}, +{ + Id: 1096 + SpriteName: "ANGELING" + Name: "Angeling" + EggItem: "Angeling_Egg" + AutoFeed: true +}, +{ + Id: 1301 + SpriteName: "AM_MUT" + Name: "Am Mut" + EggItem: "Am_Mut_Egg" + AutoFeed: true +}, +/* +{ + Id: 3636 + SpriteName: "LITTLE_ISIS" + Name: "Little Isis" + EggItem: "Little_Isis_Egg" + AutoFeed: true +}, +*/ +{ + Id: 1214 + SpriteName: "CHOCO" + Name: "Choco" + EggItem: "Choco_Egg" + AutoFeed: true +}, +/* +{ + Id: 3495 + SpriteName: "DR_EGGRING" + Name: "Eggring" + EggItem: "Eggring_Egg" + AutoFeed: true +}, +*/ +{ + Id: 1512 + SpriteName: "HYEGUN" + Name: "Hyegun" + EggItem: "Hyegun_Egg" + AutoFeed: true +}, +/* +{ + Id: 3496 + SpriteName: "DR_LUNATIC" + Name: "Leaf Lunatic" + EggItem: "Leaf_Lunatic_Egg" + AutoFeed: true +}, +*/ +{ + Id: 1180 + SpriteName: "NINE_TAIL" + Name: "Nine Tails" + EggItem: "Nine_Tails_Egg" + AutoFeed: true + Evolve: { +/* + Cat_o_Nine_Tails_Egg: { + 23187: 3 + Fox_Tail: 999 + Punisher: 1 + Nine_Tail_Card: 1 + } +*/ + } +}, +{ + Id: 1307 + SpriteName: "CAT_O_NINE_TAIL" + Name: "Cat o' Nine Tails" + EggItem: "Cat_o_Nine_Tails_Egg" + AutoFeed: true + Evolve: { +/* + Moonlight_Flower_Egg: { + 25375: 30 + Nine_Tail_Card: 10 + Sohee_Card: 10 + Munak_Card: 10 + } +*/ + } +}, +/* +{ + Id: 3669 + SpriteName: "DIABOLIC2" + Name: "Diabolic" + EggItem: "Diabolic_Egg_" + AutoFeed: true +}, +*/ +/* +{ + Id: 3670 + SpriteName: "DELETER_2" + Name: "Earth Deleter" + EggItem: "Earth_Deleter_Egg" + AutoFeed: true +}, +*/ +{ + Id: 1622 + SpriteName: "TEDDY_BEAR" + Name: "Teddy Bear" + EggItem: "Teddy_Bear_Egg" + AutoFeed: true + Evolve: { +/* + Abandoned_Teddy_Bear_Egg: { + 23189: 3 + Cursed_Seal: 300 + Cardinal_Jewel_: 50 + Teddy_Bear_Card: 1 + } +*/ + } +}, +{ + Id: 1632 + SpriteName: "GREMLIN" + Name: "Gremlin" + EggItem: "Gremlin_Egg" + AutoFeed: true + Evolve: { +/* + Hodremlin_Egg: { + 23188: 3 + Damp_Darkness: 50 + Will_Of_Darkness: 200 + Hodremlin_Card: 1 + } +*/ + } +}, +/* +{ + Id: 3731 + SpriteName: "SCATLETON" + Name: "Scatleton Crate" + EggItem: "Scatleton_Crate" + AutoFeed: true +}, +*/ +{ + Id: 1041 + SpriteName: "MUMMY" + Name: "Mummy" + EggItem: "Mummy_Egg" + AutoFeed: true + Evolve: { +/* + Ancient_Mummy_Egg: { + 23256: 3 + Rune_Of_Darkness: 200 + Gold: 30 + Ancient_Mummy_Card: 1 + } +*/ + } +}, +{ + Id: 1010 + SpriteName: "WILOW" + Name: "Willow" + EggItem: "Willow_Egg" + AutoFeed: true +}, +{ + Id: 1782 + SpriteName: "ROWEEN" + Name: "Roween" + EggItem: "Roween_Egg" + AutoFeed: true +}, +{ + Id: 1773 + SpriteName: "HODREMLIN" + Name: "Hodremlin" + EggItem: "Hodremlin_Egg" + AutoFeed: true +}, +{ + Id: 1058 + SpriteName: "METALLER" + Name: "Metaller" + EggItem: "Metaller_Egg" + AutoFeed: true +}, +{ + Id: 1297 + SpriteName: "ANCIENT_MUMMY" + Name: "Ancient Mummy" + EggItem: "Ancient_Mummy_Egg" + AutoFeed: true +}, +/*{ + Id: 2995 + SpriteName: "XM_TEDDY_BEAR" + Name: "Abandoned Teddy Bear" + EggItem: "Abandoned_Teddy_Bear_Egg" + AutoFeed: true +}, +*/ +/* UNKNOWN MONSTER +{ + Id: 0 + SpriteName: "X" + Name: "Sweet Drops" + EggItem: "Sweet_Drops_Egg" + AutoFeed: true +}, +*/ +{ + Id: 1159 + SpriteName: "PHREEONI" + Name: "Phreeoni" + EggItem: "Phreeoni_Egg" + AutoFeed: true +}, +{ + Id: 1150 + SpriteName: "MOONLIGHT" + Name: "Moonlight Flower" + EggItem: "Moonlight_Flower_Egg" + AutoFeed: true +}, +/* +{ + Id: 3971 + SpriteName: "SKELION" + Name: "Skelion" + EggItem: "Skelion_Egg" + AutoFeed: true +}, +*/ ) diff --git a/doc/constants.md b/doc/constants.md index 654e5eb64..565048840 100644 --- a/doc/constants.md +++ b/doc/constants.md @@ -13318,6 +13318,35 @@ - `Brownie_Egg`: 9060 - `Marin_Egg`: 9061 - `Novice_Poring_Egg`: 9062 +- `Mastering_Egg`: 9069 +- `Savage_Egg`: 9070 +- `Grand_Peco_Peco_Egg`: 9071 +- `High_Orc_Egg`: 9087 +- `Angeling_Egg`: 9088 +- `Am_Mut_Egg`: 9089 +- `Little_Isis_Egg`: 9090 +- `Choco_Egg`: 9091 +- `Eggring_Egg`: 9092 +- `Hyegun_Egg`: 9093 +- `Leaf_Lunatic_Egg`: 9094 +- `Nine_Tails_Egg`: 9095 +- `Cat_o_Nine_Tails_Egg`: 9096 +- `Diabolic_Egg_`: 9097 +- `Earth_Deleter_Egg`: 9098 +- `Teddy_Bear_Egg`: 9099 +- `Gremlin_Egg`: 9100 +- `Scatelon_Egg`: 9101 +- `Mummy_Egg`: 9102 +- `Willow_Egg`: 9103 +- `Roween_Egg`: 9104 +- `Hodremlin_Egg`: 9105 +- `Metaller_Egg`: 9106 +- `Ancient_Mummy_Egg`: 9107 +- `Abandoned_Teddy_Bear_Egg`: 9108 +- `Sweet_Drops_Egg`: 9109 +- `Phreeoni_Egg`: 9111 +- `Moonlight_Flower_Egg`: 9112 +- `Skelion_Egg`: 9113 - `Skull_Helm`: 10001 - `Monster_Oxygen_Mask`: 10002 - `Transparent_Headgear`: 10003 diff --git a/doc/sample/npc_rodex.txt b/doc/sample/npc_rodex.txt index a808a1aa9..0975e609c 100644 --- a/doc/sample/npc_rodex.txt +++ b/doc/sample/npc_rodex.txt @@ -20,12 +20,12 @@ prontera,150,150,4 script Rodex Mail 1_M_01,{ // Sends a messsage to attached player "Account Box" from "Rodex Test", with title "Rodex Test3", // with message "Hello World, How are You?", 1000 Zenies and 5 Red Potions attached rodex_sendmail_acc( - getcharid(CHAR_ID_CHAR), "Rodex Test", "Rodex Test3", "Hello World, How are You?", + getcharid(CHAR_ID_ACCOUNT), "Rodex Test", "Rodex Test3", "Hello World, How are You?", 1000, Red_Potion, 5 ); - // Sends a messsage to attached player "Account Box" from "Rodex Test", with title "Rodex Test6", + // Sends a messsage to attached player from "Rodex Test", with title "Rodex Test6", // with message "Hello World, How are You?", 1000 Zenies, 5 Red Potions and // 1 +10 Knife[3] with 3 Poring Cards (Broken) rodex_sendmail2( diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 36c4da35a..a00756056 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -2473,6 +2473,7 @@ arrays: --------------------------------------- *readparam(<parameter number>{, "<player name>"}) +*readparam(<parameter number>{, <account id>}) This function will return the basic stats of an invoking character, referred to by the parameter number. Instead of a number, you can use a @@ -2511,6 +2512,21 @@ Example 3: --------------------------------------- +*setparam(<parameter number>, <value>{, "<player name>"}) +*setparam(<parameter number>, <value>{, <account id>}) + +Sets a parameter on the given player. See readparam() for more info about +parameters. Keep in mind that not all read-able parameters are also set-able. + +Parameters that can be modified include: + +StatusPoint, BaseLevel, SkillPoint, Zeny, Sex, Weight, MaxWeight, JobLevel, +BaseExp, JobExp, Hp, MaxHp, Sp, MaxSp, Karma, Manner, Fame, bVit, bDex, bAgi, +bStr, bInt, bLuk + + +--------------------------------------- + *getcharid(<type>{, "<character name>"}) This function will return a unique ID number of the invoking character, @@ -2756,7 +2772,9 @@ save points. Available information types are: --------------------------------------- -*getcharip({"<character name>"|<account id>|<char id>}) +*getcharip({"<character name>"}) +*getcharip({<account id>}) +*getcharip({<character id>}) This function will return the IP address of the invoking character, or, if a player is specified, of that character. A blank string is returned if no @@ -3413,7 +3431,8 @@ behave specially when talked to by GMs. --------------------------------------- -*setgroupid(<new group id>{, "<character name>"|<account id>}) +*setgroupid(<new group id>{, "<character name>"}) +*setgroupid(<new group id>{, <account id>}) This function will temporary adjust the id of player group the account to which the player specified if the new group id is available. @@ -4372,7 +4391,7 @@ offline in the mean time, attachrid() returns false, otherwise true. --------------------------------------- -*rid2name(<rid>) +*rid2name(<account id>) Converts rid to name. Note: The player/monster/NPC must be online/enabled. Good for PCKillEvent where you can convert 'killedrid' to the name of the @@ -4616,13 +4635,12 @@ effects. --------------------------------------- -*recovery() -*recovery(<account id>) +*recovery({<account id>}) *recovery("<map name>"{, <x1>, <y1>, <x2>, <y2>}) -In its first form, this command will revive and restore full HP and SP to all -characters currently connected to the server. In its second form, it will only -affect the target player. In its third form it will affect a whole map or area. +This command will revive and restore full HP and SP to all characters currently +connected to the server. If an account id is supplied, it will instead only +affect this character. If a map is supplied it will affect a whole map or area. --------------------------------------- @@ -5138,8 +5156,10 @@ Example: close(); --------------------------------------- -*getnameditem(<item id>, <character name|character ID>) -*getnameditem("<item name>", <character name|character ID>) +*getnameditem(<item id>, "<character name>") +*getnameditem(<item id>, <character ID>) +*getnameditem("<item name>", "<character name>") +*getnameditem("<item name>", <character ID>) Create an item signed with the given character's name. @@ -5303,7 +5323,7 @@ Check getitem2() to understand the arguments of the function. --------------------------------------- -*groupranditem(<item_id/constant>) +*groupranditem(<item id>) Returns the item_id of a random item picked from the item container specified. There are different item containers and they are specified in 'db/(pre-)re/item_group.conf'. @@ -5313,7 +5333,7 @@ Example: --------------------------------------- -*getrandgroupitem(<item_id/constant>, <quantity>) +*getrandgroupitem(<item id>, <quantity>) Similar to the above example, this command allows players to obtain the specified quantity of a random item from the container. The different containers @@ -6195,7 +6215,7 @@ Examples: @ /!\ This command is deprecated @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -Prevents the player from moving when the option != 0, and 0 enables the +Prevents the player from moving when the option != 0, and 0 enables the player to move again. The player has to be the account ID of a character, and will run for the attached player if zero is supplied. @@ -6823,12 +6843,12 @@ valid <type> for gettimer() are: --------------------------------------- -*initnpctimer({ "<NPC name>" {, <Attach Flag>} } | - { "<NPC name>" | <Attach Flag> }) -*stopnpctimer({ "<NPC name>" {, <Detach Flag>} } | - { "<NPC name>" | <Detach Flag> }) -*startnpctimer({ "<NPC name>" {, <Attach Flag>} } | - { "<NPC name>" | <Attach Flag> }) +*initnpctimer({"<NPC name>"{, <Attach Flag>}}) +*initnpctimer({<Attach Flag>}) +*stopnpctimer({"<NPC name>"{, <Detach Flag>}}) +*stopnpctimer({<Detach Flag>}}) +*startnpctimer({"<NPC name>"{, <Attach Flag>}}) +*startnpctimer({<Attach Flag>}) *setnpctimer(<tick>{, "<NPC name>"}) *getnpctimer(<type of information>{, "<NPC name>"}) *attachnpctimer({"<character name>"}) @@ -9369,19 +9389,19 @@ Add quest of the <ID2> to the the quest log, and the state is "active". --------------------------------------- -*questprogress(<ID>{, PLAYTIME|HUNTING}) +*questprogress(<ID>{, <type>}) If no additional argument supplied, return the state of the quest: 0 = Quest not started (not in quest log) 1 = Quest has been given 2 = Quest completed -If parameter PLAYTIME is supplied: +If <type> PLAYTIME is supplied: 0 = Quest not started (not in quest log) 1 = The time limit has not yet been reached 2 = The time limit has been reached -If parameter HUNTING is supplied: +If <type> HUNTING is supplied: 0 = Quest not started (not in quest log) 1 = Player hasn't killed all of the target monsters 2 = Player has killed all of the target monsters @@ -10023,7 +10043,7 @@ returns 1 on success, 0 on failure. //===================================== --------------------------------------- -*join_clan(<ClanID>{,<RID>}) +*join_clan(<ClanID>{, <account id>}) Joins a player into the given clan. If no RID is given, will run with the current attached player. @@ -10032,7 +10052,7 @@ returns true on success, false on failure. --------------------------------------- -*clan_leave({<RID>}) +*clan_leave({<account id>}) Removes a player from its clan. If no RID is given, will run with the current attached player. @@ -10068,4 +10088,4 @@ the available flags are: Opens the styling shop on client ----------------------------------------
\ No newline at end of file +--------------------------------------- diff --git a/npc/dev/test.txt b/npc/dev/test.txt index a6f89f857..036a94916 100644 --- a/npc/dev/test.txt +++ b/npc/dev/test.txt @@ -150,6 +150,20 @@ function script HerculesSelfTestHelper { callsub(OnCheck, "Prefix decrement --", .@y); callsub(OnCheck, "Prefix decrement --", .@x); + // Increment and decrement operators after a condition + .@x = 0; + if (1) .@x++; + callsub(OnCheck, "Suffix increment ++ after (condition)", .@x); + .@x = 2; + if (1) .@x--; + callsub(OnCheck, "Suffix decrement -- after (condition)", .@x); + .@x = 0; + if (1) ++.@x; + callsub(OnCheck, "Prefix increment ++ after (condition)", .@x); + .@x = 2; + if (1) --.@x; + callsub(OnCheck, "Prefix decrement -- after (condition)", .@x); + // Order of [] and --/++ .@a[1] = 0; .@a[1]++; // .@a[1] = .@a[1] + 1; diff --git a/npc/instances/EndlessTower.txt b/npc/instances/EndlessTower.txt index dc60ce766..2964f7e2a 100644 --- a/npc/instances/EndlessTower.txt +++ b/npc/instances/EndlessTower.txt @@ -220,23 +220,21 @@ e_tower,81,105,0 script Tower Protection Stone 2_MONEMUS,{ switch (select(.@str$, "Enter the Dungeon", "Return to Alberta", "Cancel")) { case 1: .@instance = instance_create(.@md_name$, .@party_id); - if (.@instance < 0) { - mesf("Party Name: %s", .@p_name$); - mesf("Party Leader: %s", strcharinfo(PC_NAME)); - mesf("^0000ff%s ^000000- Reservation Failed!", .@md_name$); - close(); + if (.@instance >= 0) { + for (.@i = 1; .@i <= 6; ++.@i) { + if (instance_attachmap(.@i + "@tower", .@instance) == "") { + mesf("Party Name: %s", .@p_name$); + mesf("Party Leader: %s", strcharinfo(PC_NAME)); + mesf("^0000ff%s ^000000- Reservation Failed!", .@md_name$); + instance_destroy(.@instance); + close(); + } + } + instance_set_timeout(14400, 300, .@instance); + instance_init(.@instance); } mesf("^0000ff%s^000000 - Try to reserve", .@md_name$); mes("After making a reservation, you have to talk to NPC behind and select the menu 'Enter the Dungeon' to enter the dungeon."); - for (.@i = 1; .@i <= 6; ++.@i) { - if (instance_attachmap(.@i + "@tower", .@instance) == "") { - mesf("^0000ff%s ^000000- Reservation Failed!", .@md_name$); - instance_destroy(.@instance); - close(); - } - } - instance_set_timeout(14400, 300, .@instance); - instance_init(.@instance); close(); case 2: callsub(L_Enter, 0, 1, .@md_name$, .@p_name$); diff --git a/npc/instances/NydhoggsNest.txt b/npc/instances/NydhoggsNest.txt index 46ffdaef3..d39d90cd3 100644 --- a/npc/instances/NydhoggsNest.txt +++ b/npc/instances/NydhoggsNest.txt @@ -128,21 +128,18 @@ nyd_dun02,100,201,3 script Yggdrasil Gatekeeper HIDDEN_NPC,8,8,{ switch (select("Please allow me to enter.", "I want to go in.", "I want to leave.")) { case 1: .@instance = instance_create(.@md_name$, .@party_id); - if (.@instance < 0) { - mes("[Yggdrasil Gatekeeper]"); - mes("The Guardian seems to wish to be alone. I will go in and check, please wait out here."); - close(); + if (.@instance >= 0) { + for (.@i = 1; .@i <= 2; ++.@i) { + if (instance_attachmap(.@i + "@nyd", .@instance) == "") { + mes("[Yggdrasil Gatekeeper]"); + mes("The Guardian seems to wish to be alone. I will go in and check, please wait out here."); + instance_destroy(.@instance); + close(); + } + } + instance_set_timeout(144000, 300, .@instance); + instance_init(.@instance); } - for (.@i = 1; .@i <= 2; ++.@i) { - if (instance_attachmap(.@i + "@nyd", .@instance) == "") - break; - } - if (.@i < 2) { - instance_destroy(.@instance); - close(); - } - instance_set_timeout(144000, 300, .@instance); - instance_init(.@instance); mes("[Yggdrasil Gatekeeper]"); mes("I've recorded your request, are you ready to go inside?"); next(); diff --git a/npc/instances/OrcsMemory.txt b/npc/instances/OrcsMemory.txt index 1aaf2fd42..383786696 100644 --- a/npc/instances/OrcsMemory.txt +++ b/npc/instances/OrcsMemory.txt @@ -67,23 +67,20 @@ gef_fild10,242,202,0 script Dimensional Gorge Piece 2_MONEMUS,{ switch (select(.@str$, "Enter the Dungeon", "Cancel")) { case 1: .@instance = instance_create(.@md_name$, .@party_id); - if (.@instance < 0) { - mesf("Party Name: %s", .@p_name$); - mesf("Party Leader: %s", strcharinfo(PC_NAME)); - mesf("^0000ff%s ^000000 - Reservation Failed.", .@md_name$); - close(); + if (.@instance >= 0) { + for (.@i = 1; .@i <= 2; ++.@i) { + if (instance_attachmap(.@i + "@orcs", .@instance) == "") { + mesf("Party Name: %s", .@p_name$); + mesf("Party Leader: %s", strcharinfo(PC_NAME)); + mesf("^0000ff%s ^000000 - Reservation Failed.", .@md_name$); + instance_destroy(.@instance); + close(); + } + } + instance_set_timeout(7200, 300, .@instance); + instance_init(.@instance); } mesf("^0000ff%s^000000- Attempting to book an entrance", .@md_name$); - for (.@i = 1; .@i <= 2; ++.@i) { - if (instance_attachmap(.@i + "@orcs", .@instance) == "") - break; - } - if (.@i < 2) { - instance_destroy(.@instance); - close(); - } - instance_set_timeout(7200, 300, .@instance); - instance_init(.@instance); mesf("After making a reservation, you have to select 'Enter the Dungeon' from the menu if you wish to enter the %s.", .@md_name$); close(); case 2: diff --git a/npc/instances/SealedShrine.txt b/npc/instances/SealedShrine.txt index 3bc3d951a..91771c31c 100644 --- a/npc/instances/SealedShrine.txt +++ b/npc/instances/SealedShrine.txt @@ -118,37 +118,33 @@ monk_test,309,146,3 script Friar Patrick#edq 4_M_OLDFRIAR,{ mesf("Party name is %s...", getpartyname(.@party_id)); mesf("Name of the leader is %s...", strcharinfo(PC_NAME)); .@instance = instance_create(_("Sealed Catacomb"), .@party_id); - if (.@instance < 0) { - mes("Umm... But it seems that there is a problem here... I'll check quickly. Please wait."); - } else { + if (.@instance >= 0) { for (.@i = 1; .@i <= 2; .@i++) { if (instance_attachmap(.@i + "@cata", .@instance) == "") { - mesf("Failed to attach %d@cata as a map!", .@i); + mes("Umm... But it seems that there is a problem here... I'll check quickly. Please wait."); instance_destroy(.@instance); close(); } } - instance_set_timeout(7200, 300, .@instance); instance_init(.@instance); - - mes("Okay... I'll adjust the shrine's seal so that you and your group can enter."); - next(); - mes("[Friar Patrick]"); - mes("You will see a sign when the seal has broken. Please wait until the sign appears..."); - next(); - mes("[Friar Patrick]"); - mes("When you see the sign, put your hands on the gravestone... Then you can move inside."); - next(); - mes("[Friar Patrick]"); - mes("One thing that you should remember is... Anyone who enters this shrine will be cursed by Baphomet and cannot enter or leave while they are cursed."); - next(); - mes("[Friar Patrick]"); - mes("And one more thing... In this cursed area, some skills, which are protected by outer physical power are prohibited by the effect of the seal."); - next(); - mes("[Friar Patrick]"); - mes("For example, the skills like ^0000FFSafety Wall and Assumptio^000000... So you'd better prepare before entering the shrine."); } + mes("Okay... I'll adjust the shrine's seal so that you and your group can enter."); + next(); + mes("[Friar Patrick]"); + mes("You will see a sign when the seal has broken. Please wait until the sign appears..."); + next(); + mes("[Friar Patrick]"); + mes("When you see the sign, put your hands on the gravestone... Then you can move inside."); + next(); + mes("[Friar Patrick]"); + mes("One thing that you should remember is... Anyone who enters this shrine will be cursed by Baphomet and cannot enter or leave while they are cursed."); + next(); + mes("[Friar Patrick]"); + mes("And one more thing... In this cursed area, some skills, which are protected by outer physical power are prohibited by the effect of the seal."); + next(); + mes("[Friar Patrick]"); + mes("For example, the skills like ^0000FFSafety Wall and Assumptio^000000... So you'd better prepare before entering the shrine."); } else { mes("[Friar Patrick]"); mes("Umm... I recognize your courage, but... I can't permit anyone to enter this place. I can only permit the leader of a party to enter first."); diff --git a/npc/re/instances/BakonawaLake.txt b/npc/re/instances/BakonawaLake.txt index 65622171b..5226db6cc 100644 --- a/npc/re/instances/BakonawaLake.txt +++ b/npc/re/instances/BakonawaLake.txt @@ -82,18 +82,16 @@ ma_scene01,174,179,4 script Taho 4_M_DEWZATIMAN,{ switch (.@i) { case 1: .@instance = instance_create(.@md_name$, .@party_id); - if (.@instance < 0) { - mes("[Taho]"); - mes("Oh, the rope got dropped. I have to make a new one."); - close(); - } - if (instance_attachmap("1@ma_b", .@instance) == "") { - mesf("^0000ff%s^000000 - Reservation Failed!", .@md_name$); - instance_destroy(.@instance); - close(); + if (.@instance >= 0) { + if (instance_attachmap("1@ma_b", .@instance) == "") { + mes("[Taho]"); + mes("Oh, the rope got dropped. I have to make a new one."); + instance_destroy(.@instance); + close(); + } + instance_set_timeout(7200, 300, .@instance); + instance_init(.@instance); } - instance_set_timeout(7200, 300, .@instance); - instance_init(.@instance); mes("[Taho]"); mes("Now I'm weaving, so you can go down when I'm done."); close(); diff --git a/npc/re/instances/BangungotHospital.txt b/npc/re/instances/BangungotHospital.txt index 9e8e836c4..6972322e1 100644 --- a/npc/re/instances/BangungotHospital.txt +++ b/npc/re/instances/BangungotHospital.txt @@ -274,21 +274,19 @@ L_Enter: switch(select(((getarg(0))?"Prepare to enter the second floor.":""), "Enter the second floor.", "Do not enter.")) { case 1: .@instance = instance_create(.@md_name$,getcharid(CHAR_ID_PARTY)); - if (.@instance < 0) { - mes "[Nurse Maenne]"; - mes "A critical situation has happened."; - mes "You can't go up to the 2nd floor."; - close2; - cutin "",255; - end; - } - if (instance_attachmap("1@ma_h",.@instance) == "") { - mes "^0000ff"+.@md_name$+"^000000 - Reservation Failed!"; - instance_destroy(.@instance); - close; + if (.@instance >= 0) { + if (instance_attachmap("1@ma_h", .@instance) == "") { + mes("[Nurse Maenne]"); + mes("A critical situation has happened."); + mes("You can't go up to the 2nd floor."); + instance_destroy(.@instance); + close2(); + cutin("", 255); + end; + } + instance_set_timeout(3600, 300, .@instance); + instance_init(.@instance); } - instance_set_timeout 3600,300,.@instance; - instance_init(.@instance); mes "[Nurse Maenne]"; mes "We are preparing to go up"; mes "to the second floor."; diff --git a/npc/re/instances/BuwayaCave.txt b/npc/re/instances/BuwayaCave.txt index 393ac5d9e..1d3eddc6a 100644 --- a/npc/re/instances/BuwayaCave.txt +++ b/npc/re/instances/BuwayaCave.txt @@ -93,22 +93,19 @@ ma_fild02,312,317,5 script Guard#buwaya_cave 4_MAL_SOLDIER,{ // fall through } .@instance = instance_create(.@md_name$, .@party_id); - if (.@instance < 0) { - mes("[Guard]"); - mesf("Party name is... %s.", getpartyname(.@party_id)); - mesf("Party leader is... %s", strcharinfo(PC_NAME)); - mesf("^0000ff%s^000000 cannot be opened now.", .@md_name$); - mes("Please try a moment later."); - close(); + if (.@instance >= 0) { + if (instance_attachmap("1@ma_c", .@instance) == "") { + mes("[Guard]"); + mesf("Party name is... %s.", getpartyname(.@party_id)); + mesf("Party leader is... %s", strcharinfo(PC_NAME)); + mesf("^0000ff%s^000000 cannot be opened now.", .@md_name$); + mes("Please try a moment later."); + instance_destroy(.@instance); + close(); + } + instance_set_timeout(3600, 300, .@instance); + instance_init(.@instance); } - if (instance_attachmap("1@ma_c", .@instance) == "") { - mesf("^0000ff%s^000000 - Reservation Failed!", .@md_name$); - instance_destroy(.@instance); - close(); - } - instance_set_timeout(3600, 300, .@instance); - instance_init(.@instance); - mes("[Guard]"); mesf("I will open up the tunnel to ^0000ff%s^000000.", .@md_name$); mes("I wish you good luck."); diff --git a/npc/re/instances/EclageInterior.txt b/npc/re/instances/EclageInterior.txt index 6b2808e05..2b2117b93 100644 --- a/npc/re/instances/EclageInterior.txt +++ b/npc/re/instances/EclageInterior.txt @@ -55,20 +55,18 @@ ecl_hub01,132,12,3 script Chief of Staff#tl01::EclInstance 4_F_FAIRY,{ switch (select("Enter it.", "Forget it.")) { case 1: .@instance = instance_create(.@md_name$, .@party_id); - if (.@instance < 0) { - mes("[Shenime]"); - mes("There are some soldiers dispatched by Mayor not too long ago."); - mes("I should sure hope that you aren't the disturbance they're looking for, right?"); - close(); - } - if (instance_attachmap("1@ecl", .@instance) == "") { - mesf("^0000ff%s^000000 - Reservation Failed!", .@md_name$); - instance_destroy(.@instance); - close(); + if (.@instance >= 0) { + if (instance_attachmap("1@ecl", .@instance) == "") { + mes("[Shenime]"); + mes("There are some soldiers dispatched by Mayor not too long ago."); + mes("I should sure hope that you aren't the disturbance they're looking for, right?"); + instance_destroy(.@instance); + close(); + } + ecl_interior_time = gettimetick(2) + 20 * 60; + instance_set_timeout(1200, 1200, .@instance); + instance_init(.@instance); } - ecl_interior_time = gettimetick(2) + 20 * 60; - instance_set_timeout(1200, 1200, .@instance); - instance_init(.@instance); mes("[Shenime]"); mes("Given the tight internal security, you should prepare yourself."); mes("Wait here for a minute."); diff --git a/npc/re/instances/HazyForest.txt b/npc/re/instances/HazyForest.txt index 291ce54db..24e03b22e 100644 --- a/npc/re/instances/HazyForest.txt +++ b/npc/re/instances/HazyForest.txt @@ -101,35 +101,34 @@ bif_fild01,158,340,5 script Laphine Soldier#mist 4_M_FAIRYSOLDIER,{ mesf("Party Name %s...", getpartyname(.@party_id)); mesf("Party Leader %s...", strcharinfo(PC_NAME)); .@instance = instance_create(.@md_name$, .@party_id); - if (.@instance < 0) { - mes("Hmm..."); - next(); - mes("[Laphine Soldier]"); - if (!.@playtime) - mes("It's dangerous in the forest."); - else - mes("The atmosphere is somewhat tense in the forest."); - mes("...Why don't you just go back today?"); - close(); - } - if (instance_attachmap("1@mist", .@instance) != "") { + if (.@instance >= 0) { + if (instance_attachmap("1@mist", .@instance) == "") { + mes("Hmm..."); + next(); + mes("[Laphine Soldier]"); + if (!.@playtime) + mes("It's dangerous in the forest."); + else + mes("The atmosphere is somewhat tense in the forest."); + mes("...Why don't you just go back today?"); + instance_destroy(.@instance); + close(); + } instance_set_timeout(7200, 300, .@instance); instance_init(.@instance); - mes("I've got it. I've written them down on the report here."); - next(); - mes("[Laphine Soldier]"); - mes("You'll get permission soon."); - mes("Now go to the log tunnel, the only way to get into the Hazy Forest."); - mes("You understand?"); - next(); - mes("[Laphine Soldier]"); - mes("We can't go against the forest,"); - mes("but maybe you humans can."); - mes("Good luck!"); - close(); - } else { - instance_destroy(.@instance); } + mes("I've got it. I've written them down on the report here."); + next(); + mes("[Laphine Soldier]"); + mes("You'll get permission soon."); + mes("Now go to the log tunnel, the only way to get into the Hazy Forest."); + mes("You understand?"); + next(); + mes("[Laphine Soldier]"); + mes("We can't go against the forest,"); + mes("but maybe you humans can."); + mes("Good luck!"); + close(); case 2: mes("[Laphine Soldier]"); mes("Well, you've made the right decision."); diff --git a/npc/re/instances/MalangdoCulvert.txt b/npc/re/instances/MalangdoCulvert.txt index 2e51f0fd5..d61509511 100644 --- a/npc/re/instances/MalangdoCulvert.txt +++ b/npc/re/instances/MalangdoCulvert.txt @@ -433,20 +433,19 @@ mal_in01,160,34,4 script Missing, the Cleaner 4_CAT_SAILOR2,{ close(); case 2: .@instance = instance_create(.@md_name$, .@party_id); - if (.@instance < 0) { - mesf("Party name: %s", getpartyname(.@party_id)); - mesf("Party leader: %s", strcharinfo(PC_NAME)); - mesf("^0000ff%s^000000 - Reservation Failed!", .@md_name$); - close(); + if (.@instance >= 0) { + for (.@i = 1; .@i <= 2; .@i++) { + if (instance_attachmap(.@i + "@pump", .@instance) == "") { + mesf("Party name: %s", getpartyname(.@party_id)); + mesf("Party leader: %s", strcharinfo(PC_NAME)); + mesf("^0000ff%s^000000 - Reservation Failed!", .@md_name$); + instance_destroy(.@instance); + close(); + } + } + instance_set_timeout(3600, 300, .@instance); + instance_init(.@instance); } - if (instance_attachmap("1@pump", .@instance) == "" || instance_attachmap("2@pump", .@instance) == "") { - mesf("^0000ff%s^000000 - Reservation Failed!", .@md_name$); - instance_destroy(.@instance); - close(); - } - instance_set_timeout(3600, 300, .@instance); - instance_init(.@instance); - mesf("^3333FF%s^000000 - Reserving", .@md_name$); mes("After making the reservation, you"); mes("have to select Enter the Culvert."); diff --git a/npc/re/instances/OldGlastHeim.txt b/npc/re/instances/OldGlastHeim.txt index c317e7495..587de45bf 100644 --- a/npc/re/instances/OldGlastHeim.txt +++ b/npc/re/instances/OldGlastHeim.txt @@ -110,19 +110,19 @@ glast_01,204,273,6 script Hugin#ghinstance 4_M_SAGE_C,{ if (getcharid(CHAR_ID_CHAR) != getpartyleader(.@party_id, 2)) end; .@instance = instance_create(.@md_name$, .@party_id); - if (.@instance < 0) { - mesf("Party Name: %s", .@p_name$); - mesf("Party Leader: %s", strcharinfo(PC_NAME)); - mesf("^0000ff%s^000000 - Reservation Failed!", .@md_name$); - close(); - } - if (instance_attachmap("1@gl_k", .@instance) == "" || instance_attachmap("2@gl_k", .@instance) == "") { - mesf("^0000FF%s^000000 - Reservation Failed!", .@md_name$); - instance_destroy(.@instance); - close(); + if (.@instance >= 0) { + for (.@i = 1; .@i <= 2; .@i++) { + if (instance_attachmap(.@i + "@gl_k", .@instance) == "") { + mesf("Party Name: %s", .@p_name$); + mesf("Party Leader: %s", strcharinfo(PC_NAME)); + mesf("^0000ff%s^000000 - Reservation Failed!", .@md_name$); + instance_destroy(.@instance); + close(); + } + } + instance_set_timeout(3600, 300, .@instance); + instance_init(.@instance); } - instance_set_timeout(3600, 300, .@instance); - instance_init(.@instance); mes("[Hugin]"); mes("The time gap was created. When you're ready, talk to me again."); close(); diff --git a/npc/re/instances/WolfchevLaboratory.txt b/npc/re/instances/WolfchevLaboratory.txt index d6c5516e5..efb32be7e 100644 --- a/npc/re/instances/WolfchevLaboratory.txt +++ b/npc/re/instances/WolfchevLaboratory.txt @@ -1859,30 +1859,29 @@ lhz_dun04,151,276,3 script Researcher#memo 4_LGTSCIENCE,{ } if (getpartyleader(getcharid(CHAR_ID_PARTY),2) == getcharid(CHAR_ID_CHAR)) { .@instance = instance_create("Worsef", getcharid(CHAR_ID_PARTY)); - if (.@instance < 0) { - mes "[Wolfchev]"; - mes "Hmm.. Lab entering system is a bit weird. Would wait for me to check the system?"; - } else { - mes "[Wolfchev]"; - mes "Please hold on.."; - next; - mes "Wolfchev starts to control certain gear."; - next; - progressbar "FF00FF", 2; - if (instance_attachmap("1@lhz", .@instance) != "") { - instance_set_timeout 14400, 300, .@instance; - instance_init(.@instance); - mes "[Wolfchev]"; - mes "Alright! I have marked lan entering system code as"; - mes "^0000ff"+ strcharinfo(PC_PARTY) +"^000000 party leader's name ^0000ff"+ strcharinfo(PC_NAME) +"^000000!!."; - next; - mes "[Wolfchev]"; - mes "Now, your party is free to pass the entrance."; - } else { + if (.@instance >= 0) { + if (instance_attachmap("1@lhz", .@instance) == "") { + mes("[Wolfchev]"); + mes("Hmm.. Lab entering system is a bit weird. Would wait for me to check the system?"); instance_destroy(.@instance); + close(); } + instance_set_timeout 14400, 300, .@instance; + instance_init(.@instance); } - close; + mes("[Wolfchev]"); + mes("Please hold on.."); + next(); + mes("Wolfchev starts to control certain gear."); + next(); + progressbar("FF00FF", 2); + mes("[Wolfchev]"); + mes("Alright! I have marked lan entering system code as"); + mesf("^0000ff%s^000000 party leader's name ^0000ff%s^000000!!.", strcharinfo(PC_PARTY), strcharinfo(PC_NAME)); + next(); + mes("[Wolfchev]"); + mes("Now, your party is free to pass the entrance."); + close(); } else { mes "[Wolfchev]"; mes "You are not the ^0000ffLeader of the party^000000, are you? Please go get the leader."; diff --git a/npc/re/instances/ghost_palace.txt b/npc/re/instances/ghost_palace.txt index e4ca12f99..3e708dc57 100644 --- a/npc/re/instances/ghost_palace.txt +++ b/npc/re/instances/ghost_palace.txt @@ -91,27 +91,24 @@ dali02,44,129,5 script Unpleasent Royal Guard 4_M_SAKRAYROYAL,{ .@instance = instance_create(_("Ghost Palace"), .@party_id); .@p_name$ = getpartyname(.@party_id); .@md_name$ = _("Ghost Palace"); - if (.@instance < 0) { - mesf("Party Name: %s", .@p_name$); - mesf("Party Leader: %s", strcharinfo(PC_NAME)); - mesf("^0000FF%s^000000 - Reservation Failed!", .@md_name$); - close(); - } - if (instance_attachmap("1@spa", .@instance) != "") { + if (.@instance >= 0) { + if (instance_attachmap("1@spa", .@instance) == "") { + mesf("Party Name: %s", .@p_name$); + mesf("Party Leader: %s", strcharinfo(PC_NAME)); + mesf("^0000FF%s^000000 - Reservation Failed!", .@md_name$); + instance_destroy(.@instance); + close(); + } instance_set_timeout(3600, 300, .@instance); instance_init(.@instance); if (!questprogress(1260)) setquest(1260); - mes("[Unpleasent Royal Guard]"); - mes("Thank You..\r" - "I will open the secret passage to ^0000FFGhost Palace.^000000\r" - "Please be ready!"); - close(); - } else { - instance_destroy(.@instance); - mesf("^0000FF%s^000000 - Reservation Failed!", .@md_name$); - close(); } + mes("[Unpleasent Royal Guard]"); + mes("Thank You..\r" + "I will open the secret passage to ^0000FFGhost Palace.^000000\r" + "Please be ready!"); + close(); } dali02,41,134,0 script Interdimensional Device::gpportal PORTAL,{ diff --git a/npc/re/instances/octopus_cave.txt b/npc/re/instances/octopus_cave.txt index e4d8d4357..4c964072a 100644 --- a/npc/re/instances/octopus_cave.txt +++ b/npc/re/instances/octopus_cave.txt @@ -85,22 +85,19 @@ mal_dun01,151,235,5 script Starfish 4_ASTER,{ erasequest(4197); if (countitem(Octopus_Hunt_Stick)) { .@instance = instance_create(.@md_name$, .@party_id); - if (.@instance < 0) { - mes("[Starfish]"); - mesf("Party name is... %s.", getpartyname(.@party_id)); - mesf("Party leader is... %s.", strcharinfo(PC_NAME)); - mesf("^0000FF%s^000000, I cannot open now, hehe.", .@md_name$); - mes("Now is not the time, please wait."); - close(); + if (.@instance >= 0) { + if (instance_attachmap("1@cash", .@instance) == "") { + mes("[Starfish]"); + mesf("Party name is... %s.", getpartyname(.@party_id)); + mesf("Party leader is... %s.", strcharinfo(PC_NAME)); + mesf("^0000FF%s^000000, I cannot open now, hehe.", .@md_name$); + mes("Now is not the time, please wait."); + instance_destroy(.@instance); + close(); + } + instance_set_timeout(3600, 300, .@instance); + instance_init(.@instance); } - if (instance_attachmap("1@cash", .@instance) == "") { - mesf("^0000FF%s^000000 - Reservation Failed!", .@md_name$); - instance_destroy(.@instance); - close(); - } - instance_set_timeout(3600, 300, .@instance); - instance_init(.@instance); - mes("[Starfish]"); mesf("I will open the gate for a while to ^0000FF%s^000000.", .@md_name$); mes("Please catch that pervert octopus, and come back with it sticked to the pick, hehe."); diff --git a/npc/re/instances/saras_memory.txt b/npc/re/instances/saras_memory.txt index c9a47534b..9eac396aa 100644 --- a/npc/re/instances/saras_memory.txt +++ b/npc/re/instances/saras_memory.txt @@ -185,19 +185,17 @@ dali,138,118,0 script Dimensional Device#dimen PORTAL,{ if (getcharid(CHAR_ID_CHAR) != getpartyleader(.@party_id, 2)) end; .@instance = instance_create(.@md_name$, .@party_id); - if (.@instance < 0) { - mesf("Party Name: %s", .@p_name$); - mesf("Party Leader: %s", strcharinfo(PC_NAME)); - mesf("^0000FF%s^000000 - Reservation Failed!", .@md_name$); - close(); - } - if (instance_attachmap("1@sara", .@instance) == "") { - mesf("^0000FF%s^000000 - Reservation Failed!", .@md_name$); - instance_destroy(.@instance); - close(); + if (.@instance >= 0) { + if (instance_attachmap("1@sara", .@instance) == "") { + mesf("Party Name: %s", .@p_name$); + mesf("Party Leader: %s", strcharinfo(PC_NAME)); + mesf("^0000FF%s^000000 - Reservation Failed!", .@md_name$); + instance_destroy(.@instance); + close(); + } + instance_set_timeout(3600, 300, .@instance); + instance_init(.@instance); } - instance_set_timeout(3600, 300, .@instance); - instance_init(.@instance); mes("^FF0000The dimensional boots up cleanly. Use the device to enter the crack in space and time.^000000"); close(); case 2: diff --git a/sql-files/item_db_re.sql b/sql-files/item_db_re.sql index e72e96b32..5763847dc 100644 --- a/sql-files/item_db_re.sql +++ b/sql-files/item_db_re.sql @@ -5601,6 +5601,35 @@ REPLACE INTO `item_db` VALUES ('9059','Tikbalang_Pet','Tikbalang Egg','7','0','2 REPLACE INTO `item_db` VALUES ('9060','Brownie_Egg','Egg of Domovoi','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 ('9061','Marin_Egg','Marin 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 ('9062','Novice_Poring_Egg','Novice Poring 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 ('9069','Mastering_Egg','Mastering 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 ('9070','Savage_Egg','Savage 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 ('9071','Grand_Peco_Peco_Egg','Grand Peco Peco 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 ('9087','High_Orc_Egg','High Orc 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 ('9088','Angeling_Egg','Angeling 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 ('9089','Am_Mut_Egg','Am Mut 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 ('9090','Little_Isis_Egg','Little Isis 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 ('9091','Choco_Egg','Choco 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 ('9092','Eggring_Egg','Eggring 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 ('9093','Hyegun_Egg','Hyegun 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 ('9094','Leaf_Lunatic_Egg','Leaf Lunatic 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 ('9095','Nine_Tails_Egg','Nine Tails 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 ('9096','Cat_o_Nine_Tails_Egg','Cat o\' Nine Tails 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 ('9097','Diabolic_Egg_','Diabolic 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 ('9098','Earth_Deleter_Egg','Earth Deleter 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 ('9099','Teddy_Bear_Egg','Teddy Bear 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 ('9100','Gremlin_Egg','Gremlin 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 ('9101','Scatelon_Egg','Scatleton 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 ('9102','Mummy_Egg','Mummy 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 ('9103','Willow_Egg','Willow 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 ('9104','Roween_Egg','Roween 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 ('9105','Hodremlin_Egg','Hodremlin 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 ('9106','Metaller_Egg','Metaller 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 ('9107','Ancient_Mummy_Egg','Ancient Mummy 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 ('9108','Abandoned_Teddy_Bear_Egg','Abandoned Teddy Bear 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 ('9109','Sweet_Drops_Egg','Sweet Drops 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 ('9111','Phreeoni_Egg','Phreeoni 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 ('9112','Moonlight_Flower_Egg','Moonlight Flower 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 ('9113','Skelion_Egg','Skelion 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 ('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/main.sql b/sql-files/main.sql index 2e51d6a12..8f7e5355b 100644 --- a/sql-files/main.sql +++ b/sql-files/main.sql @@ -782,6 +782,7 @@ CREATE TABLE IF NOT EXISTS `pet` ( `hungry` SMALLINT(9) UNSIGNED NOT NULL DEFAULT '0', `rename_flag` TINYINT(4) UNSIGNED NOT NULL DEFAULT '0', `incubate` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `autofeed` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', PRIMARY KEY (`pet_id`) ) ENGINE=MyISAM; @@ -893,6 +894,7 @@ INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1496588700); -- 2017-06-0 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 +INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1528180320); -- 2018-06-05--12-02.sql -- -- Table structure for table `storage` -- diff --git a/sql-files/upgrades/2018-06-05--12-02.sql b/sql-files/upgrades/2018-06-05--12-02.sql new file mode 100644 index 000000000..26c22243f --- /dev/null +++ b/sql-files/upgrades/2018-06-05--12-02.sql @@ -0,0 +1,24 @@ +#1528180320 + +-- This file is part of Hercules. +-- http://herc.ws - http://github.com/HerculesWS/Hercules +-- +-- Copyright (C) 2018 Hercules Dev Team +-- Copyright (C) 2018 Dastgir +-- +-- 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 `pet` ADD COLUMN `autofeed` TINYINT(2) UNSIGNED NOT NULL DEFAULT '0'; + +INSERT INTO `sql_updates` (`timestamp`, `ignored`) VALUES (1528180320 , 'No'); diff --git a/sql-files/upgrades/index.txt b/sql-files/upgrades/index.txt index dac60b6aa..5a737f93a 100644 --- a/sql-files/upgrades/index.txt +++ b/sql-files/upgrades/index.txt @@ -45,3 +45,4 @@ 2017-11-04--10-39.sql 2018-02-26--15-57.sql 2018-03-10--04-06.sql +2018-06-05--12-02.sql diff --git a/src/char/int_pet.c b/src/char/int_pet.c index 0ece11b51..f270f205d 100644 --- a/src/char/int_pet.c +++ b/src/char/int_pet.c @@ -66,19 +66,19 @@ int inter_pet_tosql(const struct s_pet *p) if (p->pet_id == 0) { // New pet. if (SQL_ERROR == SQL->Query(inter->sql_handle, "INSERT INTO `%s` " - "(`class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`) " - "VALUES ('%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", + "(`class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`, `autofeed`) " + "VALUES ('%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, - p->equip, intimate, hungry, p->rename_flag, p->incubate)) { + p->equip, intimate, hungry, p->rename_flag, p->incubate, p->autofeed)) { Sql_ShowDebug(inter->sql_handle); return 0; } pet_id = (int)SQL->LastInsertId(inter->sql_handle); } else { // Update pet. - if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incubate`='%d' WHERE `pet_id`='%d'", + if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incubate`='%d', `autofeed`='%d' WHERE `pet_id`='%d'", pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, - p->equip, intimate, hungry, p->rename_flag, p->incubate, p->pet_id)) { + p->equip, intimate, hungry, p->rename_flag, p->incubate, p->autofeed, p->pet_id)) { Sql_ShowDebug(inter->sql_handle); return 0; } @@ -102,9 +102,9 @@ int inter_pet_fromsql(int pet_id, struct s_pet* p) nullpo_ret(p); memset(p, 0, sizeof(struct s_pet)); - //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`) + //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`, `autofeed`) - if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) ) + if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`,`autofeed` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) ) { Sql_ShowDebug(inter->sql_handle); return 0; @@ -124,6 +124,7 @@ int inter_pet_fromsql(int pet_id, struct s_pet* p) SQL->GetData(inter->sql_handle, 9, &data, NULL); p->hungry = atoi(data); SQL->GetData(inter->sql_handle, 10, &data, NULL); p->rename_flag = atoi(data); SQL->GetData(inter->sql_handle, 11, &data, NULL); p->incubate = atoi(data); + SQL->GetData(inter->sql_handle, 12, &data, NULL); p->autofeed = atoi(data); SQL->FreeResult(inter->sql_handle); diff --git a/src/common/HPM.h b/src/common/HPM.h index e55397022..efa5d8370 100644 --- a/src/common/HPM.h +++ b/src/common/HPM.h @@ -42,11 +42,7 @@ #define DLL HINSTANCE #else // ! WIN32 #include <dlfcn.h> - #ifdef RTLD_DEEPBIND // Certain linux distributions require this, but it's not available everywhere - #define plugin_open(x) dlopen((x),RTLD_NOW|RTLD_DEEPBIND) - #else // ! RTLD_DEEPBIND - #define plugin_open(x) dlopen((x),RTLD_NOW) - #endif // RTLD_DEEPBIND + #define plugin_open(x) dlopen((x), RTLD_NOW) #define plugin_import(x,y,z) (z)dlsym((x),(y)) #define plugin_close(x) dlclose(x) #define plugin_geterror(buf) ((void)buf, dlerror()) diff --git a/src/common/HPMDataCheck.h b/src/common/HPMDataCheck.h index 8df39df02..2370dfa8d 100644 --- a/src/common/HPMDataCheck.h +++ b/src/common/HPMDataCheck.h @@ -588,6 +588,7 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = { { "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_PET_EVOLUTION", sizeof(struct PACKET_CZ_PET_EVOLUTION), SERVER_TYPE_MAP }, { "PACKET_CZ_PRIVATE_AIRSHIP_REQUEST", sizeof(struct PACKET_CZ_PRIVATE_AIRSHIP_REQUEST), 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 }, @@ -696,6 +697,7 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = { { "packet_viewequip_ack", sizeof(struct packet_viewequip_ack), SERVER_TYPE_MAP }, { "packet_whisper_message", sizeof(struct packet_whisper_message), SERVER_TYPE_MAP }, { "packet_wis_end", sizeof(struct packet_wis_end), SERVER_TYPE_MAP }, + { "pet_evolution_items", sizeof(struct pet_evolution_items), SERVER_TYPE_MAP }, #else #define MAP_PACKETS_STRUCT_H #endif // MAP_PACKETS_STRUCT_H @@ -746,6 +748,7 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = { #ifdef MAP_PET_H { "pet_bonus", sizeof(struct pet_bonus), SERVER_TYPE_MAP }, { "pet_data", sizeof(struct pet_data), SERVER_TYPE_MAP }, + { "pet_evolve_data", sizeof(struct pet_evolve_data), SERVER_TYPE_MAP }, { "pet_interface", sizeof(struct pet_interface), SERVER_TYPE_MAP }, { "pet_loot", sizeof(struct pet_loot), SERVER_TYPE_MAP }, { "pet_recovery", sizeof(struct pet_recovery), SERVER_TYPE_MAP }, diff --git a/src/common/console.c b/src/common/console.c index 0b0a900f6..e7edd7e1e 100644 --- a/src/common/console.c +++ b/src/common/console.c @@ -133,7 +133,10 @@ int console_parse_key_pressed(void) **/ CPCMD_C(exit, server) { - core->runflag = 0; + if (core->shutdown_callback != NULL) + core->shutdown_callback(); + else + core->runflag = CORE_ST_STOP; } /** diff --git a/src/common/core.c b/src/common/core.c index 1bd332eec..406bb7629 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -80,9 +80,6 @@ // And don't complain to us if the XYZ plugin you installed wiped your hard disk, or worse. // Note: This feature is deprecated, and should not be used. -/// Called when a terminate signal is received. -void (*shutdown_callback)(void) = NULL; - struct core_interface core_s; struct core_interface *core = &core_s; @@ -128,8 +125,8 @@ static BOOL WINAPI console_handler(DWORD c_event) case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: - if( shutdown_callback != NULL ) - shutdown_callback(); + if (core->shutdown_callback != NULL) + core->shutdown_callback(); else core->runflag = CORE_ST_STOP;// auto-shutdown break; @@ -158,8 +155,8 @@ static void sig_proc(int sn) case SIGTERM: if (++is_called > 3) exit(EXIT_SUCCESS); - if( shutdown_callback != NULL ) - shutdown_callback(); + if (core->shutdown_callback != NULL) + core->shutdown_callback(); else core->runflag = CORE_ST_STOP;// auto-shutdown break; diff --git a/src/common/mmo.h b/src/common/mmo.h index 74d48dd47..0b4ba4a45 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -544,6 +544,7 @@ struct s_pet { char name[NAME_LENGTH]; char rename_flag; char incubate; + int autofeed; }; struct s_homunculus { //[orn] diff --git a/src/map/battle.c b/src/map/battle.c index 6a961afeb..4d320704a 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -7319,6 +7319,7 @@ 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, }, + { "features/enable_pet_autofeed", &battle_config.feature_enable_pet_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, }, diff --git a/src/map/battle.h b/src/map/battle.h index c325daf0d..f4176f142 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -563,6 +563,7 @@ struct Battle_Config { int feature_rodex_use_accountmail; int feature_enable_homun_autofeed; + int feature_enable_pet_autofeed; int storage_use_item; diff --git a/src/map/clif.c b/src/map/clif.c index aeaf03e43..c085c4fe4 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -9093,7 +9093,7 @@ void clif_feel_hate_reset(struct map_session_data *sd) /// value: /// 0 = disabled /// 1 = enabled -void clif_zc_config(struct map_session_data* sd, int type, int flag) +void clif_zc_config(struct map_session_data* sd, enum CZ_CONFIG type, int flag) { int fd; nullpo_retv(sd); @@ -13755,6 +13755,115 @@ void clif_parse_ChangePetName(int fd, struct map_session_data *sd) pet->change_name(sd, RFIFOP(fd,2)); } +void clif_parse_pet_evolution(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); +/// Request to Evolve the pet (CZ_PET_EVOLUTION) [Dastgir/Hercules] +/// 09fb <Length>.W <EvolvedPetEggID>.W {<index>.W <amount>.W}*items +void clif_parse_pet_evolution(int fd, struct map_session_data *sd) +{ + const struct PACKET_CZ_PET_EVOLUTION *p = RP2PTR(fd); + int i = 0, idx, petIndex; + + Assert_retv(p->PacketLength >= (uint16)sizeof(struct PACKET_CZ_PET_EVOLUTION)); + + if (sd->status.pet_id == 0) { + clif->petEvolutionResult(fd, PET_EVOL_NO_CALLPET); + return; + } + + ARR_FIND(0, MAX_INVENTORY, idx, sd->status.inventory[idx].card[0] == CARD0_PET && + sd->status.pet_id == MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); + + if (idx == MAX_INVENTORY) { + clif->petEvolutionResult(fd, PET_EVOL_NO_PETEGG); + return; + } + + // Not Loyal Yet + if (sd->pd == NULL || sd->pd->pet.intimate < 900) { + clif->petEvolutionResult(fd, PET_EVOL_RG_FAMILIAR); + return; + } + + ARR_FIND(0, MAX_PET_DB, petIndex, pet->db[petIndex].class_ == sd->pd->pet.class_); + + if (petIndex == MAX_PET_DB) { + // Which error? + clif->petEvolutionResult(fd, PET_EVOL_UNKNOWN); + return; + } + + // Client side validation is not done as it is insecure. + for (i = 0; i < VECTOR_LENGTH(pet->db[petIndex].evolve_data); i++) { + struct pet_evolve_data *ped = &VECTOR_INDEX(pet->db[petIndex].evolve_data, i); + if (ped->petEggId == p->EvolvedPetEggID) { + int j; + int pet_id; + + if (VECTOR_LENGTH(ped->items) == 0) { + clif->petEvolutionResult(fd, PET_EVOL_NO_RECIPE); + return; + } + for (j = 0; j < VECTOR_LENGTH(ped->items); j++) { + struct itemlist_entry *list = &VECTOR_INDEX(ped->items, j); + int n = pc->search_inventory(sd, list->id); + + if (n == INDEX_NOT_FOUND) { + clif->petEvolutionResult(fd, PET_EVOL_NO_MATERIAL); + return; + } + } + + for (j = 0; j < VECTOR_LENGTH(ped->items); j++) { + struct itemlist_entry *list = &VECTOR_INDEX(ped->items, j); + int n = pc->search_inventory(sd, list->id); + + if (pc->delitem(sd, n, list->amount, 0, DELITEM_NORMAL, LOG_TYPE_EGG) == 1) { + clif->petEvolutionResult(fd, PET_EVOL_NO_MATERIAL); + return; + } + } + + // Return to Egg + pet->return_egg(sd, sd->pd); + + if (pc->delitem(sd, idx, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG) == 1) { + clif->petEvolutionResult(fd, PET_EVOL_NO_PETEGG); + return; + } + + pet_id = pet->search_petDB_index(ped->petEggId, PET_EGG); + if (pet_id >= 0) { + sd->catch_target_class = pet->db[pet_id].class_; + + intif->create_pet( + sd->status.account_id, sd->status.char_id, + (short)pet->db[pet_id].class_, (short)mob->db(pet->db[pet_id].class_)->lv, + (short)pet->db[pet_id].EggID, 0, (short)pet->db[pet_id].intimate, + 100, 0, 1, pet->db[pet_id].jname); + clif->petEvolutionResult(fd, PET_EVOL_SUCCESS); + } else { + clif->petEvolutionResult(fd, PET_EVOL_UNKNOWN); + } + return; + } + } + + clif->petEvolutionResult(fd, PET_EVOL_UNKNOWN); +} + +/** + * Result of Pet Evolution (ZC_PET_EVOLUTION_RESULT) + * 0x9fc <Result>.L + */ +void clif_pet_evolution_result(int fd, enum pet_evolution_result result) { +#if PACKETVER >= 20140122 + WFIFOHEAD(fd, packet_len(0x9fc)); + WFIFOW(fd, 0) = 0x9fc; + WFIFOL(fd, 2) = result; + WFIFOSET(fd, packet_len(0x9fc)); +#endif +} + void clif_parse_GMKick(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /kill (CZ_DISCONNECT_CHARACTER). /// Request to disconnect a character. @@ -16154,24 +16263,38 @@ void clif_parse_cz_config(int fd, struct map_session_data *sd) __attribute__((no /// 02d8 <type>.L <value>.L /// type: /// 0 = open equip window +/// 2 = pet autofeeding /// 3 = homunculus autofeeding /// value: /// 0 = disabled /// 1 = enabled void clif_parse_cz_config(int fd, struct map_session_data *sd) { - int type = RFIFOL(fd, 2); + enum CZ_CONFIG type = RFIFOL(fd, 2); int flag = RFIFOL(fd, 6); - if (type == CZ_CONFIG_OPEN_EQUIPMENT_WINDOW) { + switch (type) { + case CZ_CONFIG_OPEN_EQUIPMENT_WINDOW: sd->status.show_equip = flag; - } else if (type == CZ_CONFIG_HOMUNCULUS_AUTOFEEDING) { - struct homun_data *hd; - hd = sd->hd; + break; + case CZ_CONFIG_PET_AUTOFEEDING: { + struct pet_data *pd = sd->pd; + nullpo_retv(pd); + if (pd->petDB->autofeed == 0) { + clif->message(fd, "Autofeed is disabled for this pet."); + return; + } + pd->pet.autofeed = flag; + break; + } + case CZ_CONFIG_HOMUNCULUS_AUTOFEEDING: { + struct homun_data *hd = sd->hd; nullpo_retv(hd); hd->homunculus.autofeed = flag; - } else { - ShowWarning("clif_parse_cz_config: Unsupported type has been received (%d).", type); + break; + } + default: + ShowWarning("clif_parse_cz_config: Unsupported type has been received (%u).\n", type); return; } clif->zc_config(sd, type, flag); @@ -21991,4 +22114,9 @@ void clif_defaults(void) { clif->pReqStyleChange = clif_parse_cz_req_style_change; clif->cz_req_style_change_sub = clif_cz_req_style_change_sub; clif->style_change_response = clif_style_change_response; + + // -- Pet Evolution + clif->pPetEvolution = clif_parse_pet_evolution; + clif->petEvolutionResult = clif_pet_evolution_result; + } diff --git a/src/map/clif.h b/src/map/clif.h index 4b625023f..eb9881533 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -592,6 +592,17 @@ enum private_airship { P_AIRSHIP_ITEM_INVALID }; +/** Pet Evolution Results */ +enum pet_evolution_result { + PET_EVOL_UNKNOWN = 0x0, + PET_EVOL_NO_CALLPET = 0x1, + PET_EVOL_NO_PETEGG = 0x2, + PET_EVOL_NO_RECIPE = 0x3, + PET_EVOL_NO_MATERIAL = 0x4, + PET_EVOL_RG_FAMILIAR = 0x5, + PET_EVOL_SUCCESS = 0x6, +}; + /** * Structures **/ @@ -834,7 +845,7 @@ struct clif_interface { void (*mission_info) (struct map_session_data *sd, int mob_id, unsigned char progress); void (*feel_hate_reset) (struct map_session_data *sd); void (*partytickack) (struct map_session_data* sd, bool flag); - void (*zc_config) (struct map_session_data *sd, int type, int flag); + void (*zc_config) (struct map_session_data *sd, enum CZ_CONFIG type, int flag); void (*viewequip_ack) (struct map_session_data* sd, struct map_session_data* tsd); void (*equpcheckbox) (struct map_session_data* sd); void (*displayexp) (struct map_session_data *sd, uint64 exp, char type, bool is_quest); @@ -1484,6 +1495,8 @@ struct clif_interface { void (*pReqStyleChange) (int fd, struct map_session_data *sd); void (*cz_req_style_change_sub) (struct map_session_data *sd, int type, int16 idx, bool isitem); void (*style_change_response) (struct map_session_data *sd, enum stylist_shop flag); + void (*pPetEvolution) (int fd, struct map_session_data *sd); + void (*petEvolutionResult) (int fd, enum pet_evolution_result result); }; #ifdef HERCULES_CORE diff --git a/src/map/packets.h b/src/map/packets.h index e5fda598d..ebd971005 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -3029,7 +3029,7 @@ packet(0x96e,-1,clif->ackmergeitems); // 2014-01-22aRagexeRE #if PACKETVER >= 20140122 // new packets - packet(0x09fb,-1,clif->pDull/*,XXX*/); // CZ_PET_EVOLUTION + packet(0x09fb,-1,clif->pPetEvolution); // CZ_PET_EVOLUTION packet(0x09fc,6); // ZC_PET_EVOLUTION_RESULT packet(0x09fd,-1); // ZC_NOTIFY_MOVEENTRY11 packet(0x09fe,-1); // ZC_NOTIFY_NEWENTRY11 diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index d152ffd2a..bcdf1061a 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -1762,6 +1762,18 @@ struct PACKET_ZC_STYLE_CHANGE_RES { int8 flag; } __attribute__((packed)); +struct pet_evolution_items { + int16 index; + int16 amount; +} __attribute__((packed)); + +struct PACKET_CZ_PET_EVOLUTION { + int16 PacketType; + uint16 PacketLength; + int16 EvolvedPetEggID; + // struct pet_evolution_items items[]; +} __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/pet.c b/src/map/pet.c index 4bac79dc8..58c26d1ce 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -85,8 +85,21 @@ void pet_set_intimate(struct pet_data *pd, int value) sd = pd->msd; pd->pet.intimate = value; + if( (intimate >= battle_config.pet_equip_min_friendly && pd->pet.intimate < battle_config.pet_equip_min_friendly) || (intimate < battle_config.pet_equip_min_friendly && pd->pet.intimate >= battle_config.pet_equip_min_friendly) ) status_calc_pc(sd,SCO_NONE); + + /* Pet is lost, delete the egg */ + if (value <= 0) { + int i; + + ARR_FIND(0, MAX_INVENTORY, i, sd->status.inventory[i].card[0] == CARD0_PET && + pd->pet.pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2])); + + if (i != MAX_INVENTORY) { + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG); + } + } } int pet_create_egg(struct map_session_data *sd, int item_id) @@ -233,6 +246,13 @@ int pet_hungry(int tid, int64 tick, int id, intptr_t data) { return 1; //You lost the pet already, the rest is irrelevant. pd->pet.hungry--; + /* Pet Autofeed */ + if (battle_config.feature_enable_homun_autofeed != 0) { + if (pd->petDB->autofeed == 1 && pd->pet.autofeed == 1 && pd->pet.hungry <= 25) { + pet->food(sd, pd); + } + } + if( pd->pet.hungry < 0 ) { pet_stop_attack(pd); @@ -311,23 +331,21 @@ int pet_performance(struct map_session_data *sd, struct pet_data *pd) int pet_return_egg(struct map_session_data *sd, struct pet_data *pd) { - struct item tmp_item; - int flag; + int i; nullpo_retr(1, sd); nullpo_retr(1, pd); pet->lootitem_drop(pd,sd); - memset(&tmp_item,0,sizeof(tmp_item)); - tmp_item.nameid = pd->petDB->EggID; - tmp_item.identify = 1; - tmp_item.card[0] = CARD0_PET; - tmp_item.card[1] = GetWord(pd->pet.pet_id,0); - tmp_item.card[2] = GetWord(pd->pet.pet_id,1); - tmp_item.card[3] = pd->pet.rename_flag; - if((flag = pc->additem(sd,&tmp_item,1,LOG_TYPE_EGG))) { - clif->additem(sd,0,0,flag); - map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false); + + // Pet Evolution + ARR_FIND(0, MAX_INVENTORY, i, sd->status.inventory[i].card[0] == CARD0_PET && + pd->pet.pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2])); + + if (i != MAX_INVENTORY) { + sd->status.inventory[i].identify = 1; + sd->status.inventory[i].bound = IBT_NONE; } + pd->pet.incubate = 1; unit->free(&pd->bl,CLR_OUTSIGHT); @@ -462,19 +480,23 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag) { } if(p->incubate == 1) { int i; - //Delete egg from inventory. [Skotlex] - for (i = 0; i < MAX_INVENTORY; i++) { - if(sd->status.inventory[i].card[0] == CARD0_PET && - p->pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2])) - break; - } - if(i >= MAX_INVENTORY) { + // Get Egg Index + ARR_FIND(0, MAX_INVENTORY, i, sd->status.inventory[i].card[0] == CARD0_PET && + p->pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2])); + + if(i == MAX_INVENTORY) { ShowError("pet_recv_petdata: Hatching pet (%d:%s) aborted, couldn't find egg in inventory for removal!\n",p->pet_id, p->name); sd->status.pet_id = 0; return 1; } - if (!pet->birth_process(sd,p)) //Pet hatched. Delete egg. - pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG); + + + if (!pet->birth_process(sd,p)) { + // Pet Evolution, Hide the egg by setting identify to 0 [Dastgir/Hercules] + sd->status.inventory[i].identify = 0; + // bind the egg to the character to avoid moving it via forged packets [Asheraf] + sd->status.inventory[i].bound = IBT_CHARACTER; + } } else { pet->data_init(sd,p); if(sd->pd && sd->bl.prev != NULL) { @@ -1359,6 +1381,14 @@ int pet_read_db_sub(struct config_setting_t *it, int n, const char *source) if (libconfig->setting_lookup_int(it, "ChangeTargetRate", &i32)) pet->db[n].change_target_rate = i32; + // Pet Evolution + if ((t = libconfig->setting_get_member(it, "Evolve")) && config_setting_is_group(t)) { + pet->read_db_sub_evolution(t, n); + } + + if ((t = libconfig->setting_get_member(it, "AutoFeed")) && (i32 = libconfig->setting_get_bool(t))) + pet->db[n].autofeed = 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; @@ -1368,6 +1398,81 @@ int pet_read_db_sub(struct config_setting_t *it, int n, const char *source) return pet->db[n].class_; } +/** + * Read Pet Evolution Database [Dastgir/Hercules] + * @param t libconfig setting + * @param n Pet DB Index + */ +void pet_read_db_sub_evolution(struct config_setting_t *t, int n) +{ + struct config_setting_t *pett; + int i = 0; + const char *str = NULL; + + nullpo_retv(t); + Assert_retv(n >= 0 && n < MAX_PET_DB); + + VECTOR_INIT(pet->db[n].evolve_data); + + while ((pett = libconfig->setting_get_elem(t, i))) { + if (config_setting_is_group(pett)) { + struct pet_evolve_data ped; + struct item_data *data; + struct config_setting_t *item; + int j = 0, i32 = 0; + + str = config_setting_name(pett); + + if (!(data = itemdb->name2id(str))) { + ShowWarning("pet_read_evolve_db_sub: Invalid Egg '%s' in Pet #%d, skipping.\n", str, pet->db[n].class_); + return; + } else { + ped.petEggId = data->nameid; + } + + VECTOR_INIT(ped.items); + + while ((item = libconfig->setting_get_elem(pett, j))) { + struct itemlist_entry list = { 0 }; + int quantity = 0; + + str = config_setting_name(item); + data = itemdb->search_name(str); + + if (!data) { + ShowWarning("pet_read_evolve_db_sub: required item %s not found in egg %d\n", str, ped.petEggId); + j++; + continue; + } + + list.id = data->nameid; + + if (mob->get_const(item, &i32) && i32 >= 0) { + quantity = i32; + } + + if (quantity <= 0) { + ShowWarning("pet_read_evolve_db_sub: invalid quantity %d for egg %d\n", quantity, ped.petEggId); + j++; + continue; + } + + list.amount = quantity; + + VECTOR_ENSURE(ped.items, 1, 1); + VECTOR_PUSH(ped.items, list); + + j++; + + } + + VECTOR_ENSURE(pet->db[n].evolve_data, 1, 1); + VECTOR_PUSH(pet->db[n].evolve_data, ped); + } + i++; + } +} + bool pet_read_db_sub_intimacy(int idx, struct config_setting_t *t) { int i32 = 0; @@ -1396,6 +1501,7 @@ void pet_read_db_clear(void) // Remove any previous scripts in case reloaddb was invoked. for (i = 0; i < MAX_PET_DB; i++) { + int j; if (pet->db[i].pet_script) { script->free_code(pet->db[i].pet_script); pet->db[i].pet_script = NULL; @@ -1404,6 +1510,11 @@ void pet_read_db_clear(void) script->free_code(pet->db[i].equip_script); pet->db[i].equip_script = NULL; } + + for (j = 0; j < VECTOR_LENGTH(pet->db[i].evolve_data); j++) { + VECTOR_CLEAR(VECTOR_INDEX(pet->db[i].evolve_data, j).items); + } + VECTOR_CLEAR(pet->db[i].evolve_data); } memset(pet->db, 0, sizeof(pet->db)); return; @@ -1437,6 +1548,7 @@ int do_final_pet(void) int i; for( i = 0; i < MAX_PET_DB; i++ ) { + int j; if( pet->db[i].pet_script ) { script->free_code(pet->db[i].pet_script); @@ -1447,9 +1559,16 @@ int do_final_pet(void) script->free_code(pet->db[i].equip_script); pet->db[i].equip_script = NULL; } + + /* Pet Evolution [Dastgir/Hercules] */ + for (j = 0; j < VECTOR_LENGTH(pet->db[i].evolve_data); j++) { + VECTOR_CLEAR(VECTOR_INDEX(pet->db[i].evolve_data, j).items); + } + VECTOR_CLEAR(pet->db[i].evolve_data); } ers_destroy(pet->item_drop_ers); ers_destroy(pet->item_drop_list_ers); + return 0; } void pet_defaults(void) { @@ -1503,4 +1622,6 @@ void pet_defaults(void) { 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; + + pet->read_db_sub_evolution = pet_read_db_sub_evolution; } diff --git a/src/map/pet.h b/src/map/pet.h index d341be97c..b3a16c5d7 100644 --- a/src/map/pet.h +++ b/src/map/pet.h @@ -30,6 +30,12 @@ #define MAX_PET_DB 300 #define MAX_PETLOOT_SIZE 30 +/** Pet Evolution [Dastgir/Hercules] */ +struct pet_evolve_data { + int petEggId; + VECTOR_DECL(struct itemlist_entry) items; +}; + struct s_pet_db { short class_; char name[NAME_LENGTH],jname[NAME_LENGTH]; @@ -50,8 +56,12 @@ struct s_pet_db { int attack_rate; int defence_attack_rate; int change_target_rate; + int autofeed; struct script_code *equip_script; struct script_code *pet_script; + + /* Pet Evolution */ + VECTOR_DECL(struct pet_evolve_data) evolve_data; }; enum { PET_CLASS,PET_CATCH,PET_EGG,PET_EQUIP,PET_FOOD }; @@ -127,6 +137,7 @@ struct pet_interface { struct s_pet_db db[MAX_PET_DB]; struct eri *item_drop_ers; //For loot drops delay structures. struct eri *item_drop_list_ers; + /* */ int (*init) (bool minimal); int (*final) (void); @@ -172,6 +183,10 @@ struct pet_interface { 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); + + /* Pet Evolution [Dastgir/Hercules] */ + void (*read_db_sub_evolution) (struct config_setting_t *t, int n); + }; #ifdef HERCULES_CORE diff --git a/src/map/script.c b/src/map/script.c index 410a707f1..952496486 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -1428,8 +1428,8 @@ const char* script_parse_subexpr(const char* p,int limit) p=script->skip_space(p); while(( (op=C_OP3, opl=0, len=1,*p=='?') // ?: - || (op=C_ADD, opl=9, len=1,*p=='+') // + - || (op=C_SUB, opl=9, len=1,*p=='-') // - + || (op=C_ADD, opl=9, len=1,*p=='+' && p[1]!='+') // + + || (op=C_SUB, opl=9, len=1,*p=='-' && p[1]!='-') // - || (op=C_POW, opl=11,len=2,*p=='*' && p[1]=='*') // ** || (op=C_MUL, opl=10,len=1,*p=='*') // * || (op=C_DIV, opl=10,len=1,*p=='/') // / @@ -8597,7 +8597,8 @@ BUILDIN(disableitemuse) * return the basic stats of sd * chk pc->readparam for available type *------------------------------------------*/ -BUILDIN(readparam) { +BUILDIN(readparam) +{ int type; struct map_session_data *sd; struct script_data *data = script_getdata(st, 2); @@ -8609,7 +8610,11 @@ BUILDIN(readparam) { } if (script_hasdata(st, 3)) { - sd = script->nick2sd(st, script_getstr(st, 3)); + if (script_isstringtype(st, 3)) { + sd = script->nick2sd(st, script_getstr(st, 3)); + } else { + sd = script->id2sd(st, script_getnum(st, 3)); + } } else { sd = script->rid2sd(st); } @@ -8623,6 +8628,43 @@ BUILDIN(readparam) { return true; } +BUILDIN(setparam) +{ + int type; + struct map_session_data *sd; + struct script_data *data = script_getdata(st, 2); + int val = script_getnum(st, 3); + + if (data_isreference(data) && reference_toparam(data)) { + type = reference_getparamtype(data); + } else { + type = script->conv_num(st, data); + } + + if (script_hasdata(st, 4)) { + if (script_isstringtype(st, 4)) { + sd = script->nick2sd(st, script_getstr(st, 4)); + } else { + sd = script->id2sd(st, script_getnum(st, 4)); + } + } else { + sd = script->rid2sd(st); + } + + if (sd == NULL) { + script_pushint(st, 0); + return true; + } + + if (pc->setparam(sd, type, val) == 0) { + script_pushint(st, 0); + return false; + } + + script_pushint(st, 1); + return true; +} + /*========================================== * Return charid identification * return by @num : @@ -21160,6 +21202,7 @@ BUILDIN(instance_create) const char *name; int owner_id, res; int type = IOT_PARTY; + struct map_session_data *sd = map->id2sd(st->rid); name = script_getstr(st, 2); owner_id = script_getnum(st, 3); @@ -21172,22 +21215,43 @@ BUILDIN(instance_create) } res = instance->create(owner_id, name, (enum instance_owner_type) type); - if( res == -4 ) { // Already exists - script_pushint(st, -1); - return true; - } else if( res < 0 ) { + if (sd != NULL) { + switch (res) { + case -4: // Already exists + clif->msgtable_str(sd, MSG_MDUNGEON_SUBSCRIPTION_ERROR_DUPLICATE, name); + break; + case -3: // No free instances + clif->msgtable_str(sd, MSG_MDUNGEON_SUBSCRIPTION_ERROR_EXIST, name); + break; + case -2: // Invalid type + clif->msgtable_str(sd, MSG_MDUNGEON_SUBSCRIPTION_ERROR_RIGHT, name); + break; + case -1: // Unknown + clif->msgtable_str(sd, MSG_MDUNGEON_SUBSCRIPTION_ERROR_UNKNOWN, name); + break; + default: + if (res < 0) + ShowError("buildin_instance_create: failed to unknown reason [%d].\n", res); + } + } else { const char *err; - switch(res) { - case -3: err = "No free instances"; break; - case -2: err = "Invalid party ID"; break; - case -1: err = "Invalid type"; break; - default: err = "Unknown"; break; + switch (res) { + case -3: + err = "No free instances"; + break; + case -2: + err = "Invalid party ID"; + break; + case -1: + err = "Invalid type"; + break; + default: + err = "Unknown"; + break; } - ShowError("buildin_instance_create: %s [%d].\n", err, res); - script_pushint(st, -2); - return true; + if (res < 0) + ShowError("buildin_instance_create: %s [%d].\n", err, res); } - script_pushint(st, res); return true; } @@ -23860,7 +23924,7 @@ bool rodex_sendmail_sub(struct script_state* st, struct rodex_message *msg) { const char *sender_name, *title, *body; - if (!strcmp(script->getfuncname(st), "rodex_sendmail_acc2")) + if (strcmp(script->getfuncname(st), "rodex_sendmail_acc") == 0 || strcmp(script->getfuncname(st), "rodex_sendmail_acc2") == 0) msg->receiver_accountid = script_getnum(st, 2); else msg->receiver_id = script_getnum(st, 2); @@ -24390,6 +24454,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(checkweight,"vi*"), BUILDIN_DEF(checkweight2,"rr"), BUILDIN_DEF(readparam,"i?"), + BUILDIN_DEF(setparam,"ii?"), BUILDIN_DEF(getcharid,"i?"), BUILDIN_DEF(getnpcid,"i?"), BUILDIN_DEF(getpartyname,"i"), diff --git a/src/map/skill.c b/src/map/skill.c index 6eacde897..34c36d7f3 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -15027,8 +15027,9 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, } break; default: - skill->check_condition_castend_unknown(sd, &skill_id, &skill_lv); - break; + if (!skill->check_condition_castend_unknown(sd, &skill_id, &skill_lv)) + break; + return 0; } st = &sd->battle_status; @@ -15115,8 +15116,9 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, return 1; } -void skill_check_condition_castend_unknown(struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv) +bool skill_check_condition_castend_unknown(struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv) { + return false; } // type&2: consume items (after skill was used) diff --git a/src/map/skill.h b/src/map/skill.h index e16094eae..bd1dc3344 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -2172,7 +2172,7 @@ struct skill_interface { int (*check_condition_castbegin_mount_unknown) (struct status_change *sc, uint16 *skill_id); int (*check_condition_castbegin_madogear_unknown) (struct status_change *sc, uint16 *skill_id); int (*check_condition_castbegin_unknown) (struct status_change *sc, uint16 *skill_id); - void (*check_condition_castend_unknown) (struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv); + bool (*check_condition_castend_unknown) (struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv); bool (*get_requirement_off_unknown) (struct status_change *sc, uint16 *skill_id); bool (*get_requirement_item_unknown) (struct status_change *sc, struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv, uint16 *idx, int *i); void (*get_requirement_unknown) (struct status_change *sc, struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv, struct skill_condition *req); diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc index 7c609f0bf..6d184d082 100644 --- a/src/plugins/HPMHooking/HPMHooking.Defs.inc +++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc @@ -1266,8 +1266,8 @@ typedef void (*HPMHOOK_pre_clif_feel_hate_reset) (struct map_session_data **sd); typedef void (*HPMHOOK_post_clif_feel_hate_reset) (struct map_session_data *sd); typedef void (*HPMHOOK_pre_clif_partytickack) (struct map_session_data **sd, bool *flag); typedef void (*HPMHOOK_post_clif_partytickack) (struct map_session_data *sd, bool flag); -typedef void (*HPMHOOK_pre_clif_zc_config) (struct map_session_data **sd, int *type, int *flag); -typedef void (*HPMHOOK_post_clif_zc_config) (struct map_session_data *sd, int type, int flag); +typedef void (*HPMHOOK_pre_clif_zc_config) (struct map_session_data **sd, enum CZ_CONFIG *type, int *flag); +typedef void (*HPMHOOK_post_clif_zc_config) (struct map_session_data *sd, enum CZ_CONFIG type, int flag); typedef void (*HPMHOOK_pre_clif_viewequip_ack) (struct map_session_data **sd, struct map_session_data **tsd); typedef void (*HPMHOOK_post_clif_viewequip_ack) (struct map_session_data *sd, struct map_session_data *tsd); typedef void (*HPMHOOK_pre_clif_equpcheckbox) (struct map_session_data **sd); @@ -2450,6 +2450,10 @@ typedef void (*HPMHOOK_pre_clif_cz_req_style_change_sub) (struct map_session_dat typedef void (*HPMHOOK_post_clif_cz_req_style_change_sub) (struct map_session_data *sd, int type, int16 idx, bool isitem); typedef void (*HPMHOOK_pre_clif_style_change_response) (struct map_session_data **sd, enum stylist_shop *flag); typedef void (*HPMHOOK_post_clif_style_change_response) (struct map_session_data *sd, enum stylist_shop flag); +typedef void (*HPMHOOK_pre_clif_pPetEvolution) (int *fd, struct map_session_data **sd); +typedef void (*HPMHOOK_post_clif_pPetEvolution) (int fd, struct map_session_data *sd); +typedef void (*HPMHOOK_pre_clif_petEvolutionResult) (int *fd, enum pet_evolution_result *result); +typedef void (*HPMHOOK_post_clif_petEvolutionResult) (int fd, enum pet_evolution_result result); #endif // MAP_CLIF_H #ifdef COMMON_CORE_H /* cmdline */ typedef void (*HPMHOOK_pre_cmdline_init) (void); @@ -6110,6 +6114,8 @@ typedef bool (*HPMHOOK_pre_pet_read_db_sub_intimacy) (int *idx, struct config_se 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); +typedef void (*HPMHOOK_pre_pet_read_db_sub_evolution) (struct config_setting_t **t, int *n); +typedef void (*HPMHOOK_post_pet_read_db_sub_evolution) (struct config_setting_t *t, int n); #endif // MAP_PET_H #ifdef CHAR_PINCODE_H /* pincode */ typedef void (*HPMHOOK_pre_pincode_handle) (int *fd, struct char_session_data **sd); @@ -7102,8 +7108,8 @@ typedef int (*HPMHOOK_pre_skill_check_condition_castbegin_madogear_unknown) (str typedef int (*HPMHOOK_post_skill_check_condition_castbegin_madogear_unknown) (int retVal___, struct status_change *sc, uint16 *skill_id); typedef int (*HPMHOOK_pre_skill_check_condition_castbegin_unknown) (struct status_change **sc, uint16 **skill_id); typedef int (*HPMHOOK_post_skill_check_condition_castbegin_unknown) (int retVal___, struct status_change *sc, uint16 *skill_id); -typedef void (*HPMHOOK_pre_skill_check_condition_castend_unknown) (struct map_session_data **sd, uint16 **skill_id, uint16 **skill_lv); -typedef void (*HPMHOOK_post_skill_check_condition_castend_unknown) (struct map_session_data *sd, uint16 *skill_id, uint16 *skill_lv); +typedef bool (*HPMHOOK_pre_skill_check_condition_castend_unknown) (struct map_session_data **sd, uint16 **skill_id, uint16 **skill_lv); +typedef bool (*HPMHOOK_post_skill_check_condition_castend_unknown) (bool retVal___, struct map_session_data *sd, uint16 *skill_id, uint16 *skill_lv); typedef bool (*HPMHOOK_pre_skill_get_requirement_off_unknown) (struct status_change **sc, uint16 **skill_id); typedef bool (*HPMHOOK_post_skill_get_requirement_off_unknown) (bool retVal___, struct status_change *sc, uint16 *skill_id); typedef bool (*HPMHOOK_pre_skill_get_requirement_item_unknown) (struct status_change **sc, struct map_session_data **sd, uint16 **skill_id, uint16 **skill_lv, uint16 **idx, int **i); diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc index d17955db7..671a9cb5c 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc @@ -2046,6 +2046,10 @@ struct { struct HPMHookPoint *HP_clif_cz_req_style_change_sub_post; struct HPMHookPoint *HP_clif_style_change_response_pre; struct HPMHookPoint *HP_clif_style_change_response_post; + struct HPMHookPoint *HP_clif_pPetEvolution_pre; + struct HPMHookPoint *HP_clif_pPetEvolution_post; + struct HPMHookPoint *HP_clif_petEvolutionResult_pre; + struct HPMHookPoint *HP_clif_petEvolutionResult_post; struct HPMHookPoint *HP_cmdline_init_pre; struct HPMHookPoint *HP_cmdline_init_post; struct HPMHookPoint *HP_cmdline_final_pre; @@ -4762,6 +4766,8 @@ struct { 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_pet_read_db_sub_evolution_pre; + struct HPMHookPoint *HP_pet_read_db_sub_evolution_post; struct HPMHookPoint *HP_quest_init_pre; struct HPMHookPoint *HP_quest_init_post; struct HPMHookPoint *HP_quest_final_pre; @@ -8421,6 +8427,10 @@ struct { int HP_clif_cz_req_style_change_sub_post; int HP_clif_style_change_response_pre; int HP_clif_style_change_response_post; + int HP_clif_pPetEvolution_pre; + int HP_clif_pPetEvolution_post; + int HP_clif_petEvolutionResult_pre; + int HP_clif_petEvolutionResult_post; int HP_cmdline_init_pre; int HP_cmdline_init_post; int HP_cmdline_final_pre; @@ -11137,6 +11147,8 @@ struct { int HP_pet_read_db_sub_intimacy_post; int HP_pet_read_db_clear_pre; int HP_pet_read_db_clear_post; + int HP_pet_read_db_sub_evolution_pre; + int HP_pet_read_db_sub_evolution_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 c9463b1b8..942693da8 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc @@ -1046,6 +1046,8 @@ struct HookingPointData HookingPoints[] = { { HP_POP(clif->pReqStyleChange, HP_clif_pReqStyleChange) }, { HP_POP(clif->cz_req_style_change_sub, HP_clif_cz_req_style_change_sub) }, { HP_POP(clif->style_change_response, HP_clif_style_change_response) }, + { HP_POP(clif->pPetEvolution, HP_clif_pPetEvolution) }, + { HP_POP(clif->petEvolutionResult, HP_clif_petEvolutionResult) }, /* cmdline_interface */ { HP_POP(cmdline->init, HP_cmdline_init) }, { HP_POP(cmdline->final, HP_cmdline_final) }, @@ -2439,6 +2441,7 @@ struct HookingPointData HookingPoints[] = { { 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) }, + { HP_POP(pet->read_db_sub_evolution, HP_pet_read_db_sub_evolution) }, /* 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 bd2ef870f..5cd54ba22 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc @@ -11221,10 +11221,10 @@ void HP_clif_partytickack(struct map_session_data *sd, bool flag) { } return; } -void HP_clif_zc_config(struct map_session_data *sd, int type, int flag) { +void HP_clif_zc_config(struct map_session_data *sd, enum CZ_CONFIG type, int flag) { int hIndex = 0; if (HPMHooks.count.HP_clif_zc_config_pre > 0) { - void (*preHookFunc) (struct map_session_data **sd, int *type, int *flag); + void (*preHookFunc) (struct map_session_data **sd, enum CZ_CONFIG *type, int *flag); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_zc_config_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_clif_zc_config_pre[hIndex].func; @@ -11239,7 +11239,7 @@ void HP_clif_zc_config(struct map_session_data *sd, int type, int flag) { HPMHooks.source.clif.zc_config(sd, type, flag); } if (HPMHooks.count.HP_clif_zc_config_post > 0) { - void (*postHookFunc) (struct map_session_data *sd, int type, int flag); + void (*postHookFunc) (struct map_session_data *sd, enum CZ_CONFIG type, int flag); for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_zc_config_post; hIndex++) { postHookFunc = HPMHooks.list.HP_clif_zc_config_post[hIndex].func; postHookFunc(sd, type, flag); @@ -26649,6 +26649,58 @@ void HP_clif_style_change_response(struct map_session_data *sd, enum stylist_sho } return; } +void HP_clif_pPetEvolution(int fd, struct map_session_data *sd) { + int hIndex = 0; + if (HPMHooks.count.HP_clif_pPetEvolution_pre > 0) { + void (*preHookFunc) (int *fd, struct map_session_data **sd); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_pPetEvolution_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_clif_pPetEvolution_pre[hIndex].func; + preHookFunc(&fd, &sd); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.clif.pPetEvolution(fd, sd); + } + if (HPMHooks.count.HP_clif_pPetEvolution_post > 0) { + void (*postHookFunc) (int fd, struct map_session_data *sd); + for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_pPetEvolution_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_clif_pPetEvolution_post[hIndex].func; + postHookFunc(fd, sd); + } + } + return; +} +void HP_clif_petEvolutionResult(int fd, enum pet_evolution_result result) { + int hIndex = 0; + if (HPMHooks.count.HP_clif_petEvolutionResult_pre > 0) { + void (*preHookFunc) (int *fd, enum pet_evolution_result *result); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_petEvolutionResult_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_clif_petEvolutionResult_pre[hIndex].func; + preHookFunc(&fd, &result); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.clif.petEvolutionResult(fd, result); + } + if (HPMHooks.count.HP_clif_petEvolutionResult_post > 0) { + void (*postHookFunc) (int fd, enum pet_evolution_result result); + for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_petEvolutionResult_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_clif_petEvolutionResult_post[hIndex].func; + postHookFunc(fd, result); + } + } + return; +} /* cmdline_interface */ void HP_cmdline_init(void) { int hIndex = 0; @@ -63447,6 +63499,32 @@ void HP_pet_read_db_clear(void) { } return; } +void HP_pet_read_db_sub_evolution(struct config_setting_t *t, int n) { + int hIndex = 0; + if (HPMHooks.count.HP_pet_read_db_sub_evolution_pre > 0) { + void (*preHookFunc) (struct config_setting_t **t, int *n); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_read_db_sub_evolution_pre; hIndex++) { + preHookFunc = HPMHooks.list.HP_pet_read_db_sub_evolution_pre[hIndex].func; + preHookFunc(&t, &n); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return; + } + } + { + HPMHooks.source.pet.read_db_sub_evolution(t, n); + } + if (HPMHooks.count.HP_pet_read_db_sub_evolution_post > 0) { + void (*postHookFunc) (struct config_setting_t *t, int n); + for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_read_db_sub_evolution_post; hIndex++) { + postHookFunc = HPMHooks.list.HP_pet_read_db_sub_evolution_post[hIndex].func; + postHookFunc(t, n); + } + } + return; +} /* quest_interface */ void HP_quest_init(bool minimal) { int hIndex = 0; @@ -76386,31 +76464,32 @@ int HP_skill_check_condition_castbegin_unknown(struct status_change *sc, uint16 } return retVal___; } -void HP_skill_check_condition_castend_unknown(struct map_session_data *sd, uint16 *skill_id, uint16 *skill_lv) { +bool HP_skill_check_condition_castend_unknown(struct map_session_data *sd, uint16 *skill_id, uint16 *skill_lv) { int hIndex = 0; + bool retVal___ = false; if (HPMHooks.count.HP_skill_check_condition_castend_unknown_pre > 0) { - void (*preHookFunc) (struct map_session_data **sd, uint16 **skill_id, uint16 **skill_lv); + bool (*preHookFunc) (struct map_session_data **sd, uint16 **skill_id, uint16 **skill_lv); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_check_condition_castend_unknown_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_skill_check_condition_castend_unknown_pre[hIndex].func; - preHookFunc(&sd, &skill_id, &skill_lv); + retVal___ = preHookFunc(&sd, &skill_id, &skill_lv); } if (*HPMforce_return) { *HPMforce_return = false; - return; + return retVal___; } } { - HPMHooks.source.skill.check_condition_castend_unknown(sd, skill_id, skill_lv); + retVal___ = HPMHooks.source.skill.check_condition_castend_unknown(sd, skill_id, skill_lv); } if (HPMHooks.count.HP_skill_check_condition_castend_unknown_post > 0) { - void (*postHookFunc) (struct map_session_data *sd, uint16 *skill_id, uint16 *skill_lv); + bool (*postHookFunc) (bool retVal___, struct map_session_data *sd, uint16 *skill_id, uint16 *skill_lv); for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_check_condition_castend_unknown_post; hIndex++) { postHookFunc = HPMHooks.list.HP_skill_check_condition_castend_unknown_post[hIndex].func; - postHookFunc(sd, skill_id, skill_lv); + retVal___ = postHookFunc(retVal___, sd, skill_id, skill_lv); } } - return; + return retVal___; } bool HP_skill_get_requirement_off_unknown(struct status_change *sc, uint16 *skill_id) { int hIndex = 0; diff --git a/tools/petevolutionconverter.py b/tools/petevolutionconverter.py new file mode 100644 index 000000000..0ccc71314 --- /dev/null +++ b/tools/petevolutionconverter.py @@ -0,0 +1,248 @@ +#!/usr/bin/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 Dastgir +# +# 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/>. +# +# Usage: +# python petevolutionconverter.py PetEvolutionCln.lub re ../ > pet_evolve_db.conf + +import re +import sys +import utils.common as Tools + +def printHeader(): + print('''//================= 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) + Evolve: { + EggID: { (string, Evolved Pet EggID) + Name: Amount (items required to perform evolution) + ... + } + } + AutoFeed: true/false (boolean, defaults to false) + PetScript: <" Pet Script (can also be multi-line) "> + EquipScript: <" Equip Script (can also be multi-line) "> +}, +**************************************************************************/''') + +def printID(db, name, tabSize = 1): + if (name not in db or int(db[name]) == 0): + return + print('{}{}: {}'.format('\t'*tabSize, name, db[name])) + +def printString(db, name, tabSize = 1): + if (name not in db or db[name].strip() == ""): + return + print('{}{}: "{}"'.format('\t'*tabSize, name, db[name])) + +def printBool(db, name): + if (name not in db or db[name] == '0'): + return + print('\t{}: true'.format(name)) + +def printScript(db, name): + if (name not in db or db[name].strip() == ""): + return + print('\t{}: <{}>'.format(name, db[name])) + +def printEntry(ItemDB, EvolveDB, autoFeedDB, entry, mode, serverpath): + PetDB = Tools.LoadDB('pet_db', mode, serverpath) + + for i, db in enumerate(PetDB): + print('{') + printID(db, 'Id') + printString(db, 'SpriteName') + printString(db, 'Name') + + printString(db, 'TamingItem') + printString(db, 'EggItem') + printString(db, 'AccessoryItem') + printString(db, 'FoodItem') + printID(db, 'FoodEffectiveness') + printID(db, 'HungerDelay') + + if ('Intimacy' in db and (db['Intimacy']['Initial'] != 0 or db['Intimacy']['FeedIncrement'] != 0 or + db['Intimacy']['OverFeedDecrement'] != 0 or db['Intimacy']['OwnerDeathDecrement'] != 0)): + print('\tIntimacy: {') + printID(db['Intimacy'], 'Initial', 2) + printID(db['Intimacy'], 'FeedIncrement', 2) + printID(db['Intimacy'], 'OverFeedDecrement', 2) + printID(db['Intimacy'], 'OwnerDeathDecrement', 2) + print('\t}') + # + printID(db, 'CaptureRate') + printID(db, 'Speed') + printBool(db, 'SpecialPerformance') + printBool(db, 'TalkWithEmotes') + printID(db, 'AttackRate') + printID(db, 'DefendRate') + printID(db, 'ChangeTargetRate') + if (str(db['Id']) in autoFeedDB): + print('\tAutoFeed: true') + else: + print('\tAutoFeed: false') + printScript(db, 'PetScript') + printScript(db, 'EquipScript') + + if (db['EggItem'] in EvolveDB): + entry = EvolveDB[db['EggItem']] + print('\tEvolve: {') + + for evolve in entry: + if ('comment' in evolve): + print('/*') + print('\t\t{}: {'.format(evolve['Id'])) + + for items in evolve['items']: + print('\t\t\t{}: {}'.format(items[0], items[1])) + + print('\t\t}') + if ('comment' in evolve): + print('*/') + + print('\t}') + print('},') + +def saveEntry(EvolveDB, entry): + if (entry['from'] not in EvolveDB): + EvolveDB[entry['from']] = list() + EvolveDB[entry['from']].append(entry) + return EvolveDB + +def getItemConstant(entry, ItemDB, itemID): + if (itemID in ItemDB): + return ItemDB[itemID] + print(itemID, "not found", entry) + entry['comment'] = 1 + return itemID + +def ConvertDB(luaName, mode, serverpath): + ItemDB = Tools.LoadDBConsts('item_db', mode, serverpath) + f = open(luaName) + content = f.read() + f.close() + + recipeDB = re.findall(r'InsertEvolutionRecipeLGU\((\d+),\s*(\d+),\s*(\d+),\s*(\d+)\)', content) + autoFeedDB = re.findall(r'InsertPetAutoFeeding\((\d+)\)', content) + + current = 0 + + entry = dict() + EvolveDB = dict() + + printHeader() + for recipe in recipeDB: + fromEgg = getItemConstant(entry, ItemDB, int(recipe[0])) + petEgg = getItemConstant(entry, ItemDB, int(recipe[1])) + + if (current == 0): + entry = { + 'Id': petEgg, + 'from': fromEgg, + 'items': list() + } + current = petEgg + + if (current != petEgg): + EvolveDB = saveEntry(EvolveDB, entry) + entry = { + 'Id': petEgg, + 'from': fromEgg, + 'items': list() + } + entry['id'] = petEgg + entry['items'] = list() + current = petEgg + + itemConst = getItemConstant(entry, ItemDB, int(recipe[2])) + quantity = int(recipe[3]) + + entry['items'].append((itemConst, quantity)) + saveEntry(EvolveDB, entry) + + printEntry(ItemDB, EvolveDB, autoFeedDB, entry, mode, serverpath) + print(')') + + +if len(sys.argv) != 4: + print('Pet Evolution Lua to DB') + print('Usage:') + print(' petevolutionconverter.py lua mode serverpath') + print("example:") + print(' petevolutionconverter.py PetEvolutionCln.lua pre-re ../') + exit(1) + +ConvertDB(sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/tools/utils/common.py b/tools/utils/common.py index 1a398d544..7b7811654 100644 --- a/tools/utils/common.py +++ b/tools/utils/common.py @@ -48,3 +48,18 @@ def LoadDBConsts(DBname, mode, serverpath): print('LoadDBConsts: invalid database name {}'.format(DBname)) exit(1) return consts + +def LoadDB(DBname, mode, serverpath): + filenames = [serverpath + 'db/{}/{}.conf'.format(mode, DBname)] + + if os.path.isfile(serverpath + 'db/{}2.conf'.format(DBname)): + filenames.append(serverpath + 'db/{}2.conf'.format(DBname)) + + consts = dict() + for filename in filenames: + with io.open(filename) as f: + config = libconf.load(f) + db = config[DBname] + return db + print('LoadDB: invalid database name {}'.format(DBname)) + exit(1) |