refactor: Make creature handle all its animations
This commit is contained in:
parent
b5cd07126f
commit
47bf9485f6
11 changed files with 80 additions and 73 deletions
|
@ -264,7 +264,7 @@ void ActionExecutor::executeOpenLock(Creature &actor, ObjectAction &action, floa
|
|||
bool reached = navigateCreature(actor, door->position(), 1.0f, dt);
|
||||
if (reached) {
|
||||
actor.face(*door);
|
||||
actor.playUnlockDoorAnimation();
|
||||
actor.playAnimation(Creature::Animation::UnlockDoor);
|
||||
door->setLocked(false);
|
||||
door->open(&actor);
|
||||
if (!door->blueprint().onOpen().empty()) {
|
||||
|
|
|
@ -224,6 +224,7 @@ shared_ptr<ModelSceneNode> CharacterGeneration::getCharacterModel(SceneGraph &sc
|
|||
|
||||
unique_ptr<Creature> creature(objectFactory->newCreature());
|
||||
creature->load(_character);
|
||||
creature->updateModelAnimation();
|
||||
|
||||
return creature->model();
|
||||
}
|
||||
|
|
|
@ -202,6 +202,7 @@ shared_ptr<ModelSceneNode> ClassSelection::getCharacterModel(const CreatureConfi
|
|||
|
||||
unique_ptr<Creature> creature(objectFactory->newCreature());
|
||||
creature->load(config);
|
||||
creature->updateModelAnimation();
|
||||
|
||||
return creature->model();
|
||||
}
|
||||
|
|
|
@ -182,11 +182,6 @@ void Creature::updateModel() {
|
|||
rightWeaponModel = Models::instance().get(rightWeaponModelName);
|
||||
}
|
||||
_model->attach("rhand", rightWeaponModel);
|
||||
|
||||
// Animation
|
||||
|
||||
_model->setDefaultAnimation(getPauseAnimation());
|
||||
_model->playDefaultAnimation();
|
||||
}
|
||||
|
||||
string Creature::getBodyModelName() const {
|
||||
|
@ -312,32 +307,64 @@ void Creature::loadPortrait(int appearance) {
|
|||
_portrait = Textures::instance().get(resRef, TextureType::GUI);
|
||||
}
|
||||
|
||||
void Creature::playDefaultAnimation() {
|
||||
if (_model) {
|
||||
_model->playDefaultAnimation();
|
||||
}
|
||||
void Creature::update(float dt) {
|
||||
SpatialObject::update(dt);
|
||||
updateModelAnimation();
|
||||
}
|
||||
|
||||
void Creature::playGreetingAnimation() {
|
||||
if (_movementType != MovementType::None) return;
|
||||
|
||||
playAnimation(g_animGreeting, kAnimationPropagate);
|
||||
}
|
||||
|
||||
void Creature::playTalkAnimation() {
|
||||
void Creature::updateModelAnimation() {
|
||||
if (!_model) return;
|
||||
|
||||
_model->playAnimation(g_animTalkBody, kAnimationLoop | kAnimationPropagate);
|
||||
if (_animFireForget) {
|
||||
if (!_model->isAnimationFinished()) return;
|
||||
|
||||
if (_headModel) {
|
||||
_headModel->playAnimation(g_animTalkHead, kAnimationLoop | kAnimationOverlay, 0.25f);
|
||||
_animFireForget = false;
|
||||
_animDirty = true;
|
||||
}
|
||||
if (!_animDirty) return;
|
||||
|
||||
switch (_movementType) {
|
||||
case MovementType::Run:
|
||||
_model->playAnimation(getRunAnimation(), kAnimationLoop | kAnimationPropagate | kAnimationBlend);
|
||||
break;
|
||||
case MovementType::Walk:
|
||||
_model->playAnimation(getWalkAnimation(), kAnimationLoop | kAnimationPropagate | kAnimationBlend);
|
||||
break;
|
||||
default:
|
||||
if (_talking) {
|
||||
_model->playAnimation(g_animTalkBody, kAnimationLoop | kAnimationPropagate);
|
||||
if (_headModel) {
|
||||
_headModel->playAnimation(g_animTalkHead, kAnimationLoop | kAnimationOverlay, 0.25f);
|
||||
}
|
||||
} else {
|
||||
_model->playAnimation(getPauseAnimation(), kAnimationLoop | kAnimationPropagate | kAnimationBlend);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
_animDirty = false;
|
||||
}
|
||||
|
||||
void Creature::playUnlockDoorAnimation() {
|
||||
if (!_model) return;
|
||||
void Creature::clearAllActions() {
|
||||
SpatialObject::clearAllActions();
|
||||
setMovementType(MovementType::None);
|
||||
}
|
||||
|
||||
_model->playAnimation(g_animUnlockDoor, kAnimationBlend);
|
||||
void Creature::playAnimation(Animation anim) {
|
||||
if (!_model || _movementType != MovementType::None) return;
|
||||
|
||||
string animName;
|
||||
switch (anim) {
|
||||
case Animation::UnlockDoor:
|
||||
animName = g_animUnlockDoor;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!animName.empty()) {
|
||||
_model->playAnimation(animName, kAnimationPropagate | kAnimationBlend);
|
||||
_animFireForget = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Creature::equip(const string &resRef) {
|
||||
|
@ -388,38 +415,18 @@ void Creature::setTag(const string &tag) {
|
|||
}
|
||||
|
||||
void Creature::setMovementType(MovementType type) {
|
||||
if (!_model || _movementType == type) return;
|
||||
|
||||
switch (type) {
|
||||
case MovementType::Walk:
|
||||
_model->playAnimation(getWalkAnimation(), kAnimationLoop | kAnimationPropagate | kAnimationBlend);
|
||||
break;
|
||||
case MovementType::Run:
|
||||
_model->playAnimation(getRunAnimation(), kAnimationLoop | kAnimationPropagate | kAnimationBlend);
|
||||
break;
|
||||
default:
|
||||
if (_talking) {
|
||||
playTalkAnimation();
|
||||
} else {
|
||||
_model->playDefaultAnimation();
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (_movementType == type) return;
|
||||
|
||||
_movementType = type;
|
||||
_animDirty = true;
|
||||
_animFireForget = false;
|
||||
}
|
||||
|
||||
void Creature::setTalking(bool talking) {
|
||||
if (_talking == talking) return;
|
||||
|
||||
if (_movementType == MovementType::None) {
|
||||
if (talking) {
|
||||
playTalkAnimation();
|
||||
} else {
|
||||
playDefaultAnimation();
|
||||
}
|
||||
}
|
||||
_talking = talking;
|
||||
_animDirty = true;
|
||||
}
|
||||
|
||||
const string &Creature::getPauseAnimation() const {
|
||||
|
|
|
@ -44,6 +44,10 @@ public:
|
|||
Run
|
||||
};
|
||||
|
||||
enum class Animation {
|
||||
UnlockDoor
|
||||
};
|
||||
|
||||
struct Path {
|
||||
glm::vec3 destination { 0.0f };
|
||||
std::vector<glm::vec3> points;
|
||||
|
@ -53,12 +57,18 @@ public:
|
|||
|
||||
Creature(uint32_t id, ObjectFactory *objectFactory, scene::SceneGraph *sceneGraph);
|
||||
|
||||
void update(float dt) override;
|
||||
void clearAllActions() override;
|
||||
|
||||
glm::vec3 selectablePosition() const override;
|
||||
|
||||
void load(const resource::GffStruct &gffs);
|
||||
void load(const std::shared_ptr<CreatureBlueprint> &blueprint);
|
||||
void load(const CreatureConfiguration &config);
|
||||
|
||||
void playAnimation(Animation anim);
|
||||
void updateModelAnimation();
|
||||
|
||||
Gender gender() const;
|
||||
int appearance() const;
|
||||
std::shared_ptr<render::Texture> portrait() const;
|
||||
|
@ -68,17 +78,8 @@ public:
|
|||
std::shared_ptr<CreatureBlueprint> blueprint() const;
|
||||
|
||||
void setTag(const std::string &tag);
|
||||
virtual void setMovementType(MovementType type);
|
||||
virtual void setTalking(bool talking);
|
||||
|
||||
// Animations
|
||||
|
||||
void playDefaultAnimation();
|
||||
void playGreetingAnimation();
|
||||
void playTalkAnimation();
|
||||
void playUnlockDoorAnimation();
|
||||
|
||||
// END Animations
|
||||
void setMovementType(MovementType type);
|
||||
void setTalking(bool talking);
|
||||
|
||||
// Equipment
|
||||
|
||||
|
@ -121,6 +122,8 @@ private:
|
|||
MovementType _movementType { MovementType::None };
|
||||
bool _talking { false };
|
||||
CreatureAttributes _attributes;
|
||||
bool _animDirty { true };
|
||||
bool _animFireForget { false };
|
||||
|
||||
// Scripts
|
||||
|
||||
|
@ -135,12 +138,14 @@ private:
|
|||
|
||||
// END Loading
|
||||
|
||||
void updateModel();
|
||||
|
||||
ModelType parseModelType(const std::string &s) const;
|
||||
|
||||
std::string getBodyModelName() const;
|
||||
std::string getBodyTextureName() const;
|
||||
std::string getHeadModelName() const;
|
||||
std::string getWeaponModelName(InventorySlot slot) const;
|
||||
ModelType parseModelType(const std::string &s) const;
|
||||
void updateModel();
|
||||
|
||||
const std::string &getPauseAnimation() const;
|
||||
const std::string &getRunAnimation() const;
|
||||
|
|
|
@ -36,6 +36,10 @@ void Object::update(float dt) {
|
|||
_actionQueue.update();
|
||||
}
|
||||
|
||||
void Object::clearAllActions() {
|
||||
_actionQueue.clear();
|
||||
}
|
||||
|
||||
void Object::runUserDefinedEvent(int eventNumber) {
|
||||
if (!_onUserDefined.empty()) {
|
||||
runScript(_onUserDefined, _id, kObjectInvalid, eventNumber);
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
virtual ~Object() = default;
|
||||
|
||||
virtual void update(float dt);
|
||||
virtual void clearAllActions();
|
||||
|
||||
void runUserDefinedEvent(int eventNumber);
|
||||
|
||||
|
|
|
@ -78,12 +78,6 @@ void SpatialObject::update(float dt) {
|
|||
}
|
||||
}
|
||||
|
||||
void SpatialObject::playAnimation(const string &name, int flags, float speed) {
|
||||
if (_model) {
|
||||
_model->playAnimation(name, flags, speed);
|
||||
}
|
||||
}
|
||||
|
||||
bool SpatialObject::isSelectable() const {
|
||||
return _selectable;
|
||||
}
|
||||
|
|
|
@ -42,8 +42,6 @@ class SpatialObject : public Object {
|
|||
public:
|
||||
void update(float dt) override;
|
||||
|
||||
virtual void playAnimation(const std::string &name, int flags = 0, float speed = 1.0f);
|
||||
|
||||
void addItem(const std::shared_ptr<Item> &item);
|
||||
|
||||
float distanceTo(const glm::vec2 &point) const;
|
||||
|
|
|
@ -103,10 +103,6 @@ bool Player::handleKeyUp(const SDL_KeyboardEvent &event) {
|
|||
_moveRight = false;
|
||||
return true;
|
||||
|
||||
case SDL_SCANCODE_X:
|
||||
_party->leader()->playGreetingAnimation();
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ Variable Routines::actionCloseDoor(const vector<Variable> &args, ExecutionContex
|
|||
|
||||
Variable Routines::clearAllActions(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||
shared_ptr<Object> actor(getObjectById(ctx.callerId, ctx));
|
||||
actor->actionQueue().clear();
|
||||
actor->clearAllActions();
|
||||
return Variable();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue