1
0
mirror of https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn.git synced 2024-12-14 10:23:17 +02:00

Adding locale back in to main source, instead of a submodule.

This commit is contained in:
Oarcinae 2017-08-05 09:47:46 -04:00
parent 4af8d328fe
commit fe1bdbf61a
12 changed files with 3287 additions and 4 deletions

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "oarc_utils"]
path = locale
url = https://github.com/Oarcinae/FactorioUtils

1
locale

@ -1 +0,0 @@
Subproject commit a788fcc4ac079eee1c52b88cf79722b09bf97a96

21
locale/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 Oarcinae
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

18
locale/README.md Normal file
View File

@ -0,0 +1,18 @@
# FactorioUtils
My softmod utilities for factorio
## Instructions
Include this repo inside a folder named "locale". This is the only folder that can be included in a scenario.
## Note
This is meant to be used with my own scenarios. It's hacky but convenient for myself.
## Credit
RSO is not my own creation. It was done by Orzelek. I requested permission to include it in my scenario.
https://mods.factorio.com/mods/orzelek/rso-mod
Several other portions of the code (tags, frontier style rocket silo) have also been adapted from other scenario code.
Credit to 3Ra as well: https://github.com/3RaGaming/3Ra-Enhanced-Vanilla

79
locale/frontier_silo.lua Normal file
View File

@ -0,0 +1,79 @@
-- frontier_silo.lua
-- Nov 2016
require("config")
require("locale/oarc_utils")
-- Create a rocket silo
local function CreateRocketSilo(surface, chunkArea, force)
if CheckIfInArea(global.siloPosition, chunkArea) then
-- Delete any entities beneat the silo?
for _, entity in pairs(surface.find_entities_filtered{area = {{global.siloPosition.x-5, global.siloPosition.y-6},{global.siloPosition.x+6, global.siloPosition.y+6}}}) do
entity.destroy()
end
-- Set tiles below the silo
local tiles = {}
local i = 1
for dx = -6,6 do
for dy = -7,6 do
tiles[i] = {name = "grass", position = {global.siloPosition.x+dx, global.siloPosition.y+dy}}
i=i+1
end
end
surface.set_tiles(tiles, false)
tiles = {}
i = 1
for dx = -5,5 do
for dy = -6,5 do
tiles[i] = {name = "concrete", position = {global.siloPosition.x+dx, global.siloPosition.y+dy}}
i=i+1
end
end
surface.set_tiles(tiles, true)
-- Create silo and assign to a force
local silo = surface.create_entity{name = "rocket-silo", position = {global.siloPosition.x+0.5, global.siloPosition.y}, force = force}
silo.destructible = false
silo.minable = false
-- Make silo safe from being removed.
if ENABLE_REGROWTH then
OarcRegrowthOffLimits(global.siloPosition, 5)
end
end
end
-- Generates the rocket silo during chunk generation event
-- Includes a crop circle
function GenerateRocketSiloChunk(event)
local surface = event.surface
local chunkArea = event.area
local chunkAreaCenter = {x=chunkArea.left_top.x+(CHUNK_SIZE/2),
y=chunkArea.left_top.y+(CHUNK_SIZE/2)}
local safeArea = {left_top=
{x=global.siloPosition.x-150,
y=global.siloPosition.y-150},
right_bottom=
{x=global.siloPosition.x+150,
y=global.siloPosition.y+150}}
-- Clear enemies directly next to the rocket
if CheckIfInArea(chunkAreaCenter,safeArea) then
for _, entity in pairs(surface.find_entities_filtered{area = chunkArea, force = "enemy"}) do
entity.destroy()
end
end
-- Create rocket silo
CreateRocketSilo(surface, chunkArea, MAIN_FORCE)
CreateCropCircle(surface, global.siloPosition, chunkArea, 40)
end
function ChartRocketSiloArea(force, surface)
force.chart(surface, {{global.siloPosition.x-(CHUNK_SIZE*2), global.siloPosition.y-(CHUNK_SIZE*2)}, {global.siloPosition.x+(CHUNK_SIZE*2), global.siloPosition.y+(CHUNK_SIZE*2)}})
end

