Skip to content

Commit fd900b6

Browse files
committed
Bugfix: Stoneguardians will no longer cause newworld.zen to crash
1 parent ce17f15 commit fd900b6

File tree

3 files changed

+53
-15
lines changed

3 files changed

+53
-15
lines changed

src/components/CharacterAI.cpp

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,9 @@ namespace REGoth
222222

223223
bool CharacterAI::tryPlayTransitionAnimationTo(const bs::String& anim)
224224
{
225+
// Cannot play animations if the character has no model yet
226+
if (!mVisual->hasVisual()) return false;
227+
225228
bs::String playingNow = mVisual->getPlayingAnimationName();
226229
auto clipPlayingNow = mVisual->findAnimationClip(playingNow);
227230

@@ -499,30 +502,45 @@ namespace REGoth
499502

500503
bool CharacterAI::changeWeaponMode(AI::WeaponMode mode)
501504
{
502-
bs::String stateTarget = AnimationState::constructStateAnimationName(mode, mWalkMode, "");
503-
504-
bool wasAllowed = tryPlayTransitionAnimationTo(stateTarget);
505-
506-
if (wasAllowed)
505+
if (!mVisual->hasVisual())
507506
{
507+
// If the model hasn't been set up yet, just make it start in the target mode.
508+
// This happens on the Stone-Guardians in Gothic 2, which call NPC_SetToFistMode() before
509+
// calling MDL_SetVisual().
510+
508511
mWeaponMode = mode;
509-
}
510512

511-
if (!wasAllowed)
513+
return true;
514+
}
515+
else
512516
{
513-
// FIXME: We're missing some aniAliases, for example, "T_RUN_2_SNEAK" exists,
514-
// and "T_SNEAK_2_RUN" is just the same animation but in reverse. This
515-
// is defined using an aniAlias, which does not seem to be implemented.
516-
auto c = mVisual->findAnimationClip(stateTarget);
517+
// Model exists, check if the state transition is possible
517518

518-
if (c)
519+
bs::String stateTarget = AnimationState::constructStateAnimationName(mode, mWalkMode, "");
520+
521+
bool wasAllowed = tryPlayTransitionAnimationTo(stateTarget);
522+
523+
if (wasAllowed)
519524
{
520-
mVisual->playAnimationClip(c);
521525
mWeaponMode = mode;
522526
}
523-
}
524527

525-
return wasAllowed;
528+
if (!wasAllowed)
529+
{
530+
// FIXME: We're missing some aniAliases, for example, "T_RUN_2_SNEAK" exists,
531+
// and "T_SNEAK_2_RUN" is just the same animation but in reverse. This
532+
// is defined using an aniAlias, which does not seem to be implemented.
533+
auto c = mVisual->findAnimationClip(stateTarget);
534+
535+
if (c)
536+
{
537+
mVisual->playAnimationClip(c);
538+
mWeaponMode = mode;
539+
}
540+
}
541+
542+
return wasAllowed;
543+
}
526544
}
527545

528546
void CharacterAI::tryToggleWalking()

src/components/VisualSkeletalAnimation.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,17 @@ namespace REGoth
132132
useFirstMeshOfModelScript();
133133
}
134134

135+
bool VisualSkeletalAnimation::hasVisual() const
136+
{
137+
if (!mModelScript)
138+
return false;
139+
140+
if (!mMesh)
141+
return false;
142+
143+
return true;
144+
}
145+
135146
bs::Bounds VisualSkeletalAnimation::getBounds() const
136147
{
137148
return mSubRenderable ? mSubRenderable->getBounds() : bs::Bounds();

src/components/VisualSkeletalAnimation.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,15 @@ namespace REGoth
7878
*/
7979
void setVisual(const bs::String& visual);
8080

81+
/**
82+
* @return Whether a visual has been assigned to this component, so that it can play animations.
83+
*
84+
* If no visual has been assigned, methods related to playing or querying animations might fail.
85+
*
86+
* @note Having a *Visual* assigned means that there is a model-script and a mesh set.
87+
*/
88+
bool hasVisual() const;
89+
8190
/**
8291
* Calculates how far the characters animation has moved since the last
8392
* call ot this function via animation.

0 commit comments

Comments
 (0)