#include "common.h"
#include "Timer.h"
#include "ModelIndices.h"
#include "Streaming.h"
#include "CopPed.h"
#include "Population.h"
#include "RenderBuffer.h"
#include "Camera.h"
#include "Ropes.h"
CRope CRopes::aRopes[8];
RwImVertexIndex RopeIndices[64] = {
0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7,
7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15,
15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23,
23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31,
31, 32 // unused
};
void
CRope::Update(void)
{
int i;
float step = Pow(0.85f, CTimer::GetTimeStep());
if(!m_bWasRegistered && CTimer::GetTimeInMilliseconds() > m_updateTimer){
m_speed[0].z -= 0.0015f*CTimer::GetTimeStep();
m_pos[0] += m_speed[0]*CTimer::GetTimeStep();
}
for(i = 1; i < ARRAY_SIZE(m_pos); i++){
CVector prevPos = m_pos[i];
m_pos[i] += m_speed[i]*step*CTimer::GetTimeStep();
m_pos[i].z -= 0.05f*CTimer::GetTimeStep();
CVector dist = m_pos[i] - m_pos[i-1];
m_pos[i] = m_pos[i-1] + (0.625f/dist.Magnitude())*dist;
m_speed[i] = (m_pos[i] - prevPos)/CTimer::GetTimeStep();
}
if(!m_bWasRegistered && m_pos[0].z < 0.0f)
m_bActive = false;
m_bWasRegistered = false;
}
void
CRope::Render(void)
{
int i;
int numVerts = 0;
if(!TheCamera.IsSphereVisible(m_pos[16], 20.0f))
return;
for(i = 0; i < ARRAY_SIZE(m_pos); i++){
RwIm3DVertexSetRGBA(&TempBufferRenderVertices[i], 128, 128, 128, 100);
RwIm3DVertexSetPos(&TempBufferRenderVertices[i], m_pos[i].x, m_pos[i].y, m_pos[i].z);
}
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
if(RwIm3DTransform(TempBufferRenderVertices, ARRAY_SIZE(m_pos), nil, rwIM3D_VERTEXXYZ|rwIM3D_VERTEXRGBA)){
#ifdef FIX_BUGS
RwIm3DRenderIndexedPrimitive(rwPRIMTYPELINELIST, RopeIndices, 2*(ARRAY_SIZE(m_pos)-1));
#else
RwIm3DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, RopeIndices, 2*(ARRAY_SIZE(m_pos)-1));
#endif
RwIm3DEnd();
}
}
void
CRopes::Init(void)
{
int i;
for(i = 0; i < ARRAY_SIZE(aRopes); i++)
aRopes[i].m_bActive = false;
}
void
CRopes::Update(void)
{
int i;
for(i = 0; i < ARRAY_SIZE(aRopes); i++)
if(aRopes[i].m_bActive)
aRopes[i].Update();
}
void
CRopes::Render(void)
{
int i;
for(i = 0; i < ARRAY_SIZE(aRopes); i++)
if(aRopes[i].m_bActive)
aRopes[i].Render();
}
bool
CRopes::RegisterRope(uintptr id, CVector pos, bool setUpdateTimer)
{
int i, j;
for(i = 0; i < ARRAY_SIZE(aRopes); i++){
if(aRopes[i].m_bActive && aRopes[i].m_id == id){
aRopes[i].m_pos[0] = pos;
aRopes[i].m_speed[0] = CVector(0.0f, 0.0f, 0.0f);
aRopes[i].m_bWasRegistered = true;
return true;
}
}
for(i = 0; i < ARRAY_SIZE(aRopes); i++)
if(!aRopes[i].m_bActive){
aRopes[i].m_id = id;
aRopes[i].m_pos[0] = pos;
aRopes[i].m_speed[0] = CVector(0.0f, 0.0f, 0.0f);
aRopes[i].m_unk = false;
aRopes[i].m_bWasRegistered = true;
aRopes[i].m_updateTimer = setUpdateTimer ? CTimer::GetTimeInMilliseconds() + 20000 : 0;
for(j = 1; j < ARRAY_SIZE(aRopes[0].m_pos); j++){
if(j & 1)
aRopes[i].m_pos[j] = aRopes[i].m_pos[j-1] + CVector(0.0f, 0.0f, 0.625f);
else
aRopes[i].m_pos[j] = aRopes[i].m_pos[j-1] - CVector(0.0f, 0.0f, 0.625f);
aRopes[i].m_speed[j] = CVector(0.0f, 0.0f, 0.0f);
}
aRopes[i].m_bActive = true;
return true;
}
return false;
}
void
CRopes::SetSpeedOfTopNode(uintptr id, CVector speed)
{
int i;
for(i = 0; i < ARRAY_SIZE(aRopes); i++)
if(aRopes[i].m_bActive && aRopes[i].m_id == id){
aRopes[i].m_speed[0] = speed;
return;
}
}
bool
CRopes::FindCoorsAlongRope(uintptr id, float t, CVector *coors)
{
int i, j;
float f;
for(i = 0; i < ARRAY_SIZE(aRopes); i++)
if(aRopes[i].m_bActive && aRopes[i].m_id == id){
t = (ARRAY_SIZE(aRopes[0].m_pos)-1)*clamp(t, 0.0f, 0.999f);
j = t;
f = t - j;
*coors = (1.0f-f)*aRopes[i].m_pos[j] + f*aRopes[i].m_pos[j+1];
return true;
}
return false;
}
bool
CRopes::CreateRopeWithSwatComingDown(CVector pos)
{
static uint32 ropeId = 0;
if(!CStreaming::HasModelLoaded(MI_SWAT) || !RegisterRope(ropeId+100, pos, true))
return false;
CCopPed *swat = (CCopPed*)CPopulation::AddPed(PEDTYPE_COP, COP_HELI_SWAT, pos);
swat->bUsesCollision = false;
swat->m_pRopeEntity = (CEntity*)1;
swat->m_nRopeID = 100 + ropeId;
CAnimManager::BlendAnimation(swat->GetClump(), ASSOCGRP_STD, ANIM_STD_ABSEIL, 4.0f);
ropeId++;
return true;
}