Explorar o código

Merge branch 'master' into feature/map_zones

Aleos hai 1 ano
pai
achega
b43cd4ced1
Modificáronse 50 ficheiros con 1422 adicións e 1012 borrados
  1. 1 1
      .github/workflows/build_servers_gcc.yml
  2. 1 2
      conf/battle/exp.conf
  3. 9 4
      conf/battle/monster.conf
  4. 282 1
      db/pre-re/mob_db.yml
  5. 39 39
      db/pre-re/mob_skill_db.txt
  6. 13 19
      db/pre-re/skill_db.yml
  7. 1 13
      db/pre-re/status.yml
  8. 3 8
      db/re/item_db_equip.yml
  9. 2 1
      db/re/item_db_usable.yml
  10. 3 3
      db/re/mob_db.yml
  11. 51 51
      db/re/mob_skill_db.txt
  12. 14 19
      db/re/skill_db.yml
  13. 1 13
      db/re/status.yml
  14. 2 2
      doc/permissions.txt
  15. 1 1
      doc/yaml/db/license.yml
  16. 5 5
      npc/re/merchants/ammo_boxes.txt
  17. 4 2
      src/char/char.cpp
  18. 65 22
      src/char/char_logif.cpp
  19. 1 1
      src/common/database.hpp
  20. 1 2
      src/common/utilities.hpp
  21. 154 67
      src/map/battle.cpp
  22. 7 3
      src/map/battle.hpp
  23. 1 1
      src/map/battleground.cpp
  24. 1 1
      src/map/battleground.hpp
  25. 244 260
      src/map/clif.cpp
  26. 11 11
      src/map/clif.hpp
  27. 5 8
      src/map/clif_packetdb.hpp
  28. 14 5
      src/map/elemental.cpp
  29. 1 1
      src/map/elemental.hpp
  30. 8 19
      src/map/guild.cpp
  31. 3 3
      src/map/guild.hpp
  32. 6 6
      src/map/intif.cpp
  33. 3 3
      src/map/intif.hpp
  34. 33 21
      src/map/mob.cpp
  35. 1 1
      src/map/mob.hpp
  36. 3 3
      src/map/npc.cpp
  37. 44 0
      src/map/packets.hpp
  38. 1 1
      src/map/party.cpp
  39. 1 1
      src/map/party.hpp
  40. 3 3
      src/map/pc.cpp
  41. 1 1
      src/map/script.cpp
  42. 1 1
      src/map/script_constants.hpp
  43. 222 233
      src/map/skill.cpp
  44. 10 10
      src/map/skill.hpp
  45. 80 70
      src/map/status.cpp
  46. 2 2
      src/map/status.hpp
  47. 4 4
      src/map/unit.cpp
  48. 48 56
      src/map/vending.cpp
  49. 2 2
      src/map/vending.hpp
  50. 9 6
      src/tool/csv2yaml.cpp

+ 1 - 1
.github/workflows/build_servers_gcc.yml

@@ -31,7 +31,7 @@ jobs:
           # Available: ubuntu-22.04, ubuntu-20.04
           os: [ubuntu-latest]
           # Older versions of GCC are not available via unaltered aptitude repo lists.
-          gcc: ['9', '10', '11']
+          gcc: ['9', '10', '11', '12', '13']
 
     steps:
       - uses: actions/checkout@v2

+ 1 - 2
conf/battle/exp.conf

@@ -33,8 +33,7 @@ max_exp_gain_rate: 0
 // Method of calculating earned experience when defeating a monster:
 // 0 = uses damage given / total damage as damage ratio
 // 1 = uses damage given / max_hp as damage ratio
-// NOTE: Using type 1 disables the bonus where the first attacker gets 
-//       his share of the exp doubled when multiple people attack the mob.
+// 2 = 0 + first attacker counts twice
 exp_calc_type: 0
 
 // Experience increase per attacker. That is, every additional attacker to the

+ 9 - 4
conf/battle/monster.conf

@@ -79,10 +79,10 @@ monster_chase_refresh: 30
 // 8: Enable mob-warping when standing on Dimensional Door
 mob_warp: 0
 
-// If these are set above 0, they define the time (in ms) during which monsters
-// will have their 'AI' active after all players have left their vicinity.
-mob_active_time: 0
-boss_active_time: 0
+// Defines the time (in ms) during which monsters will have their AI active
+// after all players have left their vicinity.
+mob_active_time: 5000
+boss_active_time: 5000
 
 // Mobs and Pets view-range adjustment (range2 column in the mob_db) (Note 2)
 view_range_rate: 100
@@ -302,3 +302,8 @@ slave_stick_with_master: no
 // Also used in delaying the spawning of guardians when a guild is not loaded.
 // Default (Official): 1000
 mob_respawn_time: 1000
+
+// Defines the time (in ms) after which a monster unlocks its target when trapped.
+// During this time monsters will still be in idle mode and use idle skills on random
+// targets, but they continue chasing their original target when no longer trapped.
+mob_unlock_time: 2000

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 282 - 1
db/pre-re/mob_db.yml


+ 39 - 39
db/pre-re/mob_skill_db.txt

@@ -102,7 +102,7 @@
 1019,Peco Peco@NPC_EMOTION,chase,197,1,2000,0,5000,yes,self,always,0,6,,,,,,
 1019,Peco Peco@NPC_FIREATTACK,attack,186,1,2000,0,5000,yes,target,always,0,,,,,,,
 1019,Peco Peco@NPC_PROVOCATION,chase,194,1,200,0,5000,yes,target,always,0,,,,,,19,
-1020,Mandragora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,randomtarget,always,0,,,,,,,
+1020,Mandragora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,target,always,0,,,,,,,
 1023,Orc Warrior@NPC_EMOTION,chase,197,1,2000,0,5000,yes,self,always,0,,,,,,,
 1023,Orc Warrior@NPC_GROUNDATTACK,attack,185,2,500,500,5000,no,target,always,0,,,,,,6,
 1023,Orc Warrior@NPC_EMOTION,chase,197,1,200,0,5000,yes,self,always,0,19,0x81,,,,,
@@ -349,7 +349,7 @@
 1067,Cornutus@NPC_WATERATTACK,attack,184,2,500,500,5000,no,target,always,0,,,,,,6,
 1067,Cornutus@CR_AUTOGUARD,attack,249,2,500,0,300000,yes,self,always,0,,,,,,,
 1067,Cornutus@CR_AUTOGUARD,chase,249,2,2000,0,300000,yes,self,longrangeattacked,,,,,,,,
-1068,Hydra@NPC_WATERATTACK,attack,184,2,500,500,5000,no,randomtarget,always,0,,,,,,,
+1068,Hydra@NPC_WATERATTACK,attack,184,2,500,500,5000,no,target,always,0,,,,,,,
 1069,Swordfish@NPC_WATERATTACK,attack,184,1,2000,0,5000,yes,target,always,0,,,,,,,
 1069,Swordfish@WZ_WATERBALL,attack,86,3,500,1500,5000,yes,target,always,0,,,,,,,
 1069,Swordfish@WZ_WATERBALL,chase,86,3,500,1500,5000,yes,target,always,0,,,,,,,
@@ -601,9 +601,9 @@
 1117,Evil Druid@NPC_UNDEADATTACK,chase,347,3,500,500,5000,no,target,always,0,,,,,,9,
 1117,Evil Druid@WZ_HEAVENDRIVE,attack,91,5,500,1200,5000,yes,target,always,0,,,,,,,
 1117,Evil Druid@WZ_HEAVENDRIVE,chase,91,5,500,1200,5000,yes,target,always,0,,,,,,,
-1118,Flora@NPC_BLOODDRAIN,attack,199,1,500,0,5000,yes,randomtarget,always,0,,,,,,,
+1118,Flora@NPC_BLOODDRAIN,attack,199,1,500,0,5000,yes,target,always,0,,,,,,,
 1118,Flora@NPC_EMOTION,idle,197,1,2000,0,5000,yes,self,always,0,2,,,,,,
-1118,Flora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,randomtarget,always,0,,,,,,,
+1118,Flora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,target,always,0,,,,,,,
 1119,Frilldora@AS_CLOAKING,attack,135,1,2000,200,5000,yes,self,always,0,,,,,,,
 1119,Frilldora@AS_CLOAKING,idle,135,1,2000,200,5000,yes,self,always,0,,,,,,,
 1119,Frilldora@AS_CLOAKING,chase,135,1,2000,200,5000,yes,self,always,0,,,,,,,
@@ -1297,7 +1297,7 @@
 1276,Raydric Archer@CR_AUTOGUARD,attack,249,2,500,0,300000,yes,self,always,0,,,,,,,
 1277,Greatest General@NPC_BLINDATTACK,idle,177,3,10000,1500,5000,no,randomtarget,longrangeattacked,,,,,,,6,
 1277,Greatest General@NPC_BLINDATTACK,idle,177,3,10000,1500,5000,no,randomtarget,casttargeted,,,,,,,6,
-1277,Greatest General@NPC_FIREATTACK,attack,186,2,500,500,5000,no,randomtarget,always,0,,,,,,,
+1277,Greatest General@NPC_FIREATTACK,attack,186,2,500,500,5000,no,target,always,0,,,,,,,
 1277,Greatest General@WZ_EARTHSPIKE,idle,90,3,5000,1500,5000,no,randomtarget,longrangeattacked,,,,,,,6,
 1277,Greatest General@WZ_EARTHSPIKE,idle,90,3,5000,1500,5000,no,randomtarget,casttargeted,,,,,,,6,
 1278,Stalactite Golem@NPC_STUNATTACK,attack,179,4,500,1500,5000,no,target,always,0,,,,,,6,
@@ -1580,7 +1580,7 @@
 1367,Blazer@WZ_SIGHTRASHER,attack,81,5,500,1000,5000,no,target,always,0,,,,,,6,
 1368,Geographer@AL_HEAL,attack,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,60,,,,,,,
 1368,Geographer@AL_HEAL,idle,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,60,,,,,,,
-1368,Geographer@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,randomtarget,always,0,,,,,,,
+1368,Geographer@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,target,always,0,,,,,,,
 1369,Grand Peco@AS_SONICBLOW,attack,136,5,500,800,5000,no,target,always,0,,,,,,6,
 1369,Grand Peco@NPC_FIREATTACK,attack,186,3,500,500,5000,no,target,always,0,,,,,,6,
 1369,Grand Peco@NPC_EMOTION,chase,197,1,200,0,5000,yes,self,always,0,19,0x81,,,,,
@@ -2563,8 +2563,8 @@
 1510,Hylozoist@MO_BODYRELOCATION,chase,264,1,2000,500,5000,no,target,always,0,,,,,,,
 1511,Amon Ra@NPC_BLOODDRAIN,idle,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
 1511,Amon Ra@NPC_BLOODDRAIN,idle,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
-1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
-1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
+1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,always,0,,,,,,29,
+1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,always,0,,,,,,29,
 1511,Amon Ra@NPC_SUMMONMONSTER,idle,209,5,5000,0,10000,no,self,longrangeattacked,0,1474,1477,1438,,,9,
 1511,Amon Ra@NPC_SUMMONMONSTER,idle,209,5,5000,0,10000,no,self,casttargeted,0,1474,1477,1438,,,9,
 1511,Amon Ra@NPC_SUMMONMONSTER,attack,209,5,5000,0,10000,no,self,longrangeattacked,0,1474,1477,1438,,,9,
@@ -2583,11 +2583,11 @@
 1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,skillused,83,,,,,,9,
 1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,longrangeattacked,,,,,,,9,
 1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,casttargeted,,,,,,,9,
-1511,Amon Ra@WZ_METEOR,attack,83,11,5000,0,3000,yes,randomtarget,always,0,,,,,,9,
+1511,Amon Ra@WZ_METEOR,attack,83,11,5000,0,3000,yes,target,always,0,,,,,,9,
 1511,Amon Ra@WZ_FIREPILLAR,idle,80,10,10000,0,2000,yes,around2,always,0,,,,,,,
 1511,Amon Ra@WZ_FIREPILLAR,idle,80,10,10000,0,2000,yes,around2,always,0,,,,,,,
 1511,Amon Ra@WZ_FIREPILLAR,attack,80,10,5000,0,2000,yes,around2,always,0,,,,,,,
-1511,Amon Ra@NPC_DARKBLESSING,attack,203,1,5000,0,2000,no,randomtarget,always,0,,,,,,,
+1511,Amon Ra@NPC_DARKBLESSING,attack,203,1,5000,0,2000,no,target,always,0,,,,,,,
 1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,5000,yes,randomtarget,always,0,,,,,,9,
 1511,Amon Ra@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
 1511,Amon Ra@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
@@ -3398,18 +3398,18 @@
 1663,Laurell Weinder@NPC_EMOTION,idle,197,1,10000,0,5000,yes,self,skillused,28,15,,,,,,
 1663,Laurell Weinder@NPC_EMOTION,attack,197,1,10000,0,5000,yes,self,skillused,28,15,,,,,,
 1663,Laurell Weinder@NPC_EMOTION,chase,197,1,10000,0,5000,yes,self,skillused,28,15,,,,,,
-1664,Photon Cannon@NPC_WINDATTACK,attack,187,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
-1664,Photon Cannon@NPC_WINDATTACK,attack,187,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
-1664,Photon Cannon@NPC_WINDATTACK,attack,187,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
-1665,Photon Cannon@NPC_FIREATTACK,attack,186,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
-1665,Photon Cannon@NPC_FIREATTACK,attack,186,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
-1665,Photon Cannon@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
-1666,Photon Cannon@NPC_WATERATTACK,attack,184,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
-1666,Photon Cannon@NPC_WATERATTACK,attack,184,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
-1666,Photon Cannon@NPC_WATERATTACK,attack,184,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
-1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
-1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
-1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
+1664,Photon Cannon@NPC_WINDATTACK,attack,187,5,1000,1000,10000,yes,target,always,0,,,,,,,
+1664,Photon Cannon@NPC_WINDATTACK,attack,187,3,2000,500,5000,yes,target,always,0,,,,,,,
+1664,Photon Cannon@NPC_WINDATTACK,attack,187,1,10000,0,0,yes,target,always,0,,,,,,,
+1665,Photon Cannon@NPC_FIREATTACK,attack,186,5,1000,1000,10000,yes,target,always,0,,,,,,,
+1665,Photon Cannon@NPC_FIREATTACK,attack,186,3,2000,500,5000,yes,target,always,0,,,,,,,
+1665,Photon Cannon@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,target,always,0,,,,,,,
+1666,Photon Cannon@NPC_WATERATTACK,attack,184,5,1000,1000,10000,yes,target,always,0,,,,,,,
+1666,Photon Cannon@NPC_WATERATTACK,attack,184,3,2000,500,5000,yes,target,always,0,,,,,,,
+1666,Photon Cannon@NPC_WATERATTACK,attack,184,1,10000,0,0,yes,target,always,0,,,,,,,
+1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,5,1000,1000,10000,yes,target,always,0,,,,,,,
+1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,3,2000,500,5000,yes,target,always,0,,,,,,,
+1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,1,10000,0,0,yes,target,always,0,,,,,,,
 1668,Archdam@NPC_PIERCINGATT,attack,158,5,1000,0,5000,yes,target,always,0,,,,,,,
 1668,Archdam@NPC_GUIDEDATTACK,attack,172,2,500,1000,20000,no,target,always,0,,,,,,29,
 1668,Archdam@KN_SPEARSTAB,attack,58,5,500,800,5000,no,target,always,0,,,,,,,
@@ -3446,9 +3446,9 @@
 1673,Dimik@NPC_COMBOATTACK,attack,171,4,500,700,5000,no,target,always,0,,,,,,,
 1673,Dimik@NPC_COMBOATTACK,chase,171,4,500,700,5000,no,target,always,0,,,,,,,
 1673,Dimik@NPC_FIREATTACK,attack,186,3,500,0,5000,yes,target,always,0,,,,,,,
-1674,Monemus@NPC_FIREATTACK,attack,186,10,500,1000,30000,yes,randomtarget,always,0,,,,,,,
-1674,Monemus@NPC_FIREATTACK,attack,186,3,1000,0,10000,yes,randomtarget,always,0,,,,,,,
-1674,Monemus@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
+1674,Monemus@NPC_FIREATTACK,attack,186,10,500,1000,30000,yes,target,always,0,,,,,,,
+1674,Monemus@NPC_FIREATTACK,attack,186,3,1000,0,10000,yes,target,always,0,,,,,,,
+1674,Monemus@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,target,always,0,,,,,,,
 1675,Venatu@NPC_SILENCEATTACK,attack,178,3,500,700,5000,no,target,always,0,,,,,,,
 1675,Venatu@NPC_GUIDEDATTACK,attack,172,3,500,1000,20000,no,target,always,0,,,,,,6,
 1675,Venatu@NPC_STUNATTACK,attack,179,2,500,1500,5000,no,target,always,0,,,,,,11,
@@ -3524,11 +3524,11 @@
 1688,Lady Tany@AL_TELEPORT,idle,26,1,1000,0,30000,yes,self,always,0,,,,,,,
 1688,Lady Tany@AL_TELEPORT,attack,26,1,1000,0,30000,yes,self,always,0,,,,,,,
 1688,Lady Tany@NPC_EXPULSION,attack,674,1,1000,1000,10000,no,target,myhpltmaxrate,60,,,,,,,
-1688,Lady Tany@AC_CHARGEARROW,attack,148,1,2000,0,5000,yes,randomtarget,always,0,,,,,,6,
-1688,Lady Tany@NPC_COMBOATTACK,attack,171,1,1000,0,5000,no,randomtarget,always,0,,,,,,,
-1688,Lady Tany@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,randomtarget,always,0,,,,,,6,
-1688,Lady Tany@NPC_GUIDEDATTACK,attack,172,5,500,0,20000,no,randomtarget,always,0,,,,,,,
-1688,Lady Tany@NPC_STUNATTACK,attack,179,5,500,0,5000,no,randomtarget,always,0,,,,,,,
+1688,Lady Tany@AC_CHARGEARROW,attack,148,1,2000,0,5000,yes,target,always,0,,,,,,6,
+1688,Lady Tany@NPC_COMBOATTACK,attack,171,1,1000,0,5000,no,target,always,0,,,,,,,
+1688,Lady Tany@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,target,always,0,,,,,,6,
+1688,Lady Tany@NPC_GUIDEDATTACK,attack,172,5,500,0,20000,no,target,always,0,,,,,,,
+1688,Lady Tany@NPC_STUNATTACK,attack,179,5,500,0,5000,no,target,always,0,,,,,,,
 1688,Lady Tany@NPC_DEFENDER,attack,205,1,500,0,30000,yes,self,longrangeattacked,,,,,,,29,
 1688,Lady Tany@NPC_POWERUP,attack,349,5,10000,0,30000,yes,self,myhpltmaxrate,30,,,,,,6,
 1688,Lady Tany@NPC_SUMMONSLAVE,attack,196,5,10000,2000,5000,no,self,slavele,2,1691,,,,,,
@@ -4220,18 +4220,18 @@
 1779,Ktullanux@NPC_AGIUP,attack,350,5,2000,0,100000,yes,self,always,0,,,,,,,
 1779,Ktullanux@NPC_AGIUP,attack,350,5,10000,0,25000,yes,self,myhpltmaxrate,30,,,,,,,
 1779,Ktullanux@AL_HEAL,idle,28,11,10000,0,10000,yes,self,myhpltmaxrate,50,,,,,,,
-1780,Muscipular@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
-1780,Muscipular@KN_SPEARSTAB,attack,58,5,500,800,5000,no,randomtarget,always,0,,,,,,6,
-1780,Muscipular@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
+1780,Muscipular@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,target,always,0,,,,,,,
+1780,Muscipular@KN_SPEARSTAB,attack,58,5,500,800,5000,no,target,always,0,,,,,,6,
+1780,Muscipular@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,target,always,0,,,,,,,
 1780,Muscipular@AL_HEAL,attack,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,50,,,,,,,
 1780,Muscipular@AL_HEAL,idle,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,50,,,,,,,
-1780,Muscipular@NPC_PETRIFYATTACK,attack,180,5,500,0,5000,yes,randomtarget,always,0,,,,,,,
-1781,Drosera@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
-1781,Drosera@KN_PIERCE,attack,56,5,500,700,5000,no,randomtarget,always,0,,,,,,,
-1781,Drosera@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
+1780,Muscipular@NPC_PETRIFYATTACK,attack,180,5,500,0,5000,yes,target,always,0,,,,,,,
+1781,Drosera@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,target,always,0,,,,,,,
+1781,Drosera@KN_PIERCE,attack,56,5,500,700,5000,no,target,always,0,,,,,,,
+1781,Drosera@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,target,always,0,,,,,,,
 1781,Drosera@RG_CLOSECONFINE,attack,1005,1,1000,0,30000,yes,target,always,0,,,,,,,
