mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-03-25 21:29:06 +02:00
Merge remote-tracking branch 'upstream/develop' into develop
This commit is contained in:
commit
184ca52885
27
.github/workflows/CheckMaps.yml
vendored
Normal file
27
.github/workflows/CheckMaps.yml
vendored
Normal 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
|
@ -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'
|
||||
|
@ -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!
|
||||
|
@ -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]
|
||||
|
@ -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=доход / минуту
|
||||
|
||||
|
@ -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__
|
||||
|
@ -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
39
locale/ru/pirates.cfg
Normal 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Чтобы запасти больше, отправьте его в каюту капитана. Если у корабля закончится топливо, экипаж проиграл.
|
@ -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=Отключено
|
||||
|
@ -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=重置市场的商品并调整价格.
|
||||
|
@ -13,20 +13,20 @@ 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• 命令: /ccolor 随机一个有趣的颜色。 /classinfo {classname} 给出指定职业的描述(注意职业名称必须使用英文,例如/classinfo deckhand)。想要管理你的职业,请使用 /take {classname} 成为指定职业或 /giveup放弃当前职业。虫子尸体太多,请点击右下角的[entity=medium-biter]。
|
||||
softmod_info_tips_2=• 船长可以通过在瞭望台的蓝色箱子中放置100个铁路信号来驾驶船舶向左或向右转。在船头的蓝箱放置信号灯可以微调登陆点\n• 赠予船的资源会出现在船长舱中,请及时取出避免爆仓。\n• 为发射井充电会消耗所在电网中的所有电力。发射井被摧毁不再导致游戏失败,除非该关卡有要求。\n• 岛上可用的矿石数量与你打碎岩石的顺序无关。\n• 每个岛上的被动污染随着时间的推移而增加。\n• 攻击的强度与剩余虫巢数成正比。 (基于时间的进化速度也与虫巢成正比,但破坏虫巢会立即使进化值跳跃,比让虫巢活着“本应”产生的还要多。)\n• 实验室产能随着航行里格数增加而提高。\n• 当船移动时,甲板上的落地物品会被移至船长舱,为了更好的性能。\n• 命令: /ccolor 随机一个有趣的颜色。 /classinfo {classname} 给出指定职业的描述(注意职业名称必须使用英文,例如/classinfo deckhand)。想要管理你的职业,请使用 /take {classname} 成为指定职业或 /giveup放弃当前职业。虫子尸体太多,请点击右下角的[entity=big-biter]。
|
||||
|
||||
softmod_info_updates_1=近期重要更新
|
||||
softmod_info_updates_2=v1.2.13\n• 增加了 /classinfofull 指令。\n• 玩家开局物品增强。\n\nv1.2.11\n• 职业花费降低\n• 在海上不再限制时间,请尽情享受闲暇时光。\n\nv1.2.8\n• 提高对玩家的中毒伤害。\n• 增强迷宫宝藏。\n• 虫子更倾向于成群进攻。
|
||||
softmod_info_updates_2=v1.3\n• 船舱内的箱子现在可摧毁\n• 流体可以更方便运输。\n• 新的职业以及管理界面。\n\nv1.2\n• 模组(mod)版本已发布。
|
||||
|
||||
softmod_info_credits_1=工作人员
|
||||
softmod_info_credits_2=海盗船由 thesixthroc 设计和编码。 Comfy 代码基础和帮助来自 Gerkiz, Hanakocz 和 Mew @ Comfy Industries (https://getcomfy.eu)。一些由 Mattisso 提供的岛屿结构蓝图。\n\n汉化:dwightkung\n\n 欢迎来和我们聊天: https://getcomfy.eu/discord\n\n"那些白手套。我永远不会忘记它们,直到我死去的那一天。" - Dr. John
|
||||
softmod_info_credits_2=海盗船由 thesixthroc 设计和编码。Piratux 参与开发。Comfy 代码基础和帮助来自 Gerkiz, Hanakocz 和 Mew @ Comfy Industries (https://getcomfy.eu)。一些由 Mattisso 提供的岛屿结构蓝图。\n\n汉化:dwightkung\n\n 欢迎来和我们聊天: https://getcomfy.eu/discord\n\n"那些白手套。我永远不会忘记它们,直到我死去的那一天。" - Dr. John
|
||||
softmod_info_credits_2_old=Softmod designed and written by thesixthroc. Comfy codebase help from Gerkiz, Hanakocz and Mew @ Comfy Industries (https://getcomfy.eu). Some island structure blueprints were contributed by Mattisso. Gold sprite by Clint Bellanger. Parrot sprites by @pixelthen.\n\n"Those white gloves. I'll never forget them 'till the day I die." - Dr. John
|
||||
thesixthroc_support_toast=如果你喜欢这个场景,欢迎给我买一杯咖啡:ko-fi.com/thesixthroc
|
||||
|
||||
softmod_info_body_promote=由 thesixthroc 制作
|
||||
softmod_info_body_promote_old2=欢迎到patreon.com/thesixthroc支持我
|
||||
|
||||
softmod_info_body_clicky=我知道了
|
||||
softmod_info_body_clicky=点击关闭
|
||||
|
||||
|
||||
|
||||
@ -71,6 +71,8 @@ parrot_radioactive_tip_1=我们需要 铀-235 才能离开这个岛...
|
||||
parrot_radioactive_tip_2=虫子不在乎我们是否污染这里,但污染使它们进化得很快。
|
||||
parrot_maze_tip_1=我们的小地图似乎有问题。
|
||||
parrot_captain_first_time_in_cabin_hint=船长可以在船长舱内购买物品,例如用于驾驶船只的铁路信号灯。
|
||||
parrot_cliff_explosive_tip=悬崖炸药?我记得它们威力巨大,可以炸掉船舱中烦人的箱子
|
||||
parrot_burried_treasure_tip=看到红色的X了吗?用机械臂挖它!
|
||||
|
||||
|
||||
|
||||
@ -151,7 +153,6 @@ error_disembark=现在不是下船的时候。
|
||||
|
||||
|
||||
|
||||
|
||||
quest_structure_market_1=需要__1__x
|
||||
quest_structure_market_2=(物品材料将在
|
||||
quest_structure_market_3=任务完成后返还)
|
||||
@ -182,10 +183,11 @@ market_error_not_captain_or_officer=购买错误:您需要成为船长或军
|
||||
market_error_maximum_loading_time=购买错误:已达到最大允许加载时间。
|
||||
|
||||
repaired_cannons=[font=heading-1]__1__ 修复了船上的重炮。[/font]
|
||||
upgraded_cannons=[font=heading-1]__1__ 修复并升级了船上的重炮。[/font]
|
||||
upgrade_hold=[font=heading-1]__1__ 购买了额外的下层船舱。[/font]
|
||||
upgrade_power=[font=heading-1]__1__ 升级了船舶的被动发电机。[/font]
|
||||
upgrade_merchants=[font=heading-1]__1__ 解锁未来岛屿上的商船。[/font]
|
||||
upgrade_rockets=[font=heading-1]__1__ 在岛屿市场解锁火箭弹的销售。[/font]
|
||||
upgrade_merchants=[font=heading-1]__1__ 解锁了未来岛屿上的商船。[/font]
|
||||
upgrade_rockets=[font=heading-1]__1__ 解锁了在岛屿市场火箭弹的销售。[/font]
|
||||
|
||||
upgrade_hold_crowsnest_form=额外下层船舱
|
||||
upgrade_power_crowsnest_form=发电机升级
|
||||
@ -213,60 +215,70 @@ role_captain_description=拥有提前驶出船坞、购买物品和其他各种
|
||||
class_obtainable=职业可获取。
|
||||
class_unobtainable=职业已禁用且不可获取。
|
||||
|
||||
class_definition_for=职业描述
|
||||
|
||||
class_deckhand=水手
|
||||
class_deckhand_explanation=Deckhand,在甲板上的时候移动得较快并且为船长舱生成矿石。
|
||||
# class_deckhand_explanation=Deckhand,在甲板上的时候移动得较快并且为船长舱生成矿石。
|
||||
class_deckhand_explanation_advanced=Deckhand,在甲板上的时候有 __1__% 的移速加成并且为船长舱生成矿石 (当前团队人数 +__2__ 每 __3__ 秒) 。
|
||||
class_fisherman=渔夫
|
||||
class_fisherman_explanation=Fisherman,捕鱼的距离较远。
|
||||
# class_fisherman_explanation=Fisherman,捕鱼的距离较远。
|
||||
class_fisherman_explanation_advanced=Fisherman,捕鱼(副作用:其他物品也一样)的范围更大 (__1__ 格额外范围)。
|
||||
class_scout=侦察兵
|
||||
class_scout_explanation=Scout,速度较快,但身体脆弱且伤害低。
|
||||
# class_scout_explanation=Scout,速度较快,但身体脆弱且伤害低。
|
||||
class_scout_explanation_advanced=Scout,有 __1__% 移速加成, 但是承受 __2__% 额外伤害并且造成的伤害有 __3__% 减益。
|
||||
class_samurai=武士
|
||||
class_samurai_explanation=Samurai,比较强壮,而且*没有装备武器*在近战中打得很好,但在其他方面表现不佳。
|
||||
# class_samurai_explanation=Samurai,比较强壮,而且*没有装备武器*在近战中打得很好,但在其他方面表现不佳。
|
||||
class_samurai_explanation_advanced=Samurai,拥有 __1__% 减伤, 赤手空拳时造成 __2__ 额外伤害 (受动能武器伤害研究影响), 但是使用武器时 __3__% 伤害减益。
|
||||
class_merchant=商人
|
||||
class_merchant_explanation=Merchant,每个里格产生 50 达布隆。
|
||||
# class_merchant_explanation=Merchant,每个里格产生 50 达布隆。
|
||||
class_merchant_explanation_advanced=Merchant,每个里格产生 50 达布隆。
|
||||
class_shoresman=海岸人
|
||||
class_shoresman_explanation=Shoresman,移动得稍微快一些,并且不在船上时为船长舱生成矿石。
|
||||
class_shoresman=陆勤
|
||||
# class_shoresman_explanation=Shoresman,移动得稍微快一些,并且不在船上时为船长舱生成矿石。
|
||||
class_shoresman_explanation_advanced=Shoresman,不在船上时有 __1__% 移速加成并且为船长舱生成矿石 (当前团队人数 +__2__ 每 __3__ 秒) 。
|
||||
class_boatswain=水手长
|
||||
class_boatswain_explanation=Boatswain,在甲板下面时移动较快并为船长舱生成矿石。
|
||||
# class_boatswain_explanation=Boatswain,在甲板下面时移动较快并为船长舱生成矿石。
|
||||
class_boatswain_explanation_advanced=Boatswain,在甲板下面时 __1__% 移速加成并且为船长舱生成矿石 (当前团队人数 +__2__ 每 __3__ 秒) 。
|
||||
class_prospector=勘探者
|
||||
class_prospector_explanation=Prospector,在手工开采时会发现较多资源。
|
||||
# class_prospector_explanation=Prospector,在手工开采时会发现较多资源。
|
||||
class_prospector_explanation_advanced=Prospector,在手工开采时会发现较多资源。
|
||||
class_lumberjack=伐木工人
|
||||
class_lumberjack_explanation=Lumberjack,在砍树时会找到较多的资源。
|
||||
# class_lumberjack_explanation=Lumberjack,在砍树时会找到较多的资源。
|
||||
class_lumberjack_explanation_advanced=Lumberjack,在砍树时会找到较多的资源。
|
||||
class_master_angler=钓鱼大师
|
||||
class_master_angler_explanation=Master Angler,钓鱼的距离非常远,捕获的量也非常多。
|
||||
# class_master_angler_explanation=Master Angler,钓鱼的距离非常远,捕获的量也非常多。
|
||||
class_master_angler_explanation_advanced=Master Angler,钓鱼的距离非常远 (__1__ 格额外范围) ,捕获的量 (+__2__ 鱼 和 +__3__ 达布隆)也非常多。
|
||||
class_wood_lord=森林之王
|
||||
class_wood_lord_explanation=Lord of the Woods,在砍树时会发现非常多的资源。
|
||||
class_wood_lord=砍伐之王
|
||||
# class_wood_lord_explanation=Lord of the Woods,在砍树时会发现非常多的资源。
|
||||
class_wood_lord_explanation_advanced=Lord of the Woods,在砍树时会发现非常多的资源。
|
||||
class_chief_excavator=首席挖掘手
|
||||
class_chief_excavator_explanation=Chief Excavator,在手工开采时发现了非常多的资源。
|
||||
# class_chief_excavator_explanation=Chief Excavator,在手工开采时发现了非常多的资源。
|
||||
class_chief_excavator_explanation_advanced=Chief Excavator,在手工开采时发现了非常多的资源。
|
||||
class_hatamoto=旗本武士
|
||||
class_hatamoto_explanation=Hatamoto,非常强悍,而且*没有装备武器*近战打得很好,但其他方面就很差。
|
||||
# class_hatamoto_explanation=Hatamoto,非常强悍,而且*没有装备武器*近战打得很好,但其他方面就很差。
|
||||
class_hatamoto_explanation_advanced=Hatamoto,拥有 __1__% 减伤, 赤手空拳时造成 __2__ 额外伤害 (受动能武器伤害研究影响), 但是使用武器时 __3__% 伤害减益。
|
||||
class_iron_leg=铁腿
|
||||
class_iron_leg_explanation=Iron Leg,在携带 3000 铁矿石时非常强韧。
|
||||
# class_iron_leg_explanation=Iron Leg,在携带 3000 铁矿石时非常强韧。
|
||||
class_iron_leg_explanation_advanced=Iron Leg,在携带至少 __2__ 铁矿石时拥有__1__% 减伤。
|
||||
class_quartermaster=军需官
|
||||
class_quartermaster_explanation=Quartermaster,为附近的船员提供+10%的物理攻击加成并为船长舱生成矿石。
|
||||
# class_quartermaster_explanation=Quartermaster,为附近的船员提供+10%的物理攻击加成并为船长舱生成矿石。
|
||||
class_quartermaster_explanation_advanced= 为附近的船员 ( __1__ 格范围) 提供 +__2__% 的物理攻击加成并为船长舱生成矿石(数量取决于附近的船员数)。
|
||||
class_dredger=挖泥手
|
||||
class_dredger_explanation=Dredger,在钓鱼时会发现令人惊奇的物品。
|
||||
# class_dredger_explanation=Dredger,在钓鱼时会发现令人惊奇的物品。
|
||||
class_dredger_explanation_advanced=Dredger,继承之前的职业加成并且在钓鱼时会发现令人惊奇的物品。
|
||||
class_smoldering=烧炭工
|
||||
class_smoldering_explanation=Smoldering,煤炭少于50时,会定期将木材转化为煤炭。
|
||||
# class_smoldering_explanation=Smoldering,煤炭少于50时,会定期将木材转化为煤炭。
|
||||
class_smoldering_explanation_advanced=Smoldering,携带的煤炭少于50时,会定期将木材转化为煤炭。
|
||||
class_gourmet=美食家
|
||||
class_gourmet_explanation=Gourmet,通过在奇特的地方吃鱼来为船长舱生成矿石。
|
||||
# class_gourmet_explanation=Gourmet,通过在奇特的地方吃鱼来为船长舱生成矿石。
|
||||
class_gourmet_explanation_advanced=Gourmet,通过在奇特的地方吃鱼来为船长舱生成矿石。
|
||||
class_chief=厨师长
|
||||
class_chief_explanation_advanced=Chief,可以把击败的敌人烹饪为美味佳肴。
|
||||
class_roc_eater=食炉者
|
||||
class_roc_eater_explanation_advanced=Roc Eater,吃鱼时,如果背包里有石炉,则消耗石炉作为替代\n同时拥有 __1__% 伤害减免。
|
||||
class_soldier=新兵
|
||||
class_soldier_explanation_advanced=Soldier,吃鱼时,有 __1__% 几率召唤防御无人机。
|
||||
class_veteran=老兵
|
||||
class_veteran_explanation_advanced=Veteran,吃鱼时,有 __1__% 几率召唤防御无人机。\n另外,有 __2__% 几率减速攻击他们的敌人。
|
||||
|
||||
|
||||
class_explanation=__1__: __2__
|
||||
@ -276,12 +288,12 @@ class_purchase=__1__ 购买了职业 __2__. ([font=scenario-message-dialog]__3__
|
||||
class_upgrade=__1__ 将他们的职业从 __2__ 升级到了 __3__ ([font=scenario-message-dialog]__4__[/font]).
|
||||
|
||||
|
||||
class_take_spare=__1__ 选择了空闲职业 __2__. ([font=scenario-message-dialog]__3__[/font])
|
||||
class_give_spare=一个空闲的 __1__ 职业被授予 __2__。 ([font=scenario-message-dialog]__3__[/font])
|
||||
# class_take_spare=__1__ 选择了空闲职业 __2__. ([font=scenario-message-dialog]__3__[/font])
|
||||
# class_give_spare=一个空闲的 __1__ 职业被授予 __2__。 ([font=scenario-message-dialog]__3__[/font])
|
||||
class_give_up=__1__ 放弃了 __2__。
|
||||
class_becomes_spare=一个 __1__ 职业现在空闲。
|
||||
class_give_up_error_no_class=职业错误:你没有任何职业可以放弃。
|
||||
class_revoke=__1__ 从 __3__ 撤销了 __2__ 。
|
||||
# class_becomes_spare=一个 __1__ 职业现在空闲。
|
||||
# class_give_up_error_no_class=职业错误:你没有任何职业可以放弃。
|
||||
# class_revoke=__1__ 从 __3__ 撤销了 __2__ 。
|
||||
class_purchase_error_prerequisite_class=职业购买错误: 你需要成为 __1__ 才能购买。
|
||||
|
||||
roles_confirm_captain=__1__ 接受了船长的角色。
|
||||
@ -307,8 +319,8 @@ roles_notify_looking_for_captain=正在物色合适的船长...
|
||||
|
||||
warn_nearly_afk_captain=注意:如果您作为船长闲置的时间过长,该职业会传递给其他船员。
|
||||
|
||||
error_class_assign_redundant=职业错误: 你已经是 __1__了。
|
||||
error_class_assign_unavailable_class=职业错误:没有空闲职业
|
||||
# error_class_assign_redundant=职业错误: 你已经是 __1__了。
|
||||
# error_class_assign_unavailable_class=职业错误:没有空闲职业
|
||||
|
||||
|
||||
|
||||
@ -402,17 +414,17 @@ gui_crew_window_buttons_join_crew=加入团队
|
||||
gui_crew_window_buttons_join_spectators=观战
|
||||
gui_crew_window_buttons_join_spectators_tooltip=您在执行此操作后的短时间内将无法重新加入船员。
|
||||
gui_crew_window_crewmembers=船员们
|
||||
gui_crew_window_crewmembers_give_up_class=放弃职业
|
||||
gui_crew_window_crewmembers_give_up_class_tooltip=放弃职业
|
||||
# gui_crew_window_crewmembers_give_up_class=放弃职业
|
||||
# gui_crew_window_crewmembers_give_up_class_tooltip=放弃职业
|
||||
gui_crew_window_crewmembers_resign_as_officer=辞去军官职务
|
||||
gui_crew_window_crewmembers_resign_as_officer_tooltip=放弃军官职务
|
||||
gui_crew_window_spectators=观众
|
||||
gui_crew_window_vote_for_difficulty=难度投票
|
||||
gui_crew_window_spare_classes=空闲职业
|
||||
gui_crew_window_assign_class_button=授予职业: __1__
|
||||
gui_crew_window_assign_class_button_tooltip=任命此玩家为 __1__。\n\n 职业描述: __2__
|
||||
gui_crew_window_selfassign_class_button=选择职业: __1__
|
||||
gui_crew_window_selfassign_class_button_tooltip=授予自己空闲的职业 __1__.\n\n 职业描述: __2__
|
||||
# gui_crew_window_spare_classes=空闲职业
|
||||
# gui_crew_window_assign_class_button=授予职业: __1__
|
||||
# gui_crew_window_assign_class_button_tooltip=任命此玩家为 __1__。\n\n 职业描述: __2__
|
||||
# gui_crew_window_selfassign_class_button=选择职业: __1__
|
||||
# gui_crew_window_selfassign_class_button_tooltip=授予自己空闲的职业 __1__.\n\n 职业描述: __2__
|
||||
gui_crew_window_captains_actions=船长的行动
|
||||
gui_crew_window_captains_actions_disband_crew=解散团队
|
||||
gui_crew_window_captains_actions_disband_crew_tooltip=结束本次航行。点击后会再次提示。
|
||||
@ -428,8 +440,8 @@ gui_crew_window_captains_actions_make_officer=任命军官
|
||||
gui_crew_window_captains_actions_make_officer_tooltip=任命此玩家为军官 (或使用/officer {玩家的名字})
|
||||
gui_crew_window_captains_actions_unmake_officer=解除军官
|
||||
gui_crew_window_captains_actions_unmake_officer_tooltip=解除此玩家军官职务 或使用 /officer {玩家的名字})
|
||||
gui_crew_window_captains_actions_revoke_class=撤销职业
|
||||
gui_crew_window_captains_actions_revoke_class_tooltip=将此玩家的职业放回备用池中。
|
||||
# gui_crew_window_captains_actions_revoke_class=撤销职业
|
||||
# gui_crew_window_captains_actions_revoke_class_tooltip=将此玩家的职业放回备用池中。
|
||||
gui_crew_window_captains_actions_summon_crew=召唤船员上船
|
||||
gui_crew_window_captains_actions_summon_crew_tooltip=将船员传送回船上
|
||||
gui_crew_window_captains_actions_tax=征税
|
||||
@ -440,6 +452,16 @@ gui_crew_window_crew_age=时长: __1__
|
||||
gui_crew_window_crew_capacity_and_difficulty=__1__, 容量 __2__.
|
||||
gui_crew_window_crew_count=船员 (__1__)
|
||||
|
||||
gui_classes=职业
|
||||
gui_classes_available_classes=可用职业
|
||||
gui_classes_taken_by=当前人员
|
||||
gui_classes_actions=操作
|
||||
gui_classes_take=选择
|
||||
gui_classes_drop=放弃
|
||||
gui_classes_take_enabled_tooltip=从事该职业获得加成!
|
||||
gui_classes_take_disabled_tooltip=此职业已被占用。
|
||||
gui_classes_drop_tooltip=放弃该职业以便他人使用。
|
||||
|
||||
gui_evo_tooltip_1=本地虫族进化值: __1__
|
||||
gui_evo_tooltip_2=里格数: __1__
|
||||
gui_evo_tooltip_3=海妖: __1__
|
||||
@ -474,7 +496,7 @@ gui_runs_ongoing_runs_join_crew=加入团队
|
||||
gui_runs_ongoing_runs_return_to_lobby=返回大厅
|
||||
gui_runs_ongoing_runs_hop_on_board=跳上船。
|
||||
gui_runs_proposals=提案
|
||||
gui_runs_proposals_endorse_proposal=批准提案
|
||||
gui_runs_proposals_endorse_proposal=赞同提案
|
||||
gui_runs_proposals_retract_endorsement=撤回支持
|
||||
gui_runs_proposals_abandon_proposal=放弃提案
|
||||
gui_runs_proposal_maker_run_name=团队名称
|
||||
@ -531,4 +553,33 @@ gui_questframe_nodamage=岛屿任务:无伤\n\n发射火箭,并且发射井
|
||||
gui_crew_tooltip_1=你的团队\n\n执行船员操作,例如选择可用的职业。
|
||||
gui_crew_tooltip_2=你的团队\n\n你是自由人,所以什么也做不了。
|
||||
|
||||
gui_classes_tooltip_1=职业面板\n\n管理已解锁的职业
|
||||
gui_classes_tooltip_2=职业面板\n\n你是自由人,这里跟你没关系。
|
||||
|
||||
gui_progress_tooltip=进度: __1__ 里格\n\n航行 __2__ 里格取得胜利
|
||||
|
||||
gui_close_button=关闭
|
||||
|
||||
cmd_notify_set_max_crews=最大并行团队数额已被设定为 __1__。
|
||||
|
||||
cmd_error_not_admin=[错误] 只有管理员可以运行这条命令!
|
||||
cmd_error_not_captain=[错误] 只有船长可以运行这条命令!
|
||||
cmd_error_invalid_player_name=[错误] 玩家 __1__ 不存在。
|
||||
cmd_error_invalid_class_name=[错误] 职业 __1__ 不存在。
|
||||
cmd_error_color_not_found=[错误] 颜色 __1__ 不存在。
|
||||
|
||||
cmd_explain_set_max_crews=管理员命令,用于设定服务器最大并行团队数额。
|
||||
cmd_explain_sail=管理员命令,强制离岛,以防万一。
|
||||
cmd_explain_setcaptain={player} 管理员命令,将船长设定为 {player}。
|
||||
cmd_explain_summoncrew=管理员命令,将队员召唤回船。
|
||||
cmd_explain_ok=用于接受船长头衔。
|
||||
cmd_explain_classinfo={class name} 详细职业描述
|
||||
# cmd_explain_classinfofull={class name} returns detailed definition of the named class.
|
||||
cmd_explain_take={class name} 为自己获取该职业
|
||||
cmd_explain_giveup=释放当前职业
|
||||
cmd_explain_ccolor=内置/color的扩展,增加了更多颜色。
|
||||
cmd_explain_plank={player} 船长命令,将玩家放逐为观众。
|
||||
cmd_explain_officer={player} 船长命令,任免官员。
|
||||
cmd_explain_undock=船长命令,提前出坞。
|
||||
cmd_explain_tax=船长命令,获取25%的金币或其他关键物品。
|
||||
cmd_explain_dev=这是一个开发者命令。
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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!',
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
'!'
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
531
modules/ai.lua
Normal 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
|
@ -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
|
||||
|
161
modules/clear_vacant_players.lua
Normal file
161
modules/clear_vacant_players.lua
Normal 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
|
@ -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
|
||||
|
@ -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
352
modules/render_beam.lua
Normal 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
|
@ -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
|
||||
|
@ -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})
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
146
utils/datastore/banhandler.lua
Normal file
146
utils/datastore/banhandler.lua
Normal 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
|
||||
)
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
BIN
utils/files/beam.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
129
utils/server.lua
129
utils/server.lua
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user