Pārlūkot izejas kodu

- Implemented new Pet Bonus System. Enjoy!! :D

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@13491 54d463be-8e91-2dee-dedb-b68131a5f0ec
zephyrus 16 gadi atpakaļ
vecāks
revīzija
d4c7aad803
9 mainītis faili ar 195 papildinājumiem un 116 dzēšanām
  1. 39 39
      db/pet_db.txt
  2. 2 1
      src/map/atcommand.c
  3. 1 0
      src/map/battle.c
  4. 6 2
      src/map/battle.h
  5. 9 8
      src/map/pc.c
  6. 124 55
      src/map/pet.c
  7. 3 1
      src/map/pet.h
  8. 7 7
      src/map/status.c
  9. 4 3
      src/map/unit.c

+ 39 - 39
db/pet_db.txt

@@ -30,43 +30,43 @@
 //but only one of each.
 
 //NOTE: The max value (100%) of attack_rate, defense_rate & change_target_rate is 10000.
-// 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
-1002,PORING,Poring,619,9001,10013,531,80,20,50,100,250,20,2000,400,1,0,350,400,800,{ petloot 10; }
-1011,CHONCHON,ChonChon,624,9006,10002,537,80,10,30,100,250,20,1500,200,1,0,500,500,250,{ petskillbonus bAgi,4,10,50; }
-1014,SPORE,Spore,630,9012,10017,537,80,20,30,100,250,20,1500,200,0,0,350,500,500,{ petrecovery SC_Poison,60; }
-1019,PECOPECO,PecoPeco,632,9014,10010,537,80,15,30,100,250,20,1000,200,1,0,400,500,800,{ petskillbonus bSpeedRate,25,20,20; }
-1023,ORC_WARRIOR,Orc Warrior,635,9017,10009,537,80,12,20,100,250,20,500,200,1,0,600,200,300,{ petskillattack2 "NPC_PIERCINGATT",100,1,0,10; }
-1026,MUNAK,Munak,636,9018,10008,537,80,20,20,100,250,20,500,100,0,0,300,750,300,{ petskillattack2 "NPC_DARKNESSATTACK",444,1,0,10; }
-1029,ISIS,Isis,639,9021,10006,537,80,20,10,100,250,20,500,200,0,0,650,450,150,{ petskillsupport "PR_MAGNIFICAT",2,60,50,50; }
-1031,POPORING,Poporing,621,9003,10013,511,80,12,30,100,250,20,1000,300,1,0,300,500,400,{ petloot 15; }
-1035,HUNTER_FLY,Hunter Fly,626,9008,10002,716,80,12,10,100,250,20,500,150,1,0,500,500,200,{ petskillattack2 "NPC_WINDATTACK",888,2,0,10;}
-1042,STEEL_CHONCHON,Steel ChonChon,625,9007,10002,1002,80,12,20,100,250,20,1000,150,1,0,500,500,200,{ petskillbonus bAgiVit,4,20,40; }
-1049,PICKY,Picky,623,9005,10012,507,80,15,40,100,250,20,2000,200,1,0,500,600,50,{ petskillbonus bStr,3,10,50;}
-1052,ROCKER,Rocker,629,9011,10014,537,80,60,30,100,250,20,1500,200,0,0,350,350,600,{ petskillbonus bAllStats,1,10,50; }
-1056,SMOKIE,Smokie,633,9015,10019,537,80,15,30,100,250,20,1000,200,1,0,600,600,100,{ petskillbonus bPerfectHide,1,3600,0; }
-1057,YOYO,Yoyo,634,9016,10018,532,80,12,20,100,250,20,1000,200,1,0,300,800,400,{ petloot 20; }
-1063,LUNATIC,Lunatic,622,9004,10007,534,80,15,40,100,250,20,1500,200,0,0,300,300,1000,{ petskillbonus bLuk,3,10,50; }
-1077,POISON_SPORE,Poison Spore,631,9013,10017,537,80,20,20,100,250,20,1000,200,0,0,600,200,400,{ petskillattack "NPC_POISON",20,0,10; }
-1101,BAPHOMET_Jr,Baphomet Jr.,642,9024,10001,518,80,30,10,100,250,20,200,100,0,0,1000,100,200,{ petskillattack2 "NPC_DARKNESSATTACK",1776,4,0,5; }
-1107,DESERT_WOLF_B,Baby Desert Wolf,628,9010,10003,537,80,10,40,100,250,20,1000,300,0,0,400,400,400,{ petskillattack "SM_PROVOKE",1,0,5;}
-1109,DEVIRUCHI,Deviruchi,641,9023,10004,711,80,30,10,100,250,20,500,150,0,0,800,200,100,{ petskillbonus bAgiDexStr,6,20,40; }
-1110,DOKEBI,Dokebi,637,9019,10005,537,80,15,20,100,250,20,500,250,0,0,300,300,800,{ petskillattack "BS_HAMMERFALL",1,0,10; }
-1113,DROPS,Drops,620,9002,10013,508,80,15,40,100,250,20,1500,400,1,0,300,400,500,{ petloot 10; }
-1155,PETIT,Petit,640,9022,10011,537,80,15,20,100,250,20,500,200,0,0,800,400,100,{ petskillattack2 "WZ_HEAVENDRIVE",500,1,0,10; }
-1167,SAVAGE_BABE,Savage Babe,627,9009,10015,537,80,9,40,100,250,20,1500,400,0,0,500,500,200,{ petskillbonus bVit,4,10,50; }
-1170,SOHEE,Sohee,638,9020,10016,537,80,20,10,100,250,20,500,300,0,0,100,1000,200,{ petheal 400,60,33,100; }
-1188,BON_GUN,Bon Gun,659,9025,10020,537,80,20,10,100,250,20,500,200,1,0,600,200,400,{ petskillattack2 "NPC_DARKNESSATTACK",555,1,1,1; }
-1200,ZHERLTHSH,Zherlthsh,660,9026,0,929,80,20,10,100,250,20,50,200,0,0,1000,100,500,{ petskillattack "AS_SONICBLOW",1,0,3; }
-1245,GOBLINE_XMAS,Christmas Goblin,12225,9029,0,911,80,20,50,100,250,20,2000,100,0,0,300,300,800,{ petskillattack "MG_SIGHT",5,5,5; }
-1275,ALICE,Alice,661,9027,0,504,80,20,10,100,250,20,100,200,0,0,100,1000,200,{ petskillsupport "AL_HEAL",5,60,25,100; }
-1815,EVENT_RICECAKE,Rice Cake,0,9028,0,511,80,20,50,100,250,20,2000,150,1,0,500,500,200,{ petskillsupport "CR_DEFENDER",3,240,50,100; }
+// 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
+1002,PORING,Poring,619,9001,10013,531,80,20,50,100,250,20,2000,400,1,0,350,400,800,{ petloot 10; },{ bonus bLuk,2; bonus bCritical,1; }
+1113,DROPS,Drops,620,9002,10013,508,80,15,40,100,250,20,1500,400,1,0,300,400,500,{ petloot 10; },{ bonus bHit,3; bonus bAtk,3; }
+1063,LUNATIC,Lunatic,622,9004,10007,534,80,15,40,100,250,20,1500,200,0,0,300,300,1000,{ petskillbonus bLuk,3,10,50; },{ bonus bCritical,2; bonus bAtk,2; }
+1049,PICKY,Picky,623,9005,10012,507,80,15,40,100,250,20,2000,200,1,0,500,600,50,{ petskillbonus bStr,3,10,50;},{ bonus bStr,1; bonus bAtk,5; }
+1011,CHONCHON,ChonChon,624,9006,10002,537,80,10,30,100,250,20,1500,200,1,0,500,500,250,{ petskillbonus bAgi,4,10,50; },{ bonus bAgi,1; bonus bFlee,2; }
+1167,SAVAGE_BABE,Savage Babe,627,9009,10015,537,80,9,40,100,250,20,1500,400,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,10,40,100,250,20,1000,300,0,0,400,400,400,{ petskillattack "SM_PROVOKE",1,0,5;},{ bonus bInt,1; bonus bMaxSP,20; }
+1052,ROCKER,Rocker,629,9011,10014,537,80,60,30,100,250,20,1500,200,0,0,350,350,600,{ petskillbonus bAllStats,1,10,50; },{ bonus bHPrecovRate,5; bonus bMaxHP,25; }
+1014,SPORE,Spore,630,9012,10017,537,80,20,30,100,250,20,1500,200,0,0,350,500,500,{ petrecovery SC_Poison,60; },{ bonus bHit,5; bonus bAtk,-2; }
+1031,POPORING,Poporing,621,9003,10013,511,80,12,30,100,250,20,1000,300,1,0,300,500,400,{ petloot 15; },{ bonus bLuk,2; bonus2 bSubEle,Ele_Poison,10; }
+1042,STEEL_CHONCHON,Steel ChonChon,625,9007,10002,1002,80,12,20,100,250,20,1000,150,1,0,500,500,200,{ petskillbonus bAgiVit,4,20,40; },{ bonus bFlee,6; bonus bAgi,-1; }
+1019,PECOPECO,PecoPeco,632,9014,10010,537,80,15,30,100,250,20,1000,200,1,0,400,500,800,{ petskillbonus bSpeedRate,25,20,20; },{ bonus bMaxHP,150; bonus bMaxSP,-10; }
+1077,POISON_SPORE,Poison Spore,631,9013,10017,537,80,20,20,100,250,20,1000,200,0,0,600,200,400,{ petskillattack "NPC_POISON",20,0,10; },{ bonus bStr,1; bonus bInt,1; }
+1056,SMOKIE,Smokie,633,9015,10019,537,80,15,30,100,250,20,1000,200,1,0,600,600,100,{ petskillbonus bPerfectHide,1,3600,0; },{ bonus bAgi,1; bonus bFlee2,1; }
+1057,YOYO,Yoyo,634,9016,10018,532,80,12,20,100,250,20,1000,200,1,0,300,800,400,{ petloot 20; },{ bonus bCritical,3; bonus bLuk,-1; }
+1023,ORC_WARRIOR,Orc Warrior,635,9017,10009,537,80,12,20,100,250,20,500,200,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,20,20,100,250,20,500,100,0,0,300,750,300,{ petskillattack2 "NPC_DARKNESSATTACK",444,1,0,10; },{ bonus bInt,1; bonus bDef,1; }
+1188,BON_GUN,Bon Gun,659,9025,10020,537,80,20,10,100,250,20,500,200,1,0,600,200,400,{ petskillattack2 "NPC_DARKNESSATTACK",555,1,1,1; },{ bonus bVit,1; bonus2 bResEff,Eff_Stun,100; }
+1110,DOKEBI,Dokebi,637,9019,10005,537,80,15,20,100,250,20,500,250,0,0,300,300,800,{ petskillattack "BS_HAMMERFALL",1,0,10; },{ bonus bMatkRate,1; bonus bAtkRate,-1; }
+1029,ISIS,Isis,639,9021,10006,537,80,20,10,100,250,20,500,200,0,0,650,450,150,{ petskillsupport "PR_MAGNIFICAT",2,60,50,50; },{ bonus bMatkRate,-1; bonus bAtkRate,1; }
+1155,PETIT,Petit,640,9022,10011,537,80,15,20,100,250,20,500,200,0,0,800,400,100,{ petskillattack2 "WZ_HEAVENDRIVE",500,1,0,10; },{ bonus bDef,-2; bonus bMdef,-2; bonus bAspdRate,1; }
+1170,SOHEE,Sohee,638,9020,10016,537,80,20,10,100,250,20,500,300,0,0,100,1000,200,{ petheal 400,60,33,100; },{ bonus bStr,1; bonus bDex,1; }
+1035,HUNTER_FLY,Hunter Fly,626,9008,10002,716,80,12,10,100,250,20,500,150,1,0,500,500,200,{ petskillattack2 "NPC_WINDATTACK",888,2,0,10; },{ bonus bFlee,-5; bonus bFlee2,2; }
+1109,DEVIRUCHI,Deviruchi,641,9023,10004,711,80,30,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; }
+1275,ALICE,Alice,661,9027,0,504,80,20,10,100,250,20,100,200,0,0,100,1000,200,{ petskillsupport "AL_HEAL",5,60,25,100; },{ bonus bMdef,1; bonus2 bSubRace,RC_DemiHuman,1; }
+1200,ZHERLTHSH,Zherlthsh,660,9026,0,929,80,20,10,100,250,20,50,200,0,0,1000,100,500,{ petskillattack "AS_SONICBLOW",1,0,3; },{ bonus2 bAddRace,RC_DemiHuman,2; bonus2 bMagicAddRace,RC_DemiHuman,2; }
+1101,BAPHOMET_Jr,Baphomet Jr.,642,9024,10001,518,80,30,10,100,250,20,200,100,0,0,1000,100,200,{ petskillattack2 "NPC_DARKNESSATTACK",1776,4,0,5; },{ bonus bDef,1; bonus bMdef,1; bonus2 bResEff,Eff_Stun,-100; }
+1815,EVENT_RICECAKE,Rice Cake,0,9028,0,511,80,20,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,20,50,100,250,20,2000,100,0,0,300,300,800,{ petskillattack "MG_SIGHT",5,5,5; },{ bonus bMaxHP,30; bonus2 bResEff,Eff_Freeze,500; }
 // Newest pets. un-official data
