Added code for placement of socketted buildings.

This was SVN commit r4073.
This commit is contained in:
Matei 2006-07-09 23:12:37 +00:00
parent eaf12ae666
commit 1034a980fe
15 changed files with 145 additions and 79 deletions

View File

@ -195,6 +195,10 @@ void CGameView::RenderModels(CUnitManager *pUnitMan, CProjectileManager *pProjec
const std::vector<CUnit*>& units=pUnitMan->GetUnits();
for (uint i=0;i<units.size();++i)
{
CEntity* ent = units[i]->GetEntity();
if( ent && !ent->m_visible )
continue;
int status = losMgr->GetUnitStatus(units[i], g_Game->GetLocalPlayer());
CModel* model = units[i]->GetModel();

View File

@ -16,6 +16,7 @@
#include "SkeletonAnimDef.h"
#include "SkeletonAnimManager.h"
#include "MeshManager.h"
#include "ObjectEntry.h"
#include "lib/res/graphics/ogl_tex.h"
#include "lib/res/h_mgr.h"
#include "ps/Profile.h"
@ -500,6 +501,8 @@ void CModel::SetPlayerColor(CColor& colour)
void CModel::SetShadingColor(CColor& colour)
{
m_ShadingColor = colour;
for (std::vector<Prop>::iterator it = m_Props.begin(); it != m_Props.end(); ++it)
for( std::vector<Prop>::iterator it = m_Props.begin(); it != m_Props.end(); ++it )
{
it->m_Model->SetShadingColor(colour);
}
}

View File

@ -17,6 +17,7 @@
#include "ps/CConsole.h"
#include "ObjectManager.h"
#include "ObjectEntry.h"
#include "simulation/Entity.h"
#include "simulation/LOSManager.h"
#include "simulation/TerritoryManager.h"
@ -96,6 +97,10 @@ CUnit* CUnitManager::PickUnit(const CVector3D& origin, const CVector3D& dir) con
CUnit* unit = m_Units[i];
float tmin, tmax;
CEntity* ent = unit->GetEntity();
if( ent && !ent->m_visible )
continue;
if (unit->GetModel()->GetBounds().RayIntersect(origin, dir, tmin, tmax)
&& losMgr->GetUnitStatus(unit, g_Game->GetLocalPlayer()) != UNIT_HIDDEN)
{

View File

@ -332,16 +332,6 @@ void Render()
glDisable( GL_DEPTH_TEST );
PROFILE_END( "render selection" );
PROFILE_START( "render building placement cursor" );
if( g_BuildingPlacer.m_active )
{
//glEnable( GL_DEPTH_TEST );
g_BuildingPlacer.render();
//glDisable( GL_DEPTH_TEST );
}
PROFILE_END( "render building placement cursor" );
PROFILE_START( "render health bars" );
pglActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);

View File

@ -1310,29 +1310,29 @@ bool CBuildingPlacer::activate(CStrW& templateName)
m_totalTime = 0;
m_valid = false;
CBaseEntity* base = g_EntityTemplateCollection.getTemplate( m_templateName );
m_template = g_EntityTemplateCollection.getTemplate( m_templateName );
if( !base )
if( !m_template )
{
deactivate();
return false;
}
// m_actor
CStr actorName ( base->m_actorName ); // convert CStrW->CStr8
CStr actorName ( m_template->m_actorName ); // convert CStrW->CStr8
std::set<CStrW> selections;
m_actor = g_UnitMan.CreateUnit( actorName, 0, selections );
m_actor->SetPlayerID(g_Game->GetLocalPlayer()->GetPlayerID());
// m_bounds
if( base->m_bound_type == CBoundingObject::BOUND_CIRCLE )
if( m_template->m_bound_type == CBoundingObject::BOUND_CIRCLE )
{
m_bounds = new CBoundingCircle( 0, 0, base->m_bound_circle );
m_bounds = new CBoundingCircle( 0, 0, m_template->m_bound_circle );
}
else if( base->m_bound_type == CBoundingObject::BOUND_OABB )
else if( m_template->m_bound_type == CBoundingObject::BOUND_OABB )
{
m_bounds = new CBoundingBox( 0, 0, CVector2D(1, 0), base->m_bound_box );
m_bounds = new CBoundingBox( 0, 0, CVector2D(1, 0), m_template->m_bound_box );
}
return true;
@ -1341,7 +1341,8 @@ bool CBuildingPlacer::activate(CStrW& templateName)
void CBuildingPlacer::mousePressed()
{
CCamera &g_Camera=*g_Game->GetView()->GetCamera();
clickPos = g_Camera.GetWorldCoordinates();
if( m_template->m_socket == L"" )
clickPos = g_Camera.GetWorldCoordinates();
m_clicked = true;
}
@ -1349,12 +1350,9 @@ void CBuildingPlacer::mouseReleased()
{
deactivate(); // do it first in case we fail for any reason
if(m_valid)
if( m_valid )
{
//HEntity ent = g_EntityManager.createFoundation( m_templateName, clickPos, m_angle );
//ent->SetPlayer(g_Game->GetLocalPlayer());
// Issue a command accross the network
// issue a place object command accross the network
CPlaceObject *msg = new CPlaceObject();
msg->m_Entities = g_Selection.m_selected;
msg->m_Template = m_templateName;
@ -1383,8 +1381,9 @@ void CBuildingPlacer::update( float timeStep )
m_totalTime += timeStep;
if(m_clicked)
if( m_clicked && m_template->m_socket == L"" )
{
// Rotate object
m_timeSinceClick += timeStep;
CCamera &g_Camera=*g_Game->GetView()->GetCamera();
CVector3D mousePos = g_Camera.GetWorldCoordinates();
@ -1404,7 +1403,7 @@ void CBuildingPlacer::update( float timeStep )
}
CVector3D pos;
if(m_clicked)
if( m_clicked )
{
pos = clickPos;
}
@ -1414,6 +1413,23 @@ void CBuildingPlacer::update( float timeStep )
pos = g_Camera.GetWorldCoordinates();
}
bool onSocket = false;
if( m_template->m_socket != L"" )
{
// If we're on a socket of our type, remember that and snap ourselves to it
m_bounds->setPosition(pos.X, pos.Z); // first, move bounds to mouse pos
CEntity* ent = getCollisionEntity( m_bounds, 0, L"" ); // now, check what we intersect
if( ent && ent->m_classes.IsMember( m_template->m_socket ) ) // if it's a socket, snap to it
{
onSocket = true;
m_angle = atan2f( ent->m_ahead.x, ent->m_ahead.y );
pos = ent->m_position;
clickPos = ent->m_position;
}
}
// Set position and angle to the location we decided on
CMatrix3D m;
float s = sin( m_angle );
float c = cos( m_angle );
@ -1425,52 +1441,33 @@ void CBuildingPlacer::update( float timeStep )
m_bounds->setPosition(pos.X, pos.Z);
if(m_bounds->m_type == CBoundingObject::BOUND_OABB)
if( m_bounds->m_type == CBoundingObject::BOUND_OABB )
{
CBoundingBox* box = (CBoundingBox*) m_bounds;
box->setOrientation(m_angle);
box->setOrientation( m_angle );
}
// It's valid to place the object here if the position is on the map and it's
// unobstructed by anything except possibly our socket (which we find out by
// by passing an ignoreClass to getCollisionObject); also, if we are a
// socketted object, we check that we are in fact on a socket, using onSocket.
CTerrain *pTerrain=g_Game->GetWorld()->GetTerrain();
m_valid = pTerrain->isOnMap(pos.X, pos.Z) && getCollisionObject(m_bounds)==0;
m_valid = pTerrain->isOnMap( pos.X, pos.Z )
&& ( m_template->m_socket == L"" || onSocket )
&& ( getCollisionObject( m_bounds, 0, m_template->m_socket ) == 0 );
// Flash our actor red if the position is invalid.
CColor col;
if(m_valid)
if( m_valid )
{
col = CColor(1.0f, 1.0f, 1.0f, 1.0f);
}
else
{
float add = (sin(4*PI*m_totalTime) + 1.0f) * 0.08f;
col = CColor(1.4f+add, 0.4f+add, 0.4f+add, 1.0f);
float add = ( sin(4*PI*m_totalTime) + 1.0f ) * 0.08f;
col = CColor( 1.4f+add, 0.4f+add, 0.4f+add, 1.0f );
}
m_actor->GetModel()->SetShadingColor(col);
}
void CBuildingPlacer::render()
{
// do nothing special - our CUnit will get rendered by the UnitManager
/*if(!m_active)
return;
CVector3D pos;
if(m_clicked)
{
pos = clickPos;
}
else
{
CCamera &g_Camera=*g_Game->GetView()->GetCamera();
pos = g_Camera.GetWorldCoordinates();
}
glBegin(GL_LINE_STRIP);
glColor3f(1,1,1);
glVertex3f(pos.X, pos.Y+6, pos.Z);
glColor3f(1,1,1);
glVertex3f(pos.X, pos.Y, pos.Z);
glColor3f(1,1,1);
glVertex3f(pos.X + 3*sin(m_angle), pos.Y, pos.Z + 3*cos(m_angle));
glEnd();*/
m_actor->GetModel()->SetShadingColor( col );
}

View File

@ -16,6 +16,7 @@
class CVector3D;
class CUnit;
class CBaseEntity;
class CBoundingObject;
#define MAX_BOOKMARKS 10
@ -154,6 +155,7 @@ struct CBuildingPlacer : public Singleton<CBuildingPlacer>
}
CStrW m_templateName;
CBaseEntity* m_template;
bool m_active;
bool m_clicked;
bool m_dragged;
@ -170,7 +172,6 @@ struct CBuildingPlacer : public Singleton<CBuildingPlacer>
void mousePressed();
void mouseReleased();
void update( float timeStep );
void render();
};
bool isMouseoverType( CEntity* ev, void* userdata );

