فهرست منبع

A little cleanup for Pet DB
* Separated pet_db for Renewal & Pre-Renewal to avoid non-existant monster in different mode.
* Cleaned script command in pet_db.txt file, just point it to doc/script_commands.txt. Read them there!
* Separated damage value for petskillattack2 to its own var 'damage', that previously use 'lv' var to store the value.
* Added config 'pet_ignore_infinite_def' in conf/battle/pet.conf,
* If disabled (val:"no"), fixed damage from pet script 'petskillattack2' will be adjusted to 1. Example, just like player attacks Shining Plant.
* Enabled by default. Previously, fixed damage ignore the infinite defense, that's why it's enabled by default.
* TODO: Correcting the logic and maybe also confirm the correct behavior!
* Added validation for pet script commands,
* Skill for petskillattack, petskillattack2, & petskillsupport
* SC range for petrecovery.
* Cleaned up some source documentation.

Signed-off-by: Cydh Ramdh <house.bad@gmail.com>

Cydh Ramdh 10 سال پیش
والد
کامیت
62bdc99f05
12فایلهای تغییر یافته به همراه270 افزوده شده و 150 حذف شده
  1. 3 0
      conf/battle/pet.conf
  2. 104 0
      db/pre-re/pet_db.txt
  3. 3 30
      db/re/pet_db.txt
  4. 13 6
      doc/script_commands.txt
  5. 2 1
      src/map/battle.c
  6. 4 0
      src/map/battle.h
  7. 13 21
      src/map/pet.c
  8. 30 26
      src/map/pet.h
  9. 76 47
      src/map/script.c
  10. 15 9
      src/map/skill.c
  11. 6 9
      src/map/status.c
  12. 1 1
      src/map/status.h

+ 3 - 0
conf/battle/pet.conf

@@ -75,3 +75,6 @@ pet_max_atk2: 1000
 // If set to yes, pets are automatically returned to egg when entering castles during WoE times
 // If set to yes, pets are automatically returned to egg when entering castles during WoE times
 // and hatching is forbidden within as well.
 // and hatching is forbidden within as well.
 pet_disable_in_gvg: no
 pet_disable_in_gvg: no
+
+// Will does petskillattack2 fixed damage ignore plant infnite defense? (Note 1)
+pet_ignore_infinite_def: yes

+ 104 - 0
db/pre-re/pet_db.txt

