265 lines
6.3 KiB
ActionScript
265 lines
6.3 KiB
ActionScript
import artifacts;
|
|
import regions.regions;
|
|
import saving;
|
|
import systems;
|
|
import object_creation;
|
|
import statuses;
|
|
from artifact_seeding import ArtifactCount;
|
|
from empire import Creeps;
|
|
|
|
Artifact@ createArtifact(const vec3d& position, const ArtifactType@ type, Region@ region = null) {
|
|
if(type is null)
|
|
return null;
|
|
ObjectDesc desc;
|
|
desc.type = OT_Artifact;
|
|
desc.radius = type.physicalSize;
|
|
desc.position = position;
|
|
desc.name = type.name;
|
|
desc.delayedCreation = true;
|
|
desc.flags |= objNoDamage;
|
|
|
|
Artifact@ obj = Artifact(desc);
|
|
obj.ArtifactType = type.id;
|
|
if(region !is null)
|
|
@obj.region = region;
|
|
obj.finalizeCreation();
|
|
if(region !is null)
|
|
region.enterRegion(obj);
|
|
return obj;
|
|
}
|
|
|
|
tidy class ArtifactScript {
|
|
const ArtifactType@ type;
|
|
StrategicIconNode@ icon;
|
|
uint regMask = 0;
|
|
double deepSpaceTime = 0;
|
|
double expire = -1.0;
|
|
|
|
void postInit(Artifact& obj) {
|
|
@type = getArtifactType(obj.ArtifactType);
|
|
if(type is null) {
|
|
error("Invalid artifact created...");
|
|
printTrace();
|
|
obj.destroy();
|
|
return;
|
|
}
|
|
|
|
obj.setNeutralAbilities(true);
|
|
obj.setAbilityDestroy(type.singleUse);
|
|
for(uint i = 0, cnt = type.abilities.length; i < cnt; ++i)
|
|
obj.createAbility(type.abilities[i].id);
|
|
|
|
if(type.orbit && obj.region !is null)
|
|
obj.orbitAround(obj.region.position);
|
|
|
|
makeMesh(obj);
|
|
ArtifactCount += 1;
|
|
}
|
|
|
|
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) {
|
|
if(!obj.region.initialized)
|
|
@obj.region = null;
|
|
else
|
|
obj.region.addStrategicIcon(-1, obj, icon);
|
|
|
|
if(obj.region !is null) {
|
|
Node@ node = obj.getNode();
|
|
node.hintParentObject(obj.region, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void destroy(Artifact& obj) {
|
|
if(icon !is null) {
|
|
if(obj.region !is null)
|
|
obj.region.removeStrategicIcon(-1, icon);
|
|
icon.markForDeletion();
|
|
@icon = null;
|
|
}
|
|
leaveRegion(obj);
|
|
ArtifactCount -= 1;
|
|
|
|
for(uint i = 0, cnt = getEmpireCount(); i < cnt; ++i) {
|
|
Empire@ other = getEmpire(i);
|
|
if(!other.major)
|
|
continue;
|
|
if(regMask & other.mask != 0) {
|
|
regMask &= ~other.mask;
|
|
other.unregisterArtifact(obj);
|
|
}
|
|
}
|
|
}
|
|
|
|
void setExpire(double time) {
|
|
expire = time;
|
|
}
|
|
|
|
bool onOwnerChange(Artifact& obj, Empire@ prevOwner) {
|
|
regionOwnerChange(obj, prevOwner);
|
|
if(obj.owner !is null && obj.owner.valid)
|
|
obj.setNeutralAbilities(false);
|
|
else
|
|
obj.setNeutralAbilities(true);
|
|
return false;
|
|
}
|
|
|
|
double tick(Artifact& obj, double time) {
|
|
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;
|
|
|
|
Node@ node = obj.getNode();
|
|
if(node !is null)
|
|
node.hintParentObject(newRegion, false);
|
|
}
|
|
|
|
if(obj.region is null) {
|
|
deepSpaceTime += time;
|
|
if(deepSpaceTime > 14.0 * 60.0) {
|
|
deepSpaceTime = randomd(-30.0,30.0);
|
|
|
|
Ship@ ship = createShip(obj.position + random3d(4000.0),
|
|
Creeps.getDesign("Gravitar"), Creeps, free = true);
|
|
ship.addAbilityOrder(0, obj, obj.radius + ship.radius + 5.0, append=true);
|
|
auto@ reg = findNearestRegion(obj.position);
|
|
ship.addMoveOrder(reg.position + (obj.position - reg.position).normalize(reg.radius * 0.8) + random3d(10.0), append=true);
|
|
ship.addAbilityOrder(0, ship, obj.radius + ship.radius + 5.0, append=true);
|
|
ship.addMoveOrder(obj.position + random3d(10.0), append=true);
|
|
ship.addStatus(getStatusID("GravitarShip"));
|
|
}
|
|
}
|
|
else if(deepSpaceTime > 0.0) {
|
|
deepSpaceTime -= time * 0.5;
|
|
}
|
|
|
|
if(expire > 0) {
|
|
expire -= time;
|
|
if(expire <= 0.001)
|
|
obj.destroy();
|
|
}
|
|
|
|
if(prevRegion is null && isOutsideUniverseExtents(obj.position))
|
|
limitToUniverseExtents(obj.position);
|
|
|
|
Empire@ owner = obj.owner;
|
|
if(owner !is null && owner.valid && !type.canOwn)
|
|
@obj.owner = defaultEmpire;
|
|
for(uint i = 0, cnt = getEmpireCount(); i < cnt; ++i) {
|
|
Empire@ other = getEmpire(i);
|
|
if(!other.major)
|
|
continue;
|
|
|
|
bool usable = false;
|
|
if(owner !is null && owner.valid && owner !is other) {
|
|
usable = false;
|
|
}
|
|
else if(prevRegion !is null) {
|
|
if(prevRegion.PlanetsMask != 0) {
|
|
usable = prevRegion.PlanetsMask & other.mask != 0;
|
|
}
|
|
else {
|
|
usable = hasPlanetsAdjacent(other, prevRegion)
|
|
&& obj.memoryMask & other.mask != 0;
|
|
}
|
|
}
|
|
if(usable) {
|
|
if(regMask & other.mask == 0) {
|
|
regMask |= other.mask;
|
|
other.registerArtifact(obj);
|
|
}
|
|
}
|
|
else {
|
|
if(regMask & other.mask != 0) {
|
|
regMask &= ~other.mask;
|
|
other.unregisterArtifact(obj);
|
|
}
|
|
}
|
|
}
|
|
|
|
icon.visible = obj.isVisibleTo(playerEmpire);
|
|
obj.abilityTick(time);
|
|
obj.orbitTick(time);
|
|
return 0.5;
|
|
}
|
|
|
|
vec3d get_strategicIconPosition(Artifact& obj) {
|
|
if(icon is null)
|
|
return obj.position;
|
|
return icon.position;
|
|
}
|
|
|
|
void load(Artifact& obj, SaveFile& file) {
|
|
loadObjectStates(obj, file);
|
|
@type = getArtifactType(file.readIdentifier(SI_Artifact));
|
|
obj.ArtifactType = type.id;
|
|
file >> cast<Savable>(obj.Abilities);
|
|
file >> cast<Savable>(obj.Orbit);
|
|
if(file >= SV_0029)
|
|
file >> regMask;
|
|
if(file >= SV_0121)
|
|
file >> expire;
|
|
}
|
|
|
|
void postLoad(Artifact& obj) {
|
|
makeMesh(obj);
|
|
}
|
|
|
|
void save(Artifact& obj, SaveFile& file) {
|
|
saveObjectStates(obj, file);
|
|
file.writeIdentifier(SI_Artifact, type.id);
|
|
file << cast<Savable>(obj.Abilities);
|
|
file << cast<Savable>(obj.Orbit);
|
|
file << regMask;
|
|
file << expire;
|
|
}
|
|
|
|
void syncInitial(const Artifact& obj, Message& msg) {
|
|
msg.writeSmall(type.id);
|
|
obj.writeOrbit(msg);
|
|
obj.writeAbilities(msg);
|
|
}
|
|
|
|
bool syncDelta(const Artifact& obj, Message& msg) {
|
|
bool used = false;
|
|
if(obj.writeAbilityDelta(msg))
|
|
used = true;
|
|
else
|
|
msg.write0();
|
|
if(obj.writeOrbitDelta(msg))
|
|
used = true;
|
|
else
|
|
msg.write0();
|
|
|
|
return used;
|
|
}
|
|
|
|
void syncDetailed(const Artifact& obj, Message& msg) {
|
|
obj.writeOrbit(msg);
|
|
obj.writeAbilities(msg);
|
|
}
|
|
};
|