Sign in to follow this  
Followers 0
FeXoR

Where to share/upload random map generators

22 posts in this topic

I wrote a random map generator and now want to know where to talk about it and where to share it if it's good enough.

I found it hard to find the things I need inside the code of the helper functions inside the "rmgen" directory. Is there a documentation or a small tutorial out there?

And what variables can be set in the .json file?

For those who have similar issues:

- The directory own scripts can be added and then work with the game and the editor in windows is (similar to the player made "scenarios" folder):

c:\users\[username]\AppData\Roaming\0ad\cache\mods\public\maps\random

Edited by FeXoR

Share this post


Link to post
Share on other sites

It's all fairly well documented on Trac actually: http://trac.wildfiregames.com/wiki/Random_Map_Generator

Except for the .json file, I don't see documentation for that yet :) Basically it follows the same format as scenarios, if you look in maps\scenarios\*.xml in the <scriptSettings> element, you will see for example:


{
"CircularMap": true,
"Description": "Arch enemies, Rome and Carthage, square off on a richly detailed map of Southern Italy.\u000a\u000aScout the lands to find free Treasures and to secure new resources.",
"GameType": "conquest",
"Keywords": [],
"LockTeams": false,
"Name": "Acropolis III",
"PlayerData": [
{
"AI": "",
"Civ": "rome",
"Colour": {
"b": 13,
"g": 13,
"r": 166
},
"Name": "Player 1",
"Resources": {
"food": 400,
"wood": 400
},
"Team": -1
},
{
"AI": "qbot",
"Civ": "cart",
"Colour": {
"b": 168,
"g": 64,
"r": 55
},
"Name": "Player 2",
"Resources": {
"food": 400,
"wood": 400
},
"Team": -1
}
],
"RevealMap": false
}

I'll try adding documentation about this.

Share this post


Link to post
Share on other sites

THX, that helps.

I made the different civil centers align to the diagonal grid that is used in-game for placing structures by default but roughly facing the center of the map (1*PI/4, 3*PI/4, 5*PI/4 and 7*PI/4).

I thought that wouldn't result in problems since a change of the wired const "BUILDING_ANGlE" (with a small written "L" ^^) did'nt change anything in-game (but the orientation of all map-generated buildings of cause).

So I made them different for each player and set them as a variable.

Well, but sometimes, often enough to occur 50% at 8 player maps, one or two civil centers are facing in a non-alligned directions (And some functions afterwards are not called).

Is the orientation for buildings in general needed as a const or even need to be named "BUILDING_ANGlE"?

Share this post


Link to post
Share on other sites

Is the orientation for buildings in general needed as a const or even need to be named "BUILDING_ANGlE"?

It's just the convention to have all the buildings facing in the same direction for aesthetic reasons, in other words facing towards the starting camera which is the same for all players (Mythos_Ruler was very insistent on that :)). That constant might be defined in each separate file, but it should be moved to the rmgen library instead.

Edit: Also AIs, I believe they layout their buildings in the same direction.

Share this post


Link to post
Share on other sites

It's just the convention to have all the buildings facing in the same direction for aesthetic reasons, in other words facing towards the starting camera which is the same for all players (Mythos_Ruler was very insistent on that :)). That constant might be defined in each separate file, but it should be moved to the rmgen library instead.

It's also better for gameplay, so that there is a consistent exit point for units and a consistent start point for building rotation if players want units to exit in a different direction.

Share this post


Link to post
Share on other sites

THX for the reply!

The problem was within my file and it's fixed now.

However, the building orientation IS inside the grid the AI and the start orientation in-game uses, but there are still the 4 possibilities.

Well, not a big issue since it works fine now.

I did many things very different then it is handled in the other RMGs.

Mine is a very early state until now and more for getting to know the functions, but if anyone wants to take a look:

fexor_rmg.rar

Share this post


Link to post
Share on other sites

Oh, and for those preferring .zip:

fexor_rmg.zip

EDIT: My dear, wrong version, now it should work... [hope]

Edited by FeXoR

Share this post


Link to post
Share on other sites