@@ -0,0 +1,104 @@
+// Pet Database
+//
+// Structure of Database:
+// MobID,Name,JName,LureID,EggID,EquipID,FoodID,Fullness,HungryDelay,R_Hungry,R_Full,Intimate,Die,Capture,Speed,S_Performance,talk_convert_class,attack_rate,defence_attack_rate,change_target_rate,pet_script,loyal_script
+//
+// 01. MobID			Monster ID of the pet.
+// 02. Name			Name of the monster as defined in the database.
+// 03. JName			The display name of the monster when hatched.
+// 04. LureID			Pet Tame Item ID.
+// 05. EggID			Pet Egg ID.
+// 06. EquipID			Pet Accessory ID.
+// 07. FoodID			Pet Food ID.
+// 08. Fullness			The amount Hunger is decreased every [HungryDelay] seconds.
+// 09. HungryDelay		The amount of time it takes for hunger to decrease after feeding. (Default: 60 seconds)
+// 10. R_Hungry			Amount of Intimacy that is increased when fed.
+// 11. R_Full			Amount of Intimacy that is decreased when over-fed.
+// 12. Intimate			Amount of Intimacy the pet starts with.
+// 13. Die			Amount of Intimacy that is decreased when the pet owner dies.
+// 14. Capture			Capture succes rate (10000 = 100%)
+// 15. Speed			Pet's walk speed. (Defaul: 150)
+// 16. S_Performance		Special Performance. (Yes = 1, No = 0)
+// 17. talk_convert_class	Disables pet talk (instead of talking they emote  with /!.)
+// 18. attack_rate			Rate of which the pet will attack (requires at least pet_support_min_friendly intimacy).
+// 19. defence_attack_rate	Rate of which the pet will retaliate when master is being attacked (requires at least pet_support_min_friendly intimacy).
+// 20. change_target_rate	Rate of which the pet will change its attack target.
+// 21. pet_script		Script to execute when the pet is hatched.
+// 22. loyal_script		Script to execute when the pet is hatched (requires at least pet_equip_min_friendly intimacy, independent of pet_script).
+//NOTE: The max value (100%) of attack_rate, defense_rate & change_target_rate is 10000.
+
+//In theory you can use any valid script, but it is run only once upon pet
+//loading, so it is recommended you use the specific pet scripts.
+//Please see "The Pet AI commands" in 'doc/script_commands.txt'.
+
+1002,PORING,Poring,619,9001,10013,531,80,60,50,100,250,20,2000,150,1,0,350,400,800,{ petloot 10; },{ bonus bLuk,2; bonus bCritical,1; }
+1113,DROPS,Drops,620,9002,10013,508,80,60,40,100,250,20,1500,150,1,0,300,400,500,{ petloot 10; },{ bonus bHit,3; bonus bAtk,3; }
+1031,POPORING,Poporing,621,9003,10013,511,80,60,30,100,250,20,1000,150,1,0,300,500,400,{ petloot 15; },{ bonus bLuk,2; bonus2 bSubEle,Ele_Poison,10; }
+1063,LUNATIC,Lunatic,622,9004,10007,534,80,60,40,100,250,20,1500,150,0,0,300,300,1000,{ petskillbonus bLuk,3,10,50; },{ bonus bCritical,2; bonus bAtk,2; }
+1049,PICKY,Picky,623,9005,10012,507,80,60,40,100,250,20,2000,150,1,0,500,600,50,{ petskillbonus bStr,3,10,50;},{ bonus bStr,1; bonus bAtk,5; }
+1011,CHONCHON,ChonChon,624,9006,10002,537,80,60,30,100,250,20,1500,150,1,0,500,500,250,{ petskillbonus bAgi,4,10,50; },{ bonus bAgi,1; bonus bFlee,2; }
+1042,STEEL_CHONCHON,Steel ChonChon,625,9007,10002,1002,80,60,20,100,250,20,1000,150,1,0,500,500,200,{ petskillbonus bAgiVit,4,20,40; },{ bonus bFlee,6; bonus bAgi,-1; }
+1035,HUNTER_FLY,Hunter Fly,626,9008,10002,716,80,60,10,100,250,20,500,150,1,0,500,500,200,{ petskillattack2 "NPC_WINDATTACK",888,2,0,10; },{ bonus bFlee,-5; bonus bFlee2,2; }
+1167,SAVAGE_BABE,Savage Babe,627,9009,10015,537,80,60,40,100,250,20,1500,150,0,0,500,500,200,{ petskillbonus bVit,4,10,50; },{ bonus bVit,1; bonus bMaxHP,50; }
+1107,DESERT_WOLF_B,Baby Desert Wolf,628,9010,10003,537,80,60,40,100,250,20,1000,150,0,0,400,400,400,{ petskillattack "SM_PROVOKE",1,0,5;},{ bonus bInt,1; bonus bMaxSP,50; }
+1052,ROCKER,Rocker,629,9011,10014,537,80,60,30,100,250,20,1500,150,0,0,350,350,600,{ petskillbonus bAllStats,1,10,50; },{ bonus bHPrecovRate,5; bonus bMaxHP,25; }
+1014,SPORE,Spore,630,9012,10017,537,80,60,30,100,250,20,1500,150,0,0,350,500,500,{ petrecovery SC_POISON,60; },{ bonus bHit,5; bonus bAtk,-2; }
+1077,POISON_SPORE,Poison Spore,631,9013,10017,537,80,60,20,100,250,20,1000,150,0,0,600,200,400,{ petskillattack "NPC_POISON",20,0,10; },{ bonus bStr,1; bonus bInt,1; }
+1019,PECOPECO,PecoPeco,632,9014,10010,537,80,60,30,100,250,20,1000,150,1,0,400,500,800,{ petskillbonus bSpeedRate,25,20,20; },{ bonus bMaxHP,150; bonus bMaxSP,-10; }
+1056,SMOKIE,Smokie,633,9015,10019,537,80,60,30,100,250,20,1000,150,1,0,600,600,100,{ petskillbonus bPerfectHide,1,3600,0; },{ bonus bAgi,1; bonus bFlee2,1; }
+1057,YOYO,Yoyo,634,9016,10018,532,80,60,20,100,250,20,1000,150,1,0,300,800,400,{ petloot 20; },{ bonus bCritical,3; bonus bLuk,-1; }
+1023,ORK_WARRIOR,Orc Warrior,635,9017,10009,537,80,60,20,100,250,20,500,150,1,0,600,200,300,{ petskillattack2 "NPC_PIERCINGATT",100,1,0,10; },{ bonus bAtk,10; bonus bDef,-3; }
+1026,MUNAK,Munak,636,9018,10008,537,80,60,20,100,250,20,500,150,0,0,300,750,300,{ petskillattack2 "NPC_DARKNESSATTACK",444,1,0,10; },{ bonus bInt,1; bonus bDef,1; }
+1110,DOKEBI,Dokebi,637,9019,10005,537,80,60,20,100,250,20,500,150,0,0,300,300,800,{ petskillattack "BS_HAMMERFALL",1,0,10; },{ bonus bMatkRate,1; bonus bAtkRate,-1; }
+1170,SOHEE,Sohee,638,9020,10016,537,80,60,10,100,250,20,500,150,0,0,100,1000,200,{ petheal 400,60,33,100; },{ bonus bStr,1; bonus bDex,1; }
+1029,ISIS,Isis,639,9021,10006,537,80,60,10,100,250,20,500,150,0,0,650,450,150,{ petskillsupport "PR_MAGNIFICAT",2,60,50,50; },{ bonus bMatkRate,-1; bonus bAtkRate,1; }
+1155,PETIT,Petite,640,9022,10011,537,80,60,20,100,250,20,500,150,0,0,800,400,100,{ petskillattack2 "WZ_HEAVENDRIVE",500,1,0,10; },{ bonus bDef,-2; bonus bMdef,-2; bonus bAspdRate,1; }
+1109,DEVIRUCHI,Deviruchi,641,9023,10004,711,80,60,10,100,250,20,500,150,0,0,800,200,100,{ petskillbonus bAgiDexStr,6,20,40; },{ bonus bMatkRate,1; bonus bAtkRate,1; bonus bMaxHPrate,-3; bonus bMaxSPrate,-3; }
+1101,BAPHOMET_,Baphomet Jr.,642,9024,10001,518,80,60,10,100,250,20,200,150,0,0,1000,100,200,{ petskillattack2 "NPC_DARKNESSATTACK",1776,4,0,5; },{ bonus bDef,1; bonus bMdef,1; bonus2 bResEff,Eff_Stun,-100; }
+1188,BON_GUN,Bon Gun,659,9025,10020,537,80,60,30,100,250,20,500,150,1,0,600,200,400,{ petskillattack2 "NPC_DARKNESSATTACK",555,1,1,1; },{ bonus bVit,1; bonus2 bResEff,Eff_Stun,100; }
+1200,ZHERLTHSH,Zealotus,660,9026,0,929,80,60,10,100,250,20,300,150,0,0,1000,100,500,{ petskillattack "AS_SONICBLOW",1,0,3; },{ bonus2 bAddRace,RC_Demihuman,2; bonus2 bMagicAddRace,RC_DemiHuman,2; }
+1275,ALICE,Alice,661,9027,0,504,80,60,20,100,250,20,800,150,0,0,100,1000,200,{ petskillsupport "AL_HEAL",5,60,25,100; },{ bonus bMdef,1; bonus2 bSubRace,RC_DemiHuman,1; }
+1815,EVENT_RICECAKE,Rice Cake,0,9028,0,511,80,60,50,100,250,20,2000,150,1,0,500,500,200,{ petskillsupport "CR_DEFENDER",3,240,50,100; },{ bonus2 bSubEle,Ele_Neutral,1; bonus bMaxHPrate,-1; }
+1245,GOBLINE_XMAS,Christmas Goblin,12225,9029,0,911,80,60,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "MG_SIGHT",5,5,5; },{ bonus bMaxHP,30; bonus2 bSubEle,Ele_Water,1; }
+
+1519,CHUNG_E,Green Maiden,12395,9030,0,6115,80,60,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "CR_SHIELDCHARGE",5,5,5; },{ bonus bDef,1; bonus2 bSubRace,RC_DemiHuman,1; }
+1879,ECLIPSE_P,Spring Rabbit,0,9031,0,7766,80,60,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "TF_THROWSTONE",1,5,5; },{}
+1122,GOBLIN_1,Goblin,14569,9032,0,7821,80,60,50,100,250,20,800,150,0,0,300,300,800,{ petskillattack "NPC_WINDATTACK",5,5,5; },{}
+1123,GOBLIN_2,Goblin,14570,9033,0,7821,80,60,50,100,250,20,800,150,0,0,300,300,800,{ petskillattack "NPC_FIREATTACK",5,5,5; },{}
+1125,GOBLIN_4,Goblin,14571,9034,0,7821,80,60,50,100,250,20,800,150,0,0,300,300,800,{ petskillattack "NPC_GROUNDATTACK",5,5,5; },{}
+1385,DELETER_,Deleter,14572,9035,0,7822,80,60,20,100,250,20,800,150,0,0,300,300,800,{ petskillattack "SM_MAGNUM",5,5,5; },{}
+1382,DIABOLIC,Diabolic,14573,9036,0,7823,80,60,10,100,250,20,800,150,0,0,300,300,800,{ petskillattack "WZ_METEOR",2,5,5; },{}
+1208,WANDER_MAN,Wanderer,14574,9037,0,7824,80,60,20,100,250,20,800,150,0,0,300,300,800,{ petskillattack "NPC_UNDEADATTACK",5,5,5; },{ bonus bAgi,3; bonus bDex,1; }
+
+1963,P_CHUNG_E,New Year Doll,0,9038,0,554,80,60,30,100,250,20,800,150,0,0,300,300,800,{ petskillattack "CR_SHIELDCHARGE",5,5,5; },{}
+
+// New pets JapanRO Mobile
+1040,GOLEM,Golem,12371,9053,10035,6111,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus bMaxHP,100; bonus bFlee,-5; }
+1143,MARIONETTE,Marionette,12361,9043,10025,6098,80,60,10,100,250,20,500,150,0,0,300,300,800,{},{ bonus bSPrecovRate,3; }
+1148,MEDUSA,Medusa,12368,9050,10032,6108,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus bVit,1; bonus2 bResEff,Eff_Stone,500; }
+1179,WHISPER,Whisper,12363,9045,10027,6100,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus bFlee,7; bonus bDef,-3; }
+1299,GOBLIN_LEADER,Goblin Leader,12364,9046,10028,6104,80,60,10,100,250,20,50,150,0,0,300,300,800,{},{ bonus2 bAddRace,RC_DemiHuman,3; }
+1370,SUCCUBUS,Succubus,12373,9055,10037,6113,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus2 bHpDrainRate,50,5; }
+1374,INCUBUS,Incubus,12370,9052,10034,6110,80,60,10,100,250,20,50,150,0,0,300,300,800,{},{ bonus bMaxSPRate,3; }
+1379,NIGHTMARE_TERROR,Nightmare Terror,12372,9054,10036,6112,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus2 bResEff,Eff_Sleep,10000; }
+1401,SHINOBI,Shinobi,12362,9044,10026,6099,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus bAgi,2; }
+1404,MIYABI_NINGYO,Miyabi Doll,12366,9048,10030,6106,80,60,15,100,250,20,200,150,0,0,300,300,800,{},{ bonus bInt,1; bonus bCastrate,-3; }
+1416,WICKED_NYMPH,Evil Nymph,12365,9047,10029,6105,80,60,15,100,250,20,500,150,0,0,300,300,800,{},{ bonus bMaxSP,30; bonus bSPrecovRate,5; }
+1495,STONE_SHOOTER,Stone Shooter,12369,9051,10033,6109,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus2 bSubEle,Ele_Fire,3; }
+1504,DULLAHAN,Dullahan,12367,9049,10031,6107,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus bCritAtkRate,5; }
+1505,LOLI_RURI,Loli Ruri,12360,9042,10024,6097,80,60,15,100,250,20,200,150,0,0,300,300,800,{},{ bonus bMaxHPRate,3; bonus3 bAutoSpellWhenHit,"AL_HEAL",1,10; }
+1513,CIVIL_SERVANT,Mao Guai,12358,9040,10022,6095,80,60,10,100,250,20,500,150,0,0,300,300,800,{},{ bonus bMaxSP,10; }
+1586,LEAF_CAT,Leaf Cat,12359,9041,10023,6096,80,60,20,100,250,20,200,150,0,0,300,300,800,{},{ bonus2 bSubRace,RC_Brute,3; }
+1630,BACSOJIN_,White Lady,12357,9039,10021,6094,80,60,10,100,250,20,2000,150,0,0,300,300,800,{},{}
+1837,IMP,Fire Imp,12374,9056,10038,6114,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus2 bSubEle,Ele_Fire,2; bonus2 bAddEle,Ele_Fire,2; }
+
+// Brasilis Quest - Suspicious Beach [UNHATCHABLE]
+2057,E_CRAMP,Strange Cramp,12408,6221,0,0,0,0,0,0,0,0,50,0,0,0,350,400,800,{},{} // kRO version
+2081,E_HYDRA,Strange Hydra,12408,6221,0,0,0,0,0,0,0,0,50,0,0,0,350,400,800,{},{} // iRO/cRO version
+
+// New pets (FIX ME: pet bonuses for 2210 and 2313 do not require loyalty)
+//2200,J_TAINI,Tiny,0,9057,0,512,80,60,10,100,250,20,0,150,1,0,300,300,800,{},{}
+//2210,XMAS_LUNATIC,Christmas Snow Rabbit,0,9058,0,529,80,60,10,100,250,20,0,150,1,0,300,300,800,{},{ bonus2 bExpAddRace,RC_All,5; }
+//2313,TIKBALANG,Tikbalang,12699,9059,0,528,80,60,10,100,250,20,1000,150,1,0,300,300,800,{},{ bonus2 bAddDamageClass,2320,10; bonus2 bAddDamageClass,2321,10; bonus2 bAddDamageClass,2322,10; bonus2 bAddDamageClass,2317,10; bonus2 bAddDamageClass,2318,10; bonus2 bAddDamageClass,2327,10; bonus2 bAddDamageClass,2319,10; bonus2 bAddDamageClass,2333,10; bonus2 bAddDamageClass,2332,10; }
+1242,MARIN,Marin,12789,9061,10039,6534,80,60,50,100,250,20,2000,150,1,0,300,300,800,{},{}
+//2398,LITTLE_PORING,Novice Poring,12846,9062,0,531,80,60,1000,0,250,0,5000,150,0,0,300,300,800,{},{ bonus bHPrecovRate,50; }

