SA-MP/saco/game/entity.cpp

677 lines
15 KiB
C++

#include <windows.h>
#include <math.h>
#include <stdio.h>
#include "../main.h"
#include "util.h"
#include "entity.h"
extern CGame *pGame;
extern CNetGame *pNetGame;
extern CChatWindow *pChatWindow;
//-----------------------------------------------------------
void CEntity::GetMatrix(PMATRIX4X4 Matrix)
{
if (!m_pEntity || !m_pEntity->mat) return;
Matrix->right.X = m_pEntity->mat->right.X;
Matrix->right.Y = m_pEntity->mat->right.Y;
Matrix->right.Z = m_pEntity->mat->right.Z;
Matrix->up.X = m_pEntity->mat->up.X;
Matrix->up.Y = m_pEntity->mat->up.Y;
Matrix->up.Z = m_pEntity->mat->up.Z;
Matrix->at.X = m_pEntity->mat->at.X;
Matrix->at.Y = m_pEntity->mat->at.Y;
Matrix->at.Z = m_pEntity->mat->at.Z;
Matrix->pos.X = m_pEntity->mat->pos.X;
Matrix->pos.Y = m_pEntity->mat->pos.Y;
Matrix->pos.Z = m_pEntity->mat->pos.Z;
}
//-----------------------------------------------------------
void CEntity::SetMatrix(MATRIX4X4 Matrix)
{
if (!m_pEntity || !m_pEntity->mat) return;
m_pEntity->mat->right.X = Matrix.right.X;
m_pEntity->mat->right.Y = Matrix.right.Y;
m_pEntity->mat->right.Z = Matrix.right.Z;
m_pEntity->mat->up.X = Matrix.up.X;
m_pEntity->mat->up.Y = Matrix.up.Y;
m_pEntity->mat->up.Z = Matrix.up.Z;
m_pEntity->mat->at.X = Matrix.at.X;
m_pEntity->mat->at.Y = Matrix.at.Y;
m_pEntity->mat->at.Z = Matrix.at.Z;
m_pEntity->mat->pos.X = Matrix.pos.X;
m_pEntity->mat->pos.Y = Matrix.pos.Y;
m_pEntity->mat->pos.Z = Matrix.pos.Z;
}
//-----------------------------------------------------------
void CEntity::FUNC_1009EC80()
{
if(!m_pEntity || m_pEntity->vtable == 0x863C40) return;
DWORD dwRenderWare = (DWORD)m_pEntity->pdwRenderWare;
DWORD dwMatrix = (DWORD)m_pEntity->mat;
DWORD dwEntity = (DWORD)m_pEntity;
if(dwEntity && dwRenderWare && dwMatrix)
{
_asm mov edx, dwRenderWare
_asm mov eax, [edx+4]
_asm add eax, 16
_asm push eax
_asm mov ecx, dwMatrix
_asm mov edx, 0x59AD70
_asm call edx
_asm mov ecx, dwEntity
_asm mov edx, 0x532B00
_asm call edx
}
}
//-----------------------------------------------------------
void CEntity::GetMoveSpeedVector(PVECTOR Vector)
{
Vector->X = m_pEntity->vecMoveSpeed.X;
Vector->Y = m_pEntity->vecMoveSpeed.Y;
Vector->Z = m_pEntity->vecMoveSpeed.Z;
}
//-----------------------------------------------------------
void CEntity::SetMoveSpeedVector(VECTOR Vector)
{
m_pEntity->vecMoveSpeed.X = Vector.X;
m_pEntity->vecMoveSpeed.Y = Vector.Y;
m_pEntity->vecMoveSpeed.Z = Vector.Z;
}
//-----------------------------------------------------------
void CEntity::FUNC_1009ED40(float fX, float fY, float fZ)
{
int x=4;
while(x) {
field_4[x-1].X = field_4[x].X;
field_4[x-1].Y = field_4[x].Y;
field_4[x-1].Z = field_4[x].Z;
x--;
}
field_4[4].X = fX;
field_4[4].Y = fY;
field_4[4].Z = fZ;
m_pEntity->vecMoveSpeed.X =
(field_4[0].X + field_4[1].X + field_4[2].X + field_4[3].X + field_4[4].X) * 0.2f;
m_pEntity->vecMoveSpeed.Y =
(field_4[0].Y + field_4[1].Y + field_4[2].Y + field_4[3].Y + field_4[4].Y) * 0.2f;
m_pEntity->vecMoveSpeed.Z =
(field_4[0].Z + field_4[1].Z + field_4[2].Z + field_4[3].Z + field_4[4].Z) * 0.2f;
}
//-----------------------------------------------------------
void CEntity::GetTurnSpeedVector(PVECTOR Vector)
{
Vector->X = m_pEntity->vecTurnSpeed.X;
Vector->Y = m_pEntity->vecTurnSpeed.Y;
Vector->Z = m_pEntity->vecTurnSpeed.Z;
}
//-----------------------------------------------------------
void CEntity::SetTurnSpeedVector(VECTOR Vector)
{
m_pEntity->vecTurnSpeed.X = Vector.X;
m_pEntity->vecTurnSpeed.Y = Vector.Y;
m_pEntity->vecTurnSpeed.Z = Vector.Z;
}
//-----------------------------------------------------------
void CEntity::ApplyTurnSpeed()
{
DWORD dwEnt = (DWORD)m_pEntity;
if(!dwEnt) return;
_asm mov ecx, dwEnt
_asm mov eax, 0x542E20
_asm call eax
}
//-----------------------------------------------------------
float CEntity::GetDistanceFromCentreOfMassToBaseOfModel()
{
DWORD dwEnt = (DWORD)m_pEntity;
float fResult = 0.0f;
if(!dwEnt) return 0.0f;
_asm mov ecx, dwEnt
_asm mov edx, 0x536BE0
_asm call edx
_asm mov fResult, eax
return fResult;
}
//-----------------------------------------------------------
void CEntity::GetBoundCentre(PVECTOR Vector)
{
DWORD dwEnt = (DWORD)m_pEntity;
if(!dwEnt) return;
_asm push Vector
_asm mov ecx, dwEnt
_asm mov edx, 0x534250
_asm call edx
}
//-----------------------------------------------------------
void CEntity::GetBoundRect(PFRECT Rect)
{
DWORD dwEnt = (DWORD)m_pEntity;
if(!dwEnt) return;
_asm push Rect
_asm mov ecx, dwEnt
_asm mov edx, 0x534120
_asm call edx
}
//-----------------------------------------------------------
UINT CEntity::GetModelIndex()
{
return m_pEntity->nModelIndex;
}
//-----------------------------------------------------------
void CEntity::TeleportTo(float x, float y, float z)
{
DWORD dwThisEntity = (DWORD)m_pEntity;
if(dwThisEntity && m_pEntity->vtable != 0x863C40) {
if( GetModelIndex() != TRAIN_PASSENGER_LOCO &&
GetModelIndex() != TRAIN_FREIGHT_LOCO &&
GetModelIndex() != TRAIN_TRAM) {
_asm mov ecx, dwThisEntity
_asm mov edx, [ecx] ; vtbl
_asm push 0
_asm push z
_asm push y
_asm push x
_asm call dword ptr [edx+56] ; method 14
} else {
ScriptCommand(&put_train_at,m_dwGTAId,x,y,z);
}
}
}
//-----------------------------------------------------------
float CEntity::GetDistanceFromLocalPlayerPed()
{
MATRIX4X4 matFromPlayer;
MATRIX4X4 matThis;
float fSX,fSY,fSZ;
CPlayerPed *pLocalPlayerPed = pGame->FindPlayerPed();
CLocalPlayer *pLocalPlayer=NULL;
if(!pLocalPlayerPed) return 10000.0f;
GetMatrix(&matThis);
if(pNetGame) {
pLocalPlayer = pNetGame->GetPlayerPool()->GetLocalPlayer();
if(pLocalPlayer && (pLocalPlayer->IsSpectating() || pLocalPlayer->IsInRCMode())) {
pGame->GetCamera()->GetMatrix(&matFromPlayer);
} else {
pLocalPlayerPed->GetMatrix(&matFromPlayer);
}
} else {
pLocalPlayerPed->GetMatrix(&matFromPlayer);
}
fSX = (matThis.pos.X - matFromPlayer.pos.X) * (matThis.pos.X - matFromPlayer.pos.X);
fSY = (matThis.pos.Y - matFromPlayer.pos.Y) * (matThis.pos.Y - matFromPlayer.pos.Y);
fSZ = (matThis.pos.Z - matFromPlayer.pos.Z) * (matThis.pos.Z - matFromPlayer.pos.Z);
return (float)sqrt(fSX + fSY + fSZ);
}
//-----------------------------------------------------------
float CEntity::GetDistanceFromCamera()
{
if(!m_pEntity || m_pEntity->vtable == 0x863C40) return 100000.0f;
MATRIX4X4 matThis;
float fSX,fSY,fSZ;
GetMatrix(&matThis);
fSX = (matThis.pos.X - *(float*)0xB6F9CC) * (matThis.pos.X - *(float*)0xB6F9CC);
fSY = (matThis.pos.Y - *(float*)0xB6F9D0) * (matThis.pos.Y - *(float*)0xB6F9D0);
fSZ = (matThis.pos.Z - *(float*)0xB6F9D4) * (matThis.pos.Z - *(float*)0xB6F9D4);
return (float)sqrt(fSX + fSY + fSZ);
}
//-----------------------------------------------------------
float CEntity::Get2DDistanceFromLocalPlayerPed()
{
MATRIX4X4 matFromPlayer;
MATRIX4X4 matThis;
float fSX,fSY,fSZ;
CPlayerPed *pLocalPlayerPed = pGame->FindPlayerPed();
CLocalPlayer *pLocalPlayer=NULL;
if(!pLocalPlayerPed) return 10000.0f;
GetMatrix(&matThis);
if(pNetGame) {
pLocalPlayer = pNetGame->GetPlayerPool()->GetLocalPlayer();
if(pLocalPlayer && (pLocalPlayer->IsSpectating() || pLocalPlayer->IsInRCMode())) {
pGame->GetCamera()->GetMatrix(&matFromPlayer);
} else {
pLocalPlayerPed->GetMatrix(&matFromPlayer);
}
} else {
pLocalPlayerPed->GetMatrix(&matFromPlayer);
}
fSX = (matThis.pos.X - matFromPlayer.pos.X) * (matThis.pos.X - matFromPlayer.pos.X);
fSY = (matThis.pos.Y - matFromPlayer.pos.Y) * (matThis.pos.Y - matFromPlayer.pos.Y);
return (float)sqrt(fSX + fSY);
}
//-----------------------------------------------------------
float CEntity::GetDistanceFromPoint(float X, float Y, float Z)
{
MATRIX4X4 matThis;
float fSX,fSY,fSZ;
GetMatrix(&matThis);
fSX = (matThis.pos.X - X) * (matThis.pos.X - X);
fSY = (matThis.pos.Y - Y) * (matThis.pos.Y - Y);
fSZ = (matThis.pos.Z - Z) * (matThis.pos.Z - Z);
return (float)sqrt(fSX + fSY + fSZ);
}
//-----------------------------------------------------------
void CEntity::Add()
{
// Check for CPlaceable messup
if(!m_pEntity || m_pEntity->vtable == 0x863C40)
{
#ifdef _DEBUG
OutputDebugString("CEntity::Add - m_pEntity == NULL or CPlaceable");
#endif
return;
}
if(!m_pEntity->dwUnkModelRel) {
// Make sure the move/turn speed is reset
VECTOR vec = {0.0f,0.0f,0.0f};
SetMoveSpeedVector(vec);
SetTurnSpeedVector(vec);
WorldAddEntity((PDWORD)m_pEntity);
MATRIX4X4 mat;
GetMatrix(&mat);
TeleportTo(mat.pos.X,mat.pos.Y,mat.pos.Z);
#ifdef _DEBUG
if (!IsAdded())
{
OutputDebugString("CEntity::Add failed...");
}
#endif
}
}
//-----------------------------------------------------------
BOOL CEntity::IsAdded()
{
// Check for CPlaceable messup
if(m_pEntity) {
if (m_pEntity->vtable == 0x863C40)
return FALSE;
if(m_pEntity->dwUnkModelRel)
return TRUE;
}
return FALSE;
}
//-----------------------------------------------------------
void CEntity::Remove()
{
// Check for CPlaceable messup
if(!m_pEntity || m_pEntity->vtable == 0x863C40)
{
#ifdef _DEBUG
OutputDebugString("CEntity::Remove - m_pEntity == NULL or CPlaceable");
#endif
return;
}
if(m_pEntity->dwUnkModelRel) {
WorldRemoveEntity((PDWORD)m_pEntity);
#ifdef _DEBUG
if (IsAdded())
{
OutputDebugString("CEntity::Remove failed...");
}
#endif
}
}
//-----------------------------------------------------------
BOOL CEntity::EnforceWorldBoundries(float fPX, float fZX, float fPY, float fNY)
{
MATRIX4X4 matWorld;
VECTOR vecMoveSpeed;
if(!m_pEntity) return FALSE;
GetMatrix(&matWorld);
GetMoveSpeedVector(&vecMoveSpeed);
if(matWorld.pos.X > fPX)
{
if(vecMoveSpeed.X != 0.0f) {
vecMoveSpeed.X = -0.2f;
vecMoveSpeed.Z = 0.1f;
}
SetMoveSpeedVector(vecMoveSpeed);
matWorld.pos.Z += 0.04f;
SetMatrix(matWorld);
return TRUE;
}
else if(matWorld.pos.X < fZX)
{
if(vecMoveSpeed.X != 0.0f) {
vecMoveSpeed.X = 0.2f;
vecMoveSpeed.Z = 0.1f;
}
SetMoveSpeedVector(vecMoveSpeed);
matWorld.pos.Z += 0.04f;
SetMatrix(matWorld);
return TRUE;
}
else if(matWorld.pos.Y > fPY)
{
if(vecMoveSpeed.Y != 0.0f) {
vecMoveSpeed.Y = -0.2f;
vecMoveSpeed.Z = 0.1f;
}
SetMoveSpeedVector(vecMoveSpeed);
matWorld.pos.Z += 0.04f;
SetMatrix(matWorld);
return TRUE;
}
else if(matWorld.pos.Y < fNY)
{
if(vecMoveSpeed.Y != 0.0f) {
vecMoveSpeed.Y = 0.2f;
vecMoveSpeed.Z = 0.1f;
}
SetMoveSpeedVector(vecMoveSpeed);
matWorld.pos.Z += 0.04f;
SetMatrix(matWorld);
return TRUE;
}
return FALSE;
}
//-----------------------------------------------------------
BOOL CEntity::HasExceededWorldBoundries(float fPX, float fZX, float fPY, float fNY)
{
MATRIX4X4 matWorld;
if(!m_pEntity) return FALSE;
GetMatrix(&matWorld);
if(matWorld.pos.X > fPX) {
return TRUE;
}
else if(matWorld.pos.X < fZX) {
return TRUE;
}
else if(matWorld.pos.Y > fPY) {
return TRUE;
}
else if(matWorld.pos.Y < fNY) {
return TRUE;
}
return FALSE;
}
//-----------------------------------------------------------
void CEntity::SetCollisionChecking(int iCheck)
{
if(!m_pEntity) return;
if(m_pEntity->vtable == 0x863C40) return;
if(iCheck) {
m_pEntity->dwProcessingFlags |= 1;
} else {
m_pEntity->dwProcessingFlags &= 0xFFFFFFFE;
}
}
//-----------------------------------------------------------
BOOL CEntity::IsCollisionCheckingEnabled()
{
if(m_pEntity && m_pEntity->vtable != 0x863C40)
{
return (BYTE)(m_pEntity->dwProcessingFlags & 1);
}
return TRUE;
}
//-----------------------------------------------------------
void CEntity::SetGravityProcessing(int iState)
{
if(!m_pEntity) return;
if(m_pEntity->vtable == 0x863C40) return;
if(iState) {
m_pEntity->dwProcessingFlags &= 0x7FFFFFFD;
} else {
m_pEntity->dwProcessingFlags |= 0x80000002;
}
}
//-----------------------------------------------------------
void CEntity::SetWaitingForCollision(int iState)
{
if(!m_pEntity) return;
if(m_pEntity->vtable == 0x863C40) return;
if(iState) {
m_pEntity->dwProcessingFlags |= 0x40000;
} else {
m_pEntity->dwProcessingFlags &= 0xFFFBFFFF;
Add();
}
}
//-----------------------------------------------------------
void CEntity::DisableStreaming()
{
if(!m_pEntity) return;
if(m_pEntity->vtable == 0x863C40) return;
m_pEntity->dwProcessingFlags |= 0x80400;
}
//-----------------------------------------------------------
void CEntity::EnableTunnelTransition()
{
if(!m_pEntity) return;
if(m_pEntity->vtable == 0x863C40) return;
m_pEntity->dwProcessingFlags |= 0x80000000;
}
//-----------------------------------------------------------
void CEntity::SetApplySpeed(int iState)
{
if(!m_pEntity) return;
if(m_pEntity->vtable == 0x863C40) return;
DWORD dwEnt = (DWORD)m_pEntity;
if(!iState) {
_asm mov edx, dwEnt
_asm mov eax, [edx+0x40]
_asm or ah, 0x20
_asm mov [edx+0x40], eax
} else {
_asm mov edx, dwEnt
_asm mov eax, [edx+0x40]
_asm and ah, 0xDF
_asm mov [edx+0x40], eax
}
}
//-----------------------------------------------------------
void CEntity::MakeNonCollidable()
{
if(m_pEntity) {
m_pEntity->dwPhysFlags &= 0xFFFFFFF7;
}
}
//-----------------------------------------------------------
void CEntity::SetClumpAlpha(int iAlpha)
{
if(!m_pEntity || !m_pEntity->pdwRenderWare || m_pEntity->vtable == 0x863C40)
return;
DWORD dwEntity = (DWORD)m_pEntity;
_asm mov eax, dwEntity
_asm mov edx, [eax+24]
_asm push iAlpha
_asm push edx
_asm mov eax, 0x732B00
_asm call eax
_asm pop edx
_asm pop edx
}
//-----------------------------------------------------------
DWORD CEntity::GetWorldBoundRadius()
{
if(m_pEntity && m_pEntity->pdwRenderWare && m_pEntity->vtable != 0x863C40)
{
return m_pEntity->pdwRenderWare[14];
}
return 0;
}
//-----------------------------------------------------------
void CEntity::SetEulerAngles(float fX, float fY, float fZ)
{
fX *= (PI/180.0f);
fY *= (PI/180.0f);
fZ *= (PI/180.0f);
float fCX = cos(fX);
float fSX = sin(fX);
float fCY = cos(fY);
float fSY = sin(fY);
float fCZ = cos(fZ);
float fSZ = sin(fZ);
float fSS = fSZ * fSX;
float fCS = fCZ * fSX;
m_pEntity->mat->right.X = fCZ * fCY - fSS * fSY;
m_pEntity->mat->right.Y = fCS * fSY + fSZ * fCY;
m_pEntity->mat->right.Z = -(fSY * fCX);
m_pEntity->mat->up.X = -(fSZ * fCX);
m_pEntity->mat->up.Y = fCZ * fCX;
m_pEntity->mat->up.Z = fSX;
m_pEntity->mat->at.X = fSS * fCY + fCZ * fSY;
m_pEntity->mat->at.Y = fSZ * fSY - fCS * fCY;
m_pEntity->mat->at.Z = fCY * fCX;
}
//-----------------------------------------------------------
//-----------------------------------------------------------
BOOL CEntity::IsStationary()
{
if (!IsAdded()) return FALSE; // movespeed vectors are invalid if its not added
if( m_pEntity->vecMoveSpeed.X == 0.0f &&
m_pEntity->vecMoveSpeed.Y == 0.0f &&
m_pEntity->vecMoveSpeed.Z == 0.0f )
{
return TRUE;
}
return FALSE;
}
//-----------------------------------------------------------