1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-22 02:12:45 +01:00

Melee against on-ground target uses alternate anim

This commit is contained in:
Daniel Evans 2019-01-02 21:02:51 +00:00
parent c307a1c5e3
commit f894718183
5 changed files with 54 additions and 19 deletions

View File

@ -688,31 +688,37 @@ bool Activities::UseItem::update(CharacterObject *character,
character->playCycle(shootcycle);
}
} else if (weapon->fireType == WeaponData::MELEE) {
/// @todo second attack animation for on-ground targets
const auto attackAnimation = shootcycle;
auto currentAnim = character->getCurrentCycle();
if (currentAnim == shootcycle || currentAnim == throwcycle) {
auto fireTime = weapon->animFirePoint / 100.f;
auto loopStart = weapon->animLoopStart / 100.f;
auto currentTime = animator->getAnimationTime(AnimIndexAction);
if (character->getCurrentCycle() != attackAnimation) {
character->playCycle(attackAnimation);
if (currentTime >= fireTime && !fired) {
Weapon::meleeHit(weapon, character);
fired = true;
}
if (animator->isCompleted(AnimIndexAction)) {
if (character->getCurrentState().primaryActive) {
animator->setAnimationTime(AnimIndexAction, loopStart);
fired = false;
}
else {
return true;
}
}
}
auto fireTime = weapon->animFirePoint / 100.f;
auto loopStart = weapon->animLoopStart / 100.f;
auto currentTime = animator->getAnimationTime(AnimIndexAction);
if (currentTime >= fireTime && !fired) {
Weapon::meleeHit(weapon, character);
fired = true;
}
if (animator->isCompleted(AnimIndexAction)) {
if (character->getCurrentState().primaryActive) {
animator->setAnimationTime(AnimIndexAction, loopStart);
fired = false;
else {
const auto onGround = Weapon::targetOnGround(weapon, character);
if (onGround) {
character->playCycle(throwcycle);
}
else {
return true;
character->playCycle(shootcycle);
}
}
} else {
RW_ERROR("Unrecognized fireType: " << weapon->fireType);
return true;

View File

@ -5,10 +5,12 @@
#include <glm/glm.hpp>
#include "data/WeaponData.hpp"
#include "dynamics/HitTest.hpp"
#include "engine/GameWorld.hpp"
#include "objects/CharacterObject.hpp"
#include "objects/ProjectileObject.hpp"
bool WeaponScan::doesDamage(GameObject* target) const {
return target != source;
}
@ -60,3 +62,20 @@ void Weapon::meleeHit(WeaponData* weapon, CharacterObject* character) {
character
});
}
bool Weapon::targetOnGround(WeaponData *weapon, CharacterObject *character) {
const auto center = character->getPosition() + character->getRotation()
* weapon->fireOffset;
HitTest test {*character->engine->dynamicsWorld};
const auto result = test.sphereTest(center, weapon->meleeRadius);
bool ground = false;
for (const auto& r : result) {
if (r.object == character) {
continue;
}
if (r.object->type() == GameObject::Character) {
ground |= static_cast<CharacterObject *>(r.object)->isKnockedDown();
}
}
return ground;
}

View File

@ -58,6 +58,7 @@ namespace Weapon {
void fireProjectile(WeaponData* weapon, CharacterObject* character, float force);
void fireHitscan(WeaponData *weapon, CharacterObject* character);
void meleeHit(WeaponData *weapon, CharacterObject* character);
bool targetOnGround(WeaponData *weapon, CharacterObject* character);
}
#endif

View File

@ -26,6 +26,7 @@
#include "loaders/LoaderIFP.hpp"
#include "objects/VehicleObject.hpp"
#ifndef BT_BULLET_VERSION
#error Unable to find BT_BULLET_VERSION
#endif
@ -468,6 +469,12 @@ void CharacterObject::SetDead() {
currentState.isDead = true;
}
bool CharacterObject::isKnockedDown() const {
/// @todo husho says: State in [knocked down, getting up, dying, dead]
auto a = animator->getAnimation(AnimIndexMovement);
return a == animations->animation(AnimCycle::KnockOutShotFront0);
}
bool CharacterObject::enterVehicle(VehicleObject* vehicle, size_t seat) {
if (vehicle) {
// Check that the seat is free

View File

@ -141,6 +141,8 @@ public:
void Die();
void SetDead();
bool isKnockedDown() const;
bool takeDamage(const DamageInfo& damage) override;
bool enterVehicle(VehicleObject* vehicle, size_t seat);