View File

@ -282,8 +282,8 @@ JSBool issueCommand( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rv
CNetMessage* msg = CNetMessage::CommandFromJSArgs(msgEntities, cx, argc-1, argv+1);
if (!msg)
{
return JS_TRUE;
delete msg;
return JS_TRUE;
}
messages.push_back(msg);

View File

@ -69,6 +69,7 @@ CBaseEntity::CBaseEntity( CPlayer* player )
AddProperty( L"traits.vision.permanent", &m_permanent );
AddProperty( L"traits.is_territory_centre", &m_isTerritoryCentre );
AddProperty( L"traits.foundation", &m_foundation );
AddProperty( L"traits.socket", &m_socket );
for( int t = 0; t < EVENT_LAST; t++ )
{
@ -80,6 +81,7 @@ CBaseEntity::CBaseEntity( CPlayer* player )
m_speed = m_turningRadius = 0.0f;
m_extant = true;
m_foundation = CStrW();
m_socket = CStrW();
m_passThroughAllies = false;
m_sectorDivs = 4;

View File

@ -116,6 +116,9 @@ public:
// Foundation entity, or "" for none
CStrW m_foundation;
// Socket entity that we can be built on, or "" for free placement
CStrW m_socket;
float m_speed;
float m_runSpeed;
float m_runRegenRate;

View File

@ -45,7 +45,7 @@ CEntity* GetCollisionObject( float x, float y )
return( NULL );
}
CBoundingObject* getCollisionObject( CBoundingObject* bounds, CPlayer* player )
CBoundingObject* getCollisionObject( CBoundingObject* bounds, CPlayer* player, CStrW ignoreClass )
{
std::vector<CEntity*> entities;
g_EntityManager.GetInRange( bounds->m_pos.x, bounds->m_pos.y, COLLISION_RANGE, entities );
@ -55,9 +55,13 @@ CBoundingObject* getCollisionObject( CBoundingObject* bounds, CPlayer* player )
{
if( !(*it)->m_bounds ) continue;
if( (*it)->m_bounds == bounds ) continue;
/* If the unit is marked to ignore ally collisions, and the player parameter
is passed in and the same player as the unit, then ignore the (potential) collision */
if( player && (*it)->m_passThroughAllies && (*it)->m_player == player ) continue;
if( (*it)->m_classes.IsMember( ignoreClass ) ) continue;
if( bounds->intersects( (*it)->m_bounds ) )
{
CBoundingObject* obj = (*it)->m_bounds;
@ -68,6 +72,32 @@ CBoundingObject* getCollisionObject( CBoundingObject* bounds, CPlayer* player )
return( NULL );
}
CEntity* getCollisionEntity( CBoundingObject* bounds, CPlayer* player, CStrW ignoreClass )
{
std::vector<CEntity*> entities;
g_EntityManager.GetInRange( bounds->m_pos.x, bounds->m_pos.y, COLLISION_RANGE, entities );
std::vector<CEntity*>::iterator it;
for( it = entities.begin(); it != entities.end(); it++ )
{
if( !(*it)->m_bounds ) continue;
if( (*it)->m_bounds == bounds ) continue;
/* If the unit is marked to ignore ally collisions, and the player parameter
is passed in and the same player as the unit, then ignore the (potential) collision */
if( player && (*it)->m_passThroughAllies && (*it)->m_player == player ) continue;
if( (*it)->m_classes.IsMember( ignoreClass ) ) continue;
if( bounds->intersects( (*it)->m_bounds ) )
{
return (*it);
}
}
return( NULL );
}
HEntity getCollisionObject( CEntity* entity )
{
#ifndef NDEBUG

View File

@ -34,7 +34,8 @@ typedef std::vector<CEntity*> RayIntersects;
HEntity getCollisionObject( CEntity* entity );
HEntity getCollisionObject( CEntity* entity, float x, float y );
CBoundingObject* getCollisionObject( CBoundingObject* bounds, CPlayer* player=0 );
CBoundingObject* getCollisionObject( CBoundingObject* bounds, CPlayer* player=0, CStrW ignoreClass=L"" );
CEntity* getCollisionEntity( CBoundingObject* bounds, CPlayer* player=0, CStrW ignoreClass=L"" );
CBoundingObject* getContainingObject( const CVector2D& point );
CEntity* GetCollisionObject( float x, float y ); // Point collision
bool getRayIntersection( const CVector2D& source, const CVector2D& forward, const CVector2D& right, float length, float maxDistance, CBoundingObject* destinationCollisionObject, rayIntersectionResults* results );

View File

@ -106,6 +106,7 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation, cons
AddProperty( L"last_combat_time", &m_lastCombatTime );
AddProperty( L"last_run_time", &m_lastRunTime );
AddProperty( L"building", &m_building );
AddProperty( L"visible", &m_visible );
m_productionQueue = new CProductionQueue( this );
AddProperty( L"production_queue", m_productionQueue );
@ -168,6 +169,8 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation, cons
m_building = building;
m_visible = true;
m_associatedTerritory = 0;
m_player = g_Game->GetPlayer( 0 );
@ -243,6 +246,13 @@ void CEntity::loadBase()
// Make sure the actor has the right player colour
m_actor->SetPlayerID( m_player->GetPlayerID() );
}
// Re-enter all our auras so they can take into account our new traits
for( AuraSet::iterator it = m_aurasInfluencingMe.begin();
it != m_aurasInfluencingMe.end(); it++ )
{
(*it)->Remove( this );
}
}
void CEntity::initAttributes(const CEntity* _this)
@ -340,6 +350,10 @@ void CEntity::SetPlayer(CPlayer *pPlayer)
// Store the ID of the player in the associated model
if( m_actor )
m_actor->SetPlayerID( m_player->GetPlayerID() );
// If we're a territory centre, change the territory's owner
if( m_associatedTerritory )
m_associatedTerritory->owner = pPlayer;
}
void CEntity::updateActorTransforms()
@ -909,8 +923,13 @@ void CEntity::teleport()
void CEntity::playerChanged()
{
// Set actor player colour
if( m_actor )
m_actor->SetPlayerID( m_player->GetPlayerID() );
// If we're a territory centre, change the territory's owner
if( m_associatedTerritory )
m_associatedTerritory->owner = m_player;
}
void CEntity::checkSelection()
@ -992,6 +1011,8 @@ void CEntity::invalidateActor()
void CEntity::render()
{
if( !m_visible ) return;
if( !m_orderQueue.empty() )
{
std::deque<CEntityOrder>::iterator it;
@ -1120,15 +1141,17 @@ int CEntity::findSector( int divs, float angle, float maxAngle, bool negative )
}
void CEntity::renderSelectionOutline( float alpha )
{
if( !m_bounds )
if( !m_bounds || !m_visible )
return;
if( getCollisionObject( this ) )
glColor4f( 1.0f, 0.5f, 0.5f, alpha );
if( getCollisionObject( m_bounds, m_player, m_base->m_socket ) )
{
glColor4f( 1.0f, 0.5f, 0.5f, alpha ); // We're colliding with another unit; colour outline pink
}
else
{
const SPlayerColour& col = m_player->GetColour();
glColor3f( col.r, col.g, col.b );
glColor3f( col.r, col.g, col.b ); // Colour outline with player colour
}
glBegin( GL_LINE_LOOP );
@ -1229,7 +1252,10 @@ CVector2D CEntity::getScreenCoords( float height )
return CVector2D( sx, sy );
}
void CEntity::renderBarBorders()
{
{
if( !m_visible )
return;
if ( m_staminaBarHeight >= 0 &&
g_Selection.m_unitUITextures.find(m_healthBorderName) != g_Selection.m_unitUITextures.end() )
{
@ -1275,7 +1301,7 @@ void CEntity::renderBarBorders()
}
void CEntity::renderHealthBar()
{
if( !m_bounds )
if( !m_bounds || !m_visible )
return;
if( m_healthBarHeight < 0 )
return; // negative bar height means don't display health bar
@ -1312,7 +1338,7 @@ void CEntity::renderHealthBar()
void CEntity::renderStaminaBar()
{
if( !m_bounds )
if( !m_bounds || !m_visible )
return;
if( m_staminaBarHeight < 0 )
return; // negative bar height means don't display stamina bar
@ -1346,7 +1372,7 @@ void CEntity::renderStaminaBar()
}
void CEntity::renderRank()
{
if( !m_bounds )
if( !m_bounds || !m_visible )
return;
if( m_rankHeight < 0 )
return; // negative height means don't display rank
@ -1385,6 +1411,9 @@ void CEntity::renderRank()
}
void CEntity::renderRallyPoint()
{
if( !m_visible )
return;
if ( !m_hasRallyPoint || g_Selection.m_unitUITextures.find(m_rallyTexture) ==
g_Selection.m_unitUITextures.end() )
{

View File

@ -105,6 +105,9 @@ public:
// If this unit is still active in the gameworld - i.e. not a corpse.
bool m_extant;
// If this is false, the unit will not be drawn and cannot be interacted with using the mouse.
bool m_visible;
bool m_isRunning; //is it actually running
bool m_shouldRun; //if run was issued, it will remain true until it is stopped
bool m_triggerRun; //used in SetRun, corrects 1 frame stamina imbalance

View File

@ -73,7 +73,7 @@ void CTerritoryManager::Recalculate()
boundary.push_back( CVector2D(mapSize, mapSize) );
boundary.push_back( CVector2D(mapSize, 0) );
CTerritory* ter = new CTerritory( g_Game->GetPlayer(0), 0, boundary );
CTerritory* ter = new CTerritory( g_Game->GetPlayer(0), HEntity(), boundary );
m_Territories.push_back(ter);
@ -93,7 +93,7 @@ void CTerritoryManager::Recalculate()
std::vector<CVector2D> boundary;
CalculateBoundary( centres, i, boundary );
CTerritory* ter = new CTerritory( centres[i]->GetPlayer(), centres[i], boundary );
CTerritory* ter = new CTerritory( centres[i]->GetPlayer(), centres[i]->me, boundary );
centres[i]->m_associatedTerritory = ter;
m_Territories.push_back(ter);
@ -201,6 +201,4 @@ void CTerritoryManager::CalculateBoundary( std::vector<CEntity*>& centres, size_
boundary = newBoundary;
}
}
debug_printf("Created a boundary polygon with %d edges around index %d\n", boundary.size(), myIndex);
}

View File

@ -24,10 +24,10 @@ class CTerritory
{
public:
CPlayer* owner; // owner of the territory, or Gaia for none
CEntity* centre; // centre object of this territory
HEntity centre; // centre object of this territory
std::vector<CVector2D> boundary; // boundary polygon, in map coordinates
CTerritory(CPlayer* owner_, CEntity* centre_, std::vector<CVector2D> boundary_)
CTerritory(CPlayer* owner_, HEntity centre_, std::vector<CVector2D> boundary_)
: owner(owner_), centre(centre_), boundary(boundary_) {}
};