Merge pull request #191 from rathena/cleanup/petdb

* 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.
This commit is contained in:
aleos89 2015-01-13 12:43:07 -05:00
commit 4860a7c7c4
12 changed files with 270 additions and 150 deletions

View File

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

104
db/pre-re/pet_db.txt Normal file
View File

@ -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; }

View File

@ -28,35 +28,8 @@
//NOTE: The max value (100%) of attack_rate, defense_rate & change_target_rate is 10000.
//In theory you can use any valid script, but it is run only once upon pet
//loading, so it is recommended you use the specific pet scripts:
//petskillattack skillid, skilllv, 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; }
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; }
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; }
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; }

View File

@ -1044,6 +1044,7 @@ From here on, we will have the commands sorted as follow:
8.- Quest Log commands.
9.- Battleground commands.
10.- Pet commands.
10.1.- The Pet AI commands.
11.- Homunculus commands.
12.- Mercenary 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
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>;
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
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
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
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
inflicted and the specified number of attacks.
Value of 'rate' is between 1 and 100. 100 = 100%
---------------------------------------
===========================

View File

@ -2024,7 +2024,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
* Refined and optimized by helvetica
* 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);
@ -7947,6 +7947,7 @@ static const struct _battle_data {
{ "stormgust_knockback", &battle_config.stormgust_knockback, 1, 0, 1, },
{ "default_fixed_castrate", &battle_config.default_fixed_castrate, 20, 0, 100, },
{ "default_bind_on_equip", &battle_config.default_bind_on_equip, BOUND_CHAR, BOUND_NONE, BOUND_MAX-1, },
{ "pet_ignore_infinite_def", &battle_config.pet_ignore_infinite_def, 0, 0, 1, },
};
#ifndef STATS_OPT_OUT

View File

@ -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);
void battle_consume_ammo(struct map_session_data* sd, int skill, int lv);
bool is_infinite_defense(struct block_list *target, int flag);
// Settings
#define MIN_HAIR_STYLE battle_config.min_hair_style
@ -581,6 +584,7 @@ extern struct Battle_Config
int stormgust_knockback;
int default_fixed_castrate;
int default_bind_on_equip;
int pet_ignore_infinite_def; // Makes fixed damage of petskillattack2 ignores infinite defense
} battle_config;
void do_init_battle(void);

View File

@ -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);
if( pd->petDB ) {
if( pd->petDB->equip_script )
if( pd->petDB->pet_loyal_script )
status_calc_pc(sd,SCO_NONE);
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) {
ShowError("pet_skill_bonus_timer %d != %d\n",pd->bonus->timer,tid);
pd->bonus->timer = INVALID_TIMER;
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
} else { //Lost pet...
pd->bonus->timer = INVALID_TIMER;
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
pd->bonus->timer=add_timer(tick+timer,pet_skill_bonus_timer,sd->bl.id,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) {
ShowError("pet_recovery_timer %d != %d\n",pd->recovery->timer,tid);
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;
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) {
ShowError("pet_heal_timer %d != %d\n",pd->s_skill->timer,tid);
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
) { //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);
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);
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);
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) {
ShowError("pet_skill_support_timer %d != %d\n",pd->s_skill->timer,tid);
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) {
//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);
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);
else
unit_skilluse_id(&pd->bl, sd->bl.id, pd->s_skill->id, pd->s_skill->lv);
return 0;
}
@ -1544,7 +1533,10 @@ int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data)
*/
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;
int i,j;
@ -1555,9 +1547,9 @@ void read_petdb()
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].change_target_rate=atoi(str[19]);
pet_db[j].pet_script = NULL;
pet_db[j].equip_script = NULL;
pet_db[j].pet_loyal_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);
pet_db[j].pet_loyal_script = parse_script(str[21], filename[i], lines, 0);
j++;
entries++;
@ -1723,9 +1715,9 @@ void do_final_pet(void)
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;
}
}

View File

@ -7,28 +7,31 @@
#define MAX_PET_DB 300
#define MAX_PETLOOT_SIZE 30
/// 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];
@ -42,15 +45,16 @@ struct pet_recovery { //Stat recovery
struct pet_bonus {
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;
};
struct pet_skill_attack { //Attack Skill
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 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%
@ -87,7 +91,7 @@ struct pet_data {
} state;
int move_fail_count;
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_bonus* bonus;

View File

@ -12720,13 +12720,12 @@ BUILDIN_FUNC(getequipcardid)
BUILDIN_FUNC(petskillbonus)
{
struct pet_data *pd;
TBL_PC *sd = script_rid2sd(st);
TBL_PC *sd=script_rid2sd(st);
if(sd == NULL || sd->pd == NULL)
return SCRIPT_CMD_FAILURE;
if(sd==NULL || sd->pd==NULL)
return 0;
pd=sd->pd;
pd = sd->pd;
if (pd->bonus)
{ //Clear previous bonus
if (pd->bonus->timer != INVALID_TIMER)
@ -12734,13 +12733,13 @@ BUILDIN_FUNC(petskillbonus)
} else //init
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)
pd->state.skillbonus=0; // waiting state
pd->state.skillbonus = 0; // waiting state
// wait for timer to start
if (battle_config.pet_equip_required && pd->pet.equip == 0)
@ -13055,11 +13054,18 @@ BUILDIN_FUNC(petrecovery)
{
struct pet_data *pd;
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)
{ //Halt previous bonus
@ -13068,7 +13074,7 @@ BUILDIN_FUNC(petrecovery)
} else //Init
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->timer = INVALID_TIMER;
return SCRIPT_CMD_SUCCESS;
@ -13122,50 +13128,66 @@ BUILDIN_FUNC(petskillattack)
{
struct pet_data *pd;
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)
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->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;
}
/*==========================================
* 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)
{
struct pet_data *pd;
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)
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->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;
}
@ -13178,12 +13200,21 @@ BUILDIN_FUNC(petskillsupport)
{
struct pet_data *pd;
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)
{ //Clear previous skill
if (pd->s_skill->timer != INVALID_TIMER)
@ -13196,13 +13227,11 @@ BUILDIN_FUNC(petskillsupport)
} else //init memory
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
if (battle_config.pet_equip_required && pd->pet.equip == 0)

View File

@ -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);
//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]
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
dmg.damage= skill_lv;
dmg.damage2=0;
dmg.damage = 1*pd->a_skill->div_;
dmg.damage2 = 0;
dmg.div_= pd->a_skill->div_;
}
}

View File

@ -2481,9 +2481,9 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt)
* @return 1
* @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) {
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%)
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
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 )
pc_bonus(sd,pd->bonus->type, pd->bonus->val);
}

View File

@ -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);
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_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);