Example #1
0
    public override void OnShapeParentChanged(Microbe newShapeParent, Vector3 offset)
    {
        // Check if the pilus exists
        if (NeedsUpdateAnyway())
        {
            // Send the organelle positions to the membrane then update the pilus
            currentShapesParent.SendOrganellePositionsToMembrane();
            Update(0);
        }
        else
        {
            // Firstly the rotation relative to the master.
            var position = organelle.RotatedPositionInsideColony(lastCalculatedPosition);

            // Then the position
            position += offset;
            Vector3 middle = offset;
            Vector3 membranePointDirection = (position - middle).Normalized();
            position += membranePointDirection * Constants.DEFAULT_HEX_SIZE * 2;

            // Pilus rotation
            var angle     = GetAngle(middle - position);
            var rotation  = MathUtils.CreateRotationForPhysicsOrganelle(angle);
            var transform = new Transform(rotation, position);

            // New ownerId
            var ownerId = currentShapesParent.CreateNewOwnerId(newShapeParent, transform, addedChildShapes[0]);
            newShapeParent.AddPilus(ownerId);

            // Destroy the old shape owner
            DestroyShape();
            addedChildShapes.Add(ownerId);
        }

        currentShapesParent = newShapeParent;
    }
Example #2
0
 /// <summary>
 /// Add a pull from the given source with the given strength.
 /// </summary>
 /// <param name="source">The source of the pull to added.</param>
 /// <param name="strength">The strength of the added pull.</param>
 public void AddPull(Microbe source, float strength)
 {
     pull[source] = strength;
 }
Example #3
0
    public void Think(float delta, Random random, MicrobeAICommonData data)
    {
        _ = delta;

        // SetRandomTargetAndSpeed(random);

        // Clear the lists
        predatoryMicrobes.Clear();
        preyMicrobes.Clear();
        chunkList.Clear();

        prey = null;

        // 30 seconds about
        if (boredom == (int)random.Next(SpeciesFocus * 2, 1000.0f + SpeciesFocus * 2))
        {
            // Occasionally you need to reevaluate things
            boredom = 0;
            if (RollCheck(SpeciesActivity, 400, random))
            {
                lifeState = LifeState.PLANTLIKE_STATE;
            }
            else
            {
                lifeState = LifeState.NEUTRAL_STATE;
            }
        }
        else
        {
            boredom++;
        }

        switch (lifeState)
        {
        case LifeState.PLANTLIKE_STATE:
            // This ai would ideally just sit there, until it sees a nice opportunity pop-up unlike neutral,
            // which wanders randomly (has a gather chance) until something interesting pops up
            break;

        case LifeState.NEUTRAL_STATE:
        {
            // Before these would run every time, now they just run for the states that need them.
            boredom    = 0;
            preyPegged = false;
            prey       = null;
            if (predator == null)
            {
                GetNearestPredatorItem(data.AllMicrobes);
            }

            // Peg your prey
            if (!preyPegged)
            {
                prey = null;
                prey = GetNearestPreyItem(data.AllMicrobes);
                if (prey != null)
                {
                    preyPegged = true;
                }
            }

            if (targetChunk == null)
            {
                targetChunk = GetNearestChunkItem(data.AllChunks);
            }

            EvaluateEnvironment(random);
            break;
        }

        case LifeState.GATHERING_STATE:
        {
            // In this state you gather compounds
            if (RollCheck(SpeciesOpportunism, 400.0f, random))
            {
                lifeState = LifeState.SCAVENGING_STATE;
                boredom   = 0;
            }
            else
            {
                DoRunAndTumble(random);
            }

            break;
        }

        case LifeState.FLEEING_STATE:
        {
            if (predator == null)
            {
                GetNearestPredatorItem(data.AllMicrobes);
            }

            // In this state you run from predatory microbes
            if (predator != null)
            {
                DealWithPredators(random);
            }
            else
            {
                if (RollCheck(SpeciesActivity, 400, random))
                {
                    lifeState = LifeState.PLANTLIKE_STATE;
                    boredom   = 0;
                }
                else
                {
                    lifeState = LifeState.NEUTRAL_STATE;
                }
            }

            break;
        }

        case LifeState.PREDATING_STATE:
        {
            // Peg your prey
            if (!preyPegged)
            {
                prey = null;
                prey = GetNearestPreyItem(data.AllMicrobes);
                if (prey != null)
                {
                    preyPegged = true;
                }
            }

            if (preyPegged && prey != null)
            {
                DealWithPrey(data.AllMicrobes, random);
            }
            else
            {
                if (RollCheck(SpeciesActivity, 400, random))
                {
                    lifeState = LifeState.PLANTLIKE_STATE;
                    boredom   = 0;
                }
                else
                {
                    lifeState = LifeState.NEUTRAL_STATE;
                }
            }

            break;
        }

        case LifeState.SCAVENGING_STATE:
        {
            if (targetChunk == null)
            {
                targetChunk = GetNearestChunkItem(data.AllChunks);
            }

            if (targetChunk != null)
            {
                DealWithChunks(targetChunk, data.AllChunks);
            }
            else
            {
                if (!RollCheck(SpeciesOpportunism, 400, random))
                {
                    lifeState = LifeState.NEUTRAL_STATE;
                    boredom   = 0;
                }
                else
                {
                    lifeState = LifeState.SCAVENGING_STATE;
                }
            }

            break;
        }
        }

        // Run reflexes
        DoReflexes();

        // Clear the absorbed compounds for run and rumble
        microbe.TotalAbsorbedCompounds.Clear();
    }
