More work on RMS:
- Created binaries/data/mods/official/maps/random folder to store maps and also moved rmlibrary.js to maps (though perhaps it should be somewhere in system?). - RM generator now uses "logical terrains" that can have units attached to them in addition to textures, for things like forests. - Added basic clump placer, avoid constraints, layered painter, and random terrains (each tile is chosen between several options). - Misc. infrastructure changes. This was SVN commit r2378.
This commit is contained in:
parent
dbecf93e82
commit
bd53b14f58
10
binaries/data/mods/official/maps/random/test.js
Normal file
10
binaries/data/mods/official/maps/random/test.js
Normal file
@ -0,0 +1,10 @@
|
||||
const SIZE = 128;
|
||||
init(SIZE, "snow forest", 0);
|
||||
|
||||
constr = new AvoidTerrainConstraint("snow grass 2");
|
||||
|
||||
println(createArea(
|
||||
new MultiPlacer(new ClumpPlacer(15.0, 0.01, 0.01), 10, 100),
|
||||
new TerrainPainter(new RandomTerrain("snow grass 2|wrld_flora_pine", "snow grass 2")),
|
||||
constr
|
||||
));
|
131
binaries/data/mods/official/maps/rmlibrary.js
Normal file
131
binaries/data/mods/official/maps/rmlibrary.js
Normal file
@ -0,0 +1,131 @@
|
||||
// Object type constants
|
||||
|
||||
const
|
||||
TYPE_RECTPLACER = 1,
|
||||
TYPE_TERRAINPAINTER = 2,
|
||||
TYPE_NULLCONSTRAINT = 3,
|
||||
TYPE_RANDOMTERRAIN = 4,
|
||||
TYPE_LAYEREDPAINTER = 5,
|
||||
TYPE_AVOIDAREACONSTRAINT = 6,
|
||||
TYPE_CLUMPPLACER = 7,
|
||||
TYPE_EXACTPLACER = 8,
|
||||
TYPE_AVOIDTERRAINCONSTRAINT = 9,
|
||||
TYPE_ANDCONSTRAINT = 10,
|
||||
TYPE_MULTIPLACER = 11;
|
||||
|
||||
// Utility functions
|
||||
|
||||
function println(x) {
|
||||
print(x);
|
||||
print("\n");
|
||||
}
|
||||
|
||||
function argsToArray(x) {
|
||||
if(x.length!=1) {
|
||||
var ret = new Array();
|
||||
for(var i=0; i<x.length; i++) {
|
||||
ret[i] = x[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
return x[0];
|
||||
}
|
||||
}
|
||||
|
||||
function chooseRand() {
|
||||
if(arguments.length==0) {
|
||||
error("chooseRand: requires at least 1 argument");
|
||||
}
|
||||
var ar = argsToArray(arguments);
|
||||
return ar[randInt(ar.length)];
|
||||
}
|
||||
|
||||
// Area placers
|
||||
|
||||
function RectPlacer(x1, y1, x2, y2) {
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
this.x2 = x2;
|
||||
this.y2 = y2;
|
||||
this.raw = function() {
|
||||
return [TYPE_RECTPLACER, this.x1, this.y1, this.x2, this.y2];
|
||||
}
|
||||
}
|
||||
|
||||
function TerrainPainter(terrain) {
|
||||
this.terrain = terrain;
|
||||
this.raw = function() {
|
||||
return [TYPE_TERRAINPAINTER, this.terrain];
|
||||
}
|
||||
}
|
||||
|
||||
function NullConstraint() {
|
||||
this.raw = function() {
|
||||
return [TYPE_NULLCONSTRAINT];
|
||||
}
|
||||
}
|
||||
|
||||
function RandomTerrain() {
|
||||
this.terrains = argsToArray(arguments);
|
||||
this.raw = function() {
|
||||
return [TYPE_RANDOMTERRAIN, this.terrains];
|
||||
}
|
||||
}
|
||||
|
||||
function LayeredPainter(widths, terrains) {
|
||||
this.widths = widths;
|
||||
this.terrains = terrains;
|
||||
this.raw = function() {
|
||||
return [TYPE_LAYEREDPAINTER, this.widths, this.terrains];
|
||||
}
|
||||
}
|
||||
|
||||
function AvoidAreaConstraint(area) {
|
||||
this.area = area;
|
||||
this.raw = function() {
|
||||
return [TYPE_AVOIDAREACONSTRAINT, this.area];
|
||||
}
|
||||
}
|
||||
|
||||
function ClumpPlacer(size, coherence, smoothness) {
|
||||
this.size = size;
|
||||
this.coherence = coherence;
|
||||
this.smoothness = smoothness;
|
||||
this.raw = function() {
|
||||
return [TYPE_CLUMPPLACER, this.size, this.coherence, this.smoothness];
|
||||
}
|
||||
}
|
||||
|
||||
function ExactPlacer(cp, x, y) {
|
||||
this.cp = cp;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.raw = function() {
|
||||
return [TYPE_EXACTPLACER, this.cp, this.x, this.y];
|
||||
}
|
||||
}
|
||||
|
||||
function AvoidTerrainConstraint(texture) {
|
||||
this.texture = texture;
|
||||
this.raw = function() {
|
||||
return [TYPE_AVOIDTERRAINCONSTRAINT, this.texture];
|
||||
}
|
||||
}
|
||||
|
||||
function AndConstraint(a, b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.raw = function() {
|
||||
return [TYPE_ANDCONSTRAINT, this.a, this.b];
|
||||
}
|
||||
}
|
||||
|
||||
function MultiPlacer(cp, num, maxFail) {
|
||||
this.cp = cp;
|
||||
this.num = num;
|
||||
this.maxFail = maxFail;
|
||||
this.raw = function() {
|
||||
return [TYPE_MULTIPLACER, this.cp, this.num, this.maxFail];
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@
|
||||
#include "map.h"
|
||||
#include "entity.h"
|
||||
#include "objparse.h"
|
||||
#include "terrain.h"
|
||||
#include "simpleconstraints.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -15,8 +17,8 @@ JSFunctionSpec globalFunctions[] = {
|
||||
{"init", init, 3},
|
||||
{"print", print, 1},
|
||||
{"error", error, 1},
|
||||
{"getTerrain", getTerrain, 2},
|
||||
{"setTerrain", setTerrain, 3},
|
||||
{"getTexture", getTexture, 2},
|
||||
{"setTexture", setTexture, 3},
|
||||
{"getHeight", getHeight, 2},
|
||||
{"setHeight", setHeight, 3},
|
||||
{"randInt", randInt, 1},
|
||||
@ -49,7 +51,7 @@ void ValidateArgs(const char* types, JSContext* cx, uintN argc, jsval* argv, con
|
||||
break;
|
||||
case 's':
|
||||
if(!JSVAL_IS_STRING(argv[i])) {
|
||||
JS_ReportError(cx, "%s: argument %d must be an integer", function, i+1);
|
||||
JS_ReportError(cx, "%s: argument %d must be a string", function, i+1);
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
@ -95,13 +97,16 @@ JSBool error(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
|
||||
JSBool init(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
ValidateArgs("isn", cx, argc, argv, __FUNCTION__);
|
||||
ValidateArgs("i*n", cx, argc, argv, __FUNCTION__);
|
||||
if(theMap != 0) {
|
||||
JS_ReportError(cx, "init: cannot be called twice");
|
||||
}
|
||||
|
||||
int size = JSVAL_TO_INT(argv[0]);
|
||||
char* baseTerrain = JS_GetStringBytes(JSVAL_TO_STRING(argv[1]));
|
||||
Terrain* baseTerrain = ParseTerrain(cx, argv[1]);
|
||||
if(!baseTerrain) {
|
||||
JS_ReportError(cx, "init: argument 2 must be a terrain");
|
||||
}
|
||||
jsdouble baseHeight;
|
||||
JS_ValueToNumber(cx, argv[2], &baseHeight);
|
||||
|
||||
@ -109,31 +114,31 @@ JSBool init(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool getTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
JSBool getTexture(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
ValidateArgs("ii", cx, argc, argv, __FUNCTION__);
|
||||
if(theMap == 0) {
|
||||
JS_ReportError(cx, "getTerrain: cannot be called before init()");
|
||||
JS_ReportError(cx, "getTexture: cannot be called before init()");
|
||||
}
|
||||
|
||||
int x = JSVAL_TO_INT(argv[0]);
|
||||
int y = JSVAL_TO_INT(argv[1]);
|
||||
string terrain = theMap->getTerrain(x, y);
|
||||
*rval = NewJSString(terrain);
|
||||
string texture = theMap->getTexture(x, y);
|
||||
*rval = NewJSString(texture);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool setTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
JSBool setTexture(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
ValidateArgs("iis", cx, argc, argv, __FUNCTION__);
|
||||
if(theMap == 0) {
|
||||
JS_ReportError(cx, "setTerrain: cannot be called before init()");
|
||||
JS_ReportError(cx, "setTexture: cannot be called before init()");
|
||||
}
|
||||
|
||||
int x = JSVAL_TO_INT(argv[0]);
|
||||
int y = JSVAL_TO_INT(argv[1]);
|
||||
char* terrain = JS_GetStringBytes(JSVAL_TO_STRING(argv[2]));
|
||||
theMap->setTerrain(x, y, terrain);
|
||||
char* texture = JS_GetStringBytes(JSVAL_TO_STRING(argv[2]));
|
||||
theMap->setTexture(x, y, texture);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@ -207,6 +212,23 @@ JSBool addEntity(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *r
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool placeTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
ValidateArgs("ii*", cx, argc, argv, __FUNCTION__);
|
||||
if(theMap == 0) {
|
||||
JS_ReportError(cx, "placeTerrain: cannot be called before init()");
|
||||
}
|
||||
|
||||
int x = JSVAL_TO_INT(argv[0]);
|
||||
int y = JSVAL_TO_INT(argv[1]);
|
||||
Terrain* terrain = ParseTerrain(cx, argv[2]);
|
||||
if(!terrain) {
|
||||
JS_ReportError(cx, "placeTerrain: invalid terrain argument");
|
||||
}
|
||||
theMap->placeTerrain(x, y, terrain);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool createArea(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
if(argc != 2 && argc != 3) {
|
||||
@ -221,14 +243,14 @@ JSBool createArea(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *
|
||||
Constraint* constr;
|
||||
|
||||
if(!(placer = ParsePlacer(cx, argv[0]))) {
|
||||
JS_ReportError(cx, "createArea: argument 1 must be an area placer");
|
||||
JS_ReportError(cx, "createArea: argument 1 must be a valid area placer");
|
||||
}
|
||||
if(!(painter = ParsePainter(cx, argv[1]))) {
|
||||
JS_ReportError(cx, "createArea: argument 2 must be an area paint");
|
||||
JS_ReportError(cx, "createArea: argument 2 must be a valid area painter");
|
||||
}
|
||||
if(argc == 3) {
|
||||
if(!(constr = ParseConstraint(cx, argv[2]))) {
|
||||
JS_ReportError(cx, "createArea: argument 3 must be a constraint");
|
||||
JS_ReportError(cx, "createArea: argument 3 must be a valid constraint");
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -14,12 +14,14 @@ JSBool print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
JSBool randInt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
JSBool randFloat(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
JSBool getTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
JSBool setTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
JSBool getTexture(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
JSBool setTexture(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
JSBool getHeight(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
JSBool setHeight(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
JSBool placeTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
JSBool addEntity(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
JSBool createArea(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
@ -3,11 +3,12 @@
|
||||
|
||||
#include "point.h"
|
||||
#include "constraint.h"
|
||||
#include "map.h"
|
||||
|
||||
class CenteredPlacer
|
||||
{
|
||||
public:
|
||||
virtual bool place(class Map* m, Constraint* constr, std::vector<Point>& ret, int x, int y) = 0;
|
||||
virtual bool place(Map* m, Constraint* constr, std::vector<Point>& ret, int x, int y) = 0;
|
||||
|
||||
CenteredPlacer(void);
|
||||
virtual ~CenteredPlacer(void);
|
||||
|
86
source/tools/rmgen/clumpplacer.cpp
Normal file
86
source/tools/rmgen/clumpplacer.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include "stdafx.h"
|
||||
#include "clumpplacer.h"
|
||||
#include "random.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
ClumpPlacer::ClumpPlacer(float size, float coherence, float smoothness)
|
||||
{
|
||||
this->size = size;
|
||||
this->coherence = coherence;
|
||||
this->smoothness = smoothness;
|
||||
}
|
||||
|
||||
ClumpPlacer::~ClumpPlacer()
|
||||
{
|
||||
}
|
||||
|
||||
bool ClumpPlacer::place(class Map* m, Constraint* constr, std::vector<Point>& ret, int x, int y) {
|
||||
float radius = sqrt(size / PI);
|
||||
float perim = 3 * radius * 2 * PI;
|
||||
int intPerim = (int)(ceil(perim));
|
||||
vector<float> noise(intPerim);
|
||||
|
||||
//cout << "Starting with s=" << smoothness << ", p=" << perim << endl;
|
||||
//cout << "Ctrl Vals: " << endl;
|
||||
int ctrlPts = 1 + (int)(1.0/max(smoothness,1.0f/intPerim));
|
||||
if(ctrlPts > radius * 2 * PI) ctrlPts = (int) (radius * 2 * PI) + 1;
|
||||
vector<float> ctrlCoords(ctrlPts+1);
|
||||
vector<float> ctrlVals(ctrlPts+1);
|
||||
for(int i=0; i<ctrlPts; i++) {
|
||||
ctrlCoords[i] = i * perim / ctrlPts;
|
||||
ctrlVals[i] = 2.0*RandFloat();
|
||||
//cout << ctrlCoords[i] << " " << ctrlVals[i] << endl;
|
||||
}
|
||||
//cout << "Noise Vals: " << endl;
|
||||
int c = 0;
|
||||
int looped = 0;
|
||||
for(int i=0; i<intPerim; i++) {
|
||||
if(ctrlCoords[(c+1) % ctrlPts] < i && !looped) {
|
||||
c = (c+1) % ctrlPts;
|
||||
if(c==ctrlPts-1) looped = 1;
|
||||
}
|
||||
float t = (i - ctrlCoords[c]) / ((looped ? perim : ctrlCoords[(c+1)%ctrlPts]) - ctrlCoords[c]);
|
||||
float v0 = ctrlVals[(c+ctrlPts-1)%ctrlPts];
|
||||
float v1 = ctrlVals[c];
|
||||
float v2 = ctrlVals[(c+1)%ctrlPts];
|
||||
float v3 = ctrlVals[(c+2)%ctrlPts];
|
||||
float P = (v3 - v2) - (v0 - v1);
|
||||
float Q = (v0 - v1) - P;
|
||||
float R = v2 - v0;
|
||||
float S = v1;
|
||||
noise[i] = P*t*t*t + Q*t*t + R*t + S;
|
||||
//noise[i] = ctrlVals[(c+1)%ctrlPts] * t + ctrlVals[c] * (1-t);
|
||||
//cout << i << " " << c << " " << noise[i] << endl;
|
||||
}
|
||||
|
||||
int failed = 0;
|
||||
for(int p=0; p<intPerim; p++) {
|
||||
float th = 2 * PI * p / perim;
|
||||
float r = radius * (1 + (1-coherence)*noise[p]);
|
||||
float s = sin(th);
|
||||
float c = cos(th);
|
||||
float xx=x, yy=y;
|
||||
for(float k=0; k<r; k++) {
|
||||
int i = (int)xx, j = (int)yy;
|
||||
if(m->validT(i, j) && constr->allows(m, i, j)) {
|
||||
ret.push_back(Point(i, j));
|
||||
}
|
||||
else {
|
||||
failed++;
|
||||
}
|
||||
xx += s;
|
||||
yy += c;
|
||||
}
|
||||
}
|
||||
|
||||
return failed > 0 ? false : true;
|
||||
|
||||
/*if(m->validT(x,y)) {
|
||||
ret.push_back(Point(x,y));
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return true;*/
|
||||
}
|
20
source/tools/rmgen/clumpplacer.h
Normal file
20
source/tools/rmgen/clumpplacer.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef __CLUMPPLACER_H__
|
||||
#define __CLUMPPLACER_H__
|
||||
|
||||
#include "centeredplacer.h"
|
||||
#include "map.h"
|
||||
|
||||
class ClumpPlacer : public CenteredPlacer
|
||||
{
|
||||
private:
|
||||
float size;
|
||||
float coherence;
|
||||
float smoothness;
|
||||
public:
|
||||
virtual bool place(Map* m, Constraint* constr, std::vector<Point>& ret, int x, int y);
|
||||
|
||||
ClumpPlacer(float size, float coherence, float smoothness);
|
||||
virtual ~ClumpPlacer();
|
||||
};
|
||||
|
||||
#endif
|
74
source/tools/rmgen/layeredpainter.cpp
Normal file
74
source/tools/rmgen/layeredpainter.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include "stdafx.h"
|
||||
#include "layeredpainter.h"
|
||||
#include "area.h"
|
||||
#include "terrain.h"
|
||||
#include "map.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
LayeredPainter::LayeredPainter(const vector<Terrain*>& ts, const vector<int>& ws)
|
||||
{
|
||||
terrains = ts;
|
||||
widths = ws;
|
||||
}
|
||||
|
||||
LayeredPainter::~LayeredPainter(void)
|
||||
{
|
||||
}
|
||||
|
||||
void LayeredPainter::paint(Map* m, Area* a) {
|
||||
map<Point, int> saw;
|
||||
map<Point, int> dist;
|
||||
|
||||
queue<Point> q;
|
||||
|
||||
// push edge points
|
||||
vector<Point>& pts = a->points;
|
||||
for(int i=0; i<pts.size(); i++) {
|
||||
int x = pts[i].x, y = pts[i].y;
|
||||
for(int dx=-1; dx<=1; dx++) {
|
||||
for(int dy=-1; dy<=1; dy++) {
|
||||
int nx = x+dx, ny = y+dy;
|
||||
Point np(nx, ny);
|
||||
if(m->validT(nx, ny) && m->area[nx][ny]!=a && !saw[np]) {
|
||||
saw[np] = 1;
|
||||
dist[np] = 0;
|
||||
q.push(np);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do BFS inwards to find distances to edge
|
||||
while(!q.empty()) {
|
||||
Point p = q.front();
|
||||
q.pop();
|
||||
|
||||
int d = dist[p];
|
||||
|
||||
// paint if in area
|
||||
if(m->area[p.x][p.y] == a) {
|
||||
int w=0, i=0;
|
||||
for(; i<widths.size(); i++) {
|
||||
w += widths[i];
|
||||
if(w>=d) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
terrains[i]->place(m, p.x, p.y);
|
||||
}
|
||||
|
||||
// enqueue neighbours
|
||||
for(int dx=-1; dx<=1; dx++) {
|
||||
for(int dy=-1; dy<=1; dy++) {
|
||||
int nx = p.x+dx, ny = p.y+dy;
|
||||
Point np(nx, ny);
|
||||
if(m->validT(nx, ny) && m->area[nx][ny]==a && !saw[np]) {
|
||||
saw[np] = 1;
|
||||
dist[np] = d+1;
|
||||
q.push(np);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
20
source/tools/rmgen/layeredpainter.h
Normal file
20
source/tools/rmgen/layeredpainter.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef __LAYEREDPAINTER_H__
|
||||
#define __LAYEREDPAINTER_H__
|
||||
|
||||
#include "areapainter.h"
|
||||
#include "terrain.h"
|
||||
|
||||
class LayeredPainter :
|
||||
public AreaPainter
|
||||
{
|
||||
private:
|
||||
std::vector<Terrain*> terrains;
|
||||
std::vector<int> widths;
|
||||
public:
|
||||
LayeredPainter(const std::vector<Terrain*>& terrains, const std::vector<int>& widths);
|
||||
~LayeredPainter(void);
|
||||
|
||||
virtual void paint(class Map* m, class Area* a);
|
||||
};
|
||||
|
||||
#endif
|
@ -1,46 +0,0 @@
|
||||
// Object type constants
|
||||
|
||||
const
|
||||
TYPE_RECTPLACER = 1,
|
||||
TYPE_TERRAINPAINTER = 2,
|
||||
TYPE_NULLCONSTRAINT = 3;
|
||||
|
||||
// Utility functions
|
||||
|
||||
function println(x) {
|
||||
print(x);
|
||||
print("\n");
|
||||
}
|
||||
|
||||
function chooseRand() {
|
||||
if(arguments.length==0) {
|
||||
error("chooseRand: requires at least 1 argument");
|
||||
}
|
||||
var ar = (arguments.length==1 ? arguments[0] : arguments);
|
||||
return ar[randInt(ar.length)];
|
||||
}
|
||||
|
||||
// Area placers
|
||||
|
||||
function RectPlacer(x1, y1, x2, y2) {
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
this.x2 = x2;
|
||||
this.y2 = y2;
|
||||
this.raw = function() {
|
||||
return [TYPE_RECTPLACER, this.x1, this.y1, this.x2, this.y2];
|
||||
}
|
||||
}
|
||||
|
||||
function TerrainPainter(terrain) {
|
||||
this.terrain = terrain;
|
||||
this.raw = function() {
|
||||
return [TYPE_TERRAINPAINTER, this.terrain];
|
||||
}
|
||||
}
|
||||
|
||||
function NullConstraint() {
|
||||
this.raw = function() {
|
||||
return [TYPE_NULLCONSTRAINT];
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
Map::Map(int size, const string& baseTerrain, float baseHeight) {
|
||||
Map::Map(int size, Terrain* baseTerrain, float baseHeight) {
|
||||
if(size<0 || size>1024) {
|
||||
JS_ReportError(cx, "init: map size out of range");
|
||||
}
|
||||
@ -15,14 +15,14 @@ Map::Map(int size, const string& baseTerrain, float baseHeight) {
|
||||
|
||||
this->size = size;
|
||||
|
||||
int baseId = getId(baseTerrain);
|
||||
|
||||
terrain = new int*[size];
|
||||
texture = new int*[size];
|
||||
for(int i=0; i<size; i++) {
|
||||
terrain[i] = new int[size];
|
||||
for(int j=0; j<size; j++) {
|
||||
terrain[i][j] = baseId;
|
||||
}
|
||||
texture[i] = new int[size];
|
||||
}
|
||||
|
||||
terrainEntities = new vector<Entity*>*[size];
|
||||
for(int i=0; i<size; i++) {
|
||||
terrainEntities[i] = new vector<Entity*>[size];
|
||||
}
|
||||
|
||||
area = new Area**[size];
|
||||
@ -40,37 +40,48 @@ Map::Map(int size, const string& baseTerrain, float baseHeight) {
|
||||
height[i][j] = baseHeight;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<size; i++) {
|
||||
for(int j=0; j<size; j++) {
|
||||
baseTerrain->place(this, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map::~Map() {
|
||||
for(int i=0; i<size; i++) {
|
||||
delete[] terrain[i];
|
||||
delete[] texture[i];
|
||||
}
|
||||
delete[] terrain;
|
||||
delete[] texture;
|
||||
|
||||
for(int i=0; i<size; i++) {
|
||||
delete[] area[i];
|
||||
delete[] terrainEntities[i];
|
||||
}
|
||||
delete[] area;
|
||||
delete[] terrainEntities;
|
||||
|
||||
for(int i=0; i<size+1; i++) {
|
||||
delete[] height[i];
|
||||
}
|
||||
delete[] height;
|
||||
|
||||
for(int i=0; i<size; i++) {
|
||||
delete[] area[i];
|
||||
}
|
||||
delete[] area;
|
||||
|
||||
for(int i=0; i<entities.size(); i++) {
|
||||
delete entities[i];
|
||||
}
|
||||
}
|
||||
|
||||
int Map::getId(string terrain) {
|
||||
if(nameToId.find(terrain) != nameToId.end()) {
|
||||
return nameToId[terrain];
|
||||
int Map::getId(string texture) {
|
||||
if(nameToId.find(texture) != nameToId.end()) {
|
||||
return nameToId[texture];
|
||||
}
|
||||
else {
|
||||
int newId = nameToId.size();
|
||||
nameToId[terrain] = newId;
|
||||
idToName[newId] = terrain;
|
||||
nameToId[texture] = newId;
|
||||
idToName[newId] = texture;
|
||||
return newId;
|
||||
}
|
||||
}
|
||||
@ -83,14 +94,14 @@ bool Map::validH(int x, int y) {
|
||||
return x>=0 && y>=0 && x<size+1 && y<size+1;
|
||||
}
|
||||
|
||||
string Map::getTerrain(int x, int y) {
|
||||
if(!validT(x,y)) JS_ReportError(cx, "getTerrain: invalid tile position");
|
||||
return idToName[terrain[x][y]];
|
||||
string Map::getTexture(int x, int y) {
|
||||
if(!validT(x,y)) JS_ReportError(cx, "getTexture: invalid tile position");
|
||||
return idToName[texture[x][y]];
|
||||
}
|
||||
|
||||
void Map::setTerrain(int x, int y, const string& t) {
|
||||
if(!validT(x,y)) JS_ReportError(cx, "setTerrain: invalid tile position");
|
||||
terrain[x][y] = getId(t);
|
||||
void Map::setTexture(int x, int y, const string& t) {
|
||||
if(!validT(x,y)) JS_ReportError(cx, "setTexture: invalid tile position");
|
||||
texture[x][y] = getId(t);
|
||||
}
|
||||
|
||||
float Map::getHeight(int x, int y) {
|
||||
@ -103,6 +114,10 @@ void Map::setHeight(int x, int y, float h) {
|
||||
height[x][y] = h;
|
||||
}
|
||||
|
||||
void Map::placeTerrain(int x, int y, Terrain* t) {
|
||||
t->place(this, x, y);
|
||||
}
|
||||
|
||||
void Map::addEntity(Entity* ent) {
|
||||
entities.push_back(ent);
|
||||
}
|
||||
@ -117,5 +132,6 @@ Area* Map::createArea(AreaPlacer* placer, AreaPainter* painter, Constraint* cons
|
||||
area[points[i].x][points[i].y] = a;
|
||||
}
|
||||
painter->paint(this, a);
|
||||
areas.push_back(a);
|
||||
return a;
|
||||
}
|
@ -6,11 +6,13 @@
|
||||
#include "areaplacer.h"
|
||||
#include "constraint.h"
|
||||
#include "entity.h"
|
||||
#include "terrain.h"
|
||||
|
||||
class Map {
|
||||
public:
|
||||
int size;
|
||||
int** terrain;
|
||||
int** texture;
|
||||
std::vector<Entity*>** terrainEntities;
|
||||
float** height;
|
||||
Area*** area;
|
||||
std::map<std::string, int> nameToId;
|
||||
@ -18,20 +20,22 @@ public:
|
||||
std::vector<Entity*> entities;
|
||||
std::vector<Area*> areas;
|
||||
|
||||
Map(int size, const std::string& baseTerrain, float baseHeight);
|
||||
Map(int size, Terrain* baseTerrain, float baseHeight);
|
||||
~Map();
|
||||
|
||||
int getId(std::string terrain);
|
||||
int getId(std::string texture);
|
||||
|
||||
bool validT(int x, int y);
|
||||
bool validH(int x, int y);
|
||||
|
||||
std::string getTerrain(int x, int y);
|
||||
void setTerrain(int x, int y, const std::string& terrain);
|
||||
std::string getTexture(int x, int y);
|
||||
void setTexture(int x, int y, const std::string& texture);
|
||||
|
||||
float getHeight(int x, int y);
|
||||
void setHeight(int x, int y, float height);
|
||||
|
||||
void placeTerrain(int x, int y, Terrain* t);
|
||||
|
||||
void addEntity(class Entity* ent);
|
||||
|
||||
Area* createArea(AreaPlacer* placer, AreaPainter* painter, Constraint* constr);
|
||||
|
@ -1,11 +1,17 @@
|
||||
#include "stdafx.h"
|
||||
#include "objparse.h"
|
||||
#include "rmgen.h"
|
||||
#include "simpleconstraints.h"
|
||||
#include "simplepainters.h"
|
||||
#include "simpleplacers.h"
|
||||
#include "rectplacer.h"
|
||||
#include "layeredpainter.h"
|
||||
#include "clumpplacer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool GetRaw(JSContext* cx, jsval val, JSObject** retObj, int* retType) {
|
||||
if(!JSVAL_IS_OBJECT(val)) return 0;
|
||||
if(!JSVAL_IS_OBJECT(val)) return false;
|
||||
JSObject* obj = JSVAL_TO_OBJECT(val);
|
||||
jsval ret;
|
||||
if(!JS_CallFunctionName(cx, obj, "raw", 0, 0, &ret)) {
|
||||
@ -61,7 +67,7 @@ bool ParseFields(JSContext* cx, JSObject* array, const char* format, ...) {
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Internal Error: unsupported type '" << format[i] << "' for ParseArgs!\n";
|
||||
cerr << "Internal Error: unsupported type '" << format[i] << "' for ParseFields!\n";
|
||||
Shutdown(1);
|
||||
return false;
|
||||
}
|
||||
@ -70,31 +76,99 @@ bool ParseFields(JSContext* cx, JSObject* array, const char* format, ...) {
|
||||
return true;
|
||||
}
|
||||
|
||||
AreaPlacer* ParsePlacer(JSContext* cx, jsval val) {
|
||||
JSObject* obj; int type;
|
||||
if(!GetRaw(cx, val, &obj, &type)) return 0;
|
||||
|
||||
int x1, y1, x2, y2;
|
||||
|
||||
switch(type) {
|
||||
case TYPE_RECTPLACER:
|
||||
ParseFields(cx, obj, "iiii", &x1, &y1, &x2, &y2);
|
||||
return new RectPlacer(x1, y1, x2, y2);
|
||||
default:
|
||||
return 0;
|
||||
bool ParseArray(JSContext* cx, jsval val, vector<jsval>& ret) {
|
||||
ret.clear();
|
||||
if(!JSVAL_IS_OBJECT(val)) return false;
|
||||
JSObject* obj = JSVAL_TO_OBJECT(val);
|
||||
if(!JS_IsArrayObject(cx, obj)) return false;
|
||||
jsuint len;
|
||||
JS_GetArrayLength(cx, obj, &len);
|
||||
for(int i=0; i<len; i++) {
|
||||
jsval rval;
|
||||
JS_GetElement(cx, obj, i, &rval);
|
||||
ret.push_back(rval);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
AreaPainter* ParsePainter(JSContext* cx, jsval val) {
|
||||
JSObject* obj; int type;
|
||||
if(!GetRaw(cx, val, &obj, &type)) return 0;
|
||||
|
||||
string terrain;
|
||||
jsval jsv, jsv2;
|
||||
Terrain* terrain = 0;
|
||||
vector<jsval> array;
|
||||
vector<Terrain*> terrains;
|
||||
vector<int> widths;
|
||||
|
||||
switch(type) {
|
||||
case TYPE_TERRAINPAINTER:
|
||||
ParseFields(cx, obj, "s", &terrain);
|
||||
if(!ParseFields(cx, obj, "*", &jsv)) return 0;
|
||||
terrain = ParseTerrain(cx, jsv);
|
||||
if(terrain==0) return 0;
|
||||
return new TerrainPainter(terrain);
|
||||
|
||||
case TYPE_LAYEREDPAINTER:
|
||||
if(!ParseFields(cx, obj, "**", &jsv, &jsv2)) return 0;
|
||||
if(!ParseArray(cx, jsv, array)) return 0;
|
||||
for(int i=0; i<array.size(); i++) {
|
||||
if(!JSVAL_IS_INT(array[i])) return 0;
|
||||
widths.push_back(JSVAL_TO_INT(array[i]));
|
||||
}
|
||||
if(!ParseArray(cx, jsv2, array)) return 0;
|
||||
for(int i=0; i<array.size(); i++) {
|
||||
terrain = ParseTerrain(cx, array[i]);
|
||||
if(terrain==0) return 0;
|
||||
terrains.push_back(terrain);
|
||||
}
|
||||
if(terrains.size() != 1+widths.size()) return 0;
|
||||
return new LayeredPainter(terrains, widths);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
AreaPlacer* ParsePlacer(JSContext* cx, jsval val) {
|
||||
JSObject* obj; int type;
|
||||
if(!GetRaw(cx, val, &obj, &type)) return 0;
|
||||
|
||||
jsval jsv;
|
||||
int x, y, x1, y1, x2, y2, num, maxFail;
|
||||
CenteredPlacer* cp;
|
||||
|
||||
switch(type) {
|
||||
case TYPE_RECTPLACER:
|
||||
if(!ParseFields(cx, obj, "iiii", &x1, &y1, &x2, &y2)) return 0;
|
||||
return new RectPlacer(x1, y1, x2, y2);
|
||||
|
||||
case TYPE_EXACTPLACER:
|
||||
if(!ParseFields(cx, obj, "*ii", &jsv, &x, &y)) return 0;
|
||||
if(!(cp = ParseCenteredPlacer(cx, jsv))) return 0;
|
||||
return new ExactPlacer(cp, x, y);
|
||||
|
||||
case TYPE_MULTIPLACER:
|
||||
if(!ParseFields(cx, obj, "*ii", &jsv, &num, &maxFail)) return 0;
|
||||
if(!(cp = ParseCenteredPlacer(cx, jsv))) return 0;
|
||||
return new MultiPlacer(cp, num, maxFail);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CenteredPlacer* ParseCenteredPlacer(JSContext* cx, jsval val) {
|
||||
JSObject* obj; int type;
|
||||
if(!GetRaw(cx, val, &obj, &type)) return 0;
|
||||
|
||||
int areaId;
|
||||
float size, coherence, smoothness;
|
||||
|
||||
switch(type) {
|
||||
case TYPE_CLUMPPLACER:
|
||||
if(!ParseFields(cx, obj, "nnn", &size, &coherence, &smoothness)) return 0;
|
||||
return new ClumpPlacer(size, coherence, smoothness);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -106,11 +180,66 @@ Constraint* ParseConstraint(JSContext* cx, jsval val) {
|
||||
JSObject* obj; int type;
|
||||
if(!GetRaw(cx, val, &obj, &type)) return 0;
|
||||
|
||||
int areaId;
|
||||
string texture;
|
||||
jsval jsv, jsv2;
|
||||
Constraint* c1, *c2;
|
||||
|
||||
switch(type) {
|
||||
case TYPE_NULLCONSTRAINT:
|
||||
ParseFields(cx, obj, "");
|
||||
if(!ParseFields(cx, obj, "")) return 0;
|
||||
return new NullConstraint();
|
||||
|
||||
case TYPE_AVOIDAREACONSTRAINT:
|
||||
if(!ParseFields(cx, obj, "i", &areaId)) return 0;
|
||||
if(areaId <= 0 || areaId > theMap->areas.size()) return 0;
|
||||
return new AvoidAreaConstraint(theMap->areas[areaId-1]);
|
||||
|
||||
case TYPE_AVOIDTERRAINCONSTRAINT:
|
||||
if(!ParseFields(cx, obj, "s", &texture)) return 0;
|
||||
return new AvoidTerrainConstraint(theMap->getId(texture));
|
||||
|
||||
case TYPE_ANDCONSTRAINT:
|
||||
if(!ParseFields(cx, obj, "**", &jsv, &jsv2)) return 0;
|
||||
if(!(c1 = ParseConstraint(cx, jsv))) return 0;
|
||||
if(!(c2 = ParseConstraint(cx, jsv2))) return 0;
|
||||
return new AndConstraint(c1, c2);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Terrain* ParseTerrain(JSContext* cx, jsval val) {
|
||||
if(JSVAL_IS_STRING(val)) {
|
||||
// simple terrains are just encoded as strings
|
||||
string str = JS_GetStringBytes(JS_ValueToString(cx, val));
|
||||
return SimpleTerrain::parse(str);
|
||||
}
|
||||
else {
|
||||
// complex terrain type
|
||||
JSObject* obj; int type;
|
||||
if(!GetRaw(cx, val, &obj, &type)) return 0;
|
||||
|
||||
jsval jsv;
|
||||
Terrain* terrain = 0;
|
||||
vector<jsval> array;
|
||||
vector<Terrain*> terrains;
|
||||
|
||||
switch(type) {
|
||||
case TYPE_RANDOMTERRAIN:
|
||||
if(!ParseFields(cx, obj, "*", &jsv)) return 0;
|
||||
if(!ParseArray(cx, jsv, array)) return 0;
|
||||
for(int i=0; i<array.size(); i++) {
|
||||
terrain = ParseTerrain(cx, array[i]);
|
||||
if(terrain==0) return 0;
|
||||
terrains.push_back(terrain);
|
||||
}
|
||||
return new RandomTerrain(terrains);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -3,25 +3,38 @@
|
||||
|
||||
#include "map.h"
|
||||
#include "entity.h"
|
||||
#include "simpleconstraints.h"
|
||||
#include "simplepainters.h"
|
||||
#include "rectplacer.h"
|
||||
#include "constraint.h"
|
||||
#include "areapainter.h"
|
||||
#include "areaplacer.h"
|
||||
#include "centeredplacer.h"
|
||||
#include "terrain.h"
|
||||
|
||||
// Object type constants
|
||||
|
||||
const int
|
||||
TYPE_RECTPLACER = 1,
|
||||
TYPE_TERRAINPAINTER = 2,
|
||||
TYPE_NULLCONSTRAINT = 3;
|
||||
TYPE_NULLCONSTRAINT = 3,
|
||||
TYPE_RANDOMTERRAIN = 4,
|
||||
TYPE_LAYEREDPAINTER = 5,
|
||||
TYPE_AVOIDAREACONSTRAINT = 6,
|
||||
TYPE_CLUMPPLACER = 7,
|
||||
TYPE_EXACTPLACER = 8,
|
||||
TYPE_AVOIDTERRAINCONSTRAINT = 9,
|
||||
TYPE_ANDCONSTRAINT = 10,
|
||||
TYPE_MULTIPLACER = 11;
|
||||
|
||||
// Helper functions to parse objects from array versions
|
||||
|
||||
JSObject* GetRaw(JSContext* cx, jsval val);
|
||||
|
||||
bool ParseFields(JSContext* cx, JSObject* array, const char* format, ...);
|
||||
bool ParseArray(JSContext* cx, jsval val, std::vector<jsval>& ret);
|
||||
|
||||
AreaPainter* ParsePainter(JSContext* cx, jsval val);
|
||||
AreaPlacer* ParsePlacer(JSContext* cx, jsval val);
|
||||
Constraint* ParseConstraint(JSContext* cx, jsval val);
|
||||
Terrain* ParseTerrain(JSContext* cx, jsval val);
|
||||
CenteredPlacer* ParseCenteredPlacer(JSContext* cx, jsval val);
|
||||
|
||||
#endif
|
@ -9,6 +9,16 @@ using namespace std;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
|
||||
void OutputEntity(Entity* e, ostringstream& xml) {
|
||||
xml << "\
|
||||
<Entity>\n\
|
||||
<Template>" << e->type << "</Template>\n\
|
||||
<Player>" << e->player << "</Player>\n\
|
||||
<Position x=\"" << 4*e->x << "\" y=\"" << 4*e->y << "\" z=\"" << 4*e->z << "\" />\n\
|
||||
<Orientation angle=\"" << e->orientation << "\" />\n\
|
||||
</Entity>\n";
|
||||
}
|
||||
|
||||
void OutputXml(Map* m, FILE* f) {
|
||||
ostringstream xml;
|
||||
xml << "\
|
||||
@ -25,18 +35,20 @@ void OutputXml(Map* m, FILE* f) {
|
||||
<Entities>\n";
|
||||
|
||||
for(int i=0; i<m->entities.size(); i++) {
|
||||
Entity* e = m->entities[i];
|
||||
xml << "\
|
||||
<Entity>\n\
|
||||
<Template>" << e->type << "</Template>\n\
|
||||
<Player>" << e->player << "</Player>\n\
|
||||
<Position x=\"" << 4*e->x << "\" y=\"" << 4*e->y << "\" z=\"" << 4*e->z << "\" />\n\
|
||||
<Orientation angle=\"" << e->orientation << "\" />\n\
|
||||
</Entity>\n";
|
||||
OutputEntity(m->entities[i], xml);
|
||||
}
|
||||
|
||||
for(int x=0; x<m->size; x++) {
|
||||
for(int y=0; y<m->size; y++) {
|
||||
vector<Entity*>& vec = m->terrainEntities[x][y];
|
||||
for(int i=0; i<vec.size(); i++) {
|
||||
OutputEntity(vec[i], xml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xml << "\
|
||||
</Entities>\
|
||||
</Entities>\n\
|
||||
<Nonentities />\n\
|
||||
</Scenario>\n";
|
||||
|
||||
@ -44,7 +56,7 @@ void OutputXml(Map* m, FILE* f) {
|
||||
}
|
||||
|
||||
struct Tile {
|
||||
u16 texture1; // index into terrain_textures[]
|
||||
u16 texture1; // index into texture_textures[]
|
||||
u16 texture2; // index, or 0xFFFF for 'none'
|
||||
u32 priority; // ???
|
||||
};
|
||||
@ -65,13 +77,13 @@ struct PMP {
|
||||
|
||||
u16 heightmap[(mapsize*16 + 1)^2]; // (squared, not xor) - vertex heights
|
||||
|
||||
u32 num_terrain_textures;
|
||||
String terrain_textures[num_terrain_textures]; // filenames (no path), e.g. "cliff1.dds"
|
||||
u32 num_texture_textures;
|
||||
String texture_textures[num_texture_textures]; // filenames (no path), e.g. "cliff1.dds"
|
||||
|
||||
Tile tiles[(mapsize*16)^2];
|
||||
};*/
|
||||
int size = m->size;
|
||||
int numTerrains = m->idToName.size();
|
||||
int numTextures = m->idToName.size();
|
||||
|
||||
// header
|
||||
fwrite("PSMP", sizeof(char), 4, f);
|
||||
@ -104,25 +116,25 @@ struct PMP {
|
||||
}
|
||||
fwrite(heightmap, sizeof(u16), (size+1)*(size+1), f);
|
||||
|
||||
// num terrain textures
|
||||
fwrite(&numTerrains, sizeof(u32), 1, f);
|
||||
// num texture textures
|
||||
fwrite(&numTextures, sizeof(u32), 1, f);
|
||||
|
||||
// terrain names
|
||||
for(int i=0; i<numTerrains; i++) {
|
||||
// texture names
|
||||
for(int i=0; i<numTextures; i++) {
|
||||
string fname = m->idToName[i] + ".dds";
|
||||
int len = fname.length();
|
||||
fwrite(&len, sizeof(u32), 1, f);
|
||||
fwrite(fname.c_str(), sizeof(char), fname.length(), f);
|
||||
}
|
||||
|
||||
// terrain; note that this is an array of 16x16 patches for some reason
|
||||
// texture; note that this is an array of 16x16 patches for some reason
|
||||
Tile* tiles = new Tile[size*size];
|
||||
for(int x=0; x<size; x++) {
|
||||
for(int y=0; y<size; y++) {
|
||||
int patchX = x/16, patchY = y/16;
|
||||
int offX = x%16, offY = y%16;
|
||||
Tile& t = tiles[ (patchY*size/16 + patchX)*16*16 + (offY*16 + offX) ];
|
||||
t.texture1 = m->terrain[x][y];
|
||||
t.texture1 = m->texture[x][y];
|
||||
t.texture2 = 0xFFFF;
|
||||
t.priority = 0;
|
||||
}
|
||||
|
@ -7,8 +7,6 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
const char* LIBRARY_FILE = "library.js";
|
||||
|
||||
JSRuntime *rt = 0;
|
||||
JSContext *cx = 0;
|
||||
JSObject *global = 0;
|
||||
@ -58,8 +56,8 @@ jsval NewJSString(const string& str) {
|
||||
return STRING_TO_JSVAL(JS_NewString(cx, buf, str.length()));
|
||||
}
|
||||
|
||||
void ExecuteFile(const char* fileName) {
|
||||
FILE* f = fopen(fileName, "r");
|
||||
void ExecuteFile(const string& fileName) {
|
||||
FILE* f = fopen(fileName.c_str(), "r");
|
||||
if(!f) {
|
||||
cerr << "Cannot open " << fileName << endl;
|
||||
Shutdown(1);
|
||||
@ -72,7 +70,7 @@ void ExecuteFile(const char* fileName) {
|
||||
}
|
||||
|
||||
jsval rval;
|
||||
JSBool ok = JS_EvaluateScript(cx, global, code.c_str(), code.length(), fileName, 1, &rval);
|
||||
JSBool ok = JS_EvaluateScript(cx, global, code.c_str(), code.length(), fileName.c_str(), 1, &rval);
|
||||
if(!ok) Shutdown(1);
|
||||
}
|
||||
|
||||
@ -80,10 +78,16 @@ void ExecuteFile(const char* fileName) {
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
const string LIBRARY_FILE = "../data/mods/official/maps/rmlibrary.js";
|
||||
const string RMS_PATH = "../data/mods/official/maps/random/";
|
||||
const string SCENARIO_PATH = "../data/mods/official/maps/scenarios/";
|
||||
|
||||
clock_t start = clock();
|
||||
|
||||
InitJS();
|
||||
|
||||
if(argc!=3 && argc!=4) {
|
||||
cerr << "Usage: rmgen <script> <output name without extension> [<seed>]" << endl;
|
||||
cerr << "Usage: rmgen <script> <output map> [<seed>] (no file extensions)" << endl;
|
||||
Shutdown(1);
|
||||
}
|
||||
|
||||
@ -102,22 +106,26 @@ int main(int argc, char* argv[])
|
||||
string setts = out.str();
|
||||
jsval rval;
|
||||
JSBool ok = JS_EvaluateScript(cx, global, setts.c_str(), setts.length(),
|
||||
"settings declaration", 1, &rval);
|
||||
"map settings script", 1, &rval);
|
||||
if(!ok) Shutdown(1);
|
||||
|
||||
// Load library
|
||||
ExecuteFile(LIBRARY_FILE);
|
||||
|
||||
// Run the script
|
||||
ExecuteFile(argv[1]);
|
||||
ExecuteFile(RMS_PATH + argv[1] + ".js");
|
||||
|
||||
if(!theMap) {
|
||||
cerr << "Error:\n\tScript never called init!" << endl;
|
||||
Shutdown(1);
|
||||
}
|
||||
|
||||
string outputName = argv[2];
|
||||
string outputName = SCENARIO_PATH + argv[2];
|
||||
OutputMap(theMap, outputName);
|
||||
|
||||
clock_t end = clock();
|
||||
|
||||
printf("Took %0.3f seconds.\n", float(end-start) / CLOCKS_PER_SEC);
|
||||
|
||||
Shutdown(0);
|
||||
}
|
||||
|
@ -61,14 +61,15 @@
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
OutputDirectory="../../../binaries/system"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../../libraries/boost/include;../../../libraries/spidermonkey/include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="4"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="3"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
@ -128,12 +129,18 @@
|
||||
<File
|
||||
RelativePath=".\centeredplacer.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\clumpplacer.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\constraint.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\entity.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\layeredpainter.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\map.cpp">
|
||||
</File>
|
||||
@ -161,6 +168,9 @@
|
||||
<File
|
||||
RelativePath=".\simplepainters.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\simpleplacers.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.cpp">
|
||||
<FileConfiguration
|
||||
@ -176,6 +186,9 @@
|
||||
UsePrecompiledHeader="1"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terrain.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
@ -196,12 +209,18 @@
|
||||
<File
|
||||
RelativePath=".\centeredplacer.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\clumpplacer.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\constraint.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\entity.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\layeredpainter.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\map.h">
|
||||
</File>
|
||||
@ -229,9 +248,15 @@
|
||||
<File
|
||||
RelativePath=".\simplepainters.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\simpleplacers.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\terrain.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
@ -241,14 +266,14 @@
|
||||
<File
|
||||
RelativePath="..\..\..\libraries\spidermonkey\lib\js32d.lib">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\library.js">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\test.js">
|
||||
RelativePath="..\..\..\binaries\data\mods\official\maps\rmlibrary.js">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\binaries\data\mods\official\maps\random\test.js">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
|
@ -1,7 +1,45 @@
|
||||
#include "stdafx.h"
|
||||
#include "simpleconstraints.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// NullConstraint
|
||||
|
||||
bool NullConstraint::allows(Map* m, int x, int y)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// AvoidAreaConstraint
|
||||
|
||||
AvoidAreaConstraint::AvoidAreaConstraint(Area* area) {
|
||||
this->area = area;
|
||||
}
|
||||
|
||||
bool AvoidAreaConstraint::allows(Map* m, int x, int y)
|
||||
{
|
||||
return m->area[x][y] != area;
|
||||
}
|
||||
|
||||
// AvoidTerrainConstraint
|
||||
|
||||
AvoidTerrainConstraint::AvoidTerrainConstraint(int textureId) {
|
||||
this->textureId = textureId;
|
||||
}
|
||||
|
||||
bool AvoidTerrainConstraint::allows(Map* m, int x, int y)
|
||||
{
|
||||
return m->texture[x][y] != textureId;
|
||||
}
|
||||
|
||||
// AndConstraint
|
||||
|
||||
AndConstraint::AndConstraint(Constraint* a, Constraint*b) {
|
||||
this->a = a;
|
||||
this->b = b;
|
||||
}
|
||||
|
||||
bool AndConstraint::allows(Map* m, int x, int y)
|
||||
{
|
||||
return a->allows(m,x,y) && b->allows(m,x,y);
|
||||
}
|
@ -3,10 +3,36 @@
|
||||
|
||||
#include "constraint.h"
|
||||
#include "map.h"
|
||||
#include "area.h"
|
||||
|
||||
class NullConstraint : public Constraint {
|
||||
public:
|
||||
virtual bool allows(Map* m, int x, int y);
|
||||
};
|
||||
|
||||
class AvoidAreaConstraint : public Constraint {
|
||||
private:
|
||||
Area* area;
|
||||
public:
|
||||
AvoidAreaConstraint(Area* area);
|
||||
virtual bool allows(Map* m, int x, int y);
|
||||
};
|
||||
|
||||
class AvoidTerrainConstraint : public Constraint {
|
||||
private:
|
||||
int textureId;
|
||||
public:
|
||||
AvoidTerrainConstraint(int textureId);
|
||||
virtual bool allows(Map* m, int x, int y);
|
||||
};
|
||||
|
||||
class AndConstraint : public Constraint {
|
||||
private:
|
||||
Constraint* a;
|
||||
Constraint* b;
|
||||
public:
|
||||
AndConstraint(Constraint* a, Constraint* b);
|
||||
virtual bool allows(Map* m, int x, int y);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,18 +1,21 @@
|
||||
#include "stdafx.h"
|
||||
#include "simplepainters.h"
|
||||
#include "random.h"
|
||||
#include "rmgen.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
TerrainPainter::TerrainPainter(const string& terrain)
|
||||
// TerrainPainter
|
||||
|
||||
TerrainPainter::TerrainPainter(Terrain* terrain)
|
||||
{
|
||||
this->terrain = terrain;
|
||||
}
|
||||
|
||||
void TerrainPainter::paint(Map* m, Area* a)
|
||||
{
|
||||
int id = m->getId(terrain);
|
||||
for (int i=0; i<a->points.size(); i++) {
|
||||
Point p = a->points[i];
|
||||
m->terrain[p.x][p.y] = id;
|
||||
terrain->place(m, p.x, p.y);
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,13 @@
|
||||
#include "areapainter.h"
|
||||
#include "map.h"
|
||||
#include "area.h"
|
||||
#include "terrain.h"
|
||||
|
||||
class TerrainPainter : public AreaPainter {
|
||||
public:
|
||||
std::string terrain;
|
||||
Terrain* terrain;
|
||||
|
||||
TerrainPainter(const std::string& terrain);
|
||||
TerrainPainter(Terrain* terrain);
|
||||
void paint(Map* m, Area* a);
|
||||
};
|
||||
|
||||
|
47
source/tools/rmgen/simpleplacers.cpp
Normal file
47
source/tools/rmgen/simpleplacers.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "stdafx.h"
|
||||
#include "simpleplacers.h"
|
||||
#include "random.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// ExactPlacer
|
||||
|
||||
ExactPlacer::ExactPlacer(CenteredPlacer* centeredPlacer, int x, int y) {
|
||||
this->centeredPlacer = centeredPlacer;
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
}
|
||||
|
||||
ExactPlacer::~ExactPlacer() {
|
||||
}
|
||||
|
||||
bool ExactPlacer::place(Map* m, Constraint* constr, std::vector<Point>& ret) {
|
||||
return centeredPlacer->place(m, constr, ret, x, y);
|
||||
}
|
||||
|
||||
// MultiPlacer
|
||||
|
||||
MultiPlacer::MultiPlacer(CenteredPlacer* centeredPlacer, int numToPlace, int maxFail) {
|
||||
this->centeredPlacer = centeredPlacer;
|
||||
this->numToPlace = numToPlace;
|
||||
this->maxFail = maxFail;
|
||||
}
|
||||
|
||||
MultiPlacer::~MultiPlacer() {
|
||||
}
|
||||
|
||||
bool MultiPlacer::place(Map* m, Constraint* constr, std::vector<Point>& ret) {
|
||||
int failed = 0;
|
||||
int placed = 0;
|
||||
while(placed < numToPlace && failed <= maxFail) {
|
||||
int x = RandInt(m->size);
|
||||
int y = RandInt(m->size);
|
||||
if(constr->allows(m,x,y) && centeredPlacer->place(m, constr, ret, x, y)) {
|
||||
placed++;
|
||||
}
|
||||
else {
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
return placed == numToPlace;
|
||||
}
|
29
source/tools/rmgen/simpleplacers.h
Normal file
29
source/tools/rmgen/simpleplacers.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef __SIMPLEPLACERS_H__
|
||||
#define __SIMPLEPLACERS_H__
|
||||
|
||||
#include "areaplacer.h"
|
||||
#include "centeredplacer.h"
|
||||
#include "map.h"
|
||||
#include "constraint.h"
|
||||
|
||||
class ExactPlacer: public AreaPlacer {
|
||||
private:
|
||||
CenteredPlacer* centeredPlacer;
|
||||
int x, y;
|
||||
public:
|
||||
ExactPlacer(CenteredPlacer* centeredPlacer, int x, int y);
|
||||
virtual bool place(Map* m, Constraint* constr, std::vector<Point>& ret);
|
||||
~ExactPlacer();
|
||||
};
|
||||
|
||||
class MultiPlacer: public AreaPlacer {
|
||||
private:
|
||||
CenteredPlacer* centeredPlacer;
|
||||
int numToPlace, maxFail;
|
||||
public:
|
||||
MultiPlacer(CenteredPlacer* centeredPlacer, int numToPlace, int maxFail);
|
||||
virtual bool place(Map* m, Constraint* constr, std::vector<Point>& ret);
|
||||
~MultiPlacer();
|
||||
};
|
||||
|
||||
#endif
|
@ -32,6 +32,6 @@
|
||||
#endif
|
||||
#include "jsapi.h"
|
||||
|
||||
// TODO: reference additional headers your program requires here
|
||||
const float PI = acos(-1.0f);
|
||||
|
||||
#endif
|
88
source/tools/rmgen/terrain.cpp
Normal file
88
source/tools/rmgen/terrain.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include "stdafx.h"
|
||||
#include "terrain.h"
|
||||
#include "map.h"
|
||||
#include "entity.h"
|
||||
#include "random.h"
|
||||
#include "rmgen.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Terrain
|
||||
|
||||
Terrain::Terrain() {}
|
||||
|
||||
Terrain::~Terrain() {}
|
||||
|
||||
void Terrain::place(Map* m, int x, int y) {
|
||||
vector<Entity*>& vec = m->terrainEntities[x][y];
|
||||
for(int i=0; i<vec.size(); i++) {
|
||||
delete vec[i];
|
||||
}
|
||||
vec.clear();
|
||||
placeNew(m, x, y);
|
||||
}
|
||||
|
||||
// SimpleTerrain
|
||||
|
||||
SimpleTerrain::SimpleTerrain(const std::string& texture)
|
||||
{
|
||||
this->texture = texture;
|
||||
this->treeType = "";
|
||||
}
|
||||
|
||||
SimpleTerrain::SimpleTerrain(const std::string& texture, const std::string& treeType)
|
||||
{
|
||||
this->texture = texture;
|
||||
this->treeType = treeType;
|
||||
}
|
||||
|
||||
void SimpleTerrain::placeNew(Map* m, int x, int y) {
|
||||
vector<Entity*>& vec = m->terrainEntities[x][y];
|
||||
if(treeType != "") {
|
||||
vec.push_back(new Entity(treeType, 0, x+0.5f, 0, y+0.5f, RandFloat()*PI));
|
||||
}
|
||||
m->texture[x][y] = m->getId(texture);
|
||||
}
|
||||
|
||||
SimpleTerrain::~SimpleTerrain(void)
|
||||
{
|
||||
}
|
||||
|
||||
Terrain* SimpleTerrain::parse(const string& name) {
|
||||
static map<string, Terrain*> parsedTerrains;
|
||||
|
||||
if(parsedTerrains.find(name) != parsedTerrains.end()) {
|
||||
return parsedTerrains[name];
|
||||
}
|
||||
else {
|
||||
string texture, treeType;
|
||||
size_t pos = name.find('|');
|
||||
if(pos != name.npos) {
|
||||
texture = name.substr(0, pos);
|
||||
treeType = name.substr(pos+1, name.size()-pos-1);
|
||||
}
|
||||
else {
|
||||
texture = name;
|
||||
treeType = "";
|
||||
}
|
||||
return parsedTerrains[name] = new SimpleTerrain(texture, treeType);
|
||||
}
|
||||
}
|
||||
|
||||
// RandomTerrain
|
||||
|
||||
RandomTerrain::RandomTerrain(const vector<Terrain*>& terrains)
|
||||
{
|
||||
if(terrains.size()==0) {
|
||||
JS_ReportError(cx, "RandomTerrain: terrains array must not be empty");
|
||||
}
|
||||
this->terrains = terrains;
|
||||
}
|
||||
|
||||
void RandomTerrain::placeNew(Map* m, int x, int y) {
|
||||
terrains[RandInt(terrains.size())]->placeNew(m, x, y);
|
||||
}
|
||||
|
||||
RandomTerrain::~RandomTerrain(void)
|
||||
{
|
||||
}
|
44
source/tools/rmgen/terrain.h
Normal file
44
source/tools/rmgen/terrain.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef __TERRAIN_H__
|
||||
#define __TERRAIN_H__
|
||||
|
||||
class Terrain
|
||||
{
|
||||
public:
|
||||
Terrain();
|
||||
void place(class Map* m, int x, int y);
|
||||
virtual void placeNew(class Map* m, int x, int y) = 0; // template method
|
||||
virtual ~Terrain(void);
|
||||
};
|
||||
|
||||
class SimpleTerrain: public Terrain
|
||||
{
|
||||
private:
|
||||
std::string texture;
|
||||
std::string treeType;
|
||||
|
||||
public:
|
||||
SimpleTerrain(const std::string& texture);
|
||||
SimpleTerrain(const std::string& texture, const std::string& treeType);
|
||||
|
||||
static Terrain* parse(const std::string& name);
|
||||
|
||||
void placeNew(class Map* m, int x, int y);
|
||||
~SimpleTerrain(void);
|
||||
};
|
||||
|
||||
class RandomTerrain: public Terrain
|
||||
{
|
||||
private:
|
||||
std::vector<Terrain*> terrains;
|
||||
|
||||
public:
|
||||
RandomTerrain(const std::vector<Terrain*>& terrains);
|
||||
|
||||
void placeNew(class Map* m, int x, int y);
|
||||
~RandomTerrain(void);
|
||||
};
|
||||
|
||||
|
||||
extern std::map<std::string, Terrain*> parsedTerrains;
|
||||
|
||||
#endif
|
@ -1,8 +0,0 @@
|
||||
const SIZE = 48;
|
||||
init(SIZE, "grass1_a", 0);
|
||||
|
||||
var placer = new RectPlacer(0,0,3,4);
|
||||
placer.y2 = 6;
|
||||
var paint = new TerrainPainter("snow");
|
||||
var constr = new NullConstraint();
|
||||
println(createArea(placer, paint));
|
Loading…
Reference in New Issue
Block a user