379 lines
10 KiB
ActionScript
379 lines
10 KiB
ActionScript
#section server-side
|
|
from regions.regions import getRegion;
|
|
#section all
|
|
import orbitals;
|
|
|
|
const double HYPERDRIVE_COST = 0.08;
|
|
const double HYPERDRIVE_START_COST = 25.0;
|
|
const double HYPERDRIVE_CHARGE_TIME = 15.0;
|
|
|
|
bool canHyperdrive(Object& obj) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
if(ship is null || !ship.hasLeaderAI)
|
|
return false;
|
|
if(isFTLBlocked(ship))
|
|
return false;
|
|
return ship.blueprint.hasTagActive(ST_Hyperdrive);
|
|
}
|
|
|
|
double hyperdriveSpeed(Object& obj) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
return ship.blueprint.getEfficiencySum(SV_HyperdriveSpeed);
|
|
}
|
|
|
|
double hyperdriveMaxSpeed(Object& obj) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
return ship.blueprint.design.total(SV_HyperdriveSpeed);
|
|
}
|
|
|
|
int hyperdriveCost(Object& obj, const vec3d& position) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
if(ship is null)
|
|
return 0;
|
|
auto@ dsg = ship.blueprint.design;
|
|
Region@ reg = obj.region;
|
|
Empire@ owner = obj.owner;
|
|
if(reg !is null && owner !is null && reg.FreeFTLMask & owner.mask != 0)
|
|
return 0;
|
|
return ceil(log(dsg.size) * (dsg.total(HV_Mass)*0.5/dsg.size) * sqrt(position.distanceTo(obj.position)) * HYPERDRIVE_COST + HYPERDRIVE_START_COST + owner.HyperdriveStartCostMod) * owner.FTLCostFactor;
|
|
}
|
|
|
|
int hyperdriveCost(array<Object@>& objects, const vec3d& destination) {
|
|
int cost = 0;
|
|
for(uint i = 0, cnt = objects.length; i < cnt; ++i) {
|
|
if(!canHyperdrive(objects[i]))
|
|
continue;
|
|
cost += hyperdriveCost(objects[i], destination);
|
|
}
|
|
return cost;
|
|
}
|
|
|
|
double hyperdriveRange(Object& obj) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
if(ship is null)
|
|
return 0.0;
|
|
int scale = ship.blueprint.design.size;
|
|
return hyperdriveRange(obj, scale, playerEmpire.FTLStored);
|
|
}
|
|
|
|
double hyperdriveRange(Object& obj, int scale, int stored) {
|
|
Region@ reg = obj.region;
|
|
Empire@ owner = obj.owner;
|
|
if(reg !is null && owner !is null && reg.FreeFTLMask & owner.mask != 0)
|
|
return INFINITY;
|
|
return sqr(max(double(stored) - (HYPERDRIVE_START_COST - owner.HyperdriveStartCostMod) * owner.FTLCostFactor, 0.0) / (log(double(scale)) * HYPERDRIVE_COST * owner.FTLCostFactor));
|
|
}
|
|
|
|
bool canHyperdriveTo(Object& obj, const vec3d& pos) {
|
|
return !isFTLBlocked(obj, pos);
|
|
}
|
|
|
|
const double FLING_BEACON_RANGE = 12500.0;
|
|
const double FLING_BEACON_RANGE_SQ = sqr(FLING_BEACON_RANGE);
|
|
const double FLING_COST = 8.0;
|
|
const double FLING_CHARGE_TIME = 15.0;
|
|
const double FLING_TIME = 15.0;
|
|
|
|
bool canFling(Object& obj) {
|
|
if(isFTLBlocked(obj))
|
|
return false;
|
|
if(!obj.hasLeaderAI)
|
|
return false;
|
|
if(obj.isShip) {
|
|
return true;
|
|
}
|
|
else {
|
|
if(obj.isOrbital) {
|
|
if(obj.owner.isFlingBeacon(obj))
|
|
return false;
|
|
Orbital@ orb = cast<Orbital>(obj);
|
|
auto@ core = getOrbitalModule(orb.coreModule);
|
|
return core is null || core.canFling;
|
|
}
|
|
if(obj.isPlanet)
|
|
return true;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool canFlingTo(Object& obj, const vec3d& pos) {
|
|
return !isFTLBlocked(obj, pos);
|
|
}
|
|
|
|
double flingSpeed(Object& obj, const vec3d& pos) {
|
|
return obj.position.distanceTo(pos) / FLING_TIME;
|
|
}
|
|
|
|
int flingCost(Object& obj, vec3d position) {
|
|
Region@ reg = obj.region;
|
|
Empire@ owner = obj.owner;
|
|
if(reg !is null && owner !is null && reg.FreeFTLMask & owner.mask != 0)
|
|
return 0;
|
|
if(obj.isShip) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
auto@ dsg = ship.blueprint.design;
|
|
int scale = dsg.size;
|
|
double massFactor = dsg.total(HV_Mass) * 0.3/dsg.size;
|
|
|
|
double scaleFactor;
|
|
if(dsg.hasTag(ST_Station))
|
|
scaleFactor = pow(double(scale), 0.75);
|
|
else
|
|
scaleFactor = sqrt(double(scale));
|
|
|
|
return ceil(FLING_COST * scaleFactor * massFactor * owner.FTLCostFactor);
|
|
}
|
|
else {
|
|
if(obj.isOrbital)
|
|
return ceil(FLING_COST * obj.radius * 3.0 * owner.FTLCostFactor);
|
|
else if(obj.isPlanet)
|
|
return ceil(FLING_COST * obj.radius * 30.0 * owner.FTLCostFactor);
|
|
return INFINITY;
|
|
}
|
|
}
|
|
|
|
int flingCost(array<Object@>& objects, const vec3d& destination) {
|
|
int cost = 0;
|
|
for(uint i = 0, cnt = objects.length; i < cnt; ++i)
|
|
cost += flingCost(objects[i], destination);
|
|
return cost;
|
|
}
|
|
|
|
double flingRange(Object& obj) {
|
|
if(flingCost(obj, obj.position) > obj.owner.FTLStored)
|
|
return 0.0;
|
|
return INFINITY;
|
|
}
|
|
|
|
const double SLIPSTREAM_CHARGE_TIME = 15.0;
|
|
const double SLIPSTREAM_LIFETIME = 10.0 * 60.0;
|
|
|
|
bool canSlipstream(Object& obj) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
if(ship is null || !ship.hasLeaderAI)
|
|
return false;
|
|
if(isFTLBlocked(ship))
|
|
return false;
|
|
return ship.blueprint.hasTagActive(ST_Slipstream);
|
|
}
|
|
|
|
int slipstreamCost(Object& obj, int scale, double distance) {
|
|
Region@ reg = obj.region;
|
|
Empire@ owner = obj.owner;
|
|
if(reg !is null && owner !is null && reg.FreeFTLMask & owner.mask != 0)
|
|
return 0;
|
|
Ship@ ship = cast<Ship>(obj);
|
|
double baseCost = ship.blueprint.design.total(SV_SlipstreamCost);
|
|
double optDist = ship.blueprint.design.total(SV_SlipstreamOptimalDistance);
|
|
if(distance < optDist)
|
|
return baseCost * obj.owner.FTLCostFactor;
|
|
return baseCost * ceil(distance / optDist) * obj.owner.FTLCostFactor;
|
|
}
|
|
|
|
double slipstreamRange(Object& obj, int scale, int stored) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
|
|
Region@ reg = obj.region;
|
|
Empire@ owner = obj.owner;
|
|
if(reg !is null && owner !is null && reg.FreeFTLMask & owner.mask != 0)
|
|
return INFINITY;
|
|
|
|
double baseCost = ship.blueprint.design.total(SV_SlipstreamCost);
|
|
double optDist = ship.blueprint.design.total(SV_SlipstreamOptimalDistance);
|
|
|
|
if(stored < baseCost)
|
|
return 0.0;
|
|
return floor(double(stored) / baseCost / obj.owner.FTLCostFactor) * optDist;
|
|
}
|
|
|
|
double slipstreamLifetime(Object& obj) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
return ship.blueprint.getEfficiencyFactor(SV_SlipstreamDuration) * ship.blueprint.design.total(SV_SlipstreamDuration);
|
|
}
|
|
|
|
void slipstreamModifyPosition(Object& obj, vec3d& position) {
|
|
double radius = slipstreamInaccuracy(obj, position);
|
|
|
|
vec2d offset = random2d(radius);
|
|
position += vec3d(offset.x, randomd(-radius * 0.2, radius * 0.2), offset.y);
|
|
}
|
|
|
|
double slipstreamInaccuracy(Object& obj, const vec3d& position) {
|
|
double dist = obj.position.distanceTo(position);
|
|
return dist * 0.01;
|
|
}
|
|
|
|
bool canSlipstreamTo(Object& obj, const vec3d& point) {
|
|
auto@ reg = obj.region;
|
|
if(reg !is null) {
|
|
if(reg.BlockFTLMask & obj.owner.mask != 0)
|
|
return false;
|
|
}
|
|
@reg = getRegion(point);
|
|
if(reg !is null) {
|
|
if(reg.BlockFTLMask & obj.owner.mask != 0)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool isFTLBlocked(Object& obj, const vec3d& point) {
|
|
auto@ reg = getRegion(point);
|
|
if(reg is null)
|
|
return false;
|
|
if(reg.BlockFTLMask & obj.owner.mask != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool isFTLBlocked(Object& obj) {
|
|
auto@ reg = obj.region;
|
|
if(reg is null)
|
|
return false;
|
|
if(reg.BlockFTLMask & obj.owner.mask != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
const double JUMPDRIVE_COST = 0.06;
|
|
const double JUMPDRIVE_START_COST = 50.0;
|
|
const double JUMPDRIVE_CHARGE_TIME = 25.0;
|
|
|
|
bool canJumpdrive(Object& obj) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
if(ship is null || !ship.hasLeaderAI)
|
|
return false;
|
|
if(isFTLBlocked(ship))
|
|
return false;
|
|
return ship.blueprint.hasTagActive(ST_Jumpdrive);
|
|
}
|
|
|
|
int jumpdriveCost(Object& obj, const vec3d& fromPos, const vec3d& position) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
if(ship is null)
|
|
return 0;
|
|
auto@ dsg = ship.blueprint.design;
|
|
Region@ reg = obj.region;
|
|
Empire@ owner = obj.owner;
|
|
if(reg !is null && owner !is null && reg.FreeFTLMask & owner.mask != 0)
|
|
return 0;
|
|
double dist = position.distanceTo(fromPos);
|
|
dist = min(dist, jumpdriveRange(obj));
|
|
|
|
return ceil(log(dsg.size) * (dsg.total(HV_Mass)*0.5/dsg.size) * sqrt(dist) * JUMPDRIVE_COST + JUMPDRIVE_START_COST) * owner.FTLCostFactor;
|
|
}
|
|
|
|
int jumpdriveCost(Object& obj, const vec3d& position) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
if(ship is null)
|
|
return 0;
|
|
auto@ dsg = ship.blueprint.design;
|
|
Region@ reg = obj.region;
|
|
Empire@ owner = obj.owner;
|
|
if(reg !is null && owner !is null && reg.FreeFTLMask & owner.mask != 0)
|
|
return 0;
|
|
double dist = position.distanceTo(obj.position);
|
|
dist = min(dist, jumpdriveRange(obj));
|
|
|
|
return ceil(log(dsg.size) * (dsg.total(HV_Mass)*0.5/dsg.size) * sqrt(dist) * JUMPDRIVE_COST + JUMPDRIVE_START_COST) * owner.FTLCostFactor;
|
|
}
|
|
|
|
int jumpdriveCost(array<Object@>& objects, const vec3d& destination) {
|
|
int cost = 0;
|
|
for(uint i = 0, cnt = objects.length; i < cnt; ++i) {
|
|
if(!canHyperdrive(objects[i]))
|
|
continue;
|
|
cost += jumpdriveCost(objects[i], destination);
|
|
}
|
|
return cost;
|
|
}
|
|
|
|
double jumpdriveRange(Object& obj) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
return ship.blueprint.design.total(SV_JumpRange);
|
|
}
|
|
|
|
double jumpdriveRange(Object& obj, int scale, int stored) {
|
|
Ship@ ship = cast<Ship>(obj);
|
|
return ship.blueprint.design.total(SV_JumpRange);
|
|
}
|
|
|
|
bool canJumpdriveTo(Object& obj, const vec3d& pos) {
|
|
return !isFTLBlocked(obj, pos);
|
|
}
|
|
|
|
const double FLUX_CD_RANGE = 300.0;
|
|
|
|
bool canFluxTo(Object& obj, const vec3d& pos) {
|
|
if(obj.owner.HasFlux == 0)
|
|
return false;
|
|
|
|
auto@ reg = getRegion(pos);
|
|
auto@ curReg = obj.region;
|
|
|
|
if(curReg is null)
|
|
return false;
|
|
if(reg is null)
|
|
return false;
|
|
if(reg is curReg)
|
|
return false;
|
|
|
|
if(reg.VisionMask & obj.owner.mask == 0)
|
|
return false;
|
|
if(isFTLBlocked(obj) || isFTLBlocked(obj, pos))
|
|
return false;
|
|
if(obj.hasStatuses) {
|
|
if(obj.hasStatusEffect(fluxStatus))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
vec3d getFluxDest(Object& obj, const vec3d& pos) {
|
|
auto@ reg = getRegion(pos);
|
|
auto@ curReg = obj.region;
|
|
|
|
vec3d dir;
|
|
if(curReg !is null)
|
|
dir = (obj.position - curReg.position) / curReg.radius;
|
|
else
|
|
dir = random3d(0.6);
|
|
|
|
if(reg !is null)
|
|
return reg.position + (dir * reg.radius);
|
|
else
|
|
return pos;
|
|
}
|
|
|
|
from statuses import getStatusID;
|
|
int fluxStatus = -1;
|
|
void init() {
|
|
fluxStatus = getStatusID("FluxCooldown");
|
|
}
|
|
|
|
#section server-side
|
|
void commitFlux(Object& obj, const vec3d& pos) {
|
|
vec3d fluxPos = getFluxDest(obj, pos);
|
|
|
|
#section server
|
|
playParticleSystem("FluxJump", obj.position, obj.rotation, obj.radius * 4.0, obj.visibleMask);
|
|
playParticleSystem("FluxJump", fluxPos, obj.rotation, obj.radius * 4.0, obj.visibleMask);
|
|
#section server-side
|
|
|
|
if(obj.hasStatuses) {
|
|
double dist = fluxPos.distanceTo(obj.position);
|
|
double cd = dist / FLUX_CD_RANGE;
|
|
obj.addStatus(fluxStatus, timer=cd);
|
|
}
|
|
|
|
if(obj.hasLeaderAI) {
|
|
obj.teleportTo(fluxPos, movementPart=true);
|
|
}
|
|
else {
|
|
obj.position = fluxPos;
|
|
obj.velocity = vec3d();
|
|
obj.acceleration = vec3d();
|
|
}
|
|
}
|
|
#section all
|