From abf1b2697df06e95291014f7637cc0df6f5a10b1 Mon Sep 17 00:00:00 2001
From: gumi <git@gumi.ca>
Date: Tue, 18 Dec 2018 13:57:40 -0500
Subject: add player heal packets

---
 CHANGELOG         |  2 ++
 src/map/clif.cpp  | 25 +++++++++++++++++++++++++
 src/map/clif.hpp  |  2 ++
 src/map/pc.cpp    | 29 ++++++++++++++++++++++++++---
 src/map/pc.hpp    |  1 +
 tools/protocol.py | 29 +++++++++++++++++++++++++++++
 6 files changed, 85 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 8af6529..6bbac82 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,5 @@
+v18.12.18
+  - add packets that tell ManaPlus to update player HP
 v18.12.13
   - add support for sending player HP to manaplus
 v18.11.11
diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index 95e4ef2..f2667ac 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -4121,6 +4121,31 @@ void clif_send_mask(dumb_ptr<map_session_data> sd, int map_mask)
     clif_send(buf, sd, SendWho::SELF, wrap<ClientVersion>(2));
 }
 
+void clif_send_hp_partial(dumb_ptr<map_session_data> sd)
+{
+    nullpo_retv(sd);
+
+    Packet_Fixed<0x0232> fixed_232;
+    fixed_232.account_id = sd->status_key.account_id;
+    fixed_232.hp = sd->status.hp;
+
+    Buffer buf = create_fpacket<0x0232, 10>(fixed_232);
+    clif_send(buf, sd, SendWho::AREA_WOS, wrap<ClientVersion>(9));
+}
+
+void clif_send_hp_full(dumb_ptr<map_session_data> sd)
+{
+    nullpo_retv(sd);
+
+    Packet_Fixed<0x0233> fixed_233;
+    fixed_233.account_id = sd->status_key.account_id;
+    fixed_233.hp = sd->status.hp;
+    fixed_233.max_hp = sd->status.max_hp;
+
+    Buffer buf = create_fpacket<0x0233, 14>(fixed_233);
+    clif_send(buf, sd, SendWho::AREA_WOS, wrap<ClientVersion>(9));
+}
+
 /*==========================================
  *
  *------------------------------------------
diff --git a/src/map/clif.hpp b/src/map/clif.hpp
index 1d6365d..1abcfe3 100644
--- a/src/map/clif.hpp
+++ b/src/map/clif.hpp
@@ -111,6 +111,8 @@ void clif_update_collision(dumb_ptr<map_session_data>, short, short, short, shor
 void clif_change_music(dumb_ptr<map_session_data> sd, XString music);
 void clif_npc_action(dumb_ptr<map_session_data>, BlockId, short, int, short, short);
 void clif_send_mask(dumb_ptr<map_session_data>, int);
+void clif_send_hp_partial(dumb_ptr<map_session_data>);
+void clif_send_hp_full(dumb_ptr<map_session_data>);
 
 // trade
 void clif_traderequest(dumb_ptr<map_session_data> sd, CharName name);
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index e4c3907..3986113 100644
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -2802,7 +2802,7 @@ int pc_checkbaselevelup(dumb_ptr<map_session_data> sd)
         clif_updatestatus(sd, SP::BASELEVEL);
         clif_updatestatus(sd, SP::NEXTBASEEXP);
         pc_calcstatus(sd, 0);
-        pc_heal(sd, sd->status.max_hp, sd->status.max_sp);
+        pc_heal(sd, sd->status.max_hp, sd->status.max_sp, true);
 
         clif_misceffect(sd, 0);
         //レベルアップしたのでパーティー情報を更新する
@@ -3618,7 +3618,7 @@ int pc_setparam(dumb_ptr<block_list> bl, SP type, int val)
             clif_updatestatus(sd, SP::STATUSPOINT);
             clif_updatestatus(sd, SP::BASEEXP);
             pc_calcstatus(sd, 0);
-            pc_heal(sd, sd->status.max_hp, sd->status.max_sp);
+            pc_heal(sd, sd->status.max_hp, sd->status.max_sp, true);
             break;
         case SP::JOBLEVEL:
             nullpo_retz(sd);
@@ -3825,7 +3825,7 @@ int pc_setparam(dumb_ptr<block_list> bl, SP type, int val)
  * HP/SP回復
  *------------------------------------------
  */