Example #4
0
    /// <summary>
    /// For chasing down and killing prey in various ways
    /// </summary>
    private void DealWithPrey(List <Microbe> allMicrobes, Random random)
    {
        // Tick the engulf tick
        ticksSinceLastToggle += 1;

        bool lostPrey = false;

        try
        {
            targetPosition = prey.Translation;
        }
        catch (ObjectDisposedException)
        {
            lostPrey = true;
        }

        if (lostPrey)
        {
            preyPegged = false;
            prey       = null;
            return;
        }

        // Chase your prey if you dont like acting like a plant
        // Allows for emergence of Predatory Plants (Like a single cleed version of a venus fly trap)
        // Creatures with lethargicness of 400 will not actually chase prey, just lie in wait
        microbe.LookAtPoint = targetPosition;
        hasTargetPosition   = true;

        // Always set target Position, for use later in AI
        if (moveThisHunt)
        {
            if (moveFocused)
            {
                microbe.MovementDirection = new Vector3(0.0f, 0.0f, -Constants.AI_FOCUSED_MOVEMENT);
            }
            else
            {
                microbe.MovementDirection = new Vector3(0.0f, 0.0f, -Constants.AI_BASE_MOVEMENT);
            }
        }
        else
        {
            microbe.MovementDirection = new Vector3(0, 0, 0);
        }

        // Turn off engulf if prey is Dead
        // This is probabbly not working. This is almost certainly not working in the Godot version
        if (prey.Dead)
        {
            hasTargetPosition = false;
            prey = GetNearestPreyItem(allMicrobes);
            if (prey != null)
            {
                preyPegged = true;
            }

            microbe.EngulfMode = false;

            // You got a kill, good job
            if (!microbe.IsPlayerMicrobe && !microbe.Species.PlayerSpecies)
            {
                microbe.SuccessfulKill();
            }

            if (RollCheck(SpeciesOpportunism, 400.0f, random))
            {
                lifeState = LifeState.SCAVENGING_STATE;
                boredom   = 0;
            }
        }
        else
        {
            // Turn on engulfmode if close
            if ((microbe.Translation - targetPosition).LengthSquared() <= 300 + microbe.EngulfSize * 3.0f &&
                microbe.Compounds.GetCompoundAmount(atp) >= 1.0f &&
                !microbe.EngulfMode &&
                microbe.EngulfSize > Constants.ENGULF_SIZE_RATIO_REQ * prey.EngulfSize)
            {
                microbe.EngulfMode   = true;
                ticksSinceLastToggle = 0;
            }
            else if ((microbe.Translation - targetPosition).LengthSquared() >= 500 + microbe.EngulfSize * 3.0f &&
                     microbe.EngulfMode && ticksSinceLastToggle >= Constants.AI_ENGULF_INTERVAL)
            {
                microbe.EngulfMode   = false;
                ticksSinceLastToggle = 0;
            }
        }

        // Shoot toxins if able There should be AI that prefers shooting over engulfing, etc, not sure how to model that
        // without a million and one variables perhaps its a mix? Maybe a creature with a focus less then a certain
        // amount simply never attacks that way?  Maybe a creature with a specific focus, only ever shoots and never
        // engulfs? Maybe their lethargicness impacts that? I just dont want each enemy to feel the same you know.  For
        // now creatures with a focus under 100 will never shoot.
        if (SpeciesFocus >= 100.0f)
        {
            if (microbe.Hitpoints > 0 && microbe.AgentVacuoleCount > 0 &&
                (microbe.Translation - targetPosition).LengthSquared() <= SpeciesFocus * 10.0f)
            {
                if (microbe.Compounds.GetCompoundAmount(oxytoxy) >= Constants.MINIMUM_AGENT_EMISSION_AMOUNT)
                {
                    microbe.EmitToxin(oxytoxy);
                }
            }
        }
    }
