diff --git a/source/graphics/Terrain.cpp b/source/graphics/Terrain.cpp index 09166bb8bb..718702b7b8 100644 --- a/source/graphics/Terrain.cpp +++ b/source/graphics/Terrain.cpp @@ -210,102 +210,25 @@ float CTerrain::getSlope(float x, float z) const return MAX(MAX(h00, h01), MAX(h10, h11)) - MIN(MIN(h00, h01), MIN(h10, h11)); } -CVector2D CTerrain::getSlopeAngleFace(float x, float y, CEntity*& entity ) const +CVector2D CTerrain::getSlopeAngleFace( CEntity* entity ) const { - //side start at 0 at -180 degrees, and end up at 7 at 180 degrees - int side; - bool invert; - float top, bottom, topZ, bottomZ; - float fCell = (float)CELL_SIZE; - x /= fCell; - y /= fCell; - int xi = (int)floor(x); - int yi = (int)floor(y); - - CVector3D flat(0.0f, 0.0f, 0.0f); - CVector3D flatZ = flat; CVector2D ret; - side = entity->findSector( 8, entity->m_orientation.Y, DEGTORAD(360.0f) ) - 1; - - //Wrap around - if ( side < 0 ) - side += 8; - - //Keep it in bounds - clampCoordToMap(xi); - clampCoordToMap(yi); - - float h00 = m_Heightmap[yi*m_MapSize + xi] * HEIGHT_SCALE; - float h01 = m_Heightmap[yi*m_MapSize + xi + m_MapSize] * HEIGHT_SCALE; - float h10 = m_Heightmap[yi*m_MapSize + xi + 1] * HEIGHT_SCALE; - float h11 = m_Heightmap[yi*m_MapSize + xi + m_MapSize + 1] * HEIGHT_SCALE; - //Find heights - if ( side == 0 || side == 7 ) - { - top = (h00 + h10)/2.0f; - bottom = (h01 + h11)/2.0f; - topZ = (h00 + h01)/2.0f; - bottomZ = (h10 + h11)/2.0f; - flat.Z = sqrtf(SQR(CELL_SIZE) - SQR(top-bottom)); - flatZ.X = sqrtf(SQR(CELL_SIZE) - SQR(topZ-bottomZ)); - } - else if ( side == 1 || side == 2 ) - { - top = (h00 + h01)/2.0f; - bottom = (h10 + h11)/2.0f; - topZ = (h01 + h11)/2.0f; - bottomZ = (h00 + h10)/2.0f; - flat.X = sqrtf(SQR(CELL_SIZE) - SQR(top-bottom)); - flatZ.Z = sqrtf(SQR(CELL_SIZE) - SQR(topZ-bottomZ)); - } - else if ( side == 3 || side == 4 ) - { - top = (h01 + h11)/2.0f; - bottom = (h00 + h10)/2.0f; - topZ = (h11 + h10)/2.0f; - bottomZ = (h00 + h01)/2.0f; - flat.Z = sqrtf(SQR(CELL_SIZE) - SQR(top-bottom)); - flatZ.X = sqrtf(SQR(CELL_SIZE) - SQR(topZ-bottomZ)); - } - else - { - top = (h11 + h10)/2.0f; - bottom = (h00 + h01)/2.0f; - topZ = (h00 + h10)/2.0f; - bottomZ = (h01 + h11)/2.0f; - flat.X = sqrtf(SQR(CELL_SIZE) - SQR(top-bottom)); - flatZ.Z = sqrtf(SQR(CELL_SIZE) - SQR(topZ-bottomZ)); - } - CVector3D elevated=flat; - elevated.Y = top-bottom; - if ( elevated.Y > 0.0f ) - invert=false; - else - invert=true; - elevated.Y = fabs(elevated.Y); - elevated.Normalize(); - flat.Normalize(); - if ( invert ) - ret.x = -acosf( elevated.Dot(flat) ); - else - ret.x = acosf( elevated.Dot(flat) ); - - //Z component - elevated = flatZ; - elevated.Y = topZ-bottomZ; - if ( elevated.Y > 0.0f ) - invert=true; - else - invert=false; - elevated.Y = fabs(elevated.Y); - elevated.Normalize(); - flatZ.Normalize(); - if ( invert ) - ret.y = -acosf( elevated.Dot(flatZ) ); - else - ret.y = acosf( elevated.Dot(flatZ) ); - + const float D = 0.1f; // Amount to look forward to calculate the slope + float x = entity->m_position.X; + float z = entity->m_position.Z; + float y = getExactGroundLevel(x, z); + + // Get forward slope and use it as the x angle + CVector2D d = entity->m_ahead.normalize() * D; + float dy = getExactGroundLevel(x+d.x, z+d.y) - y; + ret.x = atan2(dy, D); + + // Get sideways slope and use it as the y angle + CVector2D d2(-d.y, d.x); + float dy2 = getExactGroundLevel(x+d2.x, z+d2.y) - y; + ret.y = atan2(dy2, D); + return ret; } diff --git a/source/graphics/Terrain.h b/source/graphics/Terrain.h index 6bc12bd2a2..722d74602d 100644 --- a/source/graphics/Terrain.h +++ b/source/graphics/Terrain.h @@ -69,7 +69,7 @@ public: float getSlope(float x, float z) const ; //Find the slope of in X and Z axes depending on the way the entity is facing - CVector2D getSlopeAngleFace(float x, float y, CEntity*& entity) const; + CVector2D getSlopeAngleFace(CEntity* entity) const; // resize this terrain such that each side has given number of patches void Resize(u32 size); diff --git a/source/scripting/EventTypes.h b/source/scripting/EventTypes.h index b927504200..242cf24e7b 100644 --- a/source/scripting/EventTypes.h +++ b/source/scripting/EventTypes.h @@ -24,7 +24,6 @@ enum EEventType EVENT_NOTIFICATION, EVENT_FORMATION, EVENT_IDLE, - EVENT_MOVEMENT, EVENT_LAST, // Projectile events @@ -55,7 +54,6 @@ static const wchar_t* const EventNames[EVENT_LAST] = /* EVENT_NOTIFICATION */ L"onNotification", /*When we receive a notification */ /* EVENT_FORMATION */ L"onFormation", /* When this unit does something with a formation */ /* EVENT_IDLE */ L"onIdle", /* When this unit becomes idle, do something */ - /* EVENT_MOVEMENT */ L"onMovement" /*Triggered by processGotoHelper(), when unit moves */ }; #endif // #ifndef EVENTTYPES_H__ diff --git a/source/simulation/Collision.cpp b/source/simulation/Collision.cpp index 282b0d1807..c1ffdde2a7 100644 --- a/source/simulation/Collision.cpp +++ b/source/simulation/Collision.cpp @@ -100,7 +100,7 @@ CEntity* getCollisionEntity( CBoundingObject* bounds, CPlayer* player, const CSt return( NULL ); } -HEntity getCollisionObject( CEntity* entity ) +HEntity getCollisionObject( CEntity* entity, bool enablePassThroughAllies ) { #ifndef NDEBUG debug_assert( entity->m_bounds ); @@ -116,8 +116,13 @@ HEntity getCollisionObject( CEntity* entity ) { if( !(*it)->m_bounds ) continue; if( (*it)->m_bounds == entity->m_bounds ) continue; - if( entity->m_base->m_passThroughAllies && (*it)->m_base->m_passThroughAllies - && entity->GetPlayer() == (*it)->GetPlayer() ) continue; + + if( enablePassThroughAllies + && entity->m_base->m_passThroughAllies + && (*it)->m_base->m_passThroughAllies + && entity->GetPlayer() == (*it)->GetPlayer() ) + continue; + if( entity->m_bounds->intersects( (*it)->m_bounds ) ) { HEntity collisionObject = HEntity((*it)->me); diff --git a/source/simulation/Collision.h b/source/simulation/Collision.h index ec29a5870b..884330cd50 100644 --- a/source/simulation/Collision.h +++ b/source/simulation/Collision.h @@ -35,7 +35,7 @@ struct rayIntersectionResults typedef std::vector RayIntersects; -HEntity getCollisionObject( CEntity* entity ); +HEntity getCollisionObject( CEntity* entity, bool enablePassThroughAllies=true ); HEntity getCollisionObject( CEntity* entity, float x, float y ); CBoundingObject* getCollisionObject( CBoundingObject* bounds, CPlayer* player=0, const CStrW* ignoreClass=0 ); CEntity* getCollisionEntity( CBoundingObject* bounds, CPlayer* player=0, const CStrW* ignoreClass=0 ); diff --git a/source/simulation/EntityManager.cpp b/source/simulation/EntityManager.cpp index 3bf9e5fbe1..903bdf1d8c 100644 --- a/source/simulation/EntityManager.cpp +++ b/source/simulation/EntityManager.cpp @@ -296,7 +296,7 @@ void CEntityManager::conformAll() if( isEntityRefd(i) ) { CEntity* entity = m_entities[i].m_entity; - CVector2D targetXZ = g_Game->GetWorld()->GetTerrain()->getSlopeAngleFace( entity->m_position.X, entity->m_position.Z, entity ); + CVector2D targetXZ = g_Game->GetWorld()->GetTerrain()->getSlopeAngleFace(entity ); while( targetXZ.x > PI ) targetXZ.x -= 2 * PI; while( targetXZ.x < -PI ) targetXZ.x += 2 * PI; diff --git a/source/simulation/EntityScriptInterface.cpp b/source/simulation/EntityScriptInterface.cpp index e548a6663d..9921a80a13 100644 --- a/source/simulation/EntityScriptInterface.cpp +++ b/source/simulation/EntityScriptInterface.cpp @@ -87,7 +87,7 @@ void CEntity::ScriptingInit() /* Any inherited property MUST be added to EntityTemplate.cpp as well */ - AddClassProperty( L"actions.move.speedCurr", &CEntity::m_speed ); + AddClassProperty( L"actions.move.speed", &CEntity::m_speed ); AddClassProperty( L"actions.move.run.speed", &CEntity::m_runSpeed ); AddClassProperty( L"actions.move.run.rangemin", &CEntity::m_runMinRange ); AddClassProperty( L"actions.move.run.range", &CEntity::m_runMaxRange ); diff --git a/source/simulation/EntityStateProcessing.cpp b/source/simulation/EntityStateProcessing.cpp index 55ed3f0729..7afba1d7fb 100644 --- a/source/simulation/EntityStateProcessing.cpp +++ b/source/simulation/EntityStateProcessing.cpp @@ -57,9 +57,14 @@ float CEntity::chooseMovementSpeed( float distance ) { bool should_run = shouldRun(distance); - const float speed = should_run? m_runSpeed : m_speed; + float speed = should_run? m_runSpeed : m_speed; const char* anim_name = should_run? "run" : "walk"; + // Modify the speed based on the slope of the terrain in our direction (obtained from our x orientation) + float angle = m_orientation_unclamped.x; + int sector = ia32_rintf( angle / (PI/2) * m_base->m_pitchDivs ); + speed -= sector * m_base->m_pitchValue; + // TODO: the animation code requires unicode for now. will be changed to // 8bit later (for consistency; note that filenames etc. need not be // unicode), so remove this then. @@ -147,8 +152,7 @@ uint CEntity::processGotoHelper( CEntityOrder* current, size_t timestep_millis, m_ahead = delta / len; m_orientation.Y = m_targetorientation; } - CEntity* _this = this; - CVector2D targetXZ = g_Game->GetWorld()->GetTerrain()->getSlopeAngleFace( m_position.X, m_position.Z, _this ); + CVector2D targetXZ = g_Game->GetWorld()->GetTerrain()->getSlopeAngleFace(this); while( targetXZ.x > PI ) targetXZ.x -= 2 * PI; while( targetXZ.x < -PI ) targetXZ.x += 2 * PI; @@ -161,8 +165,8 @@ uint CEntity::processGotoHelper( CEntityOrder* current, size_t timestep_millis, m_orientation_unclamped.x = targetXZ.x; m_orientation_unclamped.y = targetXZ.y; - CMovementEvent evt( m_orientation_unclamped.x ); - DispatchEvent(&evt); + //CMovementEvent evt( m_orientation_unclamped.x ); + //DispatchEvent(&evt); if( m_bounds && m_bounds->m_type == CBoundingObject::BOUND_OABB ) ((CBoundingBox*)m_bounds)->setOrientation( m_ahead ); @@ -186,7 +190,11 @@ uint CEntity::processGotoHelper( CEntityOrder* current, size_t timestep_millis, { m_bounds->setPosition( m_position.X, m_position.Z ); - collide = getCollisionObject( this ); + // For now, ignore passThroughAllies for low-level movement (but leave it on for long-range + // pathfinding); ideally we will enable pass-through-allies only for the long-range pathing + // and when the unit is moving to assume its place in a formation, since it looks bad to have + // units stand on each other otherwise. + collide = getCollisionObject( this, false ); if( collide ) { diff --git a/source/simulation/EntityTemplate.cpp b/source/simulation/EntityTemplate.cpp index 6184fb7e16..5aa440a8d3 100644 --- a/source/simulation/EntityTemplate.cpp +++ b/source/simulation/EntityTemplate.cpp @@ -391,7 +391,7 @@ void CEntityTemplate::ScriptingInit() AddClassProperty( L"traits.id.classes", (GetFn)&CEntityTemplate::getClassSet, (SetFn)&CEntityTemplate::setClassSet ); - AddClassProperty( L"actions.move.speedCurr", &CEntityTemplate::m_speed ); + AddClassProperty( L"actions.move.speed", &CEntityTemplate::m_speed ); AddClassProperty( L"actions.move.turningRadius", &CEntityTemplate::m_turningRadius ); AddClassProperty( L"actions.move.run.speed", &CEntityTemplate::m_runSpeed ); AddClassProperty( L"actions.move.run.rangeMin", &CEntityTemplate::m_runMinRange ); @@ -422,6 +422,7 @@ void CEntityTemplate::ScriptingInit() AddClassProperty( L"traits.rally.height", &CEntityTemplate::m_rallyHeight ); AddClassProperty( L"traits.flankPenalty.sectors", &CEntityTemplate::m_sectorDivs ); AddClassProperty( L"traits.pitch.sectors", &CEntityTemplate::m_pitchDivs ); + AddClassProperty( L"traits.pitch.value", &CEntityTemplate::m_pitchValue ); AddClassProperty( L"traits.rank.width", &CEntityTemplate::m_rankWidth ); AddClassProperty( L"traits.rank.height", &CEntityTemplate::m_rankHeight ); AddClassProperty( L"traits.rank.name", &CEntityTemplate::m_rankName ); diff --git a/source/simulation/EntityTemplate.h b/source/simulation/EntityTemplate.h index e1a73ff94b..fd0903fe20 100644 --- a/source/simulation/EntityTemplate.h +++ b/source/simulation/EntityTemplate.h @@ -146,6 +146,7 @@ public: int m_sectorDivs; int m_pitchDivs; + float m_pitchValue; float m_anchorConformX; float m_anchorConformZ; diff --git a/source/simulation/EventHandlers.cpp b/source/simulation/EventHandlers.cpp index 702679396b..8a796d7046 100644 --- a/source/simulation/EventHandlers.cpp +++ b/source/simulation/EventHandlers.cpp @@ -121,9 +121,3 @@ CIdleEvent::CIdleEvent( CEntityOrder order, int notifyType ) : CScriptEvent( L"i AddLocalProperty( L"target", &m_target ); AddLocalProperty( L"location", &m_location ); } -CMovementEvent::CMovementEvent( float slope ) : CScriptEvent( L"movementEvent", EVENT_MOVEMENT, false ) -{ - m_slope = slope; - - AddLocalProperty( L"slope", &m_slope ); -} \ No newline at end of file diff --git a/source/simulation/EventHandlers.h b/source/simulation/EventHandlers.h index 43190528e6..633ad00534 100644 --- a/source/simulation/EventHandlers.h +++ b/source/simulation/EventHandlers.h @@ -139,10 +139,4 @@ class CIdleEvent : public CScriptEvent public: CIdleEvent( CEntityOrder order, int notifyType ); }; -class CMovementEvent : public CScriptEvent -{ - float m_slope; -public: - CMovementEvent( float slope ); -}; #endif