Initial PAL/JP/Trilogy imps, various cleanup

This commit is contained in:
Phillip Stephens 2020-04-15 22:26:14 -07:00
parent 3487ea92c7
commit 582d8a6999
Signed by: Antidote
GPG Key ID: F8BEE4C83DACA60D
20 changed files with 285 additions and 91 deletions

View File

@ -21,6 +21,9 @@ struct ITweakPlayerRes : ITweak {
ResId x18_minesBreakSecondTopIcon;
ResId x1c_minesBreakSecondBottomIcon;
ResId rs5_mapArrowUp;
ResId rs5_mapArrowDown;
/* N, U, UL, L, DL, D, DR, R, UR */
std::array<ResId, 9> x24_lStick;
std::array<ResId, 9> x4c_cStick;

View File

@ -30,6 +30,7 @@
#include "PATH.hpp"
#include "DataSpec/DNACommon/Tweaks/TweakWriter.hpp"
#include "DataSpec/DNACommon/URDEVersionInfo.hpp"
#include "Tweaks/CTweakPlayerRes.hpp"
#include "Tweaks/CTweakGunRes.hpp"
#include "Tweaks/CTweakPlayer.hpp"
@ -237,8 +238,8 @@ void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssoci
if (animResInfo.evntId.isValid()) {
PAK::Entry* evntEnt = (PAK::Entry*)m_pak.lookupEntry(animResInfo.evntId);
evntEnt->name = fmt::format(FMT_STRING("ANCS_{}_{}_evnt"), id, animResInfo.name);
charAssoc.m_cskrToCharacter[animResInfo.evntId] =
std::make_pair(entry.id, fmt::format(FMT_STRING("{}_{}.evnt.yaml"), animResInfo.name, animResInfo.evntId));
charAssoc.m_cskrToCharacter[animResInfo.evntId] = std::make_pair(
entry.id, fmt::format(FMT_STRING("{}_{}.evnt.yaml"), animResInfo.name, animResInfo.evntId));
}
}
} else if (entry.type == FOURCC('MREA')) {
@ -275,8 +276,8 @@ void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(&entry).getParentPath();
if (mlvl.worldNameId.isValid())
pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath,
fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId));
pathOverrides[mlvl.worldNameId] =
hecl::ProjectPath(mlvlDirPath, fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId));
for (const MLVL::Area& area : mlvl.areas) {
{
@ -292,8 +293,8 @@ void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath();
if (area.areaNameId.isValid())
pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath,
fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), area.areaNameId));
pathOverrides[area.areaNameId] =
hecl::ProjectPath(areaDirPath, fmt::format(FMT_STRING(_SYS_STR("!name_{}.yaml")), area.areaNameId));
}
if (mlvl.worldMap.isValid()) {
@ -383,8 +384,14 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const nod::Node& pakNode, con
std::string catalogueName;
std::string name = pak.bestEntryName(pakNode, entry, catalogueName);
if (!catalogueName.empty()) {
if (catalogueName == "PlayerRes"sv)
return {ExtractTweak<CTweakPlayerRes>, {_SYS_STR(".yaml")}};
if (catalogueName == "PlayerRes"sv) {
if (isCurrentSpecWii() || getCurrentRegion() == ERegion::PAL || getCurrentRegion() == ERegion::NTSC_J) {
/* We need to use the new rep for these tweaks */
return {ExtractTweak<CTweakPlayerRes<true>>, {_SYS_STR(".yaml")}};
}
/* We need to use the old rep for these tweaks */
return {ExtractTweak<CTweakPlayerRes<false>>, {_SYS_STR(".yaml")}};
}
if (catalogueName == "GunRes"sv)
return {ExtractTweak<CTweakGunRes>, {_SYS_STR(".yaml")}};
if (catalogueName == "Player"sv)
@ -395,8 +402,14 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const nod::Node& pakNode, con
return {ExtractTweak<CTweakSlideShow>, {_SYS_STR(".yaml")}};
if (catalogueName == "Game"sv)
return {ExtractTweak<CTweakGame>, {_SYS_STR(".yaml")}};
if (catalogueName == "Targeting"sv)
return {ExtractTweak<CTweakTargeting>, {_SYS_STR(".yaml")}};
if (catalogueName == "Targeting"sv) {
if (isCurrentSpecWii() || getCurrentRegion() == ERegion::PAL || getCurrentRegion() == ERegion::NTSC_J) {
/* We need to use the new rep for these tweaks */
return {ExtractTweak<CTweakTargeting<true>>, {_SYS_STR(".yaml")}};
}
/* We need to use the old rep for these tweaks */
return {ExtractTweak<CTweakTargeting<false>>, {_SYS_STR(".yaml")}};
}
if (catalogueName == "Gui"sv)
return {ExtractTweak<CTweakGui>, {_SYS_STR(".yaml")}};
if (catalogueName == "AutoMapper"sv)

View File

@ -4,7 +4,8 @@
namespace DataSpec::DNAMP1 {
struct CTweakPlayerRes final : ITweakPlayerRes {
template <bool NewRep>
struct AT_SPECIALIZE_PARMS(true, false) CTweakPlayerRes final : ITweakPlayerRes {
AT_DECL_DNA_YAML
String<-1> m_saveStationIcon;
@ -16,6 +17,9 @@ struct CTweakPlayerRes final : ITweakPlayerRes {
String<-1> m_minesBreakSecondTopIcon;
String<-1> m_minesBreakSecondBottomIcon;
String<AT_DNA_COUNT(NewRep==true ? -1 : 0)> m_mapArrowDown;
String<AT_DNA_COUNT(NewRep==true ? -1 : 0)> m_mapArrowUp;
String<-1> m_lStickN;
String<-1> m_lStickU;
String<-1> m_lStickUL;

View File

@ -3,7 +3,8 @@
#include "../../DNACommon/Tweaks/ITweakTargeting.hpp"
namespace DataSpec::DNAMP1 {
struct CTweakTargeting final : public ITweakTargeting {
template<bool NewRep>
struct AT_SPECIALIZE_PARMS(true, false) CTweakTargeting final : public ITweakTargeting {
AT_DECL_DNA_YAML
Value<atUint32> x4_targetRadiusMode;
Value<float> x8_currLockOnExitDuration;
@ -132,6 +133,69 @@ struct CTweakTargeting final : public ITweakTargeting {
Value<float> x220_scanTargetClampMax;
Value<float> x224_angularLagSpeed;
// RS5
Vector<float, AT_DNA_COUNT(NewRep == true ? 1 : 0)> x218_;
Vector<float, AT_DNA_COUNT(NewRep == true ? 1 : 0)> x21c_;
bool x224_ = true;
bool x225_ = false;
bool x226_ = true;
bool x227_ = true;
bool x22c_ = true;
bool x22d_ = false;
bool x22e_ = true;
bool x22f_ = true;
bool x234_ = true;
bool x235_ = false;
bool x236_ = true;
bool x237_ = true;
zeus::CVector3f x23c_ = zeus::skZero3f;
float x2c8_ = 0.25f;
float x2cc_ = 0.35f;
zeus::CColor x2d0_ = (zeus::Comp32)0xb6e6ffff;
float x2d4_ = 0.39215687f;
zeus::CColor x2d8_ = (zeus::Comp32)0xa82a00ff;
float x2dc_ = 0.78431374f;
zeus::CVector3f x2e0_ = zeus::CVector3f(0.f, 0.f, 0.46f);
float x2ec_ = 0.25f;
float x2f0_ = 0.25f;
float x2f4_ = 120.f;
float x2f8_ = 0.25f;
float x2fc_ = 3.5f;
float x300_ = 0.35f;
zeus::CColor x304_ = (zeus::Comp32)0xa82a00ff;
float x308_ = 0.78431374f;
zeus::CColor x30c_ = (zeus::Comp32)0x89d6ffff;
float x310_ = 0.5019608f;
float x314_ = 11.25f;
float x318_ = 0.25f;
float x31c_ = 0.125f;
zeus::CColor x320_ = (zeus::Comp32)0xffca28ff;
float x324_ = 0.78431374f;
zeus::CColor x328_ = (zeus::Comp32)0x89d6ffff;
float x32c_ = 0.19607843f;
float x330_ = 0.f;
float x334_ = 0.25f;
float x338_ = 3.f;
float x33c_ = 0.25f;
float x340_ = 0.25f;
float x344_ = 0.25f;
float x348_ = 0.25f;
float x34c_ = 45.f;
float x350_ = 0.5f;
float x354_ = 0.65f;
float x358_ = 1.5f;
float x35c_ = 0.18f;
float x360_ = 0.15f;
float x364_ = 0.25f;
zeus::CColor x368_ = (zeus::Comp32)0x56c1fb9f;
zeus::CColor x36c_ = (zeus::Comp32)0x49c3f6a0;
zeus::CColor x370_ = (zeus::Comp32)0x49c3f631;
zeus::CColor x374_ = (zeus::Comp32)0xff8930ff;
zeus::CColor x378_ = (zeus::Comp32)0xff2f28ff;
zeus::CColor x37c_ = (zeus::Comp32)0x93e9ffff;
zeus::CColor x380_ = (zeus::Comp32)0xff6b60ff;
CTweakTargeting() = default;
CTweakTargeting(athena::io::IStreamReader& r) {
this->read(r);

View File

@ -39,6 +39,12 @@ static const hecl::SystemChar* MomErr[] = {_SYS_STR("Your metroid is in another
constexpr uint32_t MomErrCount = std::extent<decltype(MomErr)>::value;
static ERegion g_CurRegion = ERegion::Invalid;
static bool g_CurSpecIsWii = false;
ERegion getCurrentRegion() { return g_CurRegion; }
bool isCurrentSpecWii() { return g_CurSpecIsWii; }
SpecBase::SpecBase(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc)
: hecl::Database::IDataSpec(specEntry)
, m_project(project)
@ -94,6 +100,9 @@ bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector<ExtractReport
break;
}
setCurRegion(m_region);
setCurSpecIsWii(m_isWii);
if (m_standalone)
return checkFromStandaloneDisc(*m_disc, *regstr, info.extractArgs, reps);
else
@ -1223,4 +1232,11 @@ void SpecBase::WriteVersionInfo(hecl::Database::Project& project, const hecl::Pr
athena::io::FileWriter writer(versionPath.getAbsolutePath());
athena::io::ToYAMLStream(info, writer);
}
void SpecBase::setCurRegion(ERegion region) {
g_CurRegion = region;
}
void SpecBase::setCurSpecIsWii(bool isWii) {
g_CurSpecIsWii = isWii;
}
} // namespace DataSpec

View File

@ -12,7 +12,6 @@
#include "hecl/Blender/Token.hpp"
#include "Runtime/RetroTypes.hpp"
namespace nod {
class DiscBase;
class Node;
@ -26,6 +25,9 @@ class YAMLDocWriter;
namespace DataSpec {
enum class ERegion;
enum class EGame;
ERegion getCurrentRegion();
bool isCurrentSpecWii();
struct SpecBase : hecl::Database::IDataSpec {
/* HECL Adaptors */
void setThreadProject() override;
@ -181,8 +183,8 @@ protected:
bool m_backgroundRunning = false;
void readCatalog(const hecl::ProjectPath& catalogPath, athena::io::YAMLDocWriter& nameWriter);
void insertPathTag(athena::io::YAMLDocWriter& cacheWriter, const urde::SObjectTag& tag,
const hecl::ProjectPath& path, bool dump = true);
void insertPathTag(athena::io::YAMLDocWriter& cacheWriter, const urde::SObjectTag& tag, const hecl::ProjectPath& path,
bool dump = true);
bool addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDocWriter& cacheWriter);
void backgroundIndexRecursiveProc(const hecl::ProjectPath& path, athena::io::YAMLDocWriter& cacheWriter,
athena::io::YAMLDocWriter& nameWriter, int level);
@ -206,6 +208,9 @@ protected:
std::string m_version;
void WriteVersionInfo(hecl::Database::Project& project, const hecl::ProjectPath& pakPath);
static void setCurRegion(ERegion region);
static void setCurSpecIsWii(bool isWii);
};
bool IsPathAudioGroup(const hecl::ProjectPath& path);

View File

@ -428,7 +428,9 @@ struct SpecMP1 : SpecBase {
return true;
else if (classType == DNAFont::FONT<UniqueID32>::DNAType())
return true;
else if (classType == DNAMP1::CTweakPlayerRes::DNAType())
else if (classType == DNAMP1::CTweakPlayerRes<true>::DNAType())
return true;
else if (classType == DNAMP1::CTweakPlayerRes<false>::DNAType())
return true;
else if (classType == DNAMP1::CTweakGunRes::DNAType())
return true;
@ -442,7 +444,9 @@ struct SpecMP1 : SpecBase {
return true;
else if (classType == DNAMP1::CTweakAutoMapper::DNAType())
return true;
else if (classType == DNAMP1::CTweakTargeting::DNAType())
else if (classType == DNAMP1::CTweakTargeting<true>::DNAType())
return true;
else if (classType == DNAMP1::CTweakTargeting<false>::DNAType())
return true;
else if (classType == DNAMP1::CTweakGui::DNAType())
return true;
@ -583,13 +587,15 @@ struct SpecMP1 : SpecBase {
} else if (className == DataSpec::DNAMP1::SCAN::DNAType()) {
resTag.type = SBIG('SCAN');
return true;
} else if (className == DataSpec::DNAMP1::CTweakPlayerRes::DNAType() ||
} else if (className == DataSpec::DNAMP1::CTweakPlayerRes<true>::DNAType() ||
className == DataSpec::DNAMP1::CTweakPlayerRes<false>::DNAType() ||
className == DataSpec::DNAMP1::CTweakGunRes::DNAType() ||
className == DataSpec::DNAMP1::CTweakSlideShow::DNAType() ||
className == DataSpec::DNAMP1::CTweakPlayer::DNAType() ||
className == DataSpec::DNAMP1::CTweakCameraBob::DNAType() ||
className == DataSpec::DNAMP1::CTweakGame::DNAType() ||
className == DataSpec::DNAMP1::CTweakTargeting::DNAType() ||
className == DataSpec::DNAMP1::CTweakTargeting<true>::DNAType() ||
className == DataSpec::DNAMP1::CTweakTargeting<false>::DNAType() ||
className == DataSpec::DNAMP1::CTweakAutoMapper::DNAType() ||
className == DataSpec::DNAMP1::CTweakGui::DNAType() ||
className == DataSpec::DNAMP1::CTweakPlayerControl::DNAType() ||
@ -834,8 +840,12 @@ struct SpecMP1 : SpecBase {
DNAFont::FONT<UniqueID32> font;
font.read(reader);
DNAFont::WriteFONT(font, out);
} else if (classStr == DNAMP1::CTweakPlayerRes::DNAType()) {
DNAMP1::CTweakPlayerRes playerRes;
} else if (classStr == DNAMP1::CTweakPlayerRes<true>::DNAType()) {
DNAMP1::CTweakPlayerRes<true> playerRes;
playerRes.read(reader);
WriteTweak(playerRes, out);
} else if (classStr == DNAMP1::CTweakPlayerRes<false>::DNAType()) {
DNAMP1::CTweakPlayerRes<false> playerRes;
playerRes.read(reader);
WriteTweak(playerRes, out);
} else if (classStr == DNAMP1::CTweakGunRes::DNAType()) {
@ -862,8 +872,12 @@ struct SpecMP1 : SpecBase {
DNAMP1::CTweakAutoMapper autoMapper;
autoMapper.read(reader);
WriteTweak(autoMapper, out);
} else if (classStr == DNAMP1::CTweakTargeting::DNAType()) {
DNAMP1::CTweakTargeting targeting;
} else if (classStr == DNAMP1::CTweakTargeting<true>::DNAType()) {
DNAMP1::CTweakTargeting<false> targeting;
targeting.read(reader);
WriteTweak(targeting, out);
} else if (classStr == DNAMP1::CTweakTargeting<false>::DNAType()) {
DNAMP1::CTweakTargeting<false> targeting;
targeting.read(reader);
WriteTweak(targeting, out);
} else if (classStr == DNAMP1::CTweakGui::DNAType()) {

View File

@ -1428,11 +1428,14 @@ void CStateManager::InformListeners(const zeus::CVector3f& pos, EListenNoiseType
void CStateManager::ApplyKnockBack(CActor& actor, const CDamageInfo& info, const CDamageVulnerability& vuln,
const zeus::CVector3f& pos, float dampen) {
if (vuln.GetVulnerability(info.GetWeaponMode(), false) == EVulnerability::Deflect)
if (vuln.GetVulnerability(info.GetWeaponMode(), false) == EVulnerability::Deflect) {
return;
}
CHealthInfo* hInfo = actor.HealthInfo(*this);
if (!hInfo)
if (hInfo == nullptr) {
return;
}
float dampedPower = (1.f - dampen) * info.GetKnockBackPower();
if (TCastToPtr<CPlayer> player = actor) {
@ -1446,30 +1449,34 @@ void CStateManager::ApplyKnockBack(CActor& actor, const CDamageInfo& info, const
if (TCastToPtr<CPhysicsActor> physActor = actor) {
zeus::CVector3f kbVec = pos * (dampedPower - hInfo->GetKnockbackResistance()) * physActor->GetMass() * 1.5f;
if (physActor->GetMaterialList().HasMaterial(EMaterialTypes::Immovable) ||
!physActor->GetMaterialList().HasMaterial(EMaterialTypes::Grass))
!physActor->GetMaterialList().HasMaterial(EMaterialTypes::Solid)) {
return;
}
physActor->ApplyImpulseWR(kbVec, zeus::CAxisAngle());
return;
}
}
}
if (ai)
if (ai) {
ai->KnockBack(pos, *this, info, dampen == 0.f ? EKnockBackType::Direct : EKnockBackType::Radius, false,
dampedPower);
}
}
void CStateManager::KnockBackPlayer(CPlayer& player, const zeus::CVector3f& pos, float power, float resistance) {
if (player.GetMaterialList().HasMaterial(EMaterialTypes::Immovable))
if (player.GetMaterialList().HasMaterial(EMaterialTypes::Immovable)) {
return;
}
float usePower;
if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) {
usePower = power * 1000.f;
CPlayer::ESurfaceRestraints surface =
player.x2b0_outOfWaterTicks == 2 ? player.x2ac_surfaceRestraint : CPlayer::ESurfaceRestraints::Water;
if (surface != CPlayer::ESurfaceRestraints::Normal && player.GetOrbitState() == CPlayer::EPlayerOrbitState::NoOrbit)
if (surface != CPlayer::ESurfaceRestraints::Normal && player.GetOrbitState() == CPlayer::EPlayerOrbitState::NoOrbit) {
usePower /= 7.f;
}
} else {
usePower = power * 500.f;
}
@ -1496,15 +1503,17 @@ void CStateManager::ApplyDamageToWorld(TUniqueId damager, const CActor& actor, c
bool bomb = false;
TCastToConstPtr<CWeapon> weapon = actor;
if (weapon)
if (weapon) {
bomb = True(weapon->GetAttribField() & (EProjectileAttrib::Bombs | EProjectileAttrib::PowerBombs));
}
rstl::reserved_vector<TUniqueId, 1024> nearList;
BuildNearList(nearList, aabb, filter, &actor);
for (TUniqueId id : nearList) {
CEntity* ent = ObjectById(id);
if (!ent)
if (ent == nullptr) {
continue;
}
TCastToPtr<CPlayer> player = ent;
if (bomb && player) {
@ -1513,20 +1522,24 @@ void CStateManager::ApplyDamageToWorld(TUniqueId damager, const CActor& actor, c
MP1::CSamusHud::DisplayHudMemo(u"", CHUDMemoParms{0.f, true, true, true});
player->UnFreeze(*this);
} else {
if ((weapon->GetAttribField() & EProjectileAttrib::Bombs) == EProjectileAttrib::Bombs)
if ((weapon->GetAttribField() & EProjectileAttrib::Bombs) == EProjectileAttrib::Bombs) {
player->BombJump(pos, *this);
}
}
} else if (ent->GetUniqueId() != damager) {
TestBombHittingWater(actor, pos, static_cast<CActor&>(*ent));
if (TestRayDamage(pos, static_cast<CActor&>(*ent), nearList))
if (TestRayDamage(pos, static_cast<CActor&>(*ent), nearList)) {
ApplyRadiusDamage(actor, pos, static_cast<CActor&>(*ent), info);
}
}
if (TCastToPtr<CWallCrawlerSwarm> swarm = ent)
if (TCastToPtr<CWallCrawlerSwarm> swarm = ent) {
swarm->ApplyRadiusDamage(pos, info, *this);
}
if (TCastToPtr<CSnakeWeedSwarm> swarm = ent)
if (TCastToPtr<CSnakeWeedSwarm> swarm = ent) {
swarm->ApplyRadiusDamage(pos, info, *this);
}
}
}
@ -1555,28 +1568,29 @@ void CStateManager::ApplyRadiusDamage(const CActor& a1, const zeus::CVector3f& p
((bounds = a2.GetTouchBounds()) &&
CCollidableSphere::Sphere_AABox_Bool(zeus::CSphere{pos, info.GetRadius()}, *bounds))) {
float rad = info.GetRadius();
if (rad > FLT_EPSILON)
if (rad > FLT_EPSILON) {
rad = delta.magnitude() / rad;
else
} else {
rad = 0.f;
if (rad > 0.f)
}
if (rad > 0.f) {
delta.normalize();
}
bool alive = false;
if (CHealthInfo* hInfo = a2.HealthInfo(*this))
if (hInfo->GetHP() > 0.f)
if (CHealthInfo* hInfo = a2.HealthInfo(*this)) {
if (hInfo->GetHP() > 0.f) {
alive = true;
}
}
const CDamageVulnerability* vuln;
if (rad > 0.f)
vuln = a2.GetDamageVulnerability(pos, delta, info);
else
vuln = a2.GetDamageVulnerability();
const CDamageVulnerability* vuln = rad > 0.f ? a2.GetDamageVulnerability(pos, delta, info) : a2.GetDamageVulnerability();
if (vuln->WeaponHurts(info.GetWeaponMode(), true)) {
float dam = info.GetRadiusDamage(*vuln);
if (dam > 0.f)
if (dam > 0.f) {
ApplyLocalDamage(pos, delta, a2, dam, info.GetWeaponMode());
}
a2.SendScriptMsgs(EScriptObjectState::Damage, *this, EScriptObjectMessage::None);
SendScriptMsg(&a2, a1.GetUniqueId(), EScriptObjectMessage::Damage);
} else {
@ -1584,8 +1598,9 @@ void CStateManager::ApplyRadiusDamage(const CActor& a1, const zeus::CVector3f& p
SendScriptMsg(&a2, a1.GetUniqueId(), EScriptObjectMessage::InvulnDamage);
}
if (alive && info.GetKnockBackPower() > 0.f)
if (alive && info.GetKnockBackPower() > 0.f) {
ApplyKnockBack(a2, info, *vuln, (a2.GetTranslation() - a1.GetTranslation()).normalized(), rad);
}
}
}

View File

@ -57,11 +57,9 @@ extern class CStateManager* g_StateManager;
#if USE_DOWNCAST_TWEAKS
using ITweakGame = DataSpec::DNAMP1::CTweakGame;
using ITweakPlayer = DataSpec::DNAMP1::CTweakPlayer;
using ITweakPlayerRes = DataSpec::DNAMP1::CTweakPlayerRes;
using ITweakPlayerControl = DataSpec::DNAMP1::CTweakPlayerControl;
using ITweakPlayerGun = DataSpec::DNAMP1::CTweakPlayerGun;
using ITweakGunRes = DataSpec::DNAMP1::CTweakGunRes;
using ITweakTargeting = DataSpec::DNAMP1::CTweakTargeting;
using ITweakAutoMapper = DataSpec::DNAMP1::CTweakAutoMapper;
using ITweakGui = DataSpec::DNAMP1::CTweakGui;
using ITweakSlideShow = DataSpec::DNAMP1::CTweakSlideShow;
@ -71,11 +69,9 @@ using ITweakGuiColors = DataSpec::DNAMP1::CTweakGuiColors;
#else
using ITweakGame = DataSpec::ITweakGame;
using ITweakPlayer = DataSpec::ITweakPlayer;
using ITweakPlayerRes = DataSpec::ITweakPlayerRes;
using ITweakPlayerControl = DataSpec::ITweakPlayerControl;
using ITweakPlayerGun = DataSpec::ITweakPlayerGun;
using ITweakGunRes = DataSpec::ITweakGunRes;
using ITweakTargeting = DataSpec::ITweakTargeting;
using ITweakAutoMapper = DataSpec::ITweakAutoMapper;
using ITweakGui = DataSpec::ITweakGui;
using ITweakSlideShow = DataSpec::ITweakSlideShow;
@ -83,6 +79,8 @@ using ITweakParticle = DataSpec::ITweakParticle;
using ITweakBall = DataSpec::ITweakBall;
using ITweakGuiColors = DataSpec::ITweakGuiColors;
#endif
using ITweakPlayerRes = DataSpec::ITweakPlayerRes;
using ITweakTargeting = DataSpec::ITweakTargeting;
extern ITweakGame* g_tweakGame;
extern ITweakPlayer* g_tweakPlayer;

View File

@ -6,6 +6,7 @@
#include <boo/boo.hpp>
#include <boo/audiodev/IAudioVoiceEngine.hpp>
#include <hecl/Runtime.hpp>
#include "DataSpec/DNACommon/URDEVersionInfo.hpp"
namespace hecl {
class Console;
@ -13,6 +14,9 @@ class CVarManager;
} // namespace hecl
namespace urde {
using ERegion = DataSpec::ERegion;
using EGame = DataSpec::EGame;
class CStopwatch;
enum class EGameplayResult { None, Win, Lose, Playing };
@ -40,5 +44,12 @@ public:
virtual size_t GetExpectedIdSize() const = 0;
virtual void WarmupShaders() = 0;
virtual hecl::Console* Console() const = 0;
virtual EGame GetGame() const =0;
virtual ERegion GetRegion() const =0;
virtual bool IsPAL() const = 0;
virtual bool IsJapanese() const = 0;
virtual bool IsUSA() const = 0;
virtual bool IsTrilogy() const = 0;
virtual std::string_view GetVersionString() const=0;
};
} // namespace urde

View File

@ -63,8 +63,13 @@ void CTweaks::RegisterTweaks(hecl::CVarManager* cvarMgr) {
/* Targeting */
tag = g_ResFactory->GetResourceIdByName("Targeting");
strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true);
g_tweakTargeting = new DataSpec::DNAMP1::CTweakTargeting(*strm);
g_tweakTargeting->initCVars(cvarMgr);
if (g_Main->IsTrilogy() || g_Main->IsPAL() || g_Main->IsJapanese()) {
g_tweakTargeting = new DataSpec::DNAMP1::CTweakTargeting<true>(*strm);
g_tweakTargeting->initCVars(cvarMgr);
} else {
g_tweakTargeting = new DataSpec::DNAMP1::CTweakTargeting<false>(*strm);
g_tweakTargeting->initCVars(cvarMgr);
}
/* Game */
tag = g_ResFactory->GetResourceIdByName("Game");
@ -121,7 +126,12 @@ void CTweaks::RegisterResourceTweaks(hecl::CVarManager* cvarMgr) {
tag = g_ResFactory->GetResourceIdByName("PlayerRes");
strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true);
g_tweakPlayerRes = new DataSpec::DNAMP1::CTweakPlayerRes(*strm);
if (g_Main->IsTrilogy() || g_Main->IsPAL() || g_Main->IsJapanese()) {
g_tweakPlayerRes = new DataSpec::DNAMP1::CTweakPlayerRes<true>(*strm);
} else {
g_tweakPlayerRes = new DataSpec::DNAMP1::CTweakPlayerRes<false>(*strm);
}
g_tweakPlayerRes->ResolveResources(*g_ResFactory);
g_tweakPlayerRes->initCVars(cvarMgr);
}

View File

@ -37,7 +37,6 @@
#include "Runtime/GuiSys/CTextExecuteBuffer.hpp"
#include "DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp"
#include "DataSpec/DNAMP1/Tweaks/CTweakGame.hpp"
#include "DataSpec/DNACommon/URDEVersionInfo.hpp"
#include "hecl/Console.hpp"
#include "hecl/CVarCommons.hpp"
@ -49,8 +48,6 @@ class IObjectStore;
namespace MP1 {
class CMain;
using ERegion = DataSpec::ERegion;
using EGame = DataSpec::EGame;
class CGameGlobalObjects {
friend class CMain;
@ -315,13 +312,13 @@ public:
void ListWorlds(hecl::Console*, const std::vector<std::string>&);
void Warp(hecl::Console*, const std::vector<std::string>&);
hecl::Console* Console() const override { return m_console.get(); }
bool IsPAL() const { return m_version.region == ERegion::PAL; }
bool IsJapanese() const { return m_version.region == ERegion::NTSC_J; }
bool IsUSA() const { return m_version.region == ERegion::NTSC_U; }
bool IsTrilogy() const { return m_version.isTrilogy; }
ERegion GetRegion() const { return m_version.region; }
EGame GetGame() const { return m_version.game; }
std::string_view GetVersionString() const { return m_version.version; }
bool IsPAL() const override { return m_version.region == ERegion::PAL; }
bool IsJapanese() const override { return m_version.region == ERegion::NTSC_J; }
bool IsUSA() const override { return m_version.region == ERegion::NTSC_U; }
bool IsTrilogy() const override { return m_version.isTrilogy; }
ERegion GetRegion() const override { return m_version.region; }
EGame GetGame() const override { return m_version.game; }
std::string_view GetVersionString() const override{ return m_version.version; }
int m_warpWorldIdx = -1;
TAreaId m_warpAreaId = 0;

View File

@ -149,6 +149,15 @@ bool CProjectileWeaponDataFactory::CreateWPSM(CWeaponDescription* desc, CInputSt
case SBIG('FOFF'):
desc->xb0_FOFF = CPF::GetRealElement(in);
break;
case SBIG('SPS1'):
desc->x28_SPS1 = CPF::GetBool(in);
break;
case SBIG('SPS2'):
desc->x29_SPS2 = CPF::GetBool(in);
break;
case SBIG('FC60'):
desc->x29_FC60 = CPF::GetBool(in);
break;
default: {
Log.report(logvisor::Fatal, FMT_STRING("Unknown WPSM class {} @{}"), clsId, in.position());
return false;

View File

@ -54,5 +54,9 @@ public:
s32 xa8_PJFX = -1;
std::unique_ptr<CRealElement> xac_RNGE;
std::unique_ptr<CRealElement> xb0_FOFF;
// PAL/RS5
bool x28_SPS1 = false;
bool x29_SPS2 = false;
bool x29_FC60 = false;
};
} // namespace urde

View File

@ -36,10 +36,12 @@ float CDamageInfo::GetDamage(const CDamageVulnerability& dVuln) const {
float CDamageInfo::GetRadiusDamage(const CDamageVulnerability& dVuln) const {
EVulnerability vuln = dVuln.GetVulnerability(x0_weaponMode, false);
if (vuln == EVulnerability::Deflect)
if (vuln == EVulnerability::Deflect) {
return 0.f;
else if (vuln == EVulnerability::Weak)
}
if (vuln == EVulnerability::Weak) {
return 2.f * xc_radiusDamage;
}
return xc_radiusDamage;
}

View File

@ -240,36 +240,44 @@ bool CDamageVulnerability::WeaponHits(const CWeaponMode& mode, bool checkDirect)
}
EVulnerability CDamageVulnerability::GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const {
if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon)
if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon) {
return EVulnerability::Deflect;
}
if (mode.IsInstantKill())
if (mode.IsInstantKill()) {
return EVulnerability::Normal;
}
EVulnerability vuln = (&x0_power)[u32(mode.GetType())];
if (mode.IsCharged()) {
if (mode.GetType() < EWeaponType::Bomb)
if (mode.GetType() < EWeaponType::Bomb) {
vuln = (&x3c_chargedPower)[u32(mode.GetType())];
else
} else {
vuln = EVulnerability::Normal;
}
}
if (mode.IsComboed()) {
if (mode.GetType() < EWeaponType::Bomb)
if (mode.GetType() < EWeaponType::Bomb) {
vuln = (&x3c_chargedPower)[u32(mode.GetType())];
else
} else {
vuln = EVulnerability::Normal;
}
}
if (ignoreDirect)
if (ignoreDirect) {
return vuln;
}
if (vuln == EVulnerability::DirectWeak)
if (vuln == EVulnerability::DirectWeak) {
return EVulnerability::Weak;
else if (vuln == EVulnerability::DirectNormal)
}
if (vuln == EVulnerability::DirectNormal) {
return EVulnerability::Normal;
else if (vuln == EVulnerability::DirectImmune)
}
if (vuln == EVulnerability::DirectImmune) {
return EVulnerability::Immune;
}
return vuln;
}

View File

@ -483,8 +483,9 @@ void CKnockBackController::DoKnockBackAnimation(const zeus::CVector3f& backVec,
switch (x4_activeParms.x0_animState) {
case EKnockBackAnimationState::Hurled: {
float hurlVel = 5.f;
if (CHealthInfo* hInfo = parent.HealthInfo(mgr))
if (CHealthInfo* hInfo = parent.HealthInfo(mgr)) {
hurlVel += CalculateExtraHurlVelocity(mgr, magnitude, hInfo->GetKnockbackResistance());
}
hurlVel = std::sqrt(parent.GetGravityConstant() * 0.5f * hurlVel);
zeus::CVector3f backUpVec = backVec + backVec.magnitude() * zeus::skUp;
if (backUpVec.canBeNormalized()) {
@ -520,10 +521,11 @@ void CKnockBackController::ResetKnockBackImpulse(CPatterned& parent, const zeus:
if (x81_24_autoResetImpulse && x4_activeParms.x0_animState == EKnockBackAnimationState::KnockBack &&
x4_activeParms.x4_animFollowup != EKnockBackAnimationFollowUp::Freeze) {
x50_impulseDir = backVec.canBeNormalized() ? backVec.normalized() : -parent.GetTransform().basis[1];
if (x60_impulseRemTime <= 0.f)
if (x60_impulseRemTime <= 0.f) {
x5c_impulseMag = magnitude;
else
} else {
x5c_impulseMag += magnitude * (1.f - x60_impulseRemTime / ImpulseDurationTable[x20_impulseDurationIdx]);
}
x60_impulseRemTime = ImpulseDurationTable[x20_impulseDurationIdx];
}
}
@ -565,21 +567,25 @@ void CKnockBackController::SetAutoResetImpulse(bool b) {
void CKnockBackController::Update(float dt, CStateManager& mgr, CPatterned& parent) {
ApplyImpulse(dt, parent);
x64_flinchRemTime -= dt;
if (TickDeferredTimer(dt))
if (TickDeferredTimer(dt)) {
DoDeferredKnockBack(mgr, parent);
if (x82_26_locomotionDuringElectrocution && parent.GetBodyController()->IsElectrocuting())
}
if (x82_26_locomotionDuringElectrocution && parent.GetBodyController()->IsElectrocuting()) {
parent.GetBodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::Locomotion));
}
}
EKnockBackWeaponType CKnockBackController::GetKnockBackWeaponType(const CDamageInfo& info, EWeaponType wType,
EKnockBackType type) {
int stacking = 0;
if (info.GetWeaponMode().IsCharged())
if (info.GetWeaponMode().IsCharged()) {
stacking = 1;
else if (info.GetWeaponMode().IsComboed())
} else if (info.GetWeaponMode().IsComboed()) {
stacking = 2;
if (wType > EWeaponType::Phazon)
}
if (wType > EWeaponType::Phazon) {
return EKnockBackWeaponType::Invalid;
}
switch (wType) {
case EWeaponType::Power:
return EKnockBackWeaponType(type != EKnockBackType::Direct ? stacking : stacking + 1);
@ -604,6 +610,8 @@ EKnockBackWeaponType CKnockBackController::GetKnockBackWeaponType(const CDamageI
void CKnockBackController::SelectDamageState(CPatterned& parent, const CDamageInfo& info, EWeaponType wType,
EKnockBackType type) {
x4_activeParms = KnockBackParms();
EKnockBackWeaponType weaponType = GetKnockBackWeaponType(info, wType, type);
if (weaponType != EKnockBackWeaponType::Invalid) {
x4_activeParms =
@ -616,8 +624,9 @@ void CKnockBackController::KnockBack(const zeus::CVector3f& backVec, CStateManag
const CDamageInfo& info, EKnockBackType type, float magnitude) {
if (!x82_25_inDeferredKnockBack) {
zeus::CVector3f vec(backVec.toVec2f());
if (!vec.isMagnitudeSafe())
if (!vec.isMagnitudeSafe()) {
vec = -parent.GetTransform().basis[1];
}
SelectDamageState(parent, info, info.GetWeaponMode().GetType(), type);
DoKnockBackAnimation(vec, mgr, parent, magnitude);
ResetKnockBackImpulse(parent, vec, 2.f);

View File

@ -497,10 +497,11 @@ void CPatterned::Death(CStateManager& mgr, const zeus::CVector3f& dir, EScriptOb
void CPatterned::KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, const CDamageInfo& info,
EKnockBackType type, bool inDeferred, float magnitude) {
CHealthInfo* hInfo = HealthInfo(mgr);
if (!x401_27_phazingOut && !x401_28_burning && hInfo) {
if (!x401_27_phazingOut && !x401_28_burning && hInfo != nullptr) {
x460_knockBackController.KnockBack(backVec, mgr, *this, info, type, magnitude);
if (x450_bodyController->IsFrozen() && x460_knockBackController.GetActiveParms().xc_intoFreezeDur >= 0.f)
if (x450_bodyController->IsFrozen() && x460_knockBackController.GetActiveParms().xc_intoFreezeDur >= 0.f) {
x450_bodyController->FrozenBreakout();
}
switch (x460_knockBackController.GetActiveParms().x4_animFollowup) {
case EKnockBackAnimationFollowUp::Freeze:
Freeze(mgr, zeus::skZero3f, zeus::CUnitVector3f(x34_transform.transposeRotate(backVec)),
@ -545,10 +546,11 @@ void CPatterned::KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, c
break;
case EKnockBackAnimationFollowUp::IceDeath:
Death(mgr, zeus::skZero3f, EScriptObjectState::DeathRattle);
if (x54c_iceDeathExplosionParticle)
if (x54c_iceDeathExplosionParticle) {
MassiveFrozenDeath(mgr);
else if (x450_bodyController->IsFrozen())
} else if (x450_bodyController->IsFrozen()) {
x450_bodyController->FrozenBreakout();
}
break;
default:
break;

View File

@ -835,7 +835,7 @@ void CWallCrawlerSwarm::Think(float dt, CStateManager& mgr) {
const zeus::CAABox aabb = BoxForPosition(r26, r27, r20, x374_boidRadius + 0.5f);
CAreaCollisionCache ccache(aabb);
CGameCollision::BuildAreaCollisionCache(mgr, ccache);
while (boid) {
while (boid != nullptr) {
r21 += 1;
if (boid->GetActive()) {
if (x558_flavor == EFlavor::Scarab) {
@ -1235,5 +1235,15 @@ zeus::CVector3f CWallCrawlerSwarm::GetAimPosition(const CStateManager&, float dt
return x108_boids[x42c_lockOnIdx].x30_velocity * dt + x124_lastOrbitPosition;
}
void CWallCrawlerSwarm::ApplyRadiusDamage(const zeus::CVector3f& pos, const CDamageInfo& info, CStateManager& stateMgr) {
for (CBoid& boid : x108_boids) {
if (boid.GetActive() && (boid.GetTranslation() - pos).magSquared() < info.GetRadius() * info.GetRadius()) {
boid.x78_health -= info.GetRadiusDamage();
if (boid.x78_health <= 0.f) {
KillBoid(boid, stateMgr, 1.f, 0.1f);
}
}
}
}
} // namespace urde

View File

@ -205,7 +205,7 @@ public:
zeus::CVector3f GetOrbitPosition(const CStateManager&) const override;
zeus::CVector3f GetAimPosition(const CStateManager&, float) const override;
const zeus::CVector3f& GetLastKilledOffset() const { return x130_lastKilledOffset; }
void ApplyRadiusDamage(const zeus::CVector3f& pos, const CDamageInfo& info, CStateManager& stateMgr) {}
void ApplyRadiusDamage(const zeus::CVector3f& pos, const CDamageInfo& info, CStateManager& stateMgr);
const std::vector<CBoid>& GetBoids() const { return x108_boids; }
int GetCurrentLockOnId() const { return x42c_lockOnIdx; }
bool GetLockOnLocationValid(int id) const { return id >= 0 && id < x108_boids.size() && x108_boids[id].GetActive(); }