Page 1 of 1

[REQUEST] Control center

Posted: Thu Mar 27, 2014 2:33 am
by y.petremann
The devs said that they would like to make possible to play he game in a RTS like way.

On my freeplay, I've found myself doing this command to get Godlike controls :

Code: Select all

game.player.setcontroller{type=defines.controllers.god}
And I would like to see a way to have godlike controls by entering a control center and get back to character when exiting it.
When in that control center, we could have godlike controls but would be constrained in a area (impossibility to move and build ouside some limits)
But :
  1. I would like to regain control of my character. How ?
  2. How could I handle entering and exiting that control center ? Would it be a non-moving vehicle ?
  3. How could we limits move and building capacity ?
(I ask here in that way because I would like to make it but don't know how, and if somebody wants to make it, it would be really great)

Re: [REQUEST] Control center

Posted: Thu Mar 27, 2014 2:50 am
by FreeER
well, a non-moving vehicle would work decently as a control center. You'd check ontick (or game.tick%60 so it's only every second)

Code: Select all

if game.player.vehicle and game.player.vehicle.name=="control-center" then
  if game.player.controller.type~=defines.controllers.god then --I'm not sure about this code, but check to see if the player is already 'god'
    game.player.setcontroller{type=defines.controllers.god} -- if not, make him 'god'
  else -- if he is 'god', insert range check code here
  end
elseif game.player.controller.type==defines.controllers.god then -- if player is NOT in control-center and if he is 'god'
    game.player.setcontroller{type=defines.controllers.character} -- not sure if this is proper code to restore control...
end
On limiting the building capacity...I'm not sure how you could do that. From my understanding 'god' has the same building rights as the character (perhaps even greater placement range). If you simply wanted a certain range at which he could no longer build past, then you could switch to the ghost controller at that point
On limiting movement, you can have an else in the second if statement (the one that checks if player is god) so that when he is and his game.player.position > 150 from the control-center it teleports him back closer to the control center.

note: it might be game.player.character.vehicle (not game.player.vehicle)...
sorry about the 'uncertain' code, I really haven't played with changing controllers

Re: [REQUEST] Control center

Posted: Thu Mar 27, 2014 7:49 am
by SilverWarior
Something similar is already planned by developers. Kovarex mentioned it here:
https://forums.factorio.com/forum/vie ... f=6&t=2889

Re: [REQUEST] Control center

Posted: Thu Mar 27, 2014 10:16 am
by rk84
FreeER wrote:well, a non-moving vehicle would work decently as a control center. You'd check ontick (or game.tick%60 so it's only every second)

Code: Select all

if game.player.vehicle and game.player.vehicle.name=="control-center" then
  if game.player.controller.type~=defines.controllers.god then --I'm not sure about this code, but check to see if the player is already 'god'
    game.player.setcontroller{type=defines.controllers.god} -- if not, make him 'god'
  else -- if he is 'god', insert range check code here
  end
elseif game.player.controller.type==defines.controllers.god then -- if player is NOT in control-center and if he is 'god'
    game.player.setcontroller{type=defines.controllers.character} -- not sure if this is proper code to restore control...
end
On limiting the building capacity...I'm not sure how you could do that. From my understanding 'god' has the same building rights as the character (perhaps even greater placement range). If you simply wanted a certain range at which he could no longer build past, then you could switch to the ghost controller at that point
On limiting movement, you can have an else in the second if statement (the one that checks if player is god) so that when he is and his game.player.position > 150 from the control-center it teleports him back closer to the control center.

note: it might be game.player.character.vehicle (not game.player.vehicle)...
sorry about the 'uncertain' code, I really haven't played with changing controllers

Code: Select all

-- controller.type without dot
if game.player.controllertype ~= defines.controllers.god then

Code: Select all

--Set to god
game.player.setcontroller({type = defines.controllers.god})
-- Back to character
game.player.setcontroller({type = defines.controllers.character, character=player_entity})
Also game.player.vehicle is ok and more "universal" (for character and god types)