-int pc_heal(dumb_ptr<map_session_data> sd, int hp, int sp)
+int pc_heal(dumb_ptr<map_session_data> sd, int hp, int sp, bool levelup)
 {
     nullpo_retz(sd);
 
@@ -3855,7 +3855,16 @@ int pc_heal(dumb_ptr<map_session_data> sd, int hp, int sp)
     if (sd->status.sp <= 0)
         sd->status.sp = 0;
     if (hp)
+    {
         clif_updatestatus(sd, SP::HP);
+
+        if (hp > 0 && levelup) {
+            clif_send_hp_full(sd);
+        } else if (hp > 0) {
+            clif_send_hp_partial(sd);
+        }
+    }
+
     if (sp)
         clif_updatestatus(sd, SP::SP);
 
@@ -3871,6 +3880,10 @@ int pc_heal(dumb_ptr<map_session_data> sd, int hp, int sp)
 
     return hp + sp;
 }
+int pc_heal(dumb_ptr<map_session_data> sd, int hp, int sp)
+{
+    return pc_heal(sd, hp, sp, false);
+}
 
 /*==========================================
  * HP/SP回復
@@ -3986,7 +3999,14 @@ int pc_itemheal_effect(dumb_ptr<map_session_data> sd, int hp, int sp)
     if (sd->status.sp <= 0)
         sd->status.sp = 0;
     if (hp)
+    {
         clif_updatestatus(sd, SP::HP);
+
+        if (hp > 0) {
+            clif_send_hp_partial(sd);
+        }
+    }
+
     if (sp)
         clif_updatestatus(sd, SP::SP);
 
@@ -4959,7 +4979,10 @@ int pc_natural_heal_hp(dumb_ptr<map_session_data> sd)
         }
     }
     if (bhp != sd->status.hp)
+    {
         clif_updatestatus(sd, SP::HP);
+        clif_send_hp_partial(sd);
+    }
 
     sd->inchealhptick = interval_t::zero();
 
diff --git a/src/map/pc.hpp b/src/map/pc.hpp
index 2e63c26..4019617 100644
--- a/src/map/pc.hpp
+++ b/src/map/pc.hpp
@@ -139,6 +139,7 @@ int pc_useitem(dumb_ptr<map_session_data>, IOff0);
 
 int pc_damage(dumb_ptr<block_list>, dumb_ptr<map_session_data>, int);
 int pc_heal(dumb_ptr<map_session_data>, int, int);
+int pc_heal(dumb_ptr<map_session_data>, int, int, bool);
 int pc_itemheal(dumb_ptr<map_session_data> sd, int hp, int sp);
 int pc_changelook(dumb_ptr<map_session_data>, LOOK, int);
 
diff --git a/tools/protocol.py b/tools/protocol.py
index 3a0e25e..12f8ead 100755
--- a/tools/protocol.py
+++ b/tools/protocol.py
@@ -4849,6 +4849,35 @@ def build_context():
             Set updated collision for a square area
         ''',
     )
+    map_user.s(0x0232, 'send hp update',
+        define='SMSG_PLAYER_HP',
+        fixed=[
+            at(0, u16, 'packet id'),
+            at(2, account_id, 'account id'),
+            at(6, u32, 'hp'),
+        ],
+        fixed_size=10,
+        pre=[NOTHING],
+        post=[PRETTY],
+        desc='''
+            Send part of hp info
+        ''',
+    )
+    map_user.s(0x0233, 'send full hp',
+        define='SMSG_PLAYER_HP_FULL',
+        fixed=[
+            at(0, u16, 'packet id'),
+            at(2, account_id, 'account id'),
+            at(6, u32, 'hp'),
+            at(10, u32, 'max hp'),
+        ],
+        fixed_size=14,
+        pre=[NOTHING],
+        post=[PRETTY],
+        desc='''
+            Send both hp and max hp
+        ''',
+    )
 
 
     # TOC_LOGINCHAR
-- 
cgit v1.2.3-70-g09d2