Skip to content

Commit

Permalink
Merge pull request #715 from tiltedphoques/dev
Browse files Browse the repository at this point in the history
v1.6.8
  • Loading branch information
maximegmd authored Sep 29, 2024
2 parents 8de72ba + b4155e6 commit b3e9e69
Show file tree
Hide file tree
Showing 73 changed files with 1,059 additions and 269 deletions.
23 changes: 9 additions & 14 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
if: "!contains(github.event.head_commit.message, 'ci skip')"

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Checkout submodules
run: |
Expand All @@ -28,32 +28,27 @@ jobs:
# Install dependencies
- name: Update apt repositories
run: sudo apt-get update

- name: Install GCC12
shell: bash
run: |
sudo apt update
sudo apt install gcc-12 g++-12
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 110 --slave /usr/bin/g++ g++ /usr/bin/g++-12 --slave /usr/bin/gcov gcov /usr/bin/gcov-12

# Install xmake
- name: Setup xmake
uses: xmake-io/github-action-setup-xmake@v1
with:
xmake-version: '2.9.2'
xmake-version: '2.9.5'

# Update xmake repository (in order to have the file that will be cached)
- name: Update xmake repository
run: xmake repo --update

# Setup compilation mode and install project dependencies
# (continue-on-error + timeout is a temporary solution until sentry-native is fixed; shouldn't affect the building step)
- name: Configure xmake and install dependencies
run: xmake config --arch=${{ matrix.arch }} --mode=${{ matrix.mode }} --yes
continue-on-error: true
run: timeout 15m xmake config --arch=${{ matrix.arch }} --mode=${{ matrix.mode }} --yes

# Build the game
# Build the server
- name: Build
run: xmake
run: xmake -y

# Create install
#- name: Install
# run: xmake install -o packaged
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Setup xmake
uses: xmake-io/github-action-setup-xmake@v1
with:
xmake-version: '2.9.2'
xmake-version: '2.9.5'

# Install node
#- name: Setup nodejs
Expand Down
4 changes: 3 additions & 1 deletion Code/client/Events/ActivateEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ struct ActivateEvent
{
}
#elif TP_SKYRIM64
ActivateEvent(TESObjectREFR* apObject, Actor* apActivator, TESBoundObject* apObjectToGet, int32_t aCount, bool aDefaultProcessing, uint8_t aUnk1, bool aActivateFlag = false)
ActivateEvent(TESObjectREFR* apObject, Actor* apActivator, TESBoundObject* apObjectToGet, int32_t aCount, bool aDefaultProcessing, uint8_t aUnk1, TESObjectREFR::OpenState aPreActivationOpenState, bool aActivateFlag = false)
: pObject(apObject)
, pActivator(apActivator)
, pObjectToGet(apObjectToGet)
, Count(aCount)
, DefaultProcessing(aDefaultProcessing)
, Unk1(aUnk1)
, PreActivationOpenState(aPreActivationOpenState)
, ActivateFlag(aActivateFlag)
{
}
Expand All @@ -46,5 +47,6 @@ struct ActivateEvent
uint8_t Unk1;
#endif

TESObjectREFR::OpenState PreActivationOpenState;
bool ActivateFlag;
};
16 changes: 16 additions & 0 deletions Code/client/Events/SetTimeCommandEvent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

struct SetTimeCommandEvent
{
SetTimeCommandEvent() = delete;
SetTimeCommandEvent(uint8_t aHours, uint8_t aMinutes, uint32_t aPlayerId)
: Hours(aHours)
, Minutes(aMinutes)
, PlayerId(aPlayerId)
{
}

uint8_t Hours;
uint8_t Minutes;
uint32_t PlayerId;
};
10 changes: 10 additions & 0 deletions Code/client/Games/Fallout4/TESObjectREFR.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ struct TESObjectREFR : TESForm
IRR_STORE_IN_TEAMMATE = 0x5,
};

enum OpenState : uint8_t
{
kNone = 0,
kOpen,
kOpening,
kClosed,
kClosing,
};

