Skip to content

Commit

Permalink
v1.0.3
Browse files Browse the repository at this point in the history
  • Loading branch information
not_alphanine committed Jul 23, 2024
1 parent 58bf698 commit cb8ac7f
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 143 deletions.
38 changes: 38 additions & 0 deletions demo/ExampleNGPlusConfig.reds
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module NGPlus.CustomConfig

import NGPlus.DifficultyConfig.*

// Inherit UserConfig class from DefaultDifficultyConfig to get default values ETC...
public class UserConfig extends DefaultDifficultyConfig {
// Upgrades can be stacked
// All enemies can get upgrades, outside of non-cyberpsycho bosses and MaxTac (outside of health regeneration, as it really sucks on bosses)
// You can disable an upgrade by setting its application chance to 0
// Enemy upgrades should be reset on save reload
// Returned value is how often the upgrade should be applied
public static func GetFastUpgradeChance() -> Float = 95.0; // (Sandy, dodge, dash, whatever else...)
// How often the "tanky" upgrade should be applied (heavy armor and a tiny bit of regen)
public static func GetTankUpgradeChance() -> Float = 60.0;
// How often the "regen" upgrade should be applied (fast regen until enemy loses a bunch of health, at which point they won't regenerate anymore)
public static func GetRegenUpgradeChance() -> Float = 25.0;
// How often an enemy should get optical camo
public static func GetOpticalCamoUpgradeChance() -> Float = 35.0;
// How often a netrunner should be able to get the ability to do basically all quickhacks instead of their default set
public static func GetNetrunnerUpgradeChance() -> Float = 100.0;
// Currently unused, will be used in the future to upgrade enemy dodge abilities
public static func GetDodgeUpgradeChance() -> Float = 0.0;
// Not an upgrade, decides whether or not NG+ should start the Post-Heist start as normal (waking up in the trash) or with Misty wheeling you into V's apt
// True = Misty wheeling you in
// False = default behavior
public static func GetShouldFastForwardQ101Start() -> Bool = true;
// Maybe eventually random encounters can be enabled/disabled here, but I'm not sure if I want to do that
}

