710 lines
18 KiB
C++
710 lines
18 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "twine/scene/buggy.h"
|
|
#include "twine/audio/sound.h"
|
|
#include "twine/scene/actor.h"
|
|
#include "twine/scene/animations.h"
|
|
#include "twine/scene/collision.h"
|
|
#include "twine/scene/movements.h"
|
|
#include "twine/scene/scene.h"
|
|
#include "twine/shared.h"
|
|
#include "twine/twine.h"
|
|
|
|
#define MAX_SAMPLE_PITCH 11000
|
|
#define MIN_SAMPLE_PITCH2 5000
|
|
#define MAX_SAMPLE_PITCH2 8500
|
|
#define MAX_SPEED 3800
|
|
#define TEMPO_GEAR 1200 // speed change
|
|
#define SAMPLE_BUGGY 109
|
|
|
|
namespace TwinE {
|
|
|
|
void Buggy::initBuggy(uint8 numobj, uint32 flaginit) {
|
|
S_BUGGY *ptb = &ListBuggy[0];
|
|
ActorStruct *ptrobj = _engine->_scene->getActor(numobj);
|
|
|
|
// So that the objects follow their tracks without being interrupted
|
|
// by the buggy (too bad, it will be pushed)
|
|
ptrobj->_flags.bCanBePushed = true;
|
|
ptrobj->_flags.bCanDrown = true;
|
|
|
|
if (flaginit == 2 // we force the repositioning of the buggy
|
|
|| (flaginit && !NumBuggy)) // first initialization
|
|
// because the empty buggy cannot be Twinsen
|
|
{
|
|
ptb->Cube = _engine->_scene->_numCube; // Port-Ludo (Desert)
|
|
|
|
ptb->X = ptrobj->_posObj.x;
|
|
ptb->Y = ptrobj->_posObj.y;
|
|
ptb->Z = ptrobj->_posObj.z;
|
|
|
|
ptb->Beta = ptrobj->_beta;
|
|
|
|
_engine->_actor->initBody(BodyType::btNormal, numobj);
|
|
|
|
NumBuggy = (uint8)(numobj | BUGGY_PRESENT);
|
|
} else if (NumBuggy) {
|
|
if (_engine->_scene->getActor(OWN_ACTOR_SCENE_INDEX)->_move != ControlMode::kBuggyManual && _engine->_scene->getActor(OWN_ACTOR_SCENE_INDEX)->_move != ControlMode::kBuggy) {
|
|
int32 x, y;
|
|
|
|
if (_engine->_scene->_numCube == ptb->Cube) {
|
|
ptrobj->_posObj.x = ptb->X;
|
|
ptrobj->_posObj.y = ptb->Y;
|
|
ptrobj->_posObj.z = ptb->Z;
|
|
|
|
ptrobj->_beta = ptb->Beta;
|
|
|
|
_engine->_actor->initBody(BodyType::btNormal, numobj);
|
|
} else if (_engine->_scene->loadSceneCubeXY(ptb->Cube, &x, &y)) {
|
|
x -= _engine->_scene->_currentCubeX;
|
|
y -= _engine->_scene->_currentCubeY;
|
|
|
|
ptrobj->_posObj.x = ptb->X + x * 32768;
|
|
ptrobj->_posObj.y = ptb->Y;
|
|
ptrobj->_posObj.z = ptb->Z + y * 32768;
|
|
|
|
ptrobj->_beta = ptb->Beta;
|
|
|
|
ptrobj->_flags.bNoShadow = 1;
|
|
ptrobj->_flags.bIsBackgrounded = 1;
|
|
ptrobj->_flags.bNoElectricShock = 1;
|
|
ptrobj->_flags.bHasZBuffer = 1;
|
|
|
|
_engine->_actor->initBody(BodyType::btNormal, numobj);
|
|
} else {
|
|
_engine->_actor->initBody(BodyType::btNone, numobj);
|
|
}
|
|
|
|
_engine->_movements->clearRealAngle(ptrobj);
|
|
} else {
|
|
_engine->_actor->initBody(BodyType::btNone, numobj);
|
|
}
|
|
|
|
NumBuggy = (uint8)(numobj | BUGGY_PRESENT);
|
|
} else {
|
|
_engine->_actor->initBody(BodyType::btNone, numobj);
|
|
}
|
|
}
|
|
|
|
void Buggy::resetBuggy() {
|
|
S_BUGGY *ptb = &ListBuggy[0];
|
|
|
|
NumBuggy = 0;
|
|
ptb->Cube = 0;
|
|
}
|
|
|
|
void Buggy::takeBuggy() {
|
|
int32 sample;
|
|
ActorStruct *ptrobj = _engine->_scene->getActor(OWN_ACTOR_SCENE_INDEX);
|
|
S_BUGGY *ptb = &ListBuggy[0];
|
|
|
|
ptb->SpeedRot = 1024;
|
|
// TODO: ptb->LastTimer = TimerRefHR;
|
|
|
|
// TODO: ObjectClear(&ptrobj);
|
|
|
|
// Shielding in case the Buggy moved (being pushed, for example).
|
|
ptb->X = _engine->_scene->getActor(NUM_BUGGY)->_posObj.x;
|
|
ptb->Y = _engine->_scene->getActor(NUM_BUGGY)->_posObj.y;
|
|
ptb->Z = _engine->_scene->getActor(NUM_BUGGY)->_posObj.z;
|
|
|
|
ptrobj->_posObj.x = ptb->X;
|
|
ptrobj->_posObj.y = ptb->Y;
|
|
ptrobj->_posObj.z = ptb->Z;
|
|
ptrobj->_beta = ptb->Beta;
|
|
_engine->_movements->clearRealAngle(ptrobj); // To avoid crushing the beta.
|
|
|
|
ptrobj->_workFlags.bMANUAL_INTER_FRAME = true;
|
|
ptrobj->_flags.bHasZBuffer = true;
|
|
|
|
// TODO: _engine->_actor->setBehaviour(HeroBehaviourType::kBUGGY);
|
|
|
|
// Switch Buggy Scenario to NoBody.
|
|
_engine->_actor->initBody(BodyType::btNone, NUM_BUGGY);
|
|
|
|
if (ptrobj->SampleAlways) {
|
|
_engine->_sound->stopSample(ptrobj->SampleAlways);
|
|
ptrobj->SampleAlways = 0;
|
|
}
|
|
|
|
sample = SAMPLE_BUGGY;
|
|
|
|
if (_engine->_sound->isSamplePlaying(sample)) {
|
|
_engine->_sound->stopSample(sample);
|
|
}
|
|
|
|
ptrobj->SampleVolume = 20;
|
|
|
|
// TODO: ParmSampleVolume = ptrobj->SampleVolume;
|
|
|
|
Gear = 0;
|
|
TimerGear = 0;
|
|
|
|
// TODO: ptrobj->SampleAlways = _engine->_sound->playSample(SAMPLE_BUGGY, 4096, 0, 0,
|
|
// ptrobj->_posObj.x, ptrobj->_posObj.y, ptrobj->_posObj.z);
|
|
}
|
|
|
|
#if 0
|
|
static void ObjectClear(T_OBJ *ptb3d) {
|
|
memset(ptb3d, 0, sizeof(T_OBJ));
|
|
ptb3d.OBJ_3D.Body, -1
|
|
ptb3d.OBJ_3D.NextBody, -1
|
|
ptb3d.OBJ_3D.Texture, -1
|
|
ptb3d.OBJ_3D.NextTexture, -1
|
|
ptb3d.OBJ_3D.Anim, -1
|
|
}
|
|
#endif
|
|
|
|
void Buggy::leaveBuggy(HeroBehaviourType behaviour) {
|
|
int32 sample;
|
|
ActorStruct *ptrobj = _engine->_scene->getActor(OWN_ACTOR_SCENE_INDEX);
|
|
S_BUGGY *ptb = &ListBuggy[0];
|
|
|
|
sample = SAMPLE_BUGGY;
|
|
|
|
if (_engine->_sound->isSamplePlaying(sample)) {
|
|
_engine->_sound->stopSample(sample);
|
|
ptrobj->SampleAlways = 0;
|
|
}
|
|
|
|
ptb->X = ptrobj->_posObj.x;
|
|
ptb->Y = ptrobj->_posObj.y;
|
|
ptb->Z = ptrobj->_posObj.z;
|
|
ptb->Beta = ptrobj->_beta;
|
|
ptb->Cube = _engine->_scene->_numCube;
|
|
|
|
// TODO: ObjectClear(ptrobj);
|
|
|
|
ptrobj->_workFlags.bMANUAL_INTER_FRAME = 0;
|
|
ptrobj->_flags.bHasZBuffer = 0;
|
|
|
|
_engine->_actor->initBody(BodyType::btTunic, OWN_ACTOR_SCENE_INDEX);
|
|
|
|
_engine->_actor->setBehaviour(behaviour);
|
|
|
|
// Restore scenario buggy.
|
|
|
|
ptrobj = _engine->_scene->getActor(NUM_BUGGY);
|
|
|
|
ptrobj->_posObj.x = ptb->X;
|
|
ptrobj->_posObj.y = ptb->Y;
|
|
ptrobj->_posObj.z = ptb->Z;
|
|
ptrobj->_beta = ptb->Beta;
|
|
|
|
ptrobj->_brickSound = _engine->_scene->getActor(OWN_ACTOR_SCENE_INDEX)->_brickSound;
|
|
|
|
_engine->_movements->clearRealAngle(ptrobj); // To avoid crushing the beta
|
|
|
|
_engine->_actor->initBody(BodyType::btNormal, NUM_BUGGY);
|
|
|
|
// Search for a free position for Twinsen nearby.
|
|
_engine->_actor->posObjectAroundAnother(NUM_BUGGY, OWN_ACTOR_SCENE_INDEX);
|
|
}
|
|
|
|
#if 0
|
|
|
|
struct T_HALF_POLY {
|
|
uint32 Bank : 4; // coul bank poly
|
|
uint32 TexFlag : 2; // flag texture 00 rien 01 triste 10 flat 11 gouraud
|
|
uint32 PolyFlag : 2; // flag poly 00 rien 01 flat 10 gouraud 11 dither
|
|
uint32 SampleStep : 4; // sample pas twinsen
|
|
uint32 CodeJeu : 4; // code jeu
|
|
uint32 Sens : 1; // sens diagonale
|
|
uint32 Col : 1;
|
|
uint32 Dummy : 1;
|
|
uint32 IndexTex : 13; // index texture 8192
|
|
}; // 1 long
|
|
|
|
struct T_HALF_TEX {
|
|
uint16 Tx0;
|
|
uint16 Ty0;
|
|
uint16 Tx1;
|
|
uint16 Ty1;
|
|
uint16 Tx2;
|
|
uint16 Ty2;
|
|
}; // 2 Longs
|
|
|
|
int32 CalculAltitudeObjet(int32 x, int32 z, int32 cj) {
|
|
int32 y0, y1, y2, y3;
|
|
int32 dx, dz;
|
|
int32 dz0, dz1;
|
|
|
|
dx = x >> 9; // div512
|
|
dz = z >> 9; // div512
|
|
|
|
if ((dx < 0) || (dx > 63))
|
|
return -1;
|
|
if ((dz < 0) || (dz > 63))
|
|
return -1;
|
|
|
|
x &= 511;
|
|
z &= 511;
|
|
|
|
dz0 = dz * 65;
|
|
dz1 = dz0 + 65;
|
|
|
|
//---------------------------------------------------------------
|
|
if (cj == -1) {
|
|
T_HALF_POLY *mappoly = &MapPolyGround[dz * 64 * 2 + dx * 2];
|
|
|
|
if (mappoly->Sens == 0) // poly séparé par ligne reliant point 0 et 2
|
|
{
|
|
if (x >= z) // poly de droite
|
|
{
|
|
mappoly++;
|
|
}
|
|
} else // poly séparé par ligne reliant point 1 et 3
|
|
{
|
|
if (511 - x <= z) // poly de droite
|
|
{
|
|
mappoly++;
|
|
}
|
|
}
|
|
|
|
cj = (uint8)mappoly->CodeJeu;
|
|
}
|
|
//--------------------------------------------------------------
|
|
|
|
y0 = MapSommetY[dz0 + dx];
|
|
y1 = MapSommetY[dz1 + dx];
|
|
y2 = MapSommetY[dz1 + (dx + 1)];
|
|
y3 = MapSommetY[dz0 + (dx + 1)];
|
|
|
|
if (cj == CJ_FOOT_WATER OR cj == CJ_WATER) {
|
|
uint8 *i = &MapIntensity[dz0 + dx];
|
|
|
|
y0 += (i[0] >> 4) * -200;
|
|
y1 += (i[65] >> 4) * -200;
|
|
y2 += (i[65 + 1] >> 4) * -200;
|
|
y3 += (i[1] >> 4) * -200;
|
|
}
|
|
if (MapPolyGround[dz * 64 * 2 + dx * 2].Sens == 0) // poly séparé par ligne reliant point 0 et 2
|
|
{
|
|
if (x < z) // poly de gauche
|
|
{
|
|
return (y0 + ((y1 - y0) * z + (y2 - y1) * x) / 512);
|
|
} else // poly de droite
|
|
{
|
|
return (y0 + ((y3 - y0) * x + (y2 - y3) * z) / 512);
|
|
}
|
|
} else // poly séparé par ligne reliant point 1 et 3
|
|
{
|
|
if (511 - x > z) // poly de gauche
|
|
{
|
|
return (y0 + ((y3 - y0) * x + (y1 - y0) * z) / 512);
|
|
} else // poly de droite
|
|
{
|
|
return (y1 + ((y2 - y1) * x + (y3 - y2) * (511 - z)) / 512);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void Buggy::doAnimBuggy(ActorStruct *ptrobj) {
|
|
#if 0
|
|
int32 x1, y1, z1, yw;
|
|
S_BUGGY *ptb = &ListBuggy[0];
|
|
T_OBJ_3D *ptb3d = &ptrobj->Obj;
|
|
|
|
// wheels rot
|
|
int32 c, d;
|
|
|
|
int32 x, y, z;
|
|
|
|
// Trick to avoid crushing the groups in AffOneObject().
|
|
ObjectSetInterFrame(ptb3d);
|
|
|
|
if (ptrobj->_workFlags.bIsFalling || ptrobj->_workFlags.bANIM_MASTER_GRAVITY) {
|
|
return;
|
|
}
|
|
|
|
LongRotate(0, ptb->SpeedInc * 1024, ptb3d->Beta);
|
|
ptrobj->_processActor.x = ptb3d->X + X0 / 1024;
|
|
ptrobj->_processActor.z = ptb3d->Z + Z0 / 1024;
|
|
|
|
// Ideal altitude
|
|
yw = CalculAltitudeObjet(ptrobj->_processActor.x, ptrobj->_processActor.z, -1); // Ground Y for XZ
|
|
|
|
// test altitude #2: Forbidden triangles
|
|
|
|
// Front left wheel direction
|
|
ptb3d->CurrentFrame[3].Beta = (int16)ptb->BetaWheel;
|
|
// Front right wheel direction
|
|
ptb3d->CurrentFrame[6].Beta = (int16)ptb->BetaWheel;
|
|
|
|
// Management of 4 separate wheels.
|
|
|
|
// front right wheel
|
|
|
|
LongRotate(-400, 400, ptb3d->Beta);
|
|
x = ptrobj->_processActor.x + X0;
|
|
z = ptrobj->_processActor.z + Z0;
|
|
y = yw;
|
|
|
|
if (x >= 0 && x < 32768 && z >= 0 && z < 32768) {
|
|
y += CalculAltitudeObjet(x, z, -1);
|
|
}
|
|
|
|
c = (260 * 31415) / 1000; // Circumference * 10
|
|
d = Distance3D(ptb->Wheel[0].X, ptb->Wheel[0].Y, ptb->Wheel[0].Z, x, y, z);
|
|
|
|
if (ptb->Speed >= 0) {
|
|
ptb->Wheel[0].Angle += (4096 * 10 * d) / c;
|
|
} else {
|
|
ptb->Wheel[0].Angle -= (4096 * 10 * d) / c;
|
|
}
|
|
|
|
ptb->Wheel[0].X = x;
|
|
ptb->Wheel[0].Y = y;
|
|
ptb->Wheel[0].Z = z;
|
|
|
|
// front left wheel
|
|
|
|
LongRotate(400, 400, ptb3d->Beta);
|
|
x = ptrobj->_processActor.x + X0;
|
|
z = ptrobj->_processActor.z + Z0;
|
|
y = yw;
|
|
|
|
if (x >= 0 && x < 32768 && z >= 0 && z < 32768) {
|
|
y += CalculAltitudeObjet(x, z, -1);
|
|
}
|
|
|
|
c = (260 * 31415) / 1000; // Circumference * 10
|
|
d = Distance3D(ptb->Wheel[1].X, ptb->Wheel[1].Y, ptb->Wheel[1].Z, x, y, z);
|
|
|
|
if (ptb->Speed >= 0) {
|
|
ptb->Wheel[1].Angle += (4096 * 10 * d) / c;
|
|
} else {
|
|
ptb->Wheel[1].Angle -= (4096 * 10 * d) / c;
|
|
}
|
|
|
|
ptb->Wheel[1].X = x;
|
|
ptb->Wheel[1].Y = y;
|
|
ptb->Wheel[1].Z = z;
|
|
|
|
// back left wheel
|
|
|
|
LongRotate(400, -350, ptb3d->Beta);
|
|
x = ptrobj->_processActor.x + X0;
|
|
z = ptrobj->_processActor.z + Z0;
|
|
y = yw;
|
|
|
|
if (x >= 0 && x < 32768 && z >= 0 && z < 32768) {
|
|
y += CalculAltitudeObjet(x, z, -1);
|
|
}
|
|
|
|
c = (360 * 31415) / 1000; // Circumference * 10
|
|
d = Distance3D(ptb->Wheel[2].X, ptb->Wheel[2].Y, ptb->Wheel[2].Z, x, y, z);
|
|
|
|
if (ptb->Speed >= 0) {
|
|
ptb->Wheel[2].Angle += (4096 * 10 * d) / c;
|
|
} else {
|
|
ptb->Wheel[2].Angle -= (4096 * 10 * d) / c;
|
|
}
|
|
|
|
ptb->Wheel[2].X = x;
|
|
ptb->Wheel[2].Y = y;
|
|
ptb->Wheel[2].Z = z;
|
|
|
|
// back right wheel
|
|
|
|
LongRotate(-400, -350, ptb3d->Beta);
|
|
x = ptrobj->_processActor.x + X0;
|
|
z = ptrobj->_processActor.z + Z0;
|
|
y = yw;
|
|
|
|
if (x >= 0 && x < 32768 && z >= 0 && z < 32768) {
|
|
y += CalculAltitudeObjet(x, z, -1);
|
|
}
|
|
|
|
c = (360 * 31415) / 1000; // Circumference * 10
|
|
d = Distance3D(ptb->Wheel[3].X, ptb->Wheel[3].Y, ptb->Wheel[3].Z, x, y, z);
|
|
|
|
if (ptb->Speed >= 0) {
|
|
ptb->Wheel[3].Angle += (4096 * 10 * d) / c;
|
|
} else {
|
|
ptb->Wheel[3].Angle -= (4096 * 10 * d) / c;
|
|
}
|
|
|
|
ptb->Wheel[3].X = x;
|
|
ptb->Wheel[3].Y = y;
|
|
ptb->Wheel[3].Z = z;
|
|
|
|
// front right wheel
|
|
ptb3d->CurrentFrame[4].Alpha = (int16)ptb->Wheel[1].Angle;
|
|
// front left wheel
|
|
ptb3d->CurrentFrame[7].Alpha = (int16)ptb->Wheel[0].Angle;
|
|
// back left wheel
|
|
ptb3d->CurrentFrame[11].Alpha = (int16)ptb->Wheel[2].Angle;
|
|
// back right wheel
|
|
ptb3d->CurrentFrame[9].Alpha = (int16)ptb->Wheel[3].Angle;
|
|
|
|
// Car inclination (pitch)
|
|
ptb3d->CurrentFrame[1].Type = 0;
|
|
|
|
LongRotate(0, 400, ptb3d->Beta);
|
|
x1 = X0;
|
|
z1 = Z0;
|
|
LongRotate(0, -400, ptb3d->Beta);
|
|
|
|
if (Nxw + x1 >= 0 && Nxw + x1 < 32768 && Nzw + z1 >= 0 && Nzw + z1 < 32768) {
|
|
y = CalculAltitudeObjet(Nxw + x1, Nzw + z1, -1);
|
|
} else {
|
|
y = yw;
|
|
}
|
|
|
|
if (Nxw + X0 >= 0 && Nxw + X0 < 32768 && Nzw + Z0 >= 0 && Nzw + Z0 < 32768) {
|
|
y1 = CalculAltitudeObjet(Nxw + X0, Nzw + Z0, -1);
|
|
} else {
|
|
y1 = yw;
|
|
}
|
|
|
|
ptb3d->CurrentFrame[1].Alpha = (int16)(1024 - GetAngle2D(0, y, 800, y1));
|
|
ptb->Alpha = ptb3d->CurrentFrame[1].Alpha;
|
|
|
|
// Car inclination (roll)
|
|
LongRotate(400, 0, ptb3d->Beta);
|
|
x1 = X0;
|
|
z1 = Z0;
|
|
LongRotate(-400, 0, ptb3d->Beta);
|
|
|
|
if (Nxw + X0 >= 0 && Nxw + X0 < 32768 && Nzw + Z0 >= 0 && Nzw + Z0 < 32768) {
|
|
y = CalculAltitudeObjet(Nxw + X0, Nzw + Z0, -1);
|
|
} else {
|
|
y = yw;
|
|
}
|
|
|
|
if (Nxw + x1 >= 0 && Nxw + x1 < 32768 && Nzw + z1 >= 0 && Nzw + z1 < 32768) {
|
|
y1 = CalculAltitudeObjet(Nxw + x1, Nzw + z1, -1);
|
|
} else {
|
|
y1 = yw;
|
|
}
|
|
|
|
ptb3d->CurrentFrame[1].Gamma = (int16)GetAngle2D(y, 0, y1, 800);
|
|
|
|
// Steering wheel
|
|
ptb3d->CurrentFrame[12].Gamma = (int16)-ptb->BetaWheel;
|
|
|
|
// Twinsen's head
|
|
ptb3d->CurrentFrame[14].Beta = (int16)ptb->BetaWheel;
|
|
#endif
|
|
}
|
|
|
|
void Buggy::moveBuggy(ActorStruct *ptrobj) {
|
|
#if 0
|
|
S_BUGGY *ptb = &ListBuggy[0];
|
|
T_OBJ_3D *ptb3d = &ptrobj->Obj;
|
|
int32 pitch = 0;
|
|
int32 flagattack = false;
|
|
|
|
int32 speedinc;
|
|
int32 rotlevel;
|
|
int32 timerhr, deltatimer;
|
|
|
|
timerhr = TimerRefHR;
|
|
deltatimer = timerhr - ptb->LastTimer;
|
|
|
|
if ((Input & I_THROW) && (PtrComportement->Flags & CF_WEAPON)) {
|
|
// Are we in mage?
|
|
if (TabInv[FLAG_TUNIQUE].IdObj3D == 0) {
|
|
_engine->_actor->initBody(BodyType::btTunicTir, OWN_ACTOR_SCENE_INDEX);
|
|
} else {
|
|
_engine->_actor->initBody(BodyType::btMageTir, OWN_ACTOR_SCENE_INDEX);
|
|
}
|
|
|
|
_engine->_animations->initAnim(AnimationTypes::kThrowBall, AnimType::kAnimationTypeRepeat, OWN_ACTOR_SCENE_INDEX);
|
|
|
|
/* control direction pendant Aiming */
|
|
if (!ptrobj->_workFlags.bIsRotationByAnim) {
|
|
ptb3d->Beta += GetDeltaMove(&ptrobj->BoundAngle.Move);
|
|
ptb3d->Beta &= 4095;
|
|
|
|
_engine->_movements->initRealAngleConst(ptrobj);
|
|
}
|
|
|
|
_engine->_movements->_lastJoyFlag = true;
|
|
flagattack = true;
|
|
} else {
|
|
if (LastInput & I_THROW) {
|
|
// We finished shooting with the buggy,
|
|
// we close the hood
|
|
_engine->_actor->initBody(BodyType::btTunic, OWN_ACTOR_SCENE_INDEX);
|
|
_engine->_animations->initAnim(AnimationTypes::kStanding, AnimType::kAnimationTypeRepeat, OWN_ACTOR_SCENE_INDEX);
|
|
}
|
|
}
|
|
|
|
if (!flagattack && !ptrobj->_workFlags.bIsFalling && !ptrobj->_workFlags.bANIM_MASTER_GRAVITY) {
|
|
_engine->_movements->clearRealAngle(ptrobj);
|
|
|
|
if (_engine->_movements->_lastJoyFlag && (((Input & I_JOY) != LastMyJoy) || ((Input & I_FIRE) != LastMyFire))) {
|
|
_engine->_animations->initAnim(AnimationTypes::kStanding, AnimType::kAnimationTypeRepeat, OWN_ACTOR_SCENE_INDEX);
|
|
Pushing = false;
|
|
}
|
|
|
|
_engine->_movements->_lastJoyFlag = false;
|
|
|
|
// Pushing contains the number of the object being pushed
|
|
// So 1000 is an impossible value used as an initialization flag
|
|
// no animation
|
|
if (Pushing == 1000) {
|
|
_engine->_animations->initAnim(AnimationTypes::kStanding, AnimType::kAnimationTypeRepeat, OWN_ACTOR_SCENE_INDEX);
|
|
Pushing = false;
|
|
}
|
|
|
|
if (Input & I_UP) {
|
|
if (Pushing) {
|
|
_engine->_animations->initAnim(AnimationTypes::kPush, ANIM_TEMPO, OWN_ACTOR_SCENE_INDEX);
|
|
_engine->_movements->_lastJoyFlag = true;
|
|
} else {
|
|
_engine->_animations->initAnim(AnimationTypes::kForward, AnimType::kAnimationTypeRepeat, OWN_ACTOR_SCENE_INDEX);
|
|
_engine->_movements->_lastJoyFlag = true;
|
|
}
|
|
} else if (Input & I_DOWN) {
|
|
_engine->_animations->initAnim(AnimationTypes::kBackward, AnimType::kAnimationTypeRepeat, OWN_ACTOR_SCENE_INDEX);
|
|
_engine->_movements->_lastJoyFlag = true;
|
|
}
|
|
}
|
|
|
|
if (!ptrobj->_workFlags.bIsFalling && !ptrobj->_workFlags.bANIM_MASTER_GRAVITY) {
|
|
// check speed command
|
|
if ((Input & I_UP) // accelerating
|
|
&& !flagattack) {
|
|
ptb->Speed += deltatimer * 4;
|
|
|
|
if (!TimerGear)
|
|
TimerGear = TimerRefHR + TEMPO_GEAR;
|
|
else {
|
|
if (Gear < 0)
|
|
Gear = 0;
|
|
|
|
if (TimerRefHR > TimerGear && Gear < 2) {
|
|
Gear++;
|
|
TimerGear = TimerRefHR + TEMPO_GEAR;
|
|
}
|
|
}
|
|
} else if ((Input & I_DOWN) // brake / reverse
|
|
&& !flagattack) {
|
|
ptb->Speed -= deltatimer * 12;
|
|
Gear = -1;
|
|
TimerGear = 0;
|
|
} else // slow down
|
|
{
|
|
if (ptb->Speed > 0) {
|
|
ptb->Speed -= deltatimer * 7;
|
|
if (ptb->Speed < 0) {
|
|
ptb->Speed = 0;
|
|
}
|
|
}
|
|
if (ptb->Speed < 0) {
|
|
ptb->Speed += deltatimer * 7;
|
|
if (ptb->Speed > 0) {
|
|
ptb->Speed = 0;
|
|
}
|
|
}
|
|
Gear = 0;
|
|
TimerGear = 0;
|
|
}
|
|
|
|
if (ptb->Speed < -2000)
|
|
ptb->Speed = -2000;
|
|
if (ptb->Speed > MAX_SPEED)
|
|
ptb->Speed = MAX_SPEED;
|
|
|
|
speedinc = ptb->Speed * deltatimer / 1000;
|
|
} else {
|
|
speedinc = 0;
|
|
}
|
|
|
|
// check dir
|
|
|
|
if (!flagattack) {
|
|
if (Input & I_RIGHT) {
|
|
ptb->BetaWheel = -300;
|
|
if (ptb->Speed) {
|
|
rotlevel = -ptb->SpeedRot * speedinc / ptb->Speed;
|
|
} else {
|
|
rotlevel = 0;
|
|
}
|
|
} else if (Input & I_LEFT) {
|
|
ptb->BetaWheel = 300;
|
|
if (ptb->Speed) {
|
|
rotlevel = ptb->SpeedRot * speedinc / ptb->Speed;
|
|
} else {
|
|
rotlevel = 0;
|
|
}
|
|
} else {
|
|
ptb->BetaWheel = 0;
|
|
rotlevel = 0;
|
|
}
|
|
|
|
if (ptrobj->_staticFlags.bSKATING) {
|
|
ptb->Speed = 3000;
|
|
speedinc = ptb->Speed * deltatimer / 1000;
|
|
} else {
|
|
if (ptb->Speed >= 0) {
|
|
ptb3d->Beta += rotlevel;
|
|
} else {
|
|
ptb3d->Beta -= rotlevel;
|
|
}
|
|
|
|
ptb3d->Beta = ClampAngle(ptb3d->Beta);
|
|
}
|
|
} else {
|
|
ptb->BetaWheel = 0;
|
|
}
|
|
|
|
LastMyJoy = Input & I_JOY;
|
|
LastMyFire = Input & I_FIRE;
|
|
LastInput = Input;
|
|
|
|
ptb->LastTimer = timerhr;
|
|
ptb->SpeedInc = speedinc;
|
|
|
|
if (ptrobj->SampleAlways && _engine->_sound->isSamplePlaying(ptrobj->SampleAlways)) {
|
|
int32 pitch;
|
|
|
|
switch (Gear) {
|
|
case -1:
|
|
pitch = boundRuleThree(3000, MAX_SAMPLE_PITCH2, MAX_SPEED, ABS(ptb->Speed));
|
|
break;
|
|
|
|
case 0:
|
|
pitch = boundRuleThree(3000, MAX_SAMPLE_PITCH, MAX_SPEED, ABS(ptb->Speed));
|
|
if (pitch >= MAX_SAMPLE_PITCH)
|
|
TimerGear = 1;
|
|
break;
|
|
|
|
case 1:
|
|
pitch = boundRuleThree(MAX_SAMPLE_PITCH2, MIN_SAMPLE_PITCH2, TEMPO_GEAR, TimerGear - TimerRefHR);
|
|
break;
|
|
|
|
default:
|
|
pitch = MAX_SAMPLE_PITCH2;
|
|
}
|
|
|
|
_engine->_sound->ChangePitchbendSample(ptrobj->SampleAlways, pitch);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
} // namespace TwinE
|