diff --git a/source/graphics/MapReader.cpp b/source/graphics/MapReader.cpp index 2d4b1da4fe..31d6b9ab62 100755 --- a/source/graphics/MapReader.cpp +++ b/source/graphics/MapReader.cpp @@ -4,6 +4,7 @@ #include "MapReader.h" #include "UnitManager.h" #include "Unit.h" +#include "Game.h" #include "ObjectManager.h" #include "BaseEntity.h" #include "BaseEntityCollection.h" @@ -287,7 +288,7 @@ void CMapReader::ReadXML(const char* filename) } HEntity ent = g_EntityManager.create(g_EntityTemplateCollection.getTemplate(TemplateName), Position, Orientation); - ent->m_player = PlayerID; + ent->m_player = g_Game->GetPlayer( PlayerID ); } } else diff --git a/source/main.cpp b/source/main.cpp index 31b8d86b6c..fda1e4a3eb 100755 --- a/source/main.cpp +++ b/source/main.cpp @@ -718,10 +718,14 @@ TIMER(InitScripting) #endif JSI_Vector3D::init(); EntityCollection::Init( "EntityCollection" ); - // PlayerCollection::Init( "PlayerCollection" ); + SColour::ScriptingInit(); + CPlayer::ScriptingInit(); + + PlayerCollection::Init( "PlayerCollection" ); CDamageType::ScriptingInit(); CJSPropertyAccessor::ScriptingInit(); // <-- Doesn't really matter which we use, but we know CJSPropertyAccessor is already being compiled for T = CEntity. CScriptEvent::ScriptingInit(); + g_ScriptingHost.DefineConstant( "ORDER_NONE", -1 ); g_ScriptingHost.DefineConstant( "ORDER_GOTO", CEntityOrder::ORDER_GOTO ); diff --git a/source/ps/Game.cpp b/source/ps/Game.cpp index 2ce413a302..aca15a593f 100755 --- a/source/ps/Game.cpp +++ b/source/ps/Game.cpp @@ -173,8 +173,16 @@ PSRETURN CGame::StartGame(CGameAttributes *pAttribs) delete m_Players[i]; m_NumPlayers=pAttribs->GetValue("numPlayers").ToUInt(); - m_Players.resize(m_NumPlayers); - for (uint i=0;im_Name = L"Gaia"; + m_Players[0]->m_Colour.r = 0.2f; + m_Players[0]->m_Colour.g = 0.7f; + m_Players[0]->m_Colour.b = 0.2f; + + m_Players[1]->m_Name = L"Acumen"; + m_Players[1]->m_Colour.r = 1.0f; + m_Players[1]->m_Colour.g = 0.0f; + m_Players[1]->m_Colour.b = 0.0f; + + m_Players[2]->m_Name = L"Boco the Insignificant"; + m_Players[2]->m_Colour.r = 0.0f; + m_Players[2]->m_Colour.g = 0.0f; + m_Players[2]->m_Colour.b = 1.0f; + + m_pLocalPlayer=m_Players[1]; // RC, 040804 - GameView needs to be initialised before World, otherwise GameView initialisation // overwrites anything stored in the map file that gets loaded by CWorld::Initialize with default diff --git a/source/ps/Game.h b/source/ps/Game.h index 7b795dfcf7..93c934f8c3 100755 --- a/source/ps/Game.h +++ b/source/ps/Game.h @@ -74,6 +74,10 @@ public: inline CPlayer *GetPlayer(uint idx) { return m_Players[idx]; } + + inline std::vector* GetPlayers() + { return( &m_Players ); } + inline uint GetNumPlayers() { return m_NumPlayers; } diff --git a/source/ps/Interact.cpp b/source/ps/Interact.cpp index 1285f69686..ae830f155d 100755 --- a/source/ps/Interact.cpp +++ b/source/ps/Interact.cpp @@ -548,7 +548,8 @@ void CSelectedEntities::contextOrder( bool pushQueue ) contextRandomized.m_data[0].location.y += _y * radius; // Clamp it to within the map, just in case. - float mapsize = (float)g_Game->GetWorld()->GetTerrain()->GetVerticesPerSide(); + float mapsize = (float)g_Game->GetWorld()->GetTerrain()->GetVerticesPerSide() * CELL_SIZE; + if( contextRandomized.m_data[0].location.x < 0.0f ) contextRandomized.m_data[0].location.x = 0.0f; if( contextRandomized.m_data[0].location.x >= mapsize ) @@ -557,7 +558,7 @@ void CSelectedEntities::contextOrder( bool pushQueue ) contextRandomized.m_data[0].location.y = 0.0f; if( contextRandomized.m_data[0].location.y >= mapsize ) contextRandomized.m_data[0].location.y = mapsize; - + if( !pushQueue ) (*it)->clearOrders(); diff --git a/source/scripting/JSConversions.cpp b/source/scripting/JSConversions.cpp index 342d1d6261..b9532ea352 100755 --- a/source/scripting/JSConversions.cpp +++ b/source/scripting/JSConversions.cpp @@ -19,6 +19,21 @@ template<> JSObject* ToScript( HEntity* Native ) return( ToScript( &( **Native ) ) ); } +// CPlayer* +template<> bool ToPrimitive( JSContext* cx, jsval v, CPlayer*& Storage ) +{ + if( !JSVAL_IS_OBJECT( v ) ) return( false ); + CPlayer* Data = (CPlayer*)JS_GetInstancePrivate( cx, JSVAL_TO_OBJECT( v ), &CPlayer::JSI_class, NULL ); + if( !Data ) return( false ); + Storage = Data; + return( true ); +} + +template<> JSObject* ToScript( CPlayer** Native ) +{ + return( ToScript( *Native ) ); +} + // CBaseEntity* template<> bool ToPrimitive( JSContext* cx, jsval v, CBaseEntity*& Storage ) diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp index bd199ce3c2..480173100f 100755 --- a/source/scripting/ScriptGlue.cpp +++ b/source/scripting/ScriptGlue.cpp @@ -91,6 +91,7 @@ JSPropertySpec ScriptGlobalTable[] = { "camera", GLOBAL_CAMERA, JSPROP_PERMANENT, JSI_Camera::getCamera, JSI_Camera::setCamera }, { "console", GLOBAL_CONSOLE, JSPROP_PERMANENT | JSPROP_READONLY, JSI_Console::getConsole, NULL }, { "entities", 0, JSPROP_PERMANENT | JSPROP_READONLY, GetEntitySet, NULL }, + { "players", 0, JSPROP_PERMANENT | JSPROP_READONLY, GetPlayerSet, NULL }, { 0, 0, 0, 0, 0 }, }; @@ -186,6 +187,15 @@ JSBool GetEntitySet( JSContext* context, JSObject* globalObject, jsval argv, jsv return( JS_TRUE ); } +JSBool GetPlayerSet( JSContext* cx, JSObject* globalObject, jsval argv, jsval* vp ) +{ + std::vector* players = g_Game->GetPlayers(); + + *vp = OBJECT_TO_JSVAL( PlayerCollection::Create( *players ) ); + + return( JS_TRUE ); +} + JSBool setTimeout( JSContext* context, JSObject* UNUSEDPARAM(globalObject), unsigned int argc, jsval* argv, jsval* UNUSEDPARAM(rval) ) { assert( argc >= 2 ); diff --git a/source/scripting/ScriptGlue.h b/source/scripting/ScriptGlue.h index da15f19662..dd60571895 100755 --- a/source/scripting/ScriptGlue.h +++ b/source/scripting/ScriptGlue.h @@ -15,6 +15,9 @@ JSFunc getEntityByHandle; JSFunc getEntityTemplate; JSBool GetEntitySet( JSContext* context, JSObject* globalObject, jsval argv, jsval* vp ); +// Player +JSBool GetPlayerSet( JSContext* context, JSObject* globalObject, jsval argv, jsval* vp ); + // Timer JSFunc setTimeout; JSFunc setInterval; @@ -45,6 +48,7 @@ JSFunc loadLanguage; JSFunc getLanguageID; JSFunc getFPS; +JSFunc getCursorPosition; JSFunc v3dist; // Returns a string that says when ScriptGlue.cpp was last recompiled diff --git a/source/simulation/Entity.cpp b/source/simulation/Entity.cpp index 27ec88ec72..a9fd843bff 100755 --- a/source/simulation/Entity.cpp +++ b/source/simulation/Entity.cpp @@ -40,7 +40,8 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation ) AddProperty( L"actions.attack.rangemin", &m_meleeRangeMin ); AddProperty( L"position", &m_graphics_position, false, (NotifyFn)&CEntity::teleport ); AddProperty( L"orientation", &m_graphics_orientation, false, (NotifyFn)&CEntity::reorient ); - + AddProperty( L"player", &m_player ); + for( int t = 0; t < EVENT_LAST; t++ ) AddProperty( EventNames[t], &m_EventHandlers[t] ); @@ -70,7 +71,7 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation ) m_grouped = -1; - m_player = 1; + m_player = g_Game->GetPlayer( 0 ); } CEntity::~CEntity() @@ -513,8 +514,8 @@ void CEntity::renderSelectionOutline( float alpha ) glColor4f( 1.0f, 0.5f, 0.5f, alpha ); else { - int player = min(max(1, m_player), 8) - 1; - glColor4f( PlayerColours[player][0], PlayerColours[player][1], PlayerColours[player][2], alpha); + SColour& col = m_player->m_Colour; + glColor3f( col.r, col.g, col.b ); } glBegin( GL_LINE_LOOP ); diff --git a/source/simulation/Entity.h b/source/simulation/Entity.h index 258abc0c58..f95fb6ae60 100755 --- a/source/simulation/Entity.h +++ b/source/simulation/Entity.h @@ -33,6 +33,7 @@ #include #include "scripting/ScriptableObject.h" +#include "Player.h" #include "Vector2D.h" #include "Vector3D.h" @@ -68,8 +69,8 @@ public: bool m_selected; i32 m_grouped; - // The player that owns this entity. TODO: do this properly (if this way is wrong) - int m_player; + // The player that owns this entity + CPlayer* m_player; // If this unit has been removed from the gameworld but has still // has references. diff --git a/source/simulation/EntityManager.cpp b/source/simulation/EntityManager.cpp index b2caf1f9f8..2083fdf7d5 100755 --- a/source/simulation/EntityManager.cpp +++ b/source/simulation/EntityManager.cpp @@ -50,6 +50,7 @@ HEntity* CEntityManager::getByHandle( u16 index ) if( !m_entities[index].m_refcount ) return( NULL ); return( new HEntity( index ) ); } + std::vector* CEntityManager::matches( EntityPredicate predicate ) { std::vector* matchlist = new std::vector; @@ -60,6 +61,16 @@ std::vector* CEntityManager::matches( EntityPredicate predicate ) return( matchlist ); } +std::vector* CEntityManager::matches( EntityPredicateUD predicate, void* userdata ) +{ + std::vector* matchlist = new std::vector; + for( int i = 0; i < MAX_HANDLES; i++ ) + if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed ) + if( predicate( m_entities[i].m_entity, userdata ) ) + matchlist->push_back( HEntity( i ) ); + return( matchlist ); +} + std::vector* CEntityManager::matches( EntityPredicate predicate1, EntityPredicate predicate2 ) { std::vector* matchlist = new std::vector; @@ -70,6 +81,16 @@ std::vector* CEntityManager::matches( EntityPredicate predicate1, Entit return( matchlist ); } +std::vector* CEntityManager::matches( EntityPredicateUD predicate1, EntityPredicateUD predicate2, void* userdata ) +{ + std::vector* matchlist = new std::vector; + for( int i = 0; i < MAX_HANDLES; i++ ) + if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed ) + if( predicate1( m_entities[i].m_entity, userdata ) && predicate2( m_entities[i].m_entity, userdata ) ) + matchlist->push_back( HEntity( i ) ); + return( matchlist ); +} + std::vector* CEntityManager::getExtant() { std::vector* activelist = new std::vector; diff --git a/source/simulation/ScriptObject.cpp b/source/simulation/ScriptObject.cpp index 0407485b40..6481253780 100755 --- a/source/simulation/ScriptObject.cpp +++ b/source/simulation/ScriptObject.cpp @@ -8,6 +8,27 @@ CScriptObject::CScriptObject() Function = NULL; } +CScriptObject::~CScriptObject() +{ + Uproot(); +} + +void CScriptObject::Root() +{ + if( !Function ) + return; + + FunctionObject = JS_GetFunctionObject( Function ); + + JS_AddRoot( g_ScriptingHost.GetContext(), &FunctionObject ); +} + +void CScriptObject::Uproot() +{ + if( Function ) + JS_RemoveRoot( g_ScriptingHost.GetContext(), &FunctionObject ); +} + CScriptObject::CScriptObject( JSFunction* _Function ) { SetFunction( _Function ); @@ -20,7 +41,11 @@ CScriptObject::CScriptObject( jsval v ) void CScriptObject::SetFunction( JSFunction* _Function ) { + Uproot(); + Function = _Function; + + Root(); } void CScriptObject::SetJSVal( jsval v ) @@ -43,7 +68,7 @@ void CScriptObject::SetJSVal( jsval v ) JSObject* CScriptObject::GetFunctionObject() { if( Function ) - return( JS_GetFunctionObject( Function ) ); + return( FunctionObject ); return( NULL ); } @@ -78,7 +103,12 @@ bool CScriptObject::DispatchEvent( JSObject* Context, CScriptEvent* evt ) void CScriptObject::Compile( CStrW FileNameTag, CStrW FunctionBody ) { + if( Function ) + JS_RemoveRoot( g_ScriptingHost.GetContext(), &Function ); + const char* argnames[] = { "evt" }; utf16string str16=FunctionBody.utf16(); Function = JS_CompileUCFunction( g_ScriptingHost.GetContext(), NULL, NULL, 1, argnames, str16.c_str(), str16.size(), (CStr)FileNameTag, 0 ); + + Root(); } diff --git a/source/simulation/ScriptObject.h b/source/simulation/ScriptObject.h index dc0e666d49..5e89b7f29e 100755 --- a/source/simulation/ScriptObject.h +++ b/source/simulation/ScriptObject.h @@ -15,12 +15,18 @@ class CScriptObject { JSFunction* Function; + JSObject* FunctionObject; + void Root(); + void Uproot(); + public: CScriptObject(); CScriptObject( JSFunction* _Function ); CScriptObject( jsval v ); + ~CScriptObject(); + // Initialize in various ways: from a JS function, a string to be compiled, or a jsval containing either. void SetFunction( JSFunction* _Function ); void SetJSVal( jsval v );