Open source Star Ruler 2 source code!
This commit is contained in:
@@ -0,0 +1,355 @@
|
||||
import regions.regions;
|
||||
import saving;
|
||||
import oddity_navigation;
|
||||
import systems;
|
||||
import oddities;
|
||||
|
||||
void createSlipstream(const vec3d& from, const vec3d& to, double timer = -1.0, Empire@ revealEmp = null) {
|
||||
ObjectDesc desc;
|
||||
desc.type = OT_Oddity;
|
||||
desc.radius = 15.0;
|
||||
desc.position = from;
|
||||
desc.flags |= objNoPhysics;
|
||||
desc.flags |= objNoDamage;
|
||||
if(revealEmp !is null)
|
||||
@desc.owner = revealEmp;
|
||||
desc.name = locale::SLIPSTREAM_TEAR;
|
||||
|
||||
auto@ input = Oddity(desc);
|
||||
input.noCollide = true;
|
||||
|
||||
desc.position = to;
|
||||
auto@ output = Oddity(desc);
|
||||
output.noCollide = true;
|
||||
|
||||
input.linkTo(output);
|
||||
output.linkTo(input);
|
||||
|
||||
input.setGate(true);
|
||||
output.setGate(true);
|
||||
|
||||
input.setTimer(timer);
|
||||
output.setTimer(timer);
|
||||
|
||||
input.makeVisuals(Odd_Slipstream);
|
||||
output.makeVisuals(Odd_Slipstream);
|
||||
|
||||
input.linkVision(true);
|
||||
output.linkVision(true);
|
||||
}
|
||||
|
||||
void createWormhole(SystemDesc@ from, SystemDesc@ to) {
|
||||
vec3d fromPos = from.position;
|
||||
vec2d offset = random2d(100.0, from.radius - 100.0);
|
||||
fromPos.x += offset.x;
|
||||
fromPos.z += offset.y;
|
||||
|
||||
vec3d toPos = to.position;
|
||||
offset = random2d(100.0, to.radius - 100.0);
|
||||
toPos.x += offset.x;
|
||||
toPos.z += offset.y;
|
||||
|
||||
ObjectDesc desc;
|
||||
desc.type = OT_Oddity;
|
||||
desc.radius = 25.0;
|
||||
desc.position = fromPos;
|
||||
desc.flags |= objNoPhysics;
|
||||
desc.flags |= objNoDamage;
|
||||
desc.name = locale::WORMHOLE;
|
||||
|
||||
auto@ input = Oddity(desc);
|
||||
input.noCollide = true;
|
||||
|
||||
desc.position = toPos;
|
||||
auto@ output = Oddity(desc);
|
||||
output.noCollide = true;
|
||||
|
||||
input.linkTo(output);
|
||||
output.linkTo(input);
|
||||
|
||||
input.setGate(true);
|
||||
output.setGate(true);
|
||||
|
||||
input.makeVisuals(Odd_Wormhole);
|
||||
output.makeVisuals(Odd_Wormhole);
|
||||
|
||||
input.linkVision(true);
|
||||
output.linkVision(true);
|
||||
|
||||
input.setSuperior(true);
|
||||
output.setSuperior(true);
|
||||
}
|
||||
|
||||
Oddity@ createNebula(const vec3d& position, double radius, uint color = 0xf0c87040, Region@ region = null) {
|
||||
ObjectDesc desc;
|
||||
desc.type = OT_Oddity;
|
||||
desc.radius = radius;
|
||||
desc.position = position;
|
||||
desc.flags |= objNoPhysics;
|
||||
desc.flags |= objNoDamage;
|
||||
|
||||
auto@ nebula = Oddity(desc);
|
||||
if(region !is null) {
|
||||
@nebula.region = region;
|
||||
region.enterRegion(nebula);
|
||||
}
|
||||
nebula.noCollide = true;
|
||||
nebula.makeVisuals(Odd_Nebula, color=color);
|
||||
|
||||
return nebula;
|
||||
}
|
||||
|
||||
tidy class OddityScript {
|
||||
StrategicIconNode@ icon;
|
||||
bool gate = false;
|
||||
bool superior = false;
|
||||
double timer = -1.0;
|
||||
uint visualType = uint(-1);
|
||||
uint visualColor = 0xffffffff;
|
||||
Object@ link;
|
||||
|
||||
bool visionLinked = false;
|
||||
Region@ visionRegion;
|
||||
uint visionMask = 0;
|
||||
uint prevMemory = 0;
|
||||
|
||||
bool delta = false;
|
||||
|
||||
void save(Oddity& obj, SaveFile& file) {
|
||||
saveObjectStates(obj, file);
|
||||
file << gate;
|
||||
file << timer;
|
||||
file << visualType;
|
||||
file << link;
|
||||
file << visionLinked;
|
||||
file << visionRegion;
|
||||
file << visionMask;
|
||||
file << superior;
|
||||
file << prevMemory;
|
||||
file << visualColor;
|
||||
}
|
||||
|
||||
void load(Oddity& obj, SaveFile& file) {
|
||||
loadObjectStates(obj, file);
|
||||
file >> gate;
|
||||
file >> timer;
|
||||
file >> visualType;
|
||||
file >> link;
|
||||
file >> visionLinked;
|
||||
file >> visionRegion;
|
||||
file >> visionMask;
|
||||
if(file >= SV_0020)
|
||||
file >> superior;
|
||||
if(file >= SV_0067)
|
||||
file >> prevMemory;
|
||||
if(file >= SV_0099)
|
||||
file >> visualColor;
|
||||
|
||||
makeVisuals(obj, visualType, fromCreation=false, color=visualColor);
|
||||
if(gate)
|
||||
addOddityGate(obj);
|
||||
}
|
||||
|
||||
uint getVisualType() {
|
||||
return visualType;
|
||||
}
|
||||
|
||||
uint getVisualColor() {
|
||||
return visualColor;
|
||||
}
|
||||
|
||||
bool isGate() {
|
||||
return gate;
|
||||
}
|
||||
|
||||
vec3d getGateDest() {
|
||||
if(link !is null)
|
||||
return link.position;
|
||||
return vec3d();
|
||||
}
|
||||
|
||||
Object@ getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
double getTimer() {
|
||||
return timer;
|
||||
}
|
||||
|
||||
void setGate(Oddity& obj, bool value) {
|
||||
if(value == gate)
|
||||
return;
|
||||
gate = value;
|
||||
if(gate)
|
||||
addOddityGate(obj);
|
||||
else
|
||||
removeOddityGate(obj);
|
||||
delta = true;
|
||||
}
|
||||
|
||||
void linkVision(bool value) {
|
||||
visionLinked = value;
|
||||
delta = true;
|
||||
}
|
||||
|
||||
void linkTo(Oddity& obj, Object@ other) {
|
||||
@link = other;
|
||||
obj.rotation = quaterniond_fromVecToVec(vec3d_front(), (other.position - obj.position).normalized(), vec3d_up());
|
||||
delta = true;
|
||||
}
|
||||
|
||||
void setTimer(double value) {
|
||||
timer = value;
|
||||
delta = true;
|
||||
}
|
||||
|
||||
void setSuperior(bool value) {
|
||||
superior = value;
|
||||
}
|
||||
|
||||
vec3d get_strategicIconPosition(Oddity& obj) {
|
||||
if(icon is null)
|
||||
return obj.position;
|
||||
return icon.position;
|
||||
}
|
||||
|
||||
void makeVisuals(Oddity& obj, uint type, bool fromCreation = true, uint color = 0xffffffff) {
|
||||
visualType = type;
|
||||
visualColor = color;
|
||||
@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);
|
||||
updateVision(visionRegion, visionMask, 0);
|
||||
if(gate)
|
||||
removeOddityGate(obj);
|
||||
removeAmbientSource(CURRENT_PLAYER, obj.id);
|
||||
}
|
||||
|
||||
void updateVision(Region@ onRegion, uint fromMask, uint toMask) {
|
||||
if(onRegion is null)
|
||||
return;
|
||||
if(fromMask == toMask)
|
||||
return;
|
||||
|
||||
for(uint i = 0, cnt = getEmpireCount(); i < cnt; ++i) {
|
||||
Empire@ emp = getEmpire(i);
|
||||
if(fromMask & emp.mask != 0) {
|
||||
if(toMask & emp.mask == 0)
|
||||
onRegion.revokeVision(emp);
|
||||
}
|
||||
else {
|
||||
if(toMask & emp.mask != 0)
|
||||
onRegion.grantVision(emp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
updateVision(visionRegion, visionMask, 0);
|
||||
visionMask = 0;
|
||||
@visionRegion = null;
|
||||
@prevRegion = newRegion;
|
||||
}
|
||||
|
||||
if(icon !is null)
|
||||
icon.visible = obj.isVisibleTo(playerEmpire);
|
||||
|
||||
if(link !is null && !link.valid)
|
||||
@link = null;
|
||||
|
||||
//Handle vision sharing
|
||||
Region@ newRegion;
|
||||
uint newMask = 0;
|
||||
if(visionLinked && link !is null) {
|
||||
@newRegion = link.region;
|
||||
if(prevRegion is null)
|
||||
obj.donatedVision |= link.visibleMask;
|
||||
}
|
||||
if(prevRegion !is null)
|
||||
newMask = prevRegion.BasicVisionMask;
|
||||
|
||||
if(newRegion !is visionRegion) {
|
||||
updateVision(visionRegion, visionMask, 0);
|
||||
updateVision(newRegion, 0, newMask);
|
||||
@visionRegion = newRegion;
|
||||
visionMask = newMask;
|
||||
}
|
||||
else {
|
||||
updateVision(visionRegion, visionMask, newMask);
|
||||
visionMask = newMask;
|
||||
}
|
||||
|
||||
//Handle memories
|
||||
if(obj.memoryMask != prevMemory) {
|
||||
for(uint i = 0, cnt = getEmpireCount(); i < cnt; ++i) {
|
||||
auto@ emp = getEmpire(i);
|
||||
if((prevMemory & emp.mask) != (obj.memoryMask & emp.mask))
|
||||
emp.PathId += 1;
|
||||
}
|
||||
prevMemory = obj.memoryMask;
|
||||
}
|
||||
|
||||
//Kill the oddity gate if the region blocks ftl at all
|
||||
if(gate && !superior && prevRegion !is null) {
|
||||
if(prevRegion.BlockFTLMask.value & obj.owner.mask != 0) {
|
||||
if(link !is null)
|
||||
link.destroy();
|
||||
obj.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
//Handle timer
|
||||
if(timer >= 0.0) {
|
||||
timer -= time;
|
||||
if(timer <= 0.0)
|
||||
obj.destroy();
|
||||
}
|
||||
|
||||
return 0.25;
|
||||
}
|
||||
|
||||
void _write(const Oddity& obj, Message& msg) {
|
||||
msg << gate;
|
||||
msg << timer;
|
||||
msg << visualType;
|
||||
msg << visualColor;
|
||||
msg << link;
|
||||
}
|
||||
|
||||
void syncInitial(const Oddity& obj, Message& msg) {
|
||||
_write(obj, msg);
|
||||
}
|
||||
|
||||
bool syncDelta(const Oddity& obj, Message& msg) {
|
||||
bool used = false;
|
||||
if(delta) {
|
||||
used = true;
|
||||
delta = false;
|
||||
msg.write1();
|
||||
_write(obj, msg);
|
||||
}
|
||||
else
|
||||
msg.write0();
|
||||
return used;
|
||||
}
|
||||
|
||||
void syncDetailed(const Oddity& obj, Message& msg) {
|
||||
_write(obj, msg);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user