Add sanity check for animation length when using Anim_Linear as a position provider in PlayAnimation script function.

Controls
Sven Eberhardt 2015-07-07 22:59:41 -04:00
parent 221565952d
commit 103eb2528f
3 changed files with 19 additions and 6 deletions

View File

@ -42,7 +42,7 @@ namespace
const StdMeshInstance::SerializableValueProvider::ID<C4ValueProviderAction> C4ValueProviderActionID("action");
}
StdMeshInstance::ValueProvider* CreateValueProviderFromArray(C4Object* pForObj, C4ValueArray& Data)
StdMeshInstance::ValueProvider* CreateValueProviderFromArray(C4Object* pForObj, C4ValueArray& Data, const StdMeshAnimation* pos_for_animation)
{
int32_t type = Data[0].getInt();
switch (type)
@ -50,9 +50,19 @@ StdMeshInstance::ValueProvider* CreateValueProviderFromArray(C4Object* pForObj,
case C4AVP_Const:
return new C4ValueProviderConst(itofix(Data[1].getInt(), 1000));
case C4AVP_Linear:
if (Data[4].getInt() == 0)
{
int32_t end = Data[3].getInt(), len = Data[4].getInt();
if (len == 0)
throw new C4AulExecError("Length cannot be zero");
return new C4ValueProviderLinear(itofix(Data[1].getInt(), 1000), itofix(Data[2].getInt(), 1000), itofix(Data[3].getInt(), 1000), Data[4].getInt(), static_cast<C4AnimationEnding>(Data[5].getInt()));
// Sanity check for linear animations that are too long and could cause excessive animation stacks
if (pos_for_animation)
{
int32_t max_end = fixtoi(ftofix(pos_for_animation->Length), 1000);
if (end < 0 || end > max_end)
throw new C4AulExecError(FormatString("End (%d) not in range of animation '%s' (0-%d).", (int)end, pos_for_animation->Name.getData(), (int)max_end).getData());
}
return new C4ValueProviderLinear(itofix(Data[1].getInt(), 1000), itofix(Data[2].getInt(), 1000), itofix(end, 1000), len, static_cast<C4AnimationEnding>(Data[5].getInt()));
}
case C4AVP_X:
if (!pForObj) return NULL;
if (Data[4].getInt() == 0)

View File

@ -349,6 +349,6 @@ private:
C4Real Scale;
};
StdMeshInstance::ValueProvider* CreateValueProviderFromArray(C4Object* pForObj, C4ValueArray& Data);
StdMeshInstance::ValueProvider* CreateValueProviderFromArray(C4Object* pForObj, C4ValueArray& Data, const StdMeshAnimation* pos_for_animation = NULL);
#endif

View File

@ -1835,7 +1835,10 @@ static Nillable<int> FnPlayAnimation(C4Object *Obj, C4String *szAnimation, int i
if (!s_node || s_node->GetSlot() != iSlot) return C4Void();
}
StdMeshInstance::ValueProvider* p_provider = CreateValueProviderFromArray(Obj, *PositionProvider);
const StdMeshAnimation* animation = Instance->GetMesh().GetSkeleton().GetAnimationByName(szAnimation->GetData());
if (!animation) return C4Void();
StdMeshInstance::ValueProvider* p_provider = CreateValueProviderFromArray(Obj, *PositionProvider, animation);
StdMeshInstance::ValueProvider* w_provider = CreateValueProviderFromArray(Obj, *WeightProvider);
if (!p_provider || !w_provider)
{
@ -1844,7 +1847,7 @@ static Nillable<int> FnPlayAnimation(C4Object *Obj, C4String *szAnimation, int i
return C4Void();
}
StdMeshInstance::AnimationNode* n_node = Instance->PlayAnimation(szAnimation->GetData(), iSlot, s_node, p_provider, w_provider);
StdMeshInstance::AnimationNode* n_node = Instance->PlayAnimation(*animation, iSlot, s_node, p_provider, w_provider);
if (!n_node) return C4Void();
return n_node->GetNumber();