BTW! The mathematical orientation (defined by cos/sin in x/y direction) and the unit/building orientation differs.

I think unit orientation is:

-(mathematical orientation - PI/2)

How did that happen?

And why is the second vertical orientation named "z" instead of "y"?

I thought "z" would be the hight over ground or to a base hight but in 0ad it's "y"?

Sorry, questions and more questions x)

Edited by FeXoR

Share this post


Link to post
Share on other sites

And why is the second vertical orientation named "z" instead of "y"?

I thought "z" would be the hight over ground or to a base hight but in 0ad it's "y"?

That was just a choice made long ago and unlikely to change :) I've seen either Y or Z used as height equally in different applications (X could be used, too but that would be weird).

Share this post


Link to post
Share on other sites

Sooo...

Here's a function to place civil center and starting units just by giving the location and the player index of the player the units should be placed for.

This is the (very) detailed version for (hopefully) good readability, a shorter version will be added:

// Funtion to place civil centre and starting units at given location for a given player
function placeStartUnits0adAlike(startLocation, playerId)
// "startLocation" should be a list of length 2 with floats determining the 2d-point where the starting entities shall be placed.
// "startLocation[0]" should be an float determining the x coordinate of the start location.
// "startLocation[1]" should be an float determining the z coordinate of the start location. (Should by y in my book though)
// "playerId" should be the player number like seen in Atlas or the game settings ingame (Starting with 1 for the first player with default colour blue, 0 is Gaia)
{
// Some checks. Enhance if needed...

// Setting some variables
// Setting default building angle
var buildingAngle = 3*Math.PI/4;
// Getting civilisation string
var civ = g_MapSettings.PlayerData[i].Civ;
// Getting civilisation dependent default starting entities
var civEntities = g_CivData[civ].StartEntities;
// Setting start tile. Not needed but done in the other RMGs so....
var startTile = new Array(2)
startTile[0]= round(startLocation[0])
startTile[1]= round(startLocation[1])

// Place civil centre on the start tile
placeObject(startTile[0], startTile[1], civEntities[0].Template, playerId, buildingAngle);

// Place starting units
// Minimal distance to start location so that units don't stand in the civil centere
var minDistToCC = 4;
// Minimal distance between units so they don't overlap
var minDist = 1;
// Set general orientation of units
var angleMain = -(buildingAngle - PI/2); // This is a bug in my book, it should be the same as building orientation...
// Set angle width units should be spread over
var angleSpread = PI/4;
// Preset angle the first unit should be placed, reset in the outer loop
var angleStart = angleMain - angleSpread/2;
// Preset angle distance between one unit and the next of the same type, reset in the outer loop
var angleAdd = 0;
// Preset the angle a unit will be placed in comperison to the civil centre, reset inside the inner loop
var angleActual = angleStart;
// Preset number of units to place by default of the same type, reset in outer loop
var numberOfUnitsOfSameType = 1;
// Preset unit template, reset in the outer loop
var unitTemplate = '';
// Preset postition the unit will be placed, reset inside the inner loop
var unitPosition = new Array(2);
unitPosition[0] = startTile[0];
unitPosition[1] = startTile[1];
// Preset orientation of placed unit, reset in the inner loop
var unitOrientation = 0;
// Outer loop for the diffrent unit types to place beside the civil centre (so starting with 1)
for (var unitTypeIndex = 1; unitTypeIndex < civEntities.length; ++unitTypeIndex)
{
// Reset default number of units of that type
numberOfUnitsOfSameType = (civEntities[unitTypeIndex].Count !== undefined ? civEntities[unitTypeIndex].Count : 1);
// Reset the angle added per unit of that type depending on the number of them, for multiple units of that type only (otherwise 0 devision)
if (numberOfUnitsOfSameType > 1) {angleAdd = angleSpread/(numberOfUnitsOfSameType-1)};
// Reset unit tamplate
unitTemplate = civEntities[unitTypeIndex].Template;
// Inner loop for multiple units of the same type
for (var unitIndex = 0; unitIndex < numberOfUnitsOfSameType; unitIndex++)
{
// Resetting the angle the unit
if (numberOfUnitsOfSameType > 1) {angleActual = angleStart + unitIndex*angleAdd}
else {angleActual = angleMain};
// Reset the angle the unit will be placed in comperison to the civil centre
unitPosition[0] = startTile[0] + (minDistToCC + minDist*unitTypeIndex)*cos(angleActual);
unitPosition[1] = startTile[1] + (minDistToCC + minDist*unitTypeIndex)*sin(angleActual);
// Reset orientation of placed unit
unitOrientation = -(angleActual - PI/2); // Here is the bug again...
// Place the unit
placeObject(unitPosition[0], unitPosition[1], unitTemplate, playerId, unitOrientation);
};
};
};
 

