forked from 0ad/0ad
# Updates to the order system, including shift-click queueing.
This was SVN commit r4240.
This commit is contained in:
parent
01b02d145d
commit
6732af1ba9
@ -430,8 +430,8 @@ void CGameView::Update(float DeltaTime)
|
||||
{
|
||||
if(!m_TrackManager.Update(DeltaTime))
|
||||
ResetCamera();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float delta = powf( m_ViewSnapSmoothness, DeltaTime );
|
||||
|
@ -620,3 +620,9 @@ bool keyRespondsTo( int hotkey, int sdlkey )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns true if one of the key combinations for the given hotkey is pressed
|
||||
bool isKeyDown( const CStr& keyname )
|
||||
{
|
||||
return hotkeys[getKeyCode(keyname)];
|
||||
}
|
||||
|
@ -1382,6 +1382,7 @@ void CBuildingPlacer::mouseReleased()
|
||||
{
|
||||
// issue a place object command accross the network
|
||||
CPlaceObject *msg = new CPlaceObject();
|
||||
msg->m_IsQueued = hotkeys[HOTKEY_ORDER_QUEUE];
|
||||
msg->m_Entities = g_Selection.m_selected;
|
||||
msg->m_Template = m_templateName;
|
||||
msg->m_X = (u32) (clickPos.X * 1000);
|
||||
|
@ -288,6 +288,7 @@ void initKeyNameMap()
|
||||
SKeycodeMapping* it = keycodeMapping;
|
||||
while( it->keycode != 0 )
|
||||
{
|
||||
debug_printf("adding key %s\n", it->keyname);
|
||||
keymap.insert( std::pair<CStr,int>( CStr( it->keyname ).LowerCase(), it->keycode ) );
|
||||
if( it->altkeyname )
|
||||
keymap.insert( std::pair<CStr,int>( CStr( it->altkeyname ).LowerCase(), it->keycode ) );
|
||||
|
@ -210,6 +210,7 @@ END_NMT_CLASS()
|
||||
|
||||
START_NMT_CLASS(CNetCommand, NMT_NONE)
|
||||
NMT_FIELD(CEntityList, m_Entities)
|
||||
NMT_FIELD_INT(m_IsQueued, u32, 1)
|
||||
END_NMT_CLASS()
|
||||
|
||||
DERIVE_NMT_CLASS_(NetCommand, Goto)
|
||||
|
@ -89,7 +89,7 @@ void CNetMessage::ScriptingInit()
|
||||
def(NMT_FormationGeneric);
|
||||
}
|
||||
|
||||
CNetCommand *CNetMessage::CommandFromJSArgs(const CEntityList &entities, JSContext *cx, uintN argc, jsval *argv)
|
||||
CNetCommand *CNetMessage::CommandFromJSArgs(const CEntityList &entities, JSContext *cx, uintN argc, jsval *argv, bool isQueued)
|
||||
{
|
||||
debug_assert(argc >= 1);
|
||||
|
||||
@ -160,6 +160,7 @@ CNetCommand *CNetMessage::CommandFromJSArgs(const CEntityList &entities, JSConte
|
||||
case NMT_ ## _msg: \
|
||||
{ \
|
||||
C##_msg *msg = new C##_msg(); \
|
||||
msg->m_IsQueued = isQueued; \
|
||||
msg->m_Entities = entities; \
|
||||
ReadPosition(msg, m_Target); \
|
||||
return msg; \
|
||||
@ -169,6 +170,7 @@ CNetCommand *CNetMessage::CommandFromJSArgs(const CEntityList &entities, JSConte
|
||||
case NMT_ ## _msg: \
|
||||
{ \
|
||||
C##_msg *msg = new C##_msg(); \
|
||||
msg->m_IsQueued = isQueued; \
|
||||
msg->m_Entities = entities; \
|
||||
ReadEntity(msg, m_Target); \
|
||||
return msg; \
|
||||
@ -178,6 +180,7 @@ CNetCommand *CNetMessage::CommandFromJSArgs(const CEntityList &entities, JSConte
|
||||
case NMT_ ## _msg: \
|
||||
{ \
|
||||
C##_msg *msg = new C##_msg(); \
|
||||
msg->m_IsQueued = isQueued; \
|
||||
msg->m_Entities = entities; \
|
||||
ReadEntity(msg, m_Target); \
|
||||
ReadInt(msg, m_Action); \
|
||||
@ -188,6 +191,7 @@ CNetCommand *CNetMessage::CommandFromJSArgs(const CEntityList &entities, JSConte
|
||||
case NMT_ ## _msg: \
|
||||
{ \
|
||||
C##_msg *msg = new C##_msg(); \
|
||||
msg->m_IsQueued = isQueued; \
|
||||
msg->m_Entities = entities; \
|
||||
ReadInt(msg, m_Type); \
|
||||
ReadString(msg, m_Name); \
|
||||
@ -198,6 +202,7 @@ CNetCommand *CNetMessage::CommandFromJSArgs(const CEntityList &entities, JSConte
|
||||
case NMT_ ## _msg: \
|
||||
{ \
|
||||
C##_msg *msg = new C##_msg(); \
|
||||
msg->m_IsQueued = isQueued; \
|
||||
msg->m_Entities = entities; \
|
||||
ReadString(msg, m_Template); \
|
||||
ReadInt(msg, m_X); \
|
||||
|
@ -74,7 +74,7 @@ public:
|
||||
*/
|
||||
static void ScriptingInit();
|
||||
|
||||
static CNetCommand *CommandFromJSArgs(const CEntityList &entities, JSContext* cx, uintN argc, jsval* argv);
|
||||
static CNetCommand *CommandFromJSArgs(const CEntityList &entities, JSContext* cx, uintN argc, jsval* argv, bool isQueued);
|
||||
|
||||
//These can create a net message without JS args
|
||||
static CNetMessage *CreatePositionMessage( const CEntityList& entities, const int type, CVector2D pos );
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "ps/Network/Client.h"
|
||||
#include "ps/Network/Server.h"
|
||||
#include "ps/i18n.h"
|
||||
#include "ps/Hotkey.h"
|
||||
#include "ps/scripting/JSCollection.h"
|
||||
#include "ps/scripting/JSInterface_Console.h"
|
||||
#include "ps/scripting/JSInterface_Selection.h"
|
||||
@ -206,10 +207,10 @@ void CreateFormationMessage( std::vector<CNetMessage*>& msgList, CNetMessage* ms
|
||||
// returns: command in serialized form [string]
|
||||
JSBool issueCommand( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
// at least one for target object, and then 1 or more for the CommandFromJSArgs
|
||||
JSU_REQUIRE_MIN_PARAMS(2);
|
||||
// at least one for target object, one for isQueued, and then 1 or more for the CommandFromJSArgs
|
||||
JSU_REQUIRE_MIN_PARAMS(3);
|
||||
|
||||
debug_assert(JSVAL_IS_OBJECT(argv[0]));
|
||||
JSU_ASSERT(JSVAL_IS_OBJECT(argv[0]), "Argument 0 must be an entity collection.");
|
||||
*rval = JSVAL_NULL;
|
||||
|
||||
CEntityList entities, msgEntities;
|
||||
@ -221,6 +222,8 @@ JSBool issueCommand( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rv
|
||||
|
||||
msgEntities = entities;
|
||||
std::map<int, CEntityList> entityStore;
|
||||
|
||||
bool isQueued = ToPrimitive<bool>(argv[1]);
|
||||
|
||||
//Destroy old notifiers if we're explicitly being reassigned
|
||||
for ( size_t i=0; i < entities.size(); i++)
|
||||
@ -248,7 +251,7 @@ JSBool issueCommand( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rv
|
||||
else
|
||||
msgEntities.push_back( entities[i] );
|
||||
}
|
||||
CNetMessage* msg = CNetMessage::CommandFromJSArgs(msgEntities, cx, argc-1, argv+1);
|
||||
CNetMessage* msg = CNetMessage::CommandFromJSArgs(msgEntities, cx, argc-2, argv+2, isQueued);
|
||||
if (!msg)
|
||||
{
|
||||
delete msg;
|
||||
@ -310,6 +313,17 @@ JSBool isFormationLocked( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval
|
||||
*rval = entity->GetFormation()->IsLocked() ? JS_TRUE : JS_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// Get the state of a given hotkey (from the hotkeys file)
|
||||
JSBool isOrderQueued( JSContext* cx, JSObject* UNUSED(obj), uint argc, jsval* argv, jsval* rval )
|
||||
{
|
||||
JSU_REQUIRE_NO_PARAMS();
|
||||
|
||||
*rval = ToJSVal(hotkeys[HOTKEY_ORDER_QUEUE]);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Techs
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1364,6 +1378,7 @@ JSFunctionSpec ScriptFunctionTable[] =
|
||||
JS_FUNC(setCursor, setCursor, 1)
|
||||
JS_FUNC(getCursorName, getCursorName, 0)
|
||||
JS_FUNC(getFPS, getFPS, 0)
|
||||
JS_FUNC(isOrderQueued, isOrderQueued, 1)
|
||||
|
||||
// Miscellany
|
||||
JS_FUNC(v3dist, v3dist, 2)
|
||||
|
@ -91,7 +91,7 @@ uint CEntity::processGotoHelper( CEntityOrder* current, size_t timestep_millis,
|
||||
|
||||
float len = delta.length();
|
||||
|
||||
if( len < 0.1f )
|
||||
if( len < 0.01f )
|
||||
return( ALREADY_AT_DESTINATION );
|
||||
|
||||
// Curve smoothing.
|
||||
@ -271,7 +271,7 @@ bool CEntity::processGotoNoPathing( CEntityOrder* current, size_t timestep_milli
|
||||
case COLLISION_OVERLAPPING_OBJECTS:
|
||||
return( false );
|
||||
case COLLISION_WITH_DESTINATION:
|
||||
// We're here...
|
||||
// We're as close as we can get...
|
||||
m_orderQueue.pop_front();
|
||||
//entf_clear(ENTF_IS_RUNNING);
|
||||
//entf_clear(ENTF_SHOULD_RUN);
|
||||
|
@ -24,7 +24,7 @@ void CPathfindEngine::requestPath( HEntity entity, const CVector2D& destination
|
||||
entity->m_orderQueue.push_front( waypoint );
|
||||
}
|
||||
|
||||
void CPathfindEngine::requestLowLevelPath( HEntity entity, const CVector2D& destination, bool contact, float radius )
|
||||
void CPathfindEngine::requestLowLevelPath( HEntity entity, const CVector2D& destination, bool UNUSED(contact), float radius )
|
||||
{
|
||||
PROFILE_START("Pathfinding");
|
||||
|
||||
@ -35,45 +35,42 @@ void CPathfindEngine::requestLowLevelPath( HEntity entity, const CVector2D& dest
|
||||
std::vector<CVector2D> path = mLowPathfinder.getLastPath();
|
||||
if( path.size() > 0 )
|
||||
{
|
||||
std::vector<CVector2D>::iterator it;
|
||||
// Push the path onto the front of our order queue in reverse order,
|
||||
// so that we run through it before continuing other orders.
|
||||
|
||||
CEntityOrder node;
|
||||
for( it = path.begin(); (it+1) != path.end(); it++ )
|
||||
{
|
||||
if ( !contact )
|
||||
{
|
||||
node.m_type = CEntityOrder::ORDER_GOTO_NOPATHING;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Is this right?
|
||||
node.m_type = CEntityOrder::ORDER_GOTO_NOPATHING;
|
||||
}
|
||||
node.m_data[0].location = *it;
|
||||
entity->m_orderQueue.push_back(node);
|
||||
}
|
||||
|
||||
// Hack to make pathfinding slightly more precise:
|
||||
// If the radius was 0, make the final node be exactly at the destination
|
||||
// (otherwise, go to wherever the pathfinder tells us since we just want to be in range)
|
||||
CVector2D finalDest = (radius==0 ? destination : (*it));
|
||||
node.m_type = CEntityOrder::ORDER_GOTO_NOPATHING;
|
||||
CVector2D finalDest = (radius==0 ? destination : path[path.size()-1]);
|
||||
node.m_type = CEntityOrder::ORDER_PATH_END_MARKER; // push end marker (used as a sentinel when repathing)
|
||||
node.m_data[0].location = finalDest;
|
||||
entity->m_orderQueue.push_back(node);
|
||||
node.m_type = CEntityOrder::ORDER_PATH_END_MARKER;
|
||||
entity->m_orderQueue.push_front(node);
|
||||
node.m_type = CEntityOrder::ORDER_GOTO_NOPATHING; // push final goto step
|
||||
node.m_data[0].location = finalDest;
|
||||
entity->m_orderQueue.push_back(node);
|
||||
entity->m_orderQueue.push_front(node);
|
||||
|
||||
for( int i = ((int) path.size()) - 2; i >= 0; i-- )
|
||||
{
|
||||
node.m_type = CEntityOrder::ORDER_GOTO_NOPATHING; // TODO: For non-contact paths, do we want some other order type?
|
||||
node.m_data[0].location = path[i];
|
||||
entity->m_orderQueue.push_front(node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Hack to make pathfinding slightly more precise:
|
||||
// If radius = 0, we are still moving within the same tile, so add a GOTO order anyway
|
||||
// If radius = 0, we have an empty path but the user still wants us to move
|
||||
// within the same tile, so add a GOTO order anyway
|
||||
if(radius == 0)
|
||||
{
|
||||
CEntityOrder node;
|
||||
node.m_type = CEntityOrder::ORDER_GOTO_NOPATHING;
|
||||
node.m_data[0].location = destination;
|
||||
entity->m_orderQueue.push_back(node);
|
||||
node.m_type = CEntityOrder::ORDER_PATH_END_MARKER;
|
||||
node.m_data[0].location = destination;
|
||||
entity->m_orderQueue.push_back(node);
|
||||
entity->m_orderQueue.push_front(node);
|
||||
node.m_type = CEntityOrder::ORDER_GOTO_NOPATHING;
|
||||
node.m_data[0].location = destination;
|
||||
entity->m_orderQueue.push_front(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ void CSimulation::Simulate()
|
||||
// Task them all to a point within a radius of the target, radius depends upon
|
||||
// the number of units in the group.
|
||||
|
||||
void RandomizeLocations(CEntityOrder order, const vector <HEntity> &entities, bool clearQueue)
|
||||
void RandomizeLocations(CEntityOrder order, const vector <HEntity> &entities, bool isQueued)
|
||||
{
|
||||
vector<HEntity>::const_iterator it;
|
||||
float radius = 2.0f * sqrt( (float)entities.size() - 1 );
|
||||
@ -181,14 +181,14 @@ void RandomizeLocations(CEntityOrder order, const vector <HEntity> &entities, bo
|
||||
if( randomizedOrder.m_data[0].location.y >= mapsize )
|
||||
randomizedOrder.m_data[0].location.y = mapsize;
|
||||
|
||||
if( clearQueue )
|
||||
if( !isQueued )
|
||||
(*it)->clearOrders();
|
||||
|
||||
(*it)->pushOrder( randomizedOrder );
|
||||
}
|
||||
}
|
||||
|
||||
void FormationLocations(CEntityOrder order, const vector <HEntity> &entities, bool clearQueue)
|
||||
void FormationLocations(CEntityOrder order, const vector <HEntity> &entities, bool isQueued)
|
||||
{
|
||||
CVector2D upvec(0.0f, 1.0f);
|
||||
vector<HEntity>::const_iterator it = entities.begin();
|
||||
@ -223,20 +223,20 @@ void FormationLocations(CEntityOrder order, const vector <HEntity> &entities, bo
|
||||
if( orderCopy.m_data[0].location.y >= mapsize )
|
||||
orderCopy.m_data[0].location.y = mapsize;
|
||||
|
||||
if( clearQueue )
|
||||
if( !isQueued )
|
||||
(*it)->clearOrders();
|
||||
|
||||
(*it)->pushOrder( orderCopy );
|
||||
}
|
||||
}
|
||||
|
||||
void QueueOrder(CEntityOrder order, const vector <HEntity> &entities, bool clearQueue)
|
||||
void QueueOrder(CEntityOrder order, const vector <HEntity> &entities, bool isQueued)
|
||||
{
|
||||
vector<HEntity>::const_iterator it;
|
||||
|
||||
for (it = entities.begin(); it < entities.end(); it++)
|
||||
{
|
||||
if( clearQueue )
|
||||
if( !isQueued )
|
||||
(*it)->clearOrders();
|
||||
|
||||
(*it)->pushOrder( order );
|
||||
@ -246,46 +246,51 @@ void QueueOrder(CEntityOrder order, const vector <HEntity> &entities, bool clear
|
||||
uint CSimulation::TranslateMessage(CNetMessage* pMsg, uint clientMask, void* UNUSED(userdata))
|
||||
{
|
||||
CEntityOrder order;
|
||||
bool clearQueue = true;
|
||||
bool isQueued = true;
|
||||
|
||||
#define ENTITY_POSITION(_msg, _order) do\
|
||||
{ \
|
||||
_msg *msg=(_msg *)pMsg; \
|
||||
isQueued = msg->m_IsQueued != 0; \
|
||||
order.m_type=CEntityOrder::_order; \
|
||||
order.m_data[0].location.x=(float)msg->m_TargetX; \
|
||||
order.m_data[0].location.y=(float)msg->m_TargetY; \
|
||||
RandomizeLocations(order, msg->m_Entities, clearQueue); \
|
||||
RandomizeLocations(order, msg->m_Entities, isQueued); \
|
||||
} while(0)
|
||||
#define ENTITY_POSITION_FORM(_msg, _order) do\
|
||||
{ \
|
||||
_msg *msg=(_msg *)pMsg; \
|
||||
isQueued = msg->m_IsQueued != 0; \
|
||||
order.m_type=CEntityOrder::_order; \
|
||||
order.m_data[0].location.x=(float)msg->m_TargetX; \
|
||||
order.m_data[0].location.y=(float)msg->m_TargetY; \
|
||||
FormationLocations(order, msg->m_Entities, clearQueue); \
|
||||
FormationLocations(order, msg->m_Entities, isQueued); \
|
||||
} while(0)
|
||||
#define ENTITY_ENTITY(_msg, _order) do\
|
||||
{ \
|
||||
_msg *msg=(_msg *)pMsg; \
|
||||
isQueued = msg->m_IsQueued != 0; \
|
||||
order.m_type=CEntityOrder::_order; \
|
||||
order.m_data[0].entity=msg->m_Target; \
|
||||
QueueOrder(order, msg->m_Entities, clearQueue); \
|
||||
QueueOrder(order, msg->m_Entities, isQueued); \
|
||||
} while(0)
|
||||
#define ENTITY_ENTITY_INT(_msg, _order) do\
|
||||
{ \
|
||||
_msg *msg=(_msg *)pMsg; \
|
||||
isQueued = msg->m_IsQueued != 0; \
|
||||
order.m_type=CEntityOrder::_order; \
|
||||
order.m_data[0].entity=msg->m_Target; \
|
||||
order.m_data[1].data=msg->m_Action; \
|
||||
QueueOrder(order, msg->m_Entities, clearQueue); \
|
||||
QueueOrder(order, msg->m_Entities, isQueued); \
|
||||
} while(0)
|
||||
#define ENTITY_INT_STRING(_msg, _order) do\
|
||||
{ \
|
||||
_msg *msg=(_msg *)pMsg; \
|
||||
isQueued = msg->m_IsQueued != 0; \
|
||||
order.m_type=CEntityOrder::_order; \
|
||||
order.m_data[0].string=msg->m_Name; \
|
||||
order.m_data[1].data=msg->m_Type; \
|
||||
QueueOrder(order, msg->m_Entities, clearQueue); \
|
||||
QueueOrder(order, msg->m_Entities, isQueued); \
|
||||
} while(0)
|
||||
|
||||
switch (pMsg->GetType())
|
||||
@ -293,6 +298,7 @@ uint CSimulation::TranslateMessage(CNetMessage* pMsg, uint clientMask, void* UNU
|
||||
case NMT_AddWaypoint:
|
||||
{
|
||||
CAddWaypoint *msg=(CAddWaypoint *)pMsg;
|
||||
isQueued = msg->m_IsQueued != 0;
|
||||
order.m_type=CEntityOrder::ORDER_LAST;
|
||||
order.m_data[0].location.x=(float)msg->m_TargetX;
|
||||
order.m_data[0].location.y=(float)msg->m_TargetY;
|
||||
@ -351,6 +357,7 @@ uint CSimulation::TranslateMessage(CNetMessage* pMsg, uint clientMask, void* UNU
|
||||
case NMT_PlaceObject:
|
||||
{
|
||||
CPlaceObject *msg = (CPlaceObject *) pMsg;
|
||||
isQueued = msg->m_IsQueued != 0;
|
||||
|
||||
// Figure out the player
|
||||
CPlayer* player = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user