1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-04-22 03:51:58 +02:00

#14 gorilla strafing

This commit is contained in:
XProger 2018-06-24 03:52:59 +03:00
parent 50e4b209c3
commit 2d07e96ce8
3 changed files with 83 additions and 95 deletions

View File

@ -15,7 +15,8 @@ struct Animation {
TR::AnimFrame *frameA, *frameB;
vec3 offset, jump;
bool isEnded, isPrepareToNext, flip;
float rot;
bool isEnded, isPrepareToNext;
bool smooth;
quat *overrides; // left & right arms animation frames
@ -136,7 +137,7 @@ struct Animation {
fIndexB = frameNext / anim->frameRate;
}
getCommand(anim, frameNext, NULL, NULL, &flip);
getCommand(anim, frameNext, NULL, NULL, &rot);
if (smooth)
frameB = getFrame(anim, fIndexB);
@ -207,11 +208,11 @@ struct Animation {
return anim->speed + anim->accel * t * t * 0.5f;
}
void getCommand(TR::Animation *anim, int frameIndex, vec3 *offset, vec3 *jump, bool *flip) {
void getCommand(TR::Animation *anim, int frameIndex, vec3 *offset, vec3 *jump, float *rot) {
int16 *ptr = &level->commands[anim->animCommand];
if (offset) *offset = vec3(0.0f);
if (flip) *flip = false;
if (rot) *rot = 0.0f;
for (int i = 0; i < anim->acCount; i++) {
int cmd = *ptr++;
@ -233,10 +234,10 @@ struct Animation {
break;
case TR::ANIM_CMD_SOUND : ptr += 2; break;
case TR::ANIM_CMD_EFFECT :
if (flip) {
if (rot) {
int frame = (*ptr++) - anim->frameStart;
int fx = (*ptr++) & 0x3FFF;
*flip = fx == TR::Effect::ROTATE_180 && frame == frameIndex;
*rot = (fx == TR::Effect::ROTATE_180 && frame == frameIndex) ? PI : 0.0f;
} else
ptr += 2;
break;

View File

@ -1185,7 +1185,7 @@ struct Controller {
mat4 matrix;
matrix.identity();
matrix.translate(pos);
if (angle.y != 0.0f) matrix.rotateY(angle.y - (animation.flip ? PI * animation.delta : 0.0f));
if (angle.y != 0.0f) matrix.rotateY(angle.y - animation.rot * animation.delta);
if (angle.x != 0.0f) matrix.rotateX(angle.x);
if (angle.z != 0.0f) matrix.rotateZ(angle.z);
return matrix;

View File

@ -255,6 +255,15 @@ struct Enemy : Character {
return 0;
}
void turn(bool tilt, float w) {
float angleY = 0.0f;
if (tilt)
getTargetInfo(0, NULL, NULL, &angleY, NULL);
turn(angleY, w);
}
int lift(float delta, float speed) {
speed *= Core::deltaTime;
decrease(delta, pos.y, speed);
@ -634,12 +643,7 @@ struct Wolf : Enemy {
}
virtual void updatePosition() {
float angleY = 0.0f;
if (state == STATE_RUN || state == STATE_WALK || state == STATE_STALK)
getTargetInfo(0, NULL, NULL, &angleY, NULL);
turn(angleY, state == STATE_RUN ? WOLF_TURN_FAST : WOLF_TURN_SLOW);
turn(state == STATE_RUN || state == STATE_WALK || state == STATE_STALK, state == STATE_RUN ? WOLF_TURN_FAST : WOLF_TURN_SLOW);
if (state == STATE_DEATH) {
animation.overrideMask = 0;
@ -758,12 +762,7 @@ struct Lion : Enemy {
}
virtual void updatePosition() {
float angleY = 0.0f;
if (state == STATE_RUN || state == STATE_WALK || state == STATE_ROAR)
getTargetInfo(0, NULL, NULL, &angleY, NULL);
turn(angleY, state == STATE_RUN ? LION_TURN_FAST : LION_TURN_SLOW);
turn(state == STATE_RUN || state == STATE_WALK || state == STATE_ROAR, state == STATE_RUN ? LION_TURN_FAST : LION_TURN_SLOW);
if (state == STATE_DEATH) {
animation.overrideMask = 0;
@ -800,16 +799,16 @@ struct Gorilla : Enemy {
STATE_DEATH ,
STATE_IDLE1 ,
STATE_IDLE2 ,
STATE_LSTEP ,
STATE_RSTEP ,
STATE_LEFT ,
STATE_RIGHT ,
STATE_JUMP ,
STATE_HANG ,
};
enum {
BEH_ATTACK = 1,
BEH_LSTEP = 2,
BEH_RSTEP = 4,
FLAG_ATTACK = 1,
FLAG_LEFT = 2,
FLAG_RIGHT = 4,
};
Gorilla(IGame *game, int entity) : Enemy(game, entity, 22, 341, 250.0f, 1.0f) {
@ -822,32 +821,32 @@ struct Gorilla : Enemy {
virtual int getStateGround() {
if (!think(true))
return state;
float angle;
getTargetInfo(0, NULL, NULL, &angle, NULL);
if (nextState == state)
nextState = STATE_NONE;
if (targetDist < GORILLA_DIST_AGGRESSION)
flags.unused |= BEH_ATTACK;
flags.unused |= FLAG_ATTACK;
switch (state) {
case STATE_STOP :
flags.unused &= ~(BEH_LSTEP | BEH_RSTEP);
if (nextState != STATE_NONE)
return nextState;
if (targetDist < GORILLA_DIST_ATTACK)
if (targetCanAttack && targetDist < GORILLA_DIST_ATTACK)
return STATE_ATTACK;
if (!(flags.unused & BEH_ATTACK)) {
// TODO
if (!(flags.unused & FLAG_ATTACK) && zone == target->zone && targetInView) {
int r = rand() % 512;
if (r < 120) return STATE_JUMP;
if (r < 240) return STATE_IDLE1;
if (r < 360) return STATE_IDLE2;
if (r < 480) return STATE_RUN;
return (r % 2) ? STATE_LEFT : STATE_RIGHT;
}
return STATE_RUN;
case STATE_RUN :
if (!flags.unused && targetInView)
return STATE_STOP;
if (targetInView && collide(target) & HIT_MASK) {
if (targetInView && (collide(target) & HIT_MASK)) {
nextState = STATE_ATTACK;
return STATE_STOP;
}
@ -859,6 +858,8 @@ struct Gorilla : Enemy {
nextState = STATE_IDLE1;
else if (r < 480)
nextState = STATE_IDLE2;
else
break;
return STATE_STOP;
}
break;
@ -867,11 +868,9 @@ struct Gorilla : Enemy {
bite(15, vec3(0.0f, -19.0f, 75.0f), 200.0f);
nextState = STATE_STOP;
}
case STATE_LSTEP :
flags.unused |= BEH_LSTEP;
return STATE_STOP;
case STATE_RSTEP :
flags.unused |= BEH_RSTEP;
break;
case STATE_LEFT :
case STATE_RIGHT :
return STATE_STOP;
default : ;
}
@ -881,7 +880,7 @@ struct Gorilla : Enemy {
virtual void hit(float damage, Controller *enemy = NULL, TR::HitType hitType = TR::HIT_DEFAULT) {
Enemy::hit(damage, enemy, hitType);
flags.unused |= BEH_ATTACK;
flags.unused |= FLAG_ATTACK;
};
virtual int getStateDeath() {
@ -890,13 +889,36 @@ struct Gorilla : Enemy {
return animation.setAnim(ANIM_DEATH + rand() % 2);
}
virtual void updateAnimation(bool commands) {
Enemy::updateAnimation(commands);
switch (state) {
case STATE_STOP :
if (flags.unused & FLAG_LEFT) angle.y += PI * 0.5f;
if (flags.unused & FLAG_RIGHT) angle.y -= PI * 0.5f;
flags.unused &= ~(FLAG_LEFT | FLAG_RIGHT);
break;
case STATE_LEFT :
if (!(flags.unused & FLAG_LEFT)) {
flags.unused |= FLAG_LEFT;
angle.y -= PI * 0.5f;
}
break;
case STATE_RIGHT :
if (!(flags.unused & FLAG_RIGHT)) {
flags.unused |= FLAG_RIGHT;
angle.y += PI * 0.5f;
}
break;
default : ;
}
if ((state == STATE_LEFT || state == STATE_RIGHT) && animation.isPrepareToNext && animation.anims[animation.next].state == STATE_STOP)
animation.rot = (state == STATE_LEFT ? -PI : PI) * 0.5f;
}
virtual void updatePosition() {
float angleY = 0.0f;
if (state == STATE_RUN)
getTargetInfo(0, NULL, NULL, &angleY, NULL);
turn(angleY, GORILLA_TURN_FAST);
turn(state == STATE_RUN, GORILLA_TURN_FAST);
if (state == STATE_DEATH) {
animation.overrideMask = 0;
@ -953,7 +975,7 @@ struct Rat : Enemy {
modelLand = level->getModelIndex(TR::Entity::ENEMY_RAT_LAND) - 1;
modelWater = level->getModelIndex(TR::Entity::ENEMY_RAT_WATER) - 1;
}
const virtual TR::Model* getModel() {
bool water = getRoom().flags.water;
int modelIndex = water ? modelWater : modelLand;
@ -1076,12 +1098,7 @@ struct Rat : Enemy {
}
virtual void updatePosition() {
float angleY = 0.0f;
if ((stand == STAND_GROUND && state == STATE_RUN) || (stand == STAND_ONWATER && state == STATE_WATER_SWIM))
getTargetInfo(0, NULL, NULL, &angleY, NULL);
turn(angleY, RAT_TURN_FAST);
turn((stand == STAND_GROUND && state == STATE_RUN) || (stand == STAND_ONWATER && state == STATE_WATER_SWIM), RAT_TURN_FAST);
if (state == STATE_DEATH) {
animation.overrideMask = 0;
@ -1283,12 +1300,7 @@ struct Crocodile : Enemy {
}
virtual void updatePosition() {
float angleY = 0.0f;
if ((stand == STAND_GROUND && (state == STATE_RUN || state == STATE_WALK)) || (stand == STAND_UNDERWATER && state == STATE_WATER_SWIM))
getTargetInfo(0, NULL, NULL, &angleY, NULL);
turn(angleY, RAT_TURN_FAST);
turn((stand == STAND_GROUND && (state == STATE_RUN || state == STATE_WALK)) || (stand == STAND_UNDERWATER && state == STATE_WATER_SWIM), CROCODILE_TURN_FAST);
if (state == STATE_DEATH) {
animation.overrideMask = 0;
@ -1453,11 +1465,7 @@ struct Bear : Enemy {
}
virtual void updatePosition() {
float angleY = 0.0f;
if (state == STATE_RUN || state == STATE_WALK || state == STATE_HIND)
getTargetInfo(0, NULL, NULL, &angleY, NULL);
turn(angleY, state == STATE_RUN ? BEAR_TURN_FAST : BEAR_TURN_SLOW);
turn(state == STATE_RUN || state == STATE_WALK || state == STATE_HIND, state == STATE_RUN ? BEAR_TURN_FAST : BEAR_TURN_SLOW);
if (state == STATE_DEATH) {
animation.overrideMask = 0;
@ -1531,10 +1539,8 @@ struct Bat : Enemy {
}
virtual void updatePosition() {
float angleY = 0.0f;
if (state == STATE_FLY || state == STATE_ATTACK)
getTargetInfo(0, NULL, NULL, &angleY, NULL);
turn(angleY, BAT_TURN_SPEED);
turn(state == STATE_FLY || state == STATE_ATTACK, BAT_TURN_SPEED);
if (flying) {
float wy = waypoint.y - (target->stand != STAND_ONWATER ? 765.0f : 64.0f);
lift(wy - pos.y, BAT_LIFT_SPEED);
@ -1659,11 +1665,7 @@ struct Rex : Enemy {
return;
}
float angleY = 0.0f;
getTargetInfo(0, NULL, NULL, &angleY, NULL);
if (state == STATE_RUN || state == STATE_WALK)
turn(angleY, state == STATE_RUN ? REX_TURN_FAST : REX_TURN_SLOW);
turn(state == STATE_RUN || state == STATE_WALK, state == STATE_RUN ? REX_TURN_FAST : REX_TURN_SLOW);
Enemy::updatePosition();
setOverrides(true, jointChest, jointHead);
@ -1777,11 +1779,7 @@ struct Raptor : Enemy {
return;
}
float angleY = 0.0f;
getTargetInfo(0, NULL, NULL, &angleY, NULL);
if (state == STATE_RUN || state == STATE_WALK)
turn(angleY, state == STATE_RUN ? RAPTOR_TURN_FAST : RAPTOR_TURN_SLOW);
turn(state == STATE_RUN || state == STATE_WALK, state == STATE_RUN ? RAPTOR_TURN_FAST : RAPTOR_TURN_SLOW);
Enemy::updatePosition();
setOverrides(true, jointChest, jointHead);
@ -2007,11 +2005,7 @@ struct Mutant : Enemy {
}
virtual void updatePosition() {
float angleY = 0.0f;
getTargetInfo(0, NULL, NULL, &angleY, NULL);
if (state == STATE_RUN || state == STATE_WALK || state == STATE_FLY)
turn(angleY, (state == STATE_RUN || state == STATE_FLY) ? MUTANT_TURN_FAST : MUTANT_TURN_SLOW);
turn(state == STATE_RUN || state == STATE_WALK || state == STATE_FLY, (state == STATE_RUN || state == STATE_FLY) ? MUTANT_TURN_FAST : MUTANT_TURN_SLOW);
if (flying)
lift(target->pos.y - pos.y, MUTANT_LIFT_SPEED);
@ -2163,9 +2157,11 @@ struct GiantMutant : Enemy {
}
virtual void updatePosition() {
float angleY = 0.0f;
if (target && target->health > 0.0f && fabsf(targetAngle) > GIANT_MUTANT_MIN_ANGLE)
if (state == STATE_TURN_LEFT || state == STATE_TURN_RIGHT || state == STATE_WALK || state == STATE_STOP)
turn(targetAngle, GIANT_MUTANT_TURN_SLOW);
angleY = targetAngle;
turn(angleY, GIANT_MUTANT_TURN_SLOW);
Enemy::updatePosition();
//setOverrides(true, jointChest, jointHead);
@ -2260,11 +2256,7 @@ struct Centaur : Enemy {
}
virtual void updatePosition() {
float angleY = 0.0f;
getTargetInfo(0, NULL, NULL, &angleY, NULL);
if (state == STATE_RUN)
turn(angleY, CENTAUR_TURN_FAST);
turn(state == STATE_RUN, CENTAUR_TURN_FAST);
Enemy::updatePosition();
setOverrides(true, jointChest, jointHead);
@ -2473,12 +2465,7 @@ struct Human : Enemy {
virtual void updatePosition() {
fullChestRotation = state == STATE_FIRE || state == STATE_AIM || (state == STATE_WAIT && getEntity().type == TR::Entity::ENEMY_MR_T);
if (state == STATE_RUN || state == STATE_WALK) {
float angleY = 0.0f;
getTargetInfo(0, NULL, NULL, &angleY, NULL);
turn(angleY, state == STATE_RUN ? HUMAN_TURN_FAST : HUMAN_TURN_SLOW);
} else
turn(0, HUMAN_TURN_SLOW);
turn(state == STATE_RUN || state == STATE_WALK, state == STATE_RUN ? HUMAN_TURN_FAST : HUMAN_TURN_SLOW);
Enemy::updatePosition();
setOverrides(true, jointChest, jointHead);