struct RemoveItemData
{
uint8_t stackData[0x20]{};
Expand Down Expand Up @@ -194,6 +203,7 @@ struct TESObjectREFR : TESForm
void LockChange() noexcept;

const float GetHeight() noexcept;
OpenState GetOpenState() noexcept;

Inventory GetInventory() const noexcept;
void SetInventory(const Inventory& acContainer) noexcept;
Expand Down
9 changes: 9 additions & 0 deletions Code/client/Games/References.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,15 @@ const float TESObjectREFR::GetHeight() noexcept
return boundMax.z - GetBoundMin().z;
}

TESObjectREFR::OpenState TESObjectREFR::GetOpenState() noexcept
{
using ObjectReference = TESObjectREFR;

PAPYRUS_FUNCTION(TESObjectREFR::OpenState, ObjectReference, GetOpenState);

return s_pGetOpenState(this);
}

bool ActorState::SetWeaponDrawn(bool aDraw) noexcept
{
TP_THIS_FUNCTION(TSetWeaponState, bool, ActorState, bool aDraw);
Expand Down
11 changes: 11 additions & 0 deletions Code/client/Games/Skyrim/Forms/MagicItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ bool MagicItem::IsBuffSpell() const noexcept
}
}

bool MagicItem::IsBoundWeaponSpell() noexcept
{
for (EffectItem* pEffect : listOfEffects)
{
if (pEffect->pEffectSetting && pEffect->pEffectSetting->eArchetype == EffectArchetypes::ArchetypeID::kBoundWeapon)
return true;
}

return false;
}

EffectItem* MagicItem::GetEffect(const uint32_t aEffectId) noexcept
{
for (EffectItem* pEffect : listOfEffects)
Expand Down
1 change: 1 addition & 0 deletions Code/client/Games/Skyrim/Forms/MagicItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ struct MagicItem : TESBoundObject
bool IsInvisibilitySpell() const noexcept;
bool IsHealingSpell() const noexcept;
bool IsBuffSpell() const noexcept;
bool IsBoundWeaponSpell() noexcept;

EffectItem* GetEffect(const uint32_t aEffectId) noexcept;

Expand Down
10 changes: 9 additions & 1 deletion Code/client/Games/Skyrim/TESObjectREFR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,15 @@ bool TP_MAKE_THISCALL(HookActivate, TESObjectREFR, TESObjectREFR* apActivator, u
// Exclude books from activation since only reading them removes them from the cell
// Note: Books are now unsynced
if (pActivator && apThis->baseForm->formType != FormType::Book)
World::Get().GetRunner().Trigger(ActivateEvent(apThis, pActivator, apObjectToGet, aUnk1, aCount, aDefaultProcessing));
{
auto openState = TESObjectREFR::kNone;
if (apThis->baseForm->formType == FormType::Door)
openState = apThis->GetOpenState();

World::Get().GetRunner().Trigger(
ActivateEvent(apThis, pActivator, apObjectToGet, aCount, aDefaultProcessing, aUnk1, openState)
);
}

return TiltedPhoques::ThisCall(RealActivate, apThis, apActivator, aUnk1, apObjectToGet, aCount, aDefaultProcessing);
}
Expand Down
10 changes: 10 additions & 0 deletions Code/client/Games/Skyrim/TESObjectREFR.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ struct TESObjectREFR : TESForm
CHANGE_REFR_EXTRA_GAME_ONLY = 1u << 31,
};

enum OpenState : uint8_t
{
kNone = 0,
kOpen,
kOpening,
kClosed,
kClosing,
};

static TESObjectREFR* GetByHandle(uint32_t aHandle) noexcept;
static uint32_t* GetNullHandle() noexcept;

Expand Down Expand Up @@ -188,6 +197,7 @@ struct TESObjectREFR : TESForm

const float GetHeight() noexcept;
void EnableImpl() noexcept;
OpenState GetOpenState() noexcept;

Inventory GetInventory() const noexcept;
Inventory GetInventory(std::function<bool(TESForm&)> aFilter) const noexcept;
Expand Down
16 changes: 16 additions & 0 deletions Code/client/NvidiaUtil.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "NvidiaUtil.h"
#include <d3d11.h>

bool IsNvidiaOverlayLoaded()
{
return GetModuleHandleW(L"nvspcap64.dll");
}

