Skip to content

Commit

Permalink
Implements feature for animations to spawn additional animations.
Browse files Browse the repository at this point in the history
  • Loading branch information
CCHyper committed Aug 13, 2022
1 parent d0e074a commit a9202de
Show file tree
Hide file tree
Showing 6 changed files with 416 additions and 1 deletion.
135 changes: 135 additions & 0 deletions src/extensions/anim/animext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
******************************************************************************/
#include "animext.h"
#include "anim.h"
#include "animtype.h"
#include "animtypeext.h"
#include "wwcrc.h"
#include "tibsun_inline.h"
#include "asserthandler.h"
#include "debughandler.h"

Expand Down Expand Up @@ -156,3 +159,135 @@ void AnimClassExtension::Compute_CRC(WWCRCEngine &crc) const
ASSERT(ThisPtr != nullptr);
//EXT_DEBUG_TRACE("AnimClassExtension::Compute_CRC - Name: %s (0x%08X)\n", ThisPtr->Name(), (uintptr_t)(ThisPtr));
}


/**
* Processes any start events.
*
* @author: CCHyper
*/
bool AnimClassExtension::Start()
{
AnimTypeClassExtension *animext = AnimTypeClassExtensions.find(ThisPtr->Class);
if (!animext) {
return false;
}

/**
* #issue-752
*
* Spawns the start animations.
*/
Spawn_Animations(ThisPtr->Center_Coord(), animext->StartAnims, animext->StartAnimsCount, animext->StartAnimsMinimum, animext->StartAnimsMaximum);

return true;
}


/**
* Processes any middle events.
*
* @author: CCHyper
*/
bool AnimClassExtension::Middle()
{
AnimTypeClassExtension *animext = AnimTypeClassExtensions.find(ThisPtr->Class);
if (!animext) {
return false;
}

/**
* #issue-752
*
* Spawns the middle animations.
*/
Spawn_Animations(ThisPtr->Center_Coord(), animext->MiddleAnims, animext->MiddleAnimsCount, animext->MiddleAnimsMinimum, animext->MiddleAnimsMaximum);

return true;
}


/**
* Processes any end events.
*
* @author: CCHyper
*/
bool AnimClassExtension::End()
{
AnimTypeClassExtension *animext = AnimTypeClassExtensions.find(ThisPtr->Class);
if (!animext) {
return false;
}

/**
* #issue-752
*
* Spawns the end animations.
*/
Spawn_Animations(ThisPtr->Center_Coord(), animext->EndAnims, animext->EndAnimsCount, animext->EndAnimsMinimum, animext->EndAnimsMaximum);

return true;
}


/**
* #issue-752
*
* Spawns the requested animation from the parsed type lists.
*
* @author: CCHyper
*/
bool AnimClassExtension::Spawn_Animations(const Coordinate &coord, const TypeList<AnimTypeClass *> &animlist, const TypeList<int> &countlist, const TypeList<int> &minlist, const TypeList<int> &maxlist)
{
if (!animlist.Count()) {
return false;
}

/**
* Some checks to make sure values are within expected ranges.
*/
if (!countlist.Count()) {
ASSERT(animlist.Count() == minlist.Count());
ASSERT(animlist.Count() == maxlist.Count());
}

/**
* Iterate over all animations set and spawn them.
*/
for (int index = 0; index < animlist.Count(); ++index) {

const AnimTypeClass *animtype = animlist[index];

int count = 1;

/**
* Pick a random count based on the minimum and maximum values
* defined and spawn the animations.
*/
if (animlist.Count() == countlist.Count()) {
count = countlist[index];

} else if (minlist.Count() && maxlist.Count()) {

int min = minlist[index];
int max = maxlist[index];

if (min != max) {
count = Random_Pick(std::min(min, max), std::max(min, max));
} else {
count = std::min(min, max);
}
}

/**
* Based on the count decided above, spawn the animation type.
*/
for (int i = 0; i < count; ++i) {
AnimClass *anim = new AnimClass(animtype, (Coordinate &)coord);
ASSERT(anim != nullptr);
}
}

return true;
}

8 changes: 8 additions & 0 deletions src/extensions/anim/animext.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#include "ttimer.h"
#include "ftimer.h"
#include "typelist.h"


class AnimClass;
Expand All @@ -52,6 +53,13 @@ class AnimClassExtension final : public Extension<AnimClass>
virtual void Detach(TARGET target, bool all = true) override;
virtual void Compute_CRC(WWCRCEngine &crc) const override;

