diff --git a/locale/en/locale.cfg b/locale/en/locale.cfg index fc938322..2baf3e71 100644 --- a/locale/en/locale.cfg +++ b/locale/en/locale.cfg @@ -143,6 +143,7 @@ angels-ore6=umber gui_1=First wave in gui_2=Wave: gui_3=Threat: +gui_4=Paused for: tooltip_1=High threat may empower biters.\nBiter health: __1__%\nMax active biters: __2__~ tooltip_2=gain / minute diff --git a/locale/en/rpg.cfg b/locale/en/rpg.cfg index 8cff61a4..53b156ce 100644 --- a/locale/en/rpg.cfg +++ b/locale/en/rpg.cfg @@ -86,6 +86,9 @@ no_mana=Not enough mana! mana_label=Mana Settings: tooltip_check=Checked: true\nUnchecked: false info_text_label=Common RPG settings. These settings are per player basis. +spellbook_label=Spellbook - explains the requirement for each spell. +entity_spells_label=Normal Spells +special_spells_label=Special Spells health_text_label=Show health/mana bar? health_only_text_label=Show health bar? reset_text_label=Reset your skillpoints? @@ -109,9 +112,6 @@ cast_spell_enabled_label=Casting spells with fish has been enabled! cast_spell_disabled_label=Casting spells with fish has been disabled! magic_tooltip=When simply constructing items is not enough.\nNOTE! Use Raw-fish to cast spells. magic_spell=Select what entity to spawn -magic_item_requirement=__1__ [item=__2__] requires __3__ mana to cast. Level: __4__\n -magic_entity_requirement=__1__ [entity=__2__] requires __3__ mana to cast. Level: __4__\n -magic_special_requirement=__1__ __2__ requires __3__ mana to cast. Level: __4__\n allocation_settings_label=Allocations Settings: allocation_label=Select what skill to auto-allocate. allocation_tooltip=This will automatically allocate all available points to the given node. @@ -128,6 +128,8 @@ distractor=Distractor Capsule warp=Warp Gate pointy_explosives=Detonate Chest repair_aoe=Repair AOE +charge=Charge +eternal_blades=Eternal Blades [allocations] diff --git a/maps/mountain_fortress_v3/buried_enemies.lua b/maps/mountain_fortress_v3/buried_enemies.lua index 7b15e214..49c2763c 100644 --- a/maps/mountain_fortress_v3/buried_enemies.lua +++ b/maps/mountain_fortress_v3/buried_enemies.lua @@ -42,7 +42,7 @@ local function create_particles(data) if not surface or not surface.valid then return end - for i = 1, amount, 1 do + for _ = 1, amount, 1 do local m = random(6, 12) local m2 = m * 0.005 diff --git a/maps/mountain_fortress_v3/locomotive/defense_system.lua b/maps/mountain_fortress_v3/locomotive/defense_system.lua index ef0c059d..b5be5334 100644 --- a/maps/mountain_fortress_v3/locomotive/defense_system.lua +++ b/maps/mountain_fortress_v3/locomotive/defense_system.lua @@ -87,10 +87,6 @@ function Public.enable_poison_defense(pos) end pos = pos or locomotive.position create_defense_system({x = pos.x, y = pos.y}, 'poison-cloud', pos) - if random(1, 4) == 1 then - local random_angles = {rad(random(344))} - create_defense_system({x = pos.x + 24 * cos(random_angles[1]), y = pos.y + -24 * sin(random_angles[1])}, 'poison-cloud', pos) - end end function Public.enable_robotic_defense(pos) @@ -104,10 +100,6 @@ function Public.enable_robotic_defense(pos) pos = pos or locomotive.position create_defense_system({x = pos.x, y = pos.y}, 'destroyer-capsule', pos) - if random(1, 4) == 1 then - local random_angles = {rad(random(324))} - create_defense_system({x = pos.x + 24 * cos(random_angles[1]), y = pos.y + -24 * sin(random_angles[1])}, 'destroyer-capsule', pos) - end end return Public diff --git a/maps/mountain_fortress_v3/main.lua b/maps/mountain_fortress_v3/main.lua index 10d85aaa..29a5ddfb 100644 --- a/maps/mountain_fortress_v3/main.lua +++ b/maps/mountain_fortress_v3/main.lua @@ -172,7 +172,6 @@ function Public.reset_map() RPG.enable_health_and_mana_bars(true) RPG.enable_wave_defense(true) RPG.enable_mana(true) - RPG.enable_flame_boots(true) RPG.personal_tax_rate(0.4) RPG.enable_stone_path(true) RPG.enable_aoe_punch(true) @@ -497,7 +496,6 @@ local on_tick = function() end local on_init = function() - local this = WPT.get() Public.reset_map() game.map_settings.path_finder.general_entity_collision_penalty = 10 -- Recommended value @@ -511,11 +509,6 @@ local on_init = function() Difficulty.set_tooltip(tooltip) - this.rocks_yield_ore_maximum_amount = 500 - this.type_modifier = 1 - this.rocks_yield_ore_base_amount = 40 - this.rocks_yield_ore_distance_modifier = 0.020 - local T = Map.Pop_info() T.localised_category = 'mountain_fortress_v3' T.main_caption_color = {r = 150, g = 150, b = 0} diff --git a/maps/mountain_fortress_v3/mining.lua b/maps/mountain_fortress_v3/mining.lua index 4c360eb2..a9728669 100644 --- a/maps/mountain_fortress_v3/mining.lua +++ b/maps/mountain_fortress_v3/mining.lua @@ -120,17 +120,17 @@ local valid_rocks = { } local valid_trees = { - ['dead-tree-desert'] = true, - ['dead-dry-hairy-tree'] = true, - ['dry-hairy-tree'] = true, - ['tree-06'] = true, - ['tree-06-brown'] = true, - ['dry-tree'] = true, - ['tree-01'] = true, - ['tree-02-red'] = true, - ['tree-03'] = true, - ['tree-04'] = true, - ['tree-08-brown'] = true + ['dead-tree-desert'] = 'wood', + ['dead-dry-hairy-tree'] = 'wood', + ['dry-hairy-tree'] = 'wood', + ['tree-06'] = 'wood', + ['tree-06-brown'] = 'wood', + ['dry-tree'] = 'wood', + ['tree-01'] = 'iron-ore', + ['tree-02-red'] = 'copper-ore', + ['tree-03'] = 'coal', + ['tree-04'] = 'coal', + ['tree-08-brown'] = 'stone' } local valid_scrap = { @@ -143,15 +143,6 @@ local valid_scrap = { ['mineable-wreckages'] = true } -local reward_wood = { - ['dead-tree-desert'] = true, - ['dead-dry-hairy-tree'] = true, - ['dry-hairy-tree'] = true, - ['tree-06'] = true, - ['tree-06-brown'] = true, - ['dry-tree'] = true -} - local rock_yield = { ['rock-big'] = 1, ['rock-huge'] = 2, @@ -197,31 +188,27 @@ local function create_particles(surface, name, position, amount, cause_position) end end -local function mining_chances_ores() - local data = { - {name = 'iron-ore', chance = 26}, - {name = 'copper-ore', chance = 21}, - {name = 'coal', chance = 17}, - {name = 'stone', chance = 6}, - {name = 'uranium-ore', chance = 2} - } - - return data -end +local mining_chances_ores = { + {name = 'iron-ore', chance = 26}, + {name = 'copper-ore', chance = 21}, + {name = 'coal', chance = 17}, + {name = 'stone', chance = 6}, + {name = 'uranium-ore', chance = 2} +} local harvest_raffle_ores = {} -for _, t in pairs(mining_chances_ores()) do - for _ = 1, t.chance, 1 do - harvest_raffle_ores[#harvest_raffle_ores + 1] = t.name +for _, data in pairs(mining_chances_ores) do + for _ = 1, data.chance, 1 do + harvest_raffle_ores[#harvest_raffle_ores + 1] = data.name end end local size_of_ore_raffle = #harvest_raffle_ores local scrap_raffle = {} -for _, t in pairs(mining_chance_weights) do - for _ = 1, t.chance, 1 do - scrap_raffle[#scrap_raffle + 1] = t.name +for _, data in pairs(mining_chance_weights) do + for _ = 1, data.chance, 1 do + scrap_raffle[#scrap_raffle + 1] = data.name end end @@ -229,10 +216,11 @@ local size_of_scrap_raffle = #scrap_raffle local function get_amount(data) local entity = data.entity - local t_modifier = WPT.get('type_modifier') - local rocks_yield_ore_distance_modifier = WPT.get('rocks_yield_ore_distance_modifier') - local rocks_yield_ore_base_amount = WPT.get('rocks_yield_ore_base_amount') - local rocks_yield_ore_maximum_amount = WPT.get('rocks_yield_ore_maximum_amount') + local mining_utils = WPT.get('mining_utils') + local t_modifier = mining_utils.type_modifier + local rocks_yield_ore_distance_modifier = mining_utils.rocks_yield_ore_distance_modifier + local rocks_yield_ore_base_amount = mining_utils.rocks_yield_ore_base_amount + local rocks_yield_ore_maximum_amount = mining_utils.rocks_yield_ore_maximum_amount local distance_to_center = floor(sqrt(entity.position.x ^ 2 + entity.position.y ^ 2)) local type_modifier = 1 local amount @@ -301,20 +289,11 @@ local function randomness(data) harvest_amount = get_amount(data) - local n = entity.name - if n == 'tree-08-brown' then - harvest = 'stone' - elseif n == 'tree-04' then - harvest = 'coal' - elseif n == 'tree-02-red' then - harvest = 'copper-ore' - elseif n == 'tree-01' then - harvest = 'iron-ore' - elseif n == 'tree-03' then - harvest = 'coal' - elseif reward_wood[n] then - harvest = 'wood' - harvest_amount = random(1, 20) + if valid_trees[entity.name] then + harvest = valid_trees[entity.name] + if harvest == 'wood' then + harvest_amount = random(1, 20) + end else harvest = harvest_raffle_ores[random(1, size_of_ore_raffle)] end @@ -431,8 +410,10 @@ function Public.on_player_mined_entity(event) is_scrap = true end + local buffer = event.buffer + if valid_rocks[entity.name] or valid_trees[entity.name] or is_scrap then - event.buffer.clear() + buffer.clear() local data = { entity = entity, diff --git a/maps/mountain_fortress_v3/table.lua b/maps/mountain_fortress_v3/table.lua index 29687451..607d85c1 100644 --- a/maps/mountain_fortress_v3/table.lua +++ b/maps/mountain_fortress_v3/table.lua @@ -234,7 +234,14 @@ function Public.reset_table() shuffled_zones = nil } this.alert_zone_1 = false -- alert the players - this.radars_reveal_new_chunks = false -- allows for the player to explore the map instead + this.radars_reveal_new_chunks = false -- allows for the player to explore the map instead, + + this.mining_utils = { + rocks_yield_ore_maximum_amount = 500, + type_modifier = 1, + rocks_yield_ore_base_amount = 40, + rocks_yield_ore_distance_modifier = 0.020 + } for k, _ in pairs(this.players) do this.players[k] = {} diff --git a/modules/difficulty_vote_by_amount.lua b/modules/difficulty_vote_by_amount.lua index c16684f8..c3d1a727 100644 --- a/modules/difficulty_vote_by_amount.lua +++ b/modules/difficulty_vote_by_amount.lua @@ -182,7 +182,7 @@ local function poll_difficulty(player) type = 'flow' } - label_flow.add({type = 'label', caption = '- - - - - - - - - - - - - - - - - -'}) + inside_frame.add({type = 'line'}) label_flow.style.horizontal_align = 'center' label_flow.style.horizontally_stretchable = true @@ -205,6 +205,8 @@ local function poll_difficulty(player) b.style.font = 'heading-3' b.style.minimal_width = 96 b.enabled = false + + inside_frame.add({type = 'line'}) end local function set_difficulty() diff --git a/modules/rpg/commands.lua b/modules/rpg/commands.lua index f8f22599..2c6c29a2 100644 --- a/modules/rpg/commands.lua +++ b/modules/rpg/commands.lua @@ -122,7 +122,7 @@ commands.add_command( player.play_sound {path = 'utility/scenario_message', volume_modifier = 1} player.print(msg) else - player.print('Please type a name of a player who is connected.', Color.warning) + player.print('[Stats] Please type a name of a player who is connected.', Color.warning) end end ) diff --git a/modules/rpg/functions.lua b/modules/rpg/functions.lua index adc54d1c..7d31378c 100644 --- a/modules/rpg/functions.lua +++ b/modules/rpg/functions.lua @@ -2,6 +2,7 @@ local Public = require 'modules.rpg.table' local Task = require 'utils.task' local Gui = require 'utils.gui' local Color = require 'utils.color_presets' +local BiterHealthBooster = require 'modules.biter_health_booster_v2' local P = require 'utils.player_modifiers' local Token = require 'utils.token' local Alert = require 'utils.alert' @@ -12,9 +13,11 @@ local xp_floating_text_color = Public.xp_floating_text_color local experience_levels = Public.experience_levels local points_per_level = Public.points_per_level local settings_level = Public.gui_settings_levels + +local round = math.round local floor = math.floor local random = math.random -local round = math.round +local abs = math.abs --RPG Frames local main_frame_name = Public.main_frame_name @@ -41,7 +44,7 @@ local desync = end local surface = data.surface local fake_shooter = surface.create_entity({name = 'character', position = entity.position, force = 'enemy'}) - for i = 1, 3 do + for _ = 1, 3 do surface.create_entity( { name = 'explosive-rocket', @@ -155,6 +158,98 @@ local function level_up(player) Public.level_up_effects(player) end +local function has_health_boost(entity, damage, final_damage_amount, cause) + local biter_health_boost = BiterHealthBooster.get('biter_health_boost') + local biter_health_boost_units = BiterHealthBooster.get('biter_health_boost_units') + + local get_health_pool + + if not entity.valid then + return + end + + --Handle the custom health pool of the biter health booster, if it is used in the map. + if biter_health_boost then + local health_pool = biter_health_boost_units[entity.unit_number] + if health_pool then + get_health_pool = health_pool[1] + --Set entity health relative to health pool + local max_health = health_pool[3].max_health + local m = health_pool[1] / max_health + local final_health = round(entity.prototype.max_health * m) + + health_pool[1] = round(health_pool[1] + final_damage_amount) + health_pool[1] = round(health_pool[1] - damage) + + --Set entity health relative to health pool + entity.health = final_health + + if health_pool[1] <= 0 then + local entity_number = entity.unit_number + entity.die(entity.force.name, cause) + + if biter_health_boost_units[entity_number] then + biter_health_boost_units[entity_number] = nil + end + end + else + entity.health = entity.health + final_damage_amount + entity.health = entity.health - damage + if entity.health <= 0 then + entity.die(cause.force.name, cause) + end + end + else + --Handle vanilla damage. + entity.health = entity.health + final_damage_amount + entity.health = entity.health - damage + if entity.health <= 0 then + entity.die(cause.force.name, cause) + end + end + + return get_health_pool +end + +local function set_health_boost(entity, damage, cause) + local biter_health_boost = BiterHealthBooster.get('biter_health_boost') + local biter_health_boost_units = BiterHealthBooster.get('biter_health_boost_units') + + local get_health_pool + + if not entity.valid then + return + end + + --Handle the custom health pool of the biter health booster, if it is used in the map. + if biter_health_boost then + local health_pool = biter_health_boost_units[entity.unit_number] + if health_pool then + get_health_pool = health_pool[1] + --Set entity health relative to health pool + local max_health = health_pool[3].max_health + local m = health_pool[1] / max_health + local final_health = round(entity.prototype.max_health * m) + + health_pool[1] = round(health_pool[1] - damage) + + --Set entity health relative to health pool + entity.health = final_health + + if health_pool[1] <= 0 then + local entity_number = entity.unit_number + entity.die(entity.force.name, cause) + + if biter_health_boost_units[entity_number] then + biter_health_boost_units[entity_number] = nil + end + end + end + end + + return get_health_pool +end + local function add_to_global_pool(amount, personal_tax) local rpg_extra = Public.get('rpg_extra') @@ -480,6 +575,95 @@ function Public.update_health(player) end end +function Public.log_aoe_punch(callback) + local debug = Public.get('rpg_extra').debug_aoe_punch + if not debug then + return + end + callback() +end + +--Melee damage modifier +function Public.aoe_punch(character, target, damage, get_health_pool) + if not (target and target.valid) then + return + end + + local base_vector = {target.position.x - character.position.x, target.position.y - character.position.y} + + local vector = {base_vector[1], base_vector[2]} + vector[1] = vector[1] * 1000 + vector[2] = vector[2] * 1000 + + character.surface.create_entity({name = 'blood-explosion-huge', position = target.position}) + + if abs(vector[1]) > abs(vector[2]) then + local d = abs(vector[1]) + if abs(vector[1]) > 0 then + vector[1] = vector[1] / d + end + if abs(vector[2]) > 0 then + vector[2] = vector[2] / d + end + else + local d = abs(vector[2]) + if abs(vector[2]) > 0 then + vector[2] = vector[2] / d + end + if abs(vector[1]) > 0 and d > 0 then + vector[1] = vector[1] / d + end + end + + vector[1] = vector[1] * 1.5 + vector[2] = vector[2] * 1.5 + + local a = 0.20 + + local cs = character.surface + local cp = character.position + + for i = 1, 16, 1 do + for x = i * -1 * a, i * a, 1 do + for y = i * -1 * a, i * a, 1 do + local p = {cp.x + x + vector[1] * i, cp.y + y + vector[2] * i} + cs.create_trivial_smoke({name = 'train-smoke', position = p}) + for _, e in pairs(cs.find_entities({{p[1] - a, p[2] - a}, {p[1] + a, p[2] + a}})) do + if e.valid then + if e.health then + if e.destructible and e.minable and e.force.index ~= 3 then + if e.force.index ~= character.force.index then + if get_health_pool then + local max_unit_health = floor(get_health_pool * 0.00015) + if max_unit_health <= 0 then + max_unit_health = 4 + end + if max_unit_health >= 10 then + max_unit_health = 10 + end + local final = floor(damage * max_unit_health) + set_health_boost(e, final, character) + if e.valid and e.health <= 0 and get_health_pool <= 0 then + e.die(e.force.name, character) + end + else + if e.valid then + e.health = e.health - damage * 0.05 + if e.health <= 0 then + e.die(e.force.name, character) + end + end + end + end + end + end + end + end + end + end + end +end + function Public.level_limit_exceeded(player, value) local rpg_extra = Public.get('rpg_extra') local rpg_t = Public.get_value_from_player(player.index) @@ -617,6 +801,19 @@ function Public.get_melee_modifier(player) return total end +function Public.get_area_of_effect_range(player) + local rpg_t = Public.get_value_from_player(player.index) + if not rpg_t then + return false + end + local total = (rpg_t.level - 10) * 0.05 + + if rpg_t.level < 10 then + total = 1 + end + return total +end + function Public.get_final_damage_modifier(player) local rpg_t = Public.get_value_from_player(player.index) if not rpg_t then @@ -774,7 +971,6 @@ function Public.rpg_reset_player(player, one_time_reset) dropdown_select_index2 = 1, dropdown_select_index3 = 1, allocate_index = 1, - flame_boots = false, explosive_bullets = false, enable_entity_spawn = false, health_bar = rpg_t.health_bar, @@ -817,7 +1013,6 @@ function Public.rpg_reset_player(player, one_time_reset) dropdown_select_index2 = 1, dropdown_select_index3 = 1, allocate_index = 1, - flame_boots = false, explosive_bullets = false, enable_entity_spawn = false, points_left = 0, @@ -983,8 +1178,6 @@ function Public.global_pool(players, count) end rpg_extra.global_pool = rpg_extra.leftover_pool or 0 - - return end local damage_player_over_time_token = @@ -1021,4 +1214,7 @@ function Public.distribute_pool() print('Distributed the global XP pool') end +Public.has_health_boost = has_health_boost +Public.set_health_boost = set_health_boost + Public.add_to_global_pool = add_to_global_pool diff --git a/modules/rpg/gui.lua b/modules/rpg/gui.lua index b28b4f96..c66abbab 100644 --- a/modules/rpg/gui.lua +++ b/modules/rpg/gui.lua @@ -17,6 +17,9 @@ local main_frame_name = Public.main_frame_name local draw_main_frame_name = Public.draw_main_frame_name local close_main_frame_name = Public.close_main_frame_name local settings_button_name = Public.settings_button_name +local settings_tooltip_frame = Public.settings_tooltip_frame +local close_settings_tooltip_frame = Public.close_settings_tooltip_frame +local settings_tooltip_name = Public.settings_tooltip_name local settings_frame_name = Public.settings_frame_name local discard_button_name = Public.discard_button_name local save_button_name = Public.save_button_name @@ -459,6 +462,21 @@ function Public.remove_frame(player) end end +function Public.clear_settings_frames(player) + local screen = player.gui.screen + local center = player.gui.center + + local setting_tooltip_frame = center[settings_tooltip_frame] + local setting_frame = screen[settings_frame_name] + + if setting_tooltip_frame then + remove_target_frame(setting_tooltip_frame) + end + if setting_frame then + remove_target_frame(setting_frame) + end +end + local toggle = Public.toggle Public.remove_main_frame = remove_main_frame @@ -501,7 +519,6 @@ Gui.on_click( local spell_gui_input3 = data.spell_gui_input3 local magic_pickup_gui_input = data.magic_pickup_gui_input local movement_speed_gui_input = data.movement_speed_gui_input - local flame_boots_gui_input = data.flame_boots_gui_input local explosive_bullets_gui_input = data.explosive_bullets_gui_input local enable_entity_gui_input = data.enable_entity_gui_input local stone_path_gui_input = data.stone_path_gui_input @@ -539,14 +556,6 @@ Gui.on_click( end end - if flame_boots_gui_input and flame_boots_gui_input.valid then - if not flame_boots_gui_input.state then - rpg_t.flame_boots = false - elseif flame_boots_gui_input.state then - rpg_t.flame_boots = true - end - end - if explosive_bullets_gui_input and explosive_bullets_gui_input.valid then if not explosive_bullets_gui_input.state then rpg_t.explosive_bullets = false @@ -672,6 +681,26 @@ Gui.on_click( end ) +Gui.on_click( + close_settings_tooltip_frame, + function(event) + local is_spamming = SpamProtection.is_spamming(event.player, nil, 'RPG Close Button') + if is_spamming then + return + end + local player = event.player + local center = player.gui.center + if not player or not player.valid or not player.character then + return + end + + local main_frame = center[settings_tooltip_frame] + if main_frame and main_frame.valid then + remove_target_frame(main_frame) + end + end +) + Gui.on_click( settings_button_name, function(event) @@ -695,11 +724,41 @@ Gui.on_click( Gui.remove_data_recursively(frame) frame.destroy() else + ComfyGui.clear_all_center_frames(player) Public.extra_settings(player) end end ) +Gui.on_click( + settings_tooltip_name, + function(event) + local is_spamming = SpamProtection.is_spamming(event.player, nil, 'RPG Settings Tooltip Button') + if is_spamming then + return + end + local player = event.player + if not player or not player.valid or not player.character then + return + end + + local surface_name = Public.get('rpg_extra').surface_name + if sub(player.surface.name, 0, #surface_name) ~= surface_name then + return + end + + local center = player.gui.center + local main_frame = center[settings_tooltip_frame] + if main_frame and main_frame.valid then + remove_target_frame(main_frame) + else + ComfyGui.clear_all_center_frames(player) + ComfyGui.clear_all_screen_frames(player) + Public.settings_tooltip(player) + end + end +) + Gui.on_click( enable_spawning_frame_name, function(event) diff --git a/modules/rpg/main.lua b/modules/rpg/main.lua index 2e652544..37ffc341 100644 --- a/modules/rpg/main.lua +++ b/modules/rpg/main.lua @@ -24,15 +24,6 @@ local round = math.round local floor = math.floor local random = math.random local sqrt = math.sqrt -local abs = math.abs - -local function log_aoe_punch(callback) - local debug = Public.get('rpg_extra').debug_aoe_punch - if not debug then - return - end - callback() -end local function on_gui_click(event) if not event then @@ -408,233 +399,6 @@ local function regen_mana_player(players) end end -local function give_player_flameboots(player) - local rpg_t = Public.get_value_from_player(player.index) - if not rpg_t then - return - end - - if not rpg_t.flame_boots then - return - end - - if not player.character then - return - end - if player.character.driving then - return - end - - if not rpg_t.mana then - return - end - - if rpg_t.mana <= 0 then - player.print(({'rpg_main.flame_boots_worn_out'}), {r = 0.22, g = 0.77, b = 0.44}) - rpg_t.flame_boots = false - return - end - - if rpg_t.mana % 500 == 0 then - player.print(({'rpg_main.flame_mana_remaining', rpg_t.mana}), {r = 0.22, g = 0.77, b = 0.44}) - end - - local p = player.position - - player.surface.create_entity({name = 'fire-flame', position = p}) - - rpg_t.mana = rpg_t.mana - 5 - if rpg_t.mana <= 0 then - rpg_t.mana = 0 - end - if player.gui.screen[main_frame_name] then - local f = player.gui.screen[main_frame_name] - local data = Gui.get_data(f) - if data.mana and data.mana.valid then - data.mana.caption = rpg_t.mana - end - end -end - -local function has_health_boost(entity, damage, final_damage_amount, cause) - local biter_health_boost = BiterHealthBooster.get('biter_health_boost') - local biter_health_boost_units = BiterHealthBooster.get('biter_health_boost_units') - - local get_health_pool - - --Handle the custom health pool of the biter health booster, if it is used in the map. - if biter_health_boost then - local health_pool = biter_health_boost_units[entity.unit_number] - if health_pool then - get_health_pool = health_pool[1] - --Set entity health relative to health pool - local max_health = health_pool[3].max_health - local m = health_pool[1] / max_health - local final_health = round(entity.prototype.max_health * m) - - health_pool[1] = round(health_pool[1] + final_damage_amount) - health_pool[1] = round(health_pool[1] - damage) - - --Set entity health relative to health pool - entity.health = final_health - - if health_pool[1] <= 0 then - local entity_number = entity.unit_number - entity.die(entity.force.name, cause) - - if biter_health_boost_units[entity_number] then - biter_health_boost_units[entity_number] = nil - end - end - else - entity.health = entity.health + final_damage_amount - entity.health = entity.health - damage - if entity.health <= 0 then - entity.die(cause.force.name, cause) - end - end - else - --Handle vanilla damage. - entity.health = entity.health + final_damage_amount - entity.health = entity.health - damage - if entity.health <= 0 then - entity.die(cause.force.name, cause) - end - end - - return get_health_pool -end - -local function set_health_boost(entity, damage, cause) - local biter_health_boost = BiterHealthBooster.get('biter_health_boost') - local biter_health_boost_units = BiterHealthBooster.get('biter_health_boost_units') - - local get_health_pool - - --Handle the custom health pool of the biter health booster, if it is used in the map. - if biter_health_boost then - local health_pool = biter_health_boost_units[entity.unit_number] - if health_pool then - get_health_pool = health_pool[1] - --Set entity health relative to health pool - local max_health = health_pool[3].max_health - local m = health_pool[1] / max_health - local final_health = round(entity.prototype.max_health * m) - - health_pool[1] = round(health_pool[1] - damage) - - --Set entity health relative to health pool - entity.health = final_health - - if health_pool[1] <= 0 then - local entity_number = entity.unit_number - entity.die(entity.force.name, cause) - - if biter_health_boost_units[entity_number] then - biter_health_boost_units[entity_number] = nil - end - end - end - end - - return get_health_pool -end - ---Melee damage modifier -local function aoe_punch(character, target, damage, get_health_pool) - if not (target and target.valid) then - return - end - - local base_vector = {target.position.x - character.position.x, target.position.y - character.position.y} - - local vector = {base_vector[1], base_vector[2]} - vector[1] = vector[1] * 1000 - vector[2] = vector[2] * 1000 - - character.surface.create_entity( - { - name = 'flying-text', - position = {character.position.x + base_vector[1] * 0.5, character.position.y + base_vector[2] * 0.5}, - text = ({'rpg_main.aoe_punch_text'}), - color = {255, 0, 0} - } - ) - character.surface.create_entity({name = 'blood-explosion-huge', position = target.position}) - character.surface.create_entity( - { - name = 'big-artillery-explosion', - position = {target.position.x + vector[1] * 0.5, target.position.y + vector[2] * 0.5} - } - ) - - if abs(vector[1]) > abs(vector[2]) then - local d = abs(vector[1]) - if abs(vector[1]) > 0 then - vector[1] = vector[1] / d - end - if abs(vector[2]) > 0 then - vector[2] = vector[2] / d - end - else - local d = abs(vector[2]) - if abs(vector[2]) > 0 then - vector[2] = vector[2] / d - end - if abs(vector[1]) > 0 and d > 0 then - vector[1] = vector[1] / d - end - end - - vector[1] = vector[1] * 1.5 - vector[2] = vector[2] * 1.5 - - local a = 0.20 - - local cs = character.surface - local cp = character.position - - for i = 1, 16, 1 do - for x = i * -1 * a, i * a, 1 do - for y = i * -1 * a, i * a, 1 do - local p = {cp.x + x + vector[1] * i, cp.y + y + vector[2] * i} - cs.create_trivial_smoke({name = 'train-smoke', position = p}) - for _, e in pairs(cs.find_entities({{p[1] - a, p[2] - a}, {p[1] + a, p[2] + a}})) do - if e.valid then - if e.health then - if e.destructible and e.minable and e.force.index ~= 3 then - if e.force.index ~= character.force.index then - if get_health_pool then - local max_unit_health = floor(get_health_pool * 0.00015) - if max_unit_health <= 0 then - max_unit_health = 4 - end - if max_unit_health >= 10 then - max_unit_health = 10 - end - local final = floor(damage * max_unit_health) - set_health_boost(e, final, character) - if e.valid and e.health <= 0 and get_health_pool <= 0 then - e.die(e.force.name, character) - end - else - if e.valid then - e.health = e.health - damage * 0.05 - if e.health <= 0 then - e.die(e.force.name, character) - end - end - end - end - end - end - end - end - end - end - end -end - local function is_position_near(area, entity) local status = false @@ -645,7 +409,7 @@ local function is_position_near(area, entity) return pos.x >= lt.x and pos.y >= lt.y and pos.x <= rb.x and pos.y <= rb.y end - if inside(entity, area) then + if inside(entity) then status = true end @@ -755,7 +519,7 @@ local function on_entity_damaged(event) ) end - local get_health_pool = has_health_boost(entity, damage, final_damage_amount, cause) + local get_health_pool = Public.has_health_boost(entity, damage, final_damage_amount, cause) --Cause a one punch. if enable_aoe_punch then @@ -763,7 +527,7 @@ local function on_entity_damaged(event) local chance = Public.get_aoe_punch_chance(cause.player) * 10 local chance_to_hit = random(0, 999) local success = chance_to_hit < chance - log_aoe_punch( + Public.log_aoe_punch( function() if success then print('[OnePunch]: Chance: ' .. chance .. ' Chance to hit: ' .. chance_to_hit .. ' Success: true' .. ' Damage: ' .. damage) @@ -772,10 +536,11 @@ local function on_entity_damaged(event) end end ) - if success then - aoe_punch(cause, entity, damage, get_health_pool) -- only kill the biters if their health is below or equal to zero - return - end + -- if success then + log(serpent.block('hit')) + Public.aoe_punch(cause, entity, damage, get_health_pool) -- only kill the biters if their health is below or equal to zero + return + -- end end end @@ -844,12 +609,6 @@ local function on_player_changed_position(event) return end - local enable_flame_boots = Public.get('rpg_extra').enable_flame_boots - - if enable_flame_boots then - give_player_flameboots(player) - end - if random(1, 64) ~= 1 then return end @@ -1011,7 +770,7 @@ end local function get_near_coord_modifier(range) local coord = {x = (range * -1) + random(0, range * 2), y = (range * -1) + random(0, range * 2)} - for i = 1, 5, 1 do + for _ = 1, 5, 1 do local new_coord = {x = (range * -1) + random(0, range * 2), y = (range * -1) + random(0, range * 2)} if new_coord.x ^ 2 + new_coord.y ^ 2 < coord.x ^ 2 + coord.y ^ 2 then coord = new_coord @@ -1090,7 +849,7 @@ local function on_player_used_capsule(event) return end - local conjure_items = Public.spells + local conjure_items = Public.all_spells local projectile_types = Public.get_projectiles local player = game.players[event.player_index] @@ -1133,8 +892,8 @@ local function on_player_used_capsule(event) local mana = rpg_t.mana local surface = player.surface - local object = conjure_items[rpg_t.dropdown_select_index] - if not object then + local spell = conjure_items[rpg_t.dropdown_select_index] + if not spell then return end @@ -1149,11 +908,11 @@ local function on_player_used_capsule(event) right_bottom = {x = position.x + radius, y = position.y + radius} } - if rpg_t.level < object.level then + if rpg_t.level < spell.level then return Public.cast_spell(player, true) end - if not object.enabled then + if not spell.enabled then return end @@ -1162,34 +921,41 @@ local function on_player_used_capsule(event) return end - if mana < object.mana_cost then + if mana < spell.mana_cost then return Public.cast_spell(player, true) end local target_pos - if object.target then + if spell.target then target_pos = {position.x, position.y} - elseif projectile_types[object.entityName] then - local coord_modifier = get_near_coord_modifier(projectile_types[object.entityName].max_range) + elseif projectile_types[spell.entityName] then + local coord_modifier = get_near_coord_modifier(projectile_types[spell.entityName].max_range) target_pos = {position.x + coord_modifier.x, position.y + coord_modifier.y} end local range - if object.range then - range = object.range + if spell.range then + range = spell.range else range = 0 end local force - if object.force then - force = object.force + if spell.force then + force = spell.force else force = 'player' end + if spell.check_if_active then + if rpg_t.has_custom_spell_active then + Public.cast_spell(player, true) + return + end + end + local data = { - self = object, + self = spell, player = player, damage_entity = damage_entity, position = position, @@ -1202,14 +968,14 @@ local function on_player_used_capsule(event) rpg_t = rpg_t } - object.callback(data) + spell.callback(data) - local msg = player.name .. ' casted ' .. object.entityName .. '. ' + local msg = player.name .. ' casted ' .. spell.entityName .. '. ' - rpg_t.last_spawned = game.tick + object.tick + rpg_t.last_spawned = game.tick + spell.tick Public.update_mana(player) - local reward_xp = object.mana_cost * 0.085 + local reward_xp = spell.mana_cost * 0.085 if reward_xp < 1 then reward_xp = 1 end @@ -1232,7 +998,6 @@ local function tick() local ticker = game.tick local players = game.connected_players local count = #players - local enable_flameboots = Public.get('rpg_extra').enable_flameboots local enable_mana = Public.get('rpg_extra').enable_mana if ticker % nth_tick == 0 then @@ -1244,9 +1009,6 @@ local function tick() if enable_mana then regen_mana_player(players) end - if enable_flameboots then - give_player_flameboots(players) - end end end @@ -1268,4 +1030,16 @@ Event.add(defines.events.on_player_changed_surface, on_player_changed_surface) Event.add(defines.events.on_player_removed, on_player_removed) Event.on_nth_tick(10, tick) +Event.add( + defines.events.on_gui_closed, + function(event) + local player = game.get_player(event.player_index) + if not player or not player.valid then + return + end + + Public.clear_settings_frames(player) + end +) + return Public diff --git a/modules/rpg/settings.lua b/modules/rpg/settings.lua index 483e9150..69eee080 100644 --- a/modules/rpg/settings.lua +++ b/modules/rpg/settings.lua @@ -4,6 +4,9 @@ local P = require 'utils.player_modifiers' local Session = require 'utils.datastore.session_data' local settings_frame_name = Public.settings_frame_name +local close_settings_tooltip_frame = Public.close_settings_tooltip_frame +local settings_tooltip_frame = Public.settings_tooltip_frame +local settings_tooltip_name = Public.settings_tooltip_name local save_button_name = Public.save_button_name local discard_button_name = Public.discard_button_name local spell_gui_button_name = Public.spell_gui_button_name @@ -15,6 +18,16 @@ local spell3_button_name = Public.spell3_button_name local settings_level = Public.gui_settings_levels +local comparators = { + ['levels'] = function(a, b) + return a.level < b.level + end +} + +local function get_comparator(sort_by) + return comparators[sort_by] +end + local function create_input_element(frame, type, value, items, index) if type == 'slider' then return frame.add({type = 'slider', value = value, minimum_value = 0, maximum_value = 1}) @@ -22,12 +35,22 @@ local function create_input_element(frame, type, value, items, index) if type == 'boolean' then return frame.add({type = 'checkbox', state = value}) end + if type == 'label' then + return frame.add({type = 'label', caption = value}) + end if type == 'dropdown' then return frame.add({type = 'drop-down', items = items, selected_index = index}) end return frame.add({type = 'text-box', text = value}) end +local function create_custom_label_element(frame, sprite, localised_string, value) + local t = frame.add({type = 'flow'}) + t.add({type = 'label', caption = '[' .. sprite .. ']'}) + t.add({type = 'label', caption = localised_string}) + return t.add({type = 'label', caption = value}) +end + function Public.update_spell_gui_indicator(player) local rpg_t = Public.get_value_from_player(player.index) local main_frame = player.gui.screen[spell_gui_frame_name] @@ -155,25 +178,12 @@ function Public.extra_settings(player) local rpg_extra = Public.get('rpg_extra') local rpg_t = Public.get_value_from_player(player.index) local trusted = Session.get_trusted_table() - local main_frame = - player.gui.screen.add( - { - type = 'frame', - name = settings_frame_name, - caption = ({'rpg_settings.name'}), - direction = 'vertical' - } - ) - main_frame.auto_center = true + + local main_frame, inside_table = Gui.add_main_frame_with_toolbar(player, 'screen', settings_frame_name, settings_tooltip_name, nil, 'RPG Settings', true) + local main_frame_style = main_frame.style main_frame_style.width = 500 - - local inside_frame = main_frame.add {type = 'frame', style = 'inside_shallow_frame'} - local inside_frame_style = inside_frame.style - inside_frame_style.padding = 0 - local inside_table = inside_frame.add {type = 'table', column_count = 1} - local inside_table_style = inside_table.style - inside_table_style.vertical_spacing = 0 + main_frame.auto_center = true inside_table.add({type = 'line'}) @@ -327,7 +337,6 @@ function Public.extra_settings(player) local spell_gui_input1 local spell_gui_input2 local spell_gui_input3 - local flame_boots_gui_input local explosive_bullets_gui_input local stone_path_gui_input local aoe_punch_gui_input @@ -412,48 +421,6 @@ function Public.extra_settings(player) end end - if rpg_extra.enable_flame_boots then - local flame_boots_label = - setting_grid.add( - { - type = 'label', - caption = ({'rpg_settings.flameboots_label'}), - tooltip = ({'rpg_settings.flameboots_tooltip'}) - } - ) - - local flame_boots_label_style = flame_boots_label.style - flame_boots_label_style.horizontally_stretchable = true - flame_boots_label_style.height = 35 - flame_boots_label_style.vertical_align = 'center' - - local flame_boots_input = setting_grid.add({type = 'flow'}) - local flame_boots_input_style = flame_boots_input.style - flame_boots_input_style.height = 35 - flame_boots_input_style.vertical_align = 'center' - local flame_mod - if rpg_t.flame_boots then - flame_mod = rpg_t.flame_boots - else - flame_mod = false - end - flame_boots_gui_input = create_input_element(flame_boots_input, 'boolean', flame_mod) - - if rpg_t.mana > 50 then - if rpg_t.level < settings_level['flameboots_label'] then - flame_boots_gui_input.enabled = false - flame_boots_gui_input.tooltip = ({'rpg_settings.low_level', 100}) - flame_boots_label.tooltip = ({'rpg_settings.low_level', 100}) - else - flame_boots_gui_input.enabled = true - flame_boots_gui_input.tooltip = ({'rpg_settings.tooltip_check'}) - end - else - flame_boots_gui_input.enabled = false - flame_boots_gui_input.tooltip = ({'rpg_settings.no_mana'}) - end - end - if rpg_extra.enable_explosive_bullets_globally then local explosive_bullets_label = setting_grid.add( @@ -556,7 +523,7 @@ function Public.extra_settings(player) { type = 'label', caption = ({'rpg_settings.magic_spell'}), - tooltip = '' + tooltip = 'Check the info button at upper right for more information' } ) @@ -573,33 +540,6 @@ function Public.extra_settings(player) conjure_input_style.vertical_align = 'center' conjure_gui_input = create_input_element(conjure_input, 'dropdown', false, names, rpg_t.dropdown_select_index) - for _, entity in pairs(spells) do - if entity.type == 'item' then - conjure_label.tooltip = ({ - 'rpg_settings.magic_item_requirement', - conjure_label.tooltip, - entity.entityName, - entity.mana_cost, - entity.level - }) - elseif entity.type == 'entity' then - conjure_label.tooltip = ({ - 'rpg_settings.magic_entity_requirement', - conjure_label.tooltip, - entity.entityName, - entity.mana_cost, - entity.level - }) - elseif entity.type == 'special' then - conjure_label.tooltip = ({ - 'rpg_settings.magic_special_requirement', - conjure_label.tooltip, - entity.name, - entity.mana_cost, - entity.level - }) - end - end if not spells[rpg_t.dropdown_select_index1] then rpg_t.dropdown_select_index1 = 1 end @@ -686,10 +626,6 @@ function Public.extra_settings(player) data.enable_entity_gui_input = enable_entity_gui_input end - if rpg_extra.enable_flame_boots then - data.flame_boots_gui_input = flame_boots_gui_input - end - if rpg_extra.enable_explosive_bullets_globally then data.explosive_bullets_gui_input = explosive_bullets_gui_input end @@ -725,3 +661,89 @@ function Public.extra_settings(player) player.opened = main_frame end + +function Public.settings_tooltip(player) + local rpg_extra = Public.get('rpg_extra') + + local main_frame, inside_table = Gui.add_main_frame_with_toolbar(player, 'center', settings_tooltip_frame, nil, close_settings_tooltip_frame, 'Spell info') + + local inside_table_style = inside_table.style + inside_table_style.width = 500 + + inside_table.add({type = 'line'}) + + local info_text = inside_table.add({type = 'label', caption = ({'rpg_settings.spellbook_label'})}) + local info_text_style = info_text.style + info_text_style.font = 'heading-2' + info_text_style.padding = 0 + info_text_style.left_padding = 10 + info_text_style.horizontal_align = 'left' + info_text_style.vertical_align = 'bottom' + info_text_style.font_color = {0.55, 0.55, 0.99} + + if rpg_extra.enable_mana then + local normal_spell_pane = inside_table.add({type = 'scroll-pane'}) + local ns = normal_spell_pane.style + ns.vertically_squashable = true + ns.bottom_padding = 5 + ns.left_padding = 5 + ns.right_padding = 5 + ns.top_padding = 5 + + normal_spell_pane.add({type = 'line'}) + + local entity_spells = normal_spell_pane.add({type = 'label', caption = ({'rpg_settings.entity_spells_label'})}) + local entity_spells_style = entity_spells.style + entity_spells_style.font = 'heading-3' + entity_spells_style.padding = 0 + entity_spells_style.left_padding = 10 + entity_spells_style.horizontal_align = 'left' + entity_spells_style.font_color = {0.55, 0.55, 0.99} + + local normal_spell_grid = normal_spell_pane.add({type = 'table', column_count = 2}) + + local spells = Public.rebuild_spells() + + local comparator = get_comparator('levels') + table.sort(spells, comparator) + + for _, entity in pairs(spells) do + if entity.type == 'item' then + local text = '[item=' .. entity.entityName .. '] requires ' .. entity.mana_cost .. ' mana to cast. Level: ' .. entity.level + create_input_element(normal_spell_grid, 'label', text) + elseif entity.type == 'entity' then + local text = '[entity=' .. entity.entityName .. '] requires ' .. entity.mana_cost .. ' mana to cast. Level: ' .. entity.level + create_input_element(normal_spell_grid, 'label', text) + end + end + + normal_spell_pane.add({type = 'line'}) + + local special_spell_pane = inside_table.add({type = 'scroll-pane'}) + local ss = special_spell_pane.style + ss.vertically_squashable = true + ss.bottom_padding = 5 + ss.left_padding = 5 + ss.right_padding = 5 + ss.top_padding = 5 + + local special_spells = special_spell_pane.add({type = 'label', caption = ({'rpg_settings.special_spells_label'})}) + local special_spells_style = special_spells.style + special_spells_style.font = 'heading-3' + special_spells_style.padding = 0 + special_spells_style.left_padding = 10 + special_spells_style.horizontal_align = 'left' + special_spells_style.font_color = {0.55, 0.55, 0.99} + + local special_spell_grid = special_spell_pane.add({type = 'table', column_count = 1}) + + for _, entity in pairs(spells) do + if entity.type == 'special' then + local text = 'requires ' .. entity.mana_cost .. ' mana to cast. Level: ' .. entity.level + create_custom_label_element(special_spell_grid, entity.sprite, entity.name, text) + end + end + end + + player.opened = main_frame +end diff --git a/modules/rpg/spells.lua b/modules/rpg/spells.lua index fc23187c..b5ed4493 100644 --- a/modules/rpg/spells.lua +++ b/modules/rpg/spells.lua @@ -1,11 +1,128 @@ local Public = require 'modules.rpg.table' +local Token = require 'utils.token' +local Task = require 'utils.task' local spells = {} local random = math.random +local floor = math.floor + +local states = { + ['attack'] = 'nuclear-smoke', + ['support'] = 'poison-capsule-smoke' +} + +local repair_buildings = + Token.register( + function(data) + local entity = data.entity + if entity and entity.valid then + local rng = 0.1 + if random(1, 5) == 1 then + rng = 0.2 + elseif random(1, 8) == 1 then + rng = 0.4 + end + local to_heal = entity.prototype.max_health * rng + if entity.health and to_heal then + entity.health = entity.health + to_heal + end + end + end +) + +local function get_area(pos, dist) + local area = { + left_top = { + x = pos.x - dist, + y = pos.y - dist + }, + right_bottom = { + x = pos.x + dist, + y = pos.y + dist + } + } + return area +end + +local function area_of_effect(player, position, state, radius, callback, find_entities) + if not radius then + return + end + + local cs = player.surface + local cp = position or player.position + + if radius and radius > 256 then + radius = 256 + end + + local area = get_area(cp, radius) + + if not states[state] then + return + end + + for x = area.left_top.x, area.right_bottom.x, 1 do + for y = area.left_top.y, area.right_bottom.y, 1 do + local d = floor((cp.x - x) ^ 2 + (cp.y - y) ^ 2) + if d < radius then + local p = {x = x, y = y} + if find_entities then + for _, e in pairs(cs.find_entities_filtered({position = p})) do + if e and e.valid and e.name ~= 'character' and e.health and e.destructible and e.type ~= 'simple-entity' and e.type ~= 'simple-entity-with-owner' then + callback(e, p) + end + end + else + callback(p) + end + + cs.create_trivial_smoke({name = states[state], position = p}) + end + end + end +end + +local restore_movement_speed_token = + Token.register( + function(event) + local player_index = event.player_index + local old_speed = event.old_speed + local rpg_t = event.rpg_t + + if rpg_t then + rpg_t.has_custom_spell_active = nil + end + + local player = game.get_player(player_index) + if not player or not player.valid then + return + end + + player.character.character_running_speed_modifier = old_speed + end +) + +local function do_projectile(player_surface, name, _position, _force, target, max_range) + player_surface.create_entity( + { + name = name, + position = _position, + force = _force, + source = _position, + target = target or nil, + max_range = max_range or nil, + speed = 0.4, + fast_replace = true, + create_build_effect_smoke = false + } + ) +end local function create_projectiles(data) local self = data.self local player = data.player + local rpg_t = data.rpg_t local damage_entity = data.damage_entity local position = data.position local surface = data.surface @@ -13,22 +130,12 @@ local function create_projectiles(data) local target_pos = data.target_pos local range = data.range - local function do_projectile(player_surface, name, _position, _force, target, max_range) - player_surface.create_entity( - { - name = name, - position = _position, - force = _force, - source = _position, - target = target, - max_range = max_range, - speed = 0.4 - } - ) - end - if self.aoe then for _ = 1, self.amount do + if self.mana_cost > rpg_t.mana then + break + end + local damage_area = { left_top = {x = position.x - 2, y = position.y - 2}, right_bottom = {x = position.x + 2, y = position.y + 2} @@ -37,6 +144,7 @@ local function create_projectiles(data) if self.damage then for _, e in pairs(surface.find_entities_filtered({area = damage_area})) do damage_entity(e) + Public.remove_mana(player, self.mana_cost) end end end @@ -46,14 +154,16 @@ local function create_projectiles(data) right_bottom = {x = position.x + 2, y = position.y + 2} } do_projectile(surface, self.entityName, position, force, target_pos, range) + if self.damage then for _, e in pairs(surface.find_entities_filtered({area = damage_area})) do damage_entity(e) + Public.remove_mana(player, self.mana_cost) end end end + Public.cast_spell(player) - Public.remove_mana(player, self.mana_cost) end local function create_entity(data) @@ -93,8 +203,8 @@ local function create_entity(data) Public.remove_mana(player, self.mana_cost) end end + Public.cast_spell(player) - Public.remove_mana(player, self.mana_cost) end local function insert_onto(data) @@ -520,7 +630,7 @@ spells[#spells + 1] = { mana_cost = 100, tick = 100, enabled = true, - sprite = 'recipe/explosives', + sprite = 'recipe=explosives', callback = function(data) local self = data.self local player = data.player @@ -561,13 +671,31 @@ spells[#spells + 1] = { mana_cost = 150, tick = 100, enabled = true, - sprite = 'recipe/repair-pack', + sprite = 'recipe=repair-pack', callback = function(data) local self = data.self + local rpg_t = data.rpg_t local player = data.player local position = data.position - Public.repair_aoe(player, position) + local range = Public.get_area_of_effect_range(player) + + area_of_effect( + player, + position, + 'support', + range, + function(entity) + if entity.prototype.max_health ~= entity.health then + if self.mana_cost < rpg_t.mana then + Task.set_timeout_in_ticks(10, repair_buildings, {entity = entity}) + Public.remove_mana(player, self.mana_cost) + end + end + end, + true + ) + Public.cast_spell(player) Public.remove_mana(player, self.mana_cost) end @@ -585,9 +713,30 @@ spells[#spells + 1] = { mana_cost = 70, tick = 100, enabled = true, - sprite = 'virtual-signal/signal-S', + sprite = 'virtual-signal=signal-S', callback = function(data) - create_projectiles(data) + local self = data.self + local rpg_t = data.rpg_t + local player = data.player + local position = data.position + + local range = Public.get_area_of_effect_range(player) + + area_of_effect( + player, + position, + 'attack', + range, + function(p) + if self.mana_cost < rpg_t.mana then + do_projectile(player.surface, 'acid-stream-spitter-big', p, player.force, p) + Public.remove_mana(player, self.mana_cost) + end + end, + false + ) + + Public.cast_spell(player) end } spells[#spells + 1] = { @@ -601,7 +750,7 @@ spells[#spells + 1] = { mana_cost = 10000, -- they who know, will know tick = 320, enabled = false, - sprite = 'entity/tank', + sprite = 'entity=tank', callback = function(data) create_entity(data) end @@ -617,7 +766,7 @@ spells[#spells + 1] = { mana_cost = 19500, -- they who know, will know tick = 320, enabled = false, - sprite = 'entity/spidertron', + sprite = 'entity=spidertron', callback = function(data) create_entity(data) end @@ -636,7 +785,7 @@ spells[#spells + 1] = { mana_cost = 140, tick = 320, enabled = true, - sprite = 'item/raw-fish', + sprite = 'item=raw-fish', callback = function(data) insert_onto(data) end @@ -655,7 +804,7 @@ spells[#spells + 1] = { mana_cost = 140, tick = 320, enabled = true, - sprite = 'item/explosives', + sprite = 'item=explosives', callback = function(data) insert_onto(data) end @@ -673,7 +822,7 @@ spells[#spells + 1] = { mana_cost = 150, tick = 320, enabled = true, - sprite = 'entity/compilatron', + sprite = 'entity=compilatron', callback = function(data) local self = data.self local player = data.player @@ -698,7 +847,7 @@ spells[#spells + 1] = { mana_cost = 220, tick = 320, enabled = true, - sprite = 'recipe/distractor-capsule', + sprite = 'recipe=distractor-capsule', callback = function(data) create_projectiles(data) end @@ -713,7 +862,7 @@ spells[#spells + 1] = { mana_cost = 340, tick = 2000, enabled = true, - sprite = 'virtual-signal/signal-W', + sprite = 'virtual-signal=signal-W', callback = function(data) local player = data.player local surface = data.surface @@ -731,6 +880,93 @@ spells[#spells + 1] = { Public.cast_spell(player) end } +spells[#spells + 1] = { + name = {'spells.charge'}, + entityName = 'haste', + target = false, + force = 'player', + level = 25, + type = 'special', + mana_cost = 100, + tick = 2000, + check_if_active = true, + enabled = true, + sprite = 'virtual-signal=signal-info', + callback = function(data) + local self = data.self + local player = data.player + local rpg_t = data.rpg_t + rpg_t.has_custom_spell_active = true + + Public.remove_mana(player, self.mana_cost) + for _ = 1, 3 do + player.play_sound {path = 'utility/armor_insert', volume_modifier = 1} + end + + Task.set_timeout_in_ticks(300, restore_movement_speed_token, {player_index = player.index, old_speed = player.character.character_running_speed_modifier, rpg_t = rpg_t}) + player.character.character_running_speed_modifier = player.character.character_running_speed_modifier + 1 + Public.cast_spell(player) + end +} +spells[#spells + 1] = { + name = {'spells.eternal_blades'}, + entityName = 'eternal_blades', + target = false, + force = 'player', + level = 25, + type = 'special', + mana_cost = 100, + tick = 2000, + check_if_active = true, + enabled = false, + sprite = 'virtual-signal=signal-info', + callback = function(data) + local self = data.self + local player = data.player + local position = data.position + + local range = Public.get_area_of_effect_range(player) + + local damage = 34 + + area_of_effect( + player, + position, + 'attack', + range, + function(entity) + if entity.force.index ~= player.force.index then + local get_health_pool = Public.has_health_boost(entity, damage, damage, player.character) + if get_health_pool then + local max_unit_health = floor(get_health_pool * 0.00015) + if max_unit_health <= 0 then + max_unit_health = 4 + end + if max_unit_health >= 10 then + max_unit_health = 10 + end + local final = floor(damage * max_unit_health) + Public.set_health_boost(entity, final, player.character) + if entity.valid and entity.health <= 0 and get_health_pool <= 0 then + entity.die(entity.force.name, player.character) + end + else + if entity.valid then + entity.health = entity.health - damage * 0.05 + if entity.health <= 0 then + entity.die(entity.force.name, player.character) + end + end + end + end + end, + true + ) + + Public.cast_spell(player) + Public.remove_mana(player, self.mana_cost) + end +} Public.projectile_types = { ['explosives'] = {name = 'grenade', count = 0.5, max_range = 32, tick_speed = 1}, @@ -772,7 +1008,7 @@ Public.projectile_types = { } Public.get_projectiles = Public.projectile_types -Public.spells = spells +Public.all_spells = spells --- Retrieves the spells table or a given spell. ---@param key string @@ -780,10 +1016,10 @@ function Public.get_spells(key) if game then return error('Calling Public.get_spells() after on_init() or on_load() has run is a desync risk.', 2) end - if Public.spells[key] then - return Public.spells[key] + if Public.all_spells[key] then + return Public.all_spells[key] else - return Public.spells + return Public.all_spells end end @@ -798,10 +1034,10 @@ function Public.disable_spell(key) if type(key) == 'table' then for _, k in pairs(key) do - Public.spells[k].enabled = false + Public.all_spells[k].enabled = false end - elseif Public.spells[key] then - Public.spells[key].enabled = false + elseif Public.all_spells[key] then + Public.all_spells[key].enabled = false end end @@ -811,7 +1047,7 @@ function Public.clear_spell_table() return error('Calling Public.clear_spell_table() after on_init() or on_load() has run is a desync risk.', 2) end - Public.spells = {} + Public.all_spells = {} end --- Adds a spell to the rpg_spells @@ -859,7 +1095,7 @@ function Public.set_new_spell(tbl) return error('A spell requires enabled. boolean', 2) end - Public.spells[#Public.spells + 1] = tbl + Public.all_spells[#Public.all_spells + 1] = tbl end end @@ -894,7 +1130,7 @@ function Public.disable_cooldowns_on_spells() end end - Public.spells = new_spells + Public.all_spells = new_spells return new_spells end diff --git a/modules/rpg/table.lua b/modules/rpg/table.lua index 51e4c80e..60105d77 100644 --- a/modules/rpg/table.lua +++ b/modules/rpg/table.lua @@ -10,6 +10,9 @@ local this = { --! Gui Frames local settings_frame_name = Gui.uid_name() +local settings_tooltip_frame = Gui.uid_name() +local close_settings_tooltip_frame = Gui.uid_name() +local settings_tooltip_name = Gui.uid_name() local save_button_name = Gui.uid_name() local discard_button_name = Gui.uid_name() local draw_main_frame_name = Gui.uid_name() @@ -43,7 +46,6 @@ Public.gui_settings_levels = { ['reset_text_label'] = 50, ['stone_path_label'] = 20, ['aoe_punch_label'] = 30, - ['flameboots_label'] = 100, ['explosive_bullets_label'] = 50 } @@ -103,7 +105,6 @@ function Public.reset_table() this.rpg_extra.enable_mana = false this.rpg_extra.mana_limit = 100000 this.rpg_extra.enable_wave_defense = false - this.rpg_extra.enable_flame_boots = false this.rpg_extra.enable_explosive_bullets = false this.rpg_extra.enable_explosive_bullets_globally = false this.rpg_extra.enable_range_buffs = false @@ -294,14 +295,6 @@ function Public.enable_wave_defense(value) return this.rpg_extra.enable_wave_defense end ---- Enables/disabled flame boots. ----@param value boolean -function Public.enable_flame_boots(value) - this.rpg_extra.enable_flame_boots = value or false - - return this.rpg_extra.enable_flame_boots -end - --- Enables/disabled explosive bullets globally. ---@param value boolean function Public.enable_explosive_bullets_globally(value) @@ -396,6 +389,9 @@ function Public.tweaked_crafting_items(tbl) end Public.settings_frame_name = settings_frame_name +Public.settings_tooltip_frame = settings_tooltip_frame +Public.close_settings_tooltip_frame = close_settings_tooltip_frame +Public.settings_tooltip_name = settings_tooltip_name Public.save_button_name = save_button_name Public.discard_button_name = discard_button_name Public.draw_main_frame_name = draw_main_frame_name diff --git a/modules/show_inventory.lua b/modules/show_inventory.lua index 0a384eee..6d5deb16 100644 --- a/modules/show_inventory.lua +++ b/modules/show_inventory.lua @@ -483,7 +483,7 @@ commands.add_command( if validate_player(target_player) then open_inventory(player, target_player) else - player.print('Please type a name of a player who is connected.', Color.warning) + player.print('[Inventory] Please type a name of a player who is connected.', Color.warning) end else return diff --git a/modules/wave_defense/gui.lua b/modules/wave_defense/gui.lua index 3af97de2..5b1f8409 100644 --- a/modules/wave_defense/gui.lua +++ b/modules/wave_defense/gui.lua @@ -76,6 +76,9 @@ function Public.update_gui(player) biter_health_boost = biter_health_boosts end + local paused = Public.get('paused') + local paused_waves_for = Public.get('paused_waves_for') + local last_pause = Public.get('last_pause') local wave_number = Public.get('wave_number') local next_wave = Public.get('next_wave') local last_wave = Public.get('last_wave') @@ -84,19 +87,38 @@ function Public.update_gui(player) local enable_threat_log = Public.get('enable_threat_log') gui.label.caption = {'wave_defense.gui_2'} - gui.wave_number.caption = wave_number - if wave_number == 0 then - gui.label.caption = {'wave_defense.gui_1'} - gui.wave_number.caption = floor((next_wave - game.tick) / 60) + 1 + if not paused then + gui.wave_number.caption = wave_number + if wave_number == 0 then + gui.label.caption = {'wave_defense.gui_1'} + gui.wave_number.caption = floor((next_wave - game.tick) / 60) + 1 .. 's' + end + local interval = next_wave - last_wave + local value = 1 - (next_wave - game.tick) / interval + if value < 0 then + value = 0 + elseif value > 1 then + value = 1 + end + gui.progressbar.value = value + else + gui.label.caption = {'wave_defense.gui_4'} + local pause_for = floor((paused_waves_for - game.tick) / 60) + 1 + if pause_for < 0 then + pause_for = 0 + end + gui.wave_number.caption = pause_for .. 's' + + local interval = paused_waves_for - last_pause + local value = 1 - (paused_waves_for - game.tick) / interval + if value < 0 then + value = 0 + elseif value > 1 then + value = 1 + end + gui.progressbar.value = value + return end - local interval = next_wave - last_wave - local value = 1 - (next_wave - game.tick) / interval - if value < 0 then - value = 0 - elseif value > 1 then - value = 1 - end - gui.progressbar.value = value gui.threat.caption = {'wave_defense.gui_3'} gui.threat.tooltip = {'wave_defense.tooltip_1', biter_health_boost * 100, max_active_biters} diff --git a/modules/wave_defense/main.lua b/modules/wave_defense/main.lua index dab67837..65f871d3 100644 --- a/modules/wave_defense/main.lua +++ b/modules/wave_defense/main.lua @@ -294,7 +294,7 @@ local function get_random_close_spawner() local center = target.position local spawner local retries = 0 - for i = 1, get_random_close_spawner_attempts, 1 do + for _ = 1, get_random_close_spawner_attempts, 1 do ::retry:: if #generated_units.nests < 1 then return false @@ -309,11 +309,7 @@ local function get_random_close_spawner() end goto retry end - if - not spawner or - (center.x - spawner_2.position.x) ^ 2 + (center.y - spawner_2.position.y) ^ 2 < - (center.x - spawner.position.x) ^ 2 + (center.y - spawner.position.y) ^ 2 - then + if not spawner or (center.x - spawner_2.position.x) ^ 2 + (center.y - spawner_2.position.y) ^ 2 < (center.x - spawner.position.x) ^ 2 + (center.y - spawner.position.y) ^ 2 then spawner = spawner_2 if spawner and spawner.position then debug_print('get_random_close_spawner - Found at x' .. spawner.position.x .. ' y' .. spawner.position.y) @@ -365,9 +361,7 @@ local function set_main_target() end Public.set('target', sec_target) - debug_print( - 'set_main_target -- New main target ' .. sec_target.name .. ' at position x' .. sec_target.position.x .. ' y' .. sec_target.position.y .. ' selected.' - ) + debug_print('set_main_target -- New main target ' .. sec_target.name .. ' at position x' .. sec_target.position.x .. ' y' .. sec_target.position.y .. ' selected.') end local function set_group_spawn_position(surface) @@ -644,7 +638,7 @@ local function reform_group(group) local position = group.surface.find_non_colliding_position('biter-spawner', group_position, step_length, 4) if position then local new_group = group.surface.create_unit_group {position = position, force = group.force} - for key, biter in pairs(group.members) do + for _, biter in pairs(group.members) do new_group.add_member(biter) end debug_print('Creating new unit group, because old one was stuck.') @@ -684,7 +678,7 @@ local function get_side_targets(group) local distance_to_target = floor(sqrt((target_position.x - group_position.x) ^ 2 + (target_position.y - group_position.y) ^ 2)) local steps = floor(distance_to_target / step_length) + 1 - for i = 1, steps, 1 do + for _ = 1, steps, 1 do local old_position = group_position local obstacles = group.surface.find_entities_filtered { @@ -740,7 +734,7 @@ local function get_main_command(group) debug_print('get_commmands - distance_to_target:' .. distance_to_target .. ' steps:' .. steps) debug_print('get_commmands - vector ' .. vector[1] .. '_' .. vector[2]) - for i = 1, steps, 1 do + for _ = 1, steps, 1 do local old_position = group_position group_position.x = group_position.x + vector[1] group_position.y = group_position.y + vector[2] @@ -887,7 +881,7 @@ local function give_side_commands_to_group() end local generated_units = Public.get('generated_units') - for k, group in pairs(generated_units.unit_groups) do + for _, group in pairs(generated_units.unit_groups) do if type(group) ~= 'number' then if group.valid then command_to_side_target(group) @@ -905,7 +899,7 @@ local function give_main_command_to_group() end local generated_units = Public.get('generated_units') - for k, group in pairs(generated_units.unit_groups) do + for _, group in pairs(generated_units.unit_groups) do if type(group) ~= 'number' then if group.valid then if group.surface.index == target.surface.index then @@ -958,7 +952,7 @@ local function spawn_unit_group(fs, only_bosses) left_top = {spawn_position.x - radius, spawn_position.y - radius}, right_bottom = {spawn_position.x + radius, spawn_position.y + radius} } - for k, v in pairs(surface.find_entities_filtered {area = area, name = 'land-mine'}) do + for _, v in pairs(surface.find_entities_filtered {area = area, name = 'land-mine'}) do if v and v.valid then debug_print('spawn_unit_group - found land-mines') v.die() @@ -1033,7 +1027,7 @@ local function check_group_positions() return end - for k, group in pairs(generated_units.unit_groups) do + for _, group in pairs(generated_units.unit_groups) do if group.valid then local ugp = generated_units.unit_group_pos.positions if group.state == defines.group_state.finished then @@ -1095,8 +1089,13 @@ Event.on_nth_tick( local paused = Public.get('paused') if paused then + local players = game.connected_players + for _, player in pairs(players) do + Public.update_gui(player) + end return end + local enable_grace_time = Public.get('enable_grace_time') if enable_grace_time and (not enable_grace_time.enabled) then if not enable_grace_time.set then diff --git a/modules/wave_defense/pause_waves.lua b/modules/wave_defense/pause_waves.lua index 1a1e5ad2..8d1b93c1 100644 --- a/modules/wave_defense/pause_waves.lua +++ b/modules/wave_defense/pause_waves.lua @@ -114,14 +114,31 @@ local function pause_waves_state(state) if state then game.print('[color=blue][Wave Defense][/color] New waves will not spawn for 5 minutes!', {r = 0.98, g = 0.66, b = 0.22}) Public.set('paused', true) + Public.set('last_pause', game.tick) + Public.set('paused_waves_for', game.tick + 18000) + + local next_wave = Public.get('next_wave') + Public.set('next_wave', next_wave + 18000) else game.print('[color=blue][Wave Defense][/color] Waves will spawn normally again.', {r = 0.98, g = 0.66, b = 0.22}) Public.set('paused', false) + Public.set('paused_waves_for', nil) + Public.set('last_pause', nil) end end local pause_waves_state_token = Token.register(pause_waves_state) +function Public.toggle_pause_wave() + local greeting = random_greetings[random(1, random_greetings_size)] + + local players = game.connected_players + for i = 1, #players do + local player = players[i] + Public.display_pause_wave(player, greeting) + end +end + Gui.on_click( save_button_name, function(event) @@ -203,12 +220,34 @@ Event.on_nth_tick( return end - local greeting = random_greetings[random(1, random_greetings_size)] + local paused = Public.get('paused') + if paused then + return + end - local players = game.connected_players - for i = 1, #players do - local player = players[i] - Public.display_pause_wave(player, greeting) + Public.toggle_pause_wave() + end +) + +commands.add_command( + 'wave_defense_pause_waves', + 'Usable only for admins - pauses the wave defense waves!', + function() + local player = game.player + + if player and player.valid then + if not player.admin then + return + end + + local paused = Public.get('paused') + if paused then + return + end + + print('[Wave Defense] ' .. player.name .. ' paused wave defense.') + + Public.toggle_pause_wave() end end ) diff --git a/utils/commands/where.lua b/utils/commands/where.lua index 27d49091..810b2d9e 100644 --- a/utils/commands/where.lua +++ b/utils/commands/where.lua @@ -91,7 +91,7 @@ local function create_mini_camera_gui(player, caption, position, surface) player_data.target_player = target_player else remove_player_data(player) - player.print('Please type a name of a player who is connected.', Color.warning) + player.print('[Where] Please type a name of a player who is connected.', Color.warning) return end @@ -140,7 +140,7 @@ commands.add_command( create_mini_camera_gui(player, target_player.name, target_player.position, target_player.surface.index) else remove_player_data(player) - player.print('Please type a name of a player who is connected.', Color.warning) + player.print('[Where] Please type a name of a player who is connected.', Color.warning) end else return diff --git a/utils/files/info.png b/utils/files/info.png new file mode 100644 index 00000000..dec20983 Binary files /dev/null and b/utils/files/info.png differ diff --git a/utils/gui.lua b/utils/gui.lua index 50887a62..3746ba10 100644 --- a/utils/gui.lua +++ b/utils/gui.lua @@ -41,6 +41,7 @@ Public.pin_black_icon = 'file/utils/files/pin-black.png' Public.infinite_icon = 'file/utils/files/infinity.png' Public.arrow_up_icon = 'file/utils/files/arrow-up.png' Public.arrow_down_icon = 'file/utils/files/arrow-down.png' +Public.info_icon = 'file/utils/files/info.png' function Public.uid_name() return tostring(Token.uid()) @@ -97,7 +98,7 @@ function Public.get_data(element) end -- Adds a gui that is alike the factorio native gui. -function Public.add_main_frame_with_toolbar(player, align, set_frame_name, set_settings_button_name, close_main_frame_name, name) +function Public.add_main_frame_with_toolbar(player, align, set_frame_name, set_settings_button_name, close_main_frame_name, name, info) if not align then return end @@ -132,19 +133,35 @@ function Public.add_main_frame_with_toolbar(player, align, set_frame_name, set_s widget.style.horizontally_stretchable = true if set_settings_button_name then - titlebar.add { - type = 'sprite-button', - name = set_settings_button_name, - style = 'frame_action_button', - sprite = Public.settings_white_icon, - mouse_button_filter = {'left'}, - hovered_sprite = Public.settings_black_icon, - clicked_sprite = Public.settings_black_icon, - tooltip = 'Settings', - tags = { - action = 'open_settings_gui' + if not info then + titlebar.add { + type = 'sprite-button', + name = set_settings_button_name, + style = 'frame_action_button', + sprite = Public.settings_white_icon, + mouse_button_filter = {'left'}, + hovered_sprite = Public.settings_black_icon, + clicked_sprite = Public.settings_black_icon, + tooltip = 'Settings', + tags = { + action = 'open_settings_gui' + } } - } + else + titlebar.add { + type = 'sprite-button', + name = set_settings_button_name, + style = 'frame_action_button', + sprite = Public.info_icon, + mouse_button_filter = {'left'}, + hovered_sprite = Public.info_icon, + clicked_sprite = Public.info_icon, + tooltip = 'Info', + tags = { + action = 'open_settings_gui' + } + } + end end if close_main_frame_name then @@ -166,7 +183,7 @@ function Public.add_main_frame_with_toolbar(player, align, set_frame_name, set_s local inside_frame = main_frame.add { type = 'frame', - style = 'b_inner_frame' + style = 'inside_shallow_frame' } local inside_frame_style = inside_frame.style @@ -453,6 +470,20 @@ function Public.clear_main_frame(player) end end +function Public.clear_all_center_frames(player) + for _, child in pairs(player.gui.center.children) do + child.destroy() + end +end + +function Public.clear_all_screen_frames(player) + for _, child in pairs(player.gui.screen.children) do + if not screen_elements[child.name] then + child.destroy() + end + end +end + function Public.clear_all_active_frames(player) for _, child in pairs(player.gui.left.children) do child.destroy() diff --git a/utils/gui/admin.lua b/utils/gui/admin.lua index 52f7d62a..5d5d1fb3 100644 --- a/utils/gui/admin.lua +++ b/utils/gui/admin.lua @@ -663,7 +663,7 @@ local function on_gui_click(event) return end if target_player_name == 'Select Player' then - player.print('No target player selected.', {r = 0.88, g = 0.88, b = 0.88}) + player.print('[AdminGui] No target player selected.', {r = 0.88, g = 0.88, b = 0.88}) return end local target_player = game.players[target_player_name] diff --git a/utils/gui/bottom_frame.lua b/utils/gui/bottom_frame.lua index 27c3f40e..44f98bd0 100644 --- a/utils/gui/bottom_frame.lua +++ b/utils/gui/bottom_frame.lua @@ -19,22 +19,10 @@ Global.register( local Public = {} -local bottom_guis_frame = Gui.uid_name() +local main_frame_name = Gui.uid_name() local clear_corpse_button_name = Gui.uid_name() local bottom_quickbar_button_name = Gui.uid_name() -function Public.toggle_player_frame(player, state) - local gui = player.gui - local frame = gui.screen[bottom_guis_frame] - if frame and frame.valid then - if state then - frame.visible = true - else - frame.visible = false - end - end -end - function Public.get_player_data(player, remove_user_data) if remove_user_data then if this.players[player.index] then @@ -43,9 +31,7 @@ function Public.get_player_data(player, remove_user_data) return end if not this.players[player.index] then - this.players[player.index] = { - hidden = false - } + this.players[player.index] = {} end return this.players[player.index] end @@ -69,9 +55,9 @@ function Public.set(key, value) end end -function Public.clear_data(player) - this.players[player.index] = nil - this.bottom_quickbar_button[player.index] = nil +function Public.remove_player(index) + this.players[index] = nil + this.bottom_quickbar_button[index] = nil end function Public.reset() @@ -91,15 +77,15 @@ end local function destroy_frame(player) local gui = player.gui - local frame = gui.screen[bottom_guis_frame] + local frame = gui.screen[main_frame_name] if frame and frame.valid then frame.destroy() end end -local function create_frame(player, alignment, location, portable, hidden) +local function create_frame(player, alignment, location, portable) local gui = player.gui - local frame = gui.screen[bottom_guis_frame] + local frame = gui.screen[main_frame_name] if frame and frame.valid then destroy_frame(player) end @@ -109,14 +95,18 @@ local function create_frame(player, alignment, location, portable, hidden) frame = player.gui.screen.add { type = 'frame', - name = bottom_guis_frame, + name = main_frame_name, direction = alignment } - if hidden then - frame.visible = false - else - frame.visible = true + local data = Public.get_player_data(player) + + if data.visible ~= nil then + if data.visible then + frame.visible = true + else + frame.visible = false + end end frame.style.padding = 3 @@ -171,6 +161,8 @@ local function set_location(player, state) local resolution = player.display_resolution local scale = player.display_scale + state = state or data.state + if state == 'bottom_left' then if data.above then location = { @@ -200,24 +192,21 @@ local function set_location(player, state) end data.bottom_state = 'bottom_right' else - Public.get_player_data(player, true) location = { x = (resolution.width / 2) - ((54 + -528) * scale), y = (resolution.height - (96 * scale)) } end - create_frame(player, alignment, location, data.portable, data.hidden) + data.state = state + + create_frame(player, alignment, location, data.portable) end --- Activates the custom buttons ---@param value boolean function Public.activate_custom_buttons(value) - if value then - this.activate_custom_buttons = value - else - this.activate_custom_buttons = false - end + this.activate_custom_buttons = value or false end --- Fetches if the custom buttons are activated @@ -239,9 +228,10 @@ Gui.on_click( Event.add( defines.events.on_player_joined_game, function(event) - local player = game.get_player(event.player_index) if this.activate_custom_buttons then - set_location(player) + local player = game.get_player(event.player_index) + local data = Public.get_player_data(player) + set_location(player, data.state) end end ) @@ -249,19 +239,10 @@ Event.add( Event.add( defines.events.on_player_display_resolution_changed, function(event) - local player = game.get_player(event.player_index) if this.activate_custom_buttons then - set_location(player) - end - end -) - -Event.add( - defines.events.on_player_respawned, - function(event) - local player = game.get_player(event.player_index) - if this.activate_custom_buttons then - set_location(player) + local player = game.get_player(event.player_index) + local data = Public.get_player_data(player) + set_location(player, data.state) end end ) @@ -271,7 +252,8 @@ Event.add( function(event) local player = game.get_player(event.player_index) if this.activate_custom_buttons then - set_location(player) + local data = Public.get_player_data(player) + set_location(player, data.state) end end ) @@ -281,12 +263,53 @@ Event.add( function(event) local player = game.get_player(event.player_index) destroy_frame(player) - Public.clear_data(player) end ) -Public.bottom_guis_frame = bottom_guis_frame +Event.add( + defines.events.on_pre_player_died, + function(event) + if this.activate_custom_buttons then + local player = game.get_player(event.player_index) + destroy_frame(player) + end + end +) + +Event.add( + defines.events.on_player_respawned, + function(event) + if this.activate_custom_buttons then + local player = game.get_player(event.player_index) + local data = Public.get_player_data(player) + set_location(player, data.state) + end + end +) + +Event.add( + defines.events.on_player_removed, + function(event) + Public.remove_player(event.player_index) + end +) + +function Public.toggle_player_frame(player, state) + local gui = player.gui + local frame = gui.screen[main_frame_name] + if frame and frame.valid then + local data = Public.get_player_data(player) + if state then + data.visible = true + frame.visible = true + else + data.visible = false + frame.visible = false + end + end +end +Public.main_frame_name = main_frame_name Public.set_location = set_location -Gui.screen_to_bypass(bottom_guis_frame) +Gui.screen_to_bypass(main_frame_name) return Public