summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/battle/battle.conf7
-rw-r--r--conf/battle/skill.conf9
-rw-r--r--db/pet_db.txt7
-rw-r--r--db/pet_db2.txt7
-rw-r--r--db/pre-re/skill_db.txt4
-rw-r--r--db/pre-re/skill_unit_db.txt10
-rw-r--r--db/re/item_db.conf1
-rw-r--r--db/re/skill_db.txt4
-rw-r--r--db/re/skill_unit_db.txt12
-rw-r--r--doc/item_db.txt1
-rw-r--r--doc/sample/npc_test_quest.txt8
-rw-r--r--doc/script_commands.txt70
-rw-r--r--npc/scripts_jobs.conf26
-rw-r--r--src/common/console.c2
-rw-r--r--src/common/malloc.c2
-rw-r--r--src/map/battle.c17
-rw-r--r--src/map/battle.h1
-rw-r--r--src/map/itemdb.c5
-rw-r--r--src/map/itemdb.h1
-rw-r--r--src/map/map.c8
-rw-r--r--src/map/mob.c19
-rw-r--r--src/map/mob.h9
-rw-r--r--src/map/npc.c85
-rw-r--r--src/map/npc.h3
-rw-r--r--src/map/pc.c2
-rw-r--r--src/map/pet.c49
-rw-r--r--src/map/pet.h1
-rw-r--r--src/map/script.c78
-rw-r--r--src/map/skill.c57
-rw-r--r--src/map/status.c99
-rw-r--r--src/map/unit.c40
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc16
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc4
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc107
-rwxr-xr-xtools/validateinterfaces.py102
35 files changed, 463 insertions, 410 deletions
diff --git a/conf/battle/battle.conf b/conf/battle/battle.conf
index 2e84a23e5..42d9a7262 100644
--- a/conf/battle/battle.conf
+++ b/conf/battle/battle.conf
@@ -103,7 +103,12 @@ weapon_defense_type: 0
magic_defense_type: 0
// Change attacker's direction to face opponent on every attack? (Note 3)
-attack_direction_change: 15
+// NOTE: On official servers knockback of some skills like Firewall is always based on the
+// last direction walked. Even when attacking in a completely different direction, the
+// knockback direction won't change, so e.g. if you walk north and then attack an enemy to
+// the south you will still be knocked back to the south by Firewall. Immobile monsters
+// will always be knocked back to the south as their default direction is north.
+attack_direction_change: 0
// For those who is set, their innate attack element is "not elemental"
// (100% versus on all defense-elements) (Note 3)
diff --git a/conf/battle/skill.conf b/conf/battle/skill.conf
index e6828749b..028228729 100644
--- a/conf/battle/skill.conf
+++ b/conf/battle/skill.conf
@@ -293,4 +293,11 @@ mob_max_skilllvl: 100
// 1: Gutter line system without demi gutter bug
// 2-20: Area around caster (2 = 5x5, 3 = 7x7, 4 = 9x9, ..., 20 = 41x41)
// Note: If you knock the target out of the area it will only be hit once and won't do splash damage
-bowling_bash_area: 0 \ No newline at end of file
+bowling_bash_area: 0
+
+// On official servers, Storm Gust consists of 81 units that all deal 3x3 splash damage "away from center". Due to
+// south-western cells being processed first, this usually leads to a knockback to the northeast. Knockback at the
+// edges will be away from SG. Knockback direction can also be influenced by Ganbantein and Land Protector. If you
+// punch a hole into SG it will for example create a "suck in" effect.
+// If you disable this setting, the knockback direction will be completely random (eAthena style).
+stormgust_knockback: yes
diff --git a/db/pet_db.txt b/db/pet_db.txt
index 5a3431b25..bf7623c9b 100644
--- a/db/pet_db.txt
+++ b/db/pet_db.txt
@@ -43,10 +43,6 @@
//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
@@ -55,8 +51,7 @@
//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.
+//petskillattack2) and petskillsupport at the same time, but only one of each.
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; }
diff --git a/db/pet_db2.txt b/db/pet_db2.txt
index cf39171e8..ca5e4e14a 100644
--- a/db/pet_db2.txt
+++ b/db/pet_db2.txt
@@ -43,10 +43,6 @@
//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
@@ -55,6 +51,5 @@
//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.
+//petskillattack2) and petskillsupport at the same time, but only one of each.
diff --git a/db/pre-re/skill_db.txt b/db/pre-re/skill_db.txt
index 4c085b8df..371833d98 100644
--- a/db/pre-re/skill_db.txt
+++ b/db/pre-re/skill_db.txt
@@ -124,7 +124,7 @@
77,5,6,1,6,0x28,0,10,1,yes,0,0,0,magic,0, PR_TURNUNDEAD,Turn Undead
78,9,6,1,0,0x1,0,1,0,yes,0,0,0,magic,0, PR_LEXAETERNA,Lex Aeterna
79,9,8,2,6,0,0,10,1:2:3:4:5:6:7:8:9:10,yes,0,0,0,magic,0, PR_MAGNUS,Magnus Exorcismus
-80,9,8,2,3,0x20,1:1:1:1:1:2:2:2:2:2:2,10,3:4:5:6:7:8:9:10:11:12:12,yes,0,0x80,5,magic,0, WZ_FIREPILLAR,Fire Pillar
+80,9,8,2,3,0x20,1:1:1:1:1:2:2:2:2:2:2,10,-3:-4:-5:-6:-7:-8:-9:-10:-11:-12:-12,yes,0,0x80,5,magic,0, WZ_FIREPILLAR,Fire Pillar
81,0,6,4,3,0,3,10,1,yes,0,0,0,magic,5, WZ_SIGHTRASHER,Sightrasher
83,9,8,2,3,0,3:3:3:3:3:3:3:3:3:3:14,10,1:1:2:2:3:3:4:4:5:5:15,yes,0,0,0,magic,0, WZ_METEOR,Meteor Storm
84,9,8,1,4,0,0,10,3:4:5:6:7:8:9:10:11:12,yes,0,0,0,magic,2:3:3:4:4:5:5:6:6:7, WZ_JUPITEL,Jupitel Thunder
@@ -578,7 +578,7 @@
532,0,6,4,0,0x1,0,10,1,yes,0,0,0,magic,0, NJ_BUNSINJYUTSU,Mirror Image
533,0,0,0,0,0,0,10,0,no,0,0,0,none,0, NJ_NINPOU,Spirit of the Blade
534,9,8,1,3,0,0,10,1:2:3:4:5:6:7:8:9:10,yes,0,0,0,magic,0, NJ_KOUENKA,Crimson Fire Petal
-535,0,8,4,3,0,0,10,1,yes,0,0,0,magic,1, NJ_KAENSIN,Crimson Fire Formation
+535,0,8,4,3,0,0,10,1,yes,0,0,0,magic,0, NJ_KAENSIN,Crimson Fire Formation
536,9,8,1,3,0x2,2,5,3,yes,0,0,0,magic,0, NJ_BAKUENRYU,Raging Fire Dragon
537,9,8,1,1,0,0,10,3:4:5:6:7:8:9:10:11:12,yes,0,0,0,magic,0, NJ_HYOUSENSOU,Spear of Ice
538,9,6,2,1,0x1,0,10,1,yes,0,0,0,magic,0, NJ_SUITON,Hidden Water
diff --git a/db/pre-re/skill_unit_db.txt b/db/pre-re/skill_unit_db.txt
index bba3670e8..196a79d5b 100644
--- a/db/pre-re/skill_unit_db.txt
+++ b/db/pre-re/skill_unit_db.txt
@@ -4,7 +4,7 @@
// target = friend (party +guildmates +neutral players) / party / guild
// ally (party +guildmates) / all / sameguild (guild but no allies) / enemy
// flag 0x001(UF_DEFNOTENEMY) If 'defunit_not_enemy' is set, the target is changed to 'friend'
-// 0x002(UF_NOREITERRATION) Spell cannot be stacked
+// 0x002(UF_NOREITERATION) Spell cannot be stacked
// 0x004(UF_NOFOOTSET) Spell cannot be cast near/on targets
// 0x008(UF_NOOVERLAP) Spell effects do not overlap
// 0x010(UF_PATHCHECK) Only cells with a shootable path will be placed
@@ -35,10 +35,10 @@
79,0x84, , -1, 1,3000,enemy, 0x018 //PR_MAGNUS
80,0x87,0x88, 0, 1,2000,enemy, 0x006 //WZ_FIREPILLAR
83,0x86, , 0, 3,1000,enemy, 0x010 //WZ_METEOR
- 85,0x86, , 0, 6:6:6:6:6:6:6:6:6:6:8,1250,enemy,0x018 //WZ_VERMILION
+ 85,0x86, , 5, 1:1:1:1:1:1:1:1:1:1:3,1250,enemy,0x018 //WZ_VERMILION
87,0x8d, , -1, 0, -1,all, 0x010 //WZ_ICEWALL
- 89,0x86, , 0, 5, 450,enemy, 0x018 //WZ_STORMGUST
- 91,0x86, , 0, 2,1000,enemy, 0x010 //WZ_HEAVENDRIVE
+ 89,0x86, , 4, 1, 450,enemy, 0x018 //WZ_STORMGUST
+ 91,0x86, , 2, 0,1000,enemy, 0x010 //WZ_HEAVENDRIVE
92,0x8e, , 2, 0, -1,enemy, 0x010 //WZ_QUAGMIRE
115,0x90, , 0, 1,1000,enemy, 0x006 //HT_SKIDTRAP
116,0x93, , 0, 1,1000,enemy, 0x006 //HT_LANDMINE
@@ -50,7 +50,7 @@
122,0x8f, , 0, 1,1000,enemy, 0x006 //HT_BLASTMINE
123,0x98, , 0, 1,1000,enemy, 0x006 //HT_CLAYMORETRAP
125,0x99, , 0, 1,1000,all, 0x000 //HT_TALKIEBOX
-140,0x92, , -1, 0,1000,enemy, 0x000 //AS_VENOMDUST
+140,0x92, , -1, 1,1000,enemy, 0x000 //AS_VENOMDUST
220,0xb0, , 0, 0, -1,all, 0x002 //RG_GRAFFITI
229,0xb1, , 0, 1,1000,enemy, 0x006 //AM_DEMONSTRATION
254,0x86, , -1, 0, 300,enemy, 0x010 //CR_GRANDCROSS
diff --git a/db/re/item_db.conf b/db/re/item_db.conf
index 211fd5d63..f36ea3527 100644
--- a/db/re/item_db.conf
+++ b/db/re/item_db.conf
@@ -31,6 +31,7 @@ item_db: (
BindOnEquip: true/false (boolean, defaults to false)
BuyingStore: true/false (boolean, defaults to false)
Delay: Delay to use item (int, defaults to 0)
+ KeepAfterUse: true/false (boolean, defaults to false)
Trade: { (defaults to no restrictions)
override: GroupID (int, defaults to 100)
nodrop: true/false (boolean, defaults to false)
diff --git a/db/re/skill_db.txt b/db/re/skill_db.txt
index ebaf3ab6c..df1cf5c52 100644
--- a/db/re/skill_db.txt
+++ b/db/re/skill_db.txt
@@ -124,7 +124,7 @@
77,5,6,1,6,0x28,0,10,1,yes,0,0,0,magic,0, PR_TURNUNDEAD,Turn Undead
78,9,6,1,0,0x1,0,1,0,yes,0,0,0,magic,0, PR_LEXAETERNA,Lex Aeterna
79,9,8,2,6,0,0,10,1:2:3:4:5:6:7:8:9:10,yes,0,0,0,magic,0, PR_MAGNUS,Magnus Exorcismus
-80,9,8,2,3,0x20,1:1:1:1:1:2:2:2:2:2:2,10,3:4:5:6:7:8:9:10:11:12:12,yes,0,0,5,magic,0, WZ_FIREPILLAR,Fire Pillar
+80,9,8,2,3,0x20,1:1:1:1:1:2:2:2:2:2:2,10,-3:-4:-5:-6:-7:-8:-9:-10:-11:-12:-12,yes,0,0,5,magic,0, WZ_FIREPILLAR,Fire Pillar
81,0,6,4,3,0,3,10,1,yes,0,0,0,magic,5, WZ_SIGHTRASHER,Sightrasher
83,9,8,2,3,0,3:3:3:3:3:3:3:3:3:3:14,10,1:1:2:2:3:3:4:4:5:5:15,yes,0,0,0,magic,0, WZ_METEOR,Meteor Storm
84,9,8,1,4,0,0,10,3:4:5:6:7:8:9:10:11:12,yes,0,0,0,magic,2:3:3:4:4:5:5:6:6:7, WZ_JUPITEL,Jupitel Thunder
@@ -578,7 +578,7 @@
532,0,6,4,0,0x1,0,10,1,yes,0,0,0,magic,0, NJ_BUNSINJYUTSU,Mirror Image
533,0,0,0,0,0,0,10,0,no,0,0,0,none,0, NJ_NINPOU,Spirit of the Blade
534,9,8,1,3,0,0,10,1:2:3:4:5:6:7:8:9:10,yes,0,0,0,magic,0, NJ_KOUENKA,Crimson Fire Petal
-535,0,8,4,3,0,0,10,1,yes,0,0,0,magic,1, NJ_KAENSIN,Crimson Fire Formation
+535,0,8,4,3,0,0,10,1,yes,0,0,0,magic,0, NJ_KAENSIN,Crimson Fire Formation
536,9,8,1,3,0x2,2,5,3,yes,0,0,0,magic,0, NJ_BAKUENRYU,Raging Fire Dragon
537,9,8,1,1,0,0,10,3:4:5:6:7:8:9:10:11:12,yes,0,0,0,magic,0, NJ_HYOUSENSOU,Spear of Ice
538,9,6,2,1,0x1,0,10,1,yes,0,0,0,magic,0, NJ_SUITON,Hidden Water
diff --git a/db/re/skill_unit_db.txt b/db/re/skill_unit_db.txt
index 1f93d771f..f0f359bcc 100644
--- a/db/re/skill_unit_db.txt
+++ b/db/re/skill_unit_db.txt
@@ -4,7 +4,7 @@
// target = friend (party +guildmates +neutral players) / party / guild
// ally (party +guildmates) / all / sameguild (guild but no allies) / enemy
// flag 0x001(UF_DEFNOTENEMY) If 'defunit_not_enemy' is set, the target is changed to 'friend'
-// 0x002(UF_NOREITERRATION) Spell cannot be stacked
+// 0x002(UF_NOREITERATION) Spell cannot be stacked
// 0x004(UF_NOFOOTSET) Spell cannot be cast near/on targets
// 0x008(UF_NOOVERLAP) Spell effects do not overlap
// 0x010(UF_PATHCHECK) Only cells with a shootable path will be placed
@@ -35,10 +35,10 @@
79,0x84, , -1, 1,3000,enemy, 0x018 //PR_MAGNUS
80,0x87,0x88, 0, 1,2000,enemy, 0x006 //WZ_FIREPILLAR
83,0x86, , 0, 3,1000,enemy, 0x010 //WZ_METEOR
- 85,0x86, , 0, 6:6:6:6:6:6:6:6:6:6:8,1250,enemy,0x018 //WZ_VERMILION
+ 85,0x86, , 5, 1:1:1:1:1:1:1:1:1:1:3,1250,enemy,0x018 //WZ_VERMILION
87,0x8d, , -1, 0, -1,all, 0x010 //WZ_ICEWALL
- 89,0x86, , 0, 5, 450,enemy, 0x018 //WZ_STORMGUST
- 91,0x86, , 0, 2,1000,enemy, 0x010 //WZ_HEAVENDRIVE
+ 89,0x86, , 4, 1, 450,enemy, 0x018 //WZ_STORMGUST
+ 91,0x86, , 2, 0,1000,enemy, 0x010 //WZ_HEAVENDRIVE
92,0x8e, , 2, 0, -1,enemy, 0x010 //WZ_QUAGMIRE
115,0x90, , 0, 1,1000,enemy, 0x006 //HT_SKIDTRAP
116,0x93, , 0, 1,1000,enemy, 0x006 //HT_LANDMINE
@@ -50,9 +50,9 @@
122,0x8f, , 0, 1,1000,enemy, 0x006 //HT_BLASTMINE
123,0x98, , 0, 1,1000,enemy, 0x006 //HT_CLAYMORETRAP
125,0x99, , 0, 1,1000,all, 0x000 //HT_TALKIEBOX
-140,0x92, , -1, 0,1000,enemy, 0x000 //AS_VENOMDUST
+140,0x92, , -1, 1,1000,enemy, 0x000 //AS_VENOMDUST
220,0xb0, , 0, 0, -1,all, 0x002 //RG_GRAFFITI
-229,0xb1, , 0, 1,1000,enemy, 0x006 //AM_DEMONSTRATION
+229,0xb1, , 0, 1, 500,enemy, 0x006 //AM_DEMONSTRATION
254,0x86, , -1, 0, 300,enemy, 0x010 //CR_GRANDCROSS
285,0x9a, , 3, 0, -1,all, 0x010 //SA_VOLCANO
286,0x9b, , 3, 0, -1,all, 0x010 //SA_DELUGE
diff --git a/doc/item_db.txt b/doc/item_db.txt
index ce2a248ca..6b34b8daf 100644
--- a/doc/item_db.txt
+++ b/doc/item_db.txt
@@ -36,6 +36,7 @@ item_db: (
BindOnEquip: true/false (boolean, defaults to false)
BuyingStore: true/false (boolean, defaults to false)
Delay: Delay to use item (int, defaults to 0)
+ KeepAfterUse: true/false (boolean, defaults to false)
Trade: { (defaults to no restrictions)
override: GroupID (int, defaults to 100)
nodrop: true/false (boolean, defaults to false)
diff --git a/doc/sample/npc_test_quest.txt b/doc/sample/npc_test_quest.txt
index fcf6b2a80..90659aa10 100644
--- a/doc/sample/npc_test_quest.txt
+++ b/doc/sample/npc_test_quest.txt
@@ -13,7 +13,7 @@
// 70000,0,1002,3,0,0,0,0,"3 Splats Please!"
prontera,90,95,1 script Jelly 2_F_MAGICMASTER,{
- if(checkquest(70000) == -1) {
+ if (!questprogress(70000)) {
// Quest not yet started.
mes "[Jelly]";
mes "Hey there! Would you help me?";
@@ -30,7 +30,7 @@ prontera,90,95,1 script Jelly 2_F_MAGICMASTER,{
setquest 70000; // Adds the quest to your Quest Window.
close;
}
- } else if(checkquest(70000,HUNTING) == 2) {
+ } else if (questprogress(70000,HUNTING) == 2) {
// All monsters killed.
mes "[Jelly]";
mes "Awesome! Thank you!";
@@ -38,12 +38,12 @@ prontera,90,95,1 script Jelly 2_F_MAGICMASTER,{
dispbottom "You have been rewarded with 10,000 Base Exp.";
completequest 70000; // Sets quest status to "complete".
close;
- } else if(checkquest(70000) == 1) {
+ } else if (questprogress(70000) == 1) {
// Quest is active.
mes "[Jelly]";
mes "Keep going, almost there!";
close;
- } else if(checkquest(70000) == 2) {
+ } else if (questprogress(70000) == 2) {
// Quest finished.
mes "[Jelly]";
mes "Thanks again for doing that for me!";
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index ec8274716..33e706004 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -2056,28 +2056,6 @@ else if (<condition 2>) {
---------------------------------------
-*jump_zero (<condition>),<label>;
-
- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- @ /!\ This command is deprecated @
- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
-
-This command is deprecated and it should not be used in new scripts, as it is
-scheduled to be removed at any time on or after November 27th, 2014. Please
-consider using 'if', 'switch', 'for', 'while', as appropriate.
-
-This command works like an 'if'+'goto' combination in one go. (See 'if').
-If the condition is false (equal to zero) this command will immediately
-jump to the specified label like in 'goto'.
-
-This command should not be used in scripts directly.
-
-The main reason for this command is that other control statements, like
-'switch', 'for' or 'while', are disassembled into simple expressions
-together with this command when a script is parsed.
-
----------------------------------------
-
*while (<condition>) <statement>;
This is probably the simplest and most frequently used loop structure. The
@@ -8003,8 +7981,7 @@ decision-making for the current pet of the invoking character, and will
NOT have any independent effect by themselves, which is why only one of
them each may be in effect at any time for a specific pet. A pet may
have 'petloot', 'petskillbonus', 'petskillattack' OR 'petpetskillattack2'
-and 'petskillsupport' OR 'petheal' at the same time. 'petheal' is
-deprecated and is no longer used in the default pet scripts.
+and 'petskillsupport' at the same time.
*petskillbonus <bonus type>,<value>,<duration>,<delay>;
@@ -8035,16 +8012,6 @@ time between activations. The skill numbers are as per
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.
-*petheal <level>,<delay>,<percent hp>,<percent sp>;
-
- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- @ /!\ This command is deprecated @
- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
-
-The petheal command is deprecated and it should not be used in new scripts, as
-it is scheduled to be removed after November 27th, 2014. Please consider using
-petskillsupport by specifying the AL_HEAL skill id instead.
-
*petskillattack <skill id>,<skill level>,<rate>,<bonusrate>;
*petskillattack "<skill name>",<skill level>,<rate>,<bonusrate>;
*petskillattack2 <skill id>,<damage>,<number of attacks>,<rate>,<bonusrate>;
@@ -8415,7 +8382,7 @@ that fails, the command returns an empty string instead.
*questinfo <Quest ID>, <Icon> {, <Map Mark Color>{, <Job Class>}};
-This is esentially a combination of checkquest and showevent. Use this only
+This is esentially a combination of questprogress and showevent. Use this only
in an OnInit label. For the Quest ID, specify the quest ID that you want
checked if it has been started yet.
@@ -8491,39 +8458,6 @@ Add quest of the <ID2> to the the quest log, and the state is "active".
---------------------------------------
-*checkquest(<ID>{,PLAYTIME|HUNTING})
-
- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- @ /!\ This command is deprecated @
- @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
-
-This command is deprecated and it should not be used in new scripts, as it
-is scheduled to be removed on or after November 28th, 2014. Please consider
-using questprogress() instead. Or, in special cases, questactive().
-
-If no additional argument supplied, return the state of the quest:
- -1 = Quest not started (not in quest log)
- 0 = Quest has been given, but the state is "inactive"
- 1 = Quest has been given, and the state is "active"
- 2 = Quest completed
-
-If parameter "PLAYTIME" is supplied:
- -1 = Quest not started (not in quest log)
- 0 = the time limit has not yet been reached
- 1 = the time limit has not been reached but the quest is marked as
- complete
- 2 = the time limit has been reached
-
-If parameter "HUNTING" is supplied:
- -1 = Quest not started (not in quest log)
- 0 = you haven't killed all of the target monsters and the time limit
- has not been reached.
- 1 = you haven't killed all of the target monsters but the time limit
- has been reached.
- 2 = you've killed all of the target monsters
-
----------------------------------------
-
*questprogress(<ID>{,PLAYTIME|HUNTING})
If no additional argument supplied, return the state of the quest:
diff --git a/npc/scripts_jobs.conf b/npc/scripts_jobs.conf
index 61191700e..ad6ea3d73 100644
--- a/npc/scripts_jobs.conf
+++ b/npc/scripts_jobs.conf
@@ -47,23 +47,27 @@ npc: npc/jobs/novice/supernovice.txt
npc: npc/jobs/valkyrie.txt
// ------------------------ Skill Quests ------------------------
+// - Novice
+npc: npc/quests/skills/novice_skills.txt
+// - 1-1
npc: npc/quests/skills/acolyte_skills.txt
-npc: npc/quests/skills/alchemist_skills.txt
npc: npc/quests/skills/archer_skills.txt
+npc: npc/quests/skills/mage_skills.txt
+npc: npc/quests/skills/merchant_skills.txt
+npc: npc/quests/skills/swordman_skills.txt
+npc: npc/quests/skills/thief_skills.txt
+// - 2-1
npc: npc/quests/skills/assassin_skills.txt
-npc: npc/quests/skills/bard_skills.txt
npc: npc/quests/skills/blacksmith_skills.txt
-npc: npc/quests/skills/crusader_skills.txt
-npc: npc/quests/skills/dancer_skills.txt
npc: npc/quests/skills/hunter_skills.txt
npc: npc/quests/skills/knight_skills.txt
-npc: npc/quests/skills/mage_skills.txt
-npc: npc/quests/skills/merchant_skills.txt
-npc: npc/quests/skills/monk_skills.txt
-npc: npc/quests/skills/novice_skills.txt
npc: npc/quests/skills/priest_skills.txt
npc: npc/quests/skills/rogue_skills.txt
-npc: npc/quests/skills/sage_skills.txt
-npc: npc/quests/skills/swordman_skills.txt
-npc: npc/quests/skills/thief_skills.txt
npc: npc/quests/skills/wizard_skills.txt
+// - 2-2
+npc: npc/quests/skills/alchemist_skills.txt
+npc: npc/quests/skills/bard_skills.txt
+npc: npc/quests/skills/crusader_skills.txt
+npc: npc/quests/skills/dancer_skills.txt
+npc: npc/quests/skills/monk_skills.txt
+npc: npc/quests/skills/sage_skills.txt
diff --git a/src/common/console.c b/src/common/console.c
index 577d1a3f0..6c5a5c886 100644
--- a/src/common/console.c
+++ b/src/common/console.c
@@ -112,7 +112,9 @@ CPCMD_C(ers_report,server) {
* Displays memory usage
**/
CPCMD_C(mem_report,server) {
+#ifdef USE_MEMMGR
memmgr_report(line?atoi(line):0);
+#endif
}
/**
diff --git a/src/common/malloc.c b/src/common/malloc.c
index 625875b76..244b1114c 100644
--- a/src/common/malloc.c
+++ b/src/common/malloc.c
@@ -822,8 +822,10 @@ void malloc_final (void) {
}
void malloc_init (void) {
+#ifdef USE_MEMMGR
memmgr_usage_bytes_t = 0;
memmgr_usage_bytes = 0;
+#endif
#if defined(DMALLOC) && defined(CYGWIN)
// http://dmalloc.com/docs/latest/online/dmalloc_19.html
dmalloc_debug_setup(getenv("DMALLOC_OPTIONS"));
diff --git a/src/map/battle.c b/src/map/battle.c
index 9ee4695f7..58291a3d6 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -1463,9 +1463,9 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
break;
case WZ_FIREPILLAR:
if (skill_lv > 10)
- skillratio += 100;
+ skillratio += 2300; //200% MATK each hit
else
- skillratio -= 80;
+ skillratio += -60 + 20*skill_lv; //20% MATK each hit
break;
case WZ_SIGHTRASHER:
skillratio += 20 * skill_lv;
@@ -2910,6 +2910,13 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
if ( sc->data[SC_WATER_BARRIER] )
damage = damage * ( 100 - 20 ) / 100;
+ if( sc->data[SC_FIRE_EXPANSION_SMOKE_POWDER] ) {
+ if( (flag&(BF_SHORT|BF_WEAPON)) == (BF_SHORT|BF_WEAPON) )
+ damage -= 15 * damage / 100;//15% reduction to physical melee attacks
+ else if( (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON) )
+ damage -= 50 * damage / 100;//50% reduction to physical ranged attacks
+ }
+
// Compressed code, fixed by map.h [Epoque]
if (src->type == BL_MOB) {
int i;
@@ -3384,11 +3391,10 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
switch(skill_id) {
case MG_FIREWALL:
- case NJ_KAENSIN:
- ad.dmotion = 0; //No flinch animation.
if ( tstatus->def_ele == ELE_FIRE || battle->check_undead(tstatus->race, tstatus->def_ele) )
ad.blewcount = 0; //No knockback
break;
+ case NJ_KAENSIN:
case PR_SANCTUARY:
ad.dmotion = 0; //No flinch animation.
break;
@@ -3495,7 +3501,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
}
//Constant/misc additions from skills
if (skill_id == WZ_FIREPILLAR)
- MATK_ADD(50);
+ MATK_ADD(100+50*skill_lv);
if( sd && ( sd->status.class_ == JOB_ARCH_BISHOP_T || sd->status.class_ == JOB_ARCH_BISHOP ) &&
(i=pc->checkskill(sd,AB_EUCHARISTICA)) > 0 &&
(tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK) )
@@ -6839,6 +6845,7 @@ static const struct battle_data {
{ "guild_castle_expulsion", &battle_config.guild_castle_expulsion, 0, 0, 1, },
{ "song_timer_reset", &battle_config.song_timer_reset, 0, 0, 1, },
{ "snap_dodge", &battle_config.snap_dodge, 0, 0, 1, },
+ { "stormgust_knockback", &battle_config.stormgust_knockback, 1, 0, 1, },
{ "monster_chase_refresh", &battle_config.mob_chase_refresh, 1, 0, 30, },
{ "mob_icewall_walk_block", &battle_config.mob_icewall_walk_block, 75, 0, 255, },
{ "boss_icewall_walk_block", &battle_config.boss_icewall_walk_block, 0, 0, 255, },
diff --git a/src/map/battle.h b/src/map/battle.h
index ad879bd1a..e80e0091d 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -482,6 +482,7 @@ struct Battle_Config {
int song_timer_reset; // [csnv]
int snap_dodge; // Enable or disable dodging damage snapping away [csnv]
+ int stormgust_knockback;
int feature_roulette;
};
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 67aab7a18..508a0ccec 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -1787,9 +1787,12 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source)
if ( (t = libconfig->setting_get_member(it, "BuyingStore")) )
id.flag.buyingstore = libconfig->setting_get_bool(t) ? 1 : 0;
+ if ((t = libconfig->setting_get_member(it, "KeepAfterUse")))
+ id.flag.keepafteruse = libconfig->setting_get_bool(t) ? 1 : 0;
+
if (libconfig->setting_lookup_int(it, "Delay", &i32) && i32 >= 0)
id.delay = i32;
-
+
if ( (t = libconfig->setting_get_member(it, "Trade")) ) {
if (config_setting_is_group(t)) {
config_setting_t *tt = NULL;
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index a1c4d1053..5504d72d9 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -414,6 +414,7 @@ struct item_data {
unsigned autoequip: 1;
unsigned buyingstore : 1;
unsigned bindonequip : 1;
+ unsigned keepafteruse : 1;
} flag;
struct {// item stacking limitation
unsigned short amount;
diff --git a/src/map/map.c b/src/map/map.c
index 651c895ec..c379911d3 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -2569,7 +2569,7 @@ int map_random_dir(struct block_list *bl, int16 *x, int16 *y)
}
// gat system
-inline static struct mapcell map_gat2cell(int gat) {
+struct mapcell map_gat2cell(int gat) {
struct mapcell cell;
memset(&cell,0,sizeof(struct mapcell));
@@ -2616,9 +2616,6 @@ void map_cellfromcache(struct map_data *m) {
// Set cell properties
for( xy = 0; xy < size; ++xy ) {
m->cell[xy] = map->gat2cell(decode_buffer[xy]);
-#ifdef CELL_NOSTACK
- m->cell[xy].cell_bl = 0;
-#endif
}
m->getcellp = map->getcellp;
@@ -3394,9 +3391,6 @@ int map_readgat (struct map_data* m)
type = 3; // Cell is 0 (walkable) but under water level, set to 3 (walkable water)
m->cell[xy] = map->gat2cell(type);
-#ifdef CELL_NOSTACK
- m->cell[xy].cell_bl = 0;
-#endif
}
aFree(gat);
diff --git a/src/map/mob.c b/src/map/mob.c
index 28e70c5c0..629653c8d 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -141,14 +141,9 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time)
if ( md->tomb_nid )
mob->mvptomb_destroy(md);
- CREATE(nd, struct npc_data, 1);
-
- nd->bl.id = md->tomb_nid = npc->get_new_npc_id();
-
+ nd = npc->create_npc(md->bl.m, md->bl.x, md->bl.y);
+ md->tomb_nid = nd->bl.id;
nd->dir = md->ud.dir;
- nd->bl.m = md->bl.m;
- nd->bl.x = md->bl.x;
- nd->bl.y = md->bl.y;
nd->bl.type = BL_NPC;
safestrncpy(nd->name, msg_txt(856), sizeof(nd->name)); // "Tomb"
@@ -941,6 +936,7 @@ int mob_spawn (struct mob_data *md)
md->move_fail_count = 0;
md->ud.state.attack_continue = 0;
md->ud.target_to = 0;
+ md->ud.dir = 0;
if( md->spawn_timer != INVALID_TIMER )
{
timer->delete(md->spawn_timer, mob->delayspawn);
@@ -1080,6 +1076,15 @@ int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) &&
battle->check_range(&md->bl,bl,md->db->range2)
) { //Pick closest target?
+#ifdef ACTIVEPATHSEARCH
+ struct walkpath_data wpd;
+ if (!path->search(&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x, bl->y, 0, CELL_CHKNOPASS)) // Count walk path cells
+ return 0;
+ //Standing monsters use range2, walking monsters use range3
+ if ((md->ud.walktimer == INVALID_TIMER && wpd.path_len > md->db->range2)
+ || (md->ud.walktimer != INVALID_TIMER && wpd.path_len > md->db->range3))
+ return 0;
+#endif
(*target) = bl;
md->target_id=bl->id;
md->min_chase= dist + md->db->range3;
diff --git a/src/map/mob.h b/src/map/mob.h
index c61d29103..f79b33804 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -42,6 +42,15 @@
#define MAX_MOB_CHAT 250 //Max Skill's messages
+// On official servers, monsters will only seek targets that are closer to walk to than their
+// search range. The search range is affected depending on if the monster is walking or not.
+// On some maps there can be a quite long path for just walking two cells in a direction and
+// the client does not support displaying walk paths that are longer than 14 cells, so this
+// option reduces position lag in such situation. But doing a complex search for every possible
+// target, might be CPU intensive.
+// Disable this to make monsters not do any path search when looking for a target (old behavior).
+#define ACTIVEPATHSEARCH
+
//Mob skill states.
enum MobSkillState {
MSS_ANY = -1,
diff --git a/src/map/npc.c b/src/map/npc.c
index ce668bfae..8c2f61d58 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2495,18 +2495,27 @@ bool npc_viewisid(const char * viewid)
return true;
}
+struct npc_data* npc_create_npc(int m, int x, int y)
+{
+ struct npc_data *nd;
+
+ CREATE(nd, struct npc_data, 1);
+ nd->bl.id = npc->get_new_npc_id();
+ nd->bl.prev = nd->bl.next = NULL;
+ nd->bl.m = m;
+ nd->bl.x = x;
+ nd->bl.y = y;
+
+ return nd;
+}
+
//Add then display an npc warp on map
struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y) {
int i, flag = 0;
struct npc_data *nd;
- CREATE(nd, struct npc_data, 1);
- nd->bl.id = npc->get_new_npc_id();
+ nd = npc->create_npc(from_mapid, from_x, from_y);
map->addnpc(from_mapid, nd);
- nd->bl.prev = nd->bl.next = NULL;
- nd->bl.m = from_mapid;
- nd->bl.x = from_x;
- nd->bl.y = from_y;
safestrncpy(nd->exname, name, ARRAYLENGTH(nd->exname));
if (npc->name2id(nd->exname) != NULL)
@@ -2574,14 +2583,8 @@ const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* s
return strchr(start,'\n');;//try next
}
- CREATE(nd, struct npc_data, 1);
-
- nd->bl.id = npc->get_new_npc_id();
+ nd = npc->create_npc(m, x, y);
map->addnpc(m, nd);
- nd->bl.prev = nd->bl.next = NULL;
- nd->bl.m = m;
- nd->bl.x = x;
- nd->bl.y = y;
npc->parsename(nd, w3, start, buffer, filepath);
if (!battle_config.warp_point_debug)
@@ -2716,17 +2719,12 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s
return strchr(start,'\n');// continue
}
- CREATE(nd, struct npc_data, 1);
+ nd = npc->create_npc(m, x, y);
CREATE(nd->u.shop.shop_item, struct npc_item_list, i);
memcpy(nd->u.shop.shop_item, items, sizeof(items[0])*i);
aFree(items);
nd->u.shop.count = i;
- nd->bl.prev = nd->bl.next = NULL;
- nd->bl.m = m;
- nd->bl.x = x;
- nd->bl.y = y;
- nd->bl.id = npc->get_new_npc_id();
npc->parsename(nd, w3, start, buffer, filepath);
nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath);
nd->speed = 200;
@@ -2890,8 +2888,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char*
npc->convertlabel_db(label_list,filepath);
}
- CREATE(nd, struct npc_data, 1);
-
+ nd = npc->create_npc(m, x, y);
if( sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2 )
{// OnTouch area defined
nd->u.scr.xs = xs;
@@ -2903,12 +2900,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char*
nd->u.scr.ys = -1;
}
- nd->bl.prev = nd->bl.next = NULL;
- nd->bl.m = m;
- nd->bl.x = x;
- nd->bl.y = y;
npc->parsename(nd, w3, start, buffer, filepath);
- nd->bl.id = npc->get_new_npc_id();
nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath);
nd->speed = 200;
nd->u.scr.script = scriptroot;
@@ -3040,14 +3032,8 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
return end;// next line, try to continue
}
- CREATE(nd, struct npc_data, 1);
-
- nd->bl.prev = nd->bl.next = NULL;
- nd->bl.m = m;
- nd->bl.x = x;
- nd->bl.y = y;
+ nd = npc->create_npc(m, x, y);
npc->parsename(nd, w3, start, buffer, filepath);
- nd->bl.id = npc->get_new_npc_id();
nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath);
nd->speed = 200;
nd->src_id = src_id;
@@ -3159,13 +3145,8 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
return 1;
}
- CREATE(wnd, struct npc_data, 1);
- wnd->bl.id = npc->get_new_npc_id();
+ wnd = npc->create_npc(m, snd->bl.x, snd->bl.y);
map->addnpc(m, wnd);
- wnd->bl.prev = wnd->bl.next = NULL;
- wnd->bl.m = m;
- wnd->bl.x = snd->bl.x;
- wnd->bl.y = snd->bl.y;
safestrncpy(wnd->name, "", ARRAYLENGTH(wnd->name));
safestrncpy(wnd->exname, newname, ARRAYLENGTH(wnd->exname));
wnd->class_ = WARP_CLASS;
@@ -3606,6 +3587,14 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st
return strchr(start,'\n');// continue
}
+
+void npc_parse_unknown_mapflag(const char *name, char *w3, char *w4, const char* start, const char* buffer, const char* filepath, int *retval)
+{
+ ShowError("npc_parse_mapflag: unrecognized mapflag '%s' in file '%s', line '%d'.\n", w3, filepath, strline(buffer,start-buffer));
+ if (retval)
+ *retval = EXIT_FAILURE;
+}
+
/*==========================================
* Set or disable mapflag on map
* eg : bat_c01<TAB>mapflag<TAB>battleground<TAB>2
@@ -4013,13 +4002,20 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
} else if ( !strcmpi(w3,"nocashshop") ) {
map->list[m].flag.nocashshop = (state) ? 1 : 0;
} else {
- ShowError("npc_parse_mapflag: unrecognized mapflag '%s' in file '%s', line '%d'.\n", w3, filepath, strline(buffer,start-buffer));
- if (retval) *retval = EXIT_FAILURE;
+ npc->parse_unknown_mapflag(mapname, w3, w4, start, buffer, filepath, retval);
}
return strchr(start,'\n');// continue
}
+const char* npc_parse_unknown_object(char *w1, char *w2, char *w3, char *w4, const char* start, const char* buffer, const char* filepath, int *retval)
+{
+ ShowError("npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ start = strchr(start,'\n');// skip and continue
+ *retval = EXIT_FAILURE;
+ return start;
+}
+
/**
* Parses a script file and creates NPCs/functions/mapflags/monsters/etc
* accordingly.
@@ -4208,9 +4204,7 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
}
else
{
- ShowError("npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4);
- p = strchr(p,'\n');// skip and continue
- success = EXIT_FAILURE;
+ p = npc->parse_unknown_object(w1, w2, w3, w4, p, buffer, filepath, &success);
}
}
aFree(buffer);
@@ -4663,6 +4657,7 @@ void npc_defaults(void) {
npc->parsename = npc_parsename;
npc->parseview = npc_parseview;
npc->viewisid = npc_viewisid;
+ npc->create_npc = npc_create_npc;
npc->add_warp = npc_add_warp;
npc->parse_warp = npc_parse_warp;
npc->parse_shop = npc_parse_shop;
@@ -4682,7 +4677,9 @@ void npc_defaults(void) {
npc->parse_mob2 = npc_parse_mob2;
npc->parse_mob = npc_parse_mob;
npc->parse_mapflag = npc_parse_mapflag;
+ npc->parse_unknown_mapflag = npc_parse_unknown_mapflag;
npc->parsesrcfile = npc_parsesrcfile;
+ npc->parse_unknown_object = npc_parse_unknown_object;
npc->script_event = npc_script_event;
npc->read_event_script = npc_read_event_script;
npc->path_db_clear_sub = npc_path_db_clear_sub;
diff --git a/src/map/npc.h b/src/map/npc.h
index 9c497ffe9..fba14d485 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -231,9 +231,11 @@ struct npc_interface {
void (*parsename) (struct npc_data *nd, const char *name, const char *start, const char *buffer, const char *filepath);
int (*parseview) (const char *w4, const char *start, const char *buffer, const char *filepath);
bool (*viewisid) (const char *viewid);
+ struct npc_data* (*create_npc) (int m, int x, int y);
struct npc_data* (*add_warp) (char *name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y);
const char* (*parse_warp) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
const char* (*parse_shop) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ const char* (*parse_unknown_object) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
void (*convertlabel_db) (struct npc_label_list *label_list, const char *filepath);
const char* (*skip_script) (const char *start, const char *buffer, const char *filepath, int *retval);
const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int options, int *retval);
@@ -250,6 +252,7 @@ struct npc_interface {
void (*parse_mob2) (struct spawn_data *mobspawn);
const char* (*parse_mob) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
const char* (*parse_mapflag) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ void (*parse_unknown_mapflag) (const char *name, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
int (*parsesrcfile) (const char *filepath, bool runOnInit);
int (*script_event) (struct map_session_data *sd, enum npce_event type);
void (*read_event_script) (void);
diff --git a/src/map/pc.c b/src/map/pc.c
index 6ba06c82b..9af5ee5ff 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -4519,7 +4519,7 @@ int pc_useitem(struct map_session_data *sd,int n) {
if( sd->inventory_data[n]->flag.delay_consume )
clif->useitemack(sd,n,amount,true);
else {
- if( sd->status.inventory[n].expire_time == 0 ) {
+ if (sd->status.inventory[n].expire_time == 0 && !(sd->inventory_data[n]->flag.keepafteruse)) {
clif->useitemack(sd,n,amount-1,true);
pc->delitem(sd,n,1,1,0,LOG_TYPE_CONSUME); // Rental Usable Items are not deleted until expiration
} else
diff --git a/src/map/pet.c b/src/map/pet.c
index 0378ea0c3..71dd39401 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -688,10 +688,7 @@ int pet_equipitem(struct map_session_data *sd,int index) {
//Skotlex: start support timers if need
int64 tick = timer->gettick();
if (pd->s_skill && pd->s_skill->timer == INVALID_TIMER) {
- if (pd->s_skill->id)
- pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000, pet->skill_support_timer, sd->bl.id, 0);
- else
- pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000, pet->heal_timer, sd->bl.id, 0);
+ pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000, pet->skill_support_timer, sd->bl.id, 0);
}
if (pd->bonus && pd->bonus->timer == INVALID_TIMER)
pd->bonus->timer=timer->add(tick+pd->bonus->delay*1000, pet->skill_bonus_timer, sd->bl.id, 0);
@@ -725,12 +722,8 @@ int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd) {
pd->state.skillbonus = 0;
status_calc_pc(sd,SCO_NONE);
}
- if( pd->s_skill && pd->s_skill->timer != INVALID_TIMER )
- {
- if( pd->s_skill->id )
- timer->delete(pd->s_skill->timer, pet->skill_support_timer);
- else
- timer->delete(pd->s_skill->timer, pet->heal_timer);
+ if (pd->s_skill && pd->s_skill->timer != INVALID_TIMER) {
+ timer->delete(pd->s_skill->timer, pet->skill_support_timer);
pd->s_skill->timer = INVALID_TIMER;
}
if( pd->bonus && pd->bonus->timer != INVALID_TIMER )
@@ -1117,40 +1110,6 @@ int pet_recovery_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-int pet_heal_timer(int tid, int64 tick, int id, intptr_t data) {
- struct map_session_data *sd=map->id2sd(id);
- struct status_data *st;
- struct pet_data *pd;
- unsigned int rate = 100;
-
- if(sd==NULL || sd->pd == NULL || sd->pd->s_skill == NULL)
- return 1;
-
- pd=sd->pd;
-
- if(pd->s_skill->timer != tid) {
- ShowError("pet_heal_timer %d != %d\n",pd->s_skill->timer,tid);
- return 0;
- }
-
- st = status->get_status_data(&sd->bl);
-
- if(pc_isdead(sd) ||
- (rate = get_percentage(st->sp, st->max_sp)) > pd->s_skill->sp ||
- (rate = get_percentage(st->hp, st->max_hp)) > pd->s_skill->hp ||
- (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=timer->add(timer->gettick()+(rate>10?rate:10)*100,pet->heal_timer,sd->bl.id,0);
- return 0;
- }
- pet_stop_attack(pd);
- pet_stop_walking(pd,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);
- pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000,pet->heal_timer,sd->bl.id,0);
- return 0;
-}
-
/*==========================================
* pet support skills [Skotlex]
*------------------------------------------*/
@@ -1361,7 +1320,6 @@ int do_init_pet(bool minimal) {
timer->add_func_list(pet->delay_item_drop,"pet_delay_item_drop");
timer->add_func_list(pet->skill_support_timer, "pet_skill_support_timer"); // [Skotlex]
timer->add_func_list(pet->recovery_timer,"pet_recovery_timer"); // [Valaris]
- timer->add_func_list(pet->heal_timer,"pet_heal_timer"); // [Valaris]
timer->add_interval(timer->gettick()+MIN_PETTHINKTIME,pet->ai_hard,0,0,MIN_PETTHINKTIME);
return 0;
@@ -1433,7 +1391,6 @@ void pet_defaults(void) {
pet->lootitem_drop = pet_lootitem_drop;
pet->skill_bonus_timer = pet_skill_bonus_timer;
pet->recovery_timer = pet_recovery_timer;
- pet->heal_timer = pet_heal_timer;
pet->skill_support_timer = pet_skill_support_timer;
pet->read_db = read_petdb;
}
diff --git a/src/map/pet.h b/src/map/pet.h
index 286109126..cffcf7dd0 100644
--- a/src/map/pet.h
+++ b/src/map/pet.h
@@ -149,7 +149,6 @@ struct pet_interface {
int (*lootitem_drop) (struct pet_data *pd, struct map_session_data *sd);
int (*skill_bonus_timer) (int tid, int64 tick, int id, intptr_t data);
int (*recovery_timer) (int tid, int64 tick, int id, intptr_t data);
- int (*heal_timer) (int tid, int64 tick, int id, intptr_t data);
int (*skill_support_timer) (int tid, int64 tick, int id, intptr_t data);
int (*read_db) ();
};
diff --git a/src/map/script.c b/src/map/script.c
index aa90a5b1c..e04ba6f32 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -155,7 +155,7 @@ static void script_dump_stack(struct script_state* st)
break;
case C_NAME:
- ShowMessage(" \"%s\" (id=%d ref=%p subtype=%s)\n", reference_getname(data), data->u.num, data->ref, script_op2name(script->str_data[data->u.num].type));
+ ShowMessage(" \"%s\" (id=%d ref=%p subtype=%s)\n", reference_getname(data), data->u.num, data->ref, script->op2name(script->str_data[data->u.num].type));
break;
case C_RETINFO:
@@ -12738,46 +12738,6 @@ BUILDIN(petrecovery)
}
/*==========================================
- * pet healing [Valaris] //Rewritten by [Skotlex]
- *------------------------------------------*/
-BUILDIN(petheal)
-{
- struct pet_data *pd;
- TBL_PC *sd=script->rid2sd(st);
-
- if(sd==NULL || sd->pd==NULL)
- return true;
-
- pd=sd->pd;
- if (pd->s_skill)
- { //Clear previous skill
- if (pd->s_skill->timer != INVALID_TIMER)
- {
- if (pd->s_skill->id)
- timer->delete(pd->s_skill->timer, pet->skill_support_timer);
- else
- timer->delete(pd->s_skill->timer, pet->heal_timer);
- }
- } else //init memory
- pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support));
-
- pd->s_skill->id=0; //This id identifies that it IS petheal rather than pet_skillsupport
- //Use the lv as the amount to heal
- pd->s_skill->lv=script_getnum(st,2);
- pd->s_skill->delay=script_getnum(st,3);
- pd->s_skill->hp=script_getnum(st,4);
- pd->s_skill->sp=script_getnum(st,5);
-
- //Use delay as initial offset to avoid skill/heal exploits
- if (battle_config.pet_equip_required && pd->pet.equip == 0)
- pd->s_skill->timer = INVALID_TIMER;
- else
- pd->s_skill->timer = timer->add(timer->gettick()+pd->s_skill->delay*1000,pet->heal_timer,sd->bl.id,0);
-
- return true;
-}
-
-/*==========================================
* pet attack skills [Valaris] //Rewritten by [Skotlex]
*------------------------------------------*/
/// petskillattack <skill id>,<level>,<rate>,<bonusrate>
@@ -12840,17 +12800,15 @@ BUILDIN(petskillsupport) {
return true;
pd=sd->pd;
- if (pd->s_skill)
- { //Clear previous skill
- if (pd->s_skill->timer != INVALID_TIMER)
- {
- if (pd->s_skill->id)
- timer->delete(pd->s_skill->timer, pet->skill_support_timer);
- else
- timer->delete(pd->s_skill->timer, pet->heal_timer);
+ if (pd->s_skill) {
+ //Clear previous skill
+ if (pd->s_skill->timer != INVALID_TIMER) {
+ timer->delete(pd->s_skill->timer, pet->skill_support_timer);
}
- } else //init memory
+ } else {
+ //init memory
pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support));
+ }
pd->s_skill->id=( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
pd->s_skill->lv=script_getnum(st,3);
@@ -16472,23 +16430,6 @@ BUILDIN(changequest) {
return true;
}
-// Deprecated
-// Please use questprogress instead.
-BUILDIN(checkquest) {
- struct map_session_data *sd = script->rid2sd(st);
- enum quest_check_type type = HAVEQUEST;
-
- if( sd == NULL )
- return false;
-
- if( script_hasdata(st, 3) )
- type = (enum quest_check_type)script_getnum(st, 3);
-
- script_pushint(st, quest->check(sd, script_getnum(st, 2), type));
-
- return true;
-}
-
BUILDIN(questactive) {
struct map_session_data *sd = script->rid2sd(st);
int quest_progress = 0;
@@ -19235,7 +19176,6 @@ void script_parse_builtin(void) {
BUILDIN_DEF(petskillbonus,"iiii"), // [Valaris]
BUILDIN_DEF(petrecovery,"ii"), // [Valaris]
BUILDIN_DEF(petloot,"i"), // [Valaris]
- BUILDIN_DEF_DEPRECATED(petheal,"iiii"), // Deprecated 2014-10-27 [Haru]
BUILDIN_DEF(petskillattack,"viii"), // [Skotlex]
BUILDIN_DEF(petskillattack2,"viiii"), // [Valaris]
BUILDIN_DEF(petskillsupport,"viiii"), // [Skotlex]
@@ -19285,7 +19225,6 @@ void script_parse_builtin(void) {
BUILDIN_DEF(gethominfo,"i"),
BUILDIN_DEF(getmercinfo,"i?"),
BUILDIN_DEF(checkequipedcard,"i"),
- BUILDIN_DEF2_DEPRECATED(__jump_zero,"jump_zero","il"), // Deprecated 2014-10-27 [Haru]
BUILDIN_DEF(globalmes,"s?"), //end jA addition
BUILDIN_DEF(unequip,"i"), // unequip command [Spectre]
BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris]
@@ -19477,7 +19416,6 @@ void script_parse_builtin(void) {
BUILDIN_DEF(setquest, "i"),
BUILDIN_DEF(erasequest, "i?"),
BUILDIN_DEF(completequest, "i?"),
- BUILDIN_DEF_DEPRECATED(checkquest, "i?"), // Deprecated 2014-10-28 [Haru]
BUILDIN_DEF(questprogress, "i?"),
BUILDIN_DEF(questactive, "i"),
BUILDIN_DEF(changequest, "ii"),
diff --git a/src/map/skill.c b/src/map/skill.c
index 169f4bcb9..1d94e0b14 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -2658,7 +2658,8 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
break;
// This ensures the storm randomly pushes instead of exactly a cell backwards per official mechanics.
case WZ_STORMGUST:
- dir = rnd()%8;
+ if(!battle_config.stormgust_knockback)
+ dir = rand()%8;
break;
case WL_CRIMSONROCK:
dir = map->calc_dir(bl,skill->area_temp[4],skill->area_temp[5]);
@@ -2856,9 +2857,11 @@ int skill_check_unit_range_sub (struct block_list *bl, va_list ap) {
g_skill_id = su->group->skill_id;
switch (skill_id) {
- case MH_STEINWAND:
- case MG_SAFETYWALL:
case AL_PNEUMA:
+ if(g_skill_id == SA_LANDPROTECTOR)
+ break;
+ case MG_SAFETYWALL:
+ case MH_STEINWAND:
case SC_MAELSTROM:
case SO_ELEMENTAL_SHIELD:
if(g_skill_id != MH_STEINWAND && g_skill_id != MG_SAFETYWALL && g_skill_id != AL_PNEUMA && g_skill_id != SC_MAELSTROM && g_skill_id != SO_ELEMENTAL_SHIELD)
@@ -3303,7 +3306,8 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
int x = skl->type>>16, y = skl->type&0xFFFF;
if( path->search_long(NULL, src->m, src->x, src->y, x, y, CELL_CHKWALL) )
skill->unitsetting(src,skl->skill_id,skl->skill_lv,x,y,skl->flag);
- if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
+ if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL)
+ && !map->getcell(src->m, skl->x, skl->y, CELL_CHKLANDPROTECTOR) )
clif->skill_poseffect(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,tick);
}
else if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
@@ -3758,8 +3762,6 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case NPC_SPLASHATTACK:
flag |= SD_PREAMBLE; // a fake packet will be sent for the first target to be hit
case AS_SPLASHER:
- case SM_MAGNUM:
- case MS_MAGNUM:
case HT_BLITZBEAT:
case AC_SHOWER:
case MA_SHOWER:
@@ -3869,6 +3871,14 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
}
break;
+ case SM_MAGNUM:
+ case MS_MAGNUM:
+ if( flag&1 ) {
+ //Damage depends on distance, so add it to flag if it is > 1
+ skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag|distance_bl(src, bl));
+ }
+ break;
+
case KN_BRANDISHSPEAR:
case ML_BRANDISH:
//Coded apart for it needs the flag passed to the damage calculation.
@@ -9896,7 +9906,6 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
}
pc_stop_attack(sd);
- pc_stop_walking(sd,0);
if(battle_config.skill_log && battle_config.skill_log&BL_PC)
ShowInfo("PC %d skill castend skill =%d map=%s\n",sd->bl.id,skill_id,mapname);
@@ -10098,6 +10107,11 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
}
case MG_SAFETYWALL:
+ if (map->foreachincell(skill->cell_overlap,src->m,x,y,BL_SKILL)) {
+ skill->unitsetting(src,skill_id,skill_lv,x,y,0);
+ return 0; // Don't consume gems if cast on LP
+ }
+
case MG_FIREWALL:
case MG_THUNDERSTORM:
@@ -10186,6 +10200,8 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case GN_THORNS_TRAP:
case GN_DEMONIC_FIRE:
case GN_HELLS_PLANT:
+ case GN_FIRE_EXPANSION_SMOKE_POWDER:
+ case GN_FIRE_EXPANSION_TEAR_GAS:
case SO_EARTHGRAVE:
case SO_DIAMONDDUST:
case SO_FIRE_INSIGNIA:
@@ -10265,7 +10281,8 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
tmpx = x - area + rnd()%(area * 2 + 1);
tmpy = y - area + rnd()%(area * 2 + 1);
- if( i == 0 && path->search_long(NULL, src->m, src->x, src->y, tmpx, tmpy, CELL_CHKWALL) )
+ if( i == 0 && path->search_long(NULL, src->m, src->x, src->y, tmpx, tmpy, CELL_CHKWALL)
+ && !map->getcell(src->m, tmpx, tmpy, CELL_CHKLANDPROTECTOR))
clif->skill_poseffect(src,skill_id,skill_lv,tmpx,tmpy,tick);
if( i > 0 )
@@ -10641,13 +10658,14 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case GN_FIRE_EXPANSION: {
int i;
+ int aciddemocast = 5;//If player doesent know Acid Demonstration or knows level 5 or lower, effect 5 will cast level 5 Acid Demo.
struct unit_data *ud = unit->bl2ud(src);
if( !ud ) break;
for( i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i]; i ++ ) {
if( ud->skillunit[i]->skill_id == GN_DEMONIC_FIRE &&
- distance_xy(x, y, ud->skillunit[i]->unit->bl.x, ud->skillunit[i]->unit->bl.y) < 4 ) {
+ distance_xy(x, y, ud->skillunit[i]->unit->bl.x, ud->skillunit[i]->unit->bl.y) < 3 ) {
switch( skill_lv ) {
case 3:
ud->skillunit[i]->unit_id = UNT_FIRE_EXPANSION_SMOKE_POWDER;
@@ -10657,11 +10675,13 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
ud->skillunit[i]->unit_id = UNT_FIRE_EXPANSION_TEAR_GAS;
clif->changetraplook(&ud->skillunit[i]->unit->bl, UNT_FIRE_EXPANSION_TEAR_GAS);
break;
- case 5:
+ case 5:// If player knows a level of Acid Demonstration greater then 5, that level will be casted.
+ if ( pc->checkskill(sd, CR_ACIDDEMONSTRATION) > 5 )
+ aciddemocast = pc->checkskill(sd, CR_ACIDDEMONSTRATION);
map->foreachinarea(skill->area_sub, src->m,
- ud->skillunit[i]->unit->bl.x - 3, ud->skillunit[i]->unit->bl.y - 3,
- ud->skillunit[i]->unit->bl.x + 3, ud->skillunit[i]->unit->bl.y + 3, BL_CHAR,
- src, CR_ACIDDEMONSTRATION, sd ? pc->checkskill(sd, CR_ACIDDEMONSTRATION) : skill_lv, tick, flag|BCT_ENEMY|1|SD_LEVEL, skill->castend_damage_id);
+ ud->skillunit[i]->unit->bl.x - 2, ud->skillunit[i]->unit->bl.y - 2,
+ ud->skillunit[i]->unit->bl.x + 2, ud->skillunit[i]->unit->bl.y + 2, BL_CHAR,
+ src, CR_ACIDDEMONSTRATION, aciddemocast, tick, flag|BCT_ENEMY|1|SD_LEVEL, skill->castend_damage_id);
skill->delunit(ud->skillunit[i]->unit);
break;
default:
@@ -11288,8 +11308,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
if (skill->get_unit_flag(skill_id) & UF_RANGEDSINGLEUNIT && i == (layout->count / 2))
val2 |= UF_RANGEDSINGLEUNIT; // center.
- if( range <= 0 )
- map->foreachincell(skill->cell_overlap,src->m,ux,uy,BL_SKILL,skill_id, &alive, src);
+ map->foreachincell(skill->cell_overlap,src->m,ux,uy,BL_SKILL,skill_id, &alive, src);
if( !alive )
continue;
@@ -11344,7 +11363,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
nullpo_ret(sg=src->group);
nullpo_ret(ss=map->id2bl(sg->src_id));
- if( skill->get_type(sg->skill_id) == BF_MAGIC && map->getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR )
+ if( skill->get_type(sg->skill_id) == BF_MAGIC && map->getcell(src->bl.m, src->bl.x, src->bl.y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR )
return 0; //AoE skills are ineffective. [Skotlex]
sc = status->get_sc(bl);
@@ -12142,11 +12161,11 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
break;
case UNT_FIRE_EXPANSION_SMOKE_POWDER:
- sc_start(ss, bl, status->skill2sc(GN_FIRE_EXPANSION_SMOKE_POWDER), 100, sg->skill_lv, 1000);
+ sc_start(ss, bl, SC_FIRE_EXPANSION_SMOKE_POWDER, 100, sg->skill_lv, 1000);
break;
case UNT_FIRE_EXPANSION_TEAR_GAS:
- sc_start(ss, bl, status->skill2sc(GN_FIRE_EXPANSION_TEAR_GAS), 100, sg->skill_lv, 1000);
+ sc_start(ss, bl, SC_FIRE_EXPANSION_TEAR_GAS, 100, sg->skill_lv, 1000);
break;
case UNT_HELLS_PLANT:
@@ -16010,7 +16029,7 @@ int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap) {
nullpo_ret(group);
- if( !(skill->get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP|INF2_NOLP)) && map->getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) )
+ if( !(skill->get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP|INF2_NOLP)) && map->getcell(su->bl.m, su->bl.x, su->bl.y, CELL_CHKLANDPROTECTOR) )
return 0; //AoE skills are ineffective. [Skotlex]
if( battle->check_target(&su->bl,bl,group->target_flag) <= 0 )
diff --git a/src/map/status.c b/src/map/status.c
index e2eede490..d7146adf6 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -3639,6 +3639,21 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
if (!bst || !st)
return;
+ /** [Playtester]
+ * This needs to be done even if there is currently no status change active, because
+ * we need to update the speed on the client when the last status change ends.
+ **/
+ if(flag&SCB_SPEED) {
+ struct unit_data *ud = unit->bl2ud(bl);
+ /** [Skotlex]
+ * Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER
+ * because if you step on something while walking, the moment this
+ * piece of code triggers the walk-timer is set on INVALID_TIMER)
+ **/
+ if (ud)
+ ud->state.change_walk_target = ud->state.speed_changed = 1;
+ }
+
if((!(bl->type&BL_REGEN)) && (!sc || !sc->count)) { //No difference.
status_cpy(st, bst);
return;
@@ -3815,16 +3830,9 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
}
if(flag&SCB_SPEED) {
- struct unit_data *ud = unit->bl2ud(bl);
st->speed = status->calc_speed(bl, sc, bst->speed);
- //Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER
- //because if you step on something while walking, the moment this
- //piece of code triggers the walk-timer is set on INVALID_TIMER) [Skotlex]
- if (ud)
- ud->state.change_walk_target = ud->state.speed_changed = 1;
-
if( bl->type&BL_PC && !(sd && sd->state.permanent_speed) && st->speed < battle_config.max_walk_speed )
st->speed = battle_config.max_walk_speed;
@@ -4194,14 +4202,14 @@ unsigned short status_calc_str(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return cap_value(str,0,USHRT_MAX);
+ if(sc->data[SC_FULL_THROTTLE])
+ str += str * 20 / 100;
if(sc->data[SC_HARMONIZE]) {
str -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(str,0,USHRT_MAX);
}
if(sc->data[SC_BEYOND_OF_WARCRY])
str += sc->data[SC_BEYOND_OF_WARCRY]->val3;
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && str < 50)
- return 50;
if(sc->data[SC_INCALLSTATUS])
str += sc->data[SC_INCALLSTATUS]->val1;
if(sc->data[SC_CHASEWALK2])
@@ -4232,6 +4240,8 @@ unsigned short status_calc_str(struct block_list *bl, struct status_change *sc,
str -= ((sc->data[SC_MARIONETTE_MASTER]->val3)>>16)&0xFF;
if(sc->data[SC_MARIONETTE])
str += ((sc->data[SC_MARIONETTE]->val3)>>16)&0xFF;
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ str += ((sc->data[SC_SOULLINK]->val3)>>16)&0xFF;
if(sc->data[SC_GIANTGROWTH])
str += 30;
if(sc->data[SC_SAVAGE_STEAK])
@@ -4242,8 +4252,6 @@ unsigned short status_calc_str(struct block_list *bl, struct status_change *sc,
str -= sc->data[SC_STOMACHACHE]->val1;
if(sc->data[SC_KYOUGAKU])
str -= sc->data[SC_KYOUGAKU]->val3;
- if(sc->data[SC_FULL_THROTTLE])
- str += str * 20 / 100;
return (unsigned short)cap_value(str,0,USHRT_MAX);
}
@@ -4253,12 +4261,12 @@ unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return cap_value(agi,0,USHRT_MAX);
+ if(sc->data[SC_FULL_THROTTLE])
+ agi += agi * 20 / 100;
if(sc->data[SC_HARMONIZE]) {
agi -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(agi,0,USHRT_MAX);
}
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && agi < 50)
- return 50;
if(sc->data[SC_CONCENTRATION] && !sc->data[SC_QUAGMIRE])
agi += (agi-sc->data[SC_CONCENTRATION]->val3)*sc->data[SC_CONCENTRATION]->val2/100;
if(sc->data[SC_INCALLSTATUS])
@@ -4287,6 +4295,8 @@ unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc,
agi -= ((sc->data[SC_MARIONETTE_MASTER]->val3)>>8)&0xFF;
if(sc->data[SC_MARIONETTE])
agi += ((sc->data[SC_MARIONETTE]->val3)>>8)&0xFF;
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ agi += ((sc->data[SC_SOULLINK]->val3)>>8)&0xFF;
if(sc->data[SC_ADORAMUS])
agi -= sc->data[SC_ADORAMUS]->val2;
if(sc->data[SC_DROCERA_HERB_STEAMED])
@@ -4300,8 +4310,6 @@ unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_MARSHOFABYSS])
agi -= agi * sc->data[SC_MARSHOFABYSS]->val2 / 100;
- if(sc->data[SC_FULL_THROTTLE])
- agi += agi * 20 / 100;
return (unsigned short)cap_value(agi,0,USHRT_MAX);
}
@@ -4311,12 +4319,12 @@ unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return cap_value(vit,0,USHRT_MAX);
+ if(sc->data[SC_FULL_THROTTLE])
+ vit += vit * 20 / 100;
if(sc->data[SC_HARMONIZE]) {
vit -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(vit,0,USHRT_MAX);
}
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && vit < 50)
- return 50;
if(sc->data[SC_INCALLSTATUS])
vit += sc->data[SC_INCALLSTATUS]->val1;
if(sc->data[SC_INCVIT])
@@ -4335,6 +4343,8 @@ unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc,
vit -= sc->data[SC_MARIONETTE_MASTER]->val3&0xFF;
if(sc->data[SC_MARIONETTE])
vit += sc->data[SC_MARIONETTE]->val3&0xFF;
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ vit += sc->data[SC_SOULLINK]->val3&0xFF;
if(sc->data[SC_LAUDAAGNUS])
vit += 4 + sc->data[SC_LAUDAAGNUS]->val1;
if(sc->data[SC_MINOR_BBQ])
@@ -4348,8 +4358,6 @@ unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_NOEQUIPARMOR])
vit -= vit * sc->data[SC_NOEQUIPARMOR]->val2/100;
- if(sc->data[SC_FULL_THROTTLE])
- vit += vit * 20 / 100;
return (unsigned short)cap_value(vit,0,USHRT_MAX);
}
@@ -4359,14 +4367,14 @@ unsigned short status_calc_int(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return cap_value(int_,0,USHRT_MAX);
+ if(sc->data[SC_FULL_THROTTLE])
+ int_ += int_ * 20 / 100;
if(sc->data[SC_HARMONIZE]) {
int_ -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(int_,0,USHRT_MAX);
}
if(sc->data[SC_MELODYOFSINK])
int_ -= sc->data[SC_MELODYOFSINK]->val3;
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && int_ < 50)
- return 50;
if(sc->data[SC_INCALLSTATUS])
int_ += sc->data[SC_INCALLSTATUS]->val1;
if(sc->data[SC_INCINT])
@@ -4393,6 +4401,8 @@ unsigned short status_calc_int(struct block_list *bl, struct status_change *sc,
int_ -= ((sc->data[SC_MARIONETTE_MASTER]->val4)>>16)&0xFF;
if(sc->data[SC_MARIONETTE])
int_ += ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF;
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ int_ += ((sc->data[SC_SOULLINK]->val4)>>16)&0xFF;
if(sc->data[SC_MANDRAGORA])
int_ -= 4 * sc->data[SC_MANDRAGORA]->val1;
if(sc->data[SC_COCKTAIL_WARG_BLOOD])
@@ -4410,8 +4420,6 @@ unsigned short status_calc_int(struct block_list *bl, struct status_change *sc,
if(sc->data[SC__STRIPACCESSARY])
int_ -= int_ * sc->data[SC__STRIPACCESSARY]->val2 / 100;
}
- if(sc->data[SC_FULL_THROTTLE])
- int_ += int_ * 20 / 100;
return (unsigned short)cap_value(int_,0,USHRT_MAX);
}
@@ -4421,12 +4429,12 @@ unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return cap_value(dex,0,USHRT_MAX);
+ if(sc->data[SC_FULL_THROTTLE])
+ dex += dex * 20 / 100;
if(sc->data[SC_HARMONIZE]) {
dex -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(dex,0,USHRT_MAX);
}
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && dex < 50)
- return 50;
if(sc->data[SC_CONCENTRATION] && !sc->data[SC_QUAGMIRE])
dex += (dex-sc->data[SC_CONCENTRATION]->val4)*sc->data[SC_CONCENTRATION]->val2/100;
if(sc->data[SC_INCALLSTATUS])
@@ -4457,6 +4465,8 @@ unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc,
dex -= ((sc->data[SC_MARIONETTE_MASTER]->val4)>>8)&0xFF;
if(sc->data[SC_MARIONETTE])
dex += ((sc->data[SC_MARIONETTE]->val4)>>8)&0xFF;
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ dex += ((sc->data[SC_SOULLINK]->val4)>>8)&0xFF;
if(sc->data[SC_SIROMA_ICE_TEA])
dex += sc->data[SC_SIROMA_ICE_TEA]->val1;
if(sc->data[SC_INSPIRATION])
@@ -4470,8 +4480,6 @@ unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc,
dex -= dex * sc->data[SC_MARSHOFABYSS]->val2 / 100;
if(sc->data[SC__STRIPACCESSARY] && bl->type != BL_PC)
dex -= dex * sc->data[SC__STRIPACCESSARY]->val2 / 100;
- if(sc->data[SC_FULL_THROTTLE])
- dex += dex * 20 / 100;
return (unsigned short)cap_value(dex,0,USHRT_MAX);
}
@@ -4481,14 +4489,14 @@ unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return cap_value(luk,0,USHRT_MAX);
+ if(sc->data[SC_FULL_THROTTLE])
+ luk += luk * 20 / 100;
if(sc->data[SC_HARMONIZE]) {
luk -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(luk,0,USHRT_MAX);
}
if(sc->data[SC_CURSE])
return 0;
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && luk < 50)
- return 50;
if(sc->data[SC_INCALLSTATUS])
luk += sc->data[SC_INCALLSTATUS]->val1;
if(sc->data[SC_INCLUK])
@@ -4505,6 +4513,8 @@ unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc,
luk -= sc->data[SC_MARIONETTE_MASTER]->val4&0xFF;
if(sc->data[SC_MARIONETTE])
luk += sc->data[SC_MARIONETTE]->val4&0xFF;
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ luk += sc->data[SC_SOULLINK]->val4&0xFF;
if(sc->data[SC_PUTTI_TAILS_NOODLES])
luk += sc->data[SC_PUTTI_TAILS_NOODLES]->val1;
if(sc->data[SC_INSPIRATION])
@@ -4520,8 +4530,6 @@ unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc,
luk -= luk * sc->data[SC__STRIPACCESSARY]->val2 / 100;
if(sc->data[SC_BANANA_BOMB])
luk -= luk * sc->data[SC_BANANA_BOMB]->val1 / 100;
- if(sc->data[SC_FULL_THROTTLE])
- luk += luk * 20 / 100;
return (unsigned short)cap_value(luk,0,USHRT_MAX);
}
@@ -4837,6 +4845,8 @@ signed short status_calc_hit(struct block_list *bl, struct status_change *sc, in
hit += hit * sc->data[SC_INCHITRATE]->val1/100;
if(sc->data[SC_BLIND])
hit -= hit * 25/100;
+ if(sc->data[SC_FIRE_EXPANSION_TEAR_GAS])
+ hit -= hit * 50 / 100;
if(sc->data[SC__GROOMY])
hit -= hit * sc->data[SC__GROOMY]->val3 / 100;
if(sc->data[SC_FEAR])
@@ -4922,6 +4932,10 @@ signed short status_calc_flee(struct block_list *bl, struct status_change *sc, i
flee -= flee * ( 20 + 5 * sc->data[SC_GLOOMYDAY]->val1 ) / 100;
if( sc->data[SC_SATURDAY_NIGHT_FEVER] )
flee -= flee * (40 + 10 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1) / 100;
+ if ( sc->data[SC_FIRE_EXPANSION_SMOKE_POWDER] )
+ flee += flee * 20 / 100;
+ if ( sc->data[SC_FIRE_EXPANSION_TEAR_GAS] )
+ flee -= flee * 50 / 100;
if( sc->data[SC_WIND_STEP_OPTION] )
flee += flee * sc->data[SC_WIND_STEP_OPTION]->val2 / 100;
if( sc->data[SC_ZEPHYR] )
@@ -5371,7 +5385,7 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
if( sc->data[SC_WIND_STEP_OPTION] )
val = max( val, sc->data[SC_WIND_STEP_OPTION]->val2 );
if( sc->data[SC_FULL_THROTTLE] )
- val = max( val, 30);
+ val = max( val, 25);
//FIXME: official items use a single bonus for this [ultramage]
if( sc->data[SC_MOVHASTE_HORSE] ) // temporary item-based speedup
val = max( val, 25 );
@@ -7231,9 +7245,13 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
status_change_end(bl, SC_STONE, INVALID_TIMER);
}
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
break;
case SC_INC_AGI:
status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
break;
case SC_QUAGMIRE:
status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER);
@@ -8051,6 +8069,23 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
stat = (psce->val4 >> 0)&0xFF; stat = min(stat, max_stat - tst->luk ); val4 |= cap_value(stat,0,0xFF);
}
break;
+ case SC_SOULLINK:
+ //1st Transcendent Spirit works similar to Marionette Control
+ if(sd && val2 == SL_HIGH) {
+ int stat,max_stat;
+ // Fetch target's stats
+ struct status_data* status2 = status_get_status_data(bl); // Battle status
+ val3 = 0;
+ val4 = 0;
+ max_stat = (status_get_lv(bl)-10<50)?status_get_lv(bl)-10:50;
+ stat = max(0, max_stat - status2->str ); val3 |= cap_value(stat,0,0xFF)<<16;
+ stat = max(0, max_stat - status2->agi ); val3 |= cap_value(stat,0,0xFF)<<8;
+ stat = max(0, max_stat - status2->vit ); val3 |= cap_value(stat,0,0xFF);
+ stat = max(0, max_stat - status2->int_); val4 |= cap_value(stat,0,0xFF)<<16;
+ stat = max(0, max_stat - status2->dex ); val4 |= cap_value(stat,0,0xFF)<<8;
+ stat = max(0, max_stat - status2->luk ); val4 |= cap_value(stat,0,0xFF);
+ }
+ break;
case SC_SWORDREJECT:
val2 = 15*val1; //Reflect chance
val3 = 3; //Reflections
diff --git a/src/map/unit.c b/src/map/unit.c
index 2ab13b121..c78919f52 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -100,6 +100,13 @@ int unit_walktoxy_sub(struct block_list *bl)
if( !path->search(&wpd,bl->m,bl->x,bl->y,ud->to_x,ud->to_y,ud->state.walk_easy,CELL_CHKNOPASS) )
return 0;
+#ifdef OFFICIAL_WALKPATH
+ if( !path->search_long(NULL, bl->m, bl->x, bl->y, ud->to_x, ud->to_y, CELL_CHKNOPASS) // Check if there is an obstacle between
+ && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
+ && (bl->type != BL_NPC) ) // If type is a NPC, please disregard.
+ return 0;
+#endif
+
memcpy(&ud->walkpath,&wpd,sizeof(wpd));
if (ud->target_to && ud->chaserange>1) {
@@ -391,8 +398,14 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
ud->steptimer = timer->add(tick+i, unit->step_timer, bl->id, 0);
}
- if(ud->state.change_walk_target)
- return unit->walktoxy_sub(bl);
+ if(ud->state.change_walk_target) {
+ if(unit_walktoxy_sub(bl)) {
+ return 1;
+ } else {
+ clif->fixpos(bl);
+ return 0;
+ }
+ }
ud->walkpath.path_pos++;
if(ud->walkpath.path_pos>=ud->walkpath.path_len)
@@ -572,6 +585,10 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
ud->to_y = bl->y;
ud->target_to = 0;
return 0;
+ } else if (range == 0) {
+ //Should walk on the same cell as target (for looters)
+ ud->to_x = tbl->x;
+ ud->to_y = tbl->y;
}
ud->state.walk_easy = flag&1;
@@ -1131,6 +1148,10 @@ int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type) {
if (delay <= 0 || !ud) return 0;
if (type) {
+ //Bosses can ignore skill induced walkdelay (but not damage induced)
+ if(bl->type == BL_MOB && (((TBL_MOB*)bl)->status.mode&MD_BOSS))
+ return 0;
+ //Make sure walk delay is not decreased
if (DIFF_TICK(ud->canmove_tick, tick+delay) > 0)
return 0;
} else {
@@ -1619,14 +1640,6 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
if( skill->not_ok(skill_id, sd) || !skill->check_condition_castbegin(sd, skill_id, skill_lv) )
return 0;
/**
- * "WHY IS IT HEREE": pneuma cannot be canceled past this point, the client displays the animation even,
- * if we cancel it from nodamage_id, so it has to be here for it to not display the animation.
- **/
- if( skill_id == AL_PNEUMA && map->getcell(src->m, skill_x, skill_y, CELL_CHKLANDPROTECTOR) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- return 0;
- }
- /**
* "WHY IS IT HEREE": ice wall cannot be canceled past this point, the client displays the animation even,
* if we cancel it from castend_pos, so it has to be here for it to not display the animation.
**/
@@ -2310,7 +2323,7 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i
//Clear target even if there is no timer
if (ud->target || ud->attacktimer != INVALID_TIMER)
- unit_stop_attack(bl);
+ unit->stop_attack(bl);
//Clear stepaction even if there is no timer
if (ud->stepaction || ud->steptimer != INVALID_TIMER)
@@ -2660,10 +2673,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
if( pd->s_skill )
{
if (pd->s_skill->timer != INVALID_TIMER) {
- if (pd->s_skill->id)
- timer->delete(pd->s_skill->timer, pet->skill_support_timer);
- else
- timer->delete(pd->s_skill->timer, pet->heal_timer);
+ timer->delete(pd->s_skill->timer, pet->skill_support_timer);
}
aFree(pd->s_skill);
pd->s_skill = NULL;
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
index 6e982bb70..9c616ba00 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
@@ -3301,12 +3301,16 @@ struct {
struct HPMHookPoint *HP_npc_parseview_post;
struct HPMHookPoint *HP_npc_viewisid_pre;
struct HPMHookPoint *HP_npc_viewisid_post;
+ struct HPMHookPoint *HP_npc_create_npc_pre;
+ struct HPMHookPoint *HP_npc_create_npc_post;
struct HPMHookPoint *HP_npc_add_warp_pre;
struct HPMHookPoint *HP_npc_add_warp_post;
struct HPMHookPoint *HP_npc_parse_warp_pre;
struct HPMHookPoint *HP_npc_parse_warp_post;
struct HPMHookPoint *HP_npc_parse_shop_pre;
struct HPMHookPoint *HP_npc_parse_shop_post;
+ struct HPMHookPoint *HP_npc_parse_unknown_object_pre;
+ struct HPMHookPoint *HP_npc_parse_unknown_object_post;
struct HPMHookPoint *HP_npc_convertlabel_db_pre;
struct HPMHookPoint *HP_npc_convertlabel_db_post;
struct HPMHookPoint *HP_npc_skip_script_pre;
@@ -3339,6 +3343,8 @@ struct {
struct HPMHookPoint *HP_npc_parse_mob_post;
struct HPMHookPoint *HP_npc_parse_mapflag_pre;
struct HPMHookPoint *HP_npc_parse_mapflag_post;
+ struct HPMHookPoint *HP_npc_parse_unknown_mapflag_pre;
+ struct HPMHookPoint *HP_npc_parse_unknown_mapflag_post;
struct HPMHookPoint *HP_npc_parsesrcfile_pre;
struct HPMHookPoint *HP_npc_parsesrcfile_post;
struct HPMHookPoint *HP_npc_script_event_pre;
@@ -3995,8 +4001,6 @@ struct {
struct HPMHookPoint *HP_pet_skill_bonus_timer_post;
struct HPMHookPoint *HP_pet_recovery_timer_pre;
struct HPMHookPoint *HP_pet_recovery_timer_post;
- struct HPMHookPoint *HP_pet_heal_timer_pre;
- struct HPMHookPoint *HP_pet_heal_timer_post;
struct HPMHookPoint *HP_pet_skill_support_timer_pre;
struct HPMHookPoint *HP_pet_skill_support_timer_post;
struct HPMHookPoint *HP_pet_read_db_pre;
@@ -8360,12 +8364,16 @@ struct {
int HP_npc_parseview_post;
int HP_npc_viewisid_pre;
int HP_npc_viewisid_post;
+ int HP_npc_create_npc_pre;
+ int HP_npc_create_npc_post;
int HP_npc_add_warp_pre;
int HP_npc_add_warp_post;
int HP_npc_parse_warp_pre;
int HP_npc_parse_warp_post;
int HP_npc_parse_shop_pre;
int HP_npc_parse_shop_post;
+ int HP_npc_parse_unknown_object_pre;
+ int HP_npc_parse_unknown_object_post;
int HP_npc_convertlabel_db_pre;
int HP_npc_convertlabel_db_post;
int HP_npc_skip_script_pre;
@@ -8398,6 +8406,8 @@ struct {
int HP_npc_parse_mob_post;
int HP_npc_parse_mapflag_pre;
int HP_npc_parse_mapflag_post;
+ int HP_npc_parse_unknown_mapflag_pre;
+ int HP_npc_parse_unknown_mapflag_post;
int HP_npc_parsesrcfile_pre;
int HP_npc_parsesrcfile_post;
int HP_npc_script_event_pre;
@@ -9054,8 +9064,6 @@ struct {
int HP_pet_skill_bonus_timer_post;
int HP_pet_recovery_timer_pre;
int HP_pet_recovery_timer_post;
- int HP_pet_heal_timer_pre;
- int HP_pet_heal_timer_post;
int HP_pet_skill_support_timer_pre;
int HP_pet_skill_support_timer_post;
int HP_pet_read_db_pre;
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
index 00bd82f94..545f07d01 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
@@ -1677,9 +1677,11 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(npc->parsename, HP_npc_parsename) },
{ HP_POP(npc->parseview, HP_npc_parseview) },
{ HP_POP(npc->viewisid, HP_npc_viewisid) },
+ { HP_POP(npc->create_npc, HP_npc_create_npc) },
{ HP_POP(npc->add_warp, HP_npc_add_warp) },
{ HP_POP(npc->parse_warp, HP_npc_parse_warp) },
{ HP_POP(npc->parse_shop, HP_npc_parse_shop) },
+ { HP_POP(npc->parse_unknown_object, HP_npc_parse_unknown_object) },
{ HP_POP(npc->convertlabel_db, HP_npc_convertlabel_db) },
{ HP_POP(npc->skip_script, HP_npc_skip_script) },
{ HP_POP(npc->parse_script, HP_npc_parse_script) },
@@ -1696,6 +1698,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(npc->parse_mob2, HP_npc_parse_mob2) },
{ HP_POP(npc->parse_mob, HP_npc_parse_mob) },
{ HP_POP(npc->parse_mapflag, HP_npc_parse_mapflag) },
+ { HP_POP(npc->parse_unknown_mapflag, HP_npc_parse_unknown_mapflag) },
{ HP_POP(npc->parsesrcfile, HP_npc_parsesrcfile) },
{ HP_POP(npc->script_event, HP_npc_script_event) },
{ HP_POP(npc->read_event_script, HP_npc_read_event_script) },
@@ -2029,7 +2032,6 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(pet->lootitem_drop, HP_pet_lootitem_drop) },
{ HP_POP(pet->skill_bonus_timer, HP_pet_skill_bonus_timer) },
{ HP_POP(pet->recovery_timer, HP_pet_recovery_timer) },
- { HP_POP(pet->heal_timer, HP_pet_heal_timer) },
{ HP_POP(pet->skill_support_timer, HP_pet_skill_support_timer) },
{ HP_POP(pet->read_db, HP_pet_read_db) },
/* quest */
diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index 57a609024..35e98693c 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -44115,6 +44115,33 @@ bool HP_npc_viewisid(const char *viewid) {
}
return retVal___;
}
+struct npc_data* HP_npc_create_npc(int m, int x, int y) {
+ int hIndex = 0;
+ struct npc_data* retVal___ = NULL;
+ if( HPMHooks.count.HP_npc_create_npc_pre ) {
+ struct npc_data* (*preHookFunc) (int *m, int *x, int *y);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_npc_create_npc_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_npc_create_npc_pre[hIndex].func;
+ retVal___ = preHookFunc(&m, &x, &y);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.npc.create_npc(m, x, y);
+ }
+ if( HPMHooks.count.HP_npc_create_npc_post ) {
+ struct npc_data* (*postHookFunc) (struct npc_data* retVal___, int *m, int *x, int *y);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_npc_create_npc_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_npc_create_npc_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, &m, &x, &y);
+ }
+ }
+ return retVal___;
+}
struct npc_data* HP_npc_add_warp(char *name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y) {
int hIndex = 0;
struct npc_data* retVal___ = NULL;
@@ -44196,6 +44223,33 @@ const char* HP_npc_parse_shop(char *w1, char *w2, char *w3, char *w4, const char
}
return retVal___;
}
+const char* HP_npc_parse_unknown_object(char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval) {
+ int hIndex = 0;
+ const char* retVal___ = NULL;
+ if( HPMHooks.count.HP_npc_parse_unknown_object_pre ) {
+ const char* (*preHookFunc) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_npc_parse_unknown_object_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_npc_parse_unknown_object_pre[hIndex].func;
+ retVal___ = preHookFunc(w1, w2, w3, w4, start, buffer, filepath, retval);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.npc.parse_unknown_object(w1, w2, w3, w4, start, buffer, filepath, retval);
+ }
+ if( HPMHooks.count.HP_npc_parse_unknown_object_post ) {
+ const char* (*postHookFunc) (const char* retVal___, char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_npc_parse_unknown_object_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_npc_parse_unknown_object_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, w1, w2, w3, w4, start, buffer, filepath, retval);
+ }
+ }
+ return retVal___;
+}
void HP_npc_convertlabel_db(struct npc_label_list *label_list, const char *filepath) {
int hIndex = 0;
if( HPMHooks.count.HP_npc_convertlabel_db_pre ) {
@@ -44627,6 +44681,32 @@ const char* HP_npc_parse_mapflag(char *w1, char *w2, char *w3, char *w4, const c
}
return retVal___;
}
+void HP_npc_parse_unknown_mapflag(const char *name, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_npc_parse_unknown_mapflag_pre ) {
+ void (*preHookFunc) (const char *name, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_npc_parse_unknown_mapflag_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_npc_parse_unknown_mapflag_pre[hIndex].func;
+ preHookFunc(name, w3, w4, start, buffer, filepath, retval);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.npc.parse_unknown_mapflag(name, w3, w4, start, buffer, filepath, retval);
+ }
+ if( HPMHooks.count.HP_npc_parse_unknown_mapflag_post ) {
+ void (*postHookFunc) (const char *name, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_npc_parse_unknown_mapflag_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_npc_parse_unknown_mapflag_post[hIndex].func;
+ postHookFunc(name, w3, w4, start, buffer, filepath, retval);
+ }
+ }
+ return;
+}
int HP_npc_parsesrcfile(const char *filepath, bool runOnInit) {
int hIndex = 0;
int retVal___ = 0;
@@ -53492,33 +53572,6 @@ int HP_pet_recovery_timer(int tid, int64 tick, int id, intptr_t data) {
}
return retVal___;
}
-int HP_pet_heal_timer(int tid, int64 tick, int id, intptr_t data) {
- int hIndex = 0;
- int retVal___ = 0;
- if( HPMHooks.count.HP_pet_heal_timer_pre ) {
- int (*preHookFunc) (int *tid, int64 *tick, int *id, intptr_t *data);
- *HPMforce_return = false;
- for(hIndex = 0; hIndex < HPMHooks.count.HP_pet_heal_timer_pre; hIndex++ ) {
- preHookFunc = HPMHooks.list.HP_pet_heal_timer_pre[hIndex].func;
- retVal___ = preHookFunc(&tid, &tick, &id, &data);
- }
- if( *HPMforce_return ) {
- *HPMforce_return = false;
- return retVal___;
- }
- }
- {
- retVal___ = HPMHooks.source.pet.heal_timer(tid, tick, id, data);
- }
- if( HPMHooks.count.HP_pet_heal_timer_post ) {
- int (*postHookFunc) (int retVal___, int *tid, int64 *tick, int *id, intptr_t *data);
- for(hIndex = 0; hIndex < HPMHooks.count.HP_pet_heal_timer_post; hIndex++ ) {
- postHookFunc = HPMHooks.list.HP_pet_heal_timer_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, &tid, &tick, &id, &data);
- }
- }
- return retVal___;
-}
int HP_pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) {
int hIndex = 0;
int retVal___ = 0;
diff --git a/tools/validateinterfaces.py b/tools/validateinterfaces.py
index a4222adb5..b34bd6233 100755
--- a/tools/validateinterfaces.py
+++ b/tools/validateinterfaces.py
@@ -26,7 +26,7 @@ def searchStructStart(r, ifname):
return True
return False
-def readCFile(cFile):
+def readCFile(tracker, cFile):
methods = Set()
shortIfName = ""
with open(cFile, "r") as r:
@@ -38,7 +38,7 @@ def readCFile(cFile):
ifname = m.group("name1")
if searchDefault(r, ifname) == False:
return (None, shortIfName, methods)
- lineRe = re.compile("(?P<ifname>[a-z_]+)->(?P<method>[\w_]+) ")
+ lineRe = re.compile("(?P<ifname>[a-z_]+)->(?P<method>[\w_]+)[ ][=][ ](?P<fullmethod>[^;]+);")
for line in r:
# print "cline2: " + line
test = line.strip()
@@ -55,10 +55,12 @@ def readCFile(cFile):
shortIfName = m.group("ifname")
# print "{2}: add {0}, from: {1}".format(m.group("method"), line, ifname)
methods.add(m.group("method"))
+ tracker.interfaces.add(ifname);
+ tracker.fullmethods.add(m.group("fullmethod"));
return (ifname, shortIfName, methods)
return (None, shortIfName, methods)
-def readHFile(hFile, ifname):
+def readHFile(tracker, hFile, ifname):
methods = Set()
with open(hFile, "r") as r:
if searchStructStart(r, ifname) == False:
@@ -75,15 +77,16 @@ def readHFile(hFile, ifname):
if m != None:
# print "{2}: add {0}, from: {1}".format(m.group("method"), line, ifname)
methods.add(m.group("method"))
+ tracker.fullmethods.add(ifname + "_" + m.group("method"))
return methods
def checkIfFile(tracker, cFile, hFile):
- data = readCFile(cFile)
+ data = readCFile(tracker, cFile)
cMethods = data[2]
ifname = data[0]
shortIfName = data[1]
if len(cMethods) > 0:
- hMethods = readHFile(hFile, ifname)
+ hMethods = readHFile(tracker, hFile, ifname)
for method in hMethods:
tracker.arr[ifname + "_" + method] = list()
tracker.methods.add(ifname + "_" + method)
@@ -116,7 +119,7 @@ def checkChr(ch):
return False
def checkFile(tracker, cFile):
- print "Checking: " + cFile
+# print "Checking: " + cFile
with open(cFile, "r") as r:
for line in r:
parts = re.findall(r'[\w_]+', line)
@@ -130,8 +133,16 @@ def checkFile(tracker, cFile):
continue
if checkChr(line[idx - 1]):
continue
+ if line[0:3] == " * ":
+ continue;
if line[-1] == "\n":
line = line[:-1]
+ text = line.strip()
+ if text[0:2] == "/*" or text[0:2] == "//":
+ continue
+ idx2 = line.find("//")
+ if idx2 > 0 and idx2 < idx:
+ continue
tracker.arr[part].append(line)
def processDir(tracker, srcDir):
@@ -156,25 +167,80 @@ def reportMethods(tracker):
print "\n"
-tracker = Tracker()
-tracker.arr = dict()
-tracker.methods = Set()
-tracker.retCode = 0
-if len(sys.argv) > 1 and sys.argv[1] == "silent":
- processIfDir(tracker, "../src/char");
- processIfDir(tracker, "../src/map");
- processIfDir(tracker, "../src/login");
- processIfDir(tracker, "../src/common");
-else:
- print "Checking initerfaces initialisation"
+def checkLostFile(tracker, cFile):
+# print "Checking: " + cFile
+ methodRe = re.compile("^([\w0-9* _]*)([ ]|[*])(?P<ifname>[a-z_]+)_(?P<method>[\w_]+)(|[ ])[(]")
+ with open(cFile, "r") as r:
+ for line in r:
+ if line.find("(") < 1 or len(line) < 3 or line[0] == "\t" or line[0] == " " or line.find("_defaults") > 0:
+ continue
+ m = methodRe.search(line)
+ if m != None:
+ name = "{0}_{1}".format(m.group("ifname"), m.group("method"))
+ if m.group("ifname") not in tracker.interfaces:
+ continue
+ if name not in tracker.fullmethods:
+# print "src : " + line
+ print name
+
+def processLostDir(tracker, srcDir):
+ files = os.listdir(srcDir)
+ for file1 in files:
+ if file1[0] == '.' or file1 == "..":
+ continue
+ cPath = os.path.abspath(srcDir + os.path.sep + file1)
+ if not os.path.isfile(cPath):
+ processLostDir(tracker, cPath)
+ elif file1[-2:] == ".c":
+ checkLostFile(tracker, cPath)
+
+def runIf():
processIfDir(tracker, "../src/char");
processIfDir(tracker, "../src/map");
processIfDir(tracker, "../src/login");
processIfDir(tracker, "../src/common");
- print "Checking interfaces usage"
+
+def runLost():
+ processLostDir(tracker, "../src/char");
+ processLostDir(tracker, "../src/map");
+ processLostDir(tracker, "../src/login");
+ processLostDir(tracker, "../src/common");
+
+def runLong():
processDir(tracker, "../src/char");
processDir(tracker, "../src/map");
processDir(tracker, "../src/login");
processDir(tracker, "../src/common");
reportMethods(tracker)
+
+tracker = Tracker()
+tracker.arr = dict()
+tracker.methods = Set()
+tracker.fullmethods = Set()
+tracker.interfaces = Set()
+tracker.retCode = 0
+
+if len(sys.argv) > 1:
+ cmd = sys.argv[1]
+else:
+ cmd = "default"
+
+if cmd == "silent":
+ runIf()
+elif cmd == "init":
+ print "Checking interfaces initialisation"
+ runIf()
+elif cmd == "lost":
+ print "Checking not added functions to interfaces"
+ runLost();
+elif cmd == "long":
+ print "Checking interfaces usage"
+ runLong();
+else:
+ print "Checking interfaces initialisation"
+ runIf()
+ print "Checking not added functions to interfaces"
+ runLost();
+ print "Checking interfaces usage"
+ runLong();
exit(tracker.retCode)