Open source Star Ruler 2 source code!
This commit is contained in:
@@ -0,0 +1,600 @@
|
||||
import resources;
|
||||
import systems;
|
||||
import planet_levels;
|
||||
from resources import _tempResource;
|
||||
|
||||
tidy class ObjectResources : Component_Resources {
|
||||
TradePath@[] resourcePaths;
|
||||
Object@[] pathsActive;
|
||||
Resource[] nativeResources;
|
||||
Resource primaryResource;
|
||||
Resource[] resources;
|
||||
QueuedImport[] queuedImports;
|
||||
Resources availableResources;
|
||||
array<QueuedResource@> queuedExports;
|
||||
|
||||
int ExportDisabled = 0;
|
||||
int ImportDisabled = 0;
|
||||
uint ResourceModId = 0;
|
||||
bool terraforming = false;
|
||||
double resVanishBonus = 0.0;
|
||||
|
||||
ObjectResources() {
|
||||
}
|
||||
|
||||
bool isTerraforming() {
|
||||
return terraforming;
|
||||
}
|
||||
|
||||
void getNativeResources(Player& pl, const Object& obj) {
|
||||
Empire@ plEmp = pl.emp;
|
||||
if(plEmp is obj.owner || pl == SERVER_PLAYER) {
|
||||
for(uint i = 0, cnt = nativeResources.length; i < cnt; ++i)
|
||||
yield(nativeResources[i]);
|
||||
}
|
||||
else {
|
||||
Resource@ res = _tempResource();
|
||||
for(uint i = 0, cnt = nativeResources.length; i < cnt; ++i) {
|
||||
res = nativeResources[i];
|
||||
@res.exportedTo = null;
|
||||
|
||||
if(queuedExports !is null) {
|
||||
for(uint n = 0, ncnt = queuedExports.length; n < ncnt; ++n) {
|
||||
QueuedResource@ q = queuedExports[n];
|
||||
if(q.forEmpire is plEmp && res.id == q.id)
|
||||
@res.exportedTo = q.to;
|
||||
}
|
||||
}
|
||||
|
||||
yield(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint get_nativeResourceCount() {
|
||||
return nativeResources.length;
|
||||
}
|
||||
|
||||
uint get_nativeResourceType(uint i) {
|
||||
if(i >= nativeResources.length)
|
||||
return uint(-1);
|
||||
return nativeResources[i].type.id;
|
||||
}
|
||||
|
||||
int get_nativeResourceId(uint i) {
|
||||
if(i >= nativeResources.length)
|
||||
return -1;
|
||||
return nativeResources[i].id;
|
||||
}
|
||||
|
||||
uint get_nativeResourceTotalLevel() const {
|
||||
uint level = 0;
|
||||
for(uint i = 0, cnt = nativeResources.length; i < cnt; ++i)
|
||||
level += nativeResources[i].type.level;
|
||||
return level;
|
||||
}
|
||||
|
||||
bool get_nativeResourceUsable(uint i) {
|
||||
if(i >= nativeResources.length)
|
||||
return false;
|
||||
return nativeResources[i].usable;
|
||||
}
|
||||
|
||||
uint get_primaryResourceType() const {
|
||||
if(primaryResource.type is null)
|
||||
return uint(-1);
|
||||
return primaryResource.type.id;
|
||||
}
|
||||
|
||||
uint get_primaryResourceLevel() const {
|
||||
if(primaryResource.type is null)
|
||||
return 0;
|
||||
return primaryResource.type.level;
|
||||
}
|
||||
|
||||
uint get_primaryResourceLimitLevel(const Object& obj) const {
|
||||
if(primaryResource.type is null)
|
||||
return 0;
|
||||
if(primaryResource.type.limitlessLevel)
|
||||
return getMaxPlanetLevel(obj.levelChain);
|
||||
return primaryResource.type.level;
|
||||
}
|
||||
|
||||
int get_primaryResourceId() const {
|
||||
return primaryResource.id;
|
||||
}
|
||||
|
||||
bool get_primaryResourceUsable() const {
|
||||
return primaryResource.usable;
|
||||
}
|
||||
|
||||
bool get_primaryResourceLocked() const {
|
||||
return primaryResource.locked;
|
||||
}
|
||||
|
||||
bool get_primaryResourceExported() const {
|
||||
return primaryResource.exportedTo !is null;
|
||||
}
|
||||
|
||||
bool get_nativeResourceLocked(Player& pl, Object& obj, uint i) {
|
||||
Empire@ forEmp = pl.emp;
|
||||
if(pl == SERVER_PLAYER)
|
||||
@forEmp = obj.owner;
|
||||
if(i >= nativeResources.length)
|
||||
return false;
|
||||
auto@ r = nativeResources[i];
|
||||
if(forEmp is obj.owner)
|
||||
return r.locked;
|
||||
for(uint i = 0, cnt = queuedExports.length; i < cnt; ++i) {
|
||||
QueuedResource@ q = queuedExports[i];
|
||||
if(q.forEmpire is forEmp && r.id == q.id)
|
||||
return q.locked;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
float get_resourceVanishRate() const {
|
||||
return 1.f / (1.f + resVanishBonus);
|
||||
}
|
||||
|
||||
uint getTradedResourceCount() const {
|
||||
uint tradedNative = 0;
|
||||
uint usableNative = 0;
|
||||
for(uint i = 0, cnt = nativeResources.length; i < cnt; ++i) {
|
||||
if(!nativeResources[i].usable)
|
||||
continue;
|
||||
++usableNative;
|
||||
if(nativeResources[i].exportedTo !is null)
|
||||
++tradedNative;
|
||||
}
|
||||
|
||||
return (resources.length - (usableNative - tradedNative)) + tradedNative;
|
||||
}
|
||||
|
||||
Object@ get_nativeResourceDestination(Player& pl, const Object& obj, uint i) {
|
||||
if(i >= nativeResources.length)
|
||||
return null;
|
||||
Empire@ emp = pl.emp;
|
||||
Resource@ r = nativeResources[i];
|
||||
|
||||
//Find the current export
|
||||
if(r.exportedTo !is null && (emp is obj.owner || pl == SERVER_PLAYER))
|
||||
return r.exportedTo;
|
||||
|
||||
//Try to find a queued export
|
||||
for(uint i = 0, cnt = queuedExports.length; i < cnt; ++i) {
|
||||
QueuedResource@ q = queuedExports[i];
|
||||
if(q.forEmpire is emp && r.id == q.id)
|
||||
return q.to;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Object@ getNativeResourceDestination(const Object& obj, Empire@ emp, uint i) {
|
||||
if(i >= nativeResources.length)
|
||||
return null;
|
||||
Resource@ r = nativeResources[i];
|
||||
|
||||
//Find the current export
|
||||
if(r.exportedTo !is null && emp is obj.owner)
|
||||
return nativeResources[i].exportedTo;
|
||||
|
||||
//Try to find a queued export
|
||||
for(uint i = 0, cnt = queuedExports.length; i < cnt; ++i) {
|
||||
QueuedResource@ q = queuedExports[i];
|
||||
if(q.forEmpire is emp && r.id == q.id)
|
||||
return q.to;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
uint getNativeIndex(int id) {
|
||||
for(uint i = 0, cnt = nativeResources.length; i < cnt; ++i) {
|
||||
if(nativeResources[i].id == id)
|
||||
return i;
|
||||
}
|
||||
return uint(-1);
|
||||
}
|
||||
|
||||
string getDisabledReason(Object& obj, int id) {
|
||||
uint index = getNativeIndex(id);
|
||||
if(index >= nativeResources.length)
|
||||
return "Not present";
|
||||
auto@ r = nativeResources[index];
|
||||
if(!r.type.exportable)
|
||||
return "";
|
||||
auto@ to = r.exportedTo;
|
||||
if(ExportDisabled != 0)
|
||||
return locale::EXPBLOCK_DISABLED;
|
||||
if((to !is null && to.region is null) || obj.region is null)
|
||||
return locale::EXPBLOCK_DEEPSPACE;
|
||||
if(!obj.owner.valid) {
|
||||
if(obj.isAsteroid)
|
||||
return locale::EXPBLOCK_UNMINED;
|
||||
else if(obj.isPlanet)
|
||||
return locale::EXPBLOCK_UNCOLONIZED;
|
||||
else
|
||||
return locale::EXPBLOCK_UNOWNED;
|
||||
}
|
||||
if(to !is null && obj.owner !is to.owner)
|
||||
return locale::EXPBLOCK_UNOWNED;
|
||||
if(obj.hasSurfaceComponent) {
|
||||
if(obj.population < 1.0)
|
||||
return format(locale::EXPBLOCK_POP, uint(1));
|
||||
else if(obj.resourceLevel < r.type.level)
|
||||
return format(locale::EXPBLOCK_LOWLEVEL, r.type.level);
|
||||
else if(obj.population < getPlanetLevelRequiredPop(obj, r.type.level))
|
||||
return format(locale::EXPBLOCK_POP, uint(getPlanetLevelRequiredPop(obj, r.type.level)));
|
||||
}
|
||||
if(to !is null) {
|
||||
//NOTE: Approximation of trade rules
|
||||
auto@ src = obj.region;
|
||||
auto@ dst = to.region;
|
||||
if(src !is null && dst !is null && src !is dst &&
|
||||
src.getTerritory(obj.owner) !is dst.getTerritory(obj.owner))
|
||||
return locale::EXPBLOCK_DISCONNECTED;
|
||||
}
|
||||
if(!r.usable)
|
||||
return locale::EXPBLOCK_UNUSABLE;
|
||||
return "";
|
||||
}
|
||||
|
||||
void getAvailableResources() {
|
||||
for(uint i = 0, cnt = resources.length; i < cnt; ++i)
|
||||
yield(resources[i]);
|
||||
}
|
||||
|
||||
Object@ get_availableResourceOrigin(uint index) const {
|
||||
if(index >= resources.length)
|
||||
return null;
|
||||
return resources[index].origin;
|
||||
}
|
||||
|
||||
void getImportedResources(const Object& obj) {
|
||||
for(uint i = 0, cnt = resources.length; i < cnt; ++i)
|
||||
if(resources[i].origin is null || obj !is resources[i].origin)
|
||||
yield(resources[i]);
|
||||
}
|
||||
|
||||
bool get_hasAutoImports(Player& pl, Object& obj) {
|
||||
for(uint i = 0, cnt = queuedImports.length; i < cnt; ++i)
|
||||
if(queuedImports[i].origin is null && pl.emp is queuedImports[i].forEmpire)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void getAllResources(Player& pl, const Object& obj) {
|
||||
Empire@ emp = pl.emp;
|
||||
if(emp is obj.owner || pl == SERVER_PLAYER) {
|
||||
for(uint i = 0, cnt = nativeResources.length; i < cnt; ++i)
|
||||
yield(nativeResources[i]);
|
||||
for(uint i = 0, cnt = resources.length; i < cnt; ++i) {
|
||||
if(obj !is resources[i].origin)
|
||||
yield(resources[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(uint i = 0, cnt = nativeResources.length; i < cnt; ++i)
|
||||
yield(nativeResources[i]);
|
||||
}
|
||||
for(uint i = 0, cnt = queuedImports.length; i < cnt; ++i) {
|
||||
if(queuedImports[i].forEmpire is emp)
|
||||
yield(queuedImports[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void getQueuedImports(Player& pl, const Object& obj) {
|
||||
Empire@ emp = pl.emp;
|
||||
if(queuedImports !is null) {
|
||||
for(uint i = 0, cnt = queuedImports.length; i < cnt; ++i) {
|
||||
if(queuedImports[i].forEmpire is emp)
|
||||
yield(queuedImports[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint get_queuedImportCount() {
|
||||
return queuedImports.length;
|
||||
}
|
||||
|
||||
uint get_queuedImportType(Player& pl, Object& obj, uint i) {
|
||||
if(pl.emp !is queuedImports[i].forEmpire)
|
||||
return uint(-1);
|
||||
return queuedImports[i].type.id;
|
||||
}
|
||||
|
||||
Object@ get_queuedImportOrigin(Player& pl, Object& obj, uint i) {
|
||||
if(pl.emp !is queuedImports[i].forEmpire)
|
||||
return null;
|
||||
return queuedImports[i].origin;
|
||||
}
|
||||
|
||||
void getResourceAmounts() {
|
||||
yield(availableResources);
|
||||
}
|
||||
|
||||
bool hasImportedResources(const Object& obj) const {
|
||||
if(resources.length == 0)
|
||||
return false;
|
||||
for(uint i = 0, cnt = resources.length; i < cnt; ++i) {
|
||||
if(obj !is resources[i].origin)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint getImportsOfClass(Player& pl, const Object& obj, uint clsId) const {
|
||||
const ResourceClass@ cls = getResourceClass(clsId);
|
||||
if(cls is null)
|
||||
return 0;
|
||||
|
||||
uint count = 0;
|
||||
Empire@ emp = pl.emp;
|
||||
if(emp is obj.owner) {
|
||||
for(uint i = 0, cnt = resources.length; i < cnt; ++i) {
|
||||
if(resources[i].type.cls is cls)
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for(uint i = 0, cnt = queuedImports.length; i < cnt; ++i) {
|
||||
const QueuedImport@ imp = queuedImports[i];
|
||||
if(imp.forEmpire is emp && imp.type.cls is cls)
|
||||
count += 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool get_hasAutoImports(Player& pl, const Object& obj) {
|
||||
for(uint i = 0, cnt = queuedImports.length; i < cnt; ++i)
|
||||
if(queuedImports[i].origin is null && pl.emp is queuedImports[i].forEmpire)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint get_availableResourceCount() const {
|
||||
return resources.length;
|
||||
}
|
||||
|
||||
uint get_usableResourceCount() const {
|
||||
uint amt = 0;
|
||||
for(uint i = 0, cnt = resources.length; i < cnt; ++i) {
|
||||
if(resources[i].usable)
|
||||
amt += 1;
|
||||
}
|
||||
return amt;
|
||||
}
|
||||
|
||||
uint get_availableResourceType(uint index) const {
|
||||
if(index >= resources.length)
|
||||
return uint(-1);
|
||||
return resources[index].type.id;
|
||||
}
|
||||
|
||||
bool get_availableResourceUsable(uint index) const {
|
||||
if(index >= resources.length)
|
||||
return false;
|
||||
return resources[index].usable;
|
||||
}
|
||||
|
||||
bool isResourceAvailable(uint id) const {
|
||||
return availableResources.getAmount(getResource(id)) != 0;
|
||||
}
|
||||
|
||||
uint getAvailableResourceAmount(uint id) const {
|
||||
return availableResources.getAmount(getResource(id));
|
||||
}
|
||||
|
||||
Resource@ resourceFrom(Object@ from, int id) {
|
||||
for(uint i = 0, cnt = resources.length; i < cnt; ++i) {
|
||||
Resource@ r = resources[i];
|
||||
if(r.origin is from && r.id == id)
|
||||
return r;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void setAvailableResourceVanish(Object& obj, Object@ from, int id, double vanishTime) {
|
||||
Resource@ r = resourceFrom(from, id);
|
||||
if(r !is null)
|
||||
r.vanishTime = vanishTime;
|
||||
}
|
||||
|
||||
bool get_exportEnabled() {
|
||||
return ExportDisabled == 0;
|
||||
}
|
||||
|
||||
bool get_importEnabled() {
|
||||
return ImportDisabled == 0;
|
||||
}
|
||||
|
||||
void clearLines(Resource@ res, TradePath@ path, Object@ from, Object@ to) {
|
||||
uint cnt = path.pathSize;
|
||||
if(cnt == 1) {
|
||||
path.origin.object.removeTradePathing(-1, from, res.id);
|
||||
}
|
||||
else {
|
||||
for(uint i = 0; i < cnt-1; ++i) {
|
||||
SystemDesc@ node = path.pathNode[i];
|
||||
SystemDesc@ next = path.pathNode[i+1];;
|
||||
node.object.removeTradePathing(next.index, from, res.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateLines(Resource@ res, TradePath@ path, Object@ from, Object@ to) {
|
||||
uint cnt = path.pathSize;
|
||||
if(cnt == 1) {
|
||||
path.origin.object.addTradePathing(-1, from, to, res.id, res.type.id);
|
||||
}
|
||||
else {
|
||||
for(uint i = 0; i < cnt-1; ++i) {
|
||||
SystemDesc@ node = path.pathNode[i];
|
||||
SystemDesc@ next = path.pathNode[i+1];;
|
||||
node.object.addTradePathing(next.index, from, to, res.id, res.type.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void resourceTick(Object& obj, double time) {
|
||||
//Vanish any native resources
|
||||
for(uint i = 0, cnt = nativeResources.length; i < cnt; ++i) {
|
||||
Resource@ r = nativeResources[i];
|
||||
if(!r.usable || obj.owner is null || !obj.owner.valid)
|
||||
continue;
|
||||
switch(r.type.vanishMode) {
|
||||
case VM_WhenExported:
|
||||
if(r.exportedTo is null)
|
||||
continue;
|
||||
break;
|
||||
case VM_ExportedInCombat:
|
||||
if(r.exportedTo is null) {
|
||||
if(r.origin is null || !r.origin.inCombat)
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if(!r.exportedTo.inCombat)
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case VM_Always:
|
||||
break;
|
||||
case VM_Custom:
|
||||
if(!r.type.shouldVanish(obj, r))
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if(r.exportedTo !is null) {
|
||||
float rate = r.exportedTo.resourceVanishRate;
|
||||
r.vanishTime += time * rate;
|
||||
r.exportedTo.setAvailableResourceVanish(obj, r.id, r.vanishTime);
|
||||
}
|
||||
else {
|
||||
r.vanishTime += time * get_resourceVanishRate();
|
||||
setAvailableResourceVanish(obj, obj, r.id, r.vanishTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void destroyObjResources(Object& obj) {
|
||||
for(uint i = 0, cnt = nativeResources.length; i < cnt; ++i) {
|
||||
Resource@ r = nativeResources[i];
|
||||
TradePath@ path = resourcePaths[i];
|
||||
if(pathsActive[i] !is null)
|
||||
clearLines(r, path, r.origin, pathsActive[i]);
|
||||
}
|
||||
}
|
||||
|
||||
uint get_resourceModID() {
|
||||
return ResourceModId;
|
||||
}
|
||||
|
||||
void _readRes(Object& obj, Message& msg) {
|
||||
msg >> terraforming;
|
||||
resVanishBonus = msg.read_float();
|
||||
availableResources.read(msg);
|
||||
|
||||
{
|
||||
uint cnt = msg.readSmall();
|
||||
nativeResources.length = cnt;
|
||||
for(uint i = 0; i < cnt; ++i) {
|
||||
Resource@ r = nativeResources[i];
|
||||
r.read(msg);
|
||||
|
||||
if(r.type.vanishMode != VM_Never) {
|
||||
if(r.exportedTo !is null)
|
||||
r.exportedTo.setAvailableResourceVanish(obj, r.id, r.vanishTime);
|
||||
else
|
||||
setAvailableResourceVanish(obj, obj, r.id, r.vanishTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
uint cnt = msg.readSmall();
|
||||
resources.length = cnt;
|
||||
for(uint i = 0; i < cnt; ++i)
|
||||
resources[i].read(msg);
|
||||
}
|
||||
|
||||
{
|
||||
uint cnt = msg.readSmall();
|
||||
queuedImports.length = cnt;
|
||||
for(uint i = 0; i < cnt; ++i)
|
||||
queuedImports[i].readQueued(msg);
|
||||
}
|
||||
|
||||
{
|
||||
uint cnt = msg.readSmall();
|
||||
queuedExports.length = cnt;
|
||||
for(uint i = 0; i < cnt; ++i) {
|
||||
@queuedExports[i] = QueuedResource();
|
||||
queuedExports[i].read(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if(nativeResources.length != 0)
|
||||
primaryResource.descFrom(nativeResources[0]);
|
||||
else
|
||||
primaryResource.descFrom(null);
|
||||
++ResourceModId;
|
||||
}
|
||||
|
||||
void _readPath(Object& obj, Message& msg) {
|
||||
uint cnt = msg.readSmall();
|
||||
|
||||
if(cnt != resourcePaths.length) {
|
||||
uint prev = resourcePaths.length;
|
||||
resourcePaths.length = cnt;
|
||||
pathsActive.length = cnt;
|
||||
for(uint i = prev; i < cnt; ++i) {
|
||||
@resourcePaths[i] = TradePath(obj.owner);
|
||||
@pathsActive[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
for(uint i = 0; i < cnt; ++i) {
|
||||
TradePath@ path = resourcePaths[i];
|
||||
Resource@ r = nativeResources[i];
|
||||
if(pathsActive[i] !is null)
|
||||
clearLines(r, path, r.origin, pathsActive[i]);
|
||||
@path.forEmpire = obj.owner;
|
||||
path.read(msg);
|
||||
|
||||
if(path.isUsablePath) {
|
||||
@pathsActive[i] = r.exportedTo;
|
||||
updateLines(r, path, r.origin, r.exportedTo);
|
||||
}
|
||||
else {
|
||||
@pathsActive[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void readResourceDelta(Object& obj, Message& msg) {
|
||||
if(msg.readBit())
|
||||
_readRes(obj, msg);
|
||||
if(msg.readBit())
|
||||
_readPath(obj, msg);
|
||||
}
|
||||
|
||||
void readResources(Object& obj, Message& msg) {
|
||||
_readRes(obj, msg);
|
||||
_readPath(obj, msg);
|
||||
|
||||
if(msg.readBit())
|
||||
msg >> ImportDisabled;
|
||||
else
|
||||
ImportDisabled = 0;
|
||||
|
||||
if(msg.readBit())
|
||||
msg >> ExportDisabled;
|
||||
else
|
||||
ExportDisabled = 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user