+ 3 - 30
db/pet_db.txt → db/re/pet_db.txt

@@ -28,35 +28,8 @@
 //NOTE: The max value (100%) of attack_rate, defense_rate & change_target_rate is 10000.
 //NOTE: The max value (100%) of attack_rate, defense_rate & change_target_rate is 10000.
 
 
 //In theory you can use any valid script, but it is run only once upon pet
 //In theory you can use any valid script, but it is run only once upon pet
-//loading, so it is recommended you use the specific pet scripts:
-
-//petskillattack skillid, skilllv, rate, bonusrate
-//Skill attack that triggers while the pet is attacking. Rate is the base
-//chance of execution per attack. Bonusrate is an additional success rate when
-//intimacy reaches max.
-
-//petskillattack2 skillid, damage, hits, rate, bonusrate
-//Same as petskillattack, but the damage and number of hits is fixed
-//the damage specified is total, not per hit.
-
-//petskillsupport skillid, skilllv, delay, hp%, sp%
-//Casts a support skill when the health levels are below the specified hp% and
-//sp%. Delay is the minimum time in seconds before the skill can be cast again
-
-//petheal amount, delay, hp%, sp%
-//Similar to petskillsupport, but the skill is fixed to heal (28) and the
-//heal-amount is fixed to the value given.
-
-//petrecovery type, delay: Cures the "type" status effect after "delay" seconds
-
-//petskillbonus type, value, duration, delay
-//Gives bonus stats. Type is the stat to increase (bStr, bLuk), value is the
-//amount by which it is increased, duration signals how long the bonus lasts
-//delay is the time elapsed after the bonus ends and before it starts again.
-
-//A single pet can have petloot, petskillbonus, petskillattack (or
-//petskillattack2) and petskillsupport (or petheal) at the same time,
-//but only one of each.
+//loading, so it is recommended you use the specific pet scripts.
+//Please see "The Pet AI commands" in 'doc/script_commands.txt'.
 
 
 1002,PORING,Poring,619,9001,10013,531,80,60,50,100,250,20,2000,150,1,0,350,400,800,{ petloot 10; },{ bonus bLuk,2; bonus bCritical,1; }
 1002,PORING,Poring,619,9001,10013,531,80,60,50,100,250,20,2000,150,1,0,350,400,800,{ petloot 10; },{ bonus bLuk,2; bonus bCritical,1; }
 1113,DROPS,Drops,620,9002,10013,508,80,60,40,100,250,20,1500,150,1,0,300,400,500,{ petloot 10; },{ bonus bHit,3; bonus bAtk,3; }
 1113,DROPS,Drops,620,9002,10013,508,80,60,40,100,250,20,1500,150,1,0,300,400,500,{ petloot 10; },{ bonus bHit,3; bonus bAtk,3; }
@@ -69,7 +42,7 @@
 1167,SAVAGE_BABE,Savage Babe,627,9009,10015,537,80,60,40,100,250,20,1500,150,0,0,500,500,200,{ petskillbonus bVit,4,10,50; },{ bonus bVit,1; bonus bMaxHP,50; }
 1167,SAVAGE_BABE,Savage Babe,627,9009,10015,537,80,60,40,100,250,20,1500,150,0,0,500,500,200,{ petskillbonus bVit,4,10,50; },{ bonus bVit,1; bonus bMaxHP,50; }
 1107,DESERT_WOLF_B,Baby Desert Wolf,628,9010,10003,537,80,60,40,100,250,20,1000,150,0,0,400,400,400,{ petskillattack "SM_PROVOKE",1,0,5;},{ bonus bInt,1; bonus bMaxSP,50; }
 1107,DESERT_WOLF_B,Baby Desert Wolf,628,9010,10003,537,80,60,40,100,250,20,1000,150,0,0,400,400,400,{ petskillattack "SM_PROVOKE",1,0,5;},{ bonus bInt,1; bonus bMaxSP,50; }
 1052,ROCKER,Rocker,629,9011,10014,537,80,60,30,100,250,20,1500,150,0,0,350,350,600,{ petskillbonus bAllStats,1,10,50; },{ bonus bHPrecovRate,5; bonus bMaxHP,25; }
 1052,ROCKER,Rocker,629,9011,10014,537,80,60,30,100,250,20,1500,150,0,0,350,350,600,{ petskillbonus bAllStats,1,10,50; },{ bonus bHPrecovRate,5; bonus bMaxHP,25; }
