356 lines
7.3 KiB
ActionScript
356 lines
7.3 KiB
ActionScript
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);
|
|
}
|
|
};
|