summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/map/battle/client.conf12
-rw-r--r--doc/mob_db_mode_list.md72
-rw-r--r--doc/mob_db_mode_list.txt113
-rw-r--r--doc/quest_variables.md262
-rw-r--r--doc/quest_variables.txt108
-rw-r--r--sql-files/main.sql2
-rw-r--r--src/char/char.c32
-rw-r--r--src/map/atcommand.c6
-rw-r--r--src/map/battle.c72
-rw-r--r--src/map/battle.h2
-rw-r--r--src/map/clif.c7
-rw-r--r--src/map/map.c24
-rw-r--r--src/map/map.h1
-rw-r--r--src/map/npc.c2
-rw-r--r--src/map/pc.c11
-rw-r--r--src/map/script.c28
-rw-r--r--src/map/skill.c105
-rw-r--r--src/map/status.c178
-rw-r--r--src/map/status.h20
-rw-r--r--src/map/unit.c2
-rw-r--r--src/plugins/HPMHooking/HPMHooking.Defs.inc18
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc12
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc3
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc98
24 files changed, 770 insertions, 420 deletions
diff --git a/conf/map/battle/client.conf b/conf/map/battle/client.conf
index 35c585bf6..b7d4ac781 100644
--- a/conf/map/battle/client.conf
+++ b/conf/map/battle/client.conf
@@ -177,3 +177,15 @@ client_emblem_max_blank_percent: 100
// kRO removed the packet and this re-enables the message.
// Official: false.
mvp_exp_reward_message: false
+
+// Displays the same HP value as official servers do when a character is dead.
+// (Note 1)
+// On official servers, HP are never displayed as 0, but when dead, they
+// display the value that will be shown after resurrection (50% HP for novice
+// classes, 1 HP for other classes). Athena servers, instead, show the real
+// value (0 when dead), to avoid confusion.
+// Note: this is only a visual setting, and the server will internally handle
+// it as 0 regardless of this. This means that scripts will know that the
+// character has 0 HP when dead.
+// Default: true (Official behavior)
+display_fake_hp_when_dead: true
diff --git a/doc/mob_db_mode_list.md b/doc/mob_db_mode_list.md
new file mode 100644
index 000000000..a8ad4fa0a
--- /dev/null
+++ b/doc/mob_db_mode_list.md
@@ -0,0 +1,72 @@
+# Hercules Monster Modes Reference
+
+<!--
+## Copyright
+> This file is part of Hercules.
+> http://herc.ws - http://github.com/HerculesWS/Hercules
+>
+> Copyright (C) 2012-2018 Hercules Dev Team
+> Copyright (C) Athena Dev Teams
+>
+> Hercules is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+>
+> This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+> See the GNU General Public License for more details.
+>
+> You should have received a copy of the GNU General Public License along with this program.
+> If not, see <http://www.gnu.org/licenses/>.
+-->
+
+## Description
+A reference description of Hercules's mob_db.conf `mode` field.
+
+## Monster Mode Legend:
+Constant Name | Bits | Value | Description
+:-------------------- | :-----: | :------: | :----------------
+MD_CANMOVE | 0x00001 | 1 | Enables the mob to move/chase characters.
+MD_LOOTER | 0x00002 | 2 | The mob will loot up nearby items on the ground when it's on idle state.
+MD_AGGRESSIVE | 0x00004 | 4 | Normal aggressive mob, will look for a close-by player to attack.
+MD_ASSIST | 0x00008 | 8 | When a nearby mob of the same class attacks, assist types will join them.
+MD_CASTSENSOR_IDLE | 0x00010 | 16 | Will go after characters who start casting on them if idle or walking (without a target).
+MD_BOSS | 0x00020 | 32 | Special flag which makes mobs immune to certain status changes and skills.
+MD_PLANT | 0x00040 | 64 | Always receives 1 damage from attacks.
+MD_CANATTACK | 0x00080 | 128 | Enables the mob to attack/retaliate when you are within attack range. <br/>Note that this only enables them to use normal attacks, skills are always allowed.
+MD_DETECTOR | 0x00100 | 256 | Enables mob to detect and attack characters who are in hiding/cloak.
+MD_CASTSENSOR_CHASE | 0x00200 | 512 | Will go after characters who start casting on them if idle or chasing other players (they switch chase targets)
+MD_CHANGECHASE | 0x00400 | 1024 | Allows chasing mobs to switch targets if another player happens to be within attack range (handy on ranged attackers, for example)
+MD_ANGRY | 0x00800 | 2048 | These mobs are "hyper-active". Apart from "chase"/"attack", they have the states "follow"/"angry". </br>Once hit, they stop using these states and use the normal ones. The new states are used to determine a different skill-set for their "before attacked" and "after attacked" states. </br>Also, when "following", they automatically switch to whoever character is closest.
+MD_CHANGETARGET_MELEE | 0x01000 | 4096 | Enables a mob to switch targets when attacked while attacking someone else.
+MD_CHANGETARGET_CHASE | 0x02000 | 8192 | Enables a mob to switch targets when attacked while chasing another character.
+MD_TARGETWEAK | 0x04000 | 16384 | Allows aggressive monsters to only be aggressive against characters that are five levels below it's own level. </br>For example, a monster of level 104 will not pick fights with a level 99.
+MD_NOKNOCKBACK | 0x08000 | 32768 | Monsters will be immune to knockback's effect.
+MD_RANDOMTARGET | 0x10000 | 65536 | Picks a new random target in range on each attack/skill. (not implemented)
+
+## Aegis Mob Types:
+What Aegis has are mob-types, where each type represents an AI behavior that is mimicked by a group of eA mode bits.
+This is the table to convert from one to another:
+
+No. | Bits | Mob Type | Aegis/eA Description
+--: | :----: | :------: | :----------------
+ 01 | 0x0081 | Any | passive
+ 02 | 0x0083 | Any | passive, looter
+ 03 | 0x1089 | Any | passive, assist and change-target melee
+ 04 | 0x3885 | Any | angry, change-target melee/chase
+ 05 | 0x2085 | Any | aggressive, change-target chase
+ 06 | 0x0000 | Plants | passive, immobile, can't attack
+ 07 | 0x108B | Any | passive, looter, assist, change-target melee
+ 08 | 0x6085 | Any | aggressive, change-target chase, target weak enemies
+ 09 | 0x3095 | Guardian | aggressive, change-target melee/chase, cast sensor idle
+ 10 | 0x0084 | Any | aggressive, immobile
+ 11 | 0x0084 | Guardian | aggressive, immobile
+ 12 | 0x2085 | Guardian | aggressive, change-target chase
+ 13 | 0x308D | Any | aggressive, change-target melee/chase, assist
+ 17 | 0x0091 | Any | passive, cast sensor idle
+ 19 | 0x3095 | Any | aggressive, change-target melee/chase, cast sensor idle
+ 20 | 0x3295 | Any | aggressive, change-target melee/chase, cast sensor idle/chase
+ 21 | 0x3695 | Any | aggressive, change-target melee/chase, cast sensor idle/chase, chase-change target
+ 25 | 0x0001 | Pet | passive, can't attack
+ 26 | 0xB695 | Any | aggressive, change-target melee/chase, cast sensor idle/chase, chase-change target, random target
+ 27 | 0x8084 | Any | aggressive, immobile, random target
+
+- Note that the detector bit due to being Insect/Demon, Plant and Boss mode bits need to be added independently of this list.
+
diff --git a/doc/mob_db_mode_list.txt b/doc/mob_db_mode_list.txt
deleted file mode 100644
index 32e7a0e8d..000000000
--- a/doc/mob_db_mode_list.txt
+++ /dev/null
@@ -1,113 +0,0 @@
-//===== Hercules Documentation ===============================
-//= Hercules Monster Modes Reference
-//===== By: ==================================================
-//= Hercules Dev Team
-//===== Current Version: =====================================
-//= 20120630
-//===== Description: =========================================
-//= A reference description of Hercules' mob_db 'mode' field.
-//============================================================
-
-Bit Legend:
--------------------------------------------------------------------------------
-
-MD_CANMOVE | 0x00001 | 1
-MD_LOOTER | 0x00002 | 2
-MD_AGGRESSIVE | 0x00004 | 4
-MD_ASSIST | 0x00008 | 8
-MD_CASTSENSOR_IDLE | 0x00010 | 16
-MD_BOSS | 0x00020 | 32
-MD_PLANT | 0x00040 | 64
-MD_CANATTACK | 0x00080 | 128
-MD_DETECTOR | 0x00100 | 256
-MD_CASTSENSOR_CHASE | 0x00200 | 512
-MD_CHANGECHASE | 0x00400 | 1024
-MD_ANGRY | 0x00800 | 2048
-MD_CHANGETARGET_MELEE | 0x01000 | 4096
-MD_CHANGETARGET_CHASE | 0x02000 | 8192
-MD_TARGETWEAK | 0x04000 | 16384
-MD_NOKNOCKBACK | 0x08000 | 32768
-MD_RANDOMTARGET | 0x10000 | 65536 (not implemented)
-
-Explanation for modes:
--------------------------------------------------------------------------------
-
-CanMove: Enables the mob to move/chase characters.
-
-CanAttack: Enables the mob to attack/retaliate when you are within attack
- range. Note that this only enables them to use normal attacks, skills are
- always allowed.
-
-Looter: The mob will loot up nearby items on the ground when it's on idle state.
-
-Aggressive: normal aggressive mob, will look for a close-by player to attack.
-
-Assist: When a nearby mob of the same class attacks, assist types will join them.
-
-Cast Sensor Idle: Will go after characters who start casting on them if idle
- or walking (without a target).
-
-Cast Sensor Chase: Will go after characters who start casting on them if idle
- or chasing other players (they switch chase targets)
-
-Boss: Special flag which makes mobs immune to certain status changes and skills.
-
-Plant: Always receives 1 damage from attacks.
-
-Detector: Enables mob to detect and attack characters who are in hiding/cloak.
-
-ChangeChase: Allows chasing mobs to switch targets if another player happens
- to be within attack range (handy on ranged attackers, for example)
-
-Angry: These mobs are "hyper-active". Apart from "chase"/"attack", they have
- the states "follow"/"angry". Once hit, they stop using these states and use
- the normal ones. The new states are used to determine a different skill-set
- for their "before attacked" and "after attacked" states. Also, when
- "following", they automatically switch to whoever character is closest.
-
-Change Target Melee: Enables a mob to switch targets when attacked while
- attacking someone else.
-
-Change Target Chase: Enables a mob to switch targets when attacked while
- chasing another character.
-
-Target Weak: Allows aggressive monsters to only be aggressive against
- characters that are five levels below it's own level.
- For example, a monster of level 104 will not pick fights with a level 99.
-
-NoKnockback: Monsters will be immune to Knockback's.
-
-Random Target: Picks a new random target in range on each attack / skill.
- (not implemented)
-
-Aegis Mob Types:
--------------------------------------------------------------------------------
-
-What Aegis has are mob-types, where each type represents an AI behavior that
-is mimicked by a group of eA mode bits. This is the table to convert from one
-to another:
-
-Aegis/eA (description)
-01: 0x0081 (passive)
-02: 0x0083 (passive, looter)
-03: 0x1089 (passive, assist and change-target melee)
-04: 0x3885 (angry, change-target melee/chase)
-05: 0x2085 (aggressive, change-target chase)
-06: 0x0000 (passive, immobile, can't attack) [plants]
-07: 0x108B (passive, looter, assist, change-target melee)
-08: 0x6085 (aggressive, change-target chase, target weak enemies)
-09: 0x3095 (aggressive, change-target melee/chase, cast sensor idle) [Guardian]
-10: 0x0084 (aggressive, immobile)
-11: 0x0084 (aggressive, immobile) [Guardian]
-12: 0x2085 (aggressive, change-target chase) [Guardian]
-13: 0x308D (aggressive, change-target melee/chase, assist)
-17: 0x0091 (passive, cast sensor idle)
-19: 0x3095 (aggressive, change-target melee/chase, cast sensor idle)
-20: 0x3295 (aggressive, change-target melee/chase, cast sensor idle/chase)
-21: 0x3695 (aggressive, change-target melee/chase, cast sensor idle/chase, chase-change target)
-25: 0x0001 (passive, can't attack) [Pet]
-26: 0xB695 (aggressive, change-target melee/chase, cast sensor idle/chase, chase-change target, random target)
-27: 0x8084 (aggressive, immobile, random target)
-
-- Note that the detector bit due to being Insect/Demon, plant and Boss mode
- bits need to be added independently of this list.
diff --git a/doc/quest_variables.md b/doc/quest_variables.md
new file mode 100644
index 000000000..2f8922c41
--- /dev/null
+++ b/doc/quest_variables.md
@@ -0,0 +1,262 @@
+# Quest Variables
+
+<!--
+## Copyright
+> This file is part of Hercules.
+> http://herc.ws - http://github.com/HerculesWS/Hercules
+>
+> Copyright (C) 2012-2018 Hercules Dev Team
+> Copyright (C) Athena Dev Teams
+>
+> Hercules is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+>
+> This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+> See the GNU General Public License for more details.
+>
+> You should have received a copy of the GNU General Public License along with this program.
+> If not, see <http://www.gnu.org/licenses/>.
+-->
+
+## Description
+This file should help to understand and manage bit-wise quest variables.
+You can store up to 31 boolean value into a single variable.
+
+## Sample Variable: `MISC_QUEST`
+
+Quest # No | Sample Quest
+:-------------| :------------
+Description | How to assign a bit-wise value and check it.
+Assign Value | ```MISC_QUEST = MISC_QUEST \| X;```
+Check Value | ```if (MISC_QUEST & X) { ... }```
+
+- Where `X` refer to the bit-wise value that could be used to represent the state/progress of a quest.
+
+--------------------------------------------------------------
+
+## Example
+
+Quest # 1 | Juice Maker Quest
+:-------------| :------------
+Description | How to make juices. This bit keeps final state of the quest.
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 1;```
+Check Value | ```if (MISC_QUEST & 1) { ... }```
+
+Quest # 2 | Tempestra Quest
+:-------------| :------------
+Description | Determines if player has given a potion to Tempestra.
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 2;```
+Check Value | ```if (MISC_QUEST & 2) { ... }```
+
+Quest # 3 | Morgenstein Quest
+:-------------| :------------
+Description | How to make Mixture & Counteragent. This bit keeps final state of the quest.
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 4;```
+Check Value | ```if (MISC_QUEST & 4) { ... }```
+
+Quest # 4 | Prontera Culvert Quest
+:-------------| :------------
+Description | Determines if player can enter Prontera Culverts.
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 8;```
+Check Value | ```if (MISC_QUEST & 8) { ... }```
+
+Quest # 5 | Edgar's Offer
+:-------------| :------------
+Description | Cheap ticket from Izlude to Alberta. This bit keeps final state of the quest.
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 16;```
+Check Value | ```if (MISC_QUEST & 16) { ... }```
+
+Quest # 6 | Piano Quest
+:-------------| :------------
+Description | The only way from Niflheim to Umbala.
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 32;```
+Check Value | ```if (MISC_QUEST & 32) { ... }```
+
+Quest # 7 | Bio Ethics Quest
+:-------------| :------------
+Description | Quest for homunculus skill for alchemists. This bit keeps final state of the quest.
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 64;```
+Check Value | ```if (MISC_QUEST & 64) { ... }```
+
+Quest # 8 | DTS Warper
+:-------------| :------------
+Description | Determines if player has already voted.
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 128;```
+Check Value | ```if (MISC_QUEST & 128) { ... }```
+
+Quest # 9 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 256;```
+Check Value | ```if (MISC_QUEST & 256) { ... }```
+
+Quest # 10 | Cube Room
+:-------------| :------------
+Description | Lighthalzen Cube Room quest (to enter Bio-Lab)
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 512;```
+Check Value | ```if (MISC_QUEST & 512) { ... }```
+
+Quest # 11 | Reset Skills Event
+:-------------| :------------
+Description | Yuno, Hypnotist Teacher
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 1024;```
+Check Value | ```if (MISC_QUEST & 1024) { ... }```
+
+Quest # 12 | Slotted Arm Guard Quest
+:-------------| :------------
+Description | Ninja Job Room, Boshuu
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 2048;```
+Check Value | ```if (MISC_QUEST & 2048) { ... }```
+
+Quest # 13 | Improved Arm Guard Quest
+:-------------| :------------
+Description | Ninja Job Room, Basshu
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 4096;```
+Check Value | ```if (MISC_QUEST & 4096) { ... }```
+
+Quest # 14 | Rachel Sanctuary Quest
+:-------------| :------------
+Description | Determines if player can access Rachel Santuary.
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 8192;```
+Check Value | ```if (MISC_QUEST & 8192) { ... }```
+
+Quest # 15 | Message Delivery Quest
+:-------------| :------------
+Description | Send a message to Elly, in Niflheim from Erious.
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 16384;```
+Check Value | ```if (MISC_QUEST & 16384) { ... }```
+
+Quest # 16 | Umbala Domestic Dispute?
+:-------------| :------------
+Description | Reward: 1 Yggdrasil Leaf.
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 32768;```
+Check Value | ```if (MISC_QUEST & 32768) { ... }```
+
+Quest # 17 | Access to the Turtle Island
+:-------------| :------------
+Description | Reward: ~1 Old Card Album , Old Violet Box, GB.
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 65536;```
+Check Value | ```if (MISC_QUEST & 65536) { ... }```
+
+Quest # 18 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 131072;```
+Check Value | ```if (MISC_QUEST & 131072) { ... }```
+
+Quest # 19 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 262144;```
+Check Value | ```if (MISC_QUEST & 262144) { ... }```
+
+Quest # 20 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 524288;```
+Check Value | ```if (MISC_QUEST & 524288) { ... }```
+
+Quest # 21 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 1048576;```
+Check Value | ```if (MISC_QUEST & 1048576) { ... }```
+
+Quest # 22 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 2097152;```
+Check Value | ```if (MISC_QUEST & 2097152) { ... }```
+
+Quest # 23 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 4194304;```
+Check Value | ```if (MISC_QUEST & 4194304) { ... }```
+
+Quest # 24 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 8388608;```
+Check Value | ```if (MISC_QUEST & 8388608) { ... }```
+
+Quest # 25 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 16777216;```
+Check Value | ```if (MISC_QUEST & 16777216) { ... }```
+
+Quest # 26 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 33554432;```
+Check Value | ```if (MISC_QUEST & 33554432) { ... }```
+
+Quest # 27 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 67108864;```
+Check Value | ```if (MISC_QUEST & 67108864) { ... }```
+
+Quest # 28 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 134217728;```
+Check Value | ```if (MISC_QUEST & 134217728) { ... }```
+
+Quest # 29 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 268435456;```
+Check Value | ```if (MISC_QUEST & 268435456) { ... }```
+
+Quest # 30 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 536870912;```
+Check Value | ```if (MISC_QUEST & 536870912) { ... }```
+
+Quest # 31 | -
+:-------------| :------------
+Description | -
+Assign Value | ```MISC_QUEST = MISC_QUEST \| 1073741824;```
+Check Value | ```if (MISC_QUEST & 1073741824) { ... }```
+
+### Quest#32 and onwards
+You had to use a new variable to store it.
+The existing variable `MISC_QUEST`'s value may overflow as it already reaching the max value.
+Basically the cycle repeat every 32th quests, unless the limit has been lifted in the future.
+
+ No | Formulae | Bits Value | Accumulate
+:--:|:-----------:|-----------:|-------------:
+ 1 | 2 ^ 0 | 1 | 1
+ 2 | 2 ^ 1 | 2 | 3
+ 3 | 2 ^ 2 | 4 | 7
+ 4 | 2 ^ 3 | 8 | 15
+ 5 | 2 ^ 4 | 16 | 31
+ 6 | 2 ^ 5 | 32 | 63
+ 7 | 2 ^ 6 | 64 | 127
+ 8 | 2 ^ 7 | 128 | 255
+ 9 | 2 ^ 8 | 256 | 511
+ 10 | 2 ^ 9 | 512 | 1023
+ 11 | 2 ^ 10 | 1024 | 2047
+ 12 | 2 ^ 11 | 2048 | 4095
+ 13 | 2 ^ 12 | 4096 | 8191
+ 14 | 2 ^ 13 | 8192 | 16383
+ 15 | 2 ^ 14 | 16384 | 32767
+ 16 | 2 ^ 15 | 32768 | 65535
+ 17 | 2 ^ 16 | 65536 | 131071
+ 18 | 2 ^ 17 | 131072 | 262143
+ 19 | 2 ^ 18 | 262144 | 524287
+ 20 | 2 ^ 19 | 524288 | 1048575
+ 21 | 2 ^ 20 | 1048576 | 2097151
+ 22 | 2 ^ 21 | 2097152 | 4194303
+ 23 | 2 ^ 22 | 4194304 | 8388607
+ 24 | 2 ^ 23 | 8388608 | 16777215
+ 25 | 2 ^ 24 | 16777216 | 33554431
+ 26 | 2 ^ 25 | 33554432 | 67108863
+ 27 | 2 ^ 26 | 67108864 | 134217727
+ 28 | 2 ^ 27 | 134217728 | 268435455
+ 29 | 2 ^ 28 | 268435456 | 536870911
+ 30 | 2 ^ 29 | 536870912 | 1073741823
+ 31 | 2 ^ 30 | 1073741824 | 2147483647
+
diff --git a/doc/quest_variables.txt b/doc/quest_variables.txt
deleted file mode 100644
index 0be144183..000000000
--- a/doc/quest_variables.txt
+++ /dev/null
@@ -1,108 +0,0 @@
-//===== Hercules Documentation ===============================
-//= Permanent Quest Variables
-//===== By: ==================================================
-//= Lupus
-//===== Current Version: =====================================
-//= 20120826
-//===== Description: =========================================
-//= This file should help to understand and manage bit-wise
-//= quest variables. You can store up to 31 boolean value into
-//= a single variable.
-//============================================================
-
-Variable: MISC_QUEST
---------------------------------------------------------------
-
-Quest: Juice Maker Quest
-Info: How to make juices. This bit keeps final state of the quest.
-How to set: set MISC_QUEST, MISC_QUEST | 1;
-How to check: if (MISC_QUEST & 1) {}
-
-Quest: Tempestra Quest
-Info: Determines if player has given a potion to Tempestra.
-How to set: set MISC_QUEST, MISC_QUEST | 2;
-How to check: if (MISC_QUEST & 2) {}
-
-Quest: Morgenstein Quest
-Info: How to make Mixture & Counteragent. This bit keeps final state of the quest.
-How to set: set MISC_QUEST, MISC_QUEST | 4;
-How to check: if (MISC_QUEST & 4) {}
-
-Quest: Prontera Culvert Quest
-Info: Determines if player can enter Prontera Culverts.
-How to set: set MISC_QUEST, MISC_QUEST | 8;
-How to check: if (MISC_QUEST & 8) {}
-
-Quest: Edgar's Offer
-Info: Cheap ticket from Izlude to Alberta. This bit keeps final state of the quest.
-How to set: set MISC_QUEST, MISC_QUEST | 16;
-How to check: if (MISC_QUEST & 16) {}
-
-Quest: Piano Quest
-Info: The only way from Niflheim to Umbala.
-How to set: set MISC_QUEST, MISC_QUEST | 32;
-How to check: if (MISC_QUEST & 32) {}
-
-Quest: Bio Ethics Quest
-Info: Quest for homunculus skill for alchemists. This bit keeps final state of the quest.
-How to set: set MISC_QUEST, MISC_QUEST|64;
-How to check: if (MISC_QUEST & 64) {}
-
-Quest: DTS Warper
-Info: Determines if player has already voted.
-How to set: set MISC_QUEST, MISC_QUEST|128;
-How to check: if (MISC_QUEST & 128) {}
-
-Quest: -
-Info: -
-How to set: set MISC_QUEST, MISC_QUEST | 256;
-How to check: if (MISC_QUEST & 256) {}
-
-Quest: Cube Room
-Info: Lighthalzen Cube Room quest (to enter Bio-Lab)
-How to set: set MISC_QUEST, MISC_QUEST | 512;
-How to check: if (MISC_QUEST & 512) {}
-
-Quest: Reset Skills Event
-Info: Yuno, Hypnotist Teacher
-How to set: set MISC_QUEST, MISC_QUEST | 1024;
-How to check: if (MISC_QUEST & 1024) {}
-
-Quest: Slotted Arm Guard Quest
-Info: Ninja Job Room, Boshuu
-How to set: set MISC_QUEST, MISC_QUEST | 2048;
-How to check: if (MISC_QUEST & 2048) {}
-
-Quest: Improved Arm Guard Quest
-Info: Ninja Job Room, Basshu
-How to set: set MISC_QUEST, MISC_QUEST | 4096;
-How to check: if (MISC_QUEST & 4096) {}
-
-Quest: Rachel Sanctuary Quest
-Info: Determines if player can access Rachel Santuary.
-How to set: set MISC_QUEST, MISC_QUEST | 8192;
-How to check: if (MISC_QUEST & 8192) {}
-
-Quest: Message Delivery Quest
-Info: Send a message to Elly, in Niflheim from Erious.
-How to set: set MISC_QUEST, MISC_QUEST | 16384;
-How to check: if (MISC_QUEST & 16384) {}
-
-Quest: Umbala Domestic Dispute?
-Info: Reward: 1 Yggdrasil Leaf.
-How to set: set MISC_QUEST, MISC_QUEST | 32768;
-How to check: if (MISC_QUEST & 32768) {}
-
-Quest: Access to the Turtle Island
-Info: Reward: ~1 OCA, OVB, GB.
-How to set: set MISC_QUEST, MISC_QUEST | 65536;
-How to check: if (MISC_QUEST & 65536) {}
-
-
-Variable: MISC_QUEST2
---------------------------------------------------------------
-
-Quest: -
-Info: -
-How to set: set MISC_QUEST2, MISC_QUEST2 | ?;
-How to check: if (MISC_QUEST2 & ?) {}
diff --git a/sql-files/main.sql b/sql-files/main.sql
index d918d4a35..37bfaf0ec 100644
--- a/sql-files/main.sql
+++ b/sql-files/main.sql
@@ -293,7 +293,7 @@ CREATE TABLE IF NOT EXISTS `charlog` (
`str` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`agi` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`vit` INT(11) UNSIGNED NOT NULL DEFAULT '0',
- `INT` INT(11) UNSIGNED NOT NULL DEFAULT '0',
+ `int` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`dex` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`luk` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`hair` TINYINT(4) NOT NULL DEFAULT '0',
diff --git a/src/char/char.c b/src/char/char.c
index 5575ce6fe..a09eccd8a 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -1548,9 +1548,20 @@ static int char_rename_char_sql(struct char_session_data *sd, int char_id)
// log change
if (chr->enable_logs) {
if (SQL_ERROR == SQL->Query(inter->sql_handle,
- "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)"
- "VALUES (NOW(), '%s', '%d', '%d', '%d', '%s', '0', '0', '0', '0', '0', '0', '0', '0')",
- charlog_db, "change char name", sd->account_id, char_dat.char_id, char_dat.slot, esc_name))
+ "INSERT INTO `%s` ("
+ " `time`, `char_msg`, `account_id`, `char_id`, `char_num`, `class`, `name`,"
+ " `str`, `agi`, `vit`, `int`, `dex`, `luk`,"
+ " `hair`, `hair_color`"
+ ") VALUES ("
+ " NOW(), 'change char name', '%d', '%d', '%d', '%d', '%s',"
+ " '%d', '%d', '%d', '%d', '%d', '%d',"
+ " '%d', '%d'"
+ ")",
+ charlog_db,
+ sd->account_id, char_dat.char_id, char_dat.slot, char_dat.class, esc_name,
+ char_dat.str, char_dat.agi, char_dat.vit, char_dat.int_, char_dat.dex, char_dat.luk,
+ char_dat.hair, char_dat.hair_color
+ ))
Sql_ShowDebug(inter->sql_handle);
}
@@ -4566,8 +4577,19 @@ static void char_parse_char_select(int fd, struct char_session_data *sd, uint32
// FIXME: Why are we re-escaping the name if it was already escaped in rename/make_new_char? [Panikon]
SQL->EscapeStringLen(inter->sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH));
if (SQL_ERROR == SQL->Query(inter->sql_handle,
- "INSERT INTO `%s`(`time`, `account_id`, `char_id`, `char_num`, `name`) VALUES (NOW(), '%d', '%d', '%d', '%s')",
- charlog_db, sd->account_id, cd->char_id, slot, esc_name))
+ "INSERT INTO `%s`("
+ " `time`, `char_msg`, `account_id`, `char_id`, `char_num`, `class`, `name`,"
+ " `str`, `agi`, `vit`, `int`, `dex`, `luk`,"
+ " `hair`, `hair_color`"
+ ") VALUES ("
+ " NOW(), 'char select', '%d', '%d', '%d', '%d', '%s',"
+ " '%d', '%d', '%d', '%d', '%d', '%d',"
+ " '%d', '%d')",
+ charlog_db,
+ sd->account_id, cd->char_id, slot, char_dat.class, esc_name,
+ char_dat.str, char_dat.agi, char_dat.vit, char_dat.int_, char_dat.dex, char_dat.luk,
+ char_dat.hair, char_dat.hair_color
+ ))
Sql_ShowDebug(inter->sql_handle);
}
ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name);
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index e6f022a10..179b96c32 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -1135,7 +1135,7 @@ ACMD(heal)
}
if ( hp > 0 && sp >= 0 ) {
- if(!status->heal(&sd->bl, hp, sp, 0))
+ if (status->heal(&sd->bl, hp, sp, STATUS_HEAL_DEFAULT) == 0)
clif->message(fd, msg_fd(fd,157)); // HP and SP are already with the good value.
else
clif->message(fd, msg_fd(fd,17)); // HP, SP recovered.
@@ -1152,7 +1152,7 @@ ACMD(heal)
//Opposing signs.
if ( hp ) {
if (hp > 0)
- status->heal(&sd->bl, hp, 0, 0);
+ status->heal(&sd->bl, hp, 0, STATUS_HEAL_DEFAULT);
else {
status->damage(NULL, &sd->bl, -hp, 0, 0, 0);
clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, BDT_ENDURE, 0);
@@ -1161,7 +1161,7 @@ ACMD(heal)
if ( sp ) {
if (sp > 0)
- status->heal(&sd->bl, 0, sp, 0);
+ status->heal(&sd->bl, 0, sp, STATUS_HEAL_DEFAULT);
else
status->damage(NULL, &sd->bl, 0, -sp, 0, 0);
}
diff --git a/src/map/battle.c b/src/map/battle.c
index 44241bf23..f51240810 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -1365,24 +1365,28 @@ static int64 battle_calc_defense(int attack_type, struct block_list *src, struct
#endif
}
- if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) {
- unsigned char target_count; //256 max targets should be a sane max
- target_count = unit->counttargeted(target);
- if(target_count >= battle_config.vit_penalty_count) {
- if(battle_config.vit_penalty_type == 1) {
- if( !tsc || !tsc->data[SC_STEELBODY] )
- def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
- def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
- } else { //Assume type 2
- if( !tsc || !tsc->data[SC_STEELBODY] )
- def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
- def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
+ if (battle_config.vit_penalty_type != 0 && (battle_config.vit_penalty_target & target->type) != 0) {
+ int target_count = unit->counttargeted(target);
+ if (target_count >= battle_config.vit_penalty_count) {
+ int penalty = (target_count - (battle_config.vit_penalty_count - 1)) * battle_config.vit_penalty_num;
+ if (battle_config.vit_penalty_type == 1) {
+ if (tsc == NULL || tsc->data[SC_STEELBODY] == NULL)
+ def1 = def1 * (100 - penalty) / 100;
+ def2 = def2 * (100 - penalty) / 100;
+ } else { // Assume type 2
+ if (tsc == NULL || tsc->data[SC_STEELBODY] == NULL)
+ def1 -= penalty;
+ def2 -= penalty;
}
}
#ifndef RENEWAL
- if(skill_id == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex]
+ if (skill_id == AM_ACIDTERROR)
+ def1 = 0; // Acid Terror ignores only armor defense. [Skotlex]
#endif
- if(def2 < 1) def2 = 1;
+ if (def1 < 0)
+ def1 = 0;
+ if (def2 < 1)
+ def2 = 1;
}
//Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def
if (tsd) {
@@ -2872,7 +2876,7 @@ static int64 battle_calc_damage(struct block_list *src, struct block_list *bl, s
if( sc->data[SC__MAELSTROM] && (flag&BF_MAGIC) && skill_id && (skill->get_inf(skill_id)&INF_GROUND_SKILL) ) {
// {(Maelstrom Skill LevelxAbsorbed Skill Level)+(Caster's Job/5)}/2
int sp = (sc->data[SC__MAELSTROM]->val1 * skill_lv + (t_sd ? t_sd->status.job_level / 5 : 0)) / 2;
- status->heal(bl, 0, sp, 3);
+ status->heal(bl, 0, sp, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
d->dmg_lv = ATK_BLOCK;
return 0;
}
@@ -3243,7 +3247,7 @@ static int64 battle_calc_damage(struct block_list *src, struct block_list *bl, s
//(since battle_drain is strictly for players currently)
if ((sce=sc->data[SC_HAMI_BLOODLUST]) && flag&BF_WEAPON && damage > 0 &&
rnd()%100 < sce->val3)
- status->heal(src, damage*sce->val4/100, 0, 3);
+ status->heal(src, damage*sce->val4/100, 0, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
if( (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON
&& rnd()%100 < sce->val2 && sc->fv_counter <= sce->val3 )
@@ -4224,16 +4228,16 @@ static struct Damage battle_calc_misc_attack(struct block_list *src, struct bloc
hitrate = 80; //Default hitrate
#endif
- if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) {
- unsigned char attacker_count; //256 max targets should be a sane max
- attacker_count = unit->counttargeted(target);
- if(attacker_count >= battle_config.agi_penalty_count)
- {
+ if (battle_config.agi_penalty_type != 0 && (battle_config.agi_penalty_target & target->type) != 0) {
+ int attacker_count = unit->counttargeted(target);
+ if (attacker_count >= battle_config.agi_penalty_count) {
+ int penalty = (attacker_count - (battle_config.agi_penalty_count - 1)) * battle_config.agi_penalty_num;
if (battle_config.agi_penalty_type == 1)
- flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
+ flee = flee * (100 - penalty) / 100;
else // assume type 2: absolute reduction
- flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num;
- if(flee < 1) flee = 1;
+ flee -= penalty;
+ if (flee < 1)
+ flee = 1;
}
}
@@ -4751,15 +4755,16 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
short hitrate = 80; //Default hitrate
#endif
- if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) {
- unsigned char attacker_count; //256 max targets should be a sane max
- attacker_count = unit->counttargeted(target);
- if(attacker_count >= battle_config.agi_penalty_count) {
+ if (battle_config.agi_penalty_type != 0 && (battle_config.agi_penalty_target & target->type) != 0) {
+ int attacker_count = unit->counttargeted(target);
+ if (attacker_count >= battle_config.agi_penalty_count) {
+ int penalty = (attacker_count - (battle_config.agi_penalty_count - 1)) * battle_config.agi_penalty_num;
if (battle_config.agi_penalty_type == 1)
- flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
- else //asume type 2: absolute reduction
- flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num;
- if(flee < 1) flee = 1;
+ flee = flee * (100 - penalty) / 100;
+ else // asume type 2: absolute reduction
+ flee -= penalty;
+ if (flee < 1)
+ flee = 1;
}
}
@@ -6094,7 +6099,7 @@ static void battle_drain(struct map_session_data *sd, struct block_list *tbl, in
if (!thp && !tsp) return;
- status->heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain ? 3 : 1);
+ status->heal(&sd->bl, thp, tsp, STATUS_HEAL_FORCED | (battle_config.show_hp_sp_drain ? STATUS_HEAL_SHOWEFFECT : STATUS_HEAL_DEFAULT));
if (rhp || rsp)
status_zap(tbl, rhp, rsp);
@@ -7407,6 +7412,7 @@ static const struct battle_data {
{ "features/feature_attendance_endtime",&battle_config.feature_attendance_endtime, 1, 0, 99999999, },
{ "min_item_buy_price", &battle_config.min_item_buy_price, 1, 0, INT_MAX, },
{ "min_item_sell_price", &battle_config.min_item_sell_price, 0, 0, INT_MAX, },
+ { "display_fake_hp_when_dead", &battle_config.display_fake_hp_when_dead, 1, 0, 1, },
};
static bool battle_set_value_sub(int index, int value)
diff --git a/src/map/battle.h b/src/map/battle.h
index 02536e4a1..750753c08 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -574,6 +574,8 @@ struct Battle_Config {
int min_item_buy_price;
int min_item_sell_price;
+
+ int display_fake_hp_when_dead;
};
/* criteria for battle_config.idletime_critera */
diff --git a/src/map/clif.c b/src/map/clif.c
index 19e90237f..ebf667af0 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -3245,7 +3245,12 @@ static void clif_updatestatus(struct map_session_data *sd, int type)
WFIFOL(fd,4)=sd->battle_status.max_sp;
break;
case SP_HP:
- WFIFOL(fd,4)=sd->battle_status.hp;
+ if (sd->battle_status.hp == 0 && battle_config.display_fake_hp_when_dead) {
+ // On official servers, the HP displayed when dead is the HP that the character will have at respawn.
+ WFIFOL(fd, 4) = status->get_restart_hp(sd, &sd->battle_status);
+ } else {
+ WFIFOL(fd, 4) = sd->battle_status.hp;
+ }
break;
case SP_SP:
WFIFOL(fd,4)=sd->battle_status.sp;
diff --git a/src/map/map.c b/src/map/map.c
index a352d34b0..d4d6e3323 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -3707,7 +3707,7 @@ static void map_zonedb_reload(void)
{
// first, reset maps to their initial zones:
for (int i = 0; i < map->count; i++) {
- map->zone_remove(i);
+ map->zone_remove_all(i);
if (battle_config.pk_mode) {
map->list[i].flag.pvp = 1;
@@ -4688,6 +4688,27 @@ static void map_zone_remove(int m)
map->list[m].zone_mf = NULL;
map->list[m].zone_mf_count = 0;
}
+// this one removes every flag, even if they were previously turned on before
+// the current zone was applied
+static void map_zone_remove_all(int m)
+{
+ Assert_retv(m >= 0 && m < map->count);
+
+ for (unsigned short k = 0; k < map->list[m].zone_mf_count; k++) {
+ char flag[MAP_ZONE_MAPFLAG_LENGTH];
+
+ memcpy(flag, map->list[m].zone_mf[k], MAP_ZONE_MAPFLAG_LENGTH);
+ strtok(flag, "\t");
+
+ npc->parse_mapflag(map->list[m].name, "", flag, "off", "", "", "", NULL);
+ aFree(map->list[m].zone_mf[k]);
+ map->list[m].zone_mf[k] = NULL;
+ }
+
+ aFree(map->list[m].zone_mf);
+ map->list[m].zone_mf = NULL;
+ map->list[m].zone_mf_count = 0;
+}
static inline void map_zone_mf_cache_add(int m, char *rflag)
{
Assert_retv(m >= 0 && m < map->count);
@@ -6840,6 +6861,7 @@ void map_defaults(void)
/* funcs */
map->zone_init = map_zone_init;
map->zone_remove = map_zone_remove;
+ map->zone_remove_all = map_zone_remove_all;
map->zone_apply = map_zone_apply;
map->zone_change = map_zone_change;
map->zone_change2 = map_zone_change2;
diff --git a/src/map/map.h b/src/map/map.h
index 0e38bdb13..4267c2c88 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -1220,6 +1220,7 @@ END_ZEROED_BLOCK;
/* funcs */
void (*zone_init) (void);
void (*zone_remove) (int m);
+ void (*zone_remove_all) (int m);
void (*zone_apply) (int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath);
void (*zone_change) (int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath);
void (*zone_change2) (int m, struct map_zone_data *zone);
diff --git a/src/map/npc.c b/src/map/npc.c
index a8bf7d371..7f57a9c50 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -4971,6 +4971,7 @@ static int npc_reload(void)
npc->npc_mob = npc->npc_cache_mob = npc->npc_delay_mob = 0;
// reset mapflags
+ map->zone_reload();
map->flags_init();
// Reprocess npc files and reload constants
@@ -4980,7 +4981,6 @@ static int npc_reload(void)
instance->reload();
- map->zone_reload();
map->zone_init();
npc->motd = npc->name2id("HerculesMOTD"); /* [Ind/Hercules] */
diff --git a/src/map/pc.c b/src/map/pc.c
index b8a6912ee..78b773550 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -399,7 +399,7 @@ static int pc_banding(struct map_session_data *sd, uint16 skill_lv)
for( j = 0; j < i; j++ ) {
bsd = map->id2sd(b_sd[j]);
if( bsd != NULL ) {
- status->set_hp(&bsd->bl,hp,0); // Set hp
+ status->set_hp(&bsd->bl, hp, STATUS_HEAL_DEFAULT); // Set hp
if( (sc = status->get_sc(&bsd->bl)) != NULL && sc->data[SC_BANDING] ) {
sc->data[SC_BANDING]->val2 = c; // Set the counter. It doesn't count your self.
status_calc_bl(&bsd->bl, status->sc2scb_flag(SC_BANDING)); // Set atk and def.
@@ -523,10 +523,9 @@ static int pc_setrestartvalue(struct map_session_data *sd, int type)
if (type&1) {
//Normal resurrection
- st->hp = 1; //Otherwise status->heal may fail if dead.
- status->heal(&sd->bl, bst->hp, 0, 1);
+ status->heal(&sd->bl, bst->hp, 0, STATUS_HEAL_FORCED | STATUS_HEAL_ALLOWREVIVE);
if( st->sp < bst->sp )
- status->set_sp(&sd->bl, bst->sp, 1);
+ status->set_sp(&sd->bl, bst->sp, STATUS_HEAL_FORCED);
} else { //Just for saving on the char-server (with values as if respawned)
sd->status.hp = bst->hp;
sd->status.sp = (st->sp < bst->sp) ? bst->sp : st->sp;
@@ -8827,7 +8826,7 @@ static int pc_itemheal(struct map_session_data *sd, int itemid, int hp, int sp)
}
}
- return status->heal(&sd->bl, hp, sp, 1);
+ return status->heal(&sd->bl, hp, sp, STATUS_HEAL_FORCED);
}
/*==========================================
@@ -10878,7 +10877,7 @@ static void pc_regen(struct map_session_data *sd, unsigned int diff_tick)
}
if (hp > 0 || sp > 0)
- status->heal(&sd->bl, hp, sp, 0);
+ status->heal(&sd->bl, hp, sp, STATUS_HEAL_DEFAULT);
return;
}
diff --git a/src/map/script.c b/src/map/script.c
index 8c09bb8d8..41f21cd72 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -6855,7 +6855,7 @@ static BUILDIN(heal)
hp=script_getnum(st,2);
sp=script_getnum(st,3);
- status->heal(&sd->bl, hp, sp, 1);
+ status->heal(&sd->bl, hp, sp, STATUS_HEAL_FORCED);
return true;
}
/*==========================================
@@ -18781,7 +18781,7 @@ static BUILDIN(setunitdata)
md->level = val;
break;
case UDT_HP:
- status->set_hp(bl, (unsigned int) val, 0);
+ status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
clif->charnameack(0, &md->bl);
break;
case UDT_MAXHP:
@@ -18789,7 +18789,7 @@ static BUILDIN(setunitdata)
clif->charnameack(0, &md->bl);
break;
case UDT_SP:
- status->set_sp(bl, (unsigned int) val, 0);
+ status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXSP:
md->status.max_sp = (unsigned int) val;
@@ -18950,13 +18950,13 @@ static BUILDIN(setunitdata)
hd->homunculus.level = (short) val;
break;
case UDT_HP:
- status->set_hp(bl, (unsigned int) val, 0);
+ status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXHP:
hd->homunculus.max_hp = val;
break;
case UDT_SP:
- status->set_sp(bl, (unsigned int) val, 0);
+ status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXSP:
hd->homunculus.max_sp = val;
@@ -19089,13 +19089,13 @@ static BUILDIN(setunitdata)
pd->pet.level = (short) val;
break;
case UDT_HP:
- status->set_hp(bl, (unsigned int) val, 0);
+ status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXHP:
pd->status.max_hp = (unsigned int) val;
break;
case UDT_SP:
- status->set_sp(bl, (unsigned int) val, 0);
+ status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXSP:
pd->status.max_sp = (unsigned int) val;
@@ -19223,13 +19223,13 @@ static BUILDIN(setunitdata)
mc->base_status.size = (unsigned char) val;
break;
case UDT_HP:
- status->set_hp(bl, (unsigned int) val, 0);
+ status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXHP:
mc->base_status.max_hp = (unsigned int) val;
break;
case UDT_SP:
- status->set_sp(bl, (unsigned int) val, 0);
+ status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXSP:
mc->base_status.max_sp = (unsigned int) val;
@@ -19357,13 +19357,13 @@ static BUILDIN(setunitdata)
ed->base_status.size = (unsigned char) val;
break;
case UDT_HP:
- status->set_hp(bl, (unsigned int) val, 0);
+ status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXHP:
ed->base_status.max_hp = (unsigned int) val;
break;
case UDT_SP:
- status->set_sp(bl, (unsigned int) val, 0);
+ status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXSP:
ed->base_status.max_sp = (unsigned int) val;
@@ -19489,13 +19489,13 @@ static BUILDIN(setunitdata)
nd->level = (unsigned short) val;
break;
case UDT_HP:
- status->set_hp(bl, (unsigned int) val, 0);
+ status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXHP:
nd->status.max_hp = (unsigned int) val;
break;
case UDT_SP:
- status->set_sp(bl, (unsigned int) val, 0);
+ status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXSP:
nd->status.max_sp = (unsigned int) val;
@@ -20806,7 +20806,7 @@ static BUILDIN(mercenary_heal)
hp = script_getnum(st,2);
sp = script_getnum(st,3);
- status->heal(&sd->md->bl, hp, sp, 0);
+ status->heal(&sd->md->bl, hp, sp, STATUS_HEAL_DEFAULT);
return true;
}
diff --git a/src/map/skill.c b/src/map/skill.c
index 9857badbe..8410a77d0 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -2361,11 +2361,11 @@ static int skill_counter_additional_effect(struct block_list *src, struct block_
) {
// Soul Drain should only work on targeted spells [Skotlex]
if( pc_issit(sd) ) pc->setstand(sd); // Character stuck in attacking animation while 'sitting' fix. [Skotlex]
- if( skill->get_nk(skill_id)&NK_SPLASH && skill->area_temp[1] != bl->id )
+ if (skill->get_nk(skill_id)&NK_SPLASH && skill->area_temp[1] != bl->id) {
;
- else {
+ } else {
clif->skill_nodamage(src,bl,HW_SOULDRAIN,rate,1);
- status->heal(src, 0, status->get_lv(bl)*(95+15*rate)/100, 2);
+ status->heal(src, 0, status->get_lv(bl)*(95+15*rate)/100, STATUS_HEAL_SHOWEFFECT);
}
}
@@ -2388,9 +2388,9 @@ static int skill_counter_additional_effect(struct block_list *src, struct block_
sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check.
}
}
- if( hp || sp ) {
+ if (hp != 0 || sp != 0) {
// updated to force healing to allow healing through berserk
- status->heal(src, hp, sp, battle_config.show_hp_sp_gain ? 3 : 1);
+ status->heal(src, hp, sp, STATUS_HEAL_FORCED | (battle_config.show_hp_sp_gain ? STATUS_HEAL_SHOWEFFECT : STATUS_HEAL_DEFAULT));
}
}
@@ -2899,7 +2899,7 @@ static int skill_attack(int attack_type, struct block_list *src, struct block_li
sp = sp * sc->data[SC_MAGICROD]->val2 / 100;
if(skill_id == WZ_WATERBALL && skill_lv > 1)
sp = sp/((skill_lv|1)*(skill_lv|1)); //Estimate SP cost of a single water-ball
- status->heal(bl, 0, sp, 2);
+ status->heal(bl, 0, sp, STATUS_HEAL_SHOWEFFECT);
}
}
@@ -4477,7 +4477,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
if( skill_id == MO_EXTREMITYFIST ) {
mbl = src;
i = 3; // for Asura(from caster)
- status->set_sp(src, 0, 0);
+ status->set_sp(src, 0, STATUS_HEAL_DEFAULT);
status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER);
status_change_end(src, SC_BLADESTOP, INVALID_TIMER);
#ifdef RENEWAL
@@ -4487,9 +4487,9 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
status_change_end(src, SC_NJ_NEN, INVALID_TIMER);
status_change_end(src, SC_HIDING, INVALID_TIMER);
#ifdef RENEWAL
- status->set_hp(src, max(status_get_max_hp(src)/100, 1), 0);
+ status->set_hp(src, max(status_get_max_hp(src)/100, 1), STATUS_HEAL_DEFAULT);
#else // not RENEWAL
- status->set_hp(src, 1, 0);
+ status->set_hp(src, 1, STATUS_HEAL_DEFAULT);
#endif // RENEWAL
}
dir = map->calc_dir(src,bl->x,bl->y);
@@ -4603,7 +4603,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
heal = skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, sflag);
if (skill_id == NPC_VAMPIRE_GIFT && heal > 0) {
clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1);
- status->heal(src,heal,0,0);
+ status->heal(src, heal, 0, STATUS_HEAL_DEFAULT);
}
if (skill_id == SU_SCRATCH && status->get_lv(src) >= 30 && (rnd() % 100 < (int)(status->get_lv(src) / 30) + 10)) // TODO: Need activation chance.
skill->addtimerskill(src, tick + skill->get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag);
@@ -4971,7 +4971,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
src, src, bl, skill_id, skill_lv, tick, flag);
if (heal > 0){
clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1);
- status->heal(src, heal, 0, 0);
+ status->heal(src, heal, 0, STATUS_HEAL_DEFAULT);
}
}
break;
@@ -5082,7 +5082,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
heal = 0; // Don't absorb heal from Ice Walls or other skill units.
if( heal && rnd()%100 < rate ) {
- status->heal(src, heal, 0, 0);
+ status->heal(src, heal, 0, STATUS_HEAL_DEFAULT);
clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1);
}
}
@@ -5843,7 +5843,7 @@ static int skill_castend_id(int tid, int64 tick, int id, intptr_t data)
//When Asura fails... (except when it fails from Fog of Wall)
//Consume SP/spheres
skill->consume_requirement(sd,ud->skill_id, ud->skill_lv,1);
- status->set_sp(src, 0, 0);
+ status->set_sp(src, 0, STATUS_HEAL_DEFAULT);
sc = &sd->sc;
if (sc->count) {
//End states
@@ -6126,7 +6126,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
clif->skill_nodamage (src, bl, skill_id, heal, 1);
if( tsc && tsc->data[SC_AKAITSUKI] && heal && skill_id != HLIF_HEAL )
heal = ~heal + 1;
- heal_get_jobexp = status->heal(bl,heal,0,0);
+ heal_get_jobexp = status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
if(sd && dstsd && heal > 0 && sd != dstsd && battle_config.heal_exp > 0){
heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100;
@@ -6159,8 +6159,8 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
clif->updatestatus(sd,SP_BASEEXP);
clif->updatestatus(sd,SP_JOBEXP);
}
- status->set_hp(src, 1, 0);
- status->set_sp(src, 0, 0);
+ status->set_hp(src, 1, STATUS_HEAL_DEFAULT);
+ status->set_sp(src, 0, STATUS_HEAL_DEFAULT);
break;
} else if (status->isdead(bl) && flag&1) { //Revive
skill->area_temp[0]++; //Count it in, then fall-through to the Resurrection code.
@@ -6333,7 +6333,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
break;
case SA_INSTANTDEATH:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- status->set_hp(bl,1,0);
+ status->set_hp(bl, 1, STATUS_HEAL_DEFAULT);
break;
case SA_QUESTION:
case SA_GRAVITY:
@@ -6911,7 +6911,8 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
if (dstsd && dstsd->charm_type != CHARM_TYPE_NONE && dstsd->charm_count > 0) {
pc->del_charm(dstsd, dstsd->charm_count, dstsd->charm_type);
}
- if (sp) status->heal(src, 0, sp, 3);
+ if (sp != 0)
+ status->heal(src, 0, sp, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
clif->skill_nodamage(src,bl,skill_id,skill_lv,sp?1:0);
}
break;
@@ -7273,7 +7274,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
case NV_FIRSTAID:
clif->skill_nodamage(src,bl,skill_id,5,1);
- status->heal(bl,5,0,0);
+ status->heal(bl, 5, 0, STATUS_HEAL_DEFAULT);
break;
case AL_CURE:
@@ -7350,7 +7351,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
case MER_SCAPEGOAT:
if( mer && mer->master ) {
- status->heal(&mer->master->bl, mer->battle_status.hp, 0, 2);
+ status->heal(&mer->master->bl, mer->battle_status.hp, 0, STATUS_HEAL_SHOWEFFECT);
status->damage(src, src, mer->battle_status.max_hp, 0, 0, 1);
}
break;
@@ -7667,7 +7668,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
if( tsc && tsc->data[SC_EXTREMITYFIST2] )
sp = 0;
#endif
- status->heal(bl,(int)hp,sp,0);
+ status->heal(bl, (int)hp, sp, STATUS_HEAL_DEFAULT);
}
break;
case AM_CP_WEAPON:
@@ -7842,7 +7843,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
sp = skill->get_sp(skill_id,skill_lv);
sp = sp * tsc->data[SC_MAGICROD]->val2 / 100;
if(sp < 1) sp = 1;
- status->heal(bl,0,sp,2);
+ status->heal(bl, 0, sp, STATUS_HEAL_SHOWEFFECT);
status_percent_damage(bl, src, 0, -20, false); //20% max SP damage.
} else {
struct unit_data *ud = unit->bl2ud(bl);
@@ -7874,8 +7875,8 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
if (sp) //Recover some of the SP used
sp = sp*(25*(skill_lv-1))/100;
- if(hp || sp)
- status->heal(src, hp, sp, 2);
+ if (hp != 0 || sp != 0)
+ status->heal(src, hp, sp, STATUS_HEAL_SHOWEFFECT);
}
}
break;
@@ -8118,14 +8119,14 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
{
int hp_rate = skill_lv == 0 ? 0 : skill->get_hp_rate(skill_id, skill_lv);
int gain_hp = tstatus->max_hp*abs(hp_rate)/100; // The earned is the same % of the target HP than it cost the caster. [Skotlex]
- clif->skill_nodamage(src,bl,skill_id,status->heal(bl, gain_hp, 0, 0),1);
+ clif->skill_nodamage(src, bl, skill_id, status->heal(bl, gain_hp, 0, STATUS_HEAL_DEFAULT), 1);
}
break;
case WE_FEMALE:
{
int sp_rate = skill_lv == 0 ? 0 : skill->get_sp_rate(skill_id, skill_lv);
int gain_sp = tstatus->max_sp*abs(sp_rate)/100;// The earned is the same % of the target SP than it cost the caster. [Skotlex]
- clif->skill_nodamage(src,bl,skill_id,status->heal(bl, 0, gain_sp, 0),1);
+ clif->skill_nodamage(src, bl, skill_id, status->heal(bl, 0, gain_sp, STATUS_HEAL_DEFAULT), 1);
}
break;
@@ -8165,7 +8166,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
break;
}
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
- status->heal(bl,0,sp,2);
+ status->heal(bl, 0, sp, STATUS_HEAL_SHOWEFFECT);
}
break;
@@ -8320,7 +8321,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
}
dstmd->state.soul_change_flag = 1;
sp2 = sstatus->max_sp * 3 /100;
- status->heal(src, 0, sp2, 2);
+ status->heal(src, 0, sp2, STATUS_HEAL_SHOWEFFECT);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
}
@@ -8332,8 +8333,8 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
if( tsc && tsc->data[SC_EXTREMITYFIST2] )
sp1 = tstatus->sp;
#endif // RENEWAL
- status->set_sp(src, sp2, 3);
- status->set_sp(bl, sp1, 3);
+ status->set_sp(src, sp2, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
+ status->set_sp(bl, sp1, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
}
break;
@@ -8371,7 +8372,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
clif->skill_nodamage(NULL,bl,AL_HEAL,hp,1);
if(sp > 0)
clif->skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1);
- status->heal(bl,hp,sp,0);
+ status->heal(bl, hp, sp, STATUS_HEAL_DEFAULT);
}
break;
// Full Chemical Protection
@@ -8460,7 +8461,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
sc_start(src,bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
break;
case 5: // 2000HP heal, random teleported
- status->heal(src, 2000, 0, 0);
+ status->heal(src, 2000, 0, STATUS_HEAL_DEFAULT);
if( !map_flag_vs(bl->m) )
unit->warp(bl, -1,-1,-1, CLR_TELEPORT);
break;
@@ -8754,7 +8755,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
//Eh? why double skill packet?
clif->skill_nodamage(src,bl,AL_HEAL,hp,1);
clif->skill_nodamage(src,bl,skill_id,hp,1);
- status->heal(bl, hp, 0, 0);
+ status->heal(bl, hp, 0, STATUS_HEAL_DEFAULT);
}
break;
// Homun single-target support skills [orn]
@@ -8901,7 +8902,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
int heal = status_get_max_hp(bl) * 25 / 100;
clif->skill_nodamage(src,bl,skill_id,skill_lv,
sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
- status->heal(bl,heal,0,1);
+ status->heal(bl, heal, 0, STATUS_HEAL_FORCED);
status->change_clear_buffs(bl,4);
}
break;
@@ -8955,7 +8956,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
value = status_get_max_hp(bl) * 25 / 100;
status->change_clear_buffs(bl,4);
skill->area_temp[5] &= ~0x20;
- status->heal(bl,value,0,1);
+ status->heal(bl, value, 0, STATUS_HEAL_FORCED);
type = SC_REFRESH;
}else if( skill->area_temp[5]&0x40 ){
skill->area_temp[5] &= ~0x40;
@@ -9140,7 +9141,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
clif->skill_nodamage(bl, bl, skill_id, heal, 1);
if( tsc && tsc->data[SC_AKAITSUKI] && heal )
heal = ~heal + 1;
- status->heal(bl, heal, 0, 1);
+ status->heal(bl, heal, 0, STATUS_HEAL_FORCED);
}
} else if( sd )
party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
@@ -9416,7 +9417,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
pc->setmadogear(sd, false);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
skill->castend_damage_id(src, src, skill_id, skill_lv, tick, flag);
- status->set_sp(src, 0, 0);
+ status->set_sp(src, 0, STATUS_HEAL_DEFAULT);
}
break;
@@ -9455,7 +9456,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
case 5: hp = 23; break;
}
heal = tstatus->max_hp * hp / 100;
- status->heal(bl,heal,0,2);
+ status->heal(bl, heal, 0, STATUS_HEAL_SHOWEFFECT);
clif->skill_nodamage(src, bl, skill_id, skill_lv, heal);
}
break;
@@ -9533,7 +9534,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
int sp = 100 * skill_lv;
if( dstmd ) sp = dstmd->level * 2;
if( status_zap(bl,0,sp) )
- status->heal(src,0,sp/2,3);//What does flag 3 do? [Rytech]
+ status->heal(src, 0, sp / 2, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
}
if ( tsc && tsc->data[SC__UNLUCKY] && skill_id == SC_UNLUCKY) {
//If the target was successfully inflected with the Unlucky status, give 1 of 3 random status's.
@@ -9657,7 +9658,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
case 3:
sc_start(src, bl, SC_SHIELDSPELL_REF, 100, opt, INFINITE_DURATION); // HP Recovery
val = sstatus->max_hp * ((status->get_lv(src) / 10) + (shield->refine + 1)) / 100;
- status->heal(bl, val, 0, 2);
+ status->heal(bl, val, 0, STATUS_HEAL_SHOWEFFECT);
status_change_end(bl,SC_SHIELDSPELL_REF,INVALID_TIMER);
break;
}
@@ -9800,7 +9801,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
}
heal = 120 * skill_lv + status_get_max_hp(bl) * (2 + skill_lv) / 100;
- status->heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
if( (tsc && tsc->opt1) && (rnd()%100 < ((skill_lv * 5) + (status_get_dex(src) + status->get_lv(src)) / 4) - (1 + (rnd() % 10))) ) {
status_change_end(bl, SC_STONE, INVALID_TIMER);
@@ -9871,7 +9872,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
heal = 1;
status->fixed_revive(bl, heal, 0);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- status->set_sp(bl, 0, 0);
+ status->set_sp(bl, 0, STATUS_HEAL_DEFAULT);
}
}
break;
@@ -10208,7 +10209,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
}
e_hp = ed->battle_status.max_hp * 10 / 100;
e_sp = ed->battle_status.max_sp * 10 / 100;
- status->heal(&ed->bl,e_hp,e_sp,3);
+ status->heal(&ed->bl, e_hp, e_sp, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
clif->skill_nodamage(src,&ed->bl,skill_id,skill_lv,1);
}
break;
@@ -10518,7 +10519,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
}
}
heal = 5 * status->get_lv(&hd->bl) + status->base_matk(&hd->bl, &hd->battle_status, status->get_lv(&hd->bl));
- status->heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
clif->skill_nodamage(src, src, skill_id, skill_lv, clif->skill_nodamage(src, bl, AL_HEAL, heal, 1));
status->change_start(src, src, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
status->change_start(src, bl, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
@@ -12800,7 +12801,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
if (tsc && tsc->data[SC_AKAITSUKI] && heal)
heal = ~heal + 1;
- status->heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
if (diff >= 500)
sg->val1--;
}
@@ -12821,7 +12822,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
if (status->isimmune(bl))
heal = 0;
clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
- status->heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
}
break;
@@ -13032,7 +13033,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
if( tsc && tsc->data[SC_AKAITSUKI] && heal )
heal = ~heal + 1;
clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
- status->heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
}
}
break;
@@ -13086,7 +13087,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
case 0: // Heal 1~9999 HP
heal = rnd() %9999+1;
clif->skill_nodamage(ss,bl,AL_HEAL,heal,1);
- status->heal(bl,heal,0,0);
+ status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT);
break;
case 1: // End all negative status
status->change_clear_buffs(bl,2);
@@ -13231,7 +13232,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
}
hp = tstatus->max_hp * hp / 100;
sp = tstatus->max_sp * sp / 100;
- status->heal(bl, hp, sp, 2);
+ status->heal(bl, hp, sp, STATUS_HEAL_SHOWEFFECT);
sc_start(ss, bl, type, 100, sg->skill_lv, (sg->interval * 3) + 100);
}
// Reveal hidden players every 5 seconds.
@@ -13353,7 +13354,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
clif->skill_nodamage(&src->bl, bl, AL_HEAL, hp, 0);
if( tsc && tsc->data[SC_AKAITSUKI] && hp )
hp = ~hp + 1;
- status->heal(bl, hp, 0, 0);
+ status->heal(bl, hp, 0, STATUS_HEAL_DEFAULT);
sc_start(ss, bl, type, 100, sg->skill_lv, sg->interval + 100);
}
break;
@@ -13367,13 +13368,13 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
int hp = tstatus->max_hp / 100; //+1% each 5s
if ((sg->val3) % 5) { //each 5s
if (tstatus->def_ele == skill->get_ele(sg->skill_id,sg->skill_lv)) {
- status->heal(bl, hp, 0, 2);
+ status->heal(bl, hp, 0, STATUS_HEAL_SHOWEFFECT);
} else if( (sg->unit_id == UNT_FIRE_INSIGNIA && tstatus->def_ele == ELE_EARTH)
|| (sg->unit_id == UNT_WATER_INSIGNIA && tstatus->def_ele == ELE_FIRE)
|| (sg->unit_id == UNT_WIND_INSIGNIA && tstatus->def_ele == ELE_WATER)
|| (sg->unit_id == UNT_EARTH_INSIGNIA && tstatus->def_ele == ELE_WIND)
) {
- status->heal(bl, -hp, 0, 0);
+ status->heal(bl, -hp, 0, STATUS_HEAL_DEFAULT);
}
}
sg->val3++; //timer
diff --git a/src/map/status.c b/src/map/status.c
index 370432ce7..edcdd515d 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -1240,10 +1240,15 @@ static void status_copy(struct status_data *a, const struct status_data *b)
memcpy((void*)&a->max_hp, (const void*)&b->max_hp, sizeof(struct status_data)-(sizeof(a->hp)+sizeof(a->sp)));
}
-//Sets HP to given value. Flag is the flag passed to status->heal in case
-//final value is higher than current (use 2 to make a healing effect display
-//on players) It will always succeed (overrides Berserk block), but it can't kill.
-static int status_set_hp(struct block_list *bl, unsigned int hp, int flag)
+/**
+ * Sets HP to the given value.
+ *
+ * @param bl The target unit.
+ * @param hp The desired HP value.
+ * @param flag Additional options. @see enum status_heal_flag. STATUS_HEAL_FORCED is always implied.
+ * @return The amount of HP gained.
+ */
+static int status_set_hp(struct block_list *bl, unsigned int hp, enum status_heal_flag flag)
{
struct status_data *st;
if (hp < 1) return 0;
@@ -1254,14 +1259,19 @@ static int status_set_hp(struct block_list *bl, unsigned int hp, int flag)
if (hp > st->max_hp) hp = st->max_hp;
if (hp == st->hp) return 0;
if (hp > st->hp)
- return status->heal(bl, hp - st->hp, 0, 1|flag);
+ return status->heal(bl, hp - st->hp, 0, STATUS_HEAL_FORCED | flag);
return status_zap(bl, st->hp - hp, 0);
}
-//Sets SP to given value. Flag is the flag passed to status->heal in case
-//final value is higher than current (use 2 to make a healing effect display
-//on players)
-static int status_set_sp(struct block_list *bl, unsigned int sp, int flag)
+/**
+ * Sets SP to the given value.
+ *
+ * @param bl The target unit.
+ * @param hp The desired SP value.
+ * @param flag Additional options. @see enum status_heal_flag. STATUS_HEAL_FORCED is always implied.
+ * @return The amount of SP gained.
+ */
+static int status_set_sp(struct block_list *bl, unsigned int sp, enum status_heal_flag flag)
{
struct status_data *st;
@@ -1272,7 +1282,7 @@ static int status_set_sp(struct block_list *bl, unsigned int sp, int flag)
if (sp > st->max_sp) sp = st->max_sp;
if (sp == st->sp) return 0;
if (sp > st->sp)
- return status->heal(bl, 0, sp - st->sp, 1|flag);
+ return status->heal(bl, 0, sp - st->sp, STATUS_HEAL_FORCED | flag);
return status_zap(bl, 0, st->sp - sp);
}
@@ -1304,12 +1314,12 @@ static int status_damage(struct block_list *src, struct block_list *target, int6
sp = 0; //Not a valid SP target.
if (hp < 0) { //Assume absorbed damage.
- status->heal(target, -hp, 0, 1);
+ status->heal(target, -hp, 0, STATUS_HEAL_FORCED);
hp = 0;
}
if (sp < 0) {
- status->heal(target, 0, -sp, 1);
+ status->heal(target, 0, -sp, STATUS_HEAL_FORCED);
sp = 0;
}
@@ -1527,9 +1537,16 @@ static int status_damage(struct block_list *src, struct block_list *target, int6
return (int)(hp+sp);
}
-//Heals a character. If flag&1, this is forced healing (otherwise stuff like Berserk can block it)
-//If flag&2, when the player is healed, show the HP/SP heal effect.
-static int status_heal(struct block_list *bl, int64 in_hp, int64 in_sp, int flag)
+/**
+ * Heals a character.
+ *
+ * @param bl The target unit.
+ * @param in_hp Amount of HP to recover.
+ * @param in_sp Amount of SP to recover.
+ * @param flag Additional options, @see enum status_heal_flag.
+ * @return The amount of HP + SP healed.
+ */
+static int status_heal(struct block_list *bl, int64 in_hp, int64 in_sp, enum status_heal_flag flag)
{
struct status_data *st;
struct status_change *sc;
@@ -1538,7 +1555,9 @@ static int status_heal(struct block_list *bl, int64 in_hp, int64 in_sp, int flag
nullpo_ret(bl);
st = status->get_status_data(bl);
- if (st == &status->dummy || !st->hp)
+ if (st == &status->dummy)
+ return 0;
+ if (st->hp == 0 && (flag & STATUS_HEAL_ALLOWREVIVE) != 0)
return 0;
/* From here onwards, we consider it a 32-type as the client does not support higher and the value doesn't get through percentage modifiers */
@@ -1555,10 +1574,10 @@ static int status_heal(struct block_list *bl, int64 in_hp, int64 in_sp, int flag
hp = 0;
}
- if(hp) {
- if( sc && sc->data[SC_BERSERK] ) {
- if( flag&1 )
- flag &= ~2;
+ if (hp != 0) {
+ if (sc && sc->data[SC_BERSERK] != NULL) {
+ if ((flag & STATUS_HEAL_FORCED) != 0)
+ flag &= ~STATUS_HEAL_SHOWEFFECT;
else
hp = 0;
}
@@ -1593,7 +1612,7 @@ static int status_heal(struct block_list *bl, int64 in_hp, int64 in_sp, int flag
// send hp update to client
switch(bl->type) {
- case BL_PC: pc->heal(BL_UCAST(BL_PC, bl), hp, sp, (flag&2) ? 1 : 0); break;
+ case BL_PC: pc->heal(BL_UCAST(BL_PC, bl), hp, sp, (flag & STATUS_HEAL_SHOWEFFECT) != 0 ? 1 : 0); break;
case BL_MOB: mob->heal(BL_UCAST(BL_MOB, bl), hp); break;
case BL_HOM: homun->healed(BL_UCAST(BL_HOM, bl)); break;
case BL_MER: mercenary->heal(BL_UCAST(BL_MER, bl), hp, sp); break;
@@ -1648,18 +1667,18 @@ static int status_percent_change(struct block_list *src, struct block_list *targ
if (flag)
status->damage(src, target, INT_MAX, 0, 0, (!src||src==target?5:1));
else
- status->heal(target, INT_MAX, 0, 0);
+ status->heal(target, INT_MAX, 0, STATUS_HEAL_DEFAULT);
}
if (sp > INT_MAX) {
sp -= INT_MAX;
if (flag)
status->damage(src, target, 0, INT_MAX, 0, (!src||src==target?5:1));
else
- status->heal(target, 0, INT_MAX, 0);
+ status->heal(target, 0, INT_MAX, STATUS_HEAL_DEFAULT);
}
if (flag)
return status->damage(src, target, hp, sp, 0, (!src||src==target?5:1));
- return status->heal(target, hp, sp, 0);
+ return status->heal(target, hp, sp, STATUS_HEAL_DEFAULT);
}
static int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp)
@@ -2330,6 +2349,51 @@ static unsigned int status_get_base_maxhp(const struct map_session_data *sd, con
return (unsigned int)cap_value(val,0,UINT_MAX);
}
+/**
+ * Calculates the HP that a character will have after death, on respawn.
+ *
+ * @param sd The character to calculate.
+ * @param st The character's status data.
+ */
+static unsigned int status_get_restart_hp(const struct map_session_data *sd, const struct status_data *st)
+{
+ unsigned int hp = 0;
+
+ if (sd->special_state.restart_full_recover)
+ return st->max_hp;
+
+ if ((sd->job & MAPID_BASEMASK) == MAPID_NOVICE && (sd->job & JOBL_2) == 0 && battle_config.restart_hp_rate < 50)
+ hp = st->max_hp / 2;
+ else
+ hp = APPLY_RATE(st->max_hp, battle_config.restart_hp_rate);
+
+ if (hp > 0)
+ return hp;
+
+ return 1;
+}
+
+/**
+ * Calculates the SP that a character will have after death, on respawn.
+ *
+ * @param sd The character to calculate.
+ * @param st The character's status data.
+ */
+static unsigned int status_get_restart_sp(const struct map_session_data *sd, const struct status_data *st)
+{
+ unsigned int sp = 0;
+
+ if (sd->special_state.restart_full_recover)
+ return st->max_sp;
+
+ sp = APPLY_RATE(st->max_sp, battle_config.restart_sp_rate);
+
+ if (sp > 0)
+ return sp;
+
+ return 1; // the minimum for the respawn setting is SP:1
+}
+
static void status_calc_pc_additional(struct map_session_data *sd, enum e_status_calc_opt opt)
{
/* Just used for Plugin to give bonuses. */
@@ -2884,20 +2948,8 @@ static int status_calc_pc_(struct map_session_data *sd, enum e_status_calc_opt o
// ----- RESPAWN HP/SP -----
//
//Calc respawn hp and store it on base_status
- if (sd->special_state.restart_full_recover)
- {
- bstatus->hp = bstatus->max_hp;
- bstatus->sp = bstatus->max_sp;
- } else {
- status->calc_pc_recover_hp(sd, bstatus);
- if(!bstatus->hp)
- bstatus->hp = 1;
-
- bstatus->sp = APPLY_RATE(bstatus->max_sp, battle_config.restart_sp_rate);
-
- if( !bstatus->sp ) /* the minimum for the respawn setting is SP:1 */
- bstatus->sp = 1;
- }
+ bstatus->hp = status->get_restart_hp(sd, bstatus);
+ bstatus->sp = status->get_restart_sp(sd, bstatus);
// ----- MISC CALCULATION -----
status->calc_misc(&sd->bl, bstatus, sd->status.base_level);
@@ -9410,10 +9462,10 @@ static int status_change_start(struct block_list *src, struct block_list *bl, en
return 0;
PER( 100 / (status_get_max_hp(bl) / hp), lv );
- status->heal(bl, (!(hp%2) ? (6-lv) *4 / 100 : -(lv*4) / 100), 0, 1);
+ status->heal(bl, (!(hp%2) ? (6-lv) *4 / 100 : -(lv*4) / 100), 0, STATUS_HEAL_FORCED);
PER( 100 / (status_get_max_sp(bl) / sp), lv );
- status->heal(bl, 0,(!(sp%2) ? (6-lv) *3 / 100 : -(lv*3) / 100), 1);
+ status->heal(bl, 0,(!(sp%2) ? (6-lv) *3 / 100 : -(lv*3) / 100), STATUS_HEAL_FORCED);
}
#undef PER
break;
@@ -9646,8 +9698,8 @@ static int status_change_start(struct block_list *src, struct block_list *bl, en
switch (type) {
case SC_BERSERK:
if (!(sce->val2)) { //don't heal if already set
- status->heal(bl, st->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block.
- status->set_sp(bl, 0, 0); //Damage all SP
+ status->heal(bl, st->max_hp, 0, STATUS_HEAL_FORCED); //Do not use percent_heal as this healing must override BERSERK's block.
+ status->set_sp(bl, 0, STATUS_HEAL_DEFAULT); //Damage all SP
}
sce->val2 = 5 * st->max_hp / 100;
break;
@@ -10973,7 +11025,7 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid,
status_percent_heal(bl, 100, 0);
status_change_end(bl, SC__BLOODYLUST, INVALID_TIMER);
} else if(st->hp > 100 && sce->val2) //If val2 is removed, no HP penalty (dispelled?) [Skotlex]
- status->set_hp(bl, 100, 0);
+ status->set_hp(bl, 100, STATUS_HEAL_DEFAULT);
if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2) {
sc->data[SC_ENDURE]->val4 = 0;
status_change_end(bl, SC_ENDURE, INVALID_TIMER);
@@ -11025,8 +11077,8 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid,
if (tid == INVALID_TIMER)
break;
// "lose almost all their HP and SP" on natural expiration.
- status->set_hp(bl, 10, 0);
- status->set_sp(bl, 10, 0);
+ status->set_hp(bl, 10, STATUS_HEAL_DEFAULT);
+ status->set_sp(bl, 10, STATUS_HEAL_DEFAULT);
break;
case SC_AUTOTRADE:
if (tid == INVALID_TIMER)
@@ -11437,8 +11489,8 @@ static int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data)
hp = st->max_hp - st->hp;
if (hp > sce->val2)
hp = sce->val2;
- if (hp)
- status->heal(bl, hp, 0, 2);
+ if (hp != 0)
+ status->heal(bl, hp, 0, STATUS_HEAL_SHOWEFFECT);
sce->val4 = INVALID_TIMER;
return 1;
}
@@ -11644,7 +11696,7 @@ static int status_change_timer(int tid, int64 tick, int id, intptr_t data)
int hp = 0;
if (st->hp < st->max_hp)
hp = (sce->val1 < 0) ? (int)(sd->status.max_hp * -1 * sce->val1 / 100.) : sce->val1 ;
- status->heal(bl, hp, 0, 2);
+ status->heal(bl, hp, 0, STATUS_HEAL_SHOWEFFECT);
sc_timer_next((sce->val2 * 1000) + tick, status->change_timer, bl->id, data);
return 0;
}
@@ -11793,7 +11845,7 @@ static int status_change_timer(int tid, int64 tick, int id, intptr_t data)
break;
case SC_ABUNDANCE:
if(--(sce->val4) > 0) {
- status->heal(bl,0,60,0);
+ status->heal(bl, 0, 60, STATUS_HEAL_DEFAULT);
sc_timer_next(10000+tick, status->change_timer, bl->id, data);
}
break;
@@ -11909,7 +11961,7 @@ static int status_change_timer(int tid, int64 tick, int id, intptr_t data)
heal = ~heal + 1;
map->freeblock_lock();
- status->heal(bl, heal, 0, 2);
+ status->heal(bl, heal, 0, STATUS_HEAL_SHOWEFFECT);
if( sc->data[type] ) {
sc_timer_next(5000 + tick, status->change_timer, bl->id, data);
}
@@ -12032,7 +12084,7 @@ static int status_change_timer(int tid, int64 tick, int id, intptr_t data)
if ( sc->data[type] ) {
sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
}
- status->heal(src, damage*(5 + 5 * sce->val1)/100, 0, 0); // 5 + 5% per level
+ status->heal(src, damage*(5 + 5 * sce->val1)/100, 0, STATUS_HEAL_DEFAULT); // 5 + 5% per level
map->freeblock_unlock();
return 0;
}
@@ -12049,7 +12101,7 @@ static int status_change_timer(int tid, int64 tick, int id, intptr_t data)
case SC_DEEP_SLEEP:
if( --(sce->val4) >= 0 )
{// Recovers 3% of the player's MaxHP/MaxSP every 2 seconds.
- status->heal(bl, st->max_hp * 3 / 100, st->max_sp * 3 / 100, 2);
+ status->heal(bl, st->max_hp * 3 / 100, st->max_sp * 3 / 100, STATUS_HEAL_SHOWEFFECT);
sc_timer_next(2000 + tick, status->change_timer, bl->id, data);
return 0;
}
@@ -12059,7 +12111,7 @@ static int status_change_timer(int tid, int64 tick, int id, intptr_t data)
if( --(sce->val4) >= 0 ) {
if( !status->charge(bl,0,sce->val3) )
break;
- status->heal(bl, sce->val2, 0, 1);
+ status->heal(bl, sce->val2, 0, STATUS_HEAL_FORCED);
sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
return 0;
}
@@ -12067,7 +12119,7 @@ static int status_change_timer(int tid, int64 tick, int id, intptr_t data)
case SC_SONG_OF_MANA:
if( --(sce->val4) >= 0 ) {
- status->heal(bl,0,sce->val3,3);
+ status->heal(bl, 0, sce->val3, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT);
sc_timer_next(5000 + tick, status->change_timer, bl->id, data);
return 0;
}
@@ -12261,7 +12313,7 @@ static int status_change_timer(int tid, int64 tick, int id, intptr_t data)
return 0;
case SC_MEIKYOUSISUI:
if( --(sce->val4) > 0 ) {
- status->heal(bl, st->max_hp * (sce->val1+1) / 100, st->max_sp * sce->val1 / 100, 0);
+ status->heal(bl, st->max_hp * (sce->val1+1) / 100, st->max_sp * sce->val1 / 100, STATUS_HEAL_DEFAULT);
sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
return 0;
}
@@ -12297,7 +12349,7 @@ static int status_change_timer(int tid, int64 tick, int id, intptr_t data)
break;
case SC_FRIGG_SONG:
if( --(sce->val4) > 0 ) {
- status->heal(bl, sce->val3, 0, 0);
+ status->heal(bl, sce->val3, 0, STATUS_HEAL_DEFAULT);
sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
return 0;
}
@@ -12879,7 +12931,7 @@ static int status_natural_heal(struct block_list *bl, va_list args)
sregen->tick.hp += val;
while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) {
sregen->tick.hp -= battle_config.natural_heal_skill_interval;
- if(status->heal(bl, sregen->hp, 0, 3) < sregen->hp) {
+ if (status->heal(bl, sregen->hp, 0, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < sregen->hp) {
//Full
flag&=~(RGN_HP|RGN_SHP);
break;
@@ -12894,7 +12946,7 @@ static int status_natural_heal(struct block_list *bl, va_list args)
sregen->tick.sp += val;
while(sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval) {
sregen->tick.sp -= battle_config.natural_heal_skill_interval;
- if(status->heal(bl, 0, sregen->sp, 3) < sregen->sp) {
+ if (status->heal(bl, 0, sregen->sp, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < sregen->sp) {
//Full
flag&=~(RGN_SP|RGN_SSP);
break;
@@ -12943,7 +12995,7 @@ static int status_natural_heal(struct block_list *bl, va_list args)
val += regen->hp;
regen->tick.hp -= battle_config.natural_healhp_interval;
} while(regen->tick.hp >= (unsigned int)battle_config.natural_healhp_interval);
- if (status->heal(bl, val, 0, 1) < val)
+ if (status->heal(bl, val, 0, STATUS_HEAL_FORCED) < val)
flag&=~RGN_SHP; //full.
}
}
@@ -12962,7 +13014,7 @@ static int status_natural_heal(struct block_list *bl, va_list args)
val += regen->sp;
regen->tick.sp -= battle_config.natural_healsp_interval;
} while(regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval);
- if (status->heal(bl, 0, val, 1) < val)
+ if (status->heal(bl, 0, val, STATUS_HEAL_FORCED) < val)
flag&=~RGN_SSP; //full.
}
}
@@ -12979,7 +13031,7 @@ static int status_natural_heal(struct block_list *bl, va_list args)
while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) {
sregen->tick.hp -= battle_config.natural_heal_skill_interval;
- if(status->heal(bl, sregen->hp, 0, 3) < sregen->hp)
+ if (status->heal(bl, sregen->hp, 0, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < sregen->hp)
break; //Full
}
}
@@ -13004,7 +13056,7 @@ static int status_natural_heal(struct block_list *bl, va_list args)
}
}
sregen->tick.sp -= battle_config.natural_heal_skill_interval;
- if(status->heal(bl, 0, val, 3) < val)
+ if (status->heal(bl, 0, val, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < val)
break; //Full
}
}
@@ -13729,6 +13781,8 @@ void status_defaults(void)
status->base_atk = status_base_atk;
status->get_base_maxhp = status_get_base_maxhp;
status->get_base_maxsp = status_get_base_maxsp;
+ status->get_restart_hp = status_get_restart_hp;
+ status->get_restart_sp = status_get_restart_sp;
status->calc_npc_ = status_calc_npc_;
status->calc_str = status_calc_str;
status->calc_agi = status_calc_agi;
diff --git a/src/map/status.h b/src/map/status.h
index e7cd5e94c..17af22703 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -99,6 +99,16 @@ enum scstart_flag {
SCFLAG_ALL = SCFLAG_NONE|SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_LOADED|SCFLAG_FIXEDRATE|SCFLAG_NOICON
};
+/**
+ * Flags to be used with status->heal() and related functions.
+ */
+enum status_heal_flag {
+ STATUS_HEAL_DEFAULT = 0x00, ///< Default
+ STATUS_HEAL_FORCED = 0x01, ///< Forced healing (bypassing Berserk and similar)
+ STATUS_HEAL_SHOWEFFECT = 0x02, ///< Show the HP/SP heal effect
+ STATUS_HEAL_ALLOWREVIVE = 0x04, ///< Force resurrection in case of dead targets.
+};
+
// Status changes listing. These code are for use by the server.
typedef enum sc_type {
SC_NONE = -1,
@@ -1900,7 +1910,7 @@ enum e_joint_break
/**
* Mob mode definitions. [Skotlex]
*
- * @see doc/mob_db_mode_list.txt for a description of each mode.
+ * @see doc/mob_db_mode_list.md for a description of each mode.
*/
enum e_mode
{
@@ -2309,9 +2319,9 @@ struct status_interface {
int (*charge) (struct block_list* bl, int64 hp, int64 sp);
int (*percent_change) (struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag);
//Used to set the hp/sp of an object to an absolute value (can't kill)
- int (*set_hp) (struct block_list *bl, unsigned int hp, int flag);
- int (*set_sp) (struct block_list *bl, unsigned int sp, int flag);
- int (*heal) (struct block_list *bl,int64 hp,int64 sp, int flag);
+ int (*set_hp) (struct block_list *bl, unsigned int hp, enum status_heal_flag flag);
+ int (*set_sp) (struct block_list *bl, unsigned int sp, enum status_heal_flag flag);
+ int (*heal) (struct block_list *bl,int64 hp,int64 sp, enum status_heal_flag flag);
int (*revive) (struct block_list *bl, unsigned char per_hp, unsigned char per_sp);
int (*fixed_revive) (struct block_list *bl, unsigned int per_hp, unsigned int per_sp);
struct regen_data * (*get_regen_data) (struct block_list *bl);
@@ -2384,6 +2394,8 @@ struct status_interface {
unsigned short (*base_atk) (const struct block_list *bl, const struct status_data *st);
unsigned int (*get_base_maxhp) (const struct map_session_data *sd, const struct status_data *st);
unsigned int (*get_base_maxsp) (const struct map_session_data *sd, const struct status_data *st);
+ unsigned int (*get_restart_hp) (const struct map_session_data *sd, const struct status_data *st);
+ unsigned int (*get_restart_sp) (const struct map_session_data *sd, const struct status_data *st);
int (*calc_npc_) (struct npc_data *nd, enum e_status_calc_opt opt);
unsigned short (*calc_str) (struct block_list *bl, struct status_change *sc, int str);
unsigned short (*calc_agi) (struct block_list *bl, struct status_change *sc, int agi);
diff --git a/src/map/unit.c b/src/map/unit.c
index 9174bdccd..371be03db 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1836,7 +1836,7 @@ static int unit_set_target(struct unit_data *ud, int target_id)
struct block_list* target;
if (ud->target && (target = map->id2bl(ud->target)) != NULL && (ux = unit->bl2ud(target)) != NULL && ux->target_count > 0)
--ux->target_count;
- if (target_id && (target = map->id2bl(target_id)) != NULL && (ux = unit->bl2ud(target)) != NULL)
+ if (target_id && (target = map->id2bl(target_id)) != NULL && (ux = unit->bl2ud(target)) != NULL && ux->target_count < UCHAR_MAX)
++ux->target_count;
}
diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc
index f231180d0..7139bfa6c 100644
--- a/src/plugins/HPMHooking/HPMHooking.Defs.inc
+++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc
@@ -4458,6 +4458,8 @@ typedef void (*HPMHOOK_pre_map_zone_init) (void);
typedef void (*HPMHOOK_post_map_zone_init) (void);
typedef void (*HPMHOOK_pre_map_zone_remove) (int *m);
typedef void (*HPMHOOK_post_map_zone_remove) (int m);
+typedef void (*HPMHOOK_pre_map_zone_remove_all) (int *m);
+typedef void (*HPMHOOK_post_map_zone_remove_all) (int m);
typedef void (*HPMHOOK_pre_map_zone_apply) (int *m, struct map_zone_data **zone, const char **start, const char **buffer, const char **filepath);
typedef void (*HPMHOOK_post_map_zone_apply) (int m, struct map_zone_data *zone, const char *start, const char *buffer, const char *filepath);
typedef void (*HPMHOOK_pre_map_zone_change) (int *m, struct map_zone_data **zone, const char **start, const char **buffer, const char **filepath);
@@ -7594,12 +7596,12 @@ typedef int (*HPMHOOK_pre_status_charge) (struct block_list **bl, int64 *hp, int
typedef int (*HPMHOOK_post_status_charge) (int retVal___, struct block_list *bl, int64 hp, int64 sp);
typedef int (*HPMHOOK_pre_status_percent_change) (struct block_list **src, struct block_list **target, signed char *hp_rate, signed char *sp_rate, int *flag);
typedef int (*HPMHOOK_post_status_percent_change) (int retVal___, struct block_list *src, struct block_list *target, signed char hp_rate, signed char sp_rate, int flag);
-typedef int (*HPMHOOK_pre_status_set_hp) (struct block_list **bl, unsigned int *hp, int *flag);
-typedef int (*HPMHOOK_post_status_set_hp) (int retVal___, struct block_list *bl, unsigned int hp, int flag);
-typedef int (*HPMHOOK_pre_status_set_sp) (struct block_list **bl, unsigned int *sp, int *flag);
-typedef int (*HPMHOOK_post_status_set_sp) (int retVal___, struct block_list *bl, unsigned int sp, int flag);
-typedef int (*HPMHOOK_pre_status_heal) (struct block_list **bl, int64 *hp, int64 *sp, int *flag);
-typedef int (*HPMHOOK_post_status_heal) (int retVal___, struct block_list *bl, int64 hp, int64 sp, int flag);
+typedef int (*HPMHOOK_pre_status_set_hp) (struct block_list **bl, unsigned int *hp, enum status_heal_flag *flag);
+typedef int (*HPMHOOK_post_status_set_hp) (int retVal___, struct block_list *bl, unsigned int hp, enum status_heal_flag flag);
+typedef int (*HPMHOOK_pre_status_set_sp) (struct block_list **bl, unsigned int *sp, enum status_heal_flag *flag);
+typedef int (*HPMHOOK_post_status_set_sp) (int retVal___, struct block_list *bl, unsigned int sp, enum status_heal_flag flag);
+typedef int (*HPMHOOK_pre_status_heal) (struct block_list **bl, int64 *hp, int64 *sp, enum status_heal_flag *flag);
+typedef int (*HPMHOOK_post_status_heal) (int retVal___, struct block_list *bl, int64 hp, int64 sp, enum status_heal_flag flag);
typedef int (*HPMHOOK_pre_status_revive) (struct block_list **bl, unsigned char *per_hp, unsigned char *per_sp);
typedef int (*HPMHOOK_post_status_revive) (int retVal___, struct block_list *bl, unsigned char per_hp, unsigned char per_sp);
typedef int (*HPMHOOK_pre_status_fixed_revive) (struct block_list **bl, unsigned int *per_hp, unsigned int *per_sp);
@@ -7742,6 +7744,10 @@ typedef unsigned int (*HPMHOOK_pre_status_get_base_maxhp) (const struct map_sess
typedef unsigned int (*HPMHOOK_post_status_get_base_maxhp) (unsigned int retVal___, const struct map_session_data *sd, const struct status_data *st);
typedef unsigned int (*HPMHOOK_pre_status_get_base_maxsp) (const struct map_session_data **sd, const struct status_data **st);
typedef unsigned int (*HPMHOOK_post_status_get_base_maxsp) (unsigned int retVal___, const struct map_session_data *sd, const struct status_data *st);
+typedef unsigned int (*HPMHOOK_pre_status_get_restart_hp) (const struct map_session_data **sd, const struct status_data **st);
+typedef unsigned int (*HPMHOOK_post_status_get_restart_hp) (unsigned int retVal___, const struct map_session_data *sd, const struct status_data *st);
+typedef unsigned int (*HPMHOOK_pre_status_get_restart_sp) (const struct map_session_data **sd, const struct status_data **st);
+typedef unsigned int (*HPMHOOK_post_status_get_restart_sp) (unsigned int retVal___, const struct map_session_data *sd, const struct status_data *st);
typedef int (*HPMHOOK_pre_status_calc_npc_) (struct npc_data **nd, enum e_status_calc_opt *opt);
typedef int (*HPMHOOK_post_status_calc_npc_) (int retVal___, struct npc_data *nd, enum e_status_calc_opt opt);
typedef unsigned short (*HPMHOOK_pre_status_calc_str) (struct block_list **bl, struct status_change **sc, int *str);
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
index 42c2dc3a1..b1dfbed80 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
@@ -3388,6 +3388,8 @@ struct {
struct HPMHookPoint *HP_map_zone_init_post;
struct HPMHookPoint *HP_map_zone_remove_pre;
struct HPMHookPoint *HP_map_zone_remove_post;
+ struct HPMHookPoint *HP_map_zone_remove_all_pre;
+ struct HPMHookPoint *HP_map_zone_remove_all_post;
struct HPMHookPoint *HP_map_zone_apply_pre;
struct HPMHookPoint *HP_map_zone_apply_post;
struct HPMHookPoint *HP_map_zone_change_pre;
@@ -6250,6 +6252,10 @@ struct {
struct HPMHookPoint *HP_status_get_base_maxhp_post;
struct HPMHookPoint *HP_status_get_base_maxsp_pre;
struct HPMHookPoint *HP_status_get_base_maxsp_post;
+ struct HPMHookPoint *HP_status_get_restart_hp_pre;
+ struct HPMHookPoint *HP_status_get_restart_hp_post;
+ struct HPMHookPoint *HP_status_get_restart_sp_pre;
+ struct HPMHookPoint *HP_status_get_restart_sp_post;
struct HPMHookPoint *HP_status_calc_npc__pre;
struct HPMHookPoint *HP_status_calc_npc__post;
struct HPMHookPoint *HP_status_calc_str_pre;
@@ -10001,6 +10007,8 @@ struct {
int HP_map_zone_init_post;
int HP_map_zone_remove_pre;
int HP_map_zone_remove_post;
+ int HP_map_zone_remove_all_pre;
+ int HP_map_zone_remove_all_post;
int HP_map_zone_apply_pre;
int HP_map_zone_apply_post;
int HP_map_zone_change_pre;
@@ -12863,6 +12871,10 @@ struct {
int HP_status_get_base_maxhp_post;
int HP_status_get_base_maxsp_pre;
int HP_status_get_base_maxsp_post;
+ int HP_status_get_restart_hp_pre;
+ int HP_status_get_restart_hp_post;
+ int HP_status_get_restart_sp_pre;
+ int HP_status_get_restart_sp_post;
int HP_status_calc_npc__pre;
int HP_status_calc_npc__post;
int HP_status_calc_str_pre;
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
index 092a9831b..378eb77eb 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
@@ -1737,6 +1737,7 @@ struct HookingPointData HookingPoints[] = {
/* map_interface */
{ HP_POP(map->zone_init, HP_map_zone_init) },
{ HP_POP(map->zone_remove, HP_map_zone_remove) },
+ { HP_POP(map->zone_remove_all, HP_map_zone_remove_all) },
{ HP_POP(map->zone_apply, HP_map_zone_apply) },
{ HP_POP(map->zone_change, HP_map_zone_change) },
{ HP_POP(map->zone_change2, HP_map_zone_change2) },
@@ -3195,6 +3196,8 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(status->base_atk, HP_status_base_atk) },
{ HP_POP(status->get_base_maxhp, HP_status_get_base_maxhp) },
{ HP_POP(status->get_base_maxsp, HP_status_get_base_maxsp) },
+ { HP_POP(status->get_restart_hp, HP_status_get_restart_hp) },
+ { HP_POP(status->get_restart_sp, HP_status_get_restart_sp) },
{ HP_POP(status->calc_npc_, HP_status_calc_npc_) },
{ HP_POP(status->calc_str, HP_status_calc_str) },
{ HP_POP(status->calc_agi, HP_status_calc_agi) },
diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index ea53227bf..db191064c 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -44624,6 +44624,32 @@ void HP_map_zone_remove(int m) {
}
return;
}
+void HP_map_zone_remove_all(int m) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_map_zone_remove_all_pre > 0) {
+ void (*preHookFunc) (int *m);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_map_zone_remove_all_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_map_zone_remove_all_pre[hIndex].func;
+ preHookFunc(&m);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.map.zone_remove_all(m);
+ }
+ if (HPMHooks.count.HP_map_zone_remove_all_post > 0) {
+ void (*postHookFunc) (int m);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_map_zone_remove_all_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_map_zone_remove_all_post[hIndex].func;
+ postHookFunc(m);
+ }
+ }
+ return;
+}
void HP_map_zone_apply(int m, struct map_zone_data *zone, const char *start, const char *buffer, const char *filepath) {
int hIndex = 0;
if (HPMHooks.count.HP_map_zone_apply_pre > 0) {
@@ -81645,11 +81671,11 @@ int HP_status_percent_change(struct block_list *src, struct block_list *target,
}
return retVal___;
}
-int HP_status_set_hp(struct block_list *bl, unsigned int hp, int flag) {
+int HP_status_set_hp(struct block_list *bl, unsigned int hp, enum status_heal_flag flag) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_status_set_hp_pre > 0) {
- int (*preHookFunc) (struct block_list **bl, unsigned int *hp, int *flag);
+ int (*preHookFunc) (struct block_list **bl, unsigned int *hp, enum status_heal_flag *flag);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_status_set_hp_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_status_set_hp_pre[hIndex].func;
@@ -81664,7 +81690,7 @@ int HP_status_set_hp(struct block_list *bl, unsigned int hp, int flag) {
retVal___ = HPMHooks.source.status.set_hp(bl, hp, flag);
}
if (HPMHooks.count.HP_status_set_hp_post > 0) {
- int (*postHookFunc) (int retVal___, struct block_list *bl, unsigned int hp, int flag);
+ int (*postHookFunc) (int retVal___, struct block_list *bl, unsigned int hp, enum status_heal_flag flag);
for (hIndex = 0; hIndex < HPMHooks.count.HP_status_set_hp_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_status_set_hp_post[hIndex].func;
retVal___ = postHookFunc(retVal___, bl, hp, flag);
@@ -81672,11 +81698,11 @@ int HP_status_set_hp(struct block_list *bl, unsigned int hp, int flag) {
}
return retVal___;
}
-int HP_status_set_sp(struct block_list *bl, unsigned int sp, int flag) {
+int HP_status_set_sp(struct block_list *bl, unsigned int sp, enum status_heal_flag flag) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_status_set_sp_pre > 0) {
- int (*preHookFunc) (struct block_list **bl, unsigned int *sp, int *flag);
+ int (*preHookFunc) (struct block_list **bl, unsigned int *sp, enum status_heal_flag *flag);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_status_set_sp_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_status_set_sp_pre[hIndex].func;
@@ -81691,7 +81717,7 @@ int HP_status_set_sp(struct block_list *bl, unsigned int sp, int flag) {
retVal___ = HPMHooks.source.status.set_sp(bl, sp, flag);
}
if (HPMHooks.count.HP_status_set_sp_post > 0) {
- int (*postHookFunc) (int retVal___, struct block_list *bl, unsigned int sp, int flag);
+ int (*postHookFunc) (int retVal___, struct block_list *bl, unsigned int sp, enum status_heal_flag flag);
for (hIndex = 0; hIndex < HPMHooks.count.HP_status_set_sp_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_status_set_sp_post[hIndex].func;
retVal___ = postHookFunc(retVal___, bl, sp, flag);
@@ -81699,11 +81725,11 @@ int HP_status_set_sp(struct block_list *bl, unsigned int sp, int flag) {
}
return retVal___;
}
-int HP_status_heal(struct block_list *bl, int64 hp, int64 sp, int flag) {
+int HP_status_heal(struct block_list *bl, int64 hp, int64 sp, enum status_heal_flag flag) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_status_heal_pre > 0) {
- int (*preHookFunc) (struct block_list **bl, int64 *hp, int64 *sp, int *flag);
+ int (*preHookFunc) (struct block_list **bl, int64 *hp, int64 *sp, enum status_heal_flag *flag);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_status_heal_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_status_heal_pre[hIndex].func;
@@ -81718,7 +81744,7 @@ int HP_status_heal(struct block_list *bl, int64 hp, int64 sp, int flag) {
retVal___ = HPMHooks.source.status.heal(bl, hp, sp, flag);
}
if (HPMHooks.count.HP_status_heal_post > 0) {
- int (*postHookFunc) (int retVal___, struct block_list *bl, int64 hp, int64 sp, int flag);
+ int (*postHookFunc) (int retVal___, struct block_list *bl, int64 hp, int64 sp, enum status_heal_flag flag);
for (hIndex = 0; hIndex < HPMHooks.count.HP_status_heal_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_status_heal_post[hIndex].func;
retVal___ = postHookFunc(retVal___, bl, hp, sp, flag);
@@ -83636,6 +83662,60 @@ unsigned int HP_status_get_base_maxsp(const struct map_session_data *sd, const s
}
return retVal___;
}
+unsigned int HP_status_get_restart_hp(const struct map_session_data *sd, const struct status_data *st) {
+ int hIndex = 0;
+ unsigned int retVal___ = 0;
+ if (HPMHooks.count.HP_status_get_restart_hp_pre > 0) {
+ unsigned int (*preHookFunc) (const struct map_session_data **sd, const struct status_data **st);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_status_get_restart_hp_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_status_get_restart_hp_pre[hIndex].func;
+ retVal___ = preHookFunc(&sd, &st);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.status.get_restart_hp(sd, st);
+ }
+ if (HPMHooks.count.HP_status_get_restart_hp_post > 0) {
+ unsigned int (*postHookFunc) (unsigned int retVal___, const struct map_session_data *sd, const struct status_data *st);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_status_get_restart_hp_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_status_get_restart_hp_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, sd, st);
+ }
+ }
+ return retVal___;
+}
+unsigned int HP_status_get_restart_sp(const struct map_session_data *sd, const struct status_data *st) {
+ int hIndex = 0;
+ unsigned int retVal___ = 0;
+ if (HPMHooks.count.HP_status_get_restart_sp_pre > 0) {
+ unsigned int (*preHookFunc) (const struct map_session_data **sd, const struct status_data **st);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_status_get_restart_sp_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_status_get_restart_sp_pre[hIndex].func;
+ retVal___ = preHookFunc(&sd, &st);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.status.get_restart_sp(sd, st);
+ }
+ if (HPMHooks.count.HP_status_get_restart_sp_post > 0) {
+ unsigned int (*postHookFunc) (unsigned int retVal___, const struct map_session_data *sd, const struct status_data *st);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_status_get_restart_sp_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_status_get_restart_sp_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, sd, st);
+ }
+ }
+ return retVal___;
+}
int HP_status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) {
int hIndex = 0;
int retVal___ = 0;