-1519,CHUNG_E,Green Maiden,0,9030,0,7767,80,20,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "CR_SHIELDCHARGE",5,5,5; }
-1879,ECLIPSE_P,Spring Rabbit,0,9031,0,7766,80,20,50,100,250,20,2000,160,0,0,300,300,800,{ petskillattack "TF_THROWSTONE",1,5,5; }
-1122,GOBLIN_1,Goblin,14569,9032,0,7821,80,20,50,100,250,20,2000,100,0,0,300,300,800,{ petskillattack "NPC_WINDATTACK",5,5,5; }
-1123,GOBLIN_2,Goblin,14570,9033,0,7821,80,20,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "NPC_FIREATTACK",5,5,5; }
-1125,GOBLIN_4,Goblin,14571,9034,0,7821,80,20,50,100,250,20,2000,200,0,0,300,300,800,{ petskillattack "NPC_GROUNDATTACK",5,5,5; }
-1385,DELETER,Deleter,14572,9035,0,7822,80,20,50,100,250,20,2000,175,0,0,300,300,800,{ petskillattack "SM_MAGNUM",5,5,5; }
-1382,DIABOLIC,Diabolic,14573,9036,0,7823,80,20,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "WZ_METEOR",2,5,5; }
-1208,WANDER_MAN,Wanderer,14574,9037,0,7824,80,20,50,100,250,20,2000,100,0,0,300,300,800,{ petskillattack "NPC_UNDEADATTACK",5,5,5; }
-1963,P_CHUNG_E,New Year Doll,0,9038,0,554,80,20,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "CR_SHIELDCHARGE",5,5,5; }
+1519,CHUNG_E,Green Maiden,0,9030,0,7767,80,20,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "CR_SHIELDCHARGE",5,5,5; },{}
+1879,ECLIPSE_P,Spring Rabbit,0,9031,0,7766,80,20,50,100,250,20,2000,160,0,0,300,300,800,{ petskillattack "TF_THROWSTONE",1,5,5; },{}
+1122,GOBLIN_1,Goblin,14569,9032,0,7821,80,20,50,100,250,20,2000,100,0,0,300,300,800,{ petskillattack "NPC_WINDATTACK",5,5,5; },{}
+1123,GOBLIN_2,Goblin,14570,9033,0,7821,80,20,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "NPC_FIREATTACK",5,5,5; },{}
+1125,GOBLIN_4,Goblin,14571,9034,0,7821,80,20,50,100,250,20,2000,200,0,0,300,300,800,{ petskillattack "NPC_GROUNDATTACK",5,5,5; },{}
+1385,DELETER,Deleter,14572,9035,0,7822,80,20,50,100,250,20,2000,175,0,0,300,300,800,{ petskillattack "SM_MAGNUM",5,5,5; },{}
+1382,DIABOLIC,Diabolic,14573,9036,0,7823,80,20,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "WZ_METEOR",2,5,5; },{}
+1208,WANDER_MAN,Wanderer,14574,9037,0,7824,80,20,50,100,250,20,2000,100,0,0,300,300,800,{ petskillattack "NPC_UNDEADATTACK",5,5,5; },{}
+1963,P_CHUNG_E,New Year Doll,0,9038,0,554,80,20,50,100,250,20,2000,150,0,0,300,300,800,{ petskillattack "CR_SHIELDCHARGE",5,5,5; },{}