1105
locale/oarc_utils.lua Normal file

File diff suppressed because it is too large Load Diff

269
locale/rso/drand.lua Normal file
View File

@ -0,0 +1,269 @@
--[[------------------------------------
RandomLua v0.3.1
Pure Lua Pseudo-Random Numbers Generator
Under the MIT license.
copyright(c) 2011 linux-man
--]]------------------------------------
local _M = {}
local mod = math.fmod
local floor = math.floor
local abs = math.abs
local function normalize(n) --keep numbers at (positive) 32 bits
return n % 0x80000000
end
local function bit_and(a, b)
local r = 0
local m = 0
for m = 0, 31 do
if (a % 2 == 1) and (b % 2 == 1) then r = r + 2^m end
if a % 2 ~= 0 then a = a - 1 end
if b % 2 ~= 0 then b = b - 1 end
a = a / 2 b = b / 2
end
return normalize(r)
end
local function bit_or(a, b)
local r = 0
local m = 0
for m = 0, 31 do
if (a % 2 == 1) or (b % 2 == 1) then r = r + 2^m end
if a % 2 ~= 0 then a = a - 1 end
if b % 2 ~= 0 then b = b - 1 end
a = a / 2 b = b / 2
end
return normalize(r)
end
local function bit_xor(a, b)
local r = 0
local m = 0
for m = 0, 31 do
if a % 2 ~= b % 2 then r = r + 2^m end
if a % 2 ~= 0 then a = a - 1 end
if b % 2 ~= 0 then b = b - 1 end
a = a / 2 b = b / 2
end
return normalize(r)
end
local function seed()
--return normalize(tonumber(tostring(os.time()):reverse()))
return normalize(os.time())
end
--Mersenne twister
mersenne_twister = {}
mersenne_twister.__index = mersenne_twister
function mersenne_twister:randomseed(s)
if not s then s = seed() end
self.mt[0] = normalize(s)
for i = 1, 623 do
self.mt[i] = normalize(0x6c078965 * bit_xor(self.mt[i-1], floor(self.mt[i-1] / 0x40000000)) + i)
end
end
function mersenne_twister:random(a, b)
local y
if self.index == 0 then
for i = 0, 623 do
--y = bit_or(floor(self.mt[i] / 0x80000000) * 0x80000000, self.mt[(i + 1) % 624] % 0x80000000)
y = self.mt[(i + 1) % 624] % 0x80000000
self.mt[i] = bit_xor(self.mt[(i + 397) % 624], floor(y / 2))
if y % 2 ~= 0 then self.mt[i] = bit_xor(self.mt[i], 0x9908b0df) end
end
end
y = self.mt[self.index]
y = bit_xor(y, floor(y / 0x800))
y = bit_xor(y, bit_and(normalize(y * 0x80), 0x9d2c5680))
y = bit_xor(y, bit_and(normalize(y * 0x8000), 0xefc60000))
y = bit_xor(y, floor(y / 0x40000))
self.index = (self.index + 1) % 624
if not a then return y / 0x80000000
elseif not b then
if a == 0 then return y
else return 1 + (y % a)
end
else
return a + (y % (b - a + 1))
end
end
function _M.twister(s)
local temp = {}
setmetatable(temp, mersenne_twister)
temp.mt = {}
temp.index = 0
temp:randomseed(s)
return temp
end
--Linear Congruential Generator
linear_congruential_generator = {}
linear_congruential_generator.__index = linear_congruential_generator
function linear_congruential_generator:random(a, b)
local y = (self.a * self.x + self.c) % self.m
self.x = y
if not a then return y / 0x10000
elseif not b then
if a == 0 then return y
else return 1 + (y % a) end
else
return a + (y % (b - a + 1))
end
end
function linear_congruential_generator:randomseed(s)
if not s then s = seed() end
self.x = normalize(s)
end
function _M.lcg(s, r)
local temp = {}
setmetatable(temp, linear_congruential_generator)
temp.a, temp.c, temp.m = 1103515245, 12345, 0x10000 --from Ansi C
if r then
if r == 'nr' then temp.a, temp.c, temp.m = 1664525, 1013904223, 0x10000 --from Numerical Recipes.
elseif r == 'mvc' then temp.a, temp.c, temp.m = 214013, 2531011, 0x10000 end--from MVC
end
temp:randomseed(s)
return temp
end
-- Multiply-with-carry
multiply_with_carry = {}
multiply_with_carry.__index = multiply_with_carry
function multiply_with_carry:random(a, b)
local m = self.m
local t = self.a * self.x + self.c
local y = t % m
self.x = y
self.c = floor(t / m)
if not a then return y / 0x10000
elseif not b then
if a == 0 then return y
else return 1 + (y % a) end
else
local diff = 0
if a == b then return a end
if a < 0 then
diff = abs(a)
a = a + diff
b = b + diff
end
return a + (y % (b - a + 1)) - diff
end
end
function multiply_with_carry:randomseed(s)
if not s then s = seed() end
self.c = self.ic
self.x = normalize(s)
end
function _M.mwc(s, r)
local temp = {}
setmetatable(temp, multiply_with_carry)
temp.a, temp.c, temp.m = 1103515245, 12345, 0x10000 --from Ansi C
if r then
if r == 'nr' then temp.a, temp.c, temp.m = 1664525, 1013904223, 0x10000 --from Numerical Recipes.
elseif r == 'mvc' then temp.a, temp.c, temp.m = 214013, 2531011, 0x10000 end--from MVC
end
temp.ic = temp.c
temp:randomseed(s)
return temp
end
function _M.mwvc(s)
return _M.mwc(s, 'mvc')
end
local B = 0x10000
-- rough adaptation of Knuth float generator
function _M.krandom( seedobj, fVal1, fVal2 )
local ma = seedobj.ma
local seed = seedobj.seed
local mj, mk
if seed < 0 or not ma then
ma = {}
seedobj.ma = ma
mj = normalize( seed )
mj = mod( mj, B )
ma[55] = mj
mk = 1
for i = 1, 54 do
local ii = mod( 21 * i, 55 )
ma[ii] = mk
mk = mj - mk
if mk < 0 then mk = mk + B end
mj = ma[ii]
end
for k = 1, 4 do
for i = 1, 55 do
ma[i] = ma[i] - ma[ 1 + mod( i + 30, 55) ]
if ma[i] < 0 then ma[i] = ma[i] + B end
end
end
seedobj.inext = 0
seedobj.inextp = 31
seedobj.seed = 1
end -- if
local inext = seedobj.inext
local inextp = seedobj.inextp
inext = inext + 1
if inext == 56 then inext = 1 end
seedobj.inext = inext
inextp = inextp + 1
if inextp == 56 then inextp = 1 end
seedobj.inextp = inextp
mj = ma[ inext ] - ma[ inextp ]
if mj < 0 then mj = mj + B end
ma[ inext ] = mj
local temp_rand = mj / B
if fVal2 then
return floor( fVal1 + 0.5 + temp_rand * ( fVal2 - fVal1 ) )
elseif fVal1 then
return floor( temp_rand * fVal1 ) + 1
else
return temp_rand
end
end
-- Sys rand
sys_rand = {}
sys_rand.__index = sys_rand
function sys_rand:random(a, b)
local diff = 0
if a and b and a == b then math.random(); return a end
if a and b then
if a < 0 then
diff = abs(a)
a = a + diff
b = b + diff
end
return math.random(a, b) - diff
end
if a and a == 0 then return floor(math.random() * 0x10000) end
if a then return math.random(a) end
return math.random()
end
function sys_rand:randomseed(s)
-- ignore
return
end
function _M.sys_rand(s)
local temp = {}
setmetatable(temp, sys_rand)
return temp
end
return _M