Example #5
0
 /// <summary>
 /// Kill the microbe.
 /// </summary>
 /// <param name="microbe">The microbe to kill.</param>
 private static void Kill(Microbe microbe)
 {
     microbe.Die();
 }
Example #6
0
 public void TriggerOnMicrobeDied(Microbe microbe, bool isPlayer)
 {
     OnMicrobeDied?.Invoke(microbe, isPlayer);
 }
Example #7
0
 public void TriggerOnMicrobeSpawned(Microbe microbe)
 {
     OnMicrobeSpawned?.Invoke(microbe);
 }
Example #8
0
 protected override void CustomAttach()
 {
     currentShapesParent = organelle.ParentMicrobe;
 }
Example #9
0
 public void OnShapeParentChanged(Microbe newShapeParent, Vector3 offset)
 {
 }
Example #10
0
    /// <summary>
    ///   Called by a microbe when this organelle has been added to it
    /// </summary>
    public void OnAddedToMicrobe(Microbe microbe)
    {
        if (Definition == null)
        {
            throw new Exception("PlacedOrganelle has no definition set");
        }

        if (ParentMicrobe != null)
        {
            throw new InvalidOperationException("PlacedOrganelle is already in a microbe");
        }

        // Store parameters
        ParentMicrobe = microbe;

        // Grab the species colour for us
        Colour = microbe.Species.Colour;

        ParentMicrobe.OrganelleParent.AddChild(this);

        // Graphical display
        if (Definition.LoadedScene != null)
        {
            SetupOrganelleGraphics();
        }

        float hexSize = Constants.DEFAULT_HEX_SIZE;

        // Scale the physics hex size down for bacteria
        if (microbe.Species.IsBacteria)
        {
            hexSize *= 0.5f;
        }

        // Physics
        ParentMicrobe.Mass += Definition.Mass;

        // Add hex collision shapes
        foreach (Hex hex in Definition.GetRotatedHexes(Orientation))
        {
            var shape = new SphereShape();
            shape.Radius = hexSize * 2.0f;

            var ownerId = ParentMicrobe.CreateShapeOwner(shape);

            // This is needed to actually add the shape
            ParentMicrobe.ShapeOwnerAddShape(ownerId, shape);

            // The shape is in our parent so the final position is our
            // offset plus the hex offset
            Vector3 shapePosition = Hex.AxialToCartesian(hex) + Translation;

            // Scale for bacteria physics.
            if (microbe.Species.IsBacteria)
            {
                shapePosition *= 0.5f;
            }

            var transform = new Transform(Quat.Identity, shapePosition);
            ParentMicrobe.ShapeOwnerSetTransform(ownerId, transform);

            shapes.Add(ownerId);
        }

        // Components
        Components = new List <IOrganelleComponent>();

        foreach (var factory in Definition.ComponentFactories)
        {
            var component = factory.Create();

            if (component == null)
            {
                throw new Exception("PlacedOrganelle component factory returned null");
            }

            component.OnAttachToCell(this);

            Components.Add(component);
        }

        ResetGrowth();
    }
 private void OnPlayerUnbound(Microbe player)
 {
     TutorialState.SendEvent(TutorialEventType.MicrobePlayerUnbound, EventArgs.Empty, this);
 }