-1781,Drosera@NPC_GUIDEDATTACK,attack,172,3,500,1000,20000,no,randomtarget,always,0,,,,,,6,
-1781,Drosera@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,randomtarget,always,0,,,,,,,
+1781,Drosera@NPC_GUIDEDATTACK,attack,172,3,500,1000,20000,no,target,always,0,,,,,,6,
+1781,Drosera@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,target,always,0,,,,,,,
 1782,Roween@NPC_WINDATTACK,attack,187,2,500,500,5000,no,target,always,0,,,,,,,
 1782,Roween@NPC_COMBOATTACK,attack,171,4,500,500,5000,no,target,always,0,,,,,,6,
 1782,Roween@NPC_EMOTION,idle,197,1,2000,0,5000,yes,self,always,0,22,0x308D,,,,,

+ 13 - 19
db/pre-re/skill_db.yml

@@ -4153,7 +4153,6 @@ Body:
         Time: 120000
       - Level: 5
         Time: 60000
-    Duration2: 3000
     Requires:
       SpCost: 10
       ItemCost:
@@ -6888,12 +6887,9 @@ Body:
     MaxLevel: 10
     Type: Magic
     TargetType: Self
-    DamageFlags:
-      IgnoreAtkCard: true
-      IgnoreFlee: true
     Flags:
       TargetSelf: true
-    Range: 5
+    Range: 9
     Hit: Single
     HitCount: 1
     Element: Holy
@@ -10002,15 +9998,15 @@ Body:
     Element: Weapon
     Duration1:
       - Level: 1
-        Time: 4000
+        Time: 2000
       - Level: 2
-        Time: 8000
+        Time: 4000
       - Level: 3
-        Time: 12000
+        Time: 6000
       - Level: 4
-        Time: 16000
+        Time: 8000
       - Level: 5
-        Time: 24000
+        Time: 10000
     CastDelayFlags:
       IgnoreStatus: true
     Requires:
@@ -10026,7 +10022,7 @@ Body:
         - Level: 5
           Amount: 12
       SpiritSphereCost: 1
-    Status: Stop
+    Status: Ankle
   - Id: 372
     Name: CH_CHAINCRUSH
     Description: Chain Crush Combo
@@ -10805,7 +10801,7 @@ Body:
       IgnoreDefense: true
     Flags:
       TargetTrap: true
-    Range: 5
+    Range: 4
     Hit: Multi_Hit
     HitCount: 5
     Element: Weapon
@@ -10847,7 +10843,7 @@ Body:
       Weapon:
         1hSpear: true
         2hSpear: true
-    Status: Stop
+    Status: Ankle
   - Id: 398
     Name: LK_HEADCRUSH
     Description: Traumatic Blow
@@ -11066,7 +11062,7 @@ Body:
     TargetType: Attack
     DamageFlags:
       NoDamage: true
-    Range: 7
+    Range: 9
     Hit: Single
     HitCount: 1
     ActiveInstance: 3
@@ -16336,7 +16332,7 @@ Body:
     Flags:
       IsNpc: true
     HitCount: 1
-    Duration1: -1
+    Duration1: 300000
     Status: Invincible
   - Id: 686
     Name: NPC_INVINCIBLEOFF
@@ -16348,8 +16344,6 @@ Body:
     Flags:
       IsNpc: true
     HitCount: 1
-    Duration1: 60000
-    Status: InvincibleOff
   - Id: 687
     Name: NPC_ALLHEAL
     Description: Full Heal
@@ -32758,7 +32752,7 @@ Body:
       IgnoreDefense: true
     Flags:
       TargetTrap: true
-    Range: 5
+    Range: 4
     Hit: Multi_Hit
     HitCount: 5
     Element: Weapon
@@ -32801,7 +32795,7 @@ Body:
           Amount: 27
         - Level: 5
           Amount: 30
-    Status: Stop
+    Status: Ankle
   - Id: 8219
     Name: ML_DEFENDER
     Description: Defending_Aura

+ 1 - 13
db/pre-re/status.yml

@@ -769,7 +769,6 @@ Body:
       NoBanishingBuster: true
       NoClearance: true
       RemoveOnChangeMap: true
-    MinDuration: 5000
   - Status: Keeping
     DurationLookup: NPC_KEEPING
     CalcFlags:
@@ -2824,23 +2823,12 @@ Body:
     Icon: EFST_INVINCIBLE
     DurationLookup: NPC_INVINCIBLE
     CalcFlags:
+      Aspd: true
       Speed: true
     Flags:
       NoDispell: true
       NoBanishingBuster: true
       NoClearance: true
-    EndOnStart:
-      Invincibleoff: true
-  - Status: Invincibleoff
-    DurationLookup: NPC_INVINCIBLEOFF
-    CalcFlags:
-      Speed: true
-    Flags:
-      NoDispell: true
-      NoBanishingBuster: true
-      NoClearance: true
-    EndOnStart:
-      Invincible: true
   - Status: Manu_Atk
     Icon: EFST_MANU_ATK
     Flags:

+ 3 - 8
db/re/item_db_equip.yml

@@ -948,7 +948,7 @@ Body:
     Refineable: true
     Script: |
       bonus2 bAddEff,Eff_Curse,30;
-      bonus2 bComaClass,Class_All,10;
+      bonus2 bComaClass,Class_Normal,10;
   - Id: 1133
     AegisName: Fire_Brand
     Name: Fireblend
@@ -185843,13 +185843,10 @@ Body:
     Script: |
       .@r = getrefine();
       .@val = getskilllv("GN_CARTBOOST");
-      .@a = (.@r>= 7 ? 20 : (.@r>= 5 ? 10 : 3));
-      .@b = (.@r>= 7 ? 100 : (.@r>= 5 ? 50 : 0));
       bonus bUnbreakableShoes;
       bonus bMdef,10;
-      bonus bMaxHPrate,.@a;
-      bonus bMaxSPrate,.@a;
-      bonus2 bVariableCastrate,"GN_CARTCANNON",-.@b;
+      bonus bMaxHPrate,3;
+      bonus bMaxSPrate,3;
       bonus bHit,20*.@val;
       bonus bAspdRate,4*.@val;
       bonus bAtkRate,4*getskilllv("GN_FIRE_EXPANSION");
@@ -185861,14 +185858,12 @@ Body:
          bonus bMaxSPrate,7;
          bonus2 bVariableCastrate,"GN_CARTCANNON",-50;
          bonus2 bSkillAtk,"GN_CARTCANNON",BaseLevel/2;
-         bonus bAllStats,BaseLevel/2;
       }
       if (.@r>=7) {
          bonus bMaxHPrate,10;
          bonus bMaxSPrate,10;
          bonus2 bVariableCastrate,"GN_CARTCANNON",-50;
          bonus2 bSkillAtk,"GN_CARTCANNON",BaseLevel/2;
-         bonus bAllStats,BaseLevel/2;
       }
   - Id: 470062
     AegisName: Lethargy_P_Shoes

+ 2 - 1
db/re/item_db_usable.yml

@@ -56781,7 +56781,8 @@ Body:
       NoMail: true
       NoAuction: true
     Script: |
-      itemskill "RK_LUXANIMA",1;
+      if ((eaclass()&EAJ_THIRDMASK) == EAJ_RUNE_KNIGHT)
+         itemskill "RK_LUXANIMA",1;
   - Id: 22541
     AegisName: PCBang_Coupon_Box6
     Name: PC Room Coupon Box VI

+ 3 - 3
db/re/mob_db.yml

@@ -78188,7 +78188,7 @@ Body:
     AttackDelay: 1020
     AttackMotion: 500
     DamageMotion: 768
-    Ai: 10
+    Ai: 21
     Class: Boss
     Drops:
       - Item: Brinaranea_Card
@@ -78220,7 +78220,7 @@ Body:
     AttackDelay: 608
     AttackMotion: 408
     DamageMotion: 336
-    Ai: 10
+    Ai: 21
     Class: Boss
     Drops:
       - Item: Muspellskoll_Card
@@ -78362,7 +78362,7 @@ Body:
     AttackDelay: 750
     AttackMotion: 510
     DamageMotion: 500
-    Ai: 10
+    Ai: 21
     Class: Boss
     Drops:
       - Item: M_Morocc_Card

+ 51 - 51
db/re/mob_skill_db.txt

@@ -102,7 +102,7 @@
 1019,Peco Peco@NPC_EMOTION,chase,197,1,2000,0,5000,yes,self,always,0,6,,,,,,
 1019,Peco Peco@NPC_FIREATTACK,attack,186,1,2000,0,5000,yes,target,always,0,,,,,,,
 1019,Peco Peco@NPC_PROVOCATION,chase,194,1,200,0,5000,yes,target,always,0,,,,,,19,
-1020,Mandragora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,randomtarget,always,0,,,,,,,
+1020,Mandragora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,target,always,0,,,,,,,
 1023,Orc Warrior@NPC_EMOTION,chase,197,1,2000,0,5000,yes,self,always,0,,,,,,,
 1023,Orc Warrior@NPC_GROUNDATTACK,attack,185,2,500,500,5000,no,target,always,0,,,,,,6,
 1023,Orc Warrior@NPC_EMOTION,chase,197,1,200,0,5000,yes,self,always,0,19,0x81,,,,,
@@ -351,7 +351,7 @@
 1067,Cornutus@NPC_WATERATTACK,attack,184,2,500,500,5000,no,target,always,0,,,,,,6,
 1067,Cornutus@CR_AUTOGUARD,attack,249,2,500,0,300000,yes,self,always,0,,,,,,,
 1067,Cornutus@CR_AUTOGUARD,chase,249,2,2000,0,300000,yes,self,longrangeattacked,,,,,,,,
-1068,Hydra@NPC_WATERATTACK,attack,184,2,500,500,5000,no,randomtarget,always,0,,,,,,,
+1068,Hydra@NPC_WATERATTACK,attack,184,2,500,500,5000,no,target,always,0,,,,,,,
 1069,Swordfish@NPC_WATERATTACK,attack,184,1,2000,0,5000,yes,target,always,0,,,,,,,
 1069,Swordfish@WZ_WATERBALL,attack,86,3,500,1500,5000,yes,target,always,0,,,,,,,
 1069,Swordfish@WZ_WATERBALL,chase,86,3,500,1500,5000,yes,target,always,0,,,,,,,
@@ -603,9 +603,9 @@
 1117,Evil Druid@NPC_UNDEADATTACK,chase,347,3,500,500,5000,no,target,always,0,,,,,,9,
 1117,Evil Druid@WZ_HEAVENDRIVE,attack,91,5,500,1200,5000,yes,target,always,0,,,,,,,
 1117,Evil Druid@WZ_HEAVENDRIVE,chase,91,5,500,1200,5000,yes,target,always,0,,,,,,,
-1118,Flora@NPC_BLOODDRAIN,attack,199,1,500,0,5000,yes,randomtarget,always,0,,,,,,,
+1118,Flora@NPC_BLOODDRAIN,attack,199,1,500,0,5000,yes,target,always,0,,,,,,,
 1118,Flora@NPC_EMOTION,idle,197,1,2000,0,5000,yes,self,always,0,2,,,,,,
-1118,Flora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,randomtarget,always,0,,,,,,,
+1118,Flora@NPC_GROUNDATTACK,attack,185,1,2000,0,5000,yes,target,always,0,,,,,,,
 1119,Frilldora@AS_CLOAKING,attack,135,1,2000,200,5000,yes,self,always,0,,,,,,,
 1119,Frilldora@AS_CLOAKING,idle,135,1,2000,200,5000,yes,self,always,0,,,,,,,
 1119,Frilldora@AS_CLOAKING,chase,135,1,2000,200,5000,yes,self,always,0,,,,,,,
@@ -1301,7 +1301,7 @@
 1276,Raydric Archer@CR_AUTOGUARD,attack,249,2,500,0,300000,yes,self,always,0,,,,,,,
 1277,Greatest General@NPC_BLINDATTACK,idle,177,3,10000,1500,5000,no,randomtarget,longrangeattacked,,,,,,,6,
 1277,Greatest General@NPC_BLINDATTACK,idle,177,3,10000,1500,5000,no,randomtarget,casttargeted,,,,,,,6,
-1277,Greatest General@NPC_FIREATTACK,attack,186,2,500,500,5000,no,randomtarget,always,0,,,,,,,
+1277,Greatest General@NPC_FIREATTACK,attack,186,2,500,500,5000,no,target,always,0,,,,,,,
 1277,Greatest General@WZ_EARTHSPIKE,idle,90,3,5000,1500,5000,no,randomtarget,longrangeattacked,,,,,,,6,
 1277,Greatest General@WZ_EARTHSPIKE,idle,90,3,5000,1500,5000,no,randomtarget,casttargeted,,,,,,,6,
 1278,Stalactite Golem@NPC_STUNATTACK,attack,179,4,500,1500,5000,no,target,always,0,,,,,,6,
@@ -1584,7 +1584,7 @@
 1367,Blazer@WZ_SIGHTRASHER,attack,81,5,500,1000,5000,no,target,always,0,,,,,,6,
 1368,Geographer@AL_HEAL,attack,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,60,,,,,,,
 1368,Geographer@AL_HEAL,idle,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,60,,,,,,,
-1368,Geographer@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,randomtarget,always,0,,,,,,,
+1368,Geographer@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,target,always,0,,,,,,,
 1369,Grand Peco@AS_SONICBLOW,attack,136,5,500,800,5000,no,target,always,0,,,,,,6,
 1369,Grand Peco@NPC_FIREATTACK,attack,186,3,500,500,5000,no,target,always,0,,,,,,6,
 1369,Grand Peco@NPC_EMOTION,chase,197,1,200,0,5000,yes,self,always,0,19,0x81,,,,,
@@ -2569,8 +2569,8 @@
 1510,Hylozoist@MO_BODYRELOCATION,chase,264,1,2000,500,5000,no,target,always,0,,,,,,,
 1511,Amon Ra@NPC_BLOODDRAIN,idle,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
 1511,Amon Ra@NPC_BLOODDRAIN,idle,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
-1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
-1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
+1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,always,0,,,,,,29,
+1511,Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,always,0,,,,,,29,
 1511,Amon Ra@NPC_SUMMONMONSTER,idle,209,5,5000,0,10000,no,self,longrangeattacked,0,1474,1477,1438,,,9,
 1511,Amon Ra@NPC_SUMMONMONSTER,idle,209,5,5000,0,10000,no,self,casttargeted,0,1474,1477,1438,,,9,
 1511,Amon Ra@NPC_SUMMONMONSTER,attack,209,5,5000,0,10000,no,self,longrangeattacked,0,1474,1477,1438,,,9,
@@ -2589,11 +2589,11 @@
 1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,skillused,83,,,,,,9,
 1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,longrangeattacked,,,,,,,9,
 1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,casttargeted,,,,,,,9,
-1511,Amon Ra@WZ_METEOR,attack,83,11,5000,0,3000,yes,randomtarget,always,0,,,,,,9,
+1511,Amon Ra@WZ_METEOR,attack,83,11,5000,0,3000,yes,target,always,0,,,,,,9,
 1511,Amon Ra@WZ_FIREPILLAR,idle,80,10,10000,0,2000,yes,around2,always,0,,,,,,,
 1511,Amon Ra@WZ_FIREPILLAR,idle,80,10,10000,0,2000,yes,around2,always,0,,,,,,,
 1511,Amon Ra@WZ_FIREPILLAR,attack,80,10,5000,0,2000,yes,around2,always,0,,,,,,,
-1511,Amon Ra@NPC_DARKBLESSING,attack,203,1,5000,0,2000,no,randomtarget,always,0,,,,,,,
+1511,Amon Ra@NPC_DARKBLESSING,attack,203,1,5000,0,2000,no,target,always,0,,,,,,,
 1511,Amon Ra@WZ_METEOR,idle,83,11,10000,0,5000,yes,randomtarget,always,0,,,,,,9,
 1511,Amon Ra@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
 1511,Amon Ra@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
@@ -3405,18 +3405,18 @@
 1663,Laurell Weinder@NPC_EMOTION,idle,197,1,10000,0,5000,yes,self,skillused,28,15,,,,,,
 1663,Laurell Weinder@NPC_EMOTION,attack,197,1,10000,0,5000,yes,self,skillused,28,15,,,,,,
 1663,Laurell Weinder@NPC_EMOTION,chase,197,1,10000,0,5000,yes,self,skillused,28,15,,,,,,
-1664,Photon Cannon@NPC_WINDATTACK,attack,187,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
-1664,Photon Cannon@NPC_WINDATTACK,attack,187,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
-1664,Photon Cannon@NPC_WINDATTACK,attack,187,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
-1665,Photon Cannon@NPC_FIREATTACK,attack,186,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
-1665,Photon Cannon@NPC_FIREATTACK,attack,186,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
-1665,Photon Cannon@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
-1666,Photon Cannon@NPC_WATERATTACK,attack,184,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
-1666,Photon Cannon@NPC_WATERATTACK,attack,184,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
-1666,Photon Cannon@NPC_WATERATTACK,attack,184,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
-1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,5,1000,1000,10000,yes,randomtarget,always,0,,,,,,,
-1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,3,2000,500,5000,yes,randomtarget,always,0,,,,,,,
-1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
+1664,Photon Cannon@NPC_WINDATTACK,attack,187,5,1000,1000,10000,yes,target,always,0,,,,,,,
+1664,Photon Cannon@NPC_WINDATTACK,attack,187,3,2000,500,5000,yes,target,always,0,,,,,,,
+1664,Photon Cannon@NPC_WINDATTACK,attack,187,1,10000,0,0,yes,target,always,0,,,,,,,
+1665,Photon Cannon@NPC_FIREATTACK,attack,186,5,1000,1000,10000,yes,target,always,0,,,,,,,
+1665,Photon Cannon@NPC_FIREATTACK,attack,186,3,2000,500,5000,yes,target,always,0,,,,,,,
+1665,Photon Cannon@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,target,always,0,,,,,,,
+1666,Photon Cannon@NPC_WATERATTACK,attack,184,5,1000,1000,10000,yes,target,always,0,,,,,,,
+1666,Photon Cannon@NPC_WATERATTACK,attack,184,3,2000,500,5000,yes,target,always,0,,,,,,,
+1666,Photon Cannon@NPC_WATERATTACK,attack,184,1,10000,0,0,yes,target,always,0,,,,,,,
+1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,5,1000,1000,10000,yes,target,always,0,,,,,,,
+1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,3,2000,500,5000,yes,target,always,0,,,,,,,
+1667,Photon Cannon@NPC_GROUNDATTACK,attack,185,1,10000,0,0,yes,target,always,0,,,,,,,
 1668,Archdam@NPC_PIERCINGATT,attack,158,5,1000,0,5000,yes,target,always,0,,,,,,,
 1668,Archdam@NPC_GUIDEDATTACK,attack,172,2,500,1000,20000,no,target,always,0,,,,,,29,
 1668,Archdam@KN_SPEARSTAB,attack,58,5,500,800,5000,no,target,always,0,,,,,,,
@@ -3453,9 +3453,9 @@
 1673,Dimik@NPC_COMBOATTACK,attack,171,4,500,700,5000,no,target,always,0,,,,,,,
 1673,Dimik@NPC_COMBOATTACK,chase,171,4,500,700,5000,no,target,always,0,,,,,,,
 1673,Dimik@NPC_FIREATTACK,attack,186,3,500,0,5000,yes,target,always,0,,,,,,,
-1674,Monemus@NPC_FIREATTACK,attack,186,10,500,1000,30000,yes,randomtarget,always,0,,,,,,,
-1674,Monemus@NPC_FIREATTACK,attack,186,3,1000,0,10000,yes,randomtarget,always,0,,,,,,,
-1674,Monemus@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,randomtarget,always,0,,,,,,,
+1674,Monemus@NPC_FIREATTACK,attack,186,10,500,1000,30000,yes,target,always,0,,,,,,,
+1674,Monemus@NPC_FIREATTACK,attack,186,3,1000,0,10000,yes,target,always,0,,,,,,,
+1674,Monemus@NPC_FIREATTACK,attack,186,1,10000,0,0,yes,target,always,0,,,,,,,
 1675,Venatu@NPC_SILENCEATTACK,attack,178,3,500,700,5000,no,target,always,0,,,,,,,
 1675,Venatu@NPC_GUIDEDATTACK,attack,172,3,500,1000,20000,no,target,always,0,,,,,,6,
 1675,Venatu@NPC_STUNATTACK,attack,179,2,500,1500,5000,no,target,always,0,,,,,,11,
@@ -3531,11 +3531,11 @@
 1688,Lady Tany@AL_TELEPORT,idle,26,1,1000,0,30000,yes,self,always,0,,,,,,,
 1688,Lady Tany@AL_TELEPORT,attack,26,1,1000,0,30000,yes,self,always,0,,,,,,,
 1688,Lady Tany@NPC_EXPULSION,attack,674,1,1000,1000,10000,no,target,myhpltmaxrate,60,,,,,,,