// This makes the Nvidia overlay happy.
// The call to D3D11CreateDevice probably causes some of their
// internal hooks to be called and do the required init work before the game window opens.
HRESULT CreateEarlyDxDevice(ID3D11Device* apOutDevice, D3D_FEATURE_LEVEL* apOutFeatureLevel)
{
return D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &apOutDevice,
apOutFeatureLevel, nullptr);
}
8 changes: 8 additions & 0 deletions Code/client/NvidiaUtil.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

#include <Windows.h>
#include <d3d11.h>

bool IsNvidiaOverlayLoaded();

HRESULT CreateEarlyDxDevice(ID3D11Device* apOutDevice, D3D_FEATURE_LEVEL* apOutFeatureLevel);
3 changes: 3 additions & 0 deletions Code/client/Services/CommandService.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

struct World;
struct TransportService;
struct SetTimeCommandEvent;
struct TeleportCommandResponse;

/**
Expand All @@ -19,6 +20,7 @@ struct CommandService
TP_NOCOPYMOVE(CommandService);

protected:
void OnSetTimeCommand(const SetTimeCommandEvent&) const noexcept;
/**
* @brief Processes result of teleport command.
*/
Expand All @@ -28,5 +30,6 @@ struct CommandService
World& m_world;
TransportService& m_transport;

entt::scoped_connection m_setTimeConnection;
entt::scoped_connection m_teleportConnection;
};
14 changes: 14 additions & 0 deletions Code/client/Services/Generic/CommandService.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

#include <Services/CommandService.h>
#include <Services/TransportService.h>

Expand All @@ -8,18 +9,31 @@
#include <Forms/TESWorldSpace.h>
#include <PlayerCharacter.h>

#include <Events/SetTimeCommandEvent.h>

#include <Messages/TeleportCommandRequest.h>
#include <Messages/TeleportCommandResponse.h>
#include "Messages/SetTimeCommandRequest.h"

#include <Structs/GridCellCoords.h>

CommandService::CommandService(World& aWorld, TransportService& aTransport, entt::dispatcher& aDispatcher)
: m_world(aWorld)
, m_transport(aTransport)
{
m_setTimeConnection = aDispatcher.sink<SetTimeCommandEvent>().connect<&CommandService::OnSetTimeCommand>(this);
m_teleportConnection = aDispatcher.sink<TeleportCommandResponse>().connect<&CommandService::OnTeleportCommandResponse>(this);
}

void CommandService::OnSetTimeCommand(const SetTimeCommandEvent& acEvent) const noexcept
{
SetTimeCommandRequest request{};
request.Hours = acEvent.Hours;
request.Minutes = acEvent.Minutes;
request.PlayerId = acEvent.PlayerId;
m_transport.Send(request);
}

void CommandService::OnTeleportCommandResponse(const TeleportCommandResponse& acMessage) noexcept
{
spdlog::info("TeleportCommandResponse: {:X}:{:X} at position {}, {}, {}", acMessage.CellId.ModId, acMessage.CellId.BaseId, acMessage.Position.x, acMessage.Position.y, acMessage.Position.z);
Expand Down
2 changes: 1 addition & 1 deletion Code/client/Services/Generic/MagicService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ void MagicService::OnAddTargetEvent(const AddTargetEvent& acEvent) noexcept
// These effects are applied through spell cast sync
if (SpellItem* pSpellItem = Cast<SpellItem>(TESForm::GetById(acEvent.SpellID)))
{
if ((pSpellItem->eCastingType == MagicSystem::CastingType::CONCENTRATION && !pSpellItem->IsHealingSpell()) || pSpellItem->IsWardSpell() || pSpellItem->IsInvisibilitySpell())
if ((pSpellItem->eCastingType == MagicSystem::CastingType::CONCENTRATION && !pSpellItem->IsHealingSpell()) || pSpellItem->IsWardSpell() || pSpellItem->IsInvisibilitySpell() || pSpellItem->IsBoundWeaponSpell())
{
return;
}
Expand Down
14 changes: 14 additions & 0 deletions Code/client/Services/Generic/ObjectService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ void ObjectService::OnActivate(const ActivateEvent& acEvent) noexcept
return;

request.ActivatorId = serverIdRes.value();
request.PreActivationOpenState = acEvent.PreActivationOpenState;

m_transport.Send(request);
}
Expand All @@ -298,6 +299,19 @@ void ObjectService::OnActivateNotify(const NotifyActivate& acMessage) noexcept
return;
}