BTW, this does'nt seam to be a good place to put this, suggestions very welcome.P.S.: Did I mention this game is pure @#$%ing awesomeness?P.P.S.: Oh, I hope I did'nt break any forum rules now ;0|

Share this post


Link to post
Share on other sites

Got some strange formation issues in the post writer tool... well...

Here's a more reasonable version.

Swapped sin and cos so unit orientation and mathematical point calculation matches.

Still I think that's a little strange...

Many variables are set in the loop now with var over and over again... is this OK?

But it's much shorter now:

// Funtion to place civil centre and starting units at given location for a given player
function placeStartUnits(startLocation, playerId)
// "startLocation" should be a list of length 2 with floats determining the 2d-point where the starting entities shall be placed.
// "startLocation[0]" should be an float determining the x coordinate of the start location.
// "startLocation[1]" should be an float determining the z coordinate of the start location. (Should by y in my book though)
// "playerId" should be the player number like seen in Atlas or the game settings ingame (Starting with 1 for the first player with default colour blue, 0 is Gaia)
{
// Some checks. Enhance if needed...

// Setting some variables
// Setting default building angle, can be got from the global "BUILDING_ANGlE" in further versions
var buildingOrientation = 3*Math.PI/4;
// Getting civilisation dependent default starting entities
var civEntities = g_CivData[g_MapSettings.PlayerData[i].Civ].StartEntities;

// Place civil centre on the start location
placeObject(startLocation[0], startLocation[1], civEntities[0].Template, playerId, buildingOrientation);

// Place starting units
// Minimal distance to start location so that units don't stand in the civil centere
var minDistToCC = 4;
// Minimal distance between units so they don't overlap
var minDist = 1;
// Set angle width units should be spread over
var angleSpread = PI/4;
// Outer loop for the diffrent unit types to place beside the civil centre (so starting with 1)
for (var unitTypeIndex = 1; unitTypeIndex < civEntities.length; ++unitTypeIndex)
{
// Reset default number of units of that type
var unitCount = (civEntities[unitTypeIndex].Count !== undefined ? civEntities[unitTypeIndex].Count : 1);
// Reset the angle added per unit of that type depending on the number of them, for multiple units of that type only (otherwise 0 devision)
if (unitCount > 1) {var angleAdd = angleSpread/(unitCount-1)};
// Inner loop for multiple units of the same type
for (var unitIndex = 0; unitIndex < unitCount; unitIndex++)
{
// Resetting the angle the unit will be placed in comperison to the city centre
if (unitCount > 1) {var angleActual = buildingOrientation - angleSpread/2 + unitIndex*angleAdd}
else {var angleActual = buildingOrientation};
// Place the unit
placeObject(
startLocation[0] + (minDistToCC + minDist*unitTypeIndex)*sin(angleActual),
startLocation[1] + (minDistToCC + minDist*unitTypeIndex)*cos(angleActual),
civEntities[unitTypeIndex].Template, playerId, angleActual);
};
};
};

Share this post


Link to post
Share on other sites

This function is already present in SVN version of the game. It now looks like this:

function createStartingPlayerEntities(fx, fz, playerid, civEntities, BUILDING_ANGlE)
{
var uDist = 6;
var uSpace = 2;
placeObject(fx, fz, civEntities[0].Template, playerid, BUILDING_ANGlE);
for (var j = 1; j < civEntities.length; ++j)
{
var uAngle = -BUILDING_ANGlE + PI * (j - 1) / 2;
var count = (civEntities[j].Count !== undefined ? civEntities[j].Count : 1);
for (var numberofentities = 0; numberofentities < count; numberofentities++)
{
var ux = fx + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2));
var uz = fz + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2));
placeObject(ux, uz, civEntities[j].Template, playerid, (j % 2 - 1) * PI + uAngle);
}
}
}

Share this post


Link to post
Share on other sites

I think something like that should be added to one of the rmgen .js files to make it easier for random map designers.

They still can make there own arrangements of starting units if they like.

Perhaps some value checks of function parameters should be added...

Perhaps the starting units should be placed right (female peasants), left (male peasants) and in front (Scout) to need less space (smaller maximum distance to start location).

Greetings U gorgeous bunch of individuals!

Oh, did'nt see this, thx!

Share this post


Link to post
Share on other sites

But you insist of define coordinated one by one.

Do you think that is wise?

Or tell me a reason?

Well, sry, your decision...

Share this post


Link to post
Share on other sites

Hehe, U made the same "mistake" like me.

Swap sin and cos ^^

Share this post


Link to post
Share on other sites
But you insist of define coordinated one by one.

Do you think that is wise?

Or tell me a reason?

Well, sry, your decision...

We want the function to be simple to use for new scripters. Also it is better to have a unified formation for all random maps.

Hehe, U made the same "mistake" like me.

Swap sin and cos ^^

:huh:

Share this post


Link to post
Share on other sites

:huh:

To adjust the "build in" unit orientation of all (I guess) entity placement functions to the "usually" used determination of the unit position in polar coordinates (by distance and angle to the position of the civil center with cos/sin for x/y) it is adjusted by inverting the angle:

var uAngle = -BUILDING_ANGlE + PI * (j - 1) / 2;

Note the "-" in front of "BUILDING_ANGlE".

...and then adding (or subtract dependent of the braces used) PI/2:

var ux = fx + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2));
var uz = fz + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2));

Note the "uAngle + PI/2" in cos/sin.

But it can be done by switching cos and sin like it's done in my second function.

I don't know yet if this is mathematical correct implemented when the 2nd planar axis is indeed z and not y.

But at least it's hard to get used to for me (and as it seams to others too ^^)

Hope i managed to explain my point.

Share this post


Link to post
Share on other sites

I missed some functions to determine the distance between two points and the angle the vector between them has.

So I added some functions to my script:

// Function to get the distance between 2 points
function getDistance(point1, point2) {return Math.pow(Math.pow(point1[0] - point2[0], 2) + Math.pow(point1[1] - point2[1], 2), 1/2)};

// Function to get the distance between 2 points given in seperate coordinates
function getDistanceXZ(x1, z1, x2, z2) {return getDistance([x1, z1], [x2, z2])};

// Function to get the direction from one point to another
function getDirection(point1, point2) {return Math.asin((point2[1] - point1[1])/getDistance(point1, point2))};
function getDirectionAlternative(point1, point2) {return Math.acos((point2[0] - point1[0])/getDistance(point1, point2))};

// Function to get the direction from one point to another given in seperate coordinates
function getDirectionXZ(x1, z1, x2, z2) {return getDirection([x1, z1], [x2, z2])};

Share this post


Link to post
Share on other sites

I HOPE with the exchanged sin/cos everything's in order :S

Share this post


Link to post
Share on other sites

Of cause I mixed it up...

And forgot the area of definition that is only PI not 2*PI...

A function working and consistent to the unit placement orientation for getting the angle of a vector from one point towards another is for example (perhaps not the best):

// Function to get the direction from one point to another
function getDirection(point1, point2)
{
var vector = [point2[0] - point1[0], point2[1] - point1[1]];
var output = Math.acos(vector[0]/getDistance(point1, point2));
if (vector[1] > 0) {output = PI + (PI - Math.acos(vector[0]/getDistance(point1, point2)))};
return (output + PI/2) % (2*PI);
};

The other functions are correct...

Edited by FeXoR

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0