-1688,Lady Tany@AC_CHARGEARROW,attack,148,1,2000,0,5000,yes,randomtarget,always,0,,,,,,6,
-1688,Lady Tany@NPC_COMBOATTACK,attack,171,1,1000,0,5000,no,randomtarget,always,0,,,,,,,
-1688,Lady Tany@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,randomtarget,always,0,,,,,,6,
-1688,Lady Tany@NPC_GUIDEDATTACK,attack,172,5,500,0,20000,no,randomtarget,always,0,,,,,,,
-1688,Lady Tany@NPC_STUNATTACK,attack,179,5,500,0,5000,no,randomtarget,always,0,,,,,,,
+1688,Lady Tany@AC_CHARGEARROW,attack,148,1,2000,0,5000,yes,target,always,0,,,,,,6,
+1688,Lady Tany@NPC_COMBOATTACK,attack,171,1,1000,0,5000,no,target,always,0,,,,,,,
+1688,Lady Tany@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,target,always,0,,,,,,6,
+1688,Lady Tany@NPC_GUIDEDATTACK,attack,172,5,500,0,20000,no,target,always,0,,,,,,,
+1688,Lady Tany@NPC_STUNATTACK,attack,179,5,500,0,5000,no,target,always,0,,,,,,,
 1688,Lady Tany@NPC_DEFENDER,attack,205,1,500,0,30000,yes,self,longrangeattacked,,,,,,,29,
 1688,Lady Tany@NPC_POWERUP,attack,349,5,10000,0,30000,yes,self,myhpltmaxrate,30,,,,,,6,
 1688,Lady Tany@NPC_SUMMONSLAVE,attack,196,5,10000,2000,5000,no,self,slavele,2,1691,,,,,,
@@ -4228,18 +4228,18 @@
 1779,Ktullanux@NPC_AGIUP,attack,350,5,2000,0,100000,yes,self,always,0,,,,,,,
 1779,Ktullanux@NPC_AGIUP,attack,350,5,10000,0,25000,yes,self,myhpltmaxrate,30,,,,,,,
 1779,Ktullanux@AL_HEAL,idle,28,11,10000,0,10000,yes,self,myhpltmaxrate,50,,,,,,,
-1780,Muscipular@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
-1780,Muscipular@KN_SPEARSTAB,attack,58,5,500,800,5000,no,randomtarget,always,0,,,,,,6,
-1780,Muscipular@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
+1780,Muscipular@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,target,always,0,,,,,,,
+1780,Muscipular@KN_SPEARSTAB,attack,58,5,500,800,5000,no,target,always,0,,,,,,6,
+1780,Muscipular@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,target,always,0,,,,,,,
 1780,Muscipular@AL_HEAL,attack,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,50,,,,,,,
 1780,Muscipular@AL_HEAL,idle,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,50,,,,,,,
-1780,Muscipular@NPC_PETRIFYATTACK,attack,180,5,500,0,5000,yes,randomtarget,always,0,,,,,,,
-1781,Drosera@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
-1781,Drosera@KN_PIERCE,attack,56,5,500,700,5000,no,randomtarget,always,0,,,,,,,
-1781,Drosera@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,randomtarget,always,0,,,,,,,
+1780,Muscipular@NPC_PETRIFYATTACK,attack,180,5,500,0,5000,yes,target,always,0,,,,,,,
+1781,Drosera@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,yes,target,always,0,,,,,,,
+1781,Drosera@KN_PIERCE,attack,56,5,500,700,5000,no,target,always,0,,,,,,,
+1781,Drosera@NPC_GROUNDATTACK,attack,185,1,1000,0,5000,yes,target,always,0,,,,,,,
 1781,Drosera@RG_CLOSECONFINE,attack,1005,1,1000,0,30000,yes,target,always,0,,,,,,,
-1781,Drosera@NPC_GUIDEDATTACK,attack,172,3,500,1000,20000,no,randomtarget,always,0,,,,,,6,
-1781,Drosera@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,randomtarget,always,0,,,,,,,
+1781,Drosera@NPC_GUIDEDATTACK,attack,172,3,500,1000,20000,no,target,always,0,,,,,,6,
+1781,Drosera@NPC_SLEEPATTACK,attack,182,5,500,0,5000,yes,target,always,0,,,,,,,
 1782,Roween@NPC_WINDATTACK,attack,187,2,500,500,5000,no,target,always,0,,,,,,,
 1782,Roween@NPC_COMBOATTACK,attack,171,4,500,500,5000,no,target,always,0,,,,,,6,
 1782,Roween@NPC_EMOTION,idle,197,1,2000,0,5000,yes,self,always,0,22,0x308D,,,,,
@@ -7980,8 +7980,8 @@
 2311,Manananggal@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
 2311,Manananggal@AL_TELEPORT,idle,26,1,1000,0,30000,yes,self,always,0,,,,,,,
 2311,Manananggal@AL_TELEPORT,attack,26,1,100,0,30000,yes,self,always,0,,,,,,,
-2311,Manananggal@NPC_BLOODDRAIN,chase,199,1,2000,0,5000,yes,randomtarget,myhpltmaxrate,50,,,,,,3,
-2311,Manananggal@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,myhpltmaxrate,50,,,,,,3,
+2311,Manananggal@NPC_BLOODDRAIN,chase,199,1,2000,0,5000,yes,target,myhpltmaxrate,50,,,,,,3,
+2311,Manananggal@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,myhpltmaxrate,50,,,,,,3,
 2311,Manananggal@NPC_COMBOATTACK,chase,171,5,1000,0,5000,yes,target,always,0,,,,,,7,
 2311,Manananggal@NPC_COMBOATTACK,attack,171,5,1000,0,5000,yes,target,always,0,,,,,,7,
 2312,Mangkukulam@AL_TELEPORT,idle,26,1,500,0,30000,yes,self,always,0,,,,,,,
@@ -8009,8 +8009,8 @@
 2315,Wakwak@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
 2315,Wakwak@AL_TELEPORT,idle,26,1,500,0,30000,yes,self,always,0,,,,,,,
 2315,Wakwak@AL_TELEPORT,attack,26,1,50,0,30000,yes,self,always,0,,,,,,,
-2315,Wakwak@NPC_BLOODDRAIN,chase,199,1,2000,0,5000,yes,randomtarget,myhpltmaxrate,50,,,,,,3,
-2315,Wakwak@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,myhpltmaxrate,50,,,,,,3,
+2315,Wakwak@NPC_BLOODDRAIN,chase,199,1,2000,0,5000,yes,target,myhpltmaxrate,50,,,,,,3,
+2315,Wakwak@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,myhpltmaxrate,50,,,,,,3,
 2315,Wakwak@NPC_DARKTHUNDER,chase,341,3,1000,500,5000,yes,target,always,0,,,,,,29,
 2315,Wakwak@NPC_DARKTHUNDER,attack,341,3,1000,500,5000,yes,target,always,0,,,,,,29,
 2315,Wakwak@NPC_CURSEATTACK,attack,181,3,500,800,5000,no,target,always,0,,,,,,0,
@@ -8113,7 +8113,7 @@
 2331,Seaweed@AL_HEAL,idle,28,9,10000,500,5000,yes,friend,friendhpltmaxrate,100,,,,,,2,
 2337,Hidden Mob@NPC_INVISIBLE,idle,353,1,10000,0,30000,yes,self,always,0,,,,,,,
 2337,Hidden Mob@NPC_INVISIBLE,attack,353,1,10000,0,30000,yes,self,always,0,,,,,,,
-2337,Hidden Mob@WZ_METEOR,attack,83,5,10000,0,1000,yes,randomtarget,always,0,,,,,,,
+2337,Hidden Mob@WZ_METEOR,attack,83,5,10000,0,1000,yes,target,always,0,,,,,,,
 2338,Bangungot Manananggal@AL_TELEPORT,idle,26,1,500,0,5000,yes,self,always,0,,,,,,,
 2338,Bangungot Manananggal@NPC_BLOODDRAIN,attack,199,1,1000,0,5000,no,target,always,0,,,,,,3,
 2338,Bangungot Manananggal@NPC_COMBOATTACK,attack,171,5,500,700,5000,no,target,always,0,,,,,,1,
@@ -8129,11 +8129,11 @@
 2339,Bangungot Mangkukulam@NPC_DARKSTRIKE,chase,340,9,500,700,5000,no,target,always,0,,,,,,29,
 2339,Bangungot Mangkukulam@NPC_MENTALBREAKER,attack,159,3,500,800,5000,no,target,always,0,,,,,,14,
 2339,Bangungot Mangkukulam@NPC_MENTALBREAKER,chase,159,3,500,800,5000,no,target,always,0,,,,,,14,
-2340,Tiyanak@NPC_BLOODDRAIN,attack,199,1,500,0,5000,yes,randomtarget,always,0,,,,,,2,
+2340,Tiyanak@NPC_BLOODDRAIN,attack,199,1,500,0,5000,yes,target,always,0,,,,,,2,
 2340,Tiyanak@NPC_EMOTION,idle,197,1,2000,0,5000,yes,self,always,0,29,,,,,,
 2340,Tiyanak@CR_AUTOGUARD,chase,249,2,2000,0,300000,yes,self,longrangeattacked,,,,,,,,
 2340,Tiyanak@CR_AUTOGUARD,attack,249,2,500,0,300000,yes,self,always,0,,,,,,,
-2340,Tiyanak@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,randomtarget,always,0,,,,,,6,
+2340,Tiyanak@NPC_CRITICALSLASH,attack,170,1,500,500,5000,no,target,always,0,,,,,,6,
 2340,Tiyanak@NPC_REBIRTH,dead,208,3,2000,0,10000,yes,self,always,0,,,,,,,
 2341,RWC Boss@NPC_CALLSLAVE,attack,352,1,10000,0,30000,yes,self,always,0,,,,,,,
 2341,RWC Boss@NPC_CALLSLAVE,idle,352,1,10000,0,30000,yes,self,always,0,,,,,,,
@@ -8162,7 +8162,7 @@
 2341,RWC Boss@NPC_CRITICALWOUND,attack,673,4,2000,0,5000,yes,target,always,0,,,,,,,
 2343,Hidden Mob@NPC_INVISIBLE,idle,353,1,10000,0,30000,yes,self,always,0,,,,,,,
 2343,Hidden Mob@NPC_INVISIBLE,attack,353,1,10000,0,30000,yes,self,always,0,,,,,,,
-2343,Hidden Mob@WZ_STORMGUST,attack,89,5,10000,0,1000,yes,randomtarget,always,0,,,,,,,
+2343,Hidden Mob@WZ_STORMGUST,attack,89,5,10000,0,1000,yes,target,always,0,,,,,,,
 
 // Nightmare Pyramids
 2353,Nightmare Minorous@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
@@ -8198,8 +8198,8 @@
 2360,Nightmare Ancient Mummy@NPC_DARKBREATH,attack,202,4,500,800,5000,no,target,always,0,,,,,,7,
 2362,Nightmare Amon Ra@NPC_BLOODDRAIN,idle,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
 2362,Nightmare Amon Ra@NPC_BLOODDRAIN,idle,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
-2362,Nightmare Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
-2362,Nightmare Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,randomtarget,always,0,,,,,,29,
+2362,Nightmare Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,always,0,,,,,,29,
+2362,Nightmare Amon Ra@NPC_BLOODDRAIN,attack,199,1,2000,0,5000,yes,target,always,0,,,,,,29,
 2362,Nightmare Amon Ra@NPC_SUMMONMONSTER,idle,209,5,5000,0,10000,no,self,longrangeattacked,0,2357,2359,2361,,,9,
 2362,Nightmare Amon Ra@NPC_SUMMONMONSTER,idle,209,5,5000,0,10000,no,self,casttargeted,0,1474,1477,1438,,,9,
 2362,Nightmare Amon Ra@NPC_SUMMONMONSTER,attack,209,5,5000,0,10000,no,self,longrangeattacked,0,2357,2359,2361,,,9,
@@ -8218,11 +8218,11 @@
 2362,Nightmare Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,skillused,83,,,,,,9,
 2362,Nightmare Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,longrangeattacked,,,,,,,9,
 2362,Nightmare Amon Ra@WZ_METEOR,idle,83,11,10000,0,0,yes,randomtarget,casttargeted,,,,,,,9,
-2362,Nightmare Amon Ra@WZ_METEOR,attack,83,11,5000,0,3000,yes,randomtarget,always,0,,,,,,9,
+2362,Nightmare Amon Ra@WZ_METEOR,attack,83,11,5000,0,3000,yes,target,always,0,,,,,,9,
 2362,Nightmare Amon Ra@WZ_FIREPILLAR,idle,80,10,10000,0,2000,yes,around2,always,0,,,,,,,
 2362,Nightmare Amon Ra@WZ_FIREPILLAR,idle,80,10,10000,0,2000,yes,around2,always,0,,,,,,,
 2362,Nightmare Amon Ra@WZ_FIREPILLAR,attack,80,10,5000,0,2000,yes,around2,always,0,,,,,,,
-2362,Nightmare Amon Ra@NPC_DARKBLESSING,attack,203,1,5000,0,2000,no,randomtarget,always,0,,,,,,,
+2362,Nightmare Amon Ra@NPC_DARKBLESSING,attack,203,1,5000,0,2000,no,target,always,0,,,,,,,
 2362,Nightmare Amon Ra@WZ_METEOR,idle,83,11,10000,0,5000,yes,randomtarget,always,0,,,,,,9,
 2362,Nightmare Amon Ra@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
 2362,Nightmare Amon Ra@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,

+ 14 - 19
db/re/skill_db.yml

@@ -7234,9 +7234,8 @@ Body:
     Type: Magic
     TargetType: Self
     DamageFlags:
-      IgnoreAtkCard: true
-      IgnoreFlee: true
-    Range: 5
+      IgnoreDefense: true
+    Range: 9
     Hit: Single
     HitCount: 1
     Element: Holy
@@ -10250,15 +10249,15 @@ Body:
     Element: Weapon
     Duration1:
       - Level: 1
-        Time: 4000
+        Time: 2000
       - Level: 2
-        Time: 8000
+        Time: 4000
       - Level: 3
-        Time: 12000
+        Time: 6000
       - Level: 4
-        Time: 16000
+        Time: 8000
       - Level: 5
-        Time: 24000
+        Time: 10000
     CastDelayFlags:
       IgnoreStatus: true
     Requires:
@@ -10274,7 +10273,7 @@ Body:
         - Level: 5
           Amount: 12
       SpiritSphereCost: 1
-    Status: Stop
+    Status: Ankle
   - Id: 372
     Name: CH_CHAINCRUSH
     Description: Chain Crush Combo
@@ -11048,7 +11047,7 @@ Body:
     TargetType: Attack
     Flags:
       TargetTrap: true
-    Range: 5
+    Range: 4
     Hit: Multi_Hit
     HitCount: 5
     Element: Weapon
@@ -11103,7 +11102,7 @@ Body:
         2hSword: true
         1hSpear: true
         2hSpear: true
-    Status: Stop
+    Status: Ankle
   - Id: 398
     Name: LK_HEADCRUSH
     Description: Traumatic Blow
@@ -11313,7 +11312,7 @@ Body:
     TargetType: Attack
     DamageFlags:
       NoDamage: true
-    Range: 7
+    Range: 9
     Hit: Single
     HitCount: 1
     ActiveInstance: 3
@@ -16709,7 +16708,7 @@ Body:
     Flags:
       IsNpc: true
     HitCount: 1
-    Duration1: -1
+    Duration1: 300000
     Status: Invincible
   - Id: 686
     Name: NPC_INVINCIBLEOFF
@@ -16721,8 +16720,6 @@ Body:
     Flags:
       IsNpc: true
     HitCount: 1
-    Duration1: 60000
-    Status: InvincibleOff
   - Id: 687
     Name: NPC_ALLHEAL
     Description: Full Heal
@@ -46224,7 +46221,7 @@ Body:
     TargetType: Attack
     Flags:
       TargetTrap: true
-    Range: 5
+    Range: 4
     Hit: Multi_Hit
     HitCount: 5
     Element: Weapon
@@ -46268,7 +46265,7 @@ Body:
           Amount: 27
         - Level: 5
           Amount: 30
-    Status: Stop
+    Status: Ankle
   - Id: 8219
     Name: ML_DEFENDER
     Description: Defending_Aura
@@ -46959,9 +46956,7 @@ Body:
     Range: 2
     Hit: Single
     HitCount: 1
-    Duration1: 10000
     Cooldown: 30000
-    Status: InvincibleOff
   - Id: 8401
     Name: EL_CIRCLE_OF_FIRE
     Description: Circle of Fire

+ 1 - 13
db/re/status.yml

@@ -786,7 +786,6 @@ Body:
       NoBanishingBuster: true
       NoClearance: true
       RemoveOnChangeMap: true
-    MinDuration: 5000
   - Status: Keeping
     DurationLookup: NPC_KEEPING
     CalcFlags:
@@ -2928,23 +2927,12 @@ Body:
     Icon: EFST_INVINCIBLE
     DurationLookup: NPC_INVINCIBLE
     CalcFlags:
+      Aspd: true
       Speed: true
     Flags:
       NoDispell: true
       NoBanishingBuster: true
       NoClearance: true
-    EndOnStart:
-      Invincibleoff: true
-  - Status: Invincibleoff
-    DurationLookup: NPC_INVINCIBLEOFF
-    CalcFlags:
-      Speed: true
-    Flags:
-      NoDispell: true
-      NoBanishingBuster: true
-      NoClearance: true
-    EndOnStart:
-      Invincible: true
   - Status: Manu_Atk
     Icon: EFST_MANU_ATK
     Flags:

+ 2 - 2
doc/permissions.txt

@@ -3,7 +3,7 @@
 //===== By: ==================================================
 //= rAthena Dev Team
 //===== Last Updated: ========================================
-//= 20130613
+//= 20240414
 //===== Description: =========================================
 //= List of available permissions and their functions.
 //============================================================
@@ -227,6 +227,6 @@ Allows player to use the client command /macro_detector.
 
 *macro_register
 
-Allows player to use the client commands /maco_register (used to add new captcha) and /macro_preview (used to preview captcha by ID).
+Allows player to use the client commands /macro_register (used to add new captcha) and /macro_preview (used to preview captcha by ID).
 
 ---------------------------------------

+ 1 - 1
doc/yaml/db/license.yml

@@ -1,5 +1,5 @@
 # This file is a part of rAthena.
-#   Copyright(C) 2023 rAthena Development Team
+#   Copyright(C) 2024 rAthena Development Team
 #   https://rathena.org - https://github.com/rathena
 #
 # This program is free software: you can redistribute it and/or modify

+ 5 - 5
npc/re/merchants/ammo_boxes.txt

@@ -167,8 +167,8 @@ S_Sphere_Exchange:
 				case 1:
 					mes "[Kenny]";
 					mes "All done.";
-					delitem .@slug_id, .@new_count * 10;
-					getitem .@new_slug_id, .@old_count;
+					delitem .@old_id, .@new_count * 10;
+					getitem .@new_id, .@new_count;
 					close;
 				case 2:
 					close;
@@ -214,8 +214,8 @@ S_Old_Sphere_Exchange:
 				case 1:
 					mes "[Kenny]";
 					mes "All done.";
-					delitem .@slug_id, .@old_count;
-					getitem .@new_slug_id, .@old_count;
+					delitem .@old_id, .@old_count;
+					getitem .@new_id, .@old_count;
 					close;
 				case 2:
 					close;
@@ -262,7 +262,7 @@ S_Slug_Exchange:
 				case 1:
 					mes "[Kenny]";
 					mes "All done.";
-					delitem .@slug_id, .@new_count * 500;
+					delitem .@slug_id, .@new_count * .@req_count;
 					getitem 25187, .@new_count;
 					close;
 				case 2:

+ 4 - 2
src/char/char.cpp