Example #12
0
    /// <summary>
    ///   Called by a microbe when this organelle has been added to it
    /// </summary>
    public void OnAddedToMicrobe(Microbe microbe)
    {
        if (Definition == null)
        {
            throw new Exception("PlacedOrganelle has no definition set");
        }

        if (ParentMicrobe != null)
        {
            throw new InvalidOperationException("PlacedOrganelle is already in a microbe");
        }

        // Store parameters
        ParentMicrobe = microbe;

        // Grab the species colour for us
        Colour = microbe.Species.Colour;

        ParentMicrobe.OrganelleParent.AddChild(this);

        // Graphical display
        if (Definition.LoadedScene != null)
        {
            // There is an intermediate node so that the organelle scene root rotation and scale work
            OrganelleGraphics = new Spatial();
            var organelleSceneInstance = (Spatial)Definition.LoadedScene.Instance();

            AddChild(OrganelleGraphics);

            OrganelleGraphics.Scale = new Vector3(Constants.DEFAULT_HEX_SIZE, Constants.DEFAULT_HEX_SIZE,
                                                  Constants.DEFAULT_HEX_SIZE);

            var transform = new Transform(MathUtils.CreateRotationForOrganelle(Orientation),
                                          Definition.CalculateModelOffset());
            OrganelleGraphics.Transform = transform;

            // Store the material of the organelle to be updated
            GeometryInstance geometry;

            // Fetch the actual model from the scene to get at the material we set the tint on
            if (string.IsNullOrEmpty(Definition.DisplaySceneModelPath))
            {
                geometry = (GeometryInstance)organelleSceneInstance;
            }
            else
            {
                geometry = organelleSceneInstance.GetNode <GeometryInstance>(Definition.DisplaySceneModelPath);
            }

            // Store animation player for later use
            if (!string.IsNullOrEmpty(Definition.DisplaySceneAnimation))
            {
                OrganelleAnimation = organelleSceneInstance.GetNode <AnimationPlayer>(Definition.DisplaySceneAnimation);
            }

            organelleMaterial = (ShaderMaterial)geometry.MaterialOverride;

            OrganelleGraphics.AddChild(organelleSceneInstance);
        }

        // Position relative to origin of cell
        RotateY(Orientation * 60);
        Translation = Hex.AxialToCartesian(Position);

        float hexSize = Constants.DEFAULT_HEX_SIZE;

        // Scale the physics hex size down for bacteria
        if (microbe.Species.IsBacteria)
        {
            hexSize *= 0.5f;
        }

        // Physics
        ParentMicrobe.Mass += Definition.Mass;

        // Add hex collision shapes
        foreach (Hex hex in Definition.GetRotatedHexes(Orientation))
        {
            var shape = new SphereShape();
            shape.Radius = hexSize * 2.0f;

            var ownerId = ParentMicrobe.CreateShapeOwner(shape);

            // This is needed to actually add the shape
            ParentMicrobe.ShapeOwnerAddShape(ownerId, shape);

            // The shape is in our parent so the final position is our
            // offset plus the hex offset
            Vector3 shapePosition = Hex.AxialToCartesian(hex) + Translation;

            // Scale for bacteria physics.
            if (microbe.Species.IsBacteria)
            {
                shapePosition *= 0.5f;
            }

            var transform = new Transform(Quat.Identity, shapePosition);
            ParentMicrobe.ShapeOwnerSetTransform(ownerId, transform);

            shapes.Add(ownerId);
        }

        // Components
        Components = new List <IOrganelleComponent>();

        foreach (var factory in Definition.ComponentFactories)
        {
            var component = factory.Create();

            if (component == null)
            {
                throw new Exception("PlacedOrganelle component factory returned null");
            }

            component.OnAttachToCell(this);

            Components.Add(component);
        }

        ResetGrowth();
    }
Example #13
0
 public void Awake()
 {
     microbe = gameObject.GetComponent <Microbe>();
 }
Example #14
0
 private void RemoveCellFromColony(Microbe target)
 {
     target.Colony.RemoveFromColony(target);
 }
Example #15
0
 /// <summary>
 /// Remove the pull of the given source.
 /// </summary>
 /// <param name="source">The source of the pull to remove.</param>
 public void RemovePull(Microbe source)
 {
     pull.Remove(source);
 }
Example #16
0
 public MicrobeEventArgs(Microbe microbe)
 {
     Microbe = microbe;
 }
Example #17
0
 public void TriggerOnPlayerMicrobeSpawned(Microbe player)
 {
     OnPlayerMicrobeSpawned?.Invoke(player);
 }