Tiberium mod for 0.17

Place to get help with not working mods / modding interface.
Post Reply
silenceko
Burner Inserter
Burner Inserter
Posts: 10
Joined: Mon Apr 11, 2016 12:07 pm
Contact:

Tiberium mod for 0.17

Post by silenceko »

So here I am, looking for help to update the tiberium mod / make a new one.

goals:
tiberium should:
  • grow
    spread
    damage player
    damage buildings
    transform trees into sporetrees (1 of x ; x=100?)
    transform adjacent ore into tiberium
    replace groundtiles with TiberiumGroundTiles on creation / spread
ATM, I am not sure how or if blue tiberium should be added

grow and spread shall update in chunks. The existing mod uses an array of all tiberiumtiles and updates one tile per tick. Hence, the time needed for an updatecycle grows and grows - and takes way too long, but saves performance.

I want to update all tiles of one chunk per tick (compromise of speed and performance) or, depending on performance, onNthTick.

This is the code I struggle with, it is in working state:
(the rampant sniplets are from here: viewtopic.php?t=31745 )

Code: Select all


script.on_init(function()

	--- VARIABLES
	global.TD = true -- TiberiumDebug
	global.numChunks = 0 -- number of chunks 
	global.tibOreType = "tiberium-ore" -- ore type
	global.oreList = {} -- tiles with tiberium ore 
	global.oreListIndex = 0 -- for cycling through the list
	global.cred = {r=1, g=0, b=0, a=1} -- red color
	global.tibOrePos = {} -- position of ore
	global.tibGrowthAmount = 250 -- how much should tiberium grow at once
	global.tibGrowthRate = 3 -- number of seconds when tiberium grows
	global.tickCounter = 0 -- counter to calculate if tiberium should grow
	global.chunkCounter = 0
	global.allChunks={} -- table with all chunks stored
	global.Counter=0
	global.minTibSpreadAmount = 500 -- Amount a tile must have to spread tib  Default = 500
	global.damageForceName = "tiberium"
	game.create_force(global.damageForceName)
	global.contactDamage = 1 --how much damage should be applied to objects over tiberium?
	global.maxGrothAmount = 6000 -- how much tiberium can exist on 1 tile
	global.allChunks = game.surfaces[1].get_chunks()
	global.currentChunkPointer=1
end)--.on_init(function()

local chunks
local currentChunk

function onChunkGenerated(event) -- from mod rampant 
    if (event.surface.index == 1) then
        chunks[#chunks+1] = event
	end
end

--initial chunk scan
script.on_event(defines.events.on_chunk_generated, function(event)
   
    -- discarded for new approach
    --[[local entities = game.surfaces[1].find_entities_filtered{area = event.area, name = global.tibOreType} -- is there tiberium on chunk

    for i=1,#entities,1 do
       table.insert(global.oreList, entities[i]) -- add found tiberium to list
    end--]]
	
	global.numChunks = global.numChunks + 1 
	global.allChunks = game.surfaces[1].get_chunks()
	
	for chunk in global.allChunks do -- from mod rampant
    		onChunkGenerated({ surface = global.allChunks, 
                       area = { left_top = { x = chunk.x * 32,
                                             y = chunk.y * 32 }}})
	end
		
	if global.TD == true then
		--game.print("Number of Chunks: "..tostring(global.numChunks))
	end
	
end) -- .on_chunk_generated





function doOneStep(chunks) -- from mod rampant
    local chunk = chunks[global.currentChunk]
    .... doProcessing ....
    global.currentChunkPointer = global.currentChunkPointer + 1
    if (global.currentChunkPointer == #chunks) then
        global.currentChunkPointer = 1
    end
end

function tiberium() -- function for growing tiberium
	
	game.print("entered function tiberium()")
	
	for i=1, #global.tibOrePos, 1 do
		if global.tibOrePos[i].amount <= global.maxGrothAmount then
			global.tibOrePos[i].amount = global.tibOrePos[i].amount+global.tibGrowthAmount
		end
		--check for spread
		if global.tibOrePos[i].amount >= global.minTibSpreadAmount then --spread value reached?
			
			--add new ores to empty adjacent squares
			orePositions = {{ global.tibOrePos[i].position.x + 1, global.tibOrePos[i].position.y }, { global.tibOrePos[i].position.x - 1, global.tibOrePos[i].position.y }, 
							{ global.tibOrePos[i].position.x, global.tibOrePos[i].position.y + 1 }, { global.tibOrePos[i].position.x, global.tibOrePos[i].position.y - 1 }}
	
			for i=1,4,1 do
			--check if adjacent square is blocked
			local tile = game.surfaces[1].get_tile(orePositions[i][1], orePositions[i][2])
				if tile.valid and not tile.collides_with("player-layer") then
					
					local adjacentEntities = game.surfaces[1].find_entities_filtered{position = orePositions[i]}
	   
					if #adjacentEntities == 0 then
						--add new ore here
						local newOre = game.surfaces[1].create_entity{name = global.tibOreType, position = orePositions[i], amount = 1}
						--table.insert(global.oreList, newOre)
					end
				end
			end
		end	
	end
end -- tiberium


script.on_event(defines.events.on_tick, function(event)
	
	--check if players are over tiberium, damage them if they are unarmored
	for i, player in pairs (game.players) do
		local playerPositionOre = game.surfaces[1].find_entities_filtered{name = global.tibOreType, position = game.players[i].position}
		if #playerPositionOre > 0 and game.players[i] and game.players[i].valid and game.players[i].character and not game.players[i].character.vehicle then
			game.players[i].character.damage(global.contactDamage, game.forces.tiberium, "acid")
		end
	  
		--if player is holding tiberium products, add damage
		--[[local inventory = game.players[i].get_inventory(defines.inventory.item_main)
			if inventory then
				for p=1,#global.tiberiumProducts,1 do
				if inventory.get_item_count(global.tiberiumProducts[p]) > 0 then
					game.players[i].character.damage(0.1, game.forces.tiberium, "acid")
					break
				end
			end
		end--]]
    end	
	
	--counter for growing tiberium
	global.tickCounter = global.tickCounter + 1
	
	if global.tickCounter >= global.tibGrowthRate*60 then -- growthtime in seconds
		tiberium() -- function for growing tiberium
		global.tickCounter = 0 -- restart counter
	end
	
	global.chunkCounter = global.chunkCounter + 1
	
	
	-- this funtions updates all tiberiumtiles at once
	--global.tibOrePos=game.surfaces[1].find_entities_filtered{name = global.tibOreType} -- array with position of ore
	--for i=1, #global.tibOrePos, 1 do
	--	global.tibOrePos[i].amount = global.tibOrePos[i].amount+global.tibGrowthAmount
	--end
end) -- on_tick



What needs to be done:
cycle through chunks and update the within tiberiumtiles

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Tiberium mod for 0.17

Post by eradicator »

Oh. Growing ore. That's not gonna be cheap yea.

I'll do some speculation about what might be feasible

on_chunk_generated:
Fetch ore when it is placed (no clue how this works with RSO, you'd have to ask @orzelek).
Build a huge array of all resource entities.

on_resource_depleted:
Remove the resource entity from the array. Update the array entries of surrounding tiberium to can_grow=true.

when adding to the array:
scan the 9x9 area around the resource to check if it *can* grow at all. i.e. if there's already 8 dense tiberium/water around it there's no point in checking again until that changes. If it can't grow set can_grow = false.

For the main loop you iterate through all array entries that can_grow. If you want fixed-time updates i recommend this (shameless self advertisement).

If the only data you need to store is can_grow it'd be more space efficient if the table is {entity=can_grow}, i.e. use the entity references as table keys. Then build an index of all entities that are can_grow==true for iteration.

Iterating over entities instead of chunks has the benefit of being a) easier and b) having a sort of "random" grow effect instead of all tiles in a chunk updating at the same time.


On a more conceptual level (not knowing the original mod)...is there any limit to the growth? There's always gonna be some tiberium in the "dark chunks", i.e. chunks that have been generated but not explored. Sounds kinda scary if it just infinetly grows from there? Like...you explore and then you go back 100 hours later and there's now an unstoppable 5 billion tiberium field?
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

User avatar
darkfrei
Smart Inserter
Smart Inserter
Posts: 2904
Joined: Thu Nov 20, 2014 11:11 pm
Contact:

Re: Tiberium mod for 0.17

Post by darkfrei »

silenceko wrote:
Mon Jun 17, 2019 4:32 pm
damage player
damage buildings
Damage from ores https://mods.factorio.com/mod/dangOreus

Tiberium https://mods.factorio.com/mod/Fixed_Tiberium

Hiladdar
Fast Inserter
Fast Inserter
Posts: 214
Joined: Mon May 14, 2018 6:47 pm
Contact:

Re: Tiberium mod for 0.17

Post by Hiladdar »

Spawners and bugs already do something similar, expand. It just would be a new type of entity that increases in size and mass that can be mined, and as it grows, it can destroy player made constructs.

Implementation of how the new ore will spread can be modeled on how pollution spreads.

Rather then having one update per tic, I recommend a minimum of one update per 60 tics, since there are 60 ticks per second. I'd even think about doing some checks for growth in the size of the new ore field to be one update per 300 tics. I can see where this can really slow processing down if the checks are too aggressive.

There can be several mathematical techniques which can mitigate a field too dense, having an optimum growth set around a location which has a density of say 1000, set to grow 1% every minute based of a bell curve, but beyond, say 5k density on a tile, it only grows .01% in density. Field expansion can be set as a probability, say between .01% and 50%, based on the density and number of neighboring tiles, and total size of the field.

The other question is what happens to a biter, spitter, wurm, or nest that is affected by the new ore. Will they attack it, as if it is producing pollution? Will they affected by it and be mutated in some way? Will they just ignore it?

Finally it would make sense to have a new type of miner that can mine the new ore, with some sort of immunity to the effects of the new ore. The other question that comes up, is how to processes and render the new ore non-damaging vanilla equipment. One option is to have the miners take some damage necessitating the use of construction robots to repair miners, chests and belts. Will the new miners be affected my mining productivity? Trying to mine something out of existence is much easier if your mining productivity is less then 100% then if it is 500%. Finally what will the player dispose of all the excess and unwanted ore?

I think you have the genesis of a great module and once done, I would take it for a play through

Hiladdar

Post Reply

Return to “Modding help”