@@ -2820,7 +2820,8 @@ void char_set_defaults(){
  */
 void char_config_split_startpoint( char* w1_value, char* w2_value, struct s_point_str start_point[MAX_STARTPOINT], short* count ){
 	char *lineitem, **fields;
-	int i = 0, fields_length = 3 + 1;
+	int i = 0;
+	size_t fields_length = 3 + 1;
 
 	(*count) = 0; // Reset to begin reading
 
@@ -2859,7 +2860,8 @@ void char_config_split_startpoint( char* w1_value, char* w2_value, struct s_poin
 void char_config_split_startitem(char *w1_value, char *w2_value, struct startitem start_items[MAX_STARTITEM])
 {
 	char *lineitem, **fields;
-	int i = 0, fields_length = 3 + 1;
+	int i = 0;
+	size_t fields_length = 3 + 1;
 
 	fields = (char **)aMalloc(fields_length * sizeof(char *));
 	if (fields == NULL)

+ 65 - 22
src/char/char_logif.cpp

@@ -91,7 +91,7 @@ void chlogif_pincode_start(int fd, struct char_session_data* sd){
  * @param tick : Scheduled tick
  * @param id : GID linked to that timered call
  * @param data : data transmited for delayed function
- * @return 
+ * @return
  */
 TIMER_FUNC(chlogif_send_acc_tologin){
 	if ( chlogif_isconnected() ){
@@ -391,27 +391,70 @@ int chlogif_parse_keepalive(int fd){
  */
 void chlogif_parse_change_sex_sub(int sex, int acc, int char_id, int class_, int guild_id)
 {
-	// job modification //@TODO switch would be faster
-	if (class_ == JOB_BARD || class_ == JOB_DANCER)
-		class_ = (sex == SEX_MALE ? JOB_BARD : JOB_DANCER);
-	else if (class_ == JOB_CLOWN || class_ == JOB_GYPSY)
-		class_ = (sex == SEX_MALE ? JOB_CLOWN : JOB_GYPSY);
-	else if (class_ == JOB_BABY_BARD || class_ == JOB_BABY_DANCER)
-		class_ = (sex == SEX_MALE ? JOB_BABY_BARD : JOB_BABY_DANCER);
-	else if (class_ == JOB_MINSTREL || class_ == JOB_WANDERER)
-		class_ = (sex == SEX_MALE ? JOB_MINSTREL : JOB_WANDERER);
-	else if (class_ == JOB_MINSTREL_T || class_ == JOB_WANDERER_T)
-		class_ = (sex == SEX_MALE ? JOB_MINSTREL_T : JOB_WANDERER_T);
-	else if (class_ == JOB_BABY_MINSTREL || class_ == JOB_BABY_WANDERER)
-		class_ = (sex == SEX_MALE ? JOB_BABY_MINSTREL : JOB_BABY_WANDERER);
-	else if (class_ == JOB_KAGEROU || class_ == JOB_OBORO)
-		class_ = (sex == SEX_MALE ? JOB_KAGEROU : JOB_OBORO);
-	else if (class_ == JOB_BABY_KAGEROU || class_ == JOB_BABY_OBORO)
-		class_ = (sex == SEX_MALE ? JOB_BABY_KAGEROU : JOB_BABY_OBORO);
-	else if (class_ == JOB_TROUBADOUR || class_ == JOB_TROUVERE)
-		class_ = (sex == SEX_MALE ? JOB_TROUBADOUR : JOB_TROUVERE);
-	else if (class_ == JOB_SHINKIRO || class_ == JOB_SHIRANUI)
-		class_ = (sex == SEX_MALE ? JOB_SHINKIRO : JOB_SHIRANUI);
+	// job modification
+	switch (class_)
+	{
+	case JOB_BARD:
+		class_ = JOB_DANCER;
+		break;
+	case JOB_DANCER:
+		class_ = JOB_BARD;
+		break;
+	case JOB_CLOWN:
+		class_ = JOB_GYPSY;
+		break;
+	case JOB_GYPSY:
+		class_ = JOB_CLOWN;
+		break;
+	case JOB_BABY_BARD:
+		class_ = JOB_BABY_DANCER;
+		break;
+	case JOB_BABY_DANCER:
+		class_ = JOB_BABY_BARD;
+		break;
+	case JOB_MINSTREL:
+		class_ = JOB_WANDERER;
+		break;
+	case JOB_WANDERER:
+		class_ = JOB_MINSTREL;
+		break;
+	case JOB_MINSTREL_T:
+		class_ = JOB_WANDERER_T;
+		break;
+	case JOB_WANDERER_T:
+		class_ = JOB_MINSTREL_T;
+		break;
+	case JOB_BABY_MINSTREL:
+		class_ = JOB_BABY_WANDERER;
+		break;
+	case JOB_BABY_WANDERER:
+		class_ = JOB_BABY_MINSTREL;
+		break;
+	case JOB_KAGEROU:
+		class_ = JOB_OBORO;
+		break;
+	case JOB_OBORO:
+		class_ = JOB_KAGEROU;
+		break;
+	case JOB_BABY_KAGEROU:
+		class_ = JOB_BABY_OBORO;
+		break;
+	case JOB_BABY_OBORO:
+		class_ = JOB_BABY_KAGEROU;
+		break;
+	case JOB_TROUBADOUR:
+		class_ = JOB_TROUVERE;
+		break;
+	case JOB_TROUVERE:
+		class_ = JOB_TROUBADOUR;
+		break;
+	case JOB_SHINKIRO:
+		class_ = JOB_SHIRANUI;
+		break;
+	case JOB_SHIRANUI:
+		class_ = JOB_SHINKIRO;
+		break;
+	}
 
 	if (SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `equip` = '0' WHERE `char_id` = '%d'", schema_config.inventory_db, char_id))
 		Sql_ShowDebug(sql_handle);

+ 1 - 1
src/common/database.hpp

@@ -205,7 +205,7 @@ public:
 		}
 
 		// Resize to only fit all existing non null entries
-		this->cache.resize(max_key);
+		this->cache.resize(max_key + 1);
 		// Free the memory that was allocated too much
 		this->cache.shrink_to_fit();
 		this->loaded = true;

+ 1 - 2
src/common/utilities.hpp

@@ -293,9 +293,8 @@ namespace rathena {
 
 			if( rathena::util::safe_addition( a, b, result ) ){
 				return cap;
-			}else{
-				return result;
 			}
+			return std::min(result, cap);
 		}
 
 		template <typename T> void tolower( T& string ){

+ 154 - 67
src/map/battle.cpp

@@ -34,6 +34,8 @@
 #include "pc_groups.hpp"
 #include "pet.hpp"
 
+using namespace rathena;
+
 struct Battle_Config battle_config;
 static struct eri *delay_damage_ers; //For battle delay damage structures.
 
@@ -254,33 +256,42 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int
 	return bl_list[rnd()%c];
 }
 
-/*========================================== [Playtester]
+/**
 * Deals damage without delay, applies additional effects and triggers monster events
 * This function is called from battle_delay_damage or battle_delay_damage_sub
+* All other instances of battle damage should also go through this function (i.e. anything that displays a damage number)
+* Consider calling this function or battle_fix_damage instead status_fix_damage directly
 * @param src: Source of damage
 * @param target: Target of damage
 * @param damage: Damage to be dealt
 * @param delay: Damage delay
 * @param skill_lv: Level of skill used
-* @param skill_id: ID o skill used
+* @param skill_id: ID of skill used
 * @param dmg_lv: State of the attack (miss, etc.)
 * @param attack_type: Type of the attack (BF_NORMAL|BF_SKILL|BF_SHORT|BF_LONG|BF_WEAPON|BF_MAGIC|BF_MISC)
-* @param additional_effects: Whether additional effect should be applied
+* @param additional_effects: Whether additional effects should be applied (otherwise it's just damage+coma)
 * @param isspdamage: If the damage is done to SP
 * @param tick: Current tick
-*------------------------------------------*/
-void battle_damage(struct block_list *src, struct block_list *target, int64 damage, t_tick delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, t_tick tick, bool isspdamage) {
+* @return HP+SP+AP (0 if HP/SP/AP remained unchanged)
+*/
+int battle_damage(struct block_list *src, struct block_list *target, int64 damage, t_tick delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, t_tick tick, bool isspdamage) {
+	int dmg_change;
+	map_session_data* sd = nullptr;
+	if (src)
+		sd = BL_CAST(BL_PC, src);
 	map_freeblock_lock();
 	if (isspdamage)
-		status_fix_spdamage(src, target, damage, delay, skill_id);
+		dmg_change = status_fix_spdamage(src, target, damage, delay, skill_id);
+	else if (sd && battle_check_coma(*sd, *target, (e_battle_flag)attack_type))
+		dmg_change = status_damage(src, target, damage, 0, delay, 16, skill_id); // Coma attack
 	else
-		status_fix_damage(src, target, damage, delay, skill_id); // We have to separate here between reflect damage and others [icescope]
+		dmg_change = status_fix_damage(src, target, damage, delay, skill_id);
 	if (attack_type && !status_isdead(target) && additional_effects)
 		skill_additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, tick);
-	if (dmg_lv > ATK_BLOCK && attack_type)
+	if (dmg_lv > ATK_BLOCK && attack_type && additional_effects)
 		skill_counter_additional_effect(src, target, skill_id, skill_lv, attack_type, tick);
 	// This is the last place where we have access to the actual damage type, so any monster events depending on type must be placed here
-	if (target->type == BL_MOB) {
+	if (target->type == BL_MOB && additional_effects) {
 		mob_data *md = BL_CAST(BL_MOB, target);
 
 		if (md != nullptr) {
@@ -298,6 +309,7 @@ void battle_damage(struct block_list *src, struct block_list *target, int64 dama
 		}
 	}
 	map_freeblock_unlock();
+	return dmg_change;
 }
 
 /// Damage Delayed Structure
@@ -331,9 +343,7 @@ TIMER_FUNC(battle_delay_damage_sub){
 				//Deal damage
 				battle_damage(src, target, dat->damage, dat->delay, dat->skill_lv, dat->skill_id, dat->dmg_lv, dat->attack_type, dat->additional_effects, tick, dat->isspdamage);
 			} else if( !src && dat->skill_id == CR_REFLECTSHIELD ) { // it was monster reflected damage, and the monster died, we pass the damage to the character as expected
-				map_freeblock_lock();
-				status_fix_damage(target, target, dat->damage, dat->delay, dat->skill_id);
-				map_freeblock_unlock();
+				battle_fix_damage(target, target, dat->damage, dat->delay, dat->skill_id);
 			}
 		}
 
@@ -412,6 +422,10 @@ int battle_delay_damage(t_tick tick, int amotion, struct block_list *src, struct
 	return 0;
 }
 
+int battle_fix_damage(struct block_list* src, struct block_list* target, int64 damage, t_tick walkdelay, uint16 skill_id) {
+	return battle_damage(src, target, damage, walkdelay, 0, skill_id, ATK_DEF, BF_MISC, false, gettick(), false);
+}
+
 /**
  * Does attribute fix modifiers.
  * Added passing of the chars so that the status changes can affect it. [Skotlex]
@@ -1576,11 +1590,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 			return 0;
 	}
 
-	status_change* tsc = status_get_sc(bl); //check target status
-
-	if( tsc && tsc->getSCE(SC_INVINCIBLE) && !tsc->getSCE(SC_INVINCIBLEOFF) )
-		return 1;
-
 	switch (skill_id) {
 #ifndef RENEWAL
 		case PA_PRESSURE:
@@ -1594,6 +1603,8 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 			return damage; //These skills bypass everything else.
 	}
 
+	status_change* tsc = status_get_sc(bl); //check target status
+
 	// Nothing can reduce the damage, but Safety Wall and Millennium Shield can block it completely.
 	// So can defense sphere's but what the heck is that??? [Rytech]
 	if (skill_id == SJ_NOVAEXPLOSING && !(tsc && (tsc->getSCE(SC_SAFETYWALL) || tsc->getSCE(SC_MILLENNIUMSHIELD)))) {
@@ -1908,9 +1919,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 			}
 		}
 
-		if( sc->getSCE(SC_INVINCIBLE) && !sc->getSCE(SC_INVINCIBLEOFF) )
-			damage += damage * 75 / 100;
-
 		if ((sce = sc->getSCE(SC_BLOODLUST)) && flag&BF_WEAPON && damage > 0 && rnd()%100 < sce->val3)
 			status_heal(src, damage * sce->val4 / 100, 0, 3);
 
@@ -2833,6 +2841,10 @@ bool is_infinite_defense(struct block_list *target, int flag)
 	if(status_has_mode(tstatus,MD_IGNOREMISC) && flag&(BF_MISC) )
 		return true;
 
+	status_change* tsc = status_get_sc(target);
+	if (tsc && tsc->getSCE(SC_INVINCIBLE))
+		return true;
+
 	return false;
 }
 
@@ -3368,12 +3380,6 @@ static bool battle_skill_stacks_masteries_vvs(uint16 skill_id, e_bonus_chk_flag
 		case LG_EARTHDRIVE:
 		case NPC_DRAGONBREATH:
 			return false;
-		case CR_GRANDCROSS:
-		case NPC_GRANDDARKNESS:
-			// Grand Cross is influenced by refine bonus but not by atkpercent / masteries / Star Crumbs / Spirit Spheres
-			if (chk_flag != BCHK_REFINE)
-				return false;
-			break;
 		case LK_SPIRALPIERCE:
 			// Spiral Pierce is influenced only by refine bonus and Star Crumbs for players
 			if (chk_flag != BCHK_REFINE && chk_flag != BCHK_STAR)
@@ -3631,7 +3637,9 @@ int battle_get_misc_element(struct block_list* src, struct block_list* target, u
 static void battle_min_damage(struct Damage &wd, struct block_list &src, uint16 skill_id, int64 min) {
 	if (is_attack_right_handed(&src, skill_id)) {
 		wd.damage = cap_value(wd.damage, min, INT64_MAX);
+#ifndef RENEWAL
 		wd.basedamage = cap_value(wd.basedamage, min, INT64_MAX);
+#endif
 	}
 	// Left-hand damage is always capped to 0
 	if (is_attack_left_handed(&src, skill_id)) {
@@ -3829,9 +3837,11 @@ static void battle_calc_attack_masteries(struct Damage* wd, struct block_list *s
 	struct status_data *sstatus = status_get_status_data(src);
 	int t_class = status_get_class(target);
 
+#ifndef RENEWAL
 	if (sd) {
 		wd->basedamage = battle_addmastery(sd, target, wd->basedamage, 0);
 	}
+#endif
 
 	// Check if mastery damage applies to current skill
 	if (sd && battle_skill_stacks_masteries_vvs(skill_id, BCHK_ALL))
@@ -3933,10 +3943,10 @@ static void battle_calc_damage_parts(struct Damage* wd, struct block_list *src,s
 
 	if (sd && sd->sc.getSCE(SC_SEVENWIND)) { // Mild Wind applies element to status ATK as well as weapon ATK [helvetica]
 		wd->statusAtk = battle_attr_fix(src, target, wd->statusAtk, right_element, tstatus->def_ele, tstatus->ele_lv);
-		wd->statusAtk2 = battle_attr_fix(src, target, wd->statusAtk, left_element, tstatus->def_ele, tstatus->ele_lv);
+		wd->statusAtk2 = battle_attr_fix(src, target, wd->statusAtk2, left_element, tstatus->def_ele, tstatus->ele_lv);
 	} else { // status atk is considered neutral on normal attacks [helvetica]
 		wd->statusAtk = battle_attr_fix(src, target, wd->statusAtk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
-		wd->statusAtk2 = battle_attr_fix(src, target, wd->statusAtk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
+		wd->statusAtk2 = battle_attr_fix(src, target, wd->statusAtk2, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
 	}
 
 	// Check critical
@@ -4447,10 +4457,11 @@ static unsigned short battle_get_atkpercent(struct block_list& bl, uint16 skill_
 		atkpercent += sc.getSCE(SC_BLOODLUST)->val2;
 	if (sc.getSCE(SC_FLEET))
 		atkpercent += sc.getSCE(SC_FLEET)->val3;
+	if (sc.getSCE(SC_INVINCIBLE))
+		atkpercent += sc.getSCE(SC_INVINCIBLE)->val2;
 
 	/* Only few selected skills should use this function, DO NOT ADD any that are not caused by the skills listed below
 	* TODO:
-	* NPC_INVINCIBLE (+100)
 	* GD_GUARDUP (2*skLevel+8)
 	* EL_WATERBARRIER (-3)
 	* SC_ENERVATION (-30/-40/-50)
@@ -6570,7 +6581,7 @@ static void battle_calc_defense_reduction(struct Damage* wd, struct block_list *
 #ifndef RENEWAL
 		//Damage reduction: [VIT*0.3] + RND(0, [VIT^2/150] - [VIT*0.3] - 1) + [VIT*0.5]
 		vit_def = ((3 * def2) / 10);
-		vit_def += rnd_value(0, (def2 * def2) / 150 - ((3 * def2) / 10) - 1);
+		vit_def += rnd_value(0, max(0, (def2 * def2) / 150 - ((3 * def2) / 10) - 1));
 		vit_def += (def2 / 2);
 #else
 		vit_def = def2;
@@ -6612,7 +6623,9 @@ static void battle_calc_defense_reduction(struct Damage* wd, struct block_list *
 				return;
 			if (is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_R) || is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_L))
 				return;
-
+			[[fallthrough]];
+		case CR_GRANDCROSS: // Grand Cross is marked as "IgnoreDefense" in renewal as it's applied at the end after already combining ATK and MATK
+		case NPC_GRANDDARKNESS:
 			// Defense reduction by flat value.
 			// This completely bypasses the normal RE DEF Reduction formula.
 			wd->damage -= (def1 + vit_def);
@@ -6791,18 +6804,16 @@ static void battle_calc_attack_left_right_hands(struct Damage* wd, struct block_
 	if (sd) {
 		int skill;
 
-		if (!is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id)) {
-			wd->damage = wd->damage2;
-			wd->damage2 = 0;
-		} else if(sd->status.weapon == W_KATAR && !skill_id) { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2)
+		if(sd->status.weapon == W_KATAR && !skill_id) { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2)
 			skill = pc_checkskill(sd,TF_DOUBLE);
 			wd->damage2 = (int64)wd->damage * (1 + (skill * 2))/100;
 #ifdef RENEWAL
-		} else if(is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id) && sd->status.weapon != W_KATAR) {	//Dual-wield
+		} else if(is_attack_left_handed(src, skill_id) && sd->status.weapon != W_KATAR) {	//Dual-wield
 #else
-		} else if(is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id)) {	//Dual-wield
+		} else if(is_attack_left_handed(src, skill_id)) {	//Dual-wield
 #endif
-			if (wd->damage) {
+			// If you only have a weapon in the left hand, then your main hand damage will be identical to an unarmed attack
+			if (is_attack_right_handed(src, skill_id) && wd->damage) {
 				if( (sd->class_&MAPID_BASEMASK) == MAPID_THIEF ) {
 					skill = pc_checkskill(sd,AS_RIGHT);
 					ATK_RATER(wd->damage, 50 + (skill * 10))
@@ -6814,6 +6825,7 @@ static void battle_calc_attack_left_right_hands(struct Damage* wd, struct block_
 				if(wd->damage < 1)
 					wd->damage = 1;
 			}
+			// Left hand damage will always be adjusted, even if you don't have a weapon in the main hand
 			if (wd->damage2) {
 				if( (sd->class_&MAPID_BASEMASK) == MAPID_THIEF) {
 					skill = pc_checkskill(sd,AS_LEFT);
@@ -6946,7 +6958,7 @@ static void battle_calc_weapon_final_atk_modifiers(struct Damage* wd, struct blo
 	{
 		ATK_RATER(wd->damage, 50)
 		clif_skill_nodamage(target,target,ST_REJECTSWORD, tsc->getSCE(SC_REJECTSWORD)->val1,1);
-		status_fix_damage(target,src,wd->damage,clif_damage(target,src,gettick(),0,0,wd->damage,0,DMG_NORMAL,0,false),ST_REJECTSWORD);
+		battle_fix_damage(target,src,wd->damage,clif_damage(target,src,gettick(),0,0,wd->damage,0,DMG_NORMAL,0,false),ST_REJECTSWORD);
 		if (status_isdead(target))
 			return;
 		if( --(tsc->getSCE(SC_REJECTSWORD)->val3) <= 0 )
@@ -6964,7 +6976,7 @@ static void battle_calc_weapon_final_atk_modifiers(struct Damage* wd, struct blo
 		clif_skill_damage(target, src, gettick(), status_get_amotion(src), 0, rdamage,
 			1, SR_CRESCENTELBOW_AUTOSPELL, tsc->getSCE(SC_CRESCENTELBOW)->val1, DMG_SINGLE); // This is how official does
 		clif_damage(src, target, gettick(), status_get_amotion(src)+1000, 0, rdamage/10, 1, DMG_NORMAL, 0, false);
-		status_damage(target, src, rdamage, 0, 0, 0, 0);
+		battle_fix_damage(target, src, rdamage, 0, SR_CRESCENTELBOW);
 		status_damage(src, target, rdamage/10, 0, 0, 1, 0);
 		status_change_end(target, SC_CRESCENTELBOW);
 	}
@@ -7043,10 +7055,12 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
 	wd.flag = BF_WEAPON; //Initial Flag
 	wd.flag |= (skill_id||wd.miscflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish]
 	wd.isspdamage = false;
-	wd.damage = wd.damage2 = wd.basedamage =
+	wd.damage = wd.damage2 =
 #ifdef RENEWAL
 	wd.statusAtk = wd.statusAtk2 = wd.equipAtk = wd.equipAtk2 = wd.weaponAtk = wd.weaponAtk2 = wd.masteryAtk = wd.masteryAtk2 =
 	wd.percentAtk = wd.percentAtk2 =
+#else
+	wd.basedamage =
 #endif
 	0;
 
@@ -7324,11 +7338,13 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 		wd.dmg_lv = ATK_FLEE;
 	else if(!(infdef = is_infinite_defense(target, wd.flag))) { //no need for math against plants
 
+#ifndef RENEWAL
 		// First call function with skill_id 0 to get base damage of a normal attack
 		battle_calc_skill_base_damage(&wd, src, target, 0, 0); // base damage
 		wd.basedamage = wd.damage;
 		// Now get actual skill damage
 		if (skill_id != 0)
+#endif
 			battle_calc_skill_base_damage(&wd, src, target, skill_id, skill_lv); // base skill damage
 
 		int64 ratio = 0;
@@ -7518,9 +7534,6 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 
 	battle_calc_element_damage(&wd, src, target, skill_id, skill_lv);
 
-	if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS)
-		return wd; //Enough, rest is not needed.
-
 #ifdef RENEWAL
 	if (is_attack_critical(&wd, src, target, skill_id, skill_lv, false)) {
 		if (sd) { //Check for player so we don't crash out, monsters don't have bonus crit rates [helvetica]
@@ -7691,7 +7704,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 		return ad;
 	}
 	//Initial Values
-	ad.damage = 1;
+	ad.damage = 0;
 	ad.div_ = skill_get_num(skill_id,skill_lv);
 	ad.amotion = (skill_get_inf(skill_id)&INF_GROUND_SKILL ? 0 : sstatus->amotion); //Amotion should be 0 for ground skills.
 	ad.dmotion = tstatus->dmotion;
@@ -8793,6 +8806,46 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 				ad.damage = ad.damage * (100-mdef)/100 - mdef2;
 #endif
 		}
+
+		//Apply the physical part of the skill's damage. [Skotlex]
+		switch (skill_id) {
+			case CR_GRANDCROSS:
+			case NPC_GRANDDARKNESS: {
+				// Pre-re ATK = Take atk, apply def reduction and add refine bonus
+				// Final Damage = (ATK+MATK)*RATIO
+				// Renewal ATK = Take total atk
+				// Final Damage = ((ATK+MATK)/2)*RATIO - (tDEF + tMDEF)
+				// No need to go through the whole physical damage code
+				struct Damage wd = initialize_weapon_data(src, target, skill_id, skill_lv, mflag);
+				battle_calc_skill_base_damage(&wd, src, target, skill_id, skill_lv);
+				// Calculate ATK
+#ifdef RENEWAL
+				if (sd)
+					wd.damage = wd.statusAtk + wd.weaponAtk + wd.equipAtk + wd.percentAtk;
+#else
+				battle_calc_defense_reduction(&wd, src, target, skill_id, skill_lv);
+				if (sd) {
+					wd.damage += sstatus->rhw.atk2;
+				}
+#endif
+				// Combine ATK and MATK
+#ifdef RENEWAL
+				ad.damage = (wd.damage + ad.damage) / 2;
+#else
+				ad.damage = std::max((int64)1, wd.damage + ad.damage);
+#endif
+				// Ratio
+				skillratio += 40 * skill_lv;
+				MATK_RATE(skillratio);
+#ifdef RENEWAL
+				// Total defense reduction (renewal only)
+				battle_calc_defense_reduction(&ad, src, target, skill_id, skill_lv);
+				ad.damage -= (tstatus->mdef + tstatus->mdef2);
+#endif
+			}
+			break;
+		}
+
 		if(ad.damage<1)
 			ad.damage=1;
 		else if(sc) { //only applies when hit
@@ -8823,26 +8876,26 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 		if (!nk[NK_IGNOREELEMENT])
 			ad.damage = battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
 
-		//Apply the physical part of the skill's damage. [Skotlex]
-		switch(skill_id) {
-			case CR_GRANDCROSS:
-			case NPC_GRANDDARKNESS: {
-					struct Damage wd = battle_calc_weapon_attack(src,target,skill_id,skill_lv,mflag);
+#ifndef RENEWAL
+		ad.damage += battle_calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag);
+#endif
 
-					ad.damage = battle_attr_fix(src, target, wd.damage + ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv) * (100 + 40 * skill_lv) / 100;
-					if(src == target) {
-						if(src->type == BL_PC)
-							ad.damage = ad.damage / 2;
-						else
-							ad.damage = 0;
-					}
+		switch (skill_id) {
+			case CR_GRANDCROSS:
+			case NPC_GRANDDARKNESS:
+				if (src == target) {
+					// Grand Cross on self first applies attr_fix, then cardfix and finally halves the damage
+					if (src->type == BL_PC)
+						ad.damage = ad.damage / 2;
+					else
+						ad.damage = 0;
 				}
+				else
+					// Grand Cross on target applies attr_fix, then cardfix and then attr_fix a second time
+					ad.damage = battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
 				break;
 		}
 
-#ifndef RENEWAL
-		ad.damage += battle_calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag);
-#endif
 	} //Hint: Against plants damage will still be 1 at this point
 
 	//Apply DAMAGE_DIV_FIX and check for min damage
@@ -8921,7 +8974,10 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 
 	switch (skill_id) {
 		case TF_THROWSTONE:
-			md.damage = 50;
+			if (sd)
+				md.damage = 50;
+			else
+				md.damage = 30;
 			md.flag |= BF_WEAPON;
 			break;
 		case NPC_KILLING_AURA:
@@ -9461,6 +9517,36 @@ int64 battle_calc_return_damage(struct block_list* tbl, struct block_list *src,
 		return cap_value(rdamage, 1, status_get_max_hp(tbl));
 }
 
+/** Check for Coma damage
+ * @param sd: Source player
+ * @param bl: Target
+ * @param attack_type: Attack type
+ * @return True if Coma applies, false if Coma does not apply
+ */
+bool battle_check_coma(map_session_data& sd, struct block_list& target, e_battle_flag attack_type)
+{
+	struct status_data* tstatus = status_get_status_data(&target);
+	mob_data* dstmd = BL_CAST(BL_MOB, &target);
+
+	// Coma
+	if (sd.special_state.bonus_coma && (!dstmd || (!util::vector_exists(status_get_race2(&dstmd->bl), RC2_GVG) && status_get_class(&dstmd->bl) != CLASS_BATTLEFIELD))) {
+		int rate = 0;
+		rate += sd.indexed_bonus.coma_class[tstatus->class_] + sd.indexed_bonus.coma_class[CLASS_ALL];
+		if(!status_bl_has_mode(&target, MD_STATUSIMMUNE))
+			rate += sd.indexed_bonus.coma_race[tstatus->race] + sd.indexed_bonus.coma_race[RC_ALL];
+		if (attack_type&BF_WEAPON) {
+			rate += sd.indexed_bonus.weapon_coma_class[tstatus->class_] + sd.indexed_bonus.weapon_coma_class[CLASS_ALL];
+			if (!status_bl_has_mode(&target, MD_STATUSIMMUNE)) {
+				rate += sd.indexed_bonus.weapon_coma_ele[tstatus->def_ele] + sd.indexed_bonus.weapon_coma_ele[ELE_ALL];
+				rate += sd.indexed_bonus.weapon_coma_race[tstatus->race] + sd.indexed_bonus.weapon_coma_race[RC_ALL];
+			}
+		}
+		if (rate > 0 && rnd_chance(rate, 10000))
+			return true;
+	}
+	return false;
+}
+
 /**
  * Calculate Vellum damage on a target
  * @param sd: Player with vanish item
@@ -9595,7 +9681,7 @@ int battle_damage_area(struct block_list *bl, va_list ap) {
 		if( amotion )
 			battle_delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0,true,false);
 		else
-			status_fix_damage(src,bl,damage,0,LG_REFLECTDAMAGE);
+			battle_fix_damage(src,bl,damage,0,LG_REFLECTDAMAGE);
 		clif_damage(bl,bl,tick,amotion,dmotion,damage,1,DMG_ENDURE,0,false);
 		skill_additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
 		map_freeblock_unlock();
@@ -9962,7 +10048,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 						devotion_damage -= devotion_damage * d_sc->getSCE(SC_REBOUND_S)->val2 / 100;
 
 					clif_damage(d_bl, d_bl, gettick(), wd.amotion, wd.dmotion, devotion_damage, 1, DMG_NORMAL, 0, false);
-					status_fix_damage(NULL, d_bl, devotion_damage, 0, CR_DEVOTION);
+					battle_fix_damage(src, d_bl, devotion_damage, 0, CR_DEVOTION);
 				}
 			}
 			else
@@ -9981,7 +10067,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 
 			if (e_bl && !status_isdead(e_bl)) {
 				clif_damage(e_bl, e_bl, tick, 0, 0, damage, wd.div_, DMG_NORMAL, 0, false);
-				status_fix_damage(NULL, e_bl, damage, 0, EL_WATER_SCREEN);
+				battle_fix_damage(src, e_bl, damage, 0, EL_WATER_SCREEN);
 			}
 		}
 	}
@@ -11037,7 +11123,7 @@ static const struct _battle_data {
 	{ "skill_steal_random_options",         &battle_config.skill_steal_random_options,      0,      0,      1,              },
 	{ "motd_type",                          &battle_config.motd_type,                       0,      0,      1,              },
 	{ "finding_ore_rate",                   &battle_config.finding_ore_rate,                100,    0,      INT_MAX,        },
-	{ "exp_calc_type",                      &battle_config.exp_calc_type,                   0,      0,      1,              },
+	{ "exp_calc_type",                      &battle_config.exp_calc_type,                   0,      0,      2,              },
 	{ "exp_bonus_attacker",                 &battle_config.exp_bonus_attacker,              25,     0,      INT_MAX,        },
 	{ "exp_bonus_max_attacker",             &battle_config.exp_bonus_max_attacker,          12,     2,      INT_MAX,        },
 	{ "min_skill_delay_limit",              &battle_config.min_skill_delay_limit,           100,    10,     INT_MAX,        },
@@ -11095,8 +11181,8 @@ static const struct _battle_data {
 	{ "day_duration",                       &battle_config.day_duration,                    0,      0,      INT_MAX,        },
 	{ "night_duration",                     &battle_config.night_duration,                  0,      0,      INT_MAX,        },
 	{ "mob_remove_delay",                   &battle_config.mob_remove_delay,                60000,  1000,   INT_MAX,        },
-	{ "mob_active_time",                    &battle_config.mob_active_time,                 0,      0,      INT_MAX,        },
-	{ "boss_active_time",                   &battle_config.boss_active_time,                0,      0,      INT_MAX,        },
+	{ "mob_active_time",                    &battle_config.mob_active_time,                 5000,   0,      INT_MAX,        },
+	{ "boss_active_time",                   &battle_config.boss_active_time,                5000,   0,      INT_MAX,        },
 	{ "sg_miracle_skill_duration",          &battle_config.sg_miracle_skill_duration,       3600000, 0,     INT_MAX,        },
 	{ "hvan_explosion_intimate",            &battle_config.hvan_explosion_intimate,         45000,  0,      100000,         },
 	{ "quest_exp_rate",                     &battle_config.quest_exp_rate,                  100,    0,      INT_MAX,        },
@@ -11340,6 +11426,7 @@ static const struct _battle_data {
 	{ "feature.dynamicnpc_direction",       &battle_config.feature_dynamicnpc_direction,    0,      0,      1,              },
 
 	{ "mob_respawn_time",                   &battle_config.mob_respawn_time,                1000,   1000,   INT_MAX,        },
+	{ "mob_unlock_time",                    &battle_config.mob_unlock_time,                 2000,   0,      INT_MAX,        },
 
 	{ "feature.stylist",                    &battle_config.feature_stylist,                 1,      0,      1,              },
 	{ "feature.banking_state_enforce",      &battle_config.feature_banking_state_enforce,   0,      0,      1,              },

+ 7 - 3
src/map/battle.hpp

@@ -89,10 +89,11 @@ enum e_bonus_chk_flag : uint8 {
 struct Damage {
 #ifdef RENEWAL
 	int64 statusAtk, statusAtk2, weaponAtk, weaponAtk2, equipAtk, equipAtk2, masteryAtk, masteryAtk2, percentAtk, percentAtk2;
+#else
+	int64 basedamage; /// Right hand damage that a normal attack would deal
 #endif
 	int64 damage, /// Right hand damage
-		damage2, /// Left hand damage
-		basedamage; /// Right hand damage that a normal attack would deal
+		damage2; /// Left hand damage
 	enum e_damage_type type; /// Check clif_damage for type
 	short div_; /// Number of hit
 	int amotion,
@@ -121,8 +122,9 @@ int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64
 int64 battle_calc_bg_damage(struct block_list *src,struct block_list *bl,int64 damage,uint16 skill_id,int flag);
 int64 battle_calc_pk_damage(block_list &src, block_list &bl, int64 damage, uint16 skill_id, int flag);
 
-void battle_damage(struct block_list *src, struct block_list *target, int64 damage, t_tick delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, t_tick tick, bool spdamage);
+int battle_damage(struct block_list *src, struct block_list *target, int64 damage, t_tick delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, t_tick tick, bool spdamage);
 int battle_delay_damage (t_tick tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, t_tick ddelay, bool additional_effects, bool spdamage);
+int battle_fix_damage(struct block_list* src, struct block_list* target, int64 damage, t_tick walkdelay, uint16 skill_id);
 
 int battle_calc_chorusbonus(map_session_data *sd);
 
@@ -139,6 +141,7 @@ uint16 battle_getcurrentskill(struct block_list *bl);
 int battle_check_undead(int race,int element);
 int battle_check_target(struct block_list *src, struct block_list *target,int flag);
 bool battle_check_range(struct block_list *src,struct block_list *bl,int range);
+bool battle_check_coma(map_session_data& sd, struct block_list& target, e_battle_flag attack_type);
 
 void battle_consume_ammo(map_session_data* sd, int skill, int lv);
 
@@ -727,6 +730,7 @@ struct Battle_Config
 	int feature_dynamicnpc_direction;
 
 	int mob_respawn_time;
+	int mob_unlock_time;
 
 	int feature_stylist;
 	int feature_banking_state_enforce;

+ 1 - 1
src/map/battleground.cpp

@@ -720,7 +720,7 @@ int bg_team_get_id(struct block_list *bl)
  * @param mes: Message
  * @param len: Message length
  */
-void bg_send_message(map_session_data *sd, const char *mes, int len)
+void bg_send_message(map_session_data *sd, const char *mes, size_t len)
 {
 	nullpo_retv(sd);
 

+ 1 - 1
src/map/battleground.hpp

@@ -153,7 +153,7 @@ bool bg_queue_on_ready(const char *name, std::shared_ptr<s_battleground_queue> q
 void bg_queue_on_accept_invite(map_session_data *sd);
 void bg_queue_start_battleground(std::shared_ptr<s_battleground_queue> queue);
 bool bg_member_respawn(map_session_data *sd);
-void bg_send_message(map_session_data *sd, const char *mes, int len);
+void bg_send_message(map_session_data *sd, const char *mes, size_t len);
 
 void do_init_battleground(void);
 void do_final_battleground(void);

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 244 - 260
src/map/clif.cpp


+ 11 - 11
src/map/clif.hpp

@@ -708,7 +708,7 @@ void clif_divorced(map_session_data* sd, const char* name);
 void clif_callpartner(map_session_data& sd);
 void clif_playBGM( map_session_data& sd, const char* name );
 void clif_soundeffect( struct block_list& bl, const char* name, int type, enum send_target target );
-void clif_parse_ActionRequest_sub(map_session_data *sd, int action_type, int target_id, t_tick tick);
+void clif_parse_ActionRequest_sub( map_session_data& sd, int action_type, int target_id, t_tick tick );
 void clif_parse_LoadEndAck(int fd,map_session_data *sd);
 void clif_hotkeys_send(map_session_data *sd, int tab);
 
@@ -780,7 +780,7 @@ void clif_status_change(struct block_list *bl, int type, int flag, t_tick tick,
 void clif_efst_status_change(struct block_list *bl, int tid, enum send_target target, int type, t_tick tick, int val1, int val2, int val3);
 void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl, enum send_target target);
 
-void clif_wis_message(map_session_data* sd, const char* nick, const char* mes, int mes_len, int gmlvl);
+void clif_wis_message(map_session_data* sd, const char* nick, const char* mes, size_t mes_len, int gmlvl);
 void clif_wis_end(int fd, int result);
 
 void clif_solved_charname(int fd, int charid, const char* name);
@@ -802,7 +802,7 @@ void clif_clearcart(int fd);
 
 void clif_item_identify_list(map_session_data *sd);
 void clif_item_identified(map_session_data *sd,int idx,int flag);
-void clif_item_repair_list(map_session_data *sd, map_session_data *dstsd, int lv);
+void clif_item_repair_list( map_session_data& sd, map_session_data& dstsd, uint16 lv );
 void clif_item_repaireffect(map_session_data *sd, int idx, int flag);
 void clif_item_damaged(map_session_data* sd, unsigned short position);
 void clif_item_refine_list(map_session_data *sd);
@@ -836,7 +836,7 @@ void clif_party_invite( map_session_data& sd, map_session_data& tsd );
 void clif_party_invite_reply( map_session_data& sd, const char* nick, enum e_party_invite_reply reply );
 void clif_party_option(struct party_data *p,map_session_data *sd,int flag);
 void clif_party_withdraw( map_session_data& sd, uint32 account_id, const char* name, enum e_party_member_withdraw result, enum send_target target );
-void clif_party_message( struct party_data& party, uint32 account_id, const char* mes, int len );
+void clif_party_message( struct party_data& party, uint32 account_id, const char* mes, size_t len );
 void clif_party_xy( map_session_data& sd );
 void clif_party_xy_single( map_session_data& sd, map_session_data& tsd );
 void clif_party_hp( map_session_data& sd );
@@ -880,7 +880,7 @@ void clif_guild_castle_teleport_res(map_session_data& sd, enum e_siege_teleport_
 void clif_bg_hp(map_session_data *sd);
 void clif_bg_xy(map_session_data *sd);
 void clif_bg_xy_remove(map_session_data *sd);
-void clif_bg_message(struct s_battleground_data *bg, int src_id, const char *name, const char *mes, int len);
+void clif_bg_message(struct s_battleground_data *bg, int src_id, const char *name, const char *mes, size_t len);
 void clif_bg_updatescore(int16 m);
 void clif_bg_updatescore_single(map_session_data *sd);
 void clif_sendbgemblem_area(map_session_data *sd);
@@ -906,9 +906,9 @@ void clif_font(map_session_data *sd);
 
 // atcommand
 void clif_displaymessage(const int fd, const char* mes);
-void clif_disp_message(struct block_list* src, const char* mes, int len, enum send_target target);
-void clif_broadcast(struct block_list* bl, const char* mes, int len, int type, enum send_target target);
-void clif_broadcast2(struct block_list* bl, const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target);
+void clif_disp_message(struct block_list* src, const char* mes, size_t len, enum send_target target);
+void clif_broadcast(struct block_list* bl, const char* mes, size_t len, int type, enum send_target target);
+void clif_broadcast2(struct block_list* bl, const char* mes, size_t len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target);
 void clif_heal(int fd,int type,int val);
 void clif_resurrection(struct block_list *bl,int type);
 void clif_map_property(struct block_list *bl, enum map_property property, enum send_target t);
@@ -1100,11 +1100,11 @@ void clif_elementalconverter_list(map_session_data *sd);
 
 void clif_millenniumshield(struct block_list *bl, short shields);
 
-void clif_magicdecoy_list(map_session_data *sd, uint16 skill_lv, short x, short y);
+void clif_magicdecoy_list( map_session_data& sd, uint16 skill_lv, short x, short y );
 
-void clif_poison_list(map_session_data *sd, uint16 skill_lv);
+void clif_poison_list( map_session_data& sd, uint16 skill_lv );
 
-int clif_autoshadowspell_list(map_session_data *sd);
+void clif_autoshadowspell_list( map_session_data& sd );
 
 int clif_skill_itemlistwindow( map_session_data *sd, uint16 skill_id, uint16 skill_lv );
 void clif_elemental_info(map_session_data *sd);

+ 5 - 8
src/map/clif_packetdb.hpp

@@ -57,7 +57,6 @@
 	packet(0x0093,2);
 	parseable_packet(0x0094,6,clif_parse_GetCharNameRequest,2);
 	parseable_packet(0x0096,-1,clif_parse_WisMessage,2,4,28);
-	packet(0x0097,-1);
 	packet(0x0098,3);
 	parseable_packet(0x0099,-1,clif_parse_Broadcast,2,4);
 	packet(0x009a,-1);
@@ -1334,7 +1333,6 @@
 
 // 2008-12-10aSakexe
 #if PACKETVER >= 20081210
-	packet(0x0442,-1);
 	parseable_packet(0x0443,8,clif_parse_SkillSelectMenu,2,6);
 #endif
 
@@ -1412,7 +1410,6 @@
 	packet(0x01a2,37);
 	//packet(0x0440,10);
 	//packet(0x0441,4);
-	//packet(0x0442,8);
 	//packet(0x0443,8);
 #endif
 
@@ -2041,11 +2038,11 @@
 
 // 2013-07-17Ragexe
 #if PACKETVER >= 20130717
-	parseable_packet(0x09A7,10,clif_parse_BankDeposit,2,6);
-	parseable_packet(0x09A9,10,clif_parse_BankWithdraw,2,6);
-	parseable_packet(0x09AB,6,clif_parse_BankCheck,2);
-	parseable_packet(0x09B6,6,clif_parse_BankOpen,2);
-	parseable_packet(0x09B8,6,clif_parse_BankClose,2);
+	parseable_packet( HEADER_CZ_REQ_BANKING_DEPOSIT, sizeof( PACKET_CZ_REQ_BANKING_DEPOSIT ), clif_parse_BankDeposit, 0 );
+	parseable_packet( HEADER_CZ_REQ_BANKING_WITHDRAW, sizeof( PACKET_CZ_REQ_BANKING_WITHDRAW ), clif_parse_BankWithdraw, 0 );
+	parseable_packet( HEADER_CZ_REQ_BANKING_CHECK, sizeof( PACKET_CZ_REQ_BANKING_CHECK ), clif_parse_BankCheck, 0 );
+	parseable_packet( HEADER_CZ_REQ_OPEN_BANKING, sizeof( PACKET_CZ_REQ_OPEN_BANKING ), clif_parse_BankOpen, 0 );
+	parseable_packet( HEADER_CZ_REQ_CLOSE_BANKING, sizeof( PACKET_CZ_REQ_CLOSE_BANKING ), clif_parse_BankClose, 0 );
 #endif
 
 // 2013-07-31cRagexe

+ 14 - 5
src/map/elemental.cpp

@@ -316,7 +316,7 @@ int elemental_action(s_elemental_data *ed, block_list *bl, t_tick tick) {
 	uint16 skill_id = skill->id;
 	uint16 skill_lv = skill->lv;
 
-	if( elemental_skillnotok(skill_id, ed) )
+	if( elemental_skillnotok(skill_id, *ed) )
 		return 0;
 
 	if( ed->ud.skilltimer != INVALID_TIMER )
@@ -389,7 +389,7 @@ int elemental_change_mode_ack(s_elemental_data *ed, e_elemental_skillmode skill_
 	uint16 skill_id = skill->id;
 	uint16 skill_lv = skill->lv;
 
-	if( elemental_skillnotok(skill_id, ed) )
+	if( elemental_skillnotok(skill_id, *ed) )
 		return 0;
 
 	if( ed->ud.skilltimer != INVALID_TIMER )
@@ -460,10 +460,19 @@ int elemental_unlocktarget(s_elemental_data *ed) {
 	return 0;
 }
 
-bool elemental_skillnotok(uint16 skill_id, s_elemental_data *ed) {
+bool elemental_skillnotok( uint16 skill_id, s_elemental_data& ed ){
 	uint16 idx = skill_get_index(skill_id);
-	nullpo_retr(1,ed);
-	return idx == 0 ? false : skill_isNotOk(skill_id,ed->master); // return false or check if it,s ok for master as well
+
+	if( idx == 0 ){
+		return false;
+	}
+
+	// Check if it's ok for master as well
+	if( ed.master != nullptr ){
+		return skill_isNotOk( skill_id, *ed.master );
+	}else{
+		return true;
+	}
 }
 
 struct s_skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv){

+ 1 - 1
src/map/elemental.hpp

@@ -123,7 +123,7 @@ void elemental_summon_stop(s_elemental_data *ed);
 t_tick elemental_get_lifetime(s_elemental_data *ed);
 
 int elemental_unlocktarget(s_elemental_data *ed);
-bool elemental_skillnotok(uint16 skill_id, s_elemental_data *ed);
+bool elemental_skillnotok( uint16 skill_id, s_elemental_data& ed );
 int elemental_set_target( map_session_data *sd, block_list *bl );
 int elemental_clean_effect(s_elemental_data *ed);
 int elemental_action(s_elemental_data *ed, block_list *bl, t_tick tick);

+ 8 - 19
src/map/guild.cpp

@@ -1370,7 +1370,7 @@ int guild_recv_memberinfoshort(int guild_id,uint32 account_id,uint32 char_id,int
 /*====================================================
  * Send a message to whole guild
  *---------------------------------------------------*/
-int guild_send_message(map_session_data *sd,const char *mes,int len) {
+int guild_send_message(map_session_data *sd, const char *mes, size_t len) {
 	nullpo_ret(sd);
 
 	if(sd->status.guild_id==0)
@@ -1481,17 +1481,11 @@ int guild_notice_changed(int guild_id,const char *mes1,const char *mes2) {
 /*====================================================
  * Check condition for changing guild emblem
  *---------------------------------------------------*/
-bool guild_check_emblem_change_condition(map_session_data *sd)
-{
-	// TODO: Change sd to reference
-	if( sd == nullptr ){
-		return false;
-	}
-
-	auto &g = sd->guild;
+bool guild_check_emblem_change_condition( map_session_data& sd ){
+	auto &g = sd.guild;
 
 	if (battle_config.require_glory_guild && g != nullptr && guild_checkskill(g->guild, GD_GLORYGUILD) > 0) {
-		clif_skill_fail( *sd, GD_GLORYGUILD );
+		clif_skill_fail( sd, GD_GLORYGUILD );
 		return false;
 	}
 
@@ -1501,28 +1495,23 @@ bool guild_check_emblem_change_condition(map_session_data *sd)
 /*====================================================
  * Change guild emblem
  *---------------------------------------------------*/
-int guild_change_emblem(map_session_data *sd,int len,const char *data) {
-	nullpo_ret(sd);
-
+int guild_change_emblem( map_session_data& sd, int len, const char* data ){
 	if (!guild_check_emblem_change_condition(sd)) {
 		return 0;
 	}
 
-	return intif_guild_emblem(sd->status.guild_id,len,data);
+	return intif_guild_emblem( sd.status.guild_id, len, data );
 }
 
 /*====================================================
  * Change guild emblem version
  *---------------------------------------------------*/
-int guild_change_emblem_version(map_session_data* sd, int version)
-{
-	nullpo_ret(sd);
-
+int guild_change_emblem_version( map_session_data& sd, int version ){
 	if (!guild_check_emblem_change_condition(sd)) {
 		return 0;
 	}
 
-	return intif_guild_emblem_version(sd->status.guild_id, version);
+	return intif_guild_emblem_version( sd.status.guild_id, version );
 }
 
 /*====================================================

+ 3 - 3
src/map/guild.hpp

@@ -87,10 +87,10 @@ int guild_change_position(int guild_id,int idx,int mode,int exp_mode,const char
 int guild_position_changed(int guild_id,int idx,struct guild_position *p);
 int guild_change_notice(map_session_data *sd,int guild_id,const char *mes1,const char *mes2);
 int guild_notice_changed(int guild_id,const char *mes1,const char *mes2);
-int guild_change_emblem(map_session_data *sd,int len,const char *data);
-int guild_change_emblem_version(map_session_data* sd, int version);
+int guild_change_emblem( map_session_data& sd, int len, const char* data );
+int guild_change_emblem_version( map_session_data& sd, int version );
 int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data);
-int guild_send_message(map_session_data *sd,const char *mes,int len);
+int guild_send_message(map_session_data *sd, const char *mes, size_t len);
 int guild_recv_message(int guild_id,uint32 account_id,const char *mes,int len);
 int guild_send_dot_remove(map_session_data *sd);
 int guild_skillupack(int guild_id,uint16 skill_id,uint32 account_id);

+ 6 - 6
src/map/intif.cpp

@@ -310,7 +310,7 @@ int intif_main_message(map_session_data* sd, const char* message)
  * @param mes_len : Size of message
  * @return 0=Message not send, 1=Message send
  */
-int intif_wis_message(map_session_data *sd, char *nick, char *mes, int mes_len)
+int intif_wis_message(map_session_data *sd, char *nick, char *mes, size_t mes_len)
 {
 	int headersize = 8 + 2 * NAME_LENGTH;
 
@@ -326,7 +326,7 @@ int intif_wis_message(map_session_data *sd, char *nick, char *mes, int mes_len)
 
 	WFIFOHEAD(inter_fd,mes_len + headersize);
 	WFIFOW(inter_fd,0) = 0x3001;
-	WFIFOW(inter_fd,2) = mes_len + headersize;
+	WFIFOW(inter_fd,2) = static_cast<int16>( mes_len + headersize);
 	WFIFOL(inter_fd,4) = pc_get_group_level(sd);
 	safestrncpy(WFIFOCP(inter_fd,8), sd->status.name, NAME_LENGTH);
 	safestrncpy(WFIFOCP(inter_fd,8+NAME_LENGTH), nick, NAME_LENGTH);
@@ -748,7 +748,7 @@ int intif_break_party(int party_id)
  * @param len : Size of the message
  * @return 0=error, 1=msg sent
  */
-int intif_party_message(int party_id,uint32 account_id,const char *mes,int len)
+int intif_party_message(int party_id, uint32 account_id, const char *mes, size_t len)
 {
 	if (CheckForCharServer())
 		return 0;
@@ -758,7 +758,7 @@ int intif_party_message(int party_id,uint32 account_id,const char *mes,int len)
 
 	WFIFOHEAD(inter_fd,len + 12);
 	WFIFOW(inter_fd,0)=0x3027;
-	WFIFOW(inter_fd,2)=len+12;
+	WFIFOW(inter_fd,2)=static_cast<int16>( len + 12 );
 	WFIFOL(inter_fd,4)=party_id;
 	WFIFOL(inter_fd,8)=account_id;
 	safestrncpy(WFIFOCP(inter_fd,12),mes,len);
@@ -954,7 +954,7 @@ int intif_guild_break(int guild_id)
  * @param len : Size of the message
  * @return 0=error, 1=msg_sent
  */
-int intif_guild_message(int guild_id,uint32 account_id,const char *mes,int len)
+int intif_guild_message(int guild_id, uint32 account_id, const char *mes, size_t len)
 {
 	if (CheckForCharServer())
 		return 0;
@@ -964,7 +964,7 @@ int intif_guild_message(int guild_id,uint32 account_id,const char *mes,int len)
 
 	WFIFOHEAD(inter_fd, len + 12);
 	WFIFOW(inter_fd,0)=0x3037;
-	WFIFOW(inter_fd,2)=len+12;
+	WFIFOW(inter_fd,2)=static_cast<int16>( len + 12 );
 	WFIFOL(inter_fd,4)=guild_id;
 	WFIFOL(inter_fd,8)=account_id;
 	safestrncpy(WFIFOCP(inter_fd,12),mes,len);

+ 3 - 3
src/map/intif.hpp

@@ -29,7 +29,7 @@ int intif_broadcast_obtain_special_item(map_session_data *sd, t_itemid nameid, u
 int intif_broadcast_obtain_special_item_npc(map_session_data *sd, t_itemid nameid);
 int intif_main_message(map_session_data* sd, const char* message);
 
-int intif_wis_message(map_session_data *sd,char *nick,char *mes,int mes_len);
+int intif_wis_message(map_session_data *sd, char *nick, char *mes, size_t mes_len);
 int intif_wis_message_to_gm(char *Wisp_name, int permission, char *mes);
 
 int intif_saveregistry(map_session_data *sd);
@@ -46,7 +46,7 @@ int intif_party_changeoption(int party_id, uint32 account_id, int exp, int item)
 int intif_party_leave(int party_id, uint32 account_id, uint32 char_id, const char *name, enum e_party_member_withdraw type);
 int intif_party_changemap(map_session_data *sd, int online);
 int intif_break_party(int party_id);
-int intif_party_message(int party_id, uint32 account_id, const char *mes,int len);
+int intif_party_message(int party_id, uint32 account_id, const char *mes, size_t len);
 int intif_party_leaderchange(int party_id,uint32 account_id,uint32 char_id);
 int intif_party_sharelvlupdate(unsigned int share_lvl);
 
@@ -56,7 +56,7 @@ int intif_guild_addmember(int guild_id, struct guild_member *m);
 int intif_guild_leave(int guild_id, uint32 account_id, uint32 char_id, int flag, const char *mes);
 int intif_guild_memberinfoshort(int guild_id, uint32 account_id, uint32 char_id, int online, int lv, int class_);
 int intif_guild_break(int guild_id);
-int intif_guild_message(int guild_id, uint32 account_id, const char *mes, int len);
+int intif_guild_message(int guild_id, uint32 account_id, const char *mes, size_t len);
 int intif_guild_change_gm(int guild_id, const char* name, int len);
 int intif_guild_change_basicinfo(int guild_id, int type, const void *data, int len);
 int intif_guild_change_memberinfo(int guild_id, uint32 account_id, uint32 char_id, int type, const void *data, int len);

+ 33 - 21
src/map/mob.cpp

@@ -1164,6 +1164,7 @@ int mob_spawn (struct mob_data *md)
 	md->last_linktime = tick;
 	md->dmgtick = tick - 5000;
 	md->last_pcneartime = 0;
+	md->last_canmove = tick;
 
 	t_tick c = tick - MOB_MAX_DELAY;
 
@@ -1720,6 +1721,8 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
 	mode = status_get_mode(&md->bl);
 
 	can_move = (mode&MD_CANMOVE) && unit_can_move(&md->bl);
+	if (can_move)
+		md->last_canmove = tick;
 
 	if (md->target_id)
 	{	//Check validity of current target. [Skotlex]
@@ -1956,13 +1959,21 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
 		&& mob_is_chasing(md->state.skillstate))
 		return true;
 
-	//Out of range...
-	if (!(mode&MD_CANMOVE) || (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0))
-	{	//Can't chase. Immobile and trapped mobs should unlock target and use an idle skill.
+	// Out of range
+	if (!(mode&MD_CANMOVE) || (!can_move && (md->sc.cant.move || DIFF_TICK(tick, md->ud.canmove_tick) > 0)))
+	{	// Can't chase. Immobile and trapped mobs will use idle skills and unlock their target after a while
 		if (md->ud.attacktimer == INVALID_TIMER)
-		{ //Only unlock target if no more attack delay left
-			//This handles triggering idle/walk skill.
-			mob_unlocktarget(md,tick);
+		{ // Only switch mode if no more attack delay left
+			if (DIFF_TICK(tick, md->last_canmove) > battle_config.mob_unlock_time) {
+				// Unlock target or use idle/walk skill
+				mob_unlocktarget(md, tick);
+			}
+			else {
+				// Use idle skill but keep target for now
+				md->state.skillstate = MSS_IDLE;
+				if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL))
+					mobskill_use(md, tick, -1);
+			}
 		}
 		return true;
 	}
@@ -2620,8 +2631,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 	// determines if the monster was killed by mercenary damage only
 	merckillonly = (bool)((dmgbltypes & BL_MER) && !(dmgbltypes & ~BL_MER));
 
-	if(!battle_config.exp_calc_type && count > 1) {	//Apply first-attacker 200% exp share bonus
-		//TODO: Determine if this should go before calculating the MVP player instead of after.
+	if(battle_config.exp_calc_type == 2 && count > 1) {	//Apply first-attacker 200% exp share bonus
 		if (UINT_MAX - md->dmglog[0].dmg > md->tdmg) {
 			md->tdmg += md->dmglog[0].dmg;
 			md->dmglog[0].dmg *= 2;
@@ -2666,14 +2676,16 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 
 			if (!tmpsd[i]) continue;
 
-			if (!battle_config.exp_calc_type && md->tdmg)
-				//jAthena's exp formula based on total damage.
-				per = (double)md->dmglog[i].dmg/(double)md->tdmg;
+			if (battle_config.exp_calc_type == 1 || md->tdmg == 0) {
+				// eAthena's exp formula based on max hp
+				per = (double)md->dmglog[i].dmg / (double)status->max_hp;
+			}
 			else {
-				//eAthena's exp formula based on max hp.
-				per = (double)md->dmglog[i].dmg/(double)status->max_hp;
-				if (per > 2) per = 2; // prevents unlimited exp gain
+				// Aegis's exp formula based on total damage
+				per = (double)md->dmglog[i].dmg / (double)md->tdmg;
 			}
+			// To prevent exploits
+			if (per > 1) per = 1;
 
 			//Exclude rebirth tap from this calculation
 			count -= md->state.rebirth;
@@ -4110,7 +4122,7 @@ int mob_clone_spawn(map_session_data *sd, int16 m, int16 x, int16 y, const char
 			/**
 			 * The clone should be able to cast the skill (e.g. have the required weapon) bugreport:5299)
 			 **/
-			if( !skill_check_condition_castbegin(sd,skill_id,sd->status.skill[sk_idx].lv) )
+			if( !skill_check_condition_castbegin(*sd,skill_id,sd->status.skill[sk_idx].lv) )
 				continue;
 
 			std::shared_ptr<s_mob_skill> ms = std::make_shared<s_mob_skill>();
@@ -4585,7 +4597,7 @@ uint64 MobDatabase::parseBodyNode(const ryml::NodeRef& node) {
 		if (!this->asUInt16(node, "Str", stat))
 			return 0;
 
-		mob->status.str = max(1, stat);
+		mob->status.str = max(0, stat);
 	}
 
 	if (this->nodeExists(node, "Agi")) {
@@ -4594,7 +4606,7 @@ uint64 MobDatabase::parseBodyNode(const ryml::NodeRef& node) {
 		if (!this->asUInt16(node, "Agi", stat))
 			return 0;
 
-		mob->status.agi = max(1, stat);
+		mob->status.agi = max(0, stat);
 	}
 
 	if (this->nodeExists(node, "Vit")) {
@@ -4603,7 +4615,7 @@ uint64 MobDatabase::parseBodyNode(const ryml::NodeRef& node) {
 		if (!this->asUInt16(node, "Vit", stat))
 			return 0;
 
-		mob->status.vit = max(1, stat);
+		mob->status.vit = max(0, stat);
 	}
 
 	if (this->nodeExists(node, "Int")) {
@@ -4612,7 +4624,7 @@ uint64 MobDatabase::parseBodyNode(const ryml::NodeRef& node) {
 		if (!this->asUInt16(node, "Int", stat))
 			return 0;
 
-		mob->status.int_ = max(1, stat);
+		mob->status.int_ = max(0, stat);
 	}
 
 	if (this->nodeExists(node, "Dex")) {
@@ -4621,7 +4633,7 @@ uint64 MobDatabase::parseBodyNode(const ryml::NodeRef& node) {
 		if (!this->asUInt16(node, "Dex", stat))
 			return 0;
 
-		mob->status.dex = max(1, stat);
+		mob->status.dex = max(0, stat);
 	}
 
 	if (this->nodeExists(node, "Luk")) {
@@ -4630,7 +4642,7 @@ uint64 MobDatabase::parseBodyNode(const ryml::NodeRef& node) {
 		if (!this->asUInt16(node, "Luk", stat))
 			return 0;
 
-		mob->status.luk = max(1, stat);
+		mob->status.luk = max(0, stat);
 	}
 
 	if (this->nodeExists(node, "AttackRange")) {

+ 1 - 1
src/map/mob.hpp

@@ -359,7 +359,7 @@ struct mob_data {
 	int areanpc_id; //Required in OnTouchNPC (to avoid multiple area touchs)
 	int bg_id; // BattleGround System
 
-	t_tick next_walktime,last_thinktime,last_linktime,last_pcneartime,dmgtick;
+	t_tick next_walktime,last_thinktime,last_linktime,last_pcneartime,dmgtick,last_canmove;
 	short move_fail_count;
 	short lootitem_count;
 	short min_chase;

+ 3 - 3
src/map/npc.cpp

@@ -3161,7 +3161,7 @@ e_purchase_result npc_barter_purchase( map_session_data& sd, std::shared_ptr<s_n
 						}
 
 						// Server is configured to hide favorite items on selling
-						if( battle_config.hide_fav_sell && sd.inventory.u.items_inventory[j].favorite ){
+						if( battle_config.hide_fav_sell && sd.inventory.u.items_inventory[j].favorite != 0 ){
 							continue;
 						}
 
@@ -3205,7 +3205,7 @@ e_purchase_result npc_barter_purchase( map_session_data& sd, std::shared_ptr<s_n
 							}
 
 							// Server is configured to hide favorite items on selling
-							if( battle_config.hide_fav_sell && sd.inventory.u.items_inventory[j].favorite ){
+							if( battle_config.hide_fav_sell && sd.inventory.u.items_inventory[j].favorite != 0 ){
 								continue;
 							}
 
@@ -3250,7 +3250,7 @@ e_purchase_result npc_barter_purchase( map_session_data& sd, std::shared_ptr<s_n
 										}
 
 										// Server is configured to hide favorite items on selling
-										if( battle_config.hide_fav_sell && sd.inventory.u.items_inventory[j].favorite ){
+										if( battle_config.hide_fav_sell && sd.inventory.u.items_inventory[j].favorite != 0 ){
 											continue;
 										}
 

+ 44 - 0
src/map/packets.hpp

@@ -427,6 +427,44 @@ struct PACKET_ZC_INVENTORY_TAB{
 	bool favorite;
 } __attribute__((packed));
 
+struct PACKET_ZC_SKILL_SELECT_REQUEST_sub{
+	int16 skill_id;
+} __attribute__((packed));
+
+struct PACKET_ZC_SKILL_SELECT_REQUEST{
+	int16 packetType;
+	int16 packetLength;
+	int32 why;
+	struct PACKET_ZC_SKILL_SELECT_REQUEST_sub skills[];
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_OPEN_BANKING{
+	int16 packetType;
+	uint32 AID;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_CLOSE_BANKING{
+	int16 packetType;
+	uint32 AID;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_BANKING_CHECK{
+	int16 packetType;
+	uint32 AID;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_BANKING_DEPOSIT{
+	int16 packetType;
+	uint32 AID;
+	int32 zeny;
+} __attribute__((packed));
+
+struct PACKET_CZ_REQ_BANKING_WITHDRAW{
+	int16 packetType;
+	uint32 AID;
+	int32 zeny;
+} __attribute__((packed));
+
 // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
 #if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 )
 	#pragma pack( pop )
@@ -458,6 +496,7 @@ DEFINE_PACKET_HEADER(ZC_BOSS_INFO, 0x293)
 DEFINE_PACKET_HEADER(ZC_CASH_TIME_COUNTER, 0x298)
 DEFINE_PACKET_HEADER(ZC_CASH_ITEM_DELETE, 0x299)
 DEFINE_PACKET_HEADER(ZC_NOTIFY_BIND_ON_EQUIP, 0x2d3)
+DEFINE_PACKET_HEADER(ZC_SKILL_SELECT_REQUEST, 0x442)
 DEFINE_PACKET_HEADER(ZC_FAILED_TRADE_BUYING_STORE_TO_SELLER, 0x824)
 DEFINE_PACKET_HEADER(CZ_SSILIST_ITEM_CLICK, 0x83c)
 DEFINE_PACKET_HEADER(CZ_REQ_SE_CASH_TAB_CODE, 0x846)
@@ -469,15 +508,20 @@ DEFINE_PACKET_HEADER(ZC_INVENTORY_TAB, 0x908)
 DEFINE_PACKET_HEADER(ZC_ENTRY_QUEUE_INIT, 0x90e)
 DEFINE_PACKET_HEADER(CZ_REQ_MERGE_ITEM, 0x96e)
 DEFINE_PACKET_HEADER(ZC_BANKING_CHECK, 0x9a6)
+DEFINE_PACKET_HEADER(CZ_REQ_BANKING_DEPOSIT, 0x9a7)
 DEFINE_PACKET_HEADER(ZC_ACK_BANKING_DEPOSIT, 0x9a8)
+DEFINE_PACKET_HEADER(CZ_REQ_BANKING_WITHDRAW, 0x9a9)
 DEFINE_PACKET_HEADER(ZC_ACK_BANKING_WITHDRAW, 0x9aa)
+DEFINE_PACKET_HEADER(CZ_REQ_BANKING_CHECK, 0x9ab)
 DEFINE_PACKET_HEADER(CZ_REQ_CASH_BARGAIN_SALE_ITEM_INFO, 0x9ac)
 DEFINE_PACKET_HEADER(ZC_ACK_CASH_BARGAIN_SALE_ITEM_INFO, 0x9ad)
 DEFINE_PACKET_HEADER(CZ_REQ_APPLY_BARGAIN_SALE_ITEM, 0x9ae)
 DEFINE_PACKET_HEADER(CZ_REQ_REMOVE_BARGAIN_SALE_ITEM, 0x9b0)
 DEFINE_PACKET_HEADER(ZC_NOTIFY_BARGAIN_SALE_SELLING, 0x9b2)
 DEFINE_PACKET_HEADER(ZC_NOTIFY_BARGAIN_SALE_CLOSE, 0x9b3)
+DEFINE_PACKET_HEADER(CZ_REQ_OPEN_BANKING, 0x9b6)
 DEFINE_PACKET_HEADER(ZC_ACK_OPEN_BANKING, 0x9b7)
+DEFINE_PACKET_HEADER(CZ_REQ_CLOSE_BANKING, 0x9b8)
 DEFINE_PACKET_HEADER(ZC_ACK_CLOSE_BANKING, 0x9b9)
 DEFINE_PACKET_HEADER(ZC_ACK_COUNT_BARGAIN_SALE_ITEM, 0x9c4)
 DEFINE_PACKET_HEADER(ZC_ACK_GUILDSTORAGE_LOG, 0x9da)

+ 1 - 1
src/map/party.cpp

@@ -1039,7 +1039,7 @@ int party_send_logout(map_session_data *sd)
 	return 1;
 }
 
-int party_send_message(map_session_data *sd,const char *mes,int len)
+int party_send_message(map_session_data *sd,const char *mes, size_t len)
 {
 	if(sd->status.party_id == 0)
 		return 0;

+ 1 - 1
src/map/party.hpp

@@ -88,7 +88,7 @@ int party_changeleader(map_session_data *sd, map_session_data *t_sd, struct part
 void party_send_movemap(map_session_data *sd);
 void party_send_levelup(map_session_data *sd);
 int party_send_logout(map_session_data *sd);
-int party_send_message(map_session_data *sd,const char *mes,int len);
+int party_send_message(map_session_data *sd,const char *mes, size_t len);
 int party_recv_message(int party_id,uint32 account_id,const char *mes,int len);
 int party_skill_check(map_session_data *sd, int party_id, uint16 skill_id, uint16 skill_lv);
 int party_send_xy_clear(struct party_data *p);

+ 3 - 3
src/map/pc.cpp

@@ -1218,7 +1218,7 @@ bool pc_can_sell_item(map_session_data *sd, struct item *item, enum npc_subtype
 	if (item->equip > 0 || item->amount < 0)
 		return false;
 
-	if (battle_config.hide_fav_sell && item->favorite)
+	if (battle_config.hide_fav_sell && item->favorite != 0)
 		return false; //Cannot sell favs (optional config)
 
 	if (!battle_config.rental_transaction && item->expire_time)
@@ -5945,7 +5945,7 @@ enum e_additem_result pc_additem(map_session_data *sd,struct item *item,int amou
 		// clear equip and favorite fields first, just in case
 		if( item->equip )
 			sd->inventory.u.items_inventory[i].equip = 0;
-		if( item->favorite )
+		if( item->favorite != 0 )
 			sd->inventory.u.items_inventory[i].favorite = 0;
 		if( item->equipSwitch )
 			sd->inventory.u.items_inventory[i].equipSwitch = 0;
@@ -14546,7 +14546,7 @@ TIMER_FUNC(pc_autotrade_timer){
 	sd->autotrade_tid = INVALID_TIMER;
 
 	if (sd->state.autotrade&2)
-		vending_reopen(sd);
+		vending_reopen(*sd);
 	if (sd->state.autotrade&4)
 		buyingstore_reopen(sd);
 

+ 1 - 1
src/map/script.cpp

@@ -19867,7 +19867,7 @@ BUILDIN_FUNC(unitattack)
 		case BL_PC: {
 			map_session_data* sd = (map_session_data*)unit_bl;
 
-			clif_parse_ActionRequest_sub(sd, actiontype > 0 ? 0x07 : 0x00, target_bl->id, gettick());
+			clif_parse_ActionRequest_sub( *sd, actiontype > 0 ? 0x07 : 0x00, target_bl->id, gettick() );
 			script_pushint(st, sd->ud.target == target_bl->id);
 			return SCRIPT_CMD_SUCCESS;
 		}

+ 1 - 1
src/map/script_constants.hpp

@@ -1266,7 +1266,7 @@
 	//export_constant(SC_IGNOREDEF);
 	export_constant(SC_HELLPOWER);
 	export_constant(SC_INVINCIBLE);
-	export_constant(SC_INVINCIBLEOFF);
+	//export_constant(SC_INVINCIBLEOFF);
 	export_constant(SC_MANU_ATK);
 	export_constant(SC_MANU_DEF);
 	export_constant(SC_SPL_ATK);

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 222 - 233
src/map/skill.cpp


+ 10 - 10
src/map/skill.hpp

@@ -597,8 +597,8 @@ void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id);
 int skill_check_bl_sc(struct block_list *target, va_list ap);
 
 // Skill conditions check and remove [Inkfish]
-bool skill_check_condition_castbegin(map_session_data *sd, uint16 skill_id, uint16 skill_lv);
-bool skill_check_condition_castend(map_session_data *sd, uint16 skill_id, uint16 skill_lv);
+bool skill_check_condition_castbegin( map_session_data& sd, uint16 skill_id, uint16 skill_lv );
+bool skill_check_condition_castend( map_session_data& sd, uint16 skill_id, uint16 skill_lv );
 int skill_check_condition_char_sub (struct block_list *bl, va_list ap);
 void skill_consume_requirement(map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type);
 struct s_skill_condition skill_get_requirement(map_session_data *sd, uint16 skill_id, uint16 skill_lv);
@@ -611,9 +611,9 @@ void skill_unit_move_unit_group( std::shared_ptr<s_skill_unit_group> group, int1
 void skill_unit_move_unit(struct block_list *bl, int dx, int dy);
 
 int skill_sit(map_session_data *sd, bool sitting);
-void skill_repairweapon(map_session_data *sd, int idx);
+void skill_repairweapon( map_session_data& sd, int idx );
 void skill_identify(map_session_data *sd,int idx);
-void skill_weaponrefine(map_session_data *sd,int idx); // [Celest]
+void skill_weaponrefine( map_session_data& sd, int idx ); // [Celest]
 int skill_autospell(map_session_data *md,uint16 skill_id);
 
 int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, bool heal);
@@ -622,9 +622,9 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce
 int8 skill_isCopyable(map_session_data *sd, uint16 skill_id);
 
 // Abnormal status
-bool skill_isNotOk(uint16 skill_id, map_session_data *sd);
+bool skill_isNotOk( uint16 skill_id, map_session_data& sd );
 bool skill_isNotOk_hom(struct homun_data *hd, uint16 skill_id, uint16 skill_lv);
-bool skill_isNotOk_mercenary(uint16 skill_id, s_mercenary_data *md);
+bool skill_isNotOk_mercenary( uint16 skill_id, s_mercenary_data& md);
 
 bool skill_isNotOk_npcRange(struct block_list *src, uint16 skill_id, uint16 skill_lv, int pos_x, int pos_y);
 
@@ -2776,19 +2776,19 @@ bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *s
 /**
  * Mechanic
  **/
-int skill_magicdecoy(map_session_data *sd, t_itemid nameid);
+void skill_magicdecoy( map_session_data& sd, t_itemid nameid );
 
 /**
  * Guiltoine Cross
  **/
-int skill_poisoningweapon( map_session_data *sd, t_itemid nameid);
+void skill_poisoningweapon( map_session_data& sd, t_itemid nameid );
 
 /**
  * Auto Shadow Spell (Shadow Chaser)
  **/
-int skill_select_menu(map_session_data *sd,uint16 skill_id);
+void skill_select_menu( map_session_data& sd, uint16 skill_id );
 
-int skill_elementalanalysis(map_session_data *sd, int n, uint16 skill_lv, unsigned short *item_list); // Sorcerer Four Elemental Analisys.
+int skill_elementalanalysis( map_session_data& sd, int n, uint16 skill_lv, unsigned short *item_list ); // Sorcerer Four Elemental Analisys.
 int skill_changematerial(map_session_data *sd, int n, unsigned short *item_list);	// Genetic Change Material.
 int skill_get_elemental_type(uint16 skill_id, uint16 skill_lv);
 

+ 80 - 70
src/map/status.cpp

@@ -1403,6 +1403,7 @@ int64 status_charge(struct block_list* bl, int64 hp, int64 sp)
  *		flag&2: Fail if there is not enough to subtract
  *		flag&4: Mob does not give EXP/Loot if killed
  *		flag&8: Used to damage SP of a dead character
+ *		flag&16: Coma damage - Log it as normal damage, but actually set HP/SP to 1
  * @return hp+sp+ap
  * Note: HP/SP/AP are integer values, not percentages. Values should be
  *	 calculated either within function call or before
@@ -1470,7 +1471,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
 		flag |= 8;
 
 	sc = status_get_sc(target);
-	if( hp && battle_config.invincible_nodamage && src && sc && sc->getSCE(SC_INVINCIBLE) && !sc->getSCE(SC_INVINCIBLEOFF) )
+	if (hp && battle_config.invincible_nodamage && src && sc && sc->getSCE(SC_INVINCIBLE))
 		hp = 1;
 
 	if( hp && !(flag&1) ) {
@@ -1522,10 +1523,25 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
 		unit_skillcastcancel(target, 2);
 	}
 
+	// We need to log the real damage on exp_calc_type 1
+	if (battle_config.exp_calc_type == 1) {
+		dhp = hp;
+		// Coma real damage
+		if (flag&16)
+			dhp = status->hp - 1;
+	}
+
 	status->hp-= hp;
 	status->sp-= sp;
 	status->ap-= ap;
 
+	// Coma
+	if (flag&16) {
+		status->hp = 1;
+		status->sp = 1;
+		if (!sp) sp = 1; // To make sure the status bar is updated
+	}
+
 	if (sc && hp && status->hp) {
 		if (sc->getSCE(SC_AUTOBERSERK) &&
 			(!sc->getSCE(SC_PROVOKE) || !sc->getSCE(SC_PROVOKE)->val4) &&
@@ -1539,9 +1555,11 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
 			status_change_end(target, SC_SATURDAYNIGHTFEVER);
 	}
 
+	// Need to pass original HP damage for the mob damage log
+	dhp = cap_value(dhp, INT_MIN, INT_MAX);
 	switch (target->type) {
 		case BL_PC:  pc_damage((TBL_PC*)target,src,hp,sp,ap); break;
-		case BL_MOB: mob_damage((TBL_MOB*)target, src, hp); break;
+		case BL_MOB: mob_damage((TBL_MOB*)target, src, (int)dhp); break;
 		case BL_HOM: hom_damage((TBL_HOM*)target); break;
 		case BL_MER: mercenary_heal((TBL_MER*)target,hp,sp); break;
 		case BL_ELEM: elemental_heal((TBL_ELEM*)target,hp,sp); break;
@@ -2114,12 +2132,6 @@ bool status_check_skilluse(struct block_list *src, struct block_list *target, ui
 		return true;
 
 	if (tsc && tsc->count) {
-		/**
-		* Attacks in invincible are capped to 1 damage and handled in battle.cpp.
-		* Allow spell break and eske for sealed shrine GDB when in INVINCIBLE state.
-		**/
-		if( tsc->getSCE(SC_INVINCIBLE) && !tsc->getSCE(SC_INVINCIBLEOFF) && skill_id && !(skill_id&(SA_SPELLBREAKER|SL_SKE)) )
-			return false;
 		if(!skill_id && tsc->getSCE(SC_TRICKDEAD))
 			return false;
 		if((skill_id == WZ_STORMGUST || skill_id == WZ_FROSTNOVA || skill_id == NJ_HYOUSYOURAKU || skill_id == NPC_STORMGUST2)
@@ -8037,8 +8049,8 @@ static unsigned short status_calc_speed(struct block_list *bl, status_change *sc
 			val = max( val, 55 );
 		if( sc->getSCE(SC_AVOID) )
 			val = max( val, 10 * sc->getSCE(SC_AVOID)->val1 );
-		if( sc->getSCE(SC_INVINCIBLE) && !sc->getSCE(SC_INVINCIBLEOFF) )
-			val = max( val, 75 );
+		if (sc->getSCE(SC_INVINCIBLE))
+			val = max(val, sc->getSCE(SC_INVINCIBLE)->val3);
 		if( sc->getSCE(SC_CLOAKINGEXCEED) )
 			val = max( val, sc->getSCE(SC_CLOAKINGEXCEED)->val3);
 		if (sc->getSCE(SC_PARALYSE) && sc->getSCE(SC_PARALYSE)->val3 == 0)
@@ -8310,66 +8322,68 @@ static short status_calc_aspd_rate(struct block_list *bl, status_change *sc, int
 	if(!sc || !sc->count)
 		return cap_value(aspd_rate,0,SHRT_MAX);
 
-	if( !sc->getSCE(SC_QUAGMIRE) ) {
-		int max = 0;
-		if(sc->getSCE(SC_STAR_COMFORT))
-			max = sc->getSCE(SC_STAR_COMFORT)->val2;
+	int max = 0;
+	if (sc->getSCE(SC_STAR_COMFORT))
+		max = sc->getSCE(SC_STAR_COMFORT)->val2;
 
-		if(sc->getSCE(SC_TWOHANDQUICKEN) &&
-			max < sc->getSCE(SC_TWOHANDQUICKEN)->val2)
-			max = sc->getSCE(SC_TWOHANDQUICKEN)->val2;
+	if (sc->getSCE(SC_TWOHANDQUICKEN) &&
+		max < sc->getSCE(SC_TWOHANDQUICKEN)->val2)
+		max = sc->getSCE(SC_TWOHANDQUICKEN)->val2;
 
-		if(sc->getSCE(SC_ONEHAND) &&
-			max < sc->getSCE(SC_ONEHAND)->val2)
-			max = sc->getSCE(SC_ONEHAND)->val2;
+	if (sc->getSCE(SC_ONEHAND) &&
+		max < sc->getSCE(SC_ONEHAND)->val2)
+		max = sc->getSCE(SC_ONEHAND)->val2;
 
-		if(sc->getSCE(SC_MERC_QUICKEN) &&
-			max < sc->getSCE(SC_MERC_QUICKEN)->val2)
-			max = sc->getSCE(SC_MERC_QUICKEN)->val2;
+	if (sc->getSCE(SC_MERC_QUICKEN) &&
+		max < sc->getSCE(SC_MERC_QUICKEN)->val2)
+		max = sc->getSCE(SC_MERC_QUICKEN)->val2;
 
-		if(sc->getSCE(SC_ADRENALINE2) &&
-			max < sc->getSCE(SC_ADRENALINE2)->val3)
-			max = sc->getSCE(SC_ADRENALINE2)->val3;
+	if (sc->getSCE(SC_ADRENALINE2) &&
+		max < sc->getSCE(SC_ADRENALINE2)->val3)
+		max = sc->getSCE(SC_ADRENALINE2)->val3;
 
-		if(sc->getSCE(SC_ADRENALINE) &&
-			max < sc->getSCE(SC_ADRENALINE)->val3)
-			max = sc->getSCE(SC_ADRENALINE)->val3;
+	if (sc->getSCE(SC_ADRENALINE) &&
+		max < sc->getSCE(SC_ADRENALINE)->val3)
+		max = sc->getSCE(SC_ADRENALINE)->val3;
 
-		if(sc->getSCE(SC_SPEARQUICKEN) &&
-			max < sc->getSCE(SC_SPEARQUICKEN)->val2)
-			max = sc->getSCE(SC_SPEARQUICKEN)->val2;
+	if (sc->getSCE(SC_SPEARQUICKEN) &&
+		max < sc->getSCE(SC_SPEARQUICKEN)->val2)
+		max = sc->getSCE(SC_SPEARQUICKEN)->val2;
 
-		if(sc->getSCE(SC_GATLINGFEVER) &&
-			max < sc->getSCE(SC_GATLINGFEVER)->val2)
-			max = sc->getSCE(SC_GATLINGFEVER)->val2;
+	if (sc->getSCE(SC_GATLINGFEVER) &&
+		max < sc->getSCE(SC_GATLINGFEVER)->val2)
+		max = sc->getSCE(SC_GATLINGFEVER)->val2;
 
-		if(sc->getSCE(SC_FLEET) &&
-			max < sc->getSCE(SC_FLEET)->val2)
-			max = sc->getSCE(SC_FLEET)->val2;
+	if (sc->getSCE(SC_FLEET) &&
+		max < sc->getSCE(SC_FLEET)->val2)
+		max = sc->getSCE(SC_FLEET)->val2;
 
-		if(sc->getSCE(SC_ASSNCROS) && max < sc->getSCE(SC_ASSNCROS)->val2) {
-			if (bl->type!=BL_PC)
-				max = sc->getSCE(SC_ASSNCROS)->val2;
-			else
-				switch(((TBL_PC*)bl)->status.weapon) {
-					case W_BOW:
-					case W_REVOLVER:
-					case W_RIFLE:
-					case W_GATLING:
-					case W_SHOTGUN:
-					case W_GRENADE:
-						break;
-					default:
-						max = sc->getSCE(SC_ASSNCROS)->val2;
-			}
-		}
-		aspd_rate -= max;
+	if (sc->getSCE(SC_INVINCIBLE) &&
+		max < sc->getSCE(SC_INVINCIBLE)->val4)
+		max = sc->getSCE(SC_INVINCIBLE)->val4;
 
-		if(sc->getSCE(SC_BERSERK))
-			aspd_rate -= 300;
-		else if(sc->getSCE(SC_MADNESSCANCEL))
-			aspd_rate -= 200;
+	if (sc->getSCE(SC_ASSNCROS) && max < sc->getSCE(SC_ASSNCROS)->val2) {
+		if (bl->type != BL_PC)
+			max = sc->getSCE(SC_ASSNCROS)->val2;
+		else
+			switch (((TBL_PC*)bl)->status.weapon) {
+				case W_BOW:
+				case W_REVOLVER:
+				case W_RIFLE:
+				case W_GATLING:
+				case W_SHOTGUN:
+				case W_GRENADE:
+					break;
+				default:
+					max = sc->getSCE(SC_ASSNCROS)->val2;
+			}
 	}
+	aspd_rate -= max;
+
+	if (sc->getSCE(SC_BERSERK))
+		aspd_rate -= 300;
+	else if (sc->getSCE(SC_MADNESSCANCEL))
+		aspd_rate -= 200;
 
 	if( sc->getSCE(i=SC_ASPDPOTION3) ||
 		sc->getSCE(i=SC_ASPDPOTION2) ||
@@ -9610,11 +9624,6 @@ t_tick status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_
 				tick /= 2; // Half duration for players.
 			sc_def2 = status->mdef*100;
 			break;
-		case SC_ANKLE:
-			if(status_has_mode(status,MD_STATUSIMMUNE)) // Lasts 5 times less on bosses
-				tick /= 5;
-			sc_def = status->agi*50;
-			break;
 		case SC_JOINTBEAT:
 			tick_def2 = 1000 * ((status->luk / 2 + status->agi / 5) / 2); // (50 * LUK / 100 + 20 * AGI / 100) / 2
 			break;
@@ -11237,7 +11246,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		}
 
 		case SC_COMA: // Coma. Sends a char to 1HP. If val2, do not zap sp
-			status_zap(bl, status->hp-1, val2?0:status->sp);
+			status_zap(bl, status->hp-1, val2?0:status->sp-1);
 			return 1;
 			break;
 		case SC_CLOSECONFINE2:
@@ -11572,6 +11581,11 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		case SC_REBIRTH:
 			val2 = 20*val1; // % of life to be revived with
 			break;
+		case SC_INVINCIBLE:
+			val2 = 100; // ATKpercent increase
+			val3 = 50; // Speed increase
+			val4 = 700; // ASPD increase
+			break;
 
 		case SC_MANU_DEF:
 		case SC_MANU_ATK:
@@ -11586,7 +11600,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 
 		/* General */
 		case SC_FEAR:
-			status_change_start(src,bl,SC_ANKLE,10000,val1,0,0,0,2000,SCSTART_NOAVOID|SCSTART_NOTICKDEF|SCSTART_NORATEDEF);
+			sc_start(src, bl, SC_ANKLE, 100, 0, 2000);
 			break;
 
 		/* Rune Knight */
@@ -12850,10 +12864,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 	//SC that make stop walking
 	if (scdb->flag[SCF_STOPWALKING]) {
 		switch (type) {
-			case SC_ANKLE:
-				if (battle_config.skill_trap_type || !map_flag_gvg(bl->m))
-					unit_stop_walking(bl, 1);
-				break;
 			case SC__MANHOLE:
 				if (bl->type == BL_PC || !unit_blown_immune(bl,0x1))
 					unit_stop_walking(bl,1);

+ 2 - 2
src/map/status.hpp

@@ -499,8 +499,8 @@ enum sc_type : int16 {
 	//SC_IGNOREDEF,
 	SC_HELLPOWER = 294,
 	SC_INVINCIBLE, //295
-	SC_INVINCIBLEOFF,
-	SC_MANU_ATK,
+	//SC_INVINCIBLEOFF,
+	SC_MANU_ATK = 297,
 	SC_MANU_DEF,
 	SC_SPL_ATK,
 	SC_SPL_DEF, //300

+ 4 - 4
src/map/unit.cpp

@@ -1649,7 +1649,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
 	if (sc && sc->getSCE(SC_COMBO) &&
 		skill_is_combo(skill_id) &&
 		(sc->getSCE(SC_COMBO)->val1 == skill_id ||
-		(sd?skill_check_condition_castbegin(sd,skill_id,skill_lv):0) )) {
+		(sd?skill_check_condition_castbegin(*sd,skill_id,skill_lv):0) )) {
 		if (skill_is_combo(skill_id) == 2 && target_id == src->id && ud->target > 0)
 			target_id = ud->target;
 		else if (sc->getSCE(SC_COMBO)->val2)
@@ -1668,7 +1668,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
 
 	if (sd) {
 		// Target_id checking.
-		if(skill_isNotOk(skill_id, sd))
+		if(skill_isNotOk(skill_id, *sd))
 			return 0;
 
 		switch(skill_id) { // Check for skills that auto-select target
@@ -1851,7 +1851,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
 				break;
 		}
 
-		if (!skill_check_condition_castbegin(sd, skill_id, skill_lv))
+		if (!skill_check_condition_castbegin(*sd, skill_id, skill_lv))
 			return 0;
 	}
 
@@ -2164,7 +2164,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
 		return 0;
 
 	if( sd ) {
-		if( skill_isNotOk(skill_id, sd) || !skill_check_condition_castbegin(sd, skill_id, skill_lv) )
+		if( skill_isNotOk(skill_id, *sd) || !skill_check_condition_castbegin(*sd, skill_id, skill_lv) )
 			return 0;
 		if (skill_id == MG_FIREWALL && !skill_pos_maxcount_check(src, skill_x, skill_y, skill_id, skill_lv, BL_PC, true))
 			return 0; // Special check for Firewall only

+ 48 - 56
src/map/vending.cpp

@@ -295,38 +295,32 @@ void vending_purchasereq(map_session_data* sd, int aid, int uid, const uint8* da
  * @param at Autotrader info, or NULL if requetsed not from autotrade persistance
  * @return 0 If success, 1 - Cannot open (die, not state.prevend, trading), 2 - No cart, 3 - Count issue, 4 - Cart data isn't saved yet, 5 - No valid item found
  */
-int8 vending_openvending(map_session_data* sd, const char* message, const uint8* data, int count, struct s_autotrader *at)
-{
+int8 vending_openvending( map_session_data& sd, const char* message, const uint8* data, int count, struct s_autotrader *at ){
 	int i, j;
 	int vending_skill_lvl;
 	char message_sql[MESSAGE_SIZE*2];
 	StringBuf buf;
 
-	// TODO: Change sd to reference
-	if( sd == nullptr ){
-		return 0;
-	}
-
-	if ( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd)) {
+	if ( pc_isdead(&sd) || !sd.state.prevend || pc_istrading(&sd)) {
 		return 1; // can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once
 	}
 
-	vending_skill_lvl = pc_checkskill(sd, MC_VENDING);
+	vending_skill_lvl = pc_checkskill(&sd, MC_VENDING);
 	
 	// skill level and cart check
-	if( !vending_skill_lvl || !pc_iscarton(sd) ) {
-		clif_skill_fail( *sd, MC_VENDING );
+	if( !vending_skill_lvl || !pc_iscarton(&sd) ) {
+		clif_skill_fail( sd, MC_VENDING );
 		return 2;
 	}
 
 	// check number of items in shop
 	if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) { // invalid item count
-		clif_skill_fail( *sd, MC_VENDING );
+		clif_skill_fail( sd, MC_VENDING );
 		return 3;
 	}
 
 	if (save_settings&CHARSAVE_VENDING) // Avoid invalid data from saving
-		chrif_save(sd, CSAVE_INVENTORY|CSAVE_CART);
+		chrif_save(&sd, CSAVE_INVENTORY|CSAVE_CART);
 
 	// filter out invalid items
 	i = 0;
@@ -338,51 +332,51 @@ int8 vending_openvending(map_session_data* sd, const char* message, const uint8*
 		index -= 2; // offset adjustment (client says that the first cart position is 2)
 
 		if( index < 0 || index >= MAX_CART // invalid position
-		||  pc_cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity
+		||  pc_cartitem_amount(&sd, index, amount) < 0 // invalid item or insufficient quantity
 		//NOTE: official server does not do any of the following checks!
-		||  !sd->cart.u.items_cart[index].identify // unidentified item
-		||  sd->cart.u.items_cart[index].attribute == 1 // broken item
-		||  sd->cart.u.items_cart[index].expire_time // It should not be in the cart but just in case
-		||  (sd->cart.u.items_cart[index].bound && !pc_can_give_bounded_items(sd)) // can't trade account bound items and has no permission
-		||  !itemdb_cantrade(&sd->cart.u.items_cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item
+		||  !sd.cart.u.items_cart[index].identify // unidentified item
+		||  sd.cart.u.items_cart[index].attribute == 1 // broken item
+		||  sd.cart.u.items_cart[index].expire_time // It should not be in the cart but just in case
+		||  (sd.cart.u.items_cart[index].bound && !pc_can_give_bounded_items(&sd)) // can't trade account bound items and has no permission
+		||  !itemdb_cantrade(&sd.cart.u.items_cart[index], pc_get_group_level(&sd), pc_get_group_level(&sd)) ) // untradeable item
 			continue;
 
-		sd->vending[i].index = index;
-		sd->vending[i].amount = amount;
-		sd->vending[i].value = min(value, (unsigned int)battle_config.vending_max_value);
+		sd.vending[i].index = index;
+		sd.vending[i].amount = amount;
+		sd.vending[i].value = min(value, (unsigned int)battle_config.vending_max_value);
 		i++; // item successfully added
 	}
 
 	if (i != j) {
-		clif_displaymessage(sd->fd, msg_txt(sd, 266)); //"Some of your items cannot be vended and were removed from the shop."
-		clif_skill_fail( *sd, MC_VENDING ); // custom reply packet
+		clif_displaymessage(sd.fd, msg_txt(&sd, 266)); //"Some of your items cannot be vended and were removed from the shop."
+		clif_skill_fail( sd, MC_VENDING ); // custom reply packet
 		return 5;
 	}
 
 	if( i == 0 ) { // no valid item found
-		clif_skill_fail( *sd, MC_VENDING ); // custom reply packet
+		clif_skill_fail( sd, MC_VENDING ); // custom reply packet
 		return 5;
 	}
 
-	sd->state.prevend = 0;
-	sd->state.vending = true;
-	sd->state.workinprogress = WIP_DISABLE_NONE;
-	sd->vender_id = vending_getuid();
-	sd->vend_num = i;
-	safestrncpy(sd->message, message, MESSAGE_SIZE);
+	sd.state.prevend = 0;
+	sd.state.vending = true;
+	sd.state.workinprogress = WIP_DISABLE_NONE;
+	sd.vender_id = vending_getuid();
+	sd.vend_num = i;
+	safestrncpy(sd.message, message, MESSAGE_SIZE);
 	
-	Sql_EscapeString( mmysql_handle, message_sql, sd->message );
+	Sql_EscapeString( mmysql_handle, message_sql, sd.message );
 
 	if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`, `account_id`, `char_id`, `sex`, `map`, `x`, `y`, `title`, `autotrade`, `body_direction`, `head_direction`, `sit`) "
 		"VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, '%d', '%d', '%d' );",
-		vendings_table, sd->vender_id, sd->status.account_id, sd->status.char_id, sd->status.sex == SEX_FEMALE ? 'F' : 'M', map_getmapdata(sd->bl.m)->name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade, at ? at->dir : sd->ud.dir, at ? at->head_dir : sd->head_dir, at ? at->sit : pc_issit(sd) ) != SQL_SUCCESS ) {
+		vendings_table, sd.vender_id, sd.status.account_id, sd.status.char_id, sd.status.sex == SEX_FEMALE ? 'F' : 'M', map_getmapdata(sd.bl.m)->name, sd.bl.x, sd.bl.y, message_sql, sd.state.autotrade, at ? at->dir : sd.ud.dir, at ? at->head_dir : sd.head_dir, at ? at->sit : pc_issit(&sd) ) != SQL_SUCCESS ) {
 		Sql_ShowDebug(mmysql_handle);
 	}
 
 	StringBuf_Init(&buf);
 	StringBuf_Printf(&buf, "INSERT INTO `%s`(`vending_id`,`index`,`cartinventory_id`,`amount`,`price`) VALUES", vending_items_table);
 	for (j = 0; j < i; j++) {
-		StringBuf_Printf(&buf, "(%d,%d,%d,%d,%d)", sd->vender_id, j, sd->cart.u.items_cart[sd->vending[j].index].id, sd->vending[j].amount, sd->vending[j].value);
+		StringBuf_Printf(&buf, "(%d,%d,%d,%d,%d)", sd.vender_id, j, sd.cart.u.items_cart[sd.vending[j].index].id, sd.vending[j].amount, sd.vending[j].value);
 		if (j < i-1)
 			StringBuf_AppendStr(&buf, ",");
 	}
@@ -390,10 +384,10 @@ int8 vending_openvending(map_session_data* sd, const char* message, const uint8*
 		Sql_ShowDebug(mmysql_handle);
 	StringBuf_Destroy(&buf);
 
-	clif_openvending(sd,sd->bl.id,sd->vending);
-	clif_showvendingboard( *sd );
+	clif_openvending(&sd,sd.bl.id,sd.vending);
+	clif_showvendingboard( sd );
 
-	idb_put(vending_db, sd->status.char_id, sd);
+	idb_put(vending_db, sd.status.char_id, &sd);
 
 	return 0;
 }
@@ -497,15 +491,13 @@ bool vending_searchall(map_session_data* sd, const struct s_search_store_search*
 * Open vending for Autotrader
 * @param sd Player as autotrader
 */
-void vending_reopen( map_session_data* sd )
+void vending_reopen( map_session_data& sd )
 {
 	struct s_autotrader *at = NULL;
 	int8 fail = -1;
 
-	nullpo_retv(sd);
-
 	// Open vending for this autotrader
-	if ((at = (struct s_autotrader *)uidb_get(vending_autotrader_db, sd->status.char_id)) && at->count && at->entries) {
+	if ((at = (struct s_autotrader *)uidb_get(vending_autotrader_db, sd.status.char_id)) && at->count && at->entries) {
 		uint8 *data, *p;
 		uint16 j, count;
 
@@ -519,7 +511,7 @@ void vending_reopen( map_session_data* sd )
 			uint32 *value = (uint32*)(p + 4);
 
 			// Find item position in cart
-			ARR_FIND(0, MAX_CART, entry->index, sd->cart.u.items_cart[entry->index].id == entry->cartinventory_id);
+			ARR_FIND(0, MAX_CART, entry->index, sd.cart.u.items_cart[entry->index].id == entry->cartinventory_id);
 
 			if (entry->index == MAX_CART) {
 				count--;
@@ -527,35 +519,35 @@ void vending_reopen( map_session_data* sd )
 			}
 
 			*index = entry->index + 2;
-			*amount = itemdb_isstackable(sd->cart.u.items_cart[entry->index].nameid) ? entry->amount : 1;
+			*amount = itemdb_isstackable(sd.cart.u.items_cart[entry->index].nameid) ? entry->amount : 1;
 			*value = entry->price;
 
 			p += 8;
 		}
 
-		sd->state.prevend = 1; // Set him into a hacked prevend state
-		sd->state.autotrade = 1;
+		sd.state.prevend = 1; // Set him into a hacked prevend state
+		sd.state.autotrade = 1;
 
 		// Make sure abort all NPCs
-		npc_event_dequeue(sd);
-		pc_cleareventtimer(sd);
+		npc_event_dequeue(&sd);
+		pc_cleareventtimer(&sd);
 
 		// Open the vending again
 		if( (fail = vending_openvending(sd, at->title, data, count, at)) == 0 ) {
 			// Make vendor look perfect
-			pc_setdir(sd, at->dir, at->head_dir);
-			clif_changed_dir(&sd->bl, AREA_WOS);
+			pc_setdir(&sd, at->dir, at->head_dir);
+			clif_changed_dir(&sd.bl, AREA_WOS);
 			if( at->sit ) {
-				pc_setsit(sd);
-				skill_sit(sd, 1);
-				clif_sitting(&sd->bl);
+				pc_setsit(&sd);
+				skill_sit(&sd, 1);
+				clif_sitting(&sd.bl);
 			}
 
 			// Immediate save
-			chrif_save(sd, CSAVE_AUTOTRADE);
+			chrif_save(&sd, CSAVE_AUTOTRADE);
 
 			ShowInfo("Vending loaded for '" CL_WHITE "%s" CL_RESET "' with '" CL_WHITE "%d" CL_RESET "' items at " CL_WHITE "%s (%d,%d)" CL_RESET "\n",
-				sd->status.name, count, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y);
+				sd.status.name, count, mapindex_id2name(sd.mapindex), sd.bl.x, sd.bl.y);
 		}
 		aFree(data);
 	}
@@ -567,8 +559,8 @@ void vending_reopen( map_session_data* sd )
 	}
 
 	if (fail != 0) {
-		ShowError("vending_reopen: (Error:%d) Load failed for autotrader '" CL_WHITE "%s" CL_RESET "' (CID=%d/AID=%d)\n", fail, sd->status.name, sd->status.char_id, sd->status.account_id);
-		map_quit(sd);
+		ShowError("vending_reopen: (Error:%d) Load failed for autotrader '" CL_WHITE "%s" CL_RESET "' (CID=%d/AID=%d)\n", fail, sd.status.name, sd.status.char_id, sd.status.account_id);
+		map_quit(&sd);
 	}
 }
 

+ 2 - 2
src/map/vending.hpp

@@ -23,9 +23,9 @@ void do_final_vending(void);
 void do_init_vending(void);
 void do_init_vending_autotrade( void );
  
-void vending_reopen( map_session_data* sd );
+void vending_reopen( map_session_data& sd );
 void vending_closevending(map_session_data* sd);
-int8 vending_openvending(map_session_data* sd, const char* message, const uint8* data, int count, struct s_autotrader *at);
+int8 vending_openvending( map_session_data& sd, const char* message, const uint8* data, int count, struct s_autotrader *at );
 void vending_vendinglistreq(map_session_data* sd, int id);
 void vending_purchasereq(map_session_data* sd, int aid, int uid, const uint8* data, int count);
 bool vending_search(map_session_data* sd, t_itemid nameid);

+ 9 - 6
src/tool/csv2yaml.cpp

@@ -241,6 +241,9 @@ bool Csv2YamlTool::initialize( int argc, char* argv[] ){
 	#define export_constant_npc(a) export_constant(a)
 	init_random_option_constants();
 	#include <map/script_constants.hpp>
+	// Constants that are deprecated but still needed for conversion
+	script_set_constant(QUOTE(RC2_GUARDIAN), RC2_GUARDIAN, false, false);
+	script_set_constant(QUOTE(RC2_BATTLEFIELD), RC2_BATTLEFIELD, false, false);
 
 	std::vector<std::string> root_paths = {
 		path_db,
@@ -3367,17 +3370,17 @@ static bool mob_readdb_sub( char *fields[], size_t columns, size_t current ){
 		body << YAML::Key << "Defense" << YAML::Value << cap_value(std::stoi(fields[12]), DEFTYPE_MIN, DEFTYPE_MAX);
 	if (strtol(fields[13], nullptr, 10) > 0)
 		body << YAML::Key << "MagicDefense" << YAML::Value << cap_value(std::stoi(fields[13]), DEFTYPE_MIN, DEFTYPE_MAX);
-	if (strtol(fields[14], nullptr, 10) > 1)
+	if (strtol(fields[14], nullptr, 10) != 1)
 		body << YAML::Key << "Str" << YAML::Value << fields[14];
-	if (strtol(fields[15], nullptr, 10) > 1)
+	if (strtol(fields[15], nullptr, 10) != 1)
 		body << YAML::Key << "Agi" << YAML::Value << fields[15];
-	if (strtol(fields[16], nullptr, 10) > 1)
+	if (strtol(fields[16], nullptr, 10) != 1)
 		body << YAML::Key << "Vit" << YAML::Value << fields[16];
-	if (strtol(fields[17], nullptr, 10) > 1)
+	if (strtol(fields[17], nullptr, 10) != 1)
 		body << YAML::Key << "Int" << YAML::Value << fields[17];
-	if (strtol(fields[18], nullptr, 10) > 1)
+	if (strtol(fields[18], nullptr, 10) != 1)
 		body << YAML::Key << "Dex" << YAML::Value << fields[18];
-	if (strtol(fields[19], nullptr, 10) > 1)
+	if (strtol(fields[19], nullptr, 10) != 1)
 		body << YAML::Key << "Luk" << YAML::Value << fields[19];
 	if (strtol(fields[9], nullptr, 10) > 0)
 		body << YAML::Key << "AttackRange" << YAML::Value << fields[9];

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio