diff --git a/maps/mountain_fortress_v3/mystical_chest.lua b/maps/mountain_fortress_v3/mystical_chest.lua index 098bdc06..5f011ac0 100644 --- a/maps/mountain_fortress_v3/mystical_chest.lua +++ b/maps/mountain_fortress_v3/mystical_chest.lua @@ -744,7 +744,7 @@ local mc_random_rewards = name = 'Movement bonus', str = 'movement', color = { r = 0.00, g = 0.25, b = 0.00 }, - tooltip = 'Selecting this will grant the team a bonus movement speed for 15 minutes!', + tooltip = 'Selecting this will grant the team a bonus movement speed for 30 minutes!', func = (function (player, zone) local mc_rewards = Public.get('mc_rewards') local force = game.forces.player @@ -757,7 +757,7 @@ local mc_random_rewards = mc_rewards.temp_boosts.movement = true - Task.set_timeout_in_ticks(54000, restore_movement_speed_token, { speed = force.character_running_speed_modifier }) + Task.set_timeout_in_ticks(108000, restore_movement_speed_token, { speed = force.character_running_speed_modifier }) local scale_factor = 0.5 + (zone / 10) local speed = 0.6 * scale_factor if speed > 1 then @@ -775,7 +775,7 @@ local mc_random_rewards = name = 'Mining bonus', str = 'mining', color = { r = 0.00, g = 0.00, b = 0.25 }, - tooltip = 'Selecting this will grant the team a bonus mining speed for 15 minutes!', + tooltip = 'Selecting this will grant the team a bonus mining speed for 30 minutes!', func = (function (player) local mc_rewards = Public.get('mc_rewards') local force = game.forces.player @@ -788,7 +788,7 @@ local mc_random_rewards = mc_rewards.temp_boosts.mining = true - Task.set_timeout_in_ticks(54000, restore_mining_speed_token) + Task.set_timeout_in_ticks(108000, restore_mining_speed_token) force.manual_mining_speed_modifier = force.manual_mining_speed_modifier + 1 local message = ({ 'locomotive.mining_bonus', player.name }) Alert.alert_all_players(15, message, nil, 'achievement/tech-maniac') @@ -801,7 +801,7 @@ local mc_random_rewards = name = 'Crafting speed bonus', str = 'crafting', color = { r = 0.00, g = 0.00, b = 0.25 }, - tooltip = 'Selecting this will grant all players 100% crafting bonus for 15 minutes!', + tooltip = 'Selecting this will grant all players 100% crafting bonus for 30 minutes!', func = (function (player) local mc_rewards = Public.get('mc_rewards') local force = game.forces.player @@ -814,7 +814,7 @@ local mc_random_rewards = mc_rewards.temp_boosts.crafting = true - Task.set_timeout_in_ticks(54000, restore_crafting_speed_token) + Task.set_timeout_in_ticks(108000, restore_crafting_speed_token) force.manual_crafting_speed_modifier = force.manual_crafting_speed_modifier + 2 local message = ({ 'locomotive.crafting_bonus', player.name }) Alert.alert_all_players(15, message, nil, 'achievement/tech-maniac') diff --git a/maps/mountain_fortress_v3/stateful/functions.lua b/maps/mountain_fortress_v3/stateful/functions.lua index c2a262d9..6be53077 100644 --- a/maps/mountain_fortress_v3/stateful/functions.lua +++ b/maps/mountain_fortress_v3/stateful/functions.lua @@ -5,6 +5,8 @@ local Stateful = require 'maps.mountain_fortress_v3.stateful.table' local Server = require 'utils.server' local Event = require 'utils.event' local Core = require 'utils.core' +local StatData = require 'utils.datastore.statistics' +local RPG = require 'modules.rpg.main' local math = math @@ -15,341 +17,377 @@ local main_frame_name = Gui.uid_name() local selection_button_name = Gui.uid_name() local function highest_count(tbl, fair_vote) - if #tbl == 0 then - return nil - end + if #tbl == 0 then + return nil + end - local highest = 0 - for _, v in ipairs(tbl) do - if v.count > highest then - highest = v.count - end - end + local highest = 0 + for _, v in ipairs(tbl) do + if v.count > highest then + highest = v.count + end + end - local winners = {} - for _, v in ipairs(tbl) do - if v.count == highest then - table.insert(winners, v.index) - end - end + local winners = {} + for _, v in ipairs(tbl) do + if v.count == highest then + table.insert(winners, v.index) + end + end - if #winners == 1 then - return winners[1] - end + if #winners == 1 then + return winners[1] + end - if #winners == 0 then - return nil - end + if #winners == 0 then + return nil + end - if fair_vote then - return winners[math.random(#winners)] - else - local sum = 0 - for _, idx in ipairs(winners) do - sum = sum + idx - end - return math.floor((sum / #winners) + 0.5) - end + if fair_vote then + return winners[math.random(#winners)] + else + local sum = 0 + for _, idx in ipairs(winners) do + sum = sum + idx + end + return math.floor((sum / #winners) + 0.5) + end end local function clear_main_frame(player) - local screen = player.gui.screen - if screen[main_frame_name] and screen[main_frame_name].valid then - screen[main_frame_name].destroy() - end + local screen = player.gui.screen + if screen[main_frame_name] and screen[main_frame_name].valid then + screen[main_frame_name].destroy() + end end local function buff_main_frame(player, voted_index) - if player.gui.screen[main_frame_name] then - clear_main_frame(player) - end + if player.gui.screen[main_frame_name] then + clear_main_frame(player) + end - local buff_selection = Public.get('buff_selection') - if not buff_selection or not next(buff_selection) then - return - end + local buff_selection = Public.get('buff_selection') + if not buff_selection or not next(buff_selection) then + return + end - if game.tick > buff_selection.closing_timeout then - return - end + if game.tick > buff_selection.closing_timeout then + return + end - local main_frame, inside_frame = Gui.add_main_frame_with_toolbar(player, 'screen', main_frame_name, nil, nil, 'Buff selection') - if not inside_frame then - return - end + local main_frame, inside_frame = Gui.add_main_frame_with_toolbar(player, 'screen', main_frame_name, nil, nil, 'Buff selection') + if not inside_frame then + return + end - main_frame.force_auto_center() + main_frame.force_auto_center() - for i = 1, #buff_selection.buffs, 1 do - local buff = buff_selection.buffs[i] - local button_flow = - inside_frame.add - { - type = 'flow', - name = tostring(i), - direction = 'horizontal' - } - button_flow.style.horizontal_align = 'center' - button_flow.style.horizontally_stretchable = true - local b = button_flow.add({ type = 'button', name = selection_button_name, caption = buff.name }) - b.style.horizontal_align = 'center' - b.style.vertical_align = 'center' - b.style.font_color = buff.color - b.style.font = 'heading-2' - b.tooltip = buff.tooltip - if voted_index and voted_index == i then - b.enabled = false - b.tooltip = b.tooltip .. '\nYou have already voted for this buff.' - end - end + for i = 1, #buff_selection.buffs, 1 do + local buff = buff_selection.buffs[i] + local button_flow = + inside_frame.add + { + type = 'flow', + name = tostring(i), + direction = 'horizontal' + } + button_flow.style.horizontal_align = 'center' + button_flow.style.horizontally_stretchable = true + local b = button_flow.add({ type = 'button', name = selection_button_name, caption = buff.name }) + b.style.horizontal_align = 'center' + b.style.vertical_align = 'center' + b.style.font_color = buff.color + b.style.font = 'heading-2' + b.tooltip = buff.tooltip + if voted_index and voted_index == i then + b.enabled = false + b.tooltip = b.tooltip .. '\nYou have already voted for this buff.' + end + end - local label_flow = - inside_frame.add - { - type = 'flow' - } + local label_flow = + inside_frame.add + { + type = 'flow' + } - inside_frame.add({ type = 'line' }) + inside_frame.add({ type = 'line' }) - label_flow.style.horizontal_align = 'center' - label_flow.style.horizontally_stretchable = true + label_flow.style.horizontal_align = 'center' + label_flow.style.horizontally_stretchable = true - local timer_flow = - inside_frame.add - { - type = 'flow' - } - timer_flow.style.horizontal_align = 'center' - timer_flow.style.horizontally_stretchable = true + local timer_flow = + inside_frame.add + { + type = 'flow' + } + timer_flow.style.horizontal_align = 'center' + timer_flow.style.horizontally_stretchable = true - local b = - timer_flow.add( - { - type = 'button', - caption = math.floor((buff_selection.closing_timeout - game.tick) / 3600) .. ' minutes left until voting closes.' - } - ) - b.style.font_color = { r = 0.66, g = 0.0, b = 0.66 } - b.style.font = 'default-semibold' - b.style.minimal_width = 96 - b.enabled = false + local b = + timer_flow.add( + { + type = 'button', + caption = math.floor((buff_selection.closing_timeout - game.tick) / 3600) .. ' minutes left until voting closes.' + } + ) + b.style.font_color = { r = 0.66, g = 0.0, b = 0.66 } + b.style.font = 'default-semibold' + b.style.minimal_width = 96 + b.enabled = false - Gui.set_data(main_frame, b) + Gui.set_data(main_frame, b) - inside_frame.add({ type = 'line' }) + inside_frame.add({ type = 'line' }) end local function set_buffs_voting() - local buff_selection = Public.get('buff_selection') - if not buff_selection or not next(buff_selection) then - return - end + local buff_selection = Public.get('buff_selection') + if not buff_selection or not next(buff_selection) then + return + end - local index = highest_count(buff_selection.buffs) - if not index or not buff_selection.buffs[index] then - return - end + local index = highest_count(buff_selection.buffs) + if not index or not buff_selection.buffs[index] then + return + end - if buff_selection.index ~= index then - local message = table.concat({ '*** Current buff has changed to ', buff_selection.buffs[index].name, '! ***' }) - game.print(message, { color = buff_selection.buffs[index].print_color }) - end - buff_selection.index = index - buff_selection.name = buff_selection.buffs[index].name - buff_selection.value = buff_selection.buffs[index].value + if buff_selection.index ~= index then + local message = table.concat({ '*** Current buff has changed to ', buff_selection.buffs[index].name, '! ***' }) + game.print(message, { color = buff_selection.buffs[index].print_color }) + end + buff_selection.index = index + buff_selection.name = buff_selection.buffs[index].name + buff_selection.value = buff_selection.buffs[index].value end Gui.on_click( - selection_button_name, - function (event) - local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Poll buff selection frame name') - if is_spamming then - return - end - local element = event.element - if not element or not element.valid then - return - end + selection_button_name, + function (event) + local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Poll buff selection frame name') + if is_spamming then + return + end + local element = event.element + if not element or not element.valid then + return + end - local player = event.player - if not player or not player.valid then - return - end + local player = event.player + if not player or not player.valid then + return + end - local buff_selection = Public.get('buff_selection') - if not buff_selection or not next(buff_selection) then - return - end + local buff_selection = Public.get('buff_selection') + if not buff_selection or not next(buff_selection) then + return + end - local i = tonumber(element.parent.name) + local i = tonumber(element.parent.name) - if game.tick > buff_selection.closing_timeout then - clear_main_frame(player) - return - end + if game.tick > buff_selection.closing_timeout then + clear_main_frame(player) + return + end - if buff_selection.all_votes[player.name] and buff_selection.all_votes[player.name].index == i then - player.print('You have already voted for ' .. buff_selection.buffs[i].name .. '.', { color = buff_selection.buffs[i].print_color }) - clear_main_frame(player) - return - end + if buff_selection.all_votes[player.name] and buff_selection.all_votes[player.name].index == i then + player.print('You have already voted for ' .. buff_selection.buffs[i].name .. '.', { color = buff_selection.buffs[i].print_color }) + clear_main_frame(player) + return + end - if buff_selection.all_votes[player.name] then - local index = buff_selection.all_votes[player.name].index - buff_selection.buffs[index].count = buff_selection.buffs[index].count - 1 - if buff_selection.buffs[index].count <= 0 then - buff_selection.buffs[index].count = 0 - end - end + if buff_selection.all_votes[player.name] then + local index = buff_selection.all_votes[player.name].index + buff_selection.buffs[index].count = buff_selection.buffs[index].count - 1 + if buff_selection.buffs[index].count <= 0 then + buff_selection.buffs[index].count = 0 + end + end - buff_selection.buffs[i].count = buff_selection.buffs[i].count + 1 - buff_selection.all_votes[player.name] = { voted = true, index = i } + buff_selection.buffs[i].count = buff_selection.buffs[i].count + 1 + buff_selection.all_votes[player.name] = { voted = true, index = i } - set_buffs_voting() - buff_main_frame(player, i) - clear_main_frame(player) - local message = '*** ' .. player.name .. ' has voted for ' .. buff_selection.buffs[i].name .. '! ***' - game.print(message, { color = buff_selection.buffs[i].print_color }) - end + set_buffs_voting() + buff_main_frame(player, i) + clear_main_frame(player) + local message = '*** ' .. player.name .. ' has voted for ' .. buff_selection.buffs[i].name .. '! ***' + game.print(message, { color = buff_selection.buffs[i].print_color }) + end ) local function get_random_color() - return { r = math.random(), g = math.random(), b = math.random() } + return { r = math.random(), g = math.random(), b = math.random() } end function Public.init_buff_selection(buffs) - local buff_selection = Public.get('buff_selection') - if not buff_selection or not buff_selection.buffs then - Server.output_script_data('buff_selection not found while initing buff selection - check stateful/table.lua') - return - end + local buff_selection = Public.get('buff_selection') + if not buff_selection or not buff_selection.buffs then + Server.output_script_data('buff_selection not found while initing buff selection - check stateful/table.lua') + return + end - if not buffs or #buffs == 0 then - Server.output_script_data('buffs not found while initing buff selection, buffs equals to zero') - return - end + if not buffs or #buffs == 0 then + Server.output_script_data('buffs not found while initing buff selection, buffs equals to zero') + return + end - buff_selection.closing_timeout = game.tick + 10800 -- 3 minutes + buff_selection.closing_timeout = game.tick + 10800 -- 3 minutes - for i = 1, #buffs, 1 do - local buff = buffs[i] - if not buff or not next(buff) then - Server.output_script_data('error while iterating buffs while initing buff selection') - return - end + for i = 1, #buffs, 1 do + local buff = buffs[i] + if not buff or not next(buff) then + Server.output_script_data('error while iterating buffs while initing buff selection') + return + end - buff_selection.buffs[#buff_selection.buffs + 1] = - { - name = buff.poll_name, - tooltip = buff.tooltip, - count = 0, - index = #buff_selection.buffs + 1, - color = get_random_color(), - print_color = get_random_color(), - raw = buff - } - end + buff_selection.buffs[#buff_selection.buffs + 1] = + { + name = buff.poll_name, + tooltip = buff.tooltip, + count = 0, + index = #buff_selection.buffs + 1, + color = get_random_color(), + print_color = get_random_color(), + raw = buff + } + end +end + +function Public.reward_goal_completion() + local adjusted_zones = Public.get('adjusted_zones') + local locomotive = Public.get('locomotive') + if not locomotive then + return + end + if not locomotive.valid then + return + end + + local zone = math.floor((math.abs(locomotive.position.y / Public.zone_settings.zone_depth)) % adjusted_zones.size) + 1 + + if math.random(1, 2) == 1 then + local players = game.connected_players + for i = 1, #players do + local rng = math.random(2048, 8192) + local scale_factor = 0.8 + (zone / 20) + rng = math.floor(rng * scale_factor) + local player = players[i] + if player and player.valid then + if player.can_insert({ name = 'coin', count = rng }) then + player.insert({ name = 'coin', count = rng }) + StatData.get_data(player):increase('coins', rng) + end + end + end + return 'Coins have been granted to the whole team' + else + local rng = math.random(8192, 16384) + local scale_factor = 0.8 + (zone / 20) + rng = math.floor(rng * scale_factor) + RPG.add_to_global_pool(rng) + return 'XP has been granted to the global pool' + end end function Public.set_multi_command_final_battle() - local active_surface_index = Public.get('active_surface_index') - if not active_surface_index then return end - local surface = game.get_surface(active_surface_index) - if not surface or not surface.valid then - return - end + local active_surface_index = Public.get('active_surface_index') + if not active_surface_index then return end + local surface = game.get_surface(active_surface_index) + if not surface or not surface.valid then + return + end - local locomotive = Public.get('locomotive') - if not locomotive or not locomotive.valid then - return - end + local locomotive = Public.get('locomotive') + if not locomotive or not locomotive.valid then + return + end - surface.set_multi_command( - { - command = - { - type = defines.command.attack, - target = locomotive, - distraction = defines.distraction.by_anything - }, - unit_count = 60, - force = 'aggressors', - unit_search_distance = 256 - } - ) + surface.set_multi_command( + { + command = + { + type = defines.command.attack, + target = locomotive, + distraction = defines.distraction.by_anything + }, + unit_count = 60, + force = 'aggressors', + unit_search_distance = 256 + } + ) end Event.on_nth_tick(60, function () - local buff_selection = Public.get('buff_selection') - if not buff_selection or not next(buff_selection) then - return - end + local buff_selection = Public.get('buff_selection') + if not buff_selection or not next(buff_selection) then + return + end - if not buff_selection.voting_started then - return - end + if not buff_selection.voting_started then + return + end - Core.iter_connected_players(function (player) - if player and player.valid then - if not buff_selection.voting_closed then - local frame = player.gui.screen[main_frame_name] - if not frame or not frame.valid then - local voted_index = buff_selection.all_votes[player.name] and buff_selection.all_votes[player.name].index - buff_main_frame(player, voted_index) - else - local b = Gui.get_data(frame) - if b then - local minutes = math.floor((buff_selection.closing_timeout - game.tick) / 3600) - local minutes_str = minutes .. ' minutes left until voting closes.' - if minutes == 0 then - minutes_str = 'Less than 1 minute left until voting closes!' - elseif minutes == 1 then - minutes_str = 'Voting closes in 1 minute!' - end - b.caption = minutes_str - end - end - else - clear_main_frame(player) - end - end - end) + Core.iter_connected_players(function (player) + if player and player.valid then + if not buff_selection.voting_closed then + local frame = player.gui.screen[main_frame_name] + if not frame or not frame.valid then + local voted_index = buff_selection.all_votes[player.name] and buff_selection.all_votes[player.name].index + buff_main_frame(player, voted_index) + else + local b = Gui.get_data(frame) + if b then + local minutes = math.floor((buff_selection.closing_timeout - game.tick) / 3600) + local minutes_str = minutes .. ' minutes left until voting closes.' + if minutes == 0 then + minutes_str = 'Less than 1 minute left until voting closes!' + elseif minutes == 1 then + minutes_str = 'Voting closes in 1 minute!' + end + b.caption = minutes_str + end + end + else + clear_main_frame(player) + end + end + end) - buff_selection.closing_timeout = buff_selection.closing_timeout - 1 + buff_selection.closing_timeout = buff_selection.closing_timeout - 1 - if game.tick > buff_selection.closing_timeout and not buff_selection.voting_closed then - buff_selection.voting_closed = true - set_buffs_voting() - local buff = buff_selection.buffs[buff_selection.index] - if not buff then - Server.output_script_data('buff not found while voting closed') + if game.tick > buff_selection.closing_timeout and not buff_selection.voting_closed then + buff_selection.voting_closed = true + set_buffs_voting() + local buff = buff_selection.buffs[buff_selection.index] + if not buff then + Server.output_script_data('buff not found while voting closed') - local buff_fallback = Stateful.save_settings() - Public.notify_won_to_discord(buff_fallback) - local locomotive = Public.get('locomotive') - if locomotive and locomotive.valid then - locomotive.surface.spill_item_stack({ position = locomotive.position, stack = { name = 'coin', count = 512, quality = 'normal' } }) - end - Public.set('game_reset_tick', 5400) + local buff_fallback = Stateful.save_settings() + Public.notify_won_to_discord(buff_fallback) + local locomotive = Public.get('locomotive') + if locomotive and locomotive.valid then + locomotive.surface.spill_item_stack({ position = locomotive.position, stack = { name = 'coin', count = 512, quality = 'normal' } }) + end + Public.set('game_reset_tick', 5400) - Server.output_script_data('fallback buff granted') - return - end + Server.output_script_data('fallback buff granted') + return + end - local str = 'Votes have closed! Buff granted: ' .. buff.name .. '!' - game.print(str) - Server.to_discord_embed(str) - Public.set('game_reset_tick', 5400) - Public.notify_won_to_discord(buff.raw) - local locomotive = Public.get('locomotive') - if locomotive and locomotive.valid then - locomotive.surface.spill_item_stack({ position = locomotive.position, stack = { name = 'coin', count = 512, quality = 'normal' } }) - end + local str = 'Votes have closed! Buff granted: ' .. buff.name .. '!' + game.print(str) + Server.to_discord_embed(str) + Public.set('game_reset_tick', 5400) + Public.notify_won_to_discord(buff.raw) + local locomotive = Public.get('locomotive') + if locomotive and locomotive.valid then + locomotive.surface.spill_item_stack({ position = locomotive.position, stack = { name = 'coin', count = 512, quality = 'normal' } }) + end - Stateful.save_settings(buff.raw) + Stateful.save_settings(buff.raw) - return - end + return + end end) Public.buff_main_frame = buff_main_frame diff --git a/maps/mountain_fortress_v3/stateful/gui.lua b/maps/mountain_fortress_v3/stateful/gui.lua index 9402e0d0..7944f6fd 100644 --- a/maps/mountain_fortress_v3/stateful/gui.lua +++ b/maps/mountain_fortress_v3/stateful/gui.lua @@ -1120,8 +1120,9 @@ local function update_raw() stateful.objectives_completed.randomized_zone = true stateful.objectives_time_spent.randomized_zone = tick play_achievement_unlocked() - Alert.alert_all_players(100, 'Objective: [color=blue]Breach zone[/color] has been completed!') - Server.to_discord_embed('Objective: **Breach zone** has been completed!') + local reward = Public.reward_goal_completion() + Alert.alert_all_players(100, 'Objective: [color=blue]Breach zone[/color] has been completed! ' .. reward .. '!') + Server.to_discord_embed('Objective: **Breach zone** has been completed! ' .. reward .. '!') stateful.objectives_completed_count = stateful.objectives_completed_count + 1 end end @@ -1145,8 +1146,9 @@ local function update_raw() if not stateful.objectives_completed.supplies then stateful.objectives_completed.supplies = true stateful.objectives_time_spent.supplies = tick - Alert.alert_all_players(100, 'Objective: [color=blue]Produce items[/color] has been completed!') - Server.to_discord_embed('Objective: **Produce items** has been completed!') + local reward = Public.reward_goal_completion() + Alert.alert_all_players(100, 'Objective: [color=blue]Produce items[/color] has been completed! ' .. reward .. '!') + Server.to_discord_embed('Objective: **Produce items** has been completed! ' .. reward .. '!') play_achievement_unlocked() stateful.objectives_completed_count = stateful.objectives_completed_count + 1 end @@ -1173,8 +1175,9 @@ local function update_raw() stateful.objectives_completed.single_item = true stateful.objectives_time_spent.single_item = tick play_achievement_unlocked() - Alert.alert_all_players(100, 'Objective: [color=blue]Produce item[/color] has been completed!') - Server.to_discord_embed('Objective: **Produce item** has been completed!') + local reward = Public.reward_goal_completion() + Alert.alert_all_players(100, 'Objective: [color=blue]Produce item[/color] has been completed! ' .. reward .. '!') + Server.to_discord_embed('Objective: **Produce item** has been completed! ' .. reward .. '!') stateful.objectives_completed_count = stateful.objectives_completed_count + 1 end end @@ -1317,8 +1320,9 @@ local function update_raw() if completed and completed == true and not stateful.objectives_completed[objective_name] then stateful.objectives_completed[objective_name] = true stateful.objectives_time_spent[objective_name] = tick - Alert.alert_all_players(100, 'Objective: [color=blue]' .. objective.discord .. '[/color] has been completed!') - Server.to_discord_embed('Objective: **' .. objective.discord .. '** has been completed!') + local reward = Public.reward_goal_completion() + Alert.alert_all_players(100, 'Objective: [color=blue]' .. objective.discord .. '[/color] has been completed! ' .. reward .. '!') + Server.to_discord_embed('Objective: **' .. objective.discord .. '** has been completed! ' .. reward .. '!') play_achievement_unlocked() stateful.objectives_completed_count = stateful.objectives_completed_count + 1 end diff --git a/modules/rpg/spells.lua b/modules/rpg/spells.lua index 71d510b5..7b806845 100644 --- a/modules/rpg/spells.lua +++ b/modules/rpg/spells.lua @@ -645,7 +645,7 @@ spells[#spells + 1] = } spells[#spells + 1] = { - name = { 'entity-name.big-sand-rock' }, + name = { 'entity-name.big-rock' }, entityName = 'big-sand-rock', raffle = rock_raffle, level = 60,