-1014,SPORE,Spore,630,9012,10017,537,80,60,30,100,250,20,1500,150,0,0,350,500,500,{ petrecovery SC_Poison,60; },{ bonus bHit,5; bonus bAtk,-2; }
+1014,SPORE,Spore,630,9012,10017,537,80,60,30,100,250,20,1500,150,0,0,350,500,500,{ petrecovery SC_POISON,60; },{ bonus bHit,5; bonus bAtk,-2; }
 1077,POISON_SPORE,Poison Spore,631,9013,10017,537,80,60,20,100,250,20,1000,150,0,0,600,200,400,{ petskillattack "NPC_POISON",20,0,10; },{ bonus bStr,1; bonus bInt,1; }
 1077,POISON_SPORE,Poison Spore,631,9013,10017,537,80,60,20,100,250,20,1000,150,0,0,600,200,400,{ petskillattack "NPC_POISON",20,0,10; },{ bonus bStr,1; bonus bInt,1; }
 1019,PECOPECO,PecoPeco,632,9014,10010,537,80,60,30,100,250,20,1000,150,1,0,400,500,800,{ petskillbonus bSpeedRate,25,20,20; },{ bonus bMaxHP,150; bonus bMaxSP,-10; }
 1019,PECOPECO,PecoPeco,632,9014,10010,537,80,60,30,100,250,20,1000,150,1,0,400,500,800,{ petskillbonus bSpeedRate,25,20,20; },{ bonus bMaxHP,150; bonus bMaxSP,-10; }
 1056,SMOKIE,Smokie,633,9015,10019,537,80,60,30,100,250,20,1000,150,1,0,600,600,100,{ petskillbonus bPerfectHide,1,3600,0; },{ bonus bAgi,1; bonus bFlee2,1; }
 1056,SMOKIE,Smokie,633,9015,10019,537,80,60,30,100,250,20,1000,150,1,0,600,600,100,{ petskillbonus bPerfectHide,1,3600,0; },{ bonus bAgi,1; bonus bFlee2,1; }

+ 13 - 6
doc/script_commands.txt

@@ -1044,6 +1044,7 @@ From here on, we will have the commands sorted as follow:
 8.- Quest Log commands.
 8.- Quest Log commands.
 9.- Battleground commands.
 9.- Battleground commands.
 10.- Pet commands.
 10.- Pet commands.
+10.1.- The Pet AI commands.
 11.- Homunculus commands.
 11.- Homunculus commands.
 12.- Mercenary commands.
 12.- Mercenary commands.
 13.- Party commands.
 13.- Party commands.
@@ -8048,8 +8049,10 @@ currently has active. Valid types are:
 
 
 ---------------------------------------
 ---------------------------------------
 
 
-* The Pet AI commands
-  -------------------
+=============================
+|10.1.- The Pet AI commands.|
+=============================
+---------------------------------------
 
 
 These commands will only work if the invoking character has a pet, and are meant 
 These commands will only work if the invoking character has a pet, and are meant 
 to be executed from pet scripts. They will modify the pet AI decision-making for 
 to be executed from pet scripts. They will modify the pet AI decision-making for 
@@ -8086,9 +8089,11 @@ Nobody tried this before, so you're essentially on your own here.
 
 
 *petskillbonus <bonus type>,<value>,<duration>,<delay>;
 *petskillbonus <bonus type>,<value>,<duration>,<delay>;
 
 
-This command will make the pet give a bonus to the owner's stat (bonus type -
-bInt,bVit,bDex,bAgi,bLuk,bStr,bSpeedRate - for a full list, see the values 
-starting with 'b' in 'db/const.txt')
+This command will make the pet give a bonus to the owner's stat in certain
+duration in seconds and will be repeated for certain delay in seconds.
+
+For a full bonus list, see 'doc/item_bonus.txt'
+NOTE: Currently ONLY supported for bonuses that used by 'bonus' script.
 
 
 ---------------------------------------
 ---------------------------------------
 
 
@@ -8117,7 +8122,7 @@ This will make the pet use a specified support skill on the owner whenever the
 HP and SP are below the given percent values, with a specified delay time 
 HP and SP are below the given percent values, with a specified delay time 
 between activations. The skill numbers are as per 'db/(pre-)re/skill_db.txt'.
 between activations. The skill numbers are as per 'db/(pre-)re/skill_db.txt'.
 'petheal' works the same as 'petskillsupport' but has the skill ID hard-coded to 
 'petheal' works the same as 'petskillsupport' but has the skill ID hard-coded to 
-28 (Heal). This command is deprecated.
+AL_HEAL (ID:28). This command is deprecated.
 It's not quite certain who's stats will be used for the skills cast, the 
 It's not quite certain who's stats will be used for the skills cast, the 
 character's or the pets. Probably, Skotlex can answer that question.
 character's or the pets. Probably, Skotlex can answer that question.
 
 
@@ -8133,6 +8138,8 @@ owner is currently fighting. Skill IDs and levels are as per 'petskillsupport'.
 'petskillattack2' will make the pet cast the skill with a fixed amount of damage 
 'petskillattack2' will make the pet cast the skill with a fixed amount of damage 
 inflicted and the specified number of attacks.
 inflicted and the specified number of attacks.
 
 
+Value of 'rate' is between 1 and 100. 100 = 100%
+
 ---------------------------------------
 ---------------------------------------
 
 
 ===========================
 ===========================

+ 2 - 1
src/map/battle.c

@@ -2017,7 +2017,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
  *	Refined and optimized by helvetica
  *	Refined and optimized by helvetica
   *	flag - see e_battle_flag
   *	flag - see e_battle_flag
  */
  */
