diff --git a/soh/soh/Enhancements/enhancementTypes.h b/soh/soh/Enhancements/enhancementTypes.h index bd025115b90..9de1ef7b944 100644 --- a/soh/soh/Enhancements/enhancementTypes.h +++ b/soh/soh/Enhancements/enhancementTypes.h @@ -87,6 +87,14 @@ typedef enum { DAMAGE_OHKO } DamageMultType; +typedef enum { + PVP_DAMAGE_MULT_1X, + PVP_DAMAGE_MULT_2X, + PVP_DAMAGE_MULT_4X, + PVP_DAMAGE_MULT_8X, + PVP_DAMAGE_MULT_OHKO, +} PvpDamageMult; + typedef enum { DAMPE_NONE, DAMPE_NORMAL, diff --git a/soh/soh/Network/Anchor/Anchor.h b/soh/soh/Network/Anchor/Anchor.h index 9eb10323091..9c763b2a156 100644 --- a/soh/soh/Network/Anchor/Anchor.h +++ b/soh/soh/Network/Anchor/Anchor.h @@ -62,6 +62,7 @@ typedef struct { typedef struct { uint32_t ownerClientId; u8 pvpMode; // 0 = off, 1 = on, 2 = on with friendly fire + u8 pvpDamageMult; // 0 = 1x, 1 = 2x, 2 = 4x, 3 = 8x, 4 = OHKO u8 showLocationsMode; // 0 = none, 1 = team, 2 = all u8 teleportMode; // 0 = off, 1 = team, 2 = all u8 syncItemsAndFlags; // 0 = off, 1 = on diff --git a/soh/soh/Network/Anchor/Menu.cpp b/soh/soh/Network/Anchor/Menu.cpp index 77b544fb3df..d5c82f6e2e9 100644 --- a/soh/soh/Network/Anchor/Menu.cpp +++ b/soh/soh/Network/Anchor/Menu.cpp @@ -10,6 +10,13 @@ extern std::shared_ptr mAnchorRoomWindow; } // namespace SohGui static const char* pvpModes[3] = { "Off", "On", "On + Friendly Fire" }; +static const char* pvpDamageMults[5] = { + "1x: Kokiri sword slash damages quarter heart.", + "2x: Kokiri sword slash damages half heart.", + "4x: Kokiri sword slash damages one heart.", + "8x: Kokiri sword slash damages two hearts.", + "One Hit KO", +}; static std::vector teleportModes = { "None", "Team Only", "All" }; static std::vector showLocationsModes = { "None", "Team Only", "All" }; @@ -174,6 +181,14 @@ void AnchorAdminMenu(WidgetInfo& info) { .Color(THEME_COLOR))) { anchor->SendPacket_UpdateRoomState(); } + if (UIWidgets::CVarCombobox("PvP Damage Multiplier:", CVAR_REMOTE_ANCHOR("RoomSettings.PvpDamageMult"), + pvpDamageMults, + UIWidgets::ComboboxOptions() + .DefaultIndex(1) + .LabelPosition(UIWidgets::LabelPositions::Above) + .Color(THEME_COLOR))) { + anchor->SendPacket_UpdateRoomState(); + } if (UIWidgets::CVarCombobox("Show Locations For:", CVAR_REMOTE_ANCHOR("RoomSettings.ShowLocationsMode"), showLocationsModes, UIWidgets::ComboboxOptions() diff --git a/soh/soh/Network/Anchor/Packets/DamagePlayer.cpp b/soh/soh/Network/Anchor/Packets/DamagePlayer.cpp index e97abea4fab..acc7b726674 100644 --- a/soh/soh/Network/Anchor/Packets/DamagePlayer.cpp +++ b/soh/soh/Network/Anchor/Packets/DamagePlayer.cpp @@ -1,6 +1,7 @@ #include "soh/Network/Anchor/Anchor.h" #include #include +#include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" extern "C" { @@ -14,6 +15,24 @@ void func_80838280(Player* player); * DAMAGE_PLAYER */ +int GetPvpDamageMultiplier(const RoomState& roomState) { + uint8_t damageOption = roomState.pvpDamageMult; + switch (damageOption) { + case PVP_DAMAGE_MULT_1X: + return 1; + case PVP_DAMAGE_MULT_2X: + return 2; + case PVP_DAMAGE_MULT_4X: + return 4; + case PVP_DAMAGE_MULT_8X: + return 8; + case PVP_DAMAGE_MULT_OHKO: + return 256; + default: + return 1; + } +} + void Anchor::SendPacket_DamagePlayer(u32 clientId, u8 damageEffect, u8 damage) { if (!IsSaveLoaded()) { return; @@ -47,7 +66,7 @@ void Anchor::HandlePacket_DamagePlayer(nlohmann::json payload) { u8 damageEffect = payload["damageEffect"].get(); u8 damage = payload["damage"].get(); - self->actor.colChkInfo.damage = damage * 8; // Arbitrary number currently, need to fine tune + self->actor.colChkInfo.damage = damage * GetPvpDamageMultiplier(roomState) * 4; if (damageEffect == DUMMY_PLAYER_HIT_RESPONSE_FIRE) { for (int i = 0; i < ARRAY_COUNT(self->bodyFlameTimers); i++) { diff --git a/soh/soh/Network/Anchor/Packets/UpdateRoomState.cpp b/soh/soh/Network/Anchor/Packets/UpdateRoomState.cpp index 327385715fa..04ec6c0a2d2 100644 --- a/soh/soh/Network/Anchor/Packets/UpdateRoomState.cpp +++ b/soh/soh/Network/Anchor/Packets/UpdateRoomState.cpp @@ -21,11 +21,13 @@ nlohmann::json Anchor::PrepRoomState() { if (isGlobalRoom) { // Global room uses hardcoded settings payload["pvpMode"] = 0; + payload["pvpDamageMult"] = 0; payload["showLocationsMode"] = 0; payload["teleportMode"] = 0; payload["syncItemsAndFlags"] = 0; } else { payload["pvpMode"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.PvpMode"), 1); + payload["pvpDamageMult"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.PvpDamageMult"), 1); payload["showLocationsMode"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.ShowLocationsMode"), 1); payload["teleportMode"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.TeleportMode"), 1); payload["syncItemsAndFlags"] = CVarGetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.SyncItemsAndFlags"), 1); @@ -49,6 +51,7 @@ void Anchor::HandlePacket_UpdateRoomState(nlohmann::json payload) { roomState.ownerClientId = payload["state"]["ownerClientId"].get(); roomState.pvpMode = payload["state"]["pvpMode"].get(); + roomState.pvpDamageMult = payload["state"].value("pvpDamageMult", 1); roomState.showLocationsMode = payload["state"]["showLocationsMode"].get(); roomState.teleportMode = payload["state"]["teleportMode"].get(); roomState.syncItemsAndFlags = payload["state"]["syncItemsAndFlags"].get();