1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-05 04:37:50 +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; TR::AnimFrame *frameA, *frameB;
vec3 offset, jump; vec3 offset, jump;
bool isEnded, isPrepareToNext, flip; float rot;
bool isEnded, isPrepareToNext;
bool smooth; bool smooth;
quat *overrides; // left & right arms animation frames quat *overrides; // left & right arms animation frames
@@ -136,7 +137,7 @@ struct Animation {
fIndexB = frameNext / anim->frameRate; fIndexB = frameNext / anim->frameRate;
} }
getCommand(anim, frameNext, NULL, NULL, &flip); getCommand(anim, frameNext, NULL, NULL, &rot);
if (smooth) if (smooth)
frameB = getFrame(anim, fIndexB); frameB = getFrame(anim, fIndexB);
@@ -207,11 +208,11 @@ struct Animation {
return anim->speed + anim->accel * t * t * 0.5f; 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]; int16 *ptr = &level->commands[anim->animCommand];
if (offset) *offset = vec3(0.0f); if (offset) *offset = vec3(0.0f);
if (flip) *flip = false; if (rot) *rot = 0.0f;
for (int i = 0; i < anim->acCount; i++) { for (int i = 0; i < anim->acCount; i++) {
int cmd = *ptr++; int cmd = *ptr++;
@@ -233,10 +234,10 @@ struct Animation {
break; break;
case TR::ANIM_CMD_SOUND : ptr += 2; break; case TR::ANIM_CMD_SOUND : ptr += 2; break;
case TR::ANIM_CMD_EFFECT : case TR::ANIM_CMD_EFFECT :
if (flip) { if (rot) {
int frame = (*ptr++) - anim->frameStart; int frame = (*ptr++) - anim->frameStart;
int fx = (*ptr++) & 0x3FFF; int fx = (*ptr++) & 0x3FFF;
*flip = fx == TR::Effect::ROTATE_180 && frame == frameIndex; *rot = (fx == TR::Effect::ROTATE_180 && frame == frameIndex) ? PI : 0.0f;
} else } else
ptr += 2; ptr += 2;
break; break;

View File

@@ -1185,7 +1185,7 @@ struct Controller {
mat4 matrix; mat4 matrix;
matrix.identity(); matrix.identity();
matrix.translate(pos); 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.x != 0.0f) matrix.rotateX(angle.x);
if (angle.z != 0.0f) matrix.rotateZ(angle.z); if (angle.z != 0.0f) matrix.rotateZ(angle.z);
return matrix; return matrix;

View File

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