530 lines
16 KiB
C++
530 lines
16 KiB
C++
#include "zeroerr/assert.h"
|
|
#include "zeroerr/unittest.h"
|
|
|
|
#include "graphics/AmbientOcclusion.h"
|
|
#include "graphics/AntiAliasing.h"
|
|
#include "graphics/Canvas.h"
|
|
#include "graphics/DrawItem2D.h"
|
|
#include "graphics/Font.h"
|
|
#include "graphics/GBuffer.h"
|
|
#include "graphics/GlobalIllumination.h"
|
|
#include "graphics/Graphics.h"
|
|
#include "graphics/Grass.h"
|
|
#include "graphics/Light.h"
|
|
#include "graphics/Material.h"
|
|
#include "graphics/Mesh.h"
|
|
#include "graphics/Outline.h"
|
|
#include "graphics/Quad.h"
|
|
#include "graphics/RenderControl.h"
|
|
#include "graphics/ScreenSpaceReflection.h"
|
|
#include "graphics/Shader.h"
|
|
#include "graphics/Texture.h"
|
|
#include "graphics/Volumetric.h"
|
|
#include "graphics/Water.h"
|
|
#include "graphics/Waterfall.h"
|
|
#include "map/Fov.h"
|
|
#include "map/Map.h"
|
|
#include "map/TileLayer.h"
|
|
#include "window/Window.h"
|
|
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
using namespace eve::map;
|
|
|
|
namespace {
|
|
|
|
int countVisible(Fov *fov) {
|
|
int n = 0;
|
|
for (int y = 0; y < fov->getHeight(); ++y)
|
|
for (int x = 0; x < fov->getWidth(); ++x)
|
|
if (fov->isVisible(x, y)) ++n;
|
|
return n;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST_CASE("map.fov.algorithm.defaults") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(4, 4);
|
|
REQUIRE(fov != nullptr);
|
|
CHECK_EQ(fov->getWidth(), 4);
|
|
CHECK_EQ(fov->getHeight(), 4);
|
|
CHECK_EQ(fov->getAlgorithm(), std::string("shadowcast"));
|
|
CHECK_EQ(fov->getRadiusMetric(), std::string("euclidean"));
|
|
fov->setRadiusMetric("chebyshev");
|
|
CHECK_EQ(fov->getRadiusMetric(), std::string("chebyshev"));
|
|
fov->setRadiusMetric("nope");
|
|
CHECK_EQ(fov->getRadiusMetric(), std::string("chebyshev"));
|
|
fov->setAlgorithm("raycast");
|
|
CHECK_EQ(fov->getAlgorithm(), std::string("raycast"));
|
|
fov->setAlgorithm("permissive");
|
|
CHECK_EQ(fov->getAlgorithm(), std::string("permissive"));
|
|
fov->setAlgorithm("rectangle");
|
|
CHECK_EQ(fov->getAlgorithm(), std::string("rectangle"));
|
|
fov->setAlgorithm("nope");
|
|
CHECK_EQ(fov->getAlgorithm(), std::string("rectangle"));
|
|
CHECK_EQ(fov->getMode(), std::string("grid2d"));
|
|
CHECK_EQ(fov->getTopology(), std::string("ortho"));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.openRadius.chebyshev") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(11, 11);
|
|
REQUIRE(fov != nullptr);
|
|
fov->setRadiusMetric("chebyshev");
|
|
fov->setBlockEmpty(false);
|
|
const int id = fov->addRevealer(5, 5, 2);
|
|
CHECK(id >= 1);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(5, 5));
|
|
CHECK(fov->isVisible(5 + 2, 5));
|
|
CHECK(fov->isVisible(5, 5 + 2));
|
|
CHECK(fov->isVisible(5 + 2, 5 + 2));
|
|
CHECK(!fov->isVisible(5 + 3, 5));
|
|
// Chebyshev radius 2 => 5x5 = 25 cells
|
|
CHECK_EQ(countVisible(fov), 25);
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.wallCastsShadow") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(9, 5);
|
|
REQUIRE(fov != nullptr);
|
|
fov->setRadiusMetric("chebyshev");
|
|
fov->setBlockEmpty(false);
|
|
// Vertical wall at x=4, gap none — full column opaque
|
|
for (int y = 0; y < 5; ++y) fov->setOpaque(4, y, true);
|
|
fov->addRevealer(1, 2, 6);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(1, 2));
|
|
CHECK(fov->isVisible(4, 2)); // blocking cell itself is visible
|
|
CHECK(!fov->isVisible(6, 2)); // behind wall
|
|
CHECK(!fov->isVisible(7, 2));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.corridorAndRoom") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(7, 5);
|
|
fov->setBlockEmpty(false);
|
|
fov->setRadiusMetric("chebyshev");
|
|
// Room walls with a corridor opening east from (1,2)
|
|
for (int x = 0; x < 7; ++x) {
|
|
fov->setOpaque(x, 0, true);
|
|
fov->setOpaque(x, 4, true);
|
|
}
|
|
for (int y = 0; y < 5; ++y) {
|
|
fov->setOpaque(0, y, true);
|
|
fov->setOpaque(6, y, true);
|
|
}
|
|
// Interior divider with door at (3,2)
|
|
fov->setOpaque(3, 1, true);
|
|
fov->setOpaque(3, 3, true);
|
|
fov->addRevealer(1, 2, 8);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(1, 2));
|
|
CHECK(fov->isVisible(2, 2));
|
|
CHECK(fov->isVisible(3, 2)); // open gap between walls
|
|
CHECK(fov->isVisible(4, 2)); // room beyond door
|
|
CHECK(fov->isVisible(3, 1)); // opaque wall cell is lit when hit
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.coneFacing") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(11, 11);
|
|
fov->setBlockEmpty(false);
|
|
fov->setRadiusMetric("chebyshev");
|
|
const int id = fov->addRevealer(5, 5, 4);
|
|
// Face +X (east), half-angle 30°
|
|
fov->setRevealerFacing(id, 0.f, 30.f);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(5, 5));
|
|
CHECK(fov->isVisible(8, 5)); // east
|
|
CHECK(!fov->isVisible(2, 5)); // west outside cone
|
|
CHECK(!fov->isVisible(5, 8)); // south outside cone
|
|
fov->clearRevealerFacing(id);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(2, 5));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.multiRevealerOr") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(15, 5);
|
|
fov->setBlockEmpty(false);
|
|
fov->setRadiusMetric("chebyshev");
|
|
fov->addRevealer(1, 2, 1);
|
|
fov->addRevealer(13, 2, 1);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(1, 2));
|
|
CHECK(fov->isVisible(13, 2));
|
|
CHECK(!fov->isVisible(7, 2));
|
|
CHECK_EQ(fov->getRevealerCount(), 2);
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.exploredMemory") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(9, 9);
|
|
fov->setBlockEmpty(false);
|
|
fov->setRadiusMetric("chebyshev");
|
|
const int id = fov->addRevealer(4, 4, 2);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(4, 4));
|
|
CHECK(fov->isExplored(4, 4));
|
|
CHECK_EQ(fov->getState(4, 4), std::string("visible"));
|
|
|
|
fov->setRevealerPosition(id, 0, 0);
|
|
fov->setRevealerRadius(id, 1);
|
|
fov->compute();
|
|
CHECK(!fov->isVisible(4, 4));
|
|
CHECK(fov->isExplored(4, 4));
|
|
CHECK_EQ(fov->getState(4, 4), std::string("explored"));
|
|
CHECK(fov->isVisible(0, 0));
|
|
|
|
fov->clearMemory();
|
|
CHECK(!fov->isExplored(4, 4));
|
|
CHECK_EQ(fov->getState(4, 4), std::string("unknown"));
|
|
// clearMemory does not recompute; current visibility cleared too
|
|
CHECK(!fov->isVisible(0, 0));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.layerOpaqueGid") {
|
|
auto *mod = Map::create();
|
|
TileLayer *layer = mod->newLayer(7, 3, 8.f, 8.f);
|
|
layer->fill(2);
|
|
for (int y = 0; y < 3; ++y) layer->setTile(3, y, 1);
|
|
|
|
Fov *fov = mod->newFov(layer);
|
|
REQUIRE(fov != nullptr);
|
|
fov->setBlockEmpty(false);
|
|
fov->blockOpaqueGid(1);
|
|
fov->setRadiusMetric("chebyshev");
|
|
fov->addRevealer(0, 1, 6);
|
|
fov->compute();
|
|
CHECK(fov->isOpaque(3, 1));
|
|
CHECK(fov->isVisible(3, 1));
|
|
CHECK(!fov->isVisible(5, 1));
|
|
|
|
layer->setTile(3, 1, 2);
|
|
fov->syncFromLayer();
|
|
fov->compute();
|
|
CHECK(!fov->isOpaque(3, 1));
|
|
CHECK(fov->isVisible(5, 1));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.boundLayerAutoSyncsRevision") {
|
|
auto *mod = Map::create();
|
|
TileLayer *layer = mod->newLayer(7, 1, 8.f, 8.f);
|
|
layer->fill(2);
|
|
Fov *fov = mod->newFov(layer);
|
|
fov->setBlockEmpty(false);
|
|
fov->blockOpaqueGid(1);
|
|
fov->addRevealer(0, 0, 7);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(6, 0));
|
|
layer->setTile(3, 0, 1);
|
|
fov->compute();
|
|
CHECK(!fov->isVisible(6, 0));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.removeAndDisable") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(5, 5);
|
|
fov->setBlockEmpty(false);
|
|
const int a = fov->addRevealer(2, 2, 1);
|
|
const int b = fov->addRevealer(0, 0, 1);
|
|
fov->setRevealerEnabled(b, false);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(2, 2));
|
|
CHECK(!fov->isVisible(0, 0));
|
|
fov->removeRevealer(a);
|
|
fov->setRevealerEnabled(b, true);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(0, 0));
|
|
CHECK(!fov->isVisible(2, 2));
|
|
fov->clearRevealers();
|
|
CHECK_EQ(fov->getRevealerCount(), 0);
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.raycast.wallShadow") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(9, 5);
|
|
fov->setAlgorithm("raycast");
|
|
fov->setRadiusMetric("chebyshev");
|
|
fov->setBlockEmpty(false);
|
|
for (int y = 0; y < 5; ++y) fov->setOpaque(4, y, true);
|
|
fov->addRevealer(1, 2, 6);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(1, 2));
|
|
CHECK(fov->isVisible(4, 2));
|
|
CHECK(!fov->isVisible(6, 2));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.permissive.openRadius") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(7, 7);
|
|
fov->setAlgorithm("permissive");
|
|
fov->setRadiusMetric("chebyshev");
|
|
fov->setBlockEmpty(false);
|
|
fov->addRevealer(3, 3, 2);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(3, 3));
|
|
CHECK(fov->isVisible(5, 5));
|
|
CHECK(!fov->isVisible(6, 3));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.heightmap.cliffBlocks") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(9, 3);
|
|
fov->setMode("heightmap");
|
|
fov->setRadiusMetric("chebyshev");
|
|
fov->setBlockEmpty(false);
|
|
fov->setCliffBlock(1.f);
|
|
fov->setEyeOffset(0.f);
|
|
// Flat ground elev 0; cliff column at x=4 with elev 2
|
|
for (int y = 0; y < 3; ++y) fov->setElevation(4, y, 2.f);
|
|
fov->addRevealer(1, 1, 6);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(1, 1));
|
|
CHECK(!fov->isVisible(6, 1)); // behind high cliff
|
|
// Lower cliff should not block with cliffBlock=1 if elev=0.5
|
|
fov->setElevation(4, 1, 0.5f);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(6, 1));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.volume.bridgeLayers") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovVolume(7, 3, 4);
|
|
REQUIRE(fov != nullptr);
|
|
CHECK_EQ(fov->getDepth(), 4);
|
|
CHECK_EQ(fov->getMode(), std::string("volume"));
|
|
fov->setRadiusMetric("chebyshev");
|
|
fov->setVerticalRange(3);
|
|
// Solid slab at z=1 separates upper (z=2) and lower (z=0) spaces.
|
|
for (int x = 0; x < 7; ++x) fov->setOpaque3(x, 1, 1, true);
|
|
|
|
fov->addRevealer3(1, 1, 2, 5); // above slab
|
|
fov->compute();
|
|
CHECK(fov->isVisible3(1, 1, 2));
|
|
CHECK(fov->isVisible3(3, 1, 2));
|
|
CHECK(fov->isVisible3(3, 1, 1)); // slab surface lit
|
|
CHECK(!fov->isVisible3(3, 1, 0)); // below slab blocked
|
|
|
|
fov->clearRevealers();
|
|
fov->addRevealer3(1, 1, 0, 5); // below slab
|
|
fov->compute();
|
|
CHECK(fov->isVisible3(1, 1, 0));
|
|
CHECK(fov->isVisible3(3, 1, 1));
|
|
CHECK(!fov->isVisible3(3, 1, 2));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.volume.verticalExtend") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovVolume(5, 5, 5);
|
|
fov->setRadiusMetric("chebyshev");
|
|
fov->setVerticalRange(2);
|
|
fov->addRevealer3(2, 2, 2, 1);
|
|
fov->compute();
|
|
CHECK(fov->isVisible3(2, 2, 2));
|
|
CHECK(fov->isVisible3(2, 2, 3));
|
|
CHECK(fov->isVisible3(2, 2, 4));
|
|
CHECK(fov->isVisible3(2, 2, 1));
|
|
CHECK(fov->isVisible3(2, 2, 0));
|
|
// Block upward
|
|
fov->setOpaque3(2, 2, 3, true);
|
|
fov->compute();
|
|
CHECK(fov->isVisible3(2, 2, 3)); // opaque cell lit
|
|
CHECK(!fov->isVisible3(2, 2, 4));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.dirty.skipsRecompute") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(5, 5);
|
|
fov->setBlockEmpty(false);
|
|
fov->setRadiusMetric("chebyshev");
|
|
fov->addRevealer(2, 2, 1);
|
|
CHECK(fov->isDirty());
|
|
fov->compute();
|
|
CHECK(!fov->isDirty());
|
|
CHECK(fov->isVisible(2, 2));
|
|
// Second compute without changes is a no-op (still visible).
|
|
fov->compute();
|
|
CHECK(fov->isVisible(2, 2));
|
|
CHECK(!fov->isDirty());
|
|
fov->setOpaque(1, 2, true);
|
|
CHECK(fov->isDirty());
|
|
fov->markDirty();
|
|
CHECK(fov->isDirty());
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.maskExport") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(5, 5);
|
|
fov->setBlockEmpty(false);
|
|
fov->setRadiusMetric("chebyshev");
|
|
const int id = fov->addRevealer(2, 2, 1);
|
|
fov->compute();
|
|
CHECK_EQ(fov->getMaskByte(2, 2), 255);
|
|
CHECK(fov->getMaskValue(2, 2) > 0.9f);
|
|
|
|
fov->setRevealerPosition(id, 0, 0);
|
|
fov->setRevealerRadius(id, 0);
|
|
fov->compute();
|
|
CHECK_EQ(fov->getMaskByte(2, 2), 89); // explored ≈ 0.35*255
|
|
CHECK(!fov->isVisible(2, 2));
|
|
CHECK(fov->isExplored(2, 2));
|
|
|
|
std::vector<uint8_t> mask;
|
|
CHECK(fov->fillMaskR8(mask));
|
|
CHECK_EQ(int(mask.size()), 25);
|
|
CHECK_EQ(int(mask[size_t(2 + 2 * 5)]), 89);
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.hex.topologyRadius") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(11, 11);
|
|
fov->setTopology("hex");
|
|
fov->setBlockEmpty(false);
|
|
CHECK_EQ(fov->getTopology(), std::string("hex"));
|
|
fov->addRevealer(5, 5, 2);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(5, 5));
|
|
// Hex distance 2 neighbors should be visible; far chebyshev corner may not.
|
|
CHECK(fov->isVisible(6, 5));
|
|
const bool nearRing = fov->isVisible(5, 7) || fov->isVisible(6, 6);
|
|
CHECK(nearRing);
|
|
CHECK(!fov->isVisible(0, 0));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.hex.wallBlocksCubeLine") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(9, 5);
|
|
fov->setTopology("hex");
|
|
fov->setAlgorithm("shadowcast");
|
|
fov->setBlockEmpty(false);
|
|
for (int y = 0; y < 5; ++y) fov->setOpaque(4, y, true);
|
|
fov->addRevealer(1, 2, 5);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(1, 2));
|
|
CHECK(fov->isVisible(4, 2));
|
|
CHECK(!fov->isVisible(7, 2));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.rectangle.wallShadow") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(11, 5);
|
|
fov->setAlgorithm("rectangle");
|
|
fov->setRadiusMetric("chebyshev");
|
|
fov->setBlockEmpty(false);
|
|
for (int y = 0; y < 5; ++y) {
|
|
fov->setOpaque(5, y, true);
|
|
fov->setOpaque(6, y, true); // thick wall merges to a rect
|
|
}
|
|
fov->addRevealer(1, 2, 8);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(1, 2));
|
|
CHECK(fov->isVisible(5, 2));
|
|
CHECK(!fov->isVisible(9, 2));
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.perception.canDetect") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(7, 7);
|
|
fov->setBlockEmpty(false);
|
|
fov->setRadiusMetric("chebyshev");
|
|
fov->setPerceptionRadiusScale(1.f);
|
|
const int id = fov->addRevealer(3, 3, 1);
|
|
fov->setRevealerPerception(id, 2.f); // effective radius 3
|
|
CHECK_EQ(fov->getEffectiveRadius(id), 3);
|
|
fov->compute();
|
|
CHECK(fov->isVisible(3, 6));
|
|
fov->setDetectionMargin(0.f);
|
|
CHECK(fov->canDetect(id, 3, 3, 1.f)); // perception 2 >= stealth 1
|
|
CHECK(!fov->canDetect(id, 3, 3, 3.f)); // stealth too high
|
|
CHECK(!fov->canDetect(id, 0, 0, 0.f)); // not visible
|
|
delete fov;
|
|
}
|
|
|
|
TEST_CASE("map.fov.gpuMaskTexture") {
|
|
auto *win = eve::window::Window::create();
|
|
auto *gfx = eve::graphics::Graphics::create();
|
|
REQUIRE(win != nullptr);
|
|
REQUIRE(gfx != nullptr);
|
|
eve::window::WindowSettings settings;
|
|
settings.width = 4;
|
|
settings.height = 4;
|
|
settings.centered = true;
|
|
REQUIRE(win->setWindowSettings(settings));
|
|
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(4, 4);
|
|
fov->setBlockEmpty(false);
|
|
fov->addRevealer(1, 1, 1);
|
|
fov->compute();
|
|
CHECK(fov->buildMaskTexture(nullptr) == nullptr);
|
|
|
|
auto *tex = fov->buildMaskTexture(gfx);
|
|
REQUIRE(tex != nullptr);
|
|
CHECK_EQ(tex->getWidth(), 4);
|
|
CHECK_EQ(tex->getHeight(), 4);
|
|
delete tex;
|
|
delete fov;
|
|
win->close();
|
|
}
|
|
|
|
TEST_CASE("map.fov.accessorRoundTrips") {
|
|
auto *mod = Map::create();
|
|
Fov *fov = mod->newFovSize(4, 4);
|
|
REQUIRE(fov != nullptr);
|
|
|
|
fov->setCornerPeek(true);
|
|
CHECK(fov->getCornerPeek());
|
|
fov->setCornerPeek(false);
|
|
CHECK(!fov->getCornerPeek());
|
|
|
|
fov->setEyeOffset(1.f);
|
|
CHECK_EQ(fov->getEyeOffset(), 1.f);
|
|
|
|
fov->setCliffBlock(0.5f);
|
|
CHECK_EQ(fov->getCliffBlock(), 0.5f);
|
|
|
|
fov->setVerticalRange(3);
|
|
CHECK_EQ(fov->getVerticalRange(), 3);
|
|
|
|
fov->setPerceptionRadiusScale(1.5f);
|
|
CHECK_EQ(fov->getPerceptionRadiusScale(), 1.5f);
|
|
|
|
const int id = fov->addRevealer(1, 1, 2);
|
|
REQUIRE(id >= 0);
|
|
fov->setRevealerPosition3(id, 2, 3, 1);
|
|
fov->setRevealerRadius(id, 4);
|
|
fov->setRevealerPerception(id, 2.f);
|
|
CHECK_EQ(fov->getRevealerPerception(id), 2.f);
|
|
CHECK_EQ(fov->getRevealerCount(), 1);
|
|
fov->setRevealerEnabled(id, false);
|
|
CHECK_EQ(fov->getRevealerCount(), 1); // disabled revealers stay registered
|
|
CHECK_EQ(fov->getRevealerPerception(999), 0.f); // unknown id
|
|
|
|
delete fov;
|
|
}
|