1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-08 00:39:30 +02:00

Merge pull request #48 from M3wM3w/master

update from main
This commit is contained in:
hanakocz 2021-02-02 02:07:09 +01:00 committed by GitHub
commit 6df0069a18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 244 additions and 163 deletions

View File

@ -37,7 +37,7 @@ global_pool_amount=Amount of XP that is stored inside the global xp pool.\nRaw V
amount_harvested=Amount of trees/rocks harvested.
biters_killed=Amount of biters killed.
land_mine_placed=Amount of land-mines that can be built.
chest_placed=Amount of chests that can be placed near train.
chest_placed=Amount of chests that can be placed near train.\nLimit is per cargo-wagon.
flamethrowers_placed=Amount of flamethrower-turrets that can be built.
train_upgrades=Amount of train upgrades.
info_tooltip=Shows statistics!
@ -86,12 +86,10 @@ purchase_pickaxe=Upgrade the teams Pickaxe to tier: __1__
sold_out=Sold out!
flamethrower_turret=Upgrades the amount of flamethrowers that can be placed.
land_mine=Upgrades the amount of landmines that can be placed.
skill_reset=For when you have picked the wrong RPG path and want to start over.\nPoints will be kept.
car=Portable Car Surface\nCan be killed easily.
tank=Portable Tank Surface\nChonk tank, can resist heavy damage.
tank_cannon_na=Tank Cannon\nAvailable after wave 650.
tank_machine_gun_na=Tank Machine Gun\nAvailable after wave 400.
vehicle_machine_gun_na=Car Machine Gun\nAvailable after wave 200.
tank_cannon_na=Tank Cannon\nAvailable after wave __1__.
vehicle_machine_gun_na=Car Machine Gun\nAvailable after wave __1__.
[main]
death_message_1=__1__ should have watched where they walked!

View File

@ -85,12 +85,10 @@ purchase_pickaxe=将团队镐升级到等级:__1__
sold_out=售罄!
flamethrower_turret=升级可以放置的火焰喷射器的数量.
land_mine=升级可以放置的地雷数量.
skill_reset=重置玩家技能点.\n将保留积分.
car=便携汽车操作\n可以更容易打死.
tank=便携坦克操作\n大坦克, 可以抵抗严重伤害.
tank_cannon_na=坦克炮\n在650波之后可用.
tank_machine_gun_na=坦克机枪\n在4000波之后可用.
vehicle_machine_gun_na=汽车机枪\n在200波后可用.
tank_cannon_na=坦克炮\n在__1__波之后可用.
vehicle_machine_gun_na=汽车机枪\n在__1__波后可用.
[main]
death_message_1=__1__ 应该看着他们走的地方!

View File

