diff --git a/source/network/NetMessage.cpp b/source/network/NetMessage.cpp index 692bfdb90b..0a63cd10dc 100644 --- a/source/network/NetMessage.cpp +++ b/source/network/NetMessage.cpp @@ -87,6 +87,8 @@ void CNetMessage::ScriptingInit() def(NMT_NotifyRequest); def(NMT_FormationGoto); def(NMT_FormationGeneric); + +#undef def } CNetCommand *CNetMessage::CommandFromJSArgs(const CEntityList &entities, JSContext *cx, uintN argc, jsval *argv, bool isQueued) diff --git a/source/ps/Player.cpp b/source/ps/Player.cpp index e9dc231e16..bc41c52342 100644 --- a/source/ps/Player.cpp +++ b/source/ps/Player.cpp @@ -15,6 +15,16 @@ CPlayer::CPlayer(uint playerID): m_UpdateCB(0) { m_LOSToken = LOS_GetTokenFor(playerID); + + // Initialize diplomacy: we need to be neutral to Gaia and enemy to everyone else; + // however, if we are Gaia, we'll just be neutral to everyone; finally, everyone + // will be allied with themselves. + m_DiplomaticStance[0] = DIPLOMACY_NEUTRAL; + for(int i=1; i<=PS_MAX_PLAYERS; i++) + { + m_DiplomaticStance[i] = (m_PlayerID==0 ? DIPLOMACY_NEUTRAL : DIPLOMACY_ENEMY); + } + m_DiplomaticStance[m_PlayerID] = DIPLOMACY_ALLIED; AddSynchedProperty( L"name", &m_Name ); AddSynchedProperty( L"civilization", &m_Civilization ); @@ -26,20 +36,41 @@ CPlayer::CPlayer(uint playerID): // to CJSObject's list ISynchedJSProperty *prop=new CSynchedJSProperty(L"colour", &m_Colour, this); m_SynchedProperties[L"colour"]=prop; + + // HACK - maintain diplomacy synced in the same way, by adding a dummy property for each stance + for(int i=0; i<=PS_MAX_PLAYERS; i++) + { + CStrW name = CStrW(L"diplomaticStance_") + CStrW(i); + ISynchedJSProperty *prop=new CSynchedJSProperty(name, (int*)&m_DiplomaticStance[i], this); + m_SynchedProperties[name]=prop; + } } CPlayer::~CPlayer() { - // Side-effect of HACK - since it's not passed to CJSObject's list, it - // doesn't get freed automatically + // Side-effect of HACKs - since these properties are not passed to CJSObject's list, + // they don't get freed automatically + delete m_SynchedProperties[L"colour"]; + + for(int i=0; i<=PS_MAX_PLAYERS; i++) + { + CStrW name = CStrW(L"diplomaticStance_") + CStrW(i); + delete m_SynchedProperties[name]; + } } void CPlayer::ScriptingInit() { + g_ScriptingHost.DefineConstant("DIPLOMACY_ENEMY", DIPLOMACY_ENEMY); + g_ScriptingHost.DefineConstant("DIPLOMACY_NEUTRAL", DIPLOMACY_NEUTRAL); + g_ScriptingHost.DefineConstant("DIPLOMACY_ALLIED", DIPLOMACY_ALLIED); + AddMethod( "toString", 0 ); AddMethod( "setColour", 1); AddMethod( "getColour", 0); + AddMethod( "setDiplomaticStance", 2); + AddMethod( "getDiplomaticStance", 1); AddProperty( L"id", &CPlayer::m_PlayerID, true ); // MT: Work out how this fits with the Synched stuff... @@ -116,3 +147,44 @@ jsval CPlayer::JSI_GetColour( JSContext* cx, uintN UNUSED(argc), jsval* UNUSED(a ISynchedJSProperty *prop=GetSynchedProperty(L"colour"); return prop->Get(cx, this); } + +jsval CPlayer::JSI_SetDiplomaticStance(JSContext *cx, uintN argc, jsval *argv) +{ + JSU_ASSERT(argc==2, "2 arguments required"); + JSU_ASSERT( JSVAL_IS_INT(argv[1]), "Argument 2 must be a valid stance ID" ); + try + { + CPlayer* player = ToPrimitive( argv[0] ); + int stance = ToPrimitive( argv[1] ); + JSU_ASSERT( stance==DIPLOMACY_ENEMY || stance==DIPLOMACY_NEUTRAL || stance==DIPLOMACY_ALLIED, + "Argument 2 must be a valid stance ID" ); + + m_DiplomaticStance[player->m_PlayerID] = (EDiplomaticStance) stance; + + CStrW name = CStrW(L"diplomaticStance_") + CStrW(player->m_PlayerID); + ISynchedJSProperty *prop=GetSynchedProperty(name); + Update(name, prop); + + return JSVAL_VOID; + } + catch( PSERROR_Scripting_ConversionFailed ) + { + JS_ReportError( cx, "Could not convert argument 1 to a Player object" ); + return JSVAL_VOID; + } +} + +jsval CPlayer::JSI_GetDiplomaticStance(JSContext *cx, uintN argc, jsval *argv) +{ + JSU_ASSERT(argc==1, "1 argument required"); + try + { + CPlayer* player = ToPrimitive( argv[0] ); + return ToJSVal( (int) m_DiplomaticStance[player->m_PlayerID] ); + } + catch( PSERROR_Scripting_ConversionFailed ) + { + JS_ReportError( cx, "Could not convert argument 1 to a Player object" ); + return JSVAL_VOID; + } +} diff --git a/source/ps/Player.h b/source/ps/Player.h index f5b2e88b54..0499b6d9ac 100644 --- a/source/ps/Player.h +++ b/source/ps/Player.h @@ -5,6 +5,7 @@ #include "scripting/SynchedJSObject.h" #include "scripting/ScriptableObject.h" #include "scripting/ScriptCustomTypes.h" +#include "Game.h" class CNetMessage; class HEntity; @@ -12,6 +13,13 @@ class CTechnology; typedef SColour SPlayerColour; +enum EDiplomaticStance +{ + DIPLOMACY_ENEMY, + DIPLOMACY_NEUTRAL, + DIPLOMACY_ALLIED +}; + class CPlayer : public CSynchedJSObject { public: @@ -23,11 +31,11 @@ private: PS_uint m_PlayerID; PS_uint m_LOSToken; SPlayerColour m_Colour; + EDiplomaticStance m_DiplomaticStance[PS_MAX_PLAYERS+1]; + std::vector m_ActiveTechs; UpdateCallback *m_UpdateCB; void *m_UpdateCBData; - - std::vector m_ActiveTechs; virtual void Update(const CStrW& name, ISynchedJSProperty *prop); @@ -55,6 +63,11 @@ public: inline void SetColour(const SPlayerColour &colour) { m_Colour = colour; } + inline EDiplomaticStance GetDiplomaticStance(CPlayer* other) const + { return m_DiplomaticStance[other->m_PlayerID]; } + inline void SetDiplomaticStance(CPlayer* other, EDiplomaticStance stance) + { m_DiplomaticStance[other->m_PlayerID] = stance; } + inline void SetUpdateCallback(UpdateCallback *cb, void *userdata) { m_UpdateCB=cb; @@ -80,6 +93,8 @@ public: jsval JSI_GetControlledEntities( JSContext* context ); jsval JSI_SetColour(JSContext *context, uintN argc, jsval *argv); jsval JSI_GetColour(JSContext *context, uintN argc, jsval *argv); + jsval JSI_SetDiplomaticStance(JSContext *context, uintN argc, jsval *argv); + jsval JSI_GetDiplomaticStance(JSContext *context, uintN argc, jsval *argv); static void ScriptingInit(); }; diff --git a/source/scripting/SynchedJSObject.cpp b/source/scripting/SynchedJSObject.cpp index 04b636d540..ce9ddf1c86 100644 --- a/source/scripting/SynchedJSObject.cpp +++ b/source/scripting/SynchedJSObject.cpp @@ -16,6 +16,18 @@ void SetFromNetString(uint &val, const CStrW& string) val=string.ToUInt(); } +template <> +CStrW ToNetString(const int &val) +{ + return CStrW(val); +} + +template <> +void SetFromNetString(int &val, const CStrW& string) +{ + val=string.ToInt(); +} + template <> CStrW ToNetString(const CStrW& data) { return data; }