Files
starruler-linux/scripts/definitions/cargo.as
T
2018-07-17 14:15:37 +02:00

396 lines
8.5 KiB
ActionScript

#priority init 2000
import saving;
import attributes;
export CargoType;
export CargoStorage;
export hasDesignCosts;
export getCargoID;
export getCargoType, getCargoTypeCount;
tidy final class CargoType {
uint id;
string ident;
string name;
string description;
Sprite icon;
Color color;
double storageSize = 1.0;
HexVariable variable = HexVariable(-1);
};
tidy class CargoStorage : Serializable, Savable {
array<const CargoType@>@ types;
array<double>@ amounts;
double capacity = 0.0;
double filled = 0.0;
bool delta = false;
uint get_length() {
return types.length;
}
int index(const CargoType@ type, bool create = true) {
int ind = -1;
if(types !is null)
ind = types.find(type);
if(ind == -1 && create) {
if(types is null) {
@types = array<const CargoType@>();
@amounts = array<double>();
}
ind = types.length;
types.insertLast(type);
amounts.insertLast(0.0);
}
return ind;
}
void remove(const CargoType@ type) {
int ind = index(type, false);
if(ind == -1)
return;
if(types is null)
return;
types.removeAt(ind);
amounts.removeAt(ind);
/*if(types.length == 0) {*/
/* @types = null;*/
/* @amounts = null;*/
/*}*/
}
void removeAll() {
@types = null;
@amounts = null;
filled = 0;
}
double get(const CargoType@ type) {
int ind = index(type, false);
if(ind == -1)
return 0.0;
return amounts[ind];
}
double add(const CargoType@ type, double amount, bool partial = true) {
if(!partial && (capacity - filled) < type.storageSize * amount)
return 0.0;
double storeAmt = min(amount, (capacity - filled) / type.storageSize);
if(storeAmt <= 0.0001)
return 0.0;
int ind = index(type);
amounts[ind] += storeAmt;
filled = clamp(filled + (storeAmt * type.storageSize), 0, capacity);
delta = true;
return amount - storeAmt;
}
double consume(const CargoType@ type, double amount, bool partial = false) {
int ind = index(type, false);
if(ind == -1)
return 0.0;
if(!partial && amounts[ind] < amount)
return 0.0;
double consAmt = min(amount, amounts[ind]);
amounts[ind] -= consAmt;
filled = clamp(filled - (consAmt * type.storageSize), 0, capacity);
delta = true;
if(amounts[ind] < 0.0001)
remove(type);
return consAmt;
}
void write(Message& msg) {
if(types is null) {
msg.writeSmall(0);
}
else {
msg.writeSmall(types.length);
for(uint i = 0, cnt = types.length; i < cnt; ++i) {
msg.writeSmall(types[i].id);
msg << amounts[i];
}
}
msg << capacity;
msg << filled;
}
void read(Message& msg) {
uint cnt = msg.readSmall();
if(cnt == 0) {
if(types !is null) {
@types = null;
@amounts = null;
}
}
else {
if(types is null) {
@types = array<const CargoType@>();
@amounts = array<double>();
}
types.length = cnt;
amounts.length = cnt;
for(uint i = 0; i < cnt; ++i) {
@types[i] = getCargoType(msg.readSmall());
msg >> amounts[i];
}
}
msg >> capacity;
msg >> filled;
}
void save(SaveFile& file) {
uint cnt = 0;
if(types !is null)
cnt = types.length;
file << cnt;
for(uint i = 0; i < cnt; ++i) {
file.writeIdentifier(SI_CargoType, types[i].id);
file << amounts[i];
}
file << capacity;
file << filled;
}
void load(SaveFile& file) {
uint cnt = 0;
file >> cnt;
if(cnt == 0) {
if(types !is null) {
@types = null;
@amounts = null;
}
}
else {
if(types is null) {
@types = array<const CargoType@>();
@amounts = array<double>();
}
types.length = cnt;
amounts.length = cnt;
for(uint i = 0; i < cnt; ++i) {
auto@ type = getCargoType(file.readIdentifier(SI_CargoType));
if(type is null) {
double tmp = 0;
file >> tmp;
amounts.removeAt(i);
--cnt; --i;
}
else {
@types[i] = type;
file >> amounts[i];
}
}
}
file >> capacity;
file >> filled;
}
};
#section server
export payDesignCosts, reverseDesignCosts;
bool payDesignCosts(Object& obj, const Design@ dsg, double multiply = 1.0) {
double energyCost = dsg.total(SV_EnergyBuildCost);
if(energyCost > 0) {
if(obj.owner.consumeEnergy(energyCost, consumePartial=false) < energyCost-0.001)
return false;
}
int influenceCost = dsg.total(SV_InfluenceBuildCost);
if(influenceCost > 0) {
if(!obj.owner.consumeInfluence(influenceCost)) {
if(energyCost > 0)
obj.owner.modEnergyStored(+energyCost);
return false;
}
}
double ftlCost = dsg.total(SV_FTLBuildCost);
if(ftlCost > 0) {
if(obj.owner.consumeFTL(ftlCost, partial=false, record=false) < ftlCost-0.001) {
if(energyCost > 0)
obj.owner.modEnergyStored(+energyCost);
if(influenceCost > 0)
obj.owner.modInfluence(+influenceCost);
return false;
}
}
for(uint i = 0, cnt = getCargoTypeCount(); i < cnt; ++i) {
auto@ cargo = getCargoType(i);
if(int(cargo.variable) == -1)
continue;
double amt = dsg.total(cargo.variable) * multiply;
if(amt > 0) {
if(!obj.hasCargo || obj.consumeCargo(cargo.id, amt, partial=false) < amt - 0.001) {
for(uint j = 0; j < i; ++j) {
auto@ other = getCargoType(j);
if(int(other.variable) == -1)
continue;
double amt = dsg.total(other.variable) * multiply;
if(amt > 0)
obj.addCargo(other.id, amt);
}
if(energyCost > 0)
obj.owner.modEnergyStored(+energyCost);
if(influenceCost > 0)
obj.owner.modInfluence(+influenceCost);
if(ftlCost > 0)
obj.owner.modFTLStored(+ftlCost);
return false;
}
}
}
if(ftlCost > 0)
obj.owner.modAttribute(EA_FTLEnergySpent, AC_Add, ftlCost);
return true;
}
void reverseDesignCosts(Object& obj, const Design@ dsg, double multiply = 1.0, bool cancel = false) {
if(!cancel) {
double energyCost = dsg.total(SV_EnergyBuildCost);
if(energyCost > 0)
obj.owner.modEnergyStored(+energyCost);
int influenceCost = dsg.total(SV_EnergyBuildCost);
if(influenceCost > 0)
obj.owner.addInfluence(+influenceCost);
double ftlCost = dsg.total(SV_FTLBuildCost);
if(ftlCost > 0)
obj.owner.modFTLStored(+ftlCost, obeyMaximum=true);
}
if(obj.hasCargo) {
for(uint i = 0, cnt = getCargoTypeCount(); i < cnt; ++i) {
auto@ cargo = getCargoType(i);
if(int(cargo.variable) == -1)
continue;
double amt = dsg.total(cargo.variable) * multiply;
if(amt > 0)
obj.addCargo(cargo.id, amt);
}
}
}
#section all
bool hasDesignCosts(const Design@ dsg) {
for(uint i = 0, cnt = getCargoTypeCount(); i < cnt; ++i) {
auto@ cargo = getCargoType(i);
if(int(cargo.variable) == -1)
continue;
double amt = dsg.total(cargo.variable);
if(amt > 0)
return true;
}
if(dsg.total(SV_EnergyBuildCost) > 0)
return true;
if(dsg.total(SV_InfluenceBuildCost) > 0)
return true;
if(dsg.total(SV_FTLBuildCost) > 0)
return true;
return false;
}
array<CargoType@> cargoTypes;
dictionary cargoIdents;
int getCargoID(const string& ident) {
auto@ type = getCargoType(ident);
if(type is null)
return -1;
return int(type.id);
}
string getCargoIdent(int id) {
auto@ type = getCargoType(id);
if(type is null)
return "";
return type.ident;
}
const CargoType@ getCargoType(uint id) {
if(id >= cargoTypes.length)
return null;
return cargoTypes[id];
}
const CargoType@ getCargoType(const string& ident) {
CargoType@ def;
if(cargoIdents.get(ident, @def))
return def;
return null;
}
uint getCargoTypeCount() {
return cargoTypes.length;
}
void saveIdentifiers(SaveFile& file) {
for(uint i = 0, cnt = cargoTypes.length; i < cnt; ++i) {
auto type = cargoTypes[i];
file.addIdentifier(SI_CargoType, type.id, type.ident);
}
}
void addCargoType(CargoType@ type) {
type.id = cargoTypes.length;
cargoTypes.insertLast(type);
cargoIdents.set(type.ident, @type);
}
void loadCargo(const string& filename) {
ReadFile file(filename, false);
string key, value;
CargoType@ type;
uint index = 0;
while(file++) {
key = file.key;
value = file.value;
if(key.equals_nocase("Cargo")) {
@type = CargoType();
type.ident = value;
addCargoType(type);
type.variable = getHexVariable(type.ident+"Cost");
}
else if(type is null) {
file.error("Missing Cargo: ID' line");
}
else if(key.equals_nocase("Name")) {
type.name = localize(value);
}
else if(key.equals_nocase("Description")) {
type.description = localize(value);
}
else if(key.equals_nocase("Icon")) {
type.icon = getSprite(value);
}
else if(key.equals_nocase("Color")) {
type.color = toColor(value);
}
else if(key.equals_nocase("Storage Size")) {
type.storageSize = toDouble(value);
}
}
}
void preInit() {
FileList list("data/cargo", "*.txt", true);
for(uint i = 0, cnt = list.length; i < cnt; ++i)
loadCargo(list.path[i]);
}