@ -48,7 +48,7 @@ local function enemy_weapon_damage()
local data = {
['artillery-shell'] = 0.05,
['biological'] = 0.08,
['biological'] = 0.06,
['bullet'] = 0.08,
['capsule'] = 0.08,
['electric'] = 0.08,

View File

@ -2,6 +2,7 @@ local Color = require 'utils.color_presets'
local Task = require 'utils.task'
local Server = require 'utils.server'
local WPT = require 'maps.mountain_fortress_v3.table'
local WD = require 'modules.wave_defense.table'
local mapkeeper = '[color=blue]Mapkeeper:[/color]'
@ -121,6 +122,41 @@ commands.add_command(
end
)
commands.add_command(
'disable_biters',
'Usable only for admins - sets the queue speed of this map!',
function(cmd)
local player = game.player
if not player and player.valid then
return
end
if not player.admin then
player.print("[ERROR] You're not admin!", Color.fail)
return
end
local this = WPT.get()
local tbl = WD.get()
if not this.disable_biters_are_you_sure then
this.disable_biters_are_you_sure = true
player.print('[WARNING] This command will disable the wave_defense in-game, run this command again if you really want to do this!', Color.warning)
return
end
if not tbl.game_lost then
game.print(mapkeeper .. ' ' .. player.name .. ', has disabled the wave_defense module!', {r = 0.98, g = 0.66, b = 0.22})
tbl.game_lost = true
else
game.print(mapkeeper .. ' ' .. player.name .. ', has enabled the wave_defense module!', {r = 0.98, g = 0.66, b = 0.22})
tbl.game_lost = false
end
this.disable_biters_are_you_sure = nil
end
)
commands.add_command(
'get_queue_speed',
'Usable only for admins - gets the queue speed of this map!',

View File

@ -78,7 +78,8 @@ local protect_types = {
['fluid-wagon'] = true,
['locomotive'] = true,
['reactor'] = true,
['spidertron'] = true
['spider-vehicle'] = true,
['car'] = true
}
local reset_game =
@ -211,12 +212,19 @@ local function set_train_final_health(final_damage_amount)
local locomotive_health = WPT.get('locomotive_health')
local locomotive_max_health = WPT.get('locomotive_max_health')
local poison_deployed = WPT.get('poison_deployed')
local robotics_deployed = WPT.get('robotics_deployed')
if locomotive_health <= 5000 then
if locomotive_health >= 4000 and locomotive_health <= 6000 then
if not poison_deployed then
for i = 1, 2, 1 do
Locomotive.enable_poison_defense()
local carriages = WPT.get('carriages')
if carriages then
for i = 1, #carriages do
local entity = carriages[i]
Locomotive.enable_poison_defense(entity.position)
end
end
local p = {
position = locomotive.position
}
@ -224,6 +232,25 @@ local function set_train_final_health(final_damage_amount)
Alert.alert_all_players_location(p, msg)
WPT.set().poison_deployed = true
end
elseif locomotive_health >= 1500 and locomotive_health <= 3900 then
if not robotics_deployed then
local carriages = WPT.get('carriages')
if carriages then
for _ = 1, 10 do
for i = 1, #carriages do
local entity = carriages[i]
Locomotive.enable_robotic_defense(entity.position)
end
end
end
local p = {
position = locomotive.position
}
local msg = ({'entity.train_taking_damage'})
Alert.alert_all_players_location(p, msg)
WPT.set().robotics_deployed = true
end
elseif locomotive_health >= locomotive_max_health then
WPT.set().poison_deployed = false
end
@ -283,22 +310,24 @@ local function protect_entities(event)
if (event.cause and event.cause.valid) then
if event.cause.force.index == 2 then
if units and units[entity.unit_number] then
return set_train_final_health(dmg)
end
elseif event.cause.force.index == 2 then
set_train_final_health(dmg)
return
else
entity.health = entity.health + dmg
end
elseif not (event.cause and event.cause.valid) then
if event.force.index == 2 then
if units and units[entity.unit_number] then
return set_train_final_health(dmg)
end
entity.health = entity.health - dmg
return
end
end
elseif not (event.cause and event.cause.valid) then
if event.force and event.force.index == 2 then
if units and units[entity.unit_number] then
set_train_final_health(dmg)
return
else
entity.health = entity.health - dmg
return
end
end
end
entity.health = entity.health + dmg
end

View File

@ -203,9 +203,11 @@ function Public.add_player_to_permission_group(player, group, forced)
local gulag = game.permissions.get_group('gulag')
local tbl = gulag and gulag.players
if tbl[player.index] then
for i = 1, #tbl do
if tbl[i].index == player.index then
return
end
end
if player.admin then
return
@ -236,7 +238,6 @@ function Public.add_player_to_permission_group(player, group, forced)
locomotive_group.set_allows_action(defines.input_action.admin_action, false)
locomotive_group.set_allows_action(defines.input_action.drop_item, false)
locomotive_group.set_allows_action(defines.input_action.place_equipment, false)
locomotive_group.set_allows_action(defines.input_action.take_equipment, false)
end
if not game.permissions.get_group('plebs') then
@ -258,7 +259,6 @@ function Public.add_player_to_permission_group(player, group, forced)
not_trusted.set_allows_action(defines.input_action.admin_action, false)
not_trusted.set_allows_action(defines.input_action.drop_item, false)
not_trusted.set_allows_action(defines.input_action.place_equipment, false)
not_trusted.set_allows_action(defines.input_action.take_equipment, false)
not_trusted.set_allows_action(defines.input_action.disconnect_rolling_stock, false)
not_trusted.set_allows_action(defines.input_action.connect_rolling_stock, false)
end
@ -487,7 +487,7 @@ local function validate_index()
end
end
local function create_poison_cloud(position)
local function create_defense_system(position, name, target)
local active_surface_index = WPT.get('active_surface_index')
local surface = game.surfaces[active_surface_index]
@ -498,41 +498,61 @@ local function create_poison_cloud(position)
rad(random(359))
}
surface.create_entity({name = 'poison-cloud', position = {x = position.x, y = position.y}})
surface.create_entity(
{
name = 'poison-cloud',
name = name,
position = {x = position.x, y = position.y},
target = target,
speed = 1.5,
force = 'player'
}
)
surface.create_entity(
{
name = name,
position = {
x = position.x + 12 * cos(random_angles[1]),
y = position.y + 12 * sin(random_angles[1])
}
},
target = target,
speed = 1.5,
force = 'player'
}
)
surface.create_entity(
{
name = 'poison-cloud',
name = name,
position = {
x = position.x + 12 * cos(random_angles[2]),
y = position.y + 12 * sin(random_angles[2])
}
},
target = target,
speed = 1.5,
force = 'player'
}
)
surface.create_entity(
{
name = 'poison-cloud',
name = name,
position = {
x = position.x + 12 * cos(random_angles[3]),
y = position.y + 12 * sin(random_angles[3])
}
},
target = target,
speed = 1.5,
force = 'player'
}
)
surface.create_entity(
{
name = 'poison-cloud',
name = name,
position = {
x = position.x + 12 * cos(random_angles[4]),
y = position.y + 12 * sin(random_angles[4])
}
},
target = target,
speed = 1.5,
force = 'player'
}
)
end
@ -1038,7 +1058,7 @@ local function gui_click(event)
player.name .. ' has bought the locomotive health modifier for ' .. format_number(item.price, true) .. ' coins.'
}
)
this.locomotive_max_health = this.locomotive_max_health + 2500 * item.stack
this.locomotive_max_health = this.locomotive_max_health + 4000 * item.stack
local m = this.locomotive_health / this.locomotive_max_health
if this.carriages then
@ -1208,23 +1228,6 @@ local function gui_click(event)
redraw_coins_left(data.coins_left, player)
return
end
if name == 'skill_reset' then
player.remove_item({name = item.value, count = item.price})
local message = ({
'locomotive.rpg_reset_bought_info',
shopkeeper,
player.name,
format_number(item.price, true)
})
Alert.alert_all_players(10, message)
Functions.rpg_reset_player(player, true)
redraw_market_items(data.item_frame, player, data.search_text)
redraw_coins_left(data.coins_left, player)
return
end
if player_item_count >= cost then
if player.can_insert({name = name, count = item_count}) then
@ -1547,10 +1550,10 @@ local function on_player_and_robot_mined_entity(event)
local chests_linked_to = WPT.get('chests_linked_to')
if outside_chests[entity.unit_number] then
for k, v in pairs(chests_linked_to) do
if v[entity.unit_number] then
v.count = v.count - 1
if v.count <= 0 then
for k, data in pairs(chests_linked_to) do
if data[entity.unit_number] then
data.count = data.count - 1
if data.count <= 0 then
chests_linked_to[k] = nil
end
end
@ -1974,7 +1977,6 @@ function Public.get_items()
local explosive_bullets_cost = round(fixed_prices.explosive_bullets_cost)
local flamethrower_turrets_cost = round(fixed_prices.flamethrower_turrets_cost * (1 + flame_turret))
local land_mine_cost = round(fixed_prices.land_mine_cost * (1 + landmine))
local skill_reset_cost = round(fixed_prices.skill_reset_cost)
local pickaxe_tiers = WPT.pickaxe_upgrades
local tier = WPT.get('pickaxe_tier')
@ -2100,16 +2102,7 @@ function Public.get_items()
upgrade = true,
static = true
}
main_market_items['skill_reset'] = {
stack = 1,
value = 'coin',
price = skill_reset_cost,
tooltip = ({'main_market.skill_reset'}),
sprite = 'achievement/golem',
enabled = true,
upgrade = true,
static = true
}
if game.forces.player.technologies['logistics'].researched then
main_market_items['loader'] = {
stack = 1,
@ -2261,13 +2254,13 @@ function Public.get_items()
stack = 1,
value = 'coin',
price = 25000,
tooltip = ({'main_market.tank_cannon_na'}),
tooltip = ({'main_market.tank_cannon_na', 650}),
upgrade = false,
static = true,
enabled = false
}
end
if wave_number >= 200 then
if wave_number >= 100 then
main_market_items['vehicle-machine-gun'] = {
stack = 1,
value = 'coin',
@ -2282,7 +2275,7 @@ function Public.get_items()
stack = 1,
value = 'coin',
price = 2000,
tooltip = ({'main_market.vehicle_machine_gun_na'}),
tooltip = ({'main_market.vehicle_machine_gun_na', 100}),
upgrade = false,
static = true,
enabled = false
@ -2317,7 +2310,7 @@ function Public.transfer_pollution()
surface.clear_pollution()
end
function Public.enable_poison_defense()
function Public.enable_poison_defense(pos)
local locomotive = WPT.get('locomotive')
if not locomotive then
return
@ -2325,11 +2318,27 @@ function Public.enable_poison_defense()
if not locomotive.valid then
return
end
local pos = locomotive.position
create_poison_cloud({x = pos.x, y = pos.y})
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(359))}
create_poison_cloud({x = pos.x + 24 * cos(random_angles[1]), y = pos.y + -24 * sin(random_angles[1])})
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)
local locomotive = WPT.get('locomotive')
if not locomotive then
return
end
if not locomotive.valid then
return
end
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

