1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-03-25 21:29:06 +02:00

Merge branch 'ComfyFactory:develop' into develop

This commit is contained in:
danielmartin0 2022-07-25 12:43:40 +01:00 committed by GitHub
commit 25efb28a93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
80 changed files with 3034 additions and 852 deletions

27
.github/workflows/CheckMaps.yml vendored Normal file
View File

@ -0,0 +1,27 @@
name: CheckMaps
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the develop branch
on:
push:
branches: [develop]
pull_request:
branches: [develop]
jobs:
check:
name: Check if requestor has made a boo boo
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Factorio Control comment
uses: Gerkiz/FactorioControlChecker@v1.0.6
id: factorio_control_runner
- name: Check control.lua
if: steps.factorio_control_runner.outputs.should_run == 1
run: |
echo "Maps are required in control.lua - please fix these."
exit 1

View File

@ -18,6 +18,7 @@ require 'utils.datastore.quickbar_data'
require 'utils.datastore.message_on_join_data'
require 'utils.datastore.player_tag_data'
require 'utils.datastore.supporters'
require 'utils.datastore.banhandler'
require 'utils.chatbot'
require 'utils.commands'
require 'utils.antigrief'

1
info.json Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -9,19 +9,20 @@ spidertron_unlocked=[color=blue]Mapkeeper:[/color]\nAttention! Spidertron has be
wall_breached=[color=blue]Mapkeeper:[/color]\nSurvivor! Well done. You have completed zone __1__!
first_to_reach=[color=blue]Mapkeeper:[/color]\n__1__ was the first to reach zone __2__.
artillery_warning=[color=blue]Mapkeeper:[/color]\nWarning, Artillery have been spotted north!
cheating_through=__1__ tried to cheat their way north with their spidertron!
hinder=You are too far away from the main locomotive. You cannot go beyond this point.
cheating_through=[color=blue]Mapkeeper:[/color] __1__ tried to cheat their way north with their spidertron!
hinder=[color=blue]Mapkeeper:[/color] You are too far away from the main locomotive. You cannot go beyond this point.
heavy_legs=[color=blue]Mapkeeper:[/color] Your legs feels all of a sudden very heavy.
[entity]
treasure_1=You notice an old crate within the rubble. It's filled with treasure!
treasure_2=You find a chest underneath the broken rocks. It's filled with goodies!
treasure_3=We has found the precious!
treasure_rare_1=Your magic improves. You have found a chest that is filled with rare treasures!
treasure_rare_2=Oh how wonderful. You found a chest underneath the broken rocks. It's filled with rare goodies!
treasure_rare_3=You're a wizard! We have found the rare precious!
treasure_1=[color=blue]Mapkeeper:[/color] You notice an old crate within the rubble. It's filled with treasure!
treasure_2=[color=blue]Mapkeeper:[/color] You find a chest underneath the broken rocks. It's filled with goodies!
treasure_3=[color=blue]Mapkeeper:[/color] We has found the precious!
treasure_rare_1=[color=blue]Mapkeeper:[/color] Your magic improves. You have found a chest that is filled with rare treasures!
treasure_rare_2=[color=blue]Mapkeeper:[/color] Oh how wonderful. You found a chest underneath the broken rocks. It's filled with rare goodies!
treasure_rare_3=[color=blue]Mapkeeper:[/color] You're a wizard! We have found the rare precious!
defeated_1=[color=blue]Mapkeeper:[/color]\nOh no, the biters nom'ed the train away!\nBetter luck next time.
defeated_2=[color=blue]Mapkeeper:[/color]\nI'm not 100% sure, but - apparently the train was chewed away.\nBetter luck next time.
defeated_2=[color=blue]Mapkeeper:[/color]\nApparently the train was chewed away.\nBetter luck next time.
defeated_3=[color=blue]Mapkeeper:[/color]\nYou had one objective - defend the train *-*\nBetter luck next time.
defeated_4=[color=blue]Mapkeeper:[/color]\nLooks like we're resetting cause you did not defend the train ._.\nBetter luck next time.
reset_game=*** Soft-reset is disabled! Server will restart from scenario to load new changes. ***
@ -30,8 +31,8 @@ shutdown_game=*** Soft-reset is disabled! Server will shutdown. Most likely beca
notify_shutdown=Soft-reset is disabled! Server will shutdown. Most likely because of updates.
train_taking_damage=[color=blue]Comfylatron:[/color]\nTrain is taking heavy damage.\nDeploying defense mechanisms.
entity_limit_reached=__1__ limit reached. Purchase more slots at the market!
found_car=__1__ has found a car underneath the rumble!
radar_limit=Another radar is found nearby!
found_car=[color=blue]Mapkeeper:[/color] __1__ has found a car underneath the rumble!
radar_limit=[color=blue]Mapkeeper:[/color] Another radar is found nearby!
[gui]
@ -91,18 +92,18 @@ locomotive_health=__1__ unlocked the last missing piece for the mystical chest!\
[main_market]
chest=Upgrades the amount of chests that can be placed outside.\nCan be purchased multiple times. [__1__/7]
locomotive_max_health=Upgrades the train health.\nCan be purchased multiple times. [__1__/99]
locomotive_xp_aura=Upgrades the XP aura that is around the train. [__1__]
chest=Upgrades the amount of chests that can be placed outside.\nCan be purchased multiple times. [__1__/__2__]
locomotive_max_health=Upgrades the train health.\nCan be purchased multiple times. [__1__/__2__]
locomotive_aura_radius=Upgrades the XP aura that is around the train. [__1__/__2__]\n[Limited to save UPS]
global_car_health_modifier=Grants all cars/tanks/spidertrons a global health modifier.
xp_points_boost=Upgrades the amount of XP points you get inside the XP aura [__1__]
xp_points_boost=Upgrades the amount of XP points you get inside the XP aura [__1__/♾]
mystical_chest=Rerolls the mystical chest.
explosive_bullets=Upgrades ordinary SMG ammo to explosive bullets.
reroll_market_items=Will reroll the items in the market and shuffle prices.
purchase_pickaxe=Upgrade the teams Pickaxe to tier: __1__ [__2__/58]
purchase_pickaxe=Upgrade the teams Pickaxe to tier: __1__ [__2__/__3__]
sold_out=Sold out!
flamethrower_turret=Upgrades the amount of flamethrowers that can be placed. [__1__]
land_mine=Upgrades the amount of landmines that can be placed. [__1__]
flamethrower_turret=Upgrades the amount of flamethrowers that can be placed. [__1__/♾]
land_mine=Upgrades the amount of landmines that can be placed. [__1__/♾]
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 __1__.
@ -118,7 +119,13 @@ death_message_6=__1__ got obliterated!
death_message_7=__1__ tried to cheat their way north!
forcefield=Forcefield does not approve.
greeting=[color=blue]Comfylatron:[/color]\nGreetings, __1__!\nPlease read the map info.
death_mode_warning=[color=blue]Comfylatron:[/color]\nCAUTION! Walking outside of the locomotive aura will kill you!
aura_upgrade_warning=[color=blue]Comfylatron:[/color]\nThe locomotive aura range has been upgraded!
damage_mode_warning=[color=blue]Comfylatron:[/color]\nCAUTION! Walking outside of the locomotive aura will slowly kill you!
cleaner=[color=blue]Cleaner:[/color]\n__1__ has left his goodies! Be quick and fetch them!
reset_in=Game will __1__ in __2__ seconds!
diff_set=Difficulty has been set! Game has been set to: [color=green]__1__[/color]
diff_tooltip=Wave Defense is based on amount of players.\nBonus XP on join: __1__.\nMining speed boost: __2__.\nRunning speed boost: __3__.\nCrafting speed boost: __4__.\nMaximum coin per harvest: __5__.\nFlame Turret limit: __6__.\nLandmine limit: __7__.\nLocomotive health: __8__.\nHidden Treasure has __9__ chance to spawn.\nGrace period: __10__ minutes\nSpidertrons unlocks at zone __11__.
[functions]
researched_complete=__1__ has been researched!

View File

@ -130,6 +130,9 @@ pointy_explosives=Detonate Chest
repair_aoe=Repair AOE
charge=Charge
eternal_blades=Eternal Blades
drone_enemy=Drone - Enemy
drone_mine=Drone - Mine
[allocations]

View File

@ -101,7 +101,7 @@ spidertron_not_allowed=Паукотроны не допускаются на п
[mountain_fortress]
map_info_main_caption=Г О Р Н А Я К Р Е П О С Т Ь
map_info_sub_caption= ..копаю копаю чух чух..
map_info_text=Кусаки уловили запах рыбы в грузовом вагоне.\nПроводите поезд в гору и защищайте его как можно дольше!\nЭто, однако, будет нелёгкой задачей,\nпоскольку их сила и численность со временем увеличиваются.\n\nКроме того, южные земли со временем разрушаются.\n\nПродвигайтесь глубже для больших сокровищ, и сталкивайтесь с возрастающими опасностями.\nИсследование продуктивности добычи приведет к улучшению вашего добывающего оборудования,\nусилит вашу кирку, а также увеличит размер вашего рюкзака.\n\nКогда вы будете копать, вы встретите непроходимые темные пропасти или реки.\nНемного взрывчатки может заставить части потолка рассыпаться, заполняя пустоту, создавая новые пути.\nВсё, что вам нужно, это контейнер и прицельный выстрел.\n\nВы можете найти полезные припасы, если войдете в вагон.\nУдачи вам в пути!
map_info_text=Кусаки уловили запах рыбы в грузовом вагоне.\nПроводите поезд в гору и защищайте его как можно дольше!\nЭто, однако, будет нелёгкой задачей,\nпоскольку их сила и численность со временем увеличиваются.\n\nКроме того, южные земли со временем разрушаются.\n\nПродвигайтесь глубже, находите больше сокровищ, но и опасности возрастают.\nИсследование продуктивности добычи приведет к улучшению вашего добывающего оборудования,\nусилит вашу кирку, а также увеличит размер вашего рюкзака.\n\nКогда вы будете копать, вы встретите непроходимые темные пропасти или реки.\nНемного взрывчатки может заставить части потолка рассыпаться, заполняя пустоту, создавая новые пути.\nВсё, что вам нужно, это контейнер и точный выстрел.\n\nВы можете найти полезные припасы, если войдете в вагон.\nУдачи вам в пути!
[rocks_yield_ore_veins]
coal=угля
@ -142,6 +142,7 @@ angels-ore6=коричневое
gui_1=Первая волна через
gui_2=Волна:
gui_3=Угроза:
gui_4=Пауза на:
tooltip_1=Высокая угроза может усилить кусак.\nЗдоровье кусак: __1__%\nМаксимум активных кусак: __2__~
tooltip_2=доход / минуту

View File

@ -17,6 +17,9 @@ turret_filler_label_enabled=Включено:
turret_filler_label_amount=Количество:
turret_filler_ammo_type=Боеприпасы:
turret_filler_ammo_lower=Включить предыдущие уровни?
blueprint_requesting=Запрос по чертежу
blueprint_requesting_desc=Если положить чертёж в [entity=logistic-chest-requester] или [entity=logistic-chest-buffer], то сундук запросит предметы, нужные для постройки чертежа. Запрос формируется при закрытии сундука.
blueprint_requesting_notify=На этом сервере включена функция "Запрос по чертежу". Если положить чертёж в [entity=logistic-chest-requester] или [entity=logistic-chest-buffer], то сундук запросит предметы, нужные для постройки чертежа. Вы можете отключить функцию в меню Comfy -> Config.
[modules_towny]
map_info=__1__\n\n__2__\n\n__3__\n\n__4__\n\n__5__

View File

@ -1,7 +1,7 @@
[mountain_fortress_v3]
map_info_main_caption=Г О Р Н А Я К Р Е П О С Т Ь V3
map_info_sub_caption= ~~ копаю копаю чух чух ~~
map_info_text=[color=red]ПРОЧТИТЕ ЭТО!\nЕсли встретите ошибки или десинхронизацию, сообщите @Gerkiz!\nЕсли встретятся ошибки, ломающие игру, карта может быть перезагружена для исправления.[/color]\n\nКусаки уловили запах рыбы в грузовом вагоне.\nПроводите поезд в гору и защищайте его как можно дольше!\nЭто, однако, будет нелёгкой задачей,\nпоскольку их сила и численность со временем увеличиваются.\n\nКроме того, южные земли со временем разрушаются.\n\nПродвигайтесь глубже для больших сокровищ, и сталкивайтесь с возрастающими опасностями.\nИсследование продуктивности добычи приведет к улучшению вашего добывающего оборудования, и увеличит размер вашего рюкзака.\n\nКогда вы будете копать, вы встретите непроходимые тёмные пропасти или реки.\nПо вам будет стрелять артиллерия! Копайте быстро, копайте на север!\n\nНемного взрывчатки может вызвать обвал гор, заполняя пустоту, создавая новые пути.\nВсё, что вам нужно, это контейнер и точный выстрел.\n\nВойдите в грузовой вагон, чтобы открыть пространство вагона!\n\nСлучайные здания, генерирующие ресурсы, могут быть найдены в мире.\n\nРазмещение стальных сундуков рядом с грузовыми вагонами позволить быстро перемещать содержимое.\n\nНахождение в зоне локомотива предотвращает появление кусак при добыче объектов.\n\nИнтерфейс RPG отключается внутри локомотива.\nОтсоединение вагонов отключено.\nВы не можете отменить крафт, находясь в зоне локомотива.\n\nНе пытайтесь идти на север на Паукотроне, если поезд не рядом с вами.\nВы были предупреждены.\nУ буров большой бонус производительности, и его можно увеличить исследованиями, используйте по возможности!\nЗагадочный сундук в локомотиве предлагает некоторые награды.\nЕго нужно накормить, чтобы получить награды.\n\nУдачи вам в пути!
map_info_text=[color=red]ПРОЧТИТЕ ЭТО!\nЕсли встретите ошибки или десинхронизацию, сообщите @Gerkiz!\nЕсли встретятся ошибки, ломающие игру, карта может быть перезагружена для исправления.[/color]\n\nКусаки уловили запах рыбы в грузовом вагоне.\nПроводите поезд в гору и защищайте его как можно дольше!\nЭто, однако, будет нелёгкой задачей,\nпоскольку их сила и численность со временем увеличиваются.\n\nКроме того, южные земли со временем разрушаются.\n\nПродвигайтесь глубже для больших сокровищ, и сталкивайтесь с возрастающими опасностями.\nИсследование продуктивности добычи приведет к улучшению вашего добывающего оборудования, и увеличит размер вашего рюкзака.\n\nКогда вы будете копать, вы встретите непроходимые тёмные пропасти или реки.\nПо вам будет стрелять артиллерия! Копайте быстро, копайте на север!\n\nНемного взрывчатки может вызвать обвал гор, заполняя пустоту, создавая новые пути.\nВсё, что вам нужно, это контейнер и точный выстрел.\n\nВойдите в грузовой вагон, чтобы открыть пространство вагона!\n\nСлучайные здания, генерирующие ресурсы, могут быть найдены в мире.\n\nРазмещение стальных сундуков рядом с грузовыми вагонами позволить быстро перемещать содержимое.\n\nНахождение в зоне локомотива предотвращает появление кусак при добыче объектов.\n\nРадары нельзя строить рядом друг с другом.\n\nИнтерфейс RPG отключается внутри локомотива.\nОтсоединение вагонов отключено.\nВы не можете отменить крафт, находясь в зоне локомотива.\n\nНе пытайтесь идти на север на Паукотроне, если поезд не рядом с вами.\nВы были предупреждены.\nУ буров большой бонус производительности, и его можно увеличить исследованиями, используйте по возможности!\nЗагадочный сундук в локомотиве предлагает некоторые награды.\nЕго нужно накормить, чтобы получить награды.\n\nУдачи вам в пути!
[breached_wall]
collapse_start=[color=blue]Хранитель карты:[/color]\nПредупреждение, начинается коллапс!
@ -30,6 +30,7 @@ notify_shutdown=Мягкий сброс отключён! Сервер буде
train_taking_damage=[color=blue]Комфилатрон:[/color]\nПоезд получает большой урон.\nАктивирую защитные механизмы.
entity_limit_reached=__1__: достигнут предел. Приобретите больше ячеек на рынке!
found_car=__1__ нашёл машину под обломками!
radar_limit=Другой радар обнаружен неподалёку!
[gui]
global_pool_tooltip=Копай, создавай или беги, чтобы увеличить общий опыт!
@ -49,7 +50,7 @@ map_off=ВЫКЛ
[locomotive]
upgrades=Улучшения:
items=Предметы:
shoo=^-^ Пожалуйста, не пугайте меня ^-^
shoo=[Братан Десинхрона]
not_trusted=Чтобы купить это, вам нужно быть доверенным.
coins_left=Монет осталось: __1__
market_name=Рынок
@ -89,7 +90,7 @@ locomotive_health=__1__ разблокировал последнюю недос
[main_market]
chest=Увеличивает количество сундуков, которые можно разместить снаружи.\nМожно купить несколько раз. [__1__/7]
locomotive_max_health=Улучшает здоровье поезда.\nМожно купить несколько раз. [__1__/99]
locomotive_xp_aura=Улучшает зону опыта вокруг поезда. [__1__]
locomotive_aura_radius=Улучшает зону опыта вокруг поезда. [__1__]
global_car_health_modifier=Даёт всем автомобилям/танкам/паукотронам глобальный модификатор здоровья.
xp_points_boost=Увеличивает количество очков опыта, которые вы получаете внутри зоны опыта. [__1__]
mystical_chest=Обновляет содержимое загадочного сундука.

39
locale/ru/pirates.cfg Normal file
View File

