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
+146
View File
@@ -0,0 +1,146 @@
import resources;
import regions.regions;
import saving;
import anomalies;
tidy class AnomalyScript {
const AnomalyType@ type;
const AnomalyState@ state;
array<const AnomalyOption@> options;
array<float> progresses(getEmpireCount(), 0);
StrategicIconNode@ icon;
float get_progress(Player& player, const Anomaly& obj) {
if(player.emp is null || !player.emp.valid)
return 0.0;
else
return progresses[player.emp.index];
}
string get_narrative(Player& player, const Anomaly& obj) {
if(get_progress(player, obj) < 1.f)
return type.desc;
else if(state !is null && state.narrative.length > 0)
return state.narrative;
else
return type.narrative;
}
uint get_anomalyType(Player& player, const Anomaly& obj) {
if(get_progress(player, obj) < 1.f || type is null)
return 0;
else
return type.id;
}
uint get_optionCount(Player& player, const Anomaly& obj) {
if(get_progress(player, obj) < 1.f)
return 0;
else
return options.length;
}
uint get_option(Player& player, const Anomaly& obj, uint index) {
if(get_progress(player, obj) < 1.f || index >= options.length)
return 0;
else
return options[index].id;
}
string get_model(Player& player, const Anomaly& obj) {
if(type is null)
return "";
else if(get_progress(player, obj) >= 1.f && state !is null && state.modelName.length > 0)
return state.modelName;
else
return type.modelName;
}
string get_material(Player& player, const Anomaly& obj) {
if(type is null)
return "";
else if(get_progress(player, obj) >= 1.f && state !is null && state.matName.length > 0)
return state.matName;
else
return type.matName;
}
void postInit(Anomaly& obj) {
}
void destroy(Anomaly& obj) {
if(obj.region !is null)
obj.region.removeStrategicIcon(-1, icon);
icon.markForDeletion();
leaveRegion(obj);
}
void makeMesh(Anomaly& obj) {
MeshDesc mesh;
if(type !is null) {
@mesh.model = getModel(type.modelName);
@mesh.material = getMaterial(type.matName);
}
else {
@mesh.model = model::Debris;
@mesh.material = material::Asteroid;
}
mesh.memorable = true;
bindMesh(obj, mesh);
@icon = StrategicIconNode();
icon.establish(obj, 0.0225, spritesheet::AnomalyIcons, 0);
icon.memorable = true;
if(obj.region !is null)
obj.region.addStrategicIcon(-1, obj, icon);
}
double tick(Anomaly& obj, double time) {
Region@ prevRegion = obj.region;
if(updateRegion(obj)) {
Region@ newRegion = obj.region;
if(prevRegion !is null)
prevRegion.removeStrategicIcon(-1, icon);
if(newRegion !is null)
newRegion.addStrategicIcon(-1, obj, icon);
@prevRegion = newRegion;
}
icon.visible = obj.isVisibleTo(playerEmpire);
return 0.2;
}
void readProgress(Message& msg) {
for(uint i = 0; i < progresses.length; ++i) {
if(msg.readBit())
progresses[i] = msg.readFixed(0.0, 1.0, 7);
else
progresses[i] = 0.0;
}
}
void readChoices(Message& msg) {
@type = getAnomalyType(msg.readSmall());
@state = type.states[msg.readSmall()];
options.length = msg.readSmall();
for(uint i = 0; i < options.length; ++i)
@options[i] = type.options[msg.readLimited(type.options.length)];
}
void syncInitial(Anomaly& obj, Message& msg) {
readChoices(msg);
readProgress(msg);
makeMesh(obj);
}
void syncDelta(Anomaly& obj, Message& msg, double tDiff) {
readProgress(msg);
if(msg.readBit())
readChoices(msg);
}
void syncDetailed(Anomaly& obj, Message& msg, double tDiff) {
readProgress(msg);
readChoices(msg);
}
};
+86
View File
@@ -0,0 +1,86 @@
import artifacts;
import regions.regions;
tidy class ArtifactScript {
const ArtifactType@ type;
StrategicIconNode@ icon;
void makeMesh(Artifact& obj) {
MeshDesc mesh;
@mesh.model = type.model;
@mesh.material = type.material;
mesh.memorable = true;
bindMesh(obj, mesh);
if(type.strategicIcon.valid) {
@icon = StrategicIconNode();
if(type.strategicIcon.sheet !is null)
icon.establish(obj, type.iconSize, type.strategicIcon.sheet, type.strategicIcon.index);
else if(type.strategicIcon.mat !is null)
icon.establish(obj, type.iconSize, type.strategicIcon.mat);
icon.memorable = true;
if(obj.region !is null)
obj.region.addStrategicIcon(-1, obj, icon);
}
}
void destroy(Artifact& obj) {
if(icon !is null) {
if(obj.region !is null)
obj.region.removeStrategicIcon(-1, icon);
icon.markForDeletion();
@icon = null;
}
leaveRegion(obj);
}
bool onOwnerChange(Artifact& obj, Empire@ prevOwner) {
regionOwnerChange(obj, prevOwner);
return false;
}
double tick(Artifact& obj, double time) {
Region@ prevRegion = obj.region;
if(updateRegion(obj)) {
Region@ newRegion = obj.region;
if(prevRegion !is null)
prevRegion.removeStrategicIcon(-1, icon);
if(newRegion !is null)
newRegion.addStrategicIcon(-1, obj, icon);
@prevRegion = newRegion;
}
icon.visible = obj.isVisibleTo(playerEmpire);
obj.orbitTick(time);
obj.abilityTick(time);
return 0.2;
}
vec3d get_strategicIconPosition(Artifact& obj) {
if(icon is null)
return obj.position;
return icon.position;
}
void syncInitial(Artifact& obj, Message& msg) {
@type = getArtifactType(msg.readSmall());
obj.ArtifactType = type.id;
obj.readOrbit(msg);
obj.readAbilities(msg);
makeMesh(obj);
}
void syncDelta(Artifact& obj, Message& msg, double tDiff) {
if(msg.readBit())
obj.readAbilityDelta(msg);
if(msg.readBit())
obj.readOrbitDelta(msg);
}
void syncDetailed(Artifact& obj, Message& msg, double tDiff) {
obj.readOrbit(msg);
obj.readAbilities(msg);
}
};
+199
View File
@@ -0,0 +1,199 @@
import resources;
import regions.regions;
import saving;
tidy class AsteroidScript {
StrategicIconNode@ icon;
MeshNode@ baseNode;
array<const ResourceType@> available;
array<float> costs;
array<bool> exploited;
uint resourceLimit = 1;
uint currentResources = 0;
void makeMesh(Asteroid& obj) {
MeshDesc mesh;
switch(obj.id % 4) {
case 0:
@mesh.model = model::Asteroid1; break;
case 1:
@mesh.model = model::Asteroid2; break;
case 2:
@mesh.model = model::Asteroid3; break;
case 3:
@mesh.model = model::Asteroid4; break;
}
switch(obj.id % 3) {
case 0:
@mesh.material = material::AsteroidPegmatite; break;
case 1:
@mesh.material = material::AsteroidMagnetite; break;
case 2:
@mesh.material = material::AsteroidTonalite; break;
}
mesh.memorable = true;
bindMesh(obj, mesh);
@icon = StrategicIconNode();
if(obj.cargoTypes != 0)
icon.establish(obj, 0.015, spritesheet::OreAsteroidIcon, 0);
else
icon.establish(obj, 0.015, spritesheet::AsteroidIcon, 0);
icon.memorable = true;
if(obj.region !is null)
obj.region.addStrategicIcon(-1, obj, icon);
bool hasBase = obj.owner !is null && obj.owner.valid;
if(hasBase && baseNode is null) {
@baseNode = MeshNode(model::MiningBase, material::GenericPBR_MiningBase);
nodeSyncObject(baseNode, obj);
}
}
void destroy(Asteroid& obj) {
if(obj.region !is null)
obj.region.removeStrategicIcon(-1, icon);
icon.markForDeletion();
@icon = null;
if(baseNode !is null) {
baseNode.markForDeletion();
@baseNode = null;
}
leaveRegion(obj);
obj.destroyObjResources();
}
bool onOwnerChange(Asteroid& obj, Empire@ prevOwner) {
regionOwnerChange(obj, prevOwner);
bool hasBase = obj.owner !is null && obj.owner.valid;
obj.HasBase = hasBase ? 1.f : 0.f;
if(hasBase && baseNode is null) {
@baseNode = MeshNode(model::MiningBase, material::GenericPBR_MiningBase);
nodeSyncObject(baseNode, obj);
}
else if(baseNode !is null && !hasBase) {
baseNode.markForDeletion();
@baseNode = null;
}
return false;
}
double tick(Asteroid& obj, double time) {
Region@ prevRegion = obj.region;
if(updateRegion(obj)) {
Region@ newRegion = obj.region;
if(prevRegion !is null)
prevRegion.removeStrategicIcon(-1, icon);
if(newRegion !is null)
newRegion.addStrategicIcon(-1, obj, icon);
@prevRegion = newRegion;
}
icon.visible = obj.isVisibleTo(playerEmpire);
obj.orbitTick(time);
obj.resourceTick(time);
return 0.2;
}
vec3d get_strategicIconPosition(Asteroid& obj) {
if(icon is null)
return obj.position;
return icon.position;
}
bool canDevelop(Asteroid& obj, Empire@ emp) {
return (!obj.owner.valid || obj.owner is emp) && currentResources < resourceLimit;
}
bool canGainLimit(Asteroid& obj, Empire@ emp) {
if(!obj.owner.valid || obj.owner is emp)
return false;
return currentResources < available.length;
}
uint getAvailableCount() {
if(currentResources >= resourceLimit)
return 0;
return available.length;
}
uint getAvailable(uint index) {
if(index >= available.length)
return uint(-1);
if(exploited[index])
return uint(-1);
return available[index].id;
}
double getAvailableCost(uint index) {
if(index >= costs.length)
return -1.0;
if(exploited[index])
return -1.0;
return costs[index];
}
double getAvailableCostFor(uint resId) {
const ResourceType@ type = getResource(resId);
if(type is null)
return -1.0;
for(uint i = 0, cnt = available.length; i < cnt; ++i) {
if(exploited[i])
continue;
if(available[i] is type)
return costs[i];
}
return -1.0;
}
void _readAsteroid(Asteroid& obj, Message& msg) {
@obj.origin = msg.readObject();
uint cnt = msg.readSmall();
available.length = cnt;
costs.length = cnt;
exploited.length = cnt;
for(uint i = 0; i < cnt; ++i) {
@available[i] = getResource(msg.readLimited(getResourceCount()-1));
msg >> costs[i];
msg >> exploited[i];
}
resourceLimit = msg.readSmall();
currentResources = msg.readSmall();
}
void syncInitial(Asteroid& obj, Message& msg) {
_readAsteroid(obj, msg);
obj.readResources(msg);
obj.readCargo(msg);
obj.readOrbit(msg);
makeMesh(obj);
}
void syncDelta(Asteroid& obj, Message& msg, double tDiff) {
if(msg.readBit())
_readAsteroid(obj, msg);
if(msg.readBit())
obj.readResourceDelta(msg);
if(msg.readBit())
obj.readCargoDelta(msg);
if(msg.readBit())
obj.readOrbitDelta(msg);
}
void syncDetailed(Asteroid& obj, Message& msg, double tDiff) {
_readAsteroid(obj, msg);
obj.readResources(msg);
obj.readCargo(msg);
obj.readOrbit(msg);
}
};
+116
View File
@@ -0,0 +1,116 @@
import regions.regions;
import resources;
import civilians;
const double CIV_HEALTH = 25.0;
tidy class CivilianScript {
uint type = 0;
uint cargoType = 0;
const ResourceType@ cargoResource;
int cargoWorth = 0;
bool pickedUp = false;
double Health = 0;
uint getCivilianType() {
return type;
}
double get_health() {
return Health;
}
double get_maxHealth(const Civilian& obj) {
return CIV_HEALTH * obj.radius;
}
uint getCargoType() {
if(cargoType == CT_Resource && !pickedUp)
return CT_Goods;
return cargoType;
}
uint getCargoResource() {
if(cargoResource is null)
return uint(-1);
return cargoResource.id;
}
int getCargoWorth() {
return cargoWorth;
}
void init(Civilian& obj) {
}
void destroy(Civilian& obj) {
leaveRegion(obj);
}
bool onOwnerChange(Civilian& obj, Empire@ prevOwner) {
regionOwnerChange(obj, prevOwner);
return false;
}
double tick(Civilian& obj, double time) {
updateRegion(obj);
if(obj.hasMover)
obj.moverTick(time);
return 0.2;
}
void makeMesh(Civilian& obj) {
MeshDesc mesh;
@mesh.model = getCivilianModel(obj.owner, type, obj.radius);
@mesh.material = getCivilianMaterial(obj.owner, type, obj.radius);
@mesh.iconSheet = getCivilianIcon(obj.owner, type, obj.radius).sheet;
mesh.iconIndex = getCivilianIcon(obj.owner, type, obj.radius).index;
bindMesh(obj, mesh);
}
void _readDelta(Civilian& obj, Message& msg) {
cargoType = msg.readSmall();
cargoWorth = msg.readSmall();
pickedUp = msg.readBit();
Health = obj.maxHealth * msg.readFixed();
if(msg.readBit()) {
uint id = msg.readLimited(getResourceCount()-1);
@cargoResource = getResource(id);
}
else {
@cargoResource = null;
}
}
void syncInitial(Civilian& obj, Message& msg) {
if(msg.readBit()) {
if(!obj.hasMover)
obj.activateMover();
obj.readMover(msg);
}
msg >> type;
_readDelta(obj, msg);
makeMesh(obj);
}
void syncDetailed(Civilian& obj, Message& msg, double tDiff) {
if(msg.readBit()) {
if(!obj.hasMover)
obj.activateMover();
obj.readMover(msg);
}
_readDelta(obj, msg);
}
void syncDelta(Civilian& obj, Message& msg, double tDiff) {
if(msg.readBit()) {
if(!obj.hasMover)
obj.activateMover();
obj.readMoverDelta(msg);
}
if(msg.readBit())
_readDelta(obj, msg);
}
};
+66
View File
@@ -0,0 +1,66 @@
import regions.regions;
tidy class ColonyShipScript {
ColonyShipScript() {
}
void init(ColonyShip& ship) {
//Create the graphics
makeMesh(ship);
}
void makeMesh(ColonyShip& obj) {
MeshDesc shipMesh;
const Shipset@ ss = obj.owner.shipset;
const ShipSkin@ skin;
if(ss !is null)
@skin = ss.getSkin("Colonizer");
if(obj.owner.ColonizerModel.length != 0) {
@shipMesh.model = getModel(obj.owner.ColonizerModel);
@shipMesh.material = getMaterial(obj.owner.ColonizerMaterial);
}
else if(skin !is null) {
@shipMesh.model = skin.model;
@shipMesh.material = skin.material;
}
else {
@shipMesh.model = model::ColonyShip;
@shipMesh.material = material::VolkurGenericPBR;
}
@shipMesh.iconSheet = spritesheet::HullIcons;
shipMesh.iconIndex = 0;
bindMesh(obj, shipMesh);
}
void destroy(ColonyShip& ship) {
leaveRegion(ship);
}
bool onOwnerChange(ColonyShip& obj, Empire@ prevOwner) {
regionOwnerChange(obj, prevOwner);
return false;
}
double tick(ColonyShip& ship, double time) {
updateRegion(ship);
ship.moverTick(time);
return 0.2;
}
void syncInitial(ColonyShip& ship, Message& msg) {
ship.readMover(msg);
}
void syncDetailed(ColonyShip& ship, Message& msg, double tDiff) {
ship.readMover(msg);
}
void syncDelta(ColonyShip& ship, Message& msg, double tDiff) {
if(msg.readBit())
ship.readMoverDelta(msg);
}
};
+63
View File
@@ -0,0 +1,63 @@
import regions.regions;
tidy class FreighterScript {
FreighterScript() {
}
void makeMesh(Freighter& obj) {
MeshDesc shipMesh;
const Shipset@ ss = obj.owner.shipset;
const ShipSkin@ skin;
if(ss !is null)
@skin = ss.getSkin(obj.skin);
if(skin !is null) {
@shipMesh.model = skin.model;
@shipMesh.material = skin.material;
}
else {
@shipMesh.model = model::Fighter;
@shipMesh.material = material::Ship10;
}
@shipMesh.iconSheet = spritesheet::HullIcons;
shipMesh.iconIndex = 0;
bindMesh(obj, shipMesh);
}
void init(Freighter& ship) {
//Create the graphics
makeMesh(ship);
}
void destroy(Freighter& ship) {
leaveRegion(ship);
}
bool onOwnerChange(Freighter& obj, Empire@ prevOwner) {
regionOwnerChange(obj, prevOwner);
return false;
}
double tick(Freighter& ship, double time) {
updateRegion(ship);
ship.moverTick(time);
return 0.2;
}
void syncInitial(Freighter& ship, Message& msg) {
msg >> ship.skin;
ship.readMover(msg);
}
void syncDetailed(Freighter& ship, Message& msg, double tDiff) {
ship.readMover(msg);
}
void syncDelta(Freighter& ship, Message& msg, double tDiff) {
if(msg.readBit())
ship.readMoverDelta(msg);
}
};
+109
View File
@@ -0,0 +1,109 @@
import regions.regions;
import oddity_navigation;
import oddities;
tidy class OddityScript {
StrategicIconNode@ icon;
bool gate = false;
double timer = -1.0;
uint visualType = uint(-1);
uint visualColor = 0xffffffff;
Object@ link;
bool isGate() {
return gate;
}
vec3d getGateDest() {
if(link !is null)
return link.position;
return vec3d();
}
Object@ getLink() {
return link;
}
double getTimer() {
return timer;
}
vec3d get_strategicIconPosition(Oddity& obj) {
if(icon is null)
return obj.position;
return icon.position;
}
void _read(Oddity& obj, Message& msg) {
uint prevVisual = visualType;
bool prevGate = gate;
msg >> gate;
msg >> timer;
msg >> visualType;
msg >> visualColor;
msg >> link;
if(prevVisual == uint(-1) && visualType != uint(-1)) {
if(link !is null)
obj.rotation = quaterniond_fromVecToVec(vec3d_front(), (link.position - obj.position).normalized(), vec3d_up());
makeVisuals(obj, visualType, color=visualColor);
}
if(gate != prevGate) {
if(gate)
addOddityGate(obj);
else
removeOddityGate(obj);
}
}
double tick(Oddity& obj, double time) {
//Handle region changes
Region@ prevRegion = obj.region;
if(updateRegion(obj)) {
Region@ newRegion = obj.region;
if(icon !is null) {
if(prevRegion !is null)
prevRegion.removeStrategicIcon(-1, icon);
if(newRegion !is null)
newRegion.addStrategicIcon(-1, obj, icon);
}
@prevRegion = newRegion;
}
//Handle timer
if(timer > 0.0)
timer = max(timer - time, 0.0);
return 0.25;
}
void syncInitial(Oddity& obj, Message& msg) {
_read(obj, msg);
}
void syncDelta(Oddity& obj, Message& msg, double tDiff) {
if(msg.readBit())
_read(obj, msg);
}
void syncDetailed(Oddity& obj, Message& msg, double tDiff) {
_read(obj, msg);
}
void makeVisuals(Oddity& obj, uint type, bool fromCreation = true, uint color = 0xffffffff) {
visualType = type;
@icon = makeOddityVisuals(obj, type, fromCreation, color=color);
}
void destroy(Oddity& obj) {
if(obj.region !is null)
obj.region.removeStrategicIcon(-1, icon);
if(icon !is null)
icon.markForDeletion();
leaveRegion(obj);
if(gate)
removeOddityGate(obj);
removeAmbientSource(obj.id);
}
};
+379
View File
@@ -0,0 +1,379 @@
import regions.regions;
from resources import MoneyType;
import orbitals;
import saving;
const int STRATEGIC_RING = -1;
const double RECOVERY_TIME = 3.0 * 60.0;
tidy class OrbitalScript {
OrbitalNode@ node;
StrategicIconNode@ icon;
OrbitalSection@ core;
array<OrbitalSection@> sections;
int nextSectionId = 1;
int contestion = 0;
bool disabled = false;
Orbital@ master;
double Health = 0;
double MaxHealth = 0;
double Armor = 0;
double MaxArmor = 0;
double DR = 2.5;
double DPS = 0;
Orbital@ getMaster() {
return master;
}
bool hasMaster() {
return master !is null;
}
bool isMaster(Object@ obj) {
return master is obj;
}
double get_health(Orbital& orb) {
double v = Health;
Empire@ owner = orb.owner;
if(owner !is null)
v *= owner.OrbitalHealthMod;
return v;
}
double get_maxHealth(Orbital& orb) {
double v = MaxHealth;
Empire@ owner = orb.owner;
if(owner !is null)
v *= owner.OrbitalHealthMod;
return v;
}
double get_armor(Orbital& orb) {
double v = Armor;
Empire@ owner = orb.owner;
if(owner !is null)
v *= owner.OrbitalArmorMod;
return v;
}
double get_maxArmor(Orbital& orb) {
double v = MaxArmor;
Empire@ owner = orb.owner;
if(owner !is null)
v *= owner.OrbitalArmorMod;
return v;
}
double get_dps() {
return DPS;
}
double get_efficiency() {
return clamp(Health / max(1.0, MaxHealth), 0.0, 1.0);
}
double getValue(Player& pl, Orbital& obj, uint id) {
double value = 0.0;
for(uint i = 0, cnt = sections.length; i < cnt; ++i) {
auto@ sec = sections[i];
for(uint j = 0, jcnt = sec.type.hooks.length; j < jcnt; ++j) {
if(sec.type.hooks[j].getValue(pl, obj, sec.data[j], id, value))
return value;
}
}
return 0.0;
}
const Design@ getDesign(Player& pl, Orbital& obj, uint id) {
const Design@ value;
for(uint i = 0, cnt = sections.length; i < cnt; ++i) {
auto@ sec = sections[i];
for(uint j = 0, jcnt = sec.type.hooks.length; j < jcnt; ++j) {
if(sec.type.hooks[j].getDesign(pl, obj, sec.data[j], id, value))
return value;
}
}
return null;
}
Object@ getObject(Player& pl, Orbital& obj, uint id) {
Object@ value;
for(uint i = 0, cnt = sections.length; i < cnt; ++i) {
auto@ sec = sections[i];
if(!sec.enabled)
continue;
for(uint j = 0, jcnt = sec.type.hooks.length; j < jcnt; ++j) {
if(sec.type.hooks[j].getObject(pl, obj, sec.data[j], id, value))
return value;
}
}
return null;
}
void getSections() {
for(uint i = 0, cnt = sections.length; i < cnt; ++i)
yield(sections[i]);
}
bool hasModule(uint typeId) {
for(uint i = 0, cnt = sections.length; i < cnt; ++i) {
auto@ sec = sections[i];
if(sec.type.id == typeId)
return true;
}
return false;
}
uint get_coreModule() {
auto@ mod = core;
if(mod is null)
return uint(-1);
return mod.type.id;
}
bool get_isStandalone() {
auto@ mod = core;
if(mod is null)
return true;
return mod.type.isStandalone;
}
bool get_isContested() {
return contestion != 0;
}
bool get_isDisabled() {
return disabled || (core !is null && !core.enabled);
}
void destroy(Orbital& obj) {
if(icon !is null) {
if(obj.region !is null)
obj.region.removeStrategicIcon(STRATEGIC_RING, icon);
icon.markForDeletion();
@icon = null;
}
@node = null;
leaveRegion(obj);
obj.destroyObjResources();
if(obj.hasConstruction)
obj.destroyConstruction();
if(obj.hasAbilities)
obj.destroyAbilities();
}
bool onOwnerChange(Orbital& obj, Empire@ prevOwner) {
regionOwnerChange(obj, prevOwner);
obj.changeResourceOwner(prevOwner);
return false;
}
float timer = 0.f;
double prevFleet = 0.0;
void occasional_tick(Orbital& obj) {
Region@ prevRegion = obj.region;
if(updateRegion(obj)) {
Region@ newRegion = obj.region;
if(icon !is null) {
if(prevRegion !is null)
prevRegion.removeStrategicIcon(STRATEGIC_RING, icon);
if(newRegion !is null)
newRegion.addStrategicIcon(STRATEGIC_RING, obj, icon);
}
obj.changeResourceRegion(prevRegion, newRegion);
@prevRegion = newRegion;
}
if(icon !is null)
icon.visible = obj.isVisibleTo(playerEmpire);
if(node !is null) {
double rad = 0.0;
if(obj.hasLeaderAI && obj.SupplyCapacity > 0)
rad = obj.getFormationRadius();
if(rad != prevFleet) {
node.setFleetPlane(rad);
prevFleet = rad;
}
}
if(obj.hasLeaderAI)
obj.updateFleetStrength();
}
vec3d get_strategicIconPosition(const Orbital& obj) {
if(icon is null)
return obj.position;
return icon.position;
}
double tick(Orbital& obj, double time) {
//Tick construction
double delay = 0.2;
if(obj.hasConstruction) {
obj.constructionTick(time);
//if(obj.hasConstructionUnder(0.2))
// delay = 0.0;
}
if(obj.hasAbilities)
obj.abilityTick(time);
//Tick resources
obj.resourceTick(time);
//Tick orbit
obj.moverTick(time);
//Tick occasional stuff
timer -= float(time);
if(timer <= 0.f) {
occasional_tick(obj);
timer = 1.f;
}
return delay;
}
void _read(Orbital& obj, Message& msg) {
uint cnt = msg.readSmall();
sections.length = cnt;
for(uint i = 0; i < cnt; ++i) {
if(sections[i] is null)
@sections[i] = OrbitalSection();
msg >> sections[i];
}
if(core is null && sections.length != 0) {
@core = sections[0];
auto@ type = core.type;
@node = cast<OrbitalNode>(bindNode(obj, "OrbitalNode"));
if(node !is null)
node.establish(obj, type.id);
if(type.strategicIcon.valid) {
@icon = StrategicIconNode();
if(type.strategicIcon.sheet !is null)
icon.establish(obj, type.iconSize, type.strategicIcon.sheet, type.strategicIcon.index);
else if(type.strategicIcon.mat !is null)
icon.establish(obj, type.iconSize, type.strategicIcon.mat);
if(obj.region !is null)
obj.region.addStrategicIcon(STRATEGIC_RING, obj, icon);
}
}
msg >> contestion;
msg >> disabled;
msg >> master;
}
void _readHP(Orbital& obj, Message& msg) {
msg >> Health;
msg >> MaxHealth;
msg >> Armor;
msg >> MaxArmor;
msg >> DR;
msg >> DPS;
}
void syncInitial(Orbital& obj, Message& msg) {
_read(obj, msg);
_readHP(obj, msg);
obj.readResources(msg);
obj.readOrbit(msg);
obj.readStatuses(msg);
obj.readMover(msg);
if(msg.readBit()) {
if(!obj.hasConstruction)
obj.activateConstruction();
obj.readConstruction(msg);
}
if(msg.readBit()) {
if(!obj.hasLeaderAI)
obj.activateLeaderAI();
obj.readLeaderAI(msg);
}
if(msg.readBit()) {
if(!obj.hasAbilities)
obj.activateAbilities();
obj.readAbilities(msg);
}
if(msg.readBit()) {
if(!obj.hasCargo)
obj.activateCargo();
obj.readCargo(msg);
}
}
void syncDelta(Orbital& obj, Message& msg, double tDiff) {
if(msg.readBit())
_read(obj, msg);
if(msg.readBit())
_readHP(obj, msg);
if(msg.readBit())
obj.readOrbit(msg);
if(msg.readBit())
obj.readResourceDelta(msg);
if(msg.readBit()) {
if(!obj.hasConstruction)
obj.activateConstruction();
obj.readConstructionDelta(msg);
}
if(msg.readBit()) {
if(!obj.hasLeaderAI)
obj.activateLeaderAI();
obj.readLeaderAIDelta(msg);
}
if(msg.readBit()) {
if(!obj.hasAbilities)
obj.activateAbilities();
obj.readAbilityDelta(msg);
}
if(msg.readBit()) {
if(!obj.hasCargo)
obj.activateCargo();
obj.readCargoDelta(msg);
}
if(msg.readBit())
obj.readStatusDelta(msg);
if(msg.readBit())
obj.readOrbitDelta(msg);
if(msg.readBit())
obj.readMoverDelta(msg);
}
void syncDetailed(Orbital& obj, Message& msg, double tDiff) {
_read(obj, msg);
_readHP(obj, msg);
obj.readResources(msg);
obj.readOrbit(msg);
obj.readStatuses(msg);
obj.readMover(msg);
if(msg.readBit()) {
if(!obj.hasConstruction)
obj.activateConstruction();
obj.readConstruction(msg);
}
if(msg.readBit()) {
if(!obj.hasLeaderAI)
obj.activateLeaderAI();
obj.readLeaderAI(msg);
}
if(msg.readBit()) {
if(!obj.hasAbilities)
obj.activateAbilities();
obj.readAbilities(msg);
}
if(msg.readBit()) {
if(!obj.hasCargo)
obj.activateCargo();
obj.readCargo(msg);
}
}
};
+83
View File
@@ -0,0 +1,83 @@
import pickups;
import regions.regions;
tidy class PickupScript {
void destroy(Pickup& obj) {
leaveRegion(obj);
}
void syncInitial(Pickup& obj, Message& msg) {
msg >> obj.PickupType;
obj.readPickup(msg);
obj.initPickup();
}
void syncDelta(Pickup& obj, Message& msg, double tDiff) {
obj.readPickup(msg);
}
double tick(Pickup& obj, double time) {
updateRegion(obj);
obj.tickPickup(time);
return 0.5;
}
};
tidy class PickupControl : Component_PickupControl {
const PickupType@ type;
Object@[] protectors;
vec3d offset;
PickupControl() {
}
void generateMesh(Object& obj) {
MeshDesc mesh;
@mesh.model = type.model;
@mesh.material = type.material;
@mesh.iconSheet = type.iconSheet;
mesh.iconIndex = type.iconIndex;
mesh.memorable = true;
bindMesh(obj, mesh);
Node@ node = obj.getNode();
node.customColor = true;
node.color = Color(0x998888ff);
}
void initPickup(Object& obj) {
Pickup@ pickup = cast<Pickup>(obj);
@type = getPickupType(pickup.PickupType);
generateMesh(obj);
}
Object@ getProtector() {
if(protectors.length == 0)
return null;
return protectors[0];
}
bool get_isPickupProtected() {
return protectors.length != 0;
}
void tickPickup(Object& pickup, double time) {
if(protectors.length != 0) {
if(offset.zero)
offset = protectors[0].position - pickup.position;
auto@ prot = protectors[0];
pickup.position = prot.position + offset;
pickup.velocity = prot.velocity;
pickup.acceleration = prot.acceleration;
}
}
void readPickup(Object& obj, Message& msg) {
uint cnt = 0, prevCnt = protectors.length;
msg >> cnt;
protectors.length = cnt;
for(uint i = 0; i < cnt; ++i)
msg >> protectors[i];
}
};
+176
View File
@@ -0,0 +1,176 @@
import planet_types;
import regions.regions;
tidy class MoonData {
uint style = 0;
float size = 0.f;
};
tidy class PlanetScript {
double tickTimer = randomd(-0.2,0.2);
array<MoonData@>@ moons;
void destroy(Planet& planet) {
planet.destroySurface();
leaveRegion(planet);
planet.destroyObjResources();
}
bool onOwnerChange(Planet& planet, Empire@ prevOwner) {
regionOwnerChange(planet, prevOwner);
return false;
}
double tick(Planet& planet, double time) {
//Update region
Region@ prevRegion = planet.region;
if(updateRegion(planet)) {
planet.changeResourceRegion(prevRegion, planet.region);
planet.changeSurfaceRegion(prevRegion, planet.region);
auto@ node = planet.getNode();
if(node !is null)
node.hintParentObject(planet.region);
}
tickTimer += time;
if(tickTimer >= 1.f) {
tickTimer = 0.f;
planet.updateFleetStrength();
}
if(planet.hasMover)
planet.moverTick(time);
else
planet.orbitTick(time);
planet.resourceTick(time);
planet.surfaceTick(time);
planet.constructionTick(time);
if(planet.hasAbilities)
planet.abilityTick(time);
return 0.2;
}
void syncInitial(Planet& planet, Message& msg) {
//Read planet data
planet.Health = msg.read_float();
planet.MaxHealth = msg.read_float();
planet.PlanetType = msg.readSmall();
msg >> planet.renamed;
msg >> planet.OrbitSize;
planet.readResources(msg);
planet.readSurface(msg);
planet.readOrbit(msg);
planet.Population = planet.population;
//Create graphics
PlanetNode@ plNode = cast<PlanetNode>(bindNode(planet, "PlanetNode"));
plNode.establish(planet);
plNode.flags = planet.planetGraphicsFlags;
planet.readLeaderAI(msg);
planet.readStatuses(msg);
planet.readCargo(msg);
if(msg.readBit()) {
if(!planet.hasAbilities)
planet.activateAbilities();
planet.readAbilities(msg);
}
uint ringStyle = 0;
if(msg.readBit())
msg >> ringStyle;
if(plNode !is null) {
plNode.planetType = planet.PlanetType;
plNode.colonized = planet.owner.valid;
if(ringStyle != 0)
plNode.addRing(ringStyle);
plNode.hintParentObject(planet.region);
}
if(msg.readBit()) {
if(!planet.hasMover)
planet.activateMover();
planet.readMover(msg);
}
if(msg.readBit()) {
if(moons is null)
@moons = array<MoonData@>();
moons.length = msg.readSmall();
for(uint i = 0, cnt = moons.length; i < cnt; ++i) {
MoonData dat;
msg >> dat.size;
msg >> dat.style;
@moons[i] = dat;
if(plNode !is null)
plNode.addMoon(dat.size, dat.style);
}
}
}
void syncDelta(Planet& planet, Message& msg, double tDiff) {
if(msg.readBit())
planet.readResourceDelta(msg);
if(msg.readBit()) {
planet.readSurfaceDelta(msg);
planet.Population = planet.population;
}
if(msg.readBit())
planet.readConstructionDelta(msg);
if(msg.readBit())
planet.readLeaderAIDelta(msg);
if(msg.readBit()) {
if(!planet.hasAbilities)
planet.activateAbilities();
planet.readAbilityDelta(msg);
}
if(msg.readBit())
planet.readStatusDelta(msg);
if(msg.readBit())
planet.readCargoDelta(msg);
if(msg.readBit()) {
planet.Health = msg.read_float();
planet.MaxHealth = msg.read_float();
}
if(msg.readBit()) {
if(!planet.hasMover)
planet.activateMover();
planet.readMoverDelta(msg);
}
if(msg.readBit())
planet.readOrbitDelta(msg);
}
void syncDetailed(Planet& planet, Message& msg, double tDiff) {
planet.Health = msg.read_float();
planet.MaxHealth = msg.read_float();
planet.readResources(msg);
planet.readSurface(msg);
planet.readConstruction(msg);
planet.readStatuses(msg);
planet.readCargo(msg);
if(msg.readBit()) {
if(!planet.hasAbilities)
planet.activateAbilities();
planet.readAbilities(msg);
}
planet.Population = planet.population;
if(msg.readBit()) {
if(!planet.hasMover)
planet.activateMover();
planet.readMover(msg);
}
}
uint get_moonCount() {
if(moons is null)
return 0;
return moons.length;
}
};
+249
View File
@@ -0,0 +1,249 @@
import regions.regions;
from designs import getDesignMesh;
tidy class ShipScript {
float commandUsed = 0.f;
float timer = 1.f;
bool hasGraphics = false;
bool get_isStation(Ship& ship) {
return ship.blueprint.design.hasTag(ST_Station);
}
void occasional_tick(Ship& ship, float time) {
if(ship.hasLeaderAI)
ship.updateFleetStrength();
}
double tick(Ship& ship, double time) {
if(updateRegion(ship)) {
auto@ node = ship.getNode();
if(node !is null)
node.hintParentObject(ship.region);
}
ship.moverTick(time);
if(ship.hasLeaderAI)
ship.leaderTick(time);
timer += float(time);
if(timer >= 1.f) {
occasional_tick(ship, timer);
timer = 0.f;
}
return 0.2;
}
void destroy(Ship& ship) {
if(ship.inCombat) {
auto@ region = ship.region;
if(region !is null) {
uint debris = uint(log(ship.blueprint.design.size) / log(2.0));
if(debris > 0)
region.addShipDebris(ship.position, debris);
}
}
leaveRegion(ship);
if(ship.hasLeaderAI)
ship.leaderDestroy();
}
bool onOwnerChange(Ship& ship, Empire@ prevOwner) {
regionOwnerChange(ship, prevOwner);
if(ship.hasLeaderAI)
ship.leaderChangeOwner(prevOwner, ship.owner);
return false;
}
void createGraphics(Ship& ship, const Design@ dsg) {
if(dsg is null)
return;
MeshDesc shipMesh;
getDesignMesh(ship.owner, ship.blueprint.design, shipMesh);
shipMesh.memorable = ship.memorable;
bindMesh(ship, shipMesh);
hasGraphics = true;
if(ship.hasLeaderAI) {
auto@ node = ship.getNode();
if(node !is null)
node.animInvis = true;
}
}
void syncInitial(Ship& ship, Message& msg) {
//Find hull
uint hullID = msg.readSmall();
const Hull@ hull = getHullDefinition(hullID);
//Sync data
ship.blueprint.recvDetails(ship, msg);
if(msg.readBit()) {
ship.activateLeaderAI();
ship.leaderInit();
ship.readLeaderAI(msg);
auto@ node = ship.getNode();
if(node !is null)
node.animInvis = true;
}
else {
ship.activateSupportAI();
ship.readSupportAI(msg);
}
ship.readMover(msg);
if(msg.readBit()) {
msg >> ship.MaxEnergy;
ship.Energy = msg.readFixed(0.f, ship.MaxEnergy, 16);
}
if(msg.readBit()) {
msg >> ship.MaxSupply;
ship.Supply = msg.readFixed(0.f, ship.MaxSupply, 16);
}
if(msg.readBit()) {
msg >> ship.MaxShield;
ship.Shield = msg.readFixed(0.f, ship.MaxShield, 16);
}
if(msg.readBit()) {
ship.activateAbilities();
ship.readAbilities(msg);
}
if(msg.readBit()) {
ship.activateStatuses();
ship.readStatuses(msg);
}
if(msg.readBit()) {
ship.activateCargo();
ship.readCargo(msg);
}
if(msg.readBit()) {
ship.activateConstruction();
ship.readConstruction(msg);
}
if(msg.readBit()) {
ship.activateOrbit();
ship.readOrbit(msg);
}
createGraphics(ship, ship.blueprint.design);
}
void syncDetailed(Ship& ship, Message& msg, double tDiff) {
ship.readMover(msg);
if(ship.hasLeaderAI)
ship.readLeaderAI(msg);
else
ship.readSupportAI(msg);
ship.blueprint.recvDetails(ship, msg);
updateStats(ship);
msg >> ship.Energy;
msg >> ship.MaxEnergy;
msg >> ship.Supply;
msg >> ship.MaxSupply;
msg >> ship.Shield;
msg >> ship.MaxShield;
ship.isFTLing = msg.readBit();
ship.inCombat = msg.readBit();
if(ship.hasAbilities)
ship.readAbilities(msg);
if(ship.hasStatuses)
ship.readStatuses(msg);
if(msg.readBit()) {
if(!ship.hasCargo)
ship.activateCargo();
ship.readCargo(msg);
}
if(msg.readBit()) {
if(!ship.hasOrbit)
ship.activateOrbit();
ship.readOrbit(msg);
}
if(msg.readBit()) {
if(!ship.hasConstruction)
ship.activateConstruction();
ship.readConstruction(msg);
}
}
void updateStats(Ship& ship) {
const Design@ dsg = ship.blueprint.design;
if(dsg is null)
return;
ship.DPS = ship.blueprint.getEfficiencySum(SV_DPS);
ship.MaxDPS = dsg.total(SV_DPS);
ship.MaxSupply = dsg.total(SV_SupplyCapacity);
ship.MaxShield = dsg.total(SV_ShieldCapacity);
commandUsed = dsg.variable(ShV_REQUIRES_Command);
}
void syncDelta(Ship& ship, Message& msg, double tDiff) {
if(msg.readBit())
ship.readMoverDelta(msg);
if(msg.readBit()) {
ship.blueprint.recvDelta(ship, msg);
if(!hasGraphics)
createGraphics(ship, ship.blueprint.design);
updateStats(ship);
}
if(msg.readBit())
ship.Shield = msg.readFixed(0.f, ship.MaxShield, 16);
if(msg.readBit()) {
if(ship.hasLeaderAI)
ship.readLeaderAIDelta(msg);
else
ship.readSupportAIDelta(msg);
}
if(ship.hasAbilities) {
if(msg.readBit())
ship.readAbilityDelta(msg);
}
if(ship.hasStatuses) {
if(msg.readBit())
ship.readStatusDelta(msg);
}
if(ship.hasLeaderAI) {
if(msg.readBit()) {
if(!ship.hasCargo)
ship.activateCargo();
ship.readCargoDelta(msg);
}
}
if(msg.readBit()) {
if(msg.readBit())
msg >> ship.Energy;
else
ship.Energy = 0;
if(msg.readBit())
msg >> ship.Supply;
else
ship.Supply = 0;
ship.isFTLing = msg.readBit();
ship.inCombat = msg.readBit();
}
if(msg.readBit()) {
if(!ship.hasOrbit)
ship.activateOrbit();
ship.readOrbitDelta(msg);
}
if(ship.hasLeaderAI) {
if(msg.readBit()) {
if(!ship.hasConstruction)
ship.activateConstruction();
ship.readConstructionDelta(msg);
}
}
}
};
+68
View File
@@ -0,0 +1,68 @@
import regions.regions;
LightDesc lightDesc;
tidy class StarScript {
void syncInitial(Star& star, Message& msg) {
star.temperature = msg.read_float();
lightDesc.att_quadratic = 1.f/(2000.f*2000.f);
double temp = star.temperature;
Node@ node;
double soundRadius = star.radius;
if(temp > 0.0) {
@node = bindNode(star, "StarNode");
node.color = blackBody(temp, max((temp + 15000.0) / 40000.0, 1.0));
}
else {
@node = bindNode(star, "BlackholeNode");
node.color = blackBody(16000.0, max((16000.0 + 15000.0) / 40000.0, 1.0));
cast<BlackholeNode>(node).establish(star);
soundRadius *= 10.0;
}
if(node !is null)
node.hintParentObject(star.region);
star.readOrbit(msg);
lightDesc.position = vec3f(star.position);
lightDesc.diffuse = node.color * 1.0f;
lightDesc.specular = lightDesc.diffuse;
lightDesc.radius = star.radius;
if(star.inOrbit)
makeLight(lightDesc, node);
else
makeLight(lightDesc);
addAmbientSource("star_rumble", star.id, star.position, soundRadius);
}
void destroy(Star& obj) {
removeAmbientSource(obj.id);
leaveRegion(obj);
}
void syncDetailed(Star& star, Message& msg, double tDiff) {
star.Health = msg.read_float();
star.MaxHealth = msg.read_float();
}
void syncDelta(Star& star, Message& msg, double tDiff) {
star.Health = msg.read_float();
star.MaxHealth = msg.read_float();
}
double tick(Star& star, double time) {
if(updateRegion(star)) {
auto@ node = star.getNode();
if(node !is null)
node.hintParentObject(star.region);
}
star.orbitTick(time);
return 1.0;
}
};
+202
View File
@@ -0,0 +1,202 @@
import systems;
tidy class TerritoryScript {
TerritoryNode@ node;
set_int inner;
set_int edges;
array<Region@> regions;
array<Region@> visionPending;
array<bool> visionPendingOp;
Empire@ prevEmpire = playerEmpire;
double tick(Territory& obj, double time) {
if(playerEmpire !is prevEmpire) {
@prevEmpire = playerEmpire;
//Apply anything that was waiting
for(uint i = 0, cnt = visionPending.length; i < cnt; ++i) {
Region@ region = visionPending[i];
if(visionPendingOp[i])
node.addInner(region.id, region.position, region.radius);
else
node.removeInner(region.id);
}
visionPending.length = 0;
visionPendingOp.length = 0;
//Remove vision on systems we aren't supposed to see
for(uint i = 0, cnt = regions.length; i < cnt; ++i) {
Region@ region = regions[i];
if(obj.owner is playerEmpire || region.VisionMask & playerEmpire.visionMask == 0) {
node.removeInner(region.id);
visionPending.insertLast(region);
visionPendingOp.insertLast(true);
}
}
return 1.0;
}
for(uint i = 0, cnt = visionPending.length; i < cnt; ++i) {
Region@ region = visionPending[i];
if(obj.owner is playerEmpire || region.VisionMask & playerEmpire.visionMask != 0) {
if(visionPendingOp[i])
node.addInner(region.id, region.position, region.radius);
else
node.removeInner(region.id);
visionPending.removeAt(i);
visionPendingOp.removeAt(i);
--i; --cnt;
}
}
return 1.0;
}
bool canTradeTo(Region@ region) const {
return inner.contains(region.id) || edges.contains(region.id);
}
uint getRegionCount() const {
return regions.length;
}
Region@ getRegion(uint i) const {
if(i >= regions.length)
return null;
return regions[i];
}
void _readRegions(Territory& obj, Message& msg) {
uint cnt = 0;
msg >> cnt;
set_int newSet;
for(uint i = 0; i < cnt; ++i) {
Region@ region = cast<Region>(msg.readObject());
newSet.insert(region.id);
//Add new regions
if(!inner.contains(region.id))
add(obj, region);
//TODO: Check if this could ever result in
//an out-of-order delta putting a region
//in the wrong territory.
region.setTerritory(obj.owner, obj);
}
//Remove old regions
for(uint i = 0, ocnt = regions.length; i < ocnt; ++i) {
Region@ region = regions[i];
if(!newSet.contains(region.id)) {
remove(obj, region);
region.clearTerritory(obj.owner, obj);
--i; --ocnt;
}
}
}
void destroy(Territory& obj) {
node.markForDeletion();
@node = null;
}
void syncInitial(Territory& obj, Message& msg) {
@node = TerritoryNode();
node.setOwner(obj.owner);
_readRegions(obj, msg);
}
void syncDetailed(Territory& obj, Message& msg, double tDiff) {
_readRegions(obj, msg);
}
void syncDelta(Territory& obj, Message& msg, double tDiff) {
if(msg.readBit())
_readRegions(obj, msg);
}
void add(Territory& obj, Region@ region) {
if(obj.owner is playerEmpire || region.VisionMask & playerEmpire.visionMask != 0) {
node.addInner(region.id, region.position, region.radius);
}
else {
visionPending.insertLast(region);
visionPendingOp.insertLast(true);
}
inner.insert(region.id);
regions.insertLast(region);
if(edges.contains(region.id)) {
node.removeEdge(region.id);
edges.erase(region.id);
}
//Add edges from this region
SystemDesc@ desc = getSystem(region.SystemId);
for(uint i = 0, cnt = desc.adjacent.length; i < cnt; ++i) {
uint adj = desc.adjacent[i];
SystemDesc@ other = getSystem(adj);
if(inner.contains(other.object.id))
continue;
if(edges.contains(other.object.id))
continue;
edges.insert(other.object.id);
node.addEdge(other.object.id, other.position, other.radius);
}
}
void remove(Territory& obj, Region@ region) {
if(obj.owner is playerEmpire || region.VisionMask & playerEmpire.visionMask != 0) {
node.removeInner(region.id);
}
else {
visionPending.insertLast(region);
visionPendingOp.insertLast(false);
}
inner.erase(region.id);
regions.remove(region);
//Remove edges from this region
SystemDesc@ desc = getSystem(region.SystemId);
bool isEdge = false;
for(uint i = 0, cnt = desc.adjacent.length; i < cnt; ++i) {
uint adj = desc.adjacent[i];
SystemDesc@ other = getSystem(adj);
if(inner.contains(other.object.id))
isEdge = true;
if(!edges.contains(other.object.id))
continue;
bool found = false;
for(uint j = 0, jcnt = other.adjacent.length; j < jcnt; ++j) {
SystemDesc@ chk = getSystem(other.adjacent[j]);
if(inner.contains(chk.object.id)) {
found = true;
break;
}
}
if(!found) {
edges.erase(other.object.id);
node.removeEdge(other.object.id);
}
}
//Check if this should be added back as an edge
if(isEdge) {
edges.insert(region.id);
node.addEdge(region.id, region.position, region.radius);
}
}
};