+ 2 - 1
src/map/atcommand.c

@@ -3178,7 +3178,8 @@ int atcommand_petfriendly(const int fd, struct map_session_data* sd, const char*
 		clif_displaymessage(fd, msg_txt(183)); // Pet intimacy is already at maximum.
 		return -1;
 	}
-	pd->pet.intimate = friendly;
+
+	pet_set_intimate(pd, friendly);
 	clif_send_petstatus(sd);
 	clif_displaymessage(fd, msg_txt(182)); // Pet intimacy changed.
 	return 0;

+ 1 - 0
src/map/battle.c

@@ -3505,6 +3505,7 @@ static const struct _battle_data {
 	{ "pet_attack_support",                 &battle_config.pet_attack_support,              0,      0,      1,              },
 	{ "pet_damage_support",                 &battle_config.pet_damage_support,              0,      0,      1,              },
 	{ "pet_support_min_friendly",           &battle_config.pet_support_min_friendly,        900,    0,      950,            },
+	{ "pet_equip_min_friendly",             &battle_config.pet_equip_min_friendly,          900,    0,      950,            },
 	{ "pet_support_rate",                   &battle_config.pet_support_rate,                100,    0,      INT_MAX,        },
 	{ "pet_attack_exp_to_master",           &battle_config.pet_attack_exp_to_master,        0,      0,      1,              },
 	{ "pet_attack_exp_rate",                &battle_config.pet_attack_exp_rate,             100,    0,      INT_MAX,        },

+ 6 - 2
src/map/battle.h

@@ -180,6 +180,7 @@ extern struct Battle_Config
 	int emergency_call;
 	int guild_aura;
 	int pc_invincible_time;
+
 	int pet_catch_rate;
 	int pet_rename;
 	int pet_friendly_rate;
@@ -189,6 +190,7 @@ extern struct Battle_Config
 	int pet_attack_support;
 	int pet_damage_support;
 	int pet_support_min_friendly;	//[Skotlex]
+	int pet_equip_min_friendly;
 	int pet_support_rate;
 	int pet_attack_exp_to_master;
 	int pet_attack_exp_rate;
@@ -197,6 +199,8 @@ extern struct Battle_Config
 	int pet_max_atk1; //[Skotlex]
 	int pet_max_atk2; //[Skotlex]
 	int pet_no_gvg; //Disables pets in gvg. [Skotlex]
+	int pet_equip_required;
+
 	int skill_min_damage;
 	int finger_offensive_type;
 	int heal_exp;
@@ -280,7 +284,7 @@ extern struct Battle_Config
 	int item_rate_mvp, item_rate_common, item_rate_common_boss, item_rate_card, item_rate_card_boss,
 		item_rate_equip, item_rate_equip_boss, item_rate_heal, item_rate_heal_boss, item_rate_use,
 		item_rate_use_boss, item_rate_treasure, item_rate_adddrop;
-	
+
 	int logarithmic_drops;
 	int item_drop_common_min,item_drop_common_max;	// Added by TyrNemesis^
 	int item_drop_card_min,item_drop_card_max;
@@ -290,6 +294,7 @@ extern struct Battle_Config
 	int item_drop_use_min,item_drop_use_max;	//End
 	int item_drop_treasure_min,item_drop_treasure_max; //by [Skotlex]
 	int item_drop_adddrop_min,item_drop_adddrop_max; //[Skotlex]
+
 	int prevent_logout;	// Added by RoVeRT
 
 	int alchemist_summon_reward;	// [Valaris]
@@ -298,7 +303,6 @@ extern struct Battle_Config
 	int equip_natural_break_rate;	//Base Natural break rate for attacks.
 	int equip_self_break_rate; //Natural & Penalty skills break rate
 	int equip_skill_break_rate; //Offensive skills break rate
-	int pet_equip_required;
 	int multi_level_up;
 	int max_exp_gain_rate; //Max amount of exp bar % you can get in one go.
 	int pk_mode;

+ 9 - 8
src/map/pc.c

@@ -5201,14 +5201,15 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 
 	if(sd->status.pet_id > 0 && sd->pd)
 	{
-		struct s_pet *pet = &sd->pd->pet;
-		if(!map[sd->bl.m].flag.noexppenalty){
-			pet->intimate -= sd->pd->petDB->die;
-			if(pet->intimate < 0)
-				pet->intimate = 0;
-			clif_send_petdata(sd,sd->pd,1,pet->intimate);
-		}
-		if(sd->pd->target_id) // Unlock all targets...
+		struct pet_data *pd = sd->pd;
+		if( !map[sd->bl.m].flag.noexppenalty && !flag )
+		{
+			pet_set_intimate(pd, pd->pet.intimate - pd->petDB->die);
+			if( pd->pet.intimate < 0 )
+				pd->pet.intimate = 0;
+			clif_send_petdata(sd,sd->pd,1,pd->pet.intimate);
+		}
+		if( sd->pd->target_id ) // Unlock all targets...
 			pet_unlocktarget(sd->pd);
 	}
 

+ 124 - 55
src/map/pet.c

@@ -56,6 +56,20 @@ int pet_hungry_val(struct pet_data *pd)
 		return 0;
 }
 
