Index: ps/trunk/binaries/data/mods/public/simulation/components/UnitMotionFlying.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/UnitMotionFlying.js (revision 23207) +++ ps/trunk/binaries/data/mods/public/simulation/components/UnitMotionFlying.js (revision 23208) @@ -1,336 +1,341 @@ // (A serious implementation of this might want to use C++ instead of JS // for performance; this is just for fun.) const SHORT_FINAL = 2.5; function UnitMotionFlying() {} UnitMotionFlying.prototype.Schema = "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; UnitMotionFlying.prototype.Init = function() { this.hasTarget = false; this.reachedTarget = false; this.targetX = 0; this.targetZ = 0; this.targetMinRange = 0; this.targetMaxRange = 0; this.speed = 0; this.landing = false; this.onGround = true; this.pitch = 0; this.roll = 0; this.waterDeath = false; this.passabilityClass = Engine.QueryInterface(SYSTEM_ENTITY, IID_Pathfinder).GetPassabilityClass(this.template.PassabilityClass); }; UnitMotionFlying.prototype.OnUpdate = function(msg) { var turnLength = msg.turnLength; if (!this.hasTarget) return; var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder); var cmpHealth = Engine.QueryInterface(this.entity, IID_Health); var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); var pos = cmpPosition.GetPosition(); var angle = cmpPosition.GetRotation().y; var cmpTerrain = Engine.QueryInterface(SYSTEM_ENTITY, IID_Terrain); var cmpWaterManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_WaterManager); var ground = Math.max(cmpTerrain.GetGroundLevel(pos.x, pos.z), cmpWaterManager.GetWaterLevel(pos.x, pos.z)); var newangle = angle; var canTurn = true; if (this.landing) { if (this.speed > 0 && this.onGround) { if (pos.y <= cmpWaterManager.GetWaterLevel(pos.x, pos.z) && this.template.DiesInWater == "true") this.waterDeath = true; this.pitch = 0; // Deaccelerate forwards...at a very reduced pace. if (this.waterDeath) this.speed = Math.max(0, this.speed - turnLength * this.template.BrakingRate * 10); else this.speed = Math.max(0, this.speed - turnLength * this.template.BrakingRate); canTurn = false; // Clamp to ground if below it, or descend if above if (pos.y < ground) pos.y = ground; else if (pos.y > ground) pos.y = Math.max(ground, pos.y - turnLength * this.template.ClimbRate); } else if (this.speed == 0 && this.onGround) { if (this.waterDeath && cmpHealth) cmpHealth.Kill(); else { this.pitch = 0; // We've stopped. if (cmpGarrisonHolder) cmpGarrisonHolder.AllowGarrisoning(true,"UnitMotionFlying"); canTurn = false; this.hasTarget = false; this.landing = false; // summon planes back from the edge of the map var terrainSize = cmpTerrain.GetMapSize(); var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); if (cmpRangeManager.GetLosCircular()) { var mapRadius = terrainSize/2; var x = pos.x - mapRadius; var z = pos.z - mapRadius; var div = (mapRadius - 12) / Math.sqrt(x*x + z*z); if (div < 1) { pos.x = mapRadius + x*div; pos.z = mapRadius + z*div; newangle += Math.PI; } } else { pos.x = Math.max(Math.min(pos.x, terrainSize - 12), 12); pos.z = Math.max(Math.min(pos.z, terrainSize - 12), 12); newangle += Math.PI; } } } else { // Final Approach // We need to slow down to land! this.speed = Math.max(this.template.LandingSpeed, this.speed - turnLength * this.template.SlowingRate); canTurn = false; var targetHeight = ground; // Steep, then gradual descent. if ((pos.y - targetHeight) / this.template.FlyingHeight > 1 / SHORT_FINAL) this.pitch = - Math.PI / 18; else this.pitch = Math.PI / 18; var descentRate = ((pos.y - targetHeight) / this.template.FlyingHeight * this.template.ClimbRate + SHORT_FINAL) * SHORT_FINAL; if (pos.y < targetHeight) pos.y = Math.max(targetHeight, pos.y + turnLength * descentRate); else if (pos.y > targetHeight) pos.y = Math.max(targetHeight, pos.y - turnLength * descentRate); if (targetHeight == pos.y) { this.onGround = true; if (targetHeight == cmpWaterManager.GetWaterLevel(pos.x, pos.z) && this.template.DiesInWater) this.waterDeath = true; } } } else { // If we haven't reached max speed yet then we're still on the ground; // otherwise we're taking off or flying // this.onGround in case of a go-around after landing (but not fully stopped) if (this.speed < this.template.TakeoffSpeed && this.onGround) { if (cmpGarrisonHolder) cmpGarrisonHolder.AllowGarrisoning(false,"UnitMotionFlying"); this.pitch = 0; // Accelerate forwards this.speed = Math.min(this.template.MaxSpeed, this.speed + turnLength * this.template.AccelRate); canTurn = false; // Clamp to ground if below it, or descend if above if (pos.y < ground) pos.y = ground; else if (pos.y > ground) pos.y = Math.max(ground, pos.y - turnLength * this.template.ClimbRate); } else { this.onGround = false; // Climb/sink to max height above ground this.speed = Math.min(this.template.MaxSpeed, this.speed + turnLength * this.template.AccelRate); var targetHeight = ground + (+this.template.FlyingHeight); if (Math.abs(pos.y-targetHeight) > this.template.FlyingHeight/5) { this.pitch = Math.PI / 9; canTurn = false; } else this.pitch = 0; if (pos.y < targetHeight) pos.y = Math.min(targetHeight, pos.y + turnLength * this.template.ClimbRate); else if (pos.y > targetHeight) { pos.y = Math.max(targetHeight, pos.y - turnLength * this.template.ClimbRate); this.pitch = -1 * this.pitch; } } } // If we're in range of the target then tell people that we've reached it // (TODO: quantisation breaks this) var distFromTarget = Math.euclidDistance2D(pos.x, pos.z, this.targetX, this.targetZ); if (!this.reachedTarget && this.targetMinRange <= distFromTarget && distFromTarget <= this.targetMaxRange) { this.reachedTarget = true; - Engine.PostMessage(this.entity, MT_MotionChanged, { "starting": false, "error": false }); + Engine.PostMessage(this.entity, MT_MotionUpdate, { "updateString": "likelySuccess" }); } // If we're facing away from the target, and are still fairly close to it, // then carry on going straight so we overshoot in a straight line var isBehindTarget = ((this.targetX - pos.x) * Math.sin(angle) + (this.targetZ - pos.z) * Math.cos(angle) < 0); // Overshoot the target: carry on straight if (isBehindTarget && distFromTarget < this.template.MaxSpeed * this.template.OvershootTime) canTurn = false; if (canTurn) { // Turn towards the target var targetAngle = Math.atan2(this.targetX - pos.x, this.targetZ - pos.z); var delta = targetAngle - angle; // Wrap delta to -pi..pi delta = (delta + Math.PI) % (2*Math.PI); // range -2pi..2pi if (delta < 0) delta += 2*Math.PI; // range 0..2pi delta -= Math.PI; // range -pi..pi // Clamp to max rate var deltaClamped = Math.min(Math.max(delta, -this.template.TurnRate * turnLength), this.template.TurnRate * turnLength); // Calculate new orientation, in a peculiar way in order to make sure the // result gets close to targetAngle (rather than being n*2*pi out) newangle = targetAngle + deltaClamped - delta; if (newangle - angle > Math.PI / 18) this.roll = Math.PI / 9; else if (newangle - angle < -Math.PI / 18) this.roll = - Math.PI / 9; else this.roll = newangle - angle; } else this.roll = 0; pos.x += this.speed * turnLength * Math.sin(angle); pos.z += this.speed * turnLength * Math.cos(angle); cmpPosition.SetHeightFixed(pos.y); cmpPosition.TurnTo(newangle); cmpPosition.SetXZRotation(this.pitch, this.roll); cmpPosition.MoveTo(pos.x, pos.z); }; UnitMotionFlying.prototype.MoveToPointRange = function(x, z, minRange, maxRange) { this.hasTarget = true; this.landing = false; this.reachedTarget = false; this.targetX = x; this.targetZ = z; this.targetMinRange = minRange; this.targetMaxRange = maxRange; return true; }; UnitMotionFlying.prototype.MoveToTargetRange = function(target, minRange, maxRange) { var cmpTargetPosition = Engine.QueryInterface(target, IID_Position); if (!cmpTargetPosition || !cmpTargetPosition.IsInWorld()) return false; var targetPos = cmpTargetPosition.GetPosition2D(); this.hasTarget = true; this.reachedTarget = false; this.targetX = targetPos.x; this.targetZ = targetPos.y; this.targetMinRange = minRange; this.targetMaxRange = maxRange; return true; }; UnitMotionFlying.prototype.GetWalkSpeed = function() { return +this.template.MaxSpeed; }; UnitMotionFlying.prototype.SetSpeedMultiplier = function() { // ignore this, the speed is always the walk speed }; UnitMotionFlying.prototype.GetRunMultiplier = function() { return 1; }; +UnitMotionFlying.prototype.IsMoveRequested = function() +{ + return this.hasTarget; +}; + UnitMotionFlying.prototype.GetCurrentSpeed = function() { return this.speed; }; UnitMotionFlying.prototype.GetSpeedMultiplier = function() { return this.GetCurrentSpeed() / this.GetWalkSpeed(); }; UnitMotionFlying.prototype.GetPassabilityClassName = function() { return this.template.PassabilityClass; }; UnitMotionFlying.prototype.GetPassabilityClass = function() { return this.passabilityClass; }; UnitMotionFlying.prototype.FaceTowardsPoint = function(x, z) { // Ignore this - angle is controlled by the target-seeking code instead }; UnitMotionFlying.prototype.SetFacePointAfterMove = function() { // Ignore this - angle is controlled by the target-seeking code instead }; UnitMotionFlying.prototype.StopMoving = function() { //Invert if (!this.waterDeath) this.landing = !this.landing; }; UnitMotionFlying.prototype.SetDebugOverlay = function(enabled) { }; Engine.RegisterComponentType(IID_UnitMotion, "UnitMotionFlying", UnitMotionFlying); Index: ps/trunk/source/simulation2/scripting/MessageTypeConversions.cpp =================================================================== --- ps/trunk/source/simulation2/scripting/MessageTypeConversions.cpp (revision 23207) +++ ps/trunk/source/simulation2/scripting/MessageTypeConversions.cpp (revision 23208) @@ -1,557 +1,567 @@ /* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * 0 A.D. is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 0 A.D. If not, see . */ #include "precompiled.h" #include "ps/CLogger.h" #include "scriptinterface/ScriptInterface.h" #include "simulation2/MessageTypes.h" #define TOJSVAL_SETUP() \ JSContext* cx = scriptInterface.GetContext(); \ JSAutoRequest rq(cx); \ JS::RootedObject obj(cx, JS_NewPlainObject(cx)); \ if (!obj) \ return JS::UndefinedValue(); #define SET_MSG_PROPERTY(name) \ do { \ JS::RootedValue prop(cx);\ ScriptInterface::ToJSVal(cx, &prop, this->name); \ if (! JS_SetProperty(cx, obj, #name, prop)) \ return JS::UndefinedValue(); \ } while (0); #define FROMJSVAL_SETUP() \ JSContext* cx = scriptInterface.GetContext(); \ JSAutoRequest rq(cx); \ if (val.isPrimitive()) \ return NULL; \ JS::RootedObject obj(cx, &val.toObject()); \ JS::RootedValue prop(cx); #define GET_MSG_PROPERTY(type, name) \ type name; \ { \ if (! JS_GetProperty(cx, obj, #name, &prop)) \ return NULL; \ if (! ScriptInterface::FromJSVal(cx, prop, name)) \ return NULL; \ } JS::Value CMessage::ToJSValCached(const ScriptInterface& scriptInterface) const { if (!m_Cached) m_Cached.reset(new JS::PersistentRootedValue(scriptInterface.GetJSRuntime(), ToJSVal(scriptInterface))); return m_Cached->get(); } //////////////////////////////// JS::Value CMessageTurnStart::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); return JS::ObjectValue(*obj); } CMessage* CMessageTurnStart::FromJSVal(const ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val)) { return new CMessageTurnStart(); } //////////////////////////////// #define MESSAGE_1(name, t0, a0) \ JS::Value CMessage##name::ToJSVal(const ScriptInterface& scriptInterface) const \ { \ TOJSVAL_SETUP(); \ SET_MSG_PROPERTY(a0); \ return JS::ObjectValue(*obj); \ } \ CMessage* CMessage##name::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) \ { \ FROMJSVAL_SETUP(); \ GET_MSG_PROPERTY(t0, a0); \ return new CMessage##name(a0); \ } MESSAGE_1(Update, fixed, turnLength) MESSAGE_1(Update_MotionFormation, fixed, turnLength) MESSAGE_1(Update_MotionUnit, fixed, turnLength) MESSAGE_1(Update_Final, fixed, turnLength) //////////////////////////////// JS::Value CMessageInterpolate::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(deltaSimTime); SET_MSG_PROPERTY(offset); SET_MSG_PROPERTY(deltaRealTime); return JS::ObjectValue(*obj); } CMessage* CMessageInterpolate::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(float, deltaSimTime); GET_MSG_PROPERTY(float, offset); GET_MSG_PROPERTY(float, deltaRealTime); return new CMessageInterpolate(deltaSimTime, offset, deltaRealTime); } //////////////////////////////// JS::Value CMessageRenderSubmit::ToJSVal(const ScriptInterface& UNUSED(scriptInterface)) const { LOGWARNING("CMessageRenderSubmit::ToJSVal not implemented"); return JS::UndefinedValue(); } CMessage* CMessageRenderSubmit::FromJSVal(const ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val)) { LOGWARNING("CMessageRenderSubmit::FromJSVal not implemented"); return NULL; } //////////////////////////////// JS::Value CMessageProgressiveLoad::ToJSVal(const ScriptInterface& UNUSED(scriptInterface)) const { LOGWARNING("CMessageProgressiveLoad::ToJSVal not implemented"); return JS::UndefinedValue(); } CMessage* CMessageProgressiveLoad::FromJSVal(const ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val)) { LOGWARNING("CMessageProgressiveLoad::FromJSVal not implemented"); return NULL; } //////////////////////////////// JS::Value CMessageDeserialized::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); return JS::ObjectValue(*obj); } CMessage* CMessageDeserialized::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); return new CMessageDeserialized(); } //////////////////////////////// JS::Value CMessageCreate::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(entity); return JS::ObjectValue(*obj); } CMessage* CMessageCreate::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(entity_id_t, entity); return new CMessageCreate(entity); } //////////////////////////////// JS::Value CMessageDestroy::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(entity); return JS::ObjectValue(*obj); } CMessage* CMessageDestroy::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(entity_id_t, entity); return new CMessageDestroy(entity); } //////////////////////////////// JS::Value CMessageOwnershipChanged::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(entity); SET_MSG_PROPERTY(from); SET_MSG_PROPERTY(to); return JS::ObjectValue(*obj); } CMessage* CMessageOwnershipChanged::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(entity_id_t, entity); GET_MSG_PROPERTY(player_id_t, from); GET_MSG_PROPERTY(player_id_t, to); return new CMessageOwnershipChanged(entity, from, to); } //////////////////////////////// JS::Value CMessagePositionChanged::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(entity); SET_MSG_PROPERTY(inWorld); SET_MSG_PROPERTY(x); SET_MSG_PROPERTY(z); SET_MSG_PROPERTY(a); return JS::ObjectValue(*obj); } CMessage* CMessagePositionChanged::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(entity_id_t, entity); GET_MSG_PROPERTY(bool, inWorld); GET_MSG_PROPERTY(entity_pos_t, x); GET_MSG_PROPERTY(entity_pos_t, z); GET_MSG_PROPERTY(entity_angle_t, a); return new CMessagePositionChanged(entity, inWorld, x, z, a); } //////////////////////////////// JS::Value CMessageInterpolatedPositionChanged::ToJSVal(const ScriptInterface& UNUSED(scriptInterface)) const { LOGWARNING("CMessageInterpolatedPositionChanged::ToJSVal not implemented"); return JS::UndefinedValue(); } CMessage* CMessageInterpolatedPositionChanged::FromJSVal(const ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val)) { LOGWARNING("CMessageInterpolatedPositionChanged::FromJSVal not implemented"); return NULL; } //////////////////////////////// JS::Value CMessageTerritoryPositionChanged::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(entity); SET_MSG_PROPERTY(newTerritory); return JS::ObjectValue(*obj); } CMessage* CMessageTerritoryPositionChanged::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(entity_id_t, entity); GET_MSG_PROPERTY(player_id_t, newTerritory); return new CMessageTerritoryPositionChanged(entity, newTerritory); } //////////////////////////////// const std::array CMessageMotionUpdate::UpdateTypeStr = { { "likelySuccess", "likelyFailure", "obstructed" } }; JS::Value CMessageMotionUpdate::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); JS::RootedValue prop(cx); if (!JS_SetProperty(cx, obj, UpdateTypeStr[updateType], JS::TrueHandleValue)) return JS::UndefinedValue(); return JS::ObjectValue(*obj); } -CMessage* CMessageMotionUpdate::FromJSVal(const ScriptInterface&, JS::HandleValue) +CMessage* CMessageMotionUpdate::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { - LOGWARNING("CMessageMotionUpdate::FromJSVal not implemented"); + FROMJSVAL_SETUP(); + GET_MSG_PROPERTY(std::wstring, updateString); + + if (updateString == L"likelySuccess") + return new CMessageMotionUpdate(CMessageMotionUpdate::LIKELY_SUCCESS); + if (updateString == L"likelyFailure") + return new CMessageMotionUpdate(CMessageMotionUpdate::LIKELY_FAILURE); + if (updateString == L"obstructed") + return new CMessageMotionUpdate(CMessageMotionUpdate::OBSTRUCTED); + + LOGWARNING("CMessageMotionUpdate::FromJSVal passed wrong updateString"); return NULL; } //////////////////////////////// JS::Value CMessageTerrainChanged::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(i0); SET_MSG_PROPERTY(j0); SET_MSG_PROPERTY(i1); SET_MSG_PROPERTY(j1); return JS::ObjectValue(*obj); } CMessage* CMessageTerrainChanged::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(int32_t, i0); GET_MSG_PROPERTY(int32_t, j0); GET_MSG_PROPERTY(int32_t, i1); GET_MSG_PROPERTY(int32_t, j1); return new CMessageTerrainChanged(i0, i1, j0, j1); } //////////////////////////////// JS::Value CMessageVisibilityChanged::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(player); SET_MSG_PROPERTY(ent); SET_MSG_PROPERTY(oldVisibility); SET_MSG_PROPERTY(newVisibility); return JS::ObjectValue(*obj); } CMessage* CMessageVisibilityChanged::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(player_id_t, player); GET_MSG_PROPERTY(entity_id_t, ent); GET_MSG_PROPERTY(int, oldVisibility); GET_MSG_PROPERTY(int, newVisibility); return new CMessageVisibilityChanged(player, ent, oldVisibility, newVisibility); } //////////////////////////////// JS::Value CMessageWaterChanged::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); return JS::ObjectValue(*obj); } CMessage* CMessageWaterChanged::FromJSVal(const ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val)) { return new CMessageWaterChanged(); } //////////////////////////////// JS::Value CMessageObstructionMapShapeChanged::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); return JS::ObjectValue(*obj); } CMessage* CMessageObstructionMapShapeChanged::FromJSVal(const ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val)) { return new CMessageObstructionMapShapeChanged(); } //////////////////////////////// JS::Value CMessageTerritoriesChanged::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); return JS::ObjectValue(*obj); } CMessage* CMessageTerritoriesChanged::FromJSVal(const ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val)) { return new CMessageTerritoriesChanged(); } //////////////////////////////// JS::Value CMessageRangeUpdate::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(tag); SET_MSG_PROPERTY(added); SET_MSG_PROPERTY(removed); return JS::ObjectValue(*obj); } CMessage* CMessageRangeUpdate::FromJSVal(const ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val)) { LOGWARNING("CMessageRangeUpdate::FromJSVal not implemented"); return NULL; } //////////////////////////////// JS::Value CMessagePathResult::ToJSVal(const ScriptInterface& UNUSED(scriptInterface)) const { LOGWARNING("CMessagePathResult::ToJSVal not implemented"); return JS::UndefinedValue(); } CMessage* CMessagePathResult::FromJSVal(const ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val)) { LOGWARNING("CMessagePathResult::FromJSVal not implemented"); return NULL; } //////////////////////////////// JS::Value CMessageValueModification::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(entities); SET_MSG_PROPERTY(component); SET_MSG_PROPERTY(valueNames); return JS::ObjectValue(*obj); } CMessage* CMessageValueModification::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(std::vector, entities); GET_MSG_PROPERTY(std::wstring, component); GET_MSG_PROPERTY(std::vector, valueNames); return new CMessageValueModification(entities, component, valueNames); } //////////////////////////////// JS::Value CMessageTemplateModification::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(player); SET_MSG_PROPERTY(component); SET_MSG_PROPERTY(valueNames); return JS::ObjectValue(*obj); } CMessage* CMessageTemplateModification::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(player_id_t, player); GET_MSG_PROPERTY(std::wstring, component); GET_MSG_PROPERTY(std::vector, valueNames); return new CMessageTemplateModification(player, component, valueNames); } //////////////////////////////// JS::Value CMessageVisionRangeChanged::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(entity); SET_MSG_PROPERTY(oldRange); SET_MSG_PROPERTY(newRange); return JS::ObjectValue(*obj); } CMessage* CMessageVisionRangeChanged::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(entity_id_t, entity); GET_MSG_PROPERTY(entity_pos_t, oldRange); GET_MSG_PROPERTY(entity_pos_t, newRange); return new CMessageVisionRangeChanged(entity, oldRange, newRange); } JS::Value CMessageVisionSharingChanged::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(entity); SET_MSG_PROPERTY(player); SET_MSG_PROPERTY(add); return JS::ObjectValue(*obj); } CMessage* CMessageVisionSharingChanged::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(entity_id_t, entity); GET_MSG_PROPERTY(player_id_t, player); GET_MSG_PROPERTY(bool, add); return new CMessageVisionSharingChanged(entity, player, add); } //////////////////////////////// JS::Value CMessageMinimapPing::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); return JS::ObjectValue(*obj); } CMessage* CMessageMinimapPing::FromJSVal(const ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val)) { return new CMessageMinimapPing(); } //////////////////////////////// JS::Value CMessageCinemaPathEnded::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(name); return JS::ObjectValue(*obj); } CMessage* CMessageCinemaPathEnded::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(CStrW, name); return new CMessageCinemaPathEnded(name); } //////////////////////////////// JS::Value CMessageCinemaQueueEnded::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); return JS::ObjectValue(*obj); } CMessage* CMessageCinemaQueueEnded::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); return new CMessageCinemaQueueEnded(); } //////////////////////////////////////////////////////////////// JS::Value CMessagePlayerColorChanged::ToJSVal(const ScriptInterface& scriptInterface) const { TOJSVAL_SETUP(); SET_MSG_PROPERTY(player); return JS::ObjectValue(*obj); } CMessage* CMessagePlayerColorChanged::FromJSVal(const ScriptInterface& scriptInterface, JS::HandleValue val) { FROMJSVAL_SETUP(); GET_MSG_PROPERTY(player_id_t, player); return new CMessagePlayerColorChanged(player); } //////////////////////////////////////////////////////////////// CMessage* CMessageFromJSVal(int mtid, const ScriptInterface& scriptingInterface, JS::HandleValue val) { switch (mtid) { #define MESSAGE(name) case MT_##name: return CMessage##name::FromJSVal(scriptingInterface, val); #define INTERFACE(name) #define COMPONENT(name) #include "simulation2/TypeList.h" #undef COMPONENT #undef INTERFACE #undef MESSAGE } return NULL; }