Skip to content

Commit

Permalink
Merge pull request #7 from Silver-Ore-Team/feature/gothic1-support
Browse files Browse the repository at this point in the history
Gothic 1 Support
  • Loading branch information
muczc1wek authored Oct 4, 2024
2 parents b8e0122 + 7997329 commit 0411069
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 72 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include(FetchContent)
set(GOTHIC_API_G1 OFF)
set(GOTHIC_API_G1 ON)
set(GOTHIC_API_G1A OFF)
set(GOTHIC_API_G2 OFF)
set(GOTHIC_API_G2A ON)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ based on the solution form [AFSP Trialogue package](https://github.com/Bad-Scien
- [x] Implement the basic functionality of the multilogue system
- [ ] Increase the default display dialogue distance if needed
- [ ] Custom camera system
- [ ] Gothic 1 compatibility
- [x] Gothic 1 compatibility

## Usage
1. Download `zMultilogue.vdf` and place it inside `<GOTHIC_ROOT>/Data` with Union installed to automatically load the plugin at the start of the game.
Expand Down
4 changes: 3 additions & 1 deletion src/Gothic/Hooks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ namespace GOTHIC_NAMESPACE {
// return (this->*Ivk_oCNpc_ActivateDialogCam)(p1);
// }

auto Ivk_oCNpc_EV_Exchange = Union::CreateHook(reinterpret_cast<void*>(0x00753E30), &oCNpc::EV_Exchange_Hook);
// G1: 0x006AE310 protected: int __thiscall oCNpc::EV_Exchange(class oCMsgManipulate *)
// G2A: 0x00753E30 protected: int __thiscall oCNpc::EV_Exchange(class oCMsgManipulate *)
auto Ivk_oCNpc_EV_Exchange = Union::CreateHook(reinterpret_cast<void*>(zSwitch(0x006AE310, 0x00753E30)), &oCNpc::EV_Exchange_Hook);
int oCNpc::EV_Exchange_Hook( oCMsgManipulate* msg ) {
zSTRING msgSlot = msg->slot;
if (msgSlot) {
Expand Down
8 changes: 8 additions & 0 deletions src/NH/Commons.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

#include <Union/String.h>

namespace NH
{
using String = Union::StringUTF8;
}
130 changes: 74 additions & 56 deletions src/NH/Logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,98 +4,116 @@

#include <utility>

namespace NH {
String LoggerLevelToString(LoggerLevel level) {
String values[] = {
"NONE",
"FATAL",
"ERROR",
"WARN",
"INFO",
"DEBUG",
"TRACE"
};
return values[(size_t) level];
}

LoggerLevel StringToLoggerLevel(String level) {
String values[] = {
"NONE",
"FATAL",
"ERROR",
"WARN",
"INFO",
"DEBUG",
"TRACE"
};
namespace NH
{
LoggerLevel StringToLoggerLevel(String level)
{
String values[] = { "NONE", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" };
size_t count = sizeof(values) / sizeof(String);
for (size_t i = 0; i < count; i++) {
if (level.MakeUpper() == values[i]) {
return (LoggerLevel) i;
for (size_t i = 0; i < count; i++)
{
if (level.MakeUpper() == values[i])
{
return (LoggerLevel)i;
}
}
return LoggerLevel::None;
}

void Logger::Message(LoggerLevel level, const String &message) {
if (level == LoggerLevel::None) {
void Logger::Message(LoggerLevel level, const String& message)
{
if (level == LoggerLevel::None)
{
return;
}

size_t count = m_Adapters.GetCount();
for (size_t i = 0; i < count; i++) {
ILoggerAdapter *adapter = m_Adapters[i];
if (adapter->CanLog(level)) {
for (size_t i = 0; i < count; i++)
{
ILoggerAdapter* adapter = m_Adapters[i];
if (adapter->CanLog(level))
{
adapter->Message(level, m_LoggerName, message);
}
}
}

UnionConsoleLoggerAdapter::UnionConsoleLoggerAdapter(LoggerLevel level) : ILoggerAdapter(level) {
SetLevelColor(LoggerLevel::Fatal, Color{"\x1B[31m", "\x1B[41;1m\x1B[37;1m", "\x1B[41m\x1B[37;1m"});
SetLevelColor(LoggerLevel::Error, Color{"\x1B[31m", "\x1B[41;1m\x1B[37;1m", "\x1B[31;1m"});
SetLevelColor(LoggerLevel::Warn, Color{"\x1B[33m", "\x1B[43;1m\x1B[37m", "\x1B[0m\x1B[33;1m"});
SetLevelColor(LoggerLevel::Info, Color{"\x1b[37m", "\x1B[47;1m\x1B[30m", "\x1B[0m"});
SetLevelColor(LoggerLevel::Debug, Color{"\x1B[32m", "\x1B[42;1m\x1B[37;1m", "\x1B[0m\x1B[32;1m"});
SetLevelColor(LoggerLevel::Trace, Color{"\x1B[30;1m", "\x1B[47;1m\x1B[30m", "\x1B[37m"});
void Logger::PrintRaw(LoggerLevel level, const String& message) const
{
auto* adapter = GetAdapter<UnionConsoleLoggerAdapter>();
if ((adapter && adapter->CanLog(level)) || !adapter)
{
String::Format("\x1B[0m\x1B[36;3m{0}\x1B[0m", message).StdPrintLine();
}
}

UnionConsoleLoggerAdapter::UnionConsoleLoggerAdapter(LoggerLevel level) : ILoggerAdapter(level)
{
SetLevelColor(LoggerLevel::Fatal, Color{ "\x1B[31m", "\x1B[41;1m\x1B[37;1m", "\x1B[41m\x1B[37;1m" });
SetLevelColor(LoggerLevel::Error, Color{ "\x1B[31m", "\x1B[41;1m\x1B[37;1m", "\x1B[31;1m" });
SetLevelColor(LoggerLevel::Warn, Color{ "\x1B[33m", "\x1B[43;1m\x1B[37m", "\x1B[0m\x1B[33;1m" });
SetLevelColor(LoggerLevel::Info, Color{ "\x1B[36;1m", "\x1B[44m\x1B[37;1m", "\x1B[36m" });
SetLevelColor(LoggerLevel::Debug, Color{ "\x1B[32m", "\x1B[42;1m\x1B[37;1m", "\x1B[0m\x1B[32;1m" });
SetLevelColor(LoggerLevel::Trace, Color{ "\x1B[35m", "\x1B[35;1m\x1B[30m", "\x1B[35;1m" });
}

void UnionConsoleLoggerAdapter::SetLevelColor(LoggerLevel level, Color color) {
m_ColorTable[(size_t) level] = std::move(color);
void UnionConsoleLoggerAdapter::SetLevelColor(LoggerLevel level, Color color)
{
m_ColorTable[(size_t)level] = std::move(color);
}

void UnionConsoleLoggerAdapter::Message(LoggerLevel level, const String &channel, const String &message) {
Color color = m_ColorTable[(size_t) level];
void UnionConsoleLoggerAdapter::Message(LoggerLevel level, const String& channel, const String& message)
{
Color color = m_ColorTable[(size_t)level];

String::Format("\x1B[0m{0} {1} \x1B[0m {2}[{3}]\x1B[0m {4}{5}\x1B[0m",
color.Level, LoggerLevelToString(level),
color.Level, LoggerLevelToDisplayString(level),
color.Channel, channel,
color.Message, message)
.StdPrintLine();
}

void ZSpyLoggerAdapter::Message(LoggerLevel level, const String &channel, const String &message) {
void ZSpyLoggerAdapter::Message(LoggerLevel level, const String& channel, const String& message)
{
String formattedMessage = String(m_Prefix) + ":\t" + channel + ": [" + LoggerLevelToString(level) + "]" + message;

switch (GetGameVersion()) {
case Engine_G2A:
Gothic_II_Addon::zerr->Message(Gothic_II_Addon::zSTRING(formattedMessage.ToChar()));
break;
switch (GetGameVersion())
{
case Engine_G1:
Gothic_I_Classic::zerr->Message(Gothic_I_Classic::zSTRING(formattedMessage.ToChar()));
break;
case Engine_G2A:
Gothic_II_Addon::zerr->Message(Gothic_II_Addon::zSTRING(formattedMessage.ToChar()));
break;
}
}

LoggerFactory *LoggerFactory::s_Instance = null;
LoggerLevel UnionConsoleLoggerAdapter::DEFAULT_LEVEL = LoggerLevel::Debug;
LoggerLevel ZSpyLoggerAdapter::DEFAULT_LEVEL = LoggerLevel::Debug;

LoggerFactory* LoggerFactory::s_Instance = null;

Logger* LoggerFactory::Create(const String& name)
{

for (auto* logger: m_Loggers)
{
if (logger->m_LoggerName == name)
{
return logger;
}
}

Logger *LoggerFactory::Create(const String &name, LoggerLevel level) {
auto *logger = new NH::Logger(name, {
new NH::UnionConsoleLoggerAdapter(level),
new NH::ZSpyLoggerAdapter(level, "E")
auto* logger = new NH::Logger(name, {
new NH::UnionConsoleLoggerAdapter(UnionConsoleLoggerAdapter::DEFAULT_LEVEL),
new NH::ZSpyLoggerAdapter(ZSpyLoggerAdapter::DEFAULT_LEVEL, "B")
});
m_Loggers.Insert(logger);
return logger;
}

Logger *CreateLogger(const String &name) {
return LoggerFactory::GetInstance()->Create(name, LoggerLevel::Trace);
Logger* CreateLogger(const String& name)
{
return LoggerFactory::GetInstance()->Create(name);
}
}
35 changes: 23 additions & 12 deletions src/NH/Logger.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#pragma once

#include <NH/Commons.h>
#include <Union/String.h>
#include <Union/Array.h>

namespace NH
{
using String = Union::StringUTF8;

enum class LoggerLevel : size_t
{
Expand All @@ -18,7 +18,17 @@ namespace NH
Trace = 6
};

String LoggerLevelToString(LoggerLevel level);
constexpr const char* LoggerLevelToString(LoggerLevel level)
{
constexpr const char* values[] = { "NONE", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" };
return values[(size_t)level];
}

constexpr const char* LoggerLevelToDisplayString(LoggerLevel level)
{
constexpr const char* values[] = { " NONE", "FATAL", "ERROR", " WARN", " INFO", "DEBUG", "TRACE" };
return values[(size_t)level];
}

LoggerLevel StringToLoggerLevel(String level);

Expand All @@ -32,6 +42,7 @@ namespace NH
LoggerLevel m_Level;

explicit ILoggerAdapter(LoggerLevel level = LoggerLevel::Debug) : m_Level(level) {}
virtual ~ILoggerAdapter() = default;

bool CanLog(LoggerLevel level) const { return level <= m_Level; }

Expand All @@ -48,12 +59,16 @@ namespace NH
Union::Array<ILoggerAdapter*> m_Adapters;

public:
friend class LoggerFactory;

explicit Logger(const String& name) : m_LoggerName(name) {};

explicit Logger(const String& name, Union::Array<ILoggerAdapter*> adapters) : m_LoggerName(name), m_Adapters(adapters) {};

void Message(LoggerLevel level, const String& message);

void PrintRaw(LoggerLevel level, const String& message) const;

template<typename... Args>
void Message(LoggerLevel level, const char* format, Args... args) { Message(level, String::Format(format, args...)); }

Expand Down Expand Up @@ -87,17 +102,9 @@ namespace NH
template<typename... Args>
void Trace(const char* format, Args... args) { Trace(String::Format(format, args...)); }

void SetLoggerLevel(LoggerLevel level)
{
for (size_t i = 0; i < m_Adapters.GetCount(); i++)
{
m_Adapters[i]->SetLoggerLevel(level);
}
}

Union::Array<ILoggerAdapter*> GetAdapters() const { return m_Adapters; };

template <class T>
template<class T>
T* GetAdapter() const
{
for (int i = 0; i < m_Adapters.GetCount(); i++)
Expand All @@ -116,6 +123,8 @@ namespace NH
class UnionConsoleLoggerAdapter : public ILoggerAdapter
{
public:
static LoggerLevel DEFAULT_LEVEL;

struct Color
{
String Channel;
Expand All @@ -140,6 +149,8 @@ namespace NH
String m_Prefix;

public:
static LoggerLevel DEFAULT_LEVEL;

explicit ZSpyLoggerAdapter(LoggerLevel level = LoggerLevel::Debug, const String& prefix = "N") : ILoggerAdapter(level), m_Prefix(prefix) {}

protected:
Expand All @@ -155,7 +166,7 @@ namespace NH
LoggerFactory() = default;

public:
Logger* Create(const String& name, LoggerLevel level = LoggerLevel::Trace);
Logger* Create(const String& name);

Union::Array<Logger*> GetLoggers() { return m_Loggers.Share(); };

Expand Down
13 changes: 13 additions & 0 deletions src/Plugin.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
// Disable macro redefinition warning
#pragma warning(disable: 4005)

#include <Union/Hook.h>
#include <ZenGin/zGothicAPI.h>

#include "NH/Logger.h"


#ifdef __G1
#define GOTHIC_NAMESPACE Gothic_I_Classic
#define ENGINE Engine_G1
HOOKSPACE(Gothic_I_Classic, GetGameVersion() == ENGINE);

#include "Plugin.hpp"

#endif

#ifdef __G2A
#define GOTHIC_NAMESPACE Gothic_II_Addon
#define ENGINE Engine_G2A
Expand Down
2 changes: 1 addition & 1 deletion userapi/oCNpc.inl
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
// User API for oCNpc
// Add your methods here

int ActivateDialogCam_Hook(float);
// int ActivateDialogCam_Hook(float);
int EV_Exchange_Hook(oCMsgManipulate*);

0 comments on commit 0411069

Please sign in to comment.