mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-20 17:23:53 +00:00
more improvements
This commit is contained in:
parent
a8fb1ae51c
commit
09a0a69b04
4 changed files with 124 additions and 54 deletions
|
@ -81,6 +81,7 @@ static const std::string sHitList[] = {
|
|||
"hit3" ,
|
||||
"hit4" ,
|
||||
"hit5" ,
|
||||
"knockdown" ,
|
||||
};
|
||||
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())
|
||||
{
|
||||
mHitState = CharState_Hit;
|
||||
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)
|
||||
&& !MWBase::Environment::get().getWorld()->isSwimming(mPtr) )
|
||||
mCurrentHit = "knockdown";
|
||||
mCurrentHit = sHitList[sHitListSize-1]; //knockdown animation
|
||||
else
|
||||
{
|
||||
int iHit = rand() % sHitListSize;
|
||||
int iHit = rand() % (sHitListSize-1);
|
||||
mCurrentHit = sHitList[iHit];
|
||||
}
|
||||
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();
|
||||
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)
|
||||
{
|
||||
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
|
||||
|
@ -490,6 +509,7 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||
{
|
||||
getWeaponGroup(weaptype, weapgroup);
|
||||
mAnimation->showWeapons(false);
|
||||
|
||||
mAnimation->play(weapgroup, Priority_Weapon,
|
||||
MWRender::Animation::Group_UpperBody, true,
|
||||
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 ||
|
||||
mWeaponType == WeapType_ThowWeapon)
|
||||
{
|
||||
mAttackType = "shoot";
|
||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||
MWRender::Animation::Group_UpperBody, false,
|
||||
weapSpeed, mAttackType+" start", mAttackType+" attach",
|
||||
0.0f, 0);
|
||||
mUpperBodyState = UpperCharState_StartToAttach;
|
||||
}
|
||||
else
|
||||
{
|
||||
int attackType = stats.getAttackType();
|
||||
|
@ -655,7 +682,6 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||
mAttackType = "slash";
|
||||
else
|
||||
mAttackType = "thrust";
|
||||
}
|
||||
|
||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||
MWRender::Animation::Group_UpperBody, false,
|
||||
|
@ -664,6 +690,7 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||
mUpperBodyState = UpperCharState_StartToMinAttack;
|
||||
}
|
||||
}
|
||||
}
|
||||
animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete);
|
||||
}
|
||||
else
|
||||
|
@ -711,10 +738,10 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||
mUpperBodyState == UpperCharState_CastingSpell)
|
||||
{
|
||||
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();
|
||||
mHitState = CharState_None;
|
||||
}
|
||||
|
@ -724,53 +751,79 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
|
|||
}
|
||||
else if(complete >= 1.0f)
|
||||
{
|
||||
if(mUpperBodyState == UpperCharState_StartToMinAttack)
|
||||
std::string start, stop;
|
||||
switch(mUpperBodyState)
|
||||
{
|
||||
mAnimation->disable(mCurrentWeapon);
|
||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||
MWRender::Animation::Group_UpperBody, false,
|
||||
weapSpeed, mAttackType+" min attack", mAttackType+" max attack",
|
||||
0.0f, 0);
|
||||
case UpperCharState_StartToMinAttack:
|
||||
start = mAttackType+" min attack";
|
||||
stop = mAttackType+" max attack";
|
||||
mUpperBodyState = UpperCharState_MinAttackToMaxAttack;
|
||||
}
|
||||
else if(mUpperBodyState == UpperCharState_MaxAttackToMinHit)
|
||||
{
|
||||
mAnimation->disable(mCurrentWeapon);
|
||||
break;
|
||||
case UpperCharState_StartToAttach: //only bows, crossbows, throwing weapons here
|
||||
start = mAttackType+" attach";
|
||||
stop = mAttackType+" min attack";
|
||||
mUpperBodyState = UpperCharState_StartToMinAttack;
|
||||
break;
|
||||
case UpperCharState_MaxAttackToMinHit:
|
||||
if(mAttackType == "shoot")
|
||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||
MWRender::Animation::Group_UpperBody, false,
|
||||
weapSpeed, mAttackType+" min hit", mAttackType+" follow start",
|
||||
0.0f, 0);
|
||||
{
|
||||
start = mAttackType+" min hit";
|
||||
stop = mAttackType+" release";
|
||||
}
|
||||
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")
|
||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||
MWRender::Animation::Group_UpperBody, true,
|
||||
weapSpeed, mAttackType+" follow start", mAttackType+" follow stop",
|
||||
0.0f, 0);
|
||||
{
|
||||
start = mAttackType+" follow start";
|
||||
stop = mAttackType+" follow stop";
|
||||
}
|
||||
else
|
||||
{
|
||||
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"
|
||||
: " 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"
|
||||
: " large follow stop");
|
||||
}
|
||||
mUpperBodyState = UpperCharState_FollowStartToFollowStop;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(!start.empty())
|
||||
{
|
||||
mAnimation->disable(mCurrentWeapon);
|
||||
if (mUpperBodyState == UpperCharState_FollowStartToFollowStop)
|
||||
mAnimation->play(mCurrentWeapon, Priority_Weapon,
|
||||
MWRender::Animation::Group_UpperBody, true,
|
||||
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);
|
||||
|
|
|
@ -114,6 +114,7 @@ enum UpperBodyCharacterState {
|
|||
UpperCharState_UnEquipingWeap,
|
||||
UpperCharState_WeapEquiped,
|
||||
UpperCharState_StartToMinAttack,
|
||||
UpperCharState_StartToAttach,
|
||||
UpperCharState_MinAttackToMaxAttack,
|
||||
UpperCharState_MaxAttackToMinHit,
|
||||
UpperCharState_MinHitToHit,
|
||||
|
@ -175,6 +176,8 @@ class CharacterController
|
|||
void clearAnimQueue();
|
||||
|
||||
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();
|
||||
|
||||
|
|
|
@ -672,7 +672,20 @@ void Animation::handleTextKey(AnimState &state, const std::string &groupname, co
|
|||
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)
|
||||
{
|
||||
if(!mSkelBase || mAnimSources.empty())
|
||||
|
|
|
@ -272,6 +272,7 @@ public:
|
|||
* \param groupname Animation group to disable.
|
||||
*/
|
||||
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. */
|
||||
float getVelocity(const std::string &groupname) const;
|
||||
|
|
Loading…
Reference in a new issue