104
locale/rso/metaball.lua Normal file
View File

@ -0,0 +1,104 @@
--[[--
Metaball implementation for LUA by Dark
For bruteforce usage, nor efficient nor fast
Force scales to from inf to 1 at R
--]]--
local _M = {}
local sqrt = math.sqrt
local cos = math.cos
local sin = math.sin
local abs = math.abs
local zero_value = 0x80000000
--Classic ball
local MetaBall = {x=0, y=0, radius=0, goo=1, type="MetaBall"}
MetaBall.__index = MetaBall
_M.MetaBall=MetaBall
function MetaBall:new(x, y, radius, goo)
goo = goo or 1
return setmetatable({x=x, y=y, radius=radius, goo=goo}, MetaBall)
end
function MetaBall:force(x, y)
--Calculate force at point x y
local force = sqrt( (x - self.x)^2 + (y - self.y)^2 )
if force == 0 then return zero_value end
return (self.radius / force)^self.goo
end
--Ellipse
local MetaEllipse = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaEllipse"}
MetaEllipse.__index = MetaEllipse
_M.MetaEllipse=MetaEllipse
function MetaEllipse:new(x, y, radius, angle, x_scale, y_scale, goo)
angle = angle or 0
x_scale = x_scale or 1
y_scale = y_scale or 1
goo = goo or 1
cosa = cos(angle)
sina = sin(angle)
return setmetatable({x=x, y=y, radius=radius, angle=angle, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaEllipse)
end
function MetaEllipse:force(x, y)
--Calculate force at point x y
local force = sqrt( (( (x - self.x)*self.cosa + (y - self.y)*self.sina )^2)/(self.x_scale) +
(( (y - self.y)*self.cosa - (x - self.x)*self.sina )^2)/(self.y_scale) )
if force == 0 then return zero_value end
return (self.radius / force)^self.goo
end
--SquareBalls
local MetaSquare = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaSquare"}
MetaSquare.__index = MetaSquare
_M.MetaSquare=MetaSquare
function MetaSquare:new(x, y, radius, angle, x_scale, y_scale, goo)
angle = angle or 0
x_scale = x_scale or 1
y_scale = y_scale or 1
goo = goo or 1
cosa = cos(angle)
sina = sin(angle)
return setmetatable({x=x, y=y, radius=radius, angle=angle, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaSquare)
end
function MetaSquare:force(x, y)
--Calculate force at point x y
local force = ( abs( (x - self.x)*self.cosa + (y - self.y)*self.sina )/self.x_scale +
abs( (y - self.y)*self.cosa - (x - self.x)*self.sina )/self.y_scale )
if force == 0 then return zero_value end
return (self.radius / force)^self.goo
end
--Donuts
local MetaDonut = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaDonut"}
MetaDonut.__index = MetaDonut
_M.MetaDonut=MetaDonut
function MetaDonut:new(x, y, out_r, int_r, angle, x_scale, y_scale, goo)
angle = angle or 0
x_scale = x_scale or 1
y_scale = y_scale or 1
goo = goo or 1
cosa = cos(angle)
sina = sin(angle)
if int_r >= out_r then error("int_r >= out_r ("..int_r.." > "..out_r); return; end
local radius = out_r--(out_r - int_r)*0.5
local radius2 = int_r--(radius2 + radius)*0.5
return setmetatable({x=x, y=y, radius=radius, radius2=radius2, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaDonut)
end
function MetaDonut:force(x, y)
--Calculate force at point x y
local force = abs(self.radius - sqrt( (( (x - self.x)*self.cosa + (y - self.y)*self.sina )^2)/(self.x_scale) +
(( (y - self.y)*self.cosa - (x - self.x)*self.sina )^2)/(self.y_scale) ))
if force == 0 then return zero_value end
return (self.radius2 / force)^self.goo
end
return _M

55
locale/rso/rso_config.lua Normal file
View File

@ -0,0 +1,55 @@
debug_enabled = false
region_size = 10 -- alternative mean to control how further away resources would be, default - 256 tiles or 8 chunks
-- each region is region_size*region_size chunks
-- each chunk is 32*32 tiles
use_donut_shapes = false -- setting this to false will remove donuts from possible resource layouts
starting_area_size = 0 -- starting area in regions, safe from random nonsense
absolute_resource_chance = 0.50 -- chance to spawn an resource in a region
starting_richness_mult = 1 -- multiply starting area richness for resources
global_richness_mult = 1 -- multiply richness for all resources except starting area
global_size_mult = 1 -- multiply size for all ores, doesn't affect starting area
absolute_enemy_chance = 3 -- chance to spawn enemies per sector (can be more then one base if spawned)
enemy_base_size_multiplier = 1 -- all base sizes will be multiplied by this - larger number means bigger bases
multi_resource_active = false -- global switch for multi resource chances
multi_resource_richness_factor = 0.60 -- any additional resource is multiplied by this value times resources-1
multi_resource_size_factor = 0.90
multi_resource_chance_diminish = 0.6 -- diminishing effect factor on multi_resource_chance
min_amount=250 -- default value for minimum amount of resource in single pile
richness_distance_factor= 1 -- exponent for richness distance factor calculation
fluid_richness_distance_factor = 0.8 -- exponent for richness distance factor calculation for fluids
size_distance_factor=0.15 -- exponent for size distance factor calculation
deterministic = true -- set to false to use system for all decisions math.random
-- mode is no longer used by generation process - it autodetects endless resources
-- endless_resource_mode = false -- if true, the size of each resource is modified by the following modifier. Use with the endless resources mod.
endless_resource_mode_sizeModifier = 0.80
-- This setting isn't used anywhere in the soft mod version of RSO -- OARC
-- Just set it from Oarc's config.lua (look for ENEMY_EXPANSION)
-- disableEnemyExpansion = false -- allows for disabling of in-game biter base building
use_RSO_biter_spawning = true -- enables spawning of biters controlled by RSO mod - less enemies around with more space between bases
use_vanilla_biter_spawning = false -- enables using of vanilla spawning
biter_ratio_segment=3 --the ratio components determining how many biters to spitters will be spawned
spitter_ratio_segment=1 --eg. 1 and 1 -> equal number of biters and spitters, 10 and 1 -> 10 times as many biters to spitters
useEnemiesInPeaceMod = false -- additional override for peace mod detection - when set to true it will spawn enemies normally, needs to have enemies enabled in peace mod
-- Always leave this setting to true in this soft mod scenario version! -- OARC
ignoreMapGenSettings = true -- stops the default behaviour of reading map gen settings
fluidResourcesFactor = 20 -- temporary factor for calculation of resource %-ages for fluids
--
useResourceCollisionDetection = true -- enables avoidace calculations to reduce ores overlaping of each other
resourceCollisionDetectionRatio = 0.8 -- at least this much of ore field needs to be placable to spawn it
resourceCollisionFieldSkip = true -- determines if ore field should be skipped completely if placement based on ratio failed

1405
locale/rso/rso_control.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,171 @@
local function fillVanillaConfig()
config["iron-ore"] = {
type="resource-ore",
-- general spawn params
allotment=100, -- how common resource is
spawns_per_region={min=1, max=1}, --number of chunks
richness=10000, -- resource_ore has only one richness value - resource-liquid has min/max
size={min=15, max=25}, -- rough radius of area, too high value can produce square shaped areas
min_amount=350,
-- resource provided at starting location
-- probability: 1 = 100% chance to be in starting area
-- 0 = resource is not in starting area
starting={richness=8000, size=25, probability=1},
multi_resource_chance=0.20, -- absolute value
multi_resource={
["iron-ore"] = 2, -- ["resource_name"] = allotment
['copper-ore'] = 4,
["coal"] = 4,
["stone"] = 4,
}
}
config["copper-ore"] = {
type="resource-ore",
allotment=90,
spawns_per_region={min=1, max=1},
richness=10000,
size={min=15, max=25},
min_amount=350,
starting={richness=6000, size=25, probability=1},
multi_resource_chance=0.20,
multi_resource={
["iron-ore"] = 4,
['copper-ore'] = 2,
["coal"] = 4,
["stone"] = 4,
}
}
config["coal"] = {
type="resource-ore",
allotment=80,
spawns_per_region={min=1, max=1},
size={min=15, max=25},
richness=8000,
min_amount=350,
starting={richness=6000, size=20, probability=1},
multi_resource_chance=0.30,
multi_resource={
["crude-oil"] = 1,
["iron-ore"] = 3,
['copper-ore'] = 3,
}
}
config["stone"] = {
type="resource-ore",
allotment=60,
spawns_per_region={min=1, max=1},
richness=6000,
size={min=15, max=20},
min_amount=250,
starting={richness=5000, size=16, probability=1},
multi_resource_chance=0.30,
multi_resource={
["coal"] = 4,
["iron-ore"] = 3,
['copper-ore'] = 3,
}
}
config["uranium-ore"] = {
type="resource-ore",
allotment=50,
spawns_per_region={min=1, max=1},
richness=10000,
size={min=15, max=20},
min_amount=500,
starting={richness=2000, size=10, probability=1},
}
config["crude-oil"] = {
type="resource-liquid",
minimum_amount=10000,
allotment=70,
spawns_per_region={min=1, max=2},
richness={min=100000, max=200000}, -- richness per resource spawn
size={min=3, max=7},
starting={richness=200000, size=2, probability=1},
multi_resource_chance=0.20,
multi_resource={
["coal"] = 4,
}
}
end
local function fillEnemies()
config["enemy-base"] = {
type="entity",
force="enemy",
clear_range = {6, 6},
spawns_per_region={min=2,max=4},
size={min=2,max=4},
size_per_region_factor=1,
richness=3,
absolute_probability=absolute_enemy_chance, -- chance to spawn in region
probability_distance_factor=1.1, -- relative increase per region
max_probability_distance_factor=3, -- absolute value
along_resource_probability=0.20, -- chance to spawn in resource chunk anyway, absolute value. Can happen once per resource.
sub_spawn_probability=0.1, -- chance for this entity to spawn anything from sub_spawns table, absolute value
sub_spawn_size={min=1, max=2}, -- in same chunk
sub_spawn_distance_factor=1.01,
sub_spawn_max_distance_factor=1.5,
sub_spawns={
["small-worm-turret"]={
min_distance=0,
allotment=200,
allotment_distance_factor=0.99,
clear_range = {2, 2},
},
["medium-worm-turret"]={
min_distance=10,
allotment=100,
allotment_distance_factor=1.01,
clear_range = {2, 2},
},
["big-worm-turret"]={
min_distance=20,
allotment=100,
allotment_distance_factor=1.015,
clear_range = {2, 2},
}
}
}
end
function loadResourceConfig()
config={}
fillVanillaConfig()
fillEnemies()
return config
end

60
locale/tag.lua Normal file
View File

@ -0,0 +1,60 @@
-- control.lua
-- Apr 2017
function CreateTagGui(event)
local player = game.players[event.player_index]
if player.gui.top.tag == nil then
player.gui.top.add{name="tag", type="button", caption="Tag"}
end
end
-- Tag list
local roles = {
{display_name = "[Solo]"},
{display_name = "[Mining]"},
{display_name = "[Power]"},
{display_name = "[Oil]"},
{display_name = "[Smelt]"},
{display_name = "[Rail]"},
{display_name = "[Defense]"},
{display_name = "[Circuits]"},
{display_name = "[Science!]"},
{display_name = "[Logistics]"},
{display_name = "[Misc]"},
{display_name = "[Aliens]"},
{display_name = "[Rocket]"},
{display_name = "[AFK]"},
{display_name = "Clear"}}
local function ExpandTagGui(player)
local frame = player.gui.left["tag-panel"]
if (frame) then
frame.destroy()
else
local frame = player.gui.left.add{type="frame", name="tag-panel", caption="What are you doing:"}
for _, role in pairs(roles) do
frame.add{type="button", caption=role.display_name, name=role.display_name}
end
end
end
function TagGuiClick(event)
if not (event and event.element and event.element.valid) then return end
local player = game.players[event.element.player_index]
local name = event.element.name
if (name == "tag") then
ExpandTagGui(player)
end
if (name == "Clear") then
player.tag = ""
return
end
for _, role in pairs(roles) do
if (name == role.display_name) then
player.tag = role.display_name
end
end
end