bool Start();
bool Middle();
bool End();

private:
bool Spawn_Animations(const Coordinate &coord, const TypeList<AnimTypeClass *> &animlist, const TypeList<int> &countlist, const TypeList<int> &minlist, const TypeList<int> &maxlist);

public:
};

Expand Down
104 changes: 104 additions & 0 deletions src/extensions/anim/animext_hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "tibsun_globals.h"
#include "tibsun_inline.h"
#include "anim.h"
#include "animext.h"
#include "animext_init.h"
#include "animtype.h"
#include "animtypeext.h"
Expand Down Expand Up @@ -59,6 +60,8 @@ class AnimClassFake final : public AnimClass
{
public:
LayerType _In_Which_Layer() const;


};


Expand Down Expand Up @@ -137,6 +140,85 @@ static void Anim_Spawn_Particles(AnimClass *this_ptr)
}


/**
* Calls the AnimClass extension middle event processor.
*
* @author: CCHyper
*/
DECLARE_PATCH(_AnimClass_Start_Ext_Patch)
{
GET_REGISTER_STATIC(AnimClass *, this_ptr, esi);
static AnimClassExtension *animext;

animext = AnimClassExtensions.find(this_ptr);
if (animext) {
animext->Start();
}

original_code:
_asm { pop esi }
_asm { pop ebx }
_asm { add esp, 0x24 }
_asm { retn }
}


/**
* Calls the AnimClass extension middle event processor.
*
* @author: CCHyper
*/
DECLARE_PATCH(_AnimClass_Middle_Ext_Patch)
{
GET_REGISTER_STATIC(AnimClass *, this_ptr, esi);
static AnimClassExtension *animext;

animext = AnimClassExtensions.find(this_ptr);
if (animext) {
animext->Middle();
}

original_code:
_asm { pop edi }
_asm { pop esi }
_asm { pop ebp }
_asm { add esp, 0x38 }
_asm { retn }
}


/**
* Calls the AnimClass extension middle event processor.
*
* @author: CCHyper
*/
DECLARE_PATCH(_AnimClass_AI_End_Ext_Patch)
{
GET_REGISTER_STATIC(AnimClass *, this_ptr, esi);
static AnimClassExtension *animext;

animext = AnimClassExtensions.find(this_ptr);
if (animext) {
animext->End();
}

original_code:
/**
* Restore expected register states.
*/
_asm { mov esi, this_ptr }
_asm { xor ebp, ebp}

/**
* Stolen bytes/code.
*/
_asm { mov edx, [esi+0x64] } // this->Class
_asm { mov ecx, [edx+0x154] } // Class->ChainTo

JMP_REG(edx, 0x00415B03);
}


/**
* #issue-568
*
Expand Down Expand Up @@ -394,6 +476,28 @@ void AnimClassExtension_Hooks()
*/
AnimClassExtension_Init();

/**
* This patch removes duplicate return in AnimClass::Middle, so we only
* need to hook one place.
*/
Patch_Jump(0x004162BD, 0x0041637C);

Patch_Jump(0x00415F38, &_AnimClass_Start_Ext_Patch);

/**
* Unfortunately, this manual patch is required because the code is optimised
* and reuses "this" (ESI), which we need for the ext patch.
*/
Patch_Byte(0x0041636D, 0x8B); // mov esi, [esi+0x68] -> mov ebp, [esi+0x68]
Patch_Byte(0x0041636D+1, 0x6E); // ^
Patch_Byte(0x0041636D+2, 0x68); // ^
Patch_Byte(0x00416370, 0x85); // test esi, esi -> test ebp, ebp
Patch_Byte(0x00416370+1, 0xED); // ^
Patch_Byte(0x00416374, 0x55); // push esi -> push ebp
Patch_Jump(0x0041637C, &_AnimClass_Middle_Ext_Patch);

Patch_Jump(0x00415AFA, &_AnimClass_AI_End_Ext_Patch);

Patch_Jump(0x00415ADA, &_AnimClass_AI_RandomLoop_Randomiser_BugFix_Patch);
//Patch_Jump(0x00413C79, &_AnimClass_Constructor_Init_Class_Values_Patch); // Moved to AnimClassExtension due to patching conflict.
Patch_Jump(0x00414E8F, &_AnimClass_AI_Beginning_Patch);
Expand Down
Loading

0 comments on commit a9202de

Please sign in to comment.