@ -0,0 +1,39 @@
[pirates]
softmod_info_header_before_version_number==== Пиратский корабль v
softmod_info_header_after_version_number= ===
softmod_info_body_1=Новости и чат: getcomfy.eu/discord
softmod_info_game_description_1=Описание игры
softmod_info_game_description_2=Отправляйтесь в плавание в этом многопользовательском сценарии. Собирайте ресурсы и заправляйте корабль, чтобы выжить как можно больше лиг. Корабль движется с помощью магии кода. У каждой команды есть капитан, который выполняет такие действия, как решение, когда отплывать. Дублоны можно потратить на различных рынках на протяжении всей игры.\n\nЧем меньше команда, тем медленнее игровой прогресс.\n\n[font=default-bold]Условие победы:[/font] Пройдите 1000 лиг.\n[font=default-bold]Условие проигрыша:[/font] У корабля закончилось топливо или уничтожена пушка.
softmod_info_bugs_1=Известные недоработки
softmod_info_bugs_2=
softmod_info_new_players_1=Для новых игроков
softmod_info_new_players_2=Добывайте уголь и другие ресурсы и приносите их на корабль, чтобы поддерживать работу, или попробуйте попросить капитана о более конкретных задачах.
softmod_info_tips_1=Особенности игры, с которыми сложно справиться в одиночку
softmod_info_tips_2=• Вы можете управлять лодкой из вороньего гнезда, поместив 100 светофоров в один из синих ящиков.\n• Ресурсы, предоставленные кораблю, появляются в каюте капитана.\n• Зарядка шахты запускает ракету. Это вызывает загрязнение и эволюцию, но дает награду в виде топлива и дублонов.\n• Зарядка ракетной шахты высасывает энергию из всего остального в её сети.\n• Количество руды, доступной на острове, не зависит от порядка, в котором вы разрушаете камни.\n• Пассивное загрязнение на каждом острове со временем увеличивается.\n• Сила атак пропорциональна количеству оставшихся гнёзд. (Скорость эволюции, основанная на времени, также пропорциональна гнездам, но разрушение гнезда немедленно поднимет эволюцию на большую часть величины, которую оно «заработало бы», если бы оно выжило.)\n• Крытые рынки возвращают все плиты, потраченные на их разблокировку.\n• Производительность лабораторий увеличивается с каждой лигой.\n• Игрок, который дольше всех был капитаном между лигами 0 и 1000 (эксклюзивно), записывается в таблицу рекордов.\n• Вышедшие из игры игроки сохраняют свои предметы при себе на какое-то время — за исключением «важных» предметов, которые немедленно возвращаются команде.\n• Команды: /ccolor дает вам забавный цвет. /classinfo {имя класса} дает описание именованного класса. Чтобы управлять своим классом, используйте /take {имя класса} или /giveup. У капитанов также есть /undoc, /req, /officer, /plank.
softmod_info_updates_1=Недавние изменения
softmod_info_updates_2=v1.1.2.2.2\n- Перебалансирована сложность Nightmare\n\nv1.1.2.2.1\n- Понижение некоторых классов удалено.\n- Мелкие исправления.\n\nv1.1.2.2.0\n- Реквизиция монет заменена «налогом», который берет только 10% монет каждого игрока.\n- Увеличена монетная экономика; Награды за ракетные монеты теперь по умолчанию относятся ко второму сундуку с наградами.\n- Палубный матрос урезан в возможностях.
softmod_info_credits_1=Создатели
softmod_info_credits_2=Пиратский корабль разработан и написан thesixthroc. Кодовая база Comfy и помощь от Gerkiz, Hanakocz и Mew @ Comfy Industries (https://getcomfy.eu). Некоторые чертежи структуры острова предоставлены Mattisso.\n\nthesixthroc ищет программистов, которые помогут реализовать запланированные функции для этого мода. Приходите поболтать с нами: https://getcomfy.eu/discord\n\n"Эти белые перчатки. Я никогда не забуду их до самой смерти." - Доктор Джон
softmod_info_credits_2_old=Мод разработан и написан thesixthroc. Кодовая база Comfy и помощь от Gerkiz, Hanakocz и Mew @ Comfy Industries (https://getcomfy.eu). Некоторые чертежи структуры острова предоставлены Mattisso. Спрайт золота от Clint Bellanger. Спрайты попугая от @pixelthen.\n\n"Эти белые перчатки. Я никогда не забуду их до самой смерти." - Доктор Джон
softmod_info_body_promote=от thesixthroc
softmod_info_body_promote_old2=patreon.com/thesixthroc
softmod_info_body_clicky=Нажмите, чтобы закрыть.
softmod_info_body_some_old_stuff="Эти белые перчатки. Я никогда не забуду их до самой смерти." - Доктор Джон
proposal_displayform=__1__ — __2__
run_displayform= __2__
crewmember_displayform=[color=__2__,__3__,__4__]__5__[/color] [color=1,1,1]__6__[/color]
capacity_tooltip=Вместимость. Установите максимальное количество членов команды.
difficulty_tooltip=Сложность.\n\nБолее высокие сложности имеют более высокое загрязнение и эволюцию, более высокий урон от кусак, меньшую добычу золота, но более высокую добычу из сундуков, наряду с небольшими эффектами на время на остров, требования к квестам и положение ракетной шахты.\n\nСложность также определяет материал, из которого сделан корабль.
mode_tooltip=Режим.
auto_undock_tooltip=Максимальное время пребывания в этом месте.\n\nПо истечении этого времени лодка автоматически отплывает. Капитан может дать команду отплыть раньше, нажав эту кнопку.
atsea_loading_tooltip=Следующий пункт назначения загружается.
leave_anytime_tooltip=Капитан выбирает, когда отстыковать корабль.\n\nОни могут отстыковаться, нажав эту кнопку.
resources_needed_tooltip_0=В следующем пункте назначения эти ресурсы понадобятся для отстыковки.
resources_needed_tooltip_1=В следующем пункте назначения эти ресурсы потребуются для ранней отстыковки.\n\nЧем дольше вы остаётесь, тем меньше ресурсов потребуется, и в конечном итоге они уменьшатся до нуля.
resources_needed_tooltip_2=Капитан может отстыковаться досрочно, нажав эту кнопку, но только в том случае, если в каюте капитана хранится достаточно ресурсов.\n\nСтоимость по прибытии: __1__\nПри отходе сейчас будет потрачено: __2__
resources_needed_tooltip_3=Капитан может отстыковаться, нажав эту кнопку, но только если в каюте капитана хранится достаточно ресурсов.
resources_needed_tooltip_0_rocketvariant=В следующем пункте назначения эти ресурсы потребуются для отстыковки.\n\nРакетная шахта представляет собой запуск ракеты, а не ресурс.
resources_needed_tooltip_1_rocketvariant=В следующем пункте назначения эти ресурсы потребуются для ранней отстыковки.\n\nЧем дольше вы остаётесь, тем меньше ресурсов потребуется, и в конечном итоге их количество упадет до нуля.\n\nРакетная шахта представляет собой запуск ракеты, а не ресурс.
resources_needed_tooltip_2_rocketvariant=Капитан может отстыковаться раньше, нажав эту кнопку, но только в том случае, если в каюте капитана хранится достаточно ресурсов.\n\nРакетная шахта представляет собой запуск ракеты, а не ресурс.\n\nСтоимость по прибытии: __1__\nПри отходе сейчас будет потрачено : __2__
resources_needed_tooltip_3_rocketvariant=Капитан может отстыковаться, нажав эту кнопку, но только в том случае, если в каюте капитана хранится достаточно ресурсов.\n\nРакетная шахта представляет собой запуск ракеты, а не ресурс.
fuel_tooltip=Запас топлива: __1__.\n\nЧтобы запасти больше, отправьте его в каюту капитана. Если у корабля закончится топливо, экипаж проиграл.

View File

@ -2,6 +2,7 @@
no_valid_surface=Название поверхности не указано
flame_boots_worn_out=Ваши огненные сапоги износились.
flame_mana_remaining=Маны осталось: __1__
aoe_punch_text=АОЕ-УДАР
mana_casting_too_fast=Как быстро выяснил __1__, в магии было гораздо больше, чем просто взмахнуть палочкой и произнести несколько забавных слов.
low_level=Вам не хватает уровня для произнесения этого заклинания.
not_inside_pos=Вы машете палочкой, но понимаете, что это вне досягаемости.
@ -58,6 +59,8 @@ mana_max=Это ваша максимальная мана. Вы можете у
mining_name=СКОРОСТЬ\nДОБЫЧИ
slot_name=БОНУС\nЯЧЕЕК
melee_name=УРОН\nРУКАМИ
aoe_punch_chance=Жизни за удар: __1__\nШанс AOE-удара: __2__ % \n+__3__ [img=recipe.defender-capsule]
aoe_punch_disabled=АОЕ-удар отключен.
bonus_tooltip=Бонус дальности досягаемости: __1__\nБонус дистанции строительства: __2__\nБонус дальности выпадения предметов: __3__\nБонус дальности подбора добычи: __4__\nБонус дальности подбора предметов: __5__\nБонус дальности досягаемости ресурсов: __6__\nСкорость ремонта: __7__
reach_distance=РАДИУС\nДЕЙСТВИЙ
crafting_speed=СКОРОСТЬ\nКРАФТА
@ -82,6 +85,9 @@ no_mana=Недостаточно маны!
mana_label=Настройки маны:
tooltip_check=Отмечено: правда\nНе отмечено: ложь
info_text_label=Общие настройки RPG. Это основа для каждого игрока.
spellbook_label=Книга заклинаний - объясняет требования для каждого заклинания.
entity_spells_label=Обычные заклинания
special_spells_label=Особые заклинания
health_text_label=Показывать полоски здоровья/маны?
health_only_text_label=Показывать полоску здоровья?
reset_text_label=Сбросить очки умений?
@ -92,6 +98,9 @@ movement_text_label=Включить бонус скорости передви
movement_text_tooltip=Хотите бегать, как Флэш?\nВы можете переключить это здесь.
stone_path_label=Включить каменную тропу при добыче?
stone_path_tooltip=Включение этого автоматически создаст тропу из камня при добыче.
aoe_punch_label=Включить АОЕ-удар?
aoe_punch_tooltip=Включение этого параметра даст шанс создать AOE-удар по кусакам.\nAOE-удар работает только в том случае, если и боеприпасы, и оружие не экипированы.
aoe_punch_globally=Включено глобально.\nAOE-удар работает только в том случае, если и боеприпасы, и оружие не экипированы.
flameboots_label=Включить огненные сапоги?
flameboots_tooltip=Когда пуль просто недостаточно.
explosive_bullets_label=Включить разрывные пули?
@ -101,10 +110,7 @@ toggle_cast_spell_label=Включает возможность произнос
cast_spell_enabled_label=Произнесение заклинаний с помощью рыбы включено!
cast_spell_disabled_label=Произнесение заклинаний с помощью рыбы отключено!
magic_tooltip=Когда простого конструирования предметов недостаточно.\nПРИМЕЧАНИЕ! Используйте сырую рыбу, чтобы читать заклинания.
magic_spell=Выберите сущность для создания
magic_item_requirement=__1__ [item=__2__] требует __3__ маны для создания. Уровень: __4__\n
magic_entity_requirement=__1__ [entity=__2__] требует __3__ маны для создания. Уровень: __4__\n
magic_special_requirement=__1__ __2__ требует __3__ маны для создания. Уровень: __4__\n
magic_spell=Выберите заклинание:
allocation_settings_label=Настройки распределения:
allocation_label=Выберите умение для авто-распределения.
allocation_tooltip=Это автоматически распределит все доступные очки данному умению.
@ -120,6 +126,8 @@ distractor=Капсула с дронами-приманками
warp=Врата телепорта
pointy_explosives=Взорвать сундук
repair_aoe=Починить вокруг
charge=Заряд
eternal_blades=Вечные клинки
[allocations]
deactivated=Отключено

View File

@ -77,7 +77,7 @@ new_items_at_market=火车市场已经解锁了新物品!
[main_market]
chest=提高了可以在外面放置的箱子数量.\n可以多次购买.
locomotive_max_health=升级火车生命.\n可以多次购买
locomotive_xp_aura=升级火车周围的经验光环。
locomotive_aura_radius=升级火车周围的经验光环。
xp_points_boost=升级您在经验光环中获得的经验值
explosive_bullets=将普通的SMG弹药升级为爆炸子弹.
reroll_market_items=重置市场的商品并调整价格.

View File

@ -947,7 +947,7 @@ local function market_kill_visuals()
local m = 32
local m2 = m * 0.005
for i = 1, 1024, 1 do
for _ = 1, 1024, 1 do
surface.create_particle(
{
name = 'branch-particle',
@ -1015,7 +1015,7 @@ local function on_entity_died(event)
surface.create_entity {name = 'big-biter', position = p}
end
end
for i = 1, random(1, 2), 1 do
for _ = 1, random(1, 2), 1 do
local p = surface.find_non_colliding_position('medium-biter', event.entity.position, 3, 0.5)
if p then
surface.create_entity {name = 'medium-biter', position = p}
@ -1035,9 +1035,8 @@ local function on_entity_died(event)
Public.set('market_age', game.tick - last_reset)
Public.set('game_has_ended', true)
is_game_lost()
local name = Server.get_server_name()
local date = Server.get_start_time()
game.server_save('Final_' .. name .. '_' .. tostring(date))
game.server_save('Final_Fish_Defender_v2_' .. tostring(date))
return
end
@ -1050,7 +1049,7 @@ local function on_entity_died(event)
end
local function on_player_joined_game(event)
local player = game.players[event.player_index]
local player = game.get_player(event.player_index)
local active_surface_index = Public.get('active_surface_index')
local surface = game.surfaces[active_surface_index]
if not surface or not surface.valid then
@ -1089,7 +1088,7 @@ local function deny_building(event)
if entity.position.x >= 254 then
if entity.name ~= 'entity-ghost' then
if event.player_index then
game.players[event.player_index].insert({name = entity.name, count = 1})
game.get_player(event.player_index).insert({name = entity.name, count = 1})
else
local inventory = event.robot.get_inventory(defines.inventory.robot_cargo)
inventory.insert({name = entity.name, count = 1})
@ -1249,7 +1248,7 @@ local function on_player_respawned(event)
if not market_age then
return
end
local player = game.players[event.player_index]
local player = game.get_player(event.player_index)
player.character.destructible = false
end

View File

@ -51,7 +51,7 @@ local function enemy_weapon_damage()
}
for k, v in pairs(data) do
local new = Difficulty.get().difficulty_vote_value * v
local new = Difficulty.get().value * v
local e_old = e.get_ammo_damage_modifier(k)

View File

@ -131,22 +131,25 @@ local compare_player_pos = function(player)
end
local zone = floor((abs(p.y / zone_settings.zone_depth)) % adjusted_zones.size) + 1
local rpg_t = RPG.get_value_from_player(index)
if adjusted_zones.scrap[zone] then
RPG.set_value_to_player(index, 'scrap_zone', true)
if rpg_t and not rpg_t.scrap_zone then
rpg_t.scrap_zone = true
end
else
local has_scrap = RPG.get_value_from_player(index, 'scrap_zone')
if has_scrap then
RPG.set_value_to_player(index, 'scrap_zone', false)
if rpg_t and rpg_t.scrap_zone then
rpg_t.scrap_zone = false
end
end
if adjusted_zones.forest[zone] then
RPG.set_value_to_player(index, 'forest_zone', true)
if rpg_t and not rpg_t.forest_zone then
rpg_t.forest_zone = true
end
else
local is_in_forest = RPG.get_value_from_player(index, 'forest_zone')
if is_in_forest then
RPG.set_value_to_player(index, 'forest_zone', false)
if rpg_t and rpg_t.forest_zone then
rpg_t.forest_zone = false
end
end
end
@ -290,7 +293,7 @@ end
local function on_player_changed_position(event)
local player = game.get_player(event.player_index)
local surface_name = player.surface.name
local map_name = 'mountain_fortress_v3'
local map_name = 'mtn_v3'
if sub(surface_name, 0, #map_name) ~= map_name then
return
@ -304,6 +307,7 @@ local function on_player_changed_position(event)
distance(player)
end
local function on_player_driving_changed_state(event)
local player = game.players[event.player_index]
if not (player and player.valid) then

View File

@ -14,6 +14,7 @@ Global.register(
)
local Public = {}
local round = math.round
local floor = math.floor
local random = math.random
local abs = math.abs
@ -79,6 +80,7 @@ local function spawn_biters(data)
end
local unit_to_create
WD.wave_defense_set_unit_raffle(h * 0.20)
if random(1, 3) == 1 then
unit_to_create = WD.wave_defense_roll_spitter_name()
@ -86,10 +88,15 @@ local function spawn_biters(data)
unit_to_create = WD.wave_defense_roll_biter_name()
end
if not unit_to_create then
print('buried_enemies - unit_to_create was nil?')
return
end
local modified_unit_health = WD.get('modified_unit_health')
local modified_boss_unit_health = WD.get('modified_boss_unit_health')
WD.wave_defense_set_unit_raffle(h * 0.20)
local unit_settings = WD.get('unit_settings')
local unit = surface.create_entity({name = unit_to_create, position = position})
max_biters.amount = max_biters.amount + 1
@ -97,7 +104,11 @@ local function spawn_biters(data)
if random(1, 30) == 1 then
BiterHealthBooster.add_boss_unit(unit, modified_boss_unit_health.current_value, 0.38)
else
BiterHealthBooster.add_unit(unit, modified_unit_health.current_value)
local final_health = round(modified_unit_health.current_value * unit_settings.scale_units_by_health[unit.name], 3)
if final_health < 1 then
final_health = 1
end
BiterHealthBooster.add_unit(unit, final_health)
end
return true
end
@ -124,10 +135,17 @@ local function spawn_worms(data)
local unit = surface.create_entity({name = unit_to_create, position = position})
max_biters.amount = max_biters.amount + 1
local worm_unit_settings = WD.get('worm_unit_settings')
if random(1, 30) == 1 then
BiterHealthBooster.add_boss_unit(unit, modified_boss_unit_health.current_value, 0.38)
else
BiterHealthBooster.add_unit(unit, modified_unit_health.current_value)
local final_health = round(modified_unit_health.current_value * worm_unit_settings.scale_units_by_health[unit.name], 3)
if final_health < 1 then
final_health = 1
end
BiterHealthBooster.add_unit(unit, final_health)
end
end

View File

@ -156,6 +156,40 @@ commands.add_command(
end
)
commands.add_command(
'toggle_orbital_strikes',
'Usable only for admins - toggles orbital strikes!',
function()
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()
if not this.orbital_strikes_are_you_sure then
this.orbital_strikes_are_you_sure = true
player.print('[WARNING] This command will disable the orbital_strikes in-game, run this command again if you really want to do this!', Color.warning)
return
end
if this.orbital_strikes.enabled then
game.print(mapkeeper .. ' ' .. player.name .. ', has disabled the orbital_strikes module!', {r = 0.98, g = 0.66, b = 0.22})
this.orbital_strikes.enabled = false
else
game.print(mapkeeper .. ' ' .. player.name .. ', has enabled the orbital_strikes module!', {r = 0.98, g = 0.66, b = 0.22})
this.orbital_strikes.enabled = true
end
this.orbital_strikes_are_you_sure = nil
end
)
commands.add_command(
'get_queue_speed',
'Usable only for admins - gets the queue speed of this map!',

View File

@ -310,7 +310,7 @@ local function protect_entities(data)
end
local function is_protected(e)
local map_name = 'mountain_fortress_v3'
local map_name = 'mtn_v3'
if string.sub(e.surface.name, 0, #map_name) ~= map_name then
return true
@ -728,7 +728,7 @@ local function on_player_mined_entity(event)
end
local rpg_char = RPG.get_value_from_player(player.index)
local map_name = 'mountain_fortress_v3'
local map_name = 'mtn_v3'
if string.sub(entity.surface.name, 0, #map_name) ~= map_name then
return
@ -772,7 +772,7 @@ local function on_robot_mined_entity(event)
return
end
local map_name = 'mountain_fortress_v3'
local map_name = 'mtn_v3'
if string.sub(entity.surface.name, 0, #map_name) ~= map_name then
return
@ -968,7 +968,7 @@ local function on_entity_died(event)
local cause = event.cause
local map_name = 'mountain_fortress_v3'
local map_name = 'mtn_v3'
if string.sub(entity.surface.name, 0, #map_name) ~= map_name then
return
@ -1194,11 +1194,14 @@ local function show_mvps(player)
local collapse_amount = Collapse.get_amount()
local diff = Diff.get()
if not diff then
return
end
local time_played = Core.format_time(game.ticks_played)
local total_players = #game.players
local pickaxe_tiers = WPT.pickaxe_upgrades
local tier = WPT.get('pickaxe_tier')
local pick_tier = pickaxe_tiers[tier]
local pickaxe_upgrades = WPT.pickaxe_upgrades
local upgrades = WPT.get('upgrades')
local pick_tier = pickaxe_upgrades[upgrades.pickaxe_tier]
local server_name_matches = Server.check_server_name('Mtn Fortress')
if WPT.get('prestige_system_enabled') then
@ -1207,7 +1210,7 @@ local function show_mvps(player)
local date = Server.get_start_time()
game.server_save('Final_Mtn_Fortress_v3_' .. tostring(date))
local text = {
title = 'Game over <:helper:627426785918713877>',
title = 'Game over!',
description = 'Game statistics from the game is below',
color = 'failure',
field1 = {
@ -1241,7 +1244,7 @@ local function show_mvps(player)
},
field6 = {
text1 = 'Pickaxe Upgrade:',
text2 = pick_tier .. ' (' .. tier .. ')',
text2 = pick_tier .. ' (' .. upgrades.pickaxe_tier .. ')',
inline = 'true',
emptyField = 'true',
emptyInline = 'true'
@ -1389,7 +1392,7 @@ local function on_built_entity(event)
return
end
local map_name = 'mountain_fortress_v3'
local map_name = 'mtn_v3'
if string.sub(entity.surface.name, 0, #map_name) ~= map_name then
return
@ -1486,7 +1489,7 @@ local function on_robot_built_entity(event)
return
end
local map_name = 'mountain_fortress_v3'
local map_name = 'mtn_v3'
if string.sub(entity.surface.name, 0, #map_name) ~= map_name then
return
@ -1580,7 +1583,7 @@ end
local on_player_or_robot_built_tile = function(event)
local surface = game.surfaces[event.surface_index]
local map_name = 'mountain_fortress_v3'
local map_name = 'mtn_v3'
if string.sub(surface.name, 0, #map_name) ~= map_name then
return

View File

@ -1,8 +1,8 @@
local Server = require 'utils.server'
local Token = require 'utils.token'
local Task = require 'utils.task'
local Color = require 'utils.color_presets'
local ICW = require 'maps.mountain_fortress_v3.icw.main'
local ICT_Functions = require 'maps.mountain_fortress_v3.ic.functions'
local Event = require 'utils.event'
local Global = require 'utils.global'
local Alert = require 'utils.alert'
@ -15,6 +15,7 @@ local ICW_Func = require 'maps.mountain_fortress_v3.icw.functions'
local math2d = require 'math2d'
local Misc = require 'utils.commands.misc'
local Core = require 'utils.core'
local Beams = require 'modules.render_beam'
local zone_settings = WPT.zone_settings
local this = {
@ -73,8 +74,8 @@ local Public = {}
local random = math.random
local floor = math.floor
local round = math.round
local remove = table.remove
local sqrt = math.sqrt
local remove = table.remove
local magic_crafters_per_tick = 3
local magic_fluid_crafters_per_tick = 8
local tile_damage = 50
@ -294,10 +295,58 @@ local artillery_target_callback =
end
)
local function difficulty_and_adjust_prices()
local fixed_prices = WPT.get('marked_fixed_prices')
local difficulty_index = Difficulty.get('index')
for index, price in pairs(fixed_prices) do
if difficulty_index == 2 then
fixed_prices[index] = price * 1.5
elseif difficulty_index == 3 then
fixed_prices[index] = price * 2
end
end
end
local function do_beams_away()
local wave_number = WD.get_wave()
local orbital_strikes = WPT.get('orbital_strikes')
if not orbital_strikes.enabled then
return
end
if wave_number > 1000 then
local difficulty_index = Difficulty.get('index')
local wave_nth = 9999
if difficulty_index == 1 then
wave_nth = 1000
elseif difficulty_index == 2 then
wave_nth = 500
elseif difficulty_index == 3 then
wave_nth = 250
end
if wave_number % wave_nth == 0 then
local active_surface_index = WPT.get('active_surface_index')
local surface = game.get_surface(active_surface_index)
if not orbital_strikes[wave_number] then
orbital_strikes[wave_number] = true
Beams.new_beam_delayed(surface, random(500, 3000))
end
end
end
end
local function do_artillery_turrets_targets()
local art_table = this.art_table
local index = art_table.index
local difficulty_index = Difficulty.get('index')
if difficulty_index == 3 then
return
end
if index > #art_table then
art_table.index = 1
return
@ -376,6 +425,7 @@ local function tick()
do_magic_crafters()
do_magic_fluid_crafters()
do_artillery_turrets_targets()
do_beams_away()
end
Public.deactivate_callback =
@ -699,93 +749,6 @@ function Public.do_random_loot(entity, weights, loot)
entity.insert {name = stack.name, count = count}
end
function Public.remove_offline_players()
local offline_players_enabled = WPT.get('offline_players_enabled')
if not offline_players_enabled then
return
end
local offline_players = WPT.get('offline_players')
local offline_players_surface_removal = WPT.get('offline_players_surface_removal')
local active_surface_index = WPT.get('active_surface_index')
local surface = game.surfaces[active_surface_index]
local player_inv = {}
local items = {}
if #offline_players > 0 then
for i = 1, #offline_players, 1 do
if offline_players[i] and offline_players[i].index then
local target = game.players[offline_players[i].index]
if target and target.connected then
offline_players[i] = nil
else
if target and offline_players[i].tick < game.tick - 108000 then
local name = offline_players[i].name
player_inv[1] = target.get_inventory(defines.inventory.character_main)
player_inv[2] = target.get_inventory(defines.inventory.character_armor)
player_inv[3] = target.get_inventory(defines.inventory.character_guns)
player_inv[4] = target.get_inventory(defines.inventory.character_ammo)
player_inv[5] = target.get_inventory(defines.inventory.character_trash)
if offline_players_surface_removal then
ICT_Functions.remove_surface(target) -- remove empty surface
end
if target.get_item_count() == 0 then -- if the player has zero items, don't do anything
offline_players[i] = nil
goto final
end
local pos = game.forces.player.get_spawn_position(surface)
local e =
surface.create_entity(
{
name = 'character',
position = pos,
force = 'neutral'
}
)
local inv = e.get_inventory(defines.inventory.character_main)
e.character_inventory_slots_bonus = #player_inv[1]
for ii = 1, 5, 1 do
if player_inv[ii].valid then
for iii = 1, #player_inv[ii], 1 do
if player_inv[ii][iii].valid then
items[#items + 1] = player_inv[ii][iii]
end
end
end
end
if #items > 0 then
for item = 1, #items, 1 do
if items[item].valid then
inv.insert(items[item])
end
end
local message = ({'main.cleaner', name})
local data = {
position = pos
}
Alert.alert_all_players_location(data, message)
e.die('neutral')
else
e.destroy()
end
for ii = 1, 5, 1 do
if player_inv[ii].valid then
player_inv[ii].clear()
end
end
offline_players[i] = nil
break
end
::final::
end
end
end
end
end
local function calc_players()
local players = game.connected_players
local check_afk_players = WPT.get('check_afk_players')
@ -891,6 +854,9 @@ function Public.set_difficulty()
return
end
local Diff = Difficulty.get()
if not Diff then
return
end
local wave_defense_table = WD.get_table()
local check_if_threat_below_zero = WPT.get('check_if_threat_below_zero')
local collapse_amount = WPT.get('collapse_amount')
@ -902,16 +868,16 @@ function Public.set_difficulty()
local wave_number = WD.get_wave()
local player_count = calc_players()
if not Diff.difficulty_vote_value then
Diff.difficulty_vote_value = 0.1
if not Diff.value then
Diff.value = 0.1
end
if Diff.name == "I'm too young to die" then
wave_defense_table.max_active_biters = 768 + player_count * (90 * Diff.difficulty_vote_value)
elseif Diff.name == 'Hurt me plenty' then
wave_defense_table.max_active_biters = 845 + player_count * (90 * Diff.difficulty_vote_value)
elseif Diff.name == 'Ultra-violence' then
wave_defense_table.max_active_biters = 1000 + player_count * (90 * Diff.difficulty_vote_value)
if Diff.index == 1 then
wave_defense_table.max_active_biters = 768 + player_count * (90 * Diff.value)
elseif Diff.index == 2 then
wave_defense_table.max_active_biters = 845 + player_count * (90 * Diff.value)
elseif Diff.index == 3 then
wave_defense_table.max_active_biters = 1000 + player_count * (90 * Diff.value)
end
if wave_defense_table.max_active_biters >= 4000 then
@ -919,12 +885,12 @@ function Public.set_difficulty()
end
-- threat gain / wave
if Diff.name == "I'm too young to die" then
wave_defense_table.threat_gain_multiplier = 1.2 + player_count * Diff.difficulty_vote_value * 0.1
elseif Diff.name == 'Hurt me plenty' then
wave_defense_table.threat_gain_multiplier = 2 + player_count * Diff.difficulty_vote_value * 0.1
elseif Diff.name == 'Ultra-violence' then
wave_defense_table.threat_gain_multiplier = 4 + player_count * Diff.difficulty_vote_value * 0.1
if Diff.index == 1 then
wave_defense_table.threat_gain_multiplier = 1.2 + player_count * Diff.value * 0.1
elseif Diff.index == 2 then
wave_defense_table.threat_gain_multiplier = 2 + player_count * Diff.value * 0.1
elseif Diff.index == 3 then
wave_defense_table.threat_gain_multiplier = 4 + player_count * Diff.value * 0.1
end
-- local amount = player_count * 0.40 + 2 -- too high?
@ -942,7 +908,7 @@ function Public.set_difficulty()
threat_check = wave_defense_table.threat <= 0
end
if Diff.name == "I'm too young to die" then
if Diff.index == 1 then
if player_count < 10 then
wave_defense_table.wave_interval = 4500
else
@ -951,7 +917,7 @@ function Public.set_difficulty()
if wave_defense_table.wave_interval < 2200 or threat_check then
wave_defense_table.wave_interval = 2200
end
elseif Diff.name == 'Hurt me plenty' then
elseif Diff.index == 2 then
if player_count < 10 then
wave_defense_table.wave_interval = 3000
else
@ -960,7 +926,7 @@ function Public.set_difficulty()
if wave_defense_table.wave_interval < 1900 or threat_check then
wave_defense_table.wave_interval = 1900
end
elseif Diff.name == 'Ultra-violence' then
elseif Diff.index == 3 then
if player_count < 10 then
wave_defense_table.wave_interval = 2000
else
@ -1123,17 +1089,16 @@ function Public.boost_difficulty()
local breached_wall = WPT.get('breached_wall')
local difficulty = Difficulty.get()
local name = difficulty.difficulties[difficulty.difficulty_vote_index].name
if game.tick < difficulty.difficulty_poll_closing_timeout and breached_wall <= 1 then
if not difficulty then
return
end
Difficulty.get().name = name
Difficulty.get().difficulty_poll_closing_timeout = game.tick
local index = difficulty.index
local name = difficulty.name
Difficulty.get().button_tooltip = difficulty.tooltip[difficulty.difficulty_vote_index]
Difficulty.difficulty_gui()
if game.tick < difficulty.closing_timeout and breached_wall <= 1 then
return
end
local message = ({'main.diff_set', name})
local data = {
@ -1143,22 +1108,126 @@ function Public.boost_difficulty()
local force = game.forces.player
force.manual_mining_speed_modifier = force.manual_mining_speed_modifier + 0.5
force.character_running_speed_modifier = 0.15
force.manual_crafting_speed_modifier = 0.15
WPT.set('coin_amount', 1)
WPT.set('upgrades').flame_turret.limit = 12
WPT.set('upgrades').landmine.limit = 50
WPT.set('locomotive_health', 10000)
WPT.set('locomotive_max_health', 10000)
WPT.set('bonus_xp_on_join', 500)
WD.set('next_wave', game.tick + 3600 * 15)
WPT.set('spidertron_unlocked_at_zone', 10)
WD.set_normal_unit_current_health(1.0)
WD.set_unit_health_increment_per_wave(0.15)
WD.set_boss_unit_current_health(2)
WD.set_boss_health_increment_per_wave(1.5)
WPT.set('difficulty_set', true)
local active_surface_index = WPT.get('active_surface_index')
local surface = game.get_surface(active_surface_index)
if index == 1 then
force.manual_mining_speed_modifier = force.manual_mining_speed_modifier + 0.5
force.character_running_speed_modifier = 0.15
force.manual_crafting_speed_modifier = 0.15
WPT.set('coin_amount', 1)
WPT.set('upgrades').flame_turret.limit = 12
WPT.set('upgrades').landmine.limit = 50
WPT.set('locomotive_health', 10000)
WPT.set('locomotive_max_health', 10000)
WPT.set('bonus_xp_on_join', 500)
WD.set('next_wave', game.tick + 3600 * 15)
WPT.set('spidertron_unlocked_at_zone', 10)
WD.set_normal_unit_current_health(1.0)
WD.set_unit_health_increment_per_wave(0.15)
WD.set_boss_unit_current_health(2)
WD.set_boss_health_increment_per_wave(1.5)
WD.set('death_mode', false)
WPT.set('difficulty_set', true)
elseif index == 2 then
force.manual_mining_speed_modifier = force.manual_mining_speed_modifier + 0.25
force.character_running_speed_modifier = 0.1
force.manual_crafting_speed_modifier = 0.1
WPT.set('coin_amount', 2)
WPT.set('upgrades').flame_turret.limit = 10
WPT.set('upgrades').landmine.limit = 50
WPT.set('locomotive_health', 7000)
WPT.set('locomotive_max_health', 7000)
WPT.set('bonus_xp_on_join', 300)
WD.set('next_wave', game.tick + 3600 * 8)
WPT.set('spidertron_unlocked_at_zone', 8)
WD.set_normal_unit_current_health(1.6)
WD.set_unit_health_increment_per_wave(0.5)
WD.set_boss_unit_current_health(3)
WD.set_boss_health_increment_per_wave(5)
WD.set('death_mode', false)
WPT.set('difficulty_set', true)
local damage_warning = ({'main.damage_mode_warning'})
Alert.alert_all_players_location(data, damage_warning)
Core.iter_players(
function(player)
local pos = surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 3, 0, 5)
if pos then
player.teleport(pos, surface)
else
pos = game.forces.player.get_spawn_position(surface)
player.teleport(pos, surface)
end
end
)
local upgrades = WPT.get('upgrades')
if WPT.get('circle') then
rendering.destroy(WPT.get('circle'))
end
local locomotive = WPT.get('locomotive')
WPT.set(
'circle',
rendering.draw_circle {
surface = active_surface_index,
target = locomotive,
color = locomotive.color,
filled = false,
radius = upgrades.locomotive_aura_radius,
only_in_alt_mode = false
}
)
difficulty_and_adjust_prices()
elseif index == 3 then
force.character_running_speed_modifier = 0
force.manual_crafting_speed_modifier = 0
WPT.set('coin_amount', 4)
WPT.set('upgrades').flame_turret.limit = 3
WPT.set('upgrades').landmine.limit = 10
WPT.set('locomotive_health', 5000)
WPT.set('locomotive_max_health', 5000)
WPT.set('bonus_xp_on_join', 50)
WD.set('next_wave', game.tick + 3600 * 5)
WPT.set('spidertron_unlocked_at_zone', 6)
WD.set_normal_unit_current_health(2)
WD.set_unit_health_increment_per_wave(1)
WD.set_boss_unit_current_health(4)
WD.set_boss_health_increment_per_wave(10)
WD.set('death_mode', true)
WPT.set('difficulty_set', true)
Core.iter_players(
function(player)
local pos = surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 3, 0, 5)
if pos then
player.teleport(pos, surface)
else
pos = game.forces.player.get_spawn_position(surface)
player.teleport(pos, surface)
end
end
)
local upgrades = WPT.get('upgrades')
upgrades.locomotive_aura_radius = upgrades.locomotive_aura_radius + 20
if WPT.get('circle') then
rendering.destroy(WPT.get('circle'))
end
local locomotive = WPT.get('locomotive')
WPT.set(
'circle',
rendering.draw_circle {
surface = active_surface_index,
target = locomotive,
color = locomotive.color,
filled = false,
radius = upgrades.locomotive_aura_radius,
only_in_alt_mode = false
}
)
local aura_upgrade = ({'main.aura_upgrade_warning'})
Alert.alert_all_players_location(data, aura_upgrade)
local death_warning = ({'main.death_mode_warning'})
Alert.alert_all_players_location(data, death_warning)
difficulty_and_adjust_prices()
end
end
function Public.set_spawn_position()
@ -1289,6 +1358,10 @@ function Public.on_player_joined_game(event)
end
local message = ({'main.greeting', player.name})
Alert.alert_player(player, 15, message)
if WPT.get('death_mode') then
local death_message = ({'main.death_mode_warning'})
Alert.alert_player(player, 15, death_message)
end
for item, amount in pairs(starting_items) do
player.insert({name = item, count = amount})
end
@ -1345,24 +1418,6 @@ function Public.disable_creative()
end
end
function Public.on_pre_player_left_game(event)
local offline_players_enabled = WPT.get('offline_players_enabled')
if not offline_players_enabled then
return
end
local offline_players = WPT.get('offline_players')
local player = game.players[event.player_index]
local ticker = game.tick
if player.character then
offline_players[#offline_players + 1] = {
index = event.player_index,
name = player.name,
tick = ticker
}
end
end
function Public.on_player_respawned(event)
local player = game.get_player(event.player_index)
if not player or not player.valid then
@ -1381,7 +1436,7 @@ function Public.on_player_changed_position(event)
return
end
local player = game.players[event.player_index]
local map_name = 'mountain_fortress_v3'
local map_name = 'mtn_v3'
if string.sub(player.surface.name, 0, #map_name) ~= map_name then
return
@ -1468,6 +1523,15 @@ function Public.on_research_finished(event)
local bonus_drill = game.forces.bonus_drill
local player = game.forces.player
local research_name = research.name
local force = research.force
local technology_prototypes = game.technology_prototypes
if WPT.get('print_tech_to_discord') and force.name == 'player' then
Server.to_discord_bold({'functions.researched_complete', technology_prototypes[research_name].localised_name}, true)
end
research.force.character_inventory_slots_bonus = player.mining_drill_productivity_bonus * 50 -- +5 Slots /
bonus_drill.mining_drill_productivity_bonus = bonus_drill.mining_drill_productivity_bonus + 0.03
if bonus_drill.mining_drill_productivity_bonus >= 3 then
@ -1515,14 +1579,12 @@ local on_player_joined_game = Public.on_player_joined_game
local on_player_left_game = Public.on_player_left_game
local on_research_finished = Public.on_research_finished
local on_player_changed_position = Public.on_player_changed_position
local on_pre_player_left_game = Public.on_pre_player_left_game
local on_player_respawned = Public.on_player_respawned
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_player_left_game, on_player_left_game)
Event.add(defines.events.on_research_finished, on_research_finished)
Event.add(defines.events.on_player_changed_position, on_player_changed_position)
Event.add(defines.events.on_pre_player_left_game, on_pre_player_left_game)
Event.add(defines.events.on_player_respawned, on_player_respawned)
Event.on_nth_tick(10, tick)

View File

@ -410,8 +410,6 @@ function Public.update_gui(player)
local mined_scrap = WPT.get('mined_scrap')
local biters_killed = WPT.get('biters_killed')
local upgrades = WPT.get('upgrades')
local train_upgrades = WPT.get('train_upgrades')
local chest_limit_outside_upgrades = WPT.get('chest_limit_outside_upgrades')
if rpg_extra.global_pool == 0 then
gui.global_pool.caption = 'XP: 0'
@ -424,12 +422,11 @@ function Public.update_gui(player)
gui.scrap_mined.caption = ' [img=entity.tree-01][img=entity.rock-huge]: ' .. format_number(mined_scrap, true)
gui.scrap_mined.tooltip = ({'gui.amount_harvested'})
local pickaxe_tiers = WPT.pickaxe_upgrades
local tier = WPT.get('pickaxe_tier')
local pick_tier = pickaxe_tiers[tier]
local pickaxe_upgrades = WPT.pickaxe_upgrades
local pick_tier = pickaxe_upgrades[upgrades.pickaxe_tier]
local speed = math.round((player.force.manual_mining_speed_modifier + player.character_mining_speed_modifier + 1) * 100)
gui.pickaxe_tier.caption = ' [img=item.dummy-steel-axe]: ' .. pick_tier .. ' (' .. tier .. ')'
gui.pickaxe_tier.caption = ' [img=item.dummy-steel-axe]: ' .. pick_tier .. ' (' .. upgrades.pickaxe_tier .. ')'
gui.pickaxe_tier.tooltip = ({'gui.current_pickaxe_tier', pick_tier, speed})
gui.biters_killed.caption = ' [img=entity.small-biter]: ' .. format_number(biters_killed, true)
@ -441,10 +438,10 @@ function Public.update_gui(player)
gui.flame_turret.caption = ' [img=entity.flamethrower-turret]: ' .. format_number(upgrades.flame_turret.built, true) .. ' / ' .. format_number(upgrades.flame_turret.limit, true)
gui.flame_turret.tooltip = ({'gui.flamethrowers_placed'})
gui.train_upgrades.caption = ' [img=entity.locomotive]: ' .. format_number(train_upgrades, true)
gui.train_upgrades.caption = ' [img=entity.locomotive]: ' .. format_number(upgrades.train_upgrades, true)
gui.train_upgrades.tooltip = ({'gui.train_upgrades'})
gui.chest_upgrades.caption = ' [img=entity.steel-chest]: ' .. format_number(chest_limit_outside_upgrades, true)
gui.chest_upgrades.caption = ' [img=entity.steel-chest]: ' .. format_number(upgrades.chests_outside_upgrades, true)
gui.chest_upgrades.tooltip = ({'gui.chest_placed'})
end

View File

@ -5,6 +5,8 @@ local Token = require 'utils.token'
local IC = require 'maps.mountain_fortress_v3.ic.table'
local WPT = require 'maps.mountain_fortress_v3.table'
local RPG = require 'modules.rpg.main'
local OfflinePlayers = require 'modules.clear_vacant_players'
local Event = require 'utils.event'
local Public = {}
local main_tile_name = 'black-refined-concrete'
@ -211,7 +213,7 @@ local function get_saved_entity(entity, index)
end
local function replace_entity(cars, entity, index)
local has_upgraded_health_pool = WPT.get('has_upgraded_health_pool')
local upgrades = WPT.get('upgrades')
local unit_number = entity.unit_number
local health = floor(2000 * entity.health * 0.002)
for k, car in pairs(cars) do
@ -222,7 +224,7 @@ local function replace_entity(cars, entity, index)
cars[unit_number].saved_entity = nil
cars[unit_number].transfer_entities = car.transfer_entities
cars[unit_number].health_pool = {
enabled = has_upgraded_health_pool or false,
enabled = upgrades.has_upgraded_health_pool or false,
health = health,
max = health
}
@ -376,10 +378,7 @@ local function kick_players_from_surface(car)
if validate_entity(main_surface) then
for _, e in pairs(surface.find_entities_filtered({area = car.area})) do
if validate_entity(e) and e.name == 'character' and e.player then
e.player.teleport(
main_surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(main_surface), 3, 0, 5),
main_surface
)
e.player.teleport(main_surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(main_surface), 3, 0, 5), main_surface)
end
end
check_if_players_are_in_nauvis()
@ -424,10 +423,7 @@ local function kick_player_from_surface(player, target)
if p then
target.teleport(p, car.entity.surface)
else
target.teleport(
main_surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(main_surface), 3, 0, 5),
main_surface
)
target.teleport(main_surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(main_surface), 3, 0, 5), main_surface)
end
target.print('You were kicked out of ' .. player.name .. ' vehicle.', Color.warning)
end
@ -649,9 +645,7 @@ local find_remove_car =
return
end
for _, dropped_ent in pairs(
surface.find_entities_filtered {type = 'item-entity', area = {{position.x - 10, position.y - 10}, {position.x + 10, position.y + 10}}}
) do
for _, dropped_ent in pairs(surface.find_entities_filtered {type = 'item-entity', area = {{position.x - 10, position.y - 10}, {position.x + 10, position.y + 10}}}) do
if dropped_ent and dropped_ent.valid and dropped_ent.stack then
if types[dropped_ent.stack.name] then
dropped_ent.destroy()
@ -1104,7 +1098,7 @@ function Public.create_car(event)
end
local renders = IC.get('renders')
local has_upgraded_health_pool = WPT.get('has_upgraded_health_pool')
local upgrades = WPT.get('upgrades')
local name, mined = get_player_entity(player)
@ -1118,10 +1112,7 @@ function Public.create_car(event)
local storage = get_trusted_system(player)
if
get_owner_car_name(player) == 'car' and ce.name == 'tank' or get_owner_car_name(player) == 'car' and ce.name == 'spidertron' or
get_owner_car_name(player) == 'tank' and ce.name == 'spidertron'
then
if get_owner_car_name(player) == 'car' and ce.name == 'tank' or get_owner_car_name(player) == 'car' and ce.name == 'spidertron' or get_owner_car_name(player) == 'tank' and ce.name == 'spidertron' then
if storage.auto_upgrade and storage.auto_upgrade == 'right' then
return
end
@ -1157,7 +1148,7 @@ function Public.create_car(event)
},
doors = {},
health_pool = {
enabled = has_upgraded_health_pool or false,
enabled = upgrades.has_upgraded_health_pool or false,
health = health,
max = health
},
@ -1361,7 +1352,7 @@ function Public.check_entity_healths()
['spidertron'] = 3000
}
for k, car in pairs(cars) do
for _, car in pairs(cars) do
local m = car.health_pool.health / car.health_pool.max
if car.health_pool.health > car.health_pool.max then
@ -1434,4 +1425,16 @@ Public.get_entity_from_player_surface = get_entity_from_player_surface
Public.get_owner_car_object = get_owner_car_object
Public.render_owner_text = render_owner_text
Event.add(
OfflinePlayers.events.remove_surface,
function(event)
local target = event.target
if not target then
return
end
Public.remove_surface(target)
end
)
return Public

View File

@ -102,8 +102,8 @@ local function on_tick()
if tick % 20 == 1 then
Functions.item_transfer()
local has_upgraded_health_pool = WPT.get('has_upgraded_health_pool')
if has_upgraded_health_pool then
local upgrades = WPT.get('upgrades')
if upgrades.has_upgraded_health_pool then
Functions.check_entity_healths()
end
end
@ -214,8 +214,8 @@ local function on_gui_switch_state_changed(event)
end
local function on_entity_damaged(event)
local has_upgraded_health_pool = WPT.get('has_upgraded_health_pool')
if not has_upgraded_health_pool then
local upgrades = WPT.get('upgrades')
if not upgrades.has_upgraded_health_pool then
return
end
@ -252,8 +252,8 @@ local function on_entity_damaged(event)
end
local function on_player_repaired_entity(event)
local has_upgraded_health_pool = WPT.get('has_upgraded_health_pool')
if not has_upgraded_health_pool then
local upgrades = WPT.get('upgrades')
if not upgrades.has_upgraded_health_pool then
return
end

View File

@ -71,10 +71,7 @@ local function kick_players_from_surface(wagon)
if validate_entity(main_surface) then
for _, e in pairs(wagon.surface.find_entities_filtered({area = wagon.area})) do
if validate_entity(e) and e.name == 'character' and e.player then
e.player.teleport(
main_surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(main_surface), 3, 0, 5),
main_surface
)
e.player.teleport(main_surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(main_surface), 3, 0, 5), main_surface)
end
end
end
@ -960,10 +957,7 @@ local function move_room_to_train(icw, train, wagon)
train.top_y = destination_area.right_bottom.y
if
destination_area.left_top.x == wagon.area.left_top.x and destination_area.left_top.y == wagon.area.left_top.y and
wagon.surface.name == train.surface.name
then
if destination_area.left_top.x == wagon.area.left_top.x and destination_area.left_top.y == wagon.area.left_top.y and wagon.surface.name == train.surface.name then
return
end
kick_players_from_surface(wagon)
@ -1049,9 +1043,7 @@ local function get_connected_rolling_stock(entity, direction, carriages)
return nil
end
angle =
math.atan2(-(connected_stock.position.x - entity.position.x), connected_stock.position.y - entity.position.y) / (2 * math.pi) -
connected_stock.orientation
angle = math.atan2(-(connected_stock.position.x - entity.position.x), connected_stock.position.y - entity.position.y) / (2 * math.pi) - connected_stock.orientation
while angle < -0.5 do
angle = angle + 1
end
@ -1165,9 +1157,7 @@ function Public.draw_minimap(icw, player, surface, position)
end
local element = frame['icw_sub_frame']
if not frame.icw_auto_switch then
frame.add(
{type = 'switch', name = 'icw_auto_switch', allow_none_state = false, left_label_caption = {'gui.map_on'}, right_label_caption = {'gui.map_off'}}
)
frame.add({type = 'switch', name = 'icw_auto_switch', allow_none_state = false, left_label_caption = {'gui.map_on'}, right_label_caption = {'gui.map_off'}})
end
if not element then
element =
@ -1252,7 +1242,7 @@ end
function Public.on_player_or_robot_built_tile(event)
local surface = game.surfaces[event.surface_index]
local map_name = 'mountain_fortress_v3'
local map_name = 'mtn_v3'
if string.sub(surface.name, 0, #map_name) == map_name then
return

View File

@ -13,7 +13,7 @@ local function on_entity_died(event)
end
local wagon_types = ICW.get('wagon_types')
if not wagon_types[entity.type] then
if entity and entity.valid and not wagon_types[entity.type] then
return
end
local icw = ICW.get()

View File

@ -9,7 +9,6 @@ local Difficulty = require 'modules.difficulty_vote_by_amount'
local RPG = require 'modules.rpg.main'
local Gui = require 'utils.gui'
local Alert = require 'utils.alert'
local Math2D = require 'math2d'
local PermissionGroups = require 'maps.mountain_fortress_v3.locomotive.permission_groups'
local Public = {}
@ -18,6 +17,7 @@ local rpg_main_frame = RPG.main_frame_name
local random = math.random
local floor = math.floor
local round = math.round
local sub = string.sub
local clear_items_upon_surface_entry = {
['entity-ghost'] = true,
@ -33,6 +33,11 @@ local valid_armors = {
['power-armor-mk2'] = true
}
local non_valid_vehicles = {
['car'] = true,
['spider-vehicle'] = true
}
local function add_random_loot_to_main_market(rarity)
local main_market_items = WPT.get('main_market_items')
local items = Market.get_random_item(rarity, true, false)
@ -72,25 +77,132 @@ local function add_random_loot_to_main_market(rarity)
end
end
local function validate_player(player)
if not player then
return false
local function death_effects(player)
local position = {x = player.position.x - 0.75, y = player.position.y - 1}
local b = 0.75
for _ = 1, 5, 1 do
local p = {
(position.x + 0.4) + (b * -1 + math.random(0, b * 20) * 0.1),
position.y + (b * -1 + math.random(0, b * 20) * 0.1)
}
player.surface.create_entity({name = 'flying-text', position = p, text = '☠️', color = {255, math.random(0, 100), 0}})
end
if not player.valid then
return false
end
if not player.character then
return false
end
if not player.connected then
return false
end
if not game.get_player(player.name) then
return false
end
return true
player.play_sound {path = 'utility/axe_fighting', volume_modifier = 0.9}
end
local messages = {
' likes to play in magma.',
' got melted.',
' tried to swim in lava.',
' was incinerated.',
" couldn't put the fire out.",
' was turned into their molten form.'
}
local function is_around_train(data)
local entity = data.entity
local locomotive_aura_radius = data.locomotive_aura_radius + 20
local loco = data.locomotive.position
local position = entity.position
local inside = ((position.x - loco.x) ^ 2 + (position.y - loco.y) ^ 2) < locomotive_aura_radius ^ 2
if inside then
return true
end
return false
end
local function hurt_players_outside_of_aura()
local Diff = Difficulty.get()
if not Diff then
return
end
local difficulty_set = WPT.get('difficulty_set')
if not difficulty_set then
return
end
local death_mode = false
if Diff.index == 1 then
return
elseif Diff.index == 3 then
death_mode = true
end
local loco_surface = WPT.get('loco_surface')
if not (loco_surface and loco_surface.valid) then
return
end
local locomotive = WPT.get('locomotive')
local loco = locomotive.position
local upgrades = WPT.get('upgrades')
local players = game.connected_players
for i = 1, #players do
local player = players[i]
if not player or not player.valid then
goto pre_exit
end
local map_name = 'mtn_v3'
if sub(player.surface.name, 0, #map_name) == map_name then
local position = player.position
local inside = ((position.x - loco.x) ^ 2 + (position.y - loco.y) ^ 2) < upgrades.locomotive_aura_radius ^ 2
if not inside then
local entity = player.character
if entity and entity.valid then
death_effects(player)
player.surface.create_entity({name = 'fire-flame', position = position})
if random(1, 3) == 1 then
player.surface.create_entity({name = 'medium-scorchmark', position = position, force = 'neutral'})
end
local max_health = floor(player.character.prototype.max_health + player.character_health_bonus + player.force.character_health_bonus)
local vehicle = player.vehicle
if vehicle and vehicle.valid and non_valid_vehicles[vehicle.type] then
player.driving = false
end
if death_mode then
if entity.name == 'character' then
game.print(player.name .. messages[random(1, #messages)], {r = 200, g = 0, b = 0})
end
if entity.valid then
entity.die()
end
else
local armor_inventory = player.get_inventory(defines.inventory.character_armor)
if not armor_inventory.valid then
goto pre_exit
end
local armor = armor_inventory[1]
if not armor.valid_for_read then
goto pre_exit
end
local grid = armor.grid
if not grid or not grid.valid then
goto pre_exit
end
local equip = grid.equipment
for _, piece in pairs(equip) do
if piece.valid then
piece.energy = 0
end
end
local damage = (max_health / 18)
if entity.valid then
if entity.health - damage <= 0 then
if entity.name == 'character' then
game.print(player.name .. messages[random(1, #messages)], {r = 200, g = 0, b = 0})
end
end
end
entity.damage(damage, 'enemy')
end
end
end
end
::pre_exit::
end
end
local function give_passive_xp(data)
local xp_floating_text_color = {r = 188, g = 201, b = 63}
local visuals_delay = 1800
@ -98,33 +210,30 @@ local function give_passive_xp(data)
if not (loco_surface and loco_surface.valid) then
return
end
local locomotive_xp_aura = WPT.get('locomotive_xp_aura')
local upgrades = WPT.get('upgrades')
local locomotive = WPT.get('locomotive')
local xp_points = WPT.get('xp_points')
local aura = locomotive_xp_aura
local rpg = data.rpg
local loco = locomotive.position
local area = {
left_top = {x = loco.x - aura, y = loco.y - aura},
right_bottom = {x = loco.x + aura, y = loco.y + aura}
}
for _, player in pairs(game.connected_players) do
if not validate_player(player) then
return
if not player or not player.valid then
goto pre_exit
end
local position = player.position
local inside = ((position.x - loco.x) ^ 2 + (position.y - loco.y) ^ 2) < upgrades.locomotive_aura_radius ^ 2
if player.afk_time < 200 and not RPG.get_last_spell_cast(player) then
if Math2D.bounding_box.contains_point(area, player.position) or player.surface.index == loco_surface.index then
if inside or player.surface.index == loco_surface.index then
if player.surface.index == loco_surface.index then
PermissionGroups.add_player_to_permission_group(player, 'limited')
elseif ICFunctions.get_player_surface(player) then
return PermissionGroups.add_player_to_permission_group(player, 'limited')
PermissionGroups.add_player_to_permission_group(player, 'limited')
goto pre_exit
else
PermissionGroups.add_player_to_permission_group(player, 'near_locomotive')
end
local pos = player.position
RPG.gain_xp(player, 0.5 * (rpg[player.index].bonus + xp_points))
RPG.gain_xp(player, 0.5 * (rpg[player.index].bonus + upgrades.xp_points))
player.create_local_flying_text {
text = '+' .. '',
@ -139,7 +248,7 @@ local function give_passive_xp(data)
if player.gui.screen[rpg_main_frame] then
local f = player.gui.screen[rpg_main_frame]
local d = Gui.get_data(f)
if d.exp_gui and d.exp_gui.valid then
if d and d.exp_gui and d.exp_gui.valid then
d.exp_gui.caption = floor(rpg[player.index].xp)
end
end
@ -153,25 +262,10 @@ local function give_passive_xp(data)
end
end
end
::pre_exit::
end
end
local function is_around_train(data)
local entity = data.entity
local aura = data.aura + 20
local loco = data.locomotive.position
local area = {
left_top = {x = loco.x - aura, y = loco.y - aura},
right_bottom = {x = loco.x + aura, y = loco.y + aura}
}
local pos = entity.position
if Math2D.bounding_box.contains_point(area, pos) then
return true
end
return false
end
local function fish_tag()
local locomotive_cargo = WPT.get('locomotive_cargo')
if not (locomotive_cargo and locomotive_cargo.valid) then
@ -373,7 +467,7 @@ end
local function on_player_changed_surface(event)
local player = game.players[event.player_index]
if not validate_player(player) then
if not player or not player.valid then
return
end
@ -488,13 +582,13 @@ function Public.is_around_train(entity)
end
local surface = game.surfaces[active_surface_index]
local aura = WPT.get('locomotive_xp_aura')
local upgrades = WPT.get('upgrades')
local data = {
locomotive = locomotive,
surface = surface,
entity = entity,
aura = aura
locomotive_aura_radius = upgrades.locomotive_aura_radius
}
local success = is_around_train(data)
@ -508,43 +602,49 @@ function Public.render_train_hp()
local locomotive_health = WPT.get('locomotive_health')
local locomotive_max_health = WPT.get('locomotive_max_health')
local locomotive = WPT.get('locomotive')
local locomotive_xp_aura = WPT.get('locomotive_xp_aura')
local upgrades = WPT.get('upgrades')
WPT.set().health_text =
WPT.set(
'health_text',
rendering.draw_text {
text = 'HP: ' .. locomotive_health .. ' / ' .. locomotive_max_health,
surface = surface,
target = locomotive,
target_offset = {0, -4.5},
color = locomotive.color,
scale = 1.40,
font = 'default-game',
alignment = 'center',
scale_with_zoom = false
}
text = 'HP: ' .. locomotive_health .. ' / ' .. locomotive_max_health,
surface = surface,
target = locomotive,
target_offset = {0, -4.5},
color = locomotive.color,
scale = 1.40,
font = 'default-game',
alignment = 'center',
scale_with_zoom = false
}
)
WPT.set().caption =
WPT.set(
'caption',
rendering.draw_text {
text = 'Comfy Choo Choo',
surface = surface,
target = locomotive,
target_offset = {0, -6.25},
color = locomotive.color,
scale = 1.80,
font = 'default-game',
alignment = 'center',
scale_with_zoom = false
}
text = 'Comfy Choo Choo',
surface = surface,
target = locomotive,
target_offset = {0, -6.25},
color = locomotive.color,
scale = 1.80,
font = 'default-game',
alignment = 'center',
scale_with_zoom = false
}
)
WPT.set().circle =
WPT.set(
'circle',
rendering.draw_circle {
surface = surface,
target = locomotive,
color = locomotive.color,
filled = false,
radius = locomotive_xp_aura,
only_in_alt_mode = true
}
surface = surface,
target = locomotive,
color = locomotive.color,
filled = false,
radius = upgrades.locomotive_aura_radius,
only_in_alt_mode = true
}
)
end
function Public.transfer_pollution()
@ -567,7 +667,7 @@ function Public.transfer_pollution()
local total_interior_pollution = surface.get_total_pollution()
local pollution = surface.get_total_pollution() * (3 / (4 / 3 + 1)) * Difficulty.get().difficulty_vote_value
local pollution = surface.get_total_pollution() * (3 / (4 / 3 + 1)) * Difficulty.get().value
active_surface.pollute(locomotive.position, pollution)
game.pollution_statistics.on_flow('locomotive', pollution - total_interior_pollution)
surface.clear_pollution()
@ -583,10 +683,12 @@ local function tick()
set_locomotive_health()
validate_index()
fish_tag()
hurt_players_outside_of_aura()
end
if ticker % 120 == 0 then
-- tp_player()
boost_players()
end

View File

@ -16,7 +16,7 @@ local function contains_positions(area)
for _, wagon in pairs(wagons) do
if wagon.entity and wagon.entity.valid then
if wagon.entity.name == 'cargo-wagon' then
if inside(wagon.entity.position, area) then
if inside(wagon.entity.position) then
return true, wagon.entity
end
end
@ -35,7 +35,7 @@ local function on_built_entity(event)
return
end
local map_name = 'mountain_fortress_v3'
local map_name = 'mtn_v3'
if string.sub(entity.surface.name, 0, #map_name) ~= map_name then
return
@ -54,15 +54,15 @@ local function on_built_entity(event)
local outside_chests = WPT.get('outside_chests')
local chests_linked_to = WPT.get('chests_linked_to')
local chest_limit_outside_upgrades = WPT.get('chest_limit_outside_upgrades')
local upgrades = WPT.get('upgrades')
local chest_created
local increased = false
for k, data in pairs(outside_chests) do
for _, data in pairs(outside_chests) do
if data and data.chest and data.chest.valid then
if chests_linked_to[train.unit_number] then
local linked_to = chests_linked_to[train.unit_number].count
if linked_to == chest_limit_outside_upgrades then
if linked_to == upgrades.chests_outside_upgrades then
return
end
outside_chests[entity.unit_number] = {chest = entity, position = entity.position, linked = train.unit_number}
@ -80,7 +80,8 @@ local function on_built_entity(event)
end
::continue::
rendering.draw_text {
outside_chests[entity.unit_number].render =
rendering.draw_text {
text = '',
surface = entity.surface,
target = entity,
@ -102,7 +103,8 @@ local function on_built_entity(event)
chests_linked_to[train.unit_number] = {count = 1}
chests_linked_to[train.unit_number][entity.unit_number] = true
rendering.draw_text {
outside_chests[entity.unit_number].render =
rendering.draw_text {
text = '',
surface = entity.surface,
target = entity,
@ -159,6 +161,9 @@ local function divide_contents()
if not (chest and chest.valid) then
if chests_linked_to[data.linked] then
if chests_linked_to[data.linked][key] then
if data.render and rendering.is_valid(data.render) then
rendering.destroy(data.render)
end
chests_linked_to[data.linked][key] = nil
chests_linked_to[data.linked].count = chests_linked_to[data.linked].count - 1
if chests_linked_to[data.linked].count <= 0 then
@ -175,12 +180,16 @@ local function divide_contents()
target_chest = entity
else
if chests_linked_to[data.linked] then
if chests_linked_to[data.linked][key] then
if data then
if data.render and rendering.is_valid(data.render) then
rendering.destroy(data.render)
end
chests_linked_to[data.linked][key] = nil
chests_linked_to[data.linked].count = chests_linked_to[data.linked].count - 1
if chests_linked_to[data.linked].count <= 0 then
chests_linked_to[data.linked] = nil
end
outside_chests[key] = nil
end
end
goto continue

View File

@ -4,6 +4,7 @@ local ICW = require 'maps.mountain_fortress_v3.icw.main'
local WPT = require 'maps.mountain_fortress_v3.table'
local WD = require 'modules.wave_defense.table'
local Session = require 'utils.datastore.session_data'
local Difficulty = require 'modules.difficulty_vote_by_amount'
local RPG = require 'modules.rpg.main'
local Gui = require 'utils.gui'
local Server = require 'utils.server'
@ -44,34 +45,28 @@ local function add_space(frame)
end
local function get_items()
local chest_limit_outside_upgrades = WPT.get('chest_limit_outside_upgrades')
local health_upgrades = WPT.get('health_upgrades')
local pickaxe_tier = WPT.get('pickaxe_tier')
local aura_upgrades = WPT.get('aura_upgrades')
local market_limits = WPT.get('market_limits')
local main_market_items = WPT.get('main_market_items')
local xp_points_upgrade = WPT.get('xp_points_upgrade')
local flame_turret = WPT.get('upgrades').flame_turret.bought
local landmine = WPT.get('upgrades').landmine.bought
local upgrades = WPT.get('upgrades')
local fixed_prices = WPT.get('marked_fixed_prices')
local health_upgrades_limit = WPT.get('health_upgrades_limit')
local has_upgraded_health_pool = WPT.get('has_upgraded_health_pool')
local chest_limit_cost = round(fixed_prices.chest_limit_cost * (1 + chest_limit_outside_upgrades))
local health_cost = round(fixed_prices.health_cost * (1 + health_upgrades))
local pickaxe_cost = round(fixed_prices.pickaxe_cost * (0.1 + pickaxe_tier / 2))
local aura_cost = round(fixed_prices.aura_cost * (1 + aura_upgrades))
local xp_point_boost_cost = round(fixed_prices.xp_point_boost_cost * (1 + xp_points_upgrade))
local chests_outside_cost = round(fixed_prices.chests_outside_cost * (1 + upgrades.chests_outside_upgrades))
local health_cost = round(fixed_prices.health_cost * (1 + upgrades.health_upgrades))
local pickaxe_cost = round(fixed_prices.pickaxe_cost * (0.1 + upgrades.pickaxe_tier / 2))
local aura_cost = round(fixed_prices.aura_cost * (1 + upgrades.aura_upgrades))
local xp_point_boost_cost = round(fixed_prices.xp_point_boost_cost * (1 + upgrades.xp_points_upgrade))
local explosive_bullets_cost = round(fixed_prices.explosive_bullets_cost)
local redraw_mystical_chest_cost = round(fixed_prices.redraw_mystical_chest_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 land_mine_cost = round(fixed_prices.land_mine_cost * (1 + upgrades.landmine.bought))
local car_health_upgrade_pool = fixed_prices.car_health_upgrade_pool_cost
local pickaxe_tiers = WPT.pickaxe_upgrades
local tier = WPT.get('pickaxe_tier')
local offer = pickaxe_tiers[tier]
local pickaxe_upgrades = WPT.pickaxe_upgrades
if pickaxe_tier >= 59 then
local offer = pickaxe_upgrades[upgrades.pickaxe_tier]
if upgrades.pickaxe_tier >= market_limits.pickaxe_tier_limit then
main_market_items['upgrade_pickaxe'] = {
stack = 1,
value = 'coin',
@ -87,7 +82,7 @@ local function get_items()
stack = 1,
value = 'coin',
price = pickaxe_cost,
tooltip = ({'main_market.purchase_pickaxe', offer, pickaxe_tier - 1}),
tooltip = ({'main_market.purchase_pickaxe', offer, upgrades.pickaxe_tier, market_limits.pickaxe_tier_limit}),
sprite = 'achievement/delivery-service',
enabled = true,
upgrade = true,
@ -95,11 +90,11 @@ local function get_items()
}
end
if chest_limit_outside_upgrades == 8 then
if upgrades.chests_outside_upgrades == market_limits.chests_outside_limit then
main_market_items['chest_limit_outside'] = {
stack = 1,
value = 'coin',
price = chest_limit_cost,
price = chests_outside_cost,
tooltip = ({'locomotive.limit_reached'}),
sprite = 'achievement/so-long-and-thanks-for-all-the-fish',
enabled = false,
@ -110,8 +105,8 @@ local function get_items()
main_market_items['chest_limit_outside'] = {
stack = 1,
value = 'coin',
price = chest_limit_cost,
tooltip = ({'main_market.chest', chest_limit_outside_upgrades - 1}),
price = chests_outside_cost,
tooltip = ({'main_market.chest', upgrades.chests_outside_upgrades, market_limits.chests_outside_limit}),
sprite = 'achievement/so-long-and-thanks-for-all-the-fish',
enabled = true,
upgrade = true,
@ -119,7 +114,7 @@ local function get_items()
}
end
if health_upgrades >= health_upgrades_limit then
if upgrades.health_upgrades >= market_limits.health_upgrades_limit then
main_market_items['locomotive_max_health'] = {
stack = 1,
value = 'coin',
@ -135,7 +130,7 @@ local function get_items()
stack = 1,
value = 'coin',
price = health_cost,
tooltip = ({'main_market.locomotive_max_health', health_upgrades - 1}),
tooltip = ({'main_market.locomotive_max_health', upgrades.health_upgrades, market_limits.health_upgrades_limit}),
sprite = 'achievement/getting-on-track',
enabled = true,
upgrade = true,
@ -143,18 +138,31 @@ local function get_items()
}
end
main_market_items['locomotive_xp_aura'] = {
stack = 1,
value = 'coin',
price = aura_cost,
tooltip = ({'main_market.locomotive_xp_aura', aura_upgrades}),
sprite = 'achievement/tech-maniac',
enabled = true,
upgrade = true,
static = true
}
if upgrades.locomotive_aura_radius == market_limits.aura_limit then
main_market_items['locomotive_aura_radius'] = {
stack = 1,
value = 'coin',
price = aura_cost,
tooltip = ({'locomotive.limit_reached'}),
sprite = 'achievement/tech-maniac',
enabled = false,
upgrade = true,
static = true
}
else
main_market_items['locomotive_aura_radius'] = {
stack = 1,
value = 'coin',
price = aura_cost,
tooltip = ({'main_market.locomotive_aura_radius', upgrades.locomotive_aura_radius, market_limits.aura_limit}),
sprite = 'achievement/tech-maniac',
enabled = true,
upgrade = true,
static = true
}
end
if has_upgraded_health_pool then
if upgrades.has_upgraded_health_pool then
main_market_items['car_health_upgrade_pool'] = {
stack = 1,
value = 'coin',
@ -181,7 +189,7 @@ local function get_items()
stack = 1,
value = 'coin',
price = xp_point_boost_cost,
tooltip = ({'main_market.xp_points_boost', xp_points_upgrade}),
tooltip = ({'main_market.xp_points_boost', upgrades.xp_points_upgrade}),
sprite = 'achievement/trans-factorio-express',
enabled = true,
upgrade = true,
@ -199,7 +207,7 @@ local function get_items()
static = true
}
if WPT.get('explosive_bullets') then
if upgrades.explosive_bullets_purchased then
main_market_items['explosive_bullets'] = {
stack = 1,
value = 'coin',
@ -222,6 +230,7 @@ local function get_items()
static = true
}
end
main_market_items['flamethrower_turrets'] = {
stack = 1,
value = 'coin',
@ -236,7 +245,7 @@ local function get_items()
stack = 1,
value = 'coin',
price = land_mine_cost,
tooltip = ({'main_market.land_mine', landmine}),
tooltip = ({'main_market.land_mine', upgrades.landmine.bought}),
sprite = 'achievement/watch-your-step',
enabled = true,
upgrade = true,
@ -802,6 +811,9 @@ local function gui_opened(event)
end
local frame, inside_table = Gui.add_main_frame_with_toolbar(player, 'screen', main_frame_name, nil, close_market_gui_name, 'Market')
if not inside_table then
return
end
frame.auto_center = true
player.opened = frame
@ -933,11 +945,10 @@ local function gui_click(event)
if name == 'upgrade_pickaxe' then
player.remove_item({name = item.value, count = item.price})
this.pickaxe_tier = this.pickaxe_tier + item.stack
this.upgrades.pickaxe_tier = this.upgrades.pickaxe_tier + item.stack
local pickaxe_tiers = WPT.pickaxe_upgrades
local tier = this.pickaxe_tier
local offer = pickaxe_tiers[tier]
local pickaxe_upgrades = WPT.pickaxe_upgrades
local offer = pickaxe_upgrades[this.upgrades.pickaxe_tier]
local message = ({
'locomotive.pickaxe_bought_info',
@ -949,7 +960,7 @@ local function gui_click(event)
Alert.alert_all_players(5, message)
Server.to_discord_bold(
table.concat {
player.name .. ' has upgraded the teams pickaxe to tier ' .. tier .. ' for ' .. format_number(item.price, true) .. ' coins.'
player.name .. ' has upgraded the teams pickaxe to tier ' .. this.upgrades.pickaxe_tier .. ' for ' .. format_number(item.price, true) .. ' coins.'
}
)
@ -963,9 +974,10 @@ local function gui_click(event)
return
end
if name == 'chest_limit_outside' then
if this.chest_limit_outside_upgrades == 7 then
if this.upgrades.chests_outside_upgrades == this.market_limits.chests_outside_limit then
redraw_market_items(data.item_frame, player, data.search_text)
player.print(({'locomotive.chests_full'}), {r = 0.98, g = 0.66, b = 0.22})
return
end
player.remove_item({name = item.value, count = item.price})
@ -976,7 +988,7 @@ local function gui_click(event)
player.name .. ' has bought the chest limit upgrade for ' .. format_number(item.price, true) .. ' coins.'
}
)
this.chest_limit_outside_upgrades = this.chest_limit_outside_upgrades + item.stack
this.upgrades.chests_outside_upgrades = this.upgrades.chests_outside_upgrades + item.stack
redraw_market_items(data.item_frame, player, data.search_text)
redraw_coins_left(data.coins_left, player)
@ -1017,8 +1029,8 @@ local function gui_click(event)
end
end
this.train_upgrades = this.train_upgrades + item.stack
this.health_upgrades = this.health_upgrades + item.stack
this.upgrades.train_upgrades = this.upgrades.train_upgrades + item.stack
this.upgrades.health_upgrades = this.upgrades.health_upgrades + item.stack
rendering.set_text(this.health_text, 'HP: ' .. round(this.locomotive_health) .. ' / ' .. round(this.locomotive_max_health))
redraw_market_items(data.item_frame, player, data.search_text)
@ -1026,7 +1038,12 @@ local function gui_click(event)
return
end
if name == 'locomotive_xp_aura' then
if name == 'locomotive_aura_radius' then
if this.upgrades.locomotive_aura_radius == this.market_limits.aura_limit then
redraw_market_items(data.item_frame, player, data.search_text)
player.print(({'locomotive.limit_reached'}), {r = 0.98, g = 0.66, b = 0.22})
return
end
player.remove_item({name = item.value, count = item.price})
local message = ({'locomotive.aura_bought_info', shopkeeper, player.name, format_number(item.price, true)})
@ -1037,21 +1054,28 @@ local function gui_click(event)
player.name .. ' has bought the locomotive xp aura modifier for ' .. format_number(item.price, true) .. ' coins.'
}
)
this.locomotive_xp_aura = this.locomotive_xp_aura + 5
this.aura_upgrades = this.aura_upgrades + item.stack
this.train_upgrades = this.train_upgrades + item.stack
this.upgrades.locomotive_aura_radius = this.upgrades.locomotive_aura_radius + 5
this.upgrades.aura_upgrades = this.upgrades.aura_upgrades + item.stack
this.upgrades.train_upgrades = this.upgrades.train_upgrades + item.stack
if this.circle then
rendering.destroy(this.circle)
end
local difficulty_index = Difficulty.get('index')
local fill_circle = false
if difficulty_index == 2 or difficulty_index == 3 then
fill_circle = true
end
this.circle =
rendering.draw_circle {
surface = game.surfaces[this.active_surface_index],
target = this.locomotive,
color = this.locomotive.color,
filled = false,
radius = this.locomotive_xp_aura,
only_in_alt_mode = true
radius = this.upgrades.locomotive_aura_radius,
only_in_alt_mode = fill_circle
}
redraw_market_items(data.item_frame, player, data.search_text)
@ -1070,9 +1094,9 @@ local function gui_click(event)
player.name .. ' has bought the XP points modifier for ' .. format_number(item.price) .. ' coins.'
}
)
this.xp_points = this.xp_points + 0.5
this.xp_points_upgrade = this.xp_points_upgrade + item.stack
this.train_upgrades = this.train_upgrades + item.stack
this.upgrades.xp_points = this.upgrades.xp_points + 0.5
this.upgrades.xp_points_upgrade = this.upgrades.xp_points_upgrade + item.stack
this.upgrades.train_upgrades = this.upgrades.train_upgrades + item.stack
redraw_market_items(data.item_frame, player, data.search_text)
redraw_coins_left(data.coins_left, player)
@ -1115,7 +1139,7 @@ local function gui_click(event)
}
)
RPG.enable_explosive_bullets(true)
this.explosive_bullets = true
this.upgrades.explosive_bullets_purchased = true
redraw_market_items(data.item_frame, player, data.search_text)
redraw_coins_left(data.coins_left, player)
@ -1138,8 +1162,7 @@ local function gui_click(event)
player.name .. ' has bought the global car health modifier for ' .. format_number(item.price) .. ' coins.'
}
)
this.has_upgraded_health_pool = true
this.explosive_bullets = true
this.upgrades.has_upgraded_health_pool = true
redraw_market_items(data.item_frame, player, data.search_text)
redraw_coins_left(data.coins_left, player)

View File

@ -14,10 +14,15 @@ function Public.add_player_to_permission_group(player, group, forced)
local session = Session.get_session_table()
local AG = Antigrief.get()
local allow_decon = WPT.get('allow_decon')
local allow_decon_main_surface = WPT.get('allow_decon_main_surface')
local default_group = game.permissions.get_group('Default')
default_group.set_allows_action(defines.input_action.deconstruct, false)
default_group.set_allows_action(defines.input_action.activate_cut, false)
if allow_decon_main_surface then
default_group.set_allows_action(defines.input_action.deconstruct, true)
else
default_group.set_allows_action(defines.input_action.deconstruct, false)
end
if not game.permissions.get_group('limited') then
local limited_group = game.permissions.create_group('limited')
@ -35,13 +40,21 @@ function Public.add_player_to_permission_group(player, group, forced)
local near_locomotive_group = game.permissions.create_group('near_locomotive')
near_locomotive_group.set_allows_action(defines.input_action.cancel_craft, false)
near_locomotive_group.set_allows_action(defines.input_action.drop_item, false)
near_locomotive_group.set_allows_action(defines.input_action.deconstruct, false)
if allow_decon_main_surface then
near_locomotive_group.set_allows_action(defines.input_action.deconstruct, true)
else
near_locomotive_group.set_allows_action(defines.input_action.deconstruct, false)
end
near_locomotive_group.set_allows_action(defines.input_action.activate_cut, false)
end
if not game.permissions.get_group('main_surface') then
local main_surface_group = game.permissions.create_group('main_surface')
main_surface_group.set_allows_action(defines.input_action.deconstruct, false)
if allow_decon_main_surface then
main_surface_group.set_allows_action(defines.input_action.deconstruct, true)
else
main_surface_group.set_allows_action(defines.input_action.deconstruct, false)
end
main_surface_group.set_allows_action(defines.input_action.activate_cut, false)
end
@ -54,6 +67,7 @@ function Public.add_player_to_permission_group(player, group, forced)
not_trusted.set_allows_action(defines.input_action.add_permission_group, false)
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.cancel_research, 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)
not_trusted.set_allows_action(defines.input_action.open_train_gui, false)

View File

@ -41,9 +41,9 @@ local AntiGrief = require 'utils.antigrief'
local Misc = require 'utils.commands.misc'
local Modifiers = require 'utils.player_modifiers'
local BiterHealthBooster = require 'modules.biter_health_booster_v2'
local Reset = require 'functions.soft_reset'
local JailData = require 'utils.datastore.jail_data'
local RPG_Progression = require 'utils.datastore.rpg_data'
local OfflinePlayers = require 'modules.clear_vacant_players'
require 'maps.mountain_fortress_v3.locomotive.market'
require 'maps.mountain_fortress_v3.locomotive.linked_chests'
@ -142,14 +142,11 @@ local announce_new_map =
)
function Public.reset_map()
local Diff = Difficulty.get()
local this = WPT.get()
local wave_defense_table = WD.get_table()
Misc.set('creative_are_you_sure', false)
Misc.set('creative_enabled', false)
Reset.enable_mapkeeper(true)
this.active_surface_index = CS.create_surface()
-- this.soft_reset_counter = CS.get_reset_counter()
@ -167,6 +164,10 @@ function Public.reset_map()
game.reset_time_played()
WPT.reset_table()
OfflinePlayers.set_active_surface_index(this.active_surface_index)
OfflinePlayers.set_offline_players_enabled(true)
-- OfflinePlayers.set_offline_players_surface_removal(true)
RPG.rpg_reset_all_players()
RPG.set_surface_name(game.surfaces[this.active_surface_index].name)
RPG.enable_health_and_mana_bars(true)
@ -225,6 +226,8 @@ function Public.reset_map()
AntiGrief.enable_jail(true)
AntiGrief.damage_entity_threshold(20)
AntiGrief.explosive_threshold(32)
AntiGrief.decon_surface_blacklist(surface.name)
AntiGrief.filtered_types_on_decon({'tree', 'simple-entity', 'fish'})
PL.show_roles_in_list(true)
PL.rpg_enabled(true)
@ -244,8 +247,8 @@ function Public.reset_map()
raise_event(Gui_mf.events.reset_map, {player_index = player.index})
end
Difficulty.reset_difficulty_poll({difficulty_poll_closing_timeout = game.tick + 36000})
Diff.gui_width = 20
Difficulty.reset_difficulty_poll({closing_timeout = game.tick + 36000})
Difficulty.set_gui_width(20)
Collapse.set_kill_entities(false)
Collapse.set_kill_specific_entities(collapse_kill)
@ -489,7 +492,6 @@ local on_tick = function()
if tick % 1000 == 0 then
collapse_after_wave_200()
Functions.remove_offline_players()
Functions.set_difficulty()
Functions.is_creativity_mode_on()
end

View File

@ -1,8 +1,11 @@
local WPT = require 'maps.mountain_fortress_v3.table'
local RPG = require 'modules.rpg.main'
local Event = require 'utils.event'
local Ai = require 'modules.ai'
require 'modules.check_fullness'
local Public = {}
local Public = {events = {on_entity_mined = Event.generate_event_name('on_entity_mined')}}
local random = math.random
local floor = math.floor
local sqrt = math.sqrt
@ -337,7 +340,12 @@ local function randomness(data)
end
end
local particle = particles[harvest]
create_particles(player.surface, particle, position, 64, {x = player.position.x, y = player.position.y})
if data.script_character then
create_particles(player.surface, particle, position, 64, {x = data.script_character.position.x, y = data.script_character.position.y})
else
create_particles(player.surface, particle, position, 64, {x = player.position.x, y = player.position.y})
end
end
local function randomness_scrap(data)
@ -390,7 +398,11 @@ local function randomness_scrap(data)
end
end
local particle = particles[harvest]
create_particles(player.surface, particle, position, 64, {x = player.position.x, y = player.position.y})
if data.script_character then
create_particles(player.surface, particle, position, 64, {x = data.script_character.position.x, y = data.script_character.position.y})
else
create_particles(player.surface, particle, position, 64, {x = player.position.x, y = player.position.y})
end
end
function Public.on_player_mined_entity(event)
@ -413,13 +425,19 @@ function Public.on_player_mined_entity(event)
local buffer = event.buffer
if valid_rocks[entity.name] or valid_trees[entity.name] or is_scrap then
buffer.clear()
if buffer then
buffer.clear()
end
local data = {
entity = entity,
player = player
}
if event.script_character then
data.script_character = event.script_character
end
local index = player.index
local scrap_zone = RPG.get_value_from_player(index, 'scrap_zone')
@ -433,4 +451,26 @@ function Public.on_player_mined_entity(event)
end
end
Event.add(
Public.events.on_entity_mined,
function(event)
if not event then
return
end
Public.on_player_mined_entity(event)
end
)
Event.add(
Ai.events.on_entity_mined,
function(event)
if not event then
return
end
Public.on_player_mined_entity(event)
end
)
return Public

View File

@ -99,9 +99,7 @@ function Public.soft_reset_map(old_surface, map_gen_settings, player_starting_it
table.concat(
{
mapkeeper,
' The world has been reshaped, welcome to ',
this.original_surface_name,
' number ',
' The world has been reshaped, welcome to attempt number ',
tostring(this.soft_reset_counter),
'!'
}

View File

@ -1,5 +1,5 @@
local Global = require 'utils.global'
local surface_name = 'mountain_fortress_v3'
local surface_name = 'mtn_v3'
local WPT = require 'maps.mountain_fortress_v3.table'
local Reset = require 'maps.mountain_fortress_v3.soft_reset'
local zone_settings = WPT.zone_settings
@ -99,4 +99,4 @@ function Public.get(key)
end
end
return Public
return Public

View File

@ -95,6 +95,7 @@ function Public.reset_table()
-- @end
this.icw_locomotive = nil
this.game_lost = false
this.death_mode = false
this.fullness_enabled = true
this.locomotive_health = 10000
this.locomotive_max_health = 10000
@ -112,16 +113,14 @@ function Public.reset_table()
}
this.force_chunk = false
this.allow_decon = true
this.train_upgrades = 0
this.allow_decon_main_surface = true
this.flamethrower_damage = {}
this.mined_scrap = 0
this.print_tech_to_discord = true
this.biters_killed = 0
this.cleared_nauvis = false
this.locomotive_xp_aura = 40
this.locomotive_pos = {tbl = {}}
this.trusted_only_car_tanks = true
this.xp_points = 0
this.xp_points_upgrade = 0
--!grief prevention
this.enable_arties = 6 -- default to callback 6
--!snip
@ -142,13 +141,22 @@ function Public.reset_table()
unit_number = {
landmine = {},
flame_turret = {}
}
},
has_upgraded_health_pool = false,
explosive_bullets_purchased = false,
xp_points_upgrade = 0,
aura_upgrades = 0,
locomotive_aura_radius = 40,
train_upgrades = 0,
xp_points = 0,
health_upgrades = 0,
pickaxe_tier = 1,
chests_outside_upgrades = 1
}
this.orbital_strikes = {
enabled = true
}
this.aura_upgrades = 0
this.pickaxe_tier = 1
this.pickaxe_speed_per_purchase = 0.07
this.health_upgrades = 1
this.health_upgrades_limit = 100
this.breached_wall = 1
this.left_top = {
x = 0,
@ -167,15 +175,20 @@ function Public.reset_table()
this.spill_items_to_surface = false
this.outside_chests = {}
this.chests_linked_to = {}
this.chest_limit_outside_upgrades = 1
this.placed_trains_in_zone = {
limit = 2,
randomized = false,
zones = {}
}
this.market_limits = {
chests_outside_limit = 8,
aura_limit = 100, -- limited to save UPS
pickaxe_tier_limit = 59,
health_upgrades_limit = 100
}
this.marked_fixed_prices = {
chest_limit_cost = 3000,
health_cost = 7000,
chests_outside_cost = 3000,
health_cost = 14000,
pickaxe_cost = 3000,
aura_cost = 4000,
xp_point_boost_cost = 5000,
@ -186,12 +199,8 @@ function Public.reset_table()
redraw_mystical_chest_cost = 3000
}
this.collapse_grace = true
this.explosive_bullets = false
this.locomotive_biter = nil
this.disconnect_wagon = false
this.offline_players_enabled = true
this.offline_players = {}
this.offline_players_surface_removal = false
this.collapse_amount = false
this.collapse_speed = false
this.y_value_position = 20
@ -220,7 +229,6 @@ function Public.reset_table()
this.market_announce = game.tick + 1200
this.check_heavy_damage = true
this.prestige_system_enabled = false
this.has_upgraded_health_pool = false
this.mystical_chest_enabled = true
this.check_if_threat_below_zero = true
this.mc_rewards = {
@ -230,6 +238,7 @@ function Public.reset_table()
this.adjusted_zones = {
scrap = {},
forest = {},
slow_movement = {},
size = nil,
shuffled_zones = nil
}

View File

@ -347,7 +347,7 @@ local function wall(p, data)
entities[#entities + 1] = {
name = 'stone-wall',
position = p,
force = 'player',
force = 'neutral',
callback = stone_wall
}
if not alert_zone_1 and data.y >= -zone_settings.zone_depth then
@ -402,7 +402,7 @@ local function wall(p, data)
entities[#entities + 1] = {
name = 'stone-wall',
position = p,
force = 'player',
force = 'neutral',
callback = stone_wall
}
end
@ -817,6 +817,7 @@ local function zone_10(x, y, data, _, adjusted_zones)
local entities = data.entities
local buildings = data.buildings
local treasure = data.treasure
data.forest_zone = true
local scrapyard = get_perlin('scrapyard', p, seed)
local smol_areas = get_perlin('smol_areas', p, seed + 45000)
@ -2589,6 +2590,7 @@ local function init_terrain(adjusted_zones)
shuffle_again[inc] = map
end
end
shuffle_again = shuffle(shuffle_again)
adjusted_zones.size = size
adjusted_zones.shuffled_zones = shuffle_again
@ -2722,7 +2724,7 @@ function Public.heavy_functions(data)
local adjusted_zones = WPT.get('adjusted_zones')
init_terrain(adjusted_zones)
local map_name = 'mountain_fortress_v3'
local map_name = 'mtn_v3'
if string.sub(surface.name, 0, #map_name) ~= map_name then
return
@ -2762,7 +2764,7 @@ Event.add(
defines.events.on_chunk_generated,
function(e)
local surface = e.surface
local map_name = 'mountain_fortress_v3'
local map_name = 'mtn_v3'
if string.sub(surface.name, 0, #map_name) ~= map_name then
return

View File

@ -9,7 +9,7 @@ local Server = require 'utils.server'
local MapFuntions = require 'tools.map_functions'
local CommonFunctions = require 'utils.common'
local LayersFunctions = require 'maps.planet_prison.mod.layers'
local AIFunctions = require 'utils.ai'
local AIFunctions = require 'maps.planet_prison.ai'
local Blueprints = require 'maps.planet_prison.mod.bp'
local AfkFunctions = require 'maps.planet_prison.mod.afk'
local Timers = require 'utils.timers'

531
modules/ai.lua Normal file
View File

@ -0,0 +1,531 @@
--- created by Gerkiz
local Event = require 'utils.event'
local Color = require 'utils.color_presets'
local Utils = require 'utils.common'
local Global = require 'utils.global'
local Token = require 'utils.token'
local Task = require 'utils.task'
local this = {
timers = {},
characters = {},
characters_unit_numbers = {}
}
Global.register(
this,
function(tbl)
this = tbl
end
)
local Public = {events = {on_entity_mined = Event.generate_event_name('on_entity_mined')}}
local max_keepalive = 54000 -- 15 minutes
local remove = table.remove
local round = math.round
local default_radius = 5
Public.command = {
noop = 0,
seek_and_destroy_cmd = 1,
seek_and_mine_cmd = 2
}
local clear_corpse_token =
Token.register(
function(event)
local position = event.position
local surface = game.get_surface(event.surface_index)
local search_info = {
type = 'character-corpse',
position = position,
radius = 1
}
local corpses = surface.find_entities_filtered(search_info)
if corpses and #corpses > 0 then
for _, corpse in pairs(corpses) do
if corpse and corpse.valid then
if corpse.character_corpse_player_index == 65536 then
corpse.destroy()
end
end
end
end
end
)
local function char_callback(callback)
local entities = this.characters
for i = 1, #entities do
local data = entities[i]
if data and data.entity and data.entity.valid then
callback(data)
end
end
end
local function get_near_position(entity)
return {x = round(entity.position.x, 0), y = round(entity.position.y, 0)}
end
local function is_mining_target_taken(selected)
if not selected then
return false
end
char_callback(
function(data)
local entity = data.entity
if entity.selected == selected then
return true
end
end
)
return false
end
local function add_character(player_index, entity, render_id, data)
local index = #this.characters + 1
if not this.characters[index] then
this.characters[index] = {
player_index = player_index,
index = index,
unit_number = entity.unit_number,
entity = entity,
ttl = game.tick + (data.ttl or max_keepalive),
command = data.command,
radius = default_radius,
max_radius_mine = 20,
max_radius_destroy = 150,
render_id = render_id,
search_local = data.search_local or false,
walking_position = {count = 1, position = get_near_position(entity)}
}
end
if not this.characters_unit_numbers[entity.unit_number] then
this.characters_unit_numbers[entity.unit_number] = true
end
end
local function exists_character(unit_number)
if not next(this.characters_unit_numbers) then
return
end
if this.characters_unit_numbers[unit_number] then
return true
end
return false
end
local function remove_character(unit_number)
if not next(this.characters) then
return
end
for index, data in pairs(this.characters) do
if data and data.unit_number == unit_number then
if data.entity and data.entity.valid then
data.entity.destroy()
end
if rendering.is_valid(data.render_id) then
rendering.destroy(data.render_id)
end
remove(this.characters, index)
end
end
if this.characters_unit_numbers[unit_number] then
this.characters_unit_numbers[unit_number] = nil
end
end
local function get_dir(src, dest)
local src_x = Utils.get_axis(src, 'x')
local src_y = Utils.get_axis(src, 'y')
local dest_x = Utils.get_axis(dest, 'x')
local dest_y = Utils.get_axis(dest, 'y')
local step = {
x = nil,
y = nil
}
local precision = Utils.rand_range(1, 10)
if dest_x - precision > src_x then
step.x = 1
elseif dest_x < src_x - precision then
step.x = -1
else
step.x = 0
end
if dest_y - precision > src_y then
step.y = 1
elseif dest_y < src_y - precision then
step.y = -1
else
step.y = 0
end
return Utils.direction_lookup[step.x][step.y]
end
local function move_to(entity, target, min_distance)
local state = {
walking = false
}
local distance = Utils.get_distance(target.position, entity.position)
if min_distance < distance then
local dir = get_dir(entity.position, target.position)
if dir then
state = {
walking = true,
direction = dir
}
end
end
entity.walking_state = state
return state.walking
end
local function refill_ammo(entity)
if not entity or not entity.valid then
return
end
local weapon = entity.get_inventory(defines.inventory.character_guns)[entity.selected_gun_index]
if weapon and weapon.valid_for_read then
local selected_ammo = entity.get_inventory(defines.inventory.character_ammo)[entity.selected_gun_index]
if selected_ammo then
if not selected_ammo.valid_for_read then
if weapon.name == 'shotgun' then
entity.insert({name = 'shotgun-shell', count = 5})
end
if weapon.name == 'pistol' then
entity.insert({name = 'firearm-magazine', count = 5})
end
end
end
end
end
local function shoot_at(entity, target)
entity.selected = target
entity.shooting_state = {
state = defines.shooting.shooting_enemies,
position = target.position
}
end
local function check_progress_and_raise_event(data)
if data.entity.selected and data.entity.character_mining_progress >= 0.95 then
if not data.raised_event then
data.raised_event = true
Event.raise(
Public.events.on_entity_mined,
{
player_index = data.player_index,
entity = data.entity.selected,
surface = data.entity.surface,
script_character = data.entity
}
)
end
end
end
local function mine_entity(data, target)
data.entity.selected = target
data.entity.mining_state = {mining = true, position = target.position}
end
local function shoot_stop(entity)
entity.shooting_state = {
state = defines.shooting.not_shooting,
position = {0, 0}
}
end
local function insert_weapons(entity)
if not entity or not entity.valid then
return
end
local weapon = entity.get_inventory(defines.inventory.character_guns)[entity.selected_gun_index]
if weapon and weapon.valid_for_read then
return
end
if Utils.rand_range(1, 15) == 1 then
entity.insert({name = 'shotgun', count = 1})
entity.insert({name = 'shotgun-shell', count = 5})
elseif Utils.rand_range(1, 10) == 1 then
entity.insert({name = 'submachine-gun', count = 1})
entity.insert({name = 'firearm-magazine', count = 5})
else
entity.insert({name = 'pistol', count = 1})
entity.insert({name = 'firearm-magazine', count = 5})
end
end
local function seek_and_mine(data)
if data.radius >= data.max_radius_mine then
if data.overriden_command then
data.command = data.overriden_command
data.overriden_command = nil
return
else
data.radius = 1
end
end
local entity = data.entity
if not entity or not entity.valid then
remove_character(data.unit_number)
return
end
local surface = entity.surface
local player_index = data.player_index
local player = game.get_player(player_index)
if not player or not player.valid or not player.connected then
remove_character(data.unit_number)
return
end
local position
if data.search_local then
position = entity.position
else
position = player.position
end
local search_info = {
position = position,
radius = data.radius,
type = {
'simple-entity-with-owner',
'simple-entity',
'tree'
},
force = {
'neutral'
}
}
local closest = surface.find_entities_filtered(search_info)
if #closest ~= 0 then
local target = Utils.get_closest_neighbour_non_player(entity.position, closest)
if not target then
data.radius = data.radius + 1
return
end
data.radius = 1
if not move_to(entity, target, 1) then
if not is_mining_target_taken(target) then
if data.raised_event then
data.raised_event = nil
end
if entity.can_reach_entity(target) then
mine_entity(data, target)
else
move_to(entity, target, 1)
end
end
if data.overriden_command then
data.command = data.overriden_command
data.overriden_command = nil
end
end
else
data.radius = data.radius + 1
end
end
local function seek_enemy_and_destroy(data)
if data.radius >= data.max_radius_destroy then
remove_character(data.unit_number)
return
end
local entity = data.entity
if not entity or not entity.valid then
remove_character(data.unit_number)
return
end
local surface = entity.surface
local player_index = data.player_index
local player = game.get_player(player_index)
if not player or not player.valid or not player.connected then
remove_character(data.unit_number)
return
end
local search_info = {
type = {'unit', 'unit-spawner', 'turret'},
position = entity.position,
radius = data.radius,
force = 'enemy'
}
local closest = surface.find_entities_filtered(search_info)
if #closest ~= 0 then
local target = Utils.get_closest_neighbour_non_player(entity.position, closest)
if not target then
data.radius = data.radius + 5
return
end
data.radius = default_radius
insert_weapons(entity)
refill_ammo(entity)
local inside = ((entity.position.x - data.walking_position.position.x) ^ 2 + (entity.position.y - data.walking_position.position.y) ^ 2) < 1 ^ 2
data.walking_position.position = get_near_position(entity)
if inside then
data.walking_position.count = data.walking_position.count + 1
end
if data.walking_position.count == 3 then
data.radius = 1
data.walking_position.count = 1
data.overriden_command = data.command
data.command = Public.command.seek_and_mine_cmd
seek_and_mine(data)
else
if not move_to(entity, target, Utils.rand_range(5, 10)) then
shoot_at(entity, target)
else
shoot_stop(entity)
end
end
else
data.radius = data.radius + 5
end
end
--- Creates a new character that seeks and does stuff.
---@param data table
----- @usage local Ai = require 'modules.ai' Ai.create_char({player_index = game.player.index, command = 1})
function Public.create_char(data)
if not data or not type(data) == 'table' then
return error('No data was provided or the provided data was not a table.', 2)
end
if not data.player_index or not data.command then
return error('No correct data was not provided.', 2)
end
if data.command ~= Public.command.seek_and_destroy_cmd and data.command ~= Public.command.attack_objects_cmd and data.command ~= Public.command.seek_and_mine_cmd then
return error('No correct command was not provided.', 2)
end
local player = game.get_player(data.player_index)
if not player or not player.valid or not player.connected then
return error('Provided player was not valid or not connected.', 2)
end
local surface = player.surface
local valid_position = surface.find_non_colliding_position('character', {x = player.position.x, y = player.position.y + 2}, 3, 0.5)
if not valid_position then
return
end
local entity = surface.create_entity {name = 'character', position = valid_position, force = player.force}
if not entity or not entity.valid then
return
end
entity.associated_player = player
if player.character_health_bonus >= 200 then
entity.character_health_bonus = player.character_health_bonus / 2
end
entity.color = player.color
local index = #this.characters + 1
local render_id =
rendering.draw_text {
text = player.name .. "'s drone #" .. index,
surface = player.surface,
target = entity,
target_offset = {0, -2.25},
color = Color.orange,
scale = 1.00,
font = 'default-large-semibold',
alignment = 'center',
scale_with_zoom = false
}
add_character(player.index, entity, render_id, data)
end
Event.on_nth_tick(
2,
function()
char_callback(
function(data)
check_progress_and_raise_event(data)
end
)
end
)
Event.on_nth_tick(
10,
function()
local tick = game.tick
char_callback(
function(data)
if data.ttl <= tick then
remove_character(data.unit_number)
return
end
local command = data.command
if command == Public.command.seek_and_destroy_cmd then
seek_enemy_and_destroy(data)
elseif command == Public.command.seek_and_mine_cmd then
seek_and_mine(data)
end
end
)
end
)
Event.add(
defines.events.on_entity_died,
function(event)
local entity = event.entity
if not entity or not entity.valid then
return
end
if entity.type ~= 'character' then
return
end
local unit_number = entity.unit_number
if not exists_character(unit_number) then
return
end
Task.set_timeout_in_ticks(1, clear_corpse_token, {position = entity.position, surface_index = entity.surface.index})
remove_character(unit_number)
end
)
return Public

View File

@ -5,10 +5,12 @@ local Global = require 'utils.global'
local SpamProtection = require 'utils.spam_protection'
local Event = require 'utils.event'
local BottomFrame = require 'utils.gui.bottom_frame'
local ComfyGui = require 'utils.gui'
local Gui = require 'utils.gui'
local floor = math.floor
local print_color = {r = 120, g = 255, b = 0}
local auto_stash_button_name = Gui.uid()
local this = {
floating_text_y_offsets = {},
whitelist = {},
@ -191,16 +193,6 @@ local function get_nearby_chests(player, a, furnace, wagon)
return {chest = chests, inventory = inventories}
end
local function does_inventory_contain_item_type(inventory, item_subgroup)
for name, _ in pairs(inventory.get_contents()) do
local t = game.item_prototypes[name]
if t and t.subgroup.name == item_subgroup then
return true
end
end
return false
end
local function insert_to_furnace(player_inventory, chests, name, count, floaty_text_list)
local try = 0
@ -369,8 +361,8 @@ local function insert_item_into_chest(stack, chests, filtered_chests, name, floa
for chestnr, chest in pairs(chests.chest) do
if container[chest.type] then
local chest_inventory = chests.inventory[chestnr]
if chest_inventory and chest_inventory.can_insert(stack) then
if chest_inventory.find_item_stack(stack.name) then
if chest_inventory and chest_inventory.find_item_stack(stack.name) then
if chest_inventory.can_insert(stack) then
local inserted_count = chest_inventory.insert(stack)
stack.count = stack.count - inserted_count
prepare_floaty_text(floaty_text_list, chest.surface, chest.position, name, inserted_count)
@ -386,32 +378,43 @@ local function insert_item_into_chest(stack, chests, filtered_chests, name, floa
for chestnr, chest in pairs(filtered_chests.chest) do
if container[chest.type] then
local chest_inventory = filtered_chests.inventory[chestnr]
if chest_inventory and chest_inventory.can_insert(stack) then
if chest_inventory.is_empty() then
local inserted_count = chest_inventory.insert(stack)
stack.count = stack.count - inserted_count
prepare_floaty_text(floaty_text_list, chest.surface, chest.position, name, inserted_count)
if stack.count <= 0 then
return chestnr
end
if not chest_inventory then
break
end
local count = chest_inventory.get_item_count() == 0
if count then
local inserted_count = chest_inventory.insert(stack)
stack.count = stack.count - inserted_count
prepare_floaty_text(floaty_text_list, chest.surface, chest.position, name, inserted_count)
if stack.count <= 0 then
return chestnr
end
end
end
end
local item_prototypes = game.item_prototypes
--Attempt to store in chests with same item subgroup.
local item_subgroup = game.item_prototypes[name].subgroup.name
if item_subgroup then
for chestnr, chest in pairs(filtered_chests.chest) do
if container[chest.type] then
local chest_inventory = filtered_chests.inventory[chestnr]
if chest_inventory and chest_inventory.can_insert(stack) then
if does_inventory_contain_item_type(chest_inventory, item_subgroup) then
local inserted_count = chest_inventory.insert(stack)
stack.count = stack.count - inserted_count
prepare_floaty_text(floaty_text_list, chest.surface, chest.position, name, inserted_count)
if stack.count <= 0 then
return chestnr
if not chest_inventory then
break
end
local content = chest_inventory.get_contents()
if chest_inventory.can_insert(stack) then
for equal_name, _ in pairs(content) do
local t = item_prototypes[equal_name]
if t and t.subgroup.name == item_subgroup then
local inserted_count = chest_inventory.insert(stack)
stack.count = stack.count - inserted_count
prepare_floaty_text(floaty_text_list, chest.surface, chest.position, name, inserted_count)
if stack.count <= 0 then
return chestnr
end
end
end
end
@ -423,6 +426,9 @@ local function insert_item_into_chest(stack, chests, filtered_chests, name, floa
for chestnr, chest in pairs(filtered_chests.chest) do
if container[chest.type] then
local chest_inventory = filtered_chests.inventory[chestnr]
if not chest_inventory then
break
end
if chest_inventory.can_insert(stack) then
local inserted_count = chest_inventory.insert(stack)
stack.count = stack.count - inserted_count
@ -581,12 +587,12 @@ local function create_gui_button(player)
end
end
else
if ComfyGui.get_mod_gui_top_frame() then
ComfyGui.add_mod_button(
if Gui.get_mod_gui_top_frame() then
Gui.add_mod_button(
player,
{
type = 'sprite-button',
name = 'auto_stash',
name = auto_stash_button_name,
sprite = 'item/wooden-chest',
tooltip = tooltip
}
@ -597,7 +603,7 @@ local function create_gui_button(player)
{
type = 'sprite-button',
sprite = 'item/wooden-chest',
name = 'auto_stash',
name = auto_stash_button_name,
tooltip = tooltip
}
)
@ -641,31 +647,21 @@ local function on_player_joined_game(event)
create_gui_button(game.players[event.player_index])
end
local function on_gui_click(event)
if not event.element then
return
end
if not event.element.valid then
return
end
local player = game.players[event.player_index]
local name = 'auto_stash'
if this.bottom_button then
local data = BottomFrame.get('bottom_quickbar_button')
if data and data[player.index] then
data = data[player.index]
name = data.name
end
end
if event.element.name == name then
local is_spamming = SpamProtection.is_spamming(player, nil, 'Autostash Click')
Gui.on_click(
auto_stash_button_name,
function(event)
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Autostash click')
if is_spamming then
return
end
auto_stash(player, event)
local player = event.player
if not player or not player.valid or not player.character then
return
end
auto_stash(event.player, event)
end
end
)
function Public.insert_into_furnace(value)
if value then
@ -698,6 +694,14 @@ Event.on_configuration_changed(do_whitelist)
Event.on_init(do_whitelist)
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_gui_click, on_gui_click)
Event.add(
BottomFrame.events.bottom_quickbar_button_name,
function(data)
local event = data.event
local player = event.player
auto_stash(player, event)
end
)
return Public

View File

@ -0,0 +1,161 @@
local Global = require 'utils.global'
local Alert = require 'utils.alert'
local Event = require 'utils.event'
local this = {
settings = {
offline_players_enabled = false,
offline_players_surface_removal = false,
active_surface_index = nil, -- needs to be set else this will fail
required_online_time = 18000, -- nearest prime to 5 minutes in ticks
clear_player_after_tick = 108000 -- nearest prime to 30 minutes in ticks
},
offline_players = {}
}
Global.register(
this,
function(tbl)
this = tbl
end
)
local Public = {events = {remove_surface = Event.generate_event_name('remove_surface')}}
function Public.remove_offline_players()
if not this.settings.offline_players_enabled then
return
end
local tick = game.tick
if tick < 50 then
return
end
if not this.settings.active_surface_index then
return error('An active surface index must be set', 2)
end
local surface = game.get_surface(this.settings.active_surface_index)
local player_inv = {}
local items = {}
if #this.offline_players > 0 then
for i = 1, #this.offline_players, 1 do
if this.offline_players[i] and this.offline_players[i].index then
local target = game.get_player(this.offline_players[i].index)
if target and target.valid then
if target.connected then
this.offline_players[i] = nil
else
if this.offline_players[i].tick < tick then
local name = this.offline_players[i].name
player_inv[1] = target.get_inventory(defines.inventory.character_main)
player_inv[2] = target.get_inventory(defines.inventory.character_armor)
player_inv[3] = target.get_inventory(defines.inventory.character_guns)
player_inv[4] = target.get_inventory(defines.inventory.character_ammo)
player_inv[5] = target.get_inventory(defines.inventory.character_trash)
if this.offline_players_surface_removal then
Event.raise(this.events.remove_surface, {target = target})
end
if target.get_item_count() == 0 then -- if the player has zero items, don't do anything
this.offline_players[i] = nil
goto final
end
local pos = game.forces.player.get_spawn_position(surface)
local e =
surface.create_entity(
{
name = 'character',
position = pos,
force = 'neutral'
}
)
local inv = e.get_inventory(defines.inventory.character_main)
e.character_inventory_slots_bonus = #player_inv[1]
for ii = 1, 5, 1 do
if player_inv[ii].valid then
for iii = 1, #player_inv[ii], 1 do
if player_inv[ii][iii].valid then
items[#items + 1] = player_inv[ii][iii]
end
end
end
end
if #items > 0 then
for item = 1, #items, 1 do
if items[item].valid then
inv.insert(items[item])
end
end
local message = ({'main.cleaner', name})
local data = {
position = pos
}
Alert.alert_all_players_location(data, message)
e.die('neutral')
else
e.destroy()
end
for ii = 1, 5, 1 do
if player_inv[ii].valid then
player_inv[ii].clear()
end
end
this.offline_players[i] = nil
break
end
::final::
end
end
end
end
end
end
--- Activates the offline player module
---@param value boolean
function Public.set_offline_players_enabled(value)
this.settings.offline_players_enabled = value or false
end
--- Activates the surface removal for the module IC
---@param value boolean
function Public.set_offline_players_surface_removal(value)
this.settings.offline_players_surface_removal = value or false
end
--- Sets the active surface for this module, needs to be set else it will fail
---@param value string
function Public.set_active_surface_index(value)
this.settings.active_surface_index = value or nil
end
local remove_offline_players = Public.remove_offline_players
Event.on_nth_tick(200, remove_offline_players)
Event.add(
defines.events.on_pre_player_left_game,
function(event)
if not this.settings.offline_players_enabled then
return
end
local player = game.get_player(event.player_index)
local ticker = game.tick
if player.online_time >= this.settings.required_online_time then
if player.character then
this.offline_players[#this.offline_players + 1] = {
index = event.player_index,
name = player.name,
tick = ticker + this.settings.clear_player_after_tick
}
end
end
end
)
return Public

View File

@ -50,11 +50,11 @@ local this = {
[2] = '',
[3] = ''
},
difficulty_vote_value = 0.75,
difficulty_vote_index = 1,
value = 0.75,
index = 1,
fair_vote = false,
difficulty_poll_closing_timeout = 54000,
difficulty_player_votes = {},
closing_timeout = 54000,
all_votes = {},
gui_width = 108,
name = "I'm too young to die",
strength_modifier = 1.00,
@ -78,24 +78,24 @@ local function clear_main_frame(player)
end
function Public.difficulty_gui()
local tooltip = 'Current difficulty of the map is ' .. this.difficulties[this.difficulty_vote_index].name .. '.'
local tooltip = 'Current difficulty of the map is ' .. this.difficulties[this.index].name .. '.'
for _, player in pairs(game.connected_players) do
local top = player.gui.top
if top[top_button_name] then
top[top_button_name].caption = this.difficulties[this.difficulty_vote_index].name
top[top_button_name].caption = this.difficulties[this.index].name
top[top_button_name].tooltip = this.button_tooltip or tooltip
top[top_button_name].style.font_color = this.difficulties[this.difficulty_vote_index].print_color
top[top_button_name].style.font_color = this.difficulties[this.index].print_color
else
local b =
top.add {
type = 'button',
caption = this.difficulties[this.difficulty_vote_index].name,
caption = this.difficulties[this.index].name,
tooltip = tooltip,
name = top_button_name
}
b.style.font = 'heading-2'
b.style.font_color = this.difficulties[this.difficulty_vote_index].print_color
b.style.font_color = this.difficulties[this.index].print_color
b.style.minimal_height = 37
b.style.maximal_height = 37
b.style.minimal_width = this.gui_width
@ -148,9 +148,9 @@ local function poll_difficulty(player)
clear_main_frame(player)
end
if game.tick > this.difficulty_poll_closing_timeout then
if game.tick > this.closing_timeout then
if player.online_time ~= 0 then
local t = math.abs(math.floor((this.difficulty_poll_closing_timeout - game.tick) / 3600))
local t = math.abs(math.floor((this.closing_timeout - game.tick) / 3600))
local str = 'Votes have closed ' .. t
str = str .. ' minute'
if t > 1 then
@ -163,6 +163,9 @@ local function poll_difficulty(player)
end
local _, inside_frame = Gui.add_main_frame_with_toolbar(player, 'center', main_frame_name, nil, close_main_frame, 'Difficulty')
if not inside_frame then
return
end
for i = 1, #this.difficulties, 1 do
local button_flow =
@ -198,7 +201,7 @@ local function poll_difficulty(player)
timeleft_flow.add(
{
type = 'button',
caption = math.floor((this.difficulty_poll_closing_timeout - game.tick) / 3600) .. ' minutes left.'
caption = math.floor((this.closing_timeout - game.tick) / 3600) .. ' minutes left.'
}
)
b.style.font_color = {r = 0.66, g = 0.0, b = 0.66}
@ -215,23 +218,25 @@ local function set_difficulty()
return
end
if this.difficulty_vote_index ~= index then
if this.index ~= index then
local message = table.concat({'*** Map difficulty has changed to ', this.difficulties[index].name, ' difficulty! ***'})
game.print(message, this.difficulties[index].print_color)
Server.to_discord_embed(message)
end
this.difficulty_vote_index = index
this.difficulty_vote_value = this.difficulties[index].value
this.index = index
this.name = this.difficulties[index].name
this.value = this.difficulties[index].value
this.boss_modifier = this.difficulties[index].boss_modifier
this.strength_modifier = this.difficulties[index].strength_modifier
this.button_tooltip = this.tooltip[index]
end
function Public.reset_difficulty_poll(tbl)
if tbl then
this.difficulty_vote_value = tbl.difficulty_vote_value or 0.75
this.difficulty_vote_index = tbl.difficulty_vote_index or 1
this.difficulty_player_votes = {}
this.difficulty_poll_closing_timeout = tbl.difficulty_poll_closing_timeout or game.tick + 54000
this.value = tbl.value or 0.75
this.index = tbl.index or 1
this.all_votes = {}
this.closing_timeout = tbl.closing_timeout or game.tick + 54000
for _, p in pairs(game.connected_players) do
if p.gui.center[main_frame_name] then
clear_main_frame(p)
@ -243,10 +248,10 @@ function Public.reset_difficulty_poll(tbl)
end
Public.difficulty_gui()
else
this.difficulty_vote_value = 0.75
this.difficulty_vote_index = 1
this.difficulty_player_votes = {}
this.difficulty_poll_closing_timeout = game.tick + 54000
this.value = 0.75
this.index = 1
this.all_votes = {}
this.closing_timeout = game.tick + 54000
for _, p in pairs(game.connected_players) do
if p.gui.center[main_frame_name] then
clear_main_frame(p)
@ -262,8 +267,8 @@ end
local function on_player_joined_game(event)
local player = game.get_player(event.player_index)
if game.tick < this.difficulty_poll_closing_timeout then
if not this.difficulty_player_votes[player.name] then
if game.tick < this.closing_timeout then
if not this.all_votes[player.name] then
poll_difficulty(player)
end
else
@ -273,19 +278,19 @@ local function on_player_joined_game(event)
end
local function on_player_left_game(event)
if game.tick > this.difficulty_poll_closing_timeout then
if game.tick > this.closing_timeout then
return
end
local player = game.get_player(event.player_index)
if not this.difficulty_player_votes[player.name] then
if not this.all_votes[player.name] then
return
end
local index = this.difficulty_player_votes[player.name].index
local index = this.all_votes[player.name].index
this.difficulties[index].count = this.difficulties[index].count - 1
if this.difficulties[index].count <= 0 then
this.difficulties[index].count = 0
end
this.difficulty_player_votes[player.name] = nil
this.all_votes[player.name] = nil
set_difficulty()
Public.difficulty_gui()
end
@ -303,7 +308,13 @@ function Public.set_difficulties(...)
end
function Public.set_poll_closing_timeout(...)
this.difficulty_poll_closing_timeout = ...
this.closing_timeout = ...
end
--- Sets gui width
---@param number number
function Public.set_gui_width(number)
this.gui_width = number
end
function Public.get_fair_vote()
@ -322,6 +333,17 @@ function Public.get(key)
end
end
function Public.set(key, value)
if key and (value or value == false) then
this[key] = value
return this[key]
elseif key then
return this[key]
else
return this
end
end
Gui.on_click(
selection_button_name,
function(event)
@ -341,14 +363,19 @@ Gui.on_click(
local i = tonumber(element.parent.name)
if this.difficulty_player_votes[player.name] and this.difficulty_player_votes[player.name].index == i then
if game.tick > this.closing_timeout then
clear_main_frame(player)
return
end
if this.all_votes[player.name] and this.all_votes[player.name].index == i then
player.print('You have already voted for ' .. this.difficulties[i].name .. '.', this.difficulties[i].print_color)
clear_main_frame(player)
return
end
if this.difficulty_player_votes[player.name] then
local index = this.difficulty_player_votes[player.name].index
if this.all_votes[player.name] then
local index = this.all_votes[player.name].index
this.difficulties[index].count = this.difficulties[index].count - 1
if this.difficulties[index].count <= 0 then
this.difficulties[index].count = 0
@ -356,7 +383,7 @@ Gui.on_click(
end
this.difficulties[i].count = this.difficulties[i].count + 1
this.difficulty_player_votes[player.name] = {voted = true, index = i}
this.all_votes[player.name] = {voted = true, index = i}
set_difficulty()
Public.difficulty_gui()
@ -378,7 +405,7 @@ Gui.on_click(
if not player or not player.valid then
return
end
if game.tick > this.difficulty_poll_closing_timeout then
if game.tick > this.closing_timeout then
clear_main_frame(player)
return
end

View File

@ -94,11 +94,10 @@ local function on_player_joined_game(event)
Gui.call_existing_tab(player, 'Map Info')
end
end
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Gui.add_tab_to_gui({name = module_name, caption = 'Map Info', id = create_map_intro_token, admin = false})
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Gui.on_click(
module_name,
function(event)

352
modules/render_beam.lua Normal file
View File

@ -0,0 +1,352 @@
local Event = require 'utils.event'
local Global = require 'utils.global'
local Gui = require 'utils.gui'
local this = {
renders = {}
}
local Public = {}
Public.metatable = {__index = Public}
Global.register(
this,
function(tbl)
this = tbl
for _, render in pairs(this.renders) do
setmetatable(render, Public.metatable)
end
end
)
local target_entities = {
'character',
'tank',
'car',
'radar',
'lab',
'furnace',
'locomotive',
'cargo-wagon',
'fluid-wagon',
'artillery-wagon',
'artillery-turret',
'laser-turret',
'gun-turret',
'flamethrower-turret',
'silo',
'spidertron'
}
local sqrt = math.sqrt
local random = math.random
local remove = table.remove
local speed = 0.06
--- Draws a new render.
---@return integer
function Public:new_render()
local surface = game.get_surface(self.surface_id)
self.render_id = rendering.draw_sprite {target = self.position, sprite = self.sprite, surface = surface}
end
--- Sets a new target for a given render.
---@return table
---@return table
function Public:new_target()
local surface = game.get_surface(self.surface_id)
local position
local entities = surface.find_entities_filtered {type = target_entities}
if entities and #entities > 0 then
position = entities[random(#entities)].position
end
local chunk = surface.get_random_chunk()
local random_position = {x = (chunk.x + random()) * 32, y = (chunk.y + random()) * 32}
return position, random_position
end
--- Subtracts the given positions
---@return table|integer
function Public:subtr()
if not self.position and self.target_position then
return 0
end
return {x = self.target_position.x - self.position.x, y = self.target_position.y - self.position.y}
end
--- Sets the render scale.
function Public:set_render_scalar_size()
if not self.render_id then
return self:validate()
end
rendering.set_y_scale(self.render_id, 3.5) -- 1.5
rendering.set_x_scale(self.render_id, 7) -- 2
rendering.set_color(
self.render_id,
{
r = 1,
g = 0.7,
b = 0.7
}
)
end
--- Gets a random position.
---@return table
function Public:random_position()
return {x = self.position.x + (random() - 0.5) * 64, y = self.position.y + (random() - 0.5) * 64}
end
--- Changes the position of a render.
---@param max_abs number
---@param value boolean
---@return table|nil
function Public:change_position(max_abs, value)
if not self.position or not self.target_position then
return
end
local scalar = 0.9
local subtr = self:subtr()
if value then
subtr.y = subtr.y / scalar
end
local multiply = sqrt(subtr.x * subtr.x + subtr.y * subtr.y)
if (multiply > max_abs) then
local close = max_abs / multiply
subtr = {x = subtr.x * close, y = subtr.y * close}
end
if value then
subtr.y = subtr.y * scalar
end
return {x = self.position.x + subtr.x, y = self.position.y + subtr.y}
end
--- If a render is stuck, give it a new position.
function Public:switch_position()
if random() < 0.4 then
self.target_position = self:random_position()
else
local surface = game.get_surface(self.surface_id)
local chunk = surface.get_random_chunk()
self.target_position = {x = (chunk.x + math.random()) * 32, y = (chunk.y + math.random()) * 32}
end
end
--- Notifies for a new render
function Public:notify_new_beam()
if not self.notify then
self.notify = true
local surface = game.get_surface(self.surface_id)
game.print('[Orbital] A new orbital strike has been spotted at: [gps=' .. self.position.x .. ',' .. self.position.y .. ',' .. surface.name .. ']')
end
end
--- Renders a new chart
function Public:render_chart()
if self.chart then
self.chart.destroy()
end
local surface = game.get_surface(self.surface_id)
self.chart =
game.forces[self.force].add_chart_tag(
surface,
{
icon = {type = 'virtual', name = 'signal-info'},
position = self.position,
text = 'Beam'
}
)
end
--- Sets a new position for a render.
function Public:set_new_position()
self.position = self:change_position(speed, false)
if not self.random_pos_set then
self.random_pos_set = true
self.random_pos_tick = game.tick + 300
end
if self.position.x == self.target_position.x and self.position.y == self.target_position.y then
self:switch_position()
end
if self:validate() then
rendering.set_target(self.render_id, self.position)
self:set_render_scalar_size()
end
end
--- Creates fire flame.
function Public:render_fire_damage()
if random(1, 15) == 1 then
local surface = game.get_surface(self.surface_id)
surface.create_entity({name = 'fire-flame', position = {x = self.position.x, y = self.position.y + 5}})
if random(1, 5) == 1 then
surface.create_entity({name = 'medium-scorchmark', position = {x = self.position.x, y = self.position.y + 5}, force = 'neutral'})
end
end
end
--- Damages entities nearby.
function Public:damage_entities_nearby()
if random(1, 3) == 1 then
local surface = game.get_surface(self.surface_id)
local damage = random(10, 15)
local entities = surface.find_entities_filtered({position = self.position, radius = 20, type = 'simple-entity', invert = true})
for _, entity in pairs(entities) do
if entity.valid then
if entity.health then
if entity.force.name ~= 'enemy' then
entity.damage(damage, 'enemy')
end
end
end
end
end
end
--- Validates if a render is valid.
---@return boolean|integer
function Public:validate()
if not self.render_id then
return self:new_render()
end
if rendering.is_valid(self.render_id) then
return true
end
return false
end
--- Destroys a render.
function Public:destroy_render()
if rendering.is_valid(self.render_id) then
rendering.destroy(self.render_id)
end
return self
end
--- Destroys a render.
function Public:destroy_chart()
if self.chart then
self.chart.destroy()
end
return self
end
--- Removes a render.
function Public:remove_render()
self:destroy_render()
self:destroy_chart()
remove(this.renders, self.id)
return self
end
function Public:work(tick)
if tick < self.ttl then
self:render_chart()
self:notify_new_beam()
self:set_new_position()
self:render_fire_damage()
self:damage_entities_nearby()
if self.random_pos_set and tick > self.random_pos_tick then
self:switch_position()
self.random_pos_set = nil
self.random_pos_tick = nil
end
else
self:remove_render()
end
end
--- Creates a new render.
---@param sprite string
---@param surface userdata
---@param ttl integer|nil
---@param scalar table|nil
---@param delayed number|nil
---@return table
function Public.new(sprite, surface, ttl, scalar, delayed)
local render = setmetatable({}, Public.metatable)
render.surface_id = surface.index
local position, random_position = render:new_target()
render.position = position
render.sprite = sprite
render.force = 'player'
render.target_position = random_position
render.id = #this.renders + 1
if delayed then
render.delayed = game.tick + delayed
render.ttl = ttl or (game.tick + delayed) + 7200 -- 2 minutes duration
else
render.ttl = ttl or game.tick + 7200 -- 2 minutes duration
render:validate()
if not scalar then
render:set_render_scalar_size()
end
end
render.ttl = ttl or game.tick + 7200 -- 2 minutes duration
this.renders[render.id] = render
return render
end
--- Creates a new defined beam
---@param surface userdata
function Public.new_beam(surface)
Public.new(Gui.beam, surface)
end
--- Creates a new defined beam with a delayed action
---@param surface userdata
---@param time number
function Public.new_beam_delayed(surface, time)
Public.new(Gui.beam, surface, nil, nil, time)
end
Event.add(
defines.events.on_tick,
function()
if #this.renders == 0 then
return
end
local tick = game.tick
for id = 1, #this.renders, 1 do
local render = this.renders[id]
if render then
if render.delayed then
if tick > render.delayed then
render:work(tick)
end
else
render:work(tick)
end
end
end
end
)
if _DEBUG then
commands.add_command(
'laser',
'new laser',
function()
local player = game.player
if player and player.valid then
if not player.admin then
return
end
Public.new_beam_delayed(player.surface, 222)
end
end
)
end
return Public

View File

@ -226,4 +226,42 @@ if _DEBUG then
)
end
local RPG_Interface = {
rpg_reset_player = function(player_name)
if player_name then
local player = game.get_player(player_name)
if player and player.valid then
return Public.rpg_reset_player(player)
else
error('Remote call parameter to RPG rpg_reset_player must be a valid player name and not nil.')
end
else
error('Remote call parameter to RPG rpg_reset_player must be a valid player name and not nil.')
end
end,
give_xp = function(amount)
if type(amount) == 'number' then
return Public.give_xp(amount)
else
error('Remote call parameter to RPG give_xp must be number and not nil.')
end
end,
gain_xp = function(player_name, amount)
if player_name then
local player = game.get_player(player_name)
if player and player.valid and type(amount) == 'number' then
return Public.gain_xp(player, amount)
else
error('Remote call parameter to RPG give_xp must be a valid player name and contain amount(number) and not nil.')
end
else
error('Remote call parameter to RPG give_xp must be a valid player name and contain amount(number) and not nil.')
end
end
}
if not remote.interfaces['RPG'] then
remote.add_interface('RPG', RPG_Interface)
end
return Public

View File

@ -19,6 +19,7 @@ local round = math.round
local floor = math.floor
local random = math.random
local abs = math.abs
local sub = string.sub
--RPG Frames
local main_frame_name = Public.main_frame_name
@ -444,7 +445,7 @@ function Public.remove_mana(player, mana_to_remove)
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
if data and data.mana and data.mana.valid then
data.mana.caption = rpg_t.mana
end
end
@ -483,7 +484,7 @@ function Public.update_mana(player)
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
if data and data.mana and data.mana.valid then
data.mana.caption = rpg_t.mana
end
end
@ -542,7 +543,7 @@ function Public.reward_mana(player, mana_to_add)
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
if data and data.mana and data.mana.valid then
data.mana.caption = rpg_t.mana
end
end
@ -589,7 +590,7 @@ function Public.update_health(player)
if player.gui.screen[main_frame_name] then
local f = player.gui.screen[main_frame_name]
local data = Gui.get_data(f)
if data.health and data.health.valid then
if data and data.health and data.health.valid then
data.health.caption = (round(player.character.health * 10) / 10)
end
local shield_gui = player.character.get_inventory(defines.inventory.character_armor)
@ -597,10 +598,10 @@ function Public.update_health(player)
if shield_gui[1].grid then
local shield = math.floor(shield_gui[1].grid.shield)
local shield_max = math.floor(shield_gui[1].grid.max_shield)
if data.shield and data.shield.valid then
if data and data.shield and data.shield.valid then
data.shield.caption = shield
end
if data.shield_max and data.shield_max.valid then
if data and data.shield_max and data.shield_max.valid then
data.shield_max.caption = shield_max
end
end
@ -993,6 +994,36 @@ function Public.give_xp(amount)
end
end
-- Checks if the player is on the correct surface.
function Public.check_is_surface_valid(player)
if is_game_modded() then
return true
end
local is_surface_valid = false
local surface_name = Public.get('rpg_extra').surface_name
if type(surface_name) == 'table' then
for _, tbl_surface in pairs(surface_name) do
if sub(player.surface.name, 0, #surface_name) == tbl_surface then
is_surface_valid = true
end
end
else
if sub(player.surface.name, 0, #surface_name) ~= surface_name then
return false
else
return true
end
end
if not is_surface_valid then
return false
end
return true
end
function Public.rpg_reset_player(player, one_time_reset)
if not player.character then
player.set_controller({type = defines.controllers.god})

View File

@ -30,33 +30,66 @@ local spell1_button_name = Public.spell1_button_name
local spell2_button_name = Public.spell2_button_name
local spell3_button_name = Public.spell3_button_name
local sub = string.sub
local round = math.round
local floor = math.floor
function Public.draw_gui_char_button(player)
if player.gui.top[draw_main_frame_name] then
return
if ComfyGui.get_mod_gui_top_frame() then
local b =
ComfyGui.add_mod_button(
player,
{
type = 'sprite-button',
name = draw_main_frame_name,
caption = '[RPG]',
tooltip = 'RPG'
}
)
if b then
b.style.font_color = {165, 165, 165}
b.style.font = 'heading-3'
b.style.minimal_height = 38
b.style.maximal_height = 38
b.style.minimal_width = 50
b.style.padding = 0
b.style.margin = 0
end
else
if player.gui.top[draw_main_frame_name] then
return
end
local b = player.gui.top.add({type = 'sprite-button', name = draw_main_frame_name, caption = '[RPG]', tooltip = 'RPG'})
b.style.font_color = {165, 165, 165}
b.style.font = 'heading-3'
b.style.minimal_height = 38
b.style.maximal_height = 38
b.style.minimal_width = 50
b.style.padding = 0
b.style.margin = 0
end
local b = player.gui.top.add({type = 'sprite-button', name = draw_main_frame_name, caption = '[RPG]', tooltip = 'RPG'})
b.style.font_color = {165, 165, 165}
b.style.font = 'heading-3'
b.style.minimal_height = 38
b.style.maximal_height = 38
b.style.minimal_width = 50
b.style.padding = 0
b.style.margin = 0
end
function Public.update_char_button(player)
local rpg_t = Public.get_value_from_player(player.index)
if not player.gui.top[draw_main_frame_name] then
Public.draw_gui_char_button(player)
end
if rpg_t.points_left > 0 then
player.gui.top[draw_main_frame_name].style.font_color = {245, 0, 0}
if ComfyGui.get_mod_gui_top_frame() then
if not ComfyGui.get_button_flow(player)[draw_main_frame_name] or not ComfyGui.get_button_flow(player)[draw_main_frame_name].valid then
Public.draw_gui_char_button(player)
end
if rpg_t.points_left > 0 then
ComfyGui.get_button_flow(player)[draw_main_frame_name].style.font_color = {245, 0, 0}
else
ComfyGui.get_button_flow(player)[draw_main_frame_name].style.font_color = {175, 175, 175}
end
else
player.gui.top[draw_main_frame_name].style.font_color = {175, 175, 175}
if not player.gui.top[draw_main_frame_name] then
Public.draw_gui_char_button(player)
end
if rpg_t.points_left > 0 then
player.gui.top[draw_main_frame_name].style.font_color = {245, 0, 0}
else
player.gui.top[draw_main_frame_name].style.font_color = {175, 175, 175}
end
end
end
@ -162,7 +195,11 @@ local function draw_main_frame(player, location)
if location then
main_frame.location = location
else
main_frame.location = {x = 1, y = 40}
if ComfyGui.get_mod_gui_top_frame() then
main_frame.location = {x = 1, y = 55}
else
main_frame.location = {x = 1, y = 45}
end
end
local data = {}
@ -715,8 +752,7 @@ Gui.on_click(
return
end
local surface_name = Public.get('rpg_extra').surface_name
if sub(player.surface.name, 0, #surface_name) ~= surface_name then
if not Public.check_is_surface_valid(player) then
return
end
@ -742,8 +778,7 @@ Gui.on_click(
return
end
local surface_name = Public.get('rpg_extra').surface_name
if sub(player.surface.name, 0, #surface_name) ~= surface_name then
if not Public.check_is_surface_valid(player) then
return
end
@ -808,8 +843,7 @@ Gui.on_click(
return
end
local surface_name = Public.get('rpg_extra').surface_name
if sub(player.surface.name, 0, #surface_name) ~= surface_name then
if not Public.check_is_surface_valid(player) then
return
end
@ -836,8 +870,7 @@ Gui.on_click(
return
end
local surface_name = Public.get('rpg_extra').surface_name
if sub(player.surface.name, 0, #surface_name) ~= surface_name then
if not Public.check_is_surface_valid(player) then
return
end
@ -861,8 +894,7 @@ Gui.on_click(
return
end
local surface_name = Public.get('rpg_extra').surface_name
if sub(player.surface.name, 0, #surface_name) ~= surface_name then
if not Public.check_is_surface_valid(player) then
return
end
@ -886,8 +918,7 @@ Gui.on_click(
return
end
local surface_name = Public.get('rpg_extra').surface_name
if sub(player.surface.name, 0, #surface_name) ~= surface_name then
if not Public.check_is_surface_valid(player) then
return
end

View File

@ -19,7 +19,6 @@ local nth_tick = Public.nth_tick
--RPG Frames
local main_frame_name = Public.main_frame_name
local sub = string.sub
local round = math.round
local floor = math.floor
local random = math.random
@ -48,8 +47,7 @@ local function on_gui_click(event)
end
end
local surface_name = Public.get('rpg_extra').surface_name
if sub(player.surface.name, 0, #surface_name) ~= surface_name then
if not Public.check_is_surface_valid(player) then
return
end
@ -459,8 +457,7 @@ local function on_entity_damaged(event)
local p = cause.player
local surface_name = Public.get('rpg_extra').surface_name
if sub(p.surface.name, 0, #surface_name) ~= surface_name then
if not Public.check_is_surface_valid(p) then
return
end
@ -670,8 +667,7 @@ local function on_pre_player_mined_item(event)
return
end
local surface_name = Public.get('rpg_extra').surface_name
if sub(player.surface.name, 0, #surface_name) ~= surface_name then
if not Public.check_is_surface_valid(player) then
return
end
@ -851,7 +847,6 @@ end
local function on_player_used_capsule(event)
local enable_mana = Public.get('rpg_extra').enable_mana
local surface_name = Public.get('rpg_extra').surface_name
if not enable_mana then
return
end
@ -868,7 +863,7 @@ local function on_player_used_capsule(event)
return
end
if sub(player.surface.name, 0, #surface_name) ~= surface_name then
if not Public.check_is_surface_valid(player) then
return
end
@ -915,12 +910,12 @@ local function on_player_used_capsule(event)
right_bottom = {x = position.x + radius, y = position.y + radius}
}
if rpg_t.level < spell.level then
if not spell.enabled then
return Public.cast_spell(player, true)
end
if not spell.enabled then
return
if rpg_t.level < spell.level then
return Public.cast_spell(player, true)
end
if not Math2D.bounding_box.contains_point(area, player.position) then

View File

@ -28,7 +28,7 @@ local function get_comparator(sort_by)
return comparators[sort_by]
end
local function create_input_element(frame, type, value, items, index)
local function create_input_element(frame, type, value, items, index, tooltip)
if type == 'slider' then
return frame.add({type = 'slider', value = value, minimum_value = 0, maximum_value = 1})
end
@ -38,6 +38,7 @@ local function create_input_element(frame, type, value, items, index)
if type == 'label' then
local label = frame.add({type = 'label', caption = value})
label.style.font = 'default-listbox'
label.tooltip = tooltip or ''
return label
end
if type == 'dropdown' then
@ -46,7 +47,7 @@ local function create_input_element(frame, type, value, items, index)
return frame.add({type = 'text-box', text = value})
end
local function create_custom_label_element(frame, sprite, localised_string, value)
local function create_custom_label_element(frame, sprite, localised_string, value, tooltip)
local t = frame.add({type = 'flow'})
t.add({type = 'label', caption = '[' .. sprite .. ']'})
local heading = t.add({type = 'label', caption = localised_string})
@ -54,6 +55,8 @@ local function create_custom_label_element(frame, sprite, localised_string, valu
local subheading = t.add({type = 'label', caption = value})
subheading.style.font = 'default-listbox'
t.tooltip = tooltip or ''
return subheading
end
@ -710,13 +713,15 @@ function Public.settings_tooltip(player)
table.sort(spells, comparator)
for _, entity in pairs(spells) do
local cooldown = (entity.cooldown / 60) .. 's'
if entity.type == 'item' then
local text = '[item=' .. entity.entityName .. '] ▪️ Level: [font=default-bold]' .. entity.level .. '[/font] Mana: [font=default-bold]' .. entity.mana_cost .. '[/font]. Cooldown: [font=default-bold]' .. cooldown .. '[/font]'
create_input_element(normal_spell_grid, 'label', text)
elseif entity.type == 'entity' then
local text = '[entity=' .. entity.entityName .. '] ▪️ Level: [font=default-bold]' .. entity.level .. '[/font] Mana: [font=default-bold]' .. entity.mana_cost .. '[/font]. Cooldown: [font=default-bold]' .. cooldown .. '[/font]'
create_input_element(normal_spell_grid, 'label', text)
if entity.enabled then
local cooldown = (entity.cooldown / 60) .. 's'
if entity.type == 'item' then
local text = '[item=' .. entity.entityName .. '] ▪️ Level: [font=default-bold]' .. entity.level .. '[/font] Mana: [font=default-bold]' .. entity.mana_cost .. '[/font]. Cooldown: [font=default-bold]' .. cooldown .. '[/font]'
create_input_element(normal_spell_grid, 'label', text, nil, nil, entity.tooltip)
elseif entity.type == 'entity' then
local text = '[entity=' .. entity.entityName .. '] ▪️ Level: [font=default-bold]' .. entity.level .. '[/font] Mana: [font=default-bold]' .. entity.mana_cost .. '[/font]. Cooldown: [font=default-bold]' .. cooldown .. '[/font]'
create_input_element(normal_spell_grid, 'label', text, nil, nil, entity.tooltip)
end
end
end
@ -741,10 +746,12 @@ function Public.settings_tooltip(player)
local special_spell_grid = special_spell_pane.add({type = 'table', column_count = 1})
for _, entity in pairs(spells) do
local cooldown = (entity.cooldown / 60) .. 's'
if entity.type == 'special' then
local text = '▪️ Level: [font=default-bold]' .. entity.level .. '[/font] Mana: [font=default-bold]' .. entity.mana_cost .. '[/font]. Cooldown: [font=default-bold]' .. cooldown .. '[/font]'
create_custom_label_element(special_spell_grid, entity.special_sprite, entity.name, text)
if entity.enabled then
local cooldown = (entity.cooldown / 60) .. 's'
if entity.type == 'special' then
local text = '▪️ Level: [font=default-bold]' .. entity.level .. '[/font] Mana: [font=default-bold]' .. entity.mana_cost .. '[/font]. Cooldown: [font=default-bold]' .. cooldown .. '[/font]'
create_custom_label_element(special_spell_grid, entity.special_sprite, entity.name, text, entity.tooltip)
end
end
end
end

View File

@ -1,6 +1,7 @@
local Public = require 'modules.rpg.table'
local Token = require 'utils.token'
local Task = require 'utils.task'
local Ai = require 'modules.ai'
local spells = {}
local random = math.random
@ -120,6 +121,7 @@ local function do_projectile(player_surface, name, _position, _force, target, ma
create_build_effect_smoke = false
}
)
return true
end
local function create_projectiles(data)
@ -168,6 +170,7 @@ local function create_projectiles(data)
end
Public.cast_spell(player)
return true
end
local function create_entity(data)
@ -194,7 +197,7 @@ local function create_entity(data)
local e = surface.create_entity({name = self.entityName, position = position, force = force})
tame_unit_effects(player, e)
Public.remove_mana(player, self.mana_cost)
return
return true
end
if self.aoe then
@ -226,6 +229,7 @@ local function create_entity(data)
end
Public.cast_spell(player)
return true
end
local function insert_onto(data)
@ -235,6 +239,7 @@ local function insert_onto(data)
player.insert({name = self.entityName, count = self.amount})
Public.cast_spell(player)
Public.remove_mana(player, self.mana_cost)
return true
end
spells[#spells + 1] = {
@ -535,7 +540,7 @@ spells[#spells + 1] = {
log_spell = true,
sprite = 'recipe/shotgun-shell',
callback = function(data)
create_projectiles(data)
return create_projectiles(data)
end
}
spells[#spells + 1] = {
@ -553,7 +558,7 @@ spells[#spells + 1] = {
log_spell = true,
sprite = 'recipe/grenade',
callback = function(data)
create_projectiles(data)
return create_projectiles(data)
end
}
spells[#spells + 1] = {
@ -571,7 +576,7 @@ spells[#spells + 1] = {
log_spell = true,
sprite = 'recipe/cluster-grenade',
callback = function(data)
create_projectiles(data)
return create_projectiles(data)
end
}
spells[#spells + 1] = {
@ -589,7 +594,7 @@ spells[#spells + 1] = {
log_spell = true,
sprite = 'recipe/cannon-shell',
callback = function(data)
create_projectiles(data)
return create_projectiles(data)
end
}
spells[#spells + 1] = {
@ -607,7 +612,7 @@ spells[#spells + 1] = {
log_spell = true,
sprite = 'recipe/explosive-cannon-shell',
callback = function(data)
create_projectiles(data)
return create_projectiles(data)
end
}
spells[#spells + 1] = {
@ -625,7 +630,7 @@ spells[#spells + 1] = {
log_spell = true,
sprite = 'recipe/uranium-cannon-shell',
callback = function(data)
create_projectiles(data)
return create_projectiles(data)
end
}
spells[#spells + 1] = {
@ -644,7 +649,7 @@ spells[#spells + 1] = {
log_spell = true,
sprite = 'recipe/rocket',
callback = function(data)
create_projectiles(data)
return create_projectiles(data)
end
}
spells[#spells + 1] = {
@ -687,6 +692,7 @@ spells[#spells + 1] = {
Public.remove_mana(player, self.mana_cost)
end
Public.cast_spell(player)
return true
end
end
}
@ -733,6 +739,7 @@ spells[#spells + 1] = {
Public.cast_spell(player)
Public.remove_mana(player, self.mana_cost)
return true
end
}
spells[#spells + 1] = {
@ -771,6 +778,7 @@ spells[#spells + 1] = {
Public.remove_mana(player, self.mana_cost)
Public.cast_spell(player)
return true
end
}
spells[#spells + 1] = {
@ -825,7 +833,7 @@ spells[#spells + 1] = {
sprite = 'item/raw-fish',
special_sprite = 'item=raw-fish',
callback = function(data)
insert_onto(data)
return insert_onto(data)
end
}
spells[#spells + 1] = {
@ -845,7 +853,7 @@ spells[#spells + 1] = {
sprite = 'item/explosives',
special_sprite = 'item=explosives',
callback = function(data)
insert_onto(data)
return insert_onto(data)
end
}
spells[#spells + 1] = {
@ -873,6 +881,7 @@ spells[#spells + 1] = {
Public.suicidal_comfylatron(position, surface)
Public.cast_spell(player)
Public.remove_mana(player, self.mana_cost)
return true
end
}
spells[#spells + 1] = {
@ -891,7 +900,7 @@ spells[#spells + 1] = {
sprite = 'recipe/distractor-capsule',
special_sprite = 'recipe=distractor-capsule',
callback = function(data)
create_projectiles(data)
return create_projectiles(data)
end
}
spells[#spells + 1] = {
@ -922,6 +931,7 @@ spells[#spells + 1] = {
Public.damage_player_over_time(player, random(8, 16))
player.play_sound {path = 'utility/armor_insert', volume_modifier = 1}
Public.cast_spell(player)
return true
end
}
spells[#spells + 1] = {
@ -952,6 +962,7 @@ spells[#spells + 1] = {
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)
return true
end
}
spells[#spells + 1] = {
@ -1016,6 +1027,59 @@ spells[#spells + 1] = {
Public.cast_spell(player)
Public.remove_mana(player, self.mana_cost)
return true
end
}
spells[#spells + 1] = {
name = {'spells.drone_enemy'},
entityName = 'drone_enemy',
target = false,
force = 'player',
level = 200,
type = 'special',
mana_cost = 1000,
cooldown = 18000,
enabled = false,
enforce_cooldown = true,
log_spell = true,
sprite = 'virtual-signal/signal-info',
special_sprite = 'virtual-signal=signal-info',
tooltip = 'Creates a drone that searches for enemies and destroys them.',
callback = function(data)
local self = data.self
local player = data.player
Ai.create_char({player_index = player.index, command = 1, search_local = true})
Public.cast_spell(player)
Public.remove_mana(player, self.mana_cost)
return true
end
}
spells[#spells + 1] = {
name = {'spells.drone_mine'},
entityName = 'drone_mine',
target = false,
force = 'player',
level = 200,
type = 'special',
mana_cost = 1000,
cooldown = 18000,
enabled = false,
enforce_cooldown = true,
log_spell = true,
sprite = 'virtual-signal/signal-info',
special_sprite = 'virtual-signal=signal-info',
tooltip = 'Creates a drone mines entities around you.',
callback = function(data)
local self = data.self
local player = data.player
Ai.create_char({player_index = player.index, command = 2, search_local = false})
Public.cast_spell(player)
Public.remove_mana(player, self.mana_cost)
return true
end
}

View File

@ -89,7 +89,7 @@ Public.auto_allocate_nodes_func = {
'Vitality'
}
function Public.reset_table()
function Public.reset_table(migrate)
this.rpg_extra.debug = false
this.rpg_extra.breached_walls = 1
this.rpg_extra.reward_new_players = 0
@ -127,7 +127,9 @@ function Public.reset_table()
['pipe'] = true
}
this.tweaked_crafting_items_enabled = false
this.rpg_t = {}
if not migrate then
this.rpg_t = {}
end
this.rpg_extra.rpg_xp_yield = {
['behemoth-biter'] = 16,
['behemoth-spitter'] = 16,
@ -160,8 +162,8 @@ function Public.get(key)
end
--- Gets value from player rpg_t table
---@param key string
---@param value string
---@param key string|integer
---@param value string|nil
function Public.get_value_from_player(key, value)
if key and value then
if (this.rpg_t[key] and this.rpg_t[key][value]) then
@ -180,8 +182,8 @@ end
--- Sets value to player rpg_t table
---@param key string
---@param value string
---@param setter string
---@param value string|boolean|number|nil
---@param setter string|boolean|number|nil
function Public.set_value_to_player(key, value, setter)
if key and value then
if (this.rpg_t[key] and this.rpg_t[key][value]) then
@ -227,12 +229,8 @@ function Public.set(key)
end
--- Toggle debug - when you need to troubleshoot.
function Public.toggle_debug()
if this.rpg_extra.debug then
this.rpg_extra.debug = false
else
this.rpg_extra.debug = true
end
function Public.toggle_debug(value)
this.rpg_extra.debug = value or false
return this.rpg_extra.debug
end
@ -278,6 +276,55 @@ function Public.enable_health_and_mana_bars(value)
return this.rpg_extra.enable_health_and_mana_bars
end
--- Toggles the mod gui state.
---@param value boolean
---@param read boolean
function Public.enable_mod_gui(value, read)
if not read then
Gui.set_mod_gui_top_frame(value or false)
end
if Gui.get_mod_gui_top_frame() then
local players = game.connected_players
for i = 1, #players do
local player = players[i]
local top = player.gui.top
if top.mod_gui_top_frame and top.mod_gui_top_frame.valid then
top.mod_gui_top_frame.visible = true
end
for _, child in pairs(top.children) do
if child.caption == '[RPG]' then
child.destroy()
Public.draw_gui_char_button(player)
end
end
end
else
local players = game.connected_players
local count = 0
for i = 1, #players do
local player = players[i]
local top = Gui.get_button_flow(player)
for _, child in pairs(top.children) do
count = count + 1
if child.caption == '[RPG]' then
child.destroy()
Public.draw_gui_char_button(player)
end
end
if count == 0 then
if player.gui.top.mod_gui_top_frame and player.gui.top.mod_gui_top_frame.valid then
player.gui.top.mod_gui_top_frame.visible = false
end
else
if player.gui.top.mod_gui_top_frame and player.gui.top.mod_gui_top_frame.valid then
player.gui.top.mod_gui_top_frame.visible = true
end
end
end
end
end
--- Enables the mana feature that allows players to spawn entities.
---@param value boolean
function Public.enable_mana(value)
@ -388,6 +435,44 @@ function Public.tweaked_crafting_items(tbl)
return this.tweaked_crafting_items
end
function Public.migrate_new_rpg_tbl(player)
local rpg_t = Public.get_value_from_player(player.index, nil)
if rpg_t then
rpg_t.flame_boots = nil
rpg_t.one_punch = nil
rpg_t.points_left = rpg_t.points_to_distribute or 0
rpg_t.points_to_distribute = nil
rpg_t.aoe_punch = false
rpg_t.auto_toggle_features = {
aoe_punch = false,
stone_path = false
}
end
Public.enable_mod_gui(false, true)
local screen = player.gui.screen
for _, child in pairs(screen.children) do
if child.caption and child.caption[1] == 'rpg_settings.spell_name' then
child.destroy()
end
end
end
function Public.migrate_to_new_version()
Public.reset_table(true)
if this.rpg_spells then
this.rpg_spells = nil
end
local players = game.players
for _, player in pairs(players) do
Public.migrate_new_rpg_tbl(player)
end
end
Public.settings_frame_name = settings_frame_name
Public.settings_tooltip_frame = settings_tooltip_frame
Public.close_settings_tooltip_frame = close_settings_tooltip_frame
@ -411,4 +496,11 @@ end
Event.on_init(on_init)
Event.on_configuration_changed(
function()
print('[RPG] Migrating to new version')
Public.migrate_to_new_version()
end
)
return Public

View File

@ -12,6 +12,7 @@ Global.register(
end
)
local round = math.round
local floor = math.floor
local random = math.random
local abs = math.abs
@ -66,6 +67,7 @@ local function spawn_biters(data)
return
end
end
Public.wave_defense_set_unit_raffle(h * 0.20)
local unit_to_create
@ -78,14 +80,18 @@ local function spawn_biters(data)
local modified_unit_health = Public.get('modified_unit_health')
local modified_boss_unit_health = Public.get('modified_boss_unit_health')
Public.wave_defense_set_unit_raffle(h * 0.20)
local unit_settings = Public.get('unit_settings')
local unit = surface.create_entity({name = unit_to_create, position = position})
if random(1, 30) == 1 then
BiterHealthBooster.add_boss_unit(unit, modified_boss_unit_health.current_value, 0.38)
else
BiterHealthBooster.add_unit(unit, modified_unit_health.current_value * 2)
local final_health = round(modified_unit_health.current_value * unit_settings.scale_units_by_health[unit.name], 3)
if final_health < 1 then
final_health = 1
end
BiterHealthBooster.add_unit(unit, final_health)
end
end
@ -100,11 +106,16 @@ local function spawn_worms(data)
local unit_to_create = Public.wave_defense_roll_worm_name(sqrt(position.x ^ 2 + position.y ^ 2) * 0.20)
local unit = surface.create_entity({name = unit_to_create, position = position})
local worm_unit_settings = Public.get('worm_unit_settings')
if random(1, 30) == 1 then
BiterHealthBooster.add_boss_unit(unit, modified_boss_unit_health.current_value, 0.38)
else
BiterHealthBooster.add_unit(unit, modified_unit_health.current_value * 2)
local final_health = round(modified_unit_health.current_value * worm_unit_settings.scale_units_by_health[unit.name], 3)
if final_health < 1 then
final_health = 1
end
BiterHealthBooster.add_unit(unit, final_health)
end
end

View File

@ -29,6 +29,13 @@ commands.add_command(
return Public.spawn_unit_group(true, true)
end
if param == 'set_wave_1500' then
for _ = 1, 1500 do
Public.set_next_wave()
end
return Public.spawn_unit_group(true, true)
end
if param == 'log_all' then
return Public.toggle_debug()
end

View File

@ -3,6 +3,7 @@ local Event = require 'utils.event'
local BiterHealthBooster = require 'modules.biter_health_booster_v2'
local Difficulty = require 'modules.difficulty_vote_by_amount'
local Alert = require 'utils.alert'
local Server = require 'utils.server'
local random = math.random
local floor = math.floor
@ -535,7 +536,7 @@ local function increase_biter_damage()
end
local e = game.forces.enemy
local new = Difficulty.get().difficulty_vote_value * 0.04
local new = Difficulty.get('value') * 0.04
local melee = new
local bio = new - 0.02
local e_old_melee = e.get_ammo_damage_modifier('melee')
@ -618,6 +619,12 @@ local function set_next_wave()
end
end
local log_wave_to_discord = Public.get('log_wave_to_discord')
if wave_number % 100 == 0 and log_wave_to_discord then
Server.to_discord_embed('Current wave: ' .. wave_number)
end
local threat = Public.get('threat')
Public.set('threat', threat + floor(threat_gain))

View File

@ -50,6 +50,7 @@ function Public.reset_wave_defense()
this.biter_raffle = {}
this.debug = false
this.debug_health = false
this.log_wave_to_discord = true
this.paused = false
this.game_lost = false
this.get_random_close_spawner_attempts = 5
@ -135,6 +136,10 @@ function Public.reset_wave_defense()
this.worm_unit_settings = {
-- note that final health modifier isn't lower than 1
scale_units_by_health = {
['land-mine'] = 0.5, -- not active as of now
['gun-turret'] = 0.5, -- not active as of now
['flamethrower-turret'] = 0.4, -- not active as of now
['artillery-turret'] = 0.25, -- not active as of now
['small-worm-turret'] = 0.8,
['medium-worm-turret'] = 0.6,
['big-worm-turret'] = 0.4,

View File

@ -231,7 +231,7 @@ end
---Message all players at a given location
---@param player LuaPlayer
---@param message string
---@param color string
---@param color string|nil
function Public.alert_all_players_location(player, message, color, duration)
local length = duration or 15
Public.alert_all_players_template(
@ -264,7 +264,7 @@ end
---@param player LuaPlayer
---@param duration number
---@param message string
---@param color string
---@param color string|nil
function Public.alert_player(player, duration, message, color, sprite, volume)
Public.alert_player_template(
player,
@ -321,7 +321,7 @@ end
---Message to all players
---@param duration number
---@param message string
---@param color string
---@param color string|nil
function Public.alert_all_players(duration, message, color, sprite, volume)
local players = game.connected_players
for i = 1, #players do

View File

@ -10,16 +10,19 @@ local Color = require 'utils.color_presets'
local Server = require 'utils.server'
local Jail = require 'utils.datastore.jail_data'
local FancyTime = require 'tools.fancy_time'
local Task = require 'utils.task'
local Token = require 'utils.token'
local Public = {}
local match = string.match
local capsule_bomb_threshold = 8
local de = defines.events
local sub = string.sub
local format = string.format
local floor = math.floor
local random = math.random
local abs = math.abs
local max_count_decon = 500
local this = {
enabled = true,
@ -31,6 +34,7 @@ local this = {
corpse_history = {},
message_history = {},
cancel_crafting_history = {},
deconstruct_history = {},
whitelist_types = {},
permission_group_editing = {},
players_warned = {},
@ -45,6 +49,11 @@ local this = {
required_playtime = 2592000,
damage_entity_threshold = 20,
explosive_threshold = 16,
enable_jail_when_decon = true,
filtered_types_on_decon = {},
decon_surface_blacklist = 'nauvis',
players_warn_when_decon = {},
on_cancelled_deconstruction = {tick = 0, count = 0},
limit = 2000
}
@ -75,6 +84,17 @@ local chests = {
['logistic-container'] = true
}
-- Clears the player from players_warn_when_decon tbl.
local clear_player_decon_warnings =
Token.register(
function(event)
local player_index = event.player_index
if this.players_warn_when_decon[player_index] then
this.players_warn_when_decon[player_index] = nil
end
end
)
Global.register(
this,
function(t)
@ -187,7 +207,7 @@ local function on_marked_for_deconstruction(event)
end
local player = game.get_player(event.player_index)
if Session.get_trusted_player(player.name) or this.do_not_check_trusted then
if Session.get_trusted_player(player) or this.do_not_check_trusted then
return
end
@ -210,7 +230,7 @@ local function on_player_ammo_inventory_changed(event)
if player.admin then
return
end
if Session.get_trusted_player(player.name) or this.do_not_check_trusted then
if Session.get_trusted_player(player) or this.do_not_check_trusted then
return
end
@ -232,7 +252,7 @@ end
local function on_player_joined_game(event)
local player = game.get_player(event.player_index)
if not this.enabled then
if not Session.get_trusted_player(player.name) then
if not Session.get_trusted_player(player) then
Session.set_trusted_player(player.name)
end
return
@ -289,7 +309,7 @@ local function on_built_entity(event)
if player.admin then
return
end
if Session.get_trusted_player(player.name) or this.do_not_check_trusted then
if Session.get_trusted_player(player) or this.do_not_check_trusted then
return
end
@ -313,7 +333,7 @@ local function on_player_used_capsule(event)
local player = game.get_player(event.player_index)
if Session.get_trusted_player(player.name) or this.do_not_check_trusted then
if this.do_not_check_trusted then
return
end
@ -678,7 +698,7 @@ local function on_player_cursor_stack_changed(event)
if player.admin then
return
end
if Session.get_trusted_player(player.name) or this.do_not_check_trusted then
if Session.get_trusted_player(player) or this.do_not_check_trusted then
return
end
@ -762,7 +782,6 @@ local function on_init()
return
end
local branch_version = '0.18.35'
local sub = string.sub
local is_branch_18 = sub(branch_version, 3, 4)
local get_active_version = sub(game.active_mods.base, 3, 4)
local default = game.permissions.get_group('Default')
@ -809,6 +828,136 @@ local function on_permission_group_deleted(event)
end
end
local function on_player_deconstructed_area(event)
if not this.enabled then
return
end
local surface = event.surface
local surface_name = this.decon_surface_blacklist
if sub(surface.name, 0, #surface_name) ~= surface_name then
return
end
local player = game.get_player(event.player_index)
local area = event.area
local count = surface.count_entities_filtered({area = area, type = 'resource', invert = true})
local max_count = 0
local is_trusted = Session.get_trusted_player(player)
if is_trusted then
max_count = max_count_decon
end
if next(this.filtered_types_on_decon) then
local filtered_count = surface.count_entities_filtered({area = area, type = this.filtered_types_on_decon})
if filtered_count and filtered_count > 0 then
surface.cancel_deconstruct_area {
area = area,
force = player.force
}
end
end
if count and count >= max_count then
surface.cancel_deconstruct_area {
area = area,
force = player.force
}
if not is_trusted then
return
end
local msg = '[Deconstruct] ' .. player.name .. ' tried to deconstruct: ' .. count .. ' entities!'
Utils.print_to(nil, msg)
Server.to_discord_embed(msg)
if not this.deconstruct_history then
this.deconstruct_history = {}
end
if #this.deconstruct_history > this.limit then
overflow(this.deconstruct_history)
end
local t = abs(floor((game.tick) / 60))
t = FancyTime.short_fancy_time(t)
local str = '[' .. t .. '] '
str = str .. msg
str = str .. ' at lt_x:'
str = str .. floor(area.left_top.x)
str = str .. ' at lt_y:'
str = str .. floor(area.left_top.y)
str = str .. ' at rb_x:'
str = str .. floor(area.right_bottom.x)
str = str .. ' at rb_y:'
str = str .. floor(area.right_bottom.y)
str = str .. ' '
str = str .. 'surface:' .. player.surface.index
increment(this.deconstruct_history, str)
if this.enable_jail_when_decon and not player.admin then
if not this.players_warn_when_decon[player.index] then
this.players_warn_when_decon[player.index] = 1
local r = random(7200, 18000)
Task.set_timeout_in_ticks(r, clear_player_decon_warnings, {player_index = player.index})
end
local warnings = this.players_warn_when_decon[player.index]
if warnings then
if warnings == 1 or warnings == 2 then
Utils.print_to(player, '[Deconstruct] Warning! Do not deconstruct that many entities at once!')
this.players_warn_when_decon[player.index] = this.players_warn_when_decon[player.index] + 1
elseif warnings == 3 then
Utils.print_to(player, '[Deconstruct] Warning! Do not deconstruct that many entities at once! This is your final warning!')
this.players_warn_when_decon[player.index] = this.players_warn_when_decon[player.index] + 1
else
Jail.try_ul_data(player, true, 'script', 'Deconstructed ' .. count .. ' entities. Has been warned 3 times before getting jailed.')
this.players_warn_when_decon[player.index] = nil
end
end
end
end
end
local function on_cancelled_deconstruction(event)
local player_index = event.player_index
if player_index then
return
end
local tick = event.tick
local entity = event.entity
if not entity or not entity.valid then
return
end
local handler = this.on_cancelled_deconstruction
if tick ~= handler.tick then
handler.tick = tick
handler.count = 0
end
handler.count = handler.count + 1
local player = entity.last_user
if player and player.valid and player.connected then
local is_trusted = Session.get_trusted_player(player)
if not is_trusted then
return
end
end
if entity.force.name == 'neutral' then
return
end
if tick == handler.tick and handler.count >= max_count_decon then
return
end
entity.order_deconstruction(entity.force)
end
local function on_permission_group_edited(event)
if not this.enabled then
return
@ -891,7 +1040,7 @@ end
--- Add entity type to the whitelist so it gets logged.
---@param key string
---@param value string
---@param value string|boolean
function Public.whitelist_types(key, value)
if key and value then
this.whitelist_types[key] = value
@ -901,35 +1050,49 @@ function Public.whitelist_types(key, value)
end
--- If the event should also check trusted players.
---@param value string
---@param value boolean
function Public.do_not_check_trusted(value)
this.do_not_check_trusted = value or false
return this.do_not_check_trusted
end
--- If ANY actions should be performed when a player misbehaves.
---@param value string
---@param value boolean
function Public.enable_capsule_warning(value)
this.enable_capsule_warning = value or false
return this.enable_capsule_warning
end
--- If ANY actions should be performed when a player misbehaves.
---@param value string
---@param value boolean
function Public.enable_capsule_cursor_warning(value)
this.enable_capsule_cursor_warning = value or false
return this.enable_capsule_cursor_warning
end
--- If the script should jail a person instead of kicking them
---@param value string
---@param value boolean
function Public.enable_jail(value)
this.enable_jail = value or false
return this.enable_jail
end
--- Defines what the threshold for amount of explosives in chest should be - logged or not.
--- If the script should jail a person whenever they deconstruct multiple times.
---@param value boolean
function Public.enable_jail_when_decon(value)
this.enable_jail_when_decon = value or false
return this.enable_jail_when_decon
end
--- If the script should jail a person whenever they deconstruct multiple times.
---@param value string
function Public.decon_surface_blacklist(value)
this.decon_surface_blacklist = value or 'nauvis'
return this.decon_surface_blacklist
end
--- Defines what the threshold for amount of explosives in chest should be - logged or not.
---@param value number
function Public.explosive_threshold(value)
if value then
this.explosive_threshold = value
@ -938,8 +1101,16 @@ function Public.explosive_threshold(value)
return this.explosive_threshold
end
--- Defines if on_player_deconstructed_area should also check for other types.
---@param tbl table
function Public.filtered_types_on_decon(tbl)
if tbl then
this.filtered_types_on_decon = tbl
end
end
--- Defines what the threshold for amount of times before the script should take action.
---@param value string
---@param value number
function Public.damage_entity_threshold(value)
if value then
this.damage_entity_threshold = value
@ -964,6 +1135,8 @@ Event.add(de.on_entity_died, on_entity_died)
Event.add(de.on_built_entity, on_built_entity)
Event.add(de.on_gui_opened, on_gui_opened)
Event.add(de.on_marked_for_deconstruction, on_marked_for_deconstruction)
Event.add(de.on_player_deconstructed_area, on_player_deconstructed_area)
Event.add(de.on_cancelled_deconstruction, on_cancelled_deconstruction)
Event.add(de.on_player_ammo_inventory_changed, on_player_ammo_inventory_changed)
Event.add(de.on_player_built_tile, on_player_built_tile)
Event.add(de.on_pre_player_mined_item, on_pre_player_mined_item)

View File

@ -554,4 +554,32 @@ Public.get_closest_neighbour = function(position, objects)
return closest
end
--[[
get_closest_neighbour - Return object whose is closest to given position.
@param position - Position, origin point
@param object - Table of objects that have any sort of position datafield.
--]]
Public.get_closest_neighbour_non_player = function(position, objects)
local closest = objects[1]
local min_dist = Public.get_distance(position, closest)
local object, dist
for i = #objects, 1, -1 do
object = objects[i]
if object and object.valid and object.destructible then
dist = Public.get_distance(position, object)
if dist < min_dist then
closest = object
min_dist = dist
end
end
end
if closest and closest.valid and not closest.destructible then
return false
end
return closest
end
return Public

View File

@ -109,7 +109,21 @@ function Public.iter_connected_players(callback)
local players = game.connected_players
for i = 1, #players do
local player = players[i]
callback(player)
if player and player.valid then
callback(player)
end
end
end
--- Iterates over all players
---@param callback function
function Public.iter_players(callback)
local players = game.players
for i = 1, #players do
local player = players[i]
if player and player.valid then
callback(player)
end
end
end

View File

@ -1,7 +1,3 @@
--luacheck: ignore
local branch_version = '1.1' -- define what game version we're using
local sub = string.sub
-- Non-applicable stages are commented out.
_STAGE = {
--settings = 1,
@ -13,46 +9,3 @@ _STAGE = {
config_change = 7,
runtime = 8
}
function get_game_version()
local get_active_branch = sub(game.active_mods.base, 3, 4)
local is_branch_experimental = sub(branch_version, 3, 4)
if get_active_branch >= is_branch_experimental then
return true
else
return false
end
end
function is_loaded(module)
local res = _G.package.loaded[module]
if res then
return res
else
return false
end
end
function is_game_modded()
local i = 0
for k, _ in pairs(game.active_mods) do
i = i + 1
if i > 1 then
return true
end
end
return false
end
function is_mod_loaded(module)
if not module then
return false
end
local res = script.active_mods[module]
if res then
return true
else
return false
end
end

View File

@ -0,0 +1,146 @@
local Event = require 'utils.event'
local Server = require 'utils.server'
local Token = require 'utils.token'
local len = string.len
local gmatch = string.gmatch
local insert = table.insert
local ban_by_join_enabled = false
local try_get_ban = Server.try_get_ban
--- Jail dataset.
local jailed_data_set = 'jailed'
local try_get_is_banned_token =
Token.register(
function(data)
if not data then
return
end
local username = data.username
if not username then
return
end
local state = data.state
if state == true then
game.ban_player(data.username, data.reason)
end
end
)
Event.add(
defines.events.on_player_joined_game,
function(event)
if not ban_by_join_enabled then
return
end
local player = game.get_player(event.player_index)
if not player or not player.valid then
return
end
local secs = Server.get_current_time()
if secs == nil then
return
else
try_get_ban(player.name, try_get_is_banned_token)
end
end
)
Event.add(
defines.events.on_console_command,
function(event)
local cmd = event.command
local user = event.parameters
if not user then
return
end
if len(user) <= 2 then
return
end
local player_index
local reason
local str = ''
local t = {}
for i in gmatch(user, '%S+') do
insert(t, i)
end
player_index = t[1]
for i = 2, #t do
str = str .. t[i] .. ' '
reason = str
end
if not player_index then
return print('[on_console_command] - player_index was undefined.')
end
local target
if game.get_player(player_index) then
target = game.get_player(player_index)
else
return
end
if event.player_index then
local player = game.get_player(event.player_index)
if player and player.valid and player.admin then
-- if target.index == player.index then
-- return
-- end
local data = Server.build_embed_data()
data.username = target.name
data.admin = player.name
if cmd == 'ban' then
Server.set_data(jailed_data_set, target.name, nil) -- this is added here since we don't want to clutter the jail dataset.
if not reason then
data.reason = 'Not specified.'
Server.to_banned_embed(data)
return
else
data.reason = reason
Server.to_banned_embed(data)
return
end
elseif cmd == 'unban' then
Server.to_unbanned_embed(data)
return
end
end
else
local data = Server.build_embed_data()
data.username = target.name
data.admin = '<Server>'
if cmd == 'ban' then
Server.set_data(jailed_data_set, target.name, nil) -- this is added here since we don't want to clutter the jail dataset.
if not reason then
data.reason = 'Not specified.'
Server.to_banned_embed(data)
return
else
data.reason = reason
Server.to_banned_embed(data)
return
end
elseif cmd == 'unban' then
Server.to_unbanned_embed(data)
return
end
end
end
)

View File

@ -478,7 +478,7 @@ local function jail(player, griefer, msg, raised)
end
if not msg then
return
msg = 'Jailed by script'
end
if not game.get_player(griefer) then
@ -589,7 +589,10 @@ function Public.try_dl_data(key)
end
--- Tries to get data from the webpanel and updates the local table with values.
-- @param data_set player token
-- @param key LuaPlayer
-- @param value boolean
-- @param player LuaPlayer or <script>
-- @param message string
function Public.try_ul_data(key, value, player, message)
if type(key) == 'table' then
key = key.name

View File

@ -12,6 +12,10 @@ local Public = {}
local fetch =
Token.register(
function(data)
if not data then
return
end
local key = data.key
local value = data.value
local player = game.players[key]

View File

@ -95,6 +95,9 @@ Gui.on_click(
local left_panel = element.parent.parent
local left_panel_data = Gui.get_data(left_panel)
if not left_panel_data then
return
end
local right_panel = left_panel_data.right_panel
local selected_header = left_panel_data.selected_header

View File

@ -133,6 +133,9 @@ Gui.on_text_changed(
function(event)
local element = event.element
local gui_table = Gui.get_data(element)
if not gui_table then
return
end
local filter = element.text:gsub(' ', '_')
@ -149,6 +152,10 @@ Gui.on_click(
function(event)
local element = event.element
local data = Gui.get_data(element)
if not data then
return
end
local filter_textfield = data.filter_textfield
local gui_table = data.gui_table

View File

@ -158,11 +158,17 @@ Gui.on_click(
function(event)
local element = event.element
local header_data = Gui.get_data(element)
if not header_data then
return
end
local values = header_data.values
local player_index = header_data.player_index
local player_panel = element.parent.parent
local data = Gui.get_data(player_panel)
if not data then
return
end
local element_panel = data.element_panel
local selected_player_header = data.selected_player_header
local input_text_box = data.input_text_box
@ -191,11 +197,17 @@ Gui.on_click(
function(event)
local element = event.element
local header_data = Gui.get_data(element)
if not header_data then
return
end
local stored_data = header_data.stored_data
local element_index = header_data.element_index
local player_panel = element.parent.parent
local data = Gui.get_data(player_panel)
if not data then
return
end
local data_panel = data.data_panel
local selected_element_header = data.selected_element_header
local input_text_box = data.input_text_box
@ -246,6 +258,9 @@ Gui.on_click(
function(event)
local element = event.element
local data = Gui.get_data(element)
if not data then
return
end
local input_text_box = data.input_text_box
local player_panel = data.player_panel
@ -263,6 +278,9 @@ Gui.on_click(
Gui.clear(element_panel)
if selected_player_header then
local player_header_data = Gui.get_data(selected_player_header)
if not player_header_data then
return
end
local values = player_header_data.values
local selected_element_header = draw_element_headers(element_panel, values, selected_element_index)

View File

@ -34,7 +34,7 @@ function Public.open_debug(player)
return
end
frame = screen.add {type = 'frame', name = main_frame_name, caption = 'Debuggertron 3003', direction = 'vertical'}
frame = screen.add {type = 'frame', name = main_frame_name, caption = 'Debuggertron 3004', direction = 'vertical'}
frame.auto_center = true
local frame_style = frame.style
frame_style.height = 600
@ -73,6 +73,9 @@ Gui.on_click(
function(event)
local element = event.element
local data = Gui.get_data(element)
if not data then
return
end
local index = data.index
local frame_data = data.frame_data

View File

@ -87,6 +87,9 @@ Gui.on_click(
local left_panel = element.parent.parent
local data = Gui.get_data(left_panel)
if not data then
return
end
local selected_file_label = data.selected_file_label
@ -125,7 +128,7 @@ Gui.on_click(
local top_panel = element.parent.parent
local data = Gui.get_data(top_panel)
if not data or not data.valid then
if not data then
return
end

View File

@ -1,6 +1,5 @@
local Gui = require 'utils.gui'
local Global = require 'utils.global'
local Token = require 'utils.token'
local Color = require 'utils.color_presets'
local Model = require 'utils.debug.model'
@ -89,10 +88,10 @@ Gui.on_click(
element.style.font_color = Color.orange
data.selected_header = element
input_text_box.text = concat {'global.tokens[', token_id, ']'}
input_text_box.text = concat {'global.tokens.', token_id}
input_text_box.style.font_color = Color.black
local id = Token.get_global(token_id)
local id = Global.get_global(token_id)
local content = dump(id) or 'Could not load data.'
if content:find('function_handlers') then
content = '{}' -- desync handler

View File

@ -108,6 +108,7 @@ local core_on_load = EventCore.on_load
local core_on_nth_tick = EventCore.on_nth_tick
local core_on_configuration_changed = EventCore.on_configuration_changed
local stage_load = _STAGE.load
local raise_event = script.raise_event
local script_on_event = script.on_event
local script_on_nth_tick = script.on_nth_tick
local generate_event_name = script.generate_event_name
@ -182,6 +183,17 @@ function Event.on_init(handler)
core_on_init(handler)
end
--- This exists only to become more easily available if you are already requiring the event module.
function Event.raise(handler, data)
if data then
if not type(data) == 'table' then
return
end
end
raise_event(handler, data)
end
--- Register a handler for the script.on_load event.
-- This function must be called in the control stage or in Event.on_init or Event.on_load
-- See documentation at top of file for details on using events.

BIN
utils/files/beam.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -114,7 +114,7 @@ end
@return the created entity
]]
function Game.print_player_floating_text_position(player_index, text, color, x_offset, y_offset)
local player = Game.get_player_by_index(player_index)
local player = game.get_player(player_index)
if not player or not player.valid then
return
end

View File

@ -1,39 +1,57 @@
local Event = require 'utils.event_core'
local Token = require 'utils.token'
local Global = {
names = {},
index = 0,
filepath = {}
}
global.tokens = {}
local Global = {}
local concat = table.concat
local names = {}
Global.names = names
--- Sets a new global
---@param tbl any
---@return integer
---@return string
function Global.set_global(tbl)
local filepath = debug.getinfo(3, 'S').source:match('^.+/currently%-playing/(.+)$'):sub(1, -5):gsub('/', '_')
Global.index = Global.index + 1
Global.filepath[filepath] = Global.index
Global.names[filepath] = concat {Global.filepath[filepath], ' - ', filepath}
global.tokens[filepath] = tbl
return Global.index, filepath
end
--- Gets a global from global
---@param token number|string
---@return any|nil
function Global.get_global(token)
if global.tokens[token] then
return global.tokens[token]
end
end
function Global.register(tbl, callback)
if _LIFECYCLE ~= _STAGE.control then
error('can only be called during the control stage', 2)
end
local filepath = debug.getinfo(2, 'S').source:match('^.+/currently%-playing/(.+)$'):sub(1, -5)
local token = Token.register_global(tbl)
names[token] = concat {token, ' - ', filepath}
local token, filepath = Global.set_global(tbl)
Event.on_load(
function()
callback(Token.get_global(token))
if global.tokens[token] then
callback(Global.get_global(token))
else
callback(Global.get_global(filepath))
end
end
)
return token
return filepath
end
function Global.register_init(tbl, init_handler, callback)
if _LIFECYCLE ~= _STAGE.control then
error('can only be called during the control stage', 2)
end
local filepath = debug.getinfo(2, 'S').source:match('^.+/currently%-playing/(.+)$'):sub(1, -5)
local token = Token.register_global(tbl)
names[token] = concat {token, ' - ', filepath}
local token, filepath = Global.set_global(tbl)
Event.on_init(
function()
@ -44,11 +62,14 @@ function Global.register_init(tbl, init_handler, callback)
Event.on_load(
function()
callback(Token.get_global(token))
if global.tokens[token] then
callback(Global.get_global(token))
else
callback(Global.get_global(filepath))
end
end
)
return token
return filepath
end
return Global

View File

@ -34,6 +34,7 @@ Public.token =
end
)
Public.beam = 'file/utils/files/beam.png'
Public.settings_white_icon = 'file/utils/files/settings-white.png'
Public.settings_black_icon = 'file/utils/files/settings-black.png'
Public.pin_white_icon = 'file/utils/files/pin-white.png'
@ -396,7 +397,7 @@ end
--- This adds the given gui to the top gui.
---@param player userdata
---@param frame userdata
---@param frame userdata|table
function Public.add_mod_button(player, frame)
if Public.get_button_flow(player)[frame.name] and Public.get_button_flow(player)[frame.name].valid then
return
@ -577,6 +578,7 @@ end
local function draw_main_frame(player)
local tabs = main_gui_tabs
Public.clear_all_active_frames(player)
if Public.get_main_frame(player) then
@ -584,7 +586,6 @@ local function draw_main_frame(player)
end
local frame, inside_frame = Public.add_main_frame_with_toolbar(player, 'left', main_frame_name, nil, close_button_name, 'Comfy Panel')
local tabbed_pane = inside_frame.add({type = 'tabbed-pane', name = 'tabbed_pane'})
for name, func in pairs(tabs) do

View File

@ -247,7 +247,8 @@ local function draw_events(data)
['Mining Override History'] = antigrief.whitelist_mining_history,
['Landfill History'] = antigrief.landfill_history,
['Corpse Looting History'] = antigrief.corpse_history,
['Cancel Crafting History'] = antigrief.cancel_crafting_history
['Cancel Crafting History'] = antigrief.cancel_crafting_history,
['Deconstruct History'] = antigrief.deconstruct_history
}
local scroll_pane
@ -358,6 +359,10 @@ local function create_admin_panel(data)
local player = data.player
local frame = data.frame
local antigrief = AntiGrief.get()
if not antigrief then
return
end
frame.clear()
local player_names = {}
@ -508,6 +513,9 @@ local function create_admin_panel(data)
if antigrief.cancel_crafting_history then
table.insert(histories, 'Cancel Crafting History')
end
if antigrief.deconstruct_history then
table.insert(histories, 'Deconstruct History')
end
if #histories == 0 then
return

View File

@ -19,6 +19,8 @@ Global.register(
local Public = {}
Public.events = {bottom_quickbar_button_name = Event.generate_event_name('bottom_quickbar_button_name')}
local main_frame_name = Gui.uid_name()
local clear_corpse_button_name = Gui.uid_name()
local bottom_quickbar_button_name = Gui.uid_name()
@ -225,6 +227,17 @@ Gui.on_click(
end
)
Gui.on_click(
bottom_quickbar_button_name,
function(event)
local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Custom Bottom_quickbar_button_name')
if is_spamming then
return
end
Event.raise(Public.events.bottom_quickbar_button_name, {player = event.player, event = event})
end
)
Event.add(
defines.events.on_player_joined_game,
function(event)

View File

@ -82,7 +82,7 @@ end
local function spaghett()
local spaghetti = this.gui_config.spaghett
if spaghetti.noop then
return
return
end
if spaghetti.enabled then
for _, f in pairs(game.forces) do
@ -355,6 +355,40 @@ local fortress_functions = {
get_actor(event, '[Decon]', 'has disabled decon on car/tanks/trains.', true)
end
end,
['allow_decon_main_surface'] = function(event)
local WPT = is_loaded('maps.mountain_fortress_v3.table')
if event.element.switch_state == 'left' then
local near_locomotive_group = game.permissions.get_group('near_locomotive')
if near_locomotive_group then
near_locomotive_group.set_allows_action(defines.input_action.deconstruct, true)
end
local default_group = game.permissions.get_group('Default')
if default_group then
default_group.set_allows_action(defines.input_action.deconstruct, true)
end
local main_surface_group = game.permissions.get_group('main_surface')
if main_surface_group then
main_surface_group.set_allows_action(defines.input_action.deconstruct, true)
end
WPT.set('allow_decon_main_surface', true)
get_actor(event, '[Decon]', 'has allowed decon on main surface.', true)
else
local near_locomotive_group = game.permissions.get_group('near_locomotive')
if near_locomotive_group then
near_locomotive_group.set_allows_action(defines.input_action.deconstruct, false)
end
local default_group = game.permissions.get_group('Default')
if default_group then
default_group.set_allows_action(defines.input_action.deconstruct, false)
end
local main_surface_group = game.permissions.get_group('main_surface')
if main_surface_group then
main_surface_group.set_allows_action(defines.input_action.deconstruct, false)
end
WPT.set('allow_decon_main_surface', false)
get_actor(event, '[Decon]', 'has disabled decon on main surface.', true)
end
end,
['christmas_mode'] = function(event)
local WPT = is_loaded('maps.mountain_fortress_v3.table')
if event.element.switch_state == 'left' then
@ -667,8 +701,17 @@ local function build_config_gui(data)
if Module.allow_decon then
switch_state = 'left'
end
add_switch(scroll_pane, switch_state, 'allow_decon', 'Deconstruct', 'On = Allows decon on car/tanks/trains.\nOff = Disables decon on car/tanks/trains.')
add_switch(scroll_pane, switch_state, 'allow_decon', 'Deconstruct IC', 'On = Allows decon on car/tanks/trains.\nOff = Disables decon on car/tanks/trains.')
scroll_pane.add({type = 'line'})
switch_state = 'right'
if Module.allow_decon_main_surface then
switch_state = 'left'
end
add_switch(scroll_pane, switch_state, 'allow_decon_main_surface', 'Deconstruct Surface', 'On = Allows decon on main surface.\nOff = Disables decon on main surface.')
scroll_pane.add({type = 'line'})
switch_state = 'right'
if Module.christmas_mode then
switch_state = 'left'
end

View File

@ -950,14 +950,14 @@ local function on_player_left_game()
end
--- If the different roles should be shown in the player_list.
---@param value string
---@param value boolean
function Public.show_roles_in_list(value)
this.show_roles_in_list = value or false
return this.show_roles_in_list
end
--- Notifies player_list if RPG is enabled or not.
---@param value string
---@param value boolean
function Public.rpg_enabled(value)
this.rpg_enabled = value or false
return this.rpg_enabled

View File

@ -1,7 +1,6 @@
local Gui = require 'utils.gui'
local Global = require 'utils.global'
local Event = require 'utils.event'
local Game = require 'utils.game'
local Server = require 'utils.server'
local session = require 'utils.datastore.session_data'
local Config = require 'utils.gui.config'
@ -186,7 +185,7 @@ local function redraw_poll_viewer_content(data)
if next(edited_by_players) then
local edit_names = {'Edited by '}
for pi, _ in pairs(edited_by_players) do
local p = Game.get_player_by_index(pi)
local p = game.get_player(pi)
if p and p.valid then
insert(edit_names, p.name)
insert(edit_names, ', ')
@ -762,7 +761,7 @@ local function vote(event)
end
local function player_joined(event)
local player = Game.get_player_by_index(event.player_index)
local player = game.get_player(event.player_index)
if not player or not player.valid then
return
end

View File

@ -2,7 +2,6 @@ local Token = require 'utils.token'
local Task = require 'utils.task'
local Global = require 'utils.global'
local Event = require 'utils.event'
local Game = require 'utils.game'
local Print = require('utils.print_override')
-- local constants
@ -13,8 +12,7 @@ local concat = table.concat
local serialize = serpent.serialize
local remove = table.remove
local tostring = tostring
local len = string.len
local gmatch = string.gmatch
local raw_print = Print.raw_print
local minutes_to_ticks = 60 * 60
local hours_to_ticks = 60 * 60 * 60
@ -50,9 +48,6 @@ Global.register(
end
)
--- Jail dataset.
local jailed_data_set = 'jailed'
--- Web panel framework.
local discord_tag = '[DISCORD]'
local discord_raw_tag = '[DISCORD-RAW]'
@ -82,6 +77,7 @@ local start_scenario_tag = '[START-SCENARIO]'
local stop_scenario_tag = '[STOP-SCENARIO]'
local ping_tag = '[PING]'
local data_set_tag = '[DATA-SET]'
local ban_get_tag = '[BAN-GET]'
local data_get_tag = '[DATA-GET]'
local data_get_and_print_tag = '[DATA-GET-AND-PRINT]'
local data_get_all_tag = '[DATA-GET-ALL]'
@ -522,6 +518,10 @@ end
local function double_escape(str)
-- Excessive escaping because the data is serialized twice.
if not str then
return ''
end
return str:gsub('\\', '\\\\\\\\'):gsub('"', '\\\\\\"'):gsub('\n', '\\\\n')
end
@ -589,6 +589,16 @@ local function validate_arguments(data_set, key, callback_token)
end
end
local function validate_arguments_of_ban(username, callback_token)
if type(username) ~= 'string' then
error('username must be a string', 3)
end
if type(callback_token) ~= 'number' then
error('callback_token must be a number', 3)
end
end
local function send_try_get_data(data_set, key, callback_token)
data_set = double_escape(data_set)
key = double_escape(key)
@ -597,6 +607,13 @@ local function send_try_get_data(data_set, key, callback_token)
raw_print(message)
end
local function send_try_get_ban(username, callback_token)
username = double_escape(username)
local message = concat {ban_get_tag, callback_token, ' {', 'username:"', username, '"}'}
raw_print(message)
end
local function send_try_get_data_and_print(data_set, key, to_print, callback_token)
data_set = double_escape(data_set)
key = double_escape(key)
@ -658,6 +675,13 @@ function Public.try_get_data(data_set, key, callback_token)
send_try_get_data(data_set, key, callback_token)
end
--- Same as try_get_data returns if a user is banned.
function Public.try_get_ban(username, callback_token)
validate_arguments_of_ban(username, callback_token)
send_try_get_ban(username, callback_token)
end
--- Same as try_get_data but prints the returned value to the given player who ran the command.
function Public.try_get_data_and_print(data_set, key, to_print, callback_token)
validate_arguments(data_set, key, callback_token)
@ -1288,7 +1312,7 @@ commands.add_command(
Event.add(
defines.events.on_player_joined_game,
function(event)
local player = Game.get_player_by_index(event.player_index)
local player = game.get_player(event.player_index)
if not player or not player.valid then
return
end
@ -1324,97 +1348,6 @@ Event.add(
end
)
Event.add(
defines.events.on_console_command,
function(event)
local cmd = event.command
local user = event.parameters
if not user then
return
end
if len(user) <= 2 then
return
end
local userIndex
local reason
local str = ''
local t = {}
for i in gmatch(user, '%S+') do
insert(t, i)
end
userIndex = t[1]
for i = 2, #t do
str = str .. t[i] .. ' '
reason = str
end
if not userIndex then
return log('Log to Discord when a user is banned failed. userIndex was undefined.')
end
local banishedPlayer
if game.get_player(userIndex) then
banishedPlayer = game.get_player(userIndex)
else
return
end
if event.player_index then
local player = game.get_player(event.player_index)
if player and player.valid and player.admin then
if banishedPlayer.index == player.index then
return
end
local data = build_embed_data()
data.username = banishedPlayer.name
data.admin = player.name
if cmd == 'ban' then
Public.set_data(jailed_data_set, banishedPlayer.name, nil) -- this is added here since we don't want to clutter the jail dataset.
if not reason then
data.reason = 'Not specified.'
Public.to_banned_embed(data)
return
else
data.reason = reason
Public.to_banned_embed(data)
return
end
elseif cmd == 'unban' then
Public.to_unbanned_embed(data)
return
end
end
else
local data = build_embed_data()
data.username = banishedPlayer.name
data.admin = '<Server>'
if cmd == 'ban' then
if not reason then
data.reason = 'Not specified.'
Public.to_banned_embed(data)
return
else
data.reason = reason
Public.to_banned_embed(data)
return
end
elseif cmd == 'unban' then
Public.to_unbanned_embed(data)
return
end
end
end
)
Event.add(
defines.events.on_player_died,
function(event)

View File

@ -4,6 +4,8 @@ local Poll = {
}
local Token = require 'utils.token'
local Server = require 'utils.server'
local branch_version = '1.1' -- define what game version we're using
local sub = string.sub
--- This module is for the web server to call functions and raise events.
-- Not intended to be called by scripts.
@ -49,4 +51,48 @@ if not remote.interfaces['ServerCommands'] then
remote.add_interface('ServerCommands', SC_Interface)
end
function get_game_version()
local get_active_branch = sub(game.active_mods.base, 3, 4)
local is_branch_experimental = sub(branch_version, 3, 4)
if get_active_branch >= is_branch_experimental then
return true
else
return false
end
end
function is_loaded(module)
local res = _G.package.loaded[module]
if res then
return res
else
return false
end
end
function is_game_modded()
local active_mods = game.active_mods
local i = 0
for _, _ in pairs(active_mods) do
i = i + 1
if i > 1 then
return true
end
end
return false
end
function is_mod_loaded(module)
if not module then
return false
end
local res = game.active_mods[module]
if res then
return true
else
return false
end
end
return ServerCommands

View File

@ -26,26 +26,9 @@ function Token.get(token_id)
return tokens[token_id]
end
global.tokens = {}
function Token.register_global(var)
local c = #global.tokens + 1
global.tokens[c] = var
return c
end
function Token.get_global(token_id)
return global.tokens[token_id]
end
function Token.set_global(token_id, var)
global.tokens[token_id] = var
end
local uid_counter = 100
---@return integer
function Token.uid()
uid_counter = uid_counter + 1

View File

@ -117,4 +117,11 @@ Module.format_time = function(ticks)
return table.concat(result, ' ')
end
function Module.inside(pos, area)
local lt = area.left_top
local rb = area.right_bottom
return pos.x >= lt.x and pos.y >= lt.y and pos.x <= rb.x and pos.y <= rb.y
end
return Module