diff --git a/scripts/gui/thrive_gui.html b/scripts/gui/thrive_gui.html index e5031aab789..9750af9a1b7 100644 --- a/scripts/gui/thrive_gui.html +++ b/scripts/gui/thrive_gui.html @@ -369,6 +369,12 @@
Chloroplast
40 MP + + Chloroplast

Cost: 40 mutation points

+ Performs Process: Photosynthesis
(1 glucose)/Second

+ 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. +
Thermoplast
40 MP diff --git a/scripts/gui/thrive_style.css b/scripts/gui/thrive_style.css index 23b506fdb4c..90fcf86b350 100644 --- a/scripts/gui/thrive_style.css +++ b/scripts/gui/thrive_style.css @@ -235,14 +235,6 @@ video { flex-direction: column; } -.DisabledButton { - filter: grayscale(100%); -} - -.DisabledButton:hover { - filter: grayscale(100%); -} - .MenuButton.DisabledButton { background-image: url("../../Textures/gui/bevel/MenuDisabled.png"); } @@ -1090,6 +1082,7 @@ video { visibility: visible; } + #PlastidIcon { position: relative; left: calc(50% - 30px); diff --git a/scripts/microbe_stage/configs.as b/scripts/microbe_stage/configs.as index e1a7f742b0e..a7ab339d2e5 100644 --- a/scripts/microbe_stage/configs.as +++ b/scripts/microbe_stage/configs.as @@ -64,8 +64,8 @@ const auto MIN_BACTERIAL_LINE_SIZE = 3; const auto MAX_BACTERIAL_LINE_SIZE = 6; // What is divided during fear and aggression calculations in the AI -const auto AGRESSION_DIVISOR = 100.0f; -const auto FEAR_DIVISOR = 100.0f; +const auto AGRESSION_DIVISOR = 25.0f; +const auto FEAR_DIVISOR = 25.0f; const auto ACTIVITY_DIVISOR = 100.0f; const auto FOCUS_DIVISOR = 100.0f; @@ -140,10 +140,10 @@ const float RELATIVE_VELOCITY_TO_BUMP_SOUND = 6.0; const float INITIAL_EMISSION_RADIUS = 0.5; // The speed reduction when a cell is in rngulfing mode. -const uint ENGULFING_MOVEMENT_DIVISION = 3; +const double ENGULFING_MOVEMENT_DIVISION = 2.0f; // The speed reduction when a cell is being engulfed. -const uint ENGULFED_MOVEMENT_DIVISION = 6; +const double ENGULFED_MOVEMENT_DIVISION = 1.7f; // The amount of ATP per second spent on being on engulfing mode. const float ENGULFING_ATP_COST_SECOND = 1.5; diff --git a/scripts/microbe_stage/microbe.as b/scripts/microbe_stage/microbe.as index 7ecd910078d..41644fac989 100644 --- a/scripts/microbe_stage/microbe.as +++ b/scripts/microbe_stage/microbe.as @@ -292,12 +292,12 @@ class MicrobeSystem : ScriptSystem{ private void updateAliveCell(MicrobeSystemCached@ &in components, uint logicTime) { auto microbeEntity = components.entity; - MembraneComponent@ membraneComponent = components.fifth; RenderNode@ sceneNodeComponent = components.third; CompoundAbsorberComponent@ compoundAbsorberComponent = components.first; CompoundBagComponent@ compoundBag = components.sixth; MicrobeComponent@ microbeComponent = components.second; + microbeComponent.movementFactor = 1.0f; //LOG_INFO(""+logicTime); // Recalculating agent cooldown time. @@ -439,7 +439,12 @@ class MicrobeSystem : ScriptSystem{ Float4(0.2,0.5,1.0,0.5)); } + if(microbeComponent.engulfMode){ + microbeComponent.movementFactor = microbeComponent.movementFactor/ENGULFING_MOVEMENT_DIVISION; + } + if(microbeComponent.isBeingEngulfed){ + microbeComponent.movementFactor = microbeComponent.movementFactor/ENGULFED_MOVEMENT_DIVISION; //LOG_INFO("doing engulf damage"); MicrobeOperations::damage(world,microbeEntity,ENGULF_DAMAGE/logicTime, "isBeingEngulfed - Microbe.update()s"); diff --git a/scripts/microbe_stage/microbe_ai.as b/scripts/microbe_stage/microbe_ai.as index 143edf8cbba..471ef9cadf5 100644 --- a/scripts/microbe_stage/microbe_ai.as +++ b/scripts/microbe_stage/microbe_ai.as @@ -29,8 +29,8 @@ class MicrobeAIControllerComponent : ScriptComponent{ } float movementRadius = 2000; - // That means they evaluate every 10 seconds or so, correct? - int reevalutationInterval = 1000; + // That means they evaluate every 5 seconds or so, correct? + int reevalutationInterval = 500; int intervalRemaining; int boredom = 0; int ticksSinceLastToggle = 600; @@ -47,6 +47,7 @@ class MicrobeAIControllerComponent : ScriptComponent{ float previousAngle = 0.0f; float compoundDifference=0; ObjectID prey = NULL_OBJECT; + bool preyPegged=false; // Prey and predator lists array predatoryMicrobes; array preyMicrobes; @@ -115,22 +116,17 @@ class MicrobeAISystem : ScriptSystem{ aiComponent.intervalRemaining += logicTime; // Cache fear and aggression as we dont wnat to be calling "getSpecies" every frame for every microbe (maybe its not a big deal) SpeciesComponent@ ourSpecies = MicrobeOperations::getSpeciesComponent(world, microbeEntity); - if (ourSpecies !is null) - { - if (aiComponent.speciesAggression == -1.0f) - { + if (ourSpecies !is null){ + if (aiComponent.speciesAggression == -1.0f){ aiComponent.speciesAggression = ourSpecies.aggression; } - if (aiComponent.speciesFear == -1.0f) - { + if (aiComponent.speciesFear == -1.0f){ aiComponent.speciesFear = ourSpecies.fear; } - if (aiComponent.speciesActivity == -1.0f) - { + if (aiComponent.speciesActivity == -1.0f){ aiComponent.speciesActivity =ourSpecies.activity; } - if (aiComponent.speciesFocus == -1.0f) - { + if (aiComponent.speciesFocus == -1.0f){ aiComponent.speciesFocus = ourSpecies.focus; } } @@ -140,7 +136,7 @@ class MicrobeAISystem : ScriptSystem{ LOG_INFO("AI Focus"+aiComponent.speciesFocus); LOG_INFO("AI Activity"+aiComponent.speciesActivity);*/ - while(aiComponent.intervalRemaining > aiComponent.reevalutationInterval) { + while(aiComponent.intervalRemaining > aiComponent.reevalutationInterval){ aiComponent.intervalRemaining -= aiComponent.reevalutationInterval; int numberOfAgentVacuoles = int( microbeComponent.specialStorageOrganelles[formatUInt(oxytoxyId)]); @@ -148,22 +144,27 @@ class MicrobeAISystem : ScriptSystem{ // Clear the lists aiComponent.predatoryMicrobes.removeRange(0,aiComponent.predatoryMicrobes.length()); aiComponent.preyMicrobes.removeRange(0,aiComponent.preyMicrobes.length()); - - // Update most feared microbe and most tasty microbe - ObjectID prey = getNearestPreyItem(components,allMicrobes); + ObjectID prey = NULL_OBJECT; + // Peg your prey + if (!aiComponent.preyPegged){ + aiComponent.prey=NULL_OBJECT; + prey = getNearestPreyItem(components,allMicrobes); + aiComponent.prey = prey; + if (prey != NULL_OBJECT){ + aiComponent.preyPegged=true; + } + } ObjectID predator = getNearestPredatorItem(components,allMicrobes); //30 seconds about - if (aiComponent.boredom == GetEngine().GetRandom().GetNumber(aiComponent.speciesFocus,1000.0f+aiComponent.speciesFocus)){ + if (aiComponent.boredom == GetEngine().GetRandom().GetNumber(aiComponent.speciesFocus*2,1000.0f+aiComponent.speciesFocus*2)){ // Occassionally you need to reevaluate things aiComponent.boredom = 0; - if (GetEngine().GetRandom().GetNumber(0.0f,400.0f) <= aiComponent.speciesActivity) - { + if (rollCheck(aiComponent.speciesActivity, 400)){ //LOG_INFO("gather only"); aiComponent.lifeState = PLANTLIKE_STATE; } - else - { + else{ aiComponent.lifeState = NEUTRAL_STATE; } } @@ -182,7 +183,9 @@ class MicrobeAISystem : ScriptSystem{ { //In this state you just sit there and analyze your environment aiComponent.boredom=0; - evaluateEnvironment(components,prey,predator); + aiComponent.preyPegged=false; + prey = NULL_OBJECT; + evaluateEnvironment(components,aiComponent.prey,predator); break; } case GATHERING_STATE: @@ -193,20 +196,18 @@ class MicrobeAISystem : ScriptSystem{ } case FLEEING_STATE: { - //In this state you run from preadtory microbes - if (predator != NULL_OBJECT) - { + //In this state you run from predatory microbes + if (predator != NULL_OBJECT){ + //aiComponent.hasTargetPosition = false; dealWithPredators(components,predator); } else{ - if (GetEngine().GetRandom().GetNumber(0.0f,400.0f) <= aiComponent.speciesActivity) - { + if (rollCheck(aiComponent.speciesActivity, 400)){ //LOG_INFO("gather only"); aiComponent.lifeState = PLANTLIKE_STATE; aiComponent.boredom=0; } - else - { + else{ aiComponent.lifeState = NEUTRAL_STATE; } } @@ -214,26 +215,45 @@ class MicrobeAISystem : ScriptSystem{ } case PREDATING_STATE: { - if (prey != NULL_OBJECT) - { - dealWithPrey(components,prey); + if (aiComponent.preyPegged && aiComponent.prey != NULL_OBJECT){ + dealWithPrey(components, aiComponent.prey, allMicrobes); } else{ - if (GetEngine().GetRandom().GetNumber(0.0f,400.0f) <= aiComponent.speciesActivity) - { + if (rollCheck(aiComponent.speciesActivity, 400)){ //LOG_INFO("gather only"); aiComponent.lifeState = NEUTRAL_STATE; aiComponent.boredom=0; } - else - { + 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 + If it was ran in evaluate environment, it would only work if the microbe was in the neutral state. + So think of this as a "reflex" maybe it should go in its own "doReflex" method, + because we may need more of these very specific things in the future for things like latching onto rocks */ + // If you are predating and not being engulfed, don't run away until you switch state (keeps predators chasing you even when their predators are nearby) + // Its not a good survival strategy but it makes the game more fun. + if (predator != NULL_OBJECT && (aiComponent.lifeState != PREDATING_STATE || microbeComponent.isBeingEngulfed)){ + 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 (aiComponent.lifeState != FLEEING_STATE) + { + // Reset target position for faster fleeing + aiComponent.hasTargetPosition = false; + } + aiComponent.boredom=0; + aiComponent.lifeState = FLEEING_STATE; + } + } } + //cache stored compounds for use in the next frame (For Run and tumble) aiComponent.compoundDifference = microbeComponent.stored-aiComponent.previousStoredCompounds; aiComponent.previousStoredCompounds = microbeComponent.stored; @@ -250,28 +270,21 @@ class MicrobeAISystem : ScriptSystem{ ObjectID chosenPrey = NULL_OBJECT; CompoundId oxytoxyId = SimulationParameters::compoundRegistry().getTypeId("oxytoxy"); + // Grab the agent amounts so a small cell with a lot of toxins has the courage to attack. int numberOfAgentVacuoles = int( microbeComponent.specialStorageOrganelles[formatUInt(oxytoxyId)]); // Retrieve nearest potential prey - for (uint i = 0; i < allMicrobes.length(); i++) - { + for (uint i = 0; i < allMicrobes.length(); i++){ // Get the microbe component MicrobeComponent@ secondMicrobeComponent = cast( world.GetScriptComponentHolder("MicrobeComponent").Find(allMicrobes[i])); // At max aggression add them all - if (allMicrobes[i] != microbeEntity && (secondMicrobeComponent.speciesName != microbeComponent.speciesName) && !secondMicrobeComponent.dead) - { - // TODO: - // I think we should call this and factor it into predator calculations .specialStorageOrganelles[formatUInt(oxytoxyId)]) - // that way a small cell with alot of toxins still has the courage to attack. - // But that may be rather arcane to read through code wise. SO im not sure. - + 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))) - { + (secondMicrobeComponent.organelles.length()*1.0f))){ //You are non-threatening to me aiComponent.preyMicrobes.insertLast(allMicrobes[i]); } @@ -283,15 +296,13 @@ class MicrobeAISystem : ScriptSystem{ { Float3 testPosition = world.GetComponent_Position(aiComponent.preyMicrobes[0])._Position; chosenPrey = aiComponent.preyMicrobes[0]; - for (uint c = 0; c < aiComponent.preyMicrobes.length(); c++) - { + for (uint c = 0; c < aiComponent.preyMicrobes.length(); c++){ // Get the microbe component MicrobeComponent@ secondMicrobeComponent = cast( world.GetScriptComponentHolder("MicrobeComponent").Find(aiComponent.preyMicrobes[c])); Position@ thisPosition = world.GetComponent_Position(aiComponent.preyMicrobes[c]); - if ((testPosition - position._Position).LengthSquared() > (thisPosition._Position - position._Position).LengthSquared()) - { + if ((testPosition - position._Position).LengthSquared() > (thisPosition._Position - position._Position).LengthSquared()){ testPosition = thisPosition._Position; chosenPrey = aiComponent.preyMicrobes[c]; } @@ -320,16 +331,15 @@ class MicrobeAISystem : ScriptSystem{ // Get the microbe component MicrobeComponent@ secondMicrobeComponent = cast( world.GetScriptComponentHolder("MicrobeComponent").Find(allMicrobes[i])); - // Is this an expensive lookup?, ill come up with a more effieient means of doing this. + // Is this an expensive lookup?, ill come up with a more efficient means of doing this. CompoundId oxytoxyId = SimulationParameters::compoundRegistry().getTypeId("oxytoxy"); int numberOfAgentVacuoles = int( secondMicrobeComponent.specialStorageOrganelles[formatUInt(oxytoxyId)]); // 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))) - { + 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))){ //You are bigger then me and i am afraid of that aiComponent.predatoryMicrobes.insertLast(allMicrobes[i]); //LOG_INFO("Added predator " + allMicrobes[i] ); @@ -338,20 +348,17 @@ class MicrobeAISystem : ScriptSystem{ } // Get the nearest one if it exists - if (aiComponent.predatoryMicrobes.length() > 0 ) - { + if (aiComponent.predatoryMicrobes.length() > 0){ Float3 testPosition = world.GetComponent_Position(aiComponent.predatoryMicrobes[0])._Position; predator = aiComponent.predatoryMicrobes[0]; - for (uint c = 0; c < aiComponent.predatoryMicrobes.length(); c++) - { + for (uint c = 0; c < aiComponent.predatoryMicrobes.length(); c++){ // Get the microbe component MicrobeComponent@ secondMicrobeComponent = cast( world.GetScriptComponentHolder("MicrobeComponent").Find(aiComponent.predatoryMicrobes[c])); Position@ thisPosition = world.GetComponent_Position(aiComponent.predatoryMicrobes[c]); - if ((testPosition - position._Position).LengthSquared() > (thisPosition._Position - position._Position).LengthSquared()) - { + if ((testPosition - position._Position).LengthSquared() > (thisPosition._Position - position._Position).LengthSquared()){ testPosition = thisPosition._Position; predator = aiComponent.predatoryMicrobes[c]; } @@ -361,7 +368,7 @@ class MicrobeAISystem : ScriptSystem{ } // For chasing down and killing prey in various ways - void dealWithPrey(MicrobeAISystemCached@ components, ObjectID prey) + void dealWithPrey(MicrobeAISystemCached@ components, ObjectID prey, array@ allMicrobes ) { //LOG_INFO("chasing"+prey); // Set Components @@ -374,9 +381,14 @@ class MicrobeAISystem : ScriptSystem{ // Required For AI CompoundId oxytoxyId = SimulationParameters::compoundRegistry().getTypeId("oxytoxy"); CompoundId atpID = SimulationParameters::compoundRegistry().getTypeId("atp"); - + //LOG_INFO("predating"); MicrobeComponent@ secondMicrobeComponent = cast( world.GetScriptComponentHolder("MicrobeComponent").Find(prey)); + if (secondMicrobeComponent is null){ + aiComponent.preyPegged=false; + aiComponent.prey = NULL_OBJECT; + return; + } // Agent vacuoles. int numberOfAgentVacuoles = int( microbeComponent.specialStorageOrganelles[formatUInt(oxytoxyId)]); @@ -391,12 +403,10 @@ class MicrobeAISystem : ScriptSystem{ aiComponent.hasTargetPosition = true; //Always set target Position, for use later in AI - if (aiComponent.speciesAggression+GetEngine().GetRandom().GetNumber(-100.0f,100.0f) > aiComponent.speciesActivity) - { + if (aiComponent.speciesAggression+GetEngine().GetRandom().GetNumber(-100.0f,100.0f) > aiComponent.speciesActivity){ microbeComponent.movementDirection = Float3(0, 0, -AI_BASE_MOVEMENT); } - else - { + else{ microbeComponent.movementDirection = Float3(0, 0, 0); } @@ -404,31 +414,33 @@ class MicrobeAISystem : ScriptSystem{ // This is probabbly not working if (secondMicrobeComponent.dead == true){ aiComponent.hasTargetPosition = false; - aiComponent.lifeState = GATHERING_STATE; - if (microbeComponent.engulfMode) - { + aiComponent.prey=getNearestPreyItem(components, allMicrobes); + if (aiComponent.prey != NULL_OBJECT ) { + aiComponent.preyPegged=true; + } + + if (microbeComponent.engulfMode){ MicrobeOperations::toggleEngulfMode(world, microbeEntity); - } + } // You got a kill, good job auto playerSpecies = MicrobeOperations::getSpeciesComponent(world, "Default"); - if (!microbeComponent.isPlayerMicrobe && microbeComponent.speciesName != playerSpecies.name) - { + if (!microbeComponent.isPlayerMicrobe && microbeComponent.speciesName != playerSpecies.name){ MicrobeOperations::alterSpeciesPopulation(world,microbeEntity,CREATURE_KILL_POPULATION_GAIN); } } else { // Turn on engulfmode if close - if (((position._Position - aiComponent.targetPosition).LengthSquared() <= 300+(microbeComponent.organelles.length()*3.0f)) && (MicrobeOperations::getCompoundAmount(world,microbeEntity,atpID) >= 1.0f) + if (((position._Position - aiComponent.targetPosition).LengthSquared() <= 300+(microbeComponent.organelles.length()*3.0f)) + && (MicrobeOperations::getCompoundAmount(world,microbeEntity,atpID) >= 1.0f) && !microbeComponent.engulfMode && (float(microbeComponent.organelles.length()) > ( - ENGULF_HP_RATIO_REQ*secondMicrobeComponent.organelles.length()))) - { + ENGULF_HP_RATIO_REQ*secondMicrobeComponent.organelles.length()))){ MicrobeOperations::toggleEngulfMode(world, microbeEntity); aiComponent.ticksSinceLastToggle=0; } - else if ((position._Position - aiComponent.targetPosition).LengthSquared() >= 500+(microbeComponent.organelles.length()*3.0f) && microbeComponent.engulfMode && aiComponent.ticksSinceLastToggle >= AI_ENGULF_INTERVAL) - { + else if (((position._Position - aiComponent.targetPosition).LengthSquared() >= 500+(microbeComponent.organelles.length()*3.0f)) + && (microbeComponent.engulfMode && aiComponent.ticksSinceLastToggle >= AI_ENGULF_INTERVAL)){ MicrobeOperations::toggleEngulfMode(world, microbeEntity); aiComponent.ticksSinceLastToggle=0; } @@ -441,20 +453,17 @@ class MicrobeAISystem : ScriptSystem{ // For now creatures with a focus under 100 will never shoot. //LOG_INFO("Our focus is: "+ aiComponent.speciesFocus); - if (aiComponent.speciesFocus >= 100.0f) - { + if (aiComponent.speciesFocus >= 100.0f){ if (microbeComponent.hitpoints > 0 && numberOfAgentVacuoles > 0 && - (position._Position - aiComponent.targetPosition).LengthSquared() <= aiComponent.speciesFocus*10.0f) - { - if (MicrobeOperations::getCompoundAmount(world,microbeEntity,oxytoxyId) >= MINIMUM_AGENT_EMISSION_AMOUNT) - { + (position._Position - aiComponent.targetPosition).LengthSquared() <= aiComponent.speciesFocus*10.0f){ + if (MicrobeOperations::getCompoundAmount(world,microbeEntity,oxytoxyId) >= MINIMUM_AGENT_EMISSION_AMOUNT){ MicrobeOperations::emitAgent(world,microbeEntity, oxytoxyId,10.0f,aiComponent.speciesFocus*10.0f); } } - } + } } - // For self defense (not nessessarily fleeing) + // For self defense (not necessarily fleeing) void dealWithPredators(MicrobeAISystemCached@ components, ObjectID predator) { ObjectID microbeEntity = components.entity; @@ -462,14 +471,12 @@ class MicrobeAISystem : ScriptSystem{ MicrobeComponent@ microbeComponent = components.second; Position@ position = components.third; - if (GetEngine().GetRandom().GetNumber(0,100) <= 10) - { + if (GetEngine().GetRandom().GetNumber(0,50) <= 10){ aiComponent.hasTargetPosition = false; } // Run From Predator - if (aiComponent.hasTargetPosition == false) - { + if (aiComponent.hasTargetPosition == false){ preyFlee(microbeEntity, aiComponent, microbeComponent, position, predator); } } @@ -484,87 +491,46 @@ class MicrobeAISystem : ScriptSystem{ int numberOfAgentVacuoles = int( microbeComponent.specialStorageOrganelles[formatUInt(oxytoxyId)]); - if (GetEngine().GetRandom().GetNumber(0,100) <= 40) - { + // If focused you can run away more specifically, if not you freak out and scatter + if (!rollCheck(aiComponent.speciesFocus,500.0f)){ // Scatter auto randAngle = GetEngine().GetRandom().GetFloat(-2*PI, 2*PI); auto randDist = GetEngine().GetRandom().GetFloat(200,aiComponent.movementRadius*10); aiComponent.targetPosition = Float3(cos(randAngle) * randDist,0, sin(randAngle)* randDist); - auto vec = (aiComponent.targetPosition - position._Position); - aiComponent.direction = vec.Normalize(); - microbeComponent.facingTargetPoint = aiComponent.targetPosition; - microbeComponent.movementDirection = Float3(0, 0, -AI_BASE_MOVEMENT); - aiComponent.hasTargetPosition = true; } else { // Run specifically away - int choice = GetEngine().GetRandom().GetNumber(0,3); - switch (choice) - { - case 0: - if (world.GetComponent_Position(predator)._Position.X >= position._Position.X) - { - aiComponent.targetPosition = - Float3(GetEngine().GetRandom().GetFloat(-10.0f,-100.0f),1.0,1.0)* - world.GetComponent_Position(predator)._Position; - } - else { - aiComponent.targetPosition = - Float3(GetEngine().GetRandom().GetFloat(20.0f,100.0f),1.0,1.0)* - world.GetComponent_Position(predator)._Position; - } - break; - case 1: - if (world.GetComponent_Position(predator)._Position.Z >= position._Position.Z) - { - aiComponent.targetPosition = - Float3(1.0,1.0,GetEngine().GetRandom().GetFloat(-10.0f,-100.0f))* + aiComponent.targetPosition = Float3(GetEngine().GetRandom().GetFloat(-5000.0f,5000.0f),1.0, + GetEngine().GetRandom().GetFloat(-5000.0f,5000.0f))* world.GetComponent_Position(predator)._Position; - } - else { - aiComponent.targetPosition = - Float3(1.0,1.0,GetEngine().GetRandom().GetFloat(20.0f,100.0f))* - world.GetComponent_Position(predator)._Position; - } - break; - case 2: - case 3: - aiComponent.targetPosition = - Float3(GetEngine().GetRandom().GetFloat(-100.0f,100.0f),1.0, - GetEngine().GetRandom().GetFloat(-100.0f,100.0f))* - world.GetComponent_Position(predator)._Position; - break; } - auto vec = (aiComponent.targetPosition - position._Position); + auto vec = (position._Position-aiComponent.targetPosition); aiComponent.direction = vec.Normalize(); - microbeComponent.facingTargetPoint = aiComponent.targetPosition; - microbeComponent.movementDirection = Float3(0, 0, -AI_BASE_MOVEMENT); + microbeComponent.facingTargetPoint = -aiComponent.targetPosition; + microbeComponent.movementDirection = Float3(0, 0, -(AI_BASE_MOVEMENT)); aiComponent.hasTargetPosition = true; - } //Freak out and fire toxins everywhere - if (aiComponent.speciesAggression > aiComponent.speciesFear && aiComponent.speciesFocus >= GetEngine().GetRandom().GetNumber(0.0f,400.0f)) - { + if ((aiComponent.speciesAggression > aiComponent.speciesFear) && rollReverseCheck(aiComponent.speciesFocus, 400.0f)){ if (microbeComponent.hitpoints > 0 && numberOfAgentVacuoles > 0 && - (position._Position - aiComponent.targetPosition).LengthSquared() <= aiComponent.speciesFocus*10.0f) - { - if (MicrobeOperations::getCompoundAmount(world,microbeEntity,oxytoxyId) >= MINIMUM_AGENT_EMISSION_AMOUNT) - { + (position._Position - aiComponent.targetPosition).LengthSquared() <= aiComponent.speciesFocus*10.0f){ + if (MicrobeOperations::getCompoundAmount(world,microbeEntity,oxytoxyId) >= MINIMUM_AGENT_EMISSION_AMOUNT){ MicrobeOperations::emitAgent(world,microbeEntity, oxytoxyId,10.0f,aiComponent.speciesFocus*10.0f); } } } - } + } // For for firguring out which state to enter void evaluateEnvironment(MicrobeAISystemCached@ components, ObjectID prey, ObjectID predator) { //LOG_INFO("evaluating"); MicrobeAIControllerComponent@ aiComponent = components.first; - if (GetEngine().GetRandom().GetNumber(0.0f,500.0f) <= aiComponent.speciesActivity) + Position@ position = components.third; + if (rollCheck(aiComponent.speciesActivity,500.0f)) { aiComponent.lifeState = PLANTLIKE_STATE; aiComponent.boredom = 0; @@ -573,58 +539,45 @@ class MicrobeAISystem : ScriptSystem{ if (prey != NULL_OBJECT && predator != NULL_OBJECT) { //LOG_INFO("Both"); - if (aiComponent.speciesAggression > aiComponent.speciesFear) - { - aiComponent.lifeState = PREDATING_STATE; - } - else if (aiComponent.speciesAggression < aiComponent.speciesFear) - { - //aiComponent.lifeState = PREDATING_STATE; - aiComponent.lifeState = FLEEING_STATE; + if (GetEngine().GetRandom().GetNumber(0.0f,aiComponent.speciesAggression) > + GetEngine().GetRandom().GetNumber(0.0f,aiComponent.speciesFear) && + (aiComponent.preyMicrobes.length() > 0)){ + aiComponent.lifeState = PREDATING_STATE; } - else if (aiComponent.speciesAggression == aiComponent.speciesFear) - { - // Very rare - if (GetEngine().GetRandom().GetNumber(0,10) <= 5) - { - // Prefer predating by 10% (makes game more fun) - aiComponent.lifeState = PREDATING_STATE; - } - else { + else if (GetEngine().GetRandom().GetNumber(0.0f,aiComponent.speciesAggression) < + GetEngine().GetRandom().GetNumber(0.0f,aiComponent.speciesFear)&& + (aiComponent.predatoryMicrobes.length() > 0)){ + //aiComponent.lifeState = PREDATING_STATE; aiComponent.lifeState = FLEEING_STATE; - } } - // I want gathering to trigger more often so i added this here. Because even with predators and prey around its still important to eat compounds - if (GetEngine().GetRandom().GetNumber(0.0f,500.0f) <= aiComponent.speciesFocus && GetEngine().GetRandom().GetNumber(0,10) <= 2) - { - aiComponent.lifeState = GATHERING_STATE; + else if (aiComponent.speciesAggression == aiComponent.speciesFear && + (aiComponent.preyMicrobes.length() > 0)){ + // Prefer predating (makes game more fun) + aiComponent.lifeState = PREDATING_STATE; } + else if (rollCheck(aiComponent.speciesFocus,500.0f) && GetEngine().GetRandom().GetNumber(0,10) <= 2){ + aiComponent.lifeState = GATHERING_STATE; } - else if (prey != NULL_OBJECT) - { + } + else if (prey != NULL_OBJECT){ //LOG_INFO("prey only"); aiComponent.lifeState = PREDATING_STATE; - } - else if (predator != NULL_OBJECT) - { + else if (predator != NULL_OBJECT){ //LOG_INFO("predator only"); aiComponent.lifeState = FLEEING_STATE; // I want gathering to trigger more often so i added this here. Because even with predators around you should still graze - if (GetEngine().GetRandom().GetNumber(0.0f,500.0f) <= aiComponent.speciesFocus && GetEngine().GetRandom().GetNumber(0,10) <= 5) - { - aiComponent.lifeState = GATHERING_STATE; + if (rollCheck(aiComponent.speciesFocus,500.0f) && GetEngine().GetRandom().GetNumber(0,10) <= 5){ + aiComponent.lifeState = GATHERING_STATE; } } // Every 2 intervals or so - else if (GetEngine().GetRandom().GetNumber(0,10) < 8) - { + else if (GetEngine().GetRandom().GetNumber(0,10) < 8){ //LOG_INFO("gather only"); aiComponent.lifeState = GATHERING_STATE; } // Every 10 intervals or so - else if (GetEngine().GetRandom().GetNumber(0.0f,400.0f) <= aiComponent.speciesActivity) - { + else if (rollCheck(aiComponent.speciesActivity,400.0f)){ //LOG_INFO("gather only"); aiComponent.lifeState = PLANTLIKE_STATE; } @@ -649,8 +602,7 @@ class MicrobeAISystem : ScriptSystem{ float compoundDifference = aiComponent.compoundDifference; // Angle should only change if you havent picked up compounds or picked up less compounds - if (compoundDifference < 0 && GetEngine().GetRandom().GetNumber(0,10) < 5) - { + if (compoundDifference < 0 && GetEngine().GetRandom().GetNumber(0,10) < 5){ randAngle = aiComponent.previousAngle+GetEngine().GetRandom().GetFloat(0.1f,1.0f); aiComponent.previousAngle = randAngle; randDist = GetEngine().GetRandom().GetFloat(200.0f,float(aiComponent.movementRadius)); @@ -658,16 +610,14 @@ class MicrobeAISystem : ScriptSystem{ } // If last round you had 0, then have a high likelihood of turning - if (compoundDifference < AI_COMPOUND_BIAS && GetEngine().GetRandom().GetNumber(0,10) < 9) - { + if (compoundDifference < AI_COMPOUND_BIAS && GetEngine().GetRandom().GetNumber(0,10) < 9){ randAngle = aiComponent.previousAngle+GetEngine().GetRandom().GetFloat(1.0f,2.0f); aiComponent.previousAngle = randAngle; randDist = GetEngine().GetRandom().GetFloat(200.0f,float(aiComponent.movementRadius)); aiComponent.targetPosition = Float3(cos(randAngle) * randDist,0, sin(randAngle)* randDist); } - if (compoundDifference == 0 && GetEngine().GetRandom().GetNumber(0,10) < 9) - { + if (compoundDifference == 0 && GetEngine().GetRandom().GetNumber(0,10) < 9){ randAngle = aiComponent.previousAngle+GetEngine().GetRandom().GetFloat(1.0f,2.0f); aiComponent.previousAngle = randAngle; randDist = GetEngine().GetRandom().GetFloat(200.0f,float(aiComponent.movementRadius)); @@ -675,8 +625,7 @@ class MicrobeAISystem : ScriptSystem{ } // If positive last step you gained compounds - if (compoundDifference > 0 && GetEngine().GetRandom().GetNumber(0,10) < 5) - { + if (compoundDifference > 0 && GetEngine().GetRandom().GetNumber(0,10) < 5){ // If found food subtract from angle randomly; randAngle = aiComponent.previousAngle-GetEngine().GetRandom().GetFloat(0.1f,0.3f); aiComponent.previousAngle = randAngle; @@ -694,6 +643,17 @@ class MicrobeAISystem : ScriptSystem{ } + /* Personality checks */ + //There are cases when we want either or, so heres two state rolls + //TODO: add method for rolling stat versus stat + bool rollCheck(double ourStat, double dc){ + return (GetEngine().GetRandom().GetNumber(0.0f,dc) <= ourStat); + } + + bool rollReverseCheck(double ourStat, double dc){ + return (ourStat >= GetEngine().GetRandom().GetNumber(0.0f,dc)); + } + void Clear(){ CachedComponents.resize(0); } diff --git a/scripts/microbe_stage/microbe_operations.as b/scripts/microbe_stage/microbe_operations.as index 2d9c1c3f16e..65df873c3be 100644 --- a/scripts/microbe_stage/microbe_operations.as +++ b/scripts/microbe_stage/microbe_operations.as @@ -713,16 +713,8 @@ void toggleEngulfMode(MicrobeComponent@ microbeComponent) microbeComponent.movementFactor = 1.0f; // soundSourceComponent.stopSound("microbe-engulfment"); // Possibly comment out. } - else if (microbeComponent.isBeingEngulfed) - { - microbeComponent.movementFactor = microbeComponent.movementFactor / - ENGULFED_MOVEMENT_DIVISION; - } - else - { - microbeComponent.movementFactor = microbeComponent.movementFactor / - ENGULFING_MOVEMENT_DIVISION; - } + microbeComponent.movementFactor = microbeComponent.movementFactor / + ENGULFING_MOVEMENT_DIVISION; microbeComponent.engulfMode = !microbeComponent.engulfMode; } diff --git a/scripts/microbe_stage/setup.as b/scripts/microbe_stage/setup.as index 6b3c5cdb6a1..58470154b68 100644 --- a/scripts/microbe_stage/setup.as +++ b/scripts/microbe_stage/setup.as @@ -408,7 +408,6 @@ bool beingEngulfed(GameWorld@ world, ObjectID firstEntity, ObjectID secondEntity (ENGULF_HP_RATIO_REQ * secondMicrobeComponentOrganelles) && firstMicrobeComponent.dead == false && secondMicrobeComponent.dead == false) { - secondMicrobeComponent.movementFactor = secondMicrobeComponent.movementFactor/ENGULFED_MOVEMENT_DIVISION; secondMicrobeComponent.isBeingEngulfed = true; secondMicrobeComponent.hostileEngulfer = firstEntity; secondMicrobeComponent.wasBeingEngulfed = true; @@ -422,7 +421,6 @@ bool beingEngulfed(GameWorld@ world, ObjectID firstEntity, ObjectID secondEntity (ENGULF_HP_RATIO_REQ * firstMicrobeComponentOrganelles) && secondMicrobeComponent.dead == false && firstMicrobeComponent.dead == false) { - firstMicrobeComponent.movementFactor = firstMicrobeComponent.movementFactor/ENGULFED_MOVEMENT_DIVISION; firstMicrobeComponent.isBeingEngulfed = true; firstMicrobeComponent.hostileEngulfer = secondEntity; firstMicrobeComponent.wasBeingEngulfed = true;