251 lines
8.7 KiB
C++
251 lines
8.7 KiB
C++
|
|
// Rage headers
|
|
#include "script\wrapper.h"
|
|
#include "script\commands_shapetest.h"
|
|
#include "script\commands_water.h"
|
|
#include "physics\physics.h"
|
|
#include "physics\gtaArchetype.h"
|
|
// Game headers
|
|
#include "script\script_channel.h"
|
|
#include "script\script.h"
|
|
#include "renderer\water.h"
|
|
|
|
namespace water_commands
|
|
{
|
|
|
|
bool CommandGetWaterHeight(const scrVector & scrVecPos, float &fHeight)
|
|
{
|
|
Vector3 normal;
|
|
Vector3 vPos = Vector3(scrVecPos);
|
|
|
|
if (Water::GetWaterLevel(vPos, &fHeight, true, POOL_DEPTH, 999999.9f, NULL))
|
|
{
|
|
phSegment seg;
|
|
phIntersection intersection;
|
|
seg.Set(vPos, Vector3(vPos.x, vPos.y, -999999.9f));
|
|
intersection.Reset();
|
|
|
|
if (CPhysics::GetLevel()->TestProbe(seg, &intersection, NULL, ArchetypeFlags::GTA_MAP_TYPE_MOVER))
|
|
{
|
|
if (fHeight > intersection.GetPosition().GetZf())
|
|
{
|
|
return true; // Water is higher than land. Wet.
|
|
}
|
|
else
|
|
{
|
|
return false; // Land is higher than water. Dry.
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bool CommandGetWaterHeightNoWaves(const scrVector & scrVecPos, float &fHeight)
|
|
{
|
|
Vector3 vPos = Vector3(scrVecPos);
|
|
if (Water::GetWaterLevelNoWaves(vPos, &fHeight, POOL_DEPTH, 999999.9f, NULL))
|
|
{
|
|
phSegment seg;
|
|
phIntersection intersection;
|
|
seg.Set(vPos, Vector3(vPos.x, vPos.y, -999999.9f));
|
|
intersection.Reset();
|
|
|
|
if (CPhysics::GetLevel()->TestProbe(seg, &intersection, NULL, ArchetypeFlags::GTA_MAP_TYPE_MOVER))
|
|
{
|
|
if (fHeight > intersection.GetPosition().GetZf())
|
|
{
|
|
return true; // Water is higher than land. Wet.
|
|
}
|
|
else
|
|
{
|
|
return false; // Land is higher than water. Dry.
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CommandTestProbeAgainstWater(const scrVector & scrVecStartPos, const scrVector & scrVecEndPos, Vector3& intersectionPosition)
|
|
{
|
|
Vec3V startPos = VECTOR3_TO_VEC3V(Vector3(scrVecStartPos));
|
|
Vec3V endPos = VECTOR3_TO_VEC3V(Vector3(scrVecEndPos));
|
|
Vec3V positionOnWater;
|
|
if(Water::TestLineAgainstWater(RCC_VECTOR3(startPos),RCC_VECTOR3(endPos),&RC_VECTOR3(positionOnWater)))
|
|
{
|
|
phSegment seg(RCC_VECTOR3(startPos), RCC_VECTOR3(endPos));
|
|
phIntersection intersection;
|
|
if (CPhysics::GetLevel()->TestProbe(seg, &intersection, NULL, ArchetypeFlags::GTA_MAP_TYPE_MOVER))
|
|
{
|
|
// if the land position is further along the probe than the water position, we hit the water first
|
|
if(IsGreaterThanAll(Dot(Subtract(intersection.GetPosition(),positionOnWater),Subtract(endPos,startPos)),ScalarV(V_ZERO)))
|
|
{
|
|
RC_VEC3V(intersectionPosition) = positionOnWater;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RC_VEC3V(intersectionPosition) = positionOnWater;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
s32 WaterProbeTestHelper(bool hitOcean, Vec3V_In positionOnOcean, Vec3V_In startPos, Vec3V_In endPos, s32 blockingFlags, Vec3V_InOut intersectionPosition)
|
|
{
|
|
// Test against all blocking objects and rivers in the level
|
|
phIntersection levelIntersection;
|
|
if(CPhysics::GetLevel()->TestProbe(phSegment(RCC_VECTOR3(startPos),RCC_VECTOR3(endPos)), &levelIntersection, NULL, shapetest_commands::GetPhysicsFlags(blockingFlags) | ArchetypeFlags::GTA_RIVER_TYPE))
|
|
{
|
|
// If the probe hit the ocean and a bound in the level, use whichever was first
|
|
Vec3V positionInLevel = levelIntersection.GetPosition();
|
|
if(hitOcean && IsGreaterThanAll(Dot(Subtract(positionInLevel,positionOnOcean),Subtract(endPos,startPos)),ScalarV(V_ZERO)))
|
|
{
|
|
// The probe hit the ocean first
|
|
intersectionPosition = positionOnOcean;
|
|
return SCRIPT_WATER_TEST_RESULT_WATER;
|
|
}
|
|
else
|
|
{
|
|
// We hit either a river or a blocking object first, find out which
|
|
if(Verifyf(levelIntersection.GetInstance(),"No instance on valid intersection returned by shapetest."))
|
|
{
|
|
intersectionPosition = positionInLevel;
|
|
bool hitRiver = (levelIntersection.GetInstance()->GetArchetype()->GetTypeFlag(ArchetypeFlags::GTA_RIVER_TYPE) != 0);
|
|
return hitRiver ? SCRIPT_WATER_TEST_RESULT_WATER : SCRIPT_WATER_TEST_RESULT_BLOCKED;
|
|
}
|
|
}
|
|
}
|
|
else if(hitOcean)
|
|
{
|
|
// The probe only hit the ocean
|
|
intersectionPosition = positionOnOcean;
|
|
return SCRIPT_WATER_TEST_RESULT_WATER;
|
|
}
|
|
|
|
return SCRIPT_WATER_TEST_RESULT_NONE;
|
|
}
|
|
|
|
s32 CommandTestProbeAgainstAllWater(const scrVector & scrVecStartPos, const scrVector & scrVecEndPos, s32 blockingFlags, Vector3& intersectionPosition)
|
|
{
|
|
Vec3V startPos = VECTOR3_TO_VEC3V(Vector3(scrVecStartPos));
|
|
Vec3V endPos = VECTOR3_TO_VEC3V(Vector3(scrVecEndPos));
|
|
|
|
// Test against the ocean
|
|
Vec3V positionOnOcean;
|
|
bool hitOcean = Water::TestLineAgainstWater(RCC_VECTOR3(startPos),RCC_VECTOR3(endPos),&RC_VECTOR3(positionOnOcean));
|
|
return WaterProbeTestHelper(hitOcean,positionOnOcean,startPos,endPos,blockingFlags,RC_VEC3V(intersectionPosition));
|
|
}
|
|
|
|
s32 CommandTestVerticalProbeAgainstAllWater(const scrVector & scrVecStartPos, s32 blockingFlags, float& intersectionHeight)
|
|
{
|
|
// Create a downward vertical segment from the given position.
|
|
Vec3V startPos = VECTOR3_TO_VEC3V(Vector3(scrVecStartPos));
|
|
Vec3V endPos = startPos;
|
|
endPos.SetZf(-1000.0f);
|
|
|
|
// Test against the ocean
|
|
Vec3V positionOnOcean = startPos;
|
|
bool hitOcean = Water::GetWaterLevel(RCC_VECTOR3(startPos),&positionOnOcean[2],true, POOL_DEPTH, 999999.9f, NULL);
|
|
|
|
Vec3V finalIntersectionPosition;
|
|
s32 result = WaterProbeTestHelper(hitOcean,positionOnOcean,startPos,endPos,blockingFlags,finalIntersectionPosition);
|
|
if(result != SCRIPT_WATER_TEST_RESULT_NONE)
|
|
{
|
|
intersectionHeight = finalIntersectionPosition.GetZf();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void CommandModifyWater(float worldX, float worldY, float newSpeed, float changePercentage)
|
|
{
|
|
Water::ModifyDynamicWaterSpeed(worldX, worldY, newSpeed, changePercentage);
|
|
}
|
|
|
|
int CommandAddExtraCalmingQuad(float minX, float minY, float maxX, float maxY, float dampening)
|
|
{
|
|
scriptAssertf(dampening >=0.0f && dampening <= 1.0f, "%s: ADD_EXTRA_CALMING_QUAD - Dampening should be between 0.0 and 1.0, it is %f", CTheScripts::GetCurrentScriptNameAndProgramCounter(), dampening);
|
|
scriptAssertf(maxX - minX > 1.0f && maxY - minY > 1.0f, "%s: ADD_EXTRA_CALMING_QUAD - Invalid quad dimensions, X: %.2f - %.2f\t Y: %.2f - %.2f", CTheScripts::GetCurrentScriptNameAndProgramCounter(), maxX, minX, maxY, minY);
|
|
|
|
int idx = Water::AddExtraCalmingQuad((int)minX,(int)minY,(int)maxX,(int)maxY,dampening);
|
|
scriptAssertf(idx != -1, "%s: ADD_EXTRA_CALMING_QUAD - Failed to add a new calming quad, are we out?", CTheScripts::GetCurrentScriptNameAndProgramCounter());
|
|
|
|
return idx;
|
|
}
|
|
|
|
void CommandSetCalmedWaveHeightScaler( float scale )
|
|
{
|
|
scriptAssertf(scale >=0.0f && scale <= 1.0f, "%s: SET_CALMED_WAVE_HEIGHT_SCALER - Calmed wave height scaler should be between 0.0 and 1.0, it is %f", CTheScripts::GetCurrentScriptNameAndProgramCounter(), scale);
|
|
Water::SetScriptCalmedWaveHeightScaler(scale);
|
|
}
|
|
|
|
void CommandRemoveExtraCalmingQuad(int idx)
|
|
{
|
|
Water::RemoveExtraCalmingQuad(idx);
|
|
}
|
|
|
|
void CommandRemoveAllExtraCalmingQuads()
|
|
{
|
|
Water::RemoveAllExtraCalmingQuads();
|
|
}
|
|
|
|
void CommandSetDeepOceanScaler(float s)
|
|
{
|
|
scriptAssertf(s >=0.0f && s <= 1.0f, "%s: SET_DEEP_OCEAN_SCALER - Deep Ocean scaler should be between 0.0 and 1.0, it is %f", CTheScripts::GetCurrentScriptNameAndProgramCounter(), s);
|
|
Water::SetScriptDeepOceanScaler(s);
|
|
}
|
|
|
|
float CommandGetDeepOceanScaler()
|
|
{
|
|
return Water::GetScriptDeepOceanScaler();
|
|
}
|
|
|
|
void CommandResetDeepOceanScaler()
|
|
{
|
|
Water::SetScriptDeepOceanScaler(1.0f);
|
|
}
|
|
|
|
|
|
bool CommandSynchRecordingWithWater()
|
|
{
|
|
return Water::SynchRecordingWithWater();
|
|
}
|
|
|
|
void SetupScriptCommands()
|
|
{
|
|
SCR_REGISTER_SECURE(GET_WATER_HEIGHT,0x182029c7e52a1e4f, CommandGetWaterHeight);
|
|
SCR_REGISTER_SECURE(GET_WATER_HEIGHT_NO_WAVES,0x7f38b18228435c61, CommandGetWaterHeightNoWaves);
|
|
SCR_REGISTER_SECURE(TEST_PROBE_AGAINST_WATER,0x7cbf98360c4b22e4, CommandTestProbeAgainstWater);
|
|
SCR_REGISTER_SECURE(TEST_PROBE_AGAINST_ALL_WATER,0xd3c9aed49c894ccf, CommandTestProbeAgainstAllWater);
|
|
SCR_REGISTER_SECURE(TEST_VERTICAL_PROBE_AGAINST_ALL_WATER,0xe77dda8d6639cb5e, CommandTestVerticalProbeAgainstAllWater);
|
|
SCR_REGISTER_UNUSED(SYNCH_RECORDING_WITH_WATER,0x3ede3f11c4cd62a9, CommandSynchRecordingWithWater);
|
|
SCR_REGISTER_SECURE(MODIFY_WATER,0x93c91349de947dae, CommandModifyWater);
|
|
SCR_REGISTER_SECURE(ADD_EXTRA_CALMING_QUAD,0xcf4901abd5b28f62, CommandAddExtraCalmingQuad);
|
|
SCR_REGISTER_SECURE(REMOVE_EXTRA_CALMING_QUAD,0xf672e351681b36f7, CommandRemoveExtraCalmingQuad);
|
|
SCR_REGISTER_UNUSED(REMOVE_ALL_EXTRA_CALMING_QUAD,0x0a0c7680ead49fa3, CommandRemoveAllExtraCalmingQuads);
|
|
SCR_REGISTER_SECURE(SET_DEEP_OCEAN_SCALER,0x3999d3aa01285aaf,CommandSetDeepOceanScaler);
|
|
SCR_REGISTER_SECURE(GET_DEEP_OCEAN_SCALER,0x241ee5a1d050510d,CommandGetDeepOceanScaler);
|
|
SCR_REGISTER_SECURE(SET_CALMED_WAVE_HEIGHT_SCALER,0xae0b891009dee273,CommandSetCalmedWaveHeightScaler);
|
|
|
|
SCR_REGISTER_SECURE(RESET_DEEP_OCEAN_SCALER,0x1a7781189253be0f,CommandResetDeepOceanScaler);
|
|
}
|
|
}
|