mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-31 19:20:26 +00:00
more improvements
This commit is contained in:
parent
a8fb1ae51c
commit
09a0a69b04
@ -81,6 +81,7 @@ static const std::string sHitList[] = {
|
|||||||
"hit3" ,
|
"hit3" ,
|
||||||
"hit4" ,
|
"hit4" ,
|
||||||
"hit5" ,
|
"hit5" ,
|
||||||
|
"knockdown" ,
|
||||||
};
|
};
|
||||||
static const int sHitListSize = sizeof(sHitList)/sizeof(sHitList[0]);
|
static const int sHitListSize = sizeof(sHitList)/sizeof(sHitList[0]);
|
||||||
|
|
||||||
@ -161,23 +162,23 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
|
|||||||
{
|
{
|
||||||
if(MWWorld::Class::get(mPtr).getCreatureStats(mPtr).getAttacked())
|
if(MWWorld::Class::get(mPtr).getCreatureStats(mPtr).getAttacked())
|
||||||
{
|
{
|
||||||
mHitState = CharState_Hit;
|
|
||||||
MWWorld::Class::get(mPtr).getCreatureStats(mPtr).setAttacked(false);
|
MWWorld::Class::get(mPtr).getCreatureStats(mPtr).setAttacked(false);
|
||||||
|
|
||||||
if(!mAnimation->isPlaying(mCurrentHit))
|
if(mHitState == CharState_None)
|
||||||
{
|
{
|
||||||
|
mHitState = CharState_Hit;
|
||||||
if(mJumpState != JumpState_None && !MWBase::Environment::get().getWorld()->isFlying(mPtr)
|
if(mJumpState != JumpState_None && !MWBase::Environment::get().getWorld()->isFlying(mPtr)
|
||||||
&& !MWBase::Environment::get().getWorld()->isSwimming(mPtr) )
|
&& !MWBase::Environment::get().getWorld()->isSwimming(mPtr) )
|
||||||
mCurrentHit = "knockdown";
|
mCurrentHit = sHitList[sHitListSize-1]; //knockdown animation
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int iHit = rand() % sHitListSize;
|
int iHit = rand() % (sHitListSize-1);
|
||||||
mCurrentHit = sHitList[iHit];
|
mCurrentHit = sHitList[iHit];
|
||||||
}
|
}
|
||||||
mAnimation->play(mCurrentHit, Priority_Hit, MWRender::Animation::Group_All, true, 1, "start", "stop", 0.0f, 0);
|
mAnimation->play(mCurrentHit, Priority_Hit, MWRender::Animation::Group_All, true, 1, "start", "stop", 0.0f, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(!mAnimation->isPlaying(mCurrentHit))
|
else if(mHitState != CharState_None && !mAnimation->isPlaying(mCurrentHit))
|
||||||
{
|
{
|
||||||
mCurrentHit.erase();
|
mCurrentHit.erase();
|
||||||
mHitState = CharState_None;
|
mHitState = CharState_None;
|
||||||
@ -458,6 +459,24 @@ void CharacterController::updatePtr(const MWWorld::Ptr &ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CharacterController::playWeaponAnim(const std::string& start, const std::string& stop,
|
||||||
|
float speed, bool autoDisable, bool disablePrevious, float startpoint, bool currentWeapon)
|
||||||
|
{
|
||||||
|
std::string weapgroup;
|
||||||
|
if (currentWeapon)
|
||||||
|
weapgroup = mCurrentWeapon;
|
||||||
|
else
|
||||||
|
getWeaponGroup(mWeaponType, weapgroup);
|
||||||
|
|
||||||
|
if (disablePrevious)
|
||||||
|
mAnimation->disable(weapgroup);
|
||||||
|
|
||||||
|
mAnimation->play(weapgroup, Priority_Weapon,
|
||||||
|
MWRender::Animation::Group_All, autoDisable,
|
||||||
|
speed, start, stop,
|
||||||
|
startpoint, 0);
|
||||||
|
}
|
||||||
|
|
||||||
bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrunning, bool sneak)
|
bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrunning, bool sneak)
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
|
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
|
||||||
@ -490,6 +509,7 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||||||
{
|
{
|
||||||
getWeaponGroup(weaptype, weapgroup);
|
getWeaponGroup(weaptype, weapgroup);
|
||||||
mAnimation->showWeapons(false);
|
mAnimation->showWeapons(false);
|
||||||
|
|
||||||
mAnimation->play(weapgroup, Priority_Weapon,
|
mAnimation->play(weapgroup, Priority_Weapon,
|
||||||
MWRender::Animation::Group_UpperBody, true,
|
MWRender::Animation::Group_UpperBody, true,
|
||||||
1.0f, "equip start", "equip stop", 0.0f, 0);
|
1.0f, "equip start", "equip stop", 0.0f, 0);
|
||||||
@ -642,7 +662,14 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||||||
{
|
{
|
||||||
if(mWeaponType == WeapType_Crossbow || mWeaponType == WeapType_BowAndArrow ||
|
if(mWeaponType == WeapType_Crossbow || mWeaponType == WeapType_BowAndArrow ||
|
||||||
mWeaponType == WeapType_ThowWeapon)
|
mWeaponType == WeapType_ThowWeapon)
|
||||||
|
{
|
||||||
mAttackType = "shoot";
|
mAttackType = "shoot";
|
||||||
|
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||||
|
MWRender::Animation::Group_UpperBody, false,
|
||||||
|
weapSpeed, mAttackType+" start", mAttackType+" attach",
|
||||||
|
0.0f, 0);
|
||||||
|
mUpperBodyState = UpperCharState_StartToAttach;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int attackType = stats.getAttackType();
|
int attackType = stats.getAttackType();
|
||||||
@ -655,7 +682,6 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||||||
mAttackType = "slash";
|
mAttackType = "slash";
|
||||||
else
|
else
|
||||||
mAttackType = "thrust";
|
mAttackType = "thrust";
|
||||||
}
|
|
||||||
|
|
||||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||||
MWRender::Animation::Group_UpperBody, false,
|
MWRender::Animation::Group_UpperBody, false,
|
||||||
@ -664,6 +690,7 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||||||
mUpperBodyState = UpperCharState_StartToMinAttack;
|
mUpperBodyState = UpperCharState_StartToMinAttack;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete);
|
animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -711,10 +738,10 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||||||
mUpperBodyState == UpperCharState_CastingSpell)
|
mUpperBodyState == UpperCharState_CastingSpell)
|
||||||
{
|
{
|
||||||
mUpperBodyState = UpperCharState_WeapEquiped;
|
mUpperBodyState = UpperCharState_WeapEquiped;
|
||||||
//don't allow to continue playing hit animation after actor had attacked during it
|
|
||||||
if(mHitState != CharState_None)
|
if(mHitState != CharState_None) //don't allow to continue playing hit animation after actor had attacked during it
|
||||||
{
|
{
|
||||||
mAnimation->disable(mCurrentHit);
|
mAnimation->changeGroups(mCurrentHit, MWRender::Animation::Group_LowerBody);
|
||||||
mCurrentHit.clear();
|
mCurrentHit.clear();
|
||||||
mHitState = CharState_None;
|
mHitState = CharState_None;
|
||||||
}
|
}
|
||||||
@ -724,53 +751,79 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||||||
}
|
}
|
||||||
else if(complete >= 1.0f)
|
else if(complete >= 1.0f)
|
||||||
{
|
{
|
||||||
if(mUpperBodyState == UpperCharState_StartToMinAttack)
|
std::string start, stop;
|
||||||
|
switch(mUpperBodyState)
|
||||||
{
|
{
|
||||||
mAnimation->disable(mCurrentWeapon);
|
case UpperCharState_StartToMinAttack:
|
||||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
start = mAttackType+" min attack";
|
||||||
MWRender::Animation::Group_UpperBody, false,
|
stop = mAttackType+" max attack";
|
||||||
weapSpeed, mAttackType+" min attack", mAttackType+" max attack",
|
|
||||||
0.0f, 0);
|
|
||||||
mUpperBodyState = UpperCharState_MinAttackToMaxAttack;
|
mUpperBodyState = UpperCharState_MinAttackToMaxAttack;
|
||||||
}
|
break;
|
||||||
else if(mUpperBodyState == UpperCharState_MaxAttackToMinHit)
|
case UpperCharState_StartToAttach: //only bows, crossbows, throwing weapons here
|
||||||
{
|
start = mAttackType+" attach";
|
||||||
mAnimation->disable(mCurrentWeapon);
|
stop = mAttackType+" min attack";
|
||||||
|
mUpperBodyState = UpperCharState_StartToMinAttack;
|
||||||
|
break;
|
||||||
|
case UpperCharState_MaxAttackToMinHit:
|
||||||
if(mAttackType == "shoot")
|
if(mAttackType == "shoot")
|
||||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
{
|
||||||
MWRender::Animation::Group_UpperBody, false,
|
start = mAttackType+" min hit";
|
||||||
weapSpeed, mAttackType+" min hit", mAttackType+" follow start",
|
stop = mAttackType+" release";
|
||||||
0.0f, 0);
|
}
|
||||||
else
|
else
|
||||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
|
||||||
MWRender::Animation::Group_UpperBody, false,
|
|
||||||
weapSpeed, mAttackType+" min hit", mAttackType+" hit",
|
|
||||||
0.0f, 0);
|
|
||||||
mUpperBodyState = UpperCharState_MinHitToHit;
|
|
||||||
}
|
|
||||||
else if(mUpperBodyState == UpperCharState_MinHitToHit)
|
|
||||||
{
|
{
|
||||||
mAnimation->disable(mCurrentWeapon);
|
start = mAttackType+" min hit";
|
||||||
|
stop = mAttackType+" hit";
|
||||||
|
}
|
||||||
|
mUpperBodyState = UpperCharState_MinHitToHit;
|
||||||
|
break;
|
||||||
|
case UpperCharState_MinHitToHit:
|
||||||
if(mAttackType == "shoot")
|
if(mAttackType == "shoot")
|
||||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
{
|
||||||
MWRender::Animation::Group_UpperBody, true,
|
start = mAttackType+" follow start";
|
||||||
weapSpeed, mAttackType+" follow start", mAttackType+" follow stop",
|
stop = mAttackType+" follow stop";
|
||||||
0.0f, 0);
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float str = stats.getAttackStrength();
|
float str = stats.getAttackStrength();
|
||||||
std::string start = mAttackType+((str < 0.5f) ? " small follow start"
|
start = mAttackType+((str < 0.5f) ? " small follow start"
|
||||||
: (str < 1.0f) ? " medium follow start"
|
: (str < 1.0f) ? " medium follow start"
|
||||||
: " large follow start");
|
: " large follow start");
|
||||||
std::string stop = mAttackType+((str < 0.5f) ? " small follow stop"
|
stop = mAttackType+((str < 0.5f) ? " small follow stop"
|
||||||
: (str < 1.0f) ? " medium follow stop"
|
: (str < 1.0f) ? " medium follow stop"
|
||||||
: " large follow stop");
|
: " large follow stop");
|
||||||
|
}
|
||||||
|
mUpperBodyState = UpperCharState_FollowStartToFollowStop;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!start.empty())
|
||||||
|
{
|
||||||
|
mAnimation->disable(mCurrentWeapon);
|
||||||
|
if (mUpperBodyState == UpperCharState_FollowStartToFollowStop)
|
||||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||||
MWRender::Animation::Group_UpperBody, true,
|
MWRender::Animation::Group_UpperBody, true,
|
||||||
weapSpeed, start, stop, 0.0f, 0);
|
weapSpeed, start, stop, 0.0f, 0);
|
||||||
|
else
|
||||||
|
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||||
|
MWRender::Animation::Group_UpperBody, false,
|
||||||
|
weapSpeed, start, stop, 0.0f, 0);
|
||||||
}
|
}
|
||||||
mUpperBodyState = UpperCharState_FollowStartToFollowStop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if playing combat animation and lowerbody is not busy switch to whole body animation
|
||||||
|
if(weaptype != WeaponType::WeapType_None && complete>0.0f)
|
||||||
|
{
|
||||||
|
if( mMovementState != CharState_None ||
|
||||||
|
mJumpState != JumpState_None ||
|
||||||
|
mHitState != CharState_None ||
|
||||||
|
MWBase::Environment::get().getWorld()->isSwimming(mPtr) ||
|
||||||
|
cls.getStance(mPtr, MWWorld::Class::Sneak))
|
||||||
|
mAnimation->changeGroups(mCurrentWeapon, MWRender::Animation::Group_UpperBody);
|
||||||
|
else
|
||||||
|
mAnimation->changeGroups(mCurrentWeapon, MWRender::Animation::Group_All);
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::ContainerStoreIterator torch = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
MWWorld::ContainerStoreIterator torch = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||||
|
@ -114,6 +114,7 @@ enum UpperBodyCharacterState {
|
|||||||
UpperCharState_UnEquipingWeap,
|
UpperCharState_UnEquipingWeap,
|
||||||
UpperCharState_WeapEquiped,
|
UpperCharState_WeapEquiped,
|
||||||
UpperCharState_StartToMinAttack,
|
UpperCharState_StartToMinAttack,
|
||||||
|
UpperCharState_StartToAttach,
|
||||||
UpperCharState_MinAttackToMaxAttack,
|
UpperCharState_MinAttackToMaxAttack,
|
||||||
UpperCharState_MaxAttackToMinHit,
|
UpperCharState_MaxAttackToMinHit,
|
||||||
UpperCharState_MinHitToHit,
|
UpperCharState_MinHitToHit,
|
||||||
@ -175,6 +176,8 @@ class CharacterController
|
|||||||
void clearAnimQueue();
|
void clearAnimQueue();
|
||||||
|
|
||||||
bool updateNpcState(bool onground, bool inwater, bool isrunning, bool sneak);
|
bool updateNpcState(bool onground, bool inwater, bool isrunning, bool sneak);
|
||||||
|
void playWeaponAnim(const std::string& start, const std::string& stop,
|
||||||
|
float speed = 1.0f, bool autoDisable = true, bool disablePrevious = false, float startpoint = 0.0f, bool currentWeapon = true);
|
||||||
|
|
||||||
void updateVisibility();
|
void updateVisibility();
|
||||||
|
|
||||||
|
@ -672,7 +672,20 @@ void Animation::handleTextKey(AnimState &state, const std::string &groupname, co
|
|||||||
MWBase::Environment::get().getWorld()->castSpell(mPtr);
|
MWBase::Environment::get().getWorld()->castSpell(mPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Animation::changeGroups(const std::string &groupname, int groups)
|
||||||
|
{
|
||||||
|
AnimStateMap::iterator stateiter = mStates.begin();
|
||||||
|
stateiter = mStates.find(groupname);
|
||||||
|
if(stateiter != mStates.end())
|
||||||
|
{
|
||||||
|
if(stateiter->second.mGroups != groups)
|
||||||
|
{
|
||||||
|
stateiter->second.mGroups = groups;
|
||||||
|
resetActiveGroups();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
void Animation::play(const std::string &groupname, int priority, int groups, bool autodisable, float speedmult, const std::string &start, const std::string &stop, float startpoint, size_t loops)
|
void Animation::play(const std::string &groupname, int priority, int groups, bool autodisable, float speedmult, const std::string &start, const std::string &stop, float startpoint, size_t loops)
|
||||||
{
|
{
|
||||||
if(!mSkelBase || mAnimSources.empty())
|
if(!mSkelBase || mAnimSources.empty())
|
||||||
|
@ -272,6 +272,7 @@ public:
|
|||||||
* \param groupname Animation group to disable.
|
* \param groupname Animation group to disable.
|
||||||
*/
|
*/
|
||||||
void disable(const std::string &groupname);
|
void disable(const std::string &groupname);
|
||||||
|
void changeGroups(const std::string &groupname, int group);
|
||||||
|
|
||||||
/** Retrieves the velocity (in units per second) that the animation will move. */
|
/** Retrieves the velocity (in units per second) that the animation will move. */
|
||||||
float getVelocity(const std::string &groupname) const;
|
float getVelocity(const std::string &groupname) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user