1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-20 17:23:53 +00:00

more improvements

This commit is contained in:
mrcheko 2014-01-01 21:40:31 +02:00
parent a8fb1ae51c
commit 09a0a69b04
4 changed files with 124 additions and 54 deletions

View file

@ -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);

View file

@ -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();

View file

@ -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())

View file

@ -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;