Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements feature for animations to spawn additional animations. #753

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions src/extensions/anim/animext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
******************************************************************************/
#include "animext.h"
#include "anim.h"
#include "animtype.h"
#include "animtypeext.h"
#include "tibsun_inline.h"
#include "wwcrc.h"
#include "extension.h"
#include "asserthandler.h"
Expand Down Expand Up @@ -162,3 +165,125 @@ void AnimClassExtension::Compute_CRC(WWCRCEngine &crc) const
{
//EXT_DEBUG_TRACE("AnimClassExtension::Compute_CRC - Name: %s (0x%08X)\n", Name(), (uintptr_t)(This()));
}


/**
* Processes any start events.
*
* @author: CCHyper
*/
bool AnimClassExtension::Start()
{
AnimTypeClassExtension *animtypeext = Extension::Fetch<AnimTypeClassExtension>(This()->Class);

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

return true;
}


/**
* Processes any middle events.
*
* @author: CCHyper
*/
bool AnimClassExtension::Middle()
{
AnimTypeClassExtension *animtypeext = Extension::Fetch<AnimTypeClassExtension>(This()->Class);

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

return true;
}


/**
* Processes any end events.
*
* @author: CCHyper
*/
bool AnimClassExtension::End()
{
AnimTypeClassExtension *animtypeext = Extension::Fetch<AnimTypeClassExtension>(This()->Class);

/**
* #issue-752
*
* Spawns the end animations.
*/
Spawn_Animations(This()->Center_Coord(), animtypeext->EndAnims, animtypeext->EndAnimsCount, animtypeext->EndAnimsMinimum, animtypeext->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;
}
10 changes: 10 additions & 0 deletions src/extensions/anim/animext.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@

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


class AnimClass;
Expand Down Expand Up @@ -63,5 +66,12 @@ AnimClassExtension final : public ObjectClassExtension
virtual const AnimClass *This_Const() const override { return reinterpret_cast<const AnimClass *>(ObjectClassExtension::This_Const()); }
virtual RTTIType What_Am_I() const override { return RTTI_ANIM; }

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:
};
99 changes: 99 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 @@ -136,6 +137,82 @@ 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 = Extension::Fetch<AnimClassExtension>(this_ptr);

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 = Extension::Fetch<AnimClassExtension>(this_ptr);

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 = Extension::Fetch<AnimClassExtension>(this_ptr);

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 @@ -384,6 +461,28 @@ void AnimClassExtension_Hooks()
*/
AnimClassExtension_Init();

Patch_Jump(0x00415F38, &_AnimClass_Start_Ext_Patch);

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

/**
* 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