1
0
forked from 0ad/0ad

Polar Sea random map script.

Based on map by Hannibal Baraq.
Differential Revision: https://code.wildfiregames.com/D156
Map generation reviewed by FeXoR
Trigger Script and UnitAI change reviewed by Sandarac
Environment settings reviewed by niektb and wowgetoffyourcellphone

This was SVN commit r19254.
This commit is contained in:
elexis 2017-02-28 20:53:51 +00:00
parent 0c058d7d05
commit 79fb493da3
7 changed files with 455 additions and 11 deletions

Binary file not shown.

View File

@ -5,6 +5,7 @@
"Description" : "The central region of the vast continent of Africa, birthplace of humanity. Players start in a lush area teeming with vegetation and wildlife.",
"BaseTerrain" : ["medit_sea_depths"],
"BaseHeight" : 2,
"Keywords": ["new"],
"Preview" : "african_plains.png",
"CircularMap" : true
}

View File

@ -0,0 +1,354 @@
RMS.LoadLibrary("rmgen");
var tPrimary = ["polar_snow_a"];
var tCliff = ["polar_cliff_a", "polar_cliff_b", "polar_cliff_snow"];
var tSecondary = "polar_snow_glacial";
var tHalfSnow = ["ice_01", "ice_dirt"];
var tSnowLimited = ["polar_snow_b", "polar_ice"];
var tDirt = "ice_dirt";
var tRoad = "polar_ice_b";
var tRoadWild = "polar_ice_cracked";
var tShore = "polar_ice_snow";
var tWater = "polar_ice_c";
// gaia entities
var oWolf = "gaia/fauna_wolf_snow";
var oMuskox = "gaia/fauna_muskox";
var oWalrus = "gaia/fauna_walrus";
var oWhaleFin = "gaia/fauna_whale_fin";
var oWhaleHumpback = "gaia/fauna_whale_humpback";
var oFish = "gaia/fauna_fish";
var oStoneLarge = "gaia/geology_stonemine_medit_quarry";
var oStoneSmall = "gaia/geology_stone_alpine_a";
var oMetalLarge = "gaia/geology_metal_desert_badlands_slabs";
var oWood = "gaia/special_treasure_wood";
// decorative props
var aRockLarge = "actor|geology/stone_granite_med.xml";
var aRockMedium = "actor|geology/stone_granite_med.xml";
var aIceberg = "actor|props/special/eyecandy/iceberg.xml";
log("Initializing map...");
InitMap();
const numPlayers = getNumPlayers();
const mapSize = getMapSize();
var clPlayer = createTileClass();
var clWater = createTileClass();
var clDirt = createTileClass();
var clRock = createTileClass();
var clMetal = createTileClass();
var clHill = createTileClass();
var clFood = createTileClass();
var clBaseResource = createTileClass();
var clWolf = createTileClass();
// Expected by rmgen1
var clForest = createTileClass();
for (let ix = 0; ix < mapSize; ++ix)
for (let iz = 0; iz < mapSize; ++iz)
placeTerrain(ix, iz, tPrimary);
var playerIDs = [];
for (let i = 0; i < numPlayers; ++i)
playerIDs.push(i+1);
playerIDs = sortPlayers(playerIDs);
var playerX = new Array(numPlayers);
var playerZ = new Array(numPlayers);
var playerAngle = new Array(numPlayers);
var startAngle = randFloat(0, TWO_PI);
for (let i = 0; i < numPlayers; ++i)
{
playerAngle[i] = startAngle + i * TWO_PI / numPlayers;
playerX[i] = 0.5 + 0.35 * Math.cos(playerAngle[i]);
playerZ[i] = 0.5 + 0.35 * Math.sin(playerAngle[i]);
}
RMS.SetProgress(20);
for (let i = 0; i < numPlayers; ++i)
{
let id = playerIDs[i];
log("Creating base for player " + id + "...");
let fx = fractionToTiles(playerX[i]);
let fz = fractionToTiles(playerZ[i]);
let ix = Math.round(fx);
let iz = Math.round(fz);
addToClass(ix, iz, clPlayer);
addToClass(ix+5, iz, clPlayer);
addToClass(ix, iz+5, clPlayer);
addToClass(ix-5, iz, clPlayer);
addToClass(ix, iz-5, clPlayer);
// Create the city patch
let cityRadius = scaleByMapSize(15,25)/3;
let placer = new ClumpPlacer(PI*cityRadius*cityRadius, 0.6, 0.3, 10, ix, iz);
let painter = new LayeredPainter([tRoadWild, tRoad], [1]);
createArea(placer, painter, null);
placeCivDefaultEntities(fx, fz, id);
placeDefaultChicken(fx, fz, clBaseResource, undefined, oMuskox);
// Create metal mine
let mAngle = randFloat(0, TWO_PI);
let mDist = 12;
let mX = Math.round(fx + mDist * Math.cos(mAngle));
let mZ = Math.round(fz + mDist * Math.sin(mAngle));
let group = new SimpleGroup(
[new SimpleObject(oMetalLarge, 1, 1, 0, 0)],
true, clBaseResource, mX, mZ
);
createObjectGroup(group, 0);
// Create stone mines
mAngle += randFloat(PI/8, PI/4);
mX = Math.round(fx + mDist * Math.cos(mAngle));
mZ = Math.round(fz + mDist * Math.sin(mAngle));
group = new SimpleGroup(
[new SimpleObject(oStoneLarge, 1, 1, 0, 2)],
true, clBaseResource, mX, mZ
);
createObjectGroup(group, 0);
// Create wood treasure
mAngle += PI/4;
let bbX = Math.round(fx + mDist * Math.cos(mAngle));
let bbZ = Math.round(fz + mDist * Math.sin(mAngle));
createObjectGroup(
new SimpleGroup(
[new SimpleObject(oWood, 14,14, 0,3)],
true, clBaseResource, bbX, bbZ,
avoidClasses(clBaseResource, 4)
), 0);
// Create market
mAngle += PI/4;
placeObject(
Math.round(fx + mDist * Math.cos(mAngle)),
Math.round(fz + mDist * Math.sin(mAngle)),
"structures/" + getCivCode(id-1) + "_market",
id,
BUILDING_ORIENTATION);
}
RMS.SetProgress(30);
log("Creating central lake...");
var placer = new ChainPlacer(
2,
Math.floor(scaleByMapSize(5, 16)),
Math.floor(scaleByMapSize(35, 200)),
1,
Math.round(fractionToTiles(0.5)),
Math.round(fractionToTiles(0.5)),
0,
[Math.floor(mapSize * 0.17)]);
var terrainPainter = new LayeredPainter(
[tShore, tWater, tWater, tWater], // terrains
[1, 4, 2] // widths
);
var elevationPainter = new SmoothElevationPainter(
ELEVATION_SET, // type
-4, // elevation
4 // blend radius
);
createArea(placer, [terrainPainter, elevationPainter, paintClass(clWater)], avoidClasses(clPlayer, 20));
paintTerrainBasedOnHeight(3, Math.floor(scaleByMapSize(20, 40)), 0, tCliff);
paintTerrainBasedOnHeight(Math.floor(scaleByMapSize(20, 40)), 100, 3, tSnowLimited);
RMS.SetProgress(40);
log("Creating small lakes...");
var lakeAreas = [];
var playerConstraint = new AvoidTileClassConstraint(clPlayer, 20);
var waterConstraint = new AvoidTileClassConstraint(clWater, 8);
for (let x = 0; x < mapSize; ++x)
for (let z = 0; z < mapSize; ++z)
if (playerConstraint.allows(x, z) && waterConstraint.allows(x, z))
lakeAreas.push([x, z]);
var numLakes = scaleByMapSize(10, 16);
for (let i = 0; i < numLakes ; ++i)
{
let chosenPoint = pickRandom(lakeAreas);
if (!chosenPoint)
break;
placer = new ChainPlacer(
1,
Math.floor(scaleByMapSize(2, 4)),
Math.floor(scaleByMapSize(20, 140)),
0.7,
chosenPoint[0],
chosenPoint[1]);
let terrainPainter = new LayeredPainter(
[tShore, tWater, tWater], // terrains
[1, 3] // widths
);
let elevationPainter = new SmoothElevationPainter(ELEVATION_SET, -5, 5);
createAreas(
placer,
[terrainPainter, elevationPainter, paintClass(clWater)],
avoidClasses(clPlayer, 20),
1, 1
);
}
RMS.SetProgress(50);
createBumps(avoidClasses(clWater, 2, clPlayer, 20));
RMS.SetProgress(60);
log("Creating hills...");
createHills(
[tPrimary, tPrimary, tSecondary],
avoidClasses(clPlayer, 20, clHill, 35),
clHill, scaleByMapSize(20, 240));
RMS.SetProgress(65);
log("Creating dirt patches...");
createLayeredPatches(
[scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)],
[[tDirt,tHalfSnow], [tHalfSnow,tSnowLimited]],
[2],
avoidClasses(clWater, 3, clDirt, 5, clPlayer, 12)
);
log("Creating glacier patches...");
createPatches(
[scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)],
tSecondary,
avoidClasses(clWater, 3, clDirt, 5, clPlayer, 12)
);
RMS.SetProgress(70);
log("Creating stone mines...");
createMines(
[
[new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)],
[new SimpleObject(oStoneSmall, 2,5, 1,3)]
],
avoidClasses(clWater, 3, clPlayer, 20, clRock, 18, clHill, 2)
);
log("Creating metal mines...");
createMines(
[
[new SimpleObject(oMetalLarge, 1,1, 0,4)]
],
avoidClasses(clWater, 3, clPlayer, 20, clMetal, 18, clRock, 5, clHill, 2),
clMetal
);
RMS.SetProgress(75);
createDecoration(
[
[new SimpleObject(aRockMedium, 1,3, 0,1)],
[
new SimpleObject(aRockLarge, 1,2, 0,1),
new SimpleObject(aRockMedium, 1,3, 0,2)
]
],
[
scaleByMapSize(16, 262),
scaleByMapSize(8, 131),
],
avoidClasses(clWater, 0, clPlayer, 0)
);
createDecoration(
[
[new SimpleObject(aIceberg, 1, 1, 1, 1)]
],
[
scaleByMapSize(8, 131)
],
[stayClasses(clWater, 4), avoidClasses(clHill, 2)]
);
RMS.SetProgress(80);
createFood(
[
[new SimpleObject(oWolf, 4,6, 0,4)],
[new SimpleObject(oWalrus, 2,3, 0,2)],
[new SimpleObject(oMuskox, 2,3, 0,2)]
],
[
5 * numPlayers,
5 * numPlayers,
12 * numPlayers
],
avoidClasses(clPlayer, 35, clFood, 16, clWater, 2, clMetal, 4, clRock, 4, clHill, 2)
);
createFood(
[
[new SimpleObject(oWhaleFin, 1,2, 0,2)],
[new SimpleObject(oWhaleHumpback, 1,2, 0,2)]
],
[
scaleByMapSize(1, 6) * 3,
scaleByMapSize(1, 6) * 3,
],
[avoidClasses(clFood, 20, clHill, 5), stayClasses(clWater, 6)]
);
createFood(
[
[new SimpleObject(oFish, 2,3, 0,2)]
],
[
100
],
[avoidClasses(clFood, 12, clHill, 5), stayClasses(clWater, 6)]
);
RMS.SetProgress(85);
// Create trigger points where wolves spawn
createObjectGroups(
new SimpleGroup([new SimpleObject("special/trigger_point_A", 1, 1, 0, 0)], true, clWolf),
0,
avoidClasses(clWater, 2, clMetal, 4, clRock, 4, clPlayer, 15, clHill, 2, clWolf, 20),
1000,
100
);
RMS.SetProgress(95);
if (randInt(0, 2) == 0)
{
setSkySet("sunset 1");
setSunColor(0.8, 0.7, 0.6);
setTerrainAmbientColor(0.7, 0.6, 0.7);
setUnitsAmbientColor(0.6, 0.5, 0.6);
setSunElevation(randFloat(PI/24, PI/7));
}
else
{
setSkySet(pickRandom(["cumulus", "rain", "mountainous", "overcast", "rain", "stratus"]));
setSunElevation(randFloat(PI/9, PI/7));
}
setSunRotation(randFloat(0, TWO_PI));
setWaterColor(0.3, 0.3, 0.4);
setWaterTint(0.75, 0.75, 0.75);
setWaterMurkiness(0.92);
setWaterWaviness(0.5);
setWaterType("clap");
setFogThickness(0.76);
setFogFactor(0.7);
setPPEffect("hdr");
setPPContrast(0.6);
setPPSaturation(0.45);
setPPBloom(0.4);
ExportMap();

