mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-08 00:39:30 +02:00
commit
3b5a9e27b0
238
antigrief.lua
238
antigrief.lua
@ -39,31 +39,40 @@ local function on_player_demoted(event)
|
||||
if player.gui.left["admin_panel"] then player.gui.left["admin_panel"].destroy() end
|
||||
end
|
||||
]]
|
||||
|
||||
local function on_marked_for_deconstruction(event)
|
||||
local tracker = session.get_session_table()
|
||||
local trusted = session.get_trusted_table()
|
||||
if not event.player_index then return end
|
||||
local player = game.players[event.player_index]
|
||||
if player.admin == true then return end
|
||||
if trusted[player.name] == true then return end
|
||||
local tracker = session.get_session_table()
|
||||
local trusted = session.get_trusted_table()
|
||||
if not event.player_index then
|
||||
return
|
||||
end
|
||||
local player = game.players[event.player_index]
|
||||
if player.admin == true then
|
||||
return
|
||||
end
|
||||
if trusted[player.name] == true then
|
||||
return
|
||||
end
|
||||
|
||||
local playtime = player.online_time
|
||||
if tracker[player.name] then
|
||||
playtime = player.online_time + tracker[player.name]
|
||||
end
|
||||
if playtime < 2592000 then
|
||||
event.entity.cancel_deconstruction(game.players[event.player_index].force.name)
|
||||
player.print("You have not grown accustomed to this technology yet.", { r=0.22, g=0.99, b=0.99})
|
||||
end
|
||||
local playtime = player.online_time
|
||||
if tracker[player.name] then
|
||||
playtime = player.online_time + tracker[player.name]
|
||||
end
|
||||
if playtime < 2592000 then
|
||||
event.entity.cancel_deconstruction(game.players[event.player_index].force.name)
|
||||
player.print('You have not grown accustomed to this technology yet.', {r = 0.22, g = 0.99, b = 0.99})
|
||||
end
|
||||
end
|
||||
|
||||
local function on_player_ammo_inventory_changed(event)
|
||||
local tracker = session.get_session_table()
|
||||
local trusted = session.get_trusted_table()
|
||||
local player = game.players[event.player_index]
|
||||
if player.admin == true then return end
|
||||
if trusted[player.name] == true then return end
|
||||
local tracker = session.get_session_table()
|
||||
local trusted = session.get_trusted_table()
|
||||
local player = game.players[event.player_index]
|
||||
if player.admin == true then
|
||||
return
|
||||
end
|
||||
if trusted[player.name] == true then
|
||||
return
|
||||
end
|
||||
|
||||
local playtime = player.online_time
|
||||
if tracker[player.name] then
|
||||
@ -75,19 +84,25 @@ local function on_player_ammo_inventory_changed(event)
|
||||
player.surface.spill_item_stack(player.position, {name = "atomic-bomb", count = nukes}, false)
|
||||
player.print("You have not grown accustomed to this technology yet.", {r=0.22, g=0.99, b=0.99})
|
||||
Server.to_discord_bold(table.concat{'[Nuke] ' .. player.name .. ' tried to equip nukes but was not trusted.'})
|
||||
game.print('[Nuke] ' .. player.name .. ' tried to equip nukes but was not trusted.', {r=0.22, g=0.99, b=0.99})
|
||||
player.character.health = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_player_built_tile(event)
|
||||
local tracker = session.get_session_table()
|
||||
local trusted = session.get_trusted_table()
|
||||
local placed_tiles = event.tiles
|
||||
if placed_tiles[1].old_tile.name ~= "deepwater" and placed_tiles[1].old_tile.name ~= "water" and placed_tiles[1].old_tile.name ~= "water-green" then return end
|
||||
local player = game.players[event.player_index]
|
||||
local tracker = session.get_session_table()
|
||||
local trusted = session.get_trusted_table()
|
||||
local placed_tiles = event.tiles
|
||||
if
|
||||
placed_tiles[1].old_tile.name ~= 'deepwater' and placed_tiles[1].old_tile.name ~= 'water' and
|
||||
placed_tiles[1].old_tile.name ~= 'water-green'
|
||||
then
|
||||
return
|
||||
end
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
--[[
|
||||
--[[
|
||||
if not player.admin and not trusted[player.name] then
|
||||
local playtime = player.online_time
|
||||
if tracker[player.name] then
|
||||
@ -107,7 +122,9 @@ local function on_player_built_tile(event)
|
||||
--landfill history--
|
||||
if not global.landfill_history then global.landfill_history = {} end
|
||||
if #global.landfill_history > 999 then global.landfill_history = {} end
|
||||
local str = player.name .. " at X:"
|
||||
local t = math.abs(math.floor((game.tick) / 3600))
|
||||
local str = "[" .. t .. "] "
|
||||
str = str .. player.name .. " at X:"
|
||||
str = str .. placed_tiles[1].position.x
|
||||
str = str .. " Y:"
|
||||
str = str .. placed_tiles[1].position.y
|
||||
@ -115,26 +132,32 @@ local function on_player_built_tile(event)
|
||||
end
|
||||
|
||||
local function on_built_entity(event)
|
||||
local tracker = session.get_session_table()
|
||||
local trusted = session.get_trusted_table()
|
||||
if game.tick < 1296000 then return end
|
||||
|
||||
if event.created_entity.type == "entity-ghost" then
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
if player.admin == true then return end
|
||||
if trusted[player.name] == true then return end
|
||||
|
||||
local playtime = player.online_time
|
||||
if tracker[player.name] then
|
||||
playtime = player.online_time + tracker[player.name]
|
||||
end
|
||||
|
||||
if playtime < 432000 then
|
||||
event.created_entity.destroy()
|
||||
player.print("You have not grown accustomed to this technology yet.", { r=0.22, g=0.99, b=0.99})
|
||||
end
|
||||
end
|
||||
local tracker = session.get_session_table()
|
||||
local trusted = session.get_trusted_table()
|
||||
if game.tick < 1296000 then
|
||||
return
|
||||
end
|
||||
|
||||
if event.created_entity.type == 'entity-ghost' then
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
if player.admin == true then
|
||||
return
|
||||
end
|
||||
if trusted[player.name] == true then
|
||||
return
|
||||
end
|
||||
|
||||
local playtime = player.online_time
|
||||
if tracker[player.name] then
|
||||
playtime = player.online_time + tracker[player.name]
|
||||
end
|
||||
|
||||
if playtime < 432000 then
|
||||
event.created_entity.destroy()
|
||||
player.print('You have not grown accustomed to this technology yet.', {r = 0.22, g = 0.99, b = 0.99})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Artillery History and Antigrief
|
||||
@ -162,7 +185,9 @@ local function on_player_used_capsule(event)
|
||||
|
||||
if not global.artillery_history then global.artillery_history = {} end
|
||||
if #global.artillery_history > 999 then global.artillery_history = {} end
|
||||
local str = player.name .. " at X:"
|
||||
local t = math.abs(math.floor((game.tick) / 3600))
|
||||
local str = "[" .. t .. "] "
|
||||
str = str .. player.name .. " at X:"
|
||||
str = str .. math.floor(position.x)
|
||||
str = str .. " Y:"
|
||||
str = str .. math.floor(position.y)
|
||||
@ -170,15 +195,15 @@ local function on_player_used_capsule(event)
|
||||
end
|
||||
|
||||
local blacklisted_types = {
|
||||
["transport-belt"] = true,
|
||||
["wall"] = true,
|
||||
["underground-belt"] = true,
|
||||
["inserter"] = true,
|
||||
["land-mine"] = true,
|
||||
["gate"] = true,
|
||||
["lamp"] = true,
|
||||
["mining-drill"] = true,
|
||||
["splitter"] = true
|
||||
['transport-belt'] = true,
|
||||
['wall'] = true,
|
||||
['underground-belt'] = true,
|
||||
['inserter'] = true,
|
||||
['land-mine'] = true,
|
||||
['gate'] = true,
|
||||
['lamp'] = true,
|
||||
['mining-drill'] = true,
|
||||
['splitter'] = true
|
||||
}
|
||||
|
||||
--Friendly Fire History
|
||||
@ -190,8 +215,11 @@ local function on_entity_died(event)
|
||||
local player = event.cause.player
|
||||
if not global.friendly_fire_history then global.friendly_fire_history = {} end
|
||||
if #global.friendly_fire_history > 999 then global.friendly_fire_history = {} end
|
||||
if not player then return end
|
||||
local str = player.name .. " destroyed "
|
||||
if not player then return end
|
||||
|
||||
local t = math.abs(math.floor((game.tick) / 3600))
|
||||
local str = "[" .. t .. "] "
|
||||
str = str .. player.name .. " destroyed "
|
||||
str = str .. event.entity.name
|
||||
str = str .. " at X:"
|
||||
str = str .. math.floor(event.entity.position.x)
|
||||
@ -201,30 +229,6 @@ local function on_entity_died(event)
|
||||
global.friendly_fire_history[#global.friendly_fire_history + 1] = str
|
||||
end
|
||||
|
||||
local chest_types = {
|
||||
["container"] = true,
|
||||
["logistic-container"] = true
|
||||
}
|
||||
|
||||
--Bad Fire History
|
||||
local function on_entity_died_do_actual_usefull_logging(event)
|
||||
if not event.cause then return end
|
||||
if event.cause.name ~= "character" then return end
|
||||
local player = event.cause.player
|
||||
if not player then return end
|
||||
if not chest_types[event.entity.type] then return end
|
||||
|
||||
if event.entity.get_item_count("explosives") < 100 then return end
|
||||
|
||||
if not global.bad_fire_history then global.bad_fire_history = {} end
|
||||
if #global.bad_fire_history > 999 then global.bad_fire_history = {} end
|
||||
|
||||
local str = player.name .. " destroyed container with explosives amount: " .. event.entity.get_item_count("explosives") .. ", at location: "
|
||||
str = str .. " at X:" .. event.entity.position.x .. " Y:" .. event.entity.position.y
|
||||
|
||||
global.bad_fire_history[#global.bad_fire_history + 1] = str
|
||||
end
|
||||
|
||||
--Mining Thieves History
|
||||
local function on_player_mined_entity(event)
|
||||
if not event.entity.last_user then return end
|
||||
@ -236,7 +240,9 @@ local function on_player_mined_entity(event)
|
||||
if not global.mining_history then global.mining_history = {} end
|
||||
if #global.mining_history > 999 then global.mining_history = {} end
|
||||
|
||||
local str = player.name .. " mined "
|
||||
local t = math.abs(math.floor((game.tick) / 3600))
|
||||
local str = "[" .. t .. "] "
|
||||
str = str .. player.name .. " mined "
|
||||
str = str .. event.entity.name
|
||||
str = str .. " at X:"
|
||||
str = str .. math.floor(event.entity.position.x)
|
||||
@ -247,28 +253,54 @@ local function on_player_mined_entity(event)
|
||||
end
|
||||
|
||||
local function on_gui_opened(event)
|
||||
if not event.entity then return end
|
||||
if event.entity.name ~= "character-corpse" then return end
|
||||
local player = game.players[event.player_index]
|
||||
local corpse_owner = game.players[event.entity.character_corpse_player_index]
|
||||
if not corpse_owner then return end
|
||||
if corpse_owner.force.name ~= player.force.name then return end
|
||||
if player.name ~= corpse_owner.name then
|
||||
game.print(player.name .. " is looting " .. corpse_owner.name .. "´s body.", { r=0.85, g=0.85, b=0.85})
|
||||
Server.to_discord_bold(table.concat{'[Corpse] ' .. player.name .. " is looting " .. corpse_owner.name .. "´s body."})
|
||||
end
|
||||
if not event.entity then
|
||||
return
|
||||
end
|
||||
if event.entity.name ~= 'character-corpse' then
|
||||
return
|
||||
end
|
||||
local player = game.players[event.player_index]
|
||||
local corpse_owner = game.players[event.entity.character_corpse_player_index]
|
||||
if not corpse_owner then
|
||||
return
|
||||
end
|
||||
if corpse_owner.force.name ~= player.force.name then
|
||||
return
|
||||
end
|
||||
if player.name ~= corpse_owner.name then
|
||||
game.print(player.name .. ' is looting ' .. corpse_owner.name .. '´s body.', {r = 0.85, g = 0.85, b = 0.85})
|
||||
Server.to_discord_bold(
|
||||
table.concat {'[Corpse] ' .. player.name .. ' is looting ' .. corpse_owner.name .. '´s body.'}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_pre_player_mined_item(event)
|
||||
if event.entity.name ~= "character-corpse" then return end
|
||||
local player = game.players[event.player_index]
|
||||
local corpse_owner = game.players[event.entity.character_corpse_player_index]
|
||||
if not corpse_owner then return end
|
||||
if corpse_owner.force.name ~= player.force.name then return end
|
||||
if player.name ~= corpse_owner.name then
|
||||
game.print(player.name .. " has looted " .. corpse_owner.name .. "´s body.", { r=0.85, g=0.85, b=0.85})
|
||||
Server.to_discord_bold(table.concat{'[Corpse] ' .. player.name .. " has looted " .. corpse_owner.name .. "´s body."})
|
||||
end
|
||||
if event.entity.name ~= 'character-corpse' then
|
||||
return
|
||||
end
|
||||
local player = game.players[event.player_index]
|
||||
local corpse_owner = game.players[event.entity.character_corpse_player_index]
|
||||
if not corpse_owner then
|
||||
return
|
||||
end
|
||||
local entity = event.entity
|
||||
if not entity then
|
||||
return
|
||||
end
|
||||
local corpse_content = #entity.get_inventory(defines.inventory.character_corpse)
|
||||
if corpse_content <= 0 then
|
||||
return
|
||||
end
|
||||
if corpse_owner.force.name ~= player.force.name then
|
||||
return
|
||||
end
|
||||
if player.name ~= corpse_owner.name then
|
||||
game.print(player.name .. ' has looted ' .. corpse_owner.name .. '´s body.', {r = 0.85, g = 0.85, b = 0.85})
|
||||
Server.to_discord_bold(
|
||||
table.concat {'[Corpse] ' .. player.name .. ' has looted ' .. corpse_owner.name .. '´s body.'}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
event.add(defines.events.on_player_mined_entity, on_player_mined_entity)
|
||||
|
@ -70,6 +70,7 @@ require 'modules.autostash'
|
||||
--require 'maps.chronosphere.main'
|
||||
--require 'maps.fish_defender.main'
|
||||
--require 'maps.biter_battles_v2.main'
|
||||
--require 'maps.mountain_fortress_v3.main'
|
||||
--require 'maps.mountain_fortress_v2.main'
|
||||
--require 'maps.lumberjack.main'
|
||||
--require 'maps.dungeons.main'
|
||||
|
@ -18,7 +18,7 @@ local function reset_forces(new_surface, old_surface)
|
||||
end
|
||||
for _, tech in pairs(game.forces.player.technologies) do
|
||||
tech.researched = false
|
||||
game.player.force.set_saved_technology_progress(tech, 0)
|
||||
game.forces.player.set_saved_technology_progress(tech, 0)
|
||||
end
|
||||
end
|
||||
|
||||
|
70
maps/mountain_fortress_v3/balance.lua
Normal file
70
maps/mountain_fortress_v3/balance.lua
Normal file
@ -0,0 +1,70 @@
|
||||
local Event = require 'utils.event'
|
||||
local Difficulty = require 'modules.difficulty_vote'
|
||||
local Public = {}
|
||||
|
||||
function Public.init_enemy_weapon_damage()
|
||||
local data = {
|
||||
['artillery-shell'] = 0,
|
||||
['biological'] = 0.1,
|
||||
['bullet'] = 2,
|
||||
['cannon-shell'] = 0,
|
||||
['capsule'] = 0,
|
||||
['combat-robot-beam'] = 0,
|
||||
['combat-robot-laser'] = 0,
|
||||
['electric'] = 0,
|
||||
['flamethrower'] = 0,
|
||||
['grenade'] = 0,
|
||||
['landmine'] = 0,
|
||||
['laser-turret'] = 0,
|
||||
['melee'] = 0.5,
|
||||
['railgun'] = 0,
|
||||
['rocket'] = 0,
|
||||
['shotgun-shell'] = 0
|
||||
}
|
||||
|
||||
local e = game.forces.enemy
|
||||
|
||||
for k, v in pairs(data) do
|
||||
e.set_ammo_damage_modifier(k, v)
|
||||
end
|
||||
end
|
||||
|
||||
local function enemy_weapon_damage()
|
||||
local Diff = Difficulty.get()
|
||||
if game.tick < 100 then
|
||||
goto rtn
|
||||
end
|
||||
local e = game.forces.enemy
|
||||
|
||||
local data = {
|
||||
['artillery-shell'] = 0.1,
|
||||
['biological'] = 0.1,
|
||||
['bullet'] = 0.1,
|
||||
['capsule'] = 0.1,
|
||||
['combat-robot-beam'] = 0.1,
|
||||
['combat-robot-laser'] = 0.1,
|
||||
['electric'] = 0.1,
|
||||
['flamethrower'] = 0.1,
|
||||
--['grenade'] = 0.1,
|
||||
--['landmine'] = 0.1,
|
||||
['laser-turret'] = 0.1,
|
||||
['melee'] = 0.1
|
||||
--['railgun'] = 0.1,
|
||||
--['rocket'] = 0.1,
|
||||
--['shotgun-shell'] = 0.1
|
||||
}
|
||||
|
||||
for k, v in pairs(data) do
|
||||
local new = Diff.difficulty_vote_value * v
|
||||
|
||||
local e_old = e.get_ammo_damage_modifier(k)
|
||||
|
||||
e.set_ammo_damage_modifier(k, new + e_old)
|
||||
end
|
||||
|
||||
::rtn::
|
||||
end
|
||||
|
||||
Event.on_nth_tick(54000, enemy_weapon_damage)
|
||||
|
||||
return Public
|
201
maps/mountain_fortress_v3/biter_pets.lua
Normal file
201
maps/mountain_fortress_v3/biter_pets.lua
Normal file
@ -0,0 +1,201 @@
|
||||
local WPT = require 'maps.mountain_fortress_v3.table'
|
||||
|
||||
local math_random = math.random
|
||||
local nom_msg = {'munch', 'munch', 'yum'}
|
||||
|
||||
local Public = {}
|
||||
|
||||
local function feed_floaty_text(unit)
|
||||
unit.surface.create_entity(
|
||||
{
|
||||
name = 'flying-text',
|
||||
position = unit.position,
|
||||
text = nom_msg[math_random(1, #nom_msg)],
|
||||
color = {math_random(50, 100), 0, 255}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
local function floaty_hearts(entity, c)
|
||||
local position = {x = entity.position.x - 0.75, y = entity.position.y - 1}
|
||||
local b = 1.35
|
||||
for a = 1, c, 1 do
|
||||
local p = {
|
||||
(position.x + 0.4) + (b * -1 + math_random(0, b * 20) * 0.1),
|
||||
position.y + (b * -1 + math_random(0, b * 20) * 0.1)
|
||||
}
|
||||
entity.surface.create_entity(
|
||||
{name = 'flying-text', position = p, text = '♥', color = {math_random(150, 255), 0, 255}}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
local function tame_unit_effects(player, entity)
|
||||
floaty_hearts(entity, 7)
|
||||
|
||||
rendering.draw_text {
|
||||
text = '~' .. player.name .. "'s pet~",
|
||||
surface = player.surface,
|
||||
target = entity,
|
||||
target_offset = {0, -2.6},
|
||||
color = {
|
||||
r = player.color.r * 0.6 + 0.25,
|
||||
g = player.color.g * 0.6 + 0.25,
|
||||
b = player.color.b * 0.6 + 0.25,
|
||||
a = 1
|
||||
},
|
||||
scale = 1.05,
|
||||
font = 'default-large-semibold',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
end
|
||||
|
||||
local function find_unit(player, entity)
|
||||
local units =
|
||||
player.surface.find_entities_filtered(
|
||||
{
|
||||
type = 'unit',
|
||||
area = {{entity.position.x - 1, entity.position.y - 1}, {entity.position.x + 1, entity.position.y + 1}},
|
||||
limit = 1
|
||||
}
|
||||
)
|
||||
return units[1]
|
||||
end
|
||||
|
||||
local function feed_pet(unit)
|
||||
if unit.prototype.max_health == unit.health then
|
||||
return
|
||||
end
|
||||
unit.health = unit.health + 8 + math.floor(unit.prototype.max_health * 0.05)
|
||||
feed_floaty_text(unit)
|
||||
floaty_hearts(unit, math_random(1, 2))
|
||||
return true
|
||||
end
|
||||
|
||||
local function is_valid_player(player, unit)
|
||||
if not player.character then
|
||||
return
|
||||
end
|
||||
if not player.character.valid then
|
||||
return
|
||||
end
|
||||
if player.surface.index ~= unit.surface.index then
|
||||
return
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function Public.biter_pets_tame_unit(player, unit, forced)
|
||||
local this = WPT.get()
|
||||
|
||||
if this.biter_pets[player.index] then
|
||||
return false
|
||||
end
|
||||
|
||||
if not forced then
|
||||
if math_random(1, math.floor(unit.prototype.max_health * 0.01) + 1) ~= 1 then
|
||||
feed_floaty_text(unit)
|
||||
return true
|
||||
end
|
||||
end
|
||||
if unit.force.index == player.force.index then
|
||||
return false
|
||||
end
|
||||
unit.ai_settings.allow_destroy_when_commands_fail = false
|
||||
unit.ai_settings.allow_try_return_to_spawner = false
|
||||
unit.force = player.force
|
||||
unit.set_command({type = defines.command.wander, distraction = defines.distraction.by_enemy})
|
||||
this.biter_pets[player.index] = {last_command = 0, entity = unit}
|
||||
tame_unit_effects(player, unit)
|
||||
return true
|
||||
end
|
||||
|
||||
function Public.tame_unit_for_closest_player(unit)
|
||||
local valid_players = {}
|
||||
for _, player in pairs(game.connected_players) do
|
||||
if is_valid_player(player, unit) then
|
||||
table.insert(valid_players, player)
|
||||
end
|
||||
end
|
||||
|
||||
local nearest_player = valid_players[1]
|
||||
if not nearest_player then
|
||||
return
|
||||
end
|
||||
|
||||
Public.biter_pets_tame_unit(nearest_player, unit, true)
|
||||
end
|
||||
|
||||
local function command_unit(entity, player)
|
||||
if entity.surface ~= player.surface then
|
||||
return
|
||||
end
|
||||
local square_distance = (player.position.x - entity.position.x) ^ 2 + (player.position.y - entity.position.y) ^ 2
|
||||
|
||||
--Pet will follow, if the player is between a distance of 8 to 160 tiles away from it.
|
||||
if square_distance < 64 or square_distance > 25600 then
|
||||
entity.set_command({type = defines.command.wander, distraction = defines.distraction.by_enemy})
|
||||
else
|
||||
entity.set_command(
|
||||
{
|
||||
type = defines.command.go_to_location,
|
||||
destination_entity = player.character,
|
||||
radius = 4,
|
||||
distraction = defines.distraction.by_damage
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_player_changed_position(event)
|
||||
local this = WPT.get()
|
||||
|
||||
if math_random(1, 100) ~= 1 then
|
||||
return
|
||||
end
|
||||
local player = game.players[event.player_index]
|
||||
if not this.biter_pets[player.index] then
|
||||
return
|
||||
end
|
||||
if not this.biter_pets[player.index].entity then
|
||||
this.biter_pets[player.index] = nil
|
||||
return
|
||||
end
|
||||
if not this.biter_pets[player.index].entity.valid then
|
||||
this.biter_pets[player.index] = nil
|
||||
return
|
||||
end
|
||||
if not player.character then
|
||||
return
|
||||
end
|
||||
if this.biter_pets[player.index].last_command + 600 > game.tick then
|
||||
return
|
||||
end
|
||||
this.biter_pets[player.index].last_command = game.tick
|
||||
command_unit(this.biter_pets[player.index].entity, player)
|
||||
end
|
||||
|
||||
local function on_player_dropped_item(event)
|
||||
local player = game.players[event.player_index]
|
||||
if event.entity.stack.name ~= 'raw-fish' then
|
||||
return
|
||||
end
|
||||
local unit = find_unit(player, event.entity)
|
||||
if not unit then
|
||||
return
|
||||
end
|
||||
if Public.biter_pets_tame_unit(player, unit, false) then
|
||||
event.entity.destroy()
|
||||
return
|
||||
end
|
||||
if unit.force.index == player.force.index then
|
||||
feed_pet(unit)
|
||||
end
|
||||
end
|
||||
|
||||
local event = require 'utils.event'
|
||||
event.add(defines.events.on_player_dropped_item, on_player_dropped_item)
|
||||
event.add(defines.events.on_player_changed_position, on_player_changed_position)
|
||||
|
||||
return Public
|
116
maps/mountain_fortress_v3/commands.lua
Normal file
116
maps/mountain_fortress_v3/commands.lua
Normal file
@ -0,0 +1,116 @@
|
||||
local Color = require 'utils.color_presets'
|
||||
local Task = require 'utils.task'
|
||||
local WPT = require 'maps.mountain_fortress_v3.table'
|
||||
|
||||
local mapkeeper = '[color=blue]Mapkeeper:[/color]'
|
||||
|
||||
commands.add_command(
|
||||
'reset_game',
|
||||
'Usable only for admins - resets the game!',
|
||||
function()
|
||||
local p
|
||||
local player = game.player
|
||||
local reset_map = require 'maps.mountain_fortress_v3.main'.reset_map
|
||||
local this = WPT.get()
|
||||
|
||||
if player then
|
||||
if player ~= nil then
|
||||
p = player.print
|
||||
if not player.admin then
|
||||
p("[ERROR] You're not admin!", Color.fail)
|
||||
return
|
||||
end
|
||||
else
|
||||
p = log
|
||||
end
|
||||
end
|
||||
if not this.reset_are_you_sure then
|
||||
this.reset_are_you_sure = true
|
||||
player.print(
|
||||
'[WARNING] This command will reset the current game, run this command again if you really want to do this!',
|
||||
Color.yellow
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
game.print(mapkeeper .. ' ' .. player.name .. ', has reset the game!', {r = 0.98, g = 0.66, b = 0.22})
|
||||
this.reset_are_you_sure = nil
|
||||
reset_map()
|
||||
end
|
||||
)
|
||||
|
||||
commands.add_command(
|
||||
'disable_reset_game',
|
||||
'Usable only for admins - disables the auto-reset of map!',
|
||||
function(cmd)
|
||||
local p
|
||||
local player = game.player
|
||||
local this = WPT.get()
|
||||
local param = tostring(cmd.parameter)
|
||||
|
||||
if player then
|
||||
if player ~= nil then
|
||||
p = player.print
|
||||
if not player.admin then
|
||||
p("[ERROR] You're not admin!", Color.fail)
|
||||
return
|
||||
end
|
||||
else
|
||||
p = log
|
||||
end
|
||||
end
|
||||
if not param then
|
||||
p('[ERROR] Arguments are true/false', Color.yellow)
|
||||
return
|
||||
end
|
||||
|
||||
if not this.reset_are_you_sure then
|
||||
this.reset_are_you_sure = true
|
||||
player.print(
|
||||
'[WARNING] This command will disable the auto-reset feature, run this command again if you really want to do this!',
|
||||
Color.yellow
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
if param == 'true' then
|
||||
if this.disable_reset then
|
||||
this.reset_are_you_sure = nil
|
||||
return p('[WARNING] Reset is already disabled!', Color.fail)
|
||||
end
|
||||
|
||||
this.disable_reset = true
|
||||
|
||||
p('[SUCCESS] Auto-reset is disabled!', Color.success)
|
||||
this.reset_are_you_sure = nil
|
||||
elseif param == 'false' then
|
||||
if not this.disable_reset then
|
||||
this.reset_are_you_sure = nil
|
||||
return p('[WARNING] Reset is already enabled!', Color.fail)
|
||||
end
|
||||
|
||||
this.disable_reset = false
|
||||
p('[SUCCESS] Auto-reset is enabled!', Color.success)
|
||||
this.reset_are_you_sure = nil
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
if _DEBUG then
|
||||
commands.add_command(
|
||||
'get_queue_speed',
|
||||
'Debug only, return the current task queue speed!',
|
||||
function()
|
||||
local player = game.player
|
||||
|
||||
if player then
|
||||
if player ~= nil then
|
||||
if not player.admin then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
game.print(Task.get_queue_speed())
|
||||
end
|
||||
)
|
||||
end
|
466
maps/mountain_fortress_v3/entities.lua
Normal file
466
maps/mountain_fortress_v3/entities.lua
Normal file
@ -0,0 +1,466 @@
|
||||
require 'on_tick_schedule'
|
||||
require 'modules.rocks_broken_paint_tiles'
|
||||
|
||||
local Event = require 'utils.event'
|
||||
local Map_score = require 'comfy_panel.map_score'
|
||||
local BiterRolls = require 'modules.wave_defense.biter_rolls'
|
||||
local Loot = require 'maps.mountain_fortress_v3.loot'
|
||||
local Pets = require 'maps.mountain_fortress_v3.biter_pets'
|
||||
local tick_tack_trap = require 'maps.mountain_fortress_v3.tick_tack_trap'
|
||||
local RPG = require 'maps.mountain_fortress_v3.rpg'
|
||||
local Mining = require 'maps.mountain_fortress_v3.mining'
|
||||
local Terrain = require 'maps.mountain_fortress_v3.terrain'
|
||||
local BiterHealthBooster = require 'modules.biter_health_booster'
|
||||
|
||||
-- tables
|
||||
local WPT = require 'maps.mountain_fortress_v3.table'
|
||||
local WD = require 'modules.wave_defense.table'
|
||||
|
||||
-- module
|
||||
local Public = {}
|
||||
|
||||
local math_random = math.random
|
||||
local math_floor = math.floor
|
||||
local math_abs = math.abs
|
||||
|
||||
local mapkeeper = '[color=blue]Mapkeeper:[/color]'
|
||||
|
||||
local treasure_chest_messages = {
|
||||
"You notice an old crate within the rubble. It's filled with treasure!",
|
||||
"You find a chest underneath the broken rocks. It's filled with goodies!",
|
||||
'We has found the precious!'
|
||||
}
|
||||
|
||||
local rare_treasure_chest_messages = {
|
||||
'Your magic improves. You have found a chest that is filled with rare treasures!',
|
||||
"Oh how wonderful. You found a chest underneath the broken rocks. It's filled with rare goodies!",
|
||||
"You're a wizard! We have found the rare precious!"
|
||||
}
|
||||
|
||||
local disabled_threats = {
|
||||
['entity-ghost'] = true,
|
||||
['raw-fish'] = true
|
||||
}
|
||||
|
||||
local defeated_messages = {
|
||||
"Oh no, the biters nom'ed the train away!",
|
||||
"I'm not 100% sure, but - apparently the train was chewed away.",
|
||||
'You had one objective - defend the train *-*',
|
||||
"Looks like we're resetting cause you did not defend the train ._."
|
||||
}
|
||||
|
||||
local entity_type = {
|
||||
['unit'] = true,
|
||||
['unit-spawner'] = true,
|
||||
['simple-entity'] = true,
|
||||
['tree'] = true
|
||||
}
|
||||
|
||||
local function set_objective_health(entity, final_damage_amount)
|
||||
local this = WPT.get()
|
||||
if final_damage_amount == 0 then
|
||||
return
|
||||
end
|
||||
this.locomotive_health = math_floor(this.locomotive_health - final_damage_amount)
|
||||
this.cargo_health = math_floor(this.cargo_health - final_damage_amount)
|
||||
if this.locomotive_health > this.locomotive_max_health then
|
||||
this.locomotive_health = this.locomotive_max_health
|
||||
end
|
||||
if this.cargo_health > this.cargo_max_health then
|
||||
this.cargo_health = this.cargo_max_health
|
||||
end
|
||||
if this.locomotive_health <= 0 then
|
||||
Public.loco_died()
|
||||
end
|
||||
local m
|
||||
if entity == this.locomotive then
|
||||
m = this.locomotive_health / this.locomotive_max_health
|
||||
entity.health = 1000 * m
|
||||
elseif entity == this.locomotive_cargo then
|
||||
m = this.cargo_health / this.cargo_max_health
|
||||
entity.health = 600 * m
|
||||
end
|
||||
rendering.set_text(this.health_text, 'HP: ' .. this.locomotive_health .. ' / ' .. this.locomotive_max_health)
|
||||
end
|
||||
|
||||
local function is_protected(entity)
|
||||
local this = WPT.get()
|
||||
local map_name = 'mountain_fortress_v3'
|
||||
|
||||
if string.sub(entity.surface.name, 0, #map_name) ~= map_name then
|
||||
return true
|
||||
end
|
||||
|
||||
local protected = {this.locomotive, this.locomotive_cargo}
|
||||
for i = 1, #protected do
|
||||
if protected[i] == entity then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function protect_train(event)
|
||||
local this = WPT.get()
|
||||
if event.entity.force.index ~= 1 then
|
||||
return
|
||||
end --Player Force
|
||||
if is_protected(event.entity) then
|
||||
if event.entity == this.locomotive_cargo or event.entity == this.locomotive then
|
||||
if event.cause then
|
||||
if event.cause.force.index == 2 then
|
||||
if this.locomotive_health <= 0 then
|
||||
goto continue
|
||||
end
|
||||
set_objective_health(event.entity, event.final_damage_amount)
|
||||
end
|
||||
end
|
||||
::continue::
|
||||
end
|
||||
if not event.entity.valid then
|
||||
return
|
||||
end
|
||||
event.entity.health = event.entity.health + event.final_damage_amount
|
||||
end
|
||||
end
|
||||
|
||||
local function hidden_biter(entity)
|
||||
local surface = entity.surface
|
||||
local h = math_floor(math_abs(entity.position.y))
|
||||
local m = 1 / Terrain.level_depth
|
||||
local count = math_floor(math_random(0, h + Terrain.level_depth) * m) + 1
|
||||
local position = surface.find_non_colliding_position('small-biter', entity.position, 16, 0.5)
|
||||
if not position then
|
||||
position = entity.position
|
||||
end
|
||||
|
||||
BiterRolls.wave_defense_set_unit_raffle(h * 0.20)
|
||||
|
||||
for _ = 1, count, 1 do
|
||||
local unit
|
||||
if math_random(1, 3) == 1 then
|
||||
unit = surface.create_entity({name = BiterRolls.wave_defense_roll_spitter_name(), position = position})
|
||||
else
|
||||
unit = surface.create_entity({name = BiterRolls.wave_defense_roll_biter_name(), position = position})
|
||||
end
|
||||
|
||||
if math_random(1, 64) == 1 then
|
||||
BiterHealthBooster.add_boss_unit(unit, m * h * 5 + 1, 0.38)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function hidden_worm(entity)
|
||||
BiterRolls.wave_defense_set_worm_raffle(math.sqrt(entity.position.x ^ 2 + entity.position.y ^ 2) * 0.20)
|
||||
entity.surface.create_entity({name = BiterRolls.wave_defense_roll_worm_name(), position = entity.position})
|
||||
end
|
||||
|
||||
local function hidden_biter_pet(event)
|
||||
if math_random(1, 2048) ~= 1 then
|
||||
return
|
||||
end
|
||||
BiterRolls.wave_defense_set_unit_raffle(math.sqrt(event.entity.position.x ^ 2 + event.entity.position.y ^ 2) * 0.25)
|
||||
local unit
|
||||
if math_random(1, 3) == 1 then
|
||||
unit =
|
||||
event.entity.surface.create_entity(
|
||||
{name = BiterRolls.wave_defense_roll_spitter_name(), position = event.entity.position}
|
||||
)
|
||||
else
|
||||
unit =
|
||||
event.entity.surface.create_entity(
|
||||
{name = BiterRolls.wave_defense_roll_biter_name(), position = event.entity.position}
|
||||
)
|
||||
end
|
||||
Pets.biter_pets_tame_unit(game.players[event.player_index], unit, true)
|
||||
end
|
||||
|
||||
local function hidden_treasure(event)
|
||||
local player = game.players[event.player_index]
|
||||
local rpg_t = RPG.get_table()
|
||||
local magic = rpg_t[player.index].magic
|
||||
if math.random(1, 320) ~= 1 then
|
||||
return
|
||||
end
|
||||
if magic > 50 then
|
||||
player.print(
|
||||
rare_treasure_chest_messages[math.random(1, #rare_treasure_chest_messages)],
|
||||
{r = 0.98, g = 0.66, b = 0.22}
|
||||
)
|
||||
Loot.add_rare(event.entity.surface, event.entity.position, 'wooden-chest', magic)
|
||||
return
|
||||
end
|
||||
player.print(treasure_chest_messages[math.random(1, #treasure_chest_messages)], {r = 0.98, g = 0.66, b = 0.22})
|
||||
Loot.add(event.entity.surface, event.entity.position, 'wooden-chest')
|
||||
end
|
||||
|
||||
local function biters_chew_rocks_faster(event)
|
||||
if event.entity.force.index ~= 3 then
|
||||
return
|
||||
end --Neutral Force
|
||||
if not event.cause then
|
||||
return
|
||||
end
|
||||
if not event.cause.valid then
|
||||
return
|
||||
end
|
||||
if event.cause.force.index ~= 2 then
|
||||
return
|
||||
end --Enemy Force
|
||||
|
||||
event.entity.health = event.entity.health - event.final_damage_amount * 2.5
|
||||
end
|
||||
|
||||
local projectiles = {'grenade', 'explosive-rocket', 'grenade', 'explosive-rocket', 'explosive-cannon-projectile'}
|
||||
local function angry_tree(entity, cause)
|
||||
if entity.type ~= 'tree' then
|
||||
return
|
||||
end
|
||||
if math.abs(entity.position.y) < Terrain.level_depth then
|
||||
return
|
||||
end
|
||||
if math_random(1, 4) == 1 then
|
||||
hidden_biter(entity)
|
||||
end
|
||||
if math_random(1, 8) == 1 then
|
||||
hidden_worm(entity)
|
||||
end
|
||||
if math_random(1, 16) ~= 1 then
|
||||
return
|
||||
end
|
||||
local position = false
|
||||
if cause then
|
||||
if cause.valid then
|
||||
position = cause.position
|
||||
end
|
||||
end
|
||||
if not position then
|
||||
position = {entity.position.x + (-20 + math_random(0, 40)), entity.position.y + (-20 + math_random(0, 40))}
|
||||
end
|
||||
|
||||
entity.surface.create_entity(
|
||||
{
|
||||
name = projectiles[math_random(1, 5)],
|
||||
position = entity.position,
|
||||
force = 'neutral',
|
||||
source = entity.position,
|
||||
target = position,
|
||||
max_range = 16,
|
||||
speed = 0.01
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
local function give_coin(player)
|
||||
player.insert({name = 'coin', count = 1})
|
||||
end
|
||||
|
||||
local function on_player_mined_entity(event)
|
||||
local this = WPT.get()
|
||||
local entity = event.entity
|
||||
local player = game.players[event.player_index]
|
||||
if not player.valid then
|
||||
return
|
||||
end
|
||||
if not entity.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local map_name = 'mountain_fortress_v3'
|
||||
|
||||
if string.sub(entity.surface.name, 0, #map_name) ~= map_name then
|
||||
return
|
||||
end
|
||||
|
||||
if disabled_threats[entity.name] then
|
||||
return
|
||||
end
|
||||
|
||||
if entity.type == 'simple-entity' or entity.type == 'tree' then
|
||||
this.mined_scrap = this.mined_scrap + 1
|
||||
Mining.on_player_mined_entity(event)
|
||||
give_coin(player)
|
||||
if math.random(1, 32) == 1 then
|
||||
hidden_biter(event.entity)
|
||||
entity.destroy()
|
||||
return
|
||||
end
|
||||
if math.random(1, 512) == 1 then
|
||||
hidden_worm(event.entity)
|
||||
entity.destroy()
|
||||
return
|
||||
end
|
||||
if math_random(1, 512) == 1 then
|
||||
tick_tack_trap(entity.surface, entity.position)
|
||||
return
|
||||
end
|
||||
hidden_biter_pet(event)
|
||||
hidden_treasure(event)
|
||||
angry_tree(event.entity, game.players[event.player_index].character)
|
||||
entity.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
local function on_entity_damaged(event)
|
||||
if not event.entity then
|
||||
return
|
||||
end
|
||||
if not event.entity.valid then
|
||||
return
|
||||
end
|
||||
if not event.entity.health then
|
||||
return
|
||||
end
|
||||
protect_train(event)
|
||||
biters_chew_rocks_faster(event)
|
||||
end
|
||||
|
||||
local function on_player_repaired_entity(event)
|
||||
local this = WPT.get()
|
||||
if not event.entity then
|
||||
return
|
||||
end
|
||||
if not event.entity.valid then
|
||||
return
|
||||
end
|
||||
if not event.entity.health then
|
||||
return
|
||||
end
|
||||
local entity = event.entity
|
||||
if entity == this.locomotive_cargo or entity == this.locomotive then
|
||||
set_objective_health(entity, -1)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_entity_died(event)
|
||||
local this = WPT.get()
|
||||
|
||||
local entity = event.entity
|
||||
if not entity.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local rng = math.random(1, 32) == 1
|
||||
|
||||
if event.cause then
|
||||
if event.cause.valid then
|
||||
if event.cause.force.index == 2 or event.cause.force.index == 3 then
|
||||
entity.destroy()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local map_name = 'mountain_fortress_v3'
|
||||
|
||||
if string.sub(entity.surface.name, 0, #map_name) ~= map_name then
|
||||
return
|
||||
end
|
||||
|
||||
if disabled_threats[entity.name] then
|
||||
return
|
||||
end
|
||||
|
||||
local data = {
|
||||
entity = entity,
|
||||
surface = entity.surface
|
||||
}
|
||||
|
||||
if entity_type[entity.type] then
|
||||
if entity.type == 'unit' or entity_type == 'unit-spawner' then
|
||||
this.biters_killed = this.biters_killed + 1
|
||||
end
|
||||
if math.random(1, 32) == 1 then
|
||||
hidden_biter(event.entity)
|
||||
return
|
||||
end
|
||||
if math_random(1, 512) == 1 then
|
||||
tick_tack_trap(entity.surface, entity.position)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if entity.type == 'tree' then
|
||||
angry_tree(event.entity, event.cause)
|
||||
return
|
||||
end
|
||||
|
||||
if entity.type == 'simple-entity' then
|
||||
if rng then
|
||||
hidden_biter(event.entity)
|
||||
end
|
||||
Mining.entity_died_randomness(data)
|
||||
entity.destroy()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function Public.set_scores()
|
||||
local this = WPT.get()
|
||||
local wagon = this.locomotive_cargo
|
||||
if not wagon then
|
||||
return
|
||||
end
|
||||
if not wagon.valid then
|
||||
return
|
||||
end
|
||||
local score = math_floor(wagon.position.y * -1)
|
||||
for _, player in pairs(game.connected_players) do
|
||||
if score > Map_score.get_score(player) then
|
||||
Map_score.set_score(player, score)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.loco_died()
|
||||
local this = WPT.get()
|
||||
local surface = game.surfaces[this.active_surface_index]
|
||||
local wave_defense_table = WD.get_table()
|
||||
Public.set_scores()
|
||||
if not this.locomotive.valid then
|
||||
wave_defense_table.game_lost = true
|
||||
wave_defense_table.target = nil
|
||||
game.print(mapkeeper .. ' ' .. defeated_messages[math.random(1, #defeated_messages)], {r = 1, g = 0.5, b = 0.1})
|
||||
game.print(mapkeeper .. ' Better luck next time.', {r = 1, g = 0.5, b = 0.1})
|
||||
Public.reset_map()
|
||||
return
|
||||
end
|
||||
this.locomotive_health = 0
|
||||
this.locomotive.color = {0.49, 0, 255, 1}
|
||||
rendering.set_text(this.health_text, 'HP: ' .. this.locomotive_health .. ' / ' .. this.locomotive_max_health)
|
||||
wave_defense_table.game_lost = true
|
||||
wave_defense_table.target = nil
|
||||
game.print(mapkeeper .. ' ' .. defeated_messages[math.random(1, #defeated_messages)], {r = 1, g = 0.5, b = 0.1})
|
||||
game.print(mapkeeper .. ' Better luck next time.', {r = 1, g = 0.5, b = 0.1})
|
||||
game.print(mapkeeper .. ' Game will soft-reset shortly.', {r = 1, g = 0.5, b = 0.1})
|
||||
game.forces.enemy.set_friend('player', true)
|
||||
game.forces.player.set_friend('enemy', true)
|
||||
|
||||
local fake_shooter =
|
||||
surface.create_entity({name = 'character', position = this.locomotive.position, force = 'enemy'})
|
||||
surface.create_entity(
|
||||
{
|
||||
name = 'atomic-rocket',
|
||||
position = this.locomotive.position,
|
||||
force = 'enemy',
|
||||
speed = 1,
|
||||
max_range = 1200,
|
||||
target = this.locomotive,
|
||||
source = fake_shooter
|
||||
}
|
||||
)
|
||||
|
||||
surface.spill_item_stack(this.locomotive.position, {name = 'coin', count = 512}, false)
|
||||
surface.spill_item_stack(this.locomotive_cargo.position, {name = 'coin', count = 512}, false)
|
||||
this.game_reset_tick = game.tick + 1000
|
||||
for _, player in pairs(game.connected_players) do
|
||||
player.play_sound {path = 'utility/game_lost', volume_modifier = 0.75}
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
|
||||
Event.add(defines.events.on_player_repaired_entity, on_player_repaired_entity)
|
||||
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)
|
||||
Event.add(defines.events.on_entity_died, on_entity_died)
|
||||
|
||||
return Public
|
20
maps/mountain_fortress_v3/flamethrower_nerf.lua
Normal file
20
maps/mountain_fortress_v3/flamethrower_nerf.lua
Normal file
@ -0,0 +1,20 @@
|
||||
--Flamethrower Turret Nerf
|
||||
local function on_research_finished(event)
|
||||
local research = event.research
|
||||
local force_name = research.force.name
|
||||
if research.name == "military" then
|
||||
if not global.flamethrower_damage then global.flamethrower_damage = {} end
|
||||
global.flamethrower_damage[force_name] = -0.65
|
||||
game.forces[force_name].set_turret_attack_modifier("flamethrower-turret", global.flamethrower_damage[force_name])
|
||||
game.forces[force_name].set_ammo_damage_modifier("flamethrower", global.flamethrower_damage[force_name])
|
||||
end
|
||||
|
||||
if string.sub(research.name, 0, 18) == "refined-flammables" then
|
||||
global.flamethrower_damage[force_name] = global.flamethrower_damage[force_name] + 0.10
|
||||
game.forces[force_name].set_turret_attack_modifier("flamethrower-turret", global.flamethrower_damage[force_name])
|
||||
game.forces[force_name].set_ammo_damage_modifier("flamethrower", global.flamethrower_damage[force_name])
|
||||
end
|
||||
end
|
||||
|
||||
local event = require 'utils.event'
|
||||
event.add(defines.events.on_research_finished, on_research_finished)
|
449
maps/mountain_fortress_v3/generate.lua
Normal file
449
maps/mountain_fortress_v3/generate.lua
Normal file
@ -0,0 +1,449 @@
|
||||
local Market = require 'functions.basic_markets'
|
||||
local Loot = require 'maps.mountain_fortress_v3.loot'
|
||||
local Task = require 'utils.task'
|
||||
local Token = require 'utils.token'
|
||||
local Event = require 'utils.event'
|
||||
local Terrain = require 'maps.mountain_fortress_v3.terrain'.heavy_functions
|
||||
|
||||
local insert = table.insert
|
||||
|
||||
local tiles_per_call = 16 --how many tiles are inserted with each call of insert_action
|
||||
local total_calls = math.ceil(1024 / tiles_per_call)
|
||||
local regen_decoratives = false
|
||||
local force_chunk = false
|
||||
|
||||
local Public = {}
|
||||
|
||||
-- Set to false by modules that want to control the on_chunk_generated event themselves.
|
||||
Public.enable_register_events = true
|
||||
|
||||
local function do_tile_inner(tiles, tile, pos)
|
||||
if type(tile) == 'string' then
|
||||
insert(tiles, {name = tile, position = pos})
|
||||
end
|
||||
end
|
||||
|
||||
local function do_tile(y, x, data, shape)
|
||||
local pos = {x, y}
|
||||
|
||||
-- local coords need to be 'centered' to allow for correct rotation and scaling.
|
||||
local tile = shape(x + 0.5, y + 0.5, data)
|
||||
|
||||
if not data.surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
if type(tile) == 'table' then
|
||||
do_tile_inner(data.tiles, tile.tile, pos)
|
||||
|
||||
local hidden_tile = tile.hidden_tile
|
||||
if hidden_tile then
|
||||
insert(data.hidden_tiles, {tile = hidden_tile, position = pos})
|
||||
end
|
||||
|
||||
local entities = tile.entities
|
||||
if entities then
|
||||
for _, entity in ipairs(entities) do
|
||||
if not entity.position then
|
||||
entity.position = pos
|
||||
end
|
||||
insert(data.entities, entity)
|
||||
end
|
||||
end
|
||||
|
||||
local decoratives = tile.decoratives
|
||||
if decoratives then
|
||||
for _, decorative in ipairs(decoratives) do
|
||||
insert(data.decoratives, decorative)
|
||||
end
|
||||
end
|
||||
|
||||
local markets = tile.markets
|
||||
if markets then
|
||||
for _, t in ipairs(markets) do
|
||||
if not t.position then
|
||||
t.position = pos
|
||||
end
|
||||
insert(data.markets, t)
|
||||
end
|
||||
end
|
||||
|
||||
local treasure = tile.treasure
|
||||
if treasure then
|
||||
for _, t in ipairs(treasure) do
|
||||
if not t.position then
|
||||
t.position = pos
|
||||
end
|
||||
insert(data.treasure, t)
|
||||
end
|
||||
end
|
||||
else
|
||||
do_tile_inner(data.tiles, tile, pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function do_row(row, data, shape)
|
||||
local y = data.top_y + row
|
||||
local top_x = data.top_x
|
||||
local tiles = data.tiles
|
||||
|
||||
if not data.surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
data.y = y
|
||||
|
||||
for x = top_x, top_x + 31 do
|
||||
data.x = x
|
||||
local pos = {data.x, data.y}
|
||||
|
||||
-- local coords need to be 'centered' to allow for correct rotation and scaling.
|
||||
local tile = shape(x + 0.5, y + 0.5, data)
|
||||
|
||||
if type(tile) == 'table' then
|
||||
do_tile_inner(tiles, tile.tile, pos)
|
||||
|
||||
local hidden_tile = tile.hidden_tile
|
||||
if hidden_tile then
|
||||
insert(data.hidden_tiles, {tile = hidden_tile, position = pos})
|
||||
end
|
||||
|
||||
local entities = tile.entities
|
||||
if entities then
|
||||
for _, entity in ipairs(entities) do
|
||||
if not entity.position then
|
||||
entity.position = pos
|
||||
end
|
||||
insert(data.entities, entity)
|
||||
end
|
||||
end
|
||||
|
||||
local decoratives = tile.decoratives
|
||||
if decoratives then
|
||||
for _, decorative in ipairs(decoratives) do
|
||||
if not decorative.position then
|
||||
decorative.position = pos
|
||||
end
|
||||
insert(data.decoratives, decorative)
|
||||
end
|
||||
end
|
||||
|
||||
local markets = tile.markets
|
||||
if markets then
|
||||
for _, t in ipairs(markets) do
|
||||
if not t.position then
|
||||
t.position = pos
|
||||
end
|
||||
insert(data.markets, t)
|
||||
end
|
||||
end
|
||||
|
||||
local treasure = tile.treasure
|
||||
if treasure then
|
||||
for _, t in ipairs(treasure) do
|
||||
if not t.position then
|
||||
t.position = pos
|
||||
end
|
||||
insert(data.treasure, t)
|
||||
end
|
||||
end
|
||||
else
|
||||
do_tile_inner(tiles, tile, pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function do_place_treasure(data)
|
||||
if not data.surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local surface = data.surface
|
||||
local treasure = data.treasure
|
||||
local rnd = math.random
|
||||
|
||||
if #treasure == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
for _, e in ipairs(data.treasure) do
|
||||
if rnd(1, 6) == 1 then
|
||||
e.chest = 'iron-chest'
|
||||
end
|
||||
Loot.add(surface, e.position, e.chest)
|
||||
end
|
||||
end
|
||||
|
||||
local function do_place_markets(data)
|
||||
if not data.surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local markets = data.markets
|
||||
local surface = data.surface
|
||||
local rnd = math.random
|
||||
local abs = math.abs
|
||||
|
||||
if #markets == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local pos = markets[rnd(1, #markets)]
|
||||
if
|
||||
surface.count_entities_filtered {
|
||||
area = {{pos.x - 96, pos.y - 96}, {pos.x + 96, pos.y + 96}},
|
||||
name = 'market',
|
||||
limit = 1
|
||||
} == 0
|
||||
then
|
||||
local market = Market.mountain_market(surface, pos, abs(pos.y) * 0.004)
|
||||
market.destructible = false
|
||||
end
|
||||
end
|
||||
|
||||
local function do_place_tiles(data)
|
||||
if not data.surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
data.surface.set_tiles(data.tiles, true)
|
||||
end
|
||||
|
||||
local function do_place_hidden_tiles(data)
|
||||
if not data.surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local surface = data.surface
|
||||
for _, t in ipairs(data.hidden_tiles) do
|
||||
surface.set_hidden_tile(t.position, t.tile)
|
||||
end
|
||||
end
|
||||
|
||||
local function do_place_decoratives(data)
|
||||
if not data.surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
if regen_decoratives then
|
||||
data.surface.regenerate_decorative(nil, {{data.top_x / 32, data.top_y / 32}})
|
||||
end
|
||||
|
||||
local dec = data.decoratives
|
||||
if #dec > 0 then
|
||||
data.surface.create_decoratives({check_collision = true, decoratives = dec})
|
||||
end
|
||||
end
|
||||
|
||||
local function do_place_entities(data)
|
||||
if not data.surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local surface = data.surface
|
||||
local entity
|
||||
|
||||
for _, e in ipairs(data.entities) do
|
||||
if e.force then
|
||||
entity = surface.create_entity({name = e.name, position = e.position, force = e.force})
|
||||
else
|
||||
entity = surface.create_entity(e)
|
||||
end
|
||||
if entity and e.callback then
|
||||
local callback = Token.get(e.callback)
|
||||
callback(entity, e.data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function run_chart_update(data)
|
||||
if not data.surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local x = data.top_x / 32
|
||||
local y = data.top_y / 32
|
||||
if game.forces.player.is_chunk_charted(data.surface, {x, y}) then
|
||||
-- Don't use full area, otherwise adjacent chunks get charted
|
||||
game.forces.player.chart(
|
||||
data.surface,
|
||||
{
|
||||
{data.top_x, data.top_y},
|
||||
{data.top_x + 1, data.top_y + 1}
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
local function map_gen_action(data)
|
||||
local state = data.y
|
||||
|
||||
if state < 32 then
|
||||
if not data.surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local shape = Terrain
|
||||
if shape == nil then
|
||||
return false
|
||||
end
|
||||
|
||||
local count = total_calls
|
||||
|
||||
local y = state + data.top_y
|
||||
local x = data.x
|
||||
|
||||
local max_x = data.top_x + 32
|
||||
|
||||
data.y = y
|
||||
|
||||
repeat
|
||||
count = count - 1
|
||||
do_tile(y, x, data, shape)
|
||||
|
||||
x = x + 1
|
||||
if x == max_x then
|
||||
y = y + 1
|
||||
if y == data.top_y + 32 then
|
||||
break
|
||||
end
|
||||
x = data.top_x
|
||||
data.y = y
|
||||
end
|
||||
|
||||
data.x = x
|
||||
until count == 0
|
||||
|
||||
data.y = y - data.top_y
|
||||
return true
|
||||
elseif state == 32 then
|
||||
do_place_tiles(data)
|
||||
data.y = 33
|
||||
return true
|
||||
elseif state == 33 then
|
||||
do_place_hidden_tiles(data)
|
||||
data.y = 34
|
||||
return true
|
||||
elseif state == 34 then
|
||||
do_place_entities(data)
|
||||
data.y = 35
|
||||
return true
|
||||
elseif state == 35 then
|
||||
do_place_markets(data)
|
||||
data.y = 36
|
||||
return true
|
||||
elseif state == 36 then
|
||||
do_place_treasure(data)
|
||||
data.y = 37
|
||||
return true
|
||||
elseif state == 37 then
|
||||
do_place_decoratives(data)
|
||||
data.y = 38
|
||||
return true
|
||||
elseif state == 38 then
|
||||
run_chart_update(data)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local map_gen_action_token = Token.register(map_gen_action)
|
||||
|
||||
--- Adds generation of a Chunk of the map to the queue
|
||||
-- @param event <table> the event table from on_chunk_generated
|
||||
function Public.schedule_chunk(event)
|
||||
local surface = event.surface
|
||||
local shape = Terrain
|
||||
|
||||
if not surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
if not shape then
|
||||
return
|
||||
end
|
||||
|
||||
local area = event.area
|
||||
|
||||
local data = {
|
||||
y = 0,
|
||||
x = area.left_top.x,
|
||||
area = area,
|
||||
top_x = area.left_top.x,
|
||||
top_y = area.left_top.y,
|
||||
surface = surface,
|
||||
tiles = {},
|
||||
hidden_tiles = {},
|
||||
entities = {},
|
||||
decoratives = {},
|
||||
markets = {},
|
||||
treasure = {}
|
||||
}
|
||||
|
||||
if not data.surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
Task.queue_task(map_gen_action_token, data, total_calls)
|
||||
end
|
||||
|
||||
--- Generates a Chunk of map when called
|
||||
-- @param event <table> the event table from on_chunk_generated
|
||||
function Public.do_chunk(event)
|
||||
local surface = event.surface
|
||||
local shape = Terrain
|
||||
|
||||
if not surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
if not shape then
|
||||
return
|
||||
end
|
||||
|
||||
local area = event.area
|
||||
|
||||
local data = {
|
||||
area = area,
|
||||
top_x = area.left_top.x,
|
||||
top_y = area.left_top.y,
|
||||
surface = surface,
|
||||
tiles = {},
|
||||
hidden_tiles = {},
|
||||
entities = {},
|
||||
decoratives = {},
|
||||
markets = {},
|
||||
treasure = {}
|
||||
}
|
||||
|
||||
if not data.surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
for row = 0, 31 do
|
||||
do_row(row, data, shape)
|
||||
end
|
||||
|
||||
do_place_tiles(data)
|
||||
do_place_hidden_tiles(data)
|
||||
do_place_entities(data)
|
||||
do_place_decoratives(data)
|
||||
do_place_markets(data)
|
||||
do_place_treasure(data)
|
||||
end
|
||||
|
||||
local do_chunk = Public.do_chunk
|
||||
local schedule_chunk = Public.schedule_chunk
|
||||
|
||||
local function on_chunk(event)
|
||||
if force_chunk then
|
||||
do_chunk(event)
|
||||
elseif event.tick == 0 then
|
||||
--do_chunk(event)
|
||||
else
|
||||
schedule_chunk(event)
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_chunk_generated, on_chunk)
|
||||
|
||||
return Public
|
83
maps/mountain_fortress_v3/gui.lua
Normal file
83
maps/mountain_fortress_v3/gui.lua
Normal file
@ -0,0 +1,83 @@
|
||||
local RPG = require 'maps.mountain_fortress_v3.rpg'
|
||||
local WPT = require 'maps.mountain_fortress_v3.table'
|
||||
local floor = math.floor
|
||||
local format_number = require 'util'.format_number
|
||||
|
||||
local function create_gui(player)
|
||||
local label
|
||||
local line
|
||||
|
||||
local frame = player.gui.top.add({type = 'frame', name = 'mountain_fortress_v3'})
|
||||
frame.style.minimal_height = 38
|
||||
frame.style.maximal_height = 38
|
||||
|
||||
label = frame.add({type = 'label', caption = ' ', name = 'label'})
|
||||
label.style.font_color = {r = 0.88, g = 0.88, b = 0.88}
|
||||
label.style.font = 'default-bold'
|
||||
label.style.font_color = {r = 0.33, g = 0.66, b = 0.9}
|
||||
|
||||
label = frame.add({type = 'label', caption = ' ', name = 'global_pool'})
|
||||
label.style.font_color = {r = 0.88, g = 0.88, b = 0.88}
|
||||
label.style.font = 'default-bold'
|
||||
label.style.right_padding = 4
|
||||
label.style.font_color = {r = 0.33, g = 0.66, b = 0.9}
|
||||
|
||||
line = frame.add({type = 'line', direction = 'vertical'})
|
||||
line.style.left_padding = 4
|
||||
line.style.right_padding = 4
|
||||
|
||||
label = frame.add({type = 'label', caption = ' ', name = 'scrap_mined'})
|
||||
label.style.font_color = {r = 0.88, g = 0.88, b = 0.88}
|
||||
label.style.font = 'default-bold'
|
||||
label.style.right_padding = 4
|
||||
label.style.font_color = {r = 0.33, g = 0.66, b = 0.9}
|
||||
|
||||
line = frame.add({type = 'line', direction = 'vertical'})
|
||||
line.style.left_padding = 4
|
||||
line.style.right_padding = 4
|
||||
|
||||
label = frame.add({type = 'label', caption = ' ', name = 'biters_killed'})
|
||||
label.style.font_color = {r = 0.88, g = 0.88, b = 0.88}
|
||||
label.style.font = 'default-bold'
|
||||
label.style.right_padding = 4
|
||||
label.style.font_color = {r = 0.33, g = 0.66, b = 0.9}
|
||||
|
||||
line = frame.add({type = 'line', direction = 'vertical'})
|
||||
line.style.left_padding = 4
|
||||
line.style.right_padding = 4
|
||||
|
||||
label = frame.add({type = 'label', caption = ' ', name = 'train_upgrades'})
|
||||
label.style.font_color = {r = 0.88, g = 0.88, b = 0.88}
|
||||
label.style.font = 'default-bold'
|
||||
label.style.right_padding = 4
|
||||
label.style.font_color = {r = 0.33, g = 0.66, b = 0.9}
|
||||
end
|
||||
|
||||
local function update_gui(player)
|
||||
local rpg = RPG.get_table()
|
||||
local st = WPT.get()
|
||||
|
||||
if not player.gui.top.mountain_fortress_v3 then
|
||||
create_gui(player)
|
||||
end
|
||||
local gui = player.gui.top.mountain_fortress_v3
|
||||
|
||||
if rpg.global_pool == 0 then
|
||||
gui.global_pool.caption = 'XP: 0'
|
||||
gui.global_pool.tooltip = 'Dig, handcraft or run to increase the pool!'
|
||||
elseif rpg.global_pool > 0 then
|
||||
gui.global_pool.caption = 'XP: ' .. format_number(floor(rpg.global_pool), true)
|
||||
gui.global_pool.tooltip = 'Get this number over 5k to get some of this mad XP! \\o/'
|
||||
end
|
||||
|
||||
gui.scrap_mined.caption = ' [img=entity.tree-01][img=entity.rock-huge]: ' .. format_number(st.mined_scrap, true)
|
||||
gui.scrap_mined.tooltip = 'Amount of trees/rocks harvested.'
|
||||
|
||||
gui.biters_killed.caption = ' [img=entity.small-biter]: ' .. format_number(st.biters_killed, true)
|
||||
gui.biters_killed.tooltip = 'Amount of biters killed.'
|
||||
|
||||
gui.train_upgrades.caption = ' [img=entity.locomotive]: ' .. format_number(st.train_upgrades, true)
|
||||
gui.train_upgrades.tooltip = 'Amount of train upgrades.'
|
||||
end
|
||||
|
||||
return update_gui
|
17
maps/mountain_fortress_v3/icw/constants.lua
Normal file
17
maps/mountain_fortress_v3/icw/constants.lua
Normal file
@ -0,0 +1,17 @@
|
||||
local Public = {}
|
||||
|
||||
Public.wagon_types = {
|
||||
["cargo-wagon"] = true,
|
||||
["artillery-wagon"] = true,
|
||||
["fluid-wagon"] = true,
|
||||
["locomotive"] = true,
|
||||
}
|
||||
|
||||
Public.wagon_areas = {
|
||||
["cargo-wagon"] = {left_top = {x = -20, y = 0}, right_bottom = {x = 20, y = 60}},
|
||||
["artillery-wagon"] = {left_top = {x = -20, y = 0}, right_bottom = {x = 20, y = 60}},
|
||||
["fluid-wagon"] = {left_top = {x = -20, y = 0}, right_bottom = {x = 20, y = 60}},
|
||||
["locomotive"] = {left_top = {x = -20, y = 0}, right_bottom = {x = 20, y = 60}},
|
||||
}
|
||||
|
||||
return Public
|
758
maps/mountain_fortress_v3/icw/functions.lua
Normal file
758
maps/mountain_fortress_v3/icw/functions.lua
Normal file
@ -0,0 +1,758 @@
|
||||
local Public = {}
|
||||
|
||||
local Constants = require 'maps.mountain_fortress_v3.icw.constants'
|
||||
|
||||
local table_insert = table.insert
|
||||
local table_remove = table.remove
|
||||
local math_round = math.round
|
||||
local math_random = math.random
|
||||
|
||||
function Public.request_reconstruction(icw)
|
||||
icw.rebuild_tick = game.tick + 30
|
||||
end
|
||||
|
||||
local function delete_empty_surfaces(icw)
|
||||
for k, surface in pairs(icw.surfaces) do
|
||||
if not icw.trains[tonumber(surface.name)] then
|
||||
game.delete_surface(surface)
|
||||
table_remove(icw.surfaces, k)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function kick_players_out_of_vehicles(wagon)
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local character = player.character
|
||||
if character and character.valid and character.driving then
|
||||
if wagon.surface == player.surface then
|
||||
character.driving = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function connect_power_pole(entity, wagon_area_left_top_y)
|
||||
local surface = entity.surface
|
||||
local max_wire_distance = entity.prototype.max_wire_distance
|
||||
local area = {
|
||||
{entity.position.x - max_wire_distance, entity.position.y - max_wire_distance},
|
||||
{entity.position.x + max_wire_distance, entity.position.y - 1}
|
||||
}
|
||||
for _, pole in pairs(surface.find_entities_filtered({area = area, name = entity.name})) do
|
||||
if pole.position.y < wagon_area_left_top_y then
|
||||
entity.connect_neighbour(pole)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function equal_fluid(source_tank, target_tank)
|
||||
if not source_tank.valid then
|
||||
return
|
||||
end
|
||||
if not target_tank.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local source_fluid = source_tank.fluidbox[1]
|
||||
if not source_fluid then
|
||||
return
|
||||
end
|
||||
|
||||
local target_fluid = target_tank.fluidbox[1]
|
||||
local source_fluid_amount = source_fluid.amount
|
||||
|
||||
local amount
|
||||
if target_fluid then
|
||||
amount = source_fluid_amount - ((target_fluid.amount + source_fluid_amount) * 0.5)
|
||||
else
|
||||
amount = source_fluid.amount * 0.5
|
||||
end
|
||||
|
||||
if amount <= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
local inserted_amount =
|
||||
target_tank.insert_fluid({name = source_fluid.name, amount = amount, temperature = source_fluid.temperature})
|
||||
if inserted_amount > 0 then
|
||||
source_tank.remove_fluid({name = source_fluid.name, amount = inserted_amount})
|
||||
end
|
||||
end
|
||||
|
||||
local function divide_fluid(wagon, storage_tank)
|
||||
local fluid_wagon = wagon.entity
|
||||
equal_fluid(fluid_wagon, storage_tank)
|
||||
equal_fluid(storage_tank, fluid_wagon)
|
||||
end
|
||||
|
||||
local function input_filtered(wagon_inventory, chest, chest_inventory, free_slots)
|
||||
local request_stacks = {}
|
||||
local prototypes = game.item_prototypes
|
||||
for slot_index = 1, 4, 1 do
|
||||
local stack = chest.get_request_slot(slot_index)
|
||||
if stack then
|
||||
request_stacks[stack.name] = 10 * prototypes[stack.name].stack_size
|
||||
end
|
||||
end
|
||||
for i = 1, wagon_inventory.get_bar() - 1, 1 do
|
||||
if free_slots <= 0 then
|
||||
return
|
||||
end
|
||||
local stack = wagon_inventory[i]
|
||||
if stack.valid_for_read then
|
||||
local request_stack = request_stacks[stack.name]
|
||||
if request_stack and request_stack > chest_inventory.get_item_count(stack.name) then
|
||||
chest_inventory.insert(stack)
|
||||
stack.clear()
|
||||
free_slots = free_slots - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function input_cargo(wagon, chest)
|
||||
if not chest.request_from_buffers then
|
||||
return
|
||||
end
|
||||
|
||||
local wagon_entity = wagon.entity
|
||||
if not wagon_entity.valid then
|
||||
wagon.transfer_entities = nil
|
||||
return
|
||||
end
|
||||
|
||||
local wagon_inventory = wagon_entity.get_inventory(defines.inventory.cargo_wagon)
|
||||
if wagon_inventory.is_empty() then
|
||||
return
|
||||
end
|
||||
|
||||
local chest_inventory = chest.get_inventory(defines.inventory.chest)
|
||||
local free_slots = 0
|
||||
for i = 1, chest_inventory.get_bar() - 1, 1 do
|
||||
if not chest_inventory[i].valid_for_read then
|
||||
free_slots = free_slots + 1
|
||||
end
|
||||
end
|
||||
|
||||
if chest.get_request_slot(1) then
|
||||
input_filtered(wagon_inventory, chest, chest_inventory, free_slots)
|
||||
return
|
||||
end
|
||||
|
||||
for i = 1, wagon_inventory.get_bar() - 1, 1 do
|
||||
if free_slots <= 0 then
|
||||
return
|
||||
end
|
||||
if wagon_inventory[i].valid_for_read then
|
||||
chest_inventory.insert(wagon_inventory[i])
|
||||
wagon_inventory[i].clear()
|
||||
free_slots = free_slots - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function output_cargo(wagon, passive_chest)
|
||||
local passive_chest_inventory = passive_chest.get_inventory(defines.inventory.cargo_wagon)
|
||||
if passive_chest_inventory.is_empty() then
|
||||
return
|
||||
end
|
||||
local wagon_inventory = wagon.entity.get_inventory(defines.inventory.cargo_wagon)
|
||||
local free_slots = 0
|
||||
for i = 1, wagon_inventory.get_bar() - 1, 1 do
|
||||
if not wagon_inventory[i].valid_for_read and not wagon_inventory.get_filter(i) then
|
||||
free_slots = free_slots + 1
|
||||
end
|
||||
end
|
||||
for i = 1, passive_chest_inventory.get_bar() - 1, 1 do
|
||||
if free_slots <= 0 then
|
||||
return
|
||||
end
|
||||
if passive_chest_inventory[i].valid_for_read then
|
||||
wagon_inventory.insert(passive_chest_inventory[i])
|
||||
passive_chest_inventory[i].clear()
|
||||
free_slots = free_slots - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local transfer_functions = {
|
||||
['storage-tank'] = divide_fluid,
|
||||
['logistic-chest-requester'] = input_cargo,
|
||||
['logistic-chest-passive-provider'] = output_cargo
|
||||
}
|
||||
|
||||
local function get_wagon_for_entity(icw, entity)
|
||||
local train = icw.trains[tonumber(entity.surface.name)]
|
||||
if not train then
|
||||
return
|
||||
end
|
||||
local position = entity.position
|
||||
for k, unit_number in pairs(train.wagons) do
|
||||
local wagon = icw.wagons[unit_number]
|
||||
if wagon then
|
||||
local left_top = wagon.area.left_top
|
||||
local right_bottom = wagon.area.right_bottom
|
||||
if
|
||||
position.x >= left_top.x and position.y >= left_top.y and position.x <= right_bottom.x and
|
||||
position.y <= right_bottom.y
|
||||
then
|
||||
return wagon
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function kill_wagon_doors(icw, wagon)
|
||||
for k, e in pairs(wagon.doors) do
|
||||
icw.doors[e.unit_number] = nil
|
||||
e.destroy()
|
||||
wagon.doors[k] = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function construct_wagon_doors(icw, wagon)
|
||||
local area = wagon.area
|
||||
local surface = wagon.surface
|
||||
|
||||
for _, x in pairs({area.left_top.x - 0.55, area.right_bottom.x + 0.55}) do
|
||||
local e =
|
||||
surface.create_entity(
|
||||
{
|
||||
name = 'car',
|
||||
position = {x, area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5)},
|
||||
force = 'neutral',
|
||||
create_build_effect_smoke = false
|
||||
}
|
||||
)
|
||||
e.get_inventory(defines.inventory.fuel).insert({name = 'wood', count = 1})
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
e.operable = false
|
||||
icw.doors[e.unit_number] = wagon.entity.unit_number
|
||||
table_insert(wagon.doors, e)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_player_data(icw, player)
|
||||
local player_data = icw.players[player.index]
|
||||
if icw.players[player.index] then
|
||||
return player_data
|
||||
end
|
||||
|
||||
icw.players[player.index] = {
|
||||
surface = 1,
|
||||
fallback_surface = 1,
|
||||
zoom = 0.30,
|
||||
map_size = 360
|
||||
}
|
||||
return icw.players[player.index]
|
||||
end
|
||||
|
||||
function Public.kill_minimap(player)
|
||||
local element = player.gui.left.icw_map
|
||||
if element then
|
||||
element.destroy()
|
||||
end
|
||||
end
|
||||
|
||||
function Public.kill_wagon(icw, entity)
|
||||
if not Constants.wagon_types[entity.type] then
|
||||
return
|
||||
end
|
||||
local wagon = icw.wagons[entity.unit_number]
|
||||
local surface = wagon.surface
|
||||
kick_players_out_of_vehicles(wagon)
|
||||
kill_wagon_doors(icw, wagon)
|
||||
for _, e in pairs(surface.find_entities_filtered({area = wagon.area})) do
|
||||
if e.name == 'character' and e.player then
|
||||
local p = wagon.entity.surface.find_non_colliding_position('character', wagon.entity.position, 128, 0.5)
|
||||
if p then
|
||||
e.player.teleport(p, wagon.entity.surface)
|
||||
else
|
||||
e.player.teleport(wagon.entity.position, wagon.entity.surface)
|
||||
end
|
||||
Public.kill_minimap(e.player)
|
||||
else
|
||||
e.die()
|
||||
end
|
||||
end
|
||||
for _, tile in pairs(surface.find_tiles_filtered({area = wagon.area})) do
|
||||
surface.set_tiles({{name = 'out-of-map', position = tile.position}}, true)
|
||||
end
|
||||
wagon.entity.force.chart(surface, wagon.area)
|
||||
icw.wagons[entity.unit_number] = nil
|
||||
Public.request_reconstruction(icw)
|
||||
end
|
||||
|
||||
function Public.create_room_surface(icw, unit_number)
|
||||
if game.surfaces[tostring(unit_number)] then
|
||||
return game.surfaces[tostring(unit_number)]
|
||||
end
|
||||
local map_gen_settings = {
|
||||
['width'] = 2,
|
||||
['height'] = 2,
|
||||
['water'] = 0,
|
||||
['starting_area'] = 1,
|
||||
['cliff_settings'] = {cliff_elevation_interval = 0, cliff_elevation_0 = 0},
|
||||
['default_enable_all_autoplace_controls'] = true,
|
||||
['autoplace_settings'] = {
|
||||
['entity'] = {treat_missing_as_default = false},
|
||||
['tile'] = {treat_missing_as_default = true},
|
||||
['decorative'] = {treat_missing_as_default = false}
|
||||
}
|
||||
}
|
||||
local surface = game.create_surface(unit_number, map_gen_settings)
|
||||
surface.freeze_daytime = true
|
||||
surface.daytime = 0.1
|
||||
surface.request_to_generate_chunks({16, 16}, 2)
|
||||
surface.force_generate_chunk_requests()
|
||||
for _, tile in pairs(surface.find_tiles_filtered({area = {{-2, -2}, {2, 2}}})) do
|
||||
surface.set_tiles({{name = 'out-of-map', position = tile.position}}, true)
|
||||
end
|
||||
table_insert(icw.surfaces, surface)
|
||||
return surface
|
||||
end
|
||||
|
||||
function Public.create_wagon_room(icw, wagon)
|
||||
local surface = wagon.surface
|
||||
local area = wagon.area
|
||||
|
||||
local main_tile_name = 'tutorial-grid'
|
||||
if wagon.entity.type == 'locomotive' then
|
||||
main_tile_name = 'black-refined-concrete'
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
for x = -3, 2, 1 do
|
||||
table_insert(tiles, {name = 'hazard-concrete-right', position = {x, area.left_top.y}})
|
||||
table_insert(tiles, {name = 'hazard-concrete-right', position = {x, area.right_bottom.y - 1}})
|
||||
end
|
||||
for x = area.left_top.x, area.right_bottom.x - 1, 1 do
|
||||
for y = area.left_top.y + 2, area.right_bottom.y - 3, 1 do
|
||||
table_insert(tiles, {name = main_tile_name, position = {x, y}})
|
||||
end
|
||||
end
|
||||
for x = -3, 2, 1 do
|
||||
for y = 1, 3, 1 do
|
||||
table_insert(tiles, {name = main_tile_name, position = {x, y}})
|
||||
end
|
||||
for y = area.right_bottom.y - 4, area.right_bottom.y - 2, 1 do
|
||||
table_insert(tiles, {name = main_tile_name, position = {x, y}})
|
||||
end
|
||||
end
|
||||
|
||||
local fishes = {}
|
||||
|
||||
if wagon.entity.type == 'locomotive' then
|
||||
for x = -3, 2, 1 do
|
||||
for y = 10, 12, 1 do
|
||||
table_insert(tiles, {name = 'water', position = {x, y}})
|
||||
table_insert(fishes, {name = 'fish', position = {x, y}})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
surface.set_tiles(tiles, true)
|
||||
|
||||
for _, fish in pairs(fishes) do
|
||||
surface.create_entity(fish)
|
||||
end
|
||||
|
||||
construct_wagon_doors(icw, wagon)
|
||||
|
||||
if wagon.entity.type == 'fluid-wagon' then
|
||||
local height = area.right_bottom.y - area.left_top.y
|
||||
local positions = {
|
||||
{area.right_bottom.x, area.left_top.y + height * 0.25},
|
||||
{area.right_bottom.x, area.left_top.y + height * 0.75},
|
||||
{area.left_top.x - 1, area.left_top.y + height * 0.25},
|
||||
{area.left_top.x - 1, area.left_top.y + height * 0.75}
|
||||
}
|
||||
table.shuffle_table(positions)
|
||||
local e =
|
||||
surface.create_entity(
|
||||
{
|
||||
name = 'storage-tank',
|
||||
position = positions[1],
|
||||
force = 'neutral',
|
||||
create_build_effect_smoke = false
|
||||
}
|
||||
)
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
wagon.transfer_entities = {e}
|
||||
return
|
||||
end
|
||||
|
||||
if wagon.entity.type == 'cargo-wagon' then
|
||||
local vectors = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}}
|
||||
local v = vectors[math_random(1, 4)]
|
||||
local position = {
|
||||
math_random(area.left_top.x + 4, area.right_bottom.x - 4),
|
||||
math_random(area.left_top.y + 6, area.right_bottom.y - 6)
|
||||
}
|
||||
|
||||
local e =
|
||||
surface.create_entity(
|
||||
{
|
||||
name = 'logistic-chest-requester',
|
||||
position = position,
|
||||
force = 'neutral',
|
||||
create_build_effect_smoke = false
|
||||
}
|
||||
)
|
||||
e.destructible = false
|
||||
e.minable = false
|
||||
|
||||
local e2 =
|
||||
surface.create_entity(
|
||||
{
|
||||
name = 'logistic-chest-passive-provider',
|
||||
position = {position[1] + v[1], position[2] + v[2]},
|
||||
force = 'neutral',
|
||||
create_build_effect_smoke = false
|
||||
}
|
||||
)
|
||||
e2.destructible = false
|
||||
e2.minable = false
|
||||
|
||||
wagon.transfer_entities = {e, e2}
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function Public.create_wagon(icw, created_entity, delay_surface)
|
||||
if not created_entity.unit_number then
|
||||
return
|
||||
end
|
||||
if icw.trains[tonumber(created_entity.surface.name)] or icw.wagons[tonumber(created_entity.surface.name)] then
|
||||
return
|
||||
end
|
||||
if not Constants.wagon_types[created_entity.type] then
|
||||
return
|
||||
end
|
||||
local wagon_area = Constants.wagon_areas[created_entity.type]
|
||||
|
||||
icw.wagons[created_entity.unit_number] = {
|
||||
entity = created_entity,
|
||||
area = {
|
||||
left_top = {x = wagon_area.left_top.x, y = wagon_area.left_top.y},
|
||||
right_bottom = {x = wagon_area.right_bottom.x, y = wagon_area.right_bottom.y}
|
||||
},
|
||||
doors = {},
|
||||
entity_count = 0
|
||||
}
|
||||
local wagon = icw.wagons[created_entity.unit_number]
|
||||
|
||||
if not delay_surface then
|
||||
wagon.surface = Public.create_room_surface(icw, created_entity.unit_number)
|
||||
Public.create_wagon_room(icw, icw.wagons[created_entity.unit_number])
|
||||
end
|
||||
|
||||
Public.request_reconstruction(icw)
|
||||
return wagon
|
||||
end
|
||||
|
||||
function Public.add_wagon_entity_count(icw, added_entity)
|
||||
local wagon = get_wagon_for_entity(icw, added_entity)
|
||||
if not wagon then
|
||||
return
|
||||
end
|
||||
wagon.entity_count = wagon.entity_count + 1
|
||||
wagon.entity.minable = false
|
||||
end
|
||||
|
||||
function Public.subtract_wagon_entity_count(icw, removed_entity)
|
||||
local wagon = get_wagon_for_entity(icw, removed_entity)
|
||||
if not wagon then
|
||||
return
|
||||
end
|
||||
wagon.entity_count = wagon.entity_count - 1
|
||||
if wagon.entity_count > 0 then
|
||||
return
|
||||
end
|
||||
wagon.entity.minable = true
|
||||
end
|
||||
|
||||
function Public.use_cargo_wagon_door(icw, player, door)
|
||||
local player_data = get_player_data(icw, player)
|
||||
if player_data.state then
|
||||
player_data.state = player_data.state - 1
|
||||
if player_data.state == 0 then
|
||||
player_data.state = nil
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if not door then
|
||||
return
|
||||
end
|
||||
if not door.valid then
|
||||
return
|
||||
end
|
||||
local doors = icw.doors
|
||||
local wagons = icw.wagons
|
||||
|
||||
local wagon = false
|
||||
if doors[door.unit_number] then
|
||||
wagon = wagons[doors[door.unit_number]]
|
||||
end
|
||||
if wagons[door.unit_number] then
|
||||
wagon = wagons[door.unit_number]
|
||||
end
|
||||
if not wagon then
|
||||
return
|
||||
end
|
||||
|
||||
player_data.fallback_surface = wagon.entity.surface.index
|
||||
player_data.fallback_position = {wagon.entity.position.x, wagon.entity.position.y}
|
||||
|
||||
if wagon.entity.surface.name ~= player.surface.name then
|
||||
local surface = wagon.entity.surface
|
||||
local x_vector = (door.position.x / math.abs(door.position.x)) * 2
|
||||
local position = {wagon.entity.position.x + x_vector, wagon.entity.position.y}
|
||||
local position = surface.find_non_colliding_position('character', position, 128, 0.5)
|
||||
if not position then
|
||||
return
|
||||
end
|
||||
if wagon.entity.type == 'locomotive' then
|
||||
player.teleport(position, surface)
|
||||
player_data.state = 2
|
||||
player.driving = true
|
||||
Public.kill_minimap(player)
|
||||
else
|
||||
player.teleport(position, surface)
|
||||
Public.kill_minimap(player)
|
||||
end
|
||||
player_data.surface = surface.index
|
||||
else
|
||||
local surface = wagon.surface
|
||||
local area = wagon.area
|
||||
local x_vector = door.position.x - player.position.x
|
||||
local position
|
||||
if x_vector > 0 then
|
||||
position = {area.left_top.x + 0.5, area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5)}
|
||||
else
|
||||
position = {area.right_bottom.x - 0.5, area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5)}
|
||||
end
|
||||
local p = surface.find_non_colliding_position('character', position, 128, 0.5)
|
||||
if p then
|
||||
player.teleport(p, surface)
|
||||
else
|
||||
player.teleport(position, surface)
|
||||
end
|
||||
player_data.surface = surface.index
|
||||
end
|
||||
end
|
||||
|
||||
local function move_room_to_train(icw, train, wagon)
|
||||
if not wagon then
|
||||
return
|
||||
end
|
||||
|
||||
table_insert(train.wagons, wagon.entity.unit_number)
|
||||
|
||||
local destination_area = {
|
||||
left_top = {x = wagon.area.left_top.x, y = train.top_y},
|
||||
right_bottom = {
|
||||
x = wagon.area.right_bottom.x,
|
||||
y = train.top_y + (wagon.area.right_bottom.y - wagon.area.left_top.y)
|
||||
}
|
||||
}
|
||||
|
||||
train.top_y = destination_area.right_bottom.y
|
||||
|
||||
if
|
||||
destination_area.left_top.x == wagon.area.left_top.x and destination_area.left_top.y == wagon.area.left_top.y and
|
||||
wagon.surface.name == train.surface.name
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
kick_players_out_of_vehicles(wagon)
|
||||
local player_positions = {}
|
||||
for _, e in pairs(wagon.surface.find_entities_filtered({name = 'character', area = wagon.area})) do
|
||||
local player = e.player
|
||||
if player then
|
||||
player_positions[player.index] = {
|
||||
player.position.x,
|
||||
player.position.y + (destination_area.left_top.y - wagon.area.left_top.y)
|
||||
}
|
||||
player.teleport({0, 0}, game.surfaces.nauvis)
|
||||
end
|
||||
end
|
||||
|
||||
kill_wagon_doors(icw, wagon)
|
||||
|
||||
wagon.surface.clone_area(
|
||||
{
|
||||
source_area = wagon.area,
|
||||
destination_area = destination_area,
|
||||
destination_surface = train.surface,
|
||||
clone_tiles = true,
|
||||
clone_entities = true,
|
||||
clone_decoratives = true,
|
||||
clear_destination_entities = true,
|
||||
clear_destination_decoratives = true,
|
||||
expand_map = true
|
||||
}
|
||||
)
|
||||
|
||||
for player_index, position in pairs(player_positions) do
|
||||
local player = game.players[player_index]
|
||||
player.teleport(position, train.surface)
|
||||
end
|
||||
|
||||
for _, tile in pairs(wagon.surface.find_tiles_filtered({area = wagon.area})) do
|
||||
wagon.surface.set_tiles({{name = 'out-of-map', position = tile.position}}, true)
|
||||
end
|
||||
wagon.entity.force.chart(wagon.surface, wagon.area)
|
||||
|
||||
wagon.surface = train.surface
|
||||
wagon.area = destination_area
|
||||
wagon.transfer_entities = {}
|
||||
construct_wagon_doors(icw, wagon)
|
||||
|
||||
local left_top_y = wagon.area.left_top.y
|
||||
for _, e in pairs(wagon.surface.find_entities_filtered({type = 'electric-pole', area = wagon.area})) do
|
||||
connect_power_pole(e, left_top_y)
|
||||
end
|
||||
|
||||
for _, e in pairs(wagon.surface.find_entities_filtered({area = wagon.area, force = 'neutral'})) do
|
||||
if transfer_functions[e.name] then
|
||||
table_insert(wagon.transfer_entities, e)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.construct_train(icw, carriages)
|
||||
local unit_number = carriages[1].unit_number
|
||||
|
||||
if icw.trains[unit_number] then
|
||||
return
|
||||
end
|
||||
|
||||
local train = {surface = Public.create_room_surface(icw, unit_number), wagons = {}, top_y = 0}
|
||||
icw.trains[unit_number] = train
|
||||
|
||||
for k, carriage in pairs(carriages) do
|
||||
move_room_to_train(icw, train, icw.wagons[carriage.unit_number])
|
||||
end
|
||||
end
|
||||
|
||||
function Public.reconstruct_all_trains(icw)
|
||||
icw.trains = {}
|
||||
for unit_number, wagon in pairs(icw.wagons) do
|
||||
if not wagon.entity or not wagon.entity.valid then
|
||||
icw.wagons[unit_number] = nil
|
||||
Public.request_reconstruction(icw)
|
||||
return
|
||||
end
|
||||
|
||||
if not wagon.surface then
|
||||
wagon.surface = Public.create_room_surface(icw, unit_number)
|
||||
Public.create_wagon_room(icw, wagon)
|
||||
end
|
||||
|
||||
local carriages = wagon.entity.train.carriages
|
||||
Public.construct_train(icw, carriages)
|
||||
end
|
||||
delete_empty_surfaces(icw)
|
||||
end
|
||||
|
||||
function Public.item_transfer(icw)
|
||||
for _, wagon in pairs(icw.wagons) do
|
||||
if not wagon and not wagon.valid then
|
||||
return
|
||||
end
|
||||
if wagon.transfer_entities then
|
||||
if not wagon and not wagon.valid then
|
||||
return
|
||||
end
|
||||
|
||||
for k, e in pairs(wagon.transfer_entities) do
|
||||
transfer_functions[e.name](wagon, e)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.draw_minimap(icw, player, surface, position)
|
||||
local element = player.gui.left.icw_map
|
||||
if not element then
|
||||
local player_data = get_player_data(icw, player)
|
||||
element =
|
||||
player.gui.left.add(
|
||||
{
|
||||
type = 'camera',
|
||||
name = 'icw_map',
|
||||
position = position,
|
||||
surface_index = surface.index,
|
||||
zoom = player_data.zoom,
|
||||
tooltip = 'LMB: Increase zoom level.\nRMB: Decrease zoom level.\nMMB: Toggle camera size.'
|
||||
}
|
||||
)
|
||||
element.style.margin = 1
|
||||
element.style.minimal_height = player_data.map_size
|
||||
element.style.minimal_width = player_data.map_size
|
||||
return
|
||||
end
|
||||
element.position = position
|
||||
end
|
||||
|
||||
function Public.update_minimap(icw)
|
||||
for k, player in pairs(game.connected_players) do
|
||||
if player.character and player.character.valid then
|
||||
local wagon = get_wagon_for_entity(icw, player.character)
|
||||
if wagon then
|
||||
Public.draw_minimap(icw, player, wagon.entity.surface, wagon.entity.position)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.toggle_minimap(icw, event)
|
||||
local element = event.element
|
||||
if not element then
|
||||
return
|
||||
end
|
||||
if not element.valid then
|
||||
return
|
||||
end
|
||||
if element.name ~= 'icw_map' then
|
||||
return
|
||||
end
|
||||
local player = game.players[event.player_index]
|
||||
local player_data = get_player_data(icw, player)
|
||||
if event.button == defines.mouse_button_type.right then
|
||||
player_data.zoom = player_data.zoom - 0.07
|
||||
if player_data.zoom < 0.07 then
|
||||
player_data.zoom = 0.07
|
||||
end
|
||||
element.zoom = player_data.zoom
|
||||
return
|
||||
end
|
||||
if event.button == defines.mouse_button_type.left then
|
||||
player_data.zoom = player_data.zoom + 0.07
|
||||
if player_data.zoom > 2 then
|
||||
player_data.zoom = 2
|
||||
end
|
||||
element.zoom = player_data.zoom
|
||||
return
|
||||
end
|
||||
if event.button == defines.mouse_button_type.middle then
|
||||
player_data.map_size = player_data.map_size + 50
|
||||
if player_data.map_size > 650 then
|
||||
player_data.map_size = 250
|
||||
end
|
||||
element.style.minimal_height = player_data.map_size
|
||||
element.style.minimal_width = player_data.map_size
|
||||
element.style.maximal_height = player_data.map_size
|
||||
element.style.maximal_width = player_data.map_size
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return Public
|
192
maps/mountain_fortress_v3/icw/main.lua
Normal file
192
maps/mountain_fortress_v3/icw/main.lua
Normal file
@ -0,0 +1,192 @@
|
||||
local Global = require 'utils.global'
|
||||
local Event = require 'utils.event'
|
||||
local Functions = require 'maps.mountain_fortress_v3.icw.functions'
|
||||
local Constants = require 'maps.mountain_fortress_v3.icw.constants'
|
||||
local Public = {}
|
||||
|
||||
local math_round = math.round
|
||||
|
||||
local icw = {}
|
||||
Global.register(
|
||||
icw,
|
||||
function(tbl)
|
||||
icw = tbl
|
||||
end
|
||||
)
|
||||
|
||||
function Public.reset()
|
||||
if icw.surfaces then
|
||||
for k, surface in pairs(icw.surfaces) do
|
||||
if surface and surface.valid then
|
||||
game.delete_surface(surface)
|
||||
end
|
||||
end
|
||||
end
|
||||
for k, v in pairs(icw) do
|
||||
icw[k] = nil
|
||||
end
|
||||
icw.doors = {}
|
||||
icw.wagons = {}
|
||||
icw.trains = {}
|
||||
icw.players = {}
|
||||
icw.surfaces = {}
|
||||
end
|
||||
|
||||
local function on_entity_died(event)
|
||||
local entity = event.entity
|
||||
if not entity and not entity.valid then
|
||||
return
|
||||
end
|
||||
if not Constants.wagon_types[entity.type] then
|
||||
return
|
||||
end
|
||||
Functions.subtract_wagon_entity_count(icw, entity)
|
||||
Functions.kill_wagon(icw, entity)
|
||||
end
|
||||
|
||||
local function on_player_mined_entity(event)
|
||||
local entity = event.entity
|
||||
if not entity and not entity.valid then
|
||||
return
|
||||
end
|
||||
Functions.subtract_wagon_entity_count(icw, entity)
|
||||
Functions.kill_wagon(icw, entity)
|
||||
end
|
||||
|
||||
local function on_robot_mined_entity(event)
|
||||
local entity = event.entity
|
||||
if not entity and not entity.valid then
|
||||
return
|
||||
end
|
||||
Functions.subtract_wagon_entity_count(icw, entity)
|
||||
Functions.kill_wagon(icw, entity)
|
||||
end
|
||||
|
||||
local function on_built_entity(event)
|
||||
local created_entity = event.created_entity
|
||||
Functions.create_wagon(icw, created_entity)
|
||||
Functions.add_wagon_entity_count(icw, created_entity)
|
||||
end
|
||||
|
||||
local function on_robot_built_entity(event)
|
||||
local created_entity = event.created_entity
|
||||
Functions.create_wagon(icw, created_entity)
|
||||
Functions.add_wagon_entity_count(icw, created_entity)
|
||||
end
|
||||
|
||||
local function on_player_driving_changed_state(event)
|
||||
local player = game.players[event.player_index]
|
||||
Functions.use_cargo_wagon_door(icw, player, event.entity)
|
||||
end
|
||||
--[[
|
||||
local function on_player_created(event)
|
||||
local player = game.players[event.player_index]
|
||||
player.insert({name = "cargo-wagon", count = 5})
|
||||
player.insert({name = "artillery-wagon", count = 5})
|
||||
player.insert({name = "fluid-wagon", count = 5})
|
||||
player.insert({name = "locomotive", count = 5})
|
||||
player.insert({name = "rail", count = 100})
|
||||
end
|
||||
]]
|
||||
local function on_gui_closed(event)
|
||||
local entity = event.entity
|
||||
if not entity then
|
||||
return
|
||||
end
|
||||
if not entity.valid then
|
||||
return
|
||||
end
|
||||
if not entity.unit_number then
|
||||
return
|
||||
end
|
||||
if not icw.wagons[entity.unit_number] then
|
||||
return
|
||||
end
|
||||
Functions.kill_minimap(game.players[event.player_index])
|
||||
end
|
||||
|
||||
local function on_gui_opened(event)
|
||||
local entity = event.entity
|
||||
if not entity then
|
||||
return
|
||||
end
|
||||
if not entity.valid then
|
||||
return
|
||||
end
|
||||
if not entity.unit_number then
|
||||
return
|
||||
end
|
||||
local wagon = icw.wagons[entity.unit_number]
|
||||
if not wagon then
|
||||
return
|
||||
end
|
||||
Functions.draw_minimap(
|
||||
icw,
|
||||
game.players[event.player_index],
|
||||
wagon.surface,
|
||||
{
|
||||
wagon.area.left_top.x + (wagon.area.right_bottom.x - wagon.area.left_top.x) * 0.5,
|
||||
wagon.area.left_top.y + (wagon.area.right_bottom.y - wagon.area.left_top.y) * 0.5
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
local function on_player_died(event)
|
||||
Functions.kill_minimap(game.players[event.player_index])
|
||||
end
|
||||
|
||||
local function on_train_created(event)
|
||||
Functions.request_reconstruction(icw)
|
||||
end
|
||||
|
||||
local function on_gui_click(event)
|
||||
Functions.toggle_minimap(icw, event)
|
||||
end
|
||||
|
||||
local function on_tick()
|
||||
local tick = game.tick
|
||||
if tick % 60 == 0 then
|
||||
Functions.item_transfer(icw)
|
||||
end
|
||||
if tick % 240 == 0 then
|
||||
Functions.update_minimap(icw)
|
||||
end
|
||||
|
||||
if not icw.rebuild_tick then
|
||||
return
|
||||
end
|
||||
if icw.rebuild_tick ~= tick then
|
||||
return
|
||||
end
|
||||
Functions.reconstruct_all_trains(icw)
|
||||
icw.rebuild_tick = nil
|
||||
end
|
||||
|
||||
local function on_init()
|
||||
Public.reset()
|
||||
end
|
||||
|
||||
function Public.get_table()
|
||||
return icw
|
||||
end
|
||||
|
||||
function Public.register_wagon(wagon_entity)
|
||||
return Functions.create_wagon(icw, wagon_entity)
|
||||
end
|
||||
|
||||
Event.on_init(on_init)
|
||||
Event.add(defines.events.on_tick, on_tick)
|
||||
Event.add(defines.events.on_player_driving_changed_state, on_player_driving_changed_state)
|
||||
Event.add(defines.events.on_entity_died, on_entity_died)
|
||||
Event.add(defines.events.on_built_entity, on_built_entity)
|
||||
Event.add(defines.events.on_train_created, on_train_created)
|
||||
Event.add(defines.events.on_robot_built_entity, on_robot_built_entity)
|
||||
Event.add(defines.events.on_player_died, on_player_died)
|
||||
--Event.add(defines.events.on_player_created, on_player_created)
|
||||
Event.add(defines.events.on_gui_click, on_gui_click)
|
||||
Event.add(defines.events.on_gui_closed, on_gui_closed)
|
||||
Event.add(defines.events.on_gui_opened, on_gui_opened)
|
||||
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)
|
||||
Event.add(defines.events.on_robot_mined_entity, on_robot_mined_entity)
|
||||
|
||||
return Public
|
319
maps/mountain_fortress_v3/locomotive.lua
Normal file
319
maps/mountain_fortress_v3/locomotive.lua
Normal file
@ -0,0 +1,319 @@
|
||||
local Event = require 'utils.event'
|
||||
--local Power = require 'maps.mountain_fortress_v3.power'
|
||||
local ICW = require 'maps.mountain_fortress_v3.icw.main'
|
||||
local WPT = require 'maps.mountain_fortress_v3.table'
|
||||
local RPG = require 'maps.mountain_fortress_v3.rpg'
|
||||
require 'maps.mountain_fortress_v3.locomotive_market'
|
||||
|
||||
local Public = {}
|
||||
|
||||
local rnd = math.random
|
||||
|
||||
local function validate_player(player)
|
||||
if not player then
|
||||
return false
|
||||
end
|
||||
if not player.valid then
|
||||
return false
|
||||
end
|
||||
if not player.character then
|
||||
return false
|
||||
end
|
||||
if not player.connected then
|
||||
return false
|
||||
end
|
||||
if not game.players[player.index] then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function property_boost(data)
|
||||
local xp_floating_text_color = {r = 0, g = 127, b = 33}
|
||||
local visuals_delay = 1800
|
||||
local this = data.this
|
||||
local locomotive_surface = data.locomotive_surface
|
||||
local aura = this.locomotive_xp_aura
|
||||
local rpg = data.rpg
|
||||
local loco = this.locomotive.position
|
||||
local area = {
|
||||
left_top = {x = loco.x - aura, y = loco.y - aura},
|
||||
right_bottom = {x = loco.x + aura, y = loco.y + aura}
|
||||
}
|
||||
|
||||
for _, player in pairs(game.connected_players) do
|
||||
if not validate_player(player) then
|
||||
return
|
||||
end
|
||||
if Public.contains_positions(player.position, area) or player.surface.index == locomotive_surface.index then
|
||||
local pos = player.position
|
||||
RPG.gain_xp(player, 0.3 * (rpg[player.index].bonus + this.xp_points))
|
||||
|
||||
player.create_local_flying_text {
|
||||
text = '+' .. '',
|
||||
position = {x = pos.x, y = pos.y - 2},
|
||||
color = xp_floating_text_color,
|
||||
time_to_live = 60,
|
||||
speed = 3
|
||||
}
|
||||
rpg[player.index].xp_since_last_floaty_text = 0
|
||||
rpg[player.index].last_floaty_text = game.tick + visuals_delay
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function fish_tag()
|
||||
local this = WPT.get()
|
||||
if not this.locomotive_cargo then
|
||||
return
|
||||
end
|
||||
if not this.locomotive_cargo.valid then
|
||||
return
|
||||
end
|
||||
if not this.locomotive_cargo.surface then
|
||||
return
|
||||
end
|
||||
if not this.locomotive_cargo.surface.valid then
|
||||
return
|
||||
end
|
||||
if this.locomotive_tag then
|
||||
if this.locomotive_tag.valid then
|
||||
if
|
||||
this.locomotive_tag.position.x == this.locomotive_cargo.position.x and
|
||||
this.locomotive_tag.position.y == this.locomotive_cargo.position.y
|
||||
then
|
||||
return
|
||||
end
|
||||
this.locomotive_tag.destroy()
|
||||
end
|
||||
end
|
||||
this.locomotive_tag =
|
||||
this.locomotive_cargo.force.add_chart_tag(
|
||||
this.locomotive_cargo.surface,
|
||||
{
|
||||
icon = {type = 'item', name = 'raw-fish'},
|
||||
position = this.locomotive_cargo.position,
|
||||
text = ' '
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
local function set_player_spawn_and_refill_fish()
|
||||
local this = WPT.get()
|
||||
if not this.locomotive_cargo then
|
||||
return
|
||||
end
|
||||
if not this.locomotive_cargo.valid then
|
||||
return
|
||||
end
|
||||
this.locomotive_cargo.get_inventory(defines.inventory.cargo_wagon).insert(
|
||||
{name = 'raw-fish', count = math.random(2, 5)}
|
||||
)
|
||||
local position =
|
||||
this.locomotive_cargo.surface.find_non_colliding_position(
|
||||
'stone-furnace',
|
||||
this.locomotive_cargo.position,
|
||||
16,
|
||||
2
|
||||
)
|
||||
if not position then
|
||||
return
|
||||
end
|
||||
game.forces.player.set_spawn_position({x = position.x, y = position.y}, this.locomotive_cargo.surface)
|
||||
end
|
||||
|
||||
local function set_locomotive_health()
|
||||
local this = WPT.get()
|
||||
if not this.locomotive then
|
||||
return
|
||||
end
|
||||
if not this.locomotive.valid then
|
||||
return
|
||||
end
|
||||
local locomotive_health = WPT.get('locomotive_health')
|
||||
local locomotive_max_health = WPT.get('locomotive_max_health')
|
||||
local m = locomotive_health / locomotive_max_health
|
||||
this.locomotive.health = 1000 * m
|
||||
rendering.set_text(this.health_text, 'HP: ' .. locomotive_health .. ' / ' .. locomotive_max_health)
|
||||
end
|
||||
|
||||
local function tick()
|
||||
if game.tick % 120 == 0 then
|
||||
Public.boost_players_around_train()
|
||||
end
|
||||
|
||||
if game.tick % 30 == 0 then
|
||||
if game.tick % 1800 == 0 then
|
||||
set_player_spawn_and_refill_fish()
|
||||
end
|
||||
set_locomotive_health()
|
||||
fish_tag()
|
||||
end
|
||||
end
|
||||
|
||||
function Public.boost_players_around_train()
|
||||
local rpg = RPG.get_table()
|
||||
local this = WPT.get()
|
||||
if not this.active_surface_index then
|
||||
return
|
||||
end
|
||||
local surface = game.surfaces[this.active_surface_index]
|
||||
local icw_table = ICW.get_table()
|
||||
local unit_surface = this.locomotive.unit_number
|
||||
local locomotive_surface = game.surfaces[icw_table.wagons[unit_surface].surface.index]
|
||||
|
||||
if not this.locomotive then
|
||||
return
|
||||
end
|
||||
if not this.locomotive.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local data = {
|
||||
this = this,
|
||||
surface = surface,
|
||||
locomotive_surface = locomotive_surface,
|
||||
rpg = rpg
|
||||
}
|
||||
property_boost(data)
|
||||
end
|
||||
|
||||
function Public.render_train_hp()
|
||||
local this = WPT.get()
|
||||
local surface = game.surfaces[this.active_surface_index]
|
||||
|
||||
local names = {
|
||||
'Hanakocz',
|
||||
'Redlabel',
|
||||
'Hanakocz',
|
||||
'Gerkiz',
|
||||
'Hanakocz',
|
||||
'Mewmew',
|
||||
'Gerkiz',
|
||||
'Hanakocz',
|
||||
'Redlabel',
|
||||
'Gerkiz',
|
||||
'Hanakocz',
|
||||
'Redlabel',
|
||||
'Gerkiz',
|
||||
'Hanakocz'
|
||||
}
|
||||
|
||||
local size_of_names = #names
|
||||
|
||||
local n = names[rnd(1, size_of_names)]
|
||||
|
||||
this.health_text =
|
||||
rendering.draw_text {
|
||||
text = 'HP: ' .. this.locomotive_health .. ' / ' .. this.locomotive_max_health,
|
||||
surface = surface,
|
||||
target = this.locomotive,
|
||||
target_offset = {0, -2.5},
|
||||
color = this.locomotive.color,
|
||||
scale = 1.40,
|
||||
font = 'default-game',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
|
||||
this.caption =
|
||||
rendering.draw_text {
|
||||
text = n .. 's Comfy Train',
|
||||
surface = surface,
|
||||
target = this.locomotive,
|
||||
target_offset = {0, -4.25},
|
||||
color = this.locomotive.color,
|
||||
scale = 1.80,
|
||||
font = 'default-game',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
|
||||
this.circle =
|
||||
rendering.draw_circle {
|
||||
surface = surface,
|
||||
target = this.locomotive,
|
||||
color = this.locomotive.color,
|
||||
filled = false,
|
||||
radius = this.locomotive_xp_aura,
|
||||
only_in_alt_mode = true
|
||||
}
|
||||
end
|
||||
|
||||
function Public.locomotive_spawn(surface, position)
|
||||
local this = WPT.get()
|
||||
for y = -6, 6, 2 do
|
||||
surface.create_entity(
|
||||
{name = 'straight-rail', position = {position.x, position.y + y}, force = 'player', direction = 0}
|
||||
)
|
||||
end
|
||||
this.locomotive =
|
||||
surface.create_entity({name = 'locomotive', position = {position.x, position.y + -3}, force = 'player'})
|
||||
this.locomotive.get_inventory(defines.inventory.fuel).insert({name = 'wood', count = 100})
|
||||
|
||||
this.locomotive_cargo =
|
||||
surface.create_entity({name = 'cargo-wagon', position = {position.x, position.y + 3}, force = 'player'})
|
||||
this.locomotive_cargo.get_inventory(defines.inventory.cargo_wagon).insert({name = 'raw-fish', count = 8})
|
||||
|
||||
rendering.draw_light(
|
||||
{
|
||||
sprite = 'utility/light_medium',
|
||||
scale = 5.5,
|
||||
intensity = 1,
|
||||
minimum_darkness = 0,
|
||||
oriented = true,
|
||||
color = {255, 255, 255},
|
||||
target = this.locomotive,
|
||||
surface = surface,
|
||||
visible = true,
|
||||
only_in_alt_mode = false
|
||||
}
|
||||
)
|
||||
|
||||
for y = -1, 0, 0.05 do
|
||||
local scale = math.random(50, 100) * 0.01
|
||||
rendering.draw_sprite(
|
||||
{
|
||||
sprite = 'item/raw-fish',
|
||||
orientation = math.random(0, 100) * 0.01,
|
||||
x_scale = scale,
|
||||
y_scale = scale,
|
||||
tint = {math.random(60, 255), math.random(60, 255), math.random(60, 255)},
|
||||
render_layer = 'selection-box',
|
||||
target = this.locomotive_cargo,
|
||||
target_offset = {-0.7 + math.random(0, 140) * 0.01, y},
|
||||
surface = surface
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
this.locomotive.color = {0, 255, 0}
|
||||
this.locomotive.minable = false
|
||||
this.locomotive_cargo.minable = false
|
||||
this.locomotive_cargo.operable = true
|
||||
|
||||
local locomotive = ICW.register_wagon(this.locomotive)
|
||||
local wagon = ICW.register_wagon(this.locomotive_cargo)
|
||||
locomotive.entity_count = 999
|
||||
wagon.entity_count = 999
|
||||
|
||||
this.loco_surface = locomotive.surface
|
||||
this.locomotive_index = locomotive
|
||||
end
|
||||
|
||||
function Public.inside(pos, area)
|
||||
local lt = area.left_top
|
||||
local rb = area.right_bottom
|
||||
|
||||
return pos.x >= lt.x and pos.y >= lt.y and pos.x <= rb.x and pos.y <= rb.y
|
||||
end
|
||||
function Public.contains_positions(pos, area)
|
||||
if Public.inside(pos, area) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
Event.on_nth_tick(5, tick)
|
||||
|
||||
return Public
|
725
maps/mountain_fortress_v3/locomotive_market.lua
Normal file
725
maps/mountain_fortress_v3/locomotive_market.lua
Normal file
@ -0,0 +1,725 @@
|
||||
local Event = require 'utils.event'
|
||||
local WPT = require 'maps.mountain_fortress_v3.table'
|
||||
local WD = require 'modules.wave_defense.table'
|
||||
local ICW = require 'maps.mountain_fortress_v3.icw.main'
|
||||
local format_number = require 'util'.format_number
|
||||
|
||||
local shopkeeper = '[color=blue]Shopkeeper:[/color]'
|
||||
|
||||
local random = math.random
|
||||
|
||||
local Public = {}
|
||||
|
||||
local function shuffle(tbl)
|
||||
local size = #tbl
|
||||
for i = size, 1, -1 do
|
||||
local rand = random(size)
|
||||
tbl[i], tbl[rand] = tbl[rand], tbl[i]
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
|
||||
function Public.get_items()
|
||||
local this = WPT.get()
|
||||
|
||||
local threat_cost = 100000
|
||||
local health_cost = 30000 * (1 + this.health_upgrades)
|
||||
local aura_cost = 30000 * (1 + this.aura_upgrades)
|
||||
local xp_point_boost_cost = 30000 * (1 + this.xp_points_upgrade)
|
||||
|
||||
local items = {}
|
||||
items['clear_threat_level'] = {
|
||||
stack = 1,
|
||||
value = 'coin',
|
||||
price = threat_cost,
|
||||
tooltip = '[Wave Defense]:\nReduces the threat level by 50%\nUsable if threat level is too high.\nCan be purchased multiple times.',
|
||||
sprite = 'item/computer',
|
||||
enabled = true
|
||||
}
|
||||
items['locomotive_max_health'] = {
|
||||
stack = 1,
|
||||
value = 'coin',
|
||||
price = health_cost,
|
||||
tooltip = '[Locomotive Health]:\nUpgrades the train health.\nCan be purchased multiple times.',
|
||||
sprite = 'item/computer',
|
||||
enabled = true
|
||||
}
|
||||
items['locomotive_xp_aura'] = {
|
||||
stack = 1,
|
||||
value = 'coin',
|
||||
price = aura_cost,
|
||||
tooltip = '[XP Aura]:\nUpgrades the aura that is around the train.\nNote! Reaching breach walls gives more XP.',
|
||||
sprite = 'item/computer',
|
||||
enabled = true
|
||||
}
|
||||
items['xp_points_boost'] = {
|
||||
stack = 1,
|
||||
value = 'coin',
|
||||
price = xp_point_boost_cost,
|
||||
tooltip = '[XP Points]:\nUpgrades the amount of xp points you get inside the XP aura',
|
||||
sprite = 'item/computer',
|
||||
enabled = true
|
||||
}
|
||||
items['small-lamp'] = {stack = 1, value = 'coin', price = 5, tooltip = 'Small Sunlight'}
|
||||
items['wood'] = {stack = 50, value = 'coin', price = 12, tooltip = 'Some fine Wood'}
|
||||
items['iron-ore'] = {stack = 50, value = 'coin', price = 12, tooltip = 'Some chunky iron'}
|
||||
items['copper-ore'] = {stack = 50, value = 'coin', price = 12, tooltip = 'Some chunky copper'}
|
||||
items['stone'] = {stack = 50, value = 'coin', price = 12, tooltip = 'Some chunky stone'}
|
||||
items['coal'] = {stack = 50, value = 'coin', price = 12, tooltip = 'Some chunky coal'}
|
||||
items['uranium-ore'] = {stack = 50, value = 'coin', price = 12, tooltip = 'Some chunky uranium'}
|
||||
items['land-mine'] = {stack = 1, value = 'coin', price = 25, tooltip = 'Land Boom Danger'}
|
||||
items['raw-fish'] = {stack = 1, value = 'coin', price = 4, tooltip = 'Flappy Fish'}
|
||||
items['firearm-magazine'] = {stack = 1, value = 'coin', price = 5, tooltip = 'Firearm Pew'}
|
||||
items['crude-oil-barrel'] = {stack = 1, value = 'coin', price = 8, tooltip = 'Crude Oil Flame'}
|
||||
--
|
||||
--[[
|
||||
items['loader'] = {stack = 1, value = 'coin', price = 150, tooltip = 'Ground Inserter.'}
|
||||
items['fast-loader'] = {
|
||||
stack = 1,
|
||||
value = 'coin',
|
||||
price = 300,
|
||||
tooltip = 'Ground Fast Inserter'
|
||||
}
|
||||
]] return items
|
||||
end
|
||||
|
||||
local space = {
|
||||
minimal_height = 10,
|
||||
top_padding = 0,
|
||||
bottom_padding = 0
|
||||
}
|
||||
|
||||
local function addStyle(guiIn, styleIn)
|
||||
for k, v in pairs(styleIn) do
|
||||
guiIn.style[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
local function adjustSpace(guiIn)
|
||||
addStyle(guiIn.add {type = 'line', direction = 'horizontal'}, space)
|
||||
end
|
||||
|
||||
local function validate_player(player)
|
||||
if not player then
|
||||
return false
|
||||
end
|
||||
if not player.valid then
|
||||
return false
|
||||
end
|
||||
if not player.character then
|
||||
return false
|
||||
end
|
||||
if not player.connected then
|
||||
return false
|
||||
end
|
||||
if not game.players[player.index] then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function close_market_gui(player)
|
||||
local this = WPT.get()
|
||||
|
||||
local element = player.gui.center
|
||||
local data = this.players[player.index].data
|
||||
if not data then
|
||||
return
|
||||
end
|
||||
|
||||
if element and element.valid then
|
||||
element = element['market_gui']
|
||||
if element and element.valid then
|
||||
element.destroy()
|
||||
end
|
||||
if data.frame and data.frame.valid then
|
||||
data.frame.destroy()
|
||||
for k, _ in pairs(data) do
|
||||
data[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function redraw_market_items(gui, player, search_text)
|
||||
if not validate_player(player) then
|
||||
return
|
||||
end
|
||||
local this = WPT.get()
|
||||
|
||||
gui.clear()
|
||||
shuffle(Public.get_items())
|
||||
|
||||
local inventory = player.get_main_inventory()
|
||||
local player_item_count = inventory.get_item_count('coin')
|
||||
|
||||
local items_table = gui.add({type = 'table', column_count = 6})
|
||||
|
||||
local slider_value = math.ceil(this.players[player.index].data.slider.slider_value)
|
||||
for name, opts in pairs(Public.get_items()) do
|
||||
if not search_text then
|
||||
goto continue
|
||||
end
|
||||
if not search_text.text then
|
||||
goto continue
|
||||
end
|
||||
if not string.lower(name:gsub('-', ' ')):find(search_text.text) then
|
||||
goto continue
|
||||
end
|
||||
local item_count = opts.stack * slider_value
|
||||
local item_cost = opts.price * slider_value
|
||||
|
||||
local flow = items_table.add({type = 'flow'})
|
||||
flow.style.vertical_align = 'bottom'
|
||||
|
||||
local button =
|
||||
flow.add(
|
||||
{
|
||||
type = 'sprite-button',
|
||||
sprite = opts.sprite or 'item/' .. name,
|
||||
number = item_count,
|
||||
name = name,
|
||||
tooltip = opts.tooltip,
|
||||
style = 'slot_button',
|
||||
enabled = opts.enabled
|
||||
}
|
||||
)
|
||||
flow.add(
|
||||
{
|
||||
type = 'label',
|
||||
caption = format_number(item_cost, true) .. ' coins'
|
||||
}
|
||||
)
|
||||
|
||||
if player_item_count < item_cost then
|
||||
button.enabled = false
|
||||
end
|
||||
::continue::
|
||||
end
|
||||
end
|
||||
|
||||
local function redraw_coins_left(gui, player)
|
||||
if not validate_player(player) then
|
||||
return
|
||||
end
|
||||
|
||||
gui.clear()
|
||||
local inventory = player.get_main_inventory()
|
||||
local player_item_count = inventory.get_item_count('coin')
|
||||
|
||||
local coinsleft =
|
||||
gui.add(
|
||||
{
|
||||
type = 'label',
|
||||
caption = 'Coins left: ' .. format_number(player_item_count, true)
|
||||
}
|
||||
)
|
||||
|
||||
adjustSpace(coinsleft)
|
||||
end
|
||||
|
||||
local function slider_changed(event)
|
||||
local player = game.players[event.player_index]
|
||||
local this = WPT.get()
|
||||
local slider_value
|
||||
|
||||
slider_value = this.players
|
||||
if not slider_value then
|
||||
return
|
||||
end
|
||||
slider_value = slider_value[player.index].data
|
||||
if not slider_value then
|
||||
return
|
||||
end
|
||||
slider_value = slider_value.slider
|
||||
if not slider_value then
|
||||
return
|
||||
end
|
||||
slider_value = slider_value.slider_value
|
||||
if not slider_value then
|
||||
return
|
||||
end
|
||||
slider_value = math.ceil(slider_value)
|
||||
this.players[player.index].data.text_input.text = slider_value
|
||||
redraw_market_items(this.players[player.index].data.item_frame, player, this.players[player.index].data.search_text)
|
||||
end
|
||||
|
||||
local function text_changed(event)
|
||||
local this = WPT.get()
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
local data = this.players[player.index].data
|
||||
if not data then
|
||||
return
|
||||
end
|
||||
if not data.text_input then
|
||||
return
|
||||
end
|
||||
|
||||
if not data.text_input.text then
|
||||
return
|
||||
end
|
||||
|
||||
local value = 0
|
||||
tonumber(data.text_input.text)
|
||||
if not value then
|
||||
return
|
||||
end
|
||||
data.slider.slider_value = value
|
||||
redraw_market_items(data.item_frame, player, data.search_text)
|
||||
end
|
||||
|
||||
local function gui_opened(event)
|
||||
local this = WPT.get()
|
||||
|
||||
if not event.gui_type == defines.gui_type.entity then
|
||||
return
|
||||
end
|
||||
|
||||
local entity = event.entity
|
||||
if not entity then
|
||||
return
|
||||
end
|
||||
|
||||
if entity ~= this.market then
|
||||
return
|
||||
end
|
||||
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
if not validate_player(player) then
|
||||
return
|
||||
end
|
||||
|
||||
local inventory = player.get_main_inventory()
|
||||
local player_item_count = inventory.get_item_count('coin')
|
||||
|
||||
local data = this.players[player.index].data
|
||||
|
||||
if data.frame then
|
||||
data.frame = nil
|
||||
end
|
||||
local frame =
|
||||
player.gui.screen.add(
|
||||
{
|
||||
type = 'frame',
|
||||
caption = 'Market',
|
||||
direction = 'vertical',
|
||||
name = 'market_gui'
|
||||
}
|
||||
)
|
||||
|
||||
frame.auto_center = true
|
||||
|
||||
player.opened = frame
|
||||
frame.style.minimal_width = 500
|
||||
frame.style.minimal_height = 250
|
||||
|
||||
local search_table = frame.add({type = 'table', column_count = 2})
|
||||
search_table.add({type = 'label', caption = 'Search: '})
|
||||
local search_text = search_table.add({type = 'textfield'})
|
||||
|
||||
adjustSpace(frame)
|
||||
|
||||
local pane =
|
||||
frame.add {
|
||||
type = 'scroll-pane',
|
||||
direction = 'vertical',
|
||||
vertical_scroll_policy = 'always',
|
||||
horizontal_scroll_policy = 'never'
|
||||
}
|
||||
pane.style.maximal_height = 200
|
||||
pane.style.horizontally_stretchable = true
|
||||
pane.style.minimal_height = 200
|
||||
pane.style.right_padding = 0
|
||||
|
||||
local flow = frame.add({type = 'flow'})
|
||||
|
||||
adjustSpace(flow)
|
||||
|
||||
local slider_frame = frame.add({type = 'table', column_count = 5})
|
||||
|
||||
local left_button = slider_frame.add({type = 'button', caption = '-1', name = 'less'})
|
||||
local slider =
|
||||
slider_frame.add(
|
||||
{
|
||||
type = 'slider',
|
||||
minimum_value = 1,
|
||||
maximum_value = 1e3,
|
||||
value = 1
|
||||
}
|
||||
)
|
||||
|
||||
local right_button = slider_frame.add({type = 'button', caption = '+1', name = 'more'})
|
||||
|
||||
left_button.style.width = 0
|
||||
left_button.style.height = 0
|
||||
right_button.style.width = 0
|
||||
right_button.style.height = 0
|
||||
|
||||
slider_frame.add(
|
||||
{
|
||||
type = 'label',
|
||||
caption = 'Qty:'
|
||||
}
|
||||
)
|
||||
|
||||
local text_input =
|
||||
slider_frame.add(
|
||||
{
|
||||
type = 'textfield',
|
||||
text = 1
|
||||
}
|
||||
)
|
||||
|
||||
local coinsleft = frame.add({type = 'flow'})
|
||||
|
||||
coinsleft.add(
|
||||
{
|
||||
type = 'label',
|
||||
caption = 'Coins left: ' .. format_number(player_item_count, true)
|
||||
}
|
||||
)
|
||||
|
||||
this.players[player.index].data.search_text = search_text
|
||||
this.players[player.index].data.text_input = text_input
|
||||
this.players[player.index].data.slider = slider
|
||||
this.players[player.index].data.frame = frame
|
||||
this.players[player.index].data.item_frame = pane
|
||||
this.players[player.index].data.coins_left = coinsleft
|
||||
|
||||
redraw_market_items(pane, player, search_text)
|
||||
end
|
||||
|
||||
local function gui_click(event)
|
||||
local this = WPT.get()
|
||||
local wdt = WD.get_table()
|
||||
|
||||
local element = event.element
|
||||
local player = game.players[event.player_index]
|
||||
if not validate_player(player) then
|
||||
return
|
||||
end
|
||||
|
||||
if not this.players[player.index] then
|
||||
return
|
||||
end
|
||||
|
||||
local data = this.players[player.index].data
|
||||
if not data then
|
||||
return
|
||||
end
|
||||
|
||||
if not element.valid then
|
||||
return
|
||||
end
|
||||
local name = element.name
|
||||
|
||||
if name == 'less' then
|
||||
local slider_value = this.players[player.index].data.slider.slider_value
|
||||
if slider_value > 1 then
|
||||
data.slider.slider_value = slider_value - 1
|
||||
data.text_input.text = data.slider.slider_value
|
||||
redraw_market_items(data.item_frame, player, data.search_text)
|
||||
end
|
||||
return
|
||||
elseif name == 'more' then
|
||||
local slider_value = data.slider.slider_value
|
||||
if slider_value <= 1e3 then
|
||||
data.slider.slider_value = slider_value + 1
|
||||
data.text_input.text = data.slider.slider_value
|
||||
redraw_market_items(data.item_frame, player, data.search_text)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if not player.opened then
|
||||
return
|
||||
end
|
||||
if not player.opened.name == 'market' then
|
||||
return
|
||||
end
|
||||
if not data then
|
||||
return
|
||||
end
|
||||
local item = Public.get_items()[name]
|
||||
if not item then
|
||||
return
|
||||
end
|
||||
|
||||
local inventory = player.get_main_inventory()
|
||||
local player_item_count = inventory.get_item_count(item.value)
|
||||
local slider_value = math.ceil(data.slider.slider_value)
|
||||
local cost = (item.price * slider_value)
|
||||
local item_count = item.stack * slider_value
|
||||
|
||||
if name == 'clear_threat_level' then
|
||||
if wdt.threat <= 10000 then
|
||||
return player.print(
|
||||
shopkeeper .. ' ' .. player.name .. ', threat is already low!',
|
||||
{r = 0.98, g = 0.66, b = 0.22}
|
||||
)
|
||||
end
|
||||
player.remove_item({name = item.value, count = cost})
|
||||
|
||||
game.print(
|
||||
shopkeeper .. ' ' .. player.name .. ' has bought the group some extra time. Threat level is reduced by 50%!',
|
||||
{r = 0.98, g = 0.66, b = 0.22}
|
||||
)
|
||||
this.threat_upgrades = this.threat_upgrades + 1
|
||||
wdt.threat = wdt.threat / 2
|
||||
|
||||
redraw_market_items(data.item_frame, player, data.search_text)
|
||||
redraw_coins_left(data.coins_left, player)
|
||||
|
||||
return
|
||||
end
|
||||
if name == 'locomotive_max_health' then
|
||||
player.remove_item({name = item.value, count = cost})
|
||||
|
||||
game.print(
|
||||
shopkeeper ..
|
||||
' ' .. player.name .. ' has bought the group a train health modifier! The train health is now buffed!',
|
||||
{r = 0.98, g = 0.66, b = 0.22}
|
||||
)
|
||||
this.locomotive_max_health = this.locomotive_max_health + 2500
|
||||
local m = this.locomotive_health / this.locomotive_max_health
|
||||
this.locomotive.health = 1000 * m
|
||||
this.train_upgrades = this.train_upgrades + 1
|
||||
this.health_upgrades = this.health_upgrades + 1
|
||||
rendering.set_text(this.health_text, 'HP: ' .. this.locomotive_health .. ' / ' .. this.locomotive_max_health)
|
||||
|
||||
redraw_market_items(data.item_frame, player, data.search_text)
|
||||
redraw_coins_left(data.coins_left, player)
|
||||
|
||||
return
|
||||
end
|
||||
if name == 'locomotive_xp_aura' then
|
||||
player.remove_item({name = item.value, count = cost})
|
||||
|
||||
game.print(
|
||||
shopkeeper .. ' ' .. player.name .. ' has bought the group a XP aura modifier! The XP aura is now buffed!',
|
||||
{r = 0.98, g = 0.66, b = 0.22}
|
||||
)
|
||||
this.locomotive_xp_aura = this.locomotive_xp_aura + 5
|
||||
this.aura_upgrades = this.aura_upgrades + 1
|
||||
this.train_upgrades = this.train_upgrades + 1
|
||||
|
||||
if this.circle then
|
||||
rendering.destroy(this.circle)
|
||||
end
|
||||
this.circle =
|
||||
rendering.draw_circle {
|
||||
surface = game.surfaces[this.active_surface_index],
|
||||
target = this.locomotive,
|
||||
color = this.locomotive.color,
|
||||
filled = false,
|
||||
radius = this.locomotive_xp_aura,
|
||||
only_in_alt_mode = true
|
||||
}
|
||||
|
||||
redraw_market_items(data.item_frame, player, data.search_text)
|
||||
redraw_coins_left(data.coins_left, player)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if name == 'xp_points_boost' then
|
||||
player.remove_item({name = item.value, count = cost})
|
||||
|
||||
game.print(
|
||||
shopkeeper ..
|
||||
' ' .. player.name .. ' has bought the group a XP point modifier! You now gain more XP points!',
|
||||
{r = 0.98, g = 0.66, b = 0.22}
|
||||
)
|
||||
this.xp_points = this.xp_points + 0.5
|
||||
this.xp_points_upgrade = this.xp_points_upgrade + 1
|
||||
this.train_upgrades = this.train_upgrades + 1
|
||||
|
||||
redraw_market_items(data.item_frame, player, data.search_text)
|
||||
redraw_coins_left(data.coins_left, player)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if player_item_count >= cost then
|
||||
if player.can_insert({name = name, count = item_count}) then
|
||||
player.play_sound({path = 'entity-close/stone-furnace', volume_modifier = 0.65})
|
||||
player.remove_item({name = item.value, count = cost})
|
||||
local inserted_count = player.insert({name = name, count = item_count})
|
||||
if inserted_count < item_count then
|
||||
player.play_sound({path = 'utility/cannot_build', volume_modifier = 0.65})
|
||||
player.insert({name = item.value, count = cost})
|
||||
player.remove_item({name = name, count = inserted_count})
|
||||
end
|
||||
redraw_market_items(data.item_frame, player, data.search_text)
|
||||
redraw_coins_left(data.coins_left, player)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function gui_closed(event)
|
||||
local player = game.players[event.player_index]
|
||||
local this = WPT.get()
|
||||
|
||||
local type = event.gui_type
|
||||
|
||||
if type == defines.gui_type.custom then
|
||||
local data = this.players[player.index].data
|
||||
if not data then
|
||||
return
|
||||
end
|
||||
close_market_gui(player)
|
||||
end
|
||||
end
|
||||
|
||||
local function inside(pos, area)
|
||||
local lt = area.left_top
|
||||
local rb = area.right_bottom
|
||||
|
||||
return pos.x >= lt.x and pos.y >= lt.y and pos.x <= rb.x and pos.y <= rb.y
|
||||
end
|
||||
|
||||
local function contains_positions(pos, area)
|
||||
if inside(pos, area) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function on_player_changed_position(event)
|
||||
local this = WPT.get()
|
||||
local player = game.players[event.player_index]
|
||||
if not this.players[player.index] then
|
||||
return
|
||||
end
|
||||
local data = this.players[player.index].data
|
||||
|
||||
if data and data.frame and data.frame.valid then
|
||||
local position = this.market.position
|
||||
local area = {
|
||||
left_top = {x = position.x - 10, y = position.y - 10},
|
||||
right_bottom = {x = position.x + 10, y = position.y + 10}
|
||||
}
|
||||
if contains_positions(player.position, area) then
|
||||
return
|
||||
end
|
||||
if not data then
|
||||
return
|
||||
end
|
||||
close_market_gui(player)
|
||||
end
|
||||
end
|
||||
|
||||
local function create_market(data, rebuild)
|
||||
local surface = data.surface
|
||||
local this = data.this
|
||||
|
||||
if rebuild then
|
||||
local radius = 1024
|
||||
local area = {{x = -radius, y = -radius}, {x = radius, y = radius}}
|
||||
for _, entity in pairs(surface.find_entities_filtered {area = area, name = 'market'}) do
|
||||
entity.destroy()
|
||||
end
|
||||
this.market = nil
|
||||
end
|
||||
|
||||
local locomotive = this.locomotive_index
|
||||
|
||||
local center_position = {
|
||||
x = locomotive.area.left_top.x + (locomotive.area.right_bottom.x - locomotive.area.left_top.x) * 0.5,
|
||||
y = locomotive.area.left_top.y + (locomotive.area.right_bottom.y - locomotive.area.left_top.y) * 0.5
|
||||
}
|
||||
|
||||
this.market = surface.create_entity {name = 'market', position = center_position, force = 'player'}
|
||||
|
||||
rendering.draw_text {
|
||||
text = 'Market',
|
||||
surface = surface,
|
||||
target = this.market,
|
||||
target_offset = {0, 2},
|
||||
color = {r = 0.98, g = 0.66, b = 0.22},
|
||||
alignment = 'center'
|
||||
}
|
||||
|
||||
this.market.destructible = false
|
||||
|
||||
if not this.loco_surface then
|
||||
this.loco_surface = this.locomotive.surface
|
||||
return
|
||||
end
|
||||
|
||||
local position = this.loco_surface.find_non_colliding_position('market', center_position, 128, 0.5)
|
||||
local e =
|
||||
this.loco_surface.create_entity(
|
||||
{name = 'big-biter', position = position, force = 'player', create_build_effect_smoke = false}
|
||||
)
|
||||
e.ai_settings.allow_destroy_when_commands_fail = false
|
||||
e.ai_settings.allow_try_return_to_spawner = false
|
||||
|
||||
for x = center_position.x - 5, center_position.x + 5, 1 do
|
||||
for y = center_position.y - 5, center_position.y + 5, 1 do
|
||||
if math.random(1, 2) == 1 then
|
||||
this.loco_surface.spill_item_stack(
|
||||
{x + math.random(0, 9) * 0.1, y + math.random(0, 9) * 0.1},
|
||||
{name = 'raw-fish', count = 1},
|
||||
false
|
||||
)
|
||||
end
|
||||
this.loco_surface.set_tiles({{name = 'blue-refined-concrete', position = {x, y}}}, true)
|
||||
end
|
||||
end
|
||||
for x = center_position.x - 3, center_position.x + 3, 1 do
|
||||
for y = center_position.y - 3, center_position.y + 3, 1 do
|
||||
if math.random(1, 2) == 1 then
|
||||
this.loco_surface.spill_item_stack(
|
||||
{x + math.random(0, 9) * 0.1, y + math.random(0, 9) * 0.1},
|
||||
{name = 'raw-fish', count = 1},
|
||||
false
|
||||
)
|
||||
end
|
||||
this.loco_surface.set_tiles({{name = 'cyan-refined-concrete', position = {x, y}}}, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function place_market()
|
||||
local this = WPT.get()
|
||||
local icw_table = ICW.get_table()
|
||||
if not this.locomotive then
|
||||
return
|
||||
end
|
||||
|
||||
if not this.locomotive.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local unit_surface = this.locomotive.unit_number
|
||||
local surface = game.surfaces[icw_table.wagons[unit_surface].surface.index]
|
||||
|
||||
local data = {
|
||||
this = this,
|
||||
surface = surface
|
||||
}
|
||||
if not this.market then
|
||||
create_market(data)
|
||||
elseif not this.market.valid then
|
||||
create_market(data, true)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_tick()
|
||||
if game.tick % 30 == 0 then
|
||||
place_market()
|
||||
end
|
||||
end
|
||||
|
||||
Event.on_nth_tick(5, on_tick)
|
||||
Event.add(defines.events.on_gui_click, gui_click)
|
||||
Event.add(defines.events.on_gui_opened, gui_opened)
|
||||
Event.add(defines.events.on_gui_value_changed, slider_changed)
|
||||
Event.add(defines.events.on_gui_text_changed, text_changed)
|
||||
Event.add(defines.events.on_gui_closed, gui_closed)
|
||||
Event.add(defines.events.on_player_changed_position, on_player_changed_position)
|
||||
|
||||
return Public
|
69
maps/mountain_fortress_v3/loot.lua
Normal file
69
maps/mountain_fortress_v3/loot.lua
Normal file
@ -0,0 +1,69 @@
|
||||
local LootRaffle = require 'functions.loot_raffle'
|
||||
|
||||
local Public = {}
|
||||
local math_random = math.random
|
||||
local math_abs = math.abs
|
||||
local math_floor = math.floor
|
||||
|
||||
local blacklist = {
|
||||
['cargo-wagon'] = true,
|
||||
['locomotive'] = true,
|
||||
['artillery-wagon'] = true,
|
||||
['fluid-wagon'] = true
|
||||
}
|
||||
|
||||
function Public.add(surface, position, chest)
|
||||
local budget = 48 + math_abs(position.y) * 1.75
|
||||
budget = budget * math_random(25, 175) * 0.01
|
||||
|
||||
if math_random(1, 128) == 1 then
|
||||
budget = budget * 4
|
||||
chest = 'crash-site-chest-' .. math_random(1, 2)
|
||||
end
|
||||
|
||||
budget = math_floor(budget) + 1
|
||||
|
||||
local item_stacks = LootRaffle.roll(budget, 8, blacklist)
|
||||
local container = surface.create_entity({name = chest, position = position, force = 'neutral'})
|
||||
for _, item_stack in pairs(item_stacks) do
|
||||
container.insert(item_stack)
|
||||
end
|
||||
container.minable = false
|
||||
|
||||
for _ = 1, 3, 1 do
|
||||
if math_random(1, 8) == 1 then
|
||||
container.insert({name = 'explosives', count = math_random(25, 50)})
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Public.add_rare(surface, position, chest, magic)
|
||||
local budget = magic * 48 + math_abs(position.y) * 1.75
|
||||
budget = budget * math_random(25, 175) * 0.01
|
||||
|
||||
if math_random(1, 128) == 1 then
|
||||
budget = budget * 6
|
||||
chest = 'crash-site-chest-' .. math_random(1, 2)
|
||||
end
|
||||
|
||||
budget = math_floor(budget) + 1
|
||||
|
||||
local item_stacks = LootRaffle.roll(budget, 8, blacklist)
|
||||
local container = surface.create_entity({name = chest, position = position, force = 'neutral'})
|
||||
for _, item_stack in pairs(item_stacks) do
|
||||
container.insert(item_stack)
|
||||
end
|
||||
container.minable = false
|
||||
|
||||
for _ = 1, 3, 1 do
|
||||
if math_random(1, 8) == 1 then
|
||||
container.insert({name = 'explosives', count = math_random(25, 50)})
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Public
|
530
maps/mountain_fortress_v3/main.lua
Normal file
530
maps/mountain_fortress_v3/main.lua
Normal file
@ -0,0 +1,530 @@
|
||||
-- modules
|
||||
require 'maps.mountain_fortress_v3.generate'
|
||||
require 'maps.mountain_fortress_v3.player_list'
|
||||
require 'maps.mountain_fortress_v3.commands'
|
||||
require 'maps.mountain_fortress_v3.flamethrower_nerf'
|
||||
|
||||
require 'modules.dynamic_landfill'
|
||||
require 'modules.shotgun_buff'
|
||||
require 'modules.rocks_heal_over_time'
|
||||
require 'modules.no_deconstruction_of_neutral_entities'
|
||||
require 'modules.rocks_yield_ore_veins'
|
||||
require 'modules.spawners_contain_biters'
|
||||
require 'modules.biters_yield_coins'
|
||||
require 'modules.wave_defense.main'
|
||||
require 'modules.pistol_buffs'
|
||||
require 'modules.mineable_wreckage_yields_scrap'
|
||||
|
||||
local CS = require 'maps.mountain_fortress_v3.surface'
|
||||
local Server = require 'utils.server'
|
||||
local Explosives = require 'modules.explosives'
|
||||
local Entities = require 'maps.mountain_fortress_v3.entities'
|
||||
local update_gui = require 'maps.mountain_fortress_v3.gui'
|
||||
local ICW = require 'maps.mountain_fortress_v3.icw.main'
|
||||
local WD = require 'modules.wave_defense.table'
|
||||
local Map = require 'modules.map_info'
|
||||
local RPG = require 'maps.mountain_fortress_v3.rpg'
|
||||
local Terrain = require 'maps.mountain_fortress_v3.terrain'
|
||||
local Event = require 'utils.event'
|
||||
local WPT = require 'maps.mountain_fortress_v3.table'
|
||||
local Locomotive = require 'maps.mountain_fortress_v3.locomotive'.locomotive_spawn
|
||||
local render_train_hp = require 'maps.mountain_fortress_v3.locomotive'.render_train_hp
|
||||
local Score = require 'comfy_panel.score'
|
||||
local Poll = require 'comfy_panel.poll'
|
||||
local Collapse = require 'modules.collapse'
|
||||
local Difficulty = require 'modules.difficulty_vote'
|
||||
local Task = require 'utils.task'
|
||||
|
||||
local Public = {}
|
||||
|
||||
local starting_items = {['pistol'] = 1, ['firearm-magazine'] = 16, ['rail'] = 16, ['wood'] = 16, ['explosives'] = 32}
|
||||
|
||||
local function disable_tech()
|
||||
game.forces.player.technologies['landfill'].enabled = false
|
||||
game.forces.player.technologies['optics'].researched = true
|
||||
game.forces.player.technologies['railway'].researched = true
|
||||
game.forces.player.technologies['land-mine'].enabled = false
|
||||
end
|
||||
|
||||
local function set_difficulty()
|
||||
local Diff = Difficulty.get()
|
||||
local wave_defense_table = WD.get_table()
|
||||
local player_count = #game.connected_players
|
||||
if not Diff.difficulty_vote_value then
|
||||
Diff.difficulty_vote_value = 0.1
|
||||
end
|
||||
|
||||
wave_defense_table.max_active_biters = 768 + player_count * (90 * Diff.difficulty_vote_value)
|
||||
|
||||
-- threat gain / wave
|
||||
wave_defense_table.threat_gain_multiplier = 1.2 + player_count * Diff.difficulty_vote_value * 0.1
|
||||
|
||||
local amount = player_count * 0.25 + 2
|
||||
amount = math.floor(amount)
|
||||
if amount > 6 then
|
||||
amount = 6
|
||||
end
|
||||
Collapse.set_amount(amount)
|
||||
|
||||
wave_defense_table.wave_interval = 3600 - player_count * 60
|
||||
if wave_defense_table.wave_interval < 1800 then
|
||||
wave_defense_table.wave_interval = 1800
|
||||
end
|
||||
end
|
||||
|
||||
local function render_direction(surface)
|
||||
local counter = WPT.get('soft_reset_counter')
|
||||
if counter then
|
||||
rendering.draw_text {
|
||||
text = 'Welcome to Mountain Fortress v3!\nRun: ' .. counter,
|
||||
surface = surface,
|
||||
target = {-0, 10},
|
||||
color = {r = 0.98, g = 0.66, b = 0.22},
|
||||
scale = 3,
|
||||
font = 'heading-1',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
else
|
||||
rendering.draw_text {
|
||||
text = 'Welcome to Mountain Fortress v3!',
|
||||
surface = surface,
|
||||
target = {-0, 10},
|
||||
color = {r = 0.98, g = 0.66, b = 0.22},
|
||||
scale = 3,
|
||||
font = 'heading-1',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
end
|
||||
|
||||
rendering.draw_text {
|
||||
text = '▼',
|
||||
surface = surface,
|
||||
target = {-0, 20},
|
||||
color = {r = 0.98, g = 0.66, b = 0.22},
|
||||
scale = 3,
|
||||
font = 'heading-1',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
|
||||
rendering.draw_text {
|
||||
text = '▼',
|
||||
surface = surface,
|
||||
target = {-0, 30},
|
||||
color = {r = 0.98, g = 0.66, b = 0.22},
|
||||
scale = 3,
|
||||
font = 'heading-1',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
rendering.draw_text {
|
||||
text = '▼',
|
||||
surface = surface,
|
||||
target = {-0, 40},
|
||||
color = {r = 0.98, g = 0.66, b = 0.22},
|
||||
scale = 3,
|
||||
font = 'heading-1',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
rendering.draw_text {
|
||||
text = '▼',
|
||||
surface = surface,
|
||||
target = {-0, 50},
|
||||
color = {r = 0.98, g = 0.66, b = 0.22},
|
||||
scale = 3,
|
||||
font = 'heading-1',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
rendering.draw_text {
|
||||
text = '▼',
|
||||
surface = surface,
|
||||
target = {-0, 60},
|
||||
color = {r = 0.98, g = 0.66, b = 0.22},
|
||||
scale = 3,
|
||||
font = 'heading-1',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
rendering.draw_text {
|
||||
text = 'Biters will attack this area.',
|
||||
surface = surface,
|
||||
target = {-0, 70},
|
||||
color = {r = 0.98, g = 0.66, b = 0.22},
|
||||
scale = 3,
|
||||
font = 'heading-1',
|
||||
alignment = 'center',
|
||||
scale_with_zoom = false
|
||||
}
|
||||
|
||||
local x_min = -Terrain.level_width / 2
|
||||
local x_max = Terrain.level_width / 2
|
||||
|
||||
surface.create_entity({name = 'electric-beam', position = {x_min, 74}, source = {x_min, 74}, target = {x_max, 74}})
|
||||
surface.create_entity({name = 'electric-beam', position = {x_min, 74}, source = {x_min, 74}, target = {x_max, 74}})
|
||||
end
|
||||
|
||||
function Public.reset_map()
|
||||
local Settings = CS.get()
|
||||
local Diff = Difficulty.get()
|
||||
local this = WPT.get()
|
||||
local wave_defense_table = WD.get_table()
|
||||
local get_score = Score.get_table()
|
||||
|
||||
for _, player in pairs(game.players) do
|
||||
if player.controller_type == defines.controllers.editor then
|
||||
player.toggle_map_editor()
|
||||
end
|
||||
end
|
||||
|
||||
if not this.active_surface_index then
|
||||
this.active_surface_index = Settings.active_surface_index
|
||||
else
|
||||
this.active_surface_index = CS.create_surface()
|
||||
end
|
||||
|
||||
Poll.reset()
|
||||
ICW.reset()
|
||||
game.reset_time_played()
|
||||
WPT.reset_table()
|
||||
|
||||
disable_tech()
|
||||
|
||||
local surface = game.surfaces[this.active_surface_index]
|
||||
surface.min_brightness = 0.5
|
||||
|
||||
Explosives.set_surface_whitelist({[surface.name] = true})
|
||||
|
||||
surface.request_to_generate_chunks({-17, 47}, 1)
|
||||
surface.force_generate_chunk_requests()
|
||||
|
||||
game.forces.player.set_spawn_position({-27, 25}, surface)
|
||||
game.forces.enemy.set_ammo_damage_modifier('bullet', 1)
|
||||
game.forces.enemy.set_turret_attack_modifier('gun-turret', 1)
|
||||
|
||||
global.bad_fire_history = {}
|
||||
global.friendly_fire_history = {}
|
||||
global.landfill_history = {}
|
||||
global.mining_history = {}
|
||||
get_score.score_table = {}
|
||||
Diff.difficulty_poll_closing_timeout = game.tick + 90000
|
||||
Diff.difficulty_player_votes = {}
|
||||
|
||||
Collapse.set_kill_entities(false)
|
||||
Collapse.set_speed(8)
|
||||
Collapse.set_amount(1)
|
||||
Collapse.set_max_line_size(Terrain.level_width)
|
||||
Collapse.set_surface(surface)
|
||||
Collapse.set_position({0, 162})
|
||||
Collapse.set_direction('north')
|
||||
Collapse.start_now(false)
|
||||
|
||||
this.locomotive_health = 10000
|
||||
this.locomotive_max_health = 10000
|
||||
this.cargo_health = 10000
|
||||
this.cargo_max_health = 10000
|
||||
|
||||
Locomotive(surface, {x = -18, y = 25})
|
||||
render_train_hp()
|
||||
render_direction(surface)
|
||||
RPG.rpg_reset_all_players()
|
||||
|
||||
WD.reset_wave_defense()
|
||||
wave_defense_table.surface_index = this.active_surface_index
|
||||
wave_defense_table.target = this.locomotive_cargo
|
||||
wave_defense_table.nest_building_density = 32
|
||||
wave_defense_table.game_lost = false
|
||||
wave_defense_table.spawn_position = {x = 0, y = 100}
|
||||
|
||||
set_difficulty()
|
||||
|
||||
Task.start_queue()
|
||||
Task.set_queue_speed(2)
|
||||
|
||||
this.chunk_load_tick = game.tick + 500
|
||||
end
|
||||
|
||||
local function on_player_changed_position(event)
|
||||
local this = WPT.get()
|
||||
local player = game.players[event.player_index]
|
||||
local map_name = 'mountain_fortress_v3'
|
||||
|
||||
if string.sub(player.surface.name, 0, #map_name) ~= map_name then
|
||||
return
|
||||
end
|
||||
|
||||
local position = player.position
|
||||
local surface = game.surfaces[this.active_surface_index]
|
||||
|
||||
if position.y >= 74 then
|
||||
player.teleport({position.x, position.y - 1}, surface)
|
||||
player.print('Forcefield does not approve.', {r = 0.98, g = 0.66, b = 0.22})
|
||||
if player.character then
|
||||
player.character.health = player.character.health - 5
|
||||
player.character.surface.create_entity({name = 'water-splash', position = position})
|
||||
if player.character.health <= 0 then
|
||||
player.character.die('enemy')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_player_joined_game(event)
|
||||
local this = WPT.get()
|
||||
local surface = game.surfaces[this.active_surface_index]
|
||||
local player = game.players[event.player_index]
|
||||
|
||||
set_difficulty(event)
|
||||
|
||||
if not this.players then
|
||||
this.players = {}
|
||||
end
|
||||
|
||||
if not this.players[player.index] then
|
||||
this.players[player.index] = {
|
||||
first_join = false,
|
||||
data = {}
|
||||
}
|
||||
end
|
||||
|
||||
if not this.players[player.index].first_join then
|
||||
player.print('Greetings, ' .. player.name .. '!', {r = 0.98, g = 0.66, b = 0.22})
|
||||
player.print('Please read the map info.', {r = 0.98, g = 0.66, b = 0.22})
|
||||
this.players[player.index].first_join = true
|
||||
end
|
||||
|
||||
if player.surface.index ~= this.active_surface_index then
|
||||
if not player.character then
|
||||
player.create_character()
|
||||
end
|
||||
player.teleport(
|
||||
surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 3, 0, 5),
|
||||
surface
|
||||
)
|
||||
for item, amount in pairs(starting_items) do
|
||||
player.insert({name = item, count = amount})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_player_left_game()
|
||||
set_difficulty()
|
||||
end
|
||||
|
||||
local function on_pre_player_left_game(event)
|
||||
local this = WPT.get()
|
||||
local player = game.players[event.player_index]
|
||||
if player.controller_type == defines.controllers.editor then
|
||||
player.toggle_map_editor()
|
||||
end
|
||||
if player.character then
|
||||
this.offline_players[#this.offline_players + 1] = {
|
||||
index = event.player_index,
|
||||
name = player.name,
|
||||
tick = game.tick
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local function remove_offline_players()
|
||||
local this = WPT.get()
|
||||
local offline_players = WPT.get('offline_players')
|
||||
local active_surface_index = WPT.get('active_surface_index')
|
||||
local surface = game.surfaces[active_surface_index]
|
||||
local keeper = '[color=blue]Cleaner:[/color]'
|
||||
local player_inv = {}
|
||||
local items = {}
|
||||
if #offline_players > 0 then
|
||||
local later = {}
|
||||
for i = 1, #offline_players, 1 do
|
||||
if
|
||||
offline_players[i] and game.players[offline_players[i].index] and
|
||||
game.players[offline_players[i].index].connected
|
||||
then
|
||||
this.offline_players[i] = nil
|
||||
else
|
||||
if offline_players[i] and offline_players[i].tick < game.tick - 54000 then
|
||||
local name = offline_players[i].name
|
||||
player_inv[1] =
|
||||
game.players[offline_players[i].index].get_inventory(defines.inventory.character_main)
|
||||
player_inv[2] =
|
||||
game.players[offline_players[i].index].get_inventory(defines.inventory.character_armor)
|
||||
player_inv[3] =
|
||||
game.players[offline_players[i].index].get_inventory(defines.inventory.character_guns)
|
||||
player_inv[4] =
|
||||
game.players[offline_players[i].index].get_inventory(defines.inventory.character_ammo)
|
||||
player_inv[5] =
|
||||
game.players[offline_players[i].index].get_inventory(defines.inventory.character_trash)
|
||||
local pos = game.forces.player.get_spawn_position(surface)
|
||||
local e =
|
||||
surface.create_entity(
|
||||
{
|
||||
name = 'character',
|
||||
position = pos,
|
||||
force = 'neutral'
|
||||
}
|
||||
)
|
||||
local inv = e.get_inventory(defines.inventory.character_main)
|
||||
for ii = 1, 5, 1 do
|
||||
if player_inv[ii].valid then
|
||||
for iii = 1, #player_inv[ii], 1 do
|
||||
if player_inv[ii][iii].valid then
|
||||
items[#items + 1] = player_inv[ii][iii]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if #items > 0 then
|
||||
for item = 1, #items, 1 do
|
||||
if items[item].valid then
|
||||
inv.insert(items[item])
|
||||
end
|
||||
end
|
||||
game.print(
|
||||
keeper .. ' ' .. name .. ' has left his goodies! [gps=' .. pos.x .. ',' .. pos.y .. ']',
|
||||
{r = 0.98, g = 0.66, b = 0.22}
|
||||
)
|
||||
|
||||
e.die('neutral')
|
||||
else
|
||||
e.destroy()
|
||||
end
|
||||
|
||||
for ii = 1, 5, 1 do
|
||||
if player_inv[ii].valid then
|
||||
player_inv[ii].clear()
|
||||
end
|
||||
end
|
||||
this.offline_players[i] = nil
|
||||
else
|
||||
later[#later + 1] = offline_players[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
this.offline_players = {}
|
||||
if #later > 0 then
|
||||
for i = 1, #later, 1 do
|
||||
this.offline_players[#offline_players + 1] = later[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function disable_recipes()
|
||||
local force = game.forces.player
|
||||
force.recipes['cargo-wagon'].enabled = false
|
||||
force.recipes['fluid-wagon'].enabled = false
|
||||
force.recipes['artillery-wagon'].enabled = false
|
||||
force.recipes['locomotive'].enabled = false
|
||||
force.recipes['pistol'].enabled = false
|
||||
end
|
||||
|
||||
local function on_research_finished(event)
|
||||
disable_recipes()
|
||||
event.research.force.character_inventory_slots_bonus = game.forces.player.mining_drill_productivity_bonus * 50 -- +5 Slots / level
|
||||
local mining_speed_bonus = game.forces.player.mining_drill_productivity_bonus * 5 -- +50% speed / level
|
||||
if event.research.force.technologies['steel-axe'].researched then
|
||||
mining_speed_bonus = mining_speed_bonus + 0.5
|
||||
end -- +50% speed for steel-axe research
|
||||
event.research.force.manual_mining_speed_modifier = mining_speed_bonus
|
||||
end
|
||||
|
||||
local function is_locomotive_valid()
|
||||
local this = WPT.get()
|
||||
if not this.locomotive.valid then
|
||||
Entities.loco_died()
|
||||
end
|
||||
end
|
||||
|
||||
local function has_the_game_ended()
|
||||
local this = WPT.get()
|
||||
if this.game_reset_tick then
|
||||
if this.game_reset_tick < game.tick then
|
||||
if not this.disable_reset then
|
||||
this.game_reset_tick = nil
|
||||
Public.reset_map()
|
||||
else
|
||||
if not this.reset_the_game then
|
||||
game.print('Auto reset is disabled. Server is shutting down!', {r = 0.22, g = 0.88, b = 0.22})
|
||||
local message = 'Auto reset is disabled. Server is shutting down!'
|
||||
Server.to_discord_bold(table.concat {'*** ', message, ' ***'})
|
||||
Server.stop_scenario()
|
||||
this.reset_the_game = true
|
||||
end
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local function chunk_load()
|
||||
local this = WPT.get()
|
||||
if this.chunk_load_tick then
|
||||
if this.chunk_load_tick < game.tick then
|
||||
this.chunk_load_tick = nil
|
||||
Task.set_queue_speed(0.8)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local on_tick = function()
|
||||
local active_surface_index = WPT.get('active_surface_index')
|
||||
local surface = game.surfaces[active_surface_index]
|
||||
local wave_defense_table = WD.get_table()
|
||||
|
||||
if game.tick % 30 == 0 then
|
||||
for _, player in pairs(game.connected_players) do
|
||||
update_gui(player)
|
||||
end
|
||||
|
||||
if game.tick % 1800 == 0 then
|
||||
local collapse_pos = Collapse.get_position()
|
||||
local position = surface.find_non_colliding_position('stone-furnace', collapse_pos, 128, 1)
|
||||
if position then
|
||||
wave_defense_table.spawn_position = position
|
||||
end
|
||||
remove_offline_players()
|
||||
Entities.set_scores()
|
||||
end
|
||||
is_locomotive_valid()
|
||||
has_the_game_ended()
|
||||
chunk_load()
|
||||
end
|
||||
end
|
||||
|
||||
local on_init = function()
|
||||
local this = WPT.get()
|
||||
Public.reset_map()
|
||||
|
||||
global.custom_highscore.description = 'Wagon distance reached:'
|
||||
|
||||
this.rocks_yield_ore_maximum_amount = 500
|
||||
this.type_modifier = 1
|
||||
this.rocks_yield_ore_base_amount = 50
|
||||
this.rocks_yield_ore_distance_modifier = 0.025
|
||||
|
||||
local T = Map.Pop_info()
|
||||
T.localised_category = 'mountain_fortress'
|
||||
T.main_caption_color = {r = 150, g = 150, b = 0}
|
||||
T.sub_caption_color = {r = 0, g = 150, b = 0}
|
||||
|
||||
Explosives.set_destructible_tile('out-of-map', 1500)
|
||||
Explosives.set_destructible_tile('water', 1000)
|
||||
Explosives.set_destructible_tile('water-green', 1000)
|
||||
Explosives.set_destructible_tile('deepwater-green', 1000)
|
||||
Explosives.set_destructible_tile('deepwater', 1000)
|
||||
Explosives.set_destructible_tile('water-shallow', 1000)
|
||||
end
|
||||
|
||||
Event.on_nth_tick(10, on_tick)
|
||||
Event.on_init(on_init)
|
||||
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
||||
Event.add(defines.events.on_player_left_game, on_player_left_game)
|
||||
Event.add(defines.events.on_player_changed_position, on_player_changed_position)
|
||||
Event.add(defines.events.on_research_finished, on_research_finished)
|
||||
Event.add(defines.events.on_pre_player_left_game, on_pre_player_left_game)
|
||||
|
||||
return Public
|
190
maps/mountain_fortress_v3/mining.lua
Normal file
190
maps/mountain_fortress_v3/mining.lua
Normal file
@ -0,0 +1,190 @@
|
||||
local WPT = require 'maps.mountain_fortress_v3.table'
|
||||
|
||||
local Public = {}
|
||||
|
||||
local max_spill = 60
|
||||
local math_random = math.random
|
||||
local math_floor = math.floor
|
||||
local math_sqrt = math.sqrt
|
||||
|
||||
local valid_rocks = {
|
||||
['sand-rock-big'] = true,
|
||||
['rock-big'] = true,
|
||||
['rock-huge'] = true
|
||||
}
|
||||
|
||||
local rock_yield = {
|
||||
['rock-big'] = 1,
|
||||
['rock-huge'] = 2,
|
||||
['sand-rock-big'] = 1
|
||||
}
|
||||
|
||||
local function create_particles(surface, name, position, amount, cause_position)
|
||||
local d1 = (-100 + math_random(0, 200)) * 0.0004
|
||||
local d2 = (-100 + math_random(0, 200)) * 0.0004
|
||||
|
||||
if cause_position then
|
||||
d1 = (cause_position.x - position.x) * 0.025
|
||||
d2 = (cause_position.y - position.y) * 0.025
|
||||
end
|
||||
|
||||
for i = 1, amount, 1 do
|
||||
local m = math_random(4, 10)
|
||||
local m2 = m * 0.005
|
||||
|
||||
surface.create_particle(
|
||||
{
|
||||
name = name,
|
||||
position = position,
|
||||
frame_speed = 1,
|
||||
vertical_speed = 0.130,
|
||||
height = 0,
|
||||
movement = {
|
||||
(m2 - (math_random(0, m) * 0.01)) + d1,
|
||||
(m2 - (math_random(0, m) * 0.01)) + d2
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
local function mining_chances_ores()
|
||||
local data = {
|
||||
{name = 'iron-ore', chance = 545},
|
||||
{name = 'copper-ore', chance = 545},
|
||||
{name = 'coal', chance = 545},
|
||||
{name = 'stone', chance = 545},
|
||||
{name = 'uranium-ore', chance = 50}
|
||||
}
|
||||
return data
|
||||
end
|
||||
|
||||
local harvest_raffle_ores = {}
|
||||
for _, t in pairs(mining_chances_ores()) do
|
||||
for _ = 1, t.chance, 1 do
|
||||
table.insert(harvest_raffle_ores, t.name)
|
||||
end
|
||||
end
|
||||
|
||||
local size_of_ore_raffle = #harvest_raffle_ores
|
||||
|
||||
local function get_amount(data)
|
||||
local entity = data.entity
|
||||
local this = data.this
|
||||
local distance_to_center = math_floor(math_sqrt(entity.position.x ^ 2 + entity.position.y ^ 2))
|
||||
local type_modifier
|
||||
local amount
|
||||
local second_amount
|
||||
|
||||
local distance_modifier = 0.25
|
||||
local base_amount = 25
|
||||
local second_base_amount = 10
|
||||
local maximum_amount = 100
|
||||
if this.type_modifier then
|
||||
type_modifier = this.type_modifier
|
||||
end
|
||||
if this.rocks_yield_ore_distance_modifier then
|
||||
distance_modifier = this.rocks_yield_ore_distance_modifier
|
||||
end
|
||||
|
||||
if this.rocks_yield_ore_base_amount then
|
||||
base_amount = this.rocks_yield_ore_base_amount
|
||||
end
|
||||
if this.rocks_yield_ore_maximum_amount then
|
||||
maximum_amount = this.rocks_yield_ore_maximum_amount
|
||||
end
|
||||
|
||||
type_modifier = rock_yield[entity.name] or type_modifier
|
||||
|
||||
amount = base_amount + (distance_to_center * distance_modifier)
|
||||
second_amount = math_floor((second_base_amount + (distance_to_center * distance_modifier)) / 3)
|
||||
if amount > maximum_amount then
|
||||
amount = maximum_amount
|
||||
end
|
||||
if second_amount > maximum_amount then
|
||||
second_amount = maximum_amount
|
||||
end
|
||||
|
||||
local m = (70 + math_random(0, 60)) * 0.01
|
||||
|
||||
amount = math_floor(amount * type_modifier * m * 0.7)
|
||||
|
||||
return amount, second_amount
|
||||
end
|
||||
|
||||
function Public.entity_died_randomness(data)
|
||||
local entity = data.entity
|
||||
local surface = data.surface
|
||||
local harvest
|
||||
|
||||
harvest = harvest_raffle_ores[math.random(1, size_of_ore_raffle)]
|
||||
|
||||
local position = {x = entity.position.x, y = entity.position.y}
|
||||
|
||||
surface.spill_item_stack(position, {name = harvest, count = math_random(1, 5)}, true)
|
||||
|
||||
create_particles(surface, 'shell-particle', position, 64, {x = entity.position.x, y = entity.position.y})
|
||||
end
|
||||
|
||||
local function randomness(data)
|
||||
local entity = data.entity
|
||||
local player = data.player
|
||||
local harvest
|
||||
local harvest_amount
|
||||
|
||||
harvest = harvest_raffle_ores[math.random(1, size_of_ore_raffle)]
|
||||
harvest_amount = get_amount(data)
|
||||
|
||||
local position = {x = entity.position.x, y = entity.position.y}
|
||||
|
||||
player.surface.create_entity(
|
||||
{
|
||||
name = 'flying-text',
|
||||
position = position,
|
||||
text = '+' .. harvest_amount .. ' [img=item/' .. harvest .. ']',
|
||||
color = {r = 0, g = 127, b = 33}
|
||||
}
|
||||
)
|
||||
|
||||
if harvest_amount > max_spill then
|
||||
player.surface.spill_item_stack(position, {name = harvest, count = max_spill}, true)
|
||||
harvest_amount = harvest_amount - max_spill
|
||||
local inserted_count = player.insert({name = harvest, count = harvest_amount})
|
||||
harvest_amount = harvest_amount - inserted_count
|
||||
if harvest_amount > 0 then
|
||||
player.surface.spill_item_stack(position, {name = harvest, count = harvest_amount}, true)
|
||||
end
|
||||
else
|
||||
player.surface.spill_item_stack(position, {name = harvest, count = harvest_amount}, true)
|
||||
end
|
||||
|
||||
create_particles(player.surface, 'shell-particle', position, 64, {x = player.position.x, y = player.position.y})
|
||||
end
|
||||
|
||||
function Public.on_player_mined_entity(event)
|
||||
local entity = event.entity
|
||||
if not entity.valid then
|
||||
return
|
||||
end
|
||||
if not valid_rocks[entity.name] then
|
||||
return
|
||||
end
|
||||
|
||||
local player = game.players[event.player_index]
|
||||
local this = WPT.get()
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
|
||||
event.buffer.clear()
|
||||
|
||||
local data = {
|
||||
this = this,
|
||||
entity = entity,
|
||||
player = player
|
||||
}
|
||||
|
||||
randomness(data)
|
||||
end
|
||||
|
||||
return Public
|
661
maps/mountain_fortress_v3/player_list.lua
Normal file
661
maps/mountain_fortress_v3/player_list.lua
Normal file
@ -0,0 +1,661 @@
|
||||
local Event = require 'utils.event'
|
||||
local play_time = require 'utils.session_data'
|
||||
local Tabs = require 'comfy_panel.main'
|
||||
local RPG = require 'maps.mountain_fortress_v3.rpg'
|
||||
|
||||
local symbol_asc = '▲'
|
||||
local symbol_desc = '▼'
|
||||
|
||||
local pokemessages = {
|
||||
'a stick',
|
||||
'a leaf',
|
||||
'a moldy carrot',
|
||||
'a crispy slice of bacon',
|
||||
'a french fry',
|
||||
'a realistic toygun',
|
||||
'a broomstick',
|
||||
'a thirteen inch iron stick',
|
||||
'a mechanical keyboard',
|
||||
'a fly fishing cane',
|
||||
'a selfie stick',
|
||||
'an oversized fidget spinner',
|
||||
'a thumb extender',
|
||||
'a dirty straw',
|
||||
'a green bean',
|
||||
'a banana',
|
||||
'an umbrella',
|
||||
"grandpa's walking stick",
|
||||
'live firework',
|
||||
'a toilet brush',
|
||||
'a fake hand',
|
||||
'an undercooked hotdog',
|
||||
"a slice of yesterday's microwaved pizza",
|
||||
'bubblegum',
|
||||
'a biter leg',
|
||||
"grandma's toothbrush",
|
||||
'charred octopus',
|
||||
'a dollhouse bathtub',
|
||||
'a length of copper wire',
|
||||
'a decommissioned nuke',
|
||||
'a smelly trout',
|
||||
'an unopened can of deodorant',
|
||||
'a stone brick',
|
||||
'a half full barrel of lube',
|
||||
'a half empty barrel of lube',
|
||||
'an unexploded cannon shell',
|
||||
'a blasting programmable speaker',
|
||||
'a not so straight rail',
|
||||
'a mismatched pipe to ground',
|
||||
'a surplus box of landmines',
|
||||
'decommissioned yellow rounds',
|
||||
'an oily pumpjack shaft',
|
||||
'a melted plastic bar in the shape of the virgin mary',
|
||||
'a bottle of watermelon vitamin water',
|
||||
'a slice of watermelon',
|
||||
'a stegosaurus tibia',
|
||||
"a basking musician's clarinet",
|
||||
'a twig',
|
||||
'an undisclosed pokey item',
|
||||
'a childhood trophy everyone else got',
|
||||
'a dead starfish',
|
||||
'a titanium toothpick',
|
||||
'a nail file',
|
||||
'a stamp collection',
|
||||
'a bucket of lego',
|
||||
'a rolled up carpet',
|
||||
'a rolled up WELCOME doormat',
|
||||
"Bobby's favorite bone",
|
||||
'an empty bottle of cheap vodka',
|
||||
'a tattooing needle',
|
||||
'a peeled cucumber',
|
||||
'a stack of cotton candy',
|
||||
'a signed baseball bat',
|
||||
'that 5 dollar bill grandma sent for christmas',
|
||||
'a stack of overdue phone bills',
|
||||
"the 'relax' section of the white pages",
|
||||
'a bag of gym clothes which never made it to the washing machine',
|
||||
'a handful of peanut butter',
|
||||
"a pheasant's feather",
|
||||
'a rusty pickaxe',
|
||||
'a diamond sword',
|
||||
'the bill of rights of a banana republic',
|
||||
"one of those giant airport Toblerone's",
|
||||
'a long handed inserter',
|
||||
'a wiimote',
|
||||
'an easter chocolate rabbit',
|
||||
'a ball of yarn the cat threw up',
|
||||
'a slightly expired but perfectly edible cheese sandwich',
|
||||
'conclusive proof of lizard people existence',
|
||||
'a pen drive full of high res wallpapers',
|
||||
'a pet hamster',
|
||||
'an oversized goldfish',
|
||||
'a one foot extension cord',
|
||||
"a CD from Walmart's 1 dollar bucket",
|
||||
'a magic wand',
|
||||
'a list of disappointed people who believed in you',
|
||||
'murder exhibit no. 3',
|
||||
"a paperback copy of 'Great Expectations'",
|
||||
'a baby biter',
|
||||
'a little biter fang',
|
||||
'the latest diet fad',
|
||||
'a belt that no longer fits you',
|
||||
'an abandoned pet rock',
|
||||
'a lava lamp',
|
||||
'some spirit herbs',
|
||||
'a box of fish sticks found at the back of the freezer',
|
||||
'a bowl of tofu rice',
|
||||
'a bowl of ramen noodles',
|
||||
'a live lobster!',
|
||||
'a miniature golf cart',
|
||||
'dunce cap',
|
||||
'a fully furnished x-mas tree',
|
||||
'an orphaned power pole',
|
||||
'an horphaned power pole',
|
||||
'an box of overpriced girl scout cookies',
|
||||
'the cheapest item from the yard sale',
|
||||
'a Sharpie',
|
||||
'a glowstick',
|
||||
'a thick unibrow hair',
|
||||
'a very detailed map of Kazakhstan',
|
||||
'the official Factorio installation DVD',
|
||||
'a Liberal Arts degree',
|
||||
'a pitcher of Kool-Aid',
|
||||
'a 1/4 pound vegan burrito',
|
||||
'a bottle of expensive wine',
|
||||
'a hamster sized gravestone',
|
||||
'a counterfeit Cuban cigar',
|
||||
'an old Nokia phone',
|
||||
'a huge inferiority complex',
|
||||
'a dead real state agent',
|
||||
'a deck of tarot cards',
|
||||
'unreleased Wikileaks documents',
|
||||
'a mean-looking garden dwarf',
|
||||
'the actual mythological OBESE cat',
|
||||
'a telescope used to spy on the MILF next door',
|
||||
'a fancy candelabra',
|
||||
'the comic version of the Kama Sutra',
|
||||
"an inflatable 'Netflix & chill' doll",
|
||||
'whatever it is redlabel gets high on',
|
||||
"Obama's birth certificate",
|
||||
'a deck of Cards Against Humanity',
|
||||
'a copy of META MEME HUMOR for Dummies',
|
||||
'an abandoned, not-so-young-anymore puppy',
|
||||
'one of those useless items advertised on TV',
|
||||
'a genetic blueprint of a Japanese teen idol'
|
||||
}
|
||||
|
||||
local function get_formatted_playtime(x)
|
||||
if x < 5184000 then
|
||||
local y = x / 216000
|
||||
y = tostring(y)
|
||||
local h = ''
|
||||
for i = 1, 10, 1 do
|
||||
local z = string.sub(y, i, i)
|
||||
|
||||
if z == '.' then
|
||||
break
|
||||
else
|
||||
h = h .. z
|
||||
end
|
||||
end
|
||||
|
||||
local m = x % 216000
|
||||
m = m / 3600
|
||||
m = math.floor(m)
|
||||
m = tostring(m)
|
||||
|
||||
if h == '0' then
|
||||
local str = m .. ' minutes'
|
||||
return str
|
||||
else
|
||||
local str = h .. ' hours '
|
||||
str = str .. m
|
||||
str = str .. ' minutes'
|
||||
return str
|
||||
end
|
||||
else
|
||||
local y = x / 5184000
|
||||
y = tostring(y)
|
||||
local h = ''
|
||||
for i = 1, 10, 1 do
|
||||
local z = string.sub(y, i, i)
|
||||
|
||||
if z == '.' then
|
||||
break
|
||||
else
|
||||
h = h .. z
|
||||
end
|
||||
end
|
||||
|
||||
local m = x % 5184000
|
||||
m = m / 216000
|
||||
m = math.floor(m)
|
||||
m = tostring(m)
|
||||
|
||||
if h == '0' then
|
||||
local str = m .. ' days'
|
||||
return str
|
||||
else
|
||||
local str = h .. ' days '
|
||||
str = str .. m
|
||||
str = str .. ' hours'
|
||||
return str
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function get_rank(player)
|
||||
local play_table = play_time.get_session_table()
|
||||
local t = 0
|
||||
if play_table then
|
||||
if play_table[player.name] then
|
||||
t = play_table[player.name]
|
||||
end
|
||||
end
|
||||
|
||||
local m = (player.online_time + t) / 3600
|
||||
|
||||
local ranks = {
|
||||
'item/burner-mining-drill',
|
||||
'item/burner-inserter',
|
||||
'item/stone-furnace',
|
||||
'item/light-armor',
|
||||
'item/steam-engine',
|
||||
'item/inserter',
|
||||
'item/transport-belt',
|
||||
'item/underground-belt',
|
||||
'item/splitter',
|
||||
'item/assembling-machine-1',
|
||||
'item/long-handed-inserter',
|
||||
'item/electronic-circuit',
|
||||
'item/electric-mining-drill',
|
||||
'item/dummy-steel-axe',
|
||||
'item/heavy-armor',
|
||||
'item/steel-furnace',
|
||||
'item/gun-turret',
|
||||
'item/fast-transport-belt',
|
||||
'item/fast-underground-belt',
|
||||
'item/fast-splitter',
|
||||
'item/assembling-machine-2',
|
||||
'item/fast-inserter',
|
||||
'item/radar',
|
||||
'item/filter-inserter',
|
||||
'item/defender-capsule',
|
||||
'item/pumpjack',
|
||||
'item/chemical-plant',
|
||||
'item/solar-panel',
|
||||
'item/advanced-circuit',
|
||||
'item/modular-armor',
|
||||
'item/accumulator',
|
||||
'item/construction-robot',
|
||||
'item/distractor-capsule',
|
||||
'item/stack-inserter',
|
||||
'item/electric-furnace',
|
||||
'item/express-transport-belt',
|
||||
'item/express-underground-belt',
|
||||
'item/express-splitter',
|
||||
'item/assembling-machine-3',
|
||||
'item/processing-unit',
|
||||
'item/power-armor',
|
||||
'item/logistic-robot',
|
||||
'item/laser-turret',
|
||||
'item/stack-filter-inserter',
|
||||
'item/destroyer-capsule',
|
||||
'item/power-armor-mk2',
|
||||
'item/flamethrower-turret',
|
||||
'item/beacon',
|
||||
'item/steam-turbine',
|
||||
'item/centrifuge',
|
||||
'item/nuclear-reactor'
|
||||
}
|
||||
|
||||
--52 ranks
|
||||
|
||||
local time_needed = 240 -- in minutes between rank upgrades
|
||||
m = m / time_needed
|
||||
m = math.floor(m)
|
||||
m = m + 1
|
||||
|
||||
if m > #ranks then
|
||||
m = #ranks
|
||||
end
|
||||
|
||||
return ranks[m]
|
||||
end
|
||||
|
||||
local comparators = {
|
||||
['pokes_asc'] = function(a, b)
|
||||
return a.pokes > b.pokes
|
||||
end,
|
||||
['pokes_desc'] = function(a, b)
|
||||
return a.pokes < b.pokes
|
||||
end,
|
||||
['total_time_played_asc'] = function(a, b)
|
||||
return a.total_played_ticks < b.total_played_ticks
|
||||
end,
|
||||
['total_time_played_desc'] = function(a, b)
|
||||
return a.total_played_ticks > b.total_played_ticks
|
||||
end,
|
||||
['time_played_asc'] = function(a, b)
|
||||
return a.played_ticks < b.played_ticks
|
||||
end,
|
||||
['time_played_desc'] = function(a, b)
|
||||
return a.played_ticks > b.played_ticks
|
||||
end,
|
||||
['rpg_asc'] = function(a, b)
|
||||
return a.rpg_level < b.rpg_level
|
||||
end,
|
||||
['rpg_desc'] = function(a, b)
|
||||
return a.rpg_level > b.rpg_level
|
||||
end,
|
||||
['name_asc'] = function(a, b)
|
||||
return a.name:lower() < b.name:lower()
|
||||
end,
|
||||
['name_desc'] = function(a, b)
|
||||
return a.name:lower() > b.name:lower()
|
||||
end
|
||||
}
|
||||
|
||||
local function get_comparator(sort_by)
|
||||
return comparators[sort_by]
|
||||
end
|
||||
|
||||
local function get_sorted_list(sort_by)
|
||||
local play_table = play_time.get_session_table()
|
||||
local rpg_t = RPG.get_table()
|
||||
local player_list = {}
|
||||
for i, player in pairs(game.connected_players) do
|
||||
player_list[i] = {}
|
||||
player_list[i].rank = get_rank(player)
|
||||
player_list[i].name = player.name
|
||||
|
||||
local t = 0
|
||||
if play_table[player.name] then
|
||||
t = play_table[player.name]
|
||||
end
|
||||
|
||||
player_list[i].rpg_level = rpg_t[player.index].level
|
||||
|
||||
player_list[i].total_played_time = get_formatted_playtime(t + player.online_time)
|
||||
player_list[i].total_played_ticks = t + player.online_time
|
||||
|
||||
player_list[i].played_time = get_formatted_playtime(player.online_time)
|
||||
player_list[i].played_ticks = player.online_time
|
||||
|
||||
player_list[i].pokes = global.player_list.pokes[player.index]
|
||||
player_list[i].player_index = player.index
|
||||
end
|
||||
|
||||
local comparator = get_comparator(sort_by)
|
||||
table.sort(player_list, comparator)
|
||||
|
||||
return player_list
|
||||
end
|
||||
|
||||
local function player_list_show(player, frame, sort_by)
|
||||
local label
|
||||
|
||||
-- Frame management
|
||||
frame.clear()
|
||||
frame.style.padding = 8
|
||||
|
||||
-- Header management
|
||||
local t = frame.add {type = 'table', name = 'player_list_panel_header_table', column_count = 6}
|
||||
local column_widths = {tonumber(60), tonumber(150), tonumber(125), tonumber(150), tonumber(150), tonumber(100)}
|
||||
for _, w in ipairs(column_widths) do
|
||||
label = t.add {type = 'label', caption = ''}
|
||||
label.style.minimal_width = w
|
||||
label.style.maximal_width = w
|
||||
end
|
||||
|
||||
local headers = {
|
||||
[1] = '[color=0.1,0.7,0.1]' .. -- green
|
||||
tostring(#game.connected_players) .. '[/color]',
|
||||
[2] = 'Online' ..
|
||||
' / ' ..
|
||||
'[color=0.7,0.1,0.1]' .. -- red
|
||||
tostring(#game.players - #game.connected_players) .. '[/color]' .. ' Offline',
|
||||
[3] = 'RPG level',
|
||||
[4] = 'Total Time',
|
||||
[5] = 'Current Time',
|
||||
[6] = 'Poke'
|
||||
}
|
||||
local header_modifier = {
|
||||
['name_asc'] = function(h)
|
||||
h[2] = symbol_asc .. h[2]
|
||||
end,
|
||||
['name_desc'] = function(h)
|
||||
h[2] = symbol_desc .. h[2]
|
||||
end,
|
||||
['rpg_asc'] = function(h)
|
||||
h[3] = symbol_asc .. h[3]
|
||||
end,
|
||||
['rpg_desc'] = function(h)
|
||||
h[3] = symbol_desc .. h[3]
|
||||
end,
|
||||
['total_time_played_asc'] = function(h)
|
||||
h[4] = symbol_asc .. h[4]
|
||||
end,
|
||||
['total_time_played_desc'] = function(h)
|
||||
h[4] = symbol_desc .. h[4]
|
||||
end,
|
||||
['time_played_asc'] = function(h)
|
||||
h[5] = symbol_asc .. h[5]
|
||||
end,
|
||||
['time_played_desc'] = function(h)
|
||||
h[5] = symbol_desc .. h[5]
|
||||
end,
|
||||
['pokes_asc'] = function(h)
|
||||
h[6] = symbol_asc .. h[6]
|
||||
end,
|
||||
['pokes_desc'] = function(h)
|
||||
h[6] = symbol_desc .. h[6]
|
||||
end
|
||||
}
|
||||
|
||||
if sort_by then
|
||||
global.player_list.sorting_method[player.index] = sort_by
|
||||
else
|
||||
sort_by = global.player_list.sorting_method[player.index]
|
||||
end
|
||||
|
||||
header_modifier[sort_by](headers)
|
||||
|
||||
for k, v in ipairs(headers) do
|
||||
label =
|
||||
t.add {
|
||||
type = 'label',
|
||||
name = 'player_list_panel_header_' .. k,
|
||||
caption = v
|
||||
}
|
||||
label.style.font = 'default-bold'
|
||||
label.style.font_color = {r = 0.98, g = 0.66, b = 0.22}
|
||||
end
|
||||
|
||||
-- special style on first header
|
||||
label = t['player_list_panel_header_1']
|
||||
label.style.minimal_width = 36
|
||||
label.style.maximal_width = 36
|
||||
label.style.horizontal_align = 'right'
|
||||
|
||||
-- List management
|
||||
local player_list_panel_table =
|
||||
frame.add {
|
||||
type = 'scroll-pane',
|
||||
name = 'scroll_pane',
|
||||
direction = 'vertical',
|
||||
horizontal_scroll_policy = 'never',
|
||||
vertical_scroll_policy = 'auto'
|
||||
}
|
||||
player_list_panel_table.style.maximal_height = 530
|
||||
|
||||
player_list_panel_table =
|
||||
player_list_panel_table.add {type = 'table', name = 'player_list_panel_table', column_count = 6}
|
||||
|
||||
local player_list = get_sorted_list(sort_by)
|
||||
for i = 1, #player_list, 1 do
|
||||
-- Icon
|
||||
local sprite =
|
||||
player_list_panel_table.add {
|
||||
type = 'sprite',
|
||||
name = 'player_rank_sprite_' .. i,
|
||||
sprite = player_list[i].rank
|
||||
}
|
||||
sprite.style.minimal_width = column_widths[1]
|
||||
sprite.style.maximal_width = column_widths[1]
|
||||
|
||||
-- Name
|
||||
label =
|
||||
player_list_panel_table.add {
|
||||
type = 'label',
|
||||
name = 'player_list_panel_player_names_' .. i,
|
||||
caption = player_list[i].name
|
||||
}
|
||||
label.style.font = 'default'
|
||||
label.style.font_color = {
|
||||
r = .4 + game.players[player_list[i].player_index].color.r * 0.6,
|
||||
g = .4 + game.players[player_list[i].player_index].color.g * 0.6,
|
||||
b = .4 + game.players[player_list[i].player_index].color.b * 0.6
|
||||
}
|
||||
label.style.minimal_width = column_widths[2]
|
||||
label.style.maximal_width = column_widths[2]
|
||||
|
||||
-- RPG level
|
||||
label =
|
||||
player_list_panel_table.add {
|
||||
type = 'label',
|
||||
name = 'player_list_panel_RPG_level_' .. i,
|
||||
caption = player_list[i].rpg_level
|
||||
}
|
||||
label.style.minimal_width = column_widths[3]
|
||||
label.style.maximal_width = column_widths[3]
|
||||
|
||||
-- Total time
|
||||
label =
|
||||
player_list_panel_table.add {
|
||||
type = 'label',
|
||||
name = 'player_list_panel_player_total_time_played_' .. i,
|
||||
caption = player_list[i].total_played_time
|
||||
}
|
||||
label.style.minimal_width = column_widths[4]
|
||||
label.style.maximal_width = column_widths[4]
|
||||
|
||||
-- Current time
|
||||
label =
|
||||
player_list_panel_table.add {
|
||||
type = 'label',
|
||||
name = 'player_list_panel_player_time_played_' .. i,
|
||||
caption = player_list[i].played_time
|
||||
}
|
||||
label.style.minimal_width = column_widths[5]
|
||||
label.style.maximal_width = column_widths[5]
|
||||
|
||||
-- Poke
|
||||
local flow = player_list_panel_table.add {type = 'flow', name = 'button_flow_' .. i, direction = 'horizontal'}
|
||||
flow.add {type = 'label', name = 'button_spacer_' .. i, caption = ''}
|
||||
local button =
|
||||
flow.add {type = 'button', name = 'poke_player_' .. player_list[i].name, caption = player_list[i].pokes}
|
||||
button.style.font = 'default'
|
||||
label.style.font_color = {r = 0.83, g = 0.83, b = 0.83}
|
||||
button.style.minimal_height = 30
|
||||
button.style.minimal_width = 30
|
||||
button.style.maximal_height = 30
|
||||
button.style.maximal_width = 30
|
||||
button.style.top_padding = 0
|
||||
button.style.left_padding = 0
|
||||
button.style.right_padding = 0
|
||||
button.style.bottom_padding = 0
|
||||
end
|
||||
end
|
||||
|
||||
local function on_gui_click(event)
|
||||
if not event then
|
||||
return
|
||||
end
|
||||
if not event.element then
|
||||
return
|
||||
end
|
||||
if not event.element.valid then
|
||||
return
|
||||
end
|
||||
if not event.element.name then
|
||||
return
|
||||
end
|
||||
local player = game.players[event.element.player_index]
|
||||
|
||||
local frame = Tabs.comfy_panel_get_active_frame(player)
|
||||
if not frame then
|
||||
return
|
||||
end
|
||||
if frame.name ~= 'Players' then
|
||||
return
|
||||
end
|
||||
|
||||
local name = event.element.name
|
||||
local actions = {
|
||||
['player_list_panel_header_2'] = function()
|
||||
if string.find(event.element.caption, symbol_desc) then
|
||||
player_list_show(player, frame, 'name_asc')
|
||||
else
|
||||
player_list_show(player, frame, 'name_desc')
|
||||
end
|
||||
end,
|
||||
['player_list_panel_header_3'] = function()
|
||||
if string.find(event.element.caption, symbol_desc) then
|
||||
player_list_show(player, frame, 'rpg_asc')
|
||||
else
|
||||
player_list_show(player, frame, 'rpg_desc')
|
||||
end
|
||||
end,
|
||||
['player_list_panel_header_4'] = function()
|
||||
if string.find(event.element.caption, symbol_desc) then
|
||||
player_list_show(player, frame, 'total_time_played_asc')
|
||||
else
|
||||
player_list_show(player, frame, 'total_time_played_desc')
|
||||
end
|
||||
end,
|
||||
['player_list_panel_header_5'] = function()
|
||||
if string.find(event.element.caption, symbol_desc) then
|
||||
player_list_show(player, frame, 'time_played_asc')
|
||||
else
|
||||
player_list_show(player, frame, 'time_played_desc')
|
||||
end
|
||||
end,
|
||||
['player_list_panel_header_6'] = function()
|
||||
if string.find(event.element.caption, symbol_desc) then
|
||||
player_list_show(player, frame, 'pokes_asc')
|
||||
else
|
||||
player_list_show(player, frame, 'pokes_desc')
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
if actions[name] then
|
||||
actions[name]()
|
||||
return
|
||||
end
|
||||
|
||||
if not event.element.valid then
|
||||
return
|
||||
end
|
||||
--Poke other players
|
||||
if string.sub(event.element.name, 1, 11) == 'poke_player' then
|
||||
local poked_player = string.sub(event.element.name, 13, string.len(event.element.name))
|
||||
if player.name == poked_player then
|
||||
return
|
||||
end
|
||||
if global.player_list.last_poke_tick[event.element.player_index] + 300 < game.tick then
|
||||
local str = '>> '
|
||||
str = str .. player.name
|
||||
str = str .. ' has poked '
|
||||
str = str .. poked_player
|
||||
str = str .. ' with '
|
||||
local z = math.random(1, #pokemessages)
|
||||
str = str .. pokemessages[z]
|
||||
str = str .. ' <<'
|
||||
game.print(str)
|
||||
global.player_list.last_poke_tick[event.element.player_index] = game.tick
|
||||
local p = game.players[poked_player]
|
||||
global.player_list.pokes[p.index] = global.player_list.pokes[p.index] + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function refresh()
|
||||
for _, player in pairs(game.connected_players) do
|
||||
local frame = Tabs.comfy_panel_get_active_frame(player)
|
||||
if frame then
|
||||
if frame.name ~= 'Players' then
|
||||
return
|
||||
end
|
||||
player_list_show(player, frame, global.player_list.sorting_method[player.index])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_player_joined_game(event)
|
||||
if not global.player_list.last_poke_tick[event.player_index] then
|
||||
global.player_list.pokes[event.player_index] = 0
|
||||
global.player_list.last_poke_tick[event.player_index] = 0
|
||||
global.player_list.sorting_method[event.player_index] = 'total_time_played_desc'
|
||||
end
|
||||
refresh()
|
||||
end
|
||||
|
||||
local function on_player_left_game()
|
||||
refresh()
|
||||
end
|
||||
|
||||
local on_init = function()
|
||||
global.player_list = {}
|
||||
global.player_list.last_poke_tick = {}
|
||||
global.player_list.pokes = {}
|
||||
global.player_list.sorting_method = {}
|
||||
end
|
||||
|
||||
comfy_panel_tabs['Players'] = {gui = player_list_show, admin = false}
|
||||
|
||||
Event.on_init(on_init)
|
||||
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
||||
Event.add(defines.events.on_player_left_game, on_player_left_game)
|
||||
Event.add(defines.events.on_gui_click, on_gui_click)
|
67
maps/mountain_fortress_v3/power.lua
Normal file
67
maps/mountain_fortress_v3/power.lua
Normal file
@ -0,0 +1,67 @@
|
||||
local Event = require 'utils.event'
|
||||
local WPT = require 'maps.mountain_fortress_v3.table'
|
||||
|
||||
local function balance(t)
|
||||
local g = 0
|
||||
local c = 0
|
||||
for k, v in pairs(t) do
|
||||
if (v.valid) then
|
||||
g = g + v.energy
|
||||
c = c + v.electric_buffer_size
|
||||
end
|
||||
end
|
||||
for k, v in pairs(t) do
|
||||
if (v.valid) then
|
||||
local r = (v.electric_buffer_size / c)
|
||||
v.energy = g * r
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function tick()
|
||||
local this = WPT.get()
|
||||
if not this.energy['mountain_fortress_v3'] then
|
||||
this.energy['mountain_fortress_v3'] = this.ow_energy
|
||||
end
|
||||
|
||||
if not this.energy['loco'] then
|
||||
this.energy['loco'] = this.lo_energy
|
||||
end
|
||||
|
||||
local mountain_fortress_v3 = this.energy['mountain_fortress_v3']
|
||||
local loco = this.energy['loco']
|
||||
if not mountain_fortress_v3 or not loco then
|
||||
return
|
||||
end
|
||||
if not mountain_fortress_v3.valid or not loco.valid then
|
||||
return
|
||||
end
|
||||
balance(this.energy)
|
||||
end
|
||||
|
||||
local function built_entity(event)
|
||||
local entity = event.created_entity
|
||||
if not entity.valid then
|
||||
return
|
||||
end
|
||||
local player = game.players[event.player_index]
|
||||
local surface = entity.surface
|
||||
local map_name = 'mountain_fortress_v3'
|
||||
|
||||
if surface.name ~= map_name then
|
||||
return
|
||||
end
|
||||
if
|
||||
entity.name == 'steam-engine' or entity.name == 'steam-turbine' or entity.name == 'lab' or
|
||||
entity.name == 'rocket-silo'
|
||||
then
|
||||
if not entity.valid then
|
||||
return
|
||||
end
|
||||
player.print('"' .. entity.name .. '" Does not seem to work down here, thats strange!', {r = 1, g = 0, b = 0})
|
||||
entity.active = false
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_tick, tick)
|
||||
--Event.add(defines.events.on_built_entity, built_entity)
|
1264
maps/mountain_fortress_v3/rpg.lua
Normal file
1264
maps/mountain_fortress_v3/rpg.lua
Normal file
File diff suppressed because it is too large
Load Diff
95
maps/mountain_fortress_v3/soft_reset.lua
Normal file
95
maps/mountain_fortress_v3/soft_reset.lua
Normal file
@ -0,0 +1,95 @@
|
||||
local Server = require 'utils.server'
|
||||
local Modifers = require 'player_modifiers'
|
||||
local WPT = require 'maps.mountain_fortress_v3.table'
|
||||
|
||||
local mapkeeper = '[color=blue]Mapkeeper:[/color]'
|
||||
|
||||
local Public = {}
|
||||
|
||||
local function reset_forces(new_surface, old_surface)
|
||||
for _, f in pairs(game.forces) do
|
||||
local spawn = {
|
||||
x = game.forces.player.get_spawn_position(old_surface).x,
|
||||
y = game.forces.player.get_spawn_position(old_surface).y
|
||||
}
|
||||
f.reset()
|
||||
f.reset_evolution()
|
||||
f.set_spawn_position(spawn, new_surface)
|
||||
end
|
||||
for _, tech in pairs(game.forces.player.technologies) do
|
||||
tech.researched = false
|
||||
game.forces.player.set_saved_technology_progress(tech, 0)
|
||||
end
|
||||
end
|
||||
|
||||
local function teleport_players(surface)
|
||||
game.forces.player.set_spawn_position({-27, 25}, surface)
|
||||
|
||||
for _, player in pairs(game.connected_players) do
|
||||
player.teleport(
|
||||
surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 3, 0, 5),
|
||||
surface
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
local function equip_players(player_starting_items)
|
||||
for k, player in pairs(game.connected_players) do
|
||||
if player.character then
|
||||
player.character.destroy()
|
||||
end
|
||||
player.character = nil
|
||||
player.set_controller({type = defines.controllers.god})
|
||||
player.create_character()
|
||||
for item, amount in pairs(player_starting_items) do
|
||||
player.insert({name = item, count = amount})
|
||||
end
|
||||
Modifers.update_player_modifiers(player)
|
||||
end
|
||||
end
|
||||
|
||||
function Public.soft_reset_map(old_surface, map_gen_settings, player_starting_items)
|
||||
local this = WPT.get()
|
||||
|
||||
if not this.soft_reset_counter then
|
||||
this.soft_reset_counter = 0
|
||||
end
|
||||
if not this.original_surface_name then
|
||||
this.original_surface_name = old_surface.name
|
||||
end
|
||||
this.soft_reset_counter = this.soft_reset_counter + 1
|
||||
|
||||
local new_surface =
|
||||
game.create_surface(this.original_surface_name .. '_' .. tostring(this.soft_reset_counter), map_gen_settings)
|
||||
new_surface.request_to_generate_chunks({0, 0}, 0.5)
|
||||
new_surface.force_generate_chunk_requests()
|
||||
|
||||
reset_forces(new_surface, old_surface)
|
||||
teleport_players(new_surface)
|
||||
equip_players(player_starting_items)
|
||||
|
||||
game.delete_surface(old_surface)
|
||||
|
||||
local message = table.concat({mapkeeper .. ' Welcome to ', this.original_surface_name, '!'})
|
||||
local message_to_discord = table.concat({'** Welcome to ', this.original_surface_name, '! **'})
|
||||
|
||||
if this.soft_reset_counter > 1 then
|
||||
message =
|
||||
table.concat(
|
||||
{
|
||||
mapkeeper,
|
||||
' The world has been reshaped, welcome to ',
|
||||
this.original_surface_name,
|
||||
' number ',
|
||||
tostring(this.soft_reset_counter),
|
||||
'!'
|
||||
}
|
||||
)
|
||||
end
|
||||
game.print(message, {r = 0.98, g = 0.66, b = 0.22})
|
||||
Server.to_discord_embed(message_to_discord)
|
||||
|
||||
return new_surface
|
||||
end
|
||||
|
||||
return Public
|
89
maps/mountain_fortress_v3/surface.lua
Normal file
89
maps/mountain_fortress_v3/surface.lua
Normal file
@ -0,0 +1,89 @@
|
||||
require 'util'
|
||||
local Global = require 'utils.global'
|
||||
local Event = require 'utils.event'
|
||||
local surface_name = 'mountain_fortress_v3'
|
||||
local level_width = require 'maps.mountain_fortress_v3.terrain'.level_width
|
||||
local Reset = require 'maps.mountain_fortress_v3.soft_reset'
|
||||
|
||||
local Public = {}
|
||||
|
||||
local this = {
|
||||
active_surface_index = nil,
|
||||
surface_name = surface_name
|
||||
}
|
||||
|
||||
Global.register(
|
||||
this,
|
||||
function(tbl)
|
||||
this = tbl
|
||||
end
|
||||
)
|
||||
|
||||
local starting_items = {['pistol'] = 1, ['firearm-magazine'] = 16, ['rail'] = 16, ['wood'] = 16, ['explosives'] = 32}
|
||||
|
||||
local function on_init()
|
||||
local mgs = game.surfaces['nauvis'].map_gen_settings
|
||||
mgs.width = 16
|
||||
mgs.height = 16
|
||||
game.surfaces['nauvis'].map_gen_settings = mgs
|
||||
game.surfaces['nauvis'].clear()
|
||||
|
||||
Public.create_surface()
|
||||
end
|
||||
|
||||
function Public.create_surface()
|
||||
local map_gen_settings = {
|
||||
['seed'] = math.random(10000, 99999),
|
||||
['width'] = level_width,
|
||||
['water'] = 0.001,
|
||||
['starting_area'] = 1,
|
||||
['cliff_settings'] = {cliff_elevation_interval = 0, cliff_elevation_0 = 0},
|
||||
['default_enable_all_autoplace_controls'] = true,
|
||||
['autoplace_settings'] = {
|
||||
['entity'] = {treat_missing_as_default = false},
|
||||
['tile'] = {treat_missing_as_default = true},
|
||||
['decorative'] = {treat_missing_as_default = true}
|
||||
}
|
||||
}
|
||||
local mine = {}
|
||||
mine['control-setting:moisture:bias'] = 0.33
|
||||
mine['control-setting:moisture:frequency:multiplier'] = 1
|
||||
|
||||
map_gen_settings.property_expression_names = mine
|
||||
|
||||
if not this.active_surface_index then
|
||||
this.active_surface_index = game.create_surface(surface_name, map_gen_settings).index
|
||||
game.forces.player.set_spawn_position({-27, 25}, game.surfaces[this.active_surface_index])
|
||||
else
|
||||
game.forces.player.set_spawn_position({-27, 25}, game.surfaces[this.active_surface_index])
|
||||
this.active_surface_index =
|
||||
Reset.soft_reset_map(game.surfaces[this.active_surface_index], map_gen_settings, starting_items).index
|
||||
end
|
||||
|
||||
local surface = game.surfaces[this.active_surface_index]
|
||||
|
||||
surface.request_to_generate_chunks({-17, 45}, 1)
|
||||
surface.force_generate_chunk_requests()
|
||||
|
||||
return this.active_surface_index
|
||||
end
|
||||
|
||||
function Public.get_active_surface()
|
||||
return this.active_surface
|
||||
end
|
||||
|
||||
function Public.get_surface_name()
|
||||
return this.surface_name
|
||||
end
|
||||
|
||||
function Public.get(key)
|
||||
if key then
|
||||
return this[key]
|
||||
else
|
||||
return this
|
||||
end
|
||||
end
|
||||
|
||||
Event.on_init(on_init)
|
||||
|
||||
return Public
|
58
maps/mountain_fortress_v3/table.lua
Normal file
58
maps/mountain_fortress_v3/table.lua
Normal file
@ -0,0 +1,58 @@
|
||||
-- on table to rule them all!
|
||||
local Global = require 'utils.global'
|
||||
local Event = require 'utils.event'
|
||||
|
||||
local this = {
|
||||
disable_reset = false,
|
||||
players = {},
|
||||
offline_players = {}
|
||||
}
|
||||
local Public = {}
|
||||
|
||||
Global.register(
|
||||
this,
|
||||
function(tbl)
|
||||
this = tbl
|
||||
end
|
||||
)
|
||||
|
||||
function Public.reset_table()
|
||||
this.locomotive_index = nil
|
||||
this.loco_surface = nil
|
||||
this.game_lost = false
|
||||
this.locomotive_health = 10000
|
||||
this.locomotive_max_health = 10000
|
||||
this.cargo_health = 10000
|
||||
this.cargo_max_health = 10000
|
||||
this.train_upgrades = 0
|
||||
this.offline_players = {}
|
||||
this.biter_pets = {}
|
||||
this.mined_scrap = 0
|
||||
this.biters_killed = 0
|
||||
this.locomotive_xp_aura = 40
|
||||
this.xp_points = 0
|
||||
this.xp_points_upgrade = 0
|
||||
this.aura_upgrades = 0
|
||||
this.health_upgrades = 0
|
||||
this.threat_upgrades = 0
|
||||
this.left_top = {
|
||||
x = 0,
|
||||
y = 0
|
||||
}
|
||||
end
|
||||
|
||||
function Public.get(key)
|
||||
if key then
|
||||
return this[key]
|
||||
else
|
||||
return this
|
||||
end
|
||||
end
|
||||
|
||||
local on_init = function()
|
||||
Public.reset_table()
|
||||
end
|
||||
|
||||
Event.on_init(on_init)
|
||||
|
||||
return Public
|
1392
maps/mountain_fortress_v3/terrain.lua
Normal file
1392
maps/mountain_fortress_v3/terrain.lua
Normal file
File diff suppressed because it is too large
Load Diff
114
maps/mountain_fortress_v3/tick_tack_trap.lua
Normal file
114
maps/mountain_fortress_v3/tick_tack_trap.lua
Normal file
@ -0,0 +1,114 @@
|
||||
local tick_tacks = {'*tick*', '*tick*', '*tack*', '*tak*', '*tik*', '*tok*'}
|
||||
|
||||
local kaboom_weights = {
|
||||
{name = 'grenade', chance = 7},
|
||||
{name = 'cluster-grenade', chance = 1},
|
||||
{name = 'destroyer-capsule', chance = 1},
|
||||
{name = 'defender-capsule', chance = 4},
|
||||
{name = 'distractor-capsule', chance = 2},
|
||||
{name = 'poison-capsule', chance = 2},
|
||||
{name = 'explosive-uranium-cannon-projectile', chance = 3},
|
||||
{name = 'explosive-cannon-projectile', chance = 5}
|
||||
}
|
||||
|
||||
local kabooms = {}
|
||||
for _, t in pairs(kaboom_weights) do
|
||||
for x = 1, t.chance, 1 do
|
||||
table.insert(kabooms, t.name)
|
||||
end
|
||||
end
|
||||
|
||||
local function create_flying_text(surface, position, text)
|
||||
if not surface.valid then
|
||||
return
|
||||
end
|
||||
surface.create_entity(
|
||||
{
|
||||
name = 'flying-text',
|
||||
position = position,
|
||||
text = text,
|
||||
color = {r = 0.75, g = 0.75, b = 0.75}
|
||||
}
|
||||
)
|
||||
|
||||
surface.play_sound({path = 'utility/armor_insert', position = position, volume_modifier = 0.75})
|
||||
end
|
||||
|
||||
local function create_kaboom(surface, position, name)
|
||||
if not surface.valid then
|
||||
return
|
||||
end
|
||||
|
||||
local target = position
|
||||
local speed = 0.5
|
||||
if name == 'defender-capsule' or name == 'destroyer-capsule' or name == 'distractor-capsule' then
|
||||
surface.create_entity(
|
||||
{
|
||||
name = 'flying-text',
|
||||
position = position,
|
||||
text = '(((Sentries Engaging Target)))',
|
||||
color = {r = 0.8, g = 0.0, b = 0.0}
|
||||
}
|
||||
)
|
||||
local nearest_player_unit =
|
||||
surface.find_nearest_enemy({position = position, max_distance = 128, force = 'enemy'})
|
||||
if nearest_player_unit then
|
||||
target = nearest_player_unit.position
|
||||
end
|
||||
speed = 0.001
|
||||
end
|
||||
surface.create_entity(
|
||||
{
|
||||
name = name,
|
||||
position = position,
|
||||
force = 'enemy',
|
||||
target = target,
|
||||
speed = speed
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
local function tick_tack_trap(surface, position)
|
||||
if not surface then
|
||||
return
|
||||
end
|
||||
if not surface.valid then
|
||||
return
|
||||
end
|
||||
if not position then
|
||||
return
|
||||
end
|
||||
if not position.x then
|
||||
return
|
||||
end
|
||||
if not position.y then
|
||||
return
|
||||
end
|
||||
local tick_tack_count = math.random(5, 9)
|
||||
for t = 60, tick_tack_count * 60, 60 do
|
||||
if not global.on_tick_schedule[game.tick + t] then
|
||||
global.on_tick_schedule[game.tick + t] = {}
|
||||
end
|
||||
|
||||
if t < tick_tack_count * 60 then
|
||||
global.on_tick_schedule[game.tick + t][#global.on_tick_schedule[game.tick + t] + 1] = {
|
||||
func = create_flying_text,
|
||||
args = {surface, {x = position.x, y = position.y}, tick_tacks[math.random(1, #tick_tacks)]}
|
||||
}
|
||||
else
|
||||
if math.random(1, 10) == 1 then
|
||||
global.on_tick_schedule[game.tick + t][#global.on_tick_schedule[game.tick + t] + 1] = {
|
||||
func = create_flying_text,
|
||||
args = {surface, {x = position.x, y = position.y}, '( ͡° ͜ʖ ͡°)'}
|
||||
}
|
||||
else
|
||||
global.on_tick_schedule[game.tick + t][#global.on_tick_schedule[game.tick + t] + 1] = {
|
||||
func = create_kaboom,
|
||||
args = {surface, {x = position.x, y = position.y}, kabooms[math.random(1, #kabooms)]}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return tick_tack_trap
|
@ -29,6 +29,7 @@ local modifiers = {
|
||||
'character_mining_speed_modifier',
|
||||
'character_reach_distance_bonus',
|
||||
'character_resource_reach_distance_bonus',
|
||||
'character_maximum_following_robot_count_bonus',
|
||||
'character_running_speed_modifier'
|
||||
}
|
||||
|
||||
|
@ -155,15 +155,6 @@ function Task.start_queue()
|
||||
end
|
||||
end
|
||||
|
||||
function Task.reset_queue()
|
||||
if #task_queue > 50 then
|
||||
task_queue = {
|
||||
_head = 1,
|
||||
_tail = 0
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function Task.get_task_queue()
|
||||
return task_queue
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user