2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ RED4EXT_C_EXPORT void RED4EXT_CALL Query(RED4ext::PluginInfo* aInfo)
{
aInfo->name = L"New Game+";
aInfo->author = L"not_alphanine";
aInfo->version = RED4EXT_SEMVER_EX(1, 0, 3, RED4EXT_V0_SEMVER_PRERELEASE_TYPE_RC, 1); // Set your version here.
aInfo->version = RED4EXT_SEMVER_EX(1, 0, 3, RED4EXT_V0_SEMVER_PRERELEASE_TYPE_NONE, 0); // Set your version here.
aInfo->runtime = RED4EXT_RUNTIME_INDEPENDENT;
aInfo->sdk = RED4EXT_SDK_LATEST;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,27 +89,14 @@ class NativePersistencyReader : public redRTTI::native::NativeReader

auto expectedType = PluginContext::m_rtti->GetType(propTypeStr);

if (expectedType != prop->type)
if (!Red::IsCompatible(prop->type, expectedType))
{
auto isCompatible = false;

// Handles can point to abstract stuff, thus we need to know expected type
if (prop->type->GetType() == Red::ERTTIType::Handle)
{
auto asHandleType = static_cast<Red::CRTTIHandleType*>(prop->type);
auto asHandleExpectedType = static_cast<Red::CRTTIHandleType*>(expectedType);

isCompatible = static_cast<Red::CClass*>(asHandleExpectedType->GetInnerType())
->IsA(asHandleType->GetInnerType());
}

if (!isCompatible)
{
PluginContext::Error(std::format("Prop {}::{} type mismatch, {} != {}!", classType->name.ToString(),
PluginContext::Error(std::format("Prop {}::{} type mismatch, {} != {}!", classType->name.ToString(),
propName.ToString(), prop->type->GetName().ToString(),
propTypeStr.ToString()));
return false;
}
return false;

}

auto valuePtr = prop->GetValuePtr<std::remove_pointer_t<Red::ScriptInstance>>(aOut);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class ScriptableReader : redRTTI::native::NativeReader

if (index >= m_names->size())
{
return {};
return {};
}

return m_names->at(index);
Expand Down Expand Up @@ -87,7 +87,7 @@ class ScriptableReader : redRTTI::native::NativeReader
{
auto enumValueName = ReadCNameInternal(aCursor);
auto enumType = static_cast<Red::CEnum*>(aPropType);

std::int64_t enumValue{};
ResolveEnumValue(enumType, enumValueName, enumValue);

Expand All @@ -96,7 +96,7 @@ class ScriptableReader : redRTTI::native::NativeReader
{
s_enumSizes.insert(enumType->actualSize);
}

// Scriptable systems only seem to use actualSize=4
if (enumType->actualSize == 0)
{
Expand All @@ -109,7 +109,8 @@ class ScriptableReader : redRTTI::native::NativeReader
memcpy(aOut, &enumValue, enumType->actualSize);
}

virtual bool TryReadHandle(FileCursor& aCursor, Red::ScriptInstance aOut, Red::CBaseRTTIType* aPropType) noexcept final
virtual bool TryReadHandle(FileCursor& aCursor, Red::ScriptInstance aOut,
Red::CBaseRTTIType* aPropType) noexcept final
{
// We don't resolve handles... yet....
// And probably never will (actually NVM, might do it sometime...)
Expand All @@ -118,7 +119,8 @@ class ScriptableReader : redRTTI::native::NativeReader
return true;
}

virtual bool TryReadWeakHandle(FileCursor& aCursor, Red::ScriptInstance aOut, Red::CBaseRTTIType* aPropType) noexcept final
virtual bool TryReadWeakHandle(FileCursor& aCursor, Red::ScriptInstance aOut,
Red::CBaseRTTIType* aPropType) noexcept final
{
// Again, no resolving handles just yet
aCursor.readInt();
Expand All @@ -130,15 +132,13 @@ class ScriptableReader : redRTTI::native::NativeReader
inline ScriptableReader(std::vector<Red::CName>* aNames)
: m_names(aNames)
{

}

// This puts the reader into an invalid state by default, as we don't know any names
inline ScriptableReader() = default;

virtual ~ScriptableReader()
{

}

inline std::vector<Red::CName>* GetNames()
Expand All @@ -151,7 +151,8 @@ class ScriptableReader : redRTTI::native::NativeReader
m_names = aNames;
}

inline virtual bool TryReadClass(FileCursor& aCursor, Red::ScriptInstance aOut, Red::CBaseRTTIType* aType) noexcept final
inline virtual bool TryReadClass(FileCursor& aCursor, Red::ScriptInstance aOut,
Red::CBaseRTTIType* aType) noexcept final
{
auto classType = static_cast<Red::CClass*>(aType);

Expand All @@ -178,37 +179,22 @@ class ScriptableReader : redRTTI::native::NativeReader
const auto propTypeName = m_names->at(desc.m_typeId);
const auto propTypeExpected = PluginContext::m_rtti->GetType(propTypeName);

if (propData->type != propTypeExpected)
if (!Red::IsCompatible(propTypeExpected, propData->type))
{
auto isCompatible = false;

// NOTE: we don't resolve wrefs, so we don't care about type mismatches there...
if (propTypeExpected && propData->type->GetType() == Red::ERTTIType::Handle)
if constexpr (m_reportNonCriticalErrors)
{
auto asHandle = static_cast<Red::CRTTIHandleType*>(propData->type);
auto asHandleExpected = static_cast<Red::CRTTIHandleType*>(propTypeExpected);

isCompatible =
static_cast<Red::CClass*>(asHandleExpected->GetInnerType())->IsA(asHandle->GetInnerType());
PluginContext::Error(
std::format("NativeScriptableReader::TryReadClass, class {}, property type mismatch - {} != {}",
classType->GetName().ToString(), propData->type->GetName().ToString(),
m_names->at(desc.m_typeId).ToString()));
}

if (!isCompatible)
{
if constexpr (m_reportNonCriticalErrors)
{
PluginContext::Error(std::format(
"NativeScriptableReader::TryReadClass, class {}, property type mismatch - {} != {}",
classType->GetName().ToString(), propData->type->GetName().ToString(),
m_names->at(desc.m_typeId).ToString()));
}

continue;
}
continue;
}

aCursor.seekTo(baseOffset + desc.m_offset);

auto propPtr = propData->GetValuePtr<std::remove_pointer_t<Red::ScriptInstance>>(aOut);
auto propPtr = propData->GetValuePtr<void>(aOut);

if (!TryReadValue(aCursor, propPtr, propTypeExpected))
{
Expand All @@ -220,4 +206,4 @@ class ScriptableReader : redRTTI::native::NativeReader
return true;
}
};
}
} // namespace scriptable::native
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ void StatsSystemNode::ReadData(FileCursor& aCursor, NodeEntry& aNode) noexcept

constexpr auto shouldDumpPlayerStatModifiers = false;

if (shouldDumpPlayerStatModifiers)
if constexpr (shouldDumpPlayerStatModifiers)
{
auto handlePtr = m_package.GetChunkByTypeName("gameStatsStateMapStructure");

Expand Down
20 changes: 3 additions & 17 deletions src/parsing/definitions/package/packageReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,24 +292,10 @@ bool Package::TryReadClass(FileCursor& aCursor, Red::ScriptInstance aOut, Red::C
// Don't use .at(), we're noexcept anyway - no difference between segfault and abort()
const auto propTypeExpected = PluginContext::m_rtti->GetType(m_names[desc.m_typeId]);

if (propData->type != propTypeExpected)
if (!Red::IsCompatible(propTypeExpected, propData->type))
{
auto isCompatible = false;

// NOTE: we don't resolve wrefs, so we don't care about type mismatches there...
if (propTypeExpected && propData->type->GetType() == Red::ERTTIType::Handle)
{
auto asHandle = static_cast<Red::CRTTIHandleType*>(propData->type);
auto asHandleExpected = static_cast<Red::CRTTIHandleType*>(propTypeExpected);

isCompatible =
static_cast<Red::CClass*>(asHandleExpected->GetInnerType())->IsA(asHandle->GetInnerType());
}

if (!isCompatible)
{
continue;
}
// This can, in theory, cause issues with array reading if incompatible val ends up the last field in class...
continue;
}

aCursor.seekTo(baseOffset + desc.m_offset);
Expand Down
Loading

0 comments on commit cb8ac7f

Please sign in to comment.