Cursor position could be also be monitored/controlled.

Code: Select all

-- Get cursor map position
position = game.player.screen2realposition(game.player.cursorposition)
-- Set cursor screen position
game.player.cursorposition = game.player.real2screenposition(position)

Re: [REQUEST] Control center

Posted: Thu Mar 27, 2014 11:01 pm
by y.petremann
rk84 wrote:
FreeER wrote:well, a non-moving vehicle would work decently as a control center. You'd check ontick (or game.tick%60 so it's only every second)

Code: Select all

if game.player.vehicle and game.player.vehicle.name=="control-center" then
  if game.player.controller.type~=defines.controllers.god then --I'm not sure about this code, but check to see if the player is already 'god'
    game.player.setcontroller{type=defines.controllers.god} -- if not, make him 'god'
  else -- if he is 'god', insert range check code here
  end
elseif game.player.controller.type==defines.controllers.god then -- if player is NOT in control-center and if he is 'god'
    game.player.setcontroller{type=defines.controllers.character} -- not sure if this is proper code to restore control...
end
On limiting the building capacity...I'm not sure how you could do that. From my understanding 'god' has the same building rights as the character (perhaps even greater placement range). If you simply wanted a certain range at which he could no longer build past, then you could switch to the ghost controller at that point
On limiting movement, you can have an else in the second if statement (the one that checks if player is god) so that when he is and his game.player.position > 150 from the control-center it teleports him back closer to the control center.

note: it might be game.player.character.vehicle (not game.player.vehicle)...
sorry about the 'uncertain' code, I really haven't played with changing controllers

Code: Select all

-- controller.type without dot
if game.player.controllertype ~= defines.controllers.god then

Code: Select all

--Set to god
game.player.setcontroller({type = defines.controllers.god})
-- Back to character
game.player.setcontroller({type = defines.controllers.character, character=player_entity})
Also game.player.vehicle is ok and more "universal" (for character and god types)

Cursor position could be also be monitored/controlled.

Code: Select all

-- Get cursor map position
position = game.player.screen2realposition(game.player.cursorposition)
-- Set cursor screen position
game.player.cursorposition = game.player.real2screenposition(position)
Thanks for all your help. Mainly for the "Back to character" part, which was my main problem.

Is it possible to change the build possibility with some boolean variable ?

Also, I've used a lot Computercraft in Minecraft and would like to know if it's possible to inspect somes objects ingame, knowing attached methods, variables and their values.
For now my easiest mehod was putting some generated strings into the objective pane.

Re: [REQUEST] Control center

Posted: Thu Mar 27, 2014 11:26 pm
by FreeER
y.petremann wrote:Is it possible to change the build possibility with some boolean variable ?
Not that exactly, at least not that I am aware of. Entities (which of course includes the game.player.character) have a read/write 'active' boolean but that also prevents movement (and probably crafting as well), and more importantly I don't know how you'd set it for 'god' (if you could), so that may not be useful to you.
Hm, you could monitor the onentitybuilt event and simply kill anything that the player places (and reinsert the item to their inventory, as least if the item has the same name, which it usually does...). This partially depends on how exactly you want to limit them. If you just want to limit it based on range from the control-center you could switch the controller from god to ghost (and then back) at a certain distance.
y.petremann wrote:if it's possible to inspect somes objects ingame, knowing attached methods, variables and their values.
Somewhat...you can check their names, positions, orientations and a few other things, but you can't 'inspect'/'learn' their methods ingame. see a listing for entity variables and methods here on the wiki. and of other objects (game, player, recipes, etc.) here

Re: [REQUEST] Control center

Posted: Wed Apr 02, 2014 2:15 am
by Copern
Make sure to store the character controller somewhere before switching to the god controller. Keep in mind that when you switch to the god controller you will no longer be in a vehicle. Your character controller will still be in the vehicle you entered though. Simply checking if the player left a vehicle to switch back to the character controller won't work.

