1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-19 11:21:31 +02:00

#8 fix camera targeting; #3 fix reach state in falling state

This commit is contained in:
XProger
2017-08-31 01:38:00 +03:00
parent 28718a033e
commit 167fb1e003
6 changed files with 148 additions and 156 deletions

View File

@@ -4,6 +4,7 @@
#include "core.h" #include "core.h"
#include "frustum.h" #include "frustum.h"
#include "controller.h" #include "controller.h"
#include "character.h"
#define CAMERA_OFFSET (1024.0f + 256.0f) #define CAMERA_OFFSET (1024.0f + 256.0f)
@@ -18,11 +19,11 @@ struct Camera : Controller {
STATE_HEAVY STATE_HEAVY
}; };
Controller *owner; Character *owner;
Frustum *frustum; Frustum *frustum;
float fov, znear, zfar; float fov, znear, zfar;
vec3 target, destPos, advAngle; vec3 target, destPos, lastDest, advAngle;
float advTimer; float advTimer;
mat4 mViewInv; mat4 mViewInv;
int room; int room;
@@ -41,7 +42,7 @@ struct Camera : Controller {
bool firstPerson; bool firstPerson;
bool isVR; bool isVR;
Camera(IGame *game, Controller *owner) : Controller(game, owner ? owner->entity : 0), owner(owner), frustum(new Frustum()), timer(-1.0f), viewIndex(-1), viewIndexLast(-1), viewTarget(NULL), reflectPlane(NULL), isVR(false) { Camera(IGame *game, Character *owner) : Controller(game, owner ? owner->entity : 0), owner(owner), frustum(new Frustum()), timer(-1.0f), viewIndex(-1), viewIndexLast(-1), viewTarget(NULL), reflectPlane(NULL), isVR(false) {
changeView(false); changeView(false);
if (owner->getEntity().type != TR::Entity::LARA && level->cameraFrames) { if (owner->getEntity().type != TR::Entity::LARA && level->cameraFrames) {
state = STATE_CUTSCENE; state = STATE_CUTSCENE;
@@ -110,6 +111,16 @@ struct Camera : Controller {
this->viewIndex = viewIndex; this->viewIndex = viewIndex;
this->timer = timer; this->timer = timer;
this->speed = speed; this->speed = speed;
lastDest = pos;
}
vec3 getViewPoint() {
vec3 p = owner->getViewPoint();
if (owner->stand != Character::STAND_UNDERWATER)
p.y -= 256.0f;
if (state == STATE_COMBAT)
p.y -= 256.0f;
return p;
} }
virtual void update() { virtual void update() {
@@ -168,49 +179,45 @@ struct Camera : Controller {
} else } else
advTimer = -1.0f; advTimer = -1.0f;
/* toto
if (owner->velocity != 0.0f && advTimer < 0.0f && !Input::down[ikMouseL]) if (owner->velocity != 0.0f && advTimer < 0.0f && !Input::down[ikMouseL])
advTimer = -advTimer; advTimer = -advTimer;
*/
angle = owner->angle + advAngle; angle = owner->angle + advAngle;
angle.z = 0.0f; angle.z = 0.0f;
/* toto
if (owner->stand == Lara::STAND_ONWATER)
angle.x -= 22.0f * DEG2RAD;
if (owner->state == Lara::STATE_HANG || owner->state == Lara::STATE_HANG_LEFT || owner->state == Lara::STATE_HANG_RIGHT)
angle.x -= 60.0f * DEG2RAD;
*/
Controller *lookAt = viewTarget;
/* todo
if (owner->arms[0].target > -1 && owner->arms[1].target > -1 && owner->arms[0].target != owner->arms[1].target) {
// two diff targets
} else if (owner->arms[0].target > -1)
lookAt = owner->arms[0].target;
else if (owner->arms[1].target > -1)
lookAt = owner->arms[1].target;
else if (owner->arms[0].tracking > -1)
lookAt = owner->arms[0].tracking;
else if (owner->arms[1].tracking > -1)
lookAt = owner->arms[1].tracking;
owner->viewTarget = lookAt; if (owner->stand == Character::STAND_ONWATER)
*/ angle.x -= 22.0f * DEG2RAD;
if (owner->stand == Character::STAND_HANG)
angle.x -= 60.0f * DEG2RAD;
Controller *lookAt = viewTarget;
if (state != STATE_STATIC) {
if (owner->viewTarget)
owner->lookAt(lookAt = owner->viewTarget);
else
owner->lookAt(lookAt = viewTarget);
}
vec3 viewPoint = getViewPoint();
if (timer > 0.0f) { if (timer > 0.0f) {
timer -= Core::deltaTime; timer -= Core::deltaTime;
if (timer <= 0.0f) { if (timer <= 0.0f) {
timer = -1.0f; timer = -1.0f;
state = STATE_FOLLOW; state = STATE_FOLLOW;
viewTarget = NULL; viewTarget = owner->viewTarget = NULL;
viewIndex = -1; viewIndex = -1;
/* todo target = viewPoint;
target = owner->getViewPoint(); if (room != getRoomIndex())
*/ pos = lastDest;
} }
} } else
viewIndex = -1;
if (timer < 0.0f) { if (timer < 0.0f)
viewTarget = NULL; viewTarget = NULL;
}
if (firstPerson && viewIndex == -1) { if (firstPerson && viewIndex == -1) {
Basis head = owner->animation.getJoints(owner->getMatrix(), 14, true); Basis head = owner->animation.getJoints(owner->getMatrix(), 14, true);
@@ -233,10 +240,8 @@ struct Camera : Controller {
float lerpFactor = lookAt ? 10.0f : 6.0f; float lerpFactor = lookAt ? 10.0f : 6.0f;
vec3 dir; vec3 dir;
/* todo
target = target.lerp(owner->getViewPoint(), lerpFactor * Core::deltaTime); target = target.lerp(viewPoint, lerpFactor * Core::deltaTime);
*/
target = owner->animation.getJoints(owner->getMatrix(), 7).pos;
if (viewIndex > -1) { if (viewIndex > -1) {
TR::Camera &cam = level->cameras[viewIndex]; TR::Camera &cam = level->cameras[viewIndex];
@@ -252,17 +257,15 @@ struct Camera : Controller {
dir = getDir(); dir = getDir();
int destRoom; int destRoom;
/* todo if ((state == STATE_COMBAT || owner->state != 25) || lookAt) { // TODO: FUUU! 25 == Lara::STATE_BACK_JUMP
if ((!owner->emptyHands() || owner->state != Lara::STATE_BACK_JUMP) || lookAt > -1) {
*/
vec3 eye = target - dir * CAMERA_OFFSET; vec3 eye = target - dir * CAMERA_OFFSET;
destPos = trace(owner->getRoomIndex(), target, eye, destRoom, true); destPos = trace(owner->getRoomIndex(), target, eye, destRoom, true);
/* lastDest = destPos;
} else { } else {
vec3 eye = lastDest + dir.cross(vec3(0, 1, 0)).normal() * 2048.0f - vec3(0.0f, 512.0f, 0.0f); vec3 eye = lastDest + dir.cross(vec3(0, 1, 0)).normal() * 2048.0f - vec3(0.0f, 512.0f, 0.0f);
destPos = trace(owner->getRoomIndex(), target, eye, destRoom, true); destPos = trace(owner->getRoomIndex(), target, eye, destRoom, true);
} }
*/
room = destRoom; room = destRoom;
} }
pos = pos.lerp(destPos, Core::deltaTime * lerpFactor); pos = pos.lerp(destPos, Core::deltaTime * lerpFactor);
@@ -317,10 +320,7 @@ struct Camera : Controller {
room = owner->getRoomIndex(); room = owner->getRoomIndex();
pos = owner->pos - owner->getDir() * 1024.0f; pos = owner->pos - owner->getDir() * 1024.0f;
/* todo target = getViewPoint();
target = owner->getViewPoint();
*/
target = owner->animation.getJoints(owner->getMatrix(), 7).pos;
advAngle = vec3(0.0f); advAngle = vec3(0.0f);
advTimer = 0.0f; advTimer = 0.0f;

View File

@@ -26,6 +26,10 @@ struct Character : Controller {
DEATH = 1 << 9 DEATH = 1 << 9
}; };
Controller *viewTarget;
int jointChest;
int jointHead;
vec3 velocity; vec3 velocity;
float angleExt; float angleExt;
float speed; float speed;
@@ -39,7 +43,7 @@ struct Character : Controller {
Collision collision; Collision collision;
Character(IGame *game, int entity, float health) : Controller(game, entity), health(health), tilt(0.0f), stand(STAND_GROUND), lastInput(0), velocity(0.0f), angleExt(0.0f) { Character(IGame *game, int entity, float health) : Controller(game, entity), health(health), tilt(0.0f), stand(STAND_GROUND), lastInput(0), viewTarget(NULL), jointChest(-1), jointHead(-1), velocity(0.0f), angleExt(0.0f) {
stepHeight = 256; stepHeight = 256;
dropHeight = -256; dropHeight = -256;
@@ -197,6 +201,34 @@ struct Character : Controller {
level->entities[index].controller = new Bubble(game, index); level->entities[index].controller = new Bubble(game, index);
} }
} }
vec3 getViewPoint() {
return animation.getJoints(getMatrix(), jointChest).pos;
}
virtual void lookAt(Controller *target) {
if (health <= 0.0f)
target = NULL;
float speed = 8.0f * Core::deltaTime;
quat rot;
if (jointChest > -1) {
if (aim(target, jointChest, vec4(-PI * 0.8f, PI * 0.8f, -PI * 0.75f, PI * 0.75f), rot))
rotChest = rotChest.slerp(quat(0, 0, 0, 1).slerp(rot, 0.5f), speed);
else
rotChest = rotChest.slerp(quat(0, 0, 0, 1), speed);
animation.overrides[jointChest] = rotChest * animation.overrides[jointChest];
}
if (jointHead > -1) {
if (aim(target, jointHead, vec4(-PI * 0.25f, PI * 0.25f, -PI * 0.5f, PI * 0.5f), rot))
rotHead = rotHead.slerp(rot, speed);
else
rotHead = rotHead.slerp(quat(0, 0, 0, 1), speed);
animation.overrides[jointHead] = rotHead * animation.overrides[jointHead];
}
}
}; };
#endif #endif

View File

@@ -200,10 +200,9 @@ struct Controller {
layers[layer].mask = mask; layers[layer].mask = mask;
} }
bool aim(int target, int joint, const vec4 &angleRange, quat &rot, quat *rotAbs = NULL) { bool aim(Controller *target, int joint, const vec4 &angleRange, quat &rot, quat *rotAbs = NULL) {
if (target > -1) { if (target) {
TR::Entity &e = level->entities[target]; Box box = target->getBoundingBox();
Box box = ((Controller*)e.controller)->getBoundingBox();
vec3 t = (box.min + box.max) * 0.5f; vec3 t = (box.min + box.max) * 0.5f;
Basis b = animation.getJoints(Basis(getMatrix()), joint); Basis b = animation.getJoints(Basis(getMatrix()), joint);

View File

@@ -61,9 +61,6 @@ struct Enemy : Character {
Character *target; Character *target;
Path *path; Path *path;
int jointChest;
int jointHead;
float targetDist; float targetDist;
bool targetDead; bool targetDead;
bool targetInView; // target in enemy view zone bool targetInView; // target in enemy view zone
@@ -71,8 +68,6 @@ struct Enemy : Character {
bool targetCanAttack; bool targetCanAttack;
Enemy(IGame *game, int entity, float health, int radius, float length, float aggression) : Character(game, entity, health), ai(AI_RANDOM), mood(MOOD_SLEEP), wound(false), nextState(0), targetBox(-1), thinkTime(1.0f / 30.0f), length(length), aggression(aggression), radius(radius), target(NULL), path(NULL) { Enemy(IGame *game, int entity, float health, int radius, float length, float aggression) : Character(game, entity, health), ai(AI_RANDOM), mood(MOOD_SLEEP), wound(false), nextState(0), targetBox(-1), thinkTime(1.0f / 30.0f), length(length), aggression(aggression), radius(radius), target(NULL), path(NULL) {
jointChest = jointHead = -1;
targetDist = +INF; targetDist = +INF;
targetInView = targetFromView = targetCanAttack = false; targetInView = targetFromView = targetCanAttack = false;
} }
@@ -177,27 +172,6 @@ struct Enemy : Character {
animation.overrideMask &= ~(1 << chest); animation.overrideMask &= ~(1 << chest);
} }
void lookAt(int target, int chest, int head, bool rotate = false) {
float speed = 8.0f * Core::deltaTime;
quat rot;
if (chest > -1) {
if (rotate && aim(target, chest, vec4(-PI * 0.8f, PI * 0.8f, -PI * 0.75f, PI * 0.75f), rot))
rotChest = rotChest.slerp(quat(0, 0, 0, 1).slerp(rot, 0.5f), speed);
else
rotChest = rotChest.slerp(quat(0, 0, 0, 1), speed);
animation.overrides[chest] = rotChest * animation.overrides[chest];
}
if (head > -1) {
if (rotate && aim(target, head, vec4(-PI * 0.25f, PI * 0.25f, -PI * 0.5f, PI * 0.5f), rot))
rotHead = rotHead.slerp(rot, speed);
else
rotHead = rotHead.slerp(quat(0, 0, 0, 1), speed);
animation.overrides[head] = rotHead * animation.overrides[head];
}
}
bool getTargetInfo(int height, vec3 *pos, float *angleX, float *angleY, float *dist) { bool getTargetInfo(int height, vec3 *pos, float *angleX, float *angleY, float *dist) {
vec3 p = waypoint; vec3 p = waypoint;
p.y -= height; p.y -= height;
@@ -621,7 +595,7 @@ struct Wolf : Enemy {
Enemy::updatePosition(); Enemy::updatePosition();
setOverrides(state != STATE_DEATH, jointChest, jointHead); setOverrides(state != STATE_DEATH, jointChest, jointHead);
lookAt(target ? target->entity : -1, jointChest, jointHead); lookAt(target);
} }
}; };
@@ -770,7 +744,7 @@ struct Bear : Enemy {
Enemy::updatePosition(); Enemy::updatePosition();
setOverrides(state == STATE_RUN || state == STATE_WALK || state == STATE_HIND, jointChest, jointHead); setOverrides(state == STATE_RUN || state == STATE_WALK || state == STATE_HIND, jointChest, jointHead);
lookAt(target ? target->entity : -1, jointChest, jointHead); lookAt(target);
} }
}; };
@@ -963,7 +937,7 @@ struct Rex : Enemy {
Enemy::updatePosition(); Enemy::updatePosition();
setOverrides(true, jointChest, jointHead); setOverrides(true, jointChest, jointHead);
lookAt(target ? target->entity : -1, jointChest, jointHead, targetInView && state != STATE_DEATH && state != STATE_FATAL); lookAt(target);
} }
}; };
@@ -1081,7 +1055,7 @@ struct Raptor : Enemy {
Enemy::updatePosition(); Enemy::updatePosition();
setOverrides(true, jointChest, jointHead); setOverrides(true, jointChest, jointHead);
lookAt(target ? target->entity : -1, jointChest, jointHead, targetInView && state != STATE_DEATH); lookAt(target);
} }
}; };

View File

@@ -211,19 +211,20 @@ struct Lara : Character {
vec3 chestOffset; vec3 chestOffset;
struct Arm { struct Arm {
int tracking; // tracking target (main target) Controller *tracking; // tracking target (main target)
int target; // target for shooting Controller *target; // target for shooting
float shotTimer; float shotTimer;
quat rot, rotAbs; quat rot, rotAbs;
Weapon::Anim anim; Weapon::Anim anim;
Animation animation; Animation animation;
Arm() : tracking(NULL), target(NULL) {}
} arms[2]; } arms[2];
TR::Entity::Type usedKey; TR::Entity::Type usedKey;
TR::Entity *pickupEntity; TR::Entity *pickupEntity;
KeyHole *keyHole; KeyHole *keyHole;
int viewTarget;
int roomPrev; // water out from room int roomPrev; // water out from room
vec2 rotFactor; vec2 rotFactor;
@@ -394,7 +395,7 @@ struct Lara : Character {
} *braid; } *braid;
Lara(IGame *game, int entity) : Character(game, entity, LARA_MAX_HEALTH), dozy(false), wpnCurrent(Weapon::EMPTY), wpnNext(Weapon::EMPTY), chestOffset(pos), viewTarget(-1), braid(NULL) { Lara(IGame *game, int entity) : Character(game, entity, LARA_MAX_HEALTH), dozy(false), wpnCurrent(Weapon::EMPTY), wpnNext(Weapon::EMPTY), chestOffset(pos), braid(NULL) {
if (getEntity().type == TR::Entity::LARA) { if (getEntity().type == TR::Entity::LARA) {
if (getRoom().flags.water) if (getRoom().flags.water)
@@ -403,6 +404,8 @@ struct Lara : Character {
animation.setAnim(ANIM_STAND); animation.setAnim(ANIM_STAND);
} }
jointChest = 7;
jointHead = 14;
oxygen = LARA_MAX_OXYGEN; oxygen = LARA_MAX_OXYGEN;
hitDir = -1; hitDir = -1;
damageTime = LARA_DAMAGE_TIME; damageTime = LARA_DAMAGE_TIME;
@@ -754,10 +757,10 @@ struct Lara : Character {
//int realFrameIndex = int(arms[i].animation.time * 30.0f / anim->frameRate) % ((anim->frameEnd - anim->frameStart) / anim->frameRate + 1); //int realFrameIndex = int(arms[i].animation.time * 30.0f / anim->frameRate) % ((anim->frameEnd - anim->frameStart) / anim->frameRate + 1);
if (anim.frameIndex != anim.framePrev) { if (anim.frameIndex != anim.framePrev) {
if (anim.frameIndex == 0) { //realFrameIndex < arms[i].animation.framePrev) { if (anim.frameIndex == 0) { //realFrameIndex < arms[i].animation.framePrev) {
if ((input & ACTION) && (arm.tracking == -1 || arm.target > -1)) { if ((input & ACTION) && (!arm.tracking || arm.target)) {
armShot[i] = true; armShot[i] = true;
} else } else
wpnSetAnim(arm, Weapon::IS_ARMED, Weapon::Anim::AIM, 0.0f, -1.0f, arm.target == -1); wpnSetAnim(arm, Weapon::IS_ARMED, Weapon::Anim::AIM, 0.0f, -1.0f, arm.target == NULL);
} }
// shotgun reload sound // shotgun reload sound
if (wpnCurrent == Weapon::SHOTGUN) { if (wpnCurrent == Weapon::SHOTGUN) {
@@ -811,8 +814,8 @@ struct Lara : Character {
int room; int room;
vec3 hit = trace(getRoomIndex(), p, t, room, false); vec3 hit = trace(getRoomIndex(), p, t, room, false);
if (arm->target > -1 && checkHit(arm->target, p, hit, hit)) { if (arm->target && checkHit(arm->target, p, hit, hit)) {
((Character*)level->entities[arm->target].controller)->hit(wpnGetDamage()); ((Character*)arm->target)->hit(wpnGetDamage());
hit -= d * 64.0f; hit -= d * 64.0f;
Sprite::add(game, TR::Entity::BLOOD, room, (int)hit.x, (int)hit.y, (int)hit.z, Sprite::FRAME_ANIMATED); Sprite::add(game, TR::Entity::BLOOD, room, (int)hit.x, (int)hit.y, (int)hit.z, Sprite::FRAME_ANIMATED);
} else { } else {
@@ -848,8 +851,8 @@ struct Lara : Character {
if (input & DEATH) { if (input & DEATH) {
arms[0].shotTimer = arms[1].shotTimer = MUZZLE_FLASH_TIME + 1.0f; arms[0].shotTimer = arms[1].shotTimer = MUZZLE_FLASH_TIME + 1.0f;
arms[0].tracking = arms[1].tracking = -1; arms[0].tracking = arms[1].tracking = NULL;
arms[0].target = arms[1].target = -1; arms[0].target = arms[1].target = NULL;
animation.overrideMask = 0; animation.overrideMask = 0;
return; return;
} }
@@ -877,7 +880,7 @@ struct Lara : Character {
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
Arm &arm = arms[i]; Arm &arm = arms[i];
if (arm.target > -1 || ((input & ACTION) && arm.tracking == -1)) { if (arm.target || ((input & ACTION) && !arm.tracking)) {
if (arm.anim == Weapon::Anim::HOLD) if (arm.anim == Weapon::Anim::HOLD)
wpnSetAnim(arm, wpnState, Weapon::Anim::AIM, 0.0f, 1.0f); wpnSetAnim(arm, wpnState, Weapon::Anim::AIM, 0.0f, 1.0f);
} else } else
@@ -1025,8 +1028,10 @@ struct Lara : Character {
} }
animation.overrideMask = overrideMask; animation.overrideMask = overrideMask;
}
lookAt(viewTarget); virtual void lookAt(Controller *target) {
Character::lookAt(canLookAt() ? target : NULL);
if (wpnCurrent == Weapon::SHOTGUN) if (wpnCurrent == Weapon::SHOTGUN)
aimShotgun(); aimShotgun();
@@ -1034,31 +1039,11 @@ struct Lara : Character {
aimPistols(); aimPistols();
} }
void lookAt(int target) { // TODO: character lookAt
float speed = 8.0f * Core::deltaTime;
quat rot;
bool can = canLookAt();
// chest
if (can && aim(target, 7, vec4(-PI * 0.4f, PI * 0.4f, -PI * 0.9f, PI * 0.9f), rot))
rotChest = rotChest.slerp(quat(0, 0, 0, 1).slerp(rot, 0.5f), speed);
else
rotChest = rotChest.slerp(quat(0, 0, 0, 1), speed);
animation.overrides[7] = rotChest * animation.overrides[7];
// head
if (can && aim(target, 14, vec4(-PI * 0.25f, PI * 0.25f, -PI * 0.5f, PI * 0.5f), rot))
rotHead = rotHead.slerp(rot, speed);
else
rotHead = rotHead.slerp(quat(0, 0, 0, 1), speed);
animation.overrides[14] = rotHead * animation.overrides[14];
}
void aimShotgun() { void aimShotgun() {
quat rot; quat rot;
Arm &arm = arms[0]; Arm &arm = arms[0];
arm.target = aim(arm.target, 14, vec4(-PI * 0.4f, PI * 0.4f, -PI * 0.25f, PI * 0.25f), rot, &arm.rotAbs) ? arm.target : -1; arm.target = aim(arm.target, 14, vec4(-PI * 0.4f, PI * 0.4f, -PI * 0.25f, PI * 0.25f), rot, &arm.rotAbs) ? arm.target : NULL;
} }
void aimPistols() { void aimPistols() {
@@ -1080,7 +1065,7 @@ struct Lara : Character {
arm.target = arms[i^1].target; arm.target = arms[i^1].target;
if (!aim(arm.target, j, ranges[i], rot, &arm.rotAbs)) { if (!aim(arm.target, j, ranges[i], rot, &arm.rotAbs)) {
rot = quat(0, 0, 0, 1); rot = quat(0, 0, 0, 1);
arm.target = -1; arm.target = NULL;
} }
} }
@@ -1098,10 +1083,11 @@ struct Lara : Character {
} }
void updateTargets() { void updateTargets() {
arms[0].target = arms[1].target = -1; arms[0].target = arms[1].target = NULL;
viewTarget = NULL;
if (emptyHands() || !wpnReady()) { if (emptyHands() || !wpnReady()) {
arms[0].tracking = arms[1].tracking = -1; arms[0].tracking = arms[1].tracking = NULL;
return; return;
} }
@@ -1109,7 +1095,7 @@ struct Lara : Character {
bool retarget = false; bool retarget = false;
if (Core::settings.controls.retarget) { if (Core::settings.controls.retarget) {
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
if (arms[i].tracking == -1 || ((Character*)level->entities[arms[i].tracking].controller)->health <= 0.0f) { if (!arms[i].tracking || ((Character*)arms[i].tracking)->health <= 0.0f) {
retarget = true; retarget = true;
break; break;
} }
@@ -1119,15 +1105,15 @@ struct Lara : Character {
if (!(input & ACTION) || retarget) { if (!(input & ACTION) || retarget) {
getTargets(arms[0].tracking, arms[1].tracking); getTargets(arms[0].tracking, arms[1].tracking);
if (count == 1) if (count == 1)
arms[1].tracking = -1; arms[1].tracking = NULL;
else if (arms[0].tracking == -1 && arms[1].tracking != -1) else if (!arms[0].tracking && arms[1].tracking)
arms[0].tracking = arms[1].tracking; arms[0].tracking = arms[1].tracking;
else if (arms[1].tracking == -1 && arms[0].tracking != -1) else if (!arms[1].tracking && arms[0].tracking)
arms[1].tracking = arms[0].tracking; arms[1].tracking = arms[0].tracking;
arms[0].target = arms[0].tracking; arms[0].target = arms[0].tracking;
arms[1].target = arms[1].tracking; arms[1].target = arms[1].tracking;
} else { } else {
if (arms[0].tracking == -1 && arms[1].tracking == -1) if (!arms[0].tracking && !arms[1].tracking)
return; return;
// flip left and right by relative target direction // flip left and right by relative target direction
@@ -1137,8 +1123,8 @@ struct Lara : Character {
dir.y = 0.0f; dir.y = 0.0f;
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
if (arms[i].tracking != -1) { if (arms[i].tracking) {
vec3 v = ((Controller*)level->entities[arms[i].tracking].controller)->pos - pos; vec3 v = arms[i].tracking->pos - pos;
v.y = 0; v.y = 0;
side[i] = sign(v.cross(dir).y); side[i] = sign(v.cross(dir).y);
} }
@@ -1149,32 +1135,42 @@ struct Lara : Character {
// check occlusion for tracking targets // check occlusion for tracking targets
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
if (arms[i].tracking > -1) { if (arms[i].tracking) {
TR::Entity &e = level->entities[arms[i].tracking]; Controller *enemy = (Controller*)arms[i].tracking;
Controller *enemy = (Controller*)e.controller;
Box box = enemy->getBoundingBox(); Box box = enemy->getBoundingBox();
vec3 to = box.center(); vec3 to = box.center();
to.y = box.min.y + (box.max.y - box.min.y) / 3.0f; to.y = box.min.y + (box.max.y - box.min.y) / 3.0f;
vec3 from = pos - vec3(0, 650, 0); vec3 from = pos - vec3(0, 650, 0);
arms[i].target = checkOcclusion(from, to, (to - from).length()) ? arms[i].tracking : -1; arms[i].target = checkOcclusion(from, to, (to - from).length()) ? arms[i].tracking : NULL;
} }
if (count == 1) if (count == 1)
arms[1].target = -1; arms[1].target = NULL;
else if (arms[0].target == -1 && arms[1].target != -1) else if (!arms[0].target && arms[1].target)
arms[0].target = arms[1].target; arms[0].target = arms[1].target;
else if (arms[1].target == -1 && arms[0].target != -1) else if (!arms[1].target && arms[0].target)
arms[1].target = arms[0].target; arms[1].target = arms[0].target;
} }
if (arms[0].target && arms[1].target && arms[0].target != arms[1].target) {
viewTarget = NULL; //arms[0].target;
} else if (arms[0].target)
viewTarget = arms[0].target;
else if (arms[1].target)
viewTarget = arms[1].target;
else if (arms[0].tracking)
viewTarget = arms[0].tracking;
else if (arms[1].tracking)
viewTarget = arms[1].tracking;
} }
void getTargets(int &target1, int &target2) { void getTargets(Controller *&target1, Controller *&target2) {
vec3 dir = getDir().normal(); vec3 dir = getDir().normal();
float dist[2] = { TARGET_MAX_DIST, TARGET_MAX_DIST }; float dist[2] = { TARGET_MAX_DIST, TARGET_MAX_DIST };
target1 = target2 = -1; target1 = target2 = NULL;
vec3 from = pos - vec3(0, 650, 0); vec3 from = pos - vec3(0, 650, 0);
@@ -1199,15 +1195,15 @@ struct Lara : Character {
if (d < dist[0]) { if (d < dist[0]) {
target2 = target1; target2 = target1;
dist[1] = dist[0]; dist[1] = dist[0];
target1 = i; target1 = enemy;
dist[0] = d; dist[0] = d;
} else if (d < dist[1]) { } else if (d < dist[1]) {
target2 = i; target2 = enemy;
dist[1] = d; dist[1] = d;
} }
} }
if (target2 == -1 || dist[1] > dist[0] * 4) if (!target2 || dist[1] > dist[0] * 4)
target2 = target1; target2 = target1;
} }
@@ -1217,12 +1213,9 @@ struct Lara : Character {
return ((d - from).length() > (dist - 512.0f)); return ((d - from).length() > (dist - 512.0f));
} }
bool checkHit(int target, const vec3 &from, const vec3 &to, vec3 &point) { bool checkHit(Controller *target, const vec3 &from, const vec3 &to, vec3 &point) {
TR::Entity &e = level->entities[target]; Box box = target->getBoundingBoxLocal();
Controller *controller = (Controller*)e.controller; mat4 m = target->getMatrix();
Box box = controller->getBoundingBoxLocal();
mat4 m = controller->getMatrix();
float t; float t;
vec3 v = to - from; vec3 v = to - from;
@@ -1231,7 +1224,7 @@ struct Lara : Character {
v = v.normal(); v = v.normal();
Sphere spheres[34]; Sphere spheres[34];
int count; int count;
controller->getSpheres(spheres, count); target->getSpheres(spheres, count);
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
if (spheres[i].intersect(from, v, t)) { if (spheres[i].intersect(from, v, t)) {
point = from + v * t; point = from + v * t;
@@ -1671,16 +1664,6 @@ struct Lara : Character {
level->isFlipped = !level->isFlipped; level->isFlipped = !level->isFlipped;
} }
vec3 getViewPoint() {
vec3 offset = chestOffset = animation.getJoints(getMatrix(), 7).pos;
if (stand != STAND_UNDERWATER)
offset.y -= 256.0f;
if (!emptyHands())
offset.y -= 256.0f;
return offset;
}
virtual Stand getStand() { virtual Stand getStand() {
if (dozy) return STAND_UNDERWATER; if (dozy) return STAND_UNDERWATER;
@@ -1694,7 +1677,7 @@ struct Lara : Character {
return STAND_AIR; return STAND_AIR;
} }
if (state == STATE_HANDSTAND || state == STATE_HANG_UP) if (state == STATE_HANDSTAND || (state == STATE_HANG_UP && animation.index != ANIM_CLIMB_JUMP))
return STAND_HANG; return STAND_HANG;
if (stand == STAND_ONWATER && state != STATE_STOP) { if (stand == STAND_ONWATER && state != STATE_STOP) {
@@ -1788,14 +1771,14 @@ struct Lara : Character {
} }
} }
if (state == STATE_FORWARD_JUMP) { if (state == STATE_FORWARD_JUMP || state == STATE_FALL_BACK) {
if (emptyHands()) { if (emptyHands()) {
if (input & ACTION) return STATE_REACH; if (input & ACTION) return STATE_REACH;
if ((input & (JUMP | FORTH | WALK)) == (JUMP | FORTH | WALK)) return STATE_SWAN_DIVE; if ((input & (JUMP | FORTH | WALK)) == (JUMP | FORTH | WALK)) return STATE_SWAN_DIVE;
} }
} else } else
if (state != STATE_FALL && state != STATE_FALL_BACK && state != STATE_SWAN_DIVE && state != STATE_FAST_DIVE && state != STATE_REACH && state != STATE_UP_JUMP && state != STATE_BACK_JUMP && state != STATE_LEFT_JUMP && state != STATE_RIGHT_JUMP) if (state != STATE_FALL && state != STATE_FALL_BACK && state != STATE_SWAN_DIVE && state != STATE_FAST_DIVE && state != STATE_REACH && state != STATE_UP_JUMP && state != STATE_BACK_JUMP && state != STATE_LEFT_JUMP && state != STATE_RIGHT_JUMP)
return animation.setAnim( (state == STATE_FAST_BACK || state == STATE_SLIDE_BACK || state == STATE_ROLL_2) ? ANIM_FALL_BACK : ANIM_FALL_FORTH); return animation.setAnim(ANIM_FALL_FORTH);// (state == STATE_FAST_BACK || state == STATE_SLIDE_BACK || state == STATE_ROLL_2) ? ANIM_FALL_BACK : ANIM_FALL_FORTH);
if (state == STATE_SWAN_DIVE) if (state == STATE_SWAN_DIVE)
return STATE_FAST_DIVE; return STATE_FAST_DIVE;
@@ -2535,7 +2518,7 @@ struct Lara : Character {
// hit the wall // hit the wall
switch (stand) { switch (stand) {
case STAND_AIR : case STAND_AIR :
if (state == STATE_UP_JUMP || state == STATE_REACH) if (state == STATE_UP_JUMP || state == STATE_REACH || state == STATE_FALL_BACK)
velocity.x = velocity.z = 0.0f; velocity.x = velocity.z = 0.0f;
if (velocity.x != 0.0f || velocity.z != 0.0f) { if (velocity.x != 0.0f || velocity.z != 0.0f) {

View File

@@ -811,6 +811,10 @@ struct Level : IGame {
c->update(); c->update();
c = next; c = next;
} }
if (camera->state != Camera::STATE_STATIC)
camera->state = lara->emptyHands() ? Camera::STATE_FOLLOW : Camera::STATE_COMBAT;
camera->update(); camera->update();
if (waterCache) if (waterCache)