View File

@ -0,0 +1,16 @@
{
"settings" : {
"Name" : "Polar Sea",
"Script" : "polar_sea.js",
"Description" : "Players start in a cold polar region barren of vegetation. In the sea fish and whales abound, while the fragile icy land teems with huntable walruses and deadly wolves. These wolves, made ravenous by the harsh and forbidding climate, drawn by the scent of prey, have started appearing in terrifying numbers. A wise and strong ruler will not only achieve victory over his enemies, but also keep the number of these beasts at bay, lest they undermine his economy and cause his downfall. [color=\"red\"]Warning: It is inadvisable to disable treasures, since there is no gatherable wood. Not recommended for inexperienced players.[/color]",
"BaseTerrain" : ["medit_sea_depths"],
"BaseHeight" : 2,
"Keywords": ["new", "trigger"],
"Preview" : "polar_sea.png",
"CircularMap" : true,
"TriggerScripts" : [
"scripts/TriggerHelper.js",
"random/polar_sea_triggers.js"
]
}
}

View File

@ -0,0 +1,75 @@
var attackerTemplate = "gaia/fauna_wolf_snow";
var minWaveSize = 1;
var maxWaveSize = 3;
var firstWaveTime = 3;
var minWaveTime = 2;
var maxWaveTime = 4;
/**
* Attackers will focus the targetCount closest units that have the targetClasses type.
*/
var targetClasses = "Organic";
var targetCount = 3;
var disabledTechnologies = [
"gather_lumbering_ironaxes",
"gather_lumbering_sharpaxes",
"gather_lumbering_strongeraxes"
];
Trigger.prototype.InitDisableTechnologies = function()
{
for (let i = 1; i < TriggerHelper.GetNumberOfPlayers(); ++i)
QueryPlayerIDInterface(i).SetDisabledTechnologies(disabledTechnologies);
}
Trigger.prototype.SpawnWolvesAndAttack = function()
{
let waveSize = Math.round(Math.random() * (maxWaveSize - minWaveSize) + minWaveSize);
let attackers = TriggerHelper.SpawnUnitsFromTriggerPoints("A", attackerTemplate, waveSize, 0);
print("Spawned " + waveSize + " " + attackerTemplate + " at " + Object.keys(attackers).length + " points\n");
let targets = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).GetNonGaiaEntities().filter(ent => {
// TODO: This shouldn't occur by definition of GetNonGaiaEntities
let cmpOwnership = Engine.QueryInterface(ent, IID_Ownership);
if (cmpOwnership.GetOwner() == 0)
return false;
let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
return cmpIdentity && MatchesClassList(cmpIdentity.GetClassesList(), targetClasses)
});
let getDistance = (attacker, target) => {
let cmpPositionAttacker = Engine.QueryInterface(attacker, IID_Position);
if (!cmpPositionAttacker || !cmpPositionAttacker.IsInWorld())
return Infinity;
let cmpPositionTarget = Engine.QueryInterface(target, IID_Position);
if (!cmpPositionTarget || !cmpPositionTarget.IsInWorld())
return Infinity;
return cmpPositionAttacker.GetPosition().distanceToSquared(cmpPositionTarget.GetPosition());
};
for (let spawnPoint in attackers)
for (let attacker of attackers[spawnPoint])
for (let target of targets.sort((ent1, ent2) => getDistance(attacker, ent1) - getDistance(attacker, ent2)).slice(0, targetCount))
ProcessCommand(0, {
"type": "attack",
"entities": [attacker],
"queued": true,
"target": target
});
this.DoAfterDelay((Math.random() * (maxWaveTime - minWaveTime) + minWaveTime) * 60 * 1000, "SpawnWolvesAndAttack", {});
};
{
let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
cmpTrigger.InitDisableTechnologies();
cmpTrigger.DoAfterDelay(firstWaveTime * 60 * 1000, "SpawnWolvesAndAttack", {});
}