What you could do is create a button upon switching to the god controller when the character is detected in a control center. If that button is pressed, switch back to the character controller that you stored somewhere. Remember that the character controller is still in the vehicle and as far as I'm aware there's no way to force a character to exit a vehicle. There could be a flag that you flip after pressing the button. If the flag is set, prevent the player from getting switched back to the god controller. Flip the flag back once you've detected the character is out of the vehicle.

FreeER basically covered the things you could do about limiting building and movement range, don't think there's much else to say about that. I will add something about building limits though. You could create a table/dictionary at the start of a game with some predefined limits set. The key would be the entity name and the value would be another table containing limit and count. If you want to have a default limit for a bunch of building types, you can add a metatable with an __index defined such that it checks if the key exists in the table and if it doesn't then create a new table and finally return the value. It could look a little like this.

Code: Select all

local buildings = setmetatable({},
	{__index = function(table, key)
		if not rawget(table, key) then
			rawset(table, key, {limit=100, count = 0})
		end
		return rawget(table, key)
	end})

buildings["assembling-machine"] = {limit=300, count = 0}
-- ...more data
Further expanding on this, we could make getting count slightly easier by giving the subtables a metatable with __len defined to return the count. We could just have a function that tells us if we are at the limit too. It's quite likely we'll never want to modify limit (except perhaps on version updates) and we are probably only going to increment/decrement count by 1. Let's do something about that.

Code: Select all

-- Probably could have a better name - too lazy to come up with one atm
local Counter = {}

function Counter:new(limit, count)
	local instance = {}
	local limit = limit
	local count = count or 0

	function instance.getlimit()
		return limit
	end

	function instance.atlimit()
		return count == limit
	end

	function instance.increment()
		count = count + 1
	end

	function instance.decrement()
		count = count - 1
	end

	setmetatable(instance,
	{__len = function(table)
		return count
	end,
	__newindex = function() end})

	return instance
end
We still have the ability to change the limits in updates by creating a new instance with the count of the previous instance. Let's modify the previous buildings table slightly to reflect the changes.

Code: Select all

local buildings = setmetatable({},
	{__index = function(table, key)
		if not rawget(table, key) then
			rawset(table, key, Counter:new(100))
		end
		return rawget(table, key)
	end})

buildings["assembling-machine"] = Counter:new(300)
-- ...more data
Now we have that out of the way. Let's have a very quick look at how we would use this with onentitybuilt.

Code: Select all

game.onevent(defines.events.onentitybuilt, function(event)
	local ent = event.createdentity
	local counter = buildings[ent.name]

	if not counter.atlimit() then -- or... if #counter < counter.getlimit() then
		counter.increment()
	else
		-- Do stuff FreeER mentioned in the previous post
	end
end)
You can take it further by having the limits set per control center instead of for everything. But I'm just going to leave it at that for now. Hope all this was helpful in some way.

Re: [REQUEST] Control center

Posted: Wed Apr 02, 2014 3:27 am
by FreeER
Copern wrote:Hope all this was helpful in some way.
That was helpful to me at least! I should really look further into metatables sometime... :lol:

Re: [REQUEST] Control center

Posted: Wed Apr 02, 2014 3:32 am
by Copern
Glad to hear it was of some use! Metatables are a great thing to know and understand. They are a very powerful mechanism, definitely take some time to look into them.

Re: [REQUEST] Control center

Posted: Wed Apr 02, 2014 12:33 pm
by rk84
Copern wrote:...Remember that the character controller is still in the vehicle and as far as I'm aware there's no way to force a character to exit a vehicle...

Code: Select all

vehicle.passenger = nil
I would like to add that inventories do not carry over in controller type switch. So there might be problem with "Do player need stuff from character?" or "what to do with stuff that player collects in god mode in the end?".

Re: [REQUEST] Control center

Posted: Wed Apr 02, 2014 6:23 pm
by Copern
rk84 wrote:

Code: Select all

vehicle.passenger = nil
Ahh ok, I don't recall seeing a passenger property mentioned in the wiki. Seems some things are still missing in it.