Initial public release of rem-essentials
This commit is contained in:
+89
@@ -0,0 +1,89 @@
|
||||
#include "weapon_anim.h"
|
||||
#include "utils.h"
|
||||
#include "fl_func.h"
|
||||
#include "logger.h"
|
||||
|
||||
DWORD setModelCallAddr = 0;
|
||||
|
||||
FL_FUNC(bool EngAnimation::SetModel(PDWORD unk, const EngModel* model), setModelCallAddr);
|
||||
|
||||
// There exist many animations for the weapon models in Freelancer (e.g. barrels rotating or moving back and forth while shooting).
|
||||
// However, despite all weapon animations already being defined correctly in the ini files, there is a bug in engbase.dll that prevents these animations from playing properly.
|
||||
// In vanilla FL the internal weapon animation structs have their model set to their actual gun, but this way they don't work.
|
||||
// The fix is to set the animation structs model to its parent (the ship hull). With this the animations will play correctly.
|
||||
bool EngAnimation::SetModel_Hook(PDWORD unk, const EngModel* model)
|
||||
{
|
||||
const EngModel* currentModel = model;
|
||||
|
||||
// Find the parent (ship hull) of the weapon model.
|
||||
while (currentModel)
|
||||
{
|
||||
// If the parent has been found, ensure this is used as the model for the animation, but keep checking for greater parents.
|
||||
if (currentModel->type == EngModelType::Object)
|
||||
{
|
||||
model = currentModel;
|
||||
}
|
||||
|
||||
currentModel = currentModel->parent;
|
||||
}
|
||||
|
||||
// Call original function.
|
||||
return SetModel(unk, model);
|
||||
}
|
||||
|
||||
// This hook allows for e.g. the Cruiser forward gun animation to work without having to modify the model.
|
||||
// Normally in FL the gun .cmp files have their gun animation included.
|
||||
// However, the cruiser gun model is part of the Cruiser ship model itself, and thus the animation is also in the ship model.
|
||||
// In vanilla FL it's not possible to call ship animations when firing a gun.
|
||||
// This hook allows an animation to be played on the parent of the gun if there is a leading underscore in the animation name (_).
|
||||
int IAnimation2::Open_Hook(LPCSTR animationScript, int scriptIndex, const CAttachedEquip &equip)
|
||||
{
|
||||
// If the animation script has a leading underscore, open the animation on the parent of the equipment.
|
||||
if (animationScript && animationScript[0] == '_')
|
||||
{
|
||||
// Remove the leading underscore.
|
||||
// One could argue removing a leading underscore like this is bad practice
|
||||
// since the address is no longer DWORD-aligned.
|
||||
// However, these string addresses aren't DWORD-aligned out of the box, so it doesn't matter.
|
||||
++animationScript;
|
||||
|
||||
if (CObject* parent = equip.parent)
|
||||
{
|
||||
// Open the animation on the parent.
|
||||
return Open(parent->get_archetype()->scriptIndex, parent->engineInstance, animationScript);
|
||||
}
|
||||
}
|
||||
|
||||
// Open the animation on the attached equipment (normal routine).
|
||||
return Open(scriptIndex, equip.GetRootIndex(), animationScript);
|
||||
}
|
||||
|
||||
// Fixes the weapon animations and allows weapons to play ship animations (e.g. wings).
|
||||
void InitWeaponAnimFix()
|
||||
{
|
||||
#define SET_MODEL_FUNC_FILE_OFFSET_ENGBASE 0xADC0
|
||||
#define SET_MODEL_CALL_FILE_OFFSET_ENGBASE 0xB83F
|
||||
#define GET_ROOT_INDEX_CALL_ADDR 0x52C8AF
|
||||
#define PUSH_ZERO_ADDR 0x52C8BF
|
||||
#define ANIM_OPEN_CALL_ADDR 0x52C8C2
|
||||
|
||||
DWORD engbaseHandle = (DWORD) GetModuleHandle("engbase.dll");
|
||||
|
||||
if (engbaseHandle)
|
||||
{
|
||||
setModelCallAddr = engbaseHandle + SET_MODEL_FUNC_FILE_OFFSET_ENGBASE;
|
||||
Hook(engbaseHandle + SET_MODEL_CALL_FILE_OFFSET_ENGBASE, &EngAnimation::SetModel_Hook, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::PrintModuleError("InitWeaponAnimFix", "engbase.dll");
|
||||
}
|
||||
|
||||
// Setup for IAnimation2::Open hook
|
||||
Patch<WORD>(GET_ROOT_INDEX_CALL_ADDR, 0x5551); // Replace GetRootIndex call with push ecx + push ebx
|
||||
Nop(GET_ROOT_INDEX_CALL_ADDR + 2, 4);
|
||||
Nop(PUSH_ZERO_ADDR, 2); // Nop out two zero pushes
|
||||
Nop(ANIM_OPEN_CALL_ADDR, 1); // Nop another instruction
|
||||
|
||||
Hook(ANIM_OPEN_CALL_ADDR + 1, &IAnimation2::Open_Hook, 5);
|
||||
}
|
||||
Reference in New Issue
Block a user