Files
starruler-linux/scripts/server/components/Statuses.as
T
2018-07-17 14:15:37 +02:00

355 lines
8.6 KiB
ActionScript

import statuses;
import saving;
tidy class Statuses : Component_Statuses, Savable {
array<Status@> statuses;
array<StatusInstance@> instances;
int nextInstanceId = 1;
bool delta = false;
void save(SaveFile& file) {
file << nextInstanceId;
uint cnt = statuses.length;
file << cnt;
for(uint i = 0; i < cnt; ++i)
file << statuses[i];
cnt = instances.length;
file << cnt;
for(uint i = 0; i < cnt; ++i) {
file << statuses.find(instances[i].status);
file << instances[i];
}
}
void load(SaveFile& file) {
if(file < SV_0013)
return;
file >> nextInstanceId;
uint cnt = 0;
file >> cnt;
statuses.length = cnt;
for(uint i = 0; i < cnt; ++i) {
@statuses[i] = Status();
file >> statuses[i];
}
file >> cnt;
instances.length = cnt;
for(uint i = 0; i < cnt; ++i) {
@instances[i] = StatusInstance();
int index = 0;
file >> index;
@instances[i].status = statuses[index];
file >> instances[i];
}
}
void getStatusEffects(Player& pl, Object& obj) {
Empire@ plEmp = pl.emp;
for(uint i = 0, cnt = statuses.length; i < cnt; ++i) {
if(!statuses[i].isVisibleTo(obj, plEmp))
continue;
yield(statuses[i]);
}
}
uint get_statusEffectCount() {
return statuses.length;
}
uint get_statusEffectType(uint index) {
if(index >= statuses.length)
return uint(-1);
return statuses[index].type.id;
}
uint get_statusEffectStacks(uint index) {
if(index >= statuses.length)
return 0;
return statuses[index].stacks;
}
Object@ get_statusEffectOriginObject(uint index) {
if(index >= statuses.length)
return null;
return statuses[index].originObject;
}
Empire@ get_statusEffectOriginEmpire(uint index) {
if(index >= statuses.length)
return null;
return statuses[index].originEmpire;
}
uint getStatusStackCountAny(uint typeId) {
uint count = 0;
for(uint i = 0, cnt = statuses.length; i < cnt; ++i) {
if(statuses[i].type.id == typeId)
count += statuses[i].stacks;
}
return count;
}
uint getStatusStackCount(uint typeId, Object@ originObject = null, Empire@ originEmpire = null) {
uint count = 0;
for(uint i = 0, cnt = statuses.length; i < cnt; ++i) {
if(statuses[i].type.id == typeId && statuses[i].originObject is originObject && statuses[i].originEmpire is originEmpire)
count += statuses[i].stacks;
}
return count;
}
uint get_statusInstanceCount() {
return instances.length;
}
uint get_statusInstanceType(uint index) {
if(index >= instances.length)
return uint(-1);
return instances[index].status.type.id;
}
int get_statusInstanceId(uint index) {
if(index >= instances.length)
return -1;
return instances[index].id;
}
bool hasStatusEffect(uint typeId) {
for(uint i = 0, cnt = statuses.length; i < cnt; ++i) {
if(statuses[i].type.id == typeId)
return true;
}
return false;
}
int addStatus(Object& obj, double timer, uint typeId, Empire@ boundEmpire = null, Region@ boundRegion = null, Empire@ originEmpire = null, Object@ originObject = null) {
const StatusType@ type = getStatusType(typeId);
if(type is null)
return -1;
Status@ status;
if(type.collapses) {
for(uint i = 0, cnt = statuses.length; i < cnt; ++i) {
auto@ cur = statuses[i];
if(cur.type is type && originEmpire is cur.originEmpire && originObject is cur.originObject) {
@status = cur;
break;
}
}
}
if(status is null) {
@status = Status(type);
@status.originEmpire = originEmpire;
@status.originObject = originObject;
status.create(obj);
statuses.insertLast(status);
}
auto@ instance = status.instance(obj);
instance.id = nextInstanceId++;
instance.timer = timer;
@instance.boundEmpire = boundEmpire;
@instance.boundRegion = boundRegion;
instances.insertLast(instance);
delta = true;
return instance.id;
}
void addStatus(Object& obj, uint typeId, double timer = -1.0, Empire@ boundEmpire = null, Region@ boundRegion = null, Empire@ originEmpire = null, Object@ originObject = null) {
addStatus(obj, timer, typeId, boundEmpire, boundRegion, originEmpire, originObject);
}
void addRandomCondition(Object& obj) {
if(!obj.isPlanet)
return;
auto@ type = getRandomCondition(cast<Planet>(obj));
if(type !is null)
addStatus(obj, type.id);
}
void removeStatus(Object& obj, int id) {
StatusInstance@ instance;
for(uint i = 0, cnt = instances.length; i < cnt; ++i) {
if(instances[i].id == id) {
@instance = instances[i];
instances.removeAt(i);
break;
}
}
if(instance is null)
return;
instance.remove(obj);
if(instance.status.stacks <= 0) {
statuses.remove(instance.status);
instance.status.destroy(obj);
}
delta = true;
}
bool isStatusInstanceActive(int id) {
for(uint i = 0, cnt = instances.length; i < cnt; ++i) {
if(instances[i].id == id)
return true;
}
return false;
}
void removeStatusInstanceOfType(Object& obj, uint typeId) {
StatusInstance@ instance;
for(uint i = 0, cnt = instances.length; i < cnt; ++i) {
auto@ inst = instances[i];
if(inst.boundEmpire !is null)
continue;
if(inst.boundRegion !is null)
continue;
if(inst.timer >= 0)
continue;
if(inst.status.type.id == typeId) {
@instance = inst;
instances.removeAt(i);
break;
}
}
if(instance is null)
return;
instance.remove(obj);
if(instance.status.stacks <= 0) {
statuses.remove(instance.status);
instance.status.destroy(obj);
}
delta = true;
}
void removeStatusType(Object& obj, uint typeId) {
uint index = uint(-1);
for(uint i = 0, cnt = statuses.length; i < cnt; ++i) {
auto@ cur = statuses[i];
if(cur.type.id == typeId) {
index = i;
break;
}
}
if(index == uint(-1))
return;
removeStatusTypeByIndex(obj, index);
}
void removeStatusTypeByIndex(Object& obj, uint index) {
Status@ status;
if(index < statuses.length)
@status = statuses[index];
if(status is null)
return;
for(int j = instances.length - 1; j >= 0; --j) {
if(instances[j].status is status) {
status.remove(obj, instances[j]);
instances.removeAt(j);
}
}
statuses.removeAt(index);
status.destroy(obj);
delta = true;
}
void changeStatusOwner(Object& obj, Empire@ prevOwner, Empire@ newOwner) {
for(int i = instances.length - 1; i >= 0; --i) {
auto@ instance = instances[i];
if(instance.boundEmpire !is null && instance.boundEmpire is prevOwner) {
instance.remove(obj);
instances.removeAt(i);
}
}
for(int i = statuses.length - 1; i >= 0; --i) {
auto@ status = statuses[i];
if(status.stacks <= 0 || !status.ownerChange(obj, prevOwner, newOwner))
removeStatusTypeByIndex(obj, i);
}
}
void changeStatusRegion(Object& obj, Region@ prevRegion, Region@ newRegion) {
for(int i = instances.length - 1; i >= 0; --i) {
auto@ instance = instances[i];
if(instance.boundRegion !is null && instance.boundRegion is prevRegion) {
instance.remove(obj);
instances.removeAt(i);
}
}
for(int i = statuses.length - 1; i >= 0; --i) {
auto@ status = statuses[i];
if(status.stacks <= 0 || !status.regionChange(obj, prevRegion, newRegion))
removeStatusTypeByIndex(obj, i);
}
}
void removeRegionBoundStatus(Object& obj, Region@ region, uint typeId, double timer = -1.0) {
for(int i = instances.length - 1; i >= 0; --i) {
auto@ instance = instances[i];
if(instance.boundRegion is region && instance.status.type.id == typeId
&& abs(instance.timer - timer) < 0.9) {
instances.removeAt(i);
instance.remove(obj);
for(int j = statuses.length - 1; j >= 0; --j) {
auto@ status = statuses[j];
if(status.stacks <= 0)
removeStatusTypeByIndex(obj, j);
}
break;
}
}
}
void statusTick(Object& obj, double time) {
for(int i = instances.length - 1; i >= 0; --i) {
auto@ instance = instances[i];
if(!instance.tick(obj, time))
instances.removeAt(i);
}
for(int i = statuses.length - 1; i >= 0; --i) {
auto@ status = statuses[i];
if(status.stacks <= 0 || !status.tick(obj, time))
removeStatusTypeByIndex(obj, i);
}
}
void destroyStatus(Object& obj) {
for(int i = statuses.length - 1; i >= 0; --i) {
auto@ status = statuses[i];
status.objectDestroy(obj);
}
for(uint i = 0; i < instances.length; ++i) {
auto@ instance = instances[i];
instance.remove(obj);
if(instance.status.stacks <= 0) {
statuses.remove(instance.status);
instance.status.destroy(obj);
}
}
statuses.length = 0;
instances.length = 0;
}
void writeStatuses(Message& msg) const {
uint cnt = statuses.length;
msg.writeSmall(cnt);
for(uint i = 0; i < cnt; ++i)
msg << statuses[i];
}
bool writeStatusDelta(Message& msg) {
if(delta) {
delta = false;
msg.write1();
writeStatuses(msg);
return true;
}
return false;
}
};