+void pet_set_intimate(struct pet_data *pd, int value)
+{
+	int intimate;
+	struct map_session_data *sd;
+
+	nullpo_retv(pd);
+	intimate = pd->pet.intimate;
+	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,0);
+}
+
 int pet_create_egg(struct map_session_data *sd, int item_id)
 {
 	int pet_id = search_petDB_index(item_id, PET_EGG);
@@ -179,7 +193,7 @@ static int pet_hungry(int tid, unsigned int tick, int id, intptr data)
 {
 	struct map_session_data *sd;
 	struct pet_data *pd;
-	int interval,t;
+	int interval;
 
 	sd=map_id2sd(id);
 	if(!sd)
@@ -199,12 +213,13 @@ static int pet_hungry(int tid, unsigned int tick, int id, intptr data)
 		return 1; //You lost the pet already, the rest is irrelevant.
 	
 	pd->pet.hungry--;
-	t = pd->pet.intimate;
-	if(pd->pet.hungry < 0) {
+	if( pd->pet.hungry < 0 )
+	{
 		pet_stop_attack(pd);
 		pd->pet.hungry = 0;
-		pd->pet.intimate -= battle_config.pet_hungry_friendly_decrease;
-		if(pd->pet.intimate <= 0) {
+		pet_set_intimate(pd, pd->pet.intimate - battle_config.pet_hungry_friendly_decrease);
+		if( pd->pet.intimate <= 0 )
+		{
 			pd->pet.intimate = 0;
 			pd->status.speed = pd->db->status.speed;
 		}
@@ -291,13 +306,9 @@ static int pet_return_egg(struct map_session_data *sd, struct pet_data *pd)
 		map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
 	}
 	pd->pet.incuvate = 1;
-	//No need, pet is saved on unit_free below.
-	//intif_save_petdata(sd->status.account_id,&pd->pet);
-	if(pd->state.skillbonus) {
-		pd->state.skillbonus = 0;
-		status_calc_pc(sd,0);
-	}
 	unit_free(&pd->bl,0);
+
+	status_calc_pc(sd,0);
 	sd->status.pet_id = 0;
 
 	return 1;
@@ -358,7 +369,9 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *pet)
 	pd->last_thinktime = gettick();
 	pd->state.skillbonus = 0;
 	if( battle_config.pet_status_support )
-		run_script(pet_db[i].script,0,sd->bl.id,0);
+		run_script(pet_db[i].pet_script,0,sd->bl.id,0);
+	if( pd->petDB && pd->petDB->equip_script )
+		status_calc_pc(sd,0);
 
 	if( battle_config.pet_hungry_delay_rate != 100 )
 		interval = (pd->petDB->hungry_delay*battle_config.pet_hungry_delay_rate)/100;
@@ -686,21 +699,22 @@ static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd)
 		clif_additem(sd,0,0,flag);
 		map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
 	}
-	if (battle_config.pet_equip_required)
-	{ 	//Skotlex: halt support timers if needed
-		if(pd->state.skillbonus) {
+	if( battle_config.pet_equip_required )
+	{ // Skotlex: halt support timers if needed
+		if( pd->state.skillbonus )
+		{
 			pd->state.skillbonus = 0;
 			status_calc_pc(sd,0);
 		}
-		if (pd->s_skill && pd->s_skill->timer != -1)
+		if( pd->s_skill && pd->s_skill->timer != -1 )
 		{
-			if (pd->s_skill->id)
+			if( pd->s_skill->id )
 				delete_timer(pd->s_skill->timer, pet_skill_support_timer);
 			else
 				delete_timer(pd->s_skill->timer, pet_heal_timer);
 			pd->s_skill->timer = INVALID_TIMER;
 		}
-		if (pd->bonus && pd->bonus->timer != -1)
+		if( pd->bonus && pd->bonus->timer != -1 )
 		{
 			delete_timer(pd->bonus->timer, pet_skill_bonus_timer);
 			pd->bonus->timer = INVALID_TIMER;
@@ -722,30 +736,33 @@ static int pet_food(struct map_session_data *sd, struct pet_data *pd)
 	}
 	pc_delitem(sd,i,1,0);
 
-	if(pd->pet.hungry > 90)
-		pd->pet.intimate -= pd->petDB->r_full;
-	else {
-		if(battle_config.pet_friendly_rate != 100)
+	if( pd->pet.hungry > 90 )
+		pet_set_intimate(pd, pd->pet.intimate - pd->petDB->r_full);
+	else
+	{
+		if( battle_config.pet_friendly_rate != 100 )
 			k = (pd->petDB->r_hungry * battle_config.pet_friendly_rate)/100;
 		else
 			k = pd->petDB->r_hungry;
-		if(pd->pet.hungry > 75) {
+		if( pd->pet.hungry > 75 )
+		{
 			k = k >> 1;
-			if(k <= 0)
+			if( k <= 0 )
 				k = 1;
 		}
-		pd->pet.intimate += k;
+		pet_set_intimate(pd, pd->pet.intimate + k);
 	}
-	if(pd->pet.intimate <= 0) {
+	if( pd->pet.intimate <= 0 )
+	{
 		pd->pet.intimate = 0;
 		pet_stop_attack(pd);
 		pd->status.speed = pd->db->status.speed;
 	}
-	else if(pd->pet.intimate > 1000)
+	else if( pd->pet.intimate > 1000 )
 		pd->pet.intimate = 1000;
 	status_calc_pet(pd, 0);
 	pd->pet.hungry += pd->petDB->fullness;
-	if(pd->pet.hungry > 100)
+	if( pd->pet.hungry > 100 )
 		pd->pet.hungry = 100;
 
 	clif_send_petdata(sd,pd,2,pd->pet.hungry);
@@ -1185,10 +1202,18 @@ int read_petdb()
 
 	// Remove any previous scripts in case reloaddb was invoked.	
 	for( j = 0; j < MAX_PET_DB; j++ )
-		if (pet_db[j].script) {
-			script_free_code(pet_db[j].script);
-			pet_db[j].script = NULL;
+	{
+		if( pet_db[j].pet_script )
+		{
+			script_free_code(pet_db[j].pet_script);
+			pet_db[j].pet_script = NULL;
 		}
+		if( pet_db[j].equip_script )
+		{
+			script_free_code(pet_db[j].equip_script);
+			pet_db[j].pet_script = NULL;
+		}
+	}
 
 	// clear database
 	memset(pet_db,0,sizeof(pet_db));
@@ -1211,30 +1236,63 @@ int read_petdb()
 		lines = 0;
 		while( fgets(line, sizeof(line), fp) && j < MAX_PET_DB )
 		{			
-			char *str[32],*p,*np;
-
+			char *str[22], *p;
 			lines++;
 
 			if(line[0] == '/' && line[1] == '/')
 				continue;
+			memset(str, 0, sizeof(str));
+			p = line;
+			while( ISSPACE(*p) )
+				++p;
+			if( *p == '\0' )
+				continue; // empty line
+			for( k = 0; k < 20; ++k )
+			{
+				str[k] = p;
+				p = strchr(p,',');
+				if( p == NULL )
+					break; // comma not found
+				*p = '\0';
+				++p;
+			}
 
-			// split string into table columns
-			for(k=0,p=line;k<20;k++){
-				if((np=strchr(p,','))!=NULL){
-					str[k]=p;
-					*np=0;
-					p=np+1;
-				} else {
-					str[k]=p;
-					p+=strlen(p);
-				}
+			if( p == NULL )
+			{
+				ShowError("read_petdb: Insufficient columns in line %d, skipping.\n", lines);
+				continue;
+			}
+
+			// Pet Script
+			if( *p != '{' )
+			{
+				ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines);
+				continue;
+			}
+
+			str[20] = p;
+			p = strstr(p+1,"},");
+			if( p == NULL )
+			{
+				ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines);
+				continue;
+			}
+			p[1] = '\0';
+			p += 2;
+
+			// Equip Script
+			if( *p != '{' )
+			{
+				ShowError("read_petdb: Invalid format (Equip Script column) in line %d, skipping.\n", lines);
+				continue;
 			}
+			str[21] = p;
 
-			nameid=atoi(str[0]);
-			if(nameid<=0)
+			if( (nameid = atoi(str[0])) <= 0 )
 				continue;
 
-			if (!mobdb_checkid(nameid)) {
+			if( !mobdb_checkid(nameid) )
+			{
 				ShowWarning("pet_db reading: Invalid mob-class %d, pet not read.\n", nameid);
 				continue;
 			}
@@ -1249,7 +1307,7 @@ int read_petdb()
 			pet_db[j].fullness=atoi(str[7]);
 			pet_db[j].hungry_delay=atoi(str[8])*1000;
 			pet_db[j].r_hungry=atoi(str[9]);
-			if(pet_db[j].r_hungry <= 0)
+			if( pet_db[j].r_hungry <= 0 )
 				pet_db[j].r_hungry=1;
 			pet_db[j].r_full=atoi(str[10]);
 			pet_db[j].intimate=atoi(str[11]);
@@ -1261,10 +1319,14 @@ int read_petdb()
 			pet_db[j].attack_rate=atoi(str[17]);
 			pet_db[j].defence_attack_rate=atoi(str[18]);
 			pet_db[j].change_target_rate=atoi(str[19]);
-			pet_db[j].script = NULL;
-			if((np=strchr(p,'{'))==NULL)
-				continue;
-			pet_db[j].script = parse_script(np, filename[i], lines, 0);
+			pet_db[j].pet_script = NULL;
+			pet_db[j].equip_script = NULL;
+
+			if( *str[20] )
+				pet_db[j].pet_script = parse_script(str[20], filename[i], lines, 0);
+			if( *str[21] )
+				pet_db[j].equip_script = parse_script(str[21], filename[i], lines, 0);
+
 			j++;
 		}
 
@@ -1301,10 +1363,17 @@ int do_init_pet(void)
 int do_final_pet(void)
 {
 	int i;
-	for( i = 0; i < MAX_PET_DB; i++ ) {
-		if(pet_db[i].script) {
-			script_free_code(pet_db[i].script);
-			pet_db[i].script = NULL;
+	for( i = 0; i < MAX_PET_DB; i++ )
+	{
+		if( pet_db[i].pet_script )
+		{
+			script_free_code(pet_db[i].pet_script);
+			pet_db[i].pet_script = NULL;
+		}
+		if( pet_db[i].equip_script )
+		{
+			script_free_code(pet_db[i].equip_script);
+			pet_db[i].equip_script = NULL;
 		}
 	}
 	ers_destroy(item_drop_ers);

+ 3 - 1
src/map/pet.h

@@ -27,7 +27,8 @@ struct s_pet_db {
 	int attack_rate;
 	int defence_attack_rate;
 	int change_target_rate;
-	struct script_code *script;
+	struct script_code *equip_script;
+	struct script_code *pet_script;
 };
 extern struct s_pet_db pet_db[MAX_PET_DB];
 
@@ -101,6 +102,7 @@ struct pet_data {
 
 int pet_create_egg(struct map_session_data *sd, int item_id);
 int pet_hungry_val(struct pet_data *pd);
+void pet_set_intimate(struct pet_data *pd, int value);
 int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type);
 int pet_unlocktarget(struct pet_data *pd);
 int pet_sc_check(struct map_session_data *sd, int type); //Skotlex

+ 7 - 7
src/map/status.c

@@ -1967,16 +1967,16 @@ int status_calc_pc(struct map_session_data* sd,int first)
 		}
 	}
 
-	if(sd->pd && battle_config.pet_status_support)
-	{ // Pet
-		struct pet_data *pd=sd->pd;
-		if(pd && pd->pet.intimate > 0 &&
-			(!battle_config.pet_equip_required || pd->pet.equip > 0) &&
-			pd->state.skillbonus == 1 && pd->bonus) //Skotlex: Readjusted for pets
+	if( sd->pd )
+	{ // Pet Bonus
+		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->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);
 	}
-	//param_bonus now holds card bonuses.
 
+	//param_bonus now holds card bonuses.
 	if(status->rhw.range < 1) status->rhw.range = 1;
 	if(status->lhw.range < 1) status->lhw.range = 1;
 	if(status->rhw.range < status->lhw.range)

+ 4 - 3
src/map/unit.c

@@ -518,15 +518,16 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool
 				return 0;
 		} else
 			sd->areanpc_id=0;
-		if(sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0)
-		{	//Check if pet needs to be teleported. [Skotlex]
+		if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 )
+		{ // Check if pet needs to be teleported. [Skotlex]
 			int flag = 0;
 			struct block_list* bl = &sd->pd->bl;
 			if( !checkpath && !path_search(NULL,bl->m,bl->x,bl->y,dst_x,dst_y,0,CELL_CHKNOPASS) )
 				flag = 1;
 			else if (!check_distance_bl(&sd->bl, bl, AREA_SIZE)) //Too far, teleport.
 				flag = 2;
-			if (flag) {
+			if( flag )
+			{
 				unit_movepos(bl,sd->bl.x,sd->bl.y, 0, 0);
 				clif_slide(bl,bl->x,bl->y);
 			}