Open source Star Ruler 2 source code!
This commit is contained in:
@@ -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);
|
||||
}
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -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];
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user