View File

@ -182,8 +182,7 @@ UnitAI.prototype.UnitFsmSpec = {
// Called when being told to walk as part of a formation
"Order.FormationWalk": function(msg) {
// Let players move captured domestic animals around
if (this.IsAnimal() && !this.IsDomestic() || this.IsTurret())
if (this.IsTurret())
{
this.FinishOrder();
return;
@ -255,8 +254,7 @@ UnitAI.prototype.UnitFsmSpec = {
},
"Order.Walk": function(msg) {
// Let players move captured domestic animals around
if (this.IsAnimal() && !this.IsDomestic() || this.IsTurret())
if (this.IsTurret())
{
this.FinishOrder();
return;
@ -284,8 +282,7 @@ UnitAI.prototype.UnitFsmSpec = {
},
"Order.WalkAndFight": function(msg) {
// Let players move captured domestic animals around
if (this.IsAnimal() && !this.IsDomestic() || this.IsTurret())
if (this.IsTurret())
{
this.FinishOrder();
return;
@ -311,8 +308,7 @@ UnitAI.prototype.UnitFsmSpec = {
"Order.WalkToTarget": function(msg) {
// Let players move captured domestic animals around
if (this.IsAnimal() && !this.IsDomestic() || this.IsTurret())
if (this.IsTurret())
{
this.FinishOrder();
return;
@ -515,8 +511,7 @@ UnitAI.prototype.UnitFsmSpec = {
},
"Order.Patrol": function(msg) {
// Let players move captured domestic animals around
if (this.IsAnimal() || this.IsTurret())
if (this.IsTurret())
{
this.FinishOrder();
return;

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Entity parent="template_unit_fauna_wild_aggressive">
<Entity parent="template_unit_fauna_wild_violent">
<Attack>
<Melee>
<Hack>10.0</Hack>