Open source Star Ruler 2 source code!

This commit is contained in:
Lucas de Vries
2018-07-17 14:15:37 +02:00
commit cc307720ff
4342 changed files with 2365070 additions and 0 deletions
+232
View File
@@ -0,0 +1,232 @@
import random_events;
tidy class RandomEvents : Component_RandomEvents, EventContainer, Savable {
Mutex mtx;
array<CurrentEvent@> events;
int nextEventId = 0;
double nextRandomEvent = -1;
array<const RandomEvent@> considering;
set_int eventsEncountered;
array<int> encounteredList;
CurrentEvent consEvt;
void save(SaveFile& file) {
file << nextEventId;
file << nextRandomEvent;
uint cnt = events.length;
file << cnt;
for(uint i = 0; i < cnt; ++i)
file << events[i];
cnt = considering.length;
file << cnt;
for(uint i = 0; i < cnt; ++i)
file.writeIdentifier(SI_RandomEvent, considering[i].id);
cnt = encounteredList.length;
file << cnt;
for(uint i = 0; i < cnt; ++i)
file.writeIdentifier(SI_RandomEvent, encounteredList[i]);
}
void load(SaveFile& file) {
file >> nextEventId;
file >> nextRandomEvent;
uint cnt = 0;
file >> cnt;
events.length = cnt;
for(uint i = 0; i < cnt; ++i) {
@events[i] = CurrentEvent();
file >> events[i];
}
file >> cnt;
considering.length = 0;
considering.reserve(cnt);
for(uint i = 0; i < cnt; ++i) {
auto@ type = getRandomEvent(file.readIdentifier(SI_RandomEvent));
if(type !is null)
considering.insertLast(type);
}
file >> cnt;
encounteredList.length = cnt;
for(uint i = 0; i < cnt; ++i) {
encounteredList[i] = file.readIdentifier(SI_RandomEvent);
eventsEncountered.insert(encounteredList[i]);
}
}
CurrentEvent@ getEventByID(int id) {
for(uint i = 0, cnt = events.length; i < cnt; ++i) {
if(events[i].id == id)
return events[i];
}
return null;
}
int get_currentEventID() {
if(events.length == 0)
return -1;
Lock lck(mtx);
if(events.length == 0)
return -1;
return events[0].id;
}
bool hasCurrentEvents() {
return events.length != 0;
}
void getCurrentEvents() {
Lock lck(mtx);
for(uint i = 0, cnt = events.length; i < cnt; ++i)
yield(events[i]);
}
void getEvent(int id) {
Lock lck(mtx);
auto@ evt = getEventByID(id);
if(evt !is null)
yield(evt);
}
void create(CurrentEvent@ evt) {
CurrentEvent newEvent = evt;
Lock lck(mtx);
newEvent.id = nextEventId++;
eventsEncountered.insert(evt.type.id);
encounteredList.insertLast(evt.type.id);
events.insertLast(newEvent);
}
void setNextEvent() {
if(config::RANDOM_EVENT_OCCURRENCE == 0) {
nextRandomEvent = INFINITY;
return;
}
double time = 600.0 / config::RANDOM_EVENT_OCCURRENCE;
double mod = max(time - config::RANDOM_EVENT_MIN_INTERVAL, 0.0);
nextRandomEvent = gameTime + normald(time-mod, time+mod);
}
void spawnRandomEvent(Empire& emp, uint typeId) {
auto@ type = getRandomEvent(typeId);
if(type is null)
return;
CurrentEvent evt;
evt.clear(type);
@evt.owner = emp;
if(evt.consider()) {
evt.create();
create(evt);
}
}
void eventsTick(Empire& emp, double time) {
if(emp.isAI && emp !is playerEmpire) {
nextRandomEvent = -1;
return;
}
//Tick existing events
for(uint i = 0, cnt = events.length; i < cnt; ++i) {
auto@ evt = events[i];
if(evt.timer > 0) {
evt.timer -= time;
if(evt.timer <= 0) {
int optId = -1;
for(uint i = 0, cnt = evt.options.length; i < cnt; ++i) {
if(evt.options[i].defaultOption) {
optId = evt.options[i].id;
break;
}
}
if(optId != -1)
chooseEventOption(emp, evt.id, optId);
else
events.removeAt(i);
--i; --cnt;
}
}
}
//Consider new events
if(nextRandomEvent < 0) {
setNextEvent();
}
else if(considering.length != 0) {
const RandomEvent@ checkType;
double tot = 0;
for(uint i = 0, cnt = considering.length; i < cnt; ++i) {
double freq = considering[i].frequency;
tot += freq;
if(randomd() < freq / tot)
@checkType = considering[i];
}
if(checkType !is null) {
consEvt.clear(checkType);
@consEvt.owner = emp;
if(consEvt.consider()) {
consEvt.create();
create(consEvt);
considering.length = 0;
}
else {
considering.remove(checkType);
}
if(considering.length == 0)
setNextEvent();
}
else {
setNextEvent();
}
}
else if(nextRandomEvent < gameTime) {
for(uint i = 0, cnt = getRandomEventCount(); i < cnt; ++i) {
auto@ type = getRandomEvent(i);
if(type.mode != RTM_Random)
continue;
if(type.frequency <= 0)
continue;
if(type.unique && eventsEncountered.contains(type.id))
continue;
considering.insertLast(type);
}
if(considering.length == 0)
setNextEvent();
}
}
void chooseEventOption(Empire& emp, int evtId, uint optId) {
Lock lck(mtx);
auto@ evt = getEventByID(evtId);
if(evt !is null) {
for(uint i = 0, cnt = evt.options.length; i < cnt; ++i) {
if(evt.options[i].id == optId) {
evt.options[i].trigger(evt);
break;
}
}
events.remove(evt);
}
}
void writeEvents(Message& msg) {
if(events.length == 0) {
msg.write0();
return;
}
Lock lck(mtx);
msg.write1();
msg.writeSmall(events.length);
for(uint i = 0, cnt = events.length; i < cnt; ++i)
msg << events[i];
}
};