View File

@ -108,7 +108,7 @@ function Public.reset_map()
BuriedEnemies.reset()
Commands.reset()
Commands.activate_custom_buttons(true)
Commands.bottom_right(false)
Commands.bottom_right(true)
Poll.reset()
ICW.reset()

View File

@ -117,6 +117,7 @@ function Public.reset_table()
this.enable_arties = 6 -- default to callback 6
--!snip
this.poison_deployed = false
this.robotics_deployed = false
this.upgrades = {
showed_text = false,
landmine = {
@ -165,14 +166,13 @@ function Public.reset_table()
}
this.marked_fixed_prices = {
chest_limit_cost = 3000,
health_cost = 10000,
health_cost = 7000,
pickaxe_cost = 3000,
aura_cost = 4000,
xp_point_boost_cost = 5000,
explosive_bullets_cost = 20000,
explosive_bullets_cost = 10000,
flamethrower_turrets_cost = 3000,
land_mine_cost = 2,
skill_reset_cost = 100000
land_mine_cost = 2
}
this.collapse_grace = true
this.explosive_bullets = false

View File

@ -432,14 +432,15 @@ local function create_gui_button(player)
local tooltip
if this.insert_into_furnace and this.insert_into_wagon then
tooltip =
'Sort your inventory into nearby chests.\nLMB: Everything, excluding quickbar items.\nRMB: Only ores to nearby chests.\nCTRL+RMB: Fill nearby furnaces.\nSHIFT+LMB: Everything onto filtered slots to wagon.\nSHIFT+RMB: Only ores to wagon'
'Sort your inventory into nearby chests.\nLMB: Everything, excluding quickbar items.\nRMB: Only ores to nearby chests, excluding quickbar items.\nCTRL+RMB: Fill nearby furnaces.\nSHIFT+LMB: Everything onto filtered slots to wagon.\nSHIFT+RMB: Only ores to wagon'
elseif this.insert_into_furnace then
tooltip = 'Sort your inventory into nearby chests.\nLMB: Everything, excluding quickbar items.\nRMB: Only ores to nearby chests.\nCTRL+RMB: Fill nearby furnaces.'
tooltip =
'Sort your inventory into nearby chests.\nLMB: Everything, excluding quickbar items.\nRMB: Only ores to nearby chests, excluding quickbar items.\nCTRL+RMB: Fill nearby furnaces.'
elseif this.insert_into_wagon then
tooltip =
'Sort your inventory into nearby chests.\nLMB: Everything, excluding quickbar items.\nRMB: Only ores to nearby chests.\nSHIFT+LMB: Everything onto filtered slots to wagon.\nSHIFT+RMB: Only ores to wagon'
'Sort your inventory into nearby chests.\nLMB: Everything, excluding quickbar items.\nRMB: Only ores to nearby chests, excluding quickbar items.\nSHIFT+LMB: Everything onto filtered slots to wagon.\nSHIFT+RMB: Only ores to wagon'
else
tooltip = 'Sort your inventory into nearby chests.\nLMB: Everything, excluding quickbar items.\nRMB: Only ores to nearby chests.'
tooltip = 'Sort your inventory into nearby chests.\nLMB: Everything, excluding quickbar items.\nRMB: Only ores to nearby chests, excluding quickbar items.'
end
if this.bottom_button then
local data = Misc.get('bottom_quickbar_button')

View File

@ -117,7 +117,6 @@ local function level_up(player)
end
RPG_GUI.draw_level_text(player)
rpg_t[player.index].points_to_distribute = rpg_t[player.index].points_to_distribute + distribute_points_gain
RPG_GUI.update_char_button(player)
if rpg_t[player.index].allocate_index ~= 1 then
local node = rpg_t[player.index].allocate_index
local index = names[node]:lower()
@ -127,6 +126,8 @@ local function level_up(player)
rpg_t[player.index].total = rpg_t[player.index].total + distribute_points_gain
end
RPG_GUI.update_player_stats(player)
else
RPG_GUI.update_char_button(player)
end
if player.gui.screen[main_frame_name] then
RPG_GUI.toggle(player, true)

View File

@ -516,6 +516,10 @@ local function on_entity_damaged(event)
return
end
if event.entity.force.index == event.cause.force.index then
return
end
Functions.reward_mana(event.cause.player, 2)
--Grant the player life-on-hit.

View File

@ -216,20 +216,6 @@ function Public.conjure_items()
tick = 100,
enabled = true
}
spells[#spells + 1] = {
name = {'spells.railgun_beam'},
obj_to_create = 'railgun-beam',
target = false,
amount = 3,
damage = true,
range = 240,
force = 'player',
level = 50,
type = 'special',
mana_cost = 75,
tick = 200,
enabled = true
}
spells[#spells + 1] = {
name = {'spells.raw_fish'},
obj_to_create = 'fish',
@ -317,7 +303,6 @@ Public.projectile_types = {
force = 'enemy'
},
['lubricant-barrel'] = {name = 'acid-stream-spitter-big', count = 3, max_range = 16, tick_speed = 1},
['railgun-beam'] = {name = 'railgun-beam', count = 5, max_range = 40, tick_speed = 5},
['shotgun-shell'] = {name = 'shotgun-pellet', count = 16, max_range = 24, tick_speed = 1},
['piercing-shotgun-shell'] = {name = 'piercing-shotgun-pellet', count = 16, max_range = 24, tick_speed = 1},
['firearm-magazine'] = {name = 'shotgun-pellet', count = 16, max_range = 24, tick_speed = 1},

View File

@ -350,6 +350,7 @@ local function update_gui()
if valid then
if success then
if target then
local main = target.get_main_inventory().get_contents()
local armor = target.get_inventory(defines.inventory.character_armor).get_contents()
local guns = target.get_inventory(defines.inventory.character_guns).get_contents()
@ -372,6 +373,7 @@ local function update_gui()
end
end
end
end
else
close_player_inventory(player)
end

View File

@ -822,7 +822,9 @@ local function give_main_command_to_group()
for k, group in pairs(unit_groups) do
if type(group) ~= 'number' then
if group.valid then
if group.surface.index == target.surface.index then
command_to_main_target(group)
end
else
get_active_unit_groups_count()
end

View File

@ -190,23 +190,28 @@ end
local teleport_player_to_gulag = function(player, action)
local p_data = get_player_data(player)
local gulag_tp = function(surface)
get_player_data(player, true)
player.teleport(surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 128, 1), surface.name)
end
if action == 'jail' then
local gulag = game.surfaces['gulag']
if p_data and not p_data.locked then
p_data.fallback_surface_index = player.surface.index
p_data.position = player.position
p_data.p_group_id = player.permission_group.group_id
p_data.locked = true
end
player.teleport(gulag.find_non_colliding_position('character', {0, 0}, 128, 1), gulag.name)
local data = {
player = player
}
Task.set_timeout_in_ticks(5, clear_gui, data)
elseif action == 'free' then
jailed[player.name] = nil
if votejail[player.name] then
votejail[player.name] = nil
end
if votefree[player.name] then
votefree[player.name] = nil
end
local surface = game.surfaces[p_data.fallback_surface_index]
local p = p_data.position
local p_group = game.permissions.get_group(p_data.p_group_id)
@ -214,11 +219,12 @@ local teleport_player_to_gulag = function(player, action)
local pos = {x = p.x, y = p.y}
local get_tile = surface.get_tile(pos)
if get_tile.valid and get_tile.name == 'out-of-map' then
gulag_tp(surface)
player.teleport(surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 128, 1), surface.name)
else
get_player_data(player, true)
player.teleport(surface.find_non_colliding_position('character', p, 128, 1), surface.name)
end
get_player_data(player, true)
end
end
@ -241,6 +247,33 @@ local on_player_changed_surface = function(event)
end
end
local on_player_joined_game = function(event)
local player = game.players[event.player_index]
if not player or not player.valid then
return
end
if not jailed[player.name] then
return
end
local surface = game.surfaces['gulag']
if player.surface.index ~= surface.index then
local p_data = get_player_data(player)
if jailed[player.name] and p_data and p_data.locked then
teleport_player_to_gulag(player, 'jail')
end
end
local gulag = get_gulag_permission_group()
gulag.add_player(player)
if player.character and player.character.valid and player.character.driving then
player.character.driving = false
end
end
local validate_args = function(data)
local player = data.player
local griefer = data.griefer
@ -371,10 +404,9 @@ local jail = function(player, griefer, msg)
local g = game.players[griefer]
teleport_player_to_gulag(g, 'jail')
if g.surface.name == 'gulag' then
local gulag = get_gulag_permission_group()
gulag.add_player(griefer)
end
local message = griefer .. ' has been jailed by ' .. player .. '. Cause: ' .. msg
if game.players[griefer].character and game.players[griefer].character.valid and game.players[griefer].character.driving then
@ -407,17 +439,8 @@ local free = function(player, griefer)
local message = griefer .. ' was set free from jail by ' .. player .. '.'
jailed[griefer] = nil
set_data(jailed_data_set, griefer, nil)
if votejail[griefer] then
votejail[griefer] = nil
end
if votefree[griefer] then
votefree[griefer] = nil
end
Utils.print_to(nil, message)
Utils.action_warning_embed('{Jailed}', message)
return true
@ -597,6 +620,7 @@ Event.add(
end
)
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_player_changed_surface, on_player_changed_surface)
Event.on_init(create_gulag_surface)

View File

@ -20,33 +20,25 @@ local on_nth_tick_event_handlers = {}
if not remote.interfaces['interface'] then
remote.add_interface('interface', interface)
end ]]
local pcall = pcall
local xpcall = xpcall
local trace = debug.traceback
local log = log
local script_on_event = script.on_event
local script_on_nth_tick = script.on_nth_tick
local call_handlers
if _DEBUG then
function call_handlers(handlers, event)
if not handlers then
return log('Handlers was nil!')
local function handler_error(err)
log('\n\t' .. trace(err))
end
local function call_handlers(handlers, event)
if _DEBUG then
for i = 1, #handlers do
local handler = handlers[i]
handler(event)
end
end
else
function call_handlers(handlers, event)
if not handlers then
return log('Handlers was nil!')
end
for i = 1, #handlers do
local handler = handlers[i]
local success, error = pcall(handler, event)
if not success then
log(error)
end
xpcall(handlers[i], handler_error, event)
end
end
end