Ticket #3280: formation_pathfinding.diff
File formation_pathfinding.diff, 25.6 KB (added by , 9 years ago) |
---|
-
binaries/data/mods/public/simulation/components/Formation.js
diff --git a/binaries/data/mods/public/simulation/components/Formation.js b/binaries/data/mods/public/simulation/components/Formation.js index 6bdc3b6..0a125be 100644
a b Formation.prototype.MoveMembersIntoFormation = function(moveCenter, force) 548 548 xMin = Math.min(xMin, offset.x); 549 549 yMin = Math.min(yMin, offset.y); 550 550 } 551 this.width = xMax - xMin; 552 this.depth = yMax - yMin; 551 this.width = xMax - xMin + 4;// TODO take formation width + passClass clearance 552 this.depth = yMax - yMin + 4; 553 554 // set an obstruction size to calculate collisions 555 var cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction); 556 if (cmpObstruction) 557 cmpObstruction.SetSize(this.depth, this.width); 558 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); 559 if (cmpUnitMotion) 560 cmpUnitMotion.SetAllowedDeviation(this.width); 553 561 }; 554 562 555 563 Formation.prototype.MoveToMembersCenter = function() -
binaries/data/mods/public/simulation/components/UnitMotionFormation.js
diff --git a/binaries/data/mods/public/simulation/components/UnitMotionFormation.js b/binaries/data/mods/public/simulation/components/UnitMotionFormation.js index e69de29..3c3c35c 100644
a b 1 function UnitMotionFormation() {} 2 3 UnitMotionFormation.prototype.Schema = 4 "<empty/>"; 5 6 UnitMotionFormation.prototype.Init = function() 7 { 8 this.goal = null; 9 this.pathTicket = 0; 10 this.passClass = 0; 11 this.path = []; 12 this.speed = 1; 13 this.pathIdx = -1; 14 this.state = "IDLE"; 15 this.allowedDeviation = 8; 16 17 var cmpPathfinder = Engine.QueryInterface(SYSTEM_ENTITY, IID_Pathfinder); 18 this.passClass = cmpPathfinder.GetPassabilityClass("default"); 19 }; 20 21 UnitMotionFormation.prototype.SetPassabilityClassName = function(name) 22 { 23 var cmpPathfinder = Engine.QueryInterface(SYSTEM_ENTITY, IID_Pathfinder); 24 this.passClass = cmpPathfinder.GetPassabilityClass(name); 25 }; 26 27 // Ignore, unit radius is not important anymore, only the passability class is 28 UnitMotionFormation.prototype.SetUnitRadius = function() {}; 29 30 UnitMotionFormation.prototype.SetAllowedDeviation = function(allowedDeviation) 31 { 32 this.allowedDeviation = allowedDeviation; 33 }; 34 35 UnitMotionFormation.prototype.IsMoving = function() 36 { 37 return this.pathIdx >= 0; 38 }; 39 UnitMotionFormation.prototype.SetSpeed = function(speed) 40 { 41 this.speed = speed; 42 }; 43 44 UnitMotionFormation.prototype.MoveToPointRange = function(x, z, minRange, maxRange) 45 { 46 this.goal = { 47 "type": 0, 48 "x": x, // target x 49 "z": z, // target z 50 "u": {"x": 1, "y": 0}, // first unit axis 51 "v": {"x": 0, "y": 1}, // second unit axis 52 "hw": maxRange, // for a circle, hw is range 53 "hh": maxRange, 54 "maxdist": 0 // maxdist between waypoints, 0 -> unlimited 55 } 56 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); 57 if (!cmpPosition || !cmpPosition.IsInWorld()) 58 return false; 59 60 var pos = cmpPosition.GetPosition2D(); 61 62 var cmpPathfinder = Engine.QueryInterface(SYSTEM_ENTITY, IID_Pathfinder); 63 this.pathTicket = cmpPathfinder.ComputePathAsync(pos.x, pos.y, this.goal, this.passClass, this.entity); 64 65 this.state = "PATH_REQUESTED"; 66 return true; 67 }; 68 69 UnitMotionFormation.prototype.OnPathResult = function(msg) 70 { 71 if (msg.ticket != this.pathTicket) 72 return; 73 74 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); 75 if (!cmpPosition || !cmpPosition.IsInWorld()) 76 return; 77 78 // TODO path generalisation 79 this.path = msg.path; 80 this.pathIdx = this.path.length -1; 81 // add the current position for reference 82 var pos = cmpPosition.GetPosition2D(); 83 this.path.push({"x" : pos.x, "y": pos.y}); 84 85 var direction = Vector2D.clone(this.path[this.pathIdx]).sub(pos); 86 cmpPosition.TurnTo(Math.atan2(direction.x, direction.y)); 87 88 this.state = "FOLLOW_LINE"; 89 Engine.PostMessage(this.entity, MT_MotionChanged, { "starting": true, "error": false }); 90 }; 91 92 UnitMotionFormation.prototype.OnUpdate = function(msg) 93 { 94 if (!this.IsMoving()) 95 return; 96 if (this.state == "FOLLOW_LINE") 97 this.FollowLine(msg.turnLength); 98 else if (this.state == "TAKE_TURN") 99 this.TakeTurn(msg.turnLength); 100 }; 101 102 UnitMotionFormation.prototype.FollowLine = function(turnLength) 103 { 104 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); 105 if (!cmpPosition || !cmpPosition.IsInWorld()) 106 return; 107 108 var pos = cmpPosition.GetPosition2D(); 109 110 // project current position to original path 111 var target = this.path[this.pathIdx]; 112 var source = this.path[this.pathIdx + 1]; 113 var direction = Vector2D.clone(target).sub(source); 114 var posVec = Vector2D.clone(pos).sub(source); 115 var pathPosition = Vector2D.clone(direction).mult(posVec.dot(direction) / direction.lengthSquared()); 116 117 // Get the distance on the original path 118 var pathToWalk = Vector2D.clone(direction).sub(pathPosition); 119 var distanceToTarget = pathToWalk.length(); 120 var distanceToWalk = this.speed * turnLength; 121 122 if (distanceToTarget < distanceToWalk) // just walk straight on, and start turning 123 { 124 pos.add(pathToWalk); 125 cmpPosition.MoveTo(pos.x, pos.y); 126 // if this is the last target, stop moving 127 if (this.pathIdx) 128 { 129 // else, take a turn 130 var usedTime = distanceToTarget / this.speed; 131 this.state = "TAKE_TURN"; 132 this.TakeTurn(turnLength - usedTime); 133 } 134 else 135 { 136 this.pathIdx--; 137 Engine.PostMessage(this.entity, MT_MotionChanged, { "starting": false, "error": false }); 138 this.state = "IDLE"; 139 } 140 return; 141 } 142 143 var currentDeviation = posVec.distanceTo(pathPosition); 144 if (this.pathIdx == 0 && distanceToTarget <= currentDeviation) 145 { 146 var pathToTarget = Vector2D.clone(target).sub(pos).normalize().mult(distanceToWalk); 147 pos.add(pathToTarget); 148 cmpPosition.MoveTo(pos.x, pos.y); 149 return; 150 } 151 152 // Find the next position 153 // scale the path to walk to include the walkable distance 154 var centerPathToWalk = Vector2D.clone(pathToWalk).mult(distanceToWalk / distanceToTarget); 155 // expand the rotation matrix for the 45deg rotations 156 var leftPathToWalk = new Vector2D(centerPathToWalk.x - centerPathToWalk.y, centerPathToWalk.x + centerPathToWalk.y); 157 var rightPathToWalk = new Vector2D(centerPathToWalk.x + centerPathToWalk.y, -centerPathToWalk.x + centerPathToWalk.y); 158 159 var newCenterPosVec = Vector2D.clone(posVec).add(centerPathToWalk); 160 var newLeftPosVec = Vector2D.clone(posVec).add(leftPathToWalk); 161 var newRightPosVec = Vector2D.clone(posVec).add(rightPathToWalk); 162 163 // project the center to the original path 164 var centerPathPosition = Vector2D.clone(direction).mult(newCenterPosVec.dot(direction) / direction.lengthSquared()); 165 166 var allowLeft = newLeftPosVec.distanceToSquared(centerPathPosition) < this.allowedDeviation * this.allowedDeviation; 167 var allowRight = newRightPosVec.distanceToSquared(centerPathPosition) < this.allowedDeviation * this.allowedDeviation; 168 169 // compare the obstructions 170 var cmpPathfinder = Engine.QueryInterface(SYSTEM_ENTITY, IID_Pathfinder); 171 var centerObstructedTiles = cmpPathfinder.GetObstructedTiles(centerPathToWalk, this.entity, this.passClass); 172 var leftObstructedTiles = Infinity; 173 var rightObstructedTiles = Infinity; 174 if (allowLeft) 175 leftObstructedTiles = cmpPathfinder.GetObstructedTiles(leftPathToWalk, this.entity, this.passClass); 176 if (allowRight) 177 rightObstructedTiles = cmpPathfinder.GetObstructedTiles(rightPathToWalk, this.entity, this.passClass); 178 179 // choose the best of the three positions 180 var min = Math.min(centerObstructedTiles, leftObstructedTiles, rightObstructedTiles); 181 if (min == centerObstructedTiles) 182 pos.add(centerPathToWalk); 183 else if (min == leftObstructedTiles) 184 pos.add(leftPathToWalk); 185 else if (min == rightObstructedTiles) 186 pos.add(rightPathToWalk); 187 188 cmpPosition.MoveTo(pos.x, pos.y); 189 }; 190 191 UnitMotionFormation.prototype.TakeTurn = function(turnLength) 192 { 193 // TODO take time to make a nice turn 194 var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); 195 if (!cmpPosition || !cmpPosition.IsInWorld()) 196 return; 197 var newSource = Vector2D.clone(this.path[this.pathIdx]); 198 var newTarget = Vector2D.clone(this.path[--this.pathIdx]); 199 var newDirection = Vector2D.clone(newTarget).sub(newSource); 200 201 cmpPosition.TurnTo(Math.atan2(newDirection.x, newDirection.y)); 202 this.state = "FOLLOW_LINE"; 203 this.FollowLine(turnLength); 204 }; 205 206 Engine.RegisterComponentType(IID_UnitMotion, "UnitMotionFormation", UnitMotionFormation); -
binaries/data/mods/public/simulation/templates/template_formation.xml
diff --git a/binaries/data/mods/public/simulation/templates/template_formation.xml b/binaries/data/mods/public/simulation/templates/template_formation.xml index c17f0e7..cc151b3 100644
a b 1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Entity> 3 <!-- 3 <!----> 4 4 <VisualActor> 5 5 <Actor>props/special/common/waypoint_flag.xml</Actor> 6 <SilhouetteDisplay>false</SilhouetteDisplay> 7 <SilhouetteOccluder>true</SilhouetteOccluder> 8 <VisibleInAtlasOnly>false</VisibleInAtlasOnly> 6 9 </VisualActor> 7 -->10 <!----> 8 11 <Formation> 9 12 <RequiredMemberCount>1</RequiredMemberCount> 10 13 <DisabledTooltip></DisabledTooltip> … … 21 24 <FormationAttack> 22 25 <CanAttackAsFormation>false</CanAttackAsFormation> 23 26 </FormationAttack> 27 <Obstruction> 28 <Active>false</Active> 29 <BlockMovement>false</BlockMovement> 30 <BlockPathfinding>false</BlockPathfinding> 31 <BlockFoundation>false</BlockFoundation> 32 <BlockConstruction>false</BlockConstruction> 33 <DisableBlockMovement>true</DisableBlockMovement> 34 <DisableBlockPathfinding>true</DisableBlockPathfinding> 35 <Static width="30.0" depth="30.0"/> 36 </Obstruction> 24 37 <Ownership/> 25 38 <Position> 26 39 <Altitude>0</Altitude> … … 35 48 <FormationController>true</FormationController> 36 49 <CanGuard>true</CanGuard> 37 50 </UnitAI> 38 <UnitMotion> 39 <FormationController>true</FormationController> 40 <WalkSpeed>1.0</WalkSpeed> 41 <PassabilityClass>siege-large</PassabilityClass> 42 </UnitMotion> 51 <UnitMotionFormation/> 43 52 <Trader> 44 53 <GainMultiplier>1.0</GainMultiplier> 45 54 </Trader> -
binaries/data/mods/public/simulation/templates/template_unit.xml
diff --git a/binaries/data/mods/public/simulation/templates/template_unit.xml b/binaries/data/mods/public/simulation/templates/template_unit.xml index 761c00a..ed23f03 100644
a b 37 37 <Identity> 38 38 <GenericName>Unit</GenericName> 39 39 <Classes datatype="tokens">Unit ConquestCritical</Classes> 40 <Formations datatype="tokens"> 41 formations/null 42 </Formations> 40 <Formations datatype="tokens"> 41 formations/null 42 formations/box 43 formations/column_closed 44 formations/line_closed 45 formations/column_open 46 formations/line_open 47 formations/flank 48 formations/battle_line 49 </Formations> 43 50 </Identity> 44 51 <Looter/> 45 52 <Minimap> -
source/scriptinterface/ScriptConversions.cpp
diff --git a/source/scriptinterface/ScriptConversions.cpp b/source/scriptinterface/ScriptConversions.cpp index 8ea9b51..dc53121 100644
a b 20 20 #include "ScriptInterface.h" 21 21 22 22 #include "graphics/Entity.h" 23 #include "simulation2/helpers/PathGoal.h" // to convert path goals 23 24 #include "ps/utf16string.h" 24 25 #include "ps/CLogger.h" 25 26 #include "ps/CStr.h" … … template<> bool ScriptInterface::FromJSVal<Entity>(JSContext* cx, JS::HandleValu 205 206 JS::RootedValue position(cx); 206 207 JS::RootedValue rotation(cx); 207 208 208 // TODO: Report type errors 209 // TODO: Report type errors when loading attributes 209 210 if (!JS_GetProperty(cx, obj, "player", &player) || !FromJSVal(cx, player, out.playerID)) 210 211 FAIL("Failed to read Entity.player property"); 211 212 if (!JS_GetProperty(cx, obj, "templateName", &templateName) || !FromJSVal(cx, templateName, out.templateName)) … … template<> bool ScriptInterface::FromJSVal<Entity>(JSContext* cx, JS::HandleValu 220 221 return true; 221 222 } 222 223 224 // TODO this doesn't work (probably always uses POINT) 225 template<> bool ScriptInterface::FromJSVal<PathGoal::Type>(JSContext* cx, JS::HandleValue v, PathGoal::Type& out) 226 { 227 std::string strVal; 228 ScriptInterface::FromJSVal(cx, v, static_cast<std::string&>(strVal)); 229 if (strVal == "CIRCLE") 230 out = PathGoal::CIRCLE; 231 if (strVal == "INVERTED_CIRCLE") 232 out = PathGoal::INVERTED_CIRCLE; 233 else if (strVal == "SQUARE") 234 out = PathGoal::SQUARE; 235 else if (strVal == "INVERTED_SQUARE") 236 out = PathGoal::INVERTED_SQUARE; 237 else 238 out = PathGoal::POINT; 239 return true; 240 } 241 242 template<> bool ScriptInterface::FromJSVal<PathGoal>(JSContext* cx, JS::HandleValue val, PathGoal& out) 243 { 244 JSAutoRequest rq(cx); 245 if (!val.isObject()) 246 FAIL("Argument must be an object"); 247 248 JS::RootedObject obj(cx, &val.toObject()); 249 JS::RootedValue type(cx); 250 JS::RootedValue x(cx); 251 JS::RootedValue z(cx); 252 JS::RootedValue u(cx); 253 JS::RootedValue v(cx); 254 JS::RootedValue hw(cx); 255 JS::RootedValue hh(cx); 256 257 258 // TODO: Report type errors 259 if (!JS_GetProperty(cx, obj, "type", &type) || !FromJSVal(cx, type, out.type)) 260 FAIL("Failed to read goal.type property"); 261 if (!JS_GetProperty(cx, obj, "x", &x) || !FromJSVal(cx, x, out.x)) 262 FAIL("Failed to read goal.x property"); 263 if (!JS_GetProperty(cx, obj, "z", &z) || !FromJSVal(cx, z, out.z)) 264 FAIL("Failed to read goal.z property"); 265 if (!JS_GetProperty(cx, obj, "u", &u) || !FromJSVal(cx, u, out.u)) 266 FAIL("Failed to read goal.u property"); 267 if (!JS_GetProperty(cx, obj, "v", &v) || !FromJSVal(cx, v, out.v)) 268 FAIL("Failed to read goal.v property"); 269 if (!JS_GetProperty(cx, obj, "hw", &hw) || !FromJSVal(cx, hw, out.hw)) 270 FAIL("Failed to read goal.hw property"); 271 if (!JS_GetProperty(cx, obj, "hh", &hh) || !FromJSVal(cx, hh, out.hh)) 272 FAIL("Failed to read goal.hh property"); 273 return true; 274 } 275 223 276 //////////////////////////////////////////////////////////////// 224 277 // Primitive types: 225 278 -
source/simulation2/components/CCmpObstruction.cpp
diff --git a/source/simulation2/components/CCmpObstruction.cpp b/source/simulation2/components/CCmpObstruction.cpp index 40c6963..4e4d897 100644
a b public: 493 493 return CFixedVector2D(m_Size0 / 2, m_Size1 / 2).Length(); 494 494 } 495 495 496 virtual void SetSize(entity_pos_t width, entity_pos_t height) 497 { 498 // require this to be inactive, so we don't have to force grid updates 499 ENSURE(m_Active == false); 500 m_Size0 = width; 501 m_Size0 = height; 502 } 503 496 504 virtual bool IsControlPersistent() 497 505 { 498 506 return m_ControlPersist; -
source/simulation2/components/CCmpPathfinder.cpp
diff --git a/source/simulation2/components/CCmpPathfinder.cpp b/source/simulation2/components/CCmpPathfinder.cpp index f31c303..12ced80 100644
a b void CCmpPathfinder::RenderSubmit(SceneCollector& collector) 188 188 } 189 189 190 190 191 pass_class_t CCmpPathfinder::GetPassabilityClass( const std::string&name)191 pass_class_t CCmpPathfinder::GetPassabilityClass(std::string name) 192 192 { 193 193 if (m_PassClassMasks.find(name) == m_PassClassMasks.end()) 194 194 { … … bool CCmpPathfinder::GetDirtinessData(Grid<u8>& dirtinessGrid, bool& globalUpdat 611 611 612 612 // Async path requests: 613 613 614 u32 CCmpPathfinder::ComputePathAsync(entity_pos_t x0, entity_pos_t z0, const PathGoal&goal, pass_class_t passClass, entity_id_t notify)614 u32 CCmpPathfinder::ComputePathAsync(entity_pos_t x0, entity_pos_t z0, PathGoal goal, pass_class_t passClass, entity_id_t notify) 615 615 { 616 616 AsyncLongPathRequest req = { m_NextAsyncTicket++, x0, z0, goal, passClass, notify }; 617 617 m_AsyncLongPathRequests.push_back(req); … … ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckBuildingPlacement(const I 807 807 return ICmpObstruction::FOUNDATION_CHECK_SUCCESS; 808 808 } 809 809 810 u32 CCmpPathfinder::GetObstructedTiles(CFixedVector2D offset, entity_id_t id, pass_class_t passClass) 811 { 812 // Test against terrain: 813 ICmpObstructionManager::ObstructionSquare square; 814 CmpPtr<ICmpObstruction> cmpObstruction(GetSimContext(), id); 815 if (!cmpObstruction || !cmpObstruction->GetObstructionSquare(square)) 816 return 0; 817 818 square.x += offset.X; 819 square.z += offset.Y; 820 821 UpdateGrid(); 822 823 entity_pos_t expand; 824 const PathfinderPassability* passability = GetPassabilityFromMask(passClass); 825 if (passability && passability->m_HasClearance) 826 expand = passability->m_Clearance; 827 828 SimRasterize::Spans spans; 829 SimRasterize::RasterizeRectWithClearance(spans, square, expand, Pathfinding::NAVCELL_SIZE); 830 u32 obstructedTiles = 0; 831 for (SimRasterize::Span& span : spans) 832 { 833 i16 i0 = span.i0; 834 i16 i1 = span.i1; 835 i16 j = span.j; 836 837 // Fail if any span includes an impassable tile 838 for (i16 i = i0; i < i1; ++i) 839 if (i < 0 || i > m_Grid->m_W || j < 0 || j > m_Grid->m_H || !IS_PASSABLE(m_Grid->get(i, j), passClass)) 840 ++obstructedTiles; 841 } 842 843 return obstructedTiles; 844 } -
source/simulation2/components/CCmpPathfinder_Common.h
diff --git a/source/simulation2/components/CCmpPathfinder_Common.h b/source/simulation2/components/CCmpPathfinder_Common.h index f83b43c..6cb8ee3 100644
a b public: 139 139 140 140 virtual void HandleMessage(const CMessage& msg, bool global); 141 141 142 virtual pass_class_t GetPassabilityClass( const std::string&name);142 virtual pass_class_t GetPassabilityClass(std::string name); 143 143 144 144 virtual std::map<std::string, pass_class_t> GetPassabilityClasses(); 145 145 … … public: 156 156 m_LongPathfinder.ComputePath(x0, z0, goal, passClass, ret); 157 157 } 158 158 159 virtual u32 ComputePathAsync(entity_pos_t x0, entity_pos_t z0, const PathGoal&goal, pass_class_t passClass, entity_id_t notify);159 virtual u32 ComputePathAsync(entity_pos_t x0, entity_pos_t z0, PathGoal goal, pass_class_t passClass, entity_id_t notify); 160 160 161 161 virtual void ComputeShortPath(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t r, entity_pos_t range, const PathGoal& goal, pass_class_t passClass, WaypointPath& ret); 162 162 … … public: 191 191 192 192 virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, entity_id_t id, pass_class_t passClass, bool onlyCenterPoint); 193 193 194 virtual u32 GetObstructedTiles(CFixedVector2D offset, entity_id_t id, pass_class_t passClass); 195 194 196 virtual void FinishAsyncRequests(); 195 197 196 198 void ProcessLongRequests(const std::vector<AsyncLongPathRequest>& longRequests); -
source/simulation2/components/ICmpObstruction.cpp
diff --git a/source/simulation2/components/ICmpObstruction.cpp b/source/simulation2/components/ICmpObstruction.cpp index 33373f9..7a2245c 100644
a b std::string ICmpObstruction::CheckFoundation_wrapper(std::string className, bool 47 47 48 48 BEGIN_INTERFACE_WRAPPER(Obstruction) 49 49 DEFINE_INTERFACE_METHOD_0("GetUnitRadius", entity_pos_t, ICmpObstruction, GetUnitRadius) 50 DEFINE_INTERFACE_METHOD_2("SetSize", void, ICmpObstruction, SetSize, entity_pos_t, entity_pos_t) 50 51 DEFINE_INTERFACE_METHOD_2("CheckFoundation", std::string, ICmpObstruction, CheckFoundation_wrapper, std::string, bool) 51 52 DEFINE_INTERFACE_METHOD_0("CheckDuplicateFoundation", bool, ICmpObstruction, CheckDuplicateFoundation) 52 53 DEFINE_INTERFACE_METHOD_2("GetEntityCollisions", std::vector<entity_id_t>, ICmpObstruction, GetEntityCollisions, bool, bool) -
source/simulation2/components/ICmpObstruction.h
diff --git a/source/simulation2/components/ICmpObstruction.h b/source/simulation2/components/ICmpObstruction.h index 1b289da..7d0fd18 100644
a b public: 54 54 55 55 virtual entity_pos_t GetSize() = 0; 56 56 57 /** 58 * Passively set the size of this obstruction 59 * This must only be used on inactive obstructions, as it won't update any grids 60 */ 61 virtual void SetSize(entity_pos_t width, entity_pos_t height) = 0; 62 57 63 virtual entity_pos_t GetUnitRadius() = 0; 58 64 59 65 virtual bool IsControlPersistent() = 0; -
source/simulation2/components/ICmpPathfinder.cpp
diff --git a/source/simulation2/components/ICmpPathfinder.cpp b/source/simulation2/components/ICmpPathfinder.cpp index df01d65..a85a6d4 100644
a b 24 24 BEGIN_INTERFACE_WRAPPER(Pathfinder) 25 25 DEFINE_INTERFACE_METHOD_1("SetDebugOverlay", void, ICmpPathfinder, SetDebugOverlay, bool) 26 26 DEFINE_INTERFACE_METHOD_1("SetHierDebugOverlay", void, ICmpPathfinder, SetHierDebugOverlay, bool) 27 DEFINE_INTERFACE_METHOD_1("GetPassabilityClass", pass_class_t, ICmpPathfinder, GetPassabilityClass, std::string) 28 DEFINE_INTERFACE_METHOD_3("GetObstructedTiles", u32, ICmpPathfinder, GetObstructedTiles, CFixedVector2D, entity_id_t, pass_class_t) 29 DEFINE_INTERFACE_METHOD_5("ComputePathAsync", u32, ICmpPathfinder, ComputePathAsync, entity_pos_t, entity_pos_t, PathGoal, pass_class_t, entity_id_t) 27 30 END_INTERFACE_WRAPPER(Pathfinder) -
source/simulation2/components/ICmpPathfinder.h
diff --git a/source/simulation2/components/ICmpPathfinder.h b/source/simulation2/components/ICmpPathfinder.h index 70d818f..f57cab2 100644
a b public: 59 59 * Get the tag for a given passability class name. 60 60 * Logs an error and returns something acceptable if the name is unrecognised. 61 61 */ 62 virtual pass_class_t GetPassabilityClass( const std::string&name) = 0;62 virtual pass_class_t GetPassabilityClass(std::string name) = 0; 63 63 64 64 virtual const Grid<u16>& GetPassabilityGrid() = 0; 65 65 … … public: 87 87 * Returns a unique non-zero number, which will match the 'ticket' in the result, 88 88 * so callers can recognise each individual request they make. 89 89 */ 90 virtual u32 ComputePathAsync(entity_pos_t x0, entity_pos_t z0, const PathGoal&goal, pass_class_t passClass, entity_id_t notify) = 0;90 virtual u32 ComputePathAsync(entity_pos_t x0, entity_pos_t z0, PathGoal goal, pass_class_t passClass, entity_id_t notify) = 0; 91 91 92 92 /** 93 93 * If the debug overlay is enabled, render the path that will computed by ComputePath. … … public: 143 143 */ 144 144 virtual ICmpObstruction::EFoundationCheck CheckBuildingPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t a, entity_pos_t w, entity_pos_t h, entity_id_t id, pass_class_t passClass, bool onlyCenterPoint) = 0; 145 145 146 /** 147 * Get the number of obstructed tiles that are under an obstruction of a 148 * certain entity. Allow an offset to easily test alternative positions. 149 */ 150 virtual u32 GetObstructedTiles(CFixedVector2D offset, entity_id_t id, pass_class_t passClass) = 0; 146 151 147 152 /** 148 153 * Toggle the storage and rendering of debug info. -
source/simulation2/scripting/EngineScriptConversions.cpp
diff --git a/source/simulation2/scripting/EngineScriptConversions.cpp b/source/simulation2/scripting/EngineScriptConversions.cpp index bfbeba6..c0deaeb 100644
a b 27 27 #include "ps/Shapes.h" 28 28 #include "ps/utf16string.h" 29 29 #include "simulation2/helpers/Grid.h" 30 #include "simulation2/helpers/Pathfinding.h" 30 31 #include "simulation2/system/IComponent.h" 31 32 #include "simulation2/system/ParamNode.h" 32 33 … … template<> void ScriptInterface::ToJSVal<CFixedVector2D>(JSContext* cx, JS::Muta 247 248 ret.setObject(*obj); 248 249 } 249 250 251 template<> void ScriptInterface::ToJSVal<Waypoint>(JSContext* cx, JS::MutableHandleValue ret, const Waypoint& val) 252 { 253 JSAutoRequest rq(cx); 254 255 // apply the Vector2D prototype to the return value 256 ScriptInterface::CxPrivate* pCxPrivate = ScriptInterface::GetScriptInterfaceAndCBData(cx); 257 JS::RootedObject proto(cx, &pCxPrivate->pScriptInterface->GetCachedValue(ScriptInterface::CACHE_VECTOR2DPROTO).toObject()); 258 JS::RootedObject obj(cx, JS_NewObject(cx, nullptr, proto, JS::NullPtr())); 259 if (!obj) 260 { 261 ret.setUndefined(); 262 return; 263 } 264 265 JS::RootedValue x(cx); 266 JS::RootedValue y(cx); 267 ToJSVal(cx, &x, val.x); 268 ToJSVal(cx, &y, val.z); 269 270 JS_SetProperty(cx, obj, "x", x); 271 JS_SetProperty(cx, obj, "y", y); 272 273 ret.setObject(*obj); 274 } 275 250 276 template<> void ScriptInterface::ToJSVal<Grid<u8> >(JSContext* cx, JS::MutableHandleValue ret, const Grid<u8>& val) 251 277 { 252 278 JSAutoRequest rq(cx); … … template<> void ScriptInterface::ToJSVal<std::vector<CFixedVector2D> >(JSContext 309 335 } 310 336 ret.setObject(*obj); 311 337 } 338 339 template<> void ScriptInterface::ToJSVal<WaypointPath>(JSContext* cx, JS::MutableHandleValue ret, const WaypointPath& val) 340 { 341 JSAutoRequest rq(cx); 342 JS::RootedObject obj(cx, JS_NewArrayObject(cx, 0)); 343 if (!obj) 344 { 345 ret.setUndefined(); 346 return; 347 } 348 const std::vector<Waypoint>& waypointList = val.m_Waypoints; 349 for (size_t i = 0; i < waypointList.size(); ++i) 350 { 351 JS::RootedValue el(cx); 352 ScriptInterface::ToJSVal<Waypoint>(cx, &el, waypointList[i]); 353 JS_SetElement(cx, obj, i, el); 354 } 355 ret.setObject(*obj); 356 } -
source/simulation2/scripting/MessageTypeConversions.cpp
diff --git a/source/simulation2/scripting/MessageTypeConversions.cpp b/source/simulation2/scripting/MessageTypeConversions.cpp index 1b4ea26..f5ce641 100644
a b CMessage* CMessageRangeUpdate::FromJSVal(ScriptInterface& UNUSED(scriptInterface 385 385 386 386 //////////////////////////////// 387 387 388 JS::Value CMessagePathResult::ToJSVal(ScriptInterface& UNUSED(scriptInterface)) const388 JS::Value CMessagePathResult::ToJSVal(ScriptInterface& scriptInterface) const 389 389 { 390 LOGWARNING("CMessagePathResult::ToJSVal not implemented"); 391 return JS::UndefinedValue(); 390 TOJSVAL_SETUP(); 391 SET_MSG_PROPERTY(ticket); 392 SET_MSG_PROPERTY(path); 393 return JS::ObjectValue(*obj); 392 394 } 393 395 394 396 CMessage* CMessagePathResult::FromJSVal(ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val))