if (pObject->baseForm->formType == FormType::Door)
{
auto remotePreActivationState = static_cast<TESObjectREFR::OpenState>(acMessage.PreActivationOpenState);
TESObjectREFR::OpenState localState = pObject->GetOpenState();

if (remotePreActivationState != localState)
{
// The doors are unsynced at this point. If we'll Activate the one on our side
// it'll just continue to be unsynced (open remotely, closed locally and vice versa)
return;
}
}

// unsure if these flags are the best, but these are passed with the papyrus Activate fn
// might be an idea to have the client send the flags through NotifyActivate
#if TP_FALLOUT4
Expand Down
13 changes: 13 additions & 0 deletions Code/client/Services/Generic/OverlayClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <Messages/SendChatMessageRequest.h>
#include <Messages/TeleportRequest.h>

#include <Events/SetTimeCommandEvent.h>

#include <World.h>

OverlayClient::OverlayClient(TransportService& aTransport, TiltedPhoques::OverlayRenderHandler* apHandler)
Expand Down Expand Up @@ -44,6 +46,8 @@ bool OverlayClient::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefR
ProcessDisconnectMessage();
else if (eventName == "sendMessage")
ProcessChatMessage(eventArgs);
else if (eventName == "setTime")
ProcessSetTimeCommand(eventArgs);
else if (eventName == "launchParty")
World::Get().GetPartyService().CreateParty();
else if (eventName == "leaveParty")
Expand Down Expand Up @@ -111,10 +115,19 @@ void OverlayClient::ProcessChatMessage(CefRefPtr<CefListValue> aEventArgs)
messageRequest.ChatMessage = contents;

spdlog::info(L"Send chat message of type {}: '{}' ", messageRequest.MessageType, aEventArgs->GetString(1).ToWString());

m_transport.Send(messageRequest);
}
}

void OverlayClient::ProcessSetTimeCommand(CefRefPtr<CefListValue> aEventArgs)
{
const uint8_t hours = static_cast<uint8_t>(aEventArgs->GetInt(0));
const uint8_t minutes = static_cast<uint8_t>(aEventArgs->GetInt(1));
const uint32_t senderId = m_transport.GetLocalPlayerId();
World::Get().GetDispatcher().trigger(SetTimeCommandEvent(hours, minutes, senderId));
}

void OverlayClient::ProcessTeleportMessage(CefRefPtr<CefListValue> aEventArgs)
{
TeleportRequest request{};
Expand Down
12 changes: 12 additions & 0 deletions Code/client/Services/Generic/TransportService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ TransportService::TransportService(World& aWorld, entt::dispatcher& aDispatcher)
{
m_updateConnection = m_dispatcher.sink<UpdateEvent>().connect<&TransportService::HandleUpdate>(this);
m_settingsChangeConnection = m_dispatcher.sink<NotifySettingsChange>().connect<&TransportService::HandleNotifySettingsChange>(this);
m_connectedConnection = m_dispatcher.sink<ConnectedEvent>().connect<&TransportService::HandleConnected>(this);
m_disconnectedConnection = m_dispatcher.sink<DisconnectedEvent>().connect<&TransportService::HandleDisconnected>(this);

m_connected = false;

Expand Down Expand Up @@ -181,6 +183,16 @@ void TransportService::HandleUpdate(const UpdateEvent& acEvent) noexcept
Update();
}

void TransportService::HandleConnected(const ConnectedEvent& acEvent) noexcept
{
m_localPlayerId = acEvent.PlayerId;
}

void TransportService::HandleDisconnected(const DisconnectedEvent& acEvent) noexcept
{
m_localPlayerId = NULL;
}

void TransportService::HandleAuthenticationResponse(const AuthenticationResponse& acMessage) noexcept
{
using AR = AuthenticationResponse::ResponseType;
Expand Down
Loading

0 comments on commit b3e9e69

Please sign in to comment.