-static bool is_infinite_defense(struct block_list *target, int flag)
+bool is_infinite_defense(struct block_list *target, int flag)
 {
 {
 	struct status_data *tstatus = status_get_status_data(target);
 	struct status_data *tstatus = status_get_status_data(target);
 
 
@@ -7939,6 +7939,7 @@ static const struct _battle_data {
 	{ "snap_dodge",                         &battle_config.snap_dodge,                      0,      0,      1,              },
 	{ "snap_dodge",                         &battle_config.snap_dodge,                      0,      0,      1,              },
 	{ "stormgust_knockback",                &battle_config.stormgust_knockback,             1,      0,      1,              },
 	{ "stormgust_knockback",                &battle_config.stormgust_knockback,             1,      0,      1,              },
 	{ "default_fixed_castrate",             &battle_config.default_fixed_castrate,          20,     0,      100,            },
 	{ "default_fixed_castrate",             &battle_config.default_fixed_castrate,          20,     0,      100,            },
+	{ "pet_ignore_infinite_def",            &battle_config.pet_ignore_infinite_def,         0,      0,      1,              },
 };
 };
 
 
 #ifndef STATS_OPT_OUT
 #ifndef STATS_OPT_OUT

+ 4 - 0
src/map/battle.h

@@ -113,6 +113,9 @@ int battle_check_target(struct block_list *src, struct block_list *target,int fl
 bool battle_check_range(struct block_list *src,struct block_list *bl,int range);
 bool battle_check_range(struct block_list *src,struct block_list *bl,int range);
 
 
 void battle_consume_ammo(struct map_session_data* sd, int skill, int lv);
 void battle_consume_ammo(struct map_session_data* sd, int skill, int lv);
+
+bool is_infinite_defense(struct block_list *target, int flag);
+
 // Settings
 // Settings
 
 
 #define MIN_HAIR_STYLE battle_config.min_hair_style
 #define MIN_HAIR_STYLE battle_config.min_hair_style
@@ -580,6 +583,7 @@ extern struct Battle_Config
 	int snap_dodge; // Enable or disable dodging damage snapping away [csnv]
 	int snap_dodge; // Enable or disable dodging damage snapping away [csnv]
 	int stormgust_knockback;
 	int stormgust_knockback;
 	int default_fixed_castrate;
 	int default_fixed_castrate;
+	int pet_ignore_infinite_def; // Makes fixed damage of petskillattack2 ignores infinite defense
 } battle_config;
 } battle_config;
 
 
 void do_init_battle(void);
 void do_init_battle(void);

+ 13 - 21
src/map/pet.c

@@ -463,7 +463,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *pet)
 		run_script(pet_db[i].pet_script,0,sd->bl.id,0);
 		run_script(pet_db[i].pet_script,0,sd->bl.id,0);
 
 
 	if( pd->petDB ) {
 	if( pd->petDB ) {
-		if( pd->petDB->equip_script )
+		if( pd->petDB->pet_loyal_script )
 			status_calc_pc(sd,SCO_NONE);
 			status_calc_pc(sd,SCO_NONE);
 
 
 		if( battle_config.pet_hungry_delay_rate != 100 )
 		if( battle_config.pet_hungry_delay_rate != 100 )
@@ -1372,7 +1372,6 @@ int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data)
 	if(pd->bonus->timer != tid) {
 	if(pd->bonus->timer != tid) {
 		ShowError("pet_skill_bonus_timer %d != %d\n",pd->bonus->timer,tid);
 		ShowError("pet_skill_bonus_timer %d != %d\n",pd->bonus->timer,tid);
 		pd->bonus->timer = INVALID_TIMER;
 		pd->bonus->timer = INVALID_TIMER;
-
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -1385,7 +1384,6 @@ int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data)
 		timer = pd->bonus->duration*1000;	// the duration for pet bonuses to be in effect
 		timer = pd->bonus->duration*1000;	// the duration for pet bonuses to be in effect
 	} else { //Lost pet...
 	} else { //Lost pet...
 		pd->bonus->timer = INVALID_TIMER;
 		pd->bonus->timer = INVALID_TIMER;
-
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -1396,7 +1394,6 @@ int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data)
 
 
 	// wait for the next timer
 	// wait for the next timer
 	pd->bonus->timer=add_timer(tick+timer,pet_skill_bonus_timer,sd->bl.id,0);
 	pd->bonus->timer=add_timer(tick+timer,pet_skill_bonus_timer,sd->bl.id,0);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1421,7 +1418,6 @@ int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data)
 
 
 	if(pd->recovery->timer != tid) {
 	if(pd->recovery->timer != tid) {
 		ShowError("pet_recovery_timer %d != %d\n",pd->recovery->timer,tid);
 		ShowError("pet_recovery_timer %d != %d\n",pd->recovery->timer,tid);
-
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -1434,7 +1430,6 @@ int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data)
 	}
 	}
 
 
 	pd->recovery->timer = INVALID_TIMER;
 	pd->recovery->timer = INVALID_TIMER;
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1458,7 +1453,6 @@ int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data)
 
 
 	if(pd->s_skill->timer != tid) {
 	if(pd->s_skill->timer != tid) {
 		ShowError("pet_heal_timer %d != %d\n",pd->s_skill->timer,tid);
 		ShowError("pet_heal_timer %d != %d\n",pd->s_skill->timer,tid);
-
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -1470,7 +1464,6 @@ int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data)
 		(rate = (pd->ud.skilltimer != INVALID_TIMER)) //Another skill is in effect
 		(rate = (pd->ud.skilltimer != INVALID_TIMER)) //Another skill is in effect
 	) {  //Wait (how long? 1 sec for every 10% of remaining)
 	) {  //Wait (how long? 1 sec for every 10% of remaining)
 		pd->s_skill->timer=add_timer(gettick()+(rate>10?rate:10)*100,pet_heal_timer,sd->bl.id,0);
 		pd->s_skill->timer=add_timer(gettick()+(rate>10?rate:10)*100,pet_heal_timer,sd->bl.id,0);
-
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -1479,7 +1472,6 @@ int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data)
 	clif_skill_nodamage(&pd->bl,&sd->bl,AL_HEAL,pd->s_skill->lv,1);
 	clif_skill_nodamage(&pd->bl,&sd->bl,AL_HEAL,pd->s_skill->lv,1);
 	status_heal(&sd->bl, pd->s_skill->lv,0, 0);
 	status_heal(&sd->bl, pd->s_skill->lv,0, 0);
 	pd->s_skill->timer = add_timer(tick+pd->s_skill->delay*1000,pet_heal_timer,sd->bl.id,0);
 	pd->s_skill->timer = add_timer(tick+pd->s_skill->delay*1000,pet_heal_timer,sd->bl.id,0);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1505,7 +1497,6 @@ int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data)
 
 
 	if(pd->s_skill->timer != tid) {
 	if(pd->s_skill->timer != tid) {
 		ShowError("pet_skill_support_timer %d != %d\n",pd->s_skill->timer,tid);
 		ShowError("pet_skill_support_timer %d != %d\n",pd->s_skill->timer,tid);
-
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -1514,7 +1505,6 @@ int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data)
 	if (DIFF_TICK(pd->ud.canact_tick, tick) > 0) {
 	if (DIFF_TICK(pd->ud.canact_tick, tick) > 0) {
 		//Wait until the pet can act again.
 		//Wait until the pet can act again.
 		pd->s_skill->timer=add_timer(pd->ud.canact_tick,pet_skill_support_timer,sd->bl.id,0);
 		pd->s_skill->timer=add_timer(pd->ud.canact_tick,pet_skill_support_timer,sd->bl.id,0);
-
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -1535,7 +1525,6 @@ int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data)
 		unit_skilluse_pos(&pd->bl, sd->bl.x, sd->bl.y, pd->s_skill->id, pd->s_skill->lv);
 		unit_skilluse_pos(&pd->bl, sd->bl.x, sd->bl.y, pd->s_skill->id, pd->s_skill->lv);
 	else
 	else
 		unit_skilluse_id(&pd->bl, sd->bl.id, pd->s_skill->id, pd->s_skill->lv);
 		unit_skilluse_id(&pd->bl, sd->bl.id, pd->s_skill->id, pd->s_skill->lv);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1544,7 +1533,10 @@ int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data)
  */
  */
 void read_petdb()
 void read_petdb()
 {
 {
-	char* filename[] = {"pet_db.txt",DBIMPORT"/pet_db.txt"};
+	char* filename[] = {
+		DBPATH"pet_db.txt",
+		DBIMPORT"/pet_db.txt"
+	};
 	unsigned short nameid;
 	unsigned short nameid;
 	int i,j;
 	int i,j;
 
 
@@ -1555,9 +1547,9 @@ void read_petdb()
 			pet_db[j].pet_script = NULL;
 			pet_db[j].pet_script = NULL;
 		}
 		}
 
 
-		if( pet_db[j].equip_script ) {
-			script_free_code(pet_db[j].equip_script);
-			pet_db[j].pet_script = NULL;
+		if( pet_db[j].pet_loyal_script ) {
+			script_free_code(pet_db[j].pet_loyal_script);
+			pet_db[j].pet_loyal_script = NULL;
 		}
 		}
 	}
 	}
 
 
