Adds snapping to edges for buildings
Allows to place buildings a bit faster and more perfectly aligned. Also it helps to find a nearest placeable position in some cases. Reviewed By: elexis Comments By: Stan, wraitii Differential Revision: https://code.wildfiregames.com/D2079 This was SVN commit r23330.
This commit is contained in:
parent
cf7635f57b
commit
a8f241da5d
@ -313,6 +313,7 @@ unloadtype = Shift ; Modifier to unload all units of type
|
||||
deselectgroup = Ctrl ; Modifier to deselect units when clicking group icon, instead of selecting
|
||||
rotate.cw = RightBracket ; Rotate building placement preview clockwise
|
||||
rotate.ccw = LeftBracket ; Rotate building placement preview anticlockwise
|
||||
snaptoedges = Ctrl ; Modifier to align new structures with nearby existing structure
|
||||
|
||||
[hotkey.session.gui]
|
||||
toggle = "Alt+G" ; Toggle visibility of session GUI
|
||||
@ -377,6 +378,7 @@ healrange = true ; Display heal range overlays of selected unit
|
||||
rankabovestatusbar = true ; Show rank icons above status bars
|
||||
experiencestatusbar = true ; Show an experience status bar above each selected unit
|
||||
respoptooltipsort = 0 ; Sorting players in the resources and population tooltip by value (0 - no sort, -1 - ascending, 1 - descending)
|
||||
snaptoedgesdistancethreshold = 15 ; On which distance we don't snap to edges
|
||||
|
||||
[gui.session.minimap]
|
||||
blinkduration = 1.7 ; The blink duration while pinging
|
||||
|
@ -30,6 +30,13 @@ Vector2D.prototype.set = function(x, y)
|
||||
return this;
|
||||
};
|
||||
|
||||
Vector2D.prototype.setFrom = function(v)
|
||||
{
|
||||
this.x = v.x;
|
||||
this.y = v.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
Vector2D.prototype.add = function(v)
|
||||
{
|
||||
this.x += v.x;
|
||||
@ -240,6 +247,11 @@ Vector2D.sum = function(vectorList)
|
||||
return sum;
|
||||
};
|
||||
|
||||
Vector2D.dot = function(v1, v2)
|
||||
{
|
||||
return v1.x * v2.x + v1.y * v2.y;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Vector3D
|
||||
//
|
||||
|
@ -115,6 +115,7 @@ When you are ready to start, click the "Start game" button.
|
||||
• If the cursor is over an enemy unit or building – Attack (instead of capture or gather)
|
||||
• Otherwise – Attack move (by default all enemy units and structures along the way are targeted)
|
||||
Ctrl + Q + Right Click with unit(s) selected – Attack move, only units along the way are targeted
|
||||
Ctrl + Mouse Move near structures – Align the new structure with an existing nearby structure
|
||||
|
||||
[font="sans-bold-14"]Overlays[font="sans-14"]
|
||||
Alt + G – Hide/show the GUI
|
||||
|
@ -722,11 +722,15 @@ function handleInputBeforeGui(ev, hoveredObject)
|
||||
placementSupport.SetDefaultAngle();
|
||||
}
|
||||
|
||||
var snapData = Engine.GuiInterfaceCall("GetFoundationSnapData", {
|
||||
"template": placementSupport.template,
|
||||
"x": placementSupport.position.x,
|
||||
"z": placementSupport.position.z
|
||||
});
|
||||
let snapToEdges = Engine.HotkeyIsPressed("session.snaptoedges");
|
||||
let snapData = Engine.GuiInterfaceCall("GetFoundationSnapData", {
|
||||
"template": placementSupport.template,
|
||||
"x": placementSupport.position.x,
|
||||
"z": placementSupport.position.z,
|
||||
"angle": placementSupport.angle,
|
||||
"snapToEdges": snapToEdges && Engine.GetEdgesOfStaticObstructionsOnScreenNearTo(
|
||||
placementSupport.position.x, placementSupport.position.z)
|
||||
});
|
||||
if (snapData)
|
||||
{
|
||||
placementSupport.angle = snapData.angle;
|
||||
@ -1045,11 +1049,14 @@ function handleInputAfterGui(ev)
|
||||
return true;
|
||||
}
|
||||
|
||||
var snapData = Engine.GuiInterfaceCall("GetFoundationSnapData", {
|
||||
"template": placementSupport.template,
|
||||
"x": placementSupport.position.x,
|
||||
"z": placementSupport.position.z,
|
||||
});
|
||||
let snapToEdges = Engine.HotkeyIsPressed("session.snaptoedges");
|
||||
let snapData = Engine.GuiInterfaceCall("GetFoundationSnapData", {
|
||||
"template": placementSupport.template,
|
||||
"x": placementSupport.position.x,
|
||||
"z": placementSupport.position.z,
|
||||
"snapToEdges": snapToEdges && Engine.GetEdgesOfStaticObstructionsOnScreenNearTo(
|
||||
placementSupport.position.x, placementSupport.position.z)
|
||||
});
|
||||
if (snapData)
|
||||
{
|
||||
placementSupport.angle = snapData.angle;
|
||||
@ -1073,6 +1080,25 @@ function handleInputAfterGui(ev)
|
||||
else
|
||||
{
|
||||
placementSupport.position = Engine.GetTerrainAtScreenPoint(ev.x, ev.y);
|
||||
|
||||
let snapToEdges = Engine.HotkeyIsPressed("session.snaptoedges");
|
||||
if (snapToEdges)
|
||||
{
|
||||
let snapData = Engine.GuiInterfaceCall("GetFoundationSnapData", {
|
||||
"template": placementSupport.template,
|
||||
"x": placementSupport.position.x,
|
||||
"z": placementSupport.position.z,
|
||||
"snapToEdges": Engine.GetEdgesOfStaticObstructionsOnScreenNearTo(
|
||||
placementSupport.position.x, placementSupport.position.z)
|
||||
});
|
||||
if (snapData)
|
||||
{
|
||||
placementSupport.angle = snapData.angle;
|
||||
placementSupport.position.x = snapData.x;
|
||||
placementSupport.position.z = snapData.z;
|
||||
}
|
||||
}
|
||||
|
||||
g_DragStart = new Vector2D(ev.x, ev.y);
|
||||
inputState = INPUT_BUILDING_CLICK;
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ GuiInterface.prototype.Init = function()
|
||||
this.entsWithAuraAndStatusBars = new Set();
|
||||
this.enabledVisualRangeOverlayTypes = {};
|
||||
this.templateModified = {};
|
||||
this.obstructionSnap = new ObstructionSnap();
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1668,6 +1669,13 @@ GuiInterface.prototype.GetFoundationSnapData = function(player, data)
|
||||
return minDistEntitySnapData;
|
||||
}
|
||||
|
||||
if (data.snapToEdges)
|
||||
{
|
||||
let position = this.obstructionSnap.getPosition(data, template);
|
||||
if (position)
|
||||
return position;
|
||||
}
|
||||
|
||||
if (template.BuildRestrictions.PlacementType == "shore")
|
||||
{
|
||||
let angle = GetDockAngle(template, data.x, data.z);
|
||||
|
@ -1,3 +1,4 @@
|
||||
Engine.LoadHelperScript("ObstructionSnap.js");
|
||||
Engine.LoadHelperScript("Player.js");
|
||||
Engine.LoadComponentScript("interfaces/Attack.js");
|
||||
Engine.LoadComponentScript("interfaces/AlertRaiser.js");
|
||||
|
154
binaries/data/mods/public/simulation/helpers/ObstructionSnap.js
Normal file
154
binaries/data/mods/public/simulation/helpers/ObstructionSnap.js
Normal file
@ -0,0 +1,154 @@
|
||||
/**
|
||||
* The class allows the player to position structures so that they are aligned
|
||||
* with nearby structures.
|
||||
*/
|
||||
class ObstructionSnap
|
||||
{
|
||||
getValidEdges(allEdges, position, maxSide)
|
||||
{
|
||||
let edges = [];
|
||||
let dir1 = new Vector2D();
|
||||
let dir2 = new Vector2D();
|
||||
for (let edge of allEdges)
|
||||
{
|
||||
let signedDistance = Vector2D.dot(edge.normal, position) -
|
||||
Vector2D.dot(edge.normal, edge.begin);
|
||||
// Negative signed distance means that the template position
|
||||
// lays behind the edge.
|
||||
if (signedDistance < -this.MinimalDistanceToSnap - maxSide ||
|
||||
signedDistance > this.MinimalDistanceToSnap + maxSide)
|
||||
continue;
|
||||
dir1.setFrom(edge.begin).sub(edge.end).normalize();
|
||||
dir2.setFrom(dir1).mult(-1);
|
||||
let offsetDistance = Math.max(
|
||||
Vector2D.dot(dir1, position) - Vector2D.dot(dir1, edge.begin),
|
||||
Vector2D.dot(dir2, position) - Vector2D.dot(dir2, edge.end));
|
||||
if (offsetDistance > this.MinimalDistanceToSnap + maxSide)
|
||||
continue;
|
||||
// If a projection of the template position on the edge is
|
||||
// lying inside the edge then obviously we don't need to
|
||||
// account the offset distance.
|
||||
if (offsetDistance < 0)
|
||||
offsetDistance = 0;
|
||||
edge.signedDistance = signedDistance;
|
||||
edge.offsetDistance = offsetDistance;
|
||||
edges.push(edge);
|
||||
}
|
||||
return edges;
|
||||
}
|
||||
|
||||
// We need a small padding to avoid unnecessary collisions
|
||||
// because of loss of accuracy.
|
||||
getPadding(edge)
|
||||
{
|
||||
const snapPadding = 0.05;
|
||||
// We don't need to padding for edges with normals directed inside
|
||||
// its entity, as we try to snap from an internal side of the edge.
|
||||
return edge.order == "ccw" ? 0 : snapPadding;
|
||||
}
|
||||
|
||||
// Pick a base edge, it will be the first axis and fix the angle.
|
||||
// We can't just pick an edge by signed distance, because we might have
|
||||
// a case when one segment is closer by signed distance than another
|
||||
// one but much farther by actual (euclid) distance.
|
||||
compareEdges(a, b)
|
||||
{
|
||||
const behindA = a.signedDistance < -this.EPS;
|
||||
const behindB = b.signedDistance < -this.EPS;
|
||||
const scoreA = Math.abs(a.signedDistance) + a.offsetDistance;
|
||||
const scoreB = Math.abs(b.signedDistance) + b.offsetDistance;
|
||||
if (Math.abs(scoreA - scoreB) < this.EPS)
|
||||
{
|
||||
if (behindA != behindB)
|
||||
return behindA - behindB;
|
||||
if (!behindA)
|
||||
return a.offsetDistance - b.offsetDistance;
|
||||
return -a.signedDistance - -b.signedDistance;
|
||||
}
|
||||
return scoreA - scoreB;
|
||||
}
|
||||
|
||||
getPosition(data, template)
|
||||
{
|
||||
if (!data.snapToEdges || !template.Obstruction || !template.Obstruction.Static)
|
||||
return undefined;
|
||||
|
||||
let width = template.Obstruction.Static["@depth"] / 2;
|
||||
let depth = template.Obstruction.Static["@width"] / 2;
|
||||
const maxSide = Math.max(width, depth);
|
||||
let templatePos = Vector2D.from3D(data);
|
||||
let templateAngle = data.angle || 0;
|
||||
|
||||
let edges = this.getValidEdges(data.snapToEdges, templatePos, maxSide);
|
||||
if (!edges.length)
|
||||
return undefined;
|
||||
|
||||
let baseEdge = edges[0];
|
||||
for (let edge of edges)
|
||||
if (this.compareEdges(edge, baseEdge) < 0)
|
||||
baseEdge = edge;
|
||||
// Now we have the normal, we need to determine an angle,
|
||||
// which side will be snapped first.
|
||||
for (let dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
const angleCandidate = baseEdge.angle + dir * Math.PI / 2;
|
||||
// We need to find a minimal angle difference.
|
||||
let difference = Math.abs(angleCandidate - templateAngle);
|
||||
difference = Math.min(difference, Math.PI * 2 - difference);
|
||||
if (difference < Math.PI / 4 + this.EPS)
|
||||
{
|
||||
// We need to swap sides for orthogonal cases.
|
||||
if (dir % 2 == 0)
|
||||
[width, depth] = [depth, width];
|
||||
templateAngle = angleCandidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let distance = Vector2D.dot(baseEdge.normal, templatePos) - Vector2D.dot(baseEdge.normal, baseEdge.begin);
|
||||
templatePos.sub(Vector2D.mult(baseEdge.normal, distance - width - this.getPadding(baseEdge)));
|
||||
edges = this.getValidEdges(data.snapToEdges, templatePos, maxSide);
|
||||
if (edges.length > 1)
|
||||
{
|
||||
let pairedEdges = [];
|
||||
for (let edge of edges)
|
||||
{
|
||||
// We have to place a rectangle, so the angle between
|
||||
// edges should be 90 degrees.
|
||||
if (Math.abs(Vector2D.dot(baseEdge.normal, edge.normal)) > this.EPS)
|
||||
continue;
|
||||
let newEdge = {
|
||||
"begin": edge.end,
|
||||
"end": edge.begin,
|
||||
"normal": Vector2D.mult(edge.normal, -1),
|
||||
"signedDistance": -edge.signedDistance,
|
||||
"offsetDistance": edge.offsetDistance,
|
||||
"order": "ccw",
|
||||
};
|
||||
pairedEdges.push(edge);
|
||||
pairedEdges.push(newEdge);
|
||||
}
|
||||
pairedEdges.sort(this.compareEdges.bind(this));
|
||||
if (pairedEdges.length)
|
||||
{
|
||||
let secondEdge = pairedEdges[0];
|
||||
for (let edge of pairedEdges)
|
||||
if (this.compareEdges(edge, secondEdge) < 0)
|
||||
secondEdge = edge;
|
||||
let distance = Vector2D.dot(secondEdge.normal, templatePos) - Vector2D.dot(secondEdge.normal, secondEdge.begin);
|
||||
templatePos.sub(Vector2D.mult(secondEdge.normal, distance - depth - this.getPadding(secondEdge)));
|
||||
}
|
||||
}
|
||||
return {
|
||||
"x": templatePos.x,
|
||||
"z": templatePos.y,
|
||||
"angle": templateAngle
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
ObstructionSnap.prototype.MinimalDistanceToSnap = 5;
|
||||
|
||||
ObstructionSnap.prototype.EPS = 1e-3;
|
||||
|
||||
Engine.RegisterGlobal("ObstructionSnap", ObstructionSnap);
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -298,6 +298,7 @@ template<> void ScriptInterface::ToJSVal<char[N]>(JSContext* cx, JS::MutableHand
|
||||
ToJSVal(cx, ret, static_cast<const char*>(val)); \
|
||||
}
|
||||
|
||||
TOJSVAL_CHAR(3)
|
||||
TOJSVAL_CHAR(5)
|
||||
TOJSVAL_CHAR(6)
|
||||
TOJSVAL_CHAR(7)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -519,6 +519,11 @@ public:
|
||||
return CFixedVector2D(m_Size0 / 2, m_Size1 / 2).Length();
|
||||
}
|
||||
|
||||
virtual CFixedVector2D GetStaticSize() const
|
||||
{
|
||||
return m_Type == STATIC ? CFixedVector2D(m_Size0, m_Size1) : CFixedVector2D();
|
||||
}
|
||||
|
||||
virtual void SetUnitClearance(const entity_pos_t& clearance)
|
||||
{
|
||||
if (m_Type == UNIT)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -60,6 +60,8 @@ public:
|
||||
|
||||
virtual entity_pos_t GetSize() const = 0;
|
||||
|
||||
virtual CFixedVector2D GetStaticSize() const = 0;
|
||||
|
||||
virtual entity_pos_t GetUnitRadius() const = 0;
|
||||
|
||||
virtual EObstructionType GetObstructionType() const = 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -30,6 +30,7 @@ public:
|
||||
virtual bool GetObstructionSquare(ICmpObstructionManager::ObstructionSquare& out) const { out = obstruction; return true; }
|
||||
virtual bool GetPreviousObstructionSquare(ICmpObstructionManager::ObstructionSquare& UNUSED(out)) const { return true; }
|
||||
virtual entity_pos_t GetSize() const { return entity_pos_t::Zero(); }
|
||||
virtual CFixedVector2D GetStaticSize() const { return CFixedVector2D(); }
|
||||
virtual entity_pos_t GetUnitRadius() const { return entity_pos_t::Zero(); }
|
||||
virtual EObstructionType GetObstructionType() const { return ICmpObstruction::STATIC; }
|
||||
virtual void SetUnitClearance(const entity_pos_t& UNUSED(clearance)) { }
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -20,6 +20,7 @@
|
||||
#include "JSInterface_Simulation.h"
|
||||
|
||||
#include "graphics/GameView.h"
|
||||
#include "ps/ConfigDB.h"
|
||||
#include "ps/Game.h"
|
||||
#include "ps/GameSetup/Config.h"
|
||||
#include "ps/Pyrogenesis.h"
|
||||
@ -29,9 +30,11 @@
|
||||
#include "simulation2/components/ICmpAIManager.h"
|
||||
#include "simulation2/components/ICmpCommandQueue.h"
|
||||
#include "simulation2/components/ICmpGuiInterface.h"
|
||||
#include "simulation2/components/ICmpPosition.h"
|
||||
#include "simulation2/components/ICmpSelectable.h"
|
||||
#include "simulation2/helpers/Selection.h"
|
||||
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
|
||||
JS::Value JSI_Simulation::GuiInterfaceCall(ScriptInterface::CxPrivate* pCxPrivate, const std::wstring& name, JS::HandleValue data)
|
||||
@ -114,6 +117,79 @@ std::vector<entity_id_t> JSI_Simulation::GetEntitiesWithStaticObstructionOnScree
|
||||
return EntitySelection::GetEntitiesWithComponentInRect<StaticObstructionFilter>(*g_Game->GetSimulation2(), IID_Obstruction, *g_Game->GetView()->GetCamera(), 0, 0, g_xres, g_yres);
|
||||
}
|
||||
|
||||
JS::Value JSI_Simulation::GetEdgesOfStaticObstructionsOnScreenNearTo(ScriptInterface::CxPrivate* pCxPrivate, entity_pos_t x, entity_pos_t z)
|
||||
{
|
||||
if (!g_Game)
|
||||
return JS::UndefinedValue();
|
||||
|
||||
CSimulation2* sim = g_Game->GetSimulation2();
|
||||
ENSURE(sim);
|
||||
|
||||
JSContext* cx = pCxPrivate->pScriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue edgeList(cx);
|
||||
ScriptInterface::CreateArray(cx, &edgeList);
|
||||
int edgeListIndex = 0;
|
||||
|
||||
float distanceThreshold = 10.0f;
|
||||
CFG_GET_VAL("gui.session.snaptoedgesdistancethreshold", distanceThreshold);
|
||||
CFixedVector2D entityPos(x, z);
|
||||
|
||||
std::vector<entity_id_t> entities = GetEntitiesWithStaticObstructionOnScreen(pCxPrivate);
|
||||
for (entity_id_t entity : entities)
|
||||
{
|
||||
CmpPtr<ICmpObstruction> cmpObstruction(sim->GetSimContext(), entity);
|
||||
if (!cmpObstruction)
|
||||
continue;
|
||||
|
||||
CmpPtr<ICmpPosition> cmpPosition(sim->GetSimContext(), entity);
|
||||
if (!cmpPosition || !cmpPosition->IsInWorld())
|
||||
continue;
|
||||
|
||||
CFixedVector2D halfSize = cmpObstruction->GetStaticSize() / 2;
|
||||
if (halfSize.X.IsZero() || halfSize.Y.IsZero() || std::max(halfSize.X, halfSize.Y) <= fixed::FromInt(2))
|
||||
continue;
|
||||
|
||||
std::array<CFixedVector2D, 4> corners = {
|
||||
CFixedVector2D(-halfSize.X, -halfSize.Y),
|
||||
CFixedVector2D(-halfSize.X, halfSize.Y),
|
||||
halfSize,
|
||||
CFixedVector2D(halfSize.X, -halfSize.Y)
|
||||
};
|
||||
fixed angle = cmpPosition->GetRotation().Y;
|
||||
for (CFixedVector2D& corner : corners)
|
||||
corner = corner.Rotate(angle) + cmpPosition->GetPosition2D();
|
||||
|
||||
for (size_t i = 0; i < corners.size(); ++i)
|
||||
{
|
||||
JS::RootedValue edge(cx);
|
||||
const CFixedVector2D& corner = corners[i];
|
||||
const CFixedVector2D& nextCorner = corners[(i + 1) % corners.size()];
|
||||
|
||||
// TODO: calculate real distance;
|
||||
fixed distanceToEdge = std::min(
|
||||
(corner - entityPos).Length(),
|
||||
(nextCorner - entityPos).Length());
|
||||
if (distanceToEdge.ToFloat() > distanceThreshold)
|
||||
continue;
|
||||
|
||||
CFixedVector2D normal = -(nextCorner - corner).Perpendicular();
|
||||
normal.Normalize();
|
||||
ScriptInterface::CreateObject(
|
||||
cx,
|
||||
&edge,
|
||||
"begin", corner,
|
||||
"end", nextCorner,
|
||||
"angle", angle,
|
||||
"normal", normal,
|
||||
"order", "cw");
|
||||
|
||||
pCxPrivate->pScriptInterface->SetPropertyInt(edgeList, edgeListIndex++, edge);
|
||||
}
|
||||
}
|
||||
return edgeList;
|
||||
}
|
||||
|
||||
std::vector<entity_id_t> JSI_Simulation::PickSimilarPlayerEntities(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), const std::string& templateName, bool includeOffScreen, bool matchRank, bool allowFoundations)
|
||||
{
|
||||
return EntitySelection::PickSimilarEntities(*g_Game->GetSimulation2(), *g_Game->GetView()->GetCamera(), templateName, g_Game->GetViewedPlayerID(), includeOffScreen, matchRank, false, allowFoundations);
|
||||
@ -140,6 +216,7 @@ void JSI_Simulation::RegisterScriptFunctions(const ScriptInterface& scriptInterf
|
||||
scriptInterface.RegisterFunction<std::vector<entity_id_t>, int, &PickPlayerEntitiesOnScreen>("PickPlayerEntitiesOnScreen");
|
||||
scriptInterface.RegisterFunction<std::vector<entity_id_t>, &PickNonGaiaEntitiesOnScreen>("PickNonGaiaEntitiesOnScreen");
|
||||
scriptInterface.RegisterFunction<std::vector<entity_id_t>, &GetEntitiesWithStaticObstructionOnScreen>("GetEntitiesWithStaticObstructionOnScreen");
|
||||
scriptInterface.RegisterFunction<JS::Value, entity_pos_t, entity_pos_t, &GetEdgesOfStaticObstructionsOnScreenNearTo>("GetEdgesOfStaticObstructionsOnScreenNearTo");
|
||||
scriptInterface.RegisterFunction<std::vector<entity_id_t>, std::string, bool, bool, bool, &PickSimilarPlayerEntities>("PickSimilarPlayerEntities");
|
||||
scriptInterface.RegisterFunction<void, bool, &SetBoundingBoxDebugOverlay>("SetBoundingBoxDebugOverlay");
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -19,6 +19,7 @@
|
||||
#define INCLUDED_JSI_SIMULATION
|
||||
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
#include "simulation2/helpers/Position.h"
|
||||
#include "simulation2/system/Entity.h"
|
||||
|
||||
namespace JSI_Simulation
|
||||
@ -31,6 +32,7 @@ namespace JSI_Simulation
|
||||
std::vector<entity_id_t> PickPlayerEntitiesOnScreen(ScriptInterface::CxPrivate* pCxPrivate, int player);
|
||||
std::vector<entity_id_t> PickNonGaiaEntitiesOnScreen(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
std::vector<entity_id_t> GetEntitiesWithStaticObstructionOnScreen(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
JS::Value GetEdgesOfStaticObstructionsOnScreenNearTo(ScriptInterface::CxPrivate* pCxPrivate, entity_pos_t x, entity_pos_t z);
|
||||
std::vector<entity_id_t> PickSimilarPlayerEntities(ScriptInterface::CxPrivate* pCxPrivate, const std::string& templateName, bool includeOffScreen, bool matchRank, bool allowFoundations);
|
||||
JS::Value GetAIs(ScriptInterface::CxPrivate* pCxPrivate);
|
||||
void SetBoundingBoxDebugOverlay(ScriptInterface::CxPrivate* pCxPrivate, bool enabled);
|
||||
|
Loading…
Reference in New Issue
Block a user