Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

906 lines
26 KiB
C++

//===========================================================================//
// File: Map.cpp //
// Project: MUNGA Brick: Interest Manager //
// Contents: Interface specifications for interest manager //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 11/04/94 ECH Initial coding. //
// 11/29/94 JMA Changed Identities to IDs //
// 02/10/95 CPB Added GaugeInterestType //
// 08/25/97 ECH Infrastructure changes. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include "AdeptHeaders.hpp"
#include "Tile.hpp"
#include <ElementRenderer\GridElement.hpp>
#include "Zone.hpp"
#include "Map.hpp"
#include "CollisionVolume.hpp"
#include "LightManager.hpp"
#include <ElementRenderer\StateChange.hpp>
#include <ElementRenderer\CameraElement.hpp>
#include <MLR\MLRInfiniteLightWithFalloff.hpp>
#include "Application.hpp"
#if defined(BSP_BUG)
bool Adept::debug_bsp=true;
#endif
bool
TerrainBSP::TestLine(
CollisionQuery *query,
Scalar enter,
Scalar leave
)
{
Check_Object(this);
Check_Object(query);
//
//-----------------------------------------
// Set up the recursion avoidance variables
//-----------------------------------------
//
Check_Object(query->m_line);
Line3D *line = query->m_line;
Check_Object(query->m_zone);
Zone *zone = query->m_zone;
Check_Object(query->m_tile);
Tile *tile = query->m_tile;
TerrainBSP *bsp = this;
//
//-------------------------------------------------------------------------
// Here is the real start of the loop. We first want to find which side of
// the plane we are on and which direction we are headed
//-------------------------------------------------------------------------
//
Start_Over:
Check_Object(bsp);
Verify(enter >= 0.0f && enter <= leave);
Verify(bsp->m_planeIndex < zone->m_planeCount);
const Plane *plane = &zone->m_planes[bsp->m_planeIndex];
Scalar dot = plane->normal * line->m_direction;
Scalar separation = plane->GetDistanceTo(line->m_origin);
//
//----------------------------------------------------------
// We are heading into the plane, so see when we will hit it
//----------------------------------------------------------
//
#if defined(BSP_BUG)
if (debug_bsp)
{
SPEW((
BSP_BUG,
"### %sBSP %d",
(plane->m_normal.y > SMALL) ? "" : "pseudo ",
bsp-tile->m_BSP
));
SPEW((
BSP_BUG,
" enter: %f, leave: %f, dot: %f, sep: %f",
enter,
leave,
dot,
separation
));
}
#endif
if (dot < -SMALL)
{
Scalar distance = -separation/dot;
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((
BSP_BUG,
" distance into plane = %f",
distance
));
#endif
//
//------------------------------------------------------------------
// See if we are still on the outside of the plane when we take into
// account the distance already moved along the line. If we are,
// look to see if the line will strike the plane. If not, and there
// is no tree on the outer halfspace of the plane, we won't hit
// anything so just return
//------------------------------------------------------------------
//
if (distance > enter)
{
if (distance > leave)
{
if (!bsp->m_outerIndex)
{
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " won't reach plane and outside is empty"));
#endif
return false;
}
//
//-------------------------------------------------------------
// There is a tree to check on the outside of our plane, so set
// it as the current tree and start over
//-------------------------------------------------------------
//
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " won't reach plane, jumping to outer halfspace"));
#endif
Verify(bsp->m_outerIndex < tile->m_BSPCount);
bsp = &tile->m_BSP[bsp->m_outerIndex];
goto Start_Over;
}
//
//---------------------------------------------------------------
// We will cross into the plane space, so first check the outer
// half via recursion, as we will need to continue into the inner
// space. We will shorten the line for his test to make sure
// that any plane hits happen only within our outer halfspace.
// If our child hits something, stop the traversal. Note that if
// there is no tree on the outer space, it is empty and can just
// be ignored
//---------------------------------------------------------------
//
if (bsp->m_outerIndex)
{
Verify(bsp->m_outerIndex < tile->m_BSPCount);
Verify(enter <= distance);
Verify(distance <= leave);
Scalar new_leave = leave;
Max_Clamp(new_leave, distance);
if (tile->m_BSP[bsp->m_outerIndex].TestLine(query, enter, new_leave))
{
//
// I'm commenting out this line because I have never beaten the case where
// rounding error causes the line to exit one tile and enter the next tile
// under the terrain...
//
// Verify(!line->m_length || query->m_normal->y > SMALL);
return true;
}
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, "### returning to BSP %d", bsp-tile->m_BSP));
#endif
}
//
//-----------------------------------------------------------------
// We have struck the plane, so this is the normal of impact unless
// we go through another plane. Bump the enter to be on our plane
// surface to make sure that nothing tries to check against the
// outer space of the plane
//-----------------------------------------------------------------
//
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " crossing <%f,%f,%f>", plane->m_normal.x, plane->m_normal.y, plane->m_normal.z));
#endif
*query->m_normal = plane->normal;
enter = distance;
}
//
//----------------------------------------------------------------------
// At this point we need only concern ourself with the inner space of
// the plane. If there is no tree there, then it is solid space. We
// set the line length to the amount already traveled and then stop with
// a successful hit
//----------------------------------------------------------------------
//
if (!bsp->m_innerIndex)
{
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " inside is solid"));
#endif
line->m_length = enter;
//
// I'm commenting out this line because I have never beaten the case where
// rounding error causes the line to exit one tile and enter the next tile
// under the terrain...
//
// Verify(!line->m_length || query->m_normal->y > SMALL);
return true;
}
//
//------------------------------------------------------------
// Set our inner space tree as the current tree and start over
//------------------------------------------------------------
//
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " jumping to inner halfspace"));
#endif
Verify(bsp->m_innerIndex < tile->m_BSPCount);
bsp = &tile->m_BSP[bsp->m_innerIndex];
goto Start_Over;
}
//
//---------------------------------------------------------------
// If we are heading out of the plane, see when we will strike it
//---------------------------------------------------------------
//
else if (dot > SMALL)
{
Scalar distance = -separation/dot;
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((
BSP_BUG,
" distance out of plane = %f",
distance
));
#endif
//
//----------------------------------------------------------------
// If we are still inside the plane when we take into account the
// distance already travelled, see if the inside is solid. If so,
// set the line length to that already travelled and stop the
// traversal with a successful hit
//----------------------------------------------------------------
//
if (distance > enter)
{
if (!bsp->m_innerIndex)
{
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " inside is solid"));
#endif
line->m_length = enter;
//
// I'm commenting out this line because I have never beaten the case where
// rounding error causes the line to exit one tile and enter the next tile
// under the terrain...
//
// Verify(!line->m_length || query->m_normal->y > SMALL);
return true;
}
//
//---------------------------------------------------------------
// We now know there is a tree inside our plane halfspace. If we
// won't hit the surface of the plane, set it as the current tree
// and start over
//---------------------------------------------------------------
//
if (distance > leave)
{
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " jumping into inner halfspace"));
#endif
Verify(bsp->m_innerIndex < tile->m_BSPCount);
bsp = &tile->m_BSP[bsp->m_innerIndex];
goto Start_Over;
}
//
//---------------------------------------------------------------
// We will cross into the plane space, so first check the inner
// half via recursion, as we will need to continue into the outer
// space. We will shorten the line for his test to make sure
// that any plane hits happen only within our inner halfspace.
// If our child hits something, stop the traversal
//---------------------------------------------------------------
//
Verify(bsp->m_innerIndex < tile->m_BSPCount);
Verify(enter <= distance);
Verify(distance <= leave);
Scalar new_leave = leave;
Max_Clamp(new_leave, distance);
if (tile->m_BSP[bsp->m_innerIndex].TestLine(query, enter, new_leave))
{
//
// I'm commenting out this line because I have never beaten the case where
// rounding error causes the line to exit one tile and enter the next tile
// under the terrain...
//
// Verify(!line->m_length || query->m_normal->y > SMALL);
return true;
}
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, "### returning to BSP %d", bsp-tile->m_BSP));
#endif
enter = distance;
}
//
//---------------------------------------------------------------------
// If we get here, we only need concern ourselves with the outer space.
// If it is empty, stop the traversal with a miss
//---------------------------------------------------------------------
//
if (!bsp->m_outerIndex)
{
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " outside is empty"));
#endif
return false;
}
//
//------------------------------------------------------------
// Set the outer space tree as the current tree and start over
//------------------------------------------------------------
//
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " jumping to outer halfspace"));
#endif
Verify(bsp->m_outerIndex < tile->m_BSPCount);
bsp = &tile->m_BSP[bsp->m_outerIndex];
goto Start_Over;
}
//
//----------------------------------------------------------------------
// We are moving parallel to the plane, so check only the inside of the
// plane if that's where we are
//----------------------------------------------------------------------
//
else if (separation < SMALL)
{
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " Inside plane"));
#endif
if (!bsp->m_innerIndex)
{
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " inside is solid"));
#endif
line->m_length = enter;
//
// I'm commenting out this line because I have never beaten the case where
// rounding error causes the line to exit one tile and enter the next tile
// under the terrain...
//
// Verify(!line->m_length || query->m_normal->y > SMALL);
return true;
}
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " jumping to inner halfspace"));
#endif
Verify(bsp->m_innerIndex < tile->m_BSPCount);
bsp = &tile->m_BSP[bsp->m_innerIndex];
goto Start_Over;
}
//
//------------------------
// Check outside the plane
//------------------------
//
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " Outside plane"));
#endif
if (!bsp->m_outerIndex)
{
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " outside is empty"));
#endif
return false;
}
#if defined(BSP_BUG)
if (debug_bsp)
SPEW((BSP_BUG, " jumping to outer halfspace"));
#endif
Verify(bsp->m_outerIndex < tile->m_BSPCount);
bsp = &tile->m_BSP[bsp->m_outerIndex];
goto Start_Over;
}
//#############################################################################
//########################### Zone #################################
//#############################################################################
Tile::ClassData
*Tile::DefaultData = NULL;
const Stuff::RGBAColor
*Tile::s_GroundColor = NULL;
DECLARE_TIMER(static, Ray_Vs_BSP);
DECLARE_TIMER(static, Ray_Vs_OBB);
static bool Hide_Ground=false;
static bool __stdcall CheckHideGround() {return Hide_Ground;}
static void __stdcall EnableHideGround() {Hide_Ground = !Hide_Ground;}
static bool Hide_TileEntities=false;
static bool __stdcall CheckHideTileEntities() {return Hide_TileEntities;}
static void __stdcall EnableHideTileEntities() {Hide_TileEntities = !Hide_TileEntities;}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Tile::InitializeClass()
{
Verify(!DefaultData);
DefaultData =
new ClassData(
TileClassID,
"Adept::Tile",
ElementRenderer::GroupElement::DefaultData,
reinterpret_cast<Factory>(&Make)
);
Register_Object(DefaultData);
s_GroundColor = NULL;
Initialize_Timer(Ray_Vs_BSP, "Ray vs BSP");
Initialize_Timer(Ray_Vs_OBB, "Ray vs OBB");
AddDebuggerMenuItem("Libraries\\Adept\\Hide Ground", CheckHideGround, EnableHideGround, 0 );
AddDebuggerMenuItem("Libraries\\Adept\\Hide Tile Entities", CheckHideTileEntities, EnableHideTileEntities, 0 );
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Tile::TerminateClass()
{
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Tile::TestInstance()
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Tile::Tile(
Zone *zone,
BYTE row,
BYTE column
):
GroupElement(DefaultData),
m_collidees(NULL),
m_colliders(NULL),
m_lights(NULL),
damagableEntityList(NULL)
{
Check_Pointer(this);
m_draw = static_cast<DrawMethod>(&Tile::Draw);
AdoptStateChange(new ElementRenderer::StateChange);
m_row = row;
m_column = column;
m_zone = zone;
m_ground = NULL;
m_BSP = NULL;
m_BSPCount = 0;
m_lightsChanged = false;
m_DamageBitStart = -1;
m_damagableEntityCount = 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Tile::~Tile()
{
Check_Object(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Tile::Save(MemoryStream *stream)
{
Check_Object(this);
Check_Object(stream);
//
//--------------------------
// Write stuff to the stream
//--------------------------
//
*stream << static_cast<int>(ElementRenderer::GroupElementClassID) << m_state;
if (m_stateChange)
{
Check_Object(m_stateChange);
Verify(m_state & PropertyChangeFlag);
m_stateChange->Save(stream);
}
if (!IsLocalToParentIdentity())
*stream << m_localToParent;
//
//--------------------------
// Write the bounding volume
//--------------------------
//
if (IsBoundedByOBB())
{
*stream << m_localOBB.localToParent << m_localOBB.axisExtents
<< m_localOBB.sphereRadius;
}
else
{
Point3D center(m_localOBB.localToParent);
*stream << center;
*stream << m_localOBB.sphereRadius;
}
//
//-----------------------------------------------------------
// Write out the child count and then the children themselves
//-----------------------------------------------------------
//
ChainIteratorOf<ElementRenderer::Element*> elements(&m_group);
ElementRenderer::Element *element;
*stream << elements.GetSize();
while ((element = elements.ReadAndNext()) != NULL)
{
Check_Object(element);
element->Save(stream);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void*
Tile::TestTile(
ElementRenderer::GridElement *grid,
WORD cell,
ElementRenderer::CollisionQuery *query,
Scalar enter,
Scalar leave
)
{
Check_Object(grid);
Check_Object(query);
Verify(query->m_line->m_length >= 0.0f);
Entity::CollisionQuery *masked_query =
Cast_Pointer(Entity::CollisionQuery*, query);
//
//-------------------------------
// Figure out what tile we are in
//-------------------------------
//
Tile *tile = Cast_Object(Tile*, grid->GetIndexedElement(cell));
Entity *result = NULL;
//
//-----------------------------------------------
// Find the zone - it should be the grid's parent
//-----------------------------------------------
//
if (masked_query->m_collisionMask&Entity::WalkerMask)
{
Zone *zone = tile->m_zone;
Check_Object(zone);
Normal3D normal;
Check_Object(masked_query->m_line);
normal.Vector3D::Negate(masked_query->m_line->m_direction);
TerrainBSP::CollisionQuery
bsp_query(masked_query->m_line, &normal, zone, tile);
//
//-------------------------
// Try out our new BSP code
//-------------------------
//
bool hit;
Check_Object(tile->m_BSP);
{
RAYCAST_LOGIC("vs. BSPs");
Start_Timer(Ray_Vs_BSP);
hit = tile->m_BSP->TestLine(&bsp_query, enter, leave);
Stop_Timer(Ray_Vs_BSP);
}
if (hit)
{
*masked_query->m_normal = normal;
//
//------------------------------------------------------------------------
// This is turned off for now because I couldn't figure out the case where
// a ray exits one tile and enters another tile underneath the terrain - I
// suspect it has something to do with roundoff errors
//------------------------------------------------------------------------
//
Verify(*query->m_normal * query->m_line->m_direction < -SMALL);
Point3D impact;
query->m_line->FindEnd(&impact);
query->m_material = zone->GetMaterial(impact);
result = Map::GetInstance();
}
}
//
//---------------------------
// Check each collidee entity
//---------------------------
//
ChainIteratorOf<Entity*> collidees(&tile->m_collidees);
Entity *entity;
while ((entity = collidees.ReadAndNext()) != NULL)
{
Check_Object(entity);
Verify(!entity->IsACollider());
Verify(entity->GetInterestLevel() != Entity::DormantInterestLevel);
//
//---------------------------------------------------------------------
// If the ray is coming from us, don't check. Also don't bother if the
// masks don't match
//---------------------------------------------------------------------
//
if (
entity == masked_query->m_raySource
|| !entity->CouldCollideWith(masked_query->m_collisionMask)
)
continue;
//
//-----------------------------------------------------------------------
// If there is a hit on this element, set the return value and figure out
// the relative position of the hit to the target entity
//-----------------------------------------------------------------------
//
CollisionVolume *bounds = entity->GetHierarchicalVolume();
if (!bounds)
bounds = entity->GetSolidVolume();
Check_Object(bounds);
{
RAYCAST_LOGIC("vs. Collidees");
Start_Timer(Ray_Vs_OBB);
Verify(query->m_line->m_length >= 0.0f);
bounds = bounds->CastRay(masked_query, entity, entity->GetLocalToWorld());
Stop_Timer(Ray_Vs_OBB);
}
if (bounds)
{
result = bounds->m_entity;
query->m_data = NULL;
}
}
//
//---------------------------
// Check each collider entity
//---------------------------
//
ChainIteratorOf<Entity*> colliders(&tile->m_colliders);
while ((entity = colliders.ReadAndNext()) != NULL)
{
Check_Object(entity);
Verify(entity->IsACollider());
Verify(entity->GetInterestLevel() != Entity::DormantInterestLevel);
//
//---------------------------------------------------------------------
// If the ray is coming from us, don't check. Also don't bother if the
// masks don't match
//---------------------------------------------------------------------
//
if (
entity == masked_query->m_raySource
|| !entity->CouldCollideWith(masked_query->m_collisionMask)
)
continue;
//
//-----------------------------------------------------------------------
// If there is a hit on this element, set the return value and figure out
// the relative position of the hit to the target entity
//-----------------------------------------------------------------------
//
CollisionVolume *bounds = entity->GetHierarchicalVolume();
if (!bounds)
bounds = entity->GetSolidVolume();
Check_Object(bounds);
{
RAYCAST_LOGIC("vs. Colliders");
Start_Timer(Ray_Vs_OBB);
bounds = bounds->CastRay(masked_query, entity, entity->GetLocalToWorld());
Stop_Timer(Ray_Vs_OBB);
}
if (bounds)
{
result = bounds->m_entity;
query->m_data = NULL;
}
}
return result;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Tile::SetDrawState()
{
Check_Object(this);
m_draw = static_cast<DrawMethod>(&Tile::Draw);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Tile::Draw(
ElementRenderer::CameraElement *camera,
const ElementRenderer::StateChange *inherited_state,
int culling_state
)
{
Check_Object(this);
Check_Object(inherited_state);
Check_Object(camera);
Verify(culling_state != -1);
//
//--------------------------
// Construct our light array
//--------------------------
//
if (m_lightsChanged)
UpdateLights();
//
//-------------------
// Mix the properties
//-------------------
//
Check_Object(m_stateChange);
ElementRenderer::StateChange mixed;
mixed.Mix(*inherited_state, *m_stateChange);
MixLights(
mixed.m_lights,
inherited_state->m_lights,
m_stateChange->m_lights
);
//
//--------------------------------------
// Draw our bounds if we are supposed to
//--------------------------------------
//
#if defined(LAB_ONLY)
Callback *callback = GetCallbackSet();
unsigned index = GetCallbackIndex();
if (callback && callback[index])
{
Check_Pointer(callback[index]);
(*callback[index])(camera, inherited_state, culling_state, this);
}
#endif
//
//------------------
// Draw our children
//------------------
//
ChainIteratorOf<ElementRenderer::Element*> children(&m_group);
ElementRenderer::Element *child;
while ((child = children.ReadAndNext()) != NULL)
{
Check_Object(child);
//
//---------------------
// Deal with the ground
//---------------------
//
if (child==m_ground)
{
#if defined(LAB_ONLY)
if (Hide_Ground)
continue;
#endif
if (s_GroundColor)
{
RGBAColor old(Element::FadeColor);
Element::FadeColor = *s_GroundColor;
camera->DrawElement(child, &mixed);
Element::FadeColor = old;
}
else
camera->DrawElement(child, &mixed);
}
//
//------------------------
// Draw our other children
//------------------------
//
else
{
#if defined(LAB_ONLY)
if (Hide_TileEntities)
continue;
#endif
camera->DrawElement(child, &mixed);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Tile::UpdateLights()
{
Check_Object(this);
Verify(m_lightsChanged);
ChainIteratorOf<FiniteLight*> light_chain(&m_lights);
gosFX::Light *light;
Check_Object(m_stateChange);
int i=0;
while (
(light = light_chain.ReadAndNext()) != NULL
&& i<MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive
)
{
Check_Object(light);
if(light->m_light->GetIntensity()>Stuff::SMALL)
{
m_stateChange->m_lights[i++] = light->m_light;
}
}
if (i < MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive)
m_stateChange->m_lights[i] = NULL;
Verify(i <= MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive);
m_lightsChanged = false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Tile::AddEntityToDamagableList(Entity* entity)
{
if (!entity->IsDestroyable())
return;
if (Application::GetInstance()->GetApplicationState() != ApplicationStateEngine::LoadingGameState)
{
return;
}
if (m_damagableEntityCount >= damagableEntityList.GetLength())
{
damagableEntityList.SetLength(m_damagableEntityCount + 10);
}
damagableEntityList[m_damagableEntityCount] = entity;
++m_damagableEntityCount;
}