Open source Star Ruler 2 source code!

This commit is contained in:
Lucas de Vries
2018-07-17 14:15:37 +02:00
commit cc307720ff
4342 changed files with 2365070 additions and 0 deletions
+571
View File
@@ -0,0 +1,571 @@
#include "include/map.as"
#section server
import saving;
import map_loader;
import util.design_designer;
from empire import Creeps;
from game_start import generateNewSystem, SystemGenerateHook;
import object_creation;
import ship_groups;
import map_systems;
import statuses;
from remnant_designs import spawnRemnantFleet, loadRemnantDesigns;
class Room {
vec3d position;
SystemData@ core;
uint circle = 0;
double angle = 0;
array<SystemData@> systems;
array<uint> circles;
array<Room@> corrids;
};
#section all
enum MapSetting {
M_SysCount,
M_SystemSpacing,
M_Flatten,
};
const uint INITIAL_EXPANSE = 3;
const double REMNANT_FACTOR = 2.0;
class ExpanseMap : Map {
ExpanseMap() {
super();
name = locale::EXPANSE_MAP;
description = locale::EXPANSE_MAP_DESC;
sortIndex = -120;
eatsPlayers = true;
color = 0x5273ffff;
icon = "maps/Expanse/expanse.png";
}
#section client
void makeSettings() {
Toggle(locale::FLATTEN, M_Flatten, false, halfWidth=true);
Number(locale::SYSTEM_SPACING, M_SystemSpacing, DEFAULT_SPACING, decimals=0, step=1000, min=MIN_SPACING, halfWidth=true);
Description(locale::EXPANSE_MAP_TEXT, lines=3);
}
#section server
array<Room@> rooms;
void preGenerate() {
Map::preGenerate();
radius *= 3.0;
}
void generateRegions() {
radius /= 3.0;
Map::generateRegions();
}
void placeSystems() {
//Generate remnant homeworld
loadMap("maps/Expanse/coreMap.txt").generate(this);
//Generate base clusters
double spacing = modSpacing(getSetting(M_SystemSpacing, DEFAULT_SPACING));
bool flatten = getSetting(M_Flatten, 0.0) != 0.0;
//Calculate amount of 'rooms'
uint players = estPlayerCount;
if(players == 0)
players = 3;
uint roomCnt = players+1;
uint corridorLength = 2;
uint sysPerRoom = 7;
double roomRadius = spacing * 1.5 * sqrt(double(sysPerRoom)) + spacing;
double roomHeightVar = flatten ? 0.0 : roomRadius * 0.2;
double sysHeightVar = flatten ? 0.0 : spacing * 0.25;
double playerOffset = max(roomRadius / (twopi / double(players)), roomRadius);
//Generate rooms
double angle = 0.0;
double radius = 0.0;
double angleStep = twopi;
double anglePct = 0.0;
double startAngle = randomd(0.0, twopi);
Room@ circleStart;
uint circle = 0;
uint circleCnt = 0;
for(uint i = 0; i < roomCnt; ++i) {
Room room;
room.position = quaterniond_fromAxisAngle(vec3d_up(), angle + startAngle) * vec3d_front(radius);
if(i != 0)
room.position.y = randomd(-roomHeightVar, roomHeightVar);
room.circle = circle;
room.angle = angle + startAngle;
rooms.insertLast(room);
if(i != 0)
room.corrids.insertLast(rooms[0]);
++circleCnt;
//Proceed to next room position
angle += angleStep;
if(angle + angleStep > twopi) {
angle = 0.0;
radius += playerOffset;
startAngle = randomd(0.0, twopi);
angleStep = twopi / max(double(roomCnt - i - 1), 1.0);
circle += 1;
circleCnt = 0;
}
}
//Generate systems
for(uint i = 0; i < roomCnt; ++i) {
Room@ room = rooms[i];
//Generate systems
uint sysCount = sysPerRoom;
angle = 0.0;
radius = i == 0 ? 9000 : 0;
angleStep = twopi;
if(radius != 0) {
anglePct = (spacing / (2.0 * pi * radius));
if(sysCount > 0)
angleStep = max(anglePct * twopi, twopi / double(sysCount));
}
startAngle = randomd(0.0, twopi);
circle = 0;
int quality = 0;
if(i == 0 && roomCnt > estPlayerCount)
quality = 200;
for(uint n = 0; n < sysCount; ++n) {
//Generate system
vec3d pos = quaterniond_fromAxisAngle(vec3d_up(), angle + startAngle) * vec3d_front(radius);
if(!flatten)
pos.y = randomd(-sysHeightVar, sysHeightVar);
pos += room.position;
SystemData@ sys = addSystem(pos, quality=quality);
if(circle == 0 && (i != 0 || roomCnt == estPlayerCount))
addPossibleHomeworld(sys);
sys.assignGroup = i;
room.systems.insertLast(sys);
room.circles.insertLast(circle);
//Generate links to previous circle
if(circle > 0) {
SystemData@ closest;
double closestDist = INFINITY;
SystemData@ second;
double secondDist = INFINITY;
for(int j = int(n); j >= 0; --j) {
if(room.circles[j] < circle-1)
break;
if(room.circles[j] > circle-1)
continue;
SystemData@ other = room.systems[j];
double d = other.position.distanceToSQ(sys.position);
if(d < closestDist) {
@second = closest;
secondDist = closestDist;
closestDist = d;
@closest = other;
}
else if(d < secondDist) {
@second = other;
secondDist = d;
}
}
if(closest !is null)
addLink(sys, closest);
if(second !is null)
addLink(sys, second);
}
//Proceed to next system position
angle += angleStep;
if(angle + angleStep > twopi) {
angle = 0.0;
radius += spacing;
startAngle = randomd(0.0, twopi);
anglePct = (spacing / (2.0 * pi * radius));
if(sysCount - n - 1 > 0)
angleStep = max(anglePct * twopi, twopi / double(sysCount - n - 1));
circle += 1;
}
}
//Make expanse systems
if(i != 0) {
double aStep = min(twopi / double(roomCnt - 1), pi*0.33);
double minAngle = room.angle - aStep * 0.5;
double maxAngle = room.angle + aStep * 0.5;
aStep = (maxAngle - minAngle) / double(INITIAL_EXPANSE);
for(uint n = 0; n < INITIAL_EXPANSE; ++n) {
double ang = minAngle + double(n) * aStep + aStep * 0.5;
double rad = room.position.length + radius;
vec3d pos = quaterniond_fromAxisAngle(vec3d_up(), ang) * vec3d_front(rad);
pos.y = room.position.y;
if(!flatten)
pos.y += randomd(-spacing*0.5, spacing*0.5);
auto@ sys = addSystem(pos);
sys.assignGroup = i;
ExpanseSystem es;
es.index = sys.index;
es.shouldExpand = true;
es.minAngle = minAngle;
es.maxAngle = maxAngle;
es.circle = 0;
es.radius = rad;
es.field = i;
es.position = n;
es.spacing = spacing;
es.flatten = flatten;
trackSystems.insertLast(es);
}
}
}
//Generate corridors
for(uint i = 0; i < roomCnt; ++i) {
Room@ room = rooms[i];
for(uint n = 0, ncnt = room.corrids.length; n < ncnt; ++n) {
Room@ other = room.corrids[n];
//Build corridor between rooms
vec3d offset = (other.position - room.position);
double offdist = offset.length;
double spacStep = spacing / offdist;
double corStart = roomRadius * 0.5 / offdist;
double corEnd = 1.0 - corStart;
uint len = clamp(floor((corEnd - corStart) / spacStep), 1, corridorLength);
double corStep = (corEnd - corStart) / double(len);
corStart += corStep * 0.5;
SystemData@ first, last;
for(uint x = 0; x < len; ++x) {
vec3d corPos = room.position + offset * (corStep * x + corStart);
if(room.circle == other.circle)
corPos = corPos.normalized(room.position.length - roomRadius * 0.25);
auto@ sys = addSystem(corPos, quality=200);
if(last !is null)
addLink(last, sys);
@last = sys;
if(x == 0)
@first = last;
}
//Find systems to link to
double dist = INFINITY;
SystemData@ closest;
for(uint j = 0, jcnt = room.systems.length; j < jcnt; ++j) {
double d = room.systems[j].position.distanceToSQ(first.position);
if(d < dist) {
@closest = room.systems[j];
dist = d;
}
}
addLink(closest, first);
dist = INFINITY;
for(uint j = 0, jcnt = other.systems.length; j < jcnt; ++j) {
double d = other.systems[j].position.distanceToSQ(last.position);
if(d < dist) {
@closest = other.systems[j];
dist = d;
}
}
addLink(closest, last);
}
}
}
void createRemnant(SystemDesc@ system, double size, ExpanseSystem@ es = null) {
int fleetSize = ceil(size / double(es.defenders.length + es.queuedFleets) / 25.0) * 25;
vec3d pos = system.position;
vec2d offset = random2d(500, system.radius*0.85);
pos.x += offset.x;
pos.z += offset.y;
auto@ ship = spawnRemnantFleet(pos, fleetSize, 0.4);
if(es !is null && ship !is null) {
es.defenders.insertLast(ship);
if(es.queuedFleets > 0)
es.queuedFleets--;
}
}
void createRemnants(SystemDesc@ system, double size, ExpanseSystem@ es, bool queued = false) {
es.queuedFleets = max(randomd(pow(size, 0.14), pow(size, 0.24)), 1.0);
if(queued)
return;
while(es.queuedFleets > 0)
createRemnant(system, size, es);
}
void setPlanetsLocked(SystemDesc@ system, bool value) {
auto@ status = getStatusType("BlockedColonization");
uint plCnt = system.object.planetCount;
for(uint i = 0, cnt = plCnt; i < cnt; ++i) {
if(status !is null) {
if(value)
system.object.planets[i].addStatus(status.id);
else
system.object.planets[i].removeStatusInstanceOfType(status.id);
}
else {
system.object.planets[i].setQuarantined(value);
}
}
}
ExpanseSystem@ setExpanseSystem(SystemDesc@ sys, double remnantSize) {
ExpanseSystem es;
@es.system = sys;
es.remnantSize = remnantSize;
es.origin = origin;
createRemnants(sys, remnantSize, es);
setPlanetsLocked(sys, true);
trackSystems.insertLast(es);
return es;
}
array<ExpanseSystem@> trackSystems;
void init() {
for(uint i = 0, cnt = trackSystems.length; i < cnt; ++i) {
auto@ es = trackSystems[i];
es.origin = origin;
@es.system = getSystem(systems[0].index + es.index);
es.remnantSize = 100;
createRemnants(es.system, es.remnantSize, es);
setPlanetsLocked(es.system, true);
}
setExpanseSystem(getSystem(0), randomd(1200, 1800));
for(uint i = 0, cnt = rooms[0].systems.length; i < cnt; ++i) {
auto@ sys = getSystem(systems[0].index + rooms[0].systems[i].index);
setExpanseSystem(sys, randomd(200, 600));
}
}
void tick(double time) {
bool madeFleet = false;
for(uint i = 0, cnt = trackSystems.length; i < cnt; ++i) {
auto@ es = trackSystems[i];
if(es.system is null)
continue;
if(es.queuedFleets > 0) {
if(!madeFleet) {
createRemnant(es.system, es.remnantSize, es);
madeFleet = true;
}
}
else if(es.defended) {
bool defended = false;
for(uint n = 0, ncnt = es.defenders.length; n < ncnt; ++n) {
auto@ defender = es.defenders[n];
if(defender !is null && defender.valid) {
defended = true;
break;
}
}
if(!defended) {
setPlanetsLocked(es.system, false);
es.defended = false;
es.defenders.length = 0;
if(es.shouldExpand)
expandSystem(es);
}
}
}
}
void expandSystem(ExpanseSystem@ es) {
//Reveal the two closest systems in the next ring
for(uint i = 0; i < 2; ++i) {
bool found = false;
for(uint n = 0, ncnt = trackSystems.length; n < ncnt; ++n) {
auto@ other = trackSystems[n];
if(other.field == es.field && other.circle == es.circle+1 && other.position == es.position+i) {
found = true;
break;
}
}
if(found)
continue;
ExpanseSystem new;
new.origin = es.origin;
new.circle = es.circle+1;
new.spacing = es.spacing;
new.position = es.position+i;
new.flatten = es.flatten;
new.field = es.field;
new.minAngle = es.minAngle;
new.maxAngle = es.maxAngle;
new.radius = es.radius + es.spacing;
new.index = generatedSystems.length;
new.shouldExpand = true;
new.remnantSize = es.remnantSize * REMNANT_FACTOR;
double aStep = (new.maxAngle - new.minAngle) / double(INITIAL_EXPANSE + new.circle);
double ang = new.minAngle + double(new.position) * aStep + aStep * 0.5;
vec3d pos = quaterniond_fromAxisAngle(vec3d_up(), ang) * vec3d_front(new.radius) + new.origin;
pos.y = es.system.position.y;
trackSystems.insertLast(new);
SystemIniter hook;
@hook.mp = this;
@hook.es = new;
generateNewSystem(pos, 2000.0, hook);
}
}
void initSystem(ExpanseSystem@ es) {
auto@ desc = es.system;
const SystemType@ sysType;
do {
@sysType = getDistributedSystemType();
}
while(sysType.unique != SU_NonUnique);
SystemData data;
data.index = es.system.index;
data.position = es.system.position;
desc.radius = 250;
sysType.generate(data, es.system);
desc.object.InnerRadius = desc.radius;
desc.object.OuterRadius = desc.radius * 1.5;
desc.object.radius = desc.object.OuterRadius;
desc.radius = desc.object.OuterRadius;
desc.object.getNode().scale = desc.object.radius + 128.0;
desc.object.getNode().rebuildTransform();
postGenerateSystem(data, es.system);
finalizeSystem(data, es.system);
createRemnants(es.system, es.remnantSize * randomd(0.85, 1.15), es, queued=true);
setPlanetsLocked(es.system, true);
}
void save(SaveFile& file) {
uint cnt = trackSystems.length;
file << cnt;
for(uint i = 0; i < cnt; ++i)
file << trackSystems[i];
}
void load(SaveFile& file) {
uint cnt = 0;
file >> cnt;
trackSystems.length = cnt;
for(uint i = 0; i < cnt; ++i) {
@trackSystems[i] = ExpanseSystem();
file >> trackSystems[i];
}
if(file < SV_0107)
loadRemnantDesigns(file);
}
#section all
}
#section server
class SystemIniter : SystemGenerateHook {
ExpanseMap@ mp;
ExpanseSystem@ es;
void call(SystemDesc@ desc) {
@es.system = desc;
mp.initSystem(es);
}
}
class ExpanseSystem : Savable {
uint index = 0;
uint circle = 0;
uint position = 0;
uint field = 0;
SystemDesc@ system;
vec3d origin;
array<Ship@> defenders;
double minAngle = 0, maxAngle = 0;
double radius = 0;
double remnantSize = 0;
double spacing = 6500;
bool defended = true;
bool shouldExpand = false;
bool flatten = false;
uint queuedFleets = 0;
void save(SaveFile& file) {
file << index << circle;
file << position << field;
file << system.index;
uint cnt = defenders.length;
file << cnt;
for(uint i = 0; i < cnt; ++i)
file << defenders[i];
file << minAngle << maxAngle;
file << radius << remnantSize;
file << defended << shouldExpand;
file << spacing << flatten;
file << origin;
file << queuedFleets;
}
void load(SaveFile& file) {
file >> index >> circle;
file >> position >> field;
uint index = 0;
file >> index;
@system = getSystem(index);
uint cnt = 0;
file >> cnt;
defenders.length = cnt;
for(uint i = 0; i < cnt; ++i)
file >> defenders[i];
file >> minAngle >> maxAngle;
file >> radius >> remnantSize;
file >> defended >> shouldExpand;
file >> spacing >> flatten;
file >> origin;
if(file >= SV_0088)
file >> queuedFleets;
}
};
#section all
+44
View File
@@ -0,0 +1,44 @@
System: Orathi
Position: (0, 0, 0)
Homeworld: False
MakeStar(Temperature = 1000, Radius = 200)
ExpandSystem(500)
TriggerRegion(SetSystemAssignGroup(-2))
MakePlanet(AncientCity, Radius = 24, Conditions = False)
Rename(Orathi Prime)
AddPlanetResource(Water)
AddPlanetResource(Grain)
AddPlanetResource(Grain)
AddPlanetResource(Oil)
AddPlanetResource(AncientCity)
SpawnBuilding(Factory, (4, 3))
SpawnBuilding(Factory, (9, 6))
Trigger(DevelopTiles(1000))
AddResource(Money, +2.5)
MakePlanet(RandomLevel:1, Radius = 16, Conditions = False)
AddPlanetResource(Water)
AddPlanetResource(Meat)
MakePlanet(RandomLevel:1, Radius = 16, Conditions = False)
AddPlanetResource(Water)
AddPlanetResource(Fruit)
ExpandSystem(1000)
MakeAsteroid()
MakeAsteroid()
MakeAsteroid()
MakeAsteroid()
MakeAsteroid()
MakeArtifact()
MakeArtifact()
MakeArtifact()
MakeArtifact()
MakeArtifact()
Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB