From 7bfd9538c97a60a452128a88fbc566d51de51597 Mon Sep 17 00:00:00 2001 From: Mimi <44952533+arieshi255@users.noreply.github.com> Date: Fri, 21 Jun 2024 04:27:01 +0200 Subject: [PATCH] [3.x] WIP: Initial Action and StatusEffect implementation (#958) * Check statuses to determine valid lut entry * Add duration field to statuses * Rename buildEffects to make more sense * Add basic generic handler for applying statuseffects * Add more modifiers * Add basic modifier impl for Chara * Apply/remove modifiers for statuseffects * Add some example statuses to lut * Fix windows build error * Don't clear tick effect * Add status entry for Maim * Apply status effects properly for self when having a target * Fix hasStatusEffect to prevent duplicates * Basic dot/hot ticks implemented * Update HP on tick effects * Apply effect to correct target * Add method to simplify applying statuses to self * Add job actions for warrior * Add some actions and statuses for war * Add even more modifiers * Add statuseffect cost type * Add option to not send statusremove order * Change delModifier assert to return early instead * Add option for scripts to enable the generic/lut handler * Add enums for common action values * fix indentation * Fix modifier name for Defiance * Remove status tick logging * Move modifiers to statuseffect * Add ParryPercent modifier * Remove wrath when Defiance ends * Apply modifiers in applyStatus * Remove unused method * Persistence for cross-class skills * Add flags to StatusEffects * Some exd struct fixes * Some aoe work * Add flags to lut * Add missing changeclass * Add SET_STATUS_ME to ActionIntegrity * Improve offensive action check * Add flag to overloaded applyStatusEffectSelf * indentation fix * Some calculation work * Null-check ActionResultBuilder --------- Co-authored-by: Lucy <44952533+Skyliegirl33@users.noreply.github.com> Co-authored-by: Mordred <30826167+SapphireMordred@users.noreply.github.com> --- data/actions/player.json | 163 ++++++++++++++++-- deps/datReader/Exd/Structs.h | 13 +- .../20230309164293_AddBorrowAction.sql | 1 + src/api/PlayerMinimal.cpp | 4 +- src/common/Common.h | 71 ++++++-- src/common/Database/ZoneDbConnection.cpp | 6 +- src/scripts/action/war/ActionInnerBeast.cpp | 47 +++++ src/scripts/action/war/ActionUnchained.cpp | 33 ++++ .../statuseffect/StatusEffectDefiance.cpp | 27 +++ .../statuseffect/StatusEffectUnchained.cpp | 24 +++ src/tools/action_parse/main.cpp | 4 + src/world/Action/Action.cpp | 94 +++++++++- src/world/Action/Action.h | 8 + src/world/Action/ActionLut.cpp | 3 +- src/world/Action/ActionLut.h | 2 + src/world/Action/ActionLutData.cpp | 18 +- src/world/Action/ActionLutData.h | 3 + src/world/Action/ActionResult.cpp | 29 +++- src/world/Action/ActionResult.h | 5 + src/world/Action/ActionResultBuilder.cpp | 18 +- src/world/Action/ActionResultBuilder.h | 9 +- src/world/Action/CommonAction.h | 30 ++++ src/world/Action/Job/Warrior.cpp | 70 ++++++++ src/world/Action/Job/Warrior.h | 20 +++ src/world/Actor/Chara.cpp | 84 ++++++++- src/world/Actor/Chara.h | 12 +- src/world/Actor/Player.cpp | 17 ++ src/world/Actor/Player.h | 7 + src/world/Actor/PlayerSql.cpp | 20 ++- src/world/CMakeLists.txt | 1 + src/world/Manager/ActionMgr.cpp | 7 - src/world/Math/CalcStats.cpp | 11 +- .../Network/Handlers/PacketCommandHandler.cpp | 5 + src/world/Network/Util/PacketUtil.cpp | 2 + src/world/Script/ScriptMgr.cpp | 3 - src/world/StatusEffect/StatusEffect.cpp | 93 +++++++++- src/world/StatusEffect/StatusEffect.h | 25 ++- 37 files changed, 902 insertions(+), 87 deletions(-) create mode 100644 sql/migrations/20230309164293_AddBorrowAction.sql create mode 100644 src/scripts/action/war/ActionInnerBeast.cpp create mode 100644 src/scripts/action/war/ActionUnchained.cpp create mode 100644 src/scripts/statuseffect/StatusEffectDefiance.cpp create mode 100644 src/scripts/statuseffect/StatusEffectUnchained.cpp create mode 100644 src/world/Action/CommonAction.h create mode 100644 src/world/Action/Job/Warrior.cpp create mode 100644 src/world/Action/Job/Warrior.h diff --git a/data/actions/player.json b/data/actions/player.json index e6c9cb3e73..c266e805bb 100644 --- a/data/actions/player.json +++ b/data/actions/player.json @@ -398,7 +398,18 @@ "restorePercentage": 0, "nextCombo": [], "statuses": { - "caster": [], + "caster": [ + { + "id": 83, + "duration": 20000, + "modifiers": [ + { + "modifier": "DefensePercent", + "value": 20 + } + ] + } + ], "target": [] } }, @@ -414,7 +425,18 @@ "nextCombo": [], "statuses": { "caster": [], - "target": [] + "target": [ + { + "id": 244, + "duration": 30000, + "modifiers": [ + { + "modifier": "TickDamage", + "value": 20 + } + ] + } + ] } }, "34": { @@ -478,7 +500,18 @@ 45 ], "statuses": { - "caster": [], + "caster": [ + { + "id": 85, + "duration": 24000, + "modifiers": [ + { + "modifier": "DamageDealtPercent", + "value": 20 + } + ] + } + ], "target": [] } }, @@ -493,7 +526,18 @@ "restorePercentage": 0, "nextCombo": [], "statuses": { - "caster": [], + "caster": [ + { + "id": 86, + "duration": 20000, + "modifiers": [ + { + "modifier": "AttackPowerPercent", + "value": 50 + } + ] + } + ], "target": [] } }, @@ -523,7 +567,18 @@ "restorePercentage": 0, "nextCombo": [], "statuses": { - "caster": [], + "caster": [ + { + "id": 87, + "duration": 20000, + "modifiers": [ + { + "modifier": "HPPercent", + "value": 20 + } + ] + } + ], "target": [] } }, @@ -574,7 +629,7 @@ }, "44": { "name": "Vengeance", - "potency": 50, + "potency": 0, "comboPotency": 0, "flankPotency": 0, "frontPotency": 0, @@ -583,7 +638,18 @@ "restorePercentage": 0, "nextCombo": [], "statuses": { - "caster": [], + "caster": [ + { + "id": 89, + "duration": 20000, + "modifiers": [ + { + "modifier": "ReflectPhysical", + "value": 50 + } + ] + } + ], "target": [] } }, @@ -643,7 +709,34 @@ "restorePercentage": 0, "nextCombo": [], "statuses": { - "caster": [], + "caster": [ + { + "id": 91, + "duration": 0, + "modifiers": [ + { + "modifier": "HPPercent", + "value": 25 + }, + { + "modifier": "DamageDealtPercent", + "value": -25 + }, + { + "modifier": "HealingMagicRecoveryPercent", + "value": 20 + }, + { + "modifier": "AccuracyPercent", + "value": 5 + }, + { + "modifier": "EnmityPercent", + "value": 20 + } + ] + } + ], "target": [] } }, @@ -703,7 +796,12 @@ "restorePercentage": 0, "nextCombo": [], "statuses": { - "caster": [], + "caster": [ + { + "id": 97, + "duration": 30000 + } + ], "target": [] } }, @@ -1176,7 +1274,19 @@ "restorePercentage": 0, "nextCombo": [], "statuses": { - "caster": [], + "caster": [ + { + "id": 116, + "duration": 10000, + "flag": 4096, + "modifiers": [ + { + "modifier": "CriticalHitPercent", + "value": 100 + } + ] + } + ], "target": [] } }, @@ -2454,7 +2564,38 @@ "nextCombo": [], "statuses": { "caster": [], - "target": [] + "target": [ + { + "id": 180, + "duration": 24000, + "modifiers": [ + { + "modifier": "TickDamage", + "value": 35 + } + ] + }, + { + "id": 191, + "duration": 24000, + "modifiers": [ + { + "modifier": "HealingRecoveryPercent", + "value": -20 + } + ] + }, + { + "id": 240, + "duration": 24000, + "modifiers": [ + { + "modifier": "HeavyPercent", + "value": 40 + } + ] + } + ] } }, "169": { diff --git a/deps/datReader/Exd/Structs.h b/deps/datReader/Exd/Structs.h index 28ed82a51e..1d1de7b052 100644 --- a/deps/datReader/Exd/Structs.h +++ b/deps/datReader/Exd/Structs.h @@ -391,14 +391,14 @@ namespace Excel uint8_t EffectWidth; uint8_t CostType; uint8_t Cond; - uint8_t RecastGroup; uint8_t Element; uint8_t ProcStatus; - uint8_t UseClassJob; + uint8_t ClassJobCategory; + uint8_t RecastGroup; uint8_t Init; uint8_t Omen; - uint8_t Unknown; - int8_t Learn; + uint8_t Learn; + int8_t UseClassJob; int8_t SelectRange; int8_t SelectCorpse; int8_t AttackType; @@ -430,7 +430,7 @@ namespace Excel uint8_t HideCastBar : 1; uint8_t IsTargetLine : 1; - int8_t padding0; + int8_t unknown : 8; }; /* 75653 */ @@ -2054,7 +2054,8 @@ namespace Excel uint8_t NotControl : 1; uint8_t NotAction : 1; uint8_t NotMove : 1; - uint8_t padding0 : 6; + uint8_t padding0 : 5; + uint8_t CanOff : 1; uint8_t SemiTransparent : 1; uint8_t FcAction : 1; int8_t padding1[2]; diff --git a/sql/migrations/20230309164293_AddBorrowAction.sql b/sql/migrations/20230309164293_AddBorrowAction.sql new file mode 100644 index 0000000000..1cdc3f22ad --- /dev/null +++ b/sql/migrations/20230309164293_AddBorrowAction.sql @@ -0,0 +1 @@ +ALTER TABLE `characlass` ADD `BorrowAction` binary(40) DEFAULT NULL NULL AFTER `Lvl`; \ No newline at end of file diff --git a/src/api/PlayerMinimal.cpp b/src/api/PlayerMinimal.cpp index c761ac0439..f383a96d12 100644 --- a/src/api/PlayerMinimal.cpp +++ b/src/api/PlayerMinimal.cpp @@ -256,12 +256,14 @@ void PlayerMinimal::saveAsNew() break; } - // CharacterId, ClassIdx, Exp, Lvl + // CharacterId, ClassIdx, Exp, Lvl, BorrowAction auto stmtClass = g_charaDb.getPreparedStatement( Db::ZoneDbStatements::CHARA_CLASS_INS ); stmtClass->setUInt64( 1, m_characterId ); stmtClass->setInt( 2, g_exdData.getRow< Excel::ClassJob >( m_class )->data().WorkIndex ); stmtClass->setInt( 3, 0 ); stmtClass->setInt( 4, 1 ); + std::vector< uint8_t > borrowActionVec( Common::ARRSIZE_BORROWACTION * 4 ); + stmtClass->setBinary( 5, borrowActionVec ); g_charaDb.directExecute( stmtClass ); auto stmtSearchInfo = g_charaDb.getPreparedStatement( Db::ZoneDbStatements::CHARA_SEARCHINFO_INS ); diff --git a/src/common/Common.h b/src/common/Common.h index 27b2c06588..bceab9c0fc 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -37,6 +37,7 @@ namespace Sapphire::Common const uint16_t ARRSIZE_UNLOCKS = 64u; const uint16_t ARRSIZE_ORCHESTRION = 40u; const uint16_t ARRSIZE_MONSTERNOTE = 12u; + const uint16_t ARRSIZE_BORROWACTION = 10u; const uint8_t TOWN_COUNT = 6; @@ -887,22 +888,55 @@ namespace Sapphire::Common Perception = 73, // Unique modifiers - HPPercent = 1000, - MPPercent = 1001, - TPPercent = 1002, - GPPercent = 1003, - CPPercent = 1004, - PhysicalDamagePercent = 1005, - MagicDamagePercent = 1006, - AttackPowerPercent = 1007, - DefensePercent = 1008, - AccuracyPercent = 1009, - EvasionPercent = 1010, - MagicDefensePercent = 1011, - CriticalHitPowerPercent = 1012, - CriticalHitResiliencePercent = 1013, - CriticalHitPercent = 1014, - EnmityPercent = 1015 + TickHeal = 1000, + TickDamage = 1001, + StrengthPercent = 1002, + DexterityPercent = 1003, + VitalityPercent = 1004, + IntelligencePercent = 1005, + MindPercent = 1006, + PietyPercent = 1007, + HPPercent = 1008, + MPPercent = 1009, + TPPercent = 1010, + GPPercent = 1011, + CPPercent = 1012, + PhysicalDamagePercent = 1013, + MagicDamagePercent = 1014, + AttackPowerPercent = 1015, + DefensePercent = 1016, + AccuracyPercent = 1017, + EvasionPercent = 1018, + MagicDefensePercent = 1019, + CriticalHitPowerPercent = 1020, + CriticalHitResiliencePercent = 1021, + CriticalHitPercent = 1022, + EnmityPercent = 1023, + DamageDealtPercent = 1024, + DamageTakenPercent = 1025, + HealingMagicRecoveryPercent = 1026, + SlashingResistancePercent = 1027, + PiercingResistancePercent = 1028, + BluntResistancePercent = 1029, + ProjectileResistancePercent = 1030, + ParryPercent = 1031 + }; + + enum class StatusEffectFlag : uint32_t + { + BuffCategory = 1, + DebuffCategory = 2, + Permanent = 4, + IsGaze = 8, + Transfiguration = 16, + CanDispel = 32, + LockActions = 64, + LockControl = 128, + LockMovement = 256, + Invisibilty = 512, + CanStatusOff = 1024, + FcBuff = 2048, + RemoveOnSuccessfulHit = 4096 }; enum struct ActionAspect : uint8_t @@ -923,6 +957,7 @@ namespace Sapphire::Common MagicPoints = 3, TacticsPoints = 5, TacticsPoints1 = 6, + StatusEffect = 10, Sprint = 18, // WARGauge = 22, // DRKGauge = 25, @@ -1830,8 +1865,8 @@ namespace Sapphire::Common { SingleTarget = 1, CircularAOE = 2, - Type3 = 3, // another single target? no idea how to call it - RectangularAOE = 4, + RectangularAOE = 3, + ConeAOE = 4, CircularAoEPlaced = 7 }; diff --git a/src/common/Database/ZoneDbConnection.cpp b/src/common/Database/ZoneDbConnection.cpp index 10f9f854e0..6a0f79a0a3 100644 --- a/src/common/Database/ZoneDbConnection.cpp +++ b/src/common/Database/ZoneDbConnection.cpp @@ -161,11 +161,11 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements() prepareStatement( CHARA_SEL_QUEST, "SELECT * FROM charaquest WHERE CharacterId = ?;", CONNECTION_SYNC ); /// CLASS INFO - prepareStatement( CHARA_CLASS_SEL, "SELECT ClassIdx, Exp, Lvl FROM characlass WHERE CharacterId = ?;", + prepareStatement( CHARA_CLASS_SEL, "SELECT ClassIdx, Exp, Lvl, BorrowAction FROM characlass WHERE CharacterId = ?;", CONNECTION_SYNC ); - prepareStatement( CHARA_CLASS_INS, "INSERT INTO characlass ( CharacterId, ClassIdx, Exp, Lvl ) VALUES( ?,?,?,? );", + prepareStatement( CHARA_CLASS_INS, "INSERT INTO characlass ( CharacterId, ClassIdx, Exp, Lvl, BorrowAction ) VALUES( ?,?,?,?,? );", CONNECTION_BOTH ); - prepareStatement( CHARA_CLASS_UP, "UPDATE characlass SET Exp = ?, Lvl = ? WHERE CharacterId = ? AND ClassIdx = ?;", + prepareStatement( CHARA_CLASS_UP, "UPDATE characlass SET Exp = ?, Lvl = ?, BorrowAction = ? WHERE CharacterId = ? AND ClassIdx = ?;", CONNECTION_ASYNC ); prepareStatement( CHARA_CLASS_DEL, "DELETE FROM characlass WHERE CharacterId = ?;", CONNECTION_ASYNC ); diff --git a/src/scripts/action/war/ActionInnerBeast.cpp b/src/scripts/action/war/ActionInnerBeast.cpp new file mode 100644 index 0000000000..d4193e4d4a --- /dev/null +++ b/src/scripts/action/war/ActionInnerBeast.cpp @@ -0,0 +1,47 @@ +#include