@@ -1670,13 +1662,13 @@ void read_petdb()
 			pet_db[j].defence_attack_rate=atoi(str[18]);
 			pet_db[j].defence_attack_rate=atoi(str[18]);
 			pet_db[j].change_target_rate=atoi(str[19]);
 			pet_db[j].change_target_rate=atoi(str[19]);
 			pet_db[j].pet_script = NULL;
 			pet_db[j].pet_script = NULL;
-			pet_db[j].equip_script = NULL;
+			pet_db[j].pet_loyal_script = NULL;
 
 
 			if( *str[20] )
 			if( *str[20] )
 				pet_db[j].pet_script = parse_script(str[20], filename[i], lines, 0);
 				pet_db[j].pet_script = parse_script(str[20], filename[i], lines, 0);
 
 
 			if( *str[21] )
 			if( *str[21] )
-				pet_db[j].equip_script = parse_script(str[21], filename[i], lines, 0);
+				pet_db[j].pet_loyal_script = parse_script(str[21], filename[i], lines, 0);
 
 
 			j++;
 			j++;
 			entries++;
 			entries++;
@@ -1723,9 +1715,9 @@ void do_final_pet(void)
 			pet_db[i].pet_script = NULL;
 			pet_db[i].pet_script = NULL;
 		}
 		}
 
 
-		if( pet_db[i].equip_script ) {
-			script_free_code(pet_db[i].equip_script);
-			pet_db[i].equip_script = NULL;
+		if( pet_db[i].pet_loyal_script ) {
+			script_free_code(pet_db[i].pet_loyal_script);
+			pet_db[i].pet_loyal_script = NULL;
 		}
 		}
 	}
 	}
 
 

+ 30 - 26
src/map/pet.h

@@ -7,28 +7,31 @@
 #define MAX_PET_DB	300
 #define MAX_PET_DB	300
 #define MAX_PETLOOT_SIZE	30
 #define MAX_PETLOOT_SIZE	30
 
 
+/// Pet DB
 struct s_pet_db {
 struct s_pet_db {
-	short class_;
-	char name[NAME_LENGTH],jname[NAME_LENGTH];
-	short itemID;
-	short EggID;
-	short AcceID;
-	short FoodID;
-	int fullness;
-	int hungry_delay;
-	int r_hungry;
-	int r_full;
-	int intimate;
-	int die;
-	int capture;
-	int speed;
-	char s_perfor;
-	int talk_convert_class;
-	int attack_rate;
-	int defence_attack_rate;
-	int change_target_rate;
-	struct script_code *equip_script;
-	struct script_code *pet_script;
+	short class_; ///< Monster ID
+	char name[NAME_LENGTH], ///< AEGIS name
+		jname[NAME_LENGTH]; ///< English name
+	short itemID; ///< Lure ID
+	short EggID; ///< Egg ID
+	short AcceID; ///< Accessory ID
+	short FoodID; ///< Food ID
+	int fullness; ///< Amount of hunger decresed each hungry_delay interval
+	int hungry_delay; ///< Hunger value decrease each x seconds
+	int r_hungry; ///< Intimacy increased after feeding
+	int r_full; ///< Intimacy reduced when over-fed
+	int intimate; ///< Initial intimacy value
+	int die; ///< Intimacy decreased when die
+	int capture; ///< Capture success rate 1000 = 100%
+	int speed; ///< Walk speed
+	char s_perfor; ///< Special performance
+	int talk_convert_class; ///< Disables pet talk (instead of talking they emote  with /!.) (?)
+	int attack_rate; ///< Rate of which the pet will attack (requires at least pet_support_min_friendly intimacy).
+	int defence_attack_rate; ///< Rate of which the pet will retaliate when master is being attacked (requires at least pet_support_min_friendly intimacy).
+	int change_target_rate; ///< Rate of which the pet will change its attack target.
+	struct script_code
+		*pet_script, ///< Script since pet hatched
+		*pet_loyal_script; ///< Script when pet is loyal
 };
 };
 extern struct s_pet_db pet_db[MAX_PET_DB];
 extern struct s_pet_db pet_db[MAX_PET_DB];
 
 
@@ -42,15 +45,16 @@ struct pet_recovery { //Stat recovery
 
 
 struct pet_bonus {
 struct pet_bonus {
 	unsigned short type; //bStr, bVit?
 	unsigned short type; //bStr, bVit?
-	unsigned short val;	//Qty
-	unsigned short duration; //in secs
-	unsigned short delay;	//Time before RENEWAL_CAST (secs)
+	unsigned short val;	//value
+	unsigned short duration; //in seconds
+	unsigned short delay;	//Time before re-effect the bonus in seconds
 	int timer;
 	int timer;
 };
 };
 
 
 struct pet_skill_attack { //Attack Skill
 struct pet_skill_attack { //Attack Skill
 	unsigned short id;
 	unsigned short id;
-	unsigned short lv;
+	unsigned short lv; // Skill level
+	unsigned short damage; // Fixed damage value of petskillattack2
 	unsigned short div_; //0 = Normal skill. >0 = Fixed damage (lv), fixed div_.
 	unsigned short div_; //0 = Normal skill. >0 = Fixed damage (lv), fixed div_.
 	unsigned short rate; //Base chance of skill ocurrance (10 = 10% of attacks)
 	unsigned short rate; //Base chance of skill ocurrance (10 = 10% of attacks)
 	unsigned short bonusrate; //How being 100% loyal affects cast rate (10 = At 1000 intimacy->rate+10%
 	unsigned short bonusrate; //How being 100% loyal affects cast rate (10 = At 1000 intimacy->rate+10%
@@ -87,7 +91,7 @@ struct pet_data {
 	} state;
 	} state;
 	int move_fail_count;
 	int move_fail_count;
 	unsigned int next_walktime,last_thinktime;
 	unsigned int next_walktime,last_thinktime;
-	short rate_fix;	//Support rate as modified by intimacy (1000 = 100%) [Skotlex]
+	unsigned short rate_fix;	//Support rate as modified by intimacy (1000 = 100%) [Skotlex]
 
 
 	struct pet_recovery* recovery;
 	struct pet_recovery* recovery;
 	struct pet_bonus* bonus;
 	struct pet_bonus* bonus;

+ 76 - 47
src/map/script.c

@@ -12719,13 +12719,12 @@ BUILDIN_FUNC(getequipcardid)
 BUILDIN_FUNC(petskillbonus)
 BUILDIN_FUNC(petskillbonus)
 {
 {
 	struct pet_data *pd;
 	struct pet_data *pd;
+	TBL_PC *sd = script_rid2sd(st);
 
 
-	TBL_PC *sd=script_rid2sd(st);
-
-	if(sd==NULL || sd->pd==NULL)
-		return 0;
+	if(sd == NULL || sd->pd == NULL)
+		return SCRIPT_CMD_FAILURE;
 
 
-	pd=sd->pd;
+	pd = sd->pd;
 	if (pd->bonus)
 	if (pd->bonus)
 	{ //Clear previous bonus
 	{ //Clear previous bonus
 		if (pd->bonus->timer != INVALID_TIMER)
 		if (pd->bonus->timer != INVALID_TIMER)
@@ -12733,13 +12732,13 @@ BUILDIN_FUNC(petskillbonus)
 	} else //init
 	} else //init
 		pd->bonus = (struct pet_bonus *) aMalloc(sizeof(struct pet_bonus));
 		pd->bonus = (struct pet_bonus *) aMalloc(sizeof(struct pet_bonus));
 
 
-	pd->bonus->type=script_getnum(st,2);
-	pd->bonus->val=script_getnum(st,3);
-	pd->bonus->duration=script_getnum(st,4);
-	pd->bonus->delay=script_getnum(st,5);
+	pd->bonus->type = script_getnum(st,2);
+	pd->bonus->val = script_getnum(st,3);
+	pd->bonus->duration = script_getnum(st,4);
+	pd->bonus->delay = script_getnum(st,5);
 
 
 	if (pd->state.skillbonus == 1)
 	if (pd->state.skillbonus == 1)
-		pd->state.skillbonus=0;	// waiting state
+		pd->state.skillbonus = 0;	// waiting state
 
 
 	// wait for timer to start
 	// wait for timer to start
 	if (battle_config.pet_equip_required && pd->pet.equip == 0)
 	if (battle_config.pet_equip_required && pd->pet.equip == 0)
@@ -13054,11 +13053,18 @@ BUILDIN_FUNC(petrecovery)
 {
 {
 	struct pet_data *pd;
 	struct pet_data *pd;
 	TBL_PC *sd=script_rid2sd(st);
 	TBL_PC *sd=script_rid2sd(st);
+	int sc;
 
 
-	if(sd==NULL || sd->pd==NULL)
-		return 0;
+	if(sd == NULL || sd->pd == NULL)
+		return SCRIPT_CMD_FAILURE;
 
 
-	pd=sd->pd;
+	sc = script_getnum(st,2);
+	if (sc <= SC_NONE || sc >= SC_MAX) {
+		ShowError("buildin_petrecovery: Invalid SC type: %d\n", sc);
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	pd = sd->pd;
 
 
 	if (pd->recovery)
 	if (pd->recovery)
 	{ //Halt previous bonus
 	{ //Halt previous bonus
@@ -13067,7 +13073,7 @@ BUILDIN_FUNC(petrecovery)
 	} else //Init
 	} else //Init
 		pd->recovery = (struct pet_recovery *)aMalloc(sizeof(struct pet_recovery));
 		pd->recovery = (struct pet_recovery *)aMalloc(sizeof(struct pet_recovery));
 
 
-	pd->recovery->type = (sc_type)script_getnum(st,2);
+	pd->recovery->type = (sc_type)sc;
 	pd->recovery->delay = script_getnum(st,3);
 	pd->recovery->delay = script_getnum(st,3);
 	pd->recovery->timer = INVALID_TIMER;
 	pd->recovery->timer = INVALID_TIMER;
 	return SCRIPT_CMD_SUCCESS;
 	return SCRIPT_CMD_SUCCESS;
@@ -13121,50 +13127,66 @@ BUILDIN_FUNC(petskillattack)
 {
 {
 	struct pet_data *pd;
 	struct pet_data *pd;
 	struct script_data *data;
 	struct script_data *data;
-	TBL_PC *sd=script_rid2sd(st);
+	TBL_PC *sd = script_rid2sd(st);
+	int id = 0;
 
 
-	if(sd==NULL || sd->pd==NULL)
-		return 0;
+	if(sd == NULL || sd->pd == NULL)
+		return SCRIPT_CMD_FAILURE;
 
 
-	pd=sd->pd;
+	data = script_getdata(st, 2);
+	get_val(st, data);
+	id = (data_isstring(data) ? skill_name2id(script_getstr(st,2)) : skill_get_index(script_getnum(st,2)));
+	if (!id) {
+		ShowError("buildin_petskillattack: Invalid skill defined!\n");
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	pd = sd->pd;
 	if (pd->a_skill == NULL)
 	if (pd->a_skill == NULL)
 		pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack));
 		pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack));
 
 
-	data = script_getdata(st, 2);
-	get_val(st, data); // Convert into value in case of a variable
-	pd->a_skill->id=( data_isstring(data) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) );
-	pd->a_skill->lv=script_getnum(st,3);
+	pd->a_skill->id = id;
+	pd->a_skill->damage = 0;
+	pd->a_skill->lv = (unsigned short)min(script_getnum(st,3), skill_get_max(pd->a_skill->id));
 	pd->a_skill->div_ = 0;
 	pd->a_skill->div_ = 0;
-	pd->a_skill->rate=script_getnum(st,4);
-	pd->a_skill->bonusrate=script_getnum(st,5);
+	pd->a_skill->rate = script_getnum(st,4);
+	pd->a_skill->bonusrate = script_getnum(st,5);
 	return SCRIPT_CMD_SUCCESS;
 	return SCRIPT_CMD_SUCCESS;
 }
 }
 
 
 /*==========================================
 /*==========================================
  * pet attack skills [Valaris]
  * pet attack skills [Valaris]
  *------------------------------------------*/
  *------------------------------------------*/
-/// petskillattack2 <skill id>,<level>,<div>,<rate>,<bonusrate>
-/// petskillattack2 "<skill name>",<level>,<div>,<rate>,<bonusrate>
+/// petskillattack2 <skill id>,<damage>,<div>,<rate>,<bonusrate>
+/// petskillattack2 "<skill name>",<damage>,<div>,<rate>,<bonusrate>
 BUILDIN_FUNC(petskillattack2)
 BUILDIN_FUNC(petskillattack2)
 {
 {
 	struct pet_data *pd;
 	struct pet_data *pd;
 	struct script_data *data;
 	struct script_data *data;
-	TBL_PC *sd=script_rid2sd(st);
+	TBL_PC *sd = script_rid2sd(st);
+	int id = 0;
 
 
-	if(sd==NULL || sd->pd==NULL)
-		return 0;
+	if(sd == NULL || sd->pd == NULL)
+		return SCRIPT_CMD_FAILURE;
 
 
-	pd=sd->pd;
+	data = script_getdata(st, 2);
+	get_val(st, data);
+	id = (data_isstring(data) ? skill_name2id(script_getstr(st,2)) : skill_get_index(script_getnum(st,2)));
+	if (!id) {
+		ShowError("buildin_petskillattack2: Invalid skill defined!\n");
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	pd = sd->pd;
 	if (pd->a_skill == NULL)
 	if (pd->a_skill == NULL)
 		pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack));
 		pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack));
 
 
-	data = script_getdata(st, 2);
-	get_val(st, data); // Convert into value in case of a variable
-	pd->a_skill->id=( data_isstring(data) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) );
-	pd->a_skill->lv=script_getnum(st,3);
+	pd->a_skill->id = id;
+	pd->a_skill->damage = script_getnum(st,3); // Fixed damage
+	pd->a_skill->lv = (unsigned short)skill_get_max(pd->a_skill->id); // Adjust to max skill level
 	pd->a_skill->div_ = script_getnum(st,4);
 	pd->a_skill->div_ = script_getnum(st,4);
-	pd->a_skill->rate=script_getnum(st,5);
-	pd->a_skill->bonusrate=script_getnum(st,6);
+	pd->a_skill->rate = script_getnum(st,5);
+	pd->a_skill->bonusrate = script_getnum(st,6);
 	return SCRIPT_CMD_SUCCESS;
 	return SCRIPT_CMD_SUCCESS;
 }
 }
 
 
