diff --git a/SetupThrive.rb b/SetupThrive.rb
index ec9221c338c..b2500ebcb52 100755
--- a/SetupThrive.rb
+++ b/SetupThrive.rb
@@ -78,7 +78,7 @@ def parseExtraArgs
leviathan = Leviathan.new(
# Use this if you always want the latest commit
# version: "develop",
- version: "42ba106b2e3d098b3ab1b64ad559d3d51d931229",
+ version: "0d08da11c7d15bb5710427634371b62eccf7867d",
# Doesn't actually work, but leviathan doesn't install with sudo by
# default, or install at all for that matter
noInstallSudo: true
diff --git a/scripts/gui/thrive_gui.html b/scripts/gui/thrive_gui.html
index 7433a09a7ea..7dea5b48690 100644
--- a/scripts/gui/thrive_gui.html
+++ b/scripts/gui/thrive_gui.html
@@ -372,7 +372,7 @@
Cytoplasm
Cost: 30 mutation points
Performs Process: Glycolysis (0.125 glucose -> 5 ATP)/Second
- Storage Space: 20
+ Storage Space: 4
The material or protoplasm within a living cell. The gooey innards of a cell.
Cytoplasm 30 MP |
@@ -382,7 +382,7 @@
Metabolosomes
Cost: 45 mutation points
Performs Process: Metabolsome Respiration (In real life they Ferment, but we dont have those compounds in the game yet)
(1 Oxygen + 0.7 Glucose -> 38 ATP)/Second (Depending On Environmental Oxygen)
- Storage Space: 10
+ Storage Space: 1
Organelle-like Bacterial microcompartments (BMCs) consisting of a protein shell that encloses enzymes used for fermentation.
Metabolosomes
45 MP
@@ -391,7 +391,7 @@
Chromatophores
Cost: 55 mutation points
Performs Process: Chromatophore Photosynthesis
(0.09 CO2 -> 0.33 glucose)/Second (Depending On Environmental C02)
Performs Process: Glycolysis
(0.125 glucose -> 5 ATP)/Second (Depending On Environmental C02)
- Storage Space: 10
+ Storage Space: 1
Coloured, membrane-associated vesicles used by various prokaryotes perform photosynthesis.
Chromatophores contain bacteriochlorophyll pigments and carotenoids.
Chromatophores
55 MP
@@ -400,7 +400,7 @@
ChemosynthisizingProteins
Cost: 45 mutation points
Performs Process: Bacterial Chemosynthesis
(1 CO2 + 1 Hydrogen Sulfide -> 1 Glucose)/Second (Depending On Environmental C02)
Performs Process: Glycolysis
(0.125 glucose -> 5 ATP)/Second
- Storage Space: 20
+ Storage Space: 1
Small membrane-associated structures that convert the noxious soup containing hydrogen
sulfide from hydrothermal vents into usable energy in the form of glucose.
Chemosynthisizing Proteins
45 MP
@@ -409,8 +409,8 @@
Rusticyanin
Cost: 45 mutation points
- Performs Process: Iron Chemolithotrophy (0.09 CO2 + 0.5 Iron Ion -> 10 ATP)/Second (Depending On Environmental C02)
- Storage Space: 5
+ Performs Process: Iron Chemolithotrophy (0.09 CO2 + 0.175 Iron Ion -> 10 ATP)/Second (Depending On Environmental C02)
+ Storage Space: 1
Siderophores and Rusticyanin for storing and using iron ions and carbon from atmospheric carbon dioxide to produce ATP.
Iron Chemolithotrophy is a process by which organisms obtain their energy from the oxidation of reduced inorganic ions.
@@ -421,8 +421,9 @@
|
Flagellum
Cost: 55 mutation points
- Cost: 7 atp per second while in use.
- A whip like structure used microbes for movement.
+ Performs Process: Movement (7atp -> Faster movement speed)/Second
+ Storage Space: 1
+ A whip like structure used by microbes for movement.
Flagellum 55 MP |
Predatory Pilus 30 MP |
@@ -435,7 +436,8 @@
Nucleus
Cost: 100 mutation points
Performs Process: Eukaryote Evolution
- Allows for synthesis of RNA, MRNA, allows cell to evolve membrane bound organelles.
+ Storage Space: 15
+ Allows for synthesis of RNA and MRNA, allows cell to evolve membrane bound organelles.
Nucleus
100 MP
@@ -443,15 +445,17 @@
Mitochondria
Cost: 45 mutation points
Performs Process: Respiration
(1 Oxygen + 0.2 glucose -> 38 ATP)/Second (Depending On Environmental Oxygen)
+ Storage Space: 2
A captured prokaryote used by eukaryotic cells to perform respiration.
- The Mitochondria is the powerhouse of the cell
+ - The Mitochondria is the powerhouse of the cell
Mitochondrion
45 MP
Chloroplast
Cost: 55 mutation points
- Performs Process: Photosynthesis ( 0.09 Carbon Dioxide -> 1 glucose)/Second (Depending On Environmental C02)
+ Performs Process: Photosynthesis ( 0.09 CO2 -> 1 glucose)/Second (Depending On Environmental C02)
+ Storage Space: 2
A captured prokaryote used by eukaryotic cells to perform photosynthesis.
The chloroplast is used primarily by plant cells on earth, but some ciliates and other organisms use it too.
@@ -461,6 +465,7 @@
Thermoplast
Cost: 40 mutation points
Performs Process: Thermosynthesis (Heat -> 1 glucose)/Second (Depending On Environmental Heat)
+ Storage Space: 2
A captured prokaryote used by eukaryotic cells to perform thermosynthesis.
The thermoplast is a theoretical organelle that takes environmental heat gradients and generates energy from them.
@@ -469,6 +474,7 @@
Chemoplast
Cost: 45 mutation points
Performs Process: Chemosynthesis (0.09 CO2 + 1 Hydrogen Sulfide -> 2 Glucose)/Second (Depending On Environmental C02)
+ Storage Space: 2
Allows for synthesis of glucose from hydrogen sulfide and atmospheric carbon dioxide.
Can be used to process the normally toxic soup containing hydrogen sulfide that comes out of hydrothermal vents at the bottom of the ocean. Into glucose.
@@ -478,6 +484,7 @@
Nitrogen Fixing Plastid
Cost: 50 mutation points
Performs Process: Nitrogen Fixation (1 Oxygen + 5 ATP -> 0.5 Ammonia)/Second (Depending On Environmental Oxygen)
+ Storage Space: 2
Allows for synthesis of ammonia from atmospheric nitrogen and oxygen. For easier cell growth.
@@ -486,14 +493,15 @@
Vacuole
Cost: 50 mutation points
- Storage Space: 50
- A space or vesicle within the cytoplasm of a cell, enclosed by a membrane and used to hold compounds
+ Storage Space: 15
+ A space or vesicle within the cytoplasm of a cell, enclosed by a membrane and used to hold compounds.
Vacuole 50 MP |
Toxin Vacuole
Cost: 70 mutation points
Performs Process: OxytoxyNT Production (1 Oxygen + 5 ATP -> 5 Oxytoxy)/Second (Depending On Environmental Oxygen)
- Allows for production and storage of OxytoxyNT which can be shot at enemy cells using E. The more of this organelle you have the faster your toxin fire rate aswell.
+ Storage Space: 5
+ Allows for production and storage of OxytoxyNT which can be shot at enemy cells using E. The more of this organelle you have the faster your toxin fire rate will be.
Toxin Vacuole 70 MP |
diff --git a/scripts/microbe_stage/configs.as b/scripts/microbe_stage/configs.as
index f7779579876..7dd26f29acd 100644
--- a/scripts/microbe_stage/configs.as
+++ b/scripts/microbe_stage/configs.as
@@ -6,8 +6,13 @@
const auto CLOUD_SPAWN_RADIUS = 150;
const auto POWERUP_SPAWN_RADIUS = 85;
const auto DEFAULT_SPAWN_DENSITY = 1/25000.f;
-const auto STARTING_SPAWN_DENSITY = 50000.0f;
+const auto STARTING_SPAWN_DENSITY = 45000.0f;
const auto MAX_SPAWN_DENSITY = 20000.0f;
+//Corpse info
+const auto CORPSE_COMPOUND_COMPENSATION = 8.0f;
+const int CORPSE_CHUNK_DIVISER = 3;
+const auto CORPSE_CHUNK_AMOUNT_DIVISER = 3.0f;
+const auto CHUNK_ENGULF_COMPOUND_DIVISOR = 30.0f;
// Cell Spawn Variation
const auto MIN_SPAWN_DISTANCE = -5000.0f;
@@ -29,13 +34,6 @@ const auto MAX_OPACITY_CHITIN = 1.2f;
const auto MIN_OPACITY_MUTATION = -0.01f;
const auto MAX_OPACITY_MUTATION = 0.01f;
-//not const because we want to change these
-//current atmospheric oxygen percentage in modern times
-auto OXYGEN_PERCENTAGE = 0.21f;
-//co2 percentage (over expressed as .09% is the percenatge of all
-//non-nitrogen-non-oxygen gasses in our atmosphere)
-auto CARBON_DIOXIDE_PERCENTAGE = 0.009f;
-
// Mutation Variables
const auto MUTATION_BACTERIA_TO_EUKARYOTE = 1;
const auto MUTATION_CREATION_RATE = 0.1f;
@@ -52,12 +50,13 @@ const auto MAX_SPECIES_AGRESSION = 400.0f;
const auto MAX_SPECIES_FEAR = 400.0f;
const auto MAX_SPECIES_ACTIVITY = 400.0f;
const auto MAX_SPECIES_FOCUS = 400.0f;
+const auto MAX_SPECIES_OPPORTUNISM = 400.0f;
// Personality Mutation
const auto MAX_SPECIES_PERSONALITY_MUTATION = 20.0f;
const auto MIN_SPECIES_PERSONALITY_MUTATION = -20.0f;
-// Bacterial CXOlony configuration
+// Bacterial COlony configuration
const auto MIN_BACTERIAL_COLONY_SIZE = 1;
const auto MAX_BACTERIAL_COLONY_SIZE = 5;
const auto MIN_BACTERIAL_LINE_SIZE = 3;
@@ -68,6 +67,7 @@ const auto AGRESSION_DIVISOR = 25.0f;
const auto FEAR_DIVISOR = 25.0f;
const auto ACTIVITY_DIVISOR = 100.0f;
const auto FOCUS_DIVISOR = 100.0f;
+const auto OPPORTUNISM_DIVISOR = 100.0f;
// Cooldown for AI for toggling engulfing
const uint AI_ENGULF_INTERVAL=300;
@@ -163,11 +163,15 @@ const uint AGENT_EMISSION_COOLDOWN = 2000;
// Iron amounts per chunk.
// big iron ejects ten per 20 clicks , so about 30 per second, so ill give it enough for 1000 seconds)
const double IRON_PER_BIG_CHUNK = 30000.0f;
-// small iron ejects 3 per 20 clicks , so about 9 per second, so ill give it enough for 1000 seconds aswell
-const double IRON_PER_SMALL_CHUNK = 9000.0f;
+const bool LARGE_IRON_DISSOLVES = false;
+// small iron ejects 3 per 20 clicks , so about 9 per second
+const double IRON_PER_SMALL_CHUNK = 100.0f;
+const bool SMALL_IRON_DISSOLVES = true;
+
//Auto Evo Values
const int CREATURE_DEATH_POPULATION_LOSS = -60;
const int CREATURE_KILL_POPULATION_GAIN = 50;
+const int CREATURE_SCAVENGE_POPULATION_GAIN = 10;
const int CREATURE_REPRODUCE_POPULATION_GAIN = 50;
const int CREATURE_ESCAPE_POPULATION_GAIN = 50;
diff --git a/scripts/microbe_stage/microbe.as b/scripts/microbe_stage/microbe.as
index afe7d2ec3c2..6ed4d4b0a6a 100644
--- a/scripts/microbe_stage/microbe.as
+++ b/scripts/microbe_stage/microbe.as
@@ -484,7 +484,7 @@ class MicrobeSystem : ScriptSystem{
world.GetScriptComponentHolder("MicrobeComponent").Find(microbeComponent.hostileEngulfer));
if ((hostileMicrobeComponent is null) || (!hostileMicrobeComponent.engulfMode) ||
(hostileMicrobeComponent.dead) || (ourPosition._Position - predatorPosition._Position).LengthSquared() >=
- ((hostileMicrobeComponent.organelles.length()+3)*HEX_SIZE)+50){
+ ((hostileMicrobeComponent.totalHexCountCache+3)*HEX_SIZE)+50){
microbeComponent.hostileEngulfer = NULL_OBJECT;
microbeComponent.isBeingEngulfed = false;
}
@@ -499,7 +499,7 @@ class MicrobeSystem : ScriptSystem{
//TODO:It seems to happen no matter what (even if it takes away less atp then you generate per second),
//we should probably make it take into account the amount of atp being generated so resources arent wasted
//for now made it not take away if your atp amount is equal to your capacity
- auto osmoCost = (microbeComponent.organelles.length()*ATP_COST_FOR_OSMOREGULATION)/(logicTime);
+ auto osmoCost = (microbeComponent.totalHexCountCache*ATP_COST_FOR_OSMOREGULATION)/(logicTime);
//auto osmoCost = (microbeComponent.organelles.length()*2)/logicTime;
double atpAmount = MicrobeOperations::getCompoundAmount(world, microbeEntity,SimulationParameters::compoundRegistry().getTypeId("atp"));
@@ -576,9 +576,9 @@ class MicrobeSystem : ScriptSystem{
const Float3 velocity = physics.Body.GetVelocity();
// There should be no Y velocity so it should be zero
- const Float3 drag(velocity.X * (CELL_DRAG_MULTIPLIER+(CELL_SIZE_DRAG_MULTIPLIER*microbeComponent.organelles.length())),
- velocity.Y * (CELL_DRAG_MULTIPLIER+(CELL_SIZE_DRAG_MULTIPLIER*microbeComponent.organelles.length())),
- velocity.Z * (CELL_DRAG_MULTIPLIER+(CELL_SIZE_DRAG_MULTIPLIER*microbeComponent.organelles.length())));
+ const Float3 drag(velocity.X * (CELL_DRAG_MULTIPLIER+(CELL_SIZE_DRAG_MULTIPLIER*microbeComponent.totalHexCountCache)),
+ velocity.Y * (CELL_DRAG_MULTIPLIER+(CELL_SIZE_DRAG_MULTIPLIER*microbeComponent.totalHexCountCache)),
+ velocity.Z * (CELL_DRAG_MULTIPLIER+(CELL_SIZE_DRAG_MULTIPLIER*microbeComponent.totalHexCountCache)));
// Only add drag if it is over CELL_REQUIRED_DRAG_BEFORE_APPLY
if(abs(drag.X) >= CELL_REQUIRED_DRAG_BEFORE_APPLY){
@@ -630,7 +630,7 @@ class MicrobeSystem : ScriptSystem{
// microbeComponent.queuedMovementForce.Z);
// There is an movement without flagella cost
- auto cost = (BASE_MOVEMENT_ATP_COST*microbeComponent.organelles.length())/logicTime;
+ auto cost = (BASE_MOVEMENT_ATP_COST*microbeComponent.totalHexCountCache)/logicTime;
// TODO: if there isn't enough energy this needs to scale the impulse
MicrobeOperations::takeCompound(world, microbeEntity,
diff --git a/scripts/microbe_stage/microbe_ai.as b/scripts/microbe_stage/microbe_ai.as
index 471ef9cadf5..ddee627fc6c 100644
--- a/scripts/microbe_stage/microbe_ai.as
+++ b/scripts/microbe_stage/microbe_ai.as
@@ -18,7 +18,8 @@ const int GLUCOSE_SEARCH_THRESHHOLD = 5;
GATHERING_STATE,
FLEEING_STATE,
PREDATING_STATE,
- PLANTLIKE_STATE
+ PLANTLIKE_STATE,
+ SCAVENGING_STATE
}
class MicrobeAIControllerComponent : ScriptComponent{
@@ -40,6 +41,7 @@ class MicrobeAIControllerComponent : ScriptComponent{
double speciesFear = -1.0f;
double speciesActivity = -1.0f;
double speciesFocus = -1.0f;
+ double speciesOpportunism = -1.0;
bool hasTargetPosition = false;
Float3 targetPosition = Float3(0, 0, 0);
bool hasSearchedCompoundId = false;
@@ -47,11 +49,12 @@ class MicrobeAIControllerComponent : ScriptComponent{
float previousAngle = 0.0f;
float compoundDifference=0;
ObjectID prey = NULL_OBJECT;
+ ObjectID targetChunk = NULL_OBJECT;
bool preyPegged=false;
// Prey and predator lists
array predatoryMicrobes;
array preyMicrobes;
-
+ array chunkList;
LIFESTATE lifeState = NEUTRAL_STATE;
@@ -102,7 +105,7 @@ class MicrobeAISystem : ScriptSystem{
// This list is quite expensive to build each frame but
// there's currently no good way to cache this
array@ allMicrobes = world.GetScriptComponentHolder("MicrobeComponent").GetIndex();
-
+ array@ allChunks = world.GetComponentIndex_EngulfableComponent();
for(uint i = 0; i < CachedComponents.length(); ++i){
@@ -129,6 +132,9 @@ class MicrobeAISystem : ScriptSystem{
if (aiComponent.speciesFocus == -1.0f){
aiComponent.speciesFocus = ourSpecies.focus;
}
+ if (aiComponent.speciesOpportunism == -1.0f){
+ aiComponent.speciesOpportunism = ourSpecies.opportunism;
+ }
}
// Were for debugging
/*LOG_INFO("AI aggression"+aiComponent.speciesAggression);
@@ -144,6 +150,7 @@ class MicrobeAISystem : ScriptSystem{
// Clear the lists
aiComponent.predatoryMicrobes.removeRange(0,aiComponent.predatoryMicrobes.length());
aiComponent.preyMicrobes.removeRange(0,aiComponent.preyMicrobes.length());
+ aiComponent.chunkList.removeRange(0,aiComponent.chunkList.length());
ObjectID prey = NULL_OBJECT;
// Peg your prey
if (!aiComponent.preyPegged){
@@ -154,8 +161,12 @@ class MicrobeAISystem : ScriptSystem{
aiComponent.preyPegged=true;
}
}
- ObjectID predator = getNearestPredatorItem(components,allMicrobes);
+
+ aiComponent.targetChunk=NULL_OBJECT;
+ aiComponent.targetChunk = getNearestChunkItem(components,allChunks);
+
+ ObjectID predator = getNearestPredatorItem(components,allMicrobes);
//30 seconds about
if (aiComponent.boredom == GetEngine().GetRandom().GetNumber(aiComponent.speciesFocus*2,1000.0f+aiComponent.speciesFocus*2)){
// Occassionally you need to reevaluate things
@@ -191,7 +202,13 @@ class MicrobeAISystem : ScriptSystem{
case GATHERING_STATE:
{
//In this state you gather compounds
+ if (rollCheck(aiComponent.speciesOpportunism,400.0f)){
+ aiComponent.lifeState= SCAVENGING_STATE;
+ aiComponent.boredom = 0;
+ }
+ else {
doRunAndTumble(components);
+ }
break;
}
case FLEEING_STATE:
@@ -230,6 +247,23 @@ class MicrobeAISystem : ScriptSystem{
}
break;
}
+ case SCAVENGING_STATE:
+ {
+ if (aiComponent.targetChunk != NULL_OBJECT){
+ dealWithChunks(components, aiComponent.targetChunk, allChunks);
+ }
+ else{
+ if (!rollCheck(aiComponent.speciesOpportunism, 400)){
+ //LOG_INFO("gather only");
+ aiComponent.lifeState = NEUTRAL_STATE;
+ aiComponent.boredom=0;
+ }
+ else{
+ aiComponent.lifeState = NEUTRAL_STATE;
+ }
+ }
+ break;
+ }
}
/* Check if we are willing to run, and there is a predator nearby, if so, flee for your life
@@ -242,7 +276,7 @@ class MicrobeAISystem : ScriptSystem{
Float3 testPosition = world.GetComponent_Position(predator)._Position;
MicrobeComponent@ secondMicrobeComponent = cast(
world.GetScriptComponentHolder("MicrobeComponent").Find(predator));
- if ((position._Position - testPosition).LengthSquared() <= (2000+(secondMicrobeComponent.organelles.length()*8.0f)*2)){
+ if ((position._Position - testPosition).LengthSquared() <= (2000+(secondMicrobeComponent.totalHexCountCache*8.0f)*2)){
if (aiComponent.lifeState != FLEEING_STATE)
{
// Reset target position for faster fleeing
@@ -259,6 +293,53 @@ class MicrobeAISystem : ScriptSystem{
aiComponent.previousStoredCompounds = microbeComponent.stored;
}
}
+ // deal with chunks
+ ObjectID getNearestChunkItem(MicrobeAISystemCached@ components, array@ allChunks){
+ ObjectID microbeEntity = components.entity;
+ MicrobeAIControllerComponent@ aiComponent = components.first;
+ MicrobeComponent@ microbeComponent = components.second;
+ Position@ position = components.third;
+ ObjectID chosenChunk = NULL_OBJECT;
+
+
+ // Retrieve nearest potential chunk
+ for (uint i = 0; i < allChunks.length(); i++){
+ // Get the microbe component
+ auto compoundBag = world.GetComponent_CompoundBagComponent(allChunks[i]);
+ // Get the microbe component
+ auto engulfableComponent = world.GetComponent_EngulfableComponent(allChunks[i]);
+
+ if ((aiComponent.speciesOpportunism==MAX_SPECIES_OPPORTUNISM) or
+ ((((microbeComponent.totalHexCountCache)*1.0f)*(aiComponent.speciesOpportunism/OPPORTUNISM_DIVISOR)) >
+ (engulfableComponent.getSize()*1.0f))){
+ //You are non-threatening to me
+ aiComponent.chunkList.insertLast(allChunks[i]);
+ }
+ }
+ // Get the nearest one if it exists
+ if (aiComponent.chunkList.length() > 0 )
+ {
+ //LOG_INFO(""+aiComponent.chunkList.length());
+ if (world.GetComponent_Position(aiComponent.chunkList[0]) !is null)
+ {
+ Float3 testPosition = world.GetComponent_Position(aiComponent.chunkList[0])._Position;
+ chosenChunk = aiComponent.chunkList[0];
+ for (uint c = 0; c < aiComponent.chunkList.length(); c++){
+ // Get position
+ Position@ thisPosition = world.GetComponent_Position(aiComponent.chunkList[c]);
+ if (thisPosition !is null){
+ if ((testPosition - position._Position).LengthSquared() > (thisPosition._Position - position._Position).LengthSquared()){
+ testPosition = thisPosition._Position;
+ chosenChunk = aiComponent.chunkList[c];
+ }
+ }
+ }
+ }
+
+ }
+
+ return chosenChunk;
+ }
// Building the prey list and returning the best option
ObjectID getNearestPreyItem(MicrobeAISystemCached@ components, array@ allMicrobes){
@@ -283,8 +364,8 @@ class MicrobeAISystem : ScriptSystem{
// At max aggression add them all
if (allMicrobes[i] != microbeEntity && (secondMicrobeComponent.speciesName != microbeComponent.speciesName) && !secondMicrobeComponent.dead){
if ((aiComponent.speciesAggression==MAX_SPECIES_AGRESSION) or
- ((((numberOfAgentVacuoles+microbeComponent.organelles.length())*1.0f)*(aiComponent.speciesAggression/AGRESSION_DIVISOR)) >
- (secondMicrobeComponent.organelles.length()*1.0f))){
+ ((((numberOfAgentVacuoles+microbeComponent.totalHexCountCache)*1.0f)*(aiComponent.speciesAggression/AGRESSION_DIVISOR)) >
+ (secondMicrobeComponent.totalHexCountCache*1.0f))){
//You are non-threatening to me
aiComponent.preyMicrobes.insertLast(allMicrobes[i]);
}
@@ -338,8 +419,8 @@ class MicrobeAISystem : ScriptSystem{
// At max fear add them all
if (allMicrobes[i] != microbeEntity && (secondMicrobeComponent.speciesName != microbeComponent.speciesName) && !secondMicrobeComponent.dead){
if ((aiComponent.speciesFear==MAX_SPECIES_FEAR) or
- ((((numberOfAgentVacuoles+secondMicrobeComponent.organelles.length())*1.0f)*(aiComponent.speciesFear/FEAR_DIVISOR)) >
- (microbeComponent.organelles.length()*1.0f))){
+ ((((numberOfAgentVacuoles+secondMicrobeComponent.totalHexCountCache)*1.0f)*(aiComponent.speciesFear/FEAR_DIVISOR)) >
+ (microbeComponent.totalHexCountCache*1.0f))){
//You are bigger then me and i am afraid of that
aiComponent.predatoryMicrobes.insertLast(allMicrobes[i]);
//LOG_INFO("Added predator " + allMicrobes[i] );
@@ -427,19 +508,24 @@ class MicrobeAISystem : ScriptSystem{
if (!microbeComponent.isPlayerMicrobe && microbeComponent.speciesName != playerSpecies.name){
MicrobeOperations::alterSpeciesPopulation(world,microbeEntity,CREATURE_KILL_POPULATION_GAIN);
}
+
+ if (rollCheck(aiComponent.speciesOpportunism,400.0f)){
+ aiComponent.lifeState= SCAVENGING_STATE;
+ }
+
}
else
{
// Turn on engulfmode if close
- if (((position._Position - aiComponent.targetPosition).LengthSquared() <= 300+(microbeComponent.organelles.length()*3.0f))
+ if (((position._Position - aiComponent.targetPosition).LengthSquared() <= 300+(microbeComponent.totalHexCountCache*3.0f))
&& (MicrobeOperations::getCompoundAmount(world,microbeEntity,atpID) >= 1.0f)
&& !microbeComponent.engulfMode &&
- (float(microbeComponent.organelles.length()) > (
- ENGULF_HP_RATIO_REQ*secondMicrobeComponent.organelles.length()))){
+ (float(microbeComponent.totalHexCountCache) > (
+ ENGULF_HP_RATIO_REQ*secondMicrobeComponent.totalHexCountCache))){
MicrobeOperations::toggleEngulfMode(world, microbeEntity);
aiComponent.ticksSinceLastToggle=0;
}
- else if (((position._Position - aiComponent.targetPosition).LengthSquared() >= 500+(microbeComponent.organelles.length()*3.0f))
+ else if (((position._Position - aiComponent.targetPosition).LengthSquared() >= 500+(microbeComponent.totalHexCountCache*3.0f))
&& (microbeComponent.engulfMode && aiComponent.ticksSinceLastToggle >= AI_ENGULF_INTERVAL)){
MicrobeOperations::toggleEngulfMode(world, microbeEntity);
aiComponent.ticksSinceLastToggle=0;
@@ -463,6 +549,71 @@ class MicrobeAISystem : ScriptSystem{
}
}
+ // For chasing down and eating chunka in various ways
+ void dealWithChunks(MicrobeAISystemCached@ components, ObjectID chunk, array@ allChunks )
+ {
+ //LOG_INFO("chasing"+prey);
+ // Set Components
+ ObjectID microbeEntity = components.entity;
+ MicrobeAIControllerComponent@ aiComponent = components.first;
+ MicrobeComponent@ microbeComponent = components.second;
+ Position@ position = components.third;
+ // Tick the engulf tick
+ aiComponent.ticksSinceLastToggle+=1;
+ // Required For AI
+ CompoundId ironId = SimulationParameters::compoundRegistry().getTypeId("iron");
+ CompoundId atpID = SimulationParameters::compoundRegistry().getTypeId("atp");
+ //LOG_INFO("predating");
+ auto compoundBag = world.GetComponent_CompoundBagComponent(chunk);
+ // Get the engulfablecomponent
+ auto engulfableComponent = world.GetComponent_EngulfableComponent(chunk);
+ if (engulfableComponent is null){
+ aiComponent.targetChunk = NULL_OBJECT;
+ //(maybe immediately target a new one)
+ return;
+ }
+
+ aiComponent.targetPosition = world.GetComponent_Position(chunk)._Position;
+ auto vec = (aiComponent.targetPosition - position._Position);
+ aiComponent.direction = vec.Normalize();
+ microbeComponent.facingTargetPoint = aiComponent.targetPosition;
+ aiComponent.hasTargetPosition = true;
+
+ //Always set target Position, for use later in AI
+ microbeComponent.movementDirection = Float3(0, 0, -AI_BASE_MOVEMENT);
+
+ // Turn off engulf if chunk is gone
+ if (engulfableComponent is null){
+ aiComponent.hasTargetPosition = false;
+ aiComponent.targetChunk=getNearestChunkItem(components,allChunks);
+ if (microbeComponent.engulfMode){
+ MicrobeOperations::toggleEngulfMode(world, microbeEntity);
+ }
+ // You got a consumption, good job
+ auto playerSpecies = MicrobeOperations::getSpeciesComponent(world, "Default");
+ if (!microbeComponent.isPlayerMicrobe && microbeComponent.speciesName != playerSpecies.name){
+ MicrobeOperations::alterSpeciesPopulation(world,microbeEntity,CREATURE_SCAVENGE_POPULATION_GAIN);
+ }
+ }
+ else
+ {
+ // Turn on engulfmode if close
+ if (((position._Position - aiComponent.targetPosition).LengthSquared() <= 300+(microbeComponent.totalHexCountCache*3.0f))
+ && (MicrobeOperations::getCompoundAmount(world,microbeEntity,atpID) >= 1.0f)
+ && !microbeComponent.engulfMode &&
+ (float(microbeComponent.totalHexCountCache) > (
+ ENGULF_HP_RATIO_REQ*engulfableComponent.getSize()))){
+ MicrobeOperations::toggleEngulfMode(world, microbeEntity);
+ aiComponent.ticksSinceLastToggle=0;
+ }
+ else if (((position._Position - aiComponent.targetPosition).LengthSquared() >= 500+(microbeComponent.totalHexCountCache*3.0f))
+ && (microbeComponent.engulfMode && aiComponent.ticksSinceLastToggle >= AI_ENGULF_INTERVAL)){
+ MicrobeOperations::toggleEngulfMode(world, microbeEntity);
+ aiComponent.ticksSinceLastToggle=0;
+ }
+ }
+ }
+
// For self defense (not necessarily fleeing)
void dealWithPredators(MicrobeAISystemCached@ components, ObjectID predator)
{
@@ -530,7 +681,12 @@ class MicrobeAISystem : ScriptSystem{
//LOG_INFO("evaluating");
MicrobeAIControllerComponent@ aiComponent = components.first;
Position@ position = components.third;
- if (rollCheck(aiComponent.speciesActivity,500.0f))
+ if (rollCheck(aiComponent.speciesOpportunism,500.0f))
+ {
+ aiComponent.lifeState = SCAVENGING_STATE;
+ aiComponent.boredom = 0;
+ }
+ else if (rollCheck(aiComponent.speciesActivity,500.0f))
{
aiComponent.lifeState = PLANTLIKE_STATE;
aiComponent.boredom = 0;
@@ -571,6 +727,10 @@ class MicrobeAISystem : ScriptSystem{
aiComponent.lifeState = GATHERING_STATE;
}
}
+ else if (aiComponent.targetChunk != NULL_OBJECT){
+ //LOG_INFO("prey only");
+ aiComponent.lifeState = SCAVENGING_STATE;
+ }
// Every 2 intervals or so
else if (GetEngine().GetRandom().GetNumber(0,10) < 8){
//LOG_INFO("gather only");
diff --git a/scripts/microbe_stage/microbe_editor/microbe_editor.as b/scripts/microbe_stage/microbe_editor/microbe_editor.as
index 76980186888..f8671a8948c 100644
--- a/scripts/microbe_stage/microbe_editor/microbe_editor.as
+++ b/scripts/microbe_stage/microbe_editor/microbe_editor.as
@@ -874,21 +874,31 @@ class MicrobeEditor{
return editedMicrobe.length();
}
+ int getActualMicrobeSize() const
+ {
+ int lengthMicrobe = 0;
+ for(uint i = 0; i < editedMicrobe.length(); ++i){
+ auto organelle = cast(editedMicrobe[i]);
+ lengthMicrobe+=organelle.organelle.getHexCount();
+ }
+ return lengthMicrobe;
+ }
// Make sure this is only called when you add organelles, as it is an expensive
double getMicrobeSpeed() const
{
double finalSpeed = 0;
int flagCount=0;
- double lengthMicrobe = double(editedMicrobe.length());
+ double lengthMicrobe = 0;
for(uint i = 0; i < editedMicrobe.length(); ++i){
auto organelle = cast(editedMicrobe[i]);
+ lengthMicrobe+=organelle.organelle.getHexCount();
auto name = organelle.organelle.name;
if (name=="flagellum"){
flagCount++;
}
}
//This is complex, i Know
- //LOG_INFO(""+flagCount);
+ //LOG_INFO(""+lengthMicrobe);
finalSpeed= ((CELL_BASE_THRUST+((flagCount/(lengthMicrobe-flagCount))*FLAGELLA_BASE_FORCE))+
(CELL_DRAG_MULTIPLIER-(CELL_SIZE_DRAG_MULTIPLIER*lengthMicrobe)));
return finalSpeed;
diff --git a/scripts/microbe_stage/microbe_editor/microbe_editor_hud.as b/scripts/microbe_stage/microbe_editor/microbe_editor_hud.as
index e244a025365..ddfe7e66d78 100644
--- a/scripts/microbe_stage/microbe_editor/microbe_editor_hud.as
+++ b/scripts/microbe_stage/microbe_editor/microbe_editor_hud.as
@@ -264,7 +264,7 @@ class MicrobeEditorHudSystem : ScriptSystem{
GenericEvent@ event = GenericEvent("SizeUpdated");
NamedVars@ vars = event.GetNamedVars();
- vars.AddValue(ScriptSafeVariableBlock("size", editor.getMicrobeSize()));
+ vars.AddValue(ScriptSafeVariableBlock("size", editor.getActualMicrobeSize()));
GetEngine().GetEventHandler().CallEvent(event);
}
diff --git a/scripts/microbe_stage/microbe_operations.as b/scripts/microbe_stage/microbe_operations.as
index 389228ad4c5..a1890ba6ba7 100644
--- a/scripts/microbe_stage/microbe_operations.as
+++ b/scripts/microbe_stage/microbe_operations.as
@@ -627,23 +627,22 @@ void emitAgent(CellStageWorld@ world, ObjectID microbeEntity, CompoundId compoun
{
// The front of the microbe
Float3 exit = Hex::axialToCartesian(0, 1);
+ //This will get what it thinks is the "edge"
auto membraneCoords = membraneComponent.GetExternalOrganelle(exit.X, exit.Z);
- //Get the distance to eject the compunds
- auto maxR = 0;
+
+ //This adds the nucleus r (y) so that it can deal with weird nucleus positioning,
+ //and that is all we actually need
+ int maxR = 2;
for(uint i = 0; i < microbeComponent.organelles.length(); ++i){
- auto organelle = microbeComponent.organelles[i];
- auto hexes = organelle.organelle.getHexes();
- for(uint a = 0; a < hexes.length(); ++a){
- auto hex = hexes[a];
- if(hex.r + organelle.r > maxR){
- maxR = hex.r + organelle.r;
- }
+ auto organelle = cast(microbeComponent.organelles[i]);
+ if (organelle.organelle.name == "nucleus"){
+ maxR=maxR+(-organelle.r);
}
}
+
//The distance is two hexes away from the back of the microbe.
//This distance could be precalculated when adding/removing an organelle
//for more efficient pooping.
- auto ejectionDistance = (maxR) * HEX_SIZE/2;
auto angle = 180;
// Find the direction the microbe is facing
auto yAxis = Ogre::Quaternion(cellPosition._Orientation).zAxis();
@@ -657,8 +656,9 @@ void emitAgent(CellStageWorld@ world, ObjectID microbeEntity, CompoundId compoun
auto s = sin(finalAngle/180*PI);
auto c = cos(finalAngle/180*PI);
// Membrane coords to world coords
- auto xnew = -membraneCoords.x * c + membraneCoords.z * s;
- auto ynew = membraneCoords.x * s + membraneCoords.z * c;
+ // Plus bunch more space in world coordinates like we added before with maxr but cleaner
+ auto xnew = -(membraneCoords.x) * c + (membraneCoords.z+maxR*HEX_SIZE) * s;
+ auto ynew = (membraneCoords.x)* s + (membraneCoords.z+maxR*HEX_SIZE) * c;
// Find the direction the microbe is facing
auto vec = ( microbeComponent.facingTargetPoint - cellPosition._Position);
auto direction = vec.Normalize();
@@ -668,8 +668,8 @@ void emitAgent(CellStageWorld@ world, ObjectID microbeEntity, CompoundId compoun
if (amountToEject >= MINIMUM_AGENT_EMISSION_AMOUNT)
{
playSoundWithDistance(world, "Data/Sound/soundeffects/microbe-release-toxin.ogg",microbeEntity);
- createAgentCloud(world, compoundId, cellPosition._Position+Float3(xnew*ejectionDistance,0,ynew*ejectionDistance),
- direction, amountToEject, lifeTime, microbeComponent.speciesName);
+ createAgentCloud(world, compoundId, cellPosition._Position+Float3(xnew,0,ynew),
+ direction, amountToEject, lifeTime, microbeComponent.speciesName, microbeEntity);
// The cooldown time is inversely proportional to the amount of agent vacuoles.
@@ -1119,7 +1119,8 @@ void kill(CellStageWorld@ world, ObjectID microbeEntity)
LOG_ERROR("Trying to kill a dead microbe");
return;
}
-
+ //diable engulf mode when a cell dies
+ microbeComponent.engulfMode = false;
// Releasing all the agents.
// To not completely deadlock in this there is a maximum of 5 of these created
const int maxAgentsToShoot = 5;
@@ -1136,7 +1137,9 @@ void kill(CellStageWorld@ world, ObjectID microbeEntity)
0, GetEngine().GetRandom().GetNumber(0.0f, 1.0f) * 2 - 1);
createAgentCloud(world, compoundId, position._Position, direction, ejectedAmount,
- 2000, microbeComponent.speciesName);
+ 2000, microbeComponent.speciesName, NULL_OBJECT);
+ //take oxytoxy
+ takeCompound(world,microbeEntity,compoundId,ejectedAmount);
++createdAgents;
if(createdAgents >= maxAgentsToShoot)
@@ -1174,37 +1177,66 @@ void kill(CellStageWorld@ world, ObjectID microbeEntity)
}
}
- // They were added in order already so looping through this other thing is fine
- for(uint64 compoundID = 0; compoundID <
+
+
+ for(uint i = 0; i < uint(max(1,microbeComponent.totalHexCountCache/CORPSE_CHUNK_DIVISER)); ++i){
+ //Amount of compound in one chunk
+ double amount = double(microbeComponent.totalHexCountCache)/CORPSE_CHUNK_AMOUNT_DIVISER;
+ // Chunk(should separate into own function)
+ ObjectID chunkEntity = world.CreateEntity();
+ auto positionAdded = Float3(GetEngine().GetRandom().GetFloat(-2.0f, 2.0f),0,
+ GetEngine().GetRandom().GetFloat(-2.0f, 2.0f));
+ auto chunkPosition = world.Create_Position(chunkEntity, position._Position+positionAdded,
+ Ogre::Quaternion(Ogre::Degree(GetEngine().GetRandom().GetNumber(0, 360)),
+ Ogre::Vector3(0,1,1)));
+
+ auto renderNode = world.Create_RenderNode(chunkEntity);
+ renderNode.Scale = Float3(1.0f, 1.0f, 1.0f);
+ renderNode.Marked = true;
+ renderNode.Node.setOrientation(Ogre::Quaternion(
+ Ogre::Degree(GetEngine().GetRandom().GetNumber(0, 360)), Ogre::Vector3(0,1,1)));
+ renderNode.Node.setPosition(chunkPosition._Position);
+ // Grab random organelle from cell and use that
+ auto organelleIndex = GetEngine().GetRandom().GetNumber(0, microbeComponent.organelles.length()-1);
+ string mesh = microbeComponent.organelles[organelleIndex].organelle.mesh;
+ if (mesh != "")
+ {
+ auto model = world.Create_Model(chunkEntity, renderNode.Node, mesh);
+ // Color chunk based on cell
+ model.GraphicalObject.setCustomParameter(1, microbeComponent.speciesColour);
+ }
+ else {
+ auto model = world.Create_Model(chunkEntity, renderNode.Node, "mitochondrion.mesh");
+ // Color chunk based on cell
+ model.GraphicalObject.setCustomParameter(1, microbeComponent.speciesColour);
+ }
+ auto rigidBody = world.Create_Physics(chunkEntity, chunkPosition);
+ auto body = rigidBody.CreatePhysicsBody(world.GetPhysicalWorld(),
+ world.GetPhysicalWorld().CreateSphere(1), 10,
+ //engulfable
+ world.GetPhysicalMaterial("iron"));
+ body.ConstraintMovementAxises();
+ rigidBody.JumpTo(chunkPosition);
+ auto venter = world.Create_CompoundVenterComponent(chunkEntity);
+ //Engulfable
+ auto engulfable = world.Create_EngulfableComponent(chunkEntity);
+ engulfable.setSize(2);
+ // So that larger iron chunks give out more compounds
+ venter.setVentAmount(3);
+ venter.setDoDissolve(true);
+ auto bag = world.Create_CompoundBagComponent(chunkEntity);
+ // They were added in order already so looping through this other thing is fine
+ for(uint64 compoundID = 0; compoundID <
SimulationParameters::compoundRegistry().getSize(); ++compoundID)
- {
- //LOG_INFO(""+float(compoundsToRelease[formatInt(compoundID)]));
- //LOG_INFO(""+float(compoundsToRelease[formatUInt(compoundID)]));
- if (SimulationParameters::compoundRegistry().getTypeData(compoundID).isCloud &&
- float(compoundsToRelease[formatUInt(compoundID)]) > 0.0f)
{
- //Earlier we added all of the keys to the list by ID,in order, so this is fine
- //LOG_INFO("Releasing "+float(compoundsToRelease[formatUInt(compoundID)]));
- if (SimulationParameters::compoundRegistry().getTypeData(compoundID).isCloud)
- {
- ejectCompound(world, microbeEntity, uint64(compoundID),float(compoundsToRelease[formatUInt(compoundID)]));
- }
+ //Randomize compound amount a bit so things "rot away"
+ bag.setCompound(compoundID, (float(compoundsToRelease[formatUInt(compoundID)])/
+ GetEngine().GetRandom().GetFloat(amount/3.0f, amount)*CORPSE_COMPOUND_COMPENSATION));
}
- }
-
+ }
// Play the death sound
playSoundWithDistance(world, "Data/Sound/soundeffects/microbe-death.ogg", microbeEntity);
- //TODO: Get this working
- //auto deathAnimationEntity = world.CreateEntity();
- //auto lifeTimeComponent = world.Create_TimedLifeComponent(deathAnimationEntity, 4000);
- //auto deathAnimSceneNode = world.Create_RenderNode(deathAnimationEntity);
- //auto deathAnimModel = world.Create_Model(deathAnimationEntity, deathAnimSceneNode.Node,
- // "MicrobeDeath.mesh");
- //deathAnimSceneNode.Node.setPosition(position._Position);
-
- //LOG_WRITE("TODO: play animation deathAnimModel");
- // deathAnimModel.GraphicalObject.playAnimation("Death", false);
//subtract population
auto playerSpecies = MicrobeOperations::getSpeciesComponent(world, "Default");
if (!microbeComponent.isPlayerMicrobe &&
@@ -1217,6 +1249,10 @@ void kill(CellStageWorld@ world, ObjectID microbeEntity)
microbeComponent.dead = true;
microbeComponent.deathTimer = 5000;
microbeComponent.movementDirection = Float3(0,0,0);
+ //so they stop absorbing the compounds from the chunks they release immediately
+ auto compoundAbsorberComponent = world.GetComponent_CompoundAbsorberComponent(
+ microbeEntity);
+ compoundAbsorberComponent.disable();
if(rigidBodyComponent.Body !is null)
rigidBodyComponent.Body.ClearVelocity();
diff --git a/scripts/microbe_stage/organelle_table.as b/scripts/microbe_stage/organelle_table.as
index f1a2b0bbc2e..5489685cda1 100644
--- a/scripts/microbe_stage/organelle_table.as
+++ b/scripts/microbe_stage/organelle_table.as
@@ -263,8 +263,8 @@ void setupOrganelles(){
};
nucleusParameters.components = {
nucleusComponentFactory,
- // Cell takes up 10 spaces, so 50 cytoplasm
- storageOrganelleFactory(55.0f)
+ // Same storage as vacuole
+ storageOrganelleFactory(15.0f)
};
nucleusParameters.processes = {
};
@@ -300,7 +300,7 @@ void setupOrganelles(){
};
cytoplasmParameters.components = {
processorOrganelleFactory(1.0),
- storageOrganelleFactory(20.0f)
+ storageOrganelleFactory(4.0f)
};
cytoplasmParameters.processes = {
TweakedProcess("glycolosis", 1)
@@ -327,8 +327,8 @@ void setupOrganelles(){
};
chloroplastParameters.components = {
processorOrganelleFactory(1.0),
- //chloroplast takes 3 hexes, so allowed storage of 3 cytooplasm
- storageOrganelleFactory(15.0f)
+ //chloroplast takes 3 hexes, so allowed storage of 1 cytoplasm
+ storageOrganelleFactory(2.0f)
};
chloroplastParameters.processes = {
TweakedProcess("photosynthesis", 1)
@@ -357,7 +357,8 @@ void setupOrganelles(){
};
oxytoxyParameters.components = {
//this can't hold since it is a vacuole
- agentVacuoleFactory("oxytoxy", "oxytoxySynthesis")
+ agentVacuoleFactory("oxytoxy", "oxytoxySynthesis"),
+ storageOrganelleFactory(5.0f)
};
oxytoxyParameters.processes = {
TweakedProcess("oxytoxySynthesis", 1)
@@ -385,8 +386,8 @@ void setupOrganelles(){
};
mitochondrionParameters.components = {
processorOrganelleFactory(1.0f),
- // Mitochondria takes 2 hexes, so allowed storage of 2 cytooplasm
- storageOrganelleFactory(10.0f)
+ // Mitochondria takes 2 hexes, so allowed storage of 1 cytooplasm
+ storageOrganelleFactory(2.0f)
};
mitochondrionParameters.processes = {
TweakedProcess("respiration", 1)
@@ -413,7 +414,7 @@ void setupOrganelles(){
{"ammonia", 2}
};
vacuoleParameters.components = {
- storageOrganelleFactory(40.0f)
+ storageOrganelleFactory(15.0f)
};
vacuoleParameters.processes = {
@@ -442,7 +443,7 @@ void setupOrganelles(){
flagellumParameters.components = {
movementOrganelleFactory(20, 300),
// Flagella takes 1 hex, so allowed storage of 1 cytooplasm
- storageOrganelleFactory(5.0f)
+ storageOrganelleFactory(1.0f)
};
flagellumParameters.processes = {
@@ -471,8 +472,8 @@ void setupOrganelles(){
};
chemoplast.components = {
processorOrganelleFactory(1.0f),
- // Chemoplast takes 2 hexes, so allowed storage of 2 cytooplasm
- storageOrganelleFactory(10.0f)
+ // Chemoplast takes 2 hexes, so allowed storage of 1 cytooplasm
+ storageOrganelleFactory(2.0f)
};
chemoplast.processes = {
TweakedProcess("chemoSynthesis", 1)
@@ -500,8 +501,8 @@ void setupOrganelles(){
};
nitrogenPlastid.components = {
processorOrganelleFactory(1.0f),
- // nitrogenPlastid takes 2 hexes, so allowed storage of 2 cytooplasm
- storageOrganelleFactory(10.0f)
+ // nitrogenPlastid takes 2 hexes, so allowed storage of 1 cytooplasm
+ storageOrganelleFactory(2.0f)
};
nitrogenPlastid.processes = {
TweakedProcess("nitrogenFixing", 1)
@@ -530,7 +531,7 @@ void setupOrganelles(){
};
respiratoryProtein.components = {
processorOrganelleFactory(1.0f),
- storageOrganelleFactory(10.0f)
+ storageOrganelleFactory(1.0f)
};
respiratoryProtein.processes = {
TweakedProcess("protein_respiration", 1)
@@ -556,7 +557,7 @@ void setupOrganelles(){
};
photosyntheticProtein.components = {
processorOrganelleFactory(1.0f),
- storageOrganelleFactory(10.0f)
+ storageOrganelleFactory(1.0f)
};
photosyntheticProtein.processes = {
TweakedProcess("chromatophore_photosynthesis", 1),
@@ -583,7 +584,7 @@ void setupOrganelles(){
};
oxytoxyProtein.components = {
agentVacuoleFactory("oxytoxy", "oxytoxySynthesis"),
- storageOrganelleFactory(25.0f),
+ storageOrganelleFactory(2.0f),
processorOrganelleFactory(1.0f)
};
oxytoxyProtein.processes = {
@@ -612,7 +613,7 @@ void setupOrganelles(){
};
chemoSynthisizingProtein.components = {
processorOrganelleFactory(1.0f),
- storageOrganelleFactory(20.0f)
+ storageOrganelleFactory(1.0f)
};
chemoSynthisizingProtein.processes = {
TweakedProcess("bacterial_ChemoSynthesis", 1),
@@ -639,7 +640,7 @@ void setupOrganelles(){
};
protoplasmParameters.components = {
processorOrganelleFactory(1.0),
- storageOrganelleFactory(50.0f)
+ storageOrganelleFactory(15.0f)
};
protoplasmParameters.processes = {
TweakedProcess("glycolosis", 1)
@@ -665,7 +666,7 @@ void setupOrganelles(){
};
nitrogenFixationProtein.components = {
processorOrganelleFactory(1.0f),
- storageOrganelleFactory(25.0f)
+ storageOrganelleFactory(2.0f)
};
nitrogenFixationProtein.processes = {
TweakedProcess("nitrogenFixing", 1),
@@ -692,10 +693,10 @@ void setupOrganelles(){
};
rusticyanin.components = {
processorOrganelleFactory(1.0f),
- storageOrganelleFactory(5.0f)
+ storageOrganelleFactory(1.0f)
};
rusticyanin.processes = {
- TweakedProcess("iron_chemolithoautotrophy", 1)
+ TweakedProcess("iron_chemolithoautotrophy", 2)
};
rusticyanin.hexes = {
Int2(0, 0),
diff --git a/scripts/microbe_stage/procedural_microbes.as b/scripts/microbe_stage/procedural_microbes.as
index 4ab982b99e8..0b1206d4cc0 100644
--- a/scripts/microbe_stage/procedural_microbes.as
+++ b/scripts/microbe_stage/procedural_microbes.as
@@ -137,7 +137,7 @@ OrganelleTemplatePlaced@ getPosition(const string &in organelleName,
// Moving the center one hex to the bottom.
// This way organelles are "encouraged" to be on the bottom, rather than on the top,
// which in turn means the flagellum are more likely to be on the back side of the cell.
- auto initialOffset = Int2(HEX_NEIGHBOUR_OFFSET[formatInt(int(HEX_SIDE::BOTTOM))]);
+ auto initialOffset = Int2(HEX_NEIGHBOUR_OFFSET[formatInt(int(HEX_SIDE::TOP))]);
q = q + initialOffset.X;
r = r + initialOffset.Y;
diff --git a/scripts/microbe_stage/setup.as b/scripts/microbe_stage/setup.as
index 0be067ba685..a5a14332bf7 100644
--- a/scripts/microbe_stage/setup.as
+++ b/scripts/microbe_stage/setup.as
@@ -305,6 +305,7 @@ void cellHitFloatingOrganelle(GameWorld@ world, ObjectID firstEntity, ObjectID s
}
+// Will use this for food chunks now
void cellHitIron(GameWorld@ world, ObjectID firstEntity, ObjectID secondEntity)
{
// Determine which is the iron
@@ -321,6 +322,31 @@ void cellHitIron(GameWorld@ world, ObjectID firstEntity, ObjectID secondEntity)
floatingEntity = secondEntity;
cellEntity = firstEntity;
}
+ auto microbeComponent = MicrobeOperations::getMicrobeComponent(asCellWorld,cellEntity);
+
+ auto engulfableComponent = asCellWorld.GetComponent_EngulfableComponent(floatingEntity);
+
+ auto compoundBagComponent = asCellWorld.GetComponent_CompoundBagComponent(cellEntity);
+
+ auto floatBag = asCellWorld.GetComponent_CompoundBagComponent(floatingEntity);
+
+ if (microbeComponent !is null && engulfableComponent !is null
+ && compoundBagComponent !is null && floatBag !is null)
+ {
+ if (microbeComponent.engulfMode && microbeComponent.totalHexCountCache >=
+ engulfableComponent.getSize()*ENGULF_HP_RATIO_REQ)
+ {
+ uint64 compoundCount = SimulationParameters::compoundRegistry().getSize();
+ for(uint compoundId = 0; compoundId < compoundCount; ++compoundId){
+ CompoundId realCompoundId = compoundId;
+ double amountToTake =
+ floatBag.takeCompound(realCompoundId,floatBag.getCompoundAmount(realCompoundId));
+ // Right now you get way too much compounds for engulfing the things but hey
+ compoundBagComponent.giveCompound(realCompoundId, (amountToTake/CHUNK_ENGULF_COMPOUND_DIVISOR));
+ }
+ world.QueueDestroyEntity(floatingEntity);
+ }
+ }
}
// Cell Hit Oxytoxy
@@ -501,7 +527,8 @@ bool hitAgent(GameWorld@ world, ObjectID firstEntity, ObjectID secondEntity)
{
if (firstPropertiesComponent !is null && secondMicrobeComponent !is null)
{
- if (firstPropertiesComponent.getSpeciesName()==secondMicrobeComponent.speciesName)
+ if (firstPropertiesComponent.getSpeciesName()==secondMicrobeComponent.speciesName ||
+ firstPropertiesComponent.getParentEntity()==secondEntity)
{
shouldCollide = false;
return shouldCollide;
@@ -509,7 +536,8 @@ bool hitAgent(GameWorld@ world, ObjectID firstEntity, ObjectID secondEntity)
}
else if (secondPropertiesComponent !is null && firstMicrobeComponent !is null)
{
- if (secondPropertiesComponent.getSpeciesName()==firstMicrobeComponent.speciesName)
+ if (secondPropertiesComponent.getSpeciesName()==firstMicrobeComponent.speciesName ||
+ secondPropertiesComponent.getParentEntity()==firstEntity)
{
shouldCollide = false;
return shouldCollide;
@@ -528,25 +556,27 @@ bool hitAgent(GameWorld@ world, ObjectID firstEntity, ObjectID secondEntity)
}
void createAgentCloud(CellStageWorld@ world, CompoundId compoundId,
- Float3 pos, Float3 direction, float amount, float lifetime, string speciesName)
+ Float3 pos, Float3 direction, float amount, float lifetime,
+ string speciesName, ObjectID creatorEntity)
{
auto normalizedDirection = direction.Normalize();
auto agentEntity = world.CreateEntity();
auto position = world.Create_Position(agentEntity, pos + (direction * 1.5),
Ogre::Quaternion(Ogre::Degree(GetEngine().GetRandom().GetNumber(0, 360)),
- Ogre::Vector3(0, 1, 0)));
-
-
- auto rigidBody = world.Create_Physics(agentEntity, position);
+ Ogre::Vector3(0,1, 0)));
// Agent
auto agentProperties = world.Create_AgentProperties(agentEntity);
agentProperties.setSpeciesName(speciesName);
+ agentProperties.setParentEntity(creatorEntity);
agentProperties.setAgentType("oxytoxy");
+ auto rigidBody = world.Create_Physics(agentEntity, position);
+
+
auto body = rigidBody.CreatePhysicsBody(world.GetPhysicalWorld(),
- world.GetPhysicalWorld().CreateSphere(HEX_SIZE), 1,
+ world.GetPhysicalWorld().CreateSphere(HEX_SIZE), 0.5,
world.GetPhysicalMaterial("agentCollision"));
body.ConstraintMovementAxises();
@@ -617,6 +647,7 @@ ObjectID createToxin(CellStageWorld@ world, Float3 pos)
// Agent
auto agentProperties = world.Create_AgentProperties(toxinEntity);
agentProperties.setSpeciesName("");
+ agentProperties.setParentEntity(NULL_OBJECT);
agentProperties.setAgentType("oxytoxy");
auto model = world.Create_Model(toxinEntity, renderNode.Node, "oxytoxy.mesh");
@@ -656,6 +687,8 @@ ObjectID createIron(CellStageWorld@ world, Float3 pos)
// 5 is the default
float ironAmount = 3.0f;
double ironBagAmount= IRON_PER_SMALL_CHUNK;
+ bool dissolves=SMALL_IRON_DISSOLVES;
+ int ironEngulfSize = 2;
// There are four kinds
switch (GetEngine().GetRandom().GetNumber(0, 4))
{
@@ -675,7 +708,9 @@ ObjectID createIron(CellStageWorld@ world, Float3 pos)
mesh="iron_05.mesh";
ironSize=10;
ironAmount=10.0f;
+ ironEngulfSize = 100;
ironBagAmount=IRON_PER_BIG_CHUNK;
+ dissolves=LARGE_IRON_DISSOLVES;
break;
}
@@ -683,8 +718,10 @@ ObjectID createIron(CellStageWorld@ world, Float3 pos)
auto venter = world.Create_CompoundVenterComponent(ironEntity);
// So that larger iron chunks give out more compounds
venter.setVentAmount(ironAmount);
+ venter.setDoDissolve(dissolves);
auto bag = world.Create_CompoundBagComponent(ironEntity);
-
+ auto engulfable = world.Create_EngulfableComponent(ironEntity);
+ engulfable.setSize(ironEngulfSize);
bag.setCompound(SimulationParameters::compoundRegistry().getTypeId("iron"),ironBagAmount);
auto model = world.Create_Model(ironEntity, renderNode.Node, mesh);
// Need to set the tint
@@ -693,7 +730,7 @@ ObjectID createIron(CellStageWorld@ world, Float3 pos)
auto rigidBody = world.Create_Physics(ironEntity, position);
auto body = rigidBody.CreatePhysicsBody(world.GetPhysicalWorld(),
world.GetPhysicalWorld().CreateSphere(ironSize),100,
- //iron
+ //engulfable
world.GetPhysicalMaterial("iron"));
body.ConstraintMovementAxises();
diff --git a/scripts/microbe_stage/species_system.as b/scripts/microbe_stage/species_system.as
index 1feb5a73d12..a38d82b3b29 100644
--- a/scripts/microbe_stage/species_system.as
+++ b/scripts/microbe_stage/species_system.as
@@ -268,7 +268,7 @@ const dictionary DEFAULT_INITIAL_COMPOUNDS =
{"iron", InitialCompound(0)}
};
-// For iron phillic microbes
+// For ferrophillic microbes
const dictionary DEFAULT_INITIAL_COMPOUNDS_IRON =
{
{"atp", InitialCompound(30,300)},
@@ -280,6 +280,18 @@ const dictionary DEFAULT_INITIAL_COMPOUNDS_IRON =
{"iron", InitialCompound(30,300)}
};
+// For chemophillic microbes
+const dictionary DEFAULT_INITIAL_COMPOUNDS_CHEMO =
+ {
+ {"atp", InitialCompound(30,300)},
+ {"glucose", InitialCompound(10,30)},
+ {"ammonia", InitialCompound(30,100)},
+ {"phosphates", InitialCompound(0)},
+ {"hydrogensulfide", InitialCompound(30,300)},
+ {"oxytoxy", InitialCompound(0)},
+ {"iron", InitialCompound(0)}
+ };
+
string randomSpeciesName()
{
return "Species_" + formatInt(GetEngine().GetRandom().GetNumber(0, 10000));
@@ -312,15 +324,7 @@ class Species{
genus = generateNameSection();
epithet = generateNameSection();
- // Variables used in AI to determine general behavior
- this.aggression = GetEngine().GetRandom().GetFloat(0.0f,
- MAX_SPECIES_AGRESSION);
- this.fear = GetEngine().GetRandom().GetFloat(0.0f,
- MAX_SPECIES_FEAR);
- this.activity = GetEngine().GetRandom().GetFloat(0.0f,
- MAX_SPECIES_ACTIVITY);
- this.focus = GetEngine().GetRandom().GetFloat(0.0f,
- MAX_SPECIES_FOCUS);
+ initializeBehavior();
auto stringSize = GetEngine().GetRandom().GetNumber(MIN_INITIAL_LENGTH,
MAX_INITIAL_LENGTH);
@@ -332,11 +336,97 @@ class Species{
}
const auto cytoplasmGene = getOrganelleDefinition("cytoplasm").gene;
+ string energyGene = cytoplasmGene;
+ const auto bonusPadding = GetEngine().GetRandom().GetNumber(1, 10);
// it should always have a nucleus and a cytoplasm.
stringCode = getOrganelleDefinition("nucleus").gene +
cytoplasmGene;
+ // generated cells need to be viable for now. so heres all possible survival strategies i can think of
+ switch (GetEngine().GetRandom().GetNumber(0, 15))
+ {
+ case 0:
+ energyGene = getOrganelleDefinition("cytoplasm").gene;
+ //if cytoplasm you need a few more of them
+ for(int i = 0; i < bonusPadding; i++){
+ this.stringCode.insert(GetEngine().GetRandom().GetNumber(2,
+ stringCode.length()), energyGene);
+ }
+ break;
+ case 1:
+ energyGene = getOrganelleDefinition("metabolosome").gene;
+ break;
+ case 2:
+ energyGene = getOrganelleDefinition("rusticyanin").gene;
+ energyGene += getOrganelleDefinition("cytoplasm").gene;
+ break;
+ case 3:
+ energyGene = getOrganelleDefinition("cytoplasm").gene;
+ //if cytoplasm you need a few more of them
+ for(int i = 0; i < bonusPadding; i++){
+ this.stringCode.insert(GetEngine().GetRandom().GetNumber(2,
+ stringCode.length()), energyGene);
+ }
+ energyGene += getOrganelleDefinition("chemoSynthisizingProteins").gene;
+ break;
+ case 4:
+ energyGene = getOrganelleDefinition("mitochondrion").gene;
+ case 5:
+ energyGene = getOrganelleDefinition("chemoSynthisizingProteins").gene;
+ energyGene += getOrganelleDefinition("mitochondrion").gene;
+ case 6:
+ energyGene = getOrganelleDefinition("chloroplast").gene;
+ energyGene += getOrganelleDefinition("mitochondrion").gene;
+ case 7:
+ energyGene = getOrganelleDefinition("metabolosome").gene;
+ energyGene += getOrganelleDefinition("chemoSynthisizingProteins").gene;
+ break;
+ case 8:
+ energyGene = getOrganelleDefinition("metabolosome").gene;
+ energyGene += getOrganelleDefinition("chromatophors").gene;
+ case 9:
+ energyGene = getOrganelleDefinition("chromatophors").gene;
+ energyGene += getOrganelleDefinition("mitochondrion").gene;
+ break;
+ case 10:
+ energyGene = getOrganelleDefinition("chemoplast").gene;
+ energyGene += getOrganelleDefinition("mitochondrion").gene;
+ break;
+ case 11:
+ energyGene = getOrganelleDefinition("chemoplast").gene;
+ energyGene += getOrganelleDefinition("metabolosome").gene;
+ break;
+ case 12:
+ energyGene = getOrganelleDefinition("chromatophors").gene;
+ energyGene += getOrganelleDefinition("cytoplasm").gene;
+ break;
+ case 13:
+ energyGene = getOrganelleDefinition("chloroplast").gene;
+ energyGene += getOrganelleDefinition("cytoplasm").gene;
+ break;
+ case 14:
+
+ energyGene = getOrganelleDefinition("cytoplasm").gene;
+ //if cytoplasm you need a few more of them
+ for(int i = 0; i < bonusPadding; i++){
+ this.stringCode.insert(GetEngine().GetRandom().GetNumber(2,
+ stringCode.length()), energyGene);
+ }
+ energyGene += getOrganelleDefinition("chemoplast").gene;
+ break;
+ case 15:
+ energyGene = getOrganelleDefinition("chloroplast").gene;
+ energyGene += getOrganelleDefinition("metabolosome").gene;
+ break;
+ }
+
+ const auto energyPadding = GetEngine().GetRandom().GetNumber(1, 5);
+ for(int i = 0; i < energyPadding; i++){
+ this.stringCode.insert(GetEngine().GetRandom().GetNumber(2,
+ stringCode.length()), energyGene);
+ }
+
for(int i = 0; i < stringSize; i++){
this.stringCode += getRandomLetter(false);
}
@@ -346,8 +436,15 @@ class Species{
if (GetEngine().GetRandom().GetNumber(0, 100) <= 25)
{
for(int i = 0; i < cytoplasmPadding; i++){
- this.stringCode.insert(GetEngine().GetRandom().GetNumber(2,
+ if (GetEngine().GetRandom().GetNumber(0, 20)<= 10)
+ {
+ this.stringCode.insert(GetEngine().GetRandom().GetNumber(2,
+ stringCode.length()), energyGene);
+ }
+ else {
+ this.stringCode.insert(GetEngine().GetRandom().GetNumber(2,
stringCode.length()), cytoplasmGene);
+ }
}
}
@@ -398,15 +495,7 @@ class Species{
}
genus = parent.genus;
- // Variables used in AI to determine general behavior mutate these
- this.aggression = parent.aggression+GetEngine().GetRandom().GetFloat(
- MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION);
- this.fear = parent.fear+GetEngine().GetRandom().GetFloat(
- MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION);
- this.activity = parent.activity+GetEngine().GetRandom().GetFloat(
- MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION);
- this.focus = parent.focus+GetEngine().GetRandom().GetFloat(
- MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION);
+ mutateBehavior(parent);
// Make sure not over or under our scales
cleanPersonality();
@@ -493,8 +582,45 @@ class Species{
{
this.focus=0;
}
+
+ // Opportunism
+ if (this.opportunism > MAX_SPECIES_OPPORTUNISM)
+ {
+ this.opportunism=MAX_SPECIES_OPPORTUNISM;
+ }
+ if (this.opportunism < 0.0f)
+ {
+ this.opportunism=0;
+ }
}
+ private void initializeBehavior(){
+ // Variables used in AI to determine general behavior
+ this.aggression = GetEngine().GetRandom().GetFloat(0.0f,
+ MAX_SPECIES_AGRESSION);
+ this.fear = GetEngine().GetRandom().GetFloat(0.0f,
+ MAX_SPECIES_FEAR);
+ this.activity = GetEngine().GetRandom().GetFloat(0.0f,
+ MAX_SPECIES_ACTIVITY);
+ this.focus = GetEngine().GetRandom().GetFloat(0.0f,
+ MAX_SPECIES_FOCUS);
+ this.opportunism = GetEngine().GetRandom().GetFloat(0.0f,
+ MAX_SPECIES_OPPORTUNISM);
+ }
+
+ private void mutateBehavior(Species@ parent){
+ // Variables used in AI to determine general behavior mutate these
+ this.aggression = parent.aggression+GetEngine().GetRandom().GetFloat(
+ MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION);
+ this.fear = parent.fear+GetEngine().GetRandom().GetFloat(
+ MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION);
+ this.activity = parent.activity+GetEngine().GetRandom().GetFloat(
+ MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION);
+ this.focus = parent.focus+GetEngine().GetRandom().GetFloat(
+ MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION);
+ this.opportunism = parent.opportunism+GetEngine().GetRandom().GetFloat(
+ MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION);
+ }
private void commonConstructor(CellStageWorld@ world)
{
@forWorld = world;
@@ -505,12 +631,18 @@ class Species{
{
templateEntity = Species::createSpecies(forWorld, this.name, this.genus, this.epithet,
organelles, this.colour, this.isBacteria, this.speciesMembraneType,
- DEFAULT_INITIAL_COMPOUNDS_IRON, this.aggression, this.fear, this.activity, this.focus);
+ DEFAULT_INITIAL_COMPOUNDS_IRON, this.aggression, this.fear, this.activity, this.focus, this.opportunism);
+ }
+ else if (stringCode.findFirst('C') >= 0 || stringCode.findFirst('c') >= 0)
+ {
+ templateEntity = Species::createSpecies(forWorld, this.name, this.genus, this.epithet,
+ organelles, this.colour, this.isBacteria, this.speciesMembraneType,
+ DEFAULT_INITIAL_COMPOUNDS_CHEMO, this.aggression, this.fear, this.activity, this.focus, this.opportunism);
}
else {
templateEntity = Species::createSpecies(forWorld, this.name, this.genus, this.epithet,
organelles, this.colour, this.isBacteria, this.speciesMembraneType,
- DEFAULT_INITIAL_COMPOUNDS, this.aggression, this.fear, this.activity, this.focus);
+ DEFAULT_INITIAL_COMPOUNDS, this.aggression, this.fear, this.activity, this.focus, this.opportunism);
}
}
@@ -710,15 +842,7 @@ class Species{
genus = generateNameSection();
epithet = generateNameSection();
- // Variables used in AI to determine general behavior
- this.aggression = GetEngine().GetRandom().GetFloat(0.0f,
- MAX_SPECIES_AGRESSION);
- this.fear = GetEngine().GetRandom().GetFloat(0.0f,
- MAX_SPECIES_FEAR);
- this.activity = GetEngine().GetRandom().GetFloat(0.0f,
- MAX_SPECIES_ACTIVITY);
- this.focus = GetEngine().GetRandom().GetFloat(0.0f,
- MAX_SPECIES_FOCUS);
+ initializeBehavior();
// Bacteria are tiny, start off with a max of 3 hexes (maybe
// we should start them all off with just one? )
@@ -807,15 +931,7 @@ class Species{
}
- // Variables used in AI to determine general behavior mutate these
- this.aggression = parent.aggression+GetEngine().GetRandom().GetFloat(
- MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION);
- this.fear = parent.fear+GetEngine().GetRandom().GetFloat(
- MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION);
- this.activity = parent.activity+GetEngine().GetRandom().GetFloat(
- MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION);
- this.focus = parent.focus+GetEngine().GetRandom().GetFloat(
- MIN_SPECIES_PERSONALITY_MUTATION, MAX_SPECIES_PERSONALITY_MUTATION);
+ mutateBehavior(parent);
// Make sure not over or under our scales
cleanPersonality();
@@ -904,6 +1020,7 @@ class Species{
string epithet;
bool isBacteria;
double aggression = 100.0f;
+ double opportunism = 100.0f;
double fear = 100.0f;
double activity = 0.0f;
double focus = 0.0f;
@@ -948,9 +1065,6 @@ const auto INITIAL_BACTERIA = 4;
// If there are more species than this then all species get their population reduced by half
const auto MAX_SPECIES = 15;
-// If there are more bacteria than this then all species get their population reduced by half
-const auto MAX_BACTERIA = 6;
-
// If there are less species than this creates new ones.
const auto MIN_SPECIES = 3;
@@ -1002,7 +1116,7 @@ class SpeciesSystem : ScriptSystem{
// Various mass extinction events
// Only run one "big event" per turn
- if(species.length() > MAX_SPECIES+MAX_BACTERIA && !ranEventThisStep){
+ if(species.length() > MAX_SPECIES && !ranEventThisStep){
LOG_INFO("Mass extinction time");
// F to pay respects: TODO: add a notification for when this happens
ranEventThisStep = true;
@@ -1456,14 +1570,14 @@ ObjectID createSpecies(CellStageWorld@ world, const string &in name,
return createSpecies(world, name, "Player", "Species", convertedOrganelles,
fromTemplate.colour, fromTemplate.isBacteria, fromTemplate.speciesMembraneType,
- fromTemplate.compounds, 100.0f, 100.0f, 100.0f, 200.0f);
+ fromTemplate.compounds, 100.0f, 100.0f, 100.0f, 200.0f, 100.0f);
}
//! Creates an entity that has all the species stuff on it
//! AI controlled ones need to be in addition in SpeciesSystem
ObjectID createSpecies(CellStageWorld@ world, const string &in name, const string &in genus,
const string &in epithet, array organelles, Float4 colour,
bool isBacteria, MEMBRANE_TYPE speciesMembraneType, const dictionary &in compounds,
- double aggression, double fear, double activity, double focus)
+ double aggression, double fear, double activity, double focus, double opportunism)
{
ObjectID speciesEntity = world.CreateEntity();
@@ -1510,6 +1624,7 @@ ObjectID createSpecies(CellStageWorld@ world, const string &in name, const strin
speciesComponent.fear = fear;
speciesComponent.activity = activity;
speciesComponent.focus = focus;
+ speciesComponent.opportunism = opportunism;
// Iterates over all compounds, and sets amounts and priorities
uint64 compoundCount = SimulationParameters::compoundRegistry().getSize();
diff --git a/src/engine/component_types.h b/src/engine/component_types.h
index 5311d147e6f..e97b5c81a2d 100644
--- a/src/engine/component_types.h
+++ b/src/engine/component_types.h
@@ -22,7 +22,7 @@ enum class THRIVE_COMPONENT : uint16_t {
TIMED_LIFE,
PROPERTIES,
COMPOUND_VENTER,
-
+ ENGULFABLE,
// TODO: check is this needed for anything
// INVALID
};
diff --git a/src/general/properties_component.cpp b/src/general/properties_component.cpp
index 55e2e3e22aa..47321190827 100644
--- a/src/general/properties_component.cpp
+++ b/src/general/properties_component.cpp
@@ -20,6 +20,13 @@ std::string
{
return this->agentType;
}
+
+ObjectID
+ AgentProperties::getParentEntity()
+{
+ return this->parentId;
+}
+
void
AgentProperties::setSpeciesName(std::string newString)
{
@@ -30,3 +37,8 @@ void
{
this->agentType = newString;
}
+void
+ AgentProperties::setParentEntity(ObjectID parentId)
+{
+ this->parentId = parentId;
+}
\ No newline at end of file
diff --git a/src/general/properties_component.h b/src/general/properties_component.h
index 702728190a6..55b4f51e8d5 100644
--- a/src/general/properties_component.h
+++ b/src/general/properties_component.h
@@ -29,21 +29,26 @@ class AgentProperties : public Leviathan::Component {
static constexpr auto TYPE =
componentTypeConvert(THRIVE_COMPONENT::PROPERTIES);
- // For now this will be how we check species and agent type, i know its not
- // the most elegant but for what i want i dont think creating a whole array
- // of generic "properties" is a good use of time just yet.
+ // For now this will be how we check species and agent type and the entity
+ // ID of the parent cell, i know its not the most elegant but for what i
+ // want i dont think creating a whole array of generic "properties" is a
+ // good use of time just yet.
std::string
getSpeciesName();
std::string
getAgentType();
+ ObjectID
+ getParentEntity();
void
setSpeciesName(std::string newString);
void
setAgentType(std::string newString);
-
+ void
+ setParentEntity(ObjectID parentId);
std::string speciesName;
std::string agentType;
+ ObjectID parentId = NULL_OBJECT;
};
} // namespace thrive
diff --git a/src/microbe_stage/compound_venter_system.cpp b/src/microbe_stage/compound_venter_system.cpp
index 77bd1e9207a..c668f9918ba 100644
--- a/src/microbe_stage/compound_venter_system.cpp
+++ b/src/microbe_stage/compound_venter_system.cpp
@@ -21,6 +21,22 @@ using namespace thrive;
// CompoundVenterComponent
CompoundVenterComponent::CompoundVenterComponent() : Leviathan::Component(TYPE)
{}
+// ------------------------------------ //
+// EngulfableComponent
+EngulfableComponent::EngulfableComponent() : Leviathan::Component(TYPE) {}
+
+void
+ EngulfableComponent::setSize(float size)
+{
+ this->size = size;
+}
+
+float
+ EngulfableComponent::getSize()
+{
+ return this->size;
+}
+
void
CompoundVenterSystem::Run(CellStageWorld& world)
@@ -37,6 +53,7 @@ void
CompoundBagComponent& bag = std::get<0>(*value.second);
CompoundVenterComponent& venter = std::get<1>(*value.second);
// Loop through all the compounds in the storage bag and eject them
+ bool vented = false;
for(const auto& compound : bag.compounds) {
double compoundAmount = compound.second.amount;
CompoundId compoundId = compound.first;
@@ -45,8 +62,15 @@ void
venter.ventCompound(
position, compoundId, venter.ventAmount, world);
bag.takeCompound(compoundId, venter.ventAmount);
+ vented = true;
}
}
+
+ // If you did not vent anything this step and the venter component
+ // is flagged to dissolve you, dissolve you
+ if(vented == false && venter.getDoDissolve()) {
+ world.QueueDestroyEntity(value.first);
+ }
}
}
}
@@ -71,4 +95,16 @@ float
CompoundVenterComponent::getVentAmount()
{
return this->ventAmount;
+}
+
+void
+ CompoundVenterComponent::setDoDissolve(bool dissolve)
+{
+ this->doDissolve = dissolve;
+}
+
+bool
+ CompoundVenterComponent::getDoDissolve()
+{
+ return this->doDissolve;
}
\ No newline at end of file
diff --git a/src/microbe_stage/compound_venter_system.h b/src/microbe_stage/compound_venter_system.h
index eecaa20fbea..42c43345a3a 100644
--- a/src/microbe_stage/compound_venter_system.h
+++ b/src/microbe_stage/compound_venter_system.h
@@ -22,6 +22,8 @@ class CompoundVenterComponent : public Leviathan::Component {
float x, y;
float ventAmount = 5.0f;
+ bool doDissolve = false;
+
REFERENCE_HANDLE_UNCOUNTED_TYPE(CompoundVenterComponent);
static constexpr auto TYPE =
@@ -38,6 +40,30 @@ class CompoundVenterComponent : public Leviathan::Component {
float
getVentAmount();
+
+ void
+ setDoDissolve(bool dissolve);
+
+ bool
+ getDoDissolve();
+};
+
+class EngulfableComponent : public Leviathan::Component {
+public:
+ EngulfableComponent();
+
+ float size;
+
+ REFERENCE_HANDLE_UNCOUNTED_TYPE(EngulfableComponent);
+
+ static constexpr auto TYPE =
+ componentTypeConvert(THRIVE_COMPONENT::ENGULFABLE);
+
+ void
+ setSize(float size);
+
+ float
+ getSize();
};
class CompoundVenterSystem
diff --git a/src/microbe_stage/generate_cell_stage_world.rb b/src/microbe_stage/generate_cell_stage_world.rb
index db1e4defb63..c94fe5b4501 100644
--- a/src/microbe_stage/generate_cell_stage_world.rb
+++ b/src/microbe_stage/generate_cell_stage_world.rb
@@ -38,6 +38,7 @@
EntityComponent.new("ProcessorComponent", [ConstructorInfo.new([])]),
EntityComponent.new("CompoundBagComponent", [ConstructorInfo.new([])]),
EntityComponent.new("CompoundVenterComponent", [ConstructorInfo.new([])]),
+ EntityComponent.new("EngulfableComponent", [ConstructorInfo.new([])]),
EntityComponent.new("SpeciesComponent", [ConstructorInfo.new([
Variable.new("name", "std::string",
memberaccess: "name",
diff --git a/src/microbe_stage/process_system.cpp b/src/microbe_stage/process_system.cpp
index 0a02873acbe..caa1abd7753 100644
--- a/src/microbe_stage/process_system.cpp
+++ b/src/microbe_stage/process_system.cpp
@@ -101,7 +101,11 @@ double
void
CompoundBagComponent::giveCompound(CompoundId id, double amt)
{
+
compounds[id].amount += amt;
+ if(compounds[id].amount > storageSpace) {
+ compounds[id].amount = storageSpace;
+ }
}
void
diff --git a/src/microbe_stage/species.h b/src/microbe_stage/species.h
index 8537c685dcf..3aa53d0ea3d 100644
--- a/src/microbe_stage/species.h
+++ b/src/microbe_stage/species.h
@@ -22,6 +22,7 @@ class Species : public RegistryType {
std::string epithet;
double fear;
double aggression;
+ double opportunism;
double activity;
double focus;
MEMBRANE_TYPE speciesMembraneType;
diff --git a/src/microbe_stage/species_component.h b/src/microbe_stage/species_component.h
index 4ca1b1e9330..53132e8f888 100644
--- a/src/microbe_stage/species_component.h
+++ b/src/microbe_stage/species_component.h
@@ -37,6 +37,7 @@ class SpeciesComponent : public Leviathan::Component {
double fear;
double activity;
double focus;
+ double opportunism;
int32_t population;
int32_t generation;
diff --git a/src/scripting/script_initializer.cpp b/src/scripting/script_initializer.cpp
index 7263681dcdf..7d755ac806c 100644
--- a/src/scripting/script_initializer.cpp
+++ b/src/scripting/script_initializer.cpp
@@ -433,6 +433,8 @@ static uint16_t ProcessorComponentTYPEProxy =
static_cast(ProcessorComponent::TYPE);
static uint16_t CompoundVenterTYPEProxy =
static_cast(CompoundVenterComponent::TYPE);
+static uint16_t EngulfableComponentTYPEProxy =
+ static_cast(EngulfableComponent::TYPE);
static uint16_t SpawnedComponentTYPEProxy =
static_cast(SpawnedComponent::TYPE);
static uint16_t AgentCloudComponentTYPEProxy =
@@ -529,6 +531,42 @@ bool
asCALL_THISCALL) < 0) {
ANGELSCRIPT_REGISTERFAIL;
}
+
+ if(engine->RegisterObjectMethod("CompoundVenterComponent",
+ "bool getDoDissolve()",
+ asMETHOD(CompoundVenterComponent, getDoDissolve),
+ asCALL_THISCALL) < 0) {
+ ANGELSCRIPT_REGISTERFAIL;
+ }
+
+ if(engine->RegisterObjectMethod("CompoundVenterComponent",
+ "void setDoDissolve(bool dissolve)",
+ asMETHOD(CompoundVenterComponent, setDoDissolve),
+ asCALL_THISCALL) < 0) {
+ ANGELSCRIPT_REGISTERFAIL;
+ }
+
+ // ------------------------------------ //
+ if(engine->RegisterObjectType(
+ "EngulfableComponent", 0, asOBJ_REF | asOBJ_NOCOUNT) < 0) {
+ ANGELSCRIPT_REGISTERFAIL;
+ }
+
+ if(!bindComponentTypeId(
+ engine, "EngulfableComponent", &EngulfableComponentTYPEProxy))
+ return false;
+
+ if(engine->RegisterObjectMethod("EngulfableComponent", "float getSize()",
+ asMETHOD(EngulfableComponent, getSize), asCALL_THISCALL) < 0) {
+ ANGELSCRIPT_REGISTERFAIL;
+ }
+
+ if(engine->RegisterObjectMethod("EngulfableComponent",
+ "void setSize(float size)", asMETHOD(EngulfableComponent, setSize),
+ asCALL_THISCALL) < 0) {
+ ANGELSCRIPT_REGISTERFAIL;
+ }
+
// ------------------------------------ //
if(engine->RegisterObjectType(
"SpawnedComponent", 0, asOBJ_REF | asOBJ_NOCOUNT) < 0) {
@@ -723,6 +761,11 @@ bool
ANGELSCRIPT_REGISTERFAIL;
}
+ if(engine->RegisterObjectProperty("SpeciesComponent", "double opportunism",
+ asOFFSET(SpeciesComponent, opportunism)) < 0) {
+ ANGELSCRIPT_REGISTERFAIL;
+ }
+
if(engine->RegisterObjectProperty("SpeciesComponent", "int32 population",
asOFFSET(SpeciesComponent, population)) < 0) {
ANGELSCRIPT_REGISTERFAIL;
@@ -872,6 +915,12 @@ bool
ANGELSCRIPT_REGISTERFAIL;
}
+ if(engine->RegisterObjectMethod("AgentProperties",
+ "void setParentEntity(ObjectID parentId)",
+ asMETHOD(AgentProperties, setParentEntity), asCALL_THISCALL) < 0) {
+ ANGELSCRIPT_REGISTERFAIL;
+ }
+
if(engine->RegisterObjectMethod("AgentProperties",
"void setAgentType(string newString)",
asMETHOD(AgentProperties, setAgentType), asCALL_THISCALL) < 0) {
@@ -884,6 +933,12 @@ bool
ANGELSCRIPT_REGISTERFAIL;
}
+ if(engine->RegisterObjectMethod("AgentProperties",
+ "ObjectID getParentEntity()",
+ asMETHOD(AgentProperties, getParentEntity), asCALL_THISCALL) < 0) {
+ ANGELSCRIPT_REGISTERFAIL;
+ }
+
if(engine->RegisterObjectMethod("AgentProperties", "string getAgentType()",
asMETHOD(AgentProperties, getAgentType), asCALL_THISCALL) < 0) {
ANGELSCRIPT_REGISTERFAIL;
| |