Skip to content

Commit

Permalink
Organelle composition (Revolutionary-Games#514)
Browse files Browse the repository at this point in the history
Revising the health and reproduction system and making it more general. Also making organelles release compounds on microbe death.
  • Loading branch information
crodnu authored Apr 24, 2017
1 parent 41dae79 commit b92c626
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 310 deletions.
1 change: 0 additions & 1 deletion scripts/microbe_stage/compound_table.lua
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,5 @@ compoundTable = {
["fattyacids"] = {
name = "Fatty Acids",
volume = 1,
isUseful = true
}
}
50 changes: 43 additions & 7 deletions scripts/microbe_stage/microbe.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ function MicrobeComponent:__init(isPlayerMicrobe, speciesName)
self.dead = false
self.deathTimer = 0
self.organelles = {}
self.processOrganelles = {} -- Organelles responsible for producing compounds from other compounds
self.specialStorageOrganelles = {} -- Organelles with complete resonsiblity for a specific compound (such as agentvacuoles)
self.movementDirection = Vector3(0, 0, 0)
self.facingTargetPoint = Vector3(0, 0, 0)
Expand Down Expand Up @@ -345,6 +346,24 @@ function Microbe:removeStorageOrganelle(storageOrganelle)
self.microbe.capacity = self.microbe.capacity - storageOrganelle.capacity
end

-- Removes a process organelle
-- This will be called automatically by process organelles removed with with removeOrganelle(...)
--
-- @param processOrganelle
-- An object of type ProcessOrganelle
function Microbe:removeProcessOrganelle(processOrganelle)
self.microbe.processOrganelles[processOrganelle] = nil
end

-- Adds a process organelle
-- This will be called automatically by process organelles added with addOrganelle(...)
--
-- @param processOrganelle
-- An object of type ProcessOrganelle
function Microbe:addProcessOrganelle(processOrganelle)
self.microbe.processOrganelles[processOrganelle] = processOrganelle
end

-- Removes a special storage organelle
-- This will be called automatically by process organelles removed with with removeOrganelle(...)
--
Expand Down Expand Up @@ -607,12 +626,29 @@ end

-- Kills the microbe, releasing stored compounds into the enviroment
function Microbe:kill()
local compoundsToRelease = {}
-- Eject the compounds that was in the microbe
for compoundId in CompoundRegistry.getCompoundList() do
local total = self:getCompoundAmount(compoundId)
ejectedAmount = self:takeCompound(compoundId, total)
self:ejectCompound(compoundId, ejectedAmount)
end
local ejectedAmount = self:takeCompound(compoundId, total)
compoundsToRelease[compoundId] = ejectedAmount
end

for _, organelle in pairs(self.microbe.organelles) do
for compoundName, amount in pairs(organelleTable[organelle.name].composition) do
local compoundId = CompoundRegistry.getCompoundId(compoundName)
if(compoundsToRelease[compoundId] == nil) then
compoundsToRelease[compoundId] = amount * COMPOUND_RELEASE_PERCENTAGE
else
compoundsToRelease[compoundId] = compoundsToRelease[compoundId] + amount * COMPOUND_RELEASE_PERCENTAGE
end
end
end

for compoundId, amount in pairs(compoundsToRelease) do
self:ejectCompound(compoundId, amount)
end

for compoundId, specialStorageOrg in pairs(self.microbe.specialStorageOrganelles) do
local _amount = self:getCompoundAmount(compoundId)
while _amount > 0 do
Expand Down Expand Up @@ -795,7 +831,7 @@ function Microbe:update(logicTime)
-- If the organelle is hurt.
if organelle:getCompoundBin() < 1.0 then
-- Give the organelle access to the compound bag to take some compound.
organelle:growOrganelle(self.entity:getComponent(CompoundBagComponent.TYPE_ID))
organelle:growOrganelle(self.entity:getComponent(CompoundBagComponent.TYPE_ID), logicTime)
-- An organelle was damaged and we tried to heal it, so out health might be different.
self:calculateHealthFromOrganelles()
end
Expand All @@ -816,12 +852,12 @@ function Microbe:update(logicTime)
-- If the organelle is not split, give it some compounds to make it larger.
if organelle:getCompoundBin() < 2.0 and not organelle.wasSplit then
-- Give the organelle access to the compound bag to take some compound.
organelle:growOrganelle(self.entity:getComponent(CompoundBagComponent.TYPE_ID))
organelle:growOrganelle(self.entity:getComponent(CompoundBagComponent.TYPE_ID), logicTime)
reproductionStageComplete = false
-- If the organelle was split and has a bin less then 1, it must have been damaged.
elseif organelle:getCompoundBin() < 1.0 and organelle.wasSplit then
-- Give the organelle access to the compound bag to take some compound.
organelle:growOrganelle(self.entity:getComponent(CompoundBagComponent.TYPE_ID))
organelle:growOrganelle(self.entity:getComponent(CompoundBagComponent.TYPE_ID), logicTime)
-- If the organelle is twice its size...
elseif organelle:getCompoundBin() >= 2.0 then
--Queue this organelle for splitting after the loop.
Expand All @@ -834,7 +870,7 @@ function Microbe:update(logicTime)
-- If the nucleus hasn't finished replicating its DNA, give it some compounds.
if organelle:getCompoundBin() < 2.0 then
-- Give the organelle access to the compound back to take some compound.
organelle:growOrganelle(self.entity:getComponent(CompoundBagComponent.TYPE_ID))
organelle:growOrganelle(self.entity:getComponent(CompoundBagComponent.TYPE_ID), logicTime)
reproductionStageComplete = false
end
end
Expand Down
19 changes: 2 additions & 17 deletions scripts/microbe_stage/movement_organelle.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ function MovementOrganelle:__init(arguments, data)
if arguments == nil and data == nil then
return
end


self.energyMultiplier = 0.025
self.force = calculateForce(data.q, data.r, arguments.momentum)
Expand All @@ -55,24 +54,11 @@ function MovementOrganelle:onAddedToMicrobe(microbe, q, r, rotation, organelle)
angle = angle + 2*math.pi
end
angle = (angle * 180/math.pi + 180) % 360

self.sceneNode = OgreSceneNodeComponent()
organelle.rotation = angle

self.sceneNode = organelle.sceneNode
self.sceneNode.transform.orientation = Quaternion(Radian(Degree(angle)), Vector3(0, 0, 1))
self.sceneNode.transform.position = organelle.position.cartesian
self.sceneNode.transform.scale = Vector3(HEX_SIZE, HEX_SIZE, HEX_SIZE)
self.sceneNode.transform:touch()
self.sceneNode.parent = microbe.entity
organelle.organelleEntity:addComponent(self.sceneNode)

self.sceneNode:playAnimation("Move", true)
self.sceneNode:setAnimationSpeed(0.25)

--Adding a mesh to the organelle.
local mesh = organelleTable[organelle.name].mesh
if mesh ~= nil then
self.sceneNode.meshName = mesh
end
end

function MovementOrganelle:load(storage)
Expand All @@ -83,7 +69,6 @@ function MovementOrganelle:load(storage)
end

function MovementOrganelle:storage()
print("storing")
local storage = StorageContainer()
storage:set("energyMultiplier", self.energyMultiplier)
storage:set("force", self.force)
Expand Down
92 changes: 3 additions & 89 deletions scripts/microbe_stage/nucleus_organelle.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,12 @@ function NucleusOrganelle:__init(arguments, data)
if arguments == nil and data == nil then
return
end

self.numProteinLeft = 2
self.numNucleicAcidsLeft = 2
self.nucleusCost = self.numProteinLeft + self.numNucleicAcidsLeft

self.golgi = Entity()
self.ER = Entity()
return self
end


-- Overridded from Organelle:onAddedToMicrobe
function NucleusOrganelle:onAddedToMicrobe(microbe, q, r, rotation, organelle)
local x, y = axialToCartesian(q-1, r-1)
Expand Down Expand Up @@ -52,25 +47,13 @@ function NucleusOrganelle:onAddedToMicrobe(microbe, q, r, rotation, organelle)
self.ER.sceneNode = sceneNode2
self.ER:setVolatile(true)

self.sceneNode = OgreSceneNodeComponent()
self.sceneNode.transform.orientation = Quaternion(Radian(Degree(organelle.rotation)), Vector3(0, 0, 1))
self.sceneNode.transform.position = organelle.position.cartesian
self.sceneNode.transform.scale = Vector3(HEX_SIZE, HEX_SIZE, HEX_SIZE)
self.sceneNode.transform:touch()
local mesh = organelleTable[organelle.name].mesh
if mesh ~= nil then
self.sceneNode.meshName = mesh
end
self.sceneNode.parent = microbe.entity
organelle.organelleEntity:addComponent(self.sceneNode)
self.sceneNode = organelle.sceneNode

-- If we are not in the editor, get the color of this species.
if microbe:getSpeciesComponent() ~= nil then
local speciesColour = microbe:getSpeciesComponent().colour
self.colourSuffix = "" .. math.floor(speciesColour.x * 256) .. math.floor(speciesColour.y * 256) .. math.floor(speciesColour.z * 256)
end

self._needsColourUpdate = true
end

function NucleusOrganelle:onRemovedFromMicrobe(microbe, q, r)
Expand All @@ -85,7 +68,7 @@ end

function NucleusOrganelle:updateColour(organelle)
-- Update the colours of the additional organelle models.
if self.sceneNode.entity ~= nil and self.golgi.sceneNode.entity ~= nil then
--[[if self.sceneNode.entity ~= nil and self.golgi.sceneNode.entity ~= nil then
--print(organelle.colour.r .. ", " .. organelle.colour.g .. ", " .. organelle.colour.b)
local entity = self.sceneNode.entity
Expand All @@ -97,74 +80,5 @@ function NucleusOrganelle:updateColour(organelle)
ER_entity:tintColour("ER", organelle.colour)
organelle._needsColourUpdate = false
end
end]]
end

-- Makes nucleus larger
function NucleusOrganelle:grow(compoundBagComponent)
-- Finds the total number of needed compounds.
local sum = 0

-- Finds which compounds the cell currently has.
if compoundBagComponent:getCompoundAmount(CompoundRegistry.getCompoundId("aminoacids")) >= 1 then
sum = sum + self.numProteinLeft
end
if compoundBagComponent:getCompoundAmount(CompoundRegistry.getCompoundId("aminoacids")) >= 1 then
sum = sum + self.numNucleicAcidsLeft
end

-- If sum is 0, we either have no compounds, in which case we cannot grow the organelle, or the
-- DNA duplication is done (i.e. compoundBin = 2), in which case we wait for the microbe to
-- handle the split.
if sum == 0 then return end

-- Randomly choose which of the three compounds: glucose, amino acids, and fatty acids
-- that are used in reproductions.
local id = math.random()*sum

-- The random number is a protein, so attempt to take it.
if id <= self.numProteinLeft then
compoundBagComponent:takeCompound(CompoundRegistry.getCompoundId("aminoacids"), 1)
self.numProteinLeft = self.numProteinLeft - 1
-- The random number is a nucleic acid.
else
compoundBagComponent:takeCompound(CompoundRegistry.getCompoundId("aminoacids"), 1)
self.numNucleicAcidsLeft = self.numNucleicAcidsLeft - 1
end

-- Calculate the new growth growth
self:recalculateBin()
end

function NucleusOrganelle:damage(amount)
-- Calculate the total number of compounds we need to divide now, so that we can keep this ratio.
local totalLeft = self.numProteinLeft + self.numNucleicAcidsLeft

-- Calculate how much compounds the organelle needs to have to result in a health equal to compoundBin - amount.
local damageFactor = (2.0 - self.compoundBin + amount) * self.nucleusCost / totalLeft
self.numProteinLeft = self.numProteinLeft * damageFactor
self.numNucleicAcidsLeft = self.numNucleicAcidsLeft * damageFactor
-- Calculate the new growth value.
self:recalculateBin()
end

function NucleusOrganelle:recalculateBin()
-- Calculate the new growth growth
self.compoundBin = 2.0 - (self.numProteinLeft + self.numNucleicAcidsLeft)/self.nucleusCost

-- If the organelle is damaged...
if self.compoundBin < 1.0 then
-- Make the nucleus smaller.
self.sceneNode.transform.scale = Vector3((1.0 + self.compoundBin)/2, (1.0 + self.compoundBin)/2, (1.0 + self.compoundBin)/2)*HEX_SIZE
self.sceneNode.transform:touch()

if self.sceneNode.entity ~= nil then
self.sceneNode.entity:tintColour("nucleus" .. self.colourSuffix, ColourValue((1.0 + self.compoundBin)/2, self.compoundBin, self.compoundBin, 1.0))
end
else
-- Darken the nucleus as more DNA is made.
-- crashes the game for reasons
--self.sceneNode.entity:tintColour("nucleus" .. self.colourSuffix, ColourValue(2-self.compoundBin, 2-self.compoundBin, 2-self.compoundBin, 1.0))
end
end

Loading

0 comments on commit b92c626

Please sign in to comment.