@@ -13177,12 +13199,21 @@ BUILDIN_FUNC(petskillsupport)
 {
 {
 	struct pet_data *pd;
 	struct pet_data *pd;
 	struct script_data *data;
 	struct script_data *data;
-	TBL_PC *sd=script_rid2sd(st);
+	TBL_PC *sd = script_rid2sd(st);
+	int id = 0;
 
 
-	if(sd==NULL || sd->pd==NULL)
-		return 0;
+	if(sd == NULL || sd->pd == NULL)
+		return SCRIPT_CMD_FAILURE;
 
 
-	pd=sd->pd;
+	data = script_getdata(st, 2);
+	get_val(st, data);
+	id = (data_isstring(data) ? skill_name2id(script_getstr(st,2)) : skill_get_index(script_getnum(st,2)));
+	if (!id) {
+		ShowError("buildin_petskillsupport: Invalid skill defined!\n");
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	pd = sd->pd;
 	if (pd->s_skill)
 	if (pd->s_skill)
 	{ //Clear previous skill
 	{ //Clear previous skill
 		if (pd->s_skill->timer != INVALID_TIMER)
 		if (pd->s_skill->timer != INVALID_TIMER)
@@ -13195,13 +13226,11 @@ BUILDIN_FUNC(petskillsupport)
 	} else //init memory
 	} else //init memory
 		pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support));
 		pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support));
 
 
-	data = script_getdata(st, 2);
-	get_val(st, data); // Convert into value in case of a variable
-	pd->s_skill->id=( data_isstring(data) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) );
-	pd->s_skill->lv=script_getnum(st,3);
-	pd->s_skill->delay=script_getnum(st,4);
-	pd->s_skill->hp=script_getnum(st,5);
-	pd->s_skill->sp=script_getnum(st,6);
+	pd->s_skill->id = id;
+	pd->s_skill->lv = script_getnum(st,3);
+	pd->s_skill->delay = script_getnum(st,4);
+	pd->s_skill->hp = script_getnum(st,5);
+	pd->s_skill->sp = script_getnum(st,6);
 
 
 	//Use delay as initial offset to avoid skill/heal exploits
 	//Use delay as initial offset to avoid skill/heal exploits
 	if (battle_config.pet_equip_required && pd->pet.equip == 0)
 	if (battle_config.pet_equip_required && pd->pet.equip == 0)

+ 15 - 9
src/map/skill.c

@@ -2892,18 +2892,24 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 
 
 	dmg = battle_calc_attack(attack_type,src,bl,skill_id,skill_lv,flag&0xFFF);
 	dmg = battle_calc_attack(attack_type,src,bl,skill_id,skill_lv,flag&0xFFF);
 
 
-	//Skotlex: Adjusted to the new system
+	//! CHECKME: This check maybe breaks the battle_calc_attack, and maybe need better calculation.
+	// Adjusted to the new system [Skotlex]
 	if( src->type == BL_PET ) { // [Valaris]
 	if( src->type == BL_PET ) { // [Valaris]
 		struct pet_data *pd = (TBL_PET*)src;
 		struct pet_data *pd = (TBL_PET*)src;
-		if (pd->a_skill && pd->a_skill->div_ && pd->a_skill->id == skill_id) {
-			int element = skill_get_ele(skill_id, skill_lv);
-			/*if (skill_id == -1) Does it ever worked?
-				element = sstatus->rhw.ele;*/
-			if (element != ELE_NEUTRAL || !(battle_config.attack_attr_none&BL_PET))
-				dmg.damage=battle_attr_fix(src, bl, skill_lv, element, tstatus->def_ele, tstatus->ele_lv);
+		if (pd->a_skill && pd->a_skill->div_ && pd->a_skill->id == skill_id) { //petskillattack2
+			if (battle_config.pet_ignore_infinite_def || !is_infinite_defense(bl,dmg.flag)) {
+				int element = skill_get_ele(skill_id, skill_lv);
+				/*if (skill_id == -1) Does it ever worked?
+					element = sstatus->rhw.ele;*/
+				if (element != ELE_NEUTRAL || !(battle_config.attack_attr_none&BL_PET))
+					dmg.damage = battle_attr_fix(src, bl, pd->a_skill->damage, element, tstatus->def_ele, tstatus->ele_lv);
+				else
+					dmg.damage = pd->a_skill->damage; // Fixed damage
+				
+			}
 			else
 			else
-				dmg.damage= skill_lv;
-			dmg.damage2=0;
+				dmg.damage = 1*pd->a_skill->div_;
+			dmg.damage2 = 0;
 			dmg.div_= pd->a_skill->div_;
 			dmg.div_= pd->a_skill->div_;
 		}
 		}
 	}
 	}

+ 6 - 9
src/map/status.c

@@ -2481,9 +2481,9 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt)
  * @return 1
  * @return 1
  * @author [Skotlex]
  * @author [Skotlex]
  */
  */
-int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt)
+void status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt)
 {
 {
-	nullpo_ret(pd);
+	nullpo_retv(pd);
 
 
 	if (opt&SCO_FIRST) {
 	if (opt&SCO_FIRST) {
 		memcpy(&pd->status, &pd->db->status, sizeof(struct status_data));
 		memcpy(&pd->status, &pd->db->status, sizeof(struct status_data));
@@ -2540,11 +2540,8 @@ int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt)
 	}
 	}
 
 
 	// Support rate modifier (1000 = 100%)
 	// Support rate modifier (1000 = 100%)
-	pd->rate_fix = 1000*(pd->pet.intimate - battle_config.pet_support_min_friendly)/(1000- battle_config.pet_support_min_friendly) +500;
-	if(battle_config.pet_support_rate != 100)
-		pd->rate_fix = pd->rate_fix*battle_config.pet_support_rate/100;
-
-	return 1;
+	pd->rate_fix = min(1000 * (pd->pet.intimate - battle_config.pet_support_min_friendly) / (1000 - battle_config.pet_support_min_friendly) + 500, USHRT_MAX);
+	pd->rate_fix = min(apply_rate(pd->rate_fix, battle_config.pet_support_rate), USHRT_MAX);
 }
 }
 
 
 /**
 /**
@@ -3158,8 +3155,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
 
 
 	if( sd->pd ) { // Pet Bonus
 	if( sd->pd ) { // Pet Bonus
 		struct pet_data *pd = sd->pd;
 		struct pet_data *pd = sd->pd;
-		if( pd && pd->petDB && pd->petDB->equip_script && pd->pet.intimate >= battle_config.pet_equip_min_friendly )
-			run_script(pd->petDB->equip_script,0,sd->bl.id,0);
+		if( pd && pd->petDB && pd->petDB->pet_loyal_script && pd->pet.intimate >= battle_config.pet_equip_min_friendly )
+			run_script(pd->petDB->pet_loyal_script,0,sd->bl.id,0);
 		if( pd && pd->pet.intimate > 0 && (!battle_config.pet_equip_required || pd->pet.equip > 0) && pd->state.skillbonus == 1 && pd->bonus )
 		if( pd && pd->pet.intimate > 0 && (!battle_config.pet_equip_required || pd->pet.equip > 0) && pd->state.skillbonus == 1 && pd->bonus )
 			pc_bonus(sd,pd->bonus->type, pd->bonus->val);
 			pc_bonus(sd,pd->bonus->type, pd->bonus->val);
 	}
 	}

+ 1 - 1
src/map/status.h

@@ -2030,7 +2030,7 @@ void status_change_clear_buffs(struct block_list* bl, int type);
 
 
 void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt);
 void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt);
 int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt);
 int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt);
-int status_calc_pet_(struct pet_data* pd, enum e_status_calc_opt opt);
+void status_calc_pet_(struct pet_data* pd, enum e_status_calc_opt opt);
 int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt);
 int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt);
 int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt);
 int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt);
 int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt);
 int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt);