1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-02-09 13:37:02 +02:00

Merge pull request #50 from M3wM3w/master

update from main
This commit is contained in:
hanakocz 2021-02-13 07:39:55 +01:00 committed by GitHub
commit dede244279
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
89 changed files with 17352 additions and 93 deletions

View File

@ -157,7 +157,6 @@ local function send_poll_result_to_discord(poll)
end
local function redraw_poll_viewer_content(data)
local trusted = session.get_trusted_table()
local poll_viewer_content = data.poll_viewer_content
local remaining_time_label = data.remaining_time_label
local poll_index = data.poll_index

View File

@ -87,6 +87,9 @@ require 'modules.autostash'
--require 'maps.biter_battles_v2.main'
--require 'maps.biter_battles.biter_battles'
--![[A map that imitating MF, defending rocket silos instead of trains]]--
-- require 'maps.amap.main'
--![[Guide a Train through rough terrain, while defending it from the biters]]--
-- require 'maps.mountain_fortress_v3.main'
--require 'maps.mountain_fortress_v2.main'
@ -205,6 +208,7 @@ require 'modules.autostash'
--require 'maps.cube'
--require 'maps.mountain_race.main'
--require 'maps.native_war.main'
--require 'maps.scrap_towny_ffa.main'
---------------------------------------------------------------
---------------- MORE MODULES HERE ----------------
@ -225,6 +229,7 @@ require 'modules.autostash'
--require 'terrain_layouts.scrap_02'
--require 'terrain_layouts.watery_world'
--require 'terrain_layouts.tree_01'
--require 'terrain_layouts.scrap_towny_ffa'
---------------------------------------------------------------
if _DUMP_ENV then

96
locale/en/amap.cfg Normal file
View File

@ -0,0 +1,96 @@
[amap]
map_info_main_caption= Mountain Defense 1.7
map_info_sub_caption= 2021.1.31 edition
map_info_text= welcome to moutain defenes! \n \n Many years after the launch of the rocket, the insects made a comeback and wiped out most of the human cities. You and the other survivors have built the last bastion of humanity,. Unfortunately, the insects have found you too. They are organizing troops to march towards us. Before the insects destroy the base, launch rockets to escape from this place! \n Tips: \n 1. You can use RPG button to enhance yourself \n 2. In the RPG settings panel, you can enable magic and select your skills. \n 3. RPG magic can increase your luck \n 4. You can buy vehicles in the main market. They have internal space \n 6. The blue box in the car is enabled. It is allowed to pick up goods from the green box and get goods from the backpack. \n 5. Launching rockets will give a lot of rewards, and the more you launch, the more rewards you get. \n Author: ITAM \n Thanks: hanakoz
science= research is completed, you get __1__ Skill points and __2__ Gold coins.
roll= it's time to turn the wheel of destiny! See what happens!
what= ? What happened! )
sorry= robbery! You lost __1__ gold coins!
nbone= your number is 1, you have won __1__ gold coins!
nb2= you've got the advice of a world expert! You get __1__ skill points!
nb3= you were beaten by the little old man on the side of the road! Reward __1__ points of strength
nb4= what to do when the bug comes? Run away boy! Reward __1__ points of dexterity
nb5= this is a magic wand?! Bonus __1__ Mana
nb6= You start lifing some weights and gain __1__ points of strength!
nb7= Er, nothing happened, very calm though, these 25 waves?
nb8= oh,damn ,you lost __1__ xp!How can I make this happen?
nb9= (⊙o⊙)… You got a fish?
nb10= Oh, I went fishing and got __1__ fish. Don't forget to share!
nb11= our UAV is ready! You've got __1__ defensive drone capsules!
nb12= because of overeating. You're growing faster. Get __1__ XP!
nb14= a small gift bag, what's in it?
nb13= first prize! __1__ gold coins! congratulations
nb15= Please protect the environment and dig less stones,you lost __1__ str point!
nb16= Bananas are bananas,what?,where is my Magic wand? you lost __1__ magic point!
nb17= My muscles are too sore,oh,maybe i can't move recently.you lost __1__ dex point !
nb18= Someone poisoned you! you lost __1__ vil point!
nopoint= you don;t have enough point , so i will take your 1K coin !
joingame= Protect the rocket shaft! Don't let insects destroy it! \n map record:\n single player mode:700 waves! \n record Author: wwwax \n win: no \n \n Multiplayer 985 wave!
usecar= you used your car in the first 100 waves and lost the qualification to receive the reward. Continue to work hard next time
usecar2= achieve the challenge, get 50 skill points reward, Congratulations!
lucknb= your luck value is
whatopen= Oh, what will you get
noenough= guys, you don't have enough money
pass= you have passed the customs!!!!!!! Nice! The clearance wave number is__1__
times= you have launched__1__ Every time you launch a rocket, the reward will be repeated!
reward= it is __1__ rocket launched! You will be rewarded with __2__ skill points and __3__ gold coins.
lost= rocket silo destroyed, game failed! You survived__1__ Wave.
openchest= spend 3000 gold coins, open this box, you have a chance to get MK2!
buyxp= spend 5000 gold coins, buy 1000 experience points!
buyover= you successfully bought 1000 experience points!
getxpfromwave= oh, you pass this wave . so you get 10XP !
relax1= Do you know Rick and morty ? This is Adult cartoon full of strange and eccentric. Rick took Morty and explored the planets. It's very interesting. I strongly recommend that you see it .
relax2= When I was young, I only played one game, Warcraft 3. I have played it since primary school. It's been 14 years now!
relax3= When I was a child, I always heard strange stories. For example: Bermuda Triangle, Loch Ness water monster, spherical lightning. When I was in junior high school, I thought it was true!
relax4= Factory has been out for five years, and it won't be released until 2020. Over the years, Factory has been updated, and has not reduced its price. I think it is a very conscientious game.
relax5= Do you think this game is too crazy? Yes, I think so too!
relax6= In China, parents will ask their children what they want to do in the future, and then tell their children that they want to be a scientist. (but I don't know if that's the case now)
relax7= There is a psychological effect, called Barnum effect. It is easy for people to believe in a general description of personality, and think that it is particularly suitable for themselves and accurately reveals their personality characteristics, even if the content is empty.
relax8= Why plant vs. zombie 2, no computer version?
relax9= There is a devil living behind the moon. He always catches rabbits from the earth to eat. We must organize an army of astronauts to save rabbits!
relax10= Damn, why 1 + 1 = 2 instead of 11? There must be a mistake.
relax11= Why is there no magic in this world? Am I in the wrong world?
relax12= Do you have a girlfriend? Ah? If you don't have a girlfriend, you still come to play factory?. Go find a girlfriend!
relax13= Have you ever tried to drink beer with Coca Cola? What would it taste like?
relax14= Can't give up, never give up. Unless you're playing factory
relax15= Have you heard of flight training class? You can learn how to fly, er, with your hands for 10000 yuan?
relax16= I once picked up 50 yuan at most on the roadside! This is in my primary school, oh, this is the first pot of gold to get rich.
relax17= The best way to achieve something is to ask others to help. The second way is to pretend that you can't do anything.then wait other solve it .
relax18= Take care of yourself, don't get sick, don't let others worry you .
relax19= Unity is strength. We can build a big factory together. or Can we have a cookie, too?
relax20= I hope you have a good time, or come to comfy discord to share your happiness!
single= Warrior, it's not easy to challenge alone. I have something for you. I hope I can help you
gambel= spend 1000 coin to get 2500 coin or 0 coin !
gambel1= you get 2500 coin!
gambel2= well, you get nothing .
bag_isfull= WTF? my inventory is full ,so these rock attack me ?
too_many= you build too many flame turret !
ok_many= This is number __1__ flame turret . yous only can build 12 flame turret
buy_wall_over= __1__ bought health of wall and all turret ,them have __2__ heath now!
buy_health_wall= bought 10% heath for wall and all turret
buy_arty_dam= urgrade arty_damage 10%
player_biter_health= urgrade our biter health 10%
buy_arty_over= __1__ bought arty damage !,it have __2__ damage now!
buy_player_biter_over= __1__ bought our biter health !,our biter have __2__ health now!
player_spider_health= urgrade 10% spider health
buy_spider_health_over= __1__ bought 10% spider health !,it have __2__ health now!
player_biter_dam= urgrade biter_damage 10%
buy_biter_dam= __1__ bought biter damage !,it have __2__ damage now!
easy= I want to relax
med= Want some challenges
hard= I love challenges
cap_upgrad= this item already reach upgrade at cap of wave_number now
buy_cap_over= __1__ bought cap of upgrade, we have __2__ cap now !
buy_cap= buy cap of upgrade

View File

@ -56,7 +56,7 @@ mana_max=This is your max mana. You can increase the regen by increasing your ma
mining_name=MINING\nSPEED
slot_name=SLOT\nBONUS
melee_name=MELEE\nDAMAGE
one_punch_chance=Life on-hit: __1__\nOne punch chance: __2__ %
one_punch_chance=Life on-hit: __1__\nOne punch chance: __2__ % \n+__3__ [img=recipe.defender-capsule]
one_punch_disabled=One Punch is disabled.
bonus_tooltip=Reach distance bonus: __1__\nBuild distance bonus: __2__\nItem drop distance bonus: __3__\nLoot pickup distance bonus: __4__\nItem pickup distance bonus: __5__\nResource reach distance bonus: __6__\nRepair speed: __7__
reach_distance=REACH\nDISTANCE

96
locale/zh-CN/amap.cfg Normal file
View File

@ -0,0 +1,96 @@
[amap]
map_info_main_caption= 山地保卫战1.7
map_info_sub_caption= 2021.1.31
map_info_text= 欢迎来到山地保卫战 \n 在发射火箭很多年以后,虫子再次卷土重来,消灭了大部分人类城市。你和其他的幸存者建立了人类最后的堡垒,。不幸的是虫子也发现了你们,它们正在组织军队向我们进发,在虫子摧毁基地前,发射火箭逃离这个地方! \n 提示: \n 1.你可以利用RPG按钮来增强自己 \n 2.在RPG设置面板可以启用魔法,选择你的技能。 \n 3.RPG的魔法可以增加,你的好运 \n 4.你可以在主市场购买载具,它们拥有内部空间 \n 6.车内蓝箱子启用允许从绿箱子取货,可以从车背包内获得物品。 \n 6.你可以在车里赌博,买经验,开箱子。 \n 7.发射火箭会给大量奖励,并且发射的越多奖励越多。 \n \n 群号:701077913 \n 作者:itam \n 鸣谢:Hanakoz \n
science= 科技研发完成,你得到了奖励__1__技能点,__2__金币。
roll= 是时候转动命运之轮了!看看会发生什么吧!
what= ?发生什么事了(你因为开小差没有参与转盘抽奖!)
sorry= 抢劫!你失去了 __1__ 金币!
nbone= 你的数字为1,你获得了 __1__ 金币奖励!
nb2= 你获得了一个世外高人的指点!奖励 __1__ 点RPG
nb3= 你被路边的小老头暴打了一顿!奖励 __1__ 点体力
nb4= 虫子来了怎么办?跑把少年! 奖励 __1__ 点敏捷
nb5= 这是魔法棒?!奖励 __1__ 点魔法值
nb6= 抬杠抬杠,你在无情的抬杠。奖励 __1__ 点力量!
nb7= 额,什么也没发生,很平静的度过了,这25波?
nb8= ?缩小术,你中了名侦探柯南的暗算,损失 __1__ 经验!
nb9= (⊙o⊙)…,你得到了一条鱼?
nb10= 哦,出海打渔,捞到了1条鱼,别忘了分别人点!
nb11= 我方无人机已就绪!你获得了 __1__ 台防御无人机胶囊!
nb12= 因为暴饮暴食。你增长的更快了。获得 __1__ 点xp!
nb14= 1个小礼包,里面会有什么呢?
nb13= 一等奖! __1__ 金币!恭喜
nb15= 请保护环境,少挖石头,你失去了 __1__ 点力量
nb16= 你在干嘛?拿香蕉施法吗?你失去了 __1__ 点法力
nb17= 你因为服用兴奋剂,而产生了副作用!失去了 __1__ 点敏捷
nb18= 有人给你下毒了!快去找解药。失去了 __1__ 点活力!
nopoint= 你没有足够的点数用来扣除,所以我决定拿走你 __1__ 金币
joingame= 欢迎,新玩家请阅读地图信息! \n 地图纪录:\n 单人模式:存活700波! \n 纪录作者:wwwax \n 通关: 无 \n \n 多人模式: 985波。\n 交流群:701077913
usecar= 你在前一百波中使用了汽车,失去了领取奖励的资格,下次继续努力
usecar2= 达成挑战,获得50点技能点奖励,恭喜!
lucknb= 你的好运值为
whatopen= 哦,你开出了什么呢
noenough= 兄弟,你钱不够啊
pass= 你通关了!!!!!!!Nice!通关波数为__1__
times= 你已经发射了__1__个火箭,你每发射1个火箭奖励就会重复一次!
reward= 这是第__1__个火箭!,奖励__2__技能点,__3__金币。
lost= 火箭发射井被摧毁了,游戏失败!,你存活了__1__波。
openchest= 花费3千金币,打开这个箱子,你有机会获得MK2!
buyxp= 花费5千金币,购买1000点经验!
buyover= 你成功购买了1000点经验!
getxpfromwave= 你又坚持了一波,获得10点经验!
relax1= 你知道瑞克和莫蒂吗?这是一部充满奇怪和古怪的成人动画片。瑞克带着莫蒂去探索行星,路上非常多好玩的事情。这很有趣。我强烈建议你去看看。
relax2= 我小的时候只玩一个游戏,就是魔兽争霸3,我从小学就开始玩了。目前已经过去14年了!
relax3= 我小时候总是听闻一些奇怪的故事。例如:百慕大三角,尼斯湖水怪,球形闪电。我上初中的时候都还以为这是真的事情!
relax4= 异星工厂这个游戏已经出了5年了,直到2020年它才推出了正式版。这么多年来,异星工厂一直保持着更新,并且没有降价过,我觉得它是一个非常良心的游戏。
relax5= 你是否觉得这个游戏过于疯狂?是的,我也是这样想的!
relax6= 在中国,父母都会问小孩,你将来想要做什么,然后告诉自己的孩子,要立志成为科学家。(但我不知道,现在是不是这样了)
relax7= 有个心理学效应,叫巴纳姆效应,人很容易相信一个笼统的一般性的人格描述,并认为它特别适合自己并准确地揭示了自己的人格特点,即使内容空洞。
relax8= 为什么植物大战僵尸2,没有电脑版?
relax9= 月亮背后住着一个恶魔,它总是从地球上抓兔子来吃。我们必须组织宇航员军队,去解救兔子!
relax10= 可恶,为什么1+1=2,而不是11?这一定是哪里弄错了。
relax11= 这个世界为什么没有魔法?是我走错世界了吗?
relax12= 你有女朋友吗?啊?你没有女朋友还来玩异星工厂,快去找个女朋友!
relax13= 你试过把啤酒和可口可乐一起喝吗?会是什么味道呢?
relax14= 不能放弃,永远别放弃。除非你玩的是异星工厂
relax15= 你听说过飞行培训班吗?你只要花1万块钱,就能学会如何飞行,呃,用手?
relax16= 我曾经在路边最多捡到过50块钱!这是在我小学的时候,哦,这是发家致富的第一桶金。
relax17= 实现一件事情的最好办法就是叫别人来帮忙,第二个办法就是假装自己什么都不会。
relax18= 要照顾好自己,不要生病,不要让人担心
relax19= 团结就是力量,我们可以一起建立一个大工厂。也可以一起吃一个小饼干?
relax20= 天啊,写地图太累了,这个地图我已经写了一个多月了。从2020年12月开始,到1月20日目前。唉。
single= 勇士!单人挑战是很不容易的事情,我为你准备了一些物品!注意查收!
gambel= 花费1000金币有概率得2500金币,或者,什么都没有。
gambel1= 你赢得了2500000金币!
gambel2= 哦,你什么也没得到。
bag_isfull= 卧槽,我背包居然满了,扎了我一手的矿!
too_many= 你已经有了太多火焰炮塔!
ok_many= 这是第 __1__ 个火焰塔,你最多能拥有12个!
buy_wall_over= __1__ 升级了墙和所有炮塔的生命值,现在墙有__2__ 倍生命了!
buy_health_wall= 升级墙和所有炮塔的10%的生命值
buy_arty_dam= 升级10%的重炮伤害
player_biter_health= 升级10%的友军虫子血量
buy_arty_over= __1__ 购买了重炮伤害,现在有 __2__ 伤害了!
buy_player_biter_over= __1__ 购买了友军虫子血量,现在友军虫子有 __2__ 倍生命了!
player_spider_health= 升级蜘蛛10%的生命值
buy_spider_health_over= __1__ 升级了蜘蛛10%的生命值!,蜘蛛现在有 __2__ 生命了!
player_biter_dam= 升级友军虫子 10%的伤害
buy_biter_dam= __1__ 购买了虫子伤害 !,我方虫子现在有 __2__ 倍伤害了!
easy= 想要放松一下
med= 想要有些挑战性
hard= 我爱挑战!
cap_upgrad= 该项目已达目前波次的升级上限!
buy_cap_over= __1__ 购买了升级上限,现在升级上限为 __2__ !
buy_cap= 购买升级上限。

View File

@ -1,15 +1,15 @@
[rpg_main]
no_valid_surface=无指定操作名
flame_boots_worn_out=你的火焰鞋穿坏.
flame_boots_worn_out=你的火焰鞋穿坏.
flame_mana_remaining=剩余魔法:__1__
one_punch_text=暴击
mana_casting_too_fast= __1__ 魔法还有很多, 像 __1__ 迅速创建出, 然后挥舞着他们的魔杖,说一些难以理解的词.
mana_casting_too_fast= __1__ 魔法还有很多, 像 __2__ 迅速创建出, 然后挥舞着他们的魔杖,说一些难以理解的词.
low_level=等级不够.
not_inside_pos=你挥动你的魔杖, 但意识到它不能达到.
no_mana=你没有足够的魔力.
suicidal_comfylatron=您挥舞着魔杖,__1__在运行!
warped_ok=有轻微伤害自己的行为.
object_spawned=__1__正在制造.\n 你挥动你的魔杖和 __1__ 出现.
object_spawned= 正在施法!.\n 你挥动你的魔杖和 __1__ 出现.
out_of_reach=无法在给制定位置创建物体.
[rpg_functions]
@ -56,7 +56,7 @@ mana_max=这是你的最大魔力值。你可以通过增加你的魔法技能
mining_name=挖掘\n速度
slot_name=背包\n加成
melee_name=近战\n伤害
one_punch_chance=命中生命: __1__\n暴击几率: __2__ %
one_punch_chance=命中生命: __1__\n暴击几率: __2__ %\n +__3__ [img=recipe.defender-capsule]
one_punch_disabled=暴击被禁用
bonus_tooltip=到达距离加成: __1__\n建筑距离加成: __2__\n物品投掷距离加成: __3__\n拾取战利品距离加成: __4__\n物品拾取距离加成: __5__\n资源到达距离加成: __6__\n修理速度: __7__
reach_distance=到达\n距离
@ -88,7 +88,7 @@ movement_text_tooltip=不想像闪电一样奔跑吗?\n你可以在这里切
stone_path_label=采矿时启用石路?
stone_path_tooltip=启用此选项将在您挖掘时自动创建石头路径。
one_punch_label=启用暴击?
one_punch_tooltip=启用此选项将有一次击打敌人的机会
one_punch_tooltip=启用此选项将有一次击打敌人的机会,不能装备枪和子弹!
one_punch_globally=启用全局。
flameboots_label=启用火焰靴?
flameboots_tooltip=当子弹未击中。
@ -103,17 +103,17 @@ allocation_label=选择要自动分配的技能。
allocation_tooltip=这将自动将所有可用的点分配给给定的节点。
[spells]
acid_stream=Bitter Spew
railgun_beam=Shoop Da Whoop!!
raw_fish=Conjure Raw-fish
comfylatron=Suicidal Comfylatron
distractor=Distractor Capsule
warp=Warp Gate
acid_stream=沙虫口水
railgun_beam=轨道炮
raw_fish=生成鱼
comfylatron=自爆机器人
distractor=防御无人机
warp=回城
[allocations]
deactivated=Deactivated
str=Strength
mag=Magicka
dex=Dexterity
vit=Vitality
deactivated=不自动分配
str=力量
mag=魔法
dex=敏捷
vit=活力

314
maps/amap/basic_markets.lua Normal file
View File

@ -0,0 +1,314 @@
local Public = {}
local market = {}
local random = math.random
local floor = math.floor
local blacklist = {
-- ['cargo-wagon'] = true,
-- ['locomotive'] = true,
-- ['artillery-wagon'] = true,
-- ['artillery-turret'] = true,
-- ['fluid-wagon'] = true,
-- ['land-mine'] = true,
['car'] = true,
['tank'] = true,
['spidertron'] = true
}
market.weapons = {
['pistol'] = {value = 10, rarity = 1},
['submachine-gun'] = {value = 50, rarity = 2},
['shotgun'] = {value = 40, rarity = 2},
['combat-shotgun'] = {value = 400, rarity = 5},
['rocket-launcher'] = {value = 500, rarity = 6},
['flamethrower-turret'] = {value = 2000, rarity = 5},
['land-mine'] = {value = 16, rarity = 4}
}
market.ammo = {
['firearm-magazine'] = {value = 3, rarity = 1},
['piercing-rounds-magazine'] = {value = 6, rarity = 4},
['uranium-rounds-magazine'] = {value = 20, rarity = 8},
['shotgun-shell'] = {value = 3, rarity = 1},
['piercing-shotgun-shell'] = {value = 8, rarity = 5},
['cannon-shell'] = {value = 8, rarity = 4},
['explosive-cannon-shell'] = {value = 12, rarity = 5},
['uranium-cannon-shell'] = {value = 16, rarity = 7},
['explosive-uranium-cannon-shell'] = {value = 20, rarity = 8},
['artillery-shell'] = {value = 64, rarity = 7},
['rocket'] = {value = 45, rarity = 7},
['explosive-rocket'] = {value = 50, rarity = 7},
['atomic-bomb'] = {value = 11000, rarity = 10},
['flamethrower-ammo'] = {value = 20, rarity = 6},
['explosives'] = {value = 3, rarity = 1}
}
market.caspules = {
['grenade'] = {value = 16, rarity = 2},
['cluster-grenade'] = {value = 64, rarity = 5},
['poison-capsule'] = {value = 32, rarity = 6},
['slowdown-capsule'] = {value = 8, rarity = 1},
['defender-capsule'] = {value = 8, rarity = 1},
['distractor-capsule'] = {value = 40, rarity = 3},
['destroyer-capsule'] = {value = 80, rarity = 5},
['discharge-defense-remote'] = {value = 300, rarity = 8},
['artillery-targeting-remote'] = {value = 32, rarity = 7},
['raw-fish'] = {value = 10, rarity = 1}
}
market.armor = {
['light-armor'] = {value = 25, rarity = 1},
['heavy-armor'] = {value = 250, rarity = 4},
['modular-armor'] = {value = 750, rarity = 5},
['power-armor'] = {value = 2500, rarity = 6},
['power-armor-mk2'] = {value = 20000, rarity = 10}
}
market.equipment = {
['solar-panel-equipment'] = {value = 240, rarity = 3},
['fusion-reactor-equipment'] = {value = 9000, rarity = 7},
['energy-shield-equipment'] = {value = 400, rarity = 6},
['energy-shield-mk2-equipment'] = {value = 4000, rarity = 8},
['battery-equipment'] = {value = 160, rarity = 2},
['battery-mk2-equipment'] = {value = 2000, rarity = 8},
['personal-laser-defense-equipment'] = {value = 2500, rarity = 7},
['discharge-defense-equipment'] = {value = 5000, rarity = 7},
['belt-immunity-equipment'] = {value = 200, rarity = 1},
['exoskeleton-equipment'] = {value = 800, rarity = 3},
['personal-roboport-equipment'] = {value = 500, rarity = 3},
['personal-roboport-mk2-equipment'] = {value = 5000, rarity = 8},
['night-vision-equipment'] = {value = 250, rarity = 1}
}
market.defense = {
['stone-wall'] = {value = 4, rarity = 1},
['gate'] = {value = 8, rarity = 1},
['repair-pack'] = {value = 8, rarity = 1},
['gun-turret'] = {value = 64, rarity = 1},
['laser-turret'] = {value = 1024, rarity = 6},
['flamethrower-turret'] = {value = 2048, rarity = 6},
['artillery-turret'] = {value = 8192, rarity = 8},
['rocket-silo'] = {value = 64000, rarity = 10}
}
market.logistic = {
['wooden-chest'] = {value = 3, rarity = 1},
['iron-chest'] = {value = 10, rarity = 2},
['steel-chest'] = {value = 24, rarity = 3},
['storage-tank'] = {value = 32, rarity = 4},
['transport-belt'] = {value = 4, rarity = 1},
['fast-transport-belt'] = {value = 8, rarity = 4},
['express-transport-belt'] = {value = 24, rarity = 7},
['underground-belt'] = {value = 8, rarity = 1},
['fast-underground-belt'] = {value = 32, rarity = 4},
['express-underground-belt'] = {value = 64, rarity = 7},
['splitter'] = {value = 16, rarity = 1},
['fast-splitter'] = {value = 48, rarity = 4},
['express-splitter'] = {value = 128, rarity = 7},
['loader'] = {value = 256, rarity = 2},
['fast-loader'] = {value = 512, rarity = 5},
['express-loader'] = {value = 768, rarity = 8},
['burner-inserter'] = {value = 4, rarity = 1},
['inserter'] = {value = 8, rarity = 1},
['long-handed-inserter'] = {value = 12, rarity = 2},
['fast-inserter'] = {value = 16, rarity = 4},
['filter-inserter'] = {value = 24, rarity = 5},
['stack-inserter'] = {value = 96, rarity = 6},
['stack-filter-inserter'] = {value = 128, rarity = 7},
['small-electric-pole'] = {value = 2, rarity = 1},
['medium-electric-pole'] = {value = 12, rarity = 4},
['big-electric-pole'] = {value = 24, rarity = 5},
['substation'] = {value = 96, rarity = 8},
['pipe'] = {value = 2, rarity = 1},
['pipe-to-ground'] = {value = 8, rarity = 1},
['pump'] = {value = 16, rarity = 4},
['logistic-robot'] = {value = 28, rarity = 5},
['construction-robot'] = {value = 28, rarity = 3},
['logistic-chest-active-provider'] = {value = 128, rarity = 7},
['logistic-chest-passive-provider'] = {value = 128, rarity = 6},
['logistic-chest-storage'] = {value = 128, rarity = 6},
['logistic-chest-buffer'] = {value = 128, rarity = 7},
['logistic-chest-requester'] = {value = 128, rarity = 7},
['roboport'] = {value = 4096, rarity = 8}
}
market.vehicles = {
['rail'] = {value = 4, rarity = 1},
['train-stop'] = {value = 32, rarity = 3},
['rail-signal'] = {value = 8, rarity = 5},
['rail-chain-signal'] = {value = 8, rarity = 5},
['locomotive'] = {value = 400, rarity = 4},
['cargo-wagon'] = {value = 200, rarity = 4},
['fluid-wagon'] = {value = 300, rarity = 5},
['artillery-wagon'] = {value = 8192, rarity = 8},
['car'] = {value = 80, rarity = 1},
['tank'] = {value = 1800, rarity = 5}
}
market.wire = {
['small-lamp'] = {value = 4, rarity = 1},
['red-wire'] = {value = 4, rarity = 1},
['green-wire'] = {value = 4, rarity = 1},
['arithmetic-combinator'] = {value = 16, rarity = 1},
['decider-combinator'] = {value = 16, rarity = 1},
['constant-combinator'] = {value = 16, rarity = 1},
['power-switch'] = {value = 16, rarity = 1},
['programmable-speaker'] = {value = 24, rarity = 1},
['landfill'] = {value = 5, rarity = 3}
}
local function get_types()
local types = {}
for k, _ in pairs(market) do
types[#types + 1] = k
end
return types
end
local function get_resource_market_sells()
local sells = {
{price = {{'coin', random(5, 10)}}, offer = {type = 'give-item', item = 'wood', count = 50}},
{price = {{'coin', random(5, 10)}}, offer = {type = 'give-item', item = 'iron-ore', count = 50}},
{price = {{'coin', random(5, 10)}}, offer = {type = 'give-item', item = 'copper-ore', count = 50}},
{price = {{'coin', random(5, 10)}}, offer = {type = 'give-item', item = 'stone', count = 50}},
{price = {{'coin', random(5, 10)}}, offer = {type = 'give-item', item = 'coal', count = 50}},
{price = {{'coin', random(8, 16)}}, offer = {type = 'give-item', item = 'uranium-ore', count = 50}},
{price = {{'coin', random(2, 4)}}, offer = {type = 'give-item', item = 'crude-oil-barrel', count = 1}}
}
table.shuffle_table(sells)
return sells
end
local function get_resource_market_buys()
local buys = {
{price = {{'wood', random(10, 12)}}, offer = {type = 'give-item', item = 'coin'}},
{price = {{'iron-ore', random(10, 12)}}, offer = {type = 'give-item', item = 'coin'}},
{price = {{'copper-ore', random(10, 12)}}, offer = {type = 'give-item', item = 'coin'}},
{price = {{'stone', random(10, 12)}}, offer = {type = 'give-item', item = 'coin'}},
{price = {{'coal', random(10, 12)}}, offer = {type = 'give-item', item = 'coin'}},
{price = {{'uranium-ore', random(8, 10)}}, offer = {type = 'give-item', item = 'coin'}},
{price = {{'water-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = random(1, 2)}},
{price = {{'lubricant-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = random(3, 6)}},
{price = {{'sulfuric-acid-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = random(4, 8)}},
{price = {{'light-oil-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = random(2, 4)}},
{price = {{'heavy-oil-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = random(2, 4)}},
{price = {{'petroleum-gas-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = random(3, 5)}}
}
table.shuffle_table(buys)
return buys
end
local function get_market_item_list(rarity)
if rarity < 1 then
rarity = 1
end
if rarity > 10 then
rarity = 10
end
local types = get_types()
local list = {}
for i = 1, 9 do
local branch = market[types[i]]
for k, item in pairs(branch) do
--if item.rarity <= rarity and item.rarity + 7 >= rarity then
if item.rarity <= rarity then
local price = random(floor(item.value * 0.75), floor(item.value * 1.25))
if price < 1 then
price = 1
end
if price > 64000 then
price = 64000
end
list[#list + 1] = {price = {{'coin', price}}, offer = {type = 'give-item', item = k}}
end
end
end
if #list == 0 then
return false
end
return list
end
function Public.get_random_item(rarity, sell, buy)
rarity = rarity or 0
local items = get_market_item_list(rarity)
if not items then
return
end
if #items > 0 then
table.shuffle_table(items)
end
local items_return = {}
for i = 1, 25, 1 do
local item = items[i]
if not item then
break
end
if not blacklist[item.offer.item] then
items_return[#items_return + 1] = items[i]
end
end
if sell then
local sells = get_resource_market_sells()
for i = 1, random(1, 25), 1 do
items_return[#items_return + 1] = sells[i]
end
end
if buy then
local buys = get_resource_market_buys()
for i = 1, random(1, 25), 1 do
items_return[#items_return + 1] = buys[i]
end
end
return items_return
end
function Public.mountain_market(surface, position, rarity, buy)
if (rarity <= 1)
then
rarity = 1
end
-- game.print(rarity)
local types = get_types()
table.shuffle_table(types)
local items = get_market_item_list(rarity)
if not items then
return
end
if #items > 0 then
table.shuffle_table(items)
end
local mrk = surface.create_entity({name = 'market', position = position, force = 'neutral'})
mrk.destructible = false
for i = 1, random(5, 10), 1 do
local item = items[i]
if not item then
break
end
if not blacklist[item.offer.item] then
mrk.add_market_item(items[i])
end
end
local sells = get_resource_market_sells()
for i = 1, random(1, 3), 1 do
mrk.add_market_item(sells[i])
end
if buy then
local buys = get_resource_market_buys()
for i = 1, random(1, 3), 1 do
mrk.add_market_item(buys[i])
end
end
return mrk
end
return Public

200
maps/amap/biter_pets.lua Normal file
View File

@ -0,0 +1,200 @@
local WPT = require 'maps.amap.table'
local nom_msg = {'munch', 'munch', 'yum'}
local Public = {}
local random = math.random
local floor = math.floor
local function feed_floaty_text(unit)
unit.surface.create_entity(
{
name = 'flying-text',
position = unit.position,
text = nom_msg[random(1, #nom_msg)],
color = {random(50, 100), 0, 255}
}
)
end
local function floaty_hearts(entity, c)
local position = {x = entity.position.x - 0.75, y = entity.position.y - 1}
local b = 1.35
for _ = 1, c, 1 do
local p = {
(position.x + 0.4) + (b * -1 + random(0, b * 20) * 0.1),
position.y + (b * -1 + random(0, b * 20) * 0.1)
}
entity.surface.create_entity({name = 'flying-text', position = p, text = '', color = {random(150, 255), 0, 255}})
end
end
local function tame_unit_effects(player, entity)
floaty_hearts(entity, 7)
rendering.draw_text {
text = '~' .. player.name .. "'s pet~",
surface = player.surface,
target = entity,
target_offset = {0, -2.6},
color = {
r = player.color.r * 0.6 + 0.25,
g = player.color.g * 0.6 + 0.25,
b = player.color.b * 0.6 + 0.25,
a = 1
},
scale = 1.05,
font = 'default-large-semibold',
alignment = 'center',
scale_with_zoom = false
}
end
local function find_unit(player, entity)
local units =
player.surface.find_entities_filtered(
{
type = 'unit',
area = {{entity.position.x - 1, entity.position.y - 1}, {entity.position.x + 1, entity.position.y + 1}},
limit = 1
}
)
return units[1]
end
local function feed_pet(unit)
if unit.prototype.max_health == unit.health then
return
end
unit.health = unit.health + 8 + floor(unit.prototype.max_health * 0.05)
feed_floaty_text(unit)
floaty_hearts(unit, random(1, 2))
return true
end
local function is_valid_player(player, unit)
if not player.character then
return
end
if not player.character.valid then
return
end
if player.surface.index ~= unit.surface.index then
return
end
return true
end
function Public.biter_pets_tame_unit(player, unit, forced)
local biter_pets = WPT.get('biter_pets')
if biter_pets[player.index] then
return false
end
if not forced then
if random(1, floor(unit.prototype.max_health * 0.01) + 1) ~= 1 then
feed_floaty_text(unit)
return true
end
end
if unit.force.index == player.force.index then
return false
end
unit.ai_settings.allow_destroy_when_commands_fail = false
unit.ai_settings.allow_try_return_to_spawner = false
unit.force = player.force
unit.set_command({type = defines.command.wander, distraction = defines.distraction.by_enemy})
biter_pets[player.index] = {last_command = 0, entity = unit}
tame_unit_effects(player, unit)
return true
end
function Public.tame_unit_for_closest_player(unit)
local valid_players = {}
for _, player in pairs(game.connected_players) do
if is_valid_player(player, unit) then
table.insert(valid_players, player)
end
end
local nearest_player = valid_players[1]
if not nearest_player then
return
end
Public.biter_pets_tame_unit(nearest_player, unit, true)
end
local function command_unit(entity, player)
if entity.surface ~= player.surface then
return
end
local square_distance = (player.position.x - entity.position.x) ^ 2 + (player.position.y - entity.position.y) ^ 2
--Pet will follow, if the player is between a distance of 8 to 160 tiles away from it.
if square_distance < 64 or square_distance > 25600 then
entity.set_command({type = defines.command.wander, distraction = defines.distraction.by_enemy})
else
entity.set_command(
{
type = defines.command.go_to_location,
destination_entity = player.character,
radius = 4,
distraction = defines.distraction.by_damage
}
)
end
end
local function on_player_changed_position(event)
local biter_pets = WPT.get('biter_pets')
if random(1, 100) ~= 1 then
return
end
local player = game.players[event.player_index]
if not biter_pets[player.index] then
return
end
if not biter_pets[player.index].entity then
biter_pets[player.index] = nil
return
end
if not biter_pets[player.index].entity.valid then
biter_pets[player.index] = nil
return
end
if not player.character then
return
end
if biter_pets[player.index].last_command + 600 > game.tick then
return
end
biter_pets[player.index].last_command = game.tick
command_unit(biter_pets[player.index].entity, player)
end
local function on_player_dropped_item(event)
local player = game.players[event.player_index]
if event.entity.stack.name ~= 'raw-fish' then
return
end
local unit = find_unit(player, event.entity)
if not unit then
return
end
if Public.biter_pets_tame_unit(player, unit, false) then
event.entity.destroy()
return
end
if unit.force.index == player.force.index then
feed_pet(unit)
end
end
local event = require 'utils.event'
event.add(defines.events.on_player_dropped_item, on_player_dropped_item)
event.add(defines.events.on_player_changed_position, on_player_changed_position)
return Public

View File

@ -0,0 +1,133 @@
local Event = require 'utils.event'
local RPG_Settings = require 'modules.rpg.table'
local insert = table.insert
local floor = math.floor
local random = math.random
local coin_yield = {
['behemoth-biter'] = 5,
['behemoth-spitter'] = 5,
['behemoth-worm-turret'] = 20,
['big-biter'] = 3,
['big-spitter'] = 3,
['big-worm-turret'] = 16,
['biter-spawner'] = 32,
['medium-biter'] = 2,
['medium-spitter'] = 2,
['medium-worm-turret'] = 12,
['small-biter'] = 1,
['small-spitter'] = 1,
['small-worm-turret'] = 8,
['spitter-spawner'] = 32
}
local entities_that_earn_coins = {
['artillery-turret'] = true,
['gun-turret'] = true,
['laser-turret'] = true,
['flamethrower-turret'] = true
}
--extra coins for "boss" biters from biter_health_booster.lua
local function get_coin_count(entity)
local coin_count = coin_yield[entity.name]
if not coin_count then
return
end
if not global.biter_health_boost_units then
return coin_count
end
local unit_number = entity.unit_number
if not unit_number then
return coin_count
end
if not global.biter_health_boost_units[unit_number] then
return coin_count
end
if not global.biter_health_boost_units[unit_number][3] then
return coin_count
end
local m = 1 / global.biter_health_boost_units[unit_number][2]
coin_count = floor(coin_count * m)
if coin_count < 1 then
return 1
end
return coin_count
end
local function on_entity_died(event)
local entity = event.entity
if not entity.valid then
return
end
if entity.force.index ~= 2 then
return
end
local cause = event.cause
local coin_count = get_coin_count(entity)
if not coin_count then
return
end
local players_to_reward = {}
local p
local reward_has_been_given = false
if cause then
if cause.valid then
if (cause and cause.name == 'character' and cause.player) then
p = cause.player
end
if cause.name == 'character' then
insert(players_to_reward, cause)
reward_has_been_given = true
end
if cause.type == 'car' then
local player = cause.get_driver()
local passenger = cause.get_passenger()
if player then
insert(players_to_reward, player.player)
end
if passenger then
insert(players_to_reward, passenger.player)
end
reward_has_been_given = true
end
if cause.type == 'locomotive' then
local train_passengers = cause.train.passengers
if train_passengers then
for _, passenger in pairs(train_passengers) do
insert(players_to_reward, passenger)
end
reward_has_been_given = true
end
end
for _, player in pairs(players_to_reward) do
local forest_zone
if p then
forest_zone = RPG_Settings.get_value_from_player(p.index, 'forest_zone')
end
if forest_zone then
if random(1, 12) == 1 then
player.insert({name = 'coin', count = coin_count})
end
else
player.insert({name = 'coin', count = coin_count})
end
end
end
if entities_that_earn_coins[cause.name] then
event.entity.surface.spill_item_stack(cause.position, {name = 'coin', count = coin_count}, true)
reward_has_been_given = true
end
end
if reward_has_been_given == false then
event.entity.surface.spill_item_stack(event.entity.position, {name = 'coin', count = coin_count}, true)
end
end
Event.add(defines.events.on_entity_died, on_entity_died)

66
maps/amap/burden.lua Normal file
View File

@ -0,0 +1,66 @@
local Event = require 'utils.event'
local Modifier = require 'player_modifiers'
local Color = require 'utils.color_presets'
local function validate_player(player)
if not player then
return false
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.players[player.name] then
return false
end
return true
end
local function compute_fullness(player)
local inv = player.get_inventory(defines.inventory.character_main)
local max_stacks = #inv
local num_stacks = 0
local contents = inv.get_contents()
for item, count in pairs(contents) do
local stack_size = 1
if game.item_prototypes[item].stackable then
stack_size = game.item_prototypes[item].stack_size
end
num_stacks = num_stacks + count / stack_size
end
return num_stacks / max_stacks
end
local function check_burden(event)
local player_modifiers = Modifier.get_table()
local player = game.players[event.player_index]
if not validate_player(player) then
return
end
local fullness = compute_fullness(player)
-- player_modifiers[player.index].character_running_speed_modifier['randomness'] = 0.3 - fullness
--player_modifiers[player.index].character_mining_speed_modifier['randomess'] = 0.3 - fullness
-- Modifier.update_player_modifiers(player)
if fullness >= 0.9 and fullness <= 0.901 then
player.print('Maybe you should drop some of that inventory to lessen the burden.', Color.red)
end
end
local function on_init(event)
script.on_event(defines.events.on_player_main_inventory_changed, check_burden)
end
local function on_load(event)
script.on_event(defines.events.on_player_main_inventory_changed, check_burden)
end
Event.on_init(on_init)
Event.on_load(on_load)

View File

@ -0,0 +1,256 @@
local Event = require 'utils.event'
local Global = require 'utils.global'
local BiterRolls = require 'modules.wave_defense.biter_rolls'
local BiterHealthBooster = require 'modules.biter_health_booster'
local WD = require 'modules.wave_defense.table'
local WPT = require 'maps.amap.table'
local traps = {}
Global.register(
traps,
function(t)
traps = t
end
)
local Public = {}
local floor = math.floor
local random = math.random
local abs = math.abs
local sqrt = math.sqrt
local spawn_amount_rolls = {}
for a = 48, 1, -1 do
spawn_amount_rolls[#spawn_amount_rolls + 1] = floor(a ^ 5)
end
local random_particles = {
'dirt-2-stone-particle-medium',
'dirt-4-dust-particle',
'coal-particle'
}
local s_random_particles = #random_particles
local function create_particles(data)
local surface = data.surface
local position = data.position
local amount = data.amount
if not surface or not surface.valid then
return
end
for i = 1, amount, 1 do
local m = random(6, 12)
local m2 = m * 0.005
surface.create_particle(
{
name = random_particles[random(1, s_random_particles)],
position = position,
frame_speed = 0.1,
vertical_speed = 0.1,
height = 0.1,
movement = {m2 - (random(0, m) * 0.01), m2 - (random(0, m) * 0.01)}
}
)
end
end
local function spawn_biters(data)
local surface = data.surface
if not (surface and surface.valid) then
return
end
local position = data.position
local h = floor(abs(position.y))
local wave_number = WD.get('wave_number')
local max_biters = WPT.get('biters')
if max_biters.amount >= max_biters.limit then
return
end
if not position then
position = surface.find_non_colliding_position('small-biter', position, 10, 1)
if not position then
return
end
end
local function trigger_health()
local m = 0.0015
m = m * 1.05
local boosted_health = 1.25
if wave_number <= 10 then
wave_number = 10
end
boosted_health = boosted_health * (wave_number * 0.02)
local sum = boosted_health * 5
sum = sum + m
if sum >= 100 then
sum = 100
end
return sum
end
BiterRolls.wave_defense_set_unit_raffle(h * 0.20)
local unit
if random(1, 3) == 1 then
unit = surface.create_entity({name = BiterRolls.wave_defense_roll_spitter_name(), position = position})
max_biters.amount = max_biters.amount + 1
else
unit = surface.create_entity({name = BiterRolls.wave_defense_roll_biter_name(), position = position})
max_biters.amount = max_biters.amount + 1
end
if random(1, 32) == 1 then
local sum = trigger_health()
max_biters.amount = max_biters.amount + 1
BiterHealthBooster.add_boss_unit(unit, sum, 0.38)
end
end
local function spawn_worms(data)
local max_biters = WPT.get('biters')
if max_biters.amount >= max_biters.limit then
return
end
local surface = data.surface
if not (surface and surface.valid) then
return
end
local position = data.position
BiterRolls.wave_defense_set_worm_raffle(sqrt(position.x ^ 2 + position.y ^ 2) * 0.20)
surface.create_entity({name = BiterRolls.wave_defense_roll_worm_name(), position = position})
max_biters.amount = max_biters.amount + 1
end
function Public.buried_biter(surface, position, max)
if not (surface and surface.valid) then
return
end
if not position then
return
end
if not position.x then
return
end
if not position.y then
return
end
local amount = 8
local a = 0
max = max or random(4, 6)
local ticks = amount * 30
ticks = ticks + 90
for t = 1, ticks, 1 do
if not traps[game.tick + t] then
traps[game.tick + t] = {}
end
traps[game.tick + t][#traps[game.tick + t] + 1] = {
callback = 'create_particles',
data = {surface = surface, position = {x = position.x, y = position.y}, amount = 4}
}
if t > 90 then
if t % 30 == 29 then
a = a + 1
traps[game.tick + t][#traps[game.tick + t] + 1] = {
callback = 'spawn_biters',
data = {surface = surface, position = {x = position.x, y = position.y}}
}
if a >= max then
break
end
end
end
end
end
function Public.buried_worm(surface, position)
if not (surface and surface.valid) then
return
end
if not position then
return
end
if not position.x then
return
end
if not position.y then
return
end
local amount = 8
local ticks = amount * 30
ticks = ticks + 90
local a = false
for t = 1, ticks, 1 do
if not traps[game.tick + t] then
traps[game.tick + t] = {}
end
traps[game.tick + t][#traps[game.tick + t] + 1] = {
callback = 'create_particles',
data = {surface = surface, position = {x = position.x, y = position.y}, amount = 4}
}
if not a then
traps[game.tick + t][#traps[game.tick + t] + 1] = {
callback = 'spawn_worms',
data = {surface = surface, position = {x = position.x, y = position.y}}
}
a = true
end
end
end
local callbacks = {
['create_particles'] = create_particles,
['spawn_biters'] = spawn_biters,
['spawn_worms'] = spawn_worms
}
local function on_tick()
local t = game.tick
if not traps[t] then
return
end
for _, token in pairs(traps[t]) do
local callback = token.callback
local data = token.data
local cbl = callbacks[callback]
if callbacks[callback] then
cbl(data)
end
end
traps[t] = nil
end
function Public.reset()
for k, _ in pairs(traps) do
traps[k] = nil
end
end
Event.add(defines.events.on_tick, on_tick)
return Public

297
maps/amap/caves.lua Normal file
View File

@ -0,0 +1,297 @@
--[[
Exchange Strings
>>>eNp1UT1oFEEUfi/nkcsJonBNwMQrUtjsES/aHOFmTCMp1M5+b
29OB/Z2ztldSLRwixQWQpo0pkmKNCZgJ2gXsVHQIGpjd5LGwiJBE
AvhnNnd2VvX5IN5fPO9/xmAC3AbYuxTgKhdOeMI201vRMmk6ojBg
ElLSJaXpxwZdpkluAqO6N7uLtGeKvNYf9Xq2D7TskqI5QqXwitWK
PuB8P5VAsmYnyRGba2eDaXt8bCf5EZZJODOwZ3X0dos6DN6BPXRS
B/Fhso/hBQqA5WWonTZEV4ghWv5LAi4d7dlhyutnmT3Q+Y5q61+6
AZ84HImKwuN+RgzxYy+4H4QStbqcNufsuYbzWs6zjo17sTyVxoLM
cqOy3s9gPp1dZb01oj4sPb8xrcHGwSTqRs0JUepst8xyrIht+ipr
jlDrubqJN1/5kjSNFAt0qgKHZPEuaadiMf3Dh+/+P2ljX+eHX+62
aEEj4yCOKkScCIzm081XplVwNQcktT1leCH9xo/CJZ1Rk2b7SfKR
M0JwPPnzLV+EcxobVOmRrEX45fZ5NCQz6S4h3qIRV18Vpu32sQNs
8kwoXSdIr1kvNPjEJXfhPwM3fGG70zbN7n+hUH+/4j8HgVljp7wD
VXdsJuZ76VsGvWeHyfNjW7REoyhvvvAetn9CzJb1cQ=<<<
]]
--local List = require 'maps.chronosphere.production_list'
--local Factories = require 'maps.chronosphere.production'
local random = math.random
local Alert = require 'utils.alert'
require "player_modifiers"
require "modules.rocks_broken_paint_tiles"
require "modules.rocks_heal_over_time"
require "modules.rocks_yield_ore_veins"
local WPT = require 'maps.amap.table'
require "modules.no_deconstruction_of_neutral_entities"
local MT = require "maps.amap.basic_markets"
local RPGtable = require 'modules.rpg.table'
local Loot = require "maps.amap.loot"
local get_noise = require "utils.get_noise"
local Player_modifiers = require "player_modifiers"
local math_random = math.random
local math_floor = math.floor
local math_abs = math.abs
local Public = {}
local BiterRolls = require 'modules.wave_defense.biter_rolls'
local rock_raffle = {"sand-rock-big","sand-rock-big", "rock-big","rock-big","rock-big","rock-big","rock-big","rock-big","rock-big","rock-huge"}
local size_of_rock_raffle = #rock_raffle
local Pets = require 'maps.amap.biter_pets'
local WD = require 'modules.wave_defense.table'
local function place_entity(surface, position)
if math_random(1, 3) ~= 1 then
surface.create_entity({name = rock_raffle[math_random(1, size_of_rock_raffle)], position = position, force = "neutral"})
end
end
local function is_scrap_area(noise)
if noise > 0.67 then return end
if noise < -0.67 then return end
if noise > 0.33 then return true end
if noise < -0.33 then return true end
end
local function hidden_treasure(player, entity)
local rpg = RPGtable.get('rpg_t')
local magic = rpg[player.index].magicka
local msg = 'look,you find a treasure'
Alert.alert_player(player, 5, msg)
Loot.add_rare(entity.surface, entity.position, 'wooden-chest', magic)
end
local function register_spawner(spawner)
local nests = WD.get('nests')
if spawner.valid then
nests[#nests + 1] = spawner
end
end
local function move_away_things(surface, area)
for _, e in pairs(surface.find_entities_filtered({type = {"unit-spawner", "unit", "tree"}, area = area})) do
local position = surface.find_non_colliding_position(e.name, e.position, 128, 4)
if position then
local entity = surface.create_entity({name = e.name, position = position, force = "enemy"})
e.destroy()
-- if (entity.name == "biter-spawner" or entity.name == "spitter-spawner") and entity.force.name == "enemy" then
-- register_spawner(entity)
-- end
end
end
end
local vectors = {{0,0}, {1,0}, {-1,0}, {0,1}, {0,-1}}
local function hidden_biter_pet(player, entity)
local pos = entity.position
BiterRolls.wave_defense_set_unit_raffle(math.sqrt(pos.x ^ 2 + pos.y ^ 2) * 0.25)
local unit
if random(1, 3) == 1 then
unit = entity.surface.create_entity({name = BiterRolls.wave_defense_roll_spitter_name(), position = pos})
else
unit = entity.surface.create_entity({name = BiterRolls.wave_defense_roll_biter_name(), position = pos})
end
Pets.biter_pets_tame_unit(game.players[player.index], unit, true)
end
local function hidden_biter(player, entity)
local pos = entity.position
BiterRolls.wave_defense_set_worm_raffle(math.sqrt(pos.x ^ 2 + pos.y ^ 2) * 0.19)
BiterRolls.wave_defense_set_unit_raffle(math.sqrt(pos.x ^ 2 + pos.y ^ 2) * 0.25)
local roll = math.random(1, 3)
local unit
if roll == 1 then
unit = entity.surface.create_entity({name = BiterRolls.wave_defense_roll_spitter_name(), position = pos})
elseif roll == 2 then
unit = entity.surface.create_entity({name = BiterRolls.wave_defense_roll_biter_name(), position = pos})
else
unit = entity.surface.create_entity({name = BiterRolls.wave_defense_roll_worm_name(), position = pos})
end
end
local function on_player_mined_entity(event)
local entity = event.entity
if not entity.valid then return end
if entity.type ~= "simple-entity" then return end
local surface = entity.surface
for _, v in pairs(vectors) do
local position = {entity.position.x + v[1], entity.position.y + v[2]}
if not surface.get_tile(position).collides_with("resource-layer") then
surface.set_tiles({{name = "landfill", position = position}}, true)
end
end
if event.player_index then game.players[event.player_index].insert({name = "coin", count = 1}) end
local player = game.players[event.player_index]
--修复挖矿石路
local rpg = RPGtable.get('rpg_t')
local rpg_char = rpg[player.index]
if rpg_char.stone_path then
entity.surface.set_tiles({{name = 'stone-path', position = entity.position}}, true)
end
--挖出汽车
if random(1,1024) < 2 then
local position = {entity.position.x , entity.position.y }
--local player = game.players[event.player_index]
surface.create_entity({name = 'car', position = position, force = 'player'})
Public.unstuck_player(player.index)
local msg = ('you find a car!')
Alert.alert_player(player, 15, msg)
end
--挖出虫巢
if random(1,200) < 2 then
local position = {entity.position.x , entity.position.y }
local player = game.players[event.player_index]
surface.create_entity({name = 'biter-spawner', position = position, force = 'enemy'})
Public.unstuck_player(player.index)
end
--挖出宝藏
if random(1,150) < 2 then
local player = game.players[event.player_index]
hidden_treasure(player,entity)
end
--挖出宠物
if random(1,170) < 3 then
local player = game.players[event.player_index]
hidden_biter_pet(player,entity)
end
--来挖个虫子
if random(1,100) < 3 then
local player = game.players[event.player_index]
hidden_biter(player,entity)
end
end
--图块生成时
local function on_chunk_generated(event)
local surface = event.surface
local this = WPT.get()
if not(surface.index == game.surfaces[this.active_surface_index].index) then return end
local seed = surface.map_gen_settings.seed
local left_top_x = event.area.left_top.x
local left_top_y = event.area.left_top.y
local set_tiles = surface.set_tiles
local get_tile = surface.get_tile
local position
local noise
local tem_pos
for x = 0, 31, 1 do
for y = 0, 31, 1 do
position = {x = left_top_x + x, y = left_top_y + y}
local q =position.x^2
local w =position.y^2
local maxs =math.sqrt(q + w)
if maxs <= 120 then
if maxs > 117 then
if surface.can_place_entity{name = "stone-wall", position = {x=position.x,y=position.y}, force=game.forces.player} then
surface.create_entity{name = "stone-wall", position = {x=position.x,y=position.y}, force=game.forces.player}
end
end
local h = math_abs(position.x)
local k = math_abs(position.y)
if maxs < 115 and maxs > 113 then
if (1== h%7) or (1==k%7) then
if surface.can_place_entity{name = "gun-turret", position = position, force=game.forces.player} then
local e = surface.create_entity{name = "gun-turret", position = position, force=game.forces.player}
e.insert{name='firearm-magazine', count = 30}
end
end
end
else
if not get_tile(position).collides_with("resource-layer") then
noise = get_noise("scrapyard", position, seed)
if is_scrap_area(noise) then
set_tiles({{name = "dirt-" .. math_floor(math_abs(noise) * 12) % 4 + 3, position = position}}, true)
if maxs >= 3000 then
local roll = math_random(1,1024)
if roll <= 2 then
BiterRolls.wave_defense_set_worm_raffle(math.sqrt(position.x ^ 2 + position.y ^ 2) * 0.19)
surface.create_entity({name = BiterRolls.wave_defense_roll_worm_name(), position = position, force = 'enemy'})
end
end
if x+y > 33 and x+y < 40 then
local b = math_random(1,200)
--宝藏
if b < 3 then
local chest = 'iron-chest'
Loot.add(surface, position, chest)
end
--中立建筑
--在我上面添加代码
end
--商店代码
if y == 1 then
if x == 1 then
local a = math_random(1,8)
if a == 1 then
local q =math_abs(position.x)/80
local w =math_abs(position.y)/80
local maxs =math.floor(q+w)
-- game.print(maxs)
MT.mountain_market(surface,position,maxs)
end
end
end
place_entity(surface, position)
end
end
end
end
end
move_away_things(surface, event.area)
end
function Public.unstuck_player(index)
local player = game.get_player(index)
local surface = player.surface
local position = surface.find_non_colliding_position('character', player.position, 32, 0.5)
if not position then
return
end
player.teleport(position, surface)
end
local function on_init()
global.rocks_yield_ore_maximum_amount = 999
global.rocks_yield_ore_base_amount = 100
global.rocks_yield_ore_distance_modifier = 0.020
end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.add(defines.events.on_chunk_generated, on_chunk_generated)
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)
--Event.add(defines.events.on_entity_died, on_entity_died)
require "maps.amap.rocks_yield_ore"

187
maps/amap/diff.lua Normal file
View File

@ -0,0 +1,187 @@
local Event = require 'utils.event'
local WD = require 'modules.wave_defense.table'
local WPT = require 'maps.amap.table'
local Difficulty = require 'modules.difficulty_vote_by_amount'
local atry_talbe = require "maps.amap.enemy_arty"
local function calc_players()
local players = game.connected_players
local check_afk_players = WPT.get('check_afk_players')
if not check_afk_players then
return #players
end
local total = 0
for i = 1, #players do
local player = players[i]
if player.afk_time < 36000 then
total = total + 1
end
end
if total <= 0 then
total = 1
end
return total
end
local easy = function()
local wave_defense_table = WD.get_table()
local player_count = calc_players()
wave_defense_table.max_active_biters = 768 + player_count * 180
if wave_defense_table.max_active_biters >= 4000 then
wave_defense_table.max_active_biters = 4000
end
local wave_number = WD.get('wave_number')
if wave_number >= 1500 then
wave_number = 1500
end
-- threat gain / wave
local max_threat = 1 + player_count * 0.1
if max_threat >= 4 then
max_threat = 4
end
max_threat = max_threat + wave_number * 0.0013
WD.set_biter_health_boost(wave_number * 0.002+1)
wave_defense_table.threat_gain_multiplier = max_threat
wave_defense_table.wave_interval = 4200 - player_count * 30
if wave_defense_table.wave_interval < 1800 or wave_defense_table.threat <= 0 then
wave_defense_table.wave_interval = 1800
end
local mintime = 7500 - player_count * 150
if mintime <= 6000 then
mintime = 6000
end
game.map_settings.enemy_expansion.min_expansion_cooldown = mintime
-- game.map_settings.enemy_expansion.max_expansion_cooldown = 104000
end
local med = function()
local wave_defense_table = WD.get_table()
local player_count = calc_players()
wave_defense_table.max_active_biters = 768 + player_count * 220
if wave_defense_table.max_active_biters >= 4000 then
wave_defense_table.max_active_biters = 4000
end
local wave_number = WD.get('wave_number')
-- threat gain / wave
if wave_number >= 1500 then
wave_number = 1500
end
local max_threat = 1 + player_count * 0.1
if max_threat >= 4 then
max_threat = 4
end
max_threat = max_threat + wave_number * 0.0013
WD.set_biter_health_boost(wave_number * 0.002+1)
wave_defense_table.threat_gain_multiplier = max_threat
wave_defense_table.wave_interval = 4200 - player_count * 45
if wave_defense_table.wave_interval < 1800 or wave_defense_table.threat <= 0 then
wave_defense_table.wave_interval = 1800
end
local mintime = 7500 - player_count * 240
if mintime <= 3600 then
mintime = 3600
end
game.map_settings.enemy_expansion.min_expansion_cooldown = mintime
-- game.map_settings.enemy_expansion.max_expansion_cooldown = 104000
end
local hard = function()
local wave_defense_table = WD.get_table()
local player_count = calc_players()
wave_defense_table.max_active_biters = 768 + player_count * 280
if wave_defense_table.max_active_biters >= 4000 then
wave_defense_table.max_active_biters = 4000
end
local wave_number = WD.get('wave_number')
-- threat gain / wave
if wave_number >= 1500 then
wave_number = 1500
end
local max_threat = 1 + player_count * 0.1
if max_threat >= 4 then
max_threat = 4
end
max_threat = max_threat + wave_number * 0.0013
WD.set_biter_health_boost(wave_number * 0.002+1)
wave_defense_table.threat_gain_multiplier = max_threat
wave_defense_table.wave_interval = 3900 - player_count * 60
if wave_defense_table.wave_interval < 1800 or wave_defense_table.threat <= 0 then
wave_defense_table.wave_interval = 1800
end
local mintime = 7500 - player_count * 300
if mintime <= 3000 then
mintime = 3000
end
game.map_settings.enemy_expansion.min_expansion_cooldown = mintime
-- game.map_settings.enemy_expansion.max_expansion_cooldown = 104000
end
local set_diff = function()
local game_lost = WPT.get('game_lost')
if game_lost then
return
end
local diff= Difficulty.get()
if diff.difficulty_vote_index == 1 then
easy()
end
if diff.difficulty_vote_index == 2 then
med()
end
if diff.difficulty_vote_index == 3 then
hard()
end
--med()
local wave_number = WD.get('wave_number')
local damage_increase = 0
-- local any=wave_number+150
-- local k= math.floor(any/1000)
-- if k <= 1 then
-- k =1
-- end
-- if k >= 5 then
-- k =5
-- end
local k = math.sqrt(diff.difficulty_vote_index)
if k <= 1 then
k =1
end
k=math.floor(k)
damage_increase = wave_number * 0.001*k
game.forces.enemy.set_ammo_damage_modifier("artillery-shell", damage_increase)
game.forces.enemy.set_ammo_damage_modifier("rocket", damage_increase)
game.forces.enemy.set_ammo_damage_modifier("melee", damage_increase)
game.forces.enemy.set_ammo_damage_modifier("biological", damage_increase)
local table = atry_talbe.get()
local radius=math.floor(wave_number*0.15)*k
table.radius=350+radius
local pace=wave_number*0.0002*k+1
if pace >= 2 then
pace = 2
end
table.pace=pace
end
Event.on_nth_tick(600, set_diff)

247
maps/amap/enemy_arty.lua Normal file
View File

@ -0,0 +1,247 @@
local Event = require 'utils.event'
local Global = require 'utils.global'
local Task = require 'utils.task'
local arty_count = {}
local Public = {}
local Token = require 'utils.token'
local WPT = require 'maps.amap.table'
local artillery_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'
}
Global.register(
arty_count,
function(tbl)
arty_count = tbl
end
)
function Public.reset_table()
arty_count.max = 200
arty_count.all = {}
arty_count.count = 0
arty_count.pace = 1
arty_count.radius = 350
arty_count.distance = 1400
arty_count.surface = {}
end
function Public.get(key)
if key then
return arty_count[key]
else
return arty_count
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
local on_init = function()
Public.reset_table()
end
local function add_bullet ()
for k, p in pairs(arty_count.all) do
if arty_count.all[k].valid then
arty_count.all[k].insert{name='artillery-shell', count = '5'}
end
end
end
local function on_chunk_generated(event)
local surface = event.surface
local left_top_x = event.area.left_top.x
local left_top_y = event.area.left_top.y
local position
for x = 0, 31, 1 do
for y = 0, 31, 1 do
position = {x = left_top_x + x, y = left_top_y + y}
local q =position.x*position.x
local w =position.y*position.y
local distance =math.sqrt(q+w)
if distance >= arty_count.distance then
if arty_count.count >= arty_count.max then
return
else
local roll = math.random(1, 2024)
if roll == 1 then
local arty = surface.create_entity{name = "artillery-turret", position = position, force='enemy'}
-- arty.insert{name='artillery-shell', count = '5'}
--local k = #arty_count.all
-- game.print(k)
arty_count.all[arty.unit_number]=arty
-- game.print(arty_count.all[1].name)
arty_count.count = arty_count.count + 1
-- game.print(arty_count.count)
-- game.print(position)
end
end
end
end
end
end
local function on_entity_died(event)
local entity = event.entity
if not entity or not entity.valid then return end
if arty_count.all[entity.unit_number] then
arty_count.all[entity.unit_number] = nil
arty_count.count = arty_count.count - 1
end
-- local force = entity.force
-- local name = entity.name
-- if name == 'artillery-turret' and force.name == 'enemy' then
-- arty_count.all[entity.unit_number] = nil
-- arty_count.count = arty_count.count -1
--
-- if arty_count.count <= 0 then
-- arty_count.count = 0
-- end
end
function on_player_changed_position(event)
local player = game.players[event.player_index]
local surface = player.surface
if not surface.valid then
return
end
local position = player.position
local q =position.x*position.x
local w =position.y*position.y
local distance =math.sqrt(q+w)
--artillery-targeting-remote
game.print("123")
surface.create_entity(
{
name = 'artillery-targeting-remote',
position = position,
force = 'enemy',
-- target = position,
-- speed = 0.001
}
)
game.print("logging")
end
local artillery_target_callback =
Token.register(
function(data)
local position = data.position
local entity = data.entity
if not entity.valid then
return
end
local tx, ty = position.x, position.y
local pos = entity.position
local x, y = pos.x, pos.y
local dx, dy = tx - x, ty - y
local d = dx * dx + dy * dy
-- if d >= 1024 and d <= 441398 then -- 704 in depth~
if entity.name == 'character' then
entity.surface.create_entity {
name = 'artillery-projectile',
position = position,
target = entity,
force = 'enemy',
speed = arty_count.pace
}
elseif entity.name ~= 'character' then
entity.surface.create_entity {
name = 'rocket',
position = position,
target = entity,
force = 'enemy',
speed = arty_count.pace
}
end
end
-- end
)
local function do_artillery_turrets_targets()
--local surface = arty_count.surface
local this = WPT.get()
local surface = game.surfaces[this.active_surface_index]
--选取重炮
local roll_table = {}
for index, arty in pairs(arty_count.all) do
if arty.valid then
roll_table[#roll_table + 1] = arty
else
arty_count.all[index] = nil -- <- if not valid, remove from table
arty_count.count = arty_count.count - 1
end
end
if #roll_table <= 0 then return end
local roll = math.random(1, #roll_table)
local position = roll_table[roll].position
--扫描区域
-- local normal_area = {left_top = {-480, -480}, right_bottom = {480, 480}}
-- game.print(123)
-- normal_area= roll_table[roll].artillery_area
-- game.print(12)
local entities = surface.find_entities_filtered{position = position, radius = arty_count.radius, name = artillery_target_entities, force = game.forces.player}
-- local entities = surface.find_entities_filtered {area = normal_area, name = artillery_target_entities, force = 'player'}
if #entities == 0 then
return
end
--开火
for i = 1, arty_count.count do
local entity = entities[math.random(#entities)]
--game.print(entity.position)
if entity and entity.valid then
local data = {position = position, entity = entity}
Task.set_timeout_in_ticks(i * 60, artillery_target_callback, data)
end
end
end
Event.add(defines.events.on_chunk_generated, on_chunk_generated)
Event.add(defines.events.on_entity_died, on_entity_died)
--Event.add(defines.events.on_player_changed_position, on_player_changed_position)
--Event.on_nth_tick(600, add_bullet)
Event.on_nth_tick(10, do_artillery_turrets_targets)
Event.on_init(on_init)
return Public

1382
maps/amap/entities.lua Normal file

File diff suppressed because it is too large Load Diff

890
maps/amap/functions.lua Normal file
View File

@ -0,0 +1,890 @@
local Token = require 'utils.token'
local Task = require 'utils.task'
local Event = require 'utils.event'
local Global = require 'utils.global'
local Alert = require 'utils.alert'
local WPT = require 'maps.amap.table'
local WD = require 'modules.wave_defense.table'
local math2d = require 'math2d'
local Commands = require 'commands.misc'
local RPG = require 'modules.rpg.table'
local this = {
power_sources = {index = 1},
refill_turrets = {index = 1},
magic_crafters = {index = 1},
magic_fluid_crafters = {index = 1},
art_table = {index = 1},
surface_cleared = false
}
local starting_items = {['pistol'] = 1, ['firearm-magazine'] = 16, ['wood'] = 16}
Global.register(
this,
function(t)
this = t
end
)
local Public = {}
local random = math.random
local floor = math.floor
local remove = table.remove
local sqrt = math.sqrt
local magic_crafters_per_tick = 3
local magic_fluid_crafters_per_tick = 8
local tile_damage = 50
local artillery_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'
}
function Public.get_player_data(player, remove_user_data)
local players = WPT.get('players')
if remove_user_data then
if players[player.index] then
players[player.index] = nil
end
end
if not players[player.index] then
players[player.index] = {}
end
return players[player.index]
end
local get_player_data = Public.get_player_data
local function debug_str(msg)
local debug = WPT.get('debug')
if not debug then
return
end
print('Mtn: ' .. msg)
end
local function show_text(msg, pos, color, surface)
if color == nil then
surface.create_entity({name = 'flying-text', position = pos, text = msg})
else
surface.create_entity({name = 'flying-text', position = pos, text = msg, color = color})
end
end
local function fast_remove(tbl, index)
local count = #tbl
if index > count then
return
elseif index < count then
tbl[index] = tbl[count]
end
tbl[count] = nil
end
local function do_refill_turrets()
local refill_turrets = this.refill_turrets
local index = refill_turrets.index
if index > #refill_turrets then
refill_turrets.index = 1
return
end
local turret_data = refill_turrets[index]
local turret = turret_data.turret
if not turret.valid then
fast_remove(refill_turrets, index)
return
end
refill_turrets.index = index + 1
local data = turret_data.data
if data.liquid then
turret.fluidbox[1] = data
elseif data then
turret.insert(data)
end
end
local function do_turret_energy()
local power_sources = this.power_sources
for index = 1, #power_sources do
local ps_data = power_sources[index]
if not (ps_data and ps_data.valid) then
fast_remove(power_sources, index)
return
end
ps_data.energy = 0xfffff
end
end
local function do_magic_crafters()
local magic_crafters = this.magic_crafters
local limit = #magic_crafters
if limit == 0 then
return
end
local index = magic_crafters.index
for i = 1, magic_crafters_per_tick do
if index > limit then
index = 1
end
local data = magic_crafters[index]
local entity = data.entity
if not entity.valid then
fast_remove(magic_crafters, index)
limit = limit - 1
if limit == 0 then
return
end
else
index = index + 1
local tick = game.tick
local last_tick = data.last_tick
local rate = data.rate
local count = (tick - last_tick) * rate
local fcount = floor(count)
if fcount > 1 then
fcount = 1
end
if fcount > 0 then
entity.get_output_inventory().insert {name = data.item, count = fcount}
data.last_tick = tick - (count - fcount) / rate
end
end
end
magic_crafters.index = index
end
local function do_magic_fluid_crafters()
local magic_fluid_crafters = this.magic_fluid_crafters
local limit = #magic_fluid_crafters
if limit == 0 then
return
end
local index = magic_fluid_crafters.index
for i = 1, magic_fluid_crafters_per_tick do
if index > limit then
index = 1
end
local data = magic_fluid_crafters[index]
local entity = data.entity
if not entity.valid then
fast_remove(magic_fluid_crafters, index)
limit = limit - 1
if limit == 0 then
return
end
else
index = index + 1
local tick = game.tick
local last_tick = data.last_tick
local rate = data.rate
local count = (tick - last_tick) * rate
local fcount = floor(count)
if fcount > 0 then
local fluidbox_index = data.fluidbox_index
local fb = entity.fluidbox
local fb_data = fb[fluidbox_index] or {name = data.item, amount = 0}
fb_data.amount = fb_data.amount + fcount
fb[fluidbox_index] = fb_data
data.last_tick = tick - (count - fcount) / rate
end
end
end
magic_fluid_crafters.index = index
end
local function tick()
do_magic_crafters()
do_magic_fluid_crafters()
end
Public.deactivate_callback =
Token.register(
function(entity)
if entity and entity.valid then
entity.active = false
entity.operable = false
entity.destructible = false
end
end
)
Public.neutral_force =
Token.register(
function(entity)
if entity and entity.valid then
entity.force = 'neutral'
end
end
)
Public.enemy_force =
Token.register(
function(entity)
if entity and entity.valid then
entity.force = 'enemy'
end
end
)
Public.active_not_destructible_callback =
Token.register(
function(entity)
if entity and entity.valid then
entity.active = true
entity.operable = false
entity.destructible = false
end
end
)
Public.disable_minable_callback =
Token.register(
function(entity)
if entity and entity.valid then
entity.minable = false
end
end
)
Public.disable_minable_and_ICW_callback =
Token.register(
function(entity)
if entity and entity.valid then
entity.minable = false
ICW.register_wagon(entity, true)
end
end
)
Public.disable_destructible_callback =
Token.register(
function(entity)
if entity and entity.valid then
entity.destructible = false
entity.minable = false
end
end
)
Public.disable_active_callback =
Token.register(
function(entity)
if entity and entity.valid then
entity.active = false
end
end
)
local disable_active_callback = Public.disable_active_callback
Public.power_source_callback =
Token.register(
function(turret)
local power_sources = this.power_sources
power_sources[#power_sources + 1] = turret
end
)
Public.magic_item_crafting_callback =
Token.register(
function(entity, data)
local callback_data = data.callback_data
if not (entity and entity.valid) then
return
end
entity.minable = false
entity.destructible = false
entity.operable = false
local force = game.forces.player
local tech = callback_data.tech
if tech then
if not force.technologies[tech].researched then
entity.destroy()
return
end
end
local recipe = callback_data.recipe
if recipe then
entity.set_recipe(recipe)
else
local furance_item = callback_data.furance_item
if furance_item then
local inv = entity.get_inventory(defines.inventory.furnace_result)
inv.insert(furance_item)
end
end
local p = entity.position
local x, y = p.x, p.y
local distance = sqrt(x * x + y * y)
local output = callback_data.output
if #output == 0 then
add_magic_crafter_output(entity, output, distance)
else
for i = 1, #output do
local o = output[i]
add_magic_crafter_output(entity, o, distance)
end
end
if not callback_data.keep_active then
Task.set_timeout_in_ticks(2, disable_active_callback, entity) -- causes problems with refineries.
end
end
)
Public.magic_item_crafting_callback_weighted =
Token.register(
function(entity, data)
local callback_data = data.callback_data
if not (entity and entity.valid) then
return
end
entity.minable = false
entity.destructible = false
entity.operable = false
local weights = callback_data.weights
local loot = callback_data.loot
local p = entity.position
local i = random() * weights.total
local index = table.binary_search(weights, i)
if (index < 0) then
index = bit32.bnot(index)
end
local stack = loot[index].stack
if not stack then
return
end
local force = game.forces.player
local tech = stack.tech
if tech then
if force.technologies[tech] then
if not force.technologies[tech].researched then
entity.destroy()
return
end
end
end
local recipe = stack.recipe
if recipe then
entity.set_recipe(recipe)
else
local furance_item = stack.furance_item
if furance_item then
local inv = entity.get_inventory(defines.inventory.furnace_result)
inv.insert(furance_item)
end
end
local x, y = p.x, p.y
local distance = sqrt(x * x + y * y)
local output = stack.output
if #output == 0 then
add_magic_crafter_output(entity, output, distance)
else
for o_i = 1, #output do
local o = output[o_i]
add_magic_crafter_output(entity, o, distance)
end
end
if not callback_data.keep_active then
Task.set_timeout_in_ticks(2, disable_active_callback, entity) -- causes problems with refineries.
end
end
)
function Public.prepare_weighted_loot(loot)
local total = 0
local weights = {}
for i = 1, #loot do
local v = loot[i]
total = total + v.weight
weights[#weights + 1] = total
end
weights.total = total
return weights
end
function Public.do_random_loot(entity, weights, loot)
if not entity.valid then
return
end
entity.operable = false
--entity.destructible = false
local i = random() * weights.total
local index = table.binary_search(weights, i)
if (index < 0) then
index = bit32.bnot(index)
end
local stack = loot[index].stack
if not stack then
return
end
local df = stack.distance_factor
local count
if df then
local p = entity.position
local x, y = p.x, p.y
local d = sqrt(x * x + y * y)
count = stack.count + d * df
else
count = stack.count
end
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 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
local later = {}
for i = 1, #offline_players, 1 do
if offline_players[i] and game.players[offline_players[i].index] and game.players[offline_players[i].index].connected then
offline_players[i] = nil
else
if offline_players[i] and game.players[offline_players[i].index] and offline_players[i].tick < game.tick - 54000 then
local name = offline_players[i].name
player_inv[1] = game.players[offline_players[i].index].get_inventory(defines.inventory.character_main)
player_inv[2] = game.players[offline_players[i].index].get_inventory(defines.inventory.character_armor)
player_inv[3] = game.players[offline_players[i].index].get_inventory(defines.inventory.character_guns)
player_inv[4] = game.players[offline_players[i].index].get_inventory(defines.inventory.character_ammo)
player_inv[5] = game.players[offline_players[i].index].get_inventory(defines.inventory.character_trash)
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
else
later[#later + 1] = offline_players[i]
end
end
end
for k, _ in pairs(offline_players) do
offline_players[k] = nil
end
if #later > 0 then
for i = 1, #later, 1 do
offline_players[#offline_players + 1] = later[i]
end
end
end
end
local function calc_players()
local players = game.connected_players
local check_afk_players = WPT.get('check_afk_players')
if not check_afk_players then
return #players
end
local total = 0
for i = 1, #players do
local player = players[i]
if player.afk_time < 36000 then
total = total + 1
end
end
if total <= 0 then
total = 1
end
return total
end
function Public.on_player_joined_game(event)
local active_surface_index = WPT.get('active_surface_index')
local player = game.players[event.player_index]
local surface = game.surfaces[active_surface_index]
local reward = require 'maps.amap.main'.reward
local player_data = get_player_data(player)
if not player_data.first_join then
for item, amount in pairs(starting_items) do
player.insert({name = item, count = amount})
end
local rpg_t = RPG.get('rpg_t')
local wave_number = WD.get('wave_number')
local this = WPT.get()
for i=0,this.science do
local point = math.floor(math.random(1,5))
local money = math.floor(math.random(1,100))
rpg_t[player.index].points_to_distribute = rpg_t[player.index].points_to_distribute+point
player.insert{name='coin', count = money}
player.print({'amap.science',point,money}, {r = 0.22, g = 0.88, b = 0.22})
end
rpg_t[player.index].xp = rpg_t[player.index].xp + wave_number*10
player_data.first_join = true
player.print({'amap.joingame'})
end
if player.surface.index ~= active_surface_index then
--player.teleport(surface.find_non_colliding_position("character", game.forces.player.get_spawn_position(surface), 20, 1, false) or {x=0,y=0}, surface)
player.teleport(surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 20, 1, false) or {x=0,y=0}, surface)
else
local p = {x = player.position.x, y = player.position.y}
local get_tile = surface.get_tile(p)
if get_tile.valid and get_tile.name == 'out-of-map' then
player.teleport(surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 20, 1, false) or {x=0,y=0}, surface)
--player.teleport({x=0,y=0}, surface)
end
end
end
function Public.is_creativity_mode_on()
local creative_enabled = Commands.get('creative_enabled')
if creative_enabled then
WD.set('next_wave', 1000)
Collapse.start_now(true)
Public.set_difficulty()
end
end
local function on_player_mined_entity(event)
local name = event.entity.name
local entity = event.entity
local this = WPT.get()
if name == 'flamethrower-turret' then
this.flame = this.flame - 1
if this.flame <= 0 then
this.flame = 0
end
end
end
function Public.disable_creative()
local creative_enabled = Commands.get('creative_enabled')
if creative_enabled then
Commands.set('creative_enabled', false)
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
local on_player_or_robot_built_entity = function(event)
--change_pos 改变位置
local name = event.created_entity.name
local entity = event.created_entity
local this = WPT.get()
if name == 'flamethrower-turret' then
if this.flame >= 15 then
game.print({'amap.too_many'})
entity.destroy()
else
this.flame = this.flame + 1
game.print({'amap.ok_many',this.flame})
end
end
if name == "stone-wall" then
local this = WPT.get()
if not this.change then
local wave_defense_table = WD.get_table()
local dx = entity.position.x-this.pos.x
local dy = entity.position.y-this.pos.y
if dx < 0 then
dx=-dx
end
if dy < 0 then
dy=-dy
end
local d = dx+dy
if d < 100 then
this.change = true
end
end
--game.print(dx)
--game.print(dy)
--game.print('差值为')
--game.print(d)
--game.print('出生地为')
--game.print(this.pos)
end
end
function Public.on_player_respawned(event)
local player = game.get_player(event.player_index)
if not (player and player.valid) then
return
end
local player_data = get_player_data(player)
if player_data.died then
player_data.died = nil
end
end
function Public.on_player_died(event)
local player = game.get_player(event.player_index)
if not (player and player.valid) then
return
end
local player_data = get_player_data(player)
player_data.died = true
end
function Public.on_player_changed_position(event)
local active_surface_index = WPT.get('active_surface_index')
if not active_surface_index then
return
end
local player = game.players[event.player_index]
local map_name = 'amap'
if string.sub(player.surface.name, 0, #map_name) ~= map_name then
return
end
local position = player.position
local surface = game.surfaces[active_surface_index]
local p = {x = player.position.x, y = player.position.y}
local get_tile = surface.get_tile(p)
local config_tile = WPT.get('void_or_tile')
if config_tile == 'lab-dark-2' then
if get_tile.valid and get_tile.name == 'lab-dark-2' then
if random(1, 2) == 1 then
if random(1, 2) == 1 then
show_text('This path is not for players!', p, {r = 0.98, g = 0.66, b = 0.22}, surface)
end
player.surface.create_entity({name = 'fire-flame', position = player.position})
player.character.health = player.character.health - tile_damage
if player.character.health == 0 then
player.character.die()
local message = ({'main.death_message_' .. random(1, 7), player.name})
game.print(message, {r = 0.98, g = 0.66, b = 0.22})
end
end
end
end
if position.y >= 74 then
player.teleport({position.x, position.y - 1}, surface)
player.print(({'main.forcefield'}), {r = 0.98, g = 0.66, b = 0.22})
if player.character then
player.character.health = player.character.health - 5
player.character.surface.create_entity({name = 'water-splash', position = position})
if player.character.health <= 0 then
player.character.die('enemy')
end
end
end
end
local disable_recipes = function()
local force = game.forces.player
force.recipes['car'].enabled = false
force.recipes['tank'].enabled = false
force.recipes['pistol'].enabled = false
force.recipes['land-mine'].enabled = false
force.recipes['spidertron-remote'].enabled = false
-- force.recipes['flamethrower-turret'].enabled = false
end
function Public.disable_tech()
game.forces.player.technologies['landfill'].enabled = false
game.forces.player.technologies['spidertron'].enabled = false
game.forces.player.technologies['spidertron'].researched = false
disable_recipes()
end
local disable_tech = Public.disable_tech
function Public.on_research_finished(event)
disable_tech()
end
local function on_entity_died(event)
local name = event.entity.name
local entity = event.entity
local this = WPT.get()
if name == 'flamethrower-turret' then
this.flame = this.flame - 1
if this.flame <= 0 then
this.flame = 0
end
end
end
Public.firearm_magazine_ammo = {name = 'firearm-magazine', count = 200}
Public.piercing_rounds_magazine_ammo = {name = 'piercing-rounds-magazine', count = 200}
Public.uranium_rounds_magazine_ammo = {name = 'uranium-rounds-magazine', count = 200}
Public.light_oil_ammo = {name = 'light-oil', amount = 100}
Public.artillery_shell_ammo = {name = 'artillery-shell', count = 15}
Public.laser_turrent_power_source = {buffer_size = 2400000, power_production = 40000}
function Public.reset_table()
this.power_sources = {index = 1}
this.refill_turrets = {index = 1}
this.magic_crafters = {index = 1}
this.magic_fluid_crafters = {index = 1}
end
local on_research_finished = Public.on_research_finished
local on_player_joined_game = Public.on_player_joined_game
local on_player_respawned = Public.on_player_respawned
local on_player_died = Public.on_player_died
local on_player_changed_position = Public.on_player_changed_position
local on_pre_player_left_game = Public.on_pre_player_left_game
Event.add(defines.events.on_built_entity, on_player_or_robot_built_entity)
Event.add(defines.events.on_robot_built_entity, on_player_or_robot_built_entity)
Event.add(defines.events.on_research_finished, on_research_finished)
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_player_respawned, on_player_respawned)
Event.add(defines.events.on_player_died, on_player_died)
Event.add(defines.events.on_entity_died, on_entity_died)
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)
Event.add(defines.events.on_robot_mined_entity, on_player_mined_entity)
--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.on_nth_tick(10, tick)
Event.on_nth_tick(5, do_turret_energy)
return Public

961
maps/amap/ic/functions.lua Normal file
View File

@ -0,0 +1,961 @@
local Utils = require 'utils.core'
local Color = require 'utils.color_presets'
local Task = require 'utils.task'
local Token = require 'utils.token'
local IC_Gui = require 'maps.amap.ic.gui'
local WPT = require 'maps.amap.table'
local WD = require 'modules.wave_defense.table'
local Public = {}
local main_tile_name = 'black-refined-concrete'
local RPG = require 'modules.rpg.table'
local Loot = require "maps.amap.loot"
local function validate_entity(entity)
if not (entity and entity.valid) then
return false
end
return true
end
local function log_err(ic, err)
if ic.debug_mode then
if type(err) == 'string' then
log('IC: ' .. err)
end
end
end
local function get_trusted_system(this, player)
if not this.trust_system[player.index] then
this.trust_system[player.index] = {
[player.name] = true
}
end
return this.trust_system[player.index]
end
local function upperCase(str)
return (str:gsub('^%l', string.upper))
end
local function render_owner_text(renders, player, entity, new_owner)
local color = {
r = player.color.r * 0.6 + 0.25,
g = player.color.g * 0.6 + 0.25,
b = player.color.b * 0.6 + 0.25,
a = 1
}
if renders[player.index] then
rendering.destroy(renders[player.index])
end
if new_owner then
renders[new_owner.index] =
rendering.draw_text {
text = '## - ' .. new_owner.name .. "'s " .. entity.name .. ' - ##',
surface = entity.surface,
target = entity,
target_offset = {0, -2.6},
color = color,
scale = 1.05,
font = 'default-large-semibold',
alignment = 'center',
scale_with_zoom = false
}
else
renders[player.index] =
rendering.draw_text {
text = '## - ' .. player.name .. "'s " .. entity.name .. ' - ##',
surface = entity.surface,
target = entity,
target_offset = {0, -2.6},
color = color,
scale = 1.05,
font = 'default-large-semibold',
alignment = 'center',
scale_with_zoom = false
}
end
entity.color = color
end
local function kill_doors(ic, car)
if not validate_entity(car.entity) then
return
end
for k, e in pairs(car.doors) do
ic.doors[e.unit_number] = nil
e.destroy()
car.doors[k] = nil
end
end
local function get_owner_car_object(cars, player)
for k, car in pairs(cars) do
if car.owner == player.index then
return k
end
end
return false
end
local function get_entity_from_player_surface(cars, player)
for k, car in pairs(cars) do
if validate_entity(car.entity) then
if validate_entity(car.surface) then
if car.surface.index == player.surface.index then
return car.entity
end
end
end
end
return false
end
local function get_owner_car_surface(cars, player, target)
for k, car in pairs(cars) do
if car.owner == player.index then
if validate_entity(car.surface) then
if car.surface.index == target.surface.index then
return true
else
return false
end
else
return false
end
end
end
return false
end
local function get_player_surface(ic, player)
local surfaces = ic.surfaces
for _, surface in pairs(surfaces) do
if validate_entity(surface) then
if surface.index == player.surface.index then
return true
end
end
end
return false
end
local function get_player_entity(ic, player)
local cars = ic.cars
for k, car in pairs(cars) do
if car.owner == player.index and type(car.entity) == 'boolean' then
return car.name, true
elseif car.owner == player.index then
return car.name, false
end
end
return false, false
end
local function get_owner_car_name(ic, player)
local cars = ic.cars
local saved_surfaces = ic.saved_surfaces
local index = saved_surfaces[player.index]
for k, car in pairs(cars) do
if not index then
return false
end
if car.owner == player.index then
return car.name
end
end
return false
end
local function get_saved_entity(entity, index)
if index and index.name ~= entity.name then
local msg =
table.concat(
{
'The built entity is not the same as the saved one. ',
'Saved entity is: ' .. upperCase(index.name) .. ' - Built entity is: ' .. upperCase(entity.name) .. '. '
}
)
return false, msg
end
return true
end
local function replace_entity(cars, entity, index)
local unit_number = entity.unit_number
for k, car in pairs(cars) do
if car.saved_entity == index.saved_entity then
local c = car
cars[unit_number] = c
cars[unit_number].entity = entity
cars[unit_number].saved_entity = nil
cars[unit_number].transfer_entities = car.transfer_entities
cars[k] = nil
end
end
end
local function replace_doors(doors, entity, index)
if not validate_entity(entity) then
return
end
for k, door in pairs(doors) do
local unit_number = entity.unit_number
if index.saved_entity == door then
doors[k] = unit_number
end
end
end
local function replace_surface(surfaces, entity, index)
if not validate_entity(entity) then
return
end
for k, surface in pairs(surfaces) do
local unit_number = entity.unit_number
if tostring(index.saved_entity) == surface.name then
if validate_entity(surface) then
surface.name = tostring(unit_number)
surfaces[unit_number] = surface
surfaces[k] = nil
end
end
end
end
local function replace_surface_entity(cars, entity, index)
if not validate_entity(entity) then
return
end
for _, car in pairs(cars) do
local unit_number = entity.unit_number
if index and index.saved_entity == car.saved_entity then
if validate_entity(car.surface) then
car.surface.name = tostring(unit_number)
end
end
end
end
local function remove_logistics(car)
local chests = car.transfer_entities
for k, chest in pairs(chests) do
car.transfer_entities[k] = nil
chest.destroy()
end
end
local function set_new_area(ic, car)
local new_area = ic.car_areas
local name = car.name
local apply_area = new_area[name]
car.area = apply_area
end
local function upgrade_surface(ic, player, entity)
local ce = entity
local saved_surfaces = ic.saved_surfaces
local cars = ic.cars
local door = ic.doors
local surfaces = ic.surfaces
local index = saved_surfaces[player.index]
if not index then
return
end
if saved_surfaces[player.index] then
local c = get_owner_car_object(cars, player)
local car = ic.cars[c]
if ce.name == 'spidertron' then
car.name = 'spidertron'
elseif ce.name == 'tank' then
car.name = 'tank'
end
set_new_area(ic, car)
remove_logistics(car)
replace_entity(cars, ce, index)
replace_doors(door, ce, index)
replace_surface(surfaces, ce, index)
replace_surface_entity(cars, ce, index)
kill_doors(ic, car)
Public.create_car_room(ic, car)
saved_surfaces[player.index] = nil
return true
end
return false
end
local function save_surface(ic, entity, player)
local car = ic.cars[entity.unit_number]
car.entity = false
car.saved_entity = entity.unit_number
ic.saved_surfaces[player.index] = {saved_entity = entity.unit_number, name = entity.name}
end
local function kick_players_out_of_vehicles(car)
for _, player in pairs(game.connected_players) do
local character = player.character
if validate_entity(character) and character.driving then
if car.surface == player.surface then
character.driving = false
end
end
end
end
local function kick_players_from_surface(ic, car)
if not validate_entity(car.surface) then
return log_err('Car surface was not valid.')
end
if not car.entity or not car.entity.valid then
local main_surface = game.surfaces[ic.allowed_surface]
if validate_entity(main_surface) then
for _, e in pairs(car.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)
end
end
end
return log_err('Car entity was not valid.')
end
for _, e in pairs(car.surface.find_entities_filtered({area = car.area})) do
if validate_entity(e) and e.name == 'character' and e.player then
local p = car.entity.surface.find_non_colliding_position('character', car.entity.position, 128, 0.5)
if p then
e.player.teleport(p, car.entity.surface)
else
e.player.teleport(car.entity.position, car.entity.surface)
end
end
end
end
local function kick_player_from_surface(ic, player, target)
local cars = ic.cars
local main_surface = game.surfaces[ic.allowed_surface]
if not validate_entity(main_surface) then
return
end
local c = get_owner_car_object(cars, player)
local car = ic.cars[c]
if not validate_entity(car.entity) then
return
end
if validate_entity(player) then
if validate_entity(target) then
local locate = get_owner_car_surface(cars, player, target)
if locate then
local p = car.entity.surface.find_non_colliding_position('character', car.entity.position, 128, 0.5)
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)
end
target.print('You were kicked out of ' .. player.name .. ' vehicle.', Color.warning)
end
end
end
end
local function restore_surface(ic, player, entity)
local ce = entity
local saved_surfaces = ic.saved_surfaces
local cars = ic.cars
local door = ic.doors
local renders = ic.renders
local surfaces = ic.surfaces
local index = saved_surfaces[player.index]
if not index then
return
end
if saved_surfaces[player.index] then
local success, msg = get_saved_entity(ce, index)
if not success then
player.print(msg, Color.warning)
return true
end
replace_entity(cars, ce, index)
replace_doors(door, ce, index)
replace_surface(surfaces, ce, index)
replace_surface_entity(cars, ce, index)
saved_surfaces[player.index] = nil
render_owner_text(renders, player, ce)
return true
end
return false
end
local function input_filtered(car_inv, chest, chest_inv, free_slots)
local request_stacks = {}
local prototypes = game.item_prototypes
for slot_index = 1, 30, 1 do
local stack = chest.get_request_slot(slot_index)
if stack then
request_stacks[stack.name] = 10 * prototypes[stack.name].stack_size
end
end
for i = 1, #car_inv - 1, 1 do
if free_slots <= 0 then
return
end
local stack = car_inv[i]
if stack.valid_for_read then
local request_stack = request_stacks[stack.name]
if request_stack and request_stack > chest_inv.get_item_count(stack.name) then
chest_inv.insert(stack)
stack.clear()
free_slots = free_slots - 1
end
end
end
end
local function input_cargo(car, chest)
if not chest.request_from_buffers then
return
end
local car_entity = car.entity
if not validate_entity(car_entity) then
return
end
local car_inventory = car_entity.get_inventory(defines.inventory.car_trunk)
if car_inventory.is_empty() then
return
end
local chest_inventory = chest.get_inventory(defines.inventory.chest)
local free_slots = 0
for i = 1, chest_inventory.get_bar() - 1, 1 do
if not chest_inventory[i].valid_for_read then
free_slots = free_slots + 1
end
end
if chest.get_request_slot(1) then
input_filtered(car_inventory, chest, chest_inventory, free_slots)
return
end
for i = 1, #car_inventory - 1, 1 do
if free_slots <= 0 then
return
end
if car_inventory[i].valid_for_read then
chest_inventory.insert(car_inventory[i])
car_inventory[i].clear()
free_slots = free_slots - 1
end
end
end
local function output_cargo(car, passive_chest)
if not validate_entity(car.entity) then
return
end
if not passive_chest.valid then
return
end
local chest1 = passive_chest.get_inventory(defines.inventory.chest)
local chest2 = car.entity.get_inventory(defines.inventory.car_trunk)
for k, v in pairs(chest1.get_contents()) do
local t = {name = k, count = v}
local c = chest2.insert(t)
if (c > 0) then
chest1.remove({name = k, count = c})
end
end
end
local transfer_functions = {
['logistic-chest-requester'] = input_cargo,
['logistic-chest-passive-provider'] = output_cargo
}
local function construct_doors(ic, car)
local area = car.area
local surface = car.surface
for _, x in pairs({area.left_top.x - 1.5, area.right_bottom.x + 1.5}) do
local p = {x = x, y = area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5)}
if p.x < 0 then
surface.set_tiles({{name = main_tile_name, position = {x = p.x + 0.5, y = p.y}}}, true)
else
surface.set_tiles({{name = main_tile_name, position = {x = p.x - 1, y = p.y}}}, true)
end
local e =
surface.create_entity(
{
name = 'car',
position = {x, area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5)},
force = 'neutral',
create_build_effect_smoke = false
}
)
e.destructible = false
e.minable = false
e.operable = false
e.get_inventory(defines.inventory.fuel).insert({name = 'coal', count = 1})
ic.doors[e.unit_number] = car.entity.unit_number
car.doors[#car.doors + 1] = e
end
end
local function get_player_data(ic, player)
local player_data = ic.players[player.index]
if ic.players[player.index] then
return player_data
end
local fallback = WPT.get('active_surface_index')
if not fallback then
fallback = 1
end
ic.players[player.index] = {
surface = 1,
fallback_surface = tonumber(fallback),
notified = false
}
return ic.players[player.index]
end
local remove_car =
Token.register(
function(data)
local player = data.player
local car = data.car
player.remove_item({name = car.name, count = 1})
end
)
function Public.save_car(ic, event)
local entity = event.entity
local player = game.players[event.player_index]
local car = ic.cars[entity.unit_number]
if not car then
log_err('Car was not valid.')
return
end
local position = entity.position
local health = entity.health
kick_players_out_of_vehicles(car)
kick_players_from_surface(ic, car)
get_player_data(ic, player)
if car.owner == player.index then
save_surface(ic, entity, player)
if not ic.players[player.index].notified then
player.print(player.name .. ', the ' .. car.name .. ' has been saved', Color.success)
ic.players[player.index].notified = true
local wave_number = WD.get('wave_number')
--game.print(type(wave_number))
local a = 100
if ( wave_number <= a ) then
player.print({'amap.usecar'},Color.warning)
else
local rpg_t = RPG.get('rpg_t')
rpg_t[player.index].points_to_distribute = rpg_t[player.index].points_to_distribute+50
player.print({'amap.usecar2'},Color.success)
end
end
else
local p = game.players[car.owner]
if not p then
return
end
log_err(ic, 'Owner of this vehicle is: ' .. p.name)
save_surface(ic, entity, p)
Utils.action_warning('{Car}', player.name .. ' has looted ' .. p.name .. '´s car.')
player.print('This car was not yours to keep.', Color.warning)
local params = {
player = player,
car = car
}
Task.set_timeout_in_ticks(10, remove_car, params)
if ic.restore_on_theft then
local e = player.surface.create_entity({name = car.name, position = position, force = player.force, create_build_effect_smoke = false})
e.health = health
restore_surface(ic, p, e)
else
p.insert({name = car.name, count = 1, health = health})
p.print('Your car was stolen from you - the gods foresaw this and granted you a new one.', Color.info)
end
end
end
function Public.kill_car(ic, entity)
if not validate_entity(entity) then
return
end
local entity_type = ic.entity_type
if not entity_type[entity.type] then
return
end
local car = ic.cars[entity.unit_number]
local surface = car.surface
kick_players_out_of_vehicles(car)
kill_doors(ic, car)
kick_players_from_surface(ic, car)
for _, tile in pairs(surface.find_tiles_filtered({area = car.area})) do
surface.set_tiles({{name = 'out-of-map', position = tile.position}}, true)
end
for _, x in pairs({car.area.left_top.x - 1.5, car.area.right_bottom.x + 1.5}) do
local p = {x = x, y = car.area.left_top.y + ((car.area.right_bottom.y - car.area.left_top.y) * 0.5)}
surface.set_tiles({{name = 'out-of-map', position = {x = p.x + 0.5, y = p.y}}}, true)
surface.set_tiles({{name = 'out-of-map', position = {x = p.x - 1, y = p.y}}}, true)
end
car.entity.force.chart(surface, car.area)
game.delete_surface(surface)
ic.surfaces[entity.unit_number] = nil
ic.cars[entity.unit_number] = nil
end
function Public.validate_owner(ic, player, entity)
if validate_entity(entity) then
local cars = ic.cars
local unit_number = entity.unit_number
local car = cars[unit_number]
if not car then
return
end
if validate_entity(car.entity) then
local p = game.players[car.owner]
local list = get_trusted_system(ic, p)
if p and p.valid and p.connected then
if list[player.name] then
return
end
end
if p then
if car.owner ~= player.index and player.driving then
player.driving = false
if not player.admin then
return Utils.print_to(nil, '{Car} ' .. player.name .. ' tried to drive ' .. p.name .. '´s car.')
end
end
end
end
return false
end
return false
end
function Public.create_room_surface(ic, unit_number)
if game.surfaces[tostring(unit_number)] then
return game.surfaces[tostring(unit_number)]
end
local map_gen_settings = {
['width'] = 2,
['height'] = 2,
['water'] = 0,
['starting_area'] = 1,
['cliff_settings'] = {cliff_elevation_interval = 0, cliff_elevation_0 = 0},
['default_enable_all_autoplace_controls'] = true,
['autoplace_settings'] = {
['entity'] = {treat_missing_as_default = false},
['tile'] = {treat_missing_as_default = true},
['decorative'] = {treat_missing_as_default = false}
}
}
local surface = game.create_surface(tostring(unit_number), map_gen_settings)
surface.freeze_daytime = true
surface.daytime = 0.1
surface.request_to_generate_chunks({16, 16}, 1)
surface.force_generate_chunk_requests()
for _, tile in pairs(surface.find_tiles_filtered({area = {{-2, -2}, {2, 2}}})) do
surface.set_tiles({{name = 'out-of-map', position = tile.position}}, true)
end
ic.surfaces[unit_number] = surface
return surface
end
function Public.create_car_room(ic, car)
local surface = car.surface
local car_areas = ic.car_areas
local entity_name = car.name
local area = car_areas[entity_name]
local tiles = {}
for x = area.left_top.x, area.right_bottom.x - 1, 1 do
for y = area.left_top.y + 2, area.right_bottom.y - 3, 1 do
tiles[#tiles + 1] = {name = main_tile_name, position = {x, y}}
end
end
for x = -3, 2, 1 do
for y = area.right_bottom.y - 4, area.right_bottom.y - 2, 1 do
tiles[#tiles + 1] = {name = main_tile_name, position = {x, y}}
end
end
local fishes = {}
for x = area.left_top.x, area.right_bottom.x - 1, 1 do
for y = -0, 1, 1 do
tiles[#tiles + 1] = {name = 'water', position = {x, y}}
fishes[#fishes + 1] = {name = 'fish', position = {x, y}}
end
end
surface.set_tiles(tiles, true)
for _, fish in pairs(fishes) do
surface.create_entity(fish)
end
construct_doors(ic, car)
local mgs = surface.map_gen_settings
mgs.width = area.right_bottom.x * 2
mgs.height = area.right_bottom.y * 2
surface.map_gen_settings = mgs
local lx, ly, rx, ry = 4, 1, 5, 1
local position1 = {area.left_top.x + lx, area.left_top.y + ly}
local position2 = {area.right_bottom.x - rx, area.left_top.y + ry}
local e1 =
surface.create_entity(
{
name = 'logistic-chest-requester',
position = position1,
force = 'neutral',
create_build_effect_smoke = false
}
)
e1.destructible = false
e1.minable = false
local e2 =
surface.create_entity(
{
name = 'logistic-chest-passive-provider',
position = position2,
force = 'neutral',
create_build_effect_smoke = false
}
)
e2.destructible = false
e2.minable = false
car.transfer_entities = {e1, e2}
return
end
function Public.create_car(ic, event)
local ce = event.created_entity
local player = game.get_player(event.player_index)
local map_name = ic.allowed_surface
local entity_type = ic.entity_type
local un = ce.unit_number
if not un then
return
end
if not entity_type[ce.type] then
return
end
local name, mined = get_player_entity(ic, player)
if entity_type[name] and not mined then
return player.print('Multiple vehicles are not supported at the moment.', Color.warning)
end
if string.sub(ce.surface.name, 0, #map_name) ~= map_name then
return player.print('Multi-surface is not supported at the moment.', Color.warning)
end
if
get_owner_car_name(ic, player) == 'car' and ce.name == 'tank' or get_owner_car_name(ic, player) == 'car' and ce.name == 'spidertron' or
get_owner_car_name(ic, player) == 'tank' and ce.name == 'spidertron'
then
upgrade_surface(ic, player, ce)
render_owner_text(ic.renders, player, ce)
player.print('Your car-surface has been upgraded!', Color.success)
return
end
local saved_surface = restore_surface(ic, player, ce)
if saved_surface then
return
end
local car_areas = ic.car_areas
local car_area = car_areas[ce.name]
ic.cars[un] = {
entity = ce,
area = {
left_top = {x = car_area.left_top.x, y = car_area.left_top.y},
right_bottom = {x = car_area.right_bottom.x, y = car_area.right_bottom.y}
},
doors = {},
owner = player.index,
name = ce.name
}
local car = ic.cars[un]
car.surface = Public.create_room_surface(ic, un)
Public.create_car_room(ic, car)
render_owner_text(ic.renders, player, ce)
return car
end
function Public.remove_invalid_cars(ic)
for k, car in pairs(ic.cars) do
if type(car.entity) ~= 'boolean' then
if not validate_entity(car.entity) then
ic.cars[k] = nil
for key, value in pairs(ic.doors) do
if k == value then
ic.doors[key] = nil
end
end
kick_players_from_surface(ic, car)
end
end
end
for k, surface in pairs(ic.surfaces) do
if not ic.cars[tonumber(surface.name)] then
game.delete_surface(surface)
ic.surfaces[k] = nil
end
end
end
function Public.use_door_with_entity(ic, player, door)
local player_data = get_player_data(ic, player)
if player_data.state then
player_data.state = player_data.state - 1
if player_data.state == 0 then
player_data.state = nil
end
return
end
if not validate_entity(door) then
return
end
local doors = ic.doors
local cars = ic.cars
local car = false
if doors[door.unit_number] then
car = cars[doors[door.unit_number]]
end
if cars[door.unit_number] then
car = cars[door.unit_number]
end
if not car then
return
end
local owner = game.players[car.owner]
local list = get_trusted_system(ic, owner)
if owner and owner.valid and player.connected then
if not list[player.name] and not player.admin then
player.driving = false
return player.print('You have not been approved by ' .. owner.name .. ' to enter their vehicle.', Color.warning)
end
end
player_data.fallback_surface = car.entity.surface.index
player_data.fallback_position = {car.entity.position.x, car.entity.position.y}
if car.entity.surface.name == player.surface.name then
local surface = car.surface
if validate_entity(car.entity) and car.owner == player.index then
IC_Gui.add_toolbar(player)
car.entity.minable = false
end
if not validate_entity(surface) then
return
end
local area = car.area
local x_vector = door.position.x - player.position.x
local position
if x_vector > 0 then
position = {area.left_top.x + 0.5, area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5)}
else
position = {area.right_bottom.x - 0.5, area.left_top.y + ((area.right_bottom.y - area.left_top.y) * 0.5)}
end
local p = surface.find_non_colliding_position('character', position, 128, 0.5)
if p then
player.teleport(p, surface)
else
player.teleport(position, surface)
end
player_data.surface = surface.index
else
if validate_entity(car.entity) and car.owner == player.index then
IC_Gui.remove_toolbar(player)
car.entity.minable = true
end
local surface = car.entity.surface
local x_vector = (door.position.x / math.abs(door.position.x)) * 2
local position = {car.entity.position.x + x_vector, car.entity.position.y}
local surface_position = surface.find_non_colliding_position('character', position, 128, 0.5)
if car.entity.type == 'car' or car.entity.name == 'spidertron' then
player.teleport(surface_position, surface)
player_data.state = 2
player.driving = true
else
player.teleport(surface_position, surface)
end
player_data.surface = surface.index
end
end
function Public.item_transfer(ic)
for _, car in pairs(ic.cars) do
if validate_entity(car.entity) then
if car.transfer_entities then
for k, e in pairs(car.transfer_entities) do
if validate_entity(e) then
transfer_functions[e.name](car, e)
end
end
end
end
end
end
Public.kick_player_from_surface = kick_player_from_surface
Public.get_player_surface = get_player_surface
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
return Public

773
maps/amap/ic/gui.lua Normal file
View File

@ -0,0 +1,773 @@
local ICT = require 'maps.amap.ic.table'
local Color = require 'utils.color_presets'
local Gui = require 'utils.gui'
local Tabs = require 'comfy_panel.main'
local Event = require 'utils.event'
local rpgtable = require 'modules.rpg.table'
local Loot = require'maps.amap.loot'
local Public = {}
local Alert = require 'utils.alert'
--! Gui Frames
local save_add_player_button_name = Gui.uid_name()
local save_transfer_car_button_name = Gui.uid_name()
local discard_add_player_button_name = Gui.uid_name()
local discard_transfer_car_button_name = Gui.uid_name()
local main_frame_name = Gui.uid_name()
local draw_add_player_frame_name = Gui.uid_name()
local draw_transfer_car_frame_name = Gui.uid_name()
local main_toolbar_name = Gui.uid_name()
local cool = Gui.uid_name()
local gambel = Gui.uid_name()
local buyxp = Gui.uid_name()
local add_player_name = Gui.uid_name()
local transfer_car_name = Gui.uid_name()
local kick_player_name = Gui.uid_name()
local raise_event = script.raise_event
local add_toolbar
local remove_toolbar
local function increment(t, k)
t[k] = true
end
local function decrement(t, k)
t[k] = nil
end
local function create_player_table(player)
local trust_system = ICT.get('trust_system')
if not trust_system[player.index] then
trust_system[player.index] = {
[player.name] = true
}
end
return trust_system[player.index]
end
local function does_player_table_exist(player)
local trust_system = ICT.get('trust_system')
if not trust_system[player.index] then
return false
else
return true
end
end
local function transfer_player_table(player, new_player)
local trust_system = ICT.get('trust_system')
if not trust_system[player.index] then
return false
end
if player.index == new_player.index then
return false
end
if not trust_system[new_player.index] then
local Functions = require 'maps.amap.ic.functions'
trust_system[new_player.index] = trust_system[player.index]
local name = new_player.name
if not trust_system[new_player.index][name] then
increment(trust_system[new_player.index], name)
end
local cars = ICT.get('cars')
local renders = ICT.get('renders')
local c = Functions.get_owner_car_object(cars, player)
local car = cars[c]
car.owner = new_player.index
Functions.render_owner_text(renders, player, car.entity, new_player)
remove_toolbar(player)
add_toolbar(new_player)
trust_system[player.index] = nil
else
return false
end
return trust_system[new_player.index]
end
local function remove_main_frame(main_frame)
Gui.remove_data_recursively(main_frame)
main_frame.destroy()
end
local function draw_add_player(frame)
local main_frame =
frame.add(
{
type = 'frame',
name = draw_add_player_frame_name,
caption = 'Add Player',
direction = 'vertical'
}
)
local main_frame_style = main_frame.style
main_frame_style.width = 370
main_frame_style.use_header_filler = true
local inside_frame = main_frame.add {type = 'frame', style = 'inside_shallow_frame'}
local inside_frame_style = inside_frame.style
inside_frame_style.padding = 0
local inside_table = inside_frame.add {type = 'table', column_count = 1}
local inside_table_style = inside_table.style
inside_table_style.vertical_spacing = 5
inside_table_style.top_padding = 10
inside_table_style.left_padding = 10
inside_table_style.right_padding = 0
inside_table_style.bottom_padding = 10
inside_table_style.width = 325
local add_player_frame = main_frame.add({type = 'textfield', text = 'Name of the player.'})
add_player_frame.style.width = 140
local bottom_flow = main_frame.add({type = 'flow', direction = 'horizontal'})
local left_flow = bottom_flow.add({type = 'flow'})
left_flow.style.horizontal_align = 'left'
left_flow.style.horizontally_stretchable = true
local close_button = left_flow.add({type = 'button', name = discard_add_player_button_name, caption = 'Discard'})
close_button.style = 'back_button'
close_button.style.maximal_width = 100
local right_flow = bottom_flow.add({type = 'flow'})
right_flow.style.horizontal_align = 'right'
local save_button = right_flow.add({type = 'button', name = save_add_player_button_name, caption = 'Save'})
save_button.style = 'confirm_button'
save_button.style.maximal_width = 100
Gui.set_data(save_button, add_player_frame)
end
local function draw_transfer_car(frame)
local main_frame =
frame.add(
{
type = 'frame',
name = draw_transfer_car_frame_name,
caption = 'Transfer Car',
direction = 'vertical'
}
)
local main_frame_style = main_frame.style
main_frame_style.width = 370
main_frame_style.use_header_filler = true
local inside_frame = main_frame.add {type = 'frame', style = 'inside_shallow_frame'}
local inside_frame_style = inside_frame.style
inside_frame_style.padding = 0
local inside_table = inside_frame.add {type = 'table', column_count = 1}
local inside_table_style = inside_table.style
inside_table_style.vertical_spacing = 5
inside_table_style.top_padding = 10
inside_table_style.left_padding = 10
inside_table_style.right_padding = 0
inside_table_style.bottom_padding = 10
inside_table_style.width = 325
local transfer_car_alert_frame = main_frame.add({type = 'label', caption = "Warning, this action can't be undone!"})
transfer_car_alert_frame.style.font_color = {r = 255, g = 0, b = 0}
local transfer_car_frame = main_frame.add({type = 'textfield', text = 'Name of the player.'})
transfer_car_frame.style.width = 140
local bottom_flow = main_frame.add({type = 'flow', direction = 'horizontal'})
local left_flow = bottom_flow.add({type = 'flow'})
left_flow.style.horizontal_align = 'left'
left_flow.style.horizontally_stretchable = true
local close_button = left_flow.add({type = 'button', name = discard_transfer_car_button_name, caption = 'Discard'})
close_button.style = 'back_button'
close_button.style.maximal_width = 100
local right_flow = bottom_flow.add({type = 'flow'})
right_flow.style.horizontal_align = 'right'
local save_button = right_flow.add({type = 'button', name = save_transfer_car_button_name, caption = 'Save'})
save_button.style = 'confirm_button'
save_button.style.maximal_width = 100
Gui.set_data(save_button, transfer_car_frame)
end
local function draw_players(data)
local player_table = data.player_table
local add_player_frame = data.add_player_frame
local player = data.player
local player_list = create_player_table(player)
for p, _ in pairs(player_list) do
Gui.set_data(add_player_frame, p)
local t_label =
player_table.add(
{
type = 'label',
caption = p
}
)
t_label.style.minimal_width = 75
t_label.style.horizontal_align = 'center'
local a_label =
player_table.add(
{
type = 'label',
caption = '✔️'
}
)
a_label.style.minimal_width = 75
a_label.style.horizontal_align = 'center'
a_label.style.font = 'default-large-bold'
local kick_flow = player_table.add {type = 'flow'}
local kick_player_button =
kick_flow.add(
{
type = 'button',
caption = 'Kick ' .. p,
name = kick_player_name
}
)
if player.name == t_label.caption then
kick_player_button.enabled = false
end
kick_player_button.style.minimal_width = 75
Gui.set_data(kick_player_button, p)
end
end
local function draw_main_frame(player)
local main_frame =
player.gui.screen.add(
{
type = 'frame',
name = main_frame_name,
caption = 'Car Settings',
direction = 'vertical',
style = 'inner_frame_in_outer_frame'
}
)
main_frame.auto_center = true
local main_frame_style = main_frame.style
main_frame_style.width = 400
main_frame_style.use_header_filler = true
local inside_frame = main_frame.add {type = 'frame', style = 'inside_shallow_frame'}
local inside_frame_style = inside_frame.style
inside_frame_style.padding = 0
local inside_table = inside_frame.add {type = 'table', column_count = 1}
local inside_table_style = inside_table.style
inside_table_style.vertical_spacing = 5
inside_table_style.top_padding = 10
inside_table_style.left_padding = 10
inside_table_style.right_padding = 0
inside_table_style.bottom_padding = 10
inside_table_style.width = 350
local add_player_frame = inside_table.add({type = 'button', caption = 'Add Player', name = add_player_name})
local transfer_car_frame = inside_table.add({type = 'button', caption = 'Transfer Car', name = transfer_car_name})
local player_table =
inside_table.add {
type = 'table',
column_count = 3,
draw_horizontal_lines = true,
draw_vertical_lines = true,
vertical_centering = true
}
local player_table_style = player_table.style
player_table_style.vertical_spacing = 10
player_table_style.width = 350
player_table_style.horizontal_spacing = 30
local name_label =
player_table.add(
{
type = 'label',
caption = 'Name',
tooltip = ''
}
)
name_label.style.minimal_width = 75
name_label.style.horizontal_align = 'center'
local trusted_label =
player_table.add(
{
type = 'label',
caption = 'Allowed',
tooltip = ''
}
)
trusted_label.style.minimal_width = 75
trusted_label.style.horizontal_align = 'center'
local operations_label =
player_table.add(
{
type = 'label',
caption = 'Operations',
tooltip = ''
}
)
operations_label.style.minimal_width = 75
operations_label.style.horizontal_align = 'center'
local data = {
player_table = player_table,
add_player_frame = add_player_frame,
transfer_car_frame = transfer_car_frame,
player = player
}
draw_players(data)
player.opened = main_frame
end
local function toggle(player, recreate)
local screen = player.gui.screen
local main_frame = screen[main_frame_name]
if recreate and main_frame then
local location = main_frame.location
remove_main_frame(main_frame)
draw_main_frame(player, location)
return
end
if main_frame then
remove_main_frame(main_frame)
Tabs.comfy_panel_restore_left_gui(player)
else
Tabs.comfy_panel_clear_left_gui(player)
draw_main_frame(player)
end
end
add_toolbar = function(player, remove)
if remove then
if player.gui.top[main_toolbar_name] then
player.gui.top[cool].destroy()
player.gui.top[buyxp].destroy()
player.gui.top[gambel].destroy()
player.gui.top[main_toolbar_name].destroy()
return
end
end
if player.gui.top[main_toolbar_name] then
return
end
local tooltip = 'contorl who can enter your car.'
player.gui.top.add(
{
type = 'sprite-button',
sprite = 'item/spidertron',
name = main_toolbar_name,
tooltip = tooltip
}
)
player.gui.top.add(
{
type = 'sprite-button',
sprite = 'item/logistic-chest-storage',
name = cool,
tooltip = {'amap.openchest'}
}
)
player.gui.top.add(
{
type = 'sprite-button',
sprite = 'item/coin',
name = gambel,
tooltip = {'amap.gambel'}
}
)
player.gui.top.add(
{
type = 'sprite-button',
sprite = 'item/rocket-part',
name = buyxp,
tooltip = {'amap.buyxp'}
}
)
end
remove_toolbar = function(player)
local screen = player.gui.screen
local main_frame = screen[main_frame_name]
if main_frame and main_frame.valid then
remove_main_frame(main_frame)
end
if player.gui.top[main_toolbar_name] then
player.gui.top[main_toolbar_name].destroy()
player.gui.top[cool].destroy()
player.gui.top[buyxp].destroy()
player.gui.top[gambel].destroy()
return
end
end
Gui.on_click(
add_player_name,
function(event)
local player = event.player
if not player or not player.valid or not player.character then
return
end
local screen = player.gui.screen
local frame = screen[main_frame_name]
if not frame or not frame.valid then
return
end
local player_frame = frame[draw_add_player_frame_name]
if not player_frame or not player_frame.valid then
draw_add_player(frame)
else
player_frame.destroy()
end
end
)
Gui.on_click(
transfer_car_name,
function(event)
local player = event.player
if not player or not player.valid or not player.character then
return
end
local screen = player.gui.screen
local frame = screen[main_frame_name]
if not frame or not frame.valid then
return
end
local player_frame = frame[draw_transfer_car_frame_name]
if not player_frame or not player_frame.valid then
draw_transfer_car(frame)
else
player_frame.destroy()
end
end
)
Gui.on_click(
gambel ,
function(event)
local player = event.player
local something = player.get_inventory(defines.inventory.chest)
for k, v in pairs(something.get_contents()) do
local t = {name = k, count = v}
if t.name == 'coin' then
if v > 999 then
player.remove_item{name='coin', count = '1000'}
local roll = math.random(1,100)
if roll <= 36 then
player.insert{name='coin', count = '2500'}
player.print({'amap.gambel1'})
return
else
player.print({'amap.gambel2'})
return
end
else
player.print({'amap.noenough'})
return
end
end
end
end
)
Gui.on_click(
cool ,
function(event)
local player = event.player
local something = player.get_inventory(defines.inventory.chest)
for k, v in pairs(something.get_contents()) do
local t = {name = k, count = v}
if t.name == 'coin' then
if v > 2999 then
player.remove_item{name='coin', count = '3000'}
local luck = math.floor(math.random(1,130))
player.print({'amap.lucknb'})
player.print(luck)
local magic = luck*5+100
local msg = {'amap.whatopen'}
Loot.cool(player.surface, player.surface.find_non_colliding_position("steel-chest", player.position, 20, 1, true) or player.position, 'steel-chest', magic)
Alert.alert_player(player, 5, msg)
return
else
player.print({'amap.noenough'})
return
end
end
end
end
)
Gui.on_click(
buyxp ,
function(event)
local player = event.player
local something = player.get_inventory(defines.inventory.chest)
for k, v in pairs(something.get_contents()) do
local t = {name = k, count = v}
if t.name == 'coin' then
if v > 4999 then
player.remove_item{name='coin', count = '5000'}
local rpg_t = rpgtable.get('rpg_t')
rpg_t[player.index].xp = rpg_t[player.index].xp +1000
local msg = {'amap.buyover'}
Alert.alert_player(player, 5, msg)
return
else
player.print({'amap.noenough'})
return
end
end
end
end
)
Gui.on_click(
save_add_player_button_name,
function(event)
local player = event.player
if not player or not player.valid or not player.character then
return
end
local player_list = create_player_table(player)
local screen = player.gui.screen
local frame = screen[main_frame_name]
local add_player_frame = Gui.get_data(event.element)
if frame and frame.valid then
if add_player_frame and add_player_frame.valid and add_player_frame.text then
local text = add_player_frame.text
if not text then
return
end
local player_to_add = game.get_player(text)
if not player_to_add or not player_to_add.valid then
return player.print('Target player was not valid.', Color.warning)
end
local name = player_to_add.name
if not player_list[name] then
player.print(name .. ' was added to your vehicle.', Color.info)
player_to_add.print(player.name .. ' added you to their vehicle. You may now enter it.', Color.info)
increment(player_list, name)
else
return player.print('Target player is already trusted.', Color.warning)
end
remove_main_frame(event.element)
if player.gui.screen[main_frame_name] then
toggle(player, true)
end
end
end
end
)
Gui.on_click(
save_transfer_car_button_name,
function(event)
local player = event.player
if not player or not player.valid or not player.character then
return
end
local screen = player.gui.screen
local frame = screen[main_frame_name]
local transfer_car_frame = Gui.get_data(event.element)
if frame and frame.valid then
if transfer_car_frame and transfer_car_frame.valid and transfer_car_frame.text then
local text = transfer_car_frame.text
if not text then
return
end
local player_to_add = game.get_player(text)
if not player_to_add or not player_to_add.valid then
return player.print('Target player was not valid.', Color.warning)
end
local name = player_to_add.name
local does_player_have_a_car = does_player_table_exist(name)
if does_player_have_a_car then
return player.print(name .. ' already has a vehicle.', Color.warning)
end
local to_add = game.get_player(name)
if not (to_add and to_add.valid) then
return player.print(name .. ' does not exist.', Color.warning)
end
local success = transfer_player_table(player, to_add)
if not success then
player.print('Please try again.', Color.warning)
else
player.print('You have successfully transferred your car to ' .. name, Color.success)
to_add.print('You have become the rightfully owner of ' .. player.name .. "'s car!", Color.success)
end
remove_main_frame(event.element)
if player.gui.screen[main_frame_name] then
player.gui.screen[main_frame_name].destroy()
end
end
end
end
)
Gui.on_click(
kick_player_name,
function(event)
local player = event.player
if not player or not player.valid or not player.character then
return
end
local player_list = create_player_table(player)
local screen = player.gui.screen
local frame = screen[main_frame_name]
local player_name = Gui.get_data(event.element)
local this = ICT.get()
if frame and frame.valid then
if not player_name then
return
end
local target = game.get_player(player_name)
if not target or not target.valid then
player.print('Target player was not valid.', Color.warning)
return
end
local name = target.name
if player_list[name] then
player.print(name .. ' was removed from your vehicle.', Color.info)
decrement(player_list, name)
raise_event(
ICT.events.on_player_kicked_from_surface,
{
player = player,
target = target,
this = this
}
)
end
remove_main_frame(event.element)
if player.gui.screen[main_frame_name] then
toggle(player, true)
end
end
end
)
Gui.on_click(
discard_add_player_button_name,
function(event)
local player = event.player
if not player or not player.valid or not player.character then
return
end
local screen = player.gui.screen
local frame = screen[main_frame_name]
if not frame or not frame.valid then
return
end
local player_frame = frame[draw_add_player_frame_name]
if player_frame and player_frame.valid then
player_frame.destroy()
end
end
)
Gui.on_click(
discard_transfer_car_button_name,
function(event)
local player = event.player
if not player or not player.valid or not player.character then
return
end
local screen = player.gui.screen
local frame = screen[main_frame_name]
if not frame or not frame.valid then
return
end
local player_frame = frame[draw_transfer_car_frame_name]
if player_frame and player_frame.valid then
player_frame.destroy()
end
end
)
Gui.on_click(
main_toolbar_name,
function(event)
local player = event.player
if not player or not player.valid or not player.character then
return
end
local screen = player.gui.screen
local frame = screen[main_frame_name]
if frame and frame.valid then
frame.destroy()
else
draw_main_frame(player)
end
end
)
Public.draw_main_frame = draw_main_frame
Public.toggle = toggle
Public.add_toolbar = add_toolbar
Public.remove_toolbar = remove_toolbar
Event.add(
defines.events.on_gui_closed,
function(event)
local player = game.get_player(event.player_index)
if not player or not player.valid or not player.character then
return
end
local screen = player.gui.screen
local frame = screen[main_frame_name]
if frame and frame.valid then
frame.destroy()
end
end
)
return Public

187
maps/amap/ic/main.lua Normal file
View File

@ -0,0 +1,187 @@
require 'modules.check_fullness'
local Event = require 'utils.event'
local Functions = require 'maps.amap.ic.functions'
local IC = require 'maps.amap.ic.table'
local Minimap = require 'maps.amap.ic.minimap'
local Public = {}
Public.reset = IC.reset
Public.get_table = IC.get
local function on_entity_died(event)
local entity = event.entity
if not entity or not entity.valid then
return
end
local ic = IC.get()
if entity.type == 'car' or entity.name == 'spidertron' then
Minimap.kill_minimap(game.players[event.player_index])
Functions.kill_car(ic, entity)
end
end
local function on_player_mined_entity(event)
local entity = event.entity
if not entity or not entity.valid then
return
end
local ic = IC.get()
--Minimap.kill_minimap(game.players[event.player_index])
if entity.type == 'car' or entity.name == 'spidertron' then
Functions.save_car(ic, event)
end
end
local function on_robot_mined_entity(event)
local entity = event.entity
if not entity and not entity.valid then
return
end
local ic = IC.get()
if entity.type == 'car' or entity.name == 'spidertron' then
Functions.kill_car(ic, entity)
end
end
local function on_built_entity(event)
local ce = event.created_entity
if not ce or not ce.valid then
return
end
if (ce.type == 'car' or ce.name == 'spidertron') ~= true then
return
end
local player = game.get_player(event.player_index)
if not player or not player.valid then
return
end
local ic = IC.get()
Functions.create_car(ic, event)
end
local function on_player_driving_changed_state(event)
local ic = IC.get()
local player = game.players[event.player_index]
Functions.use_door_with_entity(ic, player, event.entity)
Functions.validate_owner(ic, player, event.entity)
end
local function on_tick()
local ic = IC.get()
local tick = game.tick
if tick % 10 == 1 then
Functions.item_transfer(ic)
end
if tick % 240 == 0 then
Minimap.update_minimap()
end
if tick % 400 == 0 then
Functions.remove_invalid_cars(ic)
end
end
local function on_gui_closed(event)
local entity = event.entity
if not entity then
return
end
if not entity.valid then
return
end
if not entity.unit_number then
return
end
local ic = IC.get()
if not ic.cars[entity.unit_number] then
return
end
Minimap.kill_minimap(game.players[event.player_index])
end
local function on_gui_opened(event)
local entity = event.entity
if not entity or not entity.valid then
return
end
if not entity.unit_number then
return
end
local ic = IC.get()
local car = ic.cars[entity.unit_number]
if not car then
return
end
Minimap.minimap(
game.players[event.player_index],
car.surface,
{
car.area.left_top.x + (car.area.right_bottom.x - car.area.left_top.x) * 0.5,
car.area.left_top.y + (car.area.right_bottom.y - car.area.left_top.y) * 0.5
}
)
end
local function on_gui_click(event)
local element = event.element
if not element or not element.valid then
return
end
local player = game.get_player(event.player_index)
if not player or not player.valid then
return
end
if event.element.name == 'minimap_button' then
Minimap.minimap(player, false)
elseif event.element.name == 'minimap_frame' or event.element.name == 'minimap_toggle_frame' then
Minimap.toggle_minimap(event)
elseif event.element.name == 'switch_auto_map' then
Minimap.toggle_auto(player)
end
end
local function trigger_on_player_kicked_from_surface(data)
local player = data.player
local target = data.target
local this = data.this
Functions.kick_player_from_surface(this, player, target)
end
local function on_init()
Public.reset()
end
local changed_surface = Minimap.changed_surface
Event.on_init(on_init)
Event.add(defines.events.on_tick, on_tick)
Event.add(defines.events.on_gui_opened, on_gui_opened)
Event.add(defines.events.on_gui_closed, on_gui_closed)
Event.add(defines.events.on_player_driving_changed_state, on_player_driving_changed_state)
Event.add(defines.events.on_entity_died, on_entity_died)
Event.add(defines.events.on_built_entity, on_built_entity)
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)
Event.add(defines.events.on_robot_mined_entity, on_robot_mined_entity)
Event.add(defines.events.on_gui_click, on_gui_click)
Event.add(defines.events.on_player_changed_surface, changed_surface)
Event.add(IC.events.on_player_kicked_from_surface, trigger_on_player_kicked_from_surface)
return Public

258
maps/amap/ic/minimap.lua Normal file
View File

@ -0,0 +1,258 @@
local Public = {}
local ICT = require 'maps.amap.ic.table'
local Functions = require 'maps.amap.ic.functions'
local Gui = require 'maps.amap.ic.gui'
local function validate_player(player)
if not player then
return false
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.players[player.name] then
return false
end
return true
end
local function create_button(player)
local button =
player.gui.top.add(
{
type = 'sprite-button',
name = 'minimap_button',
sprite = 'utility/map',
tooltip = 'Open or close minimap.'
}
)
button.visible = false
end
function Public.toggle_button(player)
if not player.gui.top['minimap_button'] then
create_button(player)
end
local ic = ICT.get()
local button = player.gui.top['minimap_button']
if Functions.get_player_surface(ic, player) then
button.visible = true
else
button.visible = false
end
end
local function get_player_data(player)
local ic = ICT.get()
local player_data = ic.minimap[player.index]
if ic.minimap[player.index] then
return player_data
end
ic.minimap[player.index] = {
surface = ic.allowed_surface,
zoom = 0.30,
map_size = 360,
auto_map = true
}
return ic.minimap[player.index]
end
function Public.toggle_auto(player)
local ic = ICT.get()
local switch = player.gui.left.minimap_toggle_frame['switch_auto_map']
if not switch or not switch.valid then
return
end
if switch.switch_state == 'left' then
ic.minimap[player.index].auto_map = true
elseif switch.switch_state == 'right' then
ic.minimap[player.index].auto_map = false
end
end
local function kill_minimap(player)
local frame = player.gui.left.minimap_toggle_frame
if not frame or not frame.valid then
return
end
if frame.visible then
frame.destroy()
end
end
local function kill_frame(player)
if player.gui.left.minimap_toggle_frame then
local element = player.gui.left.minimap_toggle_frame.minimap_frame
if not element or not element.valid then
return
end
element.destroy()
end
end
local function draw_minimap(player, surface, position)
local ic = ICT.get()
surface = surface or game.surfaces[ic.allowed_surface]
if not surface or not surface.valid then
return
end
local cars = ic.cars
local entity = Functions.get_entity_from_player_surface(cars, player)
if not position then
if not entity or not entity.valid then
kill_minimap(player)
kill_frame(player)
return
end
end
position = position or entity.position
local player_data = get_player_data(player)
local frame = player.gui.left.minimap_toggle_frame
if not frame then
frame =
player.gui.left.add(
{type = 'frame', direction = 'vertical', name = 'minimap_toggle_frame', caption = 'Minimap'}
)
end
frame.visible = true
local element = frame['minimap_frame']
if not element then
element =
player.gui.left.minimap_toggle_frame.add(
{
type = 'camera',
name = 'minimap_frame',
position = position,
surface_index = surface.index,
zoom = player_data.zoom,
tooltip = 'LMB: Increase zoom level.\nRMB: Decrease zoom level.\nMMB: Toggle camera size.'
}
)
element.style.margin = 1
element.style.minimal_height = player_data.map_size
element.style.minimal_width = player_data.map_size
return
end
element.position = position
end
function Public.minimap(player, surface, position)
local frame = player.gui.left['minimap_toggle_frame']
local ic = ICT.get()
if frame and frame.visible then
kill_minimap(player)
else
if Functions.get_player_surface(ic, player) and not surface and not position then
draw_minimap(player)
else
draw_minimap(player, surface, position)
end
end
end
function Public.update_minimap()
local ic = ICT.get()
for k, player in pairs(game.connected_players) do
if Functions.get_player_surface(ic, player) and player.gui.left.minimap_toggle_frame then
kill_frame(player)
draw_minimap(player)
else
kill_minimap(player)
end
end
end
function Public.toggle_minimap(event)
local element = event.element
if not element then
return
end
if not element.valid then
return
end
if element.name ~= 'minimap_frame' then
return
end
local player = game.players[event.player_index]
local player_data = get_player_data(player)
if event.button == defines.mouse_button_type.right then
player_data.zoom = player_data.zoom - 0.07
if player_data.zoom < 0.07 then
player_data.zoom = 0.07
end
element.zoom = player_data.zoom
return
end
if event.button == defines.mouse_button_type.left then
player_data.zoom = player_data.zoom + 0.07
if player_data.zoom > 2 then
player_data.zoom = 2
end
element.zoom = player_data.zoom
return
end
if event.button == defines.mouse_button_type.middle then
player_data.map_size = player_data.map_size + 50
if player_data.map_size > 650 then
player_data.map_size = 250
end
element.style.minimal_height = player_data.map_size
element.style.minimal_width = player_data.map_size
element.style.maximal_height = player_data.map_size
element.style.maximal_width = player_data.map_size
return
end
end
function Public.changed_surface(event)
local player = game.players[event.player_index]
if not validate_player(player) then
return
end
local ic = ICT.get()
local surface = game.surfaces[ic.allowed_surface]
if not surface or not surface.valid then
return
end
local wd = player.gui.top['wave_defense']
local diff = player.gui.top['difficulty_gui']
if Functions.get_player_surface(ic, player) then
Public.toggle_button(player)
Public.minimap(player, surface)
if wd and wd.visible then
wd.visible = false
end
if diff and diff.visible then
diff.visible = false
end
elseif player.surface.index == surface.index then
Gui.remove_toolbar(player)
Public.toggle_button(player)
kill_minimap(player)
if wd and not wd.visible then
wd.visible = true
end
if diff and not diff.visible then
diff.visible = true
end
end
end
Public.kill_minimap = kill_minimap
return Public

87
maps/amap/ic/table.lua Normal file
View File

@ -0,0 +1,87 @@
local Global = require 'utils.global'
local Event = require 'utils.event'
local this = {}
Global.register(
this,
function(tbl)
this = tbl
end
)
local Public = {
events = {
on_player_kicked_from_surface = Event.generate_event_name('on_player_kicked_from_surface')
}
}
function Public.reset()
if this.surfaces then
for k, surface in pairs(this.surfaces) do
if surface and surface.valid then
game.delete_surface(surface)
end
end
end
for k, _ in pairs(this) do
this[k] = nil
end
this.debug_mode = false
this.restore_on_theft = false
this.doors = {}
this.cars = {}
this.current_car_index = nil
this.renders = {}
this.saved_surfaces = {}
this.allowed_surface = 'nauvis'
this.trust_system = {}
this.players = {}
this.surfaces = {}
this.minimap = {}
this.entity_type = {
['car'] = true,
['tank'] = true,
['spidertron'] = true,
['spider-vehicle'] = true
}
this.car_areas = {
['car'] = {left_top = {x = -20, y = 0}, right_bottom = {x = 20, y = 20}},
['tank'] = {left_top = {x = -30, y = 0}, right_bottom = {x = 30, y = 40}},
['spidertron'] = {left_top = {x = -40, y = 0}, right_bottom = {x = 40, y = 60}},
['spider-vehicle'] = {left_top = {x = -40, y = 0}, right_bottom = {x = 40, y = 60}}
}
end
function Public.get(key)
if key then
return this[key]
else
return this
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
function Public.set_car_area(tbl)
if not tbl then
return
end
this.car_areas = tbl
end
function Public.allowed_surface(value)
if value then
this.allowed_surface = value
end
return this.allowed_surface
end
return Public

157
maps/amap/loot.lua Normal file
View File

@ -0,0 +1,157 @@
local LootRaffle = require 'functions.loot_raffle'
local Public = {}
local random = math.random
local abs = math.abs
local floor = math.floor
local sqrt = math.sqrt
local blacklist = {
['atomic-bomb'] = true,
['cargo-wagon'] = true,
['car'] = true,
['tank'] = true,
['spidertron'] = true,
['locomotive'] = true,
['artillery-wagon'] = true,
['artillery-turret'] = true,
['landfill'] = true,
['discharge-defense-equipment'] = true,
['discharge-defense-remote'] = true,
['fluid-wagon'] = true,
['pistol'] = true
}
function Public.get_distance(position)
local difficulty = sqrt(position.x ^ 2 + position.y ^ 2) * 0.0001
return difficulty
end
function Public.add(surface, position, chest)
local budget = 48 + abs(position.y) * 1.75
budget = budget * random(25, 175) * 0.01
if random(1, 128) == 1 then
budget = budget * 4
chest = 'crash-site-chest-' .. random(1, 2)
end
if random(1, 256) == 1 then
budget = budget * 4
chest = 'crash-site-chest-' .. random(1, 2)
end
budget = floor(budget) + 1
local amount = random(1, 5)
local base_amount = 12 * amount
local distance_mod = Public.get_distance(position)
local result = base_amount + budget + distance_mod
local c = game.entity_prototypes[chest]
local slots = c.get_inventory_size(defines.inventory.chest)
local item_stacks = LootRaffle.roll(result, slots, blacklist)
local container = surface.create_entity({name = chest, position = position, force = 'neutral'})
for _, item_stack in pairs(item_stacks) do
container.insert(item_stack)
end
container.minable = false
if random(1, 8) == 1 then
container.insert({name = 'coin', count = random(1, 32)})
elseif random(1, 32) == 1 then
container.insert({name = 'coin', count = random(1, 128)})
elseif random(1, 128) == 1 then
container.insert({name = 'coin', count = random(1, 256)})
end
for _ = 1, 3, 1 do
if random(1, 8) == 1 then
container.insert({name = 'explosives', count = random(25, 50)})
else
break
end
end
end
function Public.add_rare(surface, position, chest, magic)
local budget = magic * 48 + abs(position.y) * 1.75
budget = budget * random(25, 175) * 0.01
if random(1, 128) == 1 then
budget = budget * 6
chest = 'crash-site-chest-' .. random(1, 2)
end
if random(1, 128) == 1 then
budget = budget * 6
chest = 'crash-site-chest-' .. random(1, 2)
end
local amount = random(1, 5)
local base_amount = 12 * amount
local distance_mod = Public.get_distance(position)
budget = floor(budget) + 1
local result = base_amount + budget + distance_mod
local c = game.entity_prototypes[chest]
local slots = c.get_inventory_size(defines.inventory.chest)
local item_stacks = LootRaffle.roll(result, slots, blacklist)
local container = surface.create_entity({name = chest, position = position, force = 'neutral'})
for _, item_stack in pairs(item_stacks) do
container.insert(item_stack)
end
container.minable = false
for _ = 1, 3, 1 do
if random(1, 8) == 1 then
container.insert({name = 'explosives', count = random(25, 50)})
else
break
end
end
end
function Public.cool(surface, position, chest, magic)
local budget = magic * 48 + abs(position.y) * 1.75
budget = budget * random(25, 175) * 0.01
if random(1, 128) == 1 then
budget = budget * 6
chest = 'crash-site-chest-' .. random(1, 2)
end
if random(1, 128) == 1 then
budget = budget * 6
chest = 'crash-site-chest-' .. random(1, 2)
end
local amount = random(1, 5)
local base_amount = 12 * amount
local distance_mod = Public.get_distance(position)
budget = floor(budget) + 1
local result = base_amount + budget + distance_mod
local c = game.entity_prototypes[chest]
local slots = c.get_inventory_size(defines.inventory.chest)
local item_stacks = LootRaffle.roll(result, slots, blacklist)
local container = surface.create_entity({name = chest, position = position, force = 'neutral'})
for _, item_stack in pairs(item_stacks) do
container.insert(item_stack)
end
for _ = 1, 3, 1 do
if random(1, 8) == 1 then
container.insert({name = 'explosives', count = random(25, 50)})
else
break
end
end
end
return Public

686
maps/amap/main.lua Normal file
View File

@ -0,0 +1,686 @@
require 'modules.rpg.main'
require 'maps.amap.relax'
require 'maps.amap.diff'
local Functions = require 'maps.amap.functions'
local IC = require 'maps.amap.ic.table'
local CS = require 'maps.amap.surface'
local Event = require 'utils.event'
local WD = require 'modules.wave_defense.table'
local wall_health = require 'maps.amap.wall_health_booster'.set_health_modifier
local spider_health =require 'maps.amap.spider_health_booster'.set_health_modifier
local Map = require 'modules.map_info'
local AntiGrief = require 'antigrief'
--local Explosives = require 'modules.explosives'
local WPT = require 'maps.amap.table'
local Autostash = require 'modules.autostash'
local BuriedEnemies = require 'maps.amap.buried_enemies'
local RPG_Settings = require 'modules.rpg.table'
local RPG_Func = require 'modules.rpg.functions'
local Commands = require 'commands.misc'
local Task = require 'utils.task'
local Token = require 'utils.token'
local Alert = require 'utils.alert'
local rock = require 'maps.amap.rock'
local Loot = require'maps.amap.loot'
local RPG = require 'modules.rpg.table'
local Difficulty = require 'modules.difficulty_vote_by_amount'
--local arty = require "maps.amap.enemy_arty"
--require 'maps.amap.burden'
require "modules.spawners_contain_biters"
require 'maps.amap.biters_yield_coins'
--require 'maps.amap.sort'
local Public = {}
local floor = math.floor
local remove = table.remove
--require 'modules.flamethrower_nerf'
--加载地形
require 'maps.amap.caves'
require 'modules.surrounded_by_worms'
require 'maps.amap.ic.main'
require 'modules.shotgun_buff'
require 'modules.no_deconstruction_of_neutral_entities'
require 'modules.wave_defense.main'
require 'modules.charging_station'
local init_new_force = function()
local new_force = game.forces.protectors
local enemy = game.forces.enemy
if not new_force then
new_force = game.create_force('protectors')
end
new_force.set_friend('enemy', true)
enemy.set_friend('protectors', true)
end
local setting = function()
--game.map_settings.enemy_evolution.destroy_factor = 0.004
-- game.map_settings.enemy_evolution.pollution_factor = 0.000003
game.map_settings.enemy_expansion.enabled = true
game.map_settings.enemy_expansion.min_expansion_cooldown = 6000
game.map_settings.enemy_expansion.max_expansion_cooldown = 104000
--game.map_settings.enemy_evolution.time_factor = 0.00004
game.map_settings.enemy_expansion.max_expansion_distance = 20
game.map_settings.enemy_expansion.settler_group_min_size = 5
game.map_settings.enemy_expansion.settler_group_max_size = 50
global.biter_health_boost_forces[game.forces.player.index] = 1
game.forces.player.set_ammo_damage_modifier("artillery-shell", 0)
game.forces.player.set_ammo_damage_modifier("melee", 0)
game.forces.player.set_ammo_damage_modifier("biological", 0)
local index = game.forces.player.index
wall_health(index,1)
spider_health(index,1)
end
function Public.reset_map()
local this = WPT.get()
local wave_defense_table = WD.get_table()
--创建一个地表
this.active_surface_index = CS.create_surface()
Autostash.insert_into_furnace(true)
Autostash.bottom_button(true)
BuriedEnemies.reset()
Commands.reset()
Commands.activate_custom_buttons(true)
Commands.bottom_right(false)
IC.reset()
IC.allowed_surface('amap')
game.reset_time_played()
WPT.reset_table()
--记得后面改为失去一半经验!并且修订技能!
local xp = {}
local rpg_t = RPG.get('rpg_t')
for k, p in pairs(game.connected_players) do
local player = game.connected_players[k]
xp[player.index]={}
xp[player.index] = rpg_t[player.index].xp / 3
if xp[player.index] > 5000 then
xp[player.index] = 5000
end
end
RPG_Func.rpg_reset_all_players()
for k, p in pairs(game.connected_players) do
local player = game.connected_players[k]
rpg_t[player.index].xp = xp[player.index]
xp[player.index]={}
end
RPG_Settings.set_surface_name('amap')
RPG_Settings.enable_health_and_mana_bars(true)
RPG_Settings.enable_wave_defense(true)
RPG_Settings.enable_mana(true)
RPG_Settings.enable_flame_boots(true)
RPG_Settings.enable_stone_path(true)
RPG_Settings.enable_one_punch(true)
RPG_Settings.enable_one_punch_globally(false)
RPG_Settings.enable_auto_allocate(true)
RPG_Settings.disable_cooldowns_on_spells()
--初始化部队
init_new_force()
--难度设置
local Diff = Difficulty.get()
Difficulty.reset_difficulty_poll({difficulty_poll_closing_timeout = game.tick + 36000})
Diff.gui_width = 20
local surface = game.surfaces[this.active_surface_index]
--Explosives.set_surface_whitelist({[surface.name] = true})
game.forces.player.set_spawn_position({0, 0}, surface)
local players = game.connected_players
for i = 1, #players do
local player = players[i]
Commands.insert_all_items(player)
end
--生产火箭发射井
rock.spawn(surface,{x=0,y=10})
rock.market(surface)
WD.reset_wave_defense()
wave_defense_table.surface_index = this.active_surface_index
--记得修改目标!
wave_defense_table.target = this.rock
wave_defense_table.nest_building_density = 32
wave_defense_table.game_lost = false
-- wave_defense_table.set_evolution_time = true
--生成随机位置!
local positions = {x = 200, y = 200}
positions.x = math.random(-200,200)
positions.y = math.random(-200,200)
if positions.y < 75 and positions.y > -75 then
if positions.y < 0 then
positions.y = positions.y - 100
else
positions.y = positions.y + 100
end
end
if positions.x < 75 and positions.x > -75 then
if positions.x < 0 then
positions.x = positions.x - 100
else
positions.x = positions.x + 100
end
end
wave_defense_table.spawn_position = positions
this.pos = positions
this.change = false
this.science = 0
--game.print(positions)
WD.alert_boss_wave(true)
WD.clear_corpses(false)
WD.remove_entities(true)
WD.enable_threat_log(true)
WD.set_disable_threat_below_zero(true)
WD.set_biter_health_boost(1.4)
-- WD.set().wave_interval = 3300
-- WD.set().threat_gain_multiplier = 4
WD.set().next_wave = game.tick + 7200* 15
--初始化虫子科技
Functions.disable_tech()
game.forces.player.set_spawn_position({0, 0}, surface)
Task.start_queue()
Task.set_queue_speed(16)
this.chunk_load_tick = game.tick + 1200
this.game_lost = false
this.last = 0
global.worm_distance = 210
global.average_worm_amount_per_chunk = 5
setting()
end
local on_init = function()
Public.reset_map()
local tooltip = {
[1] = ({'amap.easy'}),
[2] = ({'amap.med'}),
[3] = ({'amap.hard'})
}
Difficulty.set_tooltip(tooltip)
game.forces.player.research_queue_enabled = true
local T = Map.Pop_info()
T.localised_category = 'amap'
T.main_caption_color = {r = 150, g = 150, b = 0}
T.sub_caption_color = {r = 0, g = 150, b = 0}
--Explosives.set_whitelist_entity('character')
--Explosives.set_whitelist_entity('spidertron')
--Explosives.set_whitelist_entity('car')
--Explosives.set_whitelist_entity('tank')
--地图设置
--setting()
end
local is_player_valid = function()
local players = game.connected_players
for _, player in pairs(players) do
if player.connected and not player.character or not player.character.valid then
if not player.admin then
local player_data = Functions.get_player_data(player)
if player_data.died then
return
end
player.set_controller {type = defines.controllers.god}
player.create_character()
end
end
end
end
local has_the_game_ended = function()
local game_reset_tick = WPT.get('game_reset_tick')
if game_reset_tick then
if game_reset_tick < 0 then
return
end
local this = WPT.get()
this.game_reset_tick = this.game_reset_tick - 30
if this.game_reset_tick % 1800 == 0 then
if this.game_reset_tick > 0 then
local cause_msg
if this.restart then
cause_msg = 'restart'
end
game.print(({'main.reset_in', cause_msg, this.game_reset_tick / 60}), {r = 0.22, g = 0.88, b = 0.22})
end
if this.soft_reset and this.game_reset_tick == 0 then
this.game_reset_tick = nil
Public.reset_map()
return
end
end
end
end
local chunk_load = function()
local chunk_load_tick = WPT.get('chunk_load_tick')
if chunk_load_tick then
if chunk_load_tick < game.tick then
WPT.get().chunk_load_tick = nil
Task.set_queue_speed(2)
end
end
end
local rondom = function(player,many)
if not player.character or not player.character.valid then return end
if many >= 500 then
many = 500
end
local rpg_t = RPG.get('rpg_t')
local q = math.random(0,19)
local k = math.floor(many/100)
local get_point = k*5+5
if get_point >= 25 then
get_point = 25
end
if q == 16 then
if rpg_t[player.index].magicka < (get_point+10) then
q = 17
-- player.print({'amap.nopoint'})
-- player.remove_item{name='coin', count = '1000'}
else
rpg_t[player.index].magicka =rpg_t[player.index].magicka -get_point
player.print({'amap.nb16',get_point+10})
return
end
end
if q == 17 then
if rpg_t[player.index].dexterity < (get_point+10) then
q = 18
-- player.print({'amap.nopoint'})
-- player.remove_item{name='coin', count = '1000'}
else
rpg_t[player.index].dexterity = rpg_t[player.index].dexterity - get_point
player.print({'amap.nb17',get_point})
return
end
end
if q == 18 then
if rpg_t[player.index].vitality < (get_point+10) then
q = 15
-- player.print({'amap.nopoint'})
-- player.remove_item{name='coin', count = '1000'}
else
rpg_t[player.index].vitality = rpg_t[player.index].vitality -get_point
player.print({'amap.nb18',get_point})
return
end
end
if q == 15 then
if rpg_t[player.index].strength < (get_point+10) then
local money = 1000+1000*k
player.print({'amap.nopoint',money})
player.remove_item{name='coin', count = money}
return
else
rpg_t[player.index].strength = rpg_t[player.index].strength -get_point
player.print({'amap.nb15',get_point})
return
end
end
if q == 14 then
local luck = 50*k+50
if luck >= 400 then
luck = 400
end
Loot.cool(player.surface, player.surface.find_non_colliding_position("steel-chest", player.position, 20, 1, true) or player.position, 'steel-chest', luck)
player.print({'amap.nb14',luck})
return
elseif q == 13 then
local money = 10000+1000*k
player.insert{name='coin', count =money}
player.print({'amap.nb13',money})
return
elseif q == 12 then
local get_xp = 100+k*50
rpg_t[player.index].xp = rpg_t[player.index].xp +get_xp
player.print({'amap.nb12',get_xp})
return
elseif q == 11 then
local amount = 10+10*k
player.insert{name='distractor-capsule', count = amount}
player.print({'amap.nb11',amount})
return
elseif q == 10 then
local amount = 100+100*k
player.insert{name='raw-fish', count = amount}
player.print({'amap.nb10',amount})
return
elseif q == 9 then
player.insert{name='raw-fish', count = '1'}
player.print({'amap.nb9'})
return
elseif q == 8 then
local lost_xp = 2000+k*200
if rpg_t[player.index].xp < lost_xp then
rpg_t[player.index].xp = 0
return
else
rpg_t[player.index].xp = rpg_t[player.index].xp - lost_xp
player.print({'amap.nb8',lost_xp})
return
end
elseif q == 7 then
player.print({'amap.nb7'})
return
elseif q == 6 then
rpg_t[player.index].strength = rpg_t[player.index].strength + get_point
player.print({'amap.nb6',get_point})
return
elseif q == 5 then
player.print({'amap.nb5',get_point})
rpg_t[player.index].magicka =rpg_t[player.index].magicka +get_point
return
elseif q == 4 then
player.print({'amap.nb4',get_point})
rpg_t[player.index].dexterity = rpg_t[player.index].dexterity+get_point
return
elseif q == 3 then
player.print({'amap.nb3',get_point})
rpg_t[player.index].vitality = rpg_t[player.index].vitality+get_point
return
elseif q == 2 then
player.print({'amap.nb2',get_point})
rpg_t[player.index].points_to_distribute = rpg_t[player.index].points_to_distribute+get_point
return
elseif q == 1 then
local money = 1000+1000*k
player.print({'amap.nbone',money})
player.insert{name='coin', count = money}
return
elseif q == 0 then
local money = 1000+1000*k
player.print({'amap.sorry',money})
player.remove_item{name='coin', count = money}
return
elseif q == 19 then
player.print({'amap.what'})
return
end
end
local timereward = function()
local game_lost = WPT.get('game_lost')
if game_lost then
return
end
local this = WPT.get()
local last = this.last
local wave_number = WD.get('wave_number')
if last < wave_number then
if wave_number % 25 == 0 then
game.print({'amap.roll'},{r = 0.22, g = 0.88, b = 0.22})
--biterbuff()
for k, p in pairs(game.connected_players) do
local player = game.connected_players[k]
rondom(player,wave_number)
k=k+1
end
this.last = wave_number
end
end
end
local getrawrad = function()
local game_lost = WPT.get('game_lost')
if game_lost then
return
end
local this = WPT.get()
local wave_number = WD.get('wave_number')
if wave_number > this.number then
local rpg_t = RPG.get('rpg_t')
for k, p in pairs(game.connected_players) do
local player = game.connected_players[k]
rpg_t[player.index].xp = rpg_t[player.index].xp + 10
end
this.number = wave_number
-- game.print({'amap.getxpfromwave'})
end
end
local function calc_players()
local players = game.connected_players
local check_afk_players = WPT.get('check_afk_players')
if not check_afk_players then
return #players
end
local total = 0
for i = 1, #players do
local player = players[i]
if player.afk_time < 36000 then
total = total + 1
end
end
if total <= 0 then
total = 1
end
return total
end
local change = function()
local this = WPT.get()
local roll = this.roll
if this.change then
this.change = false
this.change_dist = false
if roll == 1 then
if this.pos.x < 0 then
this.pos.x = this.pos.x - 75
else
this.pos.x = this.pos.x + 75
end
elseif roll == 2 then
if this.pos.y < 0 then
this.pos.y = this.pos.y - 75
else
this.pos.y = this.pos.y + 75
end
elseif roll == 3 then
if this.pos.y < 0 then
this.pos.y = -this.pos.y + 75
else
this.pos.y = -this.pos.y - 75
end
elseif roll == 4 then
if this.pos.x < 0 then
this.pos.x = -this.pos.x + 75
else
this.pos.x = -this.pos.x - 75
end
elseif roll == 5 then
if this.pos.x < 0 then
this.pos.x = this.pos.x - 75
else
this.pos.x = this.pos.x + 75
end
if this.pos.y < 0 then
this.pos.y = this.pos.y - 75
else
this.pos.y = this.pos.y + 75
end
elseif roll == 6 then
if this.pos.y < 0 then
this.pos.y = -this.pos.y + 75
else
this.pos.y = -this.pos.y - 75
end
if this.pos.x < 0 then
this.pos.x = -this.pos.x + 75
else
this.pos.x = -this.pos.x - 75
end
end
end
if this.change_dist then
this.change_dist = false
local k = roll
if k == 1 then
this.pos.y = -this.pos.y
this.pos.x = -this.pos.x
elseif k == 2 then
this.pos.y = -this.pos.y
elseif k == 3 then
this.pos.x = -this.pos.x
elseif k == 4 then
this.pos.y = -this.pos.y
elseif k == 5 then
this.pos.y = -this.pos.y
this.pos.x = -this.pos.x
elseif k == 6 then
this.pos.x = -this.pos.x
end
end
end
local single_rewrad = function()
local game_lost = WPT.get('game_lost')
if game_lost then
return
end
local wave_number = WD.get('wave_number')
if wave_number >= 10 then
return
end
local rpg_t = RPG.get('rpg_t')
local this = WPT.get()
local player_count = calc_players()
if this.single and player_count <= 2 and not this.first then
for k, p in pairs(game.connected_players) do
local player = game.connected_players[k]
rpg_t[player.index].points_to_distribute = rpg_t[player.index].points_to_distribute + 200
rpg_t[player.index].xp= rpg_t[player.index].xp+5000
player.insert{name='coin', count = 10000}
player.insert{name='tank', count = 1}
game.print({'amap.single'})
this.single = false
end
end
this.first = false
end
local on_tick = function()
local tick = game.tick
if tick % 40 == 0 then
-- pos()
--bigermap()
-- has_the_game_ended()
is_player_valid()
chunk_load()
timereward()
getrawrad()
-- biterup()
end
if tick % 500 == 0 then
change()
end
if tick % 600 == 0 then
local this = WPT.get()
local wave_defense_table = WD.get_table()
local roll = this.roll
wave_defense_table.spawn_position = this.pos
if this.roll == 6 then
this.roll = 1
end
this.roll=this.roll+1
end
end
function on_research_finished(Event)
local this = WPT.get()
this.science=this.science+1
local rpg_t = RPG.get('rpg_t')
for k, p in pairs(game.connected_players) do
local player = game.connected_players[k]
local point = math.floor(math.random(1,5))
local money = math.floor(math.random(1,100))
rpg_t[player.index].points_to_distribute = rpg_t[player.index].points_to_distribute+point
player.insert{name='coin', count = money}
-- player.print({'amap.science',point,money}, {r = 0.22, g = 0.88, b = 0.22})
Alert.alert_player(player, 5, {'amap.science',point,money})
k=k+1
end
end
local on_player_joined_game = function()
local player_count = calc_players()
if player_count <= 4 then
RPG_Settings.points_per_level = 10
else
RPG_Settings.points_per_level = 5
end
end
local on_player_left_game = function()
local player_count = calc_players()
if player_count <= 4 then
RPG_Settings.points_per_level = 10
else
RPG_Settings.points_per_level = 5
end
end
local change_dis = function()
local this = WPT.get()
this.change_dist=true
end
Event.add_event_filter(defines.events.on_entity_damaged, {filter = 'final-damage-amount', comparison = '>', value = 0})
Event.on_init(on_init)
Event.on_nth_tick(10, on_tick)
Event.on_nth_tick(7200, single_rewrad)
Event.on_nth_tick(60, change_dis)
--Event.add(defines.events.on_player_joined_game, on_player_joined_game)
--Event.add(defines.events.on_pre_player_left_game, on_player_left_game)
Event.add(defines.events.on_research_finished, on_research_finished)
return Public

31
maps/amap/relax.lua Normal file
View File

@ -0,0 +1,31 @@
local Event = require 'utils.event'
local msg = {
[1] = {'amap.relax1'},
[2] = {'amap.relax2'},
[3] = {'amap.relax3'},
[4] = {'amap.relax4'},
[5] = {'amap.relax5'},
[6] = {'amap.relax6'},
[7] = {'amap.relax7'},
[8] = {'amap.relax8'},
[9] = {'amap.relax9'},
[10] = {'amap.relax10'},
[11] = {'amap.relax11'},
[12] = {'amap.relax12'},
[13] = {'amap.relax13'},
[14] = {'amap.relax14'},
[15] = {'amap.relax15'},
[16] = {'amap.relax16'},
[17] = {'amap.relax17'},
[18] = {'amap.relax18'},
[19] = {'amap.relax19'},
[20] = {'amap.relax20'},
}
local on_tick = function()
local roll = math.random(1, #msg)
game.print(msg[roll],{r = 0.22, g = 0.88, b = 0.22})
end
Event.on_nth_tick(108000, on_tick)

270
maps/amap/rock.lua Normal file
View File

@ -0,0 +1,270 @@
local WPT = require 'maps.amap.table'
local Event = require 'utils.event'
local Public = {}
local Alert = require 'utils.alert'
local WD = require 'modules.wave_defense.table'
local RPG = require 'modules.rpg.table'
local wave_defense_table = WD.get_table()
local Task = require 'utils.task'
local Server = require 'utils.server'
local wall_health = require 'maps.amap.wall_health_booster'.set_health_modifier
local spider_health =require 'maps.amap.spider_health_booster'.set_health_modifier
local urgrade_item = function(market)
local this = WPT.get()
local pirce_wall=this.health*1000 + 10000
local pirce_arty=this.arty*1000 +10000
local biter_health=this.biter_health*1000 + 7000
local spider_health=this.spider_health*1000 + 10000
local pirce_biter_dam=this.biter_dam*1000 +7000
if pirce_arty >= 50000 then
pirce_arty = 50000
end
if pirce_wall >= 50000 then
pirce_wall = 50000
end
if biter_health >= 50000 then
biter_health = 50000
end
if spider_health >= 50000 then
spider_health = 50000
end
if pirce_biter_dam >= 50000 then
pirce_biter_dam = 50000
end
local health_wall = {price = {{"coin", pirce_wall}}, offer = {type = 'nothing', effect_description = {'amap.buy_health_wall'}}}
local arty_dam = {price = {{"coin", pirce_arty}}, offer = {type = 'nothing', effect_description = {'amap.buy_arty_dam'}}}
local player_biter_health={price = {{"coin", biter_health}}, offer = {type = 'nothing', effect_description = {'amap.player_biter_health'}}}
local spider_buy={price = {{"coin", spider_health}}, offer = {type = 'nothing', effect_description = {'amap.player_spider_health'}}}
local biter_dam={price = {{"coin", pirce_biter_dam}}, offer = {type = 'nothing', effect_description = {'amap.player_biter_dam'}}}
local buy_cap={price = {{"coin", 50000}}, offer = {type = 'nothing', effect_description = {'amap.buy_cap'}}}
market.add_market_item(health_wall)
market.add_market_item(arty_dam)
market.add_market_item(player_biter_health)
market.add_market_item(spider_buy)
market.add_market_item(biter_dam)
market.add_market_item(buy_cap)
end
local market_items = {
{price = {{"coin", 5}}, offer = {type = 'give-item', item = "raw-fish", count = 1}},
{price = {{"coin", 2000}}, offer = {type = 'give-item', item = 'car', count = 1}},
{price = {{"coin", 15000}}, offer = {type = 'give-item', item = 'tank', count = 1}},
{price = {{"coin", 60000}}, offer = {type = 'give-item', item = 'spidertron', count = 1}},
{price = {{"coin", 500}}, offer = {type = 'give-item', item = 'spidertron-remote', count = 1}},
--{price = {{"coin", 5000}}, offer = {type = 'give-item', item = 'locomotive', count = 1}},
--{price = {{"coin", 5000}}, offer = {type = 'give-item', item = 'cargo-wagon', count = 1}},
--{price = {{"coin", 5000}}, offer = {type = 'give-item', item = 'fluid-wagon', count = 1}}
{price = {{"coin", 25000}}, offer = {type = 'give-item', item = 'tank-cannon', count = 1}},
{price = {{"coin", 128}}, offer = {type = 'give-item', item = 'loader', count = 1}},
{price = {{"coin", 512}}, offer = {type = 'give-item', item = 'fast-loader', count = 1}},
{price = {{"coin", 4096}}, offer = {type = 'give-item', item = 'express-loader', count = 1}},
{price = {{"raw-fish", 1}}, offer = {type = 'give-item', item = 'coin', count = 5}},
{price = {{"coin", 5000}}, offer = {type = 'give-item', item = 'flamethrower-turret', count = 1}},
}
function Public.spawn(surface, position)
local this = WPT.get()
this.rock = surface.create_entity{name = "rocket-silo", position = position, force=game.forces.player}
this.rock.minable = false
game.forces.player.set_spawn_position({0,0}, surface)
end
function Public.market(surface)
local this = WPT.get()
local market = surface.create_entity{name = "market", position = {x=0, y=-10}, force=game.forces.player}
market.last_user = nil
if market ~= nil then
market.destructible = false
if market ~= nil then
game.print(1)
urgrade_item(market)
for _, item in pairs(market_items) do
market.add_market_item(item)
end
end
end
end
local function on_rocket_launched(Event)
local this = WPT.get()
--game.print({'amap.times',this.times})
local rpg_t = RPG.get('rpg_t')
--local money = 1000 + this.times*1000
local money = 10000
local point = 1
-- if money >= 50000 then
-- money = 50000
-- end
-- if point >= 100 then
-- point = 100
-- end
for k, p in pairs(game.connected_players) do
local player = game.connected_players[k]
rpg_t[player.index].points_to_distribute = rpg_t[player.index].points_to_distribute+point
player.insert{name='coin', count = money}
player.print({'amap.reward',this.times,point,money}, {r = 0.22, g = 0.88, b = 0.22})
end
if not this.pass then
local wave_number = WD.get('wave_number')
local msg = {'amap.pass',wave_number}
for k, p in pairs(game.connected_players) do
local player = game.connected_players[k]
Alert.alert_player(player, 25, msg)
end
Server.to_discord_embed(table.concat({'** we win the game ! Record is ', wave_number}))
this.pass = true
end
this.times=this.times+1
end
local function on_entity_died(Event)
local this = WPT.get()
if Event.entity == this.rock then
for _, player in pairs(game.connected_players) do
player.play_sound {path = 'utility/game_lost', volume_modifier = 0.75}
end
--game.print({'amap.lost',wave_number}),{r = 1, g = 0, b = 0, a = 0.5})
local wave_number = WD.get('wave_number')
local msg = {'amap.lost',wave_number}
for _, p in pairs(game.connected_players) do
Alert.alert_player(p, 25, msg)
end
Server.to_discord_embed(table.concat({'** we lost the game ! Record is ', wave_number}))
local Reset_map = require 'maps.amap.main'.reset_map
wave_defense_table.game_lost = true
wave_defense_table.target = nil
-- game.forces.enemy.set_friend('player', true)
--game.print('设置右军友好')
-- game.forces.player.set_friend('enemy', true)
--game.print('设置敌军友好')
--local game_reset_tick = WPT.get('game_reset_tick')
-- game.print('GG,游戏结束,稍后自动重启',{r = 0.99, g = 0.00, b = 0.22})
-- this.game_reset_tick = 5400
Reset_map()
--abc()
end
end
local function on_market_item_purchased(event)
local player = game.players[event.player_index]
local market = event.market
local offer_index = event.offer_index
local count = event.count
local offers = market.get_market_items()
local bought_offer = offers[offer_index].offer
local this = WPT.get()
local index = game.forces.player.index
if bought_offer.type ~= "nothing" then return end
if offer_index == 1 then
local wave_number = WD.get('wave_number')
local times = math.floor(wave_number/100)+this.cap
if this.health >= times then
player.print({'amap.cap_upgrad'})
local pirce_wall=this.health*1000 + 10000
if pirce_wall >= 50000 then
pirce_wall = 50000
end
player.insert{name='coin',count = pirce_wall}
return
end
this.health=this.health+1
wall_health(index,this.health*0.1+1.1)
game.print({'amap.buy_wall_over',player.name,this.health*0.1+1})
end
if offer_index == 2 then
this.arty=this.arty+1
game.forces.player.set_ammo_damage_modifier("artillery-shell", this.arty*0.1)
game.print({'amap.buy_arty_over',player.name,this.arty*0.1+1})
end
if offer_index == 3 then
local wave_number = WD.get('wave_number')
local times = math.floor(wave_number/50)+this.cap
if this.biter_health >= times then
player.print({'amap.cap_upgrad'})
local pirce_biter_dam=this.biter_health*1000 +7000
if pirce_biter_dam >= 50000 then
pirce_biter_dam = 50000
end
player.insert{name='coin',count = pirce_biter_dam}
return
end
this.biter_health=this.biter_health+1
global.biter_health_boost_forces[game.forces.player.index] = this.biter_health*0.1+1
game.print({'amap.buy_player_biter_over',player.name,this.biter_health*0.1+1})
end
if offer_index == 4 then
local wave_number = WD.get('wave_number')
local times = math.floor(wave_number/100)+this.cap
if this.spider_health >= times then
player.print({'amap.cap_upgrad'})
local spider_health=this.spider_health*1000 + 10000
if spider_health >= 50000 then
spider_health = 50000
end
player.insert{name='coin',count = spider_health}
return
end
this.spider_health=this.spider_health+1
spider_health(index,this.spider_health*0.1+1.1)
game.print({'amap.buy_spider_health_over',player.name,this.spider_health*0.1+1})
end
if offer_index == 5 then
local wave_number = WD.get('wave_number')
local times = math.floor(wave_number/100)+this.cap+1
if times >= 30 then
times = 30
end
if this.biter_dam >= times then
player.print({'amap.cap_upgrad'})
local pirce_biter_dam=this.biter_dam*1000 +7000
if pirce_biter_dam >= 50000 then
pirce_biter_dam = 50000
end
player.insert{name='coin',count = pirce_biter_dam}
return
end
this.biter_dam=this.biter_dam+1
local damage_increase = this.biter_dam*0.1
game.forces.player.set_ammo_damage_modifier("melee", damage_increase)
game.forces.player.set_ammo_damage_modifier("biological", damage_increase)
game.print({'amap.buy_biter_dam',player.name,this.biter_dam*0.1+1})
end
if offer_index == 6 then
this.cap=this.cap+1
game.print({'amap.buy_cap_over',player.name,this.cap})
end
market.force.play_sound({path = 'utility/new_objective', volume_modifier = 0.75})
market.clear_market_items()
urgrade_item(market)
for k, item in pairs(market_items) do
market.add_market_item(item)
end
end
Event.add(defines.events.on_rocket_launched, on_rocket_launched)
Event.add(defines.events.on_entity_died, on_entity_died)
Event.add(defines.events.on_market_item_purchased,on_market_item_purchased)
return Public

View File

@ -0,0 +1,177 @@
--destroying and mining rocks yields ore -- load as last module
local max_spill = 60
local math_random = math.random
local math_floor = math.floor
local math_sqrt = math.sqrt
local rock_yield = {
["rock-big"] = 1,
["rock-huge"] = 2,
["sand-rock-big"] = 1
}
local particles = {
["iron-ore"] = "iron-ore-particle",
["copper-ore"] = "copper-ore-particle",
["uranium-ore"] = "coal-particle",
["coal"] = "coal-particle",
["stone"] = "stone-particle",
["angels-ore1"] = "iron-ore-particle",
["angels-ore2"] = "copper-ore-particle",
["angels-ore3"] = "coal-particle",
["angels-ore4"] = "iron-ore-particle",
["angels-ore5"] = "iron-ore-particle",
["angels-ore6"] = "iron-ore-particle",
}
local function get_chances()
local chances = {}
if game.entity_prototypes["angels-ore1"] then
for i = 1, 6, 1 do
table.insert(chances, {"angels-ore" .. i, 1})
end
table.insert(chances, {"coal", 2})
return chances
end
table.insert(chances, {"iron-ore", 25})
table.insert(chances, {"copper-ore",17})
table.insert(chances, {"coal",13})
table.insert(chances, {"uranium-ore",2})
table.insert(chances, {"stone",7})
return chances
end
local function set_raffle()
global.rocks_yield_ore["raffle"] = {}
for _, t in pairs(get_chances()) do
for x = 1, t[2], 1 do
table.insert(global.rocks_yield_ore["raffle"], t[1])
end
end
global.rocks_yield_ore["size_of_raffle"] = #global.rocks_yield_ore["raffle"]
end
local function create_particles(surface, name, position, amount, cause_position)
local direction_mod = (-100 + math_random(0,200)) * 0.0004
local direction_mod_2 = (-100 + math_random(0,200)) * 0.0004
if cause_position then
direction_mod = (cause_position.x - position.x) * 0.025
direction_mod_2 = (cause_position.y - position.y) * 0.025
end
for i = 1, amount, 1 do
local m = math_random(4, 10)
local m2 = m * 0.005
surface.create_particle({
name = name,
position = position,
frame_speed = 1,
vertical_speed = 0.130,
height = 0,
movement = {
(m2 - (math_random(0, m) * 0.01)) + direction_mod,
(m2 - (math_random(0, m) * 0.01)) + direction_mod_2
}
})
end
end
local function get_amount(entity)
local distance_to_center = math_floor(math_sqrt(entity.position.x ^ 2 + entity.position.y ^ 2))
local amount = global.rocks_yield_ore_base_amount + (distance_to_center * global.rocks_yield_ore_distance_modifier)
if amount > global.rocks_yield_ore_maximum_amount then amount = global.rocks_yield_ore_maximum_amount end
local m = (70 + math_random(0, 60)) * 0.01
amount = math_floor(amount * rock_yield[entity.name] * m)
if amount < 1 then amount = 1 end
return amount
end
local function on_player_mined_entity(event)
local entity = event.entity
if not entity.valid then return end
if not rock_yield[entity.name] then return end
local player = game.players[event.player_index]
if not player or not player.valid then
return
end
event.buffer.clear()
local ore = global.rocks_yield_ore["raffle"][math_random(1, global.rocks_yield_ore["size_of_raffle"])]
local player = game.players[event.player_index]
local count = get_amount(entity)
count = math_floor(count * (1 + player.force.mining_drill_productivity_bonus))
global.rocks_yield_ore["ores_mined"] = global.rocks_yield_ore["ores_mined"] + count
global.rocks_yield_ore["rocks_broken"] = global.rocks_yield_ore["rocks_broken"] + 1
local position = {x = entity.position.x, y = entity.position.y}
local ore_amount = math_floor(count * 0.85) + 1
local stone_amount = math_floor(count * 0.15) + 1
player.surface.create_entity({name = "flying-text", position = position, text = "+" .. ore_amount .. " [img=item/" .. ore .. "]", color = {r = 200, g = 160, b = 30}})
create_particles(player.surface, particles[ore], position, 64, {x = player.position.x, y = player.position.y})
entity.destroy()
if ore_amount > max_spill then
local k = player.insert({name = ore, count = ore_amount})
ore_amount = ore_amount - k
if ore_amount > 0 then
-- player.surface.spill_item_stack(position,{name = ore, count = ore_amount}, true)
player.character.health = player.character.health - player.character.health*0.2 - 100
player.print({'amap.bag_isfull'},{r = 200, g = 0, b = 30})
end
else
player.surface.spill_item_stack(position,{name = ore, count = ore_amount}, true)
end
end
local function on_entity_died(event)
local entity = event.entity
if not entity.valid then return end
if not rock_yield[entity.name] then return end
local surface = entity.surface
local ore = global.rocks_yield_ore["raffle"][math_random(1, global.rocks_yield_ore["size_of_raffle"])]
local pos = {entity.position.x, entity.position.y}
create_particles(surface, particles[ore], pos, 16, false)
if event.cause then
if event.cause.valid then
if event.cause.force.index == 2 or event.cause.force.index == 3 then
entity.destroy()
return
end
end
end
entity.destroy()
end
local function on_init()
global.rocks_yield_ore = {}
global.rocks_yield_ore["rocks_broken"] = 0
global.rocks_yield_ore["ores_mined"] = 0
set_raffle()
if not global.rocks_yield_ore_distance_modifier then global.rocks_yield_ore_distance_modifier = 0.25 end
if not global.rocks_yield_ore_base_amount then global.rocks_yield_ore_base_amount = 35 end
if not global.rocks_yield_ore_maximum_amount then global.rocks_yield_ore_maximum_amount = 150 end
end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.add(defines.events.on_entity_died, on_entity_died)
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)

114
maps/amap/soft_reset.lua Normal file
View File

@ -0,0 +1,114 @@
local Server = require 'utils.server'
local Session = require 'utils.datastore.session_data'
local Modifers = require 'player_modifiers'
local WPT = require 'maps.amap.table'
local mapkeeper = '[color=blue]Mapkeeper:[/color]'
local Public = {}
local function reset_forces(new_surface, old_surface)
for _, f in pairs(game.forces) do
local spawn = {
x = game.forces.player.get_spawn_position(old_surface).x,
y = game.forces.player.get_spawn_position(old_surface).y
}
f.reset()
f.reset_evolution()
f.set_spawn_position(spawn, new_surface)
end
for _, tech in pairs(game.forces.player.technologies) do
tech.researched = false
game.forces.player.set_saved_technology_progress(tech, 0)
end
end
local function teleport_players(surface)
game.forces.player.set_spawn_position({-27, 25}, surface)
for _, player in pairs(game.connected_players) do
player.teleport(
surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(surface), 3, 0, 5),
surface
)
end
end
local function equip_players(player_starting_items, data)
for k, player in pairs(game.players) do
if player.character and player.character.valid then
player.character.destroy()
end
if player.connected then
if not player.character then
player.set_controller({type = defines.controllers.god})
player.create_character()
end
player.clear_items_inside()
Modifers.update_player_modifiers(player)
for item, amount in pairs(player_starting_items) do
player.insert({name = item, count = amount})
end
else
data.players[player.index] = nil
Session.clear_player(player)
game.remove_offline_players({player.index})
end
end
end
function Public.soft_reset_map(old_surface, map_gen_settings, player_starting_items)
local this = WPT.get()
if not this.soft_reset_counter then
this.soft_reset_counter = 0
end
if not this.original_surface_name then
this.original_surface_name = old_surface.name
end
this.soft_reset_counter = this.soft_reset_counter + 1
local new_surface =
game.create_surface(this.original_surface_name .. '_' .. tostring(this.soft_reset_counter), map_gen_settings)
new_surface.request_to_generate_chunks({0, 0}, 0.5)
new_surface.force_generate_chunk_requests()
reset_forces(new_surface, old_surface)
teleport_players(new_surface)
equip_players(player_starting_items, this)
game.delete_surface(old_surface)
local radius = 512
local area = {{x = -radius, y = -radius}, {x = radius, y = radius}}
for _, entity in pairs(new_surface.find_entities_filtered {area = area, type = 'logistic-robot'}) do
entity.destroy()
end
for _, entity in pairs(new_surface.find_entities_filtered {area = area, type = 'construction-robot'}) do
entity.destroy()
end
local message = table.concat({mapkeeper .. ' Welcome to ', this.original_surface_name, '!'})
local message_to_discord = table.concat({'** Welcome to ', this.original_surface_name, '! **'})
if this.soft_reset_counter > 1 then
message =
table.concat(
{
mapkeeper,
' The world has been reshaped, welcome to ',
this.original_surface_name,
' number ',
tostring(this.soft_reset_counter),
'!'
}
)
end
game.print(message, {r = 0.98, g = 0.66, b = 0.22})
Server.to_discord_embed(message_to_discord)
return new_surface
end
return Public

482
maps/amap/sort.lua Normal file
View File

@ -0,0 +1,482 @@
--this adds a button that stashes/sorts your inventory into nearby chests in some kind of intelligent way - mewmew
-- modified by gerkiz
local Global = require 'utils.global'
local Event = require 'utils.event'
local math_floor = math.floor
local print_color = {r = 120, g = 255, b = 0}
local autostash = {
floating_text_y_offsets = {},
whitelist = {},
insert_into_wagon = false
}
local Public = {}
Global.register(
autostash,
function(t)
autostash = t
end
)
local function create_floaty_text(surface, position, name, count)
if autostash.floating_text_y_offsets[position.x .. '_' .. position.y] then
autostash.floating_text_y_offsets[position.x .. '_' .. position.y] =
autostash.floating_text_y_offsets[position.x .. '_' .. position.y] - 0.5
else
autostash.floating_text_y_offsets[position.x .. '_' .. position.y] = 0
end
surface.create_entity(
{
name = 'flying-text',
position = {
position.x,
position.y + autostash.floating_text_y_offsets[position.x .. '_' .. position.y]
},
text = {'', '-', count, ' ', game.item_prototypes[name].localised_name},
color = {r = 255, g = 255, b = 255}
}
)
end
local function chest_is_valid(chest)
if chest.type == 'cargo-wagon' then
local t = {}
local chest_inventory = chest.get_inventory(defines.inventory.cargo_wagon)
for index = 1, 40 do
if chest_inventory.get_filter(index) ~= nil then
local n = chest_inventory.get_filter(index)
t[n] = true
end
end
if not next(t) then
return false, {}
end
return true, t
end
for _, e in pairs(
chest.surface.find_entities_filtered(
{
type = {'inserter', 'loader'},
area = {{chest.position.x - 1, chest.position.y - 1}, {chest.position.x + 1, chest.position.y + 1}}
}
)
) do
if e.name ~= 'long-handed-inserter' then
if e.position.x == chest.position.x then
if e.direction == 0 or e.direction == 4 then
return false
end
end
if e.position.y == chest.position.y then
if e.direction == 2 or e.direction == 6 then
return false
end
end
end
end
local i1 = chest.surface.find_entity('long-handed-inserter', {chest.position.x - 2, chest.position.y})
if i1 then
if i1.direction == 2 or i1.direction == 6 then
return false
end
end
local i2 = chest.surface.find_entity('long-handed-inserter', {chest.position.x + 2, chest.position.y})
if i2 then
if i2.direction == 2 or i2.direction == 6 then
return false
end
end
local i3 = chest.surface.find_entity('long-handed-inserter', {chest.position.x, chest.position.y - 2})
if i3 then
if i3.direction == 0 or i3.direction == 4 then
return false
end
end
local i4 = chest.surface.find_entity('long-handed-inserter', {chest.position.x, chest.position.y + 2})
if i4 then
if i4.direction == 0 or i4.direction == 4 then
return false
end
end
return true
end
local function sort_entities_by_distance(position, entities)
local t = {}
local distance
local index
local size_of_entities = #entities
if size_of_entities < 2 then
return
end
for _, entity in pairs(entities) do
distance = (entity.position.x - position.x) ^ 2 + (entity.position.y - position.y) ^ 2
index = math_floor(distance) + 1
if not t[index] then
t[index] = {}
end
table.insert(t[index], entity)
end
local i = 0
for _, range in pairs(t) do
for _, entity in pairs(range) do
i = i + 1
entities[i] = entity
end
end
end
local function get_nearby_chests(player, a)
local r = player.force.character_reach_distance_bonus + 10
local r_square = r * r
local chests = {}
local size_of_chests = 0
local area = {{player.position.x - r, player.position.y - r}, {player.position.x + r, player.position.y + r}}
area = a or area
local container_type = {'container', 'logistic-container', 'furnace'}
local containers = {}
local i = 0
if autostash.insert_into_wagon then
table.insert(container_type, 'cargo-wagon')
end
for _, e in pairs(player.surface.find_entities_filtered({type = container_type, area = area, force = 'player'})) do
if ((player.position.x - e.position.x) ^ 2 + (player.position.y - e.position.y) ^ 2) <= r_square then
i = i + 1
containers[i] = e
end
end
sort_entities_by_distance(player.position, containers)
for _, entity in pairs(containers) do
size_of_chests = size_of_chests + 1
chests[size_of_chests] = entity
end
return chests
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_item_into_chest(player_inventory, chests, filtered_chests, name, count, wagon)
local container = {
['container'] = true,
['logistic-container'] = true
}
local to_insert = math.floor(count / #chests)
local variator = count % #chests
if wagon then
-- Attempt to load filtered cargo wagon
for _, chest in pairs(chests) do
if chest.type == 'cargo-wagon' then
local chest_inventory = chest.get_inventory(defines.inventory.cargo_wagon)
if chest_inventory.can_insert({name = name, count = count}) then
local inserted_count = chest_inventory.insert({name = name, count = count})
player_inventory.remove({name = name, count = inserted_count})
create_floaty_text(chest.surface, chest.position, name, inserted_count)
count = count - inserted_count
if count <= 0 then
return
end
end
end
end
end
--Attempt to store into furnaces.
for _, chest in pairs(chests) do
local chest_inventory = chest.get_inventory(defines.inventory.furnace_source)
if chest_inventory and chest.type == 'furnace' then
if chest_inventory.can_insert({name = name, count = count}) then
local inserted_count = chest_inventory.insert({name = name, count = count})
player_inventory.remove({name = name, count = inserted_count})
create_floaty_text(chest.surface, chest.position, name, inserted_count)
count = count - inserted_count
if count <= 0 then
return
end
end
end
end
for _, chest in pairs(chests) do
if chest.type == 'furnace' then
local amount = to_insert
if variator > 0 then
amount = amount + 1
variator = variator - 1
end
if amount <= 0 then
return
end
local chest_inventory = chest.get_inventory(defines.inventory.chest)
if chest_inventory.can_insert({name = name, count = amount}) then
local inserted_count = chest_inventory.insert({name = name, count = amount})
player_inventory.remove({name = name, count = inserted_count})
create_floaty_text(chest.surface, chest.position, name, inserted_count)
end
end
end
--Attempt to store in chests that already have the same item.
for _, chest in pairs(chests) do
if container[chest.type] then
local chest_inventory = chest.get_inventory(defines.inventory.chest)
if chest_inventory.can_insert({name = name, count = count}) then
if chest_inventory.find_item_stack(name) then
local inserted_count = chest_inventory.insert({name = name, count = count})
player_inventory.remove({name = name, count = inserted_count})
create_floaty_text(chest.surface, chest.position, name, inserted_count)
count = count - inserted_count
if count <= 0 then
return
end
end
end
end
end
--Attempt to store in empty chests.
for _, chest in pairs(filtered_chests) do
if container[chest.type] then
local chest_inventory = chest.get_inventory(defines.inventory.chest)
if chest_inventory.can_insert({name = name, count = count}) then
if chest_inventory.is_empty() then
local inserted_count = chest_inventory.insert({name = name, count = count})
player_inventory.remove({name = name, count = inserted_count})
create_floaty_text(chest.surface, chest.position, name, inserted_count)
count = count - inserted_count
if count <= 0 then
return
end
end
end
end
end
--Attempt to store in chests with same item subgroup.
local item_subgroup = game.item_prototypes[name].subgroup.name
if item_subgroup then
for _, chest in pairs(filtered_chests) do
if container[chest.type] then
local chest_inventory = chest.get_inventory(defines.inventory.chest)
if chest_inventory.can_insert({name = name, count = count}) then
if does_inventory_contain_item_type(chest_inventory, item_subgroup) then
local inserted_count = chest_inventory.insert({name = name, count = count})
player_inventory.remove({name = name, count = inserted_count})
create_floaty_text(chest.surface, chest.position, name, inserted_count)
count = count - inserted_count
if count <= 0 then
return
end
end
end
end
end
end
--Attempt to store in mixed chests.
for _, chest in pairs(filtered_chests) do
if container[chest.type] then
local chest_inventory = chest.get_inventory(defines.inventory.chest)
if chest_inventory.can_insert({name = name, count = count}) then
local inserted_count = chest_inventory.insert({name = name, count = count})
player_inventory.remove({name = name, count = inserted_count})
create_floaty_text(chest.surface, chest.position, name, inserted_count)
count = count - inserted_count
if count <= 0 then
return
end
end
end
end
end
local function auto_stash(player, event)
local button = event.button
local shift = event.shift
if not player.character then
player.print('It seems that you are not in the realm of the living.', print_color)
return
end
if not player.character.valid then
player.print('It seems that you are not in the realm of the living.', print_color)
return
end
local inventory = player.get_inventory(defines.inventory.character_main)
if inventory.is_empty() then
player.print('Inventory is empty.', print_color)
return
end
local chests
local r = 1
local area = {{player.position.x - r, player.position.y - r}, {player.position.x + r, player.position.y + r}}
if shift then
if
button == defines.mouse_button_type.right or
button == defines.mouse_button_type.left and autostash.insert_into_wagon
then
chests = get_nearby_chests(player, area)
end
else
chests = get_nearby_chests(player)
end
if not chests[1] then
player.print('No valid nearby containers found.', print_color)
return
end
local filtered_chests = {}
local filtered_allowed
for _, e in pairs(chests) do
local is_valid, t = chest_is_valid(e)
filtered_allowed = t
if is_valid then
filtered_chests[#filtered_chests + 1] = e
end
end
autostash.floating_text_y_offsets = {}
local hotbar_items = {}
for i = 1, 100, 1 do
local prototype = player.get_quick_bar_slot(i)
if prototype then
hotbar_items[prototype.name] = true
end
end
for name, count in pairs(inventory.get_contents()) do
local is_resource = autostash.whitelist[name]
if not inventory.find_item_stack(name).grid and not hotbar_items[name] then
if shift and autostash.insert_into_wagon then
if button == defines.mouse_button_type.left then
if is_resource then
insert_item_into_chest(inventory, chests, filtered_chests, name, count, true)
end
end
if button == defines.mouse_button_type.right then
if filtered_allowed and is_resource and filtered_allowed[name] then
insert_item_into_chest(inventory, chests, filtered_chests, name, count, true)
end
end
elseif button == defines.mouse_button_type.right then
if is_resource then
insert_item_into_chest(inventory, chests, filtered_chests, name, count)
end
elseif button == defines.mouse_button_type.left then
insert_item_into_chest(inventory, chests, filtered_chests, name, count)
end
end
end
local c = autostash.floating_text_y_offsets
for k, _ in pairs(c) do
autostash.floating_text_y_offsets[k] = nil
end
end
local function create_gui_button(player)
if player.gui.top.auto_stash then
return
end
local tooltip
if autostash.insert_into_wagon then
tooltip =
'Sort your inventory into nearby chests.\nLMB: Everything, excluding quickbar items.\nRMB: Only ores.\nSHIFT+LMB: Only ores to wagon\nSHIFT+RMB: Only ores onto filtered slots to wagon.'
else
tooltip = 'Sort your inventory into nearby chests.\nLMB: Everything, excluding quickbar items.\nRMB: Only ores.'
end
local b =
player.gui.top.add(
{
type = 'sprite-button',
sprite = 'item/wooden-chest',
name = 'auto_stash',
tooltip = tooltip
}
)
b.style.font_color = {r = 0.11, g = 0.8, b = 0.44}
b.style.font = 'heading-1'
b.style.minimal_height = 38
b.style.minimal_width = 38
b.style.maximal_height = 38
b.style.maximal_width = 38
b.style.padding = 1
b.style.margin = 0
end
local function do_whitelist()
local resources = game.entity_prototypes
autostash.whitelist = {}
for k, _ in pairs(resources) do
if resources[k] and resources[k].type == 'resource' and resources[k].mineable_properties then
if resources[k].mineable_properties.products[1] then
local r = resources[k].mineable_properties.products[1].name
autostash.whitelist[r] = true
elseif resources[k].mineable_properties.products[2] then
local r = resources[k].mineable_properties.products[2].name
autostash.whitelist[r] = true
end
end
end
end
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
if event.element.name == 'auto_stash' then
auto_stash(game.players[event.player_index], event)
end
end
function Public.insert_into_wagon(value)
if value then
autostash.insert_into_wagon = value or false
end
end
Event.on_configuration_changed = function()
do_whitelist()
log('[Autostash] on_configuration_changed was called, rebuilding resource whitelist.')
end
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)
return Public

View File

@ -0,0 +1,99 @@
-- All entities that own a unit_number of a chosen force gain damage resistance.
-- ignores entity health regeneration
-- Use Public.set_health_modifier(force_index, modifier) to modify health.
-- 1 = original health, 2 = 200% total health, 4 = 400% total health,..
local Global = require 'utils.global'
local Event = require 'utils.event'
local Public = {}
local math_round = math.round
local fhb = {}
Global.register(
fhb,
function(tbl)
fhb = tbl
end
)
function Public.set_health_modifier(force_index, modifier)
if not game.forces[force_index] then return end
if not modifier then return end
if not fhb[force_index] then fhb[force_index] = {} end
fhb[force_index].m = math_round(1 / modifier, 4)
end
function Public.reset_tables()
for k, v in pairs(fhb) do fhb[k] = nil end
end
local function on_entity_damaged(event)
local entity = event.entity
if not entity then return end
if not entity.valid then return end
if not (entity.name == 'spidertron') then
return
end
local unit_number = entity.unit_number
if not unit_number then return end
local boost = fhb[entity.force.index]
if not boost then return end
if not boost[unit_number] then boost[unit_number] = entity.prototype.max_health end
local new_health = boost[unit_number] - event.final_damage_amount * boost.m
boost[unit_number] = new_health
entity.health = new_health
end
local function on_entity_died(event)
local entity = event.entity
if not entity then return end
if not entity.valid then return end
if not (entity.name == 'spidertron') then
return
end
local unit_number = entity.unit_number
if not unit_number then return end
local boost = fhb[entity.force.index]
if not boost then return end
boost[unit_number] = nil
end
local function on_player_repaired_entity(event)
local entity = event.entity
if not entity then return end
if not entity.valid then return end
if not (entity.name == 'spidertron') then
return
end
local unit_number = entity.unit_number
local boost = fhb[entity.force.index]
if not unit_number then return end
if not boost then return end
boost[unit_number] = entity.health
end
local function on_init()
Public.reset_tables()
end
Event.on_init(on_init)
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
Event.add(defines.events.on_entity_died, on_entity_died)
Event.add(defines.events.on_player_repaired_entity, on_player_repaired_entity)
return Public

80
maps/amap/surface.lua Normal file
View File

@ -0,0 +1,80 @@
local Global = require 'utils.global'
local surface_name = 'amap'
local WPT = require 'maps.amap.table'
local Reset = require 'maps.amap.soft_reset'
local Public = {}
local this = {
active_surface_index = nil,
surface_name = surface_name,
}
Global.register(
this,
function(tbl)
this = tbl
end
)
local starting_items = {['pistol'] = 1, ['firearm-magazine'] = 16, ['wood'] = 16}
function Public.create_surface()
local map_gen_settings = {
['seed'] = math.random(10000, 99999),
['starting_area'] = 1.2,
['default_enable_all_autoplace_controls'] = true,
['water'] = 0.65
}
map_gen_settings.autoplace_controls = {
["coal"] = {frequency = "1", size = "1", richness = "1"},
["stone"] = {frequency = "1", size = "1", richness = "1"},
["copper-ore"] = {frequency = "1", size = "2", richness = "1"},
["iron-ore"] = {frequency = "1", size = "2", richness = "1"},
["crude-oil"] = {frequency = "2", size = "2", richness = "1"},
["trees"] = {frequency = "1", size = "0.5", richness = "0.7"},
["enemy-base"] = {frequency = "4", size = "2", richness = "1"},
--["starting_area"] = 1.2,
}
if not this.active_surface_index then
this.active_surface_index = game.create_surface(surface_name, map_gen_settings).index
else
this.active_surface_index = Reset.soft_reset_map(game.surfaces[this.active_surface_index], map_gen_settings, starting_items).index
end
if not this.cleared_nauvis then
local mgs = game.surfaces['nauvis'].map_gen_settings
mgs.width = 16
mgs.height = 16
game.surfaces['nauvis'].map_gen_settings = mgs
game.surfaces['nauvis'].clear()
this.cleared_nauvis = true
end
--local size = game.surfaces[this.active_surface_index].map_gen_settings
-- size.width = 512
-- size.height = 512
--game.surfaces[this.active_surface_index].map_gen_settings = size
return this.active_surface_index
end
function Public.get_active_surface()
return this.active_surface
end
function Public.get_surface_name()
return this.surface_name
end
function Public.get(key)
if key then
return this[key]
else
return this
end
end
return Public

190
maps/amap/table.lua Normal file
View File

@ -0,0 +1,190 @@
local Global = require 'utils.global'
local Event = require 'utils.event'
local this = {
players = {},
traps = {}
}
local Public = {}
Global.register(
this,
function(tbl)
this = tbl
end
)
Public.level_depth = 512
Public.level_width = 512
function Public.reset_table()
-- @start
-- these 3 are in case of stop/start/reloading the instance
this.biter_dam=0
this.cap=2
this.biter_health=0
this.change_dist=false
this.spider_health=0
this.arty=0
this.health = 0
this.flame = 0
this.roll = 0
this.pass = false
this.single = true
this.science = 0
this.number = 0
this.first = true
this.times = 1
this.change = false
this.pos = {x=0,y=0}
this.last = 0
this.rock = nil
this.soft_reset = true
this.restart = false
this.shutdown = false
this.announced_message = false
this.game_saved = false
-- @end
this.icw_locomotive = nil
this.debug = false
this.game_lost = false
this.fullness_enabled = true
this.locomotive_health = 10000
this.locomotive_max_health = 10000
this.gap_between_zones = {
set = false,
gap = 900,
neg_gap = -500,
highest_pos = 0
}
this.force_chunk = false
this.train_upgrades = 0
this.biter_pets = {}
this.flamethrower_damage = {}
this.mined_scrap = 0
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
this.poison_deployed = false
this.upgrades = {
showed_text = false,
landmine = {
limit = 25,
bought = 0,
built = 0
},
flame_turret = {
limit = 6,
bought = 0,
built = 0
},
unit_number = {
landmine = {},
flame_turret = {}
}
}
this.aura_upgrades = 0
this.pickaxe_tier = 1
this.pickaxe_speed_per_purchase = 0.10
this.health_upgrades = 0
this.breached_wall = 1
this.left_top = {
x = 0,
y = 0
}
this.biters = {
amount = 0,
limit = 512
}
this.traps = {}
this.munch_time = true
this.coin_amount = 1
this.difficulty_set = false
this.bonus_xp_on_join = 250
this.main_market_items = {}
this.spill_items_to_surface = false
this.outside_chests = {}
this.chests_linked_to = {}
this.chest_limit_outside_upgrades = 1
this.placed_trains_in_zone = {
placed = 0,
positions = {},
limit = 2,
randomized = false
}
this.marked_fixed_prices = {
chest_limit_cost = 3000,
health_cost = 10000,
pickaxe_cost = 3000,
aura_cost = 4000,
xp_point_boost_cost = 5000,
explosive_bullets_cost = 20000,
flamethrower_turrets_cost = 3000,
land_mine_cost = 2,
skill_reset_cost = 100000
}
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.collapse_amount = false
this.collapse_speed = false
this.spawn_near_collapse = {
active = true,
total_pos = 35,
compare = -150,
compare_next = 200,
distance_from = 2
}
this.spidertron_unlocked_at_wave = 11
-- this.void_or_tile = 'lab-dark-2'
this.void_or_tile = 'out-of-map'
this.validate_spider = {}
this.check_afk_players = true
this.winter_mode = false
this.sent_to_discord = false
this.difficulty = {
multiply = 0.25,
highest = 10
}
--!reset player tables
for _, player in pairs(this.players) do
player.died = false
end
end
function Public.get(key)
if key then
return this[key]
else
return this
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
local on_init = function()
Public.reset_table()
end
Event.on_init(on_init)
return Public

2448
maps/amap/terrain.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,116 @@
-- All entities that own a unit_number of a chosen force gain damage resistance.
-- ignores entity health regeneration
-- Use Public.set_health_modifier(force_index, modifier) to modify health.
-- 1 = original health, 2 = 200% total health, 4 = 400% total health,..
local Global = require 'utils.global'
local Event = require 'utils.event'
local Public = {}
local math_round = math.round
local fhb = {}
Global.register(
fhb,
function(tbl)
fhb = tbl
end
)
function Public.set_health_modifier(force_index, modifier)
if not game.forces[force_index] then return end
if not modifier then return end
if not fhb[force_index] then fhb[force_index] = {} end
fhb[force_index].m = math_round(1 / modifier, 4)
end
function Public.reset_tables()
for k, v in pairs(fhb) do fhb[k] = nil end
end
local function on_entity_damaged(event)
local entity = event.entity
if not entity then return end
if not entity.valid then return end
if not (entity.name == 'stone-wall') then
if not (entity.name == 'gun-turret') then
if not (entity.name == 'laser-turret') then
-- if not (entity.name == 'flamethrower-turret') then
return
--end
end
end
end
local unit_number = entity.unit_number
if not unit_number then return end
local boost = fhb[entity.force.index]
if not boost then return end
if not boost[unit_number] then boost[unit_number] = entity.prototype.max_health end
local new_health = boost[unit_number] - event.final_damage_amount * boost.m
boost[unit_number] = new_health
entity.health = new_health
end
local function on_entity_died(event)
local entity = event.entity
if not entity then return end
if not entity.valid then return end
if not (entity.name == 'stone-wall') then
if not (entity.name == 'gun-turret') then
if not (entity.name == 'laser-turret') then
-- if not (entity.name == 'flamethrower-turret') then
return
--end
end
end
end
local unit_number = entity.unit_number
if not unit_number then return end
local boost = fhb[entity.force.index]
if not boost then return end
boost[unit_number] = nil
end
local function on_player_repaired_entity(event)
local entity = event.entity
if not entity then return end
if not entity.valid then return end
if not (entity.name == 'stone-wall') then
if not (entity.name == 'gun-turret') then
if not (entity.name == 'laser-turret') then
-- if not (entity.name == 'flamethrower-turret') then
return
--end
end
end
end
local unit_number = entity.unit_number
local boost = fhb[entity.force.index]
if not unit_number then return end
if not boost then return end
boost[unit_number] = entity.health
end
local function on_init()
Public.reset_tables()
end
Event.on_init(on_init)
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
Event.add(defines.events.on_entity_died, on_entity_died)
Event.add(defines.events.on_player_repaired_entity, on_player_repaired_entity)
return Public

View File

@ -1257,24 +1257,31 @@ function Public.reset_game()
local difficulties = {
[1] = {
name = 'Easy',
value = 0.75,
color = {r = 0.00, g = 0.25, b = 0.00},
print_color = {r = 0.00, g = 0.4, b = 0.00},
enabled = true
},
[2] = {
name = 'Normal',
value = 1,
color = {r = 0.00, g = 0.00, b = 0.25},
print_color = {r = 0.0, g = 0.0, b = 0.5}
},
[2] = {
[3] = {
name = 'Hard',
value = 1.5,
color = {r = 0.25, g = 0.00, b = 0.00},
print_color = {r = 0.4, g = 0.0, b = 0.00}
},
[3] = {
[4] = {
name = 'Nightmare',
value = 3,
color = {r = 0.35, g = 0.00, b = 0.00},
print_color = {r = 0.6, g = 0.0, b = 0.00}
},
[4] = {
[5] = {
name = 'Impossible',
value = 5,
color = {r = 0.45, g = 0.00, b = 0.00},

View File

@ -1,5 +1,6 @@
local Event = require 'utils.event'
local RPG_Settings = require 'modules.rpg.table'
local BiterHealthBooster = require 'modules.biter_health_booster_v2'
local insert = table.insert
local floor = math.floor
local random = math.random
@ -34,20 +35,22 @@ local function get_coin_count(entity)
if not coin_count then
return
end
if not global.biter_health_boost_units then
local biter_health_boost_units = BiterHealthBooster.get('biter_health_boost_units')
if not biter_health_boost_units then
return coin_count
end
local unit_number = entity.unit_number
if not unit_number then
return coin_count
end
if not global.biter_health_boost_units[unit_number] then
if not biter_health_boost_units[unit_number] then
return coin_count
end
if not global.biter_health_boost_units[unit_number][3] then
if not biter_health_boost_units[unit_number][3] then
return coin_count
end
local m = 1 / global.biter_health_boost_units[unit_number][2]
local m = 1 / biter_health_boost_units[unit_number][2]
coin_count = floor(coin_count * m)
if coin_count < 1 then
return 1

View File

@ -183,7 +183,6 @@ local function distance(player)
WPT.set().placed_trains_in_zone.randomized = false
WPT.set().placed_trains_in_zone.positions = {}
raise_event(Balance.events.breached_wall, {})
--[[ global.biter_health_boost = calculate_hp(breached_wall) ]]
if WPT.get('breached_wall') == WPT.get('spidertron_unlocked_at_wave') then
local main_market_items = WPT.get('main_market_items')
if not main_market_items['spidertron'] then
@ -241,8 +240,6 @@ local function distance(player)
RPG_Settings.set_value_to_player(index, 'bonus', bonus + 1)
local b = RPG_Settings.get_value_from_player(index, 'bonus')
Functions.gain_xp(player, bonus_xp_on_join * bonus)
local message = ({'breached_wall.wall_breached', bonus})
Alert.alert_player_warning(player, 10, message)

View File

@ -1,7 +1,7 @@
local Event = require 'utils.event'
local Global = require 'utils.global'
local BiterRolls = require 'modules.wave_defense.biter_rolls'
local BiterHealthBooster = require 'modules.biter_health_booster'
local BiterHealthBooster = require 'modules.biter_health_booster_v2'
local WD = require 'modules.wave_defense.table'
local WPT = require 'maps.mountain_fortress_v3.table'
local Diff = require 'modules.difficulty_vote_by_amount'
@ -121,7 +121,7 @@ local function spawn_biters(data)
max_biters.amount = max_biters.amount + 1
end
if random(1, 32) == 1 then
if random(1, 45) == 1 then
local sum = trigger_health()
max_biters.amount = max_biters.amount + 1
BiterHealthBooster.add_boss_unit(unit, sum, 0.38)

View File

@ -285,8 +285,12 @@ local function protect_entities(event)
return
end
if entity.type == 'simple-entity' and dmg >= 300 then
entity.health = entity.health + dmg
local check_heavy_damage = WPT.get('check_heavy_damage')
if check_heavy_damage then
if entity.type == 'simple-entity' and dmg >= 500 then
entity.health = entity.health + dmg
end
end
if entity.force.index ~= 1 then

View File

@ -1281,6 +1281,8 @@ function Public.disable_tech()
game.forces.player.technologies['landfill'].enabled = false
game.forces.player.technologies['spidertron'].enabled = false
game.forces.player.technologies['spidertron'].researched = false
game.forces.player.technologies['atomic-bomb'].enabled = false
game.forces.player.technologies['atomic-bomb'].researched = false
game.forces.player.technologies['optics'].researched = true
game.forces.player.technologies['railway'].researched = true
game.forces.player.technologies['land-mine'].enabled = false

View File

@ -1,12 +1,16 @@
local Event = require 'utils.event'
local RPG_Settings = require 'modules.rpg.table'
local WPT = require 'maps.mountain_fortress_v3.table'
local IC_Gui = require 'maps.mountain_fortress_v3.ic.gui'
local IC_Minimap = require 'maps.mountain_fortress_v3.ic.minimap'
local Gui = require 'utils.gui'
local SpamProtection = require 'utils.spam_protection'
local format_number = require 'util'.format_number
local Public = {}
Public.events = {reset_map = Event.generate_event_name('reset_map')}
local main_button_name = Gui.uid_name()
local main_frame_name = Gui.uid_name()
local floor = math.floor
@ -334,6 +338,50 @@ local function on_player_changed_surface(event)
end
end
local function enable_guis(event)
local player = game.players[event.player_index]
if not validate_player(player) then
return
end
local rpg_button = RPG_Settings.draw_main_frame_name
local info = player.gui.top[main_button_name]
local wd = player.gui.top['wave_defense']
local rpg_b = player.gui.top[rpg_button]
local diff = player.gui.top['difficulty_gui']
local charging = player.gui.top['charging_station']
IC_Gui.remove_toolbar(player)
IC_Minimap.toggle_button(player)
if info then
info.tooltip = ({'gui.info_tooltip'})
info.sprite = 'item/dummy-steel-axe'
end
local minimap = player.gui.left.icw_main_frame
if minimap and minimap.visible then
minimap.visible = false
end
if rpg_b and not rpg_b.visible then
rpg_b.visible = true
end
if diff and not diff.visible then
diff.visible = true
end
if wd and not wd.visible then
wd.visible = true
end
if charging and not charging.visible then
charging.visible = true
end
if info then
info.tooltip = ({'gui.info_tooltip'})
info.sprite = 'item/dummy-steel-axe'
info.visible = true
end
end
function Public.update_gui(player)
if not validate_player(player) then
return
@ -394,5 +442,6 @@ end
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_player_changed_surface, on_player_changed_surface)
Event.add(defines.events.on_gui_click, on_gui_click)
Event.add(Public.events.reset_map, enable_guis)
return Public

View File

@ -27,7 +27,10 @@ end
local function get_trusted_system(this, player)
if not this.trust_system[player.index] then
this.trust_system[player.index] = {
[player.name] = true
players = {
[player.name] = true
},
allow_anyone = 'right'
}
end
@ -644,7 +647,7 @@ function Public.validate_owner(ic, player, entity)
local p = game.players[car.owner]
local list = get_trusted_system(ic, p)
if p and p.valid and p.connected then
if list[player.name] then
if list.players[player.name] then
return
end
end
@ -879,10 +882,12 @@ function Public.use_door_with_entity(ic, player, door)
local owner = game.players[car.owner]
local list = get_trusted_system(ic, owner)
if owner and owner.valid and player.connected then
if not list[player.name] and not player.admin then
player.driving = false
return player.print('You have not been approved by ' .. owner.name .. ' to enter their vehicle.', Color.warning)
if owner and owner.valid and owner.index ~= player.index and player.connected then
if list.allow_anyone == 'right' then
if not list.players[player.name] and not player.admin then
player.driving = false
return player.print('You have not been approved by ' .. owner.name .. ' to enter their vehicle.', Color.warning)
end
end
end

View File

@ -17,6 +17,7 @@ local draw_transfer_car_frame_name = Gui.uid_name()
local main_toolbar_name = Gui.uid_name()
local add_player_name = Gui.uid_name()
local transfer_car_name = Gui.uid_name()
local allow_anyone_to_enter_name = Gui.uid_name()
local kick_player_name = Gui.uid_name()
local raise_event = script.raise_event
@ -35,7 +36,10 @@ local function create_player_table(player)
local trust_system = ICT.get('trust_system')
if not trust_system[player.index] then
trust_system[player.index] = {
[player.name] = true
players = {
[player.name] = true
},
allow_anyone = 'right'
}
end
return trust_system[player.index]
@ -61,7 +65,7 @@ local function transfer_player_table(player, new_player)
end
if not trust_system[new_player.index] then
local Functions = require 'maps.mountain_fortress_v3.ic.functions'
local Functions = is_loaded('maps.mountain_fortress_v3.ic.functions')
trust_system[new_player.index] = trust_system[player.index]
local name = new_player.name
@ -200,7 +204,7 @@ local function draw_players(data)
local player = data.player
local player_list = create_player_table(player)
for p, _ in pairs(player_list) do
for p, _ in pairs(player_list.players) do
Gui.set_data(add_player_frame, p)
local t_label =
player_table.add(
@ -270,8 +274,21 @@ local function draw_main_frame(player)
inside_table_style.bottom_padding = 10
inside_table_style.width = 350
local player_list = create_player_table(player)
local add_player_frame = inside_table.add({type = 'button', caption = 'Add Player', name = add_player_name})
local transfer_car_frame = inside_table.add({type = 'button', caption = 'Transfer Car', name = transfer_car_name})
local allow_anyone_to_enter =
inside_table.add(
{
type = 'switch',
name = allow_anyone_to_enter_name,
switch_state = player_list.allow_anyone,
allow_none_state = false,
left_label_caption = 'Allow everyone to enter: ON',
right_label_caption = 'OFF'
}
)
local player_table =
inside_table.add {
@ -323,6 +340,7 @@ local function draw_main_frame(player)
player_table = player_table,
add_player_frame = add_player_frame,
transfer_car_frame = transfer_car_frame,
allow_anyone_to_enter = allow_anyone_to_enter,
player = player
}
draw_players(data)
@ -429,6 +447,35 @@ Gui.on_click(
end
)
Gui.on_click(
allow_anyone_to_enter_name,
function(event)
local player = event.player
if not player or not player.valid or not player.character then
return
end
local player_list = create_player_table(player)
local screen = player.gui.screen
local frame = screen[main_frame_name]
if frame and frame.valid then
if player_list.allow_anyone == 'right' then
player_list.allow_anyone = 'left'
player.print('Everyone is allowed to enter your car!', Color.warning)
else
player_list.allow_anyone = 'right'
player.print('Everyone is disallowed to enter your car except your trusted list!', Color.warning)
end
if player.gui.screen[main_frame_name] then
toggle(player, true)
end
end
end
)
Gui.on_click(
save_add_player_button_name,
function(event)
@ -456,10 +503,10 @@ Gui.on_click(
local name = player_to_add.name
if not player_list[name] then
if not player_list.players[name] then
player.print(name .. ' was added to your vehicle.', Color.info)
player_to_add.print(player.name .. ' added you to their vehicle. You may now enter it.', Color.info)
increment(player_list, name)
increment(player_list.players, name)
else
return player.print('Target player is already trusted.', Color.warning)
end
@ -552,9 +599,9 @@ Gui.on_click(
end
local name = target.name
if player_list[name] then
if player_list.players[name] then
player.print(name .. ' was removed from your vehicle.', Color.info)
decrement(player_list, name)
decrement(player_list.players, name)
raise_event(
ICT.events.on_player_kicked_from_surface,
{

View File

@ -347,8 +347,8 @@ local function property_boost(data)
}
rpg[player.index].xp_since_last_floaty_text = 0
rpg[player.index].last_floaty_text = game.tick + visuals_delay
if player.gui.left[rpg_main_frame] then
local f = player.gui.left[rpg_main_frame]
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
d.exp_gui.caption = floor(rpg[player.index].xp)
@ -1650,8 +1650,8 @@ local function place_market()
end
local function on_research_finished()
local game_lost = WPT.get('game_lost')
if game_lost then
local market_announce = WPT.get('market_announce')
if market_announce > game.tick then
return
end
@ -1749,18 +1749,42 @@ local function on_player_driving_changed_state(event)
if not player or not player.valid then
return
end
local entity = event.entity
if not entity or not entity.valid then
return
end
local trusted = Session.get_trusted_table()
if #trusted == 0 then
return
end
local locomotive = WPT.get('locomotive')
if not locomotive or not locomotive.valid then
return
end
if not trusted[player.name] then
if player.character and player.character.valid and player.character.driving then
player.character.driving = false
if entity.unit_number == locomotive.unit_number then
if not trusted[player.name] then
if player.character and player.character.valid and player.character.driving then
player.character.driving = false
end
end
end
end
local function on_player_left_game(event)
local player = game.players[event.player_index]
if not player or not player.valid then
return
end
local trusted = Session.get_trusted_table()
if trusted[player.name] then
trusted[player.name] = nil
end
end
function Public.close_gui_player(frame)
if not frame then
return
@ -2405,5 +2429,6 @@ Event.add(defines.events.on_robot_mined_entity, on_player_and_robot_mined_entity
Event.add(defines.events.on_console_chat, on_console_chat)
Event.add(defines.events.on_player_changed_surface, on_player_changed_surface)
Event.add(defines.events.on_player_driving_changed_state, on_player_driving_changed_state)
Event.add(defines.events.on_player_left_game, on_player_left_game)
return Public

View File

@ -33,6 +33,8 @@ local Alert = require 'utils.alert'
local AntiGrief = require 'antigrief'
local Commands = require 'commands.misc'
local Modifiers = require 'player_modifiers'
local BiterHealthBooster = require 'modules.biter_health_booster_v2'
require 'maps.mountain_fortress_v3.rocks_yield_ore_veins'
require 'maps.mountain_fortress_v3.generate'
@ -48,6 +50,7 @@ require 'modules.wave_defense.main'
require 'modules.charging_station'
local Public = {}
local raise_event = script.raise_event
local floor = math.floor
local remove = table.remove
@ -148,6 +151,8 @@ function Public.reset_map()
game.forces.player.set_spawn_position({-27, 25}, surface)
game.forces.player.manual_mining_speed_modifier = 0
BiterHealthBooster.set_active_surface(tostring(surface.name))
Balance.init_enemy_weapon_damage()
AntiGrief.log_tree_harvest(true)
@ -172,6 +177,7 @@ function Public.reset_map()
player.gui.left['mvps'].destroy()
end
ICMinimap.kill_minimap(player)
raise_event(Gui_mf.events.reset_map, {player_index = player.index})
end
Difficulty.reset_difficulty_poll({difficulty_poll_closing_timeout = game.tick + 36000})
@ -206,7 +212,9 @@ function Public.reset_map()
WD.enable_threat_log(true)
WD.check_collapse_position(true)
WD.set_disable_threat_below_zero(true)
WD.increase_boss_health_per_wave(true)
WD.increase_damage_per_wave(false)
WD.increase_health_per_wave(true)
Functions.set_difficulty()
Functions.disable_creative()
@ -224,6 +232,7 @@ function Public.reset_map()
HS.get_scores()
this.chunk_load_tick = game.tick + 1200
this.market_announce = game.tick + 1200
this.game_lost = false
end

View File

@ -200,6 +200,8 @@ function Public.reset_table()
multiply = 0.25,
highest = 10
}
this.market_announce = game.tick + 1200
this.check_heavy_damage = true
--!reset player tables
for _, player in pairs(this.players) do

View File

@ -0,0 +1,139 @@
require "modules.custom_death_messages"
require "modules.flashlight_toggle_button"
require "modules.global_chat_toggle"
require "modules.worms_create_oil_patches"
require "modules.biters_yield_coins"
require "modules.scrap_towny_ffa.mining"
require "modules.scrap_towny_ffa.on_tick_schedule"
require "modules.scrap_towny_ffa.building"
require "modules.scrap_towny_ffa.town_center"
require "modules.scrap_towny_ffa.market"
require "modules.scrap_towny_ffa.slots"
require "modules.scrap_towny_ffa.wreckage_yields_scrap"
require "modules.scrap_towny_ffa.rocks_yield_ore_veins"
require "modules.scrap_towny_ffa.spawners_contain_biters"
require "modules.scrap_towny_ffa.explosives_are_explosive"
require "modules.scrap_towny_ffa.fluids_are_explosive"
require "modules.scrap_towny_ffa.trap"
require "modules.scrap_towny_ffa.turrets_drop_ammo"
require "modules.scrap_towny_ffa.combat_balance"
local Table = require "modules.scrap_towny_ffa.table"
local Nauvis = require "modules.scrap_towny_ffa.nauvis"
local Biters = require "modules.scrap_towny_ffa.biters"
local Pollution = require "modules.scrap_towny_ffa.pollution"
local Fish = require "modules.scrap_towny_ffa.fish_reproduction"
local Info = require "modules.scrap_towny_ffa.info"
local Team = require "modules.scrap_towny_ffa.team"
local Spawn = require "modules.scrap_towny_ffa.spawn"
local Radar = require "modules.scrap_towny_ffa.limited_radar"
local default_surface = "nauvis"
local function on_player_joined_game(event)
local ffatable = Table.get_table()
local player = game.players[event.player_index]
local surface = game.surfaces[default_surface]
player.game_view_settings.show_minimap = false
player.game_view_settings.show_map_view_options = false
player.game_view_settings.show_entity_info = true
--player.game_view_settings.show_side_menu = false
Info.toggle_button(player)
Info.show(player)
Team.set_player_color(player)
if player.force ~= game.forces.player then return end
-- setup outlanders
Team.set_player_to_outlander(player)
if player.online_time == 0 then
player.teleport({ 0, 0 }, game.surfaces["limbo"])
Team.give_outlander_items(player)
Team.give_key(player)
-- first time spawn point
local spawn_point = Spawn.get_spawn_point(player, surface)
Spawn.clear_spawn_point(spawn_point, surface)
player.teleport(spawn_point, surface)
return
end
if not ffatable.requests[player.index] then return end
if ffatable.requests[player.index] ~= "kill-character" then return end
if player.character then
if player.character.valid then
player.character.die()
end
end
ffatable.requests[player.index] = nil
end
local function on_player_respawned(event)
local ffatable = Table.get_table()
local player = game.players[event.player_index]
local surface = player.surface
if player.force == game.forces["rogue"] then Team.set_player_to_outlander(player) end
if player.force == game.forces["player"] then Team.give_key(player) end
-- TODO: this needs fixing!
-- 5 second cooldown
--local last_respawn = ffatable.cooldowns_last_respawn[player.name]
--if last_respawn == nil then last_respawn = 0 end
local spawn_point = Spawn.get_spawn_point(player, surface)
-- reset cooldown
ffatable.cooldowns_last_respawn[player.name] = game.tick
player.teleport(surface.find_non_colliding_position("character", spawn_point, 0, 0.5, false), surface)
end
local function on_player_died(event)
local ffatable = Table.get_table()
local player = game.players[event.player_index]
ffatable.cooldowns_last_death[player.name] = game.tick
end
local function on_init()
local ffatable = Table.get_table()
--log("on_init")
game.enemy_has_vision_on_land_mines = false
game.draw_resource_selection = true
game.disable_tutorial_triggers()
ffatable.cooldowns_last_respawn = {}
ffatable.cooldowns_last_death = {}
Nauvis.initialize()
Team.initialize()
end
local tick_actions = {
[60 * 0] = Radar.reset, -- each minute, at 00 seconds
[60 * 5] = Team.update_town_chart_tags, -- each minute, at 05 seconds
[60 * 10] = Team.set_all_player_colors, -- each minute, at 10 seconds
[60 * 15] = Fish.reproduce, -- each minute, at 15 seconds
[60 * 25] = Biters.unit_groups_start_moving, -- each minute, at 25 seconds
[60 * 30] = Radar.reset, -- each minute, at 30 seconds
[60 * 45] = Biters.validate_swarms, -- each minute, at 45 seconds
[60 * 50] = Biters.swarm, -- each minute, at 50 seconds
[60 * 55] = Pollution.market_scent -- each minute, at 55 seconds
}
local function on_nth_tick(event)
-- run each second
local tick = event.tick
local seconds = tick % 3600 -- tick will recycle minute
if not tick_actions[seconds] then return end
tick_actions[seconds]()
end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.on_nth_tick(60, on_nth_tick) -- once every second
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_player_respawned, on_player_respawned)
Event.add(defines.events.on_player_died, on_player_died)

View File

@ -0,0 +1,247 @@
-- Biters, Spawners and Worms gain additional health / resistance -- mewmew
-- modified by Gerkiz
-- Use this.biter_health_boost or this.biter_health_boost_forces to modify their health.
-- 1 = vanilla health, 2 = 200% vanilla health
-- do not use values below 1
local Event = require 'utils.event'
local Global = require 'utils.global'
local floor = math.floor
local insert = table.insert
local round = math.round
local Public = {}
local this = {
biter_health_boost = 1,
biter_health_boost_forces = {},
biter_health_boost_units = {},
biter_health_boost_count = 0,
active_surface = 'nauvis'
}
Global.register(
this,
function(t)
this = t
end
)
function Public.reset_table()
this.biter_health_boost = 1
this.biter_health_boost_forces = {}
this.biter_health_boost_units = {}
this.biter_health_boost_count = 0
this.active_surface = 'nauvis'
this.check_on_entity_died = false
end
local entity_types = {
['unit'] = true,
['turret'] = true,
['unit-spawner'] = true
}
if is_loaded('maps.biter_hatchery.terrain') then
entity_types['unit-spawner'] = nil
end
local function clean_table()
--Perform a table cleanup every 500 boosts
this.biter_health_boost_count = this.biter_health_boost_count + 1
if this.biter_health_boost_count % 500 ~= 0 then
return
end
local units_to_delete = {}
--Mark all health boost entries for deletion
for key, _ in pairs(this.biter_health_boost_units) do
units_to_delete[key] = true
end
--Remove valid health boost entries from deletion
local validTypes = {}
for k, v in pairs(entity_types) do
if v then
insert(validTypes, k)
end
end
local surface = game.surfaces[this.active_surface]
for _, unit in pairs(surface.find_entities_filtered({type = validTypes})) do
units_to_delete[unit.unit_number] = nil
end
--Remove abandoned health boost entries
for key, _ in pairs(units_to_delete) do
this.biter_health_boost_units[key] = nil
end
end
local function create_boss_healthbar(entity, size)
return rendering.draw_sprite(
{
sprite = 'virtual-signal/signal-white',
tint = {0, 200, 0},
x_scale = size * 15,
y_scale = size,
render_layer = 'light-effect',
target = entity,
target_offset = {0, -2.5},
surface = entity.surface
}
)
end
local function set_boss_healthbar(health, max_health, healthbar_id)
local m = health / max_health
local x_scale = rendering.get_y_scale(healthbar_id) * 15
rendering.set_x_scale(healthbar_id, x_scale * m)
rendering.set_color(healthbar_id, {floor(255 - 255 * m), floor(200 * m), 0})
end
function Public.add_unit(unit, health_multiplier)
if not health_multiplier then
health_multiplier = this.biter_health_boost
end
this.biter_health_boost_units[unit.unit_number] = {
floor(unit.prototype.max_health * health_multiplier),
round(1 / health_multiplier, 5)
}
clean_table()
end
function Public.add_boss_unit(unit, health_multiplier, health_bar_size)
if not health_multiplier then
health_multiplier = this.biter_health_boost
end
if not health_bar_size then
health_bar_size = 0.5
end
local health = floor(unit.prototype.max_health * health_multiplier)
this.biter_health_boost_units[unit.unit_number] = {
health,
round(1 / health_multiplier, 5),
{max_health = health, healthbar_id = create_boss_healthbar(unit, health_bar_size), last_update = game.tick}
}
clean_table()
end
local function on_entity_damaged(event)
local biter = event.entity
if not (biter and biter.valid) then
return
end
if not entity_types[biter.type] then
return
end
local biter_health_boost_units = this.biter_health_boost_units
local unit_number = biter.unit_number
--Create new health pool
local health_pool = biter_health_boost_units[unit_number]
if not health_pool then
if this.biter_health_boost_forces[biter.force.index] then
Public.add_unit(biter, this.biter_health_boost_forces[biter.force.index])
else
Public.add_unit(biter, this.biter_health_boost)
end
health_pool = this.biter_health_boost_units[unit_number]
end
--Process boss unit health bars
local boss = health_pool[3]
if boss then
if boss.last_update + 10 < game.tick then
set_boss_healthbar(health_pool[1], boss.max_health, boss.healthbar_id)
boss.last_update = game.tick
end
end
--Reduce health pool
health_pool[1] = health_pool[1] - event.final_damage_amount
--Set entity health relative to health pool
biter.health = health_pool[1] * health_pool[2]
--Proceed to kill entity if health is 0
if biter.health > 0 then
return
end
if event.cause then
if event.cause.valid then
event.entity.die(event.cause.force, event.cause)
return
end
end
biter.die(biter.force)
end
local function on_entity_died(event)
if not this.check_on_entity_died then
return
end
local biter = event.entity
if not (biter and biter.valid) then
return
end
if not entity_types[biter.type] then
return
end
local biter_health_boost_units = this.biter_health_boost_units
local unit_number = biter.unit_number
local health_pool = biter_health_boost_units[unit_number]
if health_pool then
biter_health_boost_units[unit_number] = nil
end
end
function Public.get(key)
if key then
return this[key]
else
return this
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
function Public.set_active_surface(str)
if str and type(str) == 'string' then
this.active_surface = str
end
return this.active_surface
end
function Public.check_on_entity_died(boolean)
this.check_on_entity_died = boolean or false
return this.check_on_entity_died
end
local on_init = function()
Public.reset_table()
end
Event.on_init(on_init)
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
Event.add(defines.events.on_entity_died, on_entity_died)
return Public

View File

@ -32,6 +32,9 @@ local function is_player_warned(player, reset)
end
local function compute_fullness(player)
if not player.mining_state.mining then
return false
end
local warn_player = is_player_warned(player)
local free_slots = player.get_main_inventory().count_empty_stacks()
if free_slots == 0 or free_slots == 1 then

View File

@ -479,6 +479,13 @@ function Public.get_one_punch_chance(player)
return chance
end
function Public.get_extra_following_robots(player)
local rpg_t = RPG.get('rpg_t')
local strength = rpg_t[player.index].strength
local count = math.round(strength / 2 * 0.03, 3)
return count
end
function Public.get_magicka(player)
local rpg_t = RPG.get('rpg_t')
return (rpg_t[player.index].magicka - 10) * 0.10
@ -641,6 +648,14 @@ function Public.gain_xp(player, amount, added_to_pool, text)
return
end
local f = player.gui.screen[main_frame_name]
if f and f.valid then
local d = Gui.get_data(f)
if d.exp_gui and d.exp_gui.valid then
d.exp_gui.caption = math.floor(rpg_t[player.index].xp)
end
end
if rpg_t[player.index].xp >= experience_levels[rpg_t[player.index].level + 1] then
level_up(player)
end

View File

@ -359,7 +359,8 @@ local function draw_main_frame(player, location)
melee_damage_tooltip = ({
'rpg_gui.one_punch_chance',
Functions.get_life_on_hit(player),
Functions.get_one_punch_chance(player)
Functions.get_one_punch_chance(player),
Functions.get_extra_following_robots(player)
})
else
melee_damage_tooltip = ({'rpg_gui.one_punch_disabled'})

View File

@ -3,6 +3,7 @@ local Event = require 'utils.event'
local AntiGrief = require 'antigrief'
local Color = require 'utils.color_presets'
local SpamProtection = require 'utils.spam_protection'
local BiterHealthBooster = require 'modules.biter_health_booster_v2'
local WD = require 'modules.wave_defense.table'
local Math2D = require 'math2d'
@ -214,6 +215,9 @@ local function on_entity_died(event)
end
end
local biter_health_boost = BiterHealthBooster.get('biter_health_boost')
local biter_health_boost_units = BiterHealthBooster.get('biter_health_boost_units')
if not event.cause then
return
end
@ -232,8 +236,8 @@ local function on_entity_died(event)
if rpg_extra.rpg_xp_yield[event.entity.name] then
local amount = rpg_extra.rpg_xp_yield[event.entity.name]
amount = amount / 5
if global.biter_health_boost then
local health_pool = global.biter_health_boost_units[event.entity.unit_number]
if biter_health_boost then
local health_pool = biter_health_boost_units[event.entity.unit_number]
if health_pool then
amount = amount * (1 / health_pool[2])
end
@ -268,9 +272,9 @@ local function on_entity_died(event)
end
--Grant modified XP for health boosted units
if global.biter_health_boost then
if biter_health_boost then
if enemy_types[event.entity.type] then
local health_pool = global.biter_health_boost_units[event.entity.unit_number]
local health_pool = biter_health_boost_units[event.entity.unit_number]
if health_pool then
for _, player in pairs(players) do
if rpg_extra.rpg_xp_yield[event.entity.name] then
@ -553,6 +557,14 @@ local function on_entity_damaged(event)
return
end
local item = p.cursor_stack
if item and item.valid_for_read then
if item.name == 'discharge-defense-remote' then
return
end
end
Functions.reward_mana(cause.player, 2)
--Grant the player life-on-hit.
@ -612,9 +624,12 @@ local function on_entity_damaged(event)
)
end
local biter_health_boost = BiterHealthBooster.get('biter_health_boost')
local biter_health_boost_units = BiterHealthBooster.get('biter_health_boost_units')
--Handle the custom health pool of the biter health booster, if it is used in the map.
if global.biter_health_boost then
local health_pool = global.biter_health_boost_units[entity.unit_number]
if biter_health_boost then
local health_pool = biter_health_boost_units[entity.unit_number]
if health_pool then
health_pool[1] = health_pool[1] + event.final_damage_amount
health_pool[1] = health_pool[1] - damage
@ -625,7 +640,10 @@ local function on_entity_damaged(event)
if health_pool[1] <= 0 then
local entity_number = entity.unit_number
entity.die(entity.force.name, cause)
global.biter_health_boost_units[entity_number] = nil
if biter_health_boost_units[entity_number] then
biter_health_boost_units[entity_number] = nil
end
end
return
end

View File

@ -0,0 +1,210 @@
local Public = {}
local math_random = math.random
local math_floor = math.floor
local math_sqrt = math.sqrt
local math_round = math.round
local table_size = table.size
local table_insert = table.insert
local table_remove = table.remove
local table_shuffle = table.shuffle_table
local Global = require 'utils.global'
local tick_schedule = {}
Global.register(
tick_schedule,
function(t)
tick_schedule = t
end
)
local Table = require 'modules.scrap_towny_ffa.table'
local Evolution = require "modules.scrap_towny_ffa.evolution"
local function get_commmands(target, group)
local commands = {}
local group_position = { x = group.position.x, y = group.position.y }
local step_length = 128
local target_position = target.position
local distance_to_target = math_floor(math_sqrt((target_position.x - group_position.x) ^ 2 + (target_position.y - group_position.y) ^ 2))
local steps = math_floor(distance_to_target / step_length) + 1
local vector = { math_round((target_position.x - group_position.x) / steps, 3), math_round((target_position.y - group_position.y) / steps, 3) }
for _ = 1, steps, 1 do
group_position.x = group_position.x + vector[1]
group_position.y = group_position.y + vector[2]
local position = group.surface.find_non_colliding_position("small-biter", group_position, step_length, 2)
if position then
commands[#commands + 1] = {
type = defines.command.attack_area,
destination = { x = position.x, y = position.y },
radius = 16,
distraction = defines.distraction.by_damage
}
end
end
commands[#commands + 1] = {
type = defines.command.attack_area,
destination = target.position,
radius = 12,
distraction = defines.distraction.by_enemy,
}
commands[#commands + 1] = {
type = defines.command.attack,
target = target,
distraction = defines.distraction.by_anything,
}
return commands
end
local function roll_market()
local ffatable = Table.get_table()
local town_centers = ffatable.town_centers
if town_centers == nil or table_size(town_centers) == 0 then return end
local keyset = {}
for town_name, _ in pairs(town_centers) do
table_insert(keyset, town_name)
end
local tc = math_random(1, #keyset)
return town_centers[keyset[tc]]
end
local function get_random_close_spawner(surface, market, radius)
local units = surface.find_enemy_units(market.position, radius, market.force)
if units ~= nil and #units > 0 then
-- found units, shuffle the list
table_shuffle(units)
while units[1] do
local unit = units[1]
if unit.spawner then return unit.spawner end
table_remove(units, 1)
end
end
end
local function is_swarm_valid(swarm)
local group = swarm.group
if not group then return end
if not group.valid then return end
if game.tick >= swarm.timeout then
group.destroy()
return
end
return true
end
function Public.validate_swarms()
local ffatable = Table.get_table()
for k, swarm in pairs(ffatable.swarms) do
if not is_swarm_valid(swarm) then
table_remove(ffatable.swarms, k)
end
end
end
function Public.unit_groups_start_moving()
local ffatable = Table.get_table()
for _, swarm in pairs(ffatable.swarms) do
if swarm.group then
if swarm.group.valid then
swarm.group.start_moving()
end
end
end
end
function Public.swarm(town_center, radius)
if town_center == nil then return end
local ffatable = Table.get_table()
local r = radius or 32
local tc = town_center or roll_market()
if not tc or r > 512 then return end
-- skip if town evolution < 0.25
if town_center.get_biter_evolution < 0.25 then return end
-- skip if we have to many swarms already
local count = table_size(ffatable.swarms)
local towns = table_size(ffatable.town_centers)
if count > 3 * towns then return end
local market = tc.market
local surface = market.surface
-- find a spawner
local spawner = get_random_close_spawner(surface, market, r)
if not spawner then
r = r + 16
local future = game.tick + 1
-- schedule to run this method again with a higher radius on next tick
if not tick_schedule[future] then tick_schedule[future] = {} end
tick_schedule[future][#tick_schedule[future] + 1] = {
callback = 'swarm',
params = { tc, r }
}
return
end
-- get our evolution
local evolution = 0
if spawner.name == "spitter-spawner" then
evolution = Evolution.get_biter_evolution(spawner)
else
evolution = Evolution.get_spitter_evolution(spawner)
end
-- get our target amount of enemies
local count2 = (evolution * 124) + 4
local units = spawner.surface.find_enemy_units(spawner.position, 16, market.force)
if #units < count2 then
units = spawner.surface.find_enemy_units(spawner.position, 32, market.force)
end
if #units < count2 then
units = spawner.surface.find_enemy_units(spawner.position, 64, market.force)
end
if #units < count2 then
units = spawner.surface.find_enemy_units(spawner.position, 128, market.force)
end
if not units[1] then return end
local unit_group_position = surface.find_non_colliding_position("biter-spawner", units[1].position, 256, 1)
if not unit_group_position then return end
local unit_group = surface.create_unit_group({ position = unit_group_position, force = units[1].force })
for key, unit in pairs(units) do
if key > count2 then break end
unit_group.add_member(unit)
end
unit_group.set_command({
type = defines.command.compound,
structure_type = defines.compound_command.return_last,
commands = get_commmands(market, unit_group)
})
table_insert(ffatable.swarms, { group = unit_group, timeout = game.tick + 36000 })
end
local function on_tick()
if not tick_schedule[game.tick] then return end
for _, token in pairs(tick_schedule[game.tick]) do
local callback = token.callback
local params = token.params
if callback == 'swarm' then Public.swarm(params[1], params[2]) end
end
tick_schedule[game.tick] = nil
end
local on_init = function ()
local ffatable = Table.get_table()
ffatable.swarms = {}
end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.add(defines.events.on_tick, on_tick)
return Public

View File

@ -0,0 +1,269 @@
local Public = {}
local Table = require 'modules.scrap_towny_ffa.table'
local town_radius = 27
local connection_radius = 7
local neutral_whitelist = {
["wooden-chest"] = true,
["iron-chest"] = true,
["steel-chest"] = true,
["raw-fish"] = true,
}
local entity_type_whitelist = {
["accumulator"] = true,
["ammo-turret"] = true,
["arithmetic-combinator"] = true,
["artillery-turret"] = true,
["assembling-machine"] = true,
["boiler"] = true,
["constant-combinator"] = true,
["container"] = true,
["curved-rail"] = true,
["decider-combinator"] = true,
["electric-pole"] = true,
["electric-turret"] = true,
["fluid-turret"] = true,
["furnace"] = true,
["gate"] = true,
["generator"] = true,
["heat-interface"] = true,
["heat-pipe"] = true,
["infinity-container"] = true,
["infinity-pipe"] = true,
["inserter"] = true,
["lab"] = true,
["lamp"] = true,
["land-mine"] = true,
["loader"] = true,
["logistic-container"] = true,
["market"] = true,
["mining-drill"] = true,
["offshore-pump"] = true,
["pipe"] = true,
["pipe-to-ground"] = true,
["programmable-speaker"] = true,
["pump"] = true,
["radar"] = true,
["rail-chain-signal"] = true,
["rail-signal"] = true,
["reactor"] = true,
["roboport"] = true,
["rocket-silo"] = true,
["solar-panel"] = true,
["splitter"] = true,
["storage-tank"] = true,
["straight-rail"] = true,
["train-stop"] = true,
["transport-belt"] = true,
["underground-belt"] = true,
["wall"] = true,
}
local function isolated(surface, force, position)
local position_x = position.x
local position_y = position.y
local area = { { position_x - connection_radius, position_y - connection_radius }, { position_x + connection_radius, position_y + connection_radius } }
local count = 0
for _, e in pairs(surface.find_entities_filtered({ area = area, force = force.name })) do
if entity_type_whitelist[e.type] then
count = count + 1
if count > 1 then return false end -- are there more than one team entities in the area?
end
end
return true
end
local function refund_item(event, item_name)
if item_name == "blueprint" then return end
if event.player_index then
game.players[event.player_index].insert({ name = item_name, count = 1 })
return
end
if event.robot then
local inventory = event.robot.get_inventory(defines.inventory.robot_cargo)
inventory.insert({ name = item_name, count = 1 })
return
end
end
local function error_floaty(surface, position, msg)
surface.create_entity({
name = "flying-text",
position = position,
text = msg,
color = { r = 0.77, g = 0.0, b = 0.0 }
})
end
local function in_range(pos1, pos2, radius)
if pos1 == nil then return false end
if pos2 == nil then return false end
if radius < 1 then return true end
local dx = pos1.x - pos2.x
local dy = pos1.y - pos2.y
if dx ^ 2 + dy ^ 2 < radius ^ 2 then
return true
end
return false
end
-- is the position near a town?
function Public.near_town(position, surface, radius)
local ffatable = Table.get_table()
for _, town_center in pairs(ffatable.town_centers) do
if town_center ~= nil then
local market = town_center.market
if in_range(position, market.position, radius) and market.surface == surface then
return true
end
end
end
return false
end
local function in_town(force, position)
local ffatable = Table.get_table()
local town_center = ffatable.town_centers[force.name]
if town_center ~= nil then
local center = town_center.market.position
if position.x >= center.x - town_radius and position.x <= center.x + town_radius then
if position.y >= center.y - town_radius and position.y <= center.y + town_radius then
return true
end
end
end
return false
end
local function prevent_isolation_entity(event, player)
local p = player or nil
local entity = event.created_entity
local position = entity.position
if not entity.valid then return end
local entity_name = entity.name
local item = event.item
if item == nil then return end
local item_name = item.name
local force = entity.force
if force == game.forces.player then return end
if force == game.forces["rogue"] then return end
local surface = entity.surface
local error = false
if not in_town(force, position) and isolated(surface, force, position) then
error = true
entity.destroy()
if entity_name ~= "entity-ghost" and entity_name ~= "tile-ghost" then
refund_item(event, item_name)
end
--return true
end
if error == true then
if p ~= nil then
p.play_sound({ path = "utility/cannot_build", position = p.position, volume_modifier = 0.75 })
end
error_floaty(surface, position, "Building is not connected to town!")
end
end
local function prevent_isolation_tile(event, player)
local p = player or nil
local tile = event.tile
if not tile.valid then return end
local tile_name = tile.name
local surface = game.surfaces[event.surface_index]
local tiles = event.tiles
local force
if event.player_index then
force = game.players[event.player_index].force
else
force = event.robot.force
end
local error = false
local position
for _, t in pairs(tiles) do
local old_tile = t.old_tile
position = t.position
if not in_town(force, position) and isolated(surface, force, position) then
error = true
surface.set_tiles({ { name = old_tile.name, position = position } }, true)
if tile_name ~= "tile-ghost" then
if tile_name == "stone-path" then tile_name = "stone-brick" end
refund_item(event, tile_name)
end
end
end
if error == true then
if p ~= nil then
p.play_sound({ path = "utility/cannot_build", position = p.position, volume_modifier = 0.75 })
end
error_floaty(surface, position, "Tile is not connected to town!")
end
end
local function restrictions(event, player)
local p = player or nil
local entity = event.created_entity
if not entity.valid then return end
local entity_name = entity.name
local surface = entity.surface
local position = entity.position
local error = false
if entity.force == game.forces["player"] or entity.force == game.forces["rogue"] then
if Public.near_town(position, surface, 32) then
error = true
entity.destroy()
if entity_name ~= "entity-ghost" then
refund_item(event, event.stack.name)
end
else
entity.force = game.forces["neutral"]
end
return
end
if error == true then
if p ~= nil then
p.play_sound({ path = "utility/cannot_build", position = p.position, volume_modifier = 0.75 })
end
error_floaty(surface, position, "Can't build near town!")
end
if not neutral_whitelist[entity.type] then return end
entity.force = game.forces["neutral"]
end
-- called when a player places an item, or a ghost
local function on_built_entity(event)
local player = game.players[event.player_index]
if prevent_isolation_entity(event, player) then return end
restrictions(event, player)
end
local function on_robot_built_entity(event)
if prevent_isolation_entity(event) then return end
restrictions(event)
end
-- called when a player places landfill
local function on_player_built_tile(event)
local player = game.players[event.player_index]
prevent_isolation_tile(event, player)
end
local function on_robot_built_tile(event)
prevent_isolation_tile(event)
end
local Event = require 'utils.event'
Event.add(defines.events.on_built_entity, on_built_entity)
Event.add(defines.events.on_player_built_tile, on_player_built_tile)
Event.add(defines.events.on_robot_built_entity, on_robot_built_entity)
Event.add(defines.events.on_robot_built_tile, on_robot_built_tile)
return Public

View File

@ -0,0 +1,50 @@
local string_sub = string.sub
local string_len = string.len
-- ammo damage modifiers are static values that increase with research
-- modifier is multiplied by base damage and then added to damage, so a negative value will reduce base damage and a positive value will increase damage
local balance_functions = {
["land-mine"] = function(force_name)
-- landmines normally have a modifier of 0, so have them start at 25% of normal
if force_name ~= nil then
game.forces[force_name].set_ammo_damage_modifier("landmine", -0.75)
end
end,
["military-2"] = function(force_name)
-- grenades normally have a modifier of 0, so have them start at 50% of normal
if force_name ~= nil then
game.forces[force_name].set_ammo_damage_modifier("grenade", -0.5)
end
end,
["military-4"] = function(force_name)
-- cluster-grenades normally have a modifier of 0, so have them start at 50% of normal
if force_name ~= nil then
game.forces[force_name].set_ammo_damage_modifier("grenade", -0.5)
end
end,
["stronger-explosives"] = function(force_name)
-- landmines should never increase in damage with stronger explosives
if force_name ~= nil then
game.forces[force_name].set_ammo_damage_modifier("landmine", -0.75)
-- allow grenades to increase by 10%
game.forces[force_name].set_ammo_damage_modifier("grenade", game.forces[force_name].get_ammo_damage_modifier("grenade") + 0.1)
end
end,
}
local function on_research_finished(event)
local research_name = event.research.name
local force_name = event.research.force.name
local key
for b = 1, string_len(research_name), 1 do
key = string_sub(research_name, 0, b)
if balance_functions[key] then
balance_functions[key](force_name)
return
end
end
end
local Event = require 'utils.event'
Event.add(defines.events.on_research_finished, on_research_finished)

View File

@ -0,0 +1,63 @@
local Public = {}
function Public.clear_enemies(position, surface, radius)
--log("clear_enemies {" .. position.x .. "," .. position.y .. "}")
-- clear enemies
for _, e in pairs(surface.find_entities_filtered({ force = "enemy", type = { "unit-spawner", "unit", "turret" }, position = position, radius = radius })) do
e.destroy()
end
-- clear gun turrets
for _, e in pairs(surface.find_entities_filtered({ force = "enemy", name = { "gun-turret" }, position = position, radius = radius })) do
e.destroy()
end
end
function Public.clear_units(position, surface, radius)
--log("clear_units {" .. position.x .. "," .. position.y .. "}")
-- clear units
for _, e in pairs(surface.find_entities_filtered({ force = "enemy", type = { "unit" }, position = position, radius = radius })) do
e.destroy()
end
end
function Public.clear_biters(position, surface, radius)
--log("clear_units {" .. position.x .. "," .. position.y .. "}")
-- clear biters
for _, e in pairs(surface.find_entities_filtered({ force = "enemy", name = { "small-biter", "medium-biter", "big-biter", "behemoth-biter" }, position = position, radius = radius })) do
e.destroy()
end
end
function Public.clear_spitters(position, surface, radius)
--log("clear_units {" .. position.x .. "," .. position.y .. "}")
-- clear spitters
for _, e in pairs(surface.find_entities_filtered({ force = "enemy", name = { "small-spitter", "medium-spitter", "big-spitter", "behemoth-spitter" }, position = position, radius = radius })) do
e.destroy()
end
end
function Public.clear_nests(position, surface, radius)
--log("clear_unit_spawners {" .. position.x .. "," .. position.y .. "}")
-- clear enemies
for _, e in pairs(surface.find_entities_filtered({ force = "enemy", type = { "unit-spawner" }, position = position, radius = radius })) do
e.destroy()
end
end
function Public.clear_worms(position, surface, radius)
--log("clear_turrets {" .. position.x .. "," .. position.y .. "}")
-- clear enemies
for _, e in pairs(surface.find_entities_filtered({ force = "enemy", type = { "turret" }, position = position, radius = radius })) do
e.destroy()
end
end
function Public.clear_gun_turrets(position, surface, radius)
--log("clear_gun_turrets {" .. position.x .. "," .. position.y .. "}")
-- clear gun turrets
for _, e in pairs(surface.find_entities_filtered({ force = "enemy", name = { "gun-turret" }, position = position, radius = radius })) do
e.destroy()
end
end
return Public

View File

@ -0,0 +1,585 @@
local Public = {}
local math_floor = math.floor
local Table = require 'modules.scrap_towny_ffa.table'
local biters = {
[1] = "small-biter",
[2] = "medium-biter",
[3] = "big-biter",
[4] = "behemoth-biter"
}
local spitters = {
[1] = "small-spitter",
[2] = "medium-spitter",
[3] = "big-spitter",
[4] = "behemoth-spitter"
}
local worms = {
[1] = "small-worm-turret",
[2] = "medium-worm-turret",
[3] = "big-worm-turret",
[4] = "behemoth-worm-turret"
}
-- evolution max distance in tiles
local max_evolution_distance = 1024
local max_pollution_behemoth = 256
local max_pollution_big = 64
local max_pollution_medium = 16
local max_factor = 0.8
-- technology weights (biter, spitter, worm)
local technology_weights = {
['advanced-electronics'] = { biter = 1, spitter = 1, worm = 1 },
['advanced-electronics-2'] = { biter = 1, spitter = 1, worm = 1 },
['advanced-material-processing'] = { biter = 1, spitter = 1, worm = 1 },
['advanced-material-processing-2'] = { biter = 1, spitter = 1, worm = 1 },
['advanced-oil-processing'] = { biter = 1, spitter = 1, worm = 1 },
['artillery']={biter=1, spitter=1, worm=1},
['artillery-shell-range-1']={biter=1, spitter=1, worm=1},
['artillery-shell-speed-1']={biter=1, spitter=1, worm=1},
['atomic-bomb']={biter=1, spitter=1, worm=1},
['automated-rail-transportation'] = { biter = 1, spitter = 1, worm = 1 },
['automation'] = { biter = 1, spitter = 1, worm = 1 },
['automation-2'] = { biter = 1, spitter = 1, worm = 1 },
['automation-3'] = { biter = 1, spitter = 1, worm = 1 },
['automobilism'] = { biter = 1, spitter = 1, worm = 1 },
['battery'] = { biter = 1, spitter = 1, worm = 1 },
['battery-equipment'] = { biter = 1, spitter = 1, worm = 1 },
['battery-mk2-equipment'] = { biter = 1, spitter = 1, worm = 1 },
['belt-immunity-equipment'] = { biter = 1, spitter = 1, worm = 1 },
['braking-force-1'] = { biter = 1, spitter = 1, worm = 1 },
['braking-force-2'] = { biter = 1, spitter = 1, worm = 1 },
['braking-force-3'] = { biter = 1, spitter = 1, worm = 1 },
['braking-force-4'] = { biter = 1, spitter = 1, worm = 1 },
['braking-force-5'] = { biter = 1, spitter = 1, worm = 1 },
['braking-force-6'] = { biter = 1, spitter = 1, worm = 1 },
['braking-force-7'] = { biter = 1, spitter = 1, worm = 1 },
['chemical-science-pack'] = { biter = 125, spitter = 125, worm = 125 },
['circuit-network'] = { biter = 1, spitter = 1, worm = 1 },
['cliff-explosives'] = { biter = 1, spitter = 1, worm = 1 },
['coal-liquefaction'] = { biter = 1, spitter = 1, worm = 1 },
['concrete'] = { biter = 1, spitter = 1, worm = 1 },
['construction-robotics'] = { biter = 1, spitter = 1, worm = 1 },
['defender'] = { biter = 1, spitter = 1, worm = 1 },
['destroyer'] = { biter = 1, spitter = 1, worm = 1 },
['discharge-defense-equipment'] = { biter = 5, spitter = 5, worm = 5 },
['distractor'] = { biter = 1, spitter = 1, worm = 1 },
['effect-transmission'] = { biter = 1, spitter = 1, worm = 1 },
['effectivity-module'] = { biter = 1, spitter = 1, worm = 1 },
['effectivity-module-2'] = { biter = 1, spitter = 1, worm = 1 },
['effectivity-module-3'] = { biter = 1, spitter = 1, worm = 1 },
['electric-energy-accumulators'] = { biter = 1, spitter = 1, worm = 1 },
['electric-energy-distribution-1'] = { biter = 1, spitter = 1, worm = 1 },
['electric-energy-distribution-2'] = { biter = 1, spitter = 1, worm = 1 },
['electric-engine'] = { biter = 1, spitter = 1, worm = 1 },
['electronics'] = { biter = 1, spitter = 1, worm = 1 },
['energy-shield-equipment'] = { biter = 5, spitter = 5, worm = 5 },
['energy-shield-mk2-equipment'] = { biter = 5, spitter = 5, worm = 5 },
['energy-weapons-damage-1'] = { biter = 5, spitter = 5, worm = 5 },
['energy-weapons-damage-2'] = { biter = 5, spitter = 5, worm = 5 },
['energy-weapons-damage-3'] = { biter = 5, spitter = 5, worm = 5 },
['energy-weapons-damage-4'] = { biter = 5, spitter = 5, worm = 5 },
['energy-weapons-damage-5'] = { biter = 5, spitter = 5, worm = 5 },
['energy-weapons-damage-6'] = { biter = 5, spitter = 5, worm = 5 },
['energy-weapons-damage-7'] = { biter = 5, spitter = 5, worm = 5 },
['engine'] = { biter = 1, spitter = 1, worm = 1 },
['exoskeleton-equipment'] = { biter = 5, spitter = 5, worm = 5 },
['explosive-rocketry']={biter=1, spitter=1, worm=1},
['explosives'] = { biter = 5, spitter = 5, worm = 5 },
['fast-inserter'] = { biter = 1, spitter = 1, worm = 1 },
['flamethrower'] = { biter = 5, spitter = 5, worm = 5 },
['flammables'] = { biter = 1, spitter = 1, worm = 1 },
['fluid-handling'] = { biter = 1, spitter = 1, worm = 1 },
['fluid-wagon'] = { biter = 1, spitter = 1, worm = 1 },
['follower-robot-count-1'] = { biter = 1, spitter = 1, worm = 1 },
['follower-robot-count-2'] = { biter = 1, spitter = 1, worm = 1 },
['follower-robot-count-3'] = { biter = 1, spitter = 1, worm = 1 },
['follower-robot-count-4'] = { biter = 1, spitter = 1, worm = 1 },
['follower-robot-count-5'] = { biter = 1, spitter = 1, worm = 1 },
['follower-robot-count-6'] = { biter = 1, spitter = 1, worm = 1 },
['follower-robot-count-7'] = { biter = 1, spitter = 1, worm = 1 },
['fusion-reactor-equipment'] = { biter = 1, spitter = 1, worm = 1 },
['gate'] = { biter = 1, spitter = 1, worm = 1 },
['gun-turret'] = { biter = 1, spitter = 1, worm = 1 },
['heavy-armor'] = { biter = 5, spitter = 5, worm = 5 },
['improved-equipment'] = { biter = 1, spitter = 1, worm = 1 },
['inserter-capacity-bonus-1'] = { biter = 1, spitter = 1, worm = 1 },
['inserter-capacity-bonus-3'] = { biter = 1, spitter = 1, worm = 1 },
['inserter-capacity-bonus-4'] = { biter = 1, spitter = 1, worm = 1 },
['inserter-capacity-bonus-5'] = { biter = 1, spitter = 1, worm = 1 },
['inserter-capacity-bonus-6'] = { biter = 1, spitter = 1, worm = 1 },
['inserter-capacity-bonus-7'] = { biter = 1, spitter = 1, worm = 1 },
['kovarex-enrichment-process'] = { biter = 1, spitter = 1, worm = 1 },
['land-mine'] = { biter = 5, spitter = 5, worm = 5 },
['landfill'] = { biter = 1, spitter = 1, worm = 1 },
['laser'] = { biter = 5, spitter = 5, worm = 5 },
['laser-turret-speed-1'] = { biter = 5, spitter = 5, worm = 5 },
['laser-turret-speed-2'] = { biter = 5, spitter = 5, worm = 5 },
['laser-turret-speed-3'] = { biter = 5, spitter = 5, worm = 5 },
['laser-turret-speed-4'] = { biter = 5, spitter = 5, worm = 5 },
['laser-turret-speed-5'] = { biter = 5, spitter = 5, worm = 5 },
['laser-turret-speed-6'] = { biter = 5, spitter = 5, worm = 5 },
['laser-turret-speed-7'] = { biter = 5, spitter = 5, worm = 5 },
['laser-turret'] = { biter = 5, spitter = 5, worm = 5 },
['logistic-robotics'] = { biter = 1, spitter = 1, worm = 1 },
['logistic-science-pack'] = { biter = 25, spitter = 25, worm = 25 },
['logistic-system'] = { biter = 1, spitter = 1, worm = 1 },
['logistics'] = { biter = 1, spitter = 1, worm = 1 },
['logistics-2'] = { biter = 1, spitter = 1, worm = 1 },
['logistics-3'] = { biter = 1, spitter = 1, worm = 1 },
['low-density-structure'] = { biter = 1, spitter = 1, worm = 1 },
['lubricant'] = { biter = 1, spitter = 1, worm = 1 },
['military'] = { biter = 5, spitter = 5, worm = 5 },
['military-2'] = { biter = 5, spitter = 5, worm = 5 },
['military-3'] = { biter = 5, spitter = 5, worm = 51 },
['military-4'] = { biter = 5, spitter = 5, worm = 5 },
['military-science-pack'] = { biter = 50, spitter = 50, worm = 50 },
['mining-productivity-1'] = { biter = 1, spitter = 1, worm = 1 },
['mining-productivity-2'] = { biter = 1, spitter = 1, worm = 1 },
['mining-productivity-3'] = { biter = 1, spitter = 1, worm = 1 },
['mining-productivity-4'] = { biter = 1, spitter = 1, worm = 1 },
['modular-armor'] = { biter = 1, spitter = 1, worm = 1 },
['modules'] = { biter = 1, spitter = 1, worm = 1 },
['night-vision-equipment'] = { biter = 1, spitter = 1, worm = 1 },
['nuclear-fuel-reprocessing'] = { biter = 1, spitter = 1, worm = 1 },
['nuclear-power'] = { biter = 1, spitter = 1, worm = 1 },
['oil-processing'] = { biter = 1, spitter = 1, worm = 1 },
['optics'] = { biter = 1, spitter = 1, worm = 1 },
['personal-laser-defense-equipment'] = { biter = 5, spitter = 5, worm = 5 },
['personal-roboport-equipment'] = { biter = 1, spitter = 1, worm = 1 },
['personal-roboport-mk2-equipment'] = { biter = 1, spitter = 1, worm = 1 },
['physical-projectile-damage-1'] = { biter = 5, spitter = 5, worm = 5 },
['physical-projectile-damage-2'] = { biter = 5, spitter = 5, worm = 5 },
['physical-projectile-damage-3'] = { biter = 5, spitter = 5, worm = 5 },
['physical-projectile-damage-4'] = { biter = 5, spitter = 5, worm = 5 },
['physical-projectile-damage-5'] = { biter = 5, spitter = 5, worm = 5 },
['physical-projectile-damage-6'] = { biter = 5, spitter = 5, worm = 5 },
['physical-projectile-damage-7'] = { biter = 5, spitter = 5, worm = 5 },
['plastics'] = { biter = 1, spitter = 1, worm = 1 },
['power-armor'] = { biter = 5, spitter = 5, worm = 5 },
['power-armor-mk2'] = { biter = 5, spitter = 5, worm = 5 },
['production-science-pack'] = { biter = 250, spitter = 250, worm = 250 },
['productivity-module'] = { biter = 1, spitter = 1, worm = 1 },
['productivity-module-2'] = { biter = 1, spitter = 1, worm = 1 },
['productivity-module-3'] = { biter = 1, spitter = 1, worm = 1 },
['rail-signals'] = { biter = 1, spitter = 1, worm = 1 },
['railway'] = { biter = 1, spitter = 1, worm = 1 },
['refined-flammables-1'] = { biter = 5, spitter = 5, worm = 5 },
['refined-flammables-2'] = { biter = 5, spitter = 5, worm = 51 },
['refined-flammables-3'] = { biter = 5, spitter = 5, worm = 5 },
['refined-flammables-4'] = { biter = 5, spitter = 5, worm = 5 },
['refined-flammables-5'] = { biter = 5, spitter = 5, worm = 5 },
['refined-flammables-6'] = { biter = 5, spitter = 5, worm = 5 },
['refined-flammables-7'] = { biter = 5, spitter = 5, worm = 51 },
['research-speed-1'] = { biter = 1, spitter = 1, worm = 1 },
['research-speed-2'] = { biter = 1, spitter = 1, worm = 1 },
['research-speed-3'] = { biter = 1, spitter = 1, worm = 1 },
['research-speed-4'] = { biter = 1, spitter = 1, worm = 1 },
['research-speed-5'] = { biter = 1, spitter = 1, worm = 1 },
['research-speed-6'] = { biter = 1, spitter = 1, worm = 1 },
['robotics'] = { biter = 1, spitter = 1, worm = 1 },
['rocket-control-unit'] = { biter = 1, spitter = 1, worm = 1 },
['rocket-fuel'] = { biter = 1, spitter = 1, worm = 1 },
['rocket-silo'] = { biter = 1, spitter = 1, worm = 1 },
['rocketry']={biter=1, spitter=1, worm=1},
['solar-energy'] = { biter = 1, spitter = 1, worm = 1 },
['solar-panel-equipment'] = { biter = 1, spitter = 1, worm = 1 },
['space-science-pack'] = { biter = 1000, spitter = 1000, worm = 1000 },
['speed-module'] = { biter = 1, spitter = 1, worm = 1 },
['speed-module-2'] = { biter = 1, spitter = 1, worm = 1 },
['speed-module-3'] = { biter = 1, spitter = 1, worm = 1 },
['spidertron'] = { biter = 1, spitter = 1, worm = 1 },
['stack-inserter'] = { biter = 1, spitter = 1, worm = 1 },
['steel-axe'] = { biter = 1, spitter = 1, worm = 1 },
['steel-processing'] = { biter = 1, spitter = 1, worm = 1 },
['stone-wall'] = { biter = 1, spitter = 1, worm = 1 },
['stronger-explosives-1'] = { biter = 5, spitter = 5, worm = 5 },
['stronger-explosives-2'] = { biter = 5, spitter = 5, worm = 5 },
['stronger-explosives-3'] = { biter = 5, spitter = 5, worm = 5 },
['stronger-explosives-4'] = { biter = 5, spitter = 5, worm = 5 },
['stronger-explosives-5'] = { biter = 5, spitter = 5, worm = 5 },
['stronger-explosives-6'] = { biter = 5, spitter = 5, worm = 5 },
['stronger-explosives-7'] = { biter = 5, spitter = 5, worm = 51 },
['sulfur-processing'] = { biter = 1, spitter = 1, worm = 1 },
['tank'] = { biter = 1, spitter = 1, worm = 1 },
['toolbelt'] = { biter = 1, spitter = 1, worm = 1 },
['uranium-ammo'] = { biter = 1, spitter = 1, worm = 1 },
['uranium-processing'] = { biter = 1, spitter = 1, worm = 1 },
['utility-science-pack'] = { biter = 500, spitter = 500, worm = 500 },
['weapon-shooting-speed-1'] = { biter = 5, spitter = 5, worm = 5 },
['weapon-shooting-speed-2'] = { biter = 5, spitter = 5, worm = 5 },
['weapon-shooting-speed-3'] = { biter = 5, spitter = 5, worm = 5 },
['weapon-shooting-speed-4'] = { biter = 5, spitter = 5, worm = 5 },
['weapon-shooting-speed-5'] = { biter = 5, spitter = 5, worm = 5 },
['weapon-shooting-speed-6'] = { biter = 5, spitter = 5, worm = 5 },
['worker-robots-speed-1'] = { biter = 1, spitter = 1, worm = 1 },
['worker-robots-speed-2'] = { biter = 1, spitter = 1, worm = 1 },
['worker-robots-speed-3'] = { biter = 1, spitter = 1, worm = 1 },
['worker-robots-speed-4'] = { biter = 1, spitter = 1, worm = 1 },
['worker-robots-speed-5'] = { biter = 1, spitter = 1, worm = 1 },
['worker-robots-speed-6'] = { biter = 1, spitter = 1, worm = 1 },
['worker-robots-storage-1'] = { biter = 1, spitter = 1, worm = 1 },
['worker-robots-storage-2'] = { biter = 1, spitter = 1, worm = 1 },
['worker-robots-storage-3'] = { biter = 1, spitter = 1, worm = 1 },
}
local max_biter_weight = 0
local max_spitter_weight = 0
local max_worm_weight = 0
for _, weight in pairs(technology_weights) do
max_biter_weight = max_biter_weight + weight.biter
max_spitter_weight = max_spitter_weight + weight.spitter
max_worm_weight = max_worm_weight + weight.worm
end
max_biter_weight = max_biter_weight * max_factor
max_spitter_weight = max_spitter_weight * max_factor
max_worm_weight = max_worm_weight * max_factor
local function get_unit_size(evolution)
-- returns a value 0-3 that represents the unit size
-- basically evo values of: 0%, 10%, 30%, 60%, 80%, 100%
-- small unit chances are 100%, 100%, 50%, 25%, 12.5%, 0%
-- medium unit chances are 0%, 0%, 50%, 25%, 12.5%, 0%
-- big unit chances are 0%, 0%, 0%, 50%, 25%, 0%
-- behemoth unit chances are 0%, 0%, 0%, 0%, 50%, 100%
-- and curve accordingly in between evo values
-- magic stuff happens here
if (evolution < 0.10) then return 1 end
if (evolution >= 0.10 and evolution < 0.40) then
local r = (evolution - 0.10) * 5
if math.random() < 0.5 then return 1 end
if math.random() < r then return 1 end
return 2
end
if (evolution >= 0.30 and evolution < 0.60) then
local r = (evolution - 0.30) * 3.3333
if math.random() < 0.5 then
if math.random() < 0.5 then
return 1
else
if math.random() < r then return 1 else return 2 end
end
else
if math.random() < r then return 2 else return 3 end
end
end
if (evolution >= 0.60 and evolution < 0.80) then
local r = (evolution - 0.60) * 5
if math.random() < 0.5 then
if math.random() < 0.5 then
if math.random() < r then return 1 else return 2 end
else
if math.random() < r then return 2 else return 3 end
end
else
if math.random() < r then return 3 else return 4 end
end
end
if (evolution >= 0.80 and evolution < 1.0) then
local r = (evolution - 0.80) * 5
if math.random() < 0.5 then
if math.random() < r then
if math.random() < r then
return 1
else return 2 end
else return 3 end
else return 4 end
end
if (evolution >= 1.0) then return 4 end
end
local function distance_squared(pos1, pos2)
-- calculate the distance squared
local dx = pos1.x - pos2.x
local dy = pos1.y - pos2.y
local d2 = dx * dx + dy * dy
return d2
end
local function get_relative_biter_evolution(position)
local ffatable = Table.get_table()
local relative_evolution = 0.0
local max_d2 = max_evolution_distance * max_evolution_distance
-- for all of the teams
local teams = ffatable.town_centers
for _, town_center in pairs(teams) do
local market_position = town_center.market.position
-- calculate the distance squared
local d2 = distance_squared(position, market_position)
if d2 < max_d2 then
-- get the distance factor (0.0-1.0)
local distance_factor = 1.0 - d2 / max_d2;
-- get the evolution factor (0.0-1.0)
if not town_center.evolution then town_center.evolution = {} end
if town_center.evolution.biters == nil then town_center.evolution.biters = 0.0 end
local evolution_factor = town_center.evolution.biters
local evo = distance_factor * evolution_factor
relative_evolution = math.max(relative_evolution, evo)
end
end
return relative_evolution
end
local function get_relative_spitter_evolution(position)
local ffatable = Table.get_table()
local relative_evolution = 0.0
local max_d2 = max_evolution_distance * max_evolution_distance
-- for all of the teams
local teams = ffatable.town_centers
for _, town_center in pairs(teams) do
local market_position = town_center.market.position
-- calculate the distance squared
local d2 = distance_squared(position, market_position)
if d2 < max_d2 then
-- get the distance factor (0.0-1.0)
local distance_factor = 1.0 - d2 / max_d2;
-- get the evolution factor (0.0-1.0)
if not town_center.evolution then town_center.evolution = {} end
if town_center.evolution.spitters == nil then town_center.evolution.spitters = 0.0 end
local evolution_factor = town_center.evolution.spitters
local evo = distance_factor * evolution_factor
relative_evolution = math.max(relative_evolution, evo)
end
end
return relative_evolution
end
local function get_relative_worm_evolution(position)
local ffatable = Table.get_table()
local relative_evolution = 0.0
local max_d2 = max_evolution_distance * max_evolution_distance
-- for all of the teams
local teams = ffatable.town_centers
for _, town_center in pairs(teams) do
local market_position = town_center.market.position
-- calculate the distance squared
local d2 = distance_squared(position, market_position)
if d2 < max_d2 then
-- get the distance factor (0.0-1.0)
local distance_factor = 1.0 - d2 / max_d2;
-- get the evolution factor (0.0-1.0)
if not town_center.evolution then town_center.evolution = {} end
if town_center.evolution.worms == nil then town_center.evolution.worms = 0.0 end
local evolution_factor = town_center.evolution.worms
local evo = distance_factor * evolution_factor
relative_evolution = math.max(relative_evolution, evo)
end
end
return relative_evolution
end
function Public.get_evolution(position)
return get_relative_biter_evolution(position)
end
function Public.get_biter_evolution(entity)
return get_relative_biter_evolution(entity.position)
end
function Public.get_spitter_evolution(entity)
return get_relative_spitter_evolution(entity.position)
end
function Public.get_worm_evolution(entity)
return get_relative_worm_evolution(entity.position)
end
local function get_nearby_location(position, surface, radius, entity_name)
return surface.find_non_colliding_position(entity_name, position, radius, 0.5, false)
end
local function set_biter_type(entity)
-- checks nearby evolution levels for bases and returns an appropriately leveled type
local position = entity.position
local evo = get_relative_biter_evolution(position)
local unit_size = get_unit_size(evo)
local entity_name = biters[unit_size]
if entity.name == entity_name then return end
local surface = entity.surface
local pollution = surface.get_pollution(position)
local behemoth = math_floor(pollution / max_pollution_behemoth)
local big = math_floor((pollution - (behemoth * max_pollution_behemoth)) / max_pollution_big)
local medium = math_floor((pollution - (behemoth * max_pollution_behemoth) - (big * max_pollution_big)) / max_pollution_medium)
local small = pollution - (behemoth * max_pollution_behemoth) - (big * max_pollution_big) - (medium * max_pollution_medium) + 1
if entity.valid then
for _ = 1, behemoth do
local e = surface.create_entity({ name = biters[4], position = get_nearby_location(position, surface, 5, biters[4]) })
e.copy_settings(entity);
e.ai_settings.allow_try_return_to_spawner = true
end
for _ = 1, big do
local e = surface.create_entity({ name = biters[3], position = get_nearby_location(position, surface, 5, biters[3]) })
e.copy_settings(entity);
e.ai_settings.allow_try_return_to_spawner = true
end
for _ = 1, medium do
local e = surface.create_entity({ name = biters[2], position = get_nearby_location(position, surface, 5, biters[2]) })
e.copy_settings(entity);
e.ai_settings.allow_try_return_to_spawner = true
end
for _ = 1, small do
local e = surface.create_entity({ name = biters[1], position = get_nearby_location(position, surface, 5, biters[1]) })
e.copy_settings(entity);
e.ai_settings.allow_try_return_to_spawner = true
end
local e = surface.create_entity({ name = entity_name, position = get_nearby_location(position, surface, 5, entity_name) })
e.copy_settings(entity);
e.ai_settings.allow_try_return_to_spawner = true
entity.destroy()
--log("spawned " .. entity_name)
end
end
local function set_spitter_type(entity)
-- checks nearby evolution levels for bases and returns an appropriately leveled type
local position = entity.position
local evo = get_relative_spitter_evolution(position)
local unit_size = get_unit_size(evo)
local entity_name = spitters[unit_size]
if entity.name == entity_name then return end
local surface = entity.surface
local pollution = surface.get_pollution(position)
local behemoth = math_floor(pollution / max_pollution_behemoth)
local big = math_floor((pollution - (behemoth * max_pollution_behemoth)) / max_pollution_big)
local medium = math_floor((pollution - (behemoth * max_pollution_behemoth) - (big * max_pollution_big)) / max_pollution_medium)
local small = pollution - (behemoth * max_pollution_behemoth) - (big * max_pollution_big) - (medium * max_pollution_medium) + 1
if entity.valid then
for _ = 1, behemoth do
local e = surface.create_entity({ name = spitters[4], position = get_nearby_location(position, surface, 5, spitters[4]) })
e.copy_settings(entity);
e.ai_settings.allow_try_return_to_spawner = true
end
for _ = 1, big do
local e = surface.create_entity({ name = spitters[3], position = get_nearby_location(position, surface, 5, spitters[3]) })
e.copy_settings(entity);
e.ai_settings.allow_try_return_to_spawner = true
end
for _ = 1, medium do
local e = surface.create_entity({ name = spitters[2], position = get_nearby_location(position, surface, 5, spitters[2]) })
e.copy_settings(entity);
e.ai_settings.allow_try_return_to_spawner = true
end
for _ = 1, small do
local e = surface.create_entity({ name = spitters[1], position = get_nearby_location(position, surface, 5, spitters[1]) })
e.copy_settings(entity);
e.ai_settings.allow_try_return_to_spawner = true
end
local e = surface.create_entity({ name = entity_name, position = get_nearby_location(position, surface, 5, entity_name) })
e.copy_settings(entity);
e.ai_settings.allow_try_return_to_spawner = true
entity.destroy()
--log("spawned " .. entity_name)
end
end
local function set_worm_type(entity)
-- checks nearby evolution levels for bases and returns an appropriately leveled type
local position = entity.position
local evo = get_relative_worm_evolution(position)
local unit_size = get_unit_size(evo)
local entity_name = worms[unit_size]
if entity.name == entity_name then return end
local surface = entity.surface
if entity.valid then
entity.destroy()
surface.create_entity({ name = entity_name, position = position })
--log("spawned " .. entity_name)
end
end
local function is_biter(entity)
if entity == nil or not entity.valid then return false end
if entity.name == 'small-biter' or entity.name == 'medium-biter' or entity.name == 'big-biter' or entity.name == 'behemoth-biter' then
return true
end
return false
end
local function is_spitter(entity)
if entity == nil or not entity.valid then return false end
if entity.name == 'small-spitter' or entity.name == 'medium-spitter' or entity.name == 'big-spitter' or entity.name == 'behemoth-spitter' then
return true
end
return false
end
local function is_worm(entity)
if entity == nil or not entity.valid then return false end
if entity.name == 'small-worm-turret' or entity.name == 'medium-worm-turret' or entity.name == 'big-worm-turret' or entity.name == 'behemoth-worm-turret' then
return true
end
return false
end
local function update_evolution(force_name, technology)
if technology == nil then return end
local ffatable = Table.get_table()
-- update evolution based on research completed (weighted)
local town_center = ffatable.town_centers[force_name]
-- town_center is a reference to a global table
if not town_center then return end
-- initialize if not already
local evo = town_center.evolution
-- get the weights for this technology
local weight = technology_weights[technology]
if weight == nil then
log("no technology_weights for " .. technology)
return
end
local biter_weight = weight.biter
local spitter_weight = weight.spitter
local worm_weight = weight.worm
-- update the evolution values (0.0 to 1.0)
local b = (biter_weight / max_biter_weight)
local s = (spitter_weight / max_spitter_weight)
local w = (worm_weight / max_worm_weight)
b = b + evo.biters
s = s + evo.spitters
w = w + evo.worms
evo.biters = b
evo.spitters = s
evo.worms = w
end
local function on_research_finished(event)
local research = event.research
local force_name = research.force.name
local technology = research.name
update_evolution(force_name, technology)
end
local function on_entity_spawned(event)
local entity = event.entity
-- check the unit type and handle appropriately
if is_biter(entity) then
set_biter_type(entity)
end
if is_spitter(entity) then
set_spitter_type(entity)
end
if is_worm(entity) then
set_worm_type(entity)
end
end
local function on_biter_base_built(event)
local entity = event.entity
if is_worm(entity) then
set_worm_type(entity)
end
end
local Event = require 'utils.event'
Event.add(defines.events.on_research_finished, on_research_finished)
Event.add(defines.events.on_entity_spawned, on_entity_spawned)
Event.add(defines.events.on_biter_base_built, on_biter_base_built)
return Public

View File

@ -0,0 +1,228 @@
--This will add a new game mechanic so that containers with explosives actually go boom when they get damaged.
--Made by MewMew
local math_min = math.min
local math_random = math.random
local Table = require 'modules.scrap_towny_ffa.table'
local Pollution = require "modules.scrap_towny_ffa.pollution"
--local damage_per_explosive = 100
local damage_per_explosive = 50
local empty_tile_damage_decay = 100
local out_of_map_tile_health = 1500
local max_volatility = 20
local explosive_items = {
["explosives"] = 1,
["land-mine"] = 1,
["grenade"] = 1,
["cluster-grenade"] = 3,
["artillery-shell"] = 5,
["cannon-shell"] = 3,
["explosive-cannon-shell"] = 5,
["explosive-uranium-cannon-shell"] = 5,
["uranium-cannon-shell"] = 5,
-- ["atomic-bomb"] = 100,
["explosive-rocket"] = 5,
["rocket"] = 2,
["flamethrower-ammo"] = 2,
["petroleum-gas-barrel"] = 2,
-- ["crude-oil-barrel"] = 2,
-- ["light-oil-barrel"] = 2,
-- ["heavy-oil-barrel"] = 2,
-- ["lubricant-barrel"] = 1,
-- ["shotgun-shell"] = 1,
-- ["piercing-shotgun-shell"] = 1,
-- ["firearm-magazine"] = 1,
-- ["piercing-rounds-magazine"] = 1,
-- ["uranium-rounds-magazine"] = 1,
["cliff-explosives"] = 2,
-- ["solid-fuel"] = 1
}
local circle_coordinates = {
[1] = { { x = 0, y = 0 } },
[2] = { { x = -1, y = -1 }, { x = 1, y = -1 }, { x = 0, y = -1 }, { x = -1, y = 0 }, { x = -1, y = 1 }, { x = 0, y = 1 }, { x = 1, y = 1 }, { x = 1, y = 0 } },
[3] = { { x = -2, y = -1 }, { x = -1, y = -2 }, { x = 1, y = -2 }, { x = 0, y = -2 }, { x = 2, y = -1 }, { x = -2, y = 1 }, { x = -2, y = 0 }, { x = 2, y = 1 }, { x = 2, y = 0 }, { x = -1, y = 2 }, { x = 1, y = 2 }, { x = 0, y = 2 } },
[4] = { { x = -1, y = -3 }, { x = 1, y = -3 }, { x = 0, y = -3 }, { x = -3, y = -1 }, { x = -2, y = -2 }, { x = 3, y = -1 }, { x = 2, y = -2 }, { x = -3, y = 0 }, { x = -3, y = 1 }, { x = 3, y = 1 }, { x = 3, y = 0 }, { x = -2, y = 2 }, { x = -1, y = 3 }, { x = 0, y = 3 }, { x = 1, y = 3 }, { x = 2, y = 2 } },
[5] = { { x = -3, y = -3 }, { x = -2, y = -3 }, { x = -1, y = -4 }, { x = -2, y = -4 }, { x = 1, y = -4 }, { x = 0, y = -4 }, { x = 2, y = -3 }, { x = 3, y = -3 }, { x = 2, y = -4 }, { x = -3, y = -2 }, { x = -4, y = -1 }, { x = -4, y = -2 }, { x = 3, y = -2 }, { x = 4, y = -1 }, { x = 4, y = -2 }, { x = -4, y = 1 }, { x = -4, y = 0 }, { x = 4, y = 1 }, { x = 4, y = 0 }, { x = -3, y = 3 }, { x = -3, y = 2 }, { x = -4, y = 2 }, { x = -2, y = 3 }, { x = 2, y = 3 }, { x = 3, y = 3 }, { x = 3, y = 2 }, { x = 4, y = 2 }, { x = -2, y = 4 }, { x = -1, y = 4 }, { x = 0, y = 4 }, { x = 1, y = 4 }, { x = 2, y = 4 } },
[6] = { { x = -1, y = -5 }, { x = -2, y = -5 }, { x = 1, y = -5 }, { x = 0, y = -5 }, { x = 2, y = -5 }, { x = -3, y = -4 }, { x = -4, y = -3 }, { x = 3, y = -4 }, { x = 4, y = -3 }, { x = -5, y = -1 }, { x = -5, y = -2 }, { x = 5, y = -1 }, { x = 5, y = -2 }, { x = -5, y = 1 }, { x = -5, y = 0 }, { x = 5, y = 1 }, { x = 5, y = 0 }, { x = -5, y = 2 }, { x = -4, y = 3 }, { x = 4, y = 3 }, { x = 5, y = 2 }, { x = -3, y = 4 }, { x = -2, y = 5 }, { x = -1, y = 5 }, { x = 0, y = 5 }, { x = 1, y = 5 }, { x = 3, y = 4 }, { x = 2, y = 5 } },
[7] = { { x = -4, y = -5 }, { x = -3, y = -5 }, { x = -2, y = -6 }, { x = -1, y = -6 }, { x = 0, y = -6 }, { x = 1, y = -6 }, { x = 3, y = -5 }, { x = 2, y = -6 }, { x = 4, y = -5 }, { x = -5, y = -4 }, { x = -5, y = -3 }, { x = -4, y = -4 }, { x = 4, y = -4 }, { x = 5, y = -4 }, { x = 5, y = -3 }, { x = -6, y = -1 }, { x = -6, y = -2 }, { x = 6, y = -1 }, { x = 6, y = -2 }, { x = -6, y = 1 }, { x = -6, y = 0 }, { x = 6, y = 1 }, { x = 6, y = 0 }, { x = -5, y = 3 }, { x = -6, y = 2 }, { x = 5, y = 3 }, { x = 6, y = 2 }, { x = -5, y = 4 }, { x = -4, y = 4 }, { x = -4, y = 5 }, { x = -3, y = 5 }, { x = 3, y = 5 }, { x = 4, y = 4 }, { x = 5, y = 4 }, { x = 4, y = 5 }, { x = -1, y = 6 }, { x = -2, y = 6 }, { x = 1, y = 6 }, { x = 0, y = 6 }, { x = 2, y = 6 } },
[8] = { { x = -1, y = -7 }, { x = -2, y = -7 }, { x = 1, y = -7 }, { x = 0, y = -7 }, { x = 2, y = -7 }, { x = -5, y = -5 }, { x = -4, y = -6 }, { x = -3, y = -6 }, { x = 3, y = -6 }, { x = 4, y = -6 }, { x = 5, y = -5 }, { x = -6, y = -3 }, { x = -6, y = -4 }, { x = 6, y = -4 }, { x = 6, y = -3 }, { x = -7, y = -1 }, { x = -7, y = -2 }, { x = 7, y = -1 }, { x = 7, y = -2 }, { x = -7, y = 1 }, { x = -7, y = 0 }, { x = 7, y = 1 }, { x = 7, y = 0 }, { x = -7, y = 2 }, { x = -6, y = 3 }, { x = 6, y = 3 }, { x = 7, y = 2 }, { x = -5, y = 5 }, { x = -6, y = 4 }, { x = 5, y = 5 }, { x = 6, y = 4 }, { x = -3, y = 6 }, { x = -4, y = 6 }, { x = -2, y = 7 }, { x = -1, y = 7 }, { x = 0, y = 7 }, { x = 1, y = 7 }, { x = 3, y = 6 }, { x = 2, y = 7 }, { x = 4, y = 6 } },
[9] = { { x = -4, y = -7 }, { x = -3, y = -7 }, { x = -2, y = -8 }, { x = -1, y = -8 }, { x = 0, y = -8 }, { x = 1, y = -8 }, { x = 3, y = -7 }, { x = 2, y = -8 }, { x = 4, y = -7 }, { x = -5, y = -6 }, { x = -6, y = -6 }, { x = -6, y = -5 }, { x = 5, y = -6 }, { x = 6, y = -5 }, { x = 6, y = -6 }, { x = -7, y = -4 }, { x = -7, y = -3 }, { x = 7, y = -4 }, { x = 7, y = -3 }, { x = -8, y = -2 }, { x = -8, y = -1 }, { x = 8, y = -1 }, { x = 8, y = -2 }, { x = -8, y = 0 }, { x = -8, y = 1 }, { x = 8, y = 1 }, { x = 8, y = 0 }, { x = -7, y = 3 }, { x = -8, y = 2 }, { x = 7, y = 3 }, { x = 8, y = 2 }, { x = -7, y = 4 }, { x = -6, y = 5 }, { x = 6, y = 5 }, { x = 7, y = 4 }, { x = -5, y = 6 }, { x = -6, y = 6 }, { x = -4, y = 7 }, { x = -3, y = 7 }, { x = 3, y = 7 }, { x = 5, y = 6 }, { x = 4, y = 7 }, { x = 6, y = 6 }, { x = -2, y = 8 }, { x = -1, y = 8 }, { x = 0, y = 8 }, { x = 1, y = 8 }, { x = 2, y = 8 } },
[10] = { { x = -3, y = -9 }, { x = -1, y = -9 }, { x = -2, y = -9 }, { x = 1, y = -9 }, { x = 0, y = -9 }, { x = 3, y = -9 }, { x = 2, y = -9 }, { x = -5, y = -7 }, { x = -6, y = -7 }, { x = -5, y = -8 }, { x = -4, y = -8 }, { x = -3, y = -8 }, { x = 3, y = -8 }, { x = 5, y = -7 }, { x = 5, y = -8 }, { x = 4, y = -8 }, { x = 6, y = -7 }, { x = -7, y = -5 }, { x = -7, y = -6 }, { x = -8, y = -5 }, { x = 7, y = -5 }, { x = 7, y = -6 }, { x = 8, y = -5 }, { x = -9, y = -3 }, { x = -8, y = -4 }, { x = -8, y = -3 }, { x = 8, y = -4 }, { x = 8, y = -3 }, { x = 9, y = -3 }, { x = -9, y = -1 }, { x = -9, y = -2 }, { x = 9, y = -1 }, { x = 9, y = -2 }, { x = -9, y = 1 }, { x = -9, y = 0 }, { x = 9, y = 1 }, { x = 9, y = 0 }, { x = -9, y = 3 }, { x = -9, y = 2 }, { x = -8, y = 3 }, { x = 8, y = 3 }, { x = 9, y = 3 }, { x = 9, y = 2 }, { x = -7, y = 5 }, { x = -8, y = 5 }, { x = -8, y = 4 }, { x = 7, y = 5 }, { x = 8, y = 5 }, { x = 8, y = 4 }, { x = -7, y = 6 }, { x = -6, y = 7 }, { x = -5, y = 7 }, { x = 5, y = 7 }, { x = 7, y = 6 }, { x = 6, y = 7 }, { x = -5, y = 8 }, { x = -4, y = 8 }, { x = -3, y = 8 }, { x = -3, y = 9 }, { x = -2, y = 9 }, { x = -1, y = 9 }, { x = 0, y = 9 }, { x = 1, y = 9 }, { x = 3, y = 8 }, { x = 2, y = 9 }, { x = 3, y = 9 }, { x = 5, y = 8 }, { x = 4, y = 8 } },
[11] = { { x = -5, y = -9 }, { x = -4, y = -9 }, { x = -3, y = -10 }, { x = -1, y = -10 }, { x = -2, y = -10 }, { x = 1, y = -10 }, { x = 0, y = -10 }, { x = 3, y = -10 }, { x = 2, y = -10 }, { x = 5, y = -9 }, { x = 4, y = -9 }, { x = -7, y = -7 }, { x = -6, y = -8 }, { x = 7, y = -7 }, { x = 6, y = -8 }, { x = -9, y = -5 }, { x = -8, y = -6 }, { x = 9, y = -5 }, { x = 8, y = -6 }, { x = -9, y = -4 }, { x = -10, y = -3 }, { x = 9, y = -4 }, { x = 10, y = -3 }, { x = -10, y = -2 }, { x = -10, y = -1 }, { x = 10, y = -1 }, { x = 10, y = -2 }, { x = -10, y = 0 }, { x = -10, y = 1 }, { x = 10, y = 1 }, { x = 10, y = 0 }, { x = -10, y = 2 }, { x = -10, y = 3 }, { x = 10, y = 3 }, { x = 10, y = 2 }, { x = -9, y = 4 }, { x = -9, y = 5 }, { x = 9, y = 5 }, { x = 9, y = 4 }, { x = -8, y = 6 }, { x = -7, y = 7 }, { x = 7, y = 7 }, { x = 8, y = 6 }, { x = -6, y = 8 }, { x = -5, y = 9 }, { x = -4, y = 9 }, { x = 4, y = 9 }, { x = 5, y = 9 }, { x = 6, y = 8 }, { x = -3, y = 10 }, { x = -2, y = 10 }, { x = -1, y = 10 }, { x = 0, y = 10 }, { x = 1, y = 10 }, { x = 2, y = 10 }, { x = 3, y = 10 } },
[12] = { { x = -3, y = -11 }, { x = -2, y = -11 }, { x = -1, y = -11 }, { x = 0, y = -11 }, { x = 1, y = -11 }, { x = 2, y = -11 }, { x = 3, y = -11 }, { x = -7, y = -9 }, { x = -6, y = -9 }, { x = -5, y = -10 }, { x = -4, y = -10 }, { x = 5, y = -10 }, { x = 4, y = -10 }, { x = 7, y = -9 }, { x = 6, y = -9 }, { x = -9, y = -7 }, { x = -7, y = -8 }, { x = -8, y = -8 }, { x = -8, y = -7 }, { x = 7, y = -8 }, { x = 8, y = -7 }, { x = 8, y = -8 }, { x = 9, y = -7 }, { x = -9, y = -6 }, { x = -10, y = -5 }, { x = 9, y = -6 }, { x = 10, y = -5 }, { x = -11, y = -3 }, { x = -10, y = -4 }, { x = 10, y = -4 }, { x = 11, y = -3 }, { x = -11, y = -2 }, { x = -11, y = -1 }, { x = 11, y = -1 }, { x = 11, y = -2 }, { x = -11, y = 0 }, { x = -11, y = 1 }, { x = 11, y = 1 }, { x = 11, y = 0 }, { x = -11, y = 2 }, { x = -11, y = 3 }, { x = 11, y = 3 }, { x = 11, y = 2 }, { x = -10, y = 5 }, { x = -10, y = 4 }, { x = 10, y = 5 }, { x = 10, y = 4 }, { x = -9, y = 7 }, { x = -9, y = 6 }, { x = -8, y = 7 }, { x = 8, y = 7 }, { x = 9, y = 7 }, { x = 9, y = 6 }, { x = -8, y = 8 }, { x = -7, y = 8 }, { x = -7, y = 9 }, { x = -6, y = 9 }, { x = 7, y = 8 }, { x = 7, y = 9 }, { x = 6, y = 9 }, { x = 8, y = 8 }, { x = -5, y = 10 }, { x = -4, y = 10 }, { x = -3, y = 11 }, { x = -2, y = 11 }, { x = -1, y = 11 }, { x = 0, y = 11 }, { x = 1, y = 11 }, { x = 2, y = 11 }, { x = 3, y = 11 }, { x = 4, y = 10 }, { x = 5, y = 10 } },
[13] = { { x = -5, y = -11 }, { x = -4, y = -11 }, { x = -3, y = -12 }, { x = -1, y = -12 }, { x = -2, y = -12 }, { x = 1, y = -12 }, { x = 0, y = -12 }, { x = 3, y = -12 }, { x = 2, y = -12 }, { x = 4, y = -11 }, { x = 5, y = -11 }, { x = -8, y = -9 }, { x = -7, y = -10 }, { x = -6, y = -10 }, { x = 6, y = -10 }, { x = 7, y = -10 }, { x = 8, y = -9 }, { x = -10, y = -7 }, { x = -9, y = -8 }, { x = 9, y = -8 }, { x = 10, y = -7 }, { x = -11, y = -5 }, { x = -10, y = -6 }, { x = 10, y = -6 }, { x = 11, y = -5 }, { x = -11, y = -4 }, { x = -12, y = -3 }, { x = 11, y = -4 }, { x = 12, y = -3 }, { x = -12, y = -1 }, { x = -12, y = -2 }, { x = 12, y = -1 }, { x = 12, y = -2 }, { x = -12, y = 1 }, { x = -12, y = 0 }, { x = 12, y = 1 }, { x = 12, y = 0 }, { x = -12, y = 3 }, { x = -12, y = 2 }, { x = 12, y = 3 }, { x = 12, y = 2 }, { x = -11, y = 5 }, { x = -11, y = 4 }, { x = 11, y = 4 }, { x = 11, y = 5 }, { x = -10, y = 7 }, { x = -10, y = 6 }, { x = 10, y = 6 }, { x = 10, y = 7 }, { x = -9, y = 8 }, { x = -8, y = 9 }, { x = 9, y = 8 }, { x = 8, y = 9 }, { x = -7, y = 10 }, { x = -5, y = 11 }, { x = -6, y = 10 }, { x = -4, y = 11 }, { x = 5, y = 11 }, { x = 4, y = 11 }, { x = 7, y = 10 }, { x = 6, y = 10 }, { x = -3, y = 12 }, { x = -2, y = 12 }, { x = -1, y = 12 }, { x = 0, y = 12 }, { x = 1, y = 12 }, { x = 2, y = 12 }, { x = 3, y = 12 } },
[14] = { { x = -3, y = -13 }, { x = -1, y = -13 }, { x = -2, y = -13 }, { x = 1, y = -13 }, { x = 0, y = -13 }, { x = 3, y = -13 }, { x = 2, y = -13 }, { x = -7, y = -11 }, { x = -6, y = -11 }, { x = -5, y = -12 }, { x = -6, y = -12 }, { x = -4, y = -12 }, { x = 5, y = -12 }, { x = 4, y = -12 }, { x = 7, y = -11 }, { x = 6, y = -11 }, { x = 6, y = -12 }, { x = -10, y = -9 }, { x = -9, y = -9 }, { x = -9, y = -10 }, { x = -8, y = -10 }, { x = 9, y = -9 }, { x = 9, y = -10 }, { x = 8, y = -10 }, { x = 10, y = -9 }, { x = -11, y = -7 }, { x = -10, y = -8 }, { x = 11, y = -7 }, { x = 10, y = -8 }, { x = -11, y = -6 }, { x = -12, y = -6 }, { x = -12, y = -5 }, { x = 11, y = -6 }, { x = 12, y = -6 }, { x = 12, y = -5 }, { x = -13, y = -3 }, { x = -12, y = -4 }, { x = 12, y = -4 }, { x = 13, y = -3 }, { x = -13, y = -2 }, { x = -13, y = -1 }, { x = 13, y = -1 }, { x = 13, y = -2 }, { x = -13, y = 0 }, { x = -13, y = 1 }, { x = 13, y = 1 }, { x = 13, y = 0 }, { x = -13, y = 2 }, { x = -13, y = 3 }, { x = 13, y = 3 }, { x = 13, y = 2 }, { x = -12, y = 5 }, { x = -12, y = 4 }, { x = 12, y = 5 }, { x = 12, y = 4 }, { x = -11, y = 6 }, { x = -11, y = 7 }, { x = -12, y = 6 }, { x = 11, y = 7 }, { x = 11, y = 6 }, { x = 12, y = 6 }, { x = -10, y = 8 }, { x = -10, y = 9 }, { x = -9, y = 9 }, { x = 9, y = 9 }, { x = 10, y = 9 }, { x = 10, y = 8 }, { x = -9, y = 10 }, { x = -8, y = 10 }, { x = -7, y = 11 }, { x = -6, y = 11 }, { x = 7, y = 11 }, { x = 6, y = 11 }, { x = 8, y = 10 }, { x = 9, y = 10 }, { x = -6, y = 12 }, { x = -5, y = 12 }, { x = -4, y = 12 }, { x = -3, y = 13 }, { x = -2, y = 13 }, { x = -1, y = 13 }, { x = 0, y = 13 }, { x = 1, y = 13 }, { x = 2, y = 13 }, { x = 3, y = 13 }, { x = 5, y = 12 }, { x = 4, y = 12 }, { x = 6, y = 12 } },
[15] = { { x = -5, y = -13 }, { x = -6, y = -13 }, { x = -4, y = -13 }, { x = -3, y = -14 }, { x = -1, y = -14 }, { x = -2, y = -14 }, { x = 1, y = -14 }, { x = 0, y = -14 }, { x = 3, y = -14 }, { x = 2, y = -14 }, { x = 5, y = -13 }, { x = 4, y = -13 }, { x = 6, y = -13 }, { x = -9, y = -11 }, { x = -8, y = -11 }, { x = -8, y = -12 }, { x = -7, y = -12 }, { x = 7, y = -12 }, { x = 8, y = -12 }, { x = 8, y = -11 }, { x = 9, y = -11 }, { x = -11, y = -9 }, { x = -10, y = -10 }, { x = 10, y = -10 }, { x = 11, y = -9 }, { x = -12, y = -7 }, { x = -11, y = -8 }, { x = -12, y = -8 }, { x = 11, y = -8 }, { x = 12, y = -8 }, { x = 12, y = -7 }, { x = -13, y = -5 }, { x = -13, y = -6 }, { x = 13, y = -5 }, { x = 13, y = -6 }, { x = -13, y = -4 }, { x = -14, y = -3 }, { x = 13, y = -4 }, { x = 14, y = -3 }, { x = -14, y = -2 }, { x = -14, y = -1 }, { x = 14, y = -1 }, { x = 14, y = -2 }, { x = -14, y = 0 }, { x = -14, y = 1 }, { x = 14, y = 1 }, { x = 14, y = 0 }, { x = -14, y = 2 }, { x = -14, y = 3 }, { x = 14, y = 3 }, { x = 14, y = 2 }, { x = -13, y = 4 }, { x = -13, y = 5 }, { x = 13, y = 5 }, { x = 13, y = 4 }, { x = -13, y = 6 }, { x = -12, y = 7 }, { x = 12, y = 7 }, { x = 13, y = 6 }, { x = -11, y = 9 }, { x = -11, y = 8 }, { x = -12, y = 8 }, { x = 11, y = 8 }, { x = 11, y = 9 }, { x = 12, y = 8 }, { x = -9, y = 11 }, { x = -10, y = 10 }, { x = -8, y = 11 }, { x = 9, y = 11 }, { x = 8, y = 11 }, { x = 10, y = 10 }, { x = -7, y = 12 }, { x = -8, y = 12 }, { x = -6, y = 13 }, { x = -5, y = 13 }, { x = -4, y = 13 }, { x = 5, y = 13 }, { x = 4, y = 13 }, { x = 7, y = 12 }, { x = 6, y = 13 }, { x = 8, y = 12 }, { x = -3, y = 14 }, { x = -2, y = 14 }, { x = -1, y = 14 }, { x = 0, y = 14 }, { x = 1, y = 14 }, { x = 2, y = 14 }, { x = 3, y = 14 } },
[16] = { { x = -3, y = -15 }, { x = -1, y = -15 }, { x = -2, y = -15 }, { x = 1, y = -15 }, { x = 0, y = -15 }, { x = 3, y = -15 }, { x = 2, y = -15 }, { x = -7, y = -13 }, { x = -8, y = -13 }, { x = -5, y = -14 }, { x = -6, y = -14 }, { x = -4, y = -14 }, { x = 5, y = -14 }, { x = 4, y = -14 }, { x = 7, y = -13 }, { x = 6, y = -14 }, { x = 8, y = -13 }, { x = -9, y = -12 }, { x = -10, y = -11 }, { x = 9, y = -12 }, { x = 10, y = -11 }, { x = -11, y = -10 }, { x = -12, y = -9 }, { x = 11, y = -10 }, { x = 12, y = -9 }, { x = -13, y = -7 }, { x = -13, y = -8 }, { x = 13, y = -7 }, { x = 13, y = -8 }, { x = -14, y = -6 }, { x = -14, y = -5 }, { x = 14, y = -5 }, { x = 14, y = -6 }, { x = -15, y = -3 }, { x = -14, y = -4 }, { x = 15, y = -3 }, { x = 14, y = -4 }, { x = -15, y = -2 }, { x = -15, y = -1 }, { x = 15, y = -1 }, { x = 15, y = -2 }, { x = -15, y = 0 }, { x = -15, y = 1 }, { x = 15, y = 1 }, { x = 15, y = 0 }, { x = -15, y = 2 }, { x = -15, y = 3 }, { x = 15, y = 3 }, { x = 15, y = 2 }, { x = -14, y = 5 }, { x = -14, y = 4 }, { x = 14, y = 5 }, { x = 14, y = 4 }, { x = -13, y = 7 }, { x = -14, y = 6 }, { x = 13, y = 7 }, { x = 14, y = 6 }, { x = -13, y = 8 }, { x = -12, y = 9 }, { x = 12, y = 9 }, { x = 13, y = 8 }, { x = -11, y = 10 }, { x = -10, y = 11 }, { x = 10, y = 11 }, { x = 11, y = 10 }, { x = -9, y = 12 }, { x = -8, y = 13 }, { x = -7, y = 13 }, { x = 7, y = 13 }, { x = 8, y = 13 }, { x = 9, y = 12 }, { x = -6, y = 14 }, { x = -5, y = 14 }, { x = -4, y = 14 }, { x = -3, y = 15 }, { x = -2, y = 15 }, { x = -1, y = 15 }, { x = 0, y = 15 }, { x = 1, y = 15 }, { x = 2, y = 15 }, { x = 3, y = 15 }, { x = 4, y = 14 }, { x = 5, y = 14 }, { x = 6, y = 14 } },
[17] = { { x = -5, y = -15 }, { x = -6, y = -15 }, { x = -3, y = -16 }, { x = -4, y = -16 }, { x = -4, y = -15 }, { x = -1, y = -16 }, { x = -2, y = -16 }, { x = 1, y = -16 }, { x = 0, y = -16 }, { x = 3, y = -16 }, { x = 2, y = -16 }, { x = 5, y = -15 }, { x = 4, y = -15 }, { x = 4, y = -16 }, { x = 6, y = -15 }, { x = -9, y = -13 }, { x = -10, y = -13 }, { x = -8, y = -14 }, { x = -7, y = -14 }, { x = 7, y = -14 }, { x = 9, y = -13 }, { x = 8, y = -14 }, { x = 10, y = -13 }, { x = -11, y = -12 }, { x = -11, y = -11 }, { x = -12, y = -11 }, { x = -10, y = -12 }, { x = 11, y = -11 }, { x = 11, y = -12 }, { x = 10, y = -12 }, { x = 12, y = -11 }, { x = -13, y = -10 }, { x = -13, y = -9 }, { x = -12, y = -10 }, { x = 13, y = -9 }, { x = 13, y = -10 }, { x = 12, y = -10 }, { x = -14, y = -7 }, { x = -14, y = -8 }, { x = 14, y = -7 }, { x = 14, y = -8 }, { x = -15, y = -6 }, { x = -15, y = -5 }, { x = 15, y = -5 }, { x = 15, y = -6 }, { x = -15, y = -4 }, { x = -16, y = -4 }, { x = -16, y = -3 }, { x = 15, y = -4 }, { x = 16, y = -3 }, { x = 16, y = -4 }, { x = -16, y = -2 }, { x = -16, y = -1 }, { x = 16, y = -1 }, { x = 16, y = -2 }, { x = -16, y = 0 }, { x = -16, y = 1 }, { x = 16, y = 1 }, { x = 16, y = 0 }, { x = -16, y = 2 }, { x = -16, y = 3 }, { x = 16, y = 3 }, { x = 16, y = 2 }, { x = -16, y = 4 }, { x = -15, y = 4 }, { x = -15, y = 5 }, { x = 15, y = 5 }, { x = 15, y = 4 }, { x = 16, y = 4 }, { x = -15, y = 6 }, { x = -14, y = 7 }, { x = 14, y = 7 }, { x = 15, y = 6 }, { x = -13, y = 9 }, { x = -14, y = 8 }, { x = 13, y = 9 }, { x = 14, y = 8 }, { x = -13, y = 10 }, { x = -12, y = 10 }, { x = -12, y = 11 }, { x = -11, y = 11 }, { x = 11, y = 11 }, { x = 12, y = 11 }, { x = 12, y = 10 }, { x = 13, y = 10 }, { x = -11, y = 12 }, { x = -10, y = 12 }, { x = -10, y = 13 }, { x = -9, y = 13 }, { x = 9, y = 13 }, { x = 10, y = 13 }, { x = 10, y = 12 }, { x = 11, y = 12 }, { x = -8, y = 14 }, { x = -7, y = 14 }, { x = -6, y = 15 }, { x = -5, y = 15 }, { x = -4, y = 15 }, { x = 4, y = 15 }, { x = 5, y = 15 }, { x = 7, y = 14 }, { x = 6, y = 15 }, { x = 8, y = 14 }, { x = -4, y = 16 }, { x = -3, y = 16 }, { x = -2, y = 16 }, { x = -1, y = 16 }, { x = 0, y = 16 }, { x = 1, y = 16 }, { x = 2, y = 16 }, { x = 3, y = 16 }, { x = 4, y = 16 } },
[18] = { { x = -3, y = -17 }, { x = -4, y = -17 }, { x = -1, y = -17 }, { x = -2, y = -17 }, { x = 1, y = -17 }, { x = 0, y = -17 }, { x = 3, y = -17 }, { x = 2, y = -17 }, { x = 4, y = -17 }, { x = -9, y = -15 }, { x = -8, y = -15 }, { x = -7, y = -15 }, { x = -7, y = -16 }, { x = -6, y = -16 }, { x = -5, y = -16 }, { x = 5, y = -16 }, { x = 7, y = -15 }, { x = 7, y = -16 }, { x = 6, y = -16 }, { x = 9, y = -15 }, { x = 8, y = -15 }, { x = -11, y = -13 }, { x = -10, y = -14 }, { x = -9, y = -14 }, { x = 9, y = -14 }, { x = 11, y = -13 }, { x = 10, y = -14 }, { x = -13, y = -11 }, { x = -12, y = -12 }, { x = 13, y = -11 }, { x = 12, y = -12 }, { x = -15, y = -9 }, { x = -14, y = -10 }, { x = -14, y = -9 }, { x = 14, y = -10 }, { x = 14, y = -9 }, { x = 15, y = -9 }, { x = -15, y = -8 }, { x = -15, y = -7 }, { x = -16, y = -7 }, { x = 15, y = -8 }, { x = 15, y = -7 }, { x = 16, y = -7 }, { x = -16, y = -6 }, { x = -16, y = -5 }, { x = 16, y = -5 }, { x = 16, y = -6 }, { x = -17, y = -3 }, { x = -17, y = -4 }, { x = 17, y = -3 }, { x = 17, y = -4 }, { x = -17, y = -1 }, { x = -17, y = -2 }, { x = 17, y = -1 }, { x = 17, y = -2 }, { x = -17, y = 1 }, { x = -17, y = 0 }, { x = 17, y = 1 }, { x = 17, y = 0 }, { x = -17, y = 3 }, { x = -17, y = 2 }, { x = 17, y = 3 }, { x = 17, y = 2 }, { x = -17, y = 4 }, { x = -16, y = 5 }, { x = 16, y = 5 }, { x = 17, y = 4 }, { x = -15, y = 7 }, { x = -16, y = 7 }, { x = -16, y = 6 }, { x = 15, y = 7 }, { x = 16, y = 7 }, { x = 16, y = 6 }, { x = -15, y = 9 }, { x = -15, y = 8 }, { x = -14, y = 9 }, { x = 14, y = 9 }, { x = 15, y = 9 }, { x = 15, y = 8 }, { x = -14, y = 10 }, { x = -13, y = 11 }, { x = 13, y = 11 }, { x = 14, y = 10 }, { x = -12, y = 12 }, { x = -11, y = 13 }, { x = 11, y = 13 }, { x = 12, y = 12 }, { x = -10, y = 14 }, { x = -9, y = 14 }, { x = -9, y = 15 }, { x = -8, y = 15 }, { x = -7, y = 15 }, { x = 7, y = 15 }, { x = 9, y = 14 }, { x = 9, y = 15 }, { x = 8, y = 15 }, { x = 10, y = 14 }, { x = -7, y = 16 }, { x = -6, y = 16 }, { x = -5, y = 16 }, { x = -4, y = 17 }, { x = -3, y = 17 }, { x = -2, y = 17 }, { x = -1, y = 17 }, { x = 0, y = 17 }, { x = 1, y = 17 }, { x = 2, y = 17 }, { x = 3, y = 17 }, { x = 4, y = 17 }, { x = 5, y = 16 }, { x = 6, y = 16 }, { x = 7, y = 16 } },
[19] = { { x = -7, y = -17 }, { x = -6, y = -17 }, { x = -5, y = -17 }, { x = -3, y = -18 }, { x = -4, y = -18 }, { x = -1, y = -18 }, { x = -2, y = -18 }, { x = 1, y = -18 }, { x = 0, y = -18 }, { x = 3, y = -18 }, { x = 2, y = -18 }, { x = 5, y = -17 }, { x = 4, y = -18 }, { x = 7, y = -17 }, { x = 6, y = -17 }, { x = -10, y = -15 }, { x = -9, y = -16 }, { x = -8, y = -16 }, { x = 9, y = -16 }, { x = 8, y = -16 }, { x = 10, y = -15 }, { x = -13, y = -13 }, { x = -11, y = -14 }, { x = -12, y = -14 }, { x = -12, y = -13 }, { x = 11, y = -14 }, { x = 13, y = -13 }, { x = 12, y = -13 }, { x = 12, y = -14 }, { x = -13, y = -12 }, { x = -14, y = -12 }, { x = -14, y = -11 }, { x = 13, y = -12 }, { x = 14, y = -11 }, { x = 14, y = -12 }, { x = -15, y = -10 }, { x = -16, y = -9 }, { x = 15, y = -10 }, { x = 16, y = -9 }, { x = -17, y = -7 }, { x = -16, y = -8 }, { x = 16, y = -8 }, { x = 17, y = -7 }, { x = -17, y = -5 }, { x = -17, y = -6 }, { x = 17, y = -6 }, { x = 17, y = -5 }, { x = -18, y = -3 }, { x = -18, y = -4 }, { x = 18, y = -4 }, { x = 18, y = -3 }, { x = -18, y = -1 }, { x = -18, y = -2 }, { x = 18, y = -2 }, { x = 18, y = -1 }, { x = -18, y = 1 }, { x = -18, y = 0 }, { x = 18, y = 0 }, { x = 18, y = 1 }, { x = -18, y = 3 }, { x = -18, y = 2 }, { x = 18, y = 2 }, { x = 18, y = 3 }, { x = -17, y = 5 }, { x = -18, y = 4 }, { x = 17, y = 5 }, { x = 18, y = 4 }, { x = -17, y = 7 }, { x = -17, y = 6 }, { x = 17, y = 7 }, { x = 17, y = 6 }, { x = -16, y = 9 }, { x = -16, y = 8 }, { x = 16, y = 9 }, { x = 16, y = 8 }, { x = -15, y = 10 }, { x = -14, y = 11 }, { x = 14, y = 11 }, { x = 15, y = 10 }, { x = -14, y = 12 }, { x = -13, y = 12 }, { x = -13, y = 13 }, { x = -12, y = 13 }, { x = 12, y = 13 }, { x = 13, y = 13 }, { x = 13, y = 12 }, { x = 14, y = 12 }, { x = -12, y = 14 }, { x = -11, y = 14 }, { x = -10, y = 15 }, { x = 10, y = 15 }, { x = 11, y = 14 }, { x = 12, y = 14 }, { x = -9, y = 16 }, { x = -7, y = 17 }, { x = -8, y = 16 }, { x = -5, y = 17 }, { x = -6, y = 17 }, { x = 5, y = 17 }, { x = 7, y = 17 }, { x = 6, y = 17 }, { x = 8, y = 16 }, { x = 9, y = 16 }, { x = -3, y = 18 }, { x = -4, y = 18 }, { x = -1, y = 18 }, { x = -2, y = 18 }, { x = 1, y = 18 }, { x = 0, y = 18 }, { x = 3, y = 18 }, { x = 2, y = 18 }, { x = 4, y = 18 } },
[20] = { { x = -3, y = -19 }, { x = -4, y = -19 }, { x = -1, y = -19 }, { x = -2, y = -19 }, { x = 1, y = -19 }, { x = 0, y = -19 }, { x = 3, y = -19 }, { x = 2, y = -19 }, { x = 4, y = -19 }, { x = -9, y = -17 }, { x = -7, y = -18 }, { x = -8, y = -17 }, { x = -5, y = -18 }, { x = -6, y = -18 }, { x = 5, y = -18 }, { x = 7, y = -18 }, { x = 6, y = -18 }, { x = 9, y = -17 }, { x = 8, y = -17 }, { x = -11, y = -16 }, { x = -11, y = -15 }, { x = -12, y = -15 }, { x = -10, y = -16 }, { x = 11, y = -15 }, { x = 11, y = -16 }, { x = 10, y = -16 }, { x = 12, y = -15 }, { x = -13, y = -14 }, { x = -14, y = -13 }, { x = 13, y = -14 }, { x = 14, y = -13 }, { x = -15, y = -12 }, { x = -15, y = -11 }, { x = -16, y = -11 }, { x = 15, y = -11 }, { x = 15, y = -12 }, { x = 16, y = -11 }, { x = -17, y = -9 }, { x = -16, y = -10 }, { x = 16, y = -10 }, { x = 17, y = -9 }, { x = -17, y = -8 }, { x = -18, y = -7 }, { x = 17, y = -8 }, { x = 18, y = -7 }, { x = -18, y = -6 }, { x = -18, y = -5 }, { x = 18, y = -5 }, { x = 18, y = -6 }, { x = -19, y = -4 }, { x = -19, y = -3 }, { x = 19, y = -3 }, { x = 19, y = -4 }, { x = -19, y = -2 }, { x = -19, y = -1 }, { x = 19, y = -1 }, { x = 19, y = -2 }, { x = -19, y = 0 }, { x = -19, y = 1 }, { x = 19, y = 1 }, { x = 19, y = 0 }, { x = -19, y = 2 }, { x = -19, y = 3 }, { x = 19, y = 3 }, { x = 19, y = 2 }, { x = -19, y = 4 }, { x = -18, y = 5 }, { x = 18, y = 5 }, { x = 19, y = 4 }, { x = -18, y = 7 }, { x = -18, y = 6 }, { x = 18, y = 7 }, { x = 18, y = 6 }, { x = -17, y = 9 }, { x = -17, y = 8 }, { x = 17, y = 9 }, { x = 17, y = 8 }, { x = -16, y = 10 }, { x = -16, y = 11 }, { x = -15, y = 11 }, { x = 15, y = 11 }, { x = 16, y = 11 }, { x = 16, y = 10 }, { x = -15, y = 12 }, { x = -14, y = 13 }, { x = 14, y = 13 }, { x = 15, y = 12 }, { x = -13, y = 14 }, { x = -12, y = 15 }, { x = -11, y = 15 }, { x = 11, y = 15 }, { x = 12, y = 15 }, { x = 13, y = 14 }, { x = -11, y = 16 }, { x = -10, y = 16 }, { x = -9, y = 17 }, { x = -8, y = 17 }, { x = 9, y = 17 }, { x = 8, y = 17 }, { x = 10, y = 16 }, { x = 11, y = 16 }, { x = -7, y = 18 }, { x = -5, y = 18 }, { x = -6, y = 18 }, { x = -4, y = 19 }, { x = -3, y = 19 }, { x = -2, y = 19 }, { x = -1, y = 19 }, { x = 0, y = 19 }, { x = 1, y = 19 }, { x = 2, y = 19 }, { x = 3, y = 19 }, { x = 4, y = 19 }, { x = 5, y = 18 }, { x = 7, y = 18 }, { x = 6, y = 18 } },
[21] = { { x = -7, y = -19 }, { x = -5, y = -19 }, { x = -6, y = -19 }, { x = -3, y = -20 }, { x = -4, y = -20 }, { x = -1, y = -20 }, { x = -2, y = -20 }, { x = 1, y = -20 }, { x = 0, y = -20 }, { x = 3, y = -20 }, { x = 2, y = -20 }, { x = 5, y = -19 }, { x = 4, y = -20 }, { x = 7, y = -19 }, { x = 6, y = -19 }, { x = -11, y = -17 }, { x = -10, y = -17 }, { x = -9, y = -18 }, { x = -8, y = -18 }, { x = 9, y = -18 }, { x = 8, y = -18 }, { x = 10, y = -17 }, { x = 11, y = -17 }, { x = -13, y = -15 }, { x = -14, y = -15 }, { x = -12, y = -16 }, { x = 13, y = -15 }, { x = 12, y = -16 }, { x = 14, y = -15 }, { x = -15, y = -14 }, { x = -15, y = -13 }, { x = -14, y = -14 }, { x = 15, y = -13 }, { x = 15, y = -14 }, { x = 14, y = -14 }, { x = -17, y = -11 }, { x = -16, y = -12 }, { x = 16, y = -12 }, { x = 17, y = -11 }, { x = -17, y = -10 }, { x = -18, y = -9 }, { x = 17, y = -10 }, { x = 18, y = -9 }, { x = -19, y = -7 }, { x = -18, y = -8 }, { x = 18, y = -8 }, { x = 19, y = -7 }, { x = -19, y = -6 }, { x = -19, y = -5 }, { x = 19, y = -6 }, { x = 19, y = -5 }, { x = -20, y = -4 }, { x = -20, y = -3 }, { x = 20, y = -3 }, { x = 20, y = -4 }, { x = -20, y = -2 }, { x = -20, y = -1 }, { x = 20, y = -1 }, { x = 20, y = -2 }, { x = -20, y = 0 }, { x = -20, y = 1 }, { x = 20, y = 1 }, { x = 20, y = 0 }, { x = -20, y = 2 }, { x = -20, y = 3 }, { x = 20, y = 3 }, { x = 20, y = 2 }, { x = -20, y = 4 }, { x = -19, y = 5 }, { x = 19, y = 5 }, { x = 20, y = 4 }, { x = -19, y = 7 }, { x = -19, y = 6 }, { x = 19, y = 7 }, { x = 19, y = 6 }, { x = -18, y = 9 }, { x = -18, y = 8 }, { x = 18, y = 9 }, { x = 18, y = 8 }, { x = -17, y = 11 }, { x = -17, y = 10 }, { x = 17, y = 11 }, { x = 17, y = 10 }, { x = -16, y = 12 }, { x = -15, y = 13 }, { x = 15, y = 13 }, { x = 16, y = 12 }, { x = -15, y = 14 }, { x = -14, y = 14 }, { x = -14, y = 15 }, { x = -13, y = 15 }, { x = 13, y = 15 }, { x = 14, y = 15 }, { x = 14, y = 14 }, { x = 15, y = 14 }, { x = -12, y = 16 }, { x = -11, y = 17 }, { x = -10, y = 17 }, { x = 11, y = 17 }, { x = 10, y = 17 }, { x = 12, y = 16 }, { x = -9, y = 18 }, { x = -8, y = 18 }, { x = -7, y = 19 }, { x = -5, y = 19 }, { x = -6, y = 19 }, { x = 5, y = 19 }, { x = 6, y = 19 }, { x = 7, y = 19 }, { x = 9, y = 18 }, { x = 8, y = 18 }, { x = -4, y = 20 }, { x = -3, y = 20 }, { x = -2, y = 20 }, { x = -1, y = 20 }, { x = 0, y = 20 }, { x = 1, y = 20 }, { x = 2, y = 20 }, { x = 3, y = 20 }, { x = 4, y = 20 } },
[22] = { { x = -3, y = -21 }, { x = -4, y = -21 }, { x = -1, y = -21 }, { x = -2, y = -21 }, { x = 1, y = -21 }, { x = 0, y = -21 }, { x = 3, y = -21 }, { x = 2, y = -21 }, { x = 4, y = -21 }, { x = -10, y = -19 }, { x = -9, y = -19 }, { x = -8, y = -19 }, { x = -7, y = -20 }, { x = -5, y = -20 }, { x = -6, y = -20 }, { x = 5, y = -20 }, { x = 7, y = -20 }, { x = 6, y = -20 }, { x = 9, y = -19 }, { x = 8, y = -19 }, { x = 10, y = -19 }, { x = -13, y = -17 }, { x = -12, y = -17 }, { x = -11, y = -18 }, { x = -10, y = -18 }, { x = 11, y = -18 }, { x = 10, y = -18 }, { x = 13, y = -17 }, { x = 12, y = -17 }, { x = -15, y = -15 }, { x = -13, y = -16 }, { x = -14, y = -16 }, { x = 13, y = -16 }, { x = 15, y = -15 }, { x = 14, y = -16 }, { x = -17, y = -13 }, { x = -16, y = -14 }, { x = -16, y = -13 }, { x = 17, y = -13 }, { x = 16, y = -13 }, { x = 16, y = -14 }, { x = -17, y = -12 }, { x = -18, y = -11 }, { x = 17, y = -12 }, { x = 18, y = -11 }, { x = -19, y = -10 }, { x = -19, y = -9 }, { x = -18, y = -10 }, { x = 18, y = -10 }, { x = 19, y = -10 }, { x = 19, y = -9 }, { x = -19, y = -8 }, { x = -20, y = -7 }, { x = 19, y = -8 }, { x = 20, y = -7 }, { x = -20, y = -6 }, { x = -20, y = -5 }, { x = 20, y = -6 }, { x = 20, y = -5 }, { x = -21, y = -4 }, { x = -21, y = -3 }, { x = 21, y = -3 }, { x = 21, y = -4 }, { x = -21, y = -2 }, { x = -21, y = -1 }, { x = 21, y = -1 }, { x = 21, y = -2 }, { x = -21, y = 0 }, { x = -21, y = 1 }, { x = 21, y = 1 }, { x = 21, y = 0 }, { x = -21, y = 2 }, { x = -21, y = 3 }, { x = 21, y = 3 }, { x = 21, y = 2 }, { x = -21, y = 4 }, { x = -20, y = 5 }, { x = 20, y = 5 }, { x = 21, y = 4 }, { x = -20, y = 7 }, { x = -20, y = 6 }, { x = 20, y = 7 }, { x = 20, y = 6 }, { x = -19, y = 9 }, { x = -19, y = 8 }, { x = 19, y = 9 }, { x = 19, y = 8 }, { x = -19, y = 10 }, { x = -18, y = 11 }, { x = -18, y = 10 }, { x = 18, y = 11 }, { x = 18, y = 10 }, { x = 19, y = 10 }, { x = -17, y = 13 }, { x = -17, y = 12 }, { x = -16, y = 13 }, { x = 16, y = 13 }, { x = 17, y = 13 }, { x = 17, y = 12 }, { x = -16, y = 14 }, { x = -15, y = 15 }, { x = 15, y = 15 }, { x = 16, y = 14 }, { x = -14, y = 16 }, { x = -13, y = 16 }, { x = -13, y = 17 }, { x = -12, y = 17 }, { x = 13, y = 16 }, { x = 13, y = 17 }, { x = 12, y = 17 }, { x = 14, y = 16 }, { x = -11, y = 18 }, { x = -10, y = 18 }, { x = -10, y = 19 }, { x = -9, y = 19 }, { x = -8, y = 19 }, { x = 9, y = 19 }, { x = 8, y = 19 }, { x = 11, y = 18 }, { x = 10, y = 18 }, { x = 10, y = 19 }, { x = -7, y = 20 }, { x = -6, y = 20 }, { x = -5, y = 20 }, { x = -3, y = 21 }, { x = -4, y = 21 }, { x = -1, y = 21 }, { x = -2, y = 21 }, { x = 1, y = 21 }, { x = 0, y = 21 }, { x = 3, y = 21 }, { x = 2, y = 21 }, { x = 4, y = 21 }, { x = 5, y = 20 }, { x = 7, y = 20 }, { x = 6, y = 20 } },
[23] = { { x = -8, y = -21 }, { x = -7, y = -21 }, { x = -6, y = -21 }, { x = -5, y = -21 }, { x = -3, y = -22 }, { x = -4, y = -22 }, { x = -1, y = -22 }, { x = -2, y = -22 }, { x = 1, y = -22 }, { x = 0, y = -22 }, { x = 3, y = -22 }, { x = 2, y = -22 }, { x = 5, y = -21 }, { x = 4, y = -22 }, { x = 7, y = -21 }, { x = 6, y = -21 }, { x = 8, y = -21 }, { x = -12, y = -19 }, { x = -11, y = -19 }, { x = -10, y = -20 }, { x = -9, y = -20 }, { x = -8, y = -20 }, { x = 9, y = -20 }, { x = 8, y = -20 }, { x = 11, y = -19 }, { x = 10, y = -20 }, { x = 12, y = -19 }, { x = -14, y = -17 }, { x = -13, y = -18 }, { x = -12, y = -18 }, { x = 13, y = -18 }, { x = 12, y = -18 }, { x = 14, y = -17 }, { x = -15, y = -16 }, { x = -16, y = -15 }, { x = 15, y = -16 }, { x = 16, y = -15 }, { x = -17, y = -14 }, { x = -18, y = -13 }, { x = 17, y = -14 }, { x = 18, y = -13 }, { x = -19, y = -12 }, { x = -19, y = -11 }, { x = -18, y = -12 }, { x = 18, y = -12 }, { x = 19, y = -12 }, { x = 19, y = -11 }, { x = -20, y = -10 }, { x = -20, y = -9 }, { x = 20, y = -10 }, { x = 20, y = -9 }, { x = -21, y = -8 }, { x = -21, y = -7 }, { x = -20, y = -8 }, { x = 20, y = -8 }, { x = 21, y = -8 }, { x = 21, y = -7 }, { x = -21, y = -6 }, { x = -21, y = -5 }, { x = 21, y = -6 }, { x = 21, y = -5 }, { x = -22, y = -4 }, { x = -22, y = -3 }, { x = 22, y = -3 }, { x = 22, y = -4 }, { x = -22, y = -2 }, { x = -22, y = -1 }, { x = 22, y = -1 }, { x = 22, y = -2 }, { x = -22, y = 0 }, { x = -22, y = 1 }, { x = 22, y = 1 }, { x = 22, y = 0 }, { x = -22, y = 2 }, { x = -22, y = 3 }, { x = 22, y = 3 }, { x = 22, y = 2 }, { x = -22, y = 4 }, { x = -21, y = 5 }, { x = 21, y = 5 }, { x = 22, y = 4 }, { x = -21, y = 7 }, { x = -21, y = 6 }, { x = 21, y = 7 }, { x = 21, y = 6 }, { x = -21, y = 8 }, { x = -20, y = 9 }, { x = -20, y = 8 }, { x = 20, y = 8 }, { x = 20, y = 9 }, { x = 21, y = 8 }, { x = -19, y = 11 }, { x = -20, y = 10 }, { x = 19, y = 11 }, { x = 20, y = 10 }, { x = -19, y = 12 }, { x = -18, y = 13 }, { x = -18, y = 12 }, { x = 18, y = 13 }, { x = 18, y = 12 }, { x = 19, y = 12 }, { x = -17, y = 14 }, { x = -16, y = 15 }, { x = 16, y = 15 }, { x = 17, y = 14 }, { x = -15, y = 16 }, { x = -14, y = 17 }, { x = 14, y = 17 }, { x = 15, y = 16 }, { x = -13, y = 18 }, { x = -12, y = 18 }, { x = -12, y = 19 }, { x = -11, y = 19 }, { x = 11, y = 19 }, { x = 13, y = 18 }, { x = 12, y = 18 }, { x = 12, y = 19 }, { x = -10, y = 20 }, { x = -9, y = 20 }, { x = -8, y = 20 }, { x = -8, y = 21 }, { x = -7, y = 21 }, { x = -6, y = 21 }, { x = -5, y = 21 }, { x = 5, y = 21 }, { x = 7, y = 21 }, { x = 6, y = 21 }, { x = 8, y = 20 }, { x = 9, y = 20 }, { x = 8, y = 21 }, { x = 10, y = 20 }, { x = -4, y = 22 }, { x = -3, y = 22 }, { x = -2, y = 22 }, { x = -1, y = 22 }, { x = 0, y = 22 }, { x = 1, y = 22 }, { x = 2, y = 22 }, { x = 3, y = 22 }, { x = 4, y = 22 } }
}
local function process_explosion_tile(pos, explosion_index, current_radius)
local ffatable = Table.get_table()
local surface = game.surfaces[ffatable.explosion_schedule[explosion_index].surface]
local target_entities = surface.find_entities_filtered({ area = { { pos.x - 0.5, pos.y - 0.5 }, { pos.x + 0.499, pos.y + 0.499 } } })
local explosion_animation = "explosion"
local tile = surface.get_tile(pos)
if tile.name == "out-of-map" then
if ffatable.explosion_schedule[explosion_index].damage_remaining >= out_of_map_tile_health then
explosion_animation = "big-explosion"
surface.set_tiles({ { name = "dirt-5", position = pos } }, true)
end
ffatable.explosion_schedule[explosion_index].damage_remaining = ffatable.explosion_schedule[explosion_index].damage_remaining - out_of_map_tile_health
else
local decay_explosion = true
for _, entity in pairs(target_entities) do
if entity.health then
decay_explosion = false
end
end
if decay_explosion then ffatable.explosion_schedule[explosion_index].damage_remaining = ffatable.explosion_schedule[explosion_index].damage_remaining - empty_tile_damage_decay end
end
for _, entity in pairs(target_entities) do
if entity.valid then
if entity.health then
if entity.health < ffatable.explosion_schedule[explosion_index].damage_remaining then
explosion_animation = "big-explosion"
if entity.health > 500 then explosion_animation = "big-artillery-explosion" end
ffatable.explosion_schedule[explosion_index].damage_remaining = ffatable.explosion_schedule[explosion_index].damage_remaining - entity.health
if entity.name ~= "character" then
entity.damage(2097152, "player", "explosion")
else
entity.die("player")
end
else
entity.damage(ffatable.explosion_schedule[explosion_index].damage_remaining, "player", "explosion")
if entity.valid then
ffatable.explosion_schedule[explosion_index].damage_remaining = ffatable.explosion_schedule[explosion_index].damage_remaining - entity.health
end
end
end
end
end
if ffatable.explosion_schedule[explosion_index].damage_remaining > 5000 and current_radius < 2 then
if math_random(1, 2) == 1 then
explosion_animation = "big-explosion"
else
explosion_animation = "big-artillery-explosion"
end
end
surface.create_entity({ name = explosion_animation, position = pos })
Pollution.explosion(pos, surface, explosion_animation)
if ffatable.explosion_schedule[explosion_index].damage_remaining <= 0 then return false end
return true
end
local function volatility(inventory)
local result = 0
for item, v in pairs(explosive_items) do
local c = inventory.get_item_count(item)
result = result + (c * v)
end
return math_min(max_volatility, result)
end
local function create_explosion_schedule(entity)
local ffatable = Table.get_table()
local inventory = defines.inventory.chest
if entity.type == "car" then inventory = defines.inventory.car_trunk end
local i = entity.get_inventory(inventory)
local explosives_amount = volatility(i)
if explosives_amount < 1 then return end
local center_position = entity.position
if not ffatable.explosion_schedule then ffatable.explosion_schedule = {} end
ffatable.explosion_schedule[#ffatable.explosion_schedule + 1] = {}
ffatable.explosion_schedule[#ffatable.explosion_schedule].surface = entity.surface.name
ffatable.explosion_schedule[#ffatable.explosion_schedule].damage_remaining = damage_per_explosive * explosives_amount
for current_radius = 1, 23, 1 do
ffatable.explosion_schedule[#ffatable.explosion_schedule][current_radius] = {}
ffatable.explosion_schedule[#ffatable.explosion_schedule][current_radius].trigger_tick = game.tick + (current_radius * 8)
local circle_coords = circle_coordinates[current_radius]
for index, tile_position in pairs(circle_coords) do
local pos = { x = center_position.x + tile_position.x, y = center_position.y + tile_position.y }
ffatable.explosion_schedule[#ffatable.explosion_schedule][current_radius][index] = { x = pos.x, y = pos.y }
end
end
entity.die("player")
end
local function on_entity_damaged(event)
local entity = event.entity
if not entity.valid then return end
if not entity.health then return end
if entity.health > entity.prototype.max_health * 0.75 then return end
if entity.type == "container" or entity.type == "logistic-container" then
if math_random(1, 3) == 1 or entity.health <= 0 then
create_explosion_schedule(event.entity)
return
end
end
if entity.type == "cargo-wagon" or entity.type == "car" then
if entity.health <= 0 then
create_explosion_schedule(entity)
return
end
if entity.health < 150 and math_random(1, 3) == 1 then
create_explosion_schedule(entity)
return
end
end
end
local function on_tick(event)
local ffatable = Table.get_table()
local tick = event.tick
if ffatable.explosion_schedule then
local explosion_schedule_is_alive = false
for explosion_index = 1, #ffatable.explosion_schedule, 1 do
if #ffatable.explosion_schedule[explosion_index] > 0 then
explosion_schedule_is_alive = true
for radius = 1, #ffatable.explosion_schedule[explosion_index], 1 do
if ffatable.explosion_schedule[explosion_index][radius].trigger_tick == tick then
for tile_index = 1, #ffatable.explosion_schedule[explosion_index][radius], 1 do
local continue_explosion = process_explosion_tile(ffatable.explosion_schedule[explosion_index][radius][tile_index], explosion_index, radius)
if not continue_explosion then
ffatable.explosion_schedule[explosion_index] = {}
break
end
end
if radius == #ffatable.explosion_schedule[explosion_index] then ffatable.explosion_schedule[explosion_index] = {} end
break
end
end
end
end
if not explosion_schedule_is_alive then ffatable.explosion_schedule = nil end
end
end
local on_init = function ()
local ffatable = Table.get_table()
ffatable.explosion_schedule = {}
end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
Event.add(defines.events.on_tick, on_tick)

View File

@ -0,0 +1,67 @@
local Public = {}
local math_random = math.random
local math_floor = math.floor
local Table = require 'modules.scrap_towny_ffa.table'
function Public.reproduce()
local ffatable = Table.get_table()
for _, town_center in pairs(ffatable.town_centers) do
local surface = town_center.market.surface
local position = town_center.market.position
local fishes = surface.find_entities_filtered({ name = "fish", position = position, radius = 27 })
if #fishes == 0 then return end
if #fishes >= 100 then return end
-- pick a random fish
local t = math_random(1, #fishes)
local fish = fishes[t]
-- test against all other fishes
local guppy = false
for i, f in pairs(fishes) do
if i ~= t then
if math_floor(fish.position.x) == math_floor(f.position.x) and math_floor(fish.position.y) == math_floor(f.position.y) then
guppy = true
end
end
end
if guppy == true then
--log("fish spawn {" .. fish.position.x .. "," .. fish.position.y .. "}")
surface.create_entity({ name = "water-splash", position = fish.position })
surface.create_entity({ name = "fish", position = fish.position })
end
end
end
local function on_player_used_capsule(event)
if event.item.name ~= "raw-fish" then return end
local player = game.players[event.player_index]
local surface = player.surface
local position = event.position
local tile = player.surface.get_tile(position.x, position.y)
-- return back some of the health if not healthy
if player.character.health < 250 then
player.surface.play_sound({ path = "utility/armor_insert", position = player.position, volume_modifier = 1 })
return
end
-- if using fish on water
if tile.name == "water" and tile.name == "water-green" and tile.name == "deepwater" and tile.name == "deepwater-green" then
-- get the count of fish in the water nearby and test if can be repopulated
local fishes = surface.find_entities_filtered({ name = "fish", position = position, radius = 27 })
if #fishes < 12 then
surface.create_entity({ name = "water-splash", position = position })
surface.create_entity({ name = "fish", position = position })
surface.play_sound({ path = "utility/achievement_unlocked", position = player.position, volume_modifier = 1 })
return
end
end
-- otherwise return the fish and make no sound
player.insert({ name = "raw-fish", count = 1 })
end
local Event = require 'utils.event'
Event.add(defines.events.on_player_used_capsule, on_player_used_capsule)
return Public

View File

@ -0,0 +1,194 @@
--This will add a new game mechanic so that containers with certain fluids explode when they get damaged or are destroyed.
--Made by MewMew
local math_random = math.random
local math_floor = math.floor
local Table = require 'modules.scrap_towny_ffa.table'
local Pollution = require "modules.scrap_towny_ffa.pollution"
local empty_tile_damage_decay = 50
local out_of_map_tile_health = 1500
local container_types = {
["storage-tank"] = true,
["pipe"] = true,
["pipe-to-ground"] = true
}
local fluid_damages = { -- Fluid Whitelist -- add fluid and a damage value to enable
["lubricant"] = 5,
["crude-oil"] = 5,
["gasoline"] = 8,
["heavy-oil"] = 6,
["light-oil"] = 7,
["petroleum-gas"] = 8,
}
local function shuffle(tbl)
local size = #tbl
for i = size, 1, -1 do
local rand = math_random(size)
tbl[i], tbl[rand] = tbl[rand], tbl[i]
end
return tbl
end
local function process_explosion_tile(pos, explosion_index, current_radius)
local ffatable = Table.get_table()
local surface = game.surfaces[ffatable.fluid_explosion_schedule[explosion_index].surface]
local target_entities = surface.find_entities_filtered({ area = { { pos.x - 0.5, pos.y - 0.5 }, { pos.x + 0.499, pos.y + 0.499 } } })
local explosion_animation = "explosion"
local tile = surface.get_tile(pos)
if tile.name == "out-of-map" then
if ffatable.fluid_explosion_schedule[explosion_index].damage_remaining >= out_of_map_tile_health then
explosion_animation = "big-explosion"
surface.set_tiles({ { name = "dirt-5", position = pos } }, true)
end
ffatable.fluid_explosion_schedule[explosion_index].damage_remaining = ffatable.fluid_explosion_schedule[explosion_index].damage_remaining - out_of_map_tile_health
else
local decay_explosion = true
for _, entity in pairs(target_entities) do
if entity.health then
decay_explosion = false
end
end
if decay_explosion then ffatable.fluid_explosion_schedule[explosion_index].damage_remaining = ffatable.fluid_explosion_schedule[explosion_index].damage_remaining - empty_tile_damage_decay end
end
for _, entity in pairs(target_entities) do
if entity.valid then
if entity.health then
if entity.health <= ffatable.fluid_explosion_schedule[explosion_index].damage_remaining then
explosion_animation = "big-explosion"
if entity.health > 500 then explosion_animation = "big-artillery-explosion" end
ffatable.fluid_explosion_schedule[explosion_index].damage_remaining = ffatable.fluid_explosion_schedule[explosion_index].damage_remaining - entity.health
if entity.name ~= "character" then
entity.damage(2097152, "player", "explosion")
else
entity.die("player")
end
else
entity.damage(ffatable.fluid_explosion_schedule[explosion_index].damage_remaining, "player", "explosion")
ffatable.fluid_explosion_schedule[explosion_index].damage_remaining = 0
end
end
end
end
if ffatable.fluid_explosion_schedule[explosion_index].damage_remaining > 5000 and current_radius < 2 then
if math_random(1, 2) == 1 then
explosion_animation = "big-explosion"
else
explosion_animation = "big-artillery-explosion"
end
end
surface.create_entity({ name = explosion_animation, position = pos })
Pollution.explosion(pos, surface, explosion_animation)
if ffatable.fluid_explosion_schedule[explosion_index].damage_remaining <= 0 then return false end
return true
end
local function create_explosion_schedule(entity)
local ffatable = Table.get_table()
local explosives_amount = math_floor(entity.fluidbox[1].amount)
if explosives_amount < 1 then return end
local center_position = entity.position
if not ffatable.fluid_explosion_schedule then ffatable.fluid_explosion_schedule = {} end
ffatable.fluid_explosion_schedule[#ffatable.fluid_explosion_schedule + 1] = {}
ffatable.fluid_explosion_schedule[#ffatable.fluid_explosion_schedule].surface = entity.surface.name
ffatable.fluid_explosion_schedule[#ffatable.fluid_explosion_schedule].damage_remaining = fluid_damages[entity.fluidbox[1].name] * explosives_amount
local circle_coordinates = {
[1] = { { x = 0, y = 0 } },
[2] = { { x = -1, y = -1 }, { x = 1, y = -1 }, { x = 0, y = -1 }, { x = -1, y = 0 }, { x = -1, y = 1 }, { x = 0, y = 1 }, { x = 1, y = 1 }, { x = 1, y = 0 } },
[3] = { { x = -2, y = -1 }, { x = -1, y = -2 }, { x = 1, y = -2 }, { x = 0, y = -2 }, { x = 2, y = -1 }, { x = -2, y = 1 }, { x = -2, y = 0 }, { x = 2, y = 1 }, { x = 2, y = 0 }, { x = -1, y = 2 }, { x = 1, y = 2 }, { x = 0, y = 2 } },
[4] = { { x = -1, y = -3 }, { x = 1, y = -3 }, { x = 0, y = -3 }, { x = -3, y = -1 }, { x = -2, y = -2 }, { x = 3, y = -1 }, { x = 2, y = -2 }, { x = -3, y = 0 }, { x = -3, y = 1 }, { x = 3, y = 1 }, { x = 3, y = 0 }, { x = -2, y = 2 }, { x = -1, y = 3 }, { x = 0, y = 3 }, { x = 1, y = 3 }, { x = 2, y = 2 } },
[5] = { { x = -3, y = -3 }, { x = -2, y = -3 }, { x = -1, y = -4 }, { x = -2, y = -4 }, { x = 1, y = -4 }, { x = 0, y = -4 }, { x = 2, y = -3 }, { x = 3, y = -3 }, { x = 2, y = -4 }, { x = -3, y = -2 }, { x = -4, y = -1 }, { x = -4, y = -2 }, { x = 3, y = -2 }, { x = 4, y = -1 }, { x = 4, y = -2 }, { x = -4, y = 1 }, { x = -4, y = 0 }, { x = 4, y = 1 }, { x = 4, y = 0 }, { x = -3, y = 3 }, { x = -3, y = 2 }, { x = -4, y = 2 }, { x = -2, y = 3 }, { x = 2, y = 3 }, { x = 3, y = 3 }, { x = 3, y = 2 }, { x = 4, y = 2 }, { x = -2, y = 4 }, { x = -1, y = 4 }, { x = 0, y = 4 }, { x = 1, y = 4 }, { x = 2, y = 4 } },
[6] = { { x = -1, y = -5 }, { x = -2, y = -5 }, { x = 1, y = -5 }, { x = 0, y = -5 }, { x = 2, y = -5 }, { x = -3, y = -4 }, { x = -4, y = -3 }, { x = 3, y = -4 }, { x = 4, y = -3 }, { x = -5, y = -1 }, { x = -5, y = -2 }, { x = 5, y = -1 }, { x = 5, y = -2 }, { x = -5, y = 1 }, { x = -5, y = 0 }, { x = 5, y = 1 }, { x = 5, y = 0 }, { x = -5, y = 2 }, { x = -4, y = 3 }, { x = 4, y = 3 }, { x = 5, y = 2 }, { x = -3, y = 4 }, { x = -2, y = 5 }, { x = -1, y = 5 }, { x = 0, y = 5 }, { x = 1, y = 5 }, { x = 3, y = 4 }, { x = 2, y = 5 } },
[7] = { { x = -4, y = -5 }, { x = -3, y = -5 }, { x = -2, y = -6 }, { x = -1, y = -6 }, { x = 0, y = -6 }, { x = 1, y = -6 }, { x = 3, y = -5 }, { x = 2, y = -6 }, { x = 4, y = -5 }, { x = -5, y = -4 }, { x = -5, y = -3 }, { x = -4, y = -4 }, { x = 4, y = -4 }, { x = 5, y = -4 }, { x = 5, y = -3 }, { x = -6, y = -1 }, { x = -6, y = -2 }, { x = 6, y = -1 }, { x = 6, y = -2 }, { x = -6, y = 1 }, { x = -6, y = 0 }, { x = 6, y = 1 }, { x = 6, y = 0 }, { x = -5, y = 3 }, { x = -6, y = 2 }, { x = 5, y = 3 }, { x = 6, y = 2 }, { x = -5, y = 4 }, { x = -4, y = 4 }, { x = -4, y = 5 }, { x = -3, y = 5 }, { x = 3, y = 5 }, { x = 4, y = 4 }, { x = 5, y = 4 }, { x = 4, y = 5 }, { x = -1, y = 6 }, { x = -2, y = 6 }, { x = 1, y = 6 }, { x = 0, y = 6 }, { x = 2, y = 6 } },
[8] = { { x = -1, y = -7 }, { x = -2, y = -7 }, { x = 1, y = -7 }, { x = 0, y = -7 }, { x = 2, y = -7 }, { x = -5, y = -5 }, { x = -4, y = -6 }, { x = -3, y = -6 }, { x = 3, y = -6 }, { x = 4, y = -6 }, { x = 5, y = -5 }, { x = -6, y = -3 }, { x = -6, y = -4 }, { x = 6, y = -4 }, { x = 6, y = -3 }, { x = -7, y = -1 }, { x = -7, y = -2 }, { x = 7, y = -1 }, { x = 7, y = -2 }, { x = -7, y = 1 }, { x = -7, y = 0 }, { x = 7, y = 1 }, { x = 7, y = 0 }, { x = -7, y = 2 }, { x = -6, y = 3 }, { x = 6, y = 3 }, { x = 7, y = 2 }, { x = -5, y = 5 }, { x = -6, y = 4 }, { x = 5, y = 5 }, { x = 6, y = 4 }, { x = -3, y = 6 }, { x = -4, y = 6 }, { x = -2, y = 7 }, { x = -1, y = 7 }, { x = 0, y = 7 }, { x = 1, y = 7 }, { x = 3, y = 6 }, { x = 2, y = 7 }, { x = 4, y = 6 } },
[9] = { { x = -4, y = -7 }, { x = -3, y = -7 }, { x = -2, y = -8 }, { x = -1, y = -8 }, { x = 0, y = -8 }, { x = 1, y = -8 }, { x = 3, y = -7 }, { x = 2, y = -8 }, { x = 4, y = -7 }, { x = -5, y = -6 }, { x = -6, y = -6 }, { x = -6, y = -5 }, { x = 5, y = -6 }, { x = 6, y = -5 }, { x = 6, y = -6 }, { x = -7, y = -4 }, { x = -7, y = -3 }, { x = 7, y = -4 }, { x = 7, y = -3 }, { x = -8, y = -2 }, { x = -8, y = -1 }, { x = 8, y = -1 }, { x = 8, y = -2 }, { x = -8, y = 0 }, { x = -8, y = 1 }, { x = 8, y = 1 }, { x = 8, y = 0 }, { x = -7, y = 3 }, { x = -8, y = 2 }, { x = 7, y = 3 }, { x = 8, y = 2 }, { x = -7, y = 4 }, { x = -6, y = 5 }, { x = 6, y = 5 }, { x = 7, y = 4 }, { x = -5, y = 6 }, { x = -6, y = 6 }, { x = -4, y = 7 }, { x = -3, y = 7 }, { x = 3, y = 7 }, { x = 5, y = 6 }, { x = 4, y = 7 }, { x = 6, y = 6 }, { x = -2, y = 8 }, { x = -1, y = 8 }, { x = 0, y = 8 }, { x = 1, y = 8 }, { x = 2, y = 8 } },
[10] = { { x = -3, y = -9 }, { x = -1, y = -9 }, { x = -2, y = -9 }, { x = 1, y = -9 }, { x = 0, y = -9 }, { x = 3, y = -9 }, { x = 2, y = -9 }, { x = -5, y = -7 }, { x = -6, y = -7 }, { x = -5, y = -8 }, { x = -4, y = -8 }, { x = -3, y = -8 }, { x = 3, y = -8 }, { x = 5, y = -7 }, { x = 5, y = -8 }, { x = 4, y = -8 }, { x = 6, y = -7 }, { x = -7, y = -5 }, { x = -7, y = -6 }, { x = -8, y = -5 }, { x = 7, y = -5 }, { x = 7, y = -6 }, { x = 8, y = -5 }, { x = -9, y = -3 }, { x = -8, y = -4 }, { x = -8, y = -3 }, { x = 8, y = -4 }, { x = 8, y = -3 }, { x = 9, y = -3 }, { x = -9, y = -1 }, { x = -9, y = -2 }, { x = 9, y = -1 }, { x = 9, y = -2 }, { x = -9, y = 1 }, { x = -9, y = 0 }, { x = 9, y = 1 }, { x = 9, y = 0 }, { x = -9, y = 3 }, { x = -9, y = 2 }, { x = -8, y = 3 }, { x = 8, y = 3 }, { x = 9, y = 3 }, { x = 9, y = 2 }, { x = -7, y = 5 }, { x = -8, y = 5 }, { x = -8, y = 4 }, { x = 7, y = 5 }, { x = 8, y = 5 }, { x = 8, y = 4 }, { x = -7, y = 6 }, { x = -6, y = 7 }, { x = -5, y = 7 }, { x = 5, y = 7 }, { x = 7, y = 6 }, { x = 6, y = 7 }, { x = -5, y = 8 }, { x = -4, y = 8 }, { x = -3, y = 8 }, { x = -3, y = 9 }, { x = -2, y = 9 }, { x = -1, y = 9 }, { x = 0, y = 9 }, { x = 1, y = 9 }, { x = 3, y = 8 }, { x = 2, y = 9 }, { x = 3, y = 9 }, { x = 5, y = 8 }, { x = 4, y = 8 } },
[11] = { { x = -5, y = -9 }, { x = -4, y = -9 }, { x = -3, y = -10 }, { x = -1, y = -10 }, { x = -2, y = -10 }, { x = 1, y = -10 }, { x = 0, y = -10 }, { x = 3, y = -10 }, { x = 2, y = -10 }, { x = 5, y = -9 }, { x = 4, y = -9 }, { x = -7, y = -7 }, { x = -6, y = -8 }, { x = 7, y = -7 }, { x = 6, y = -8 }, { x = -9, y = -5 }, { x = -8, y = -6 }, { x = 9, y = -5 }, { x = 8, y = -6 }, { x = -9, y = -4 }, { x = -10, y = -3 }, { x = 9, y = -4 }, { x = 10, y = -3 }, { x = -10, y = -2 }, { x = -10, y = -1 }, { x = 10, y = -1 }, { x = 10, y = -2 }, { x = -10, y = 0 }, { x = -10, y = 1 }, { x = 10, y = 1 }, { x = 10, y = 0 }, { x = -10, y = 2 }, { x = -10, y = 3 }, { x = 10, y = 3 }, { x = 10, y = 2 }, { x = -9, y = 4 }, { x = -9, y = 5 }, { x = 9, y = 5 }, { x = 9, y = 4 }, { x = -8, y = 6 }, { x = -7, y = 7 }, { x = 7, y = 7 }, { x = 8, y = 6 }, { x = -6, y = 8 }, { x = -5, y = 9 }, { x = -4, y = 9 }, { x = 4, y = 9 }, { x = 5, y = 9 }, { x = 6, y = 8 }, { x = -3, y = 10 }, { x = -2, y = 10 }, { x = -1, y = 10 }, { x = 0, y = 10 }, { x = 1, y = 10 }, { x = 2, y = 10 }, { x = 3, y = 10 } },
[12] = { { x = -3, y = -11 }, { x = -2, y = -11 }, { x = -1, y = -11 }, { x = 0, y = -11 }, { x = 1, y = -11 }, { x = 2, y = -11 }, { x = 3, y = -11 }, { x = -7, y = -9 }, { x = -6, y = -9 }, { x = -5, y = -10 }, { x = -4, y = -10 }, { x = 5, y = -10 }, { x = 4, y = -10 }, { x = 7, y = -9 }, { x = 6, y = -9 }, { x = -9, y = -7 }, { x = -7, y = -8 }, { x = -8, y = -8 }, { x = -8, y = -7 }, { x = 7, y = -8 }, { x = 8, y = -7 }, { x = 8, y = -8 }, { x = 9, y = -7 }, { x = -9, y = -6 }, { x = -10, y = -5 }, { x = 9, y = -6 }, { x = 10, y = -5 }, { x = -11, y = -3 }, { x = -10, y = -4 }, { x = 10, y = -4 }, { x = 11, y = -3 }, { x = -11, y = -2 }, { x = -11, y = -1 }, { x = 11, y = -1 }, { x = 11, y = -2 }, { x = -11, y = 0 }, { x = -11, y = 1 }, { x = 11, y = 1 }, { x = 11, y = 0 }, { x = -11, y = 2 }, { x = -11, y = 3 }, { x = 11, y = 3 }, { x = 11, y = 2 }, { x = -10, y = 5 }, { x = -10, y = 4 }, { x = 10, y = 5 }, { x = 10, y = 4 }, { x = -9, y = 7 }, { x = -9, y = 6 }, { x = -8, y = 7 }, { x = 8, y = 7 }, { x = 9, y = 7 }, { x = 9, y = 6 }, { x = -8, y = 8 }, { x = -7, y = 8 }, { x = -7, y = 9 }, { x = -6, y = 9 }, { x = 7, y = 8 }, { x = 7, y = 9 }, { x = 6, y = 9 }, { x = 8, y = 8 }, { x = -5, y = 10 }, { x = -4, y = 10 }, { x = -3, y = 11 }, { x = -2, y = 11 }, { x = -1, y = 11 }, { x = 0, y = 11 }, { x = 1, y = 11 }, { x = 2, y = 11 }, { x = 3, y = 11 }, { x = 4, y = 10 }, { x = 5, y = 10 } },
[13] = { { x = -5, y = -11 }, { x = -4, y = -11 }, { x = -3, y = -12 }, { x = -1, y = -12 }, { x = -2, y = -12 }, { x = 1, y = -12 }, { x = 0, y = -12 }, { x = 3, y = -12 }, { x = 2, y = -12 }, { x = 4, y = -11 }, { x = 5, y = -11 }, { x = -8, y = -9 }, { x = -7, y = -10 }, { x = -6, y = -10 }, { x = 6, y = -10 }, { x = 7, y = -10 }, { x = 8, y = -9 }, { x = -10, y = -7 }, { x = -9, y = -8 }, { x = 9, y = -8 }, { x = 10, y = -7 }, { x = -11, y = -5 }, { x = -10, y = -6 }, { x = 10, y = -6 }, { x = 11, y = -5 }, { x = -11, y = -4 }, { x = -12, y = -3 }, { x = 11, y = -4 }, { x = 12, y = -3 }, { x = -12, y = -1 }, { x = -12, y = -2 }, { x = 12, y = -1 }, { x = 12, y = -2 }, { x = -12, y = 1 }, { x = -12, y = 0 }, { x = 12, y = 1 }, { x = 12, y = 0 }, { x = -12, y = 3 }, { x = -12, y = 2 }, { x = 12, y = 3 }, { x = 12, y = 2 }, { x = -11, y = 5 }, { x = -11, y = 4 }, { x = 11, y = 4 }, { x = 11, y = 5 }, { x = -10, y = 7 }, { x = -10, y = 6 }, { x = 10, y = 6 }, { x = 10, y = 7 }, { x = -9, y = 8 }, { x = -8, y = 9 }, { x = 9, y = 8 }, { x = 8, y = 9 }, { x = -7, y = 10 }, { x = -5, y = 11 }, { x = -6, y = 10 }, { x = -4, y = 11 }, { x = 5, y = 11 }, { x = 4, y = 11 }, { x = 7, y = 10 }, { x = 6, y = 10 }, { x = -3, y = 12 }, { x = -2, y = 12 }, { x = -1, y = 12 }, { x = 0, y = 12 }, { x = 1, y = 12 }, { x = 2, y = 12 }, { x = 3, y = 12 } },
[14] = { { x = -3, y = -13 }, { x = -1, y = -13 }, { x = -2, y = -13 }, { x = 1, y = -13 }, { x = 0, y = -13 }, { x = 3, y = -13 }, { x = 2, y = -13 }, { x = -7, y = -11 }, { x = -6, y = -11 }, { x = -5, y = -12 }, { x = -6, y = -12 }, { x = -4, y = -12 }, { x = 5, y = -12 }, { x = 4, y = -12 }, { x = 7, y = -11 }, { x = 6, y = -11 }, { x = 6, y = -12 }, { x = -10, y = -9 }, { x = -9, y = -9 }, { x = -9, y = -10 }, { x = -8, y = -10 }, { x = 9, y = -9 }, { x = 9, y = -10 }, { x = 8, y = -10 }, { x = 10, y = -9 }, { x = -11, y = -7 }, { x = -10, y = -8 }, { x = 11, y = -7 }, { x = 10, y = -8 }, { x = -11, y = -6 }, { x = -12, y = -6 }, { x = -12, y = -5 }, { x = 11, y = -6 }, { x = 12, y = -6 }, { x = 12, y = -5 }, { x = -13, y = -3 }, { x = -12, y = -4 }, { x = 12, y = -4 }, { x = 13, y = -3 }, { x = -13, y = -2 }, { x = -13, y = -1 }, { x = 13, y = -1 }, { x = 13, y = -2 }, { x = -13, y = 0 }, { x = -13, y = 1 }, { x = 13, y = 1 }, { x = 13, y = 0 }, { x = -13, y = 2 }, { x = -13, y = 3 }, { x = 13, y = 3 }, { x = 13, y = 2 }, { x = -12, y = 5 }, { x = -12, y = 4 }, { x = 12, y = 5 }, { x = 12, y = 4 }, { x = -11, y = 6 }, { x = -11, y = 7 }, { x = -12, y = 6 }, { x = 11, y = 7 }, { x = 11, y = 6 }, { x = 12, y = 6 }, { x = -10, y = 8 }, { x = -10, y = 9 }, { x = -9, y = 9 }, { x = 9, y = 9 }, { x = 10, y = 9 }, { x = 10, y = 8 }, { x = -9, y = 10 }, { x = -8, y = 10 }, { x = -7, y = 11 }, { x = -6, y = 11 }, { x = 7, y = 11 }, { x = 6, y = 11 }, { x = 8, y = 10 }, { x = 9, y = 10 }, { x = -6, y = 12 }, { x = -5, y = 12 }, { x = -4, y = 12 }, { x = -3, y = 13 }, { x = -2, y = 13 }, { x = -1, y = 13 }, { x = 0, y = 13 }, { x = 1, y = 13 }, { x = 2, y = 13 }, { x = 3, y = 13 }, { x = 5, y = 12 }, { x = 4, y = 12 }, { x = 6, y = 12 } },
[15] = { { x = -5, y = -13 }, { x = -6, y = -13 }, { x = -4, y = -13 }, { x = -3, y = -14 }, { x = -1, y = -14 }, { x = -2, y = -14 }, { x = 1, y = -14 }, { x = 0, y = -14 }, { x = 3, y = -14 }, { x = 2, y = -14 }, { x = 5, y = -13 }, { x = 4, y = -13 }, { x = 6, y = -13 }, { x = -9, y = -11 }, { x = -8, y = -11 }, { x = -8, y = -12 }, { x = -7, y = -12 }, { x = 7, y = -12 }, { x = 8, y = -12 }, { x = 8, y = -11 }, { x = 9, y = -11 }, { x = -11, y = -9 }, { x = -10, y = -10 }, { x = 10, y = -10 }, { x = 11, y = -9 }, { x = -12, y = -7 }, { x = -11, y = -8 }, { x = -12, y = -8 }, { x = 11, y = -8 }, { x = 12, y = -8 }, { x = 12, y = -7 }, { x = -13, y = -5 }, { x = -13, y = -6 }, { x = 13, y = -5 }, { x = 13, y = -6 }, { x = -13, y = -4 }, { x = -14, y = -3 }, { x = 13, y = -4 }, { x = 14, y = -3 }, { x = -14, y = -2 }, { x = -14, y = -1 }, { x = 14, y = -1 }, { x = 14, y = -2 }, { x = -14, y = 0 }, { x = -14, y = 1 }, { x = 14, y = 1 }, { x = 14, y = 0 }, { x = -14, y = 2 }, { x = -14, y = 3 }, { x = 14, y = 3 }, { x = 14, y = 2 }, { x = -13, y = 4 }, { x = -13, y = 5 }, { x = 13, y = 5 }, { x = 13, y = 4 }, { x = -13, y = 6 }, { x = -12, y = 7 }, { x = 12, y = 7 }, { x = 13, y = 6 }, { x = -11, y = 9 }, { x = -11, y = 8 }, { x = -12, y = 8 }, { x = 11, y = 8 }, { x = 11, y = 9 }, { x = 12, y = 8 }, { x = -9, y = 11 }, { x = -10, y = 10 }, { x = -8, y = 11 }, { x = 9, y = 11 }, { x = 8, y = 11 }, { x = 10, y = 10 }, { x = -7, y = 12 }, { x = -8, y = 12 }, { x = -6, y = 13 }, { x = -5, y = 13 }, { x = -4, y = 13 }, { x = 5, y = 13 }, { x = 4, y = 13 }, { x = 7, y = 12 }, { x = 6, y = 13 }, { x = 8, y = 12 }, { x = -3, y = 14 }, { x = -2, y = 14 }, { x = -1, y = 14 }, { x = 0, y = 14 }, { x = 1, y = 14 }, { x = 2, y = 14 }, { x = 3, y = 14 } },
[16] = { { x = -3, y = -15 }, { x = -1, y = -15 }, { x = -2, y = -15 }, { x = 1, y = -15 }, { x = 0, y = -15 }, { x = 3, y = -15 }, { x = 2, y = -15 }, { x = -7, y = -13 }, { x = -8, y = -13 }, { x = -5, y = -14 }, { x = -6, y = -14 }, { x = -4, y = -14 }, { x = 5, y = -14 }, { x = 4, y = -14 }, { x = 7, y = -13 }, { x = 6, y = -14 }, { x = 8, y = -13 }, { x = -9, y = -12 }, { x = -10, y = -11 }, { x = 9, y = -12 }, { x = 10, y = -11 }, { x = -11, y = -10 }, { x = -12, y = -9 }, { x = 11, y = -10 }, { x = 12, y = -9 }, { x = -13, y = -7 }, { x = -13, y = -8 }, { x = 13, y = -7 }, { x = 13, y = -8 }, { x = -14, y = -6 }, { x = -14, y = -5 }, { x = 14, y = -5 }, { x = 14, y = -6 }, { x = -15, y = -3 }, { x = -14, y = -4 }, { x = 15, y = -3 }, { x = 14, y = -4 }, { x = -15, y = -2 }, { x = -15, y = -1 }, { x = 15, y = -1 }, { x = 15, y = -2 }, { x = -15, y = 0 }, { x = -15, y = 1 }, { x = 15, y = 1 }, { x = 15, y = 0 }, { x = -15, y = 2 }, { x = -15, y = 3 }, { x = 15, y = 3 }, { x = 15, y = 2 }, { x = -14, y = 5 }, { x = -14, y = 4 }, { x = 14, y = 5 }, { x = 14, y = 4 }, { x = -13, y = 7 }, { x = -14, y = 6 }, { x = 13, y = 7 }, { x = 14, y = 6 }, { x = -13, y = 8 }, { x = -12, y = 9 }, { x = 12, y = 9 }, { x = 13, y = 8 }, { x = -11, y = 10 }, { x = -10, y = 11 }, { x = 10, y = 11 }, { x = 11, y = 10 }, { x = -9, y = 12 }, { x = -8, y = 13 }, { x = -7, y = 13 }, { x = 7, y = 13 }, { x = 8, y = 13 }, { x = 9, y = 12 }, { x = -6, y = 14 }, { x = -5, y = 14 }, { x = -4, y = 14 }, { x = -3, y = 15 }, { x = -2, y = 15 }, { x = -1, y = 15 }, { x = 0, y = 15 }, { x = 1, y = 15 }, { x = 2, y = 15 }, { x = 3, y = 15 }, { x = 4, y = 14 }, { x = 5, y = 14 }, { x = 6, y = 14 } }
}
for current_radius = 1, 16, 1 do
ffatable.fluid_explosion_schedule[#ffatable.fluid_explosion_schedule][current_radius] = {}
ffatable.fluid_explosion_schedule[#ffatable.fluid_explosion_schedule][current_radius].trigger_tick = game.tick + (current_radius * 8)
local circle_coords = circle_coordinates[current_radius]
circle_coords = shuffle(circle_coords)
for index, tile_position in pairs(circle_coords) do
local pos = { x = center_position.x + tile_position.x, y = center_position.y + tile_position.y }
ffatable.fluid_explosion_schedule[#ffatable.fluid_explosion_schedule][current_radius][index] = { x = pos.x, y = pos.y }
end
end
entity.die("player")
end
local function on_entity_damaged(event)
local entity = event.entity
if not entity.valid then return end
if not entity.health then return end
if not container_types[entity.type] then return end
if not entity.fluidbox[1] then return end
if not fluid_damages[entity.fluidbox[1].name] then return end
if entity.health > entity.prototype.max_health * 0.75 then return end
if math.random(1, 3) == 1 or entity.health <= 0 then
create_explosion_schedule(entity)
return
end
end
local function on_tick(event)
local ffatable = Table.get_table()
local tick = event.tick
if ffatable.fluid_explosion_schedule then
local explosion_schedule_is_alive = false
for explosion_index = 1, #ffatable.fluid_explosion_schedule, 1 do
if #ffatable.fluid_explosion_schedule[explosion_index] > 0 then
explosion_schedule_is_alive = true
for radius = 1, #ffatable.fluid_explosion_schedule[explosion_index], 1 do
if ffatable.fluid_explosion_schedule[explosion_index][radius].trigger_tick == tick then
for tile_index = 1, #ffatable.fluid_explosion_schedule[explosion_index][radius], 1 do
local continue_explosion = process_explosion_tile(ffatable.fluid_explosion_schedule[explosion_index][radius][tile_index], explosion_index, radius)
if not continue_explosion then
ffatable.fluid_explosion_schedule[explosion_index] = {}
break
end
end
if radius == #ffatable.fluid_explosion_schedule[explosion_index] then ffatable.fluid_explosion_schedule[explosion_index] = {} end
break
end
end
end
end
if not explosion_schedule_is_alive then ffatable.fluid_explosion_schedule = nil end
end
end
local on_init = function ()
local ffatable = Table.get_table()
ffatable.fluid_explosion_schedule = {}
end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
Event.add(defines.events.on_tick, on_tick)

View File

@ -0,0 +1,125 @@
local Public = {}
local Table = require 'modules.scrap_towny_ffa.table'
local info = [[You are an "outlander" stuck on this god-forsaken planet with a bunch of other desolate fools. You can choose to join
an existing town if accepted, or go at it alone, building your own outpost or living as an "outlander".
The local inhabitants are indifferent to you at first, so long as you don't build or pollute, but become increasingly aggressive
by foreign technology. In fact, they get quite aggressive at the scent of it. If you were to hurt any of the natives you will be
brandished a rogue until your untimely death or until you find better digs.
To create a new town or outpost simply place a furnace down in a suitable spot that is not near any other towns or obstructed.
The world seems to be limited in size with uninhabitable zones on four sides. News towns can only be built within these
borders and you must leave room for the town's size (radius of 27) when placing a new town.
TIP: It's best to find a spot far from existing towns and pollution, as enemies will become aggressive once you form a town.
Once a town is formed, members may invite other players and teams using a raw fish. To invite another player, drop a fish
on that player (with the Z key). To accept an invite, offer a fish in return to the member. To leave a town, simply drop coal
on the market. As a member of a town, your respawn point will change to that of the town.
To form any alliance with another town, drop a fish on a member or their market. If they agree they can reciprocate with a
fish offering.
The town market is the heart of your town. If it is destroyed, your town is destroyed and you will lose all research. So
protect it well, repair it whenever possible, and if you can afford, increase its health by purchasing upgrades. If your
town falls, members will be disbanded, and all buildings will become neutral and lootable.
When building your town, note that you may only build nearby existing structures such as your town market and walls and
any other structure you have placed. Beware that biters and spitters become more aggressive towards towns that are
advanced in research. Their evolution will scale around technology progress in any nearby towns and pollution levels.
This is a FFA ("Free-For-All") world. Short of bullying and derogatory remarks, anything goes. Griefing is encouraged,
so best to setup proper defenses for your town or outpost to fend off enemies when you are there and away.
Have fun and be comfy ^.^]]
function Public.toggle_button(player)
if player.gui.top["towny_map_intro_button"] then return end
local b = player.gui.top.add({ type = "sprite-button", caption = "Towny", name = "towny_map_intro_button", tooltip = "Show Info" })
b.style.font_color = { r = 0.5, g = 0.3, b = 0.99 }
b.style.font = "heading-1"
b.style.minimal_height = 38
b.style.minimal_width = 80
b.style.top_padding = 1
b.style.left_padding = 1
b.style.right_padding = 1
b.style.bottom_padding = 1
end
function Public.show(player)
local ffatable = Table.get_table()
if player.gui.center["towny_map_intro_frame"] then player.gui.center["towny_map_intro_frame"].destroy() end
local frame = player.gui.center.add { type = "frame", name = "towny_map_intro_frame" }
frame = frame.add { type = "frame", direction = "vertical" }
local t = frame.add { type = "table", column_count = 2 }
local label = t.add { type = "label", caption = "Active Factions:" }
label.style.font = "heading-1"
label.style.font_color = { r = 0.85, g = 0.85, b = 0.85 }
label.style.right_padding = 8
t = t.add { type = "table", column_count = 4 }
local label2 = t.add { type = "label", caption = "Outlander" .. "(" .. #game.forces.player.connected_players .. ")" }
label2.style.font_color = { 170, 170, 170 }
label2.style.font = "heading-3"
label2.style.minimal_width = 80
for _, town_center in pairs(ffatable.town_centers) do
local force = town_center.market.force
local label3 = t.add { type = "label", caption = force.name .. "(" .. #force.connected_players .. ")" }
label3.style.font = "heading-3"
label3.style.minimal_width = 80
label3.style.font_color = town_center.color
end
frame.add { type = "line" }
local l = frame.add { type = "label", caption = "Instructions:" }
l.style.font = "heading-1"
l.style.font_color = { r = 0.85, g = 0.85, b = 0.85 }
local l2 = frame.add { type = "label", caption = info }
l2.style.single_line = false
l2.style.font = "heading-2"
l2.style.font_color = { r = 0.8, g = 0.7, b = 0.99 }
end
function Public.close(event)
if not event.element then return end
if not event.element.valid then return end
local parent = event.element.parent
for _ = 1, 4, 1 do
if not parent then return end
if parent.name == "towny_map_intro_frame" then
parent.destroy()
return
end
parent = parent.parent
end
end
function Public.toggle(event)
if not event.element then return end
if not event.element.valid then return end
if event.element.name == "towny_map_intro_button" then
local player = game.players[event.player_index]
if player.gui.center["towny_map_intro_frame"] then
player.gui.center["towny_map_intro_frame"].destroy()
else
Public.show(player)
end
end
end
local function on_gui_click(event)
Public.close(event)
Public.toggle(event)
end
local Event = require 'utils.event'
Event.add(defines.events.on_gui_click, on_gui_click)
return Public

View File

@ -0,0 +1,15 @@
local Public = {}
function Public.reset()
for index = 1, table.size(game.forces), 1 do
local force = game.forces[index]
if force ~= nil then
force.clear_chart("nauvis")
end
end
end
--local Event = require 'utils.event'
--Event.add(defines.events.on_chunk_charted, on_chunk_charted)
return Public

View File

@ -0,0 +1,295 @@
local table_insert = table.insert
local Table = require 'modules.scrap_towny_ffa.table'
local Town_center = require 'modules.scrap_towny_ffa.town_center'
local upgrade_functions = {
-- Upgrade Town Center Health
[1] = function(town_center, player)
local market = town_center.market
local surface = market.surface
if town_center.max_health > 500000 then return end
town_center.health = town_center.health + town_center.max_health
town_center.max_health = town_center.max_health * 2
Town_center.set_market_health(market, 0)
surface.play_sound({ path = "utility/achievement_unlocked", position = player.position, volume_modifier = 1 })
end,
-- Upgrade Backpack
[2] = function(town_center, player)
local market = town_center.market
local force = market.force
local surface = market.surface
if force.character_inventory_slots_bonus > 100 then return end
force.character_inventory_slots_bonus = force.character_inventory_slots_bonus + 5
surface.play_sound({ path = "utility/achievement_unlocked", position = player.position, volume_modifier = 1 })
end,
-- Upgrade Mining Productivity
[3] = function(town_center, player)
local market = town_center.market
local force = market.force
local surface = market.surface
if town_center.upgrades.mining_prod >= 10 then return end
town_center.upgrades.mining_prod = town_center.upgrades.mining_prod + 1
force.mining_drill_productivity_bonus = force.mining_drill_productivity_bonus + 0.1
surface.play_sound({ path = "utility/achievement_unlocked", position = player.position, volume_modifier = 1 })
end,
-- Laser Turret Slot
[4] = function(town_center, player)
local market = town_center.market
local surface = market.surface
town_center.upgrades.laser_turret.slots = town_center.upgrades.laser_turret.slots + 1
surface.play_sound({ path = "utility/new_objective", position = player.position, volume_modifier = 1 })
end,
-- Set Spawn Point
[5] = function(town_center, player)
local ffatable = Table.get_table()
local market = town_center.market
local force = market.force
local surface = market.surface
local spawn_point = force.get_spawn_position(surface)
ffatable.spawn_point[player.name] = spawn_point
surface.play_sound({ path = "utility/scenario_message", position = player.position, volume_modifier = 1 })
end,
}
local function clear_offers(market)
for _ = 1, 256, 1 do
local a = market.remove_market_item(1)
if a == false then return end
end
end
local function set_offers(town_center)
local market = town_center.market
local force = market.force
local special_offers = {}
if town_center.max_health < 500000 then
special_offers[1] = { { { "coin", town_center.max_health * 0.1 } }, "Upgrade Town Center Health" }
else
special_offers[1] = { { { "coin", 1 } }, "Maximum Health upgrades reached!" }
end
if force.character_inventory_slots_bonus <= 100 then
special_offers[2] = { { { "coin", (force.character_inventory_slots_bonus / 5 + 1) * 50 } }, "Upgrade Backpack +5 Slot" }
else
special_offers[2] = { { { "coin", 1 } }, "Maximum Backpack upgrades reached!" }
end
if town_center.upgrades.mining_prod < 10 then
special_offers[3] = { { { "coin", (town_center.upgrades.mining_prod + 1) * 400 } }, "Upgrade Mining Productivity +10%" }
else
special_offers[3] = { { { "coin", 1 } }, "Maximum Mining upgrades reached!" }
end
local laser_turret = "Laser Turret Slot [#" .. tostring(town_center.upgrades.laser_turret.slots + 1) .. "]"
special_offers[4] = { { { "coin", 1000 + (town_center.upgrades.laser_turret.slots * 50) } }, laser_turret }
local spawn_point = "Set Spawn Point"
special_offers[5] = { { { "coin", 1 } }, spawn_point }
local market_items = {}
for _, v in pairs(special_offers) do
table_insert(market_items, { price = v[1], offer = { type = 'nothing', effect_description = v[2] } })
end
-- coin purchases
table_insert(market_items, { price = { { 'coin', 1 } }, offer = { type = 'give-item', item = 'raw-fish', count = 1 } })
table_insert(market_items, { price = { { 'coin', 1 } }, offer = { type = 'give-item', item = 'wood', count = 6 } })
table_insert(market_items, { price = { { 'coin', 1 } }, offer = { type = 'give-item', item = 'iron-ore', count = 6 } })
table_insert(market_items, { price = { { 'coin', 1 } }, offer = { type = 'give-item', item = 'copper-ore', count = 6 } })
table_insert(market_items, { price = { { 'coin', 1 } }, offer = { type = 'give-item', item = 'stone', count = 6 } })
table_insert(market_items, { price = { { 'coin', 1 } }, offer = { type = 'give-item', item = 'coal', count = 6 } })
table_insert(market_items, { price = { { 'coin', 1 } }, offer = { type = 'give-item', item = 'uranium-ore', count = 4 } })
table_insert(market_items, { price = { { 'coin', 300 } }, offer = { type = 'give-item', item = 'loader', count = 1 } })
table_insert(market_items, { price = { { 'coin', 600 } }, offer = { type = 'give-item', item = 'fast-loader', count = 1 } })
table_insert(market_items, { price = { { 'coin', 900 } }, offer = { type = 'give-item', item = 'express-loader', count = 1 } })
-- scrap selling
table_insert(market_items, { price = { { 'wood', 7 } }, offer = { type = 'give-item', item = 'coin', count = 1 } })
table_insert(market_items, { price = { { 'iron-ore', 7 } }, offer = { type = 'give-item', item = 'coin', count = 1 } })
table_insert(market_items, { price = { { 'copper-ore', 7 } }, offer = { type = 'give-item', item = 'coin', count = 1 } })
table_insert(market_items, { price = { { 'stone', 7 } }, offer = { type = 'give-item', item = 'coin', count = 1 } })
table_insert(market_items, { price = { { 'coal', 7 } }, offer = { type = 'give-item', item = 'coin', count = 1 } })
table_insert(market_items, { price = { { 'uranium-ore', 5 } }, offer = { type = 'give-item', item = 'coin', count = 1 } })
table_insert(market_items, { price = { { 'copper-cable', 12 } }, offer = { type = 'give-item', item = 'coin', count = 1 } })
table_insert(market_items, { price = { { 'iron-gear-wheel', 3 } }, offer = { type = 'give-item', item = 'coin', count = 1 } })
table_insert(market_items, { price = { { 'iron-stick', 12 } }, offer = { type = 'give-item', item = 'coin', count = 1 } })
table_insert(market_items, { price = { { 'empty-barrel', 1 } }, offer = { type = 'give-item', item = 'coin', count = 1 } })
for _, item in pairs(market_items) do
market.add_market_item(item)
end
end
local function refresh_offers(event)
local ffatable = Table.get_table()
local market = event.entity or event.market
if not market then return end
if not market.valid then return end
if market.name ~= "market" then return end
local town_center = ffatable.town_centers[market.force.name]
if not town_center then return end
clear_offers(market)
set_offers(town_center)
end
local function offer_purchased(event)
local ffatable = Table.get_table()
local player = game.players[event.player_index]
local market = event.market
local offer_index = event.offer_index
local count = event.count
if not upgrade_functions[offer_index] then return end
local town_center = ffatable.town_centers[market.force.name]
if not town_center then return end
upgrade_functions[offer_index](town_center, player)
if count > 1 then
local offers = market.get_market_items()
local price = offers[offer_index].price[1].amount
player.insert({ name = "coin", count = price * (count - 1) })
end
end
local function on_gui_opened(event)
local gui_type = event.gui_type
if gui_type ~= defines.gui_type.entity then return end
local entity = event.entity
if entity == nil or not entity.valid then return end
if entity.type == "market" then refresh_offers(event) end
end
local function on_market_item_purchased(event)
offer_purchased(event)
refresh_offers(event)
end
local function inside(pos, area)
return pos.x >= area.left_top.x and pos.x <= area.right_bottom.x and pos.y >= area.left_top.y and pos.y <= area.right_bottom.y
end
local function on_tick(_)
local ffatable = Table.get_table()
if not ffatable.town_centers then return end
local items = { "burner-inserter", "inserter", "long-handed-inserter", "fast-inserter",
"filter-inserter", "stack-inserter", "stack-filter-inserter",
"loader", "fast-loader", "express-loader" }
for _, town_center in pairs(ffatable.town_centers) do
local market = town_center.market
local offers = market.get_market_items()
if offers == nil then set_offers(town_center) end
local s = market.surface
local force = market.force
-- get the bounding box for the market
local bb = market.bounding_box
local area = { left_top = { bb.left_top.x - 2, bb.left_top.y - 2 }, right_bottom = { bb.right_bottom.x + 2, bb.right_bottom.y + 2 } }
local entities = s.find_entities_filtered({ area = area, name = items })
for _, e in pairs(entities) do
if e.name ~= "loader" and e.name ~= "fast-loader" and e.name ~= "express-loader" then
local ppos = e.pickup_position
local dpos = e.drop_position
-- pulling an item from the market
if inside(ppos, bb) and e.drop_target then
local stack = e.held_stack
local spos = e.held_stack_position
if inside(spos, bb) then
local filter
local filter_mode = e.inserter_filter_mode
if filter_mode ~= nil then
for i = 1, e.filter_slot_count do
if e.get_filter(i) ~= nil then
filter = e.get_filter(i)
break
end
end
end
if (filter_mode == "whitelist" and filter == "coin") or (filter_mode == "blacklist" and filter == nil) or (filter_mode == nil) then
if stack.valid and town_center.coin_balance > 0 then
-- pull coins
stack.set_stack({ name = "coin", count = 1 })
town_center.coin_balance = town_center.coin_balance - 1
Town_center.update_coin_balance(force)
end
else
if filter_mode == "whitelist" and filter ~= nil and stack.valid then
-- purchased and pull items if output buffer is empty
-- buffer the output in a item buffer since the stack might be too small
-- output items are shared among the output
for _, trade in ipairs(offers) do
local type = trade.offer.type
local item = trade.offer.item
local count = trade.offer.count or 1
local cost = trade.price[1].amount
if type == "give-item" and item == filter then
if town_center.output_buffer[item] == nil then town_center.output_buffer[item] = 0 end
if town_center.output_buffer[item] == 0 then
-- fill buffer
if town_center.coin_balance >= cost then
town_center.coin_balance = town_center.coin_balance - cost
Town_center.update_coin_balance(force)
town_center.output_buffer[item] = town_center.output_buffer[item] + count
--log("output_buffer[" .. item .. "] = " .. town_center.output_buffer[item])
end
end
if town_center.output_buffer[item] > 0 and not stack.valid_for_read then
-- output the item
local amount = 1
if stack.can_set_stack({ name = item, count = amount }) then
town_center.output_buffer[item] = town_center.output_buffer[item] - amount
stack.set_stack({ name = item, count = amount })
--log("output_buffer[" .. item .. "] = " .. town_center.output_buffer[item])
end
end
break
end
end
end
end
end
end
-- pushing an item to the market (coins or scrap)
if e.pickup_target and inside(dpos, bb) then
local stack = e.held_stack
local spos = e.held_stack_position
if stack.valid_for_read and inside(spos, bb) then
local name = stack.name
local amount = stack.count
if name == "coin" then
-- push coins
e.remove_item(stack)
town_center.coin_balance = town_center.coin_balance + amount
Town_center.update_coin_balance(force)
else
-- push items to turn into coin
for _, trade in ipairs(offers) do
local type = trade.offer.type
local item = trade.price[1].name
local count = trade.price[1].amount
local cost = trade.offer.count
if type == "give-item" and name == item and item ~= "coin" then
e.remove_item(stack)
-- buffer the input in an item buffer that can be sold
if town_center.input_buffer[item] == nil then town_center.input_buffer[item] = 0 end
town_center.input_buffer[item] = town_center.input_buffer[item] + amount
--log("input_buffer[" .. item .. "] = " .. town_center.input_buffer[item])
if town_center.input_buffer[item] >= count then
town_center.input_buffer[item] = town_center.input_buffer[item] - count
town_center.coin_balance = town_center.coin_balance + cost
Town_center.update_coin_balance(force)
--log("input_buffer[" .. item .. "] = " .. town_center.input_buffer[item])
end
end
end
end
end
end
end
end
end
end
local Event = require 'utils.event'
Event.add(defines.events.on_tick, on_tick)
Event.add(defines.events.on_gui_opened, on_gui_opened)
Event.add(defines.events.on_market_item_purchased, on_market_item_purchased)

View File

@ -0,0 +1,98 @@
local Table = require 'modules.scrap_towny_ffa.table'
local crash_site = {
-- simple entity with owner
"crash-site-spaceship-wreck-small-1",
"crash-site-spaceship-wreck-small-2",
"crash-site-spaceship-wreck-small-3",
"crash-site-spaceship-wreck-small-4",
"crash-site-spaceship-wreck-small-5",
"crash-site-spaceship-wreck-small-6",
-- containers
"big-ship-wreck-1",
"big-ship-wreck-2",
"big-ship-wreck-3",
"crash-site-chest-1",
"crash-site-chest-2",
"crash-site-spaceship-wreck-medium-1",
"crash-site-spaceship-wreck-medium-2",
"crash-site-spaceship-wreck-medium-3",
"crash-site-spaceship-wreck-big-1",
"crash-site-spaceship-wreck-big-2",
"crash-site-spaceship"
}
local function is_crash_site(entity)
if not entity.valid then return false end
local f = false
for i = 1, #crash_site, 1 do
if entity.name == crash_site[i] then f = true end
end
return f
end
local function mining_sound(player)
if game.tick % 15 ~= 0 then return end
local target = player.selected
if target == nil or not target.valid then return end
local surface = target.surface
local position = target.position
local path = "entity-mining/" .. target.name
surface.play_sound({path = path, position = position, volume_modifier = 1, override_sound_type = "game-effect" })
end
local function on_tick()
local ffatable = Table.get_table()
for index, player in pairs(game.players) do
if player.character ~= nil then
local mining = player.mining_state.mining
if ffatable.mining[index] ~= mining then
ffatable.mining[index] = mining
-- state change
if mining == true then
--log(player.name .. " started mining")
local target = player.selected
if target ~= nil and target.valid then
--log("target name = " .. target.prototype.name)
--log("position = " .. serpent.block(target.position))
--log("mineable_properties = " .. serpent.block(target.prototype.mineable_properties))
if is_crash_site(target) then
-- mining crash site
mining_sound(player)
ffatable.mining_target[index] = target
end
end
else
--log(player.name .. " stopped mining")
local target = ffatable.mining_target[index]
if target ~= nil then
ffatable.mining_target[index] = nil
end
end
else
if mining == true then
local target = player.selected
if target ~= nil and target.valid then
--local progress = player.character_mining_progress
--log("progress = " .. progress)
if is_crash_site(target) then
-- mining crash site
mining_sound(player)
end
end
end
end
end
end
end
local on_init = function ()
local ffatable = Table.get_table()
ffatable.mining = {}
ffatable.mining_entity = {}
ffatable.mining_target = {}
end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.add(defines.events.on_tick, on_tick)

View File

@ -0,0 +1,203 @@
local Public = {}
local math_random = math.random
local function create_limbo()
game.create_surface("limbo")
end
local function initialize_nauvis()
local surface = game.surfaces["nauvis"]
-- this overrides what is in the map_gen_settings.json file
local mgs = surface.map_gen_settings
mgs.default_enable_all_autoplace_controls = true -- don't mess with this!
mgs.autoplace_controls = {
coal = { frequency = "none", size = 1, richness = "normal" },
stone = { frequency = "none", size = 1, richness = "normal" },
["copper-ore"] = { frequency = "none", size = 1, richness = "normal" },
["iron-ore"] = { frequency = "none", size = 1, richness = "normal" },
["uranium-ore"] = { frequency = "none", size = 1, richness = "normal" },
["crude-oil"] = { frequency = "none", size = 1, richness = "normal" },
trees = { frequency = 2, size = "normal", richness = "normal" },
["enemy-base"] = { frequency = 8, size = 1, richness = "normal" }
}
mgs.autoplace_settings = {
entity = {
settings = {
["rock-huge"] = { frequency = 3, size = 12, richness = "very-high" },
["rock-big"] = { frequency = 3, size = 12, richness = "very-high" },
["sand-rock-big"] = { frequency = 3, size = 12, richness = 1, "very-high" },
}
},
decorative = {
settings = {
["rock-tiny"] = { frequency = 10, size = "normal", richness = "normal" },
["rock-small"] = { frequency = 5, size = "normal", richness = "normal" },
["rock-medium"] = { frequency = 2, size = "normal", richness = "normal" },
["sand-rock-small"] = { frequency = 10, size = "normal", richness = "normal" },
["sand-rock-medium"] = { frequency = 5, size = "normal", richness = "normal" }
}
}
}
mgs.cliff_settings = {
name = "cliff",
cliff_elevation_0 = 5,
cliff_elevation_interval = 10,
richness = 0.4
}
-- water = 0 means no water allowed
-- water = 1 means elevation is not reduced when calculating water tiles (elevation < 0)
-- water = 2 means elevation is reduced by 10 when calculating water tiles (elevation < 0)
-- or rather, the water table is 10 above the normal elevation
mgs.water = 0.5
mgs.peaceful_mode = false
mgs.starting_area = "none"
mgs.terrain_segmentation = 8
mgs.width = 2048
mgs.height = 2048
--mgs.starting_points = {
-- {x = 0, y = 0}
--}
mgs.research_queue_from_the_start = "always"
-- here we put the named noise expressions for the specific noise-layer if we want to override them
mgs.property_expression_names = {
-- here we are overriding the moisture noise-layer with a fixed value of 0 to keep moisture consistently dry across the map
-- it allows to free up the moisture noise expression
-- low moisture
--moisture = 0,
-- here we are overriding the aux noise-layer with a fixed value to keep aux consistent across the map
-- it allows to free up the aux noise expression
-- aux should be not sand, nor red sand
--aux = 0.5,
-- here we are overriding the temperature noise-layer with a fixed value to keep temperature consistent across the map
-- it allows to free up the temperature noise expression
-- temperature should be 20C or 68F
--temperature = 20,
-- here we are overriding the cliffiness noise-layer with a fixed value of 0 to disable cliffs
-- it allows to free up the cliffiness noise expression (which may or may not be useful)
-- disable cliffs
--cliffiness = 0,
-- we can disable starting lakes two ways, one by setting starting-lake-noise-amplitude = 0
-- or by making the elevation a very large number
-- make sure starting lake amplitude is 0 to disable starting lakes
["starting-lake-noise-amplitude"] = 0,
-- allow enemies to get up close on spawn
["starting-area"] = 0,
-- this accepts a string representing a named noise expression
-- or number to determine the elevation based on x, y and distance from starting points
-- we can not add a named noise expression at this point, we can only reference existing ones
-- if we have any custom noise expressions defined from a mod, we will be able to use them here
-- setting it to a fixed number would mean a flat map
-- elevation < 0 means there is water unless the water table has been changed
--elevation = -1,
--elevation = 0,
--elevation-persistence = 0,
-- testing
--["control-setting:moisture:bias"] = 0.5,
--["control-setting:moisture:frequency:multiplier"] = 0,
--["control-setting:aux:bias"] = 0.5,
--["control-setting:aux:frequency:multiplier"] = 1,
--["control-setting:temperature:bias"] = 0.01,
--["control-setting:temperature:frequency:multiplier"] = 100,
--["tile:water:probability"] = -1000,
--["tile:deep-water:probability"] = -1000,
-- a constant intensity means base distribution will be consistent with regard to distance
["enemy-base-intensity"] = 1,
-- adjust this value to set how many nests spawn per tile
["enemy-base-frequency"] = 0.2,
-- this will make and average base radius around 12 tiles
["enemy-base-radius"] = 12
}
mgs.seed = math_random(10000, 99999)
surface.map_gen_settings = mgs
surface.peaceful_mode = false
surface.always_day = false
surface.freeze_daytime = false
surface.clear(true)
surface.regenerate_entity({ "rock-huge", "rock-big", "sand-rock-big" })
surface.regenerate_decorative()
end
function Public.initialize()
-- difficulty settings
game.difficulty_settings.recipe_difficulty = defines.difficulty_settings.recipe_difficulty.normal
game.difficulty_settings.technology_difficulty = defines.difficulty_settings.technology_difficulty.normal
game.difficulty_settings.technology_price_multiplier = 0.50
-- pollution settings
game.map_settings.pollution.enabled = true
game.map_settings.pollution.diffusion_ratio = 0.02 -- amount that is diffused to neighboring chunk each second
game.map_settings.pollution.min_to_diffuse = 15 -- minimum number of pollution units on the chunk to start diffusing
game.map_settings.pollution.ageing = 1 -- percent of pollution eaten by a chunk's tiles per second
game.map_settings.pollution.expected_max_per_chunk = 150 -- anything greater than this number of pollution units is visualized similarly
game.map_settings.pollution.min_to_show_per_chunk = 50
game.map_settings.pollution.min_pollution_to_damage_trees = 60
game.map_settings.pollution.pollution_with_max_forest_damage = 150
game.map_settings.pollution.pollution_per_tree_damage = 50
game.map_settings.pollution.pollution_restored_per_tree_damage = 10
game.map_settings.pollution.max_pollution_to_restore_trees = 20
game.map_settings.pollution.enemy_attack_pollution_consumption_modifier = 1
-- enemy evolution settings
game.map_settings.enemy_evolution.enabled = true
game.map_settings.enemy_evolution.time_factor = 0.0 -- percent increase in the evolution factor per second
game.map_settings.enemy_evolution.destroy_factor = 0.0 -- percent increase in the evolution factor for each spawner destroyed
game.map_settings.enemy_evolution.pollution_factor = 0.0 -- percent increase in the evolution factor for each pollution unit
-- enemy expansion settings
game.map_settings.enemy_expansion.enabled = true
game.map_settings.enemy_expansion.max_expansion_distance = 7 -- maximum distance in chunks from the nearest base (4 = 128 tiles)
game.map_settings.enemy_expansion.friendly_base_influence_radius = 4 -- consider other nests within radius number of chunks (2 = 64 tiles)
game.map_settings.enemy_expansion.other_base_coefficient = 2.0 -- multiply by coefficient for friendly bases
game.map_settings.enemy_expansion.neighbouring_base_chunk_coefficient = 0.4 -- multiply by coefficient for friendly bases (^distance)
game.map_settings.enemy_expansion.enemy_building_influence_radius = 4 -- consider player buildings within radius number of chunks
game.map_settings.enemy_expansion.building_coefficient = 1.0 -- multiply by coefficient for player buildings
game.map_settings.enemy_expansion.neighbouring_chunk_coefficient = 0.5 -- multiply by coefficient for player buildings (^distance)
game.map_settings.enemy_expansion.max_colliding_tiles_coefficient = 0.9 -- percent of unbuildable tiles to not be considered a candidate
game.map_settings.enemy_expansion.settler_group_min_size = 4 -- min size of group for building a base (multiplied by evo factor, so need evo > 0)
game.map_settings.enemy_expansion.settler_group_max_size = 12 -- max size of group for building a base (multiplied by evo factor, so need evo > 0)
game.map_settings.enemy_expansion.min_expansion_cooldown = 1200 -- minimum time before next expansion
game.map_settings.enemy_expansion.max_expansion_cooldown = 3600 -- maximum time before next expansion
-- unit group settings
game.map_settings.unit_group.min_group_gathering_time = 600
game.map_settings.unit_group.max_group_gathering_time = 3600
game.map_settings.unit_group.max_wait_time_for_late_members = 3600
game.map_settings.unit_group.max_group_radius = 30.0
game.map_settings.unit_group.min_group_radius = 5.0
game.map_settings.unit_group.max_member_speedup_when_behind = 1.4
game.map_settings.unit_group.max_member_slowdown_when_ahead = 0.6
game.map_settings.unit_group.max_group_slowdown_factor = 0.3
game.map_settings.unit_group.max_group_member_fallback_factor = 3
game.map_settings.unit_group.member_disown_distance = 10
game.map_settings.unit_group.tick_tolerance_when_member_arrives = 60
game.map_settings.unit_group.max_gathering_unit_groups = 30
game.map_settings.unit_group.max_unit_group_size = 200
---- steering settings
--game.map_settings.steering.default.radius = 1.2
--game.map_settings.steering.default.separation_force = 0.005
--game.map_settings.steering.default.separation_factor = 1.2
--game.map_settings.steering.default.force_unit_fuzzy_goto_behavior = false
--game.map_settings.steering.moving.radius = 3
--game.map_settings.steering.moving.separation_force = 0.01
--game.map_settings.steering.moving.separation_factor = 3
--game.map_settings.steering.moving.force_unit_fuzzy_goto_behavior = false
create_limbo()
initialize_nauvis()
end
return Public

View File

@ -0,0 +1,19 @@
local Table = require 'modules.scrap_towny_ffa.table'
local function on_tick()
local ffatable = Table.get_table()
if not ffatable.on_tick_schedule[game.tick] then return end
for _, schedule in pairs(ffatable.on_tick_schedule[game.tick]) do
schedule.func(unpack(schedule.args))
end
ffatable.on_tick_schedule[game.tick] = nil
end
local on_init = function ()
local ffatable = Table.get_table()
ffatable.on_tick_schedule = {}
end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.add(defines.events.on_tick, on_tick)

View File

@ -0,0 +1,99 @@
local Public = {}
local math_random = math.random
local Table = require 'modules.scrap_towny_ffa.table'
local Scrap = require 'modules.scrap_towny_ffa.scrap'
local pollution_index = {
["small-biter"] = { min = 0.1, max = 0.1 },
["medium-biter"] = { min = 0.1, max = 0.2 },
["big-biter"] = { min = 0.1, max = 0.3 },
["behemoth-biter"] = { min = 0.1, max = 0.4 },
["small-spitter"] = { min = 0.1, max = 0.1 },
["medium-spitter"] = { min = 0.1, max = 0.2 },
["big-spitter"] = { min = 0.1, max = 0.3 },
["behemoth-spitter"] = { min = 0.2, max = 0.4 },
["small-worm-turret"] = { min = 0.1, max = 0.1 },
["medium-worm-turret"] = { min = 0.1, max = 0.2 },
["big-worm-turret"] = { min = 0.1, max = 0.3 },
["behemoth-worm-turret"] = { min = 0.2, max = 0.4 },
["biter-spawner"] = { min = 0.5, max = 2.5 },
["spitter-spawner"] = { min = 0.5, max = 2.5 },
["mineable-wreckage"] = { min = 0.1, max = 0.1 },
["small-ship-wreck"] = { min = 0.1, max = 0.1 },
["medium-ship-wreck"] = { min = 0.1, max = 0.1 },
["crash-site-spaceship-wreck-small-1"] = { min = 0.1, max = 0.1 },
["crash-site-spaceship-wreck-small-2"] = { min = 0.1, max = 0.1 },
["crash-site-spaceship-wreck-small-3"] = { min = 0.1, max = 0.1 },
["crash-site-spaceship-wreck-small-4"] = { min = 0.1, max = 0.1 },
["crash-site-spaceship-wreck-small-5"] = { min = 0.1, max = 0.1 },
["crash-site-spaceship-wreck-small-6"] = { min = 0.1, max = 0.1 },
["big-ship-wreck-1"] = { min = 0.2, max = 0.4 },
["big-ship-wreck-2"] = { min = 0.2, max = 0.4 },
["big-ship-wreck-3"] = { min = 0.2, max = 0.4 },
["crash-site-chest-1"] = { min = 0.1, max = 0.2 },
["crash-site-chest-2"] = { min = 0.1, max = 0.2 },
["crash-site-spaceship-wreck-medium-1"] = { min = 0.1, max = 0.2 },
["crash-site-spaceship-wreck-medium-2"] = { min = 0.1, max = 0.2 },
["crash-site-spaceship-wreck-medium-3"] = { min = 0.1, max = 0.2 },
["crash-site-spaceship-wreck-big-1"] = { min = 0.2, max = 0.4 },
["crash-site-spaceship-wreck-big-2"] = { min = 0.2, max = 0.4 },
["crash-site-spaceship"] = { min = 0.5, max = 2.5 },
["explosion"] = { min = 0.1, max = 0.1 },
["big-explosion"] = { min = 0.2, max = 0.2 },
["big-artillery-explosion"] = { min = 0.5, max = 0.5 },
["market"] = { min = 10, max = 50 },
}
function Public.market_scent()
local ffatable = Table.get_table()
local town_centers = ffatable.town_centers
if town_centers == nil then return end
for _, town_center in pairs(town_centers) do
local market = town_center.market
local pollution = pollution_index["market"]
local amount = math_random(pollution.min, pollution.max)
market.surface.pollute(market.position, amount)
end
end
function Public.explosion(position, surface, animation)
local pollution = pollution_index[animation]
if pollution == nil then return end
local amount = math_random(pollution.min, pollution.max)
surface.pollute(position, amount)
end
local function on_player_mined_entity(event)
local entity = event.entity
if Scrap.is_scrap(entity) == true then
local pollution = pollution_index[entity.name]
local amount = math_random(pollution.min, pollution.max)
entity.surface.pollute(entity.position, amount)
end
end
local function on_entity_damaged(event)
local entity = event.entity
if not entity.valid then return end
local pollution = pollution_index[entity.name]
if pollution == nil then return end
local amount = math_random(pollution.min, pollution.max)
entity.surface.pollute(entity.position, amount)
end
local function on_entity_died(event)
local entity = event.entity
if not entity.valid then return end
local pollution = pollution_index[entity.name]
if pollution == nil then return end
local amount = math_random(pollution.min, pollution.max) * 10
entity.surface.pollute(entity.position, amount)
end
local Event = require 'utils.event'
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
Event.add(defines.events.on_entity_died, on_entity_died)
return Public

View File

@ -0,0 +1,173 @@
local math_random = math.random
local math_floor = math.floor
local table_insert = table.insert
local table_shuffle = table.shuffle_table
local Table = require 'modules.scrap_towny_ffa.table'
local Evolution = require "modules.scrap_towny_ffa.evolution"
local valid_entities = {
["rock-big"] = true,
["rock-huge"] = true,
["sand-rock-big"] = true
}
local size_raffle = {
{ "giant", 128, 256 },
{ "huge", 64, 128 },
{ "big", 32, 64 },
{ "small", 16, 32 },
{ "tiny", 8, 16 },
}
local function get_chances()
local chances = {}
table_insert(chances, { "iron-ore", 25 })
table_insert(chances, { "copper-ore", 18 })
table_insert(chances, { "mixed", 15 })
table_insert(chances, { "coal", 14 })
table_insert(chances, { "stone", 8 })
table_insert(chances, { "uranium-ore", 3 })
return chances
end
local function set_raffle()
local ffatable = Table.get_table()
ffatable.rocks_yield_ore_veins.raffle = {}
for _, t in pairs(get_chances()) do
for _ = 1, t[2], 1 do
table_insert(ffatable.rocks_yield_ore_veins.raffle, t[1])
end
end
ffatable.rocks_yield_ore_veins.mixed_ores = { "iron-ore", "copper-ore", "stone", "coal" }
end
local function get_amount(position)
local base = 256
local relative_evolution = Evolution.get_evolution(position)
local tier = 4 + math_floor(relative_evolution * 16)
return (math_random(1, base) + math_random(1, 2 ^ tier))
end
local function draw_chain(surface, count, ore, ore_entities, ore_positions)
local ffatable = Table.get_table()
local vectors = { { 0, -1 }, { -1, 0 }, { 1, 0 }, { 0, 1 } }
local r = math_random(1, #ore_entities)
local position = { x = ore_entities[r].position.x, y = ore_entities[r].position.y }
for _ = 1, count, 1 do
table_shuffle(vectors)
for i = 1, 4, 1 do
local p = { x = position.x + vectors[i][1], y = position.y + vectors[i][2] }
local name = ore
if ore == "mixed" then name = ffatable.rocks_yield_ore_veins.mixed_ores[math_random(1, #ffatable.rocks_yield_ore_veins.mixed_ores)] end
if surface.can_place_entity({ name = name, position = p, amount = 1 }) then
if not ore_positions[p.x .. "_" .. p.y] then
position.x = p.x
position.y = p.y
ore_positions[p.x .. "_" .. p.y] = true
ore_entities[#ore_entities + 1] = { name = name, position = p, amount = get_amount(p) }
break
end
else
if surface.can_fast_replace({ name = name, position = p }) then
if math_random(1, 2) == 1 then
if not ore_positions[p.x .. "_" .. p.y] then
position.x = p.x
position.y = p.y
ore_positions[p.x .. "_" .. p.y] = true
ore_entities[#ore_entities + 1] = { name = name, position = p, amount = get_amount(p), fast_replace = true }
break
end
end
end
end
end
end
end
local function ore_vein(event)
local ffatable = Table.get_table()
local surface = event.entity.surface
local size = size_raffle[math_random(1, #size_raffle)]
local ore = ffatable.rocks_yield_ore_veins.raffle[math_random(1, #ffatable.rocks_yield_ore_veins.raffle)]
local icon
if game.entity_prototypes[ore] then
icon = "[img=entity/" .. ore .. "]"
else
icon = " "
end
local player = game.players[event.player_index]
for _, p in pairs(game.connected_players) do
if p.index == player.index then
p.print(
{ "rocks_yield_ore_veins.player_print",
{ "rocks_yield_ore_veins_colors." .. ore },
{ "rocks_yield_ore_veins." .. size[1] },
{ "rocks_yield_ore_veins." .. ore },
icon
},
{ r = 0.80, g = 0.80, b = 0.80 }
)
else
if p.force == player.force then
game.print(
{ "rocks_yield_ore_veins.game_print",
"[color=" .. player.chat_color.r .. "," .. player.chat_color.g .. "," .. player.chat_color.b .. "]" .. player.name .. "[/color]",
{ "rocks_yield_ore_veins." .. size[1] },
{ "rocks_yield_ore_veins." .. ore },
icon
},
{ r = 0.80, g = 0.80, b = 0.80 }
)
end
end
end
local position = event.entity.position
local ore_entities = { { name = ore, position = { x = position.x, y = position.y }, amount = get_amount(position) } }
if ore == "mixed" then
ore_entities = { { name = ffatable.rocks_yield_ore_veins.mixed_ores[math_random(1, #ffatable.rocks_yield_ore_veins.mixed_ores)], position = { x = position.x, y = position.y }, amount = get_amount(position) } }
end
local ore_positions = { [event.entity.position.x .. "_" .. event.entity.position.y] = true }
local count = math_random(size[2], size[3])
for _ = 1, 128, 1 do
local c = math_random(math_floor(size[2] * 0.25) + 1, size[2])
if count < c then c = count end
local placed_ore_count = #ore_entities
draw_chain(surface, c, ore, ore_entities, ore_positions)
count = count - (#ore_entities - placed_ore_count)
if count <= 0 then break end
end
for _, e in pairs(ore_entities) do
surface.create_entity(e)
end
end
local function on_player_mined_entity(event)
local ffatable = Table.get_table()
if not event.entity.valid then return end
if not valid_entities[event.entity.name] then return end
if math_random(1, ffatable.rocks_yield_ore_veins.chance) ~= 1 then return end
ore_vein(event)
end
local function on_init()
local ffatable = Table.get_table()
ffatable.rocks_yield_ore_veins = {}
ffatable.rocks_yield_ore_veins.raffle = {}
ffatable.rocks_yield_ore_veins.mixed_ores = {}
ffatable.rocks_yield_ore_veins.chance = 4
set_raffle()
end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)

View File

@ -0,0 +1,36 @@
local Public = {}
local scrapable = {
-- simple entity
"small-ship-wreck",
"medium-ship-wreck",
-- simple entity with owner
"crash-site-spaceship-wreck-small-1",
"crash-site-spaceship-wreck-small-2",
"crash-site-spaceship-wreck-small-3",
"crash-site-spaceship-wreck-small-4",
"crash-site-spaceship-wreck-small-5",
"crash-site-spaceship-wreck-small-6",
"big-ship-wreck-1",
"big-ship-wreck-2",
"big-ship-wreck-3",
"crash-site-chest-1",
"crash-site-chest-2",
"crash-site-spaceship-wreck-medium-1",
"crash-site-spaceship-wreck-medium-2",
"crash-site-spaceship-wreck-medium-3",
"crash-site-spaceship-wreck-big-1",
"crash-site-spaceship-wreck-big-2",
"crash-site-spaceship"
}
function Public.is_scrap(entity)
if not entity.valid then return false end
local f = false
for i = 1, #scrapable, 1 do
if entity.name == scrapable[i] then f = true end
end
return f
end
return Public

View File

@ -0,0 +1,103 @@
local table_size = table.size
local Table = require 'modules.scrap_towny_ffa.table'
-- called whenever a player places an item
local function on_built_entity(event)
local ffatable = Table.get_table()
local entity = event.created_entity
if not entity.valid then return end
if entity.name ~= "laser-turret" then return end
local player = game.players[event.player_index]
local force = player.force
local town_center = ffatable.town_centers[force.name]
local surface = entity.surface
if force == game.forces["player"] or force == game.forces["rogue"] or town_center == nil then
surface.create_entity({
name = "flying-text",
position = entity.position,
text = "You are not acclimated to this technology!",
color = { r = 0.77, g = 0.0, b = 0.0 }
})
player.insert({ name = "laser-turret", count = 1 })
entity.destroy()
return
end
local slots = town_center.upgrades.laser_turret.slots
local locations = town_center.upgrades.laser_turret.locations
if table_size(locations) >= slots then
surface.create_entity({
name = "flying-text",
position = entity.position,
text = "You do not have enough slots!",
color = { r = 0.77, g = 0.0, b = 0.0 }
})
player.insert({ name = "laser-turret", count = 1 })
entity.destroy()
return
end
local position = entity.position
local key = tostring("{" .. position.x .. "," .. position.y .. "}")
locations[key] = true
end
-- called whenever a player places an item
local function on_robot_built_entity(event)
local ffatable = Table.get_table()
local entity = event.created_entity
if not entity.valid then return end
if entity.name ~= "laser-turret" then return end
local robot = event.robot
local force = robot.force
local town_center = ffatable.town_centers[force.name]
local surface = entity.surface
if force == game.forces["player"] or force == game.forces["rogue"] or town_center == nil then
surface.create_entity({
name = "flying-text",
position = entity.position,
text = "Robot not acclimated to this technology!",
color = { r = 0.77, g = 0.0, b = 0.0 }
})
robot.insert({ name = "laser-turret", count = 1 })
entity.destroy()
return
end
local slots = town_center.upgrades.laser_turret.slots
local locations = town_center.upgrades.laser_turret.locations
if table_size(locations) >= slots then
surface.create_entity({
name = "flying-text",
position = entity.position,
text = "Town does not have enough slots!",
color = { r = 0.77, g = 0.0, b = 0.0 }
})
robot.insert({ name = "laser-turret", count = 1 })
entity.destroy()
return
end
local position = entity.position
local key = tostring("{" .. position.x .. "," .. position.y .. "}")
locations[key] = true
end
-- called whenever a player mines an entity but before it is removed from the map
-- will have the contents of the drops
local function on_player_mined_entity(event)
local ffatable = Table.get_table()
local player = game.players[event.player_index]
local force = player.force
local entity = event.entity
if entity.name == "laser-turret" then
local town_center = ffatable.town_centers[force.name]
if force == game.forces["player"] or force == game.forces["rogue"] or town_center == nil then return end
local locations = town_center.upgrades.laser_turret.locations
local position = entity.position
local key = tostring("{" .. position.x .. "," .. position.y .. "}")
locations[key] = nil
end
end
local Event = require 'utils.event'
Event.add(defines.events.on_built_entity, on_built_entity)
Event.add(defines.events.on_robot_built_entity, on_robot_built_entity)
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)

View File

@ -0,0 +1,183 @@
local Public = {}
local table_size = table.size
local table_insert = table.insert
local math_random = math.random
local math_rad = math.rad
local math_sin = math.sin
local math_cos = math.cos
local math_floor = math.floor
local Table = require 'modules.scrap_towny_ffa.table'
local Enemy = require "modules.scrap_towny_ffa.enemy"
local Building = require "modules.scrap_towny_ffa.building"
-- don't spawn if town is within this range
local spawn_point_town_buffer = 256
-- clear enemies within this distance from spawn
local spawn_point_safety = 16
-- incremental spawn distance from existing town
-- this is how much each attempt is incremented by for checking a pollution free area
local spawn_point_incremental_distance = 16
local function force_load(position, surface, radius)
--log("is_chunk_generated = " .. tostring(surface.is_chunk_generated(position)))
surface.request_to_generate_chunks(position, radius)
--log("force load position = {" .. position.x .. "," .. position.y .. "}")
surface.force_generate_chunk_requests()
end
-- gets an area (might not be even amount)
local function get_area(position, w, h)
local x1 = math_floor(w / 2)
local x2 = w - x1
local y1 = math_floor(h / 2)
local y2 = h - y1
return { { position.x - x1, position.y - y1 }, { position.x + x2, position.y + y2 } }
end
local function clear_spawn(position, surface, w, h)
--log("clear_spawn {" .. position.x .. "," .. position.y .. "}")
local area = get_area(position, w, h)
for _, e in pairs(surface.find_entities_filtered({ area = area })) do
if e.type ~= "character" then
e.destroy()
end
end
end
-- does the position have any pollution
local function has_pollution(position, surface)
local result = surface.get_pollution(position) > 0.0
--log("has_pollution = " .. tostring(result))
return result
end
-- is the position already used
local function in_use(position)
local ffatable = Table.get_table()
local result = false
for _, v in pairs(ffatable.spawn_point) do
if v == position then result = true end
end
--log("in_use = " .. tostring(result))
return result
end
-- is the position empty
local function is_empty(position, surface)
local entity_radius = 1
local tile_radius = 1
local entities = surface.count_entities_filtered({ position = position, radius = entity_radius, collision_mask = { "object-layer", "player-layer" } })
--log("entities = " .. entities)
if entities > 0 then return false end
local tiles = surface.count_tiles_filtered({ position = position, radius = tile_radius, collision_mask = "water-tile" })
--log("water-tiles = " .. tiles)
if tiles > 0 then return false end
local result = surface.can_place_entity({ name = "character", position = position })
--log("is_empty = " .. tostring(result))
return result
end
-- finds a valid spawn point that is not near a town and not in a polluted area
local function find_valid_spawn_point(surface)
local ffatable = Table.get_table()
-- check center of map first if valid
local position = { x = 0, y = 0 }
--log("testing {" .. position.x .. "," .. position.y .. "}")
force_load(position, surface, 1)
if in_use(position) == false then
if Building.near_town(position, surface, spawn_point_town_buffer) == false then
-- force load the position
if is_empty(position, surface) == true then
--log("found valid spawn point at {" .. position.x .. "," .. position.y .. "}")
return position
end
end
end
-- otherwise find a nearby town
local keyset = {}
for town_name, _ in pairs(ffatable.town_centers) do
table_insert(keyset, town_name)
end
local count = table_size(keyset)
if count > 0 then
local town_name = keyset[math_random(1, count)]
local town_center = ffatable.town_centers[town_name]
if town_center ~= nil then
position = town_center.market.position
end
--log("town center is {" .. position.x .. "," .. position.y .. "}")
end
-- and start checking around it for a suitable spawn position
local tries = 0
local radius = spawn_point_town_buffer
local angle
while (tries < 100) do
-- 8 attempts each position
for _ = 1, 8 do
-- position on the circle radius
angle = math_random(0, 360)
local t = math_rad(angle)
local x = math_floor(position.x + math_cos(t) * radius)
local y = math_floor(position.y + math_sin(t) * radius)
local target = { x = x, y = y }
--log("testing {" .. target.x .. "," .. target.y .. "}")
force_load(position, surface, 1)
if in_use(target) == false then
if has_pollution(target, surface) == false then
if Building.near_town(target, surface, spawn_point_town_buffer) == false then
if is_empty(target, surface) == true then
--log("found valid spawn point at {" .. target.x .. "," .. target.y .. "}")
position = target
return position
end
end
end
end
end
-- near a town, increment the radius and select another angle
radius = radius + math_random(1, spawn_point_incremental_distance)
angle = math_random(0, 360)
tries = tries + 1
end
return { x = 0, y = 0 }
end
function Public.get_new_spawn_point(player, surface)
local ffatable = Table.get_table()
-- get a new spawn point
local position = find_valid_spawn_point(surface)
-- should never be invalid or blocked
ffatable.spawn_point[player.name] = position
--log("player " .. player.name .. " assigned new spawn point at {" .. position.x .. "," .. position.y .. "}")
return position
end
-- gets a new or existing spawn point for the player
function Public.get_spawn_point(player, surface)
local ffatable = Table.get_table()
if ffatable.spawn_point == nil then ffatable.spawn_point = {} end
-- test the existing spawn point
local position = ffatable.spawn_point[player.name]
if position ~= nil then
-- check that the spawn point is not blocked
if surface.can_place_entity({ name = "character", position = position }) then
--log("player " .. player.name .. "using existing spawn point at {" .. position.x .. "," .. position.y .. "}")
return position
else
position = surface.find_non_colliding_position("character", position, 16, 0.25)
if (position ~= nil) then return position end
end
end
-- otherwise get a new spawn point
return Public.get_new_spawn_point(player, surface)
end
function Public.clear_spawn_point(position, surface)
Enemy.clear_worms(position, surface, spawn_point_safety) -- behemoth worms can attack from a range of 48, clear first time only
Enemy.clear_enemies(position, surface, spawn_point_safety) -- behemoth worms can attack from a range of 48
clear_spawn(position, surface, 7, 9)
end
return Public

View File

@ -0,0 +1,33 @@
-- spawners release biters on death -- by mewmew
local math_random = math.random
local Evolution = require "modules.scrap_towny_ffa.evolution"
local biter_building_inhabitants = {
[1] = { { "small-biter", 8, 16 } },
[2] = { { "small-biter", 12, 24 } },
[3] = { { "small-biter", 8, 16 }, { "medium-biter", 1, 2 } },
[4] = { { "small-biter", 4, 8 }, { "medium-biter", 4, 8 } },
[5] = { { "small-biter", 3, 5 }, { "medium-biter", 8, 12 } },
[6] = { { "small-biter", 3, 5 }, { "medium-biter", 5, 7 }, { "big-biter", 1, 2 } },
[7] = { { "medium-biter", 6, 8 }, { "big-biter", 3, 5 } },
[8] = { { "medium-biter", 2, 4 }, { "big-biter", 6, 8 } },
[9] = { { "medium-biter", 2, 3 }, { "big-biter", 7, 9 } },
[10] = { { "big-biter", 4, 8 }, { "behemoth-biter", 3, 4 } }
}
local function on_entity_died(event)
if not event.entity.valid then return end
if event.entity.type ~= "unit-spawner" then return end
local e = math.ceil(Evolution.get_biter_evolution(event.entity) * 10)
if e < 1 then e = 1 end
for _, t in pairs(biter_building_inhabitants[e]) do
for _ = 1, math_random(t[2], t[3]), 1 do
local p = event.entity.surface.find_non_colliding_position(t[1], event.entity.position, 6, 1)
if p then event.entity.surface.create_entity { name = t[1], position = p, force = event.entity.force.name } end
end
end
end
local Event = require 'utils.event'
Event.add(defines.events.on_entity_died, on_entity_died)

View File

@ -0,0 +1,30 @@
local Public = {}
-- one table to rule them all!
local Global = require 'utils.global'
local ffatable = {}
Global.register(
ffatable,
function(tbl)
ffatable = tbl
end
)
function Public.reset_table()
for k, _ in pairs(ffatable) do
ffatable[k] = nil
end
end
function Public.get_table()
return ffatable
end
local on_init = function ()
Public.reset_table()
end
local Event = require 'utils.event'
Event.on_init(on_init)
return Public

View File

@ -0,0 +1,681 @@
local Public = {}
local table_size = table.size
local string_match = string.match
local string_lower = string.lower
local Table = require 'modules.scrap_towny_ffa.table'
local outlander_color = { 150, 150, 150 }
local outlander_chat_color = { 170, 170, 170 }
local rogue_color = { 150, 150, 150 }
local rogue_chat_color = { 170, 170, 170 }
local item_drop_radius = 1.65
local function can_force_accept_member(force)
local ffatable = Table.get_table()
local town_centers = ffatable.town_centers
local size_of_town_centers = ffatable.size_of_town_centers
local member_limit = 0
if size_of_town_centers <= 1 then return true end
for _, town in pairs(town_centers) do
member_limit = member_limit + table_size(town.market.force.connected_players)
end
member_limit = math.floor(member_limit / size_of_town_centers) + 4
if #force.connected_players >= member_limit then
game.print(">> Town " .. force.name .. " has too many settlers! Current limit (" .. member_limit .. ")", { 255, 255, 0 })
return
end
return true
end
local function is_towny(force)
if force == game.forces["player"] or force == game.forces["rogue"] then return false end
return true
end
function Public.has_key(player)
local ffatable = Table.get_table()
if player == nil then return false end
return ffatable.key[player]
end
function Public.give_key(player)
local ffatable = Table.get_table()
if player == nil then return end
ffatable.key[player] = true
end
function Public.remove_key(player)
local ffatable = Table.get_table()
if player == nil then return end
ffatable.key[player] = false
end
function Public.set_player_color(player)
local ffatable = Table.get_table()
if player.force == game.forces["player"] then
player.color = outlander_color
player.chat_color = outlander_chat_color
return
end
if player.force == game.forces["rogue"] then
player.color = rogue_color
player.chat_color = rogue_chat_color
return
end
local town_center = ffatable.town_centers[player.force.name]
if not town_center then return end
player.color = town_center.color
player.chat_color = town_center.color
end
local function set_town_color(event)
local ffatable = Table.get_table()
if event.command ~= "color" then return end
local player = game.players[event.player_index]
local force = player.force
local town_center = ffatable.town_centers[force.name]
if not town_center then
Public.set_player_color(player)
return
end
town_center.color = { player.color.r, player.color.g, player.color.b }
rendering.set_color(town_center.town_caption, town_center.color)
for _, p in pairs(force.players) do
Public.set_player_color(p)
end
end
function Public.set_all_player_colors()
for _, p in pairs(game.connected_players) do
Public.set_player_color(p)
end
end
function Public.add_player_to_town(player, town_center)
local ffatable = Table.get_table()
local market = town_center.market
local force = market.force
local surface = market.surface
player.force = market.force
Public.remove_key(player)
ffatable.spawn_point[player.name] = force.get_spawn_position(surface)
game.permissions.get_group(force.name).add_player(player)
player.tag = ""
Public.set_player_color(player)
end
function Public.give_outlander_items(player)
player.insert({ name = "stone-furnace", count = 1 })
player.insert({ name = "raw-fish", count = 3 })
player.insert({ name = "coal", count = 3 })
end
function Public.set_player_to_outlander(player)
local ffatable = Table.get_table()
player.force = game.forces.player
if ffatable.spawn_point[player.name] then
ffatable.spawn_point[player.name] = nil
end
if game.permissions.get_group("outlander") == nil then game.permissions.create_group("outlander") end
game.permissions.get_group("outlander").add_player(player)
player.tag = "[Outlander]"
Public.set_player_color(player)
Public.give_key(player)
end
local function set_player_to_rogue(player)
local ffatable = Table.get_table()
player.force = game.forces["rogue"]
if ffatable.spawn_point[player.name] then
ffatable.spawn_point[player.name] = nil
end
if game.permissions.get_group("rogue") == nil then game.permissions.create_group("rogue") end
game.permissions.get_group("rogue").add_player(player)
player.tag = "[Rogue]"
Public.set_player_color(player)
end
local function ally_outlander(player, target)
local ffatable = Table.get_table()
local requesting_force = player.force
local target_force = target.force
-- don't handle request if target is not a town
if not is_towny(requesting_force) and not is_towny(target_force) then return false end
-- don't handle request to another town if already in a town
if is_towny(requesting_force) and is_towny(target_force) then return false end
-- handle the request
if not is_towny(requesting_force) and is_towny(target_force) then
ffatable.requests[player.index] = target_force.name
local target_player = false
if target.type == "character" then
target_player = target.player
else
target_player = game.players[target_force.name]
end
if target_player then
if ffatable.requests[target_player.index] then
if ffatable.requests[target_player.index] == player.name then
if ffatable.town_centers[target_force.name] then
if not can_force_accept_member(target_force) then return true end
game.print(">> " .. player.name .. " has settled in " .. target_force.name .. "'s Town!", { 255, 255, 0 })
Public.add_player_to_town(player, ffatable.town_centers[target_force.name])
return true
end
end
end
end
game.print(">> " .. player.name .. " wants to settle in " .. target_force.name .. " Town!", { 255, 255, 0 })
return true
end
-- handle the approval
if is_towny(requesting_force) and not is_towny(target_force) then
if target.type ~= "character" then return true end
local target_player = target.player
if not target_player then return true end
ffatable.requests[player.index] = target_player.name
if ffatable.requests[target_player.index] then
if ffatable.requests[target_player.index] == player.force.name then
if not can_force_accept_member(player.force) then return true end
if player.force.name == player.name then
game.print(">> " .. player.name .. " has accepted " .. target_player.name .. " into their Town!", { 255, 255, 0 })
else
game.print(">> " .. player.name .. " has accepted " .. target_player.name .. " into" .. player.force.name .. "'s Town!", { 255, 255, 0 })
end
Public.add_player_to_town(target_player, ffatable.town_centers[player.force.name])
return true
end
end
if player.force.name == player.name then
game.print(">> " .. player.name .. " is inviting " .. target_player.name .. " into their Town!", { 255, 255, 0 })
else
game.print(">> " .. player.name .. " is inviting " .. target_player.name .. " into " .. player.force.name .. "'s Town!", { 255, 255, 0 })
end
return true
end
end
local function ally_neighbour_towns(player, target)
local requesting_force = player.force
local target_force = target.force
if target_force.get_friend(requesting_force) and requesting_force.get_friend(target_force) then return end
requesting_force.set_friend(target_force, true)
game.print(">> Town " .. requesting_force.name .. " has set " .. target_force.name .. " as their friend!", { 255, 255, 0 })
if target_force.get_friend(requesting_force) then
game.print(">> The towns " .. requesting_force.name .. " and " .. target_force.name .. " have formed an alliance!", { 255, 255, 0 })
end
end
local function ally_town(player, item)
local position = item.position
local surface = player.surface
local area = { { position.x - item_drop_radius, position.y - item_drop_radius }, { position.x + item_drop_radius, position.y + item_drop_radius } }
local requesting_force = player.force
local target = false
for _, e in pairs(surface.find_entities_filtered({ type = { "character", "market" }, area = area })) do
if e.force.name ~= requesting_force.name then
target = e
break
end
end
if not target then return end
if target.force == game.forces["enemy"] or target.force == game.forces["neutral"] then return end
if ally_outlander(player, target) then return end
ally_neighbour_towns(player, target)
end
local function declare_war(player, item)
local ffatable = Table.get_table()
local position = item.position
local surface = player.surface
local area = { { position.x - item_drop_radius, position.y - item_drop_radius }, { position.x + item_drop_radius, position.y + item_drop_radius } }
local requesting_force = player.force
local target = surface.find_entities_filtered({ type = { "character", "market" }, area = area })[1]
if not target then return end
local target_force = target.force
if not is_towny(target_force) then return end
if requesting_force.name == target_force.name then
if player.name ~= target.force.name then
Public.set_player_to_outlander(player)
game.print(">> " .. player.name .. " has abandoned " .. target_force.name .. "'s Town!", { 255, 255, 0 })
ffatable.requests[player.index] = nil
end
if player.name == target.force.name then
if target.type ~= "character" then return end
local target_player = target.player
if not target_player then return end
if target_player.index == player.index then return end
Public.set_player_to_outlander(target_player)
game.print(">> " .. player.name .. " has banished " .. target_player.name .. " from their Town!", { 255, 255, 0 })
ffatable.requests[player.index] = nil
end
return
end
if not is_towny(requesting_force) then return end
requesting_force.set_friend(target_force, false)
target_force.set_friend(requesting_force, false)
game.print(">> " .. player.name .. " has dropped the coal! Town " .. target_force.name .. " and " .. requesting_force.name .. " are now at war!", { 255, 255, 0 })
end
local function delete_chart_tag_for_all_forces(market)
local forces = game.forces
local position = market.position
local surface = market.surface
for _, force in pairs(forces) do
local tags = force.find_chart_tags(surface, { { position.x - 0.1, position.y - 0.1 }, { position.x + 0.1, position.y + 0.1 } })
local tag = tags[1]
if tag then
if tag.icon.name == "stone-furnace" then
tag.destroy()
end
end
end
end
function Public.add_chart_tag(force, market)
local position = market.position
local tags = force.find_chart_tags(market.surface, { { position.x - 0.1, position.y - 0.1 }, { position.x + 0.1, position.y + 0.1 } })
if tags[1] then return end
force.add_chart_tag(market.surface, { icon = { type = 'item', name = 'stone-furnace' }, position = position, text = market.force.name .. "'s Town" })
end
function Public.update_town_chart_tags()
local ffatable = Table.get_table()
local town_centers = ffatable.town_centers
local forces = game.forces
for _, town_center in pairs(town_centers) do
local market = town_center.market
for _, force in pairs(forces) do
if force.is_chunk_visible(market.surface, town_center.chunk_position) then
Public.add_chart_tag(force, market)
end
end
end
if game.forces["player"] ~= nil then game.forces["player"].clear_chart(game.surfaces["nauvis"]) end
if game.forces["rogue"] ~= nil then game.forces["rogue"].clear_chart(game.surfaces["nauvis"]) end
end
local function reset_permissions(permission_group)
for action_name, _ in pairs(defines.input_action) do
permission_group.set_allows_action(defines.input_action[action_name], true)
end
end
local function disable_blueprints(permission_group)
local defs = {
defines.input_action.alt_select_blueprint_entities,
defines.input_action.cancel_new_blueprint,
defines.input_action.change_blueprint_record_label,
defines.input_action.clear_selected_blueprint,
defines.input_action.create_blueprint_like,
defines.input_action.cycle_blueprint_backwards,
defines.input_action.cycle_blueprint_forwards,
defines.input_action.delete_blueprint_library,
defines.input_action.delete_blueprint_record,
defines.input_action.drop_blueprint_record,
defines.input_action.drop_to_blueprint_book,
defines.input_action.export_blueprint,
defines.input_action.grab_blueprint_record,
defines.input_action.import_blueprint,
defines.input_action.import_blueprint_string,
defines.input_action.open_blueprint_library_gui,
defines.input_action.open_blueprint_record,
defines.input_action.select_blueprint_entities,
defines.input_action.setup_blueprint,
defines.input_action.setup_single_blueprint_record,
defines.input_action.upgrade_open_blueprint,
defines.input_action.deconstruct,
defines.input_action.clear_selected_deconstruction_item,
defines.input_action.cancel_deconstruct,
defines.input_action.toggle_deconstruction_item_entity_filter_mode,
defines.input_action.toggle_deconstruction_item_tile_filter_mode,
defines.input_action.set_deconstruction_item_tile_selection_mode,
defines.input_action.set_deconstruction_item_trees_and_rocks_only,
}
for _, d in pairs(defs) do permission_group.set_allows_action(d, false) end
end
local function enable_artillery(force, permission_group)
permission_group.set_allows_action(defines.input_action.use_artillery_remote, true)
force.technologies["artillery"].enabled = true
force.technologies["artillery-shell-range-1"].enabled = false
force.technologies["artillery-shell-speed-1"].enabled = false
force.recipes["artillery-turret"].enabled = true
force.recipes["artillery-wagon"].enabled = true
force.recipes["artillery-targeting-remote"].enabled = true
force.recipes["artillery-shell"].enabled = true
end
local function disable_artillery(force, permission_group)
permission_group.set_allows_action(defines.input_action.use_artillery_remote, false)
force.technologies["artillery"].enabled = false
force.technologies["artillery-shell-range-1"].enabled = false
force.technologies["artillery-shell-speed-1"].enabled = false
force.recipes["artillery-turret"].enabled = false
force.recipes["artillery-wagon"].enabled = false
force.recipes["artillery-targeting-remote"].enabled = false
force.recipes["artillery-shell"].enabled = false
end
local function disable_spidertron(force, permission_group)
permission_group.set_allows_action(defines.input_action.send_spidertron, false)
force.technologies["spidertron"].enabled = false
force.recipes["spidertron"].enabled = false
force.recipes["spidertron-remote"].enabled = false
end
local function disable_rockets(force)
force.technologies["rocketry"].enabled = false
force.technologies["explosive-rocketry"].enabled = false
force.recipes["rocket-launcher"].enabled = false
force.recipes["rocket"].enabled = false
force.recipes["explosive-rocket"].enabled = false
end
local function disable_nukes(force)
force.technologies["atomic-bomb"].enabled = false
force.recipes["atomic-bomb"].enabled = false
end
local function disable_cluster_grenades(force)
force.recipes["cluster-grenade"].enabled = false
end
local function enable_radar(force)
force.recipes["radar"].enabled = true
force.share_chart = true
force.clear_chart("nauvis")
end
local function disable_radar(force)
force.recipes["radar"].enabled = false
force.share_chart = false
force.clear_chart("nauvis")
end
local function disable_achievements(permission_group)
permission_group.set_allows_action(defines.input_action.open_achievements_gui, false)
end
local function disable_tips_and_tricks(permission_group)
permission_group.set_allows_action(defines.input_action.open_tips_and_tricks_gui, false)
end
-- setup a team force
function Public.add_new_force(force_name)
-- disable permissions
local force = game.create_force(force_name)
local permission_group = game.permissions.create_group(force_name)
reset_permissions(permission_group)
disable_blueprints(permission_group)
enable_artillery(force, permission_group)
disable_spidertron(force, permission_group)
disable_rockets(force)
disable_nukes(force)
disable_cluster_grenades(force)
enable_radar(force)
disable_achievements(permission_group)
disable_tips_and_tricks(permission_group)
-- friendly fire
force.friendly_fire = true
-- disable technologies
force.research_queue_enabled = true
-- balance initial combat
force.set_ammo_damage_modifier("landmine", -0.75)
force.set_ammo_damage_modifier("grenade", -0.5)
end
local function kill_force(force_name)
local ffatable = Table.get_table()
local force = game.forces[force_name]
local market = ffatable.town_centers[force_name].market
local surface = market.surface
surface.create_entity({ name = "big-artillery-explosion", position = market.position })
for _, player in pairs(force.players) do
if player.character then
player.character.die()
else
ffatable.requests[player.index] = "kill-character"
end
player.force = game.forces.player
Public.set_player_color(player)
end
for _, e in pairs(surface.find_entities_filtered({ force = force_name })) do
if e.valid then
if e.type == "wall" or e.type == "gate" then
e.die()
end
end
end
game.merge_forces(force_name, "neutral")
ffatable.town_centers[force_name] = nil
ffatable.size_of_town_centers = ffatable.size_of_town_centers - 1
delete_chart_tag_for_all_forces(market)
game.print(">> " .. force_name .. "'s town has fallen! [gps=" .. math.floor(market.position.x) .. "," .. math.floor(market.position.y) .. "]", { 255, 255, 0 })
end
local player_force_disabled_recipes = { "lab", "automation-science-pack", "stone-brick", "radar" }
local player_force_enabled_recipes = { "submachine-gun", "assembling-machine-1", "small-lamp", "shotgun", "shotgun-shell", "underground-belt", "splitter", "steel-plate", "car", "cargo-wagon", "constant-combinator", "engine-unit", "green-wire", "locomotive", "rail", "train-stop", "arithmetic-combinator", "decider-combinator" }
-- setup the player force (this is the default for Outlanders)
local function setup_player_force()
local force = game.forces.player
local permission_group = game.permissions.create_group("outlander")
-- disable permissions
reset_permissions(permission_group)
disable_blueprints(permission_group)
disable_artillery(force, permission_group)
disable_spidertron(force, permission_group)
disable_rockets(force)
disable_nukes(force)
disable_cluster_grenades(force)
disable_radar(force)
disable_achievements(permission_group)
disable_tips_and_tricks(permission_group)
-- disable research
force.disable_research()
force.research_queue_enabled = false
-- friendly fire
force.friendly_fire = true
-- disable recipes
local recipes = force.recipes
for _, recipe_name in pairs(player_force_disabled_recipes) do
recipes[recipe_name].enabled = false
end
for _, recipe_name in pairs(player_force_enabled_recipes) do
recipes[recipe_name].enabled = true
end
force.set_ammo_damage_modifier("landmine", -0.75)
force.set_ammo_damage_modifier("grenade", -0.5)
end
local function setup_rogue_force()
local force_name = "rogue"
local force = game.create_force(force_name)
local permission_group = game.permissions.create_group(force_name)
-- disable permissions
reset_permissions(permission_group)
disable_blueprints(permission_group)
disable_artillery(force, permission_group)
disable_spidertron(force, permission_group)
disable_rockets(force)
disable_nukes(force)
disable_cluster_grenades(force)
disable_radar(force)
disable_achievements(permission_group)
disable_tips_and_tricks(permission_group)
-- disable research
force.disable_research()
force.research_queue_enabled = false
-- friendly fire
force.friendly_fire = true
-- disable recipes
local recipes = force.recipes
for _, recipe_name in pairs(player_force_disabled_recipes) do
recipes[recipe_name].enabled = false
end
for _, recipe_name in pairs(player_force_enabled_recipes) do
recipes[recipe_name].enabled = true
end
force.set_ammo_damage_modifier("landmine", -0.75)
force.set_ammo_damage_modifier("grenade", -0.5)
end
local function setup_enemy_force()
local e_force = game.forces["enemy"]
e_force.evolution_factor = 1 -- this should never change since we are changing biter types on spawn
e_force.set_friend(game.forces.player, true) -- outlander force (player) should not be attacked by turrets
e_force.set_cease_fire(game.forces.player, true) -- outlander force (player) should not be attacked by units
e_force.set_friend(game.forces["rogue"], false) -- rogue force (rogue) should be attacked by turrets
e_force.set_cease_fire(game.forces["rogue"], false) -- rogue force (rogue) should be attacked by units
-- note, these don't prevent an outlander or rogue from attacking a unit or spawner, we need to handle separately
end
local function on_player_dropped_item(event)
local player = game.players[event.player_index]
local entity = event.entity
if entity.stack.name == "raw-fish" then
ally_town(player, entity)
return
end
if entity.stack.name == "coal" then
declare_war(player, entity)
return
end
end
---- when a player dies, reveal their base to everyone
--local function on_player_died(event)
-- local player = game.players[event.player_index]
-- if not player.character then return end
-- if not player.character.valid then return end
-- reveal_entity_to_all(player.character)
--end
local function on_entity_damaged(event)
local entity = event.entity
if not entity.valid then return end
local cause = event.cause
local force = event.force
-- special case to handle enemies attacked by outlanders
if entity.force == game.forces["enemy"] then
if cause ~= nil then
if cause.type == "character" and force == game.forces["player"] then
local player = cause.player
if force == game.forces["player"] then
-- set the force of the player to rogue until they die or create a town
set_player_to_rogue(player)
end
end
-- cars and tanks
if cause.type == "car" or cause.type == "tank" then
local driver = cause.get_driver()
if driver ~= nil and driver.force == game.forces["player"] then
-- set the force of the player to rogue until they die or create a town
set_player_to_rogue(driver)
end
local passenger = cause.get_passenger()
if passenger ~= nil and passenger.force == game.forces["player"] then
-- set the force of the player to rogue until they die or create a town
set_player_to_rogue(passenger)
end
end
-- trains
if cause.type == "locomotive" or cause.type == "cargo-wagon" or cause.type == "fluid-wagon" or cause.type == "artillery-wagon" then
local train = cause.train
for _, passenger in pairs(train.passengers) do
if passenger ~= nil and passenger.force == game.forces["player"] then
set_player_to_rogue(passenger)
end
end
end
-- combat robots
if cause.type == "combat-robot" and force == game.forces["player"] then
local owner = cause.last_user
-- set the force of the player to rogue until they die or create a town
set_player_to_rogue(owner)
end
end
end
end
local function on_entity_died(event)
local entity = event.entity
if entity.name == "market" then
kill_force(entity.force.name)
end
end
local function on_post_entity_died(event)
local prototype = event.prototype.type
if prototype ~= "character" then return end
local entities = game.surfaces[event.surface_index].find_entities_filtered({ position = event.position, radius = 1 })
for _, e in pairs(entities) do
if e.type == "character-corpse" then
Public.remove_key(e)
end
end
end
local function on_console_command(event)
set_town_color(event)
end
local function on_console_chat(event)
local player = game.players[event.player_index]
if string_match(string_lower(event.message), "%[armor%=") then
player.clear_console()
game.print(">> " .. player.name .. " is trying to gain an unfair advantage!")
end
end
function Public.initialize()
setup_player_force()
setup_rogue_force()
setup_enemy_force()
end
local on_init = function ()
local ffatable = Table.get_table()
ffatable.key = {}
ffatable.spawn_point = {}
ffatable.requests = {}
end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.add(defines.events.on_player_dropped_item, on_player_dropped_item)
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
Event.add(defines.events.on_entity_died, on_entity_died)
Event.add(defines.events.on_post_entity_died, on_post_entity_died)
Event.add(defines.events.on_console_command, on_console_command)
Event.add(defines.events.on_console_chat, on_console_chat)
return Public

View File

@ -0,0 +1,92 @@
-- timer traps -- by mewmew
local table_insert = table.insert
local math_random = math.random
local Table = require 'modules.scrap_towny_ffa.table'
local tick_tacks = { "*tick*", "*tick*", "*tack*", "*tak*", "*tik*", "*tok*" }
local kaboom_weights = {
{ name = "grenade", chance = 7 },
{ name = "cluster-grenade", chance = 1 },
{ name = "destroyer-capsule", chance = 1 },
{ name = "defender-capsule", chance = 4 },
{ name = "distractor-capsule", chance = 3 },
{ name = "poison-capsule", chance = 2 },
{ name = "explosive-uranium-cannon-projectile", chance = 3 },
{ name = "explosive-cannon-projectile", chance = 5 },
}
local kabooms = {}
for _, t in pairs(kaboom_weights) do
for _ = 1, t.chance, 1 do
table_insert(kabooms, t.name)
end
end
local function create_flying_text(surface, position, text)
surface.create_entity({
name = "flying-text",
position = position,
text = text,
color = { r = 0.75, g = 0.75, b = 0.75 }
})
if text == "..." then return end
surface.play_sound({ path = "utility/armor_insert", position = position, volume_modifier = 0.75 })
end
local function create_kaboom(surface, position, name)
local target = position
local speed = 0.5
if name == "defender-capsule" or name == "destroyer-capsule" or name == "distractor-capsule" then
surface.create_entity({
name = "flying-text",
position = position,
text = "(((Sentries Engaging Target)))",
color = { r = 0.8, g = 0.0, b = 0.0 }
})
local nearest_player_unit = surface.find_nearest_enemy({ position = position, max_distance = 128, force = "enemy" })
if nearest_player_unit then target = nearest_player_unit.position end
speed = 0.001
end
surface.create_entity({
name = name,
position = position,
force = "enemy",
target = target,
speed = speed
})
end
local function tick_tack_trap(surface, position)
local ffatable = Table.get_table()
if not surface then return end
if not position then return end
if not position.x then return end
if not position.y then return end
local tick_tack_count = math_random(5, 9)
for t = 60, tick_tack_count * 60, 60 do
if not ffatable.on_tick_schedule[game.tick + t] then ffatable.on_tick_schedule[game.tick + t] = {} end
if t < tick_tack_count * 60 then
ffatable.on_tick_schedule[game.tick + t][#ffatable.on_tick_schedule[game.tick + t] + 1] = {
func = create_flying_text,
args = { surface, { x = position.x, y = position.y }, tick_tacks[math_random(1, #tick_tacks)] }
}
else
if math_random(1, 10) == 1 then
ffatable.on_tick_schedule[game.tick + t][#ffatable.on_tick_schedule[game.tick + t] + 1] = {
func = create_flying_text,
args = { surface, { x = position.x, y = position.y }, "..." }
}
else
ffatable.on_tick_schedule[game.tick + t][#ffatable.on_tick_schedule[game.tick + t] + 1] = {
func = create_kaboom,
args = { surface, { x = position.x, y = position.y }, kabooms[math_random(1, #kabooms)] }
}
end
end
end
end
return tick_tack_trap

View File

@ -0,0 +1,523 @@
local Public = {}
local math_random = math.random
local table_insert = table.insert
local math_floor = math.floor
local table_shuffle = table.shuffle_table
local Table = require 'modules.scrap_towny_ffa.table'
local Team = require "modules.scrap_towny_ffa.team"
local Building = require "modules.scrap_towny_ffa.building"
local town_radius = 27
local radius_between_towns = 160
local ore_amount = 250
local colors = {}
local c1 = 250
local c2 = 210
local c3 = -40
for v = c1, c2, c3 do
table_insert(colors, { 0, 0, v })
end
for v = c1, c2, c3 do
table_insert(colors, { 0, v, 0 })
end
for v = c1, c2, c3 do
table_insert(colors, { v, 0, 0 })
end
for v = c1, c2, c3 do
table_insert(colors, { 0, v, v })
end
for v = c1, c2, c3 do
table_insert(colors, { v, v, 0 })
end
for v = c1, c2, c3 do
table_insert(colors, { v, 0, v })
end
local town_wall_vectors = {}
for x = 2, town_radius, 1 do
table_insert(town_wall_vectors, { x, town_radius })
table_insert(town_wall_vectors, { x * -1, town_radius })
table_insert(town_wall_vectors, { x, town_radius * -1 })
table_insert(town_wall_vectors, { x * -1, town_radius * -1 })
end
for y = 2, town_radius - 1, 1 do
table_insert(town_wall_vectors, { town_radius, y })
table_insert(town_wall_vectors, { town_radius, y * -1 })
table_insert(town_wall_vectors, { town_radius * -1, y })
table_insert(town_wall_vectors, { town_radius * -1, y * -1 })
end
local gate_vectors_horizontal = {}
for x = -1, 1, 1 do
table_insert(gate_vectors_horizontal, { x, town_radius })
table_insert(gate_vectors_horizontal, { x, town_radius * -1 })
end
local gate_vectors_vertical = {}
for y = -1, 1, 1 do
table_insert(gate_vectors_vertical, { town_radius, y })
table_insert(gate_vectors_vertical, { town_radius * -1, y })
end
local resource_vectors = {}
resource_vectors[1] = {}
for x = 7, 24, 1 do
for y = 7, 24, 1 do
table_insert(resource_vectors[1], { x, y })
end
end
resource_vectors[2] = {}
for _, vector in pairs(resource_vectors[1]) do table_insert(resource_vectors[2], { vector[1] * -1, vector[2] }) end
resource_vectors[3] = {}
for _, vector in pairs(resource_vectors[1]) do table_insert(resource_vectors[3], { vector[1] * -1, vector[2] * -1 }) end
resource_vectors[4] = {}
for _, vector in pairs(resource_vectors[1]) do table_insert(resource_vectors[4], { vector[1], vector[2] * -1 }) end
local additional_resource_vectors = {}
additional_resource_vectors[1] = {}
for x = 10, 22, 1 do
for y = -4, 4, 1 do
table_insert(additional_resource_vectors[1], { x, y })
end
end
additional_resource_vectors[2] = {}
for _, vector in pairs(additional_resource_vectors[1]) do table_insert(additional_resource_vectors[2], { vector[1] * -1, vector[2] }) end
additional_resource_vectors[3] = {}
for y = 10, 22, 1 do
for x = -4, 4, 1 do
table_insert(additional_resource_vectors[3], { x, y })
end
end
additional_resource_vectors[4] = {}
for _, vector in pairs(additional_resource_vectors[3]) do table_insert(additional_resource_vectors[4], { vector[1], vector[2] * -1 }) end
local clear_whitelist_types = {
["simple-entity"] = true,
["resource"] = true,
["cliff"] = true,
["tree"] = true,
}
local starter_supplies = {
{ name = "raw-fish", count = 3 },
{ name = "grenade", count = 3 },
{ name = "stone", count = 32 },
{ name = "land-mine", count = 4 },
{ name = "iron-gear-wheel", count = 16 },
{ name = "iron-plate", count = 32 },
{ name = "copper-plate", count = 16 },
{ name = "shotgun", count = 1 },
{ name = "shotgun-shell", count = 8 },
{ name = "firearm-magazine", count = 16 },
{ name = "firearm-magazine", count = 16 },
{ name = "gun-turret", count = 2 },
}
local function count_nearby_ore(surface, position, ore_name)
local count = 0
local r = town_radius + 8
for _, e in pairs(surface.find_entities_filtered({ area = { { position.x - r, position.y - r }, { position.x + r, position.y + r } }, force = "neutral", name = ore_name })) do
count = count + e.amount
end
return count
end
local function draw_town_spawn(player_name)
local ffatable = Table.get_table()
local market = ffatable.town_centers[player_name].market
local position = market.position
local surface = market.surface
local area = { { position.x - (town_radius + 1), position.y - (town_radius + 1) }, { position.x + (town_radius + 1), position.y + (town_radius + 1) } }
-- remove other than cliffs, rocks and ores and trees
for _, e in pairs(surface.find_entities_filtered({ area = area, force = "neutral" })) do
if not clear_whitelist_types[e.type] then
e.destroy()
end
end
-- create walls
for _, vector in pairs(gate_vectors_horizontal) do
local p = { position.x + vector[1], position.y + vector[2] }
--p = surface.find_non_colliding_position("gate", p, 64, 1)
if p then
surface.create_entity({ name = "gate", position = p, force = player_name, direction = 2 })
end
end
for _, vector in pairs(gate_vectors_vertical) do
local p = { position.x + vector[1], position.y + vector[2] }
--p = surface.find_non_colliding_position("gate", p, 64, 1)
if p then
surface.create_entity({ name = "gate", position = p, force = player_name, direction = 0 })
end
end
for _, vector in pairs(town_wall_vectors) do
local p = { position.x + vector[1], position.y + vector[2] }
--p = surface.find_non_colliding_position("stone-wall", p, 64, 1)
if p then
surface.create_entity({ name = "stone-wall", position = p, force = player_name })
end
end
-- ore patches
local ores = { "iron-ore", "copper-ore", "stone", "coal" }
table_shuffle(ores)
for i = 1, 4, 1 do
if count_nearby_ore(surface, position, ores[i]) < 200000 then
for _, vector in pairs(resource_vectors[i]) do
local p = { position.x + vector[1], position.y + vector[2] }
p = surface.find_non_colliding_position(ores[i], p, 64, 1)
if p then
surface.create_entity({ name = ores[i], position = p, amount = ore_amount })
end
end
end
end
-- starter chests
for _, item_stack in pairs(starter_supplies) do
local m1 = -8 + math_random(0, 16)
local m2 = -8 + math_random(0, 16)
local p = { position.x + m1, position.y + m2 }
p = surface.find_non_colliding_position("wooden-chest", p, 64, 1)
if p then
local e = surface.create_entity({ name = "wooden-chest", position = p, force = player_name })
local inventory = e.get_inventory(defines.inventory.chest)
inventory.insert(item_stack)
end
end
local vector_indexes = { 1, 2, 3, 4 }
table_shuffle(vector_indexes)
-- trees
--local tree = "tree-0" .. math_random(1, 9)
--for _, vector in pairs(additional_resource_vectors[vector_indexes[1]]) do
-- if math_random(1, 6) == 1 then
-- local p = {position.x + vector[1], position.y + vector[2]}
-- p = surface.find_non_colliding_position(tree, p, 64, 1)
-- if p then
-- surface.create_entity({name = tree, position = p})
-- end
-- end
--end
--local area = {{position.x - town_radius * 1.5, position.y - town_radius * 1.5}, {position.x + town_radius * 1.5, position.y + town_radius * 1.5}}
-- pond
for _, vector in pairs(additional_resource_vectors[vector_indexes[2]]) do
local x = position.x + vector[1]
local y = position.y + vector[2]
local p = { x = x, y = y }
if surface.get_tile(p).name ~= "out-of-map" then
surface.set_tiles({ { name = "water-green", position = p } })
end
end
-- fish
for _, vector in pairs(additional_resource_vectors[vector_indexes[2]]) do
local x = position.x + vector[1] + 0.5
local y = position.y + vector[2] + 0.5
local p = { x = x, y = y }
if math_random(1, 5) == 1 then
if surface.can_place_entity({ name = "fish", position = p }) then
surface.create_entity({ name = "water-splash", position = p })
surface.create_entity({ name = "fish", position = p })
end
end
end
-- uranium ore
--if count_nearby_ore(surface, position, "uranium-ore") < 100000 then
-- for _, vector in pairs(additional_resource_vectors[vector_indexes[3]]) do
-- local p = {position.x + vector[1], position.y + vector[2]}
-- p = surface.find_non_colliding_position("uranium-ore", p, 64, 1)
-- if p then
-- surface.create_entity({name = "uranium-ore", position = p, amount = ore_amount * 2})
-- end
-- end
--end
-- oil patches
--local vectors = additional_resource_vectors[vector_indexes[4]]
--for _ = 1, 3, 1 do
-- local vector = vectors[math_random(1, #vectors)]
-- local p = {position.x + vector[1], position.y + vector[2]}
-- p = surface.find_non_colliding_position("crude-oil", p, 64, 1)
-- if p then
-- surface.create_entity({name = "crude-oil", position = p, amount = 500000})
-- end
--end
end
local function is_valid_location(surface, position)
local ffatable = Table.get_table()
if not surface.can_place_entity({ name = "market", position = position }) then
surface.create_entity({
name = "flying-text",
position = position,
text = "Position is obstructed - no room for market!",
color = { r = 0.77, g = 0.0, b = 0.0 }
})
return false
end
for _, vector in pairs(town_wall_vectors) do
local p = { x = math_floor(position.x + vector[1]), y = math_floor(position.y + vector[2]) }
local tile = surface.get_tile(p.x, p.y)
if tile.name == "out-of-map" then
surface.create_entity({
name = "flying-text",
position = position,
text = "Town would be off-map!",
color = { r = 0.77, g = 0.0, b = 0.0 }
})
return false
end
end
if ffatable.size_of_town_centers > 48 then
surface.create_entity({
name = "flying-text",
position = position,
text = "Too many town centers on the map!",
color = { r = 0.77, g = 0.0, b = 0.0 }
})
return false
end
if Building.near_town(position, surface, radius_between_towns) then
surface.create_entity({
name = "flying-text",
position = position,
text = "Town location is too close to another town center!",
color = { r = 0.77, g = 0.0, b = 0.0 }
})
return false
end
local area = { { position.x - town_radius, position.y - town_radius }, { position.x + town_radius, position.y + town_radius } }
local count = 0
for _, e in pairs(surface.find_entities_filtered({ area = area })) do
if e.force.name == "enemy" then
count = count + 1
end
end
if count > 1 then
surface.create_entity({
name = "flying-text",
position = position,
text = "I got a bad feeling about this! There are enemies nearby.",
color = { r = 0.77, g = 0.0, b = 0.0 }
})
end
return true
end
function Public.set_market_health(entity, final_damage_amount)
local ffatable = Table.get_table()
local town_center = ffatable.town_centers[entity.force.name]
town_center.health = math_floor(town_center.health - final_damage_amount)
if town_center.health > town_center.max_health then town_center.health = town_center.max_health end
local m = town_center.health / town_center.max_health
entity.health = 150 * m
rendering.set_text(town_center.health_text, "HP: " .. town_center.health .. " / " .. town_center.max_health)
end
function Public.update_coin_balance(force)
local ffatable = Table.get_table()
local town_center = ffatable.town_centers[force.name]
rendering.set_text(town_center.coins_text, "Coins: " .. town_center.coin_balance)
end
local function is_color_used(color, town_centers)
for _, center in pairs(town_centers) do
if center.color then
if center.color.r == color.r and center.color.g == color.g and center.color.b == color.b then return true end
end
end
end
local function get_color()
local ffatable = Table.get_table()
local town_centers = ffatable.town_centers
local c
local shuffle_index = {}
for i = 1, #colors, 1 do shuffle_index[i] = i end
table_shuffle(shuffle_index)
for i = 1, #colors, 1 do
c = { r = colors[shuffle_index[i]][1], g = colors[shuffle_index[i]][2], b = colors[shuffle_index[i]][3], }
if not is_color_used(c, town_centers) then return c end
end
return c
end
local function found_town(event)
local entity = event.created_entity
if entity == nil or not entity.valid then return true end -- cancel, not a valid entity placed
if entity.name ~= "stone-furnace" then return false end -- cancel, player did not place a stone-furnace
local player = game.players[event.player_index]
if player.force ~= game.forces.player and player.force ~= game.forces["rogue"] then return false end -- cancel, player is in a team already
local force_name = tostring(player.name)
if game.forces[force_name] then return end -- cancel, player is mayor of town
if Team.has_key(player) == false then return false end -- cancel, player has already placed a town
local surface = entity.surface
local ffatable = Table.get_table()
if ffatable.cooldowns_town_placement[player.index] then
if game.tick < ffatable.cooldowns_town_placement[player.index] then
surface.create_entity({
name = "flying-text",
position = entity.position,
text = "Town founding is on cooldown for " .. math.ceil((ffatable.cooldowns_town_placement[player.index] - game.tick) / 3600) .. " minutes.",
color = { r = 0.77, g = 0.0, b = 0.0 }
})
player.insert({ name = "stone-furnace", count = 1 })
entity.destroy()
return true
end
end
local position = entity.position
entity.destroy()
if not is_valid_location(surface, position) then
player.insert({ name = "stone-furnace", count = 1 })
return true
end
Team.add_new_force(force_name)
ffatable.town_centers[force_name] = {}
local town_center = ffatable.town_centers[force_name]
town_center.market = surface.create_entity({ name = "market", position = position, force = force_name })
town_center.chunk_position = { math.floor(town_center.market.position.x / 32), math.floor(town_center.market.position.y / 32) }
town_center.max_health = 1000
town_center.coin_balance = 0
town_center.input_buffer = {}
town_center.output_buffer = {}
town_center.health = town_center.max_health
town_center.color = get_color()
town_center.research_counter = 1
town_center.upgrades = {}
town_center.upgrades.mining_prod = 0
town_center.upgrades.laser_turret = {}
town_center.upgrades.laser_turret.slots = 0
town_center.upgrades.laser_turret.locations = {}
town_center.evolution = {}
town_center.evolution.biters = 0
town_center.evolution.spitters = 0
town_center.evolution.worms = 0
town_center.coins_text = rendering.draw_text {
text = "Coins: " .. town_center.coin_balance,
surface = surface,
target = town_center.market,
target_offset = { 0, -2.75 },
color = { 200, 200, 200 },
scale = 1.00,
font = "default-game",
alignment = "center",
scale_with_zoom = false
}
town_center.health_text = rendering.draw_text {
text = "HP: " .. town_center.health .. " / " .. town_center.max_health,
surface = surface,
target = town_center.market,
target_offset = { 0, -3.25 },
color = { 200, 200, 200 },
scale = 1.00,
font = "default-game",
alignment = "center",
scale_with_zoom = false
}
town_center.town_caption = rendering.draw_text {
text = player.name .. "'s Town",
surface = surface,
target = town_center.market,
target_offset = { 0, -4.25 },
color = town_center.color,
scale = 1.30,
font = "default-game",
alignment = "center",
scale_with_zoom = false
}
ffatable.size_of_town_centers = ffatable.size_of_town_centers + 1
draw_town_spawn(force_name)
Team.add_player_to_town(player, town_center)
Team.add_chart_tag(game.forces.player, town_center.market)
local force = player.force
-- set the spawn point
local pos = { x = town_center.market.position.x, y = town_center.market.position.y + 4 }
--log("setting spawn point = {" .. spawn_point.x .. "," .. spawn_point.y .. "}")
force.set_spawn_position(pos, surface)
ffatable.spawn_point[player.name] = pos
ffatable.cooldowns_town_placement[player.index] = game.tick + 3600 * 15
Team.remove_key(player)
game.print(">> " .. player.name .. " has founded a new town!", { 255, 255, 0 })
return true
end
local function on_built_entity(event)
found_town(event)
end
local function on_player_repaired_entity(event)
local entity = event.entity
if entity.name == "market" then
Public.set_market_health(entity, -4)
end
end
--local function on_robot_repaired_entity(event)
-- local entity = event.entity
-- if entity.name == "market" then
-- Public.set_market_health(entity, -4)
-- end
--end
local function on_entity_damaged(event)
local entity = event.entity
if not entity.valid then return end
if entity.name == "market" then
Public.set_market_health(entity, event.final_damage_amount)
end
end
local on_init = function ()
local ffatable = Table.get_table()
ffatable.town_centers = {}
ffatable.size_of_town_centers = 0
ffatable.cooldowns_town_placement = {}
end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.add(defines.events.on_built_entity, on_built_entity)
Event.add(defines.events.on_player_repaired_entity, on_player_repaired_entity)
--Event.add(defines.events.on_robot_repaired_entity, on_robot_repaired_entity)
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
return Public

View File

@ -0,0 +1,176 @@
--Towny balance things by Gerkiz --
local player_ammo_starting_modifiers = {
['artillery-shell'] = -0.75,
['biological'] = -0.5,
['bullet'] = -0.25,
['cannon-shell'] = -0.75,
['capsule'] = -0.5,
['combat-robot-beam'] = -0.5,
['combat-robot-laser'] = -0.5,
['electric'] = -0.5,
['flamethrower'] = -0.75,
['grenade'] = -0.5,
['landmine'] = -0.33,
['laser-turret'] = -0.75,
['melee'] = 2,
['railgun'] = 1,
['rocket'] = -0.75,
['shotgun-shell'] = -0.20
}
local player_gun_speed_modifiers = {
['artillery-shell'] = -0.75,
['biological'] = -0.5,
['bullet'] = -0.55,
['cannon-shell'] = -0.75,
['capsule'] = -0.5,
['combat-robot-beam'] = -0.5,
['combat-robot-laser'] = -0.5,
['electric'] = -0.5,
['flamethrower'] = -0.75,
['grenade'] = -0.5,
['landmine'] = -0.33,
['laser-turret'] = -0.75,
['melee'] = 1,
['railgun'] = 0,
['rocket'] = -0.75,
['shotgun-shell'] = -0.50
}
local player_ammo_research_modifiers = {
['artillery-shell'] = -0.75,
['biological'] = -0.5,
['bullet'] = -0.5,
['cannon-shell'] = -0.85,
['capsule'] = -0.5,
['combat-robot-beam'] = -0.5,
['combat-robot-laser'] = -0.5,
['electric'] = -0.6,
['flamethrower'] = -0.75,
['grenade'] = -0.5,
['landmine'] = -0.5,
['laser-turret'] = -0.75,
['melee'] = -0.5,
['railgun'] = -0.5,
['rocket'] = -0.5,
['shotgun-shell'] = -0.20
}
local player_turrets_research_modifiers = {
['gun-turret'] = -0.75,
['laser-turret'] = -0.75,
['flamethrower-turret'] = -0.75
}
local enemy_ammo_starting_modifiers = {
['artillery-shell'] = 0,
['biological'] = 0,
['bullet'] = 0,
['cannon-shell'] = 0,
['capsule'] = 0,
['combat-robot-beam'] = 0,
['combat-robot-laser'] = 0,
['electric'] = 0,
['flamethrower'] = 0,
['grenade'] = 0,
['landmine'] = 0,
['laser-turret'] = 0,
['melee'] = 0,
['railgun'] = 0,
['rocket'] = 0,
['shotgun-shell'] = 0
}
local enemy_ammo_evolution_modifiers = {
['artillery-shell'] = 1,
['biological'] = 2,
['bullet'] = 1,
--['cannon-shell'] = 1,
--['capsule'] = 1,
--['combat-robot-beam'] = 1,
--['combat-robot-laser'] = 1,
--['electric'] = 1,
['flamethrower'] = 2,
--['grenade'] = 1,
--['landmine'] = 1,
['laser-turret'] = 2,
['melee'] = 2
--['railgun'] = 1,
--['rocket'] = 1,
--['shotgun-shell'] = 1
}
function init_player_weapon_damage(force)
for k, v in pairs(player_ammo_starting_modifiers) do
force.set_ammo_damage_modifier(k, v)
end
for k, v in pairs(player_gun_speed_modifiers) do
force.set_gun_speed_modifier(k, v)
end
end
function init_enemy_weapon_damage()
local e_force = game.forces["enemy"]
for k, v in pairs(enemy_ammo_starting_modifiers) do
e_force.set_ammo_damage_modifier(k, v)
end
end
local function enemy_weapon_damage()
local f = game.forces.enemy
local ef = f.evolution_factor
for k, v in pairs(enemy_ammo_evolution_modifiers) do
local base = enemy_ammo_starting_modifiers[k]
local new = base + v * ef
f.set_ammo_damage_modifier(k, new)
end
end
local function research_finished(event)
local r = event.research
local p_force = r.force
for _, e in ipairs(r.effects) do
local t = e.type
if t == 'ammo-damage' then
local category = e.ammo_category
local factor = player_ammo_research_modifiers[category]
if factor then
local current_m = p_force.get_ammo_damage_modifier(category)
local m = e.modifier
p_force.set_ammo_damage_modifier(category, current_m + factor * m)
end
elseif t == 'turret-attack' then
local category = e.turret_id
local factor = player_turrets_research_modifiers[category]
if factor then
local current_m = p_force.get_turret_attack_modifier(category)
local m = e.modifier
p_force.set_turret_attack_modifier(category, current_m + factor * m)
end
elseif t == 'gun-speed' then
local category = e.ammo_category
local factor = player_gun_speed_modifiers[category]
if factor then
local current_m = p_force.get_gun_speed_modifier(category)
local m = e.modifier
p_force.set_gun_speed_modifier(category, current_m + factor * m)
end
end
end
end
local Event = require 'utils.event'
Event.on_init(init_enemy_weapon_damage)
Event.on_nth_tick(18000, enemy_weapon_damage)
Event.add(defines.events.on_research_finished, research_finished)

View File

@ -0,0 +1,37 @@
local math_random = math.random
local Evolution = require "modules.scrap_towny_ffa.evolution"
local Building = require "modules.scrap_towny_ffa.building"
local Scrap = require "modules.scrap_towny_ffa.scrap"
local unearthing_worm = require "modules.scrap_towny_ffa.unearthing_worm"
local unearthing_biters = require "modules.scrap_towny_ffa.unearthing_biters"
local tick_tack_trap = require "modules.scrap_towny_ffa.tick_tack_trap"
local function trap(entity)
-- check if within 32 blocks of market
if entity.type == "tree" or Scrap.is_scrap(entity) then
if math_random(1, 1024) == 1 then
if not Building.near_town(entity.position, entity.surface, 32) then
tick_tack_trap(entity.surface, entity.position)
return
end
end
if math_random(1, 256) == 1 then
if not Building.near_town(entity.position, entity.surface, 32) then
unearthing_worm(entity.surface, entity.position, Evolution.get_worm_evolution(entity))
end
end
if math_random(1, 128) == 1 then
if not Building.near_town(entity.position, entity.surface, 32) then
unearthing_biters(entity.surface, entity.position, math_random(4, 8), Evolution.get_biter_evolution(entity))
end
end
end
end
local function on_player_mined_entity(event)
local entity = event.entity
trap(entity)
end
local Event = require 'utils.event'
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)

View File

@ -0,0 +1,17 @@
local math_random = math.random
local math_min = math.min
local function on_entity_died(event)
local entity = event.entity
local surface = entity.surface
if entity.type == "ammo-turret" and entity.force.name == "enemy" then
local min = math_min(entity.get_item_count("piercing-rounds-magazine"), 20)
if min > 0 then
surface.spill_item_stack(entity.position, { name = "piercing-rounds-magazine", count = math_random(1, min) }, true)
end
end
end
local Event = require 'utils.event'
Event.add(defines.events.on_entity_died, on_entity_died)

View File

@ -0,0 +1,84 @@
local math_random = math.random
local Table = require 'modules.scrap_towny_ffa.table'
local function create_particles(surface, position, amount)
if not surface.valid then return end
for _ = 1, amount, 1 do
local m = math_random(6, 12)
local m2 = m * 0.005
surface.create_particle({
name = "stone-particle",
position = position,
frame_speed = 0.1,
vertical_speed = 0.1,
height = 0.1,
movement = { m2 - (math_random(0, m) * 0.01), m2 - (math_random(0, m) * 0.01) }
})
end
end
local function spawn_biter(surface, position, evolution)
if not surface.valid then return end
local evo = math.floor(evolution * 1000)
local biter_chances = {
{ name = "small-biter", chance = math.floor(1000 - (evo * 1.6)) },
{ name = "small-spitter", chance = math.floor(500 - evo * 0.8) },
{ name = "medium-biter", chance = -150 + evo },
{ name = "medium-spitter", chance = -75 + math.floor(evo * 0.5) },
{ name = "big-biter", chance = math.floor((evo - 500) * 3) },
{ name = "big-spitter", chance = math.floor((evo - 500) * 2) },
{ name = "behemoth-biter", chance = math.floor((evo - 800) * 6) },
{ name = "behemoth-spitter", chance = math.floor((evo - 800) * 4) }
}
local max_chance = 0
for i = 1, 8, 1 do
if biter_chances[i].chance < 0 then biter_chances[i].chance = 0 end
max_chance = max_chance + biter_chances[i].chance
end
local r = math_random(1, max_chance)
local current_chance = 0
for i = 1, 8, 1 do
current_chance = current_chance + biter_chances[i].chance
if r <= current_chance then
local biter_name = biter_chances[i].name
local p = surface.find_non_colliding_position(biter_name, position, 10, 1)
if not p then return end
surface.create_entity({ name = biter_name, position = p, force = "enemy" })
return
end
end
end
local function unearthing_biters(surface, position, amount, relative_evolution)
local ffatable = Table.get_table()
if not surface then return end
if not position then return end
if not position.x then return end
if not position.y then return end
local ticks = amount * 30
ticks = ticks + 90
for t = 1, ticks, 1 do
if not ffatable.on_tick_schedule[game.tick + t] then ffatable.on_tick_schedule[game.tick + t] = {} end
ffatable.on_tick_schedule[game.tick + t][#ffatable.on_tick_schedule[game.tick + t] + 1] = {
func = create_particles,
args = { surface, { x = position.x, y = position.y }, 4 }
}
if t > 90 then
if t % 30 == 29 then
ffatable.on_tick_schedule[game.tick + t][#ffatable.on_tick_schedule[game.tick + t] + 1] = {
func = spawn_biter,
args = { surface, { x = position.x, y = position.y }, relative_evolution }
}
end
end
end
end
return unearthing_biters

View File

@ -0,0 +1,69 @@
local math_random = math.random
local math_ceil = math.ceil
local Table = require 'modules.scrap_towny_ffa.table'
local function create_particles(surface, position, amount)
if not surface.valid then return end
for _ = 1, amount, 1 do
local m = math_random(8, 24)
local m2 = m * 0.005
surface.create_particle({
name = "stone-particle",
position = position,
frame_speed = 0.1,
vertical_speed = 0.1,
height = 0.1,
movement = { m2 - (math_random(0, m) * 0.01), m2 - (math_random(0, m) * 0.01) }
})
end
end
local function spawn_worm(surface, position, evolution_index)
if not surface.valid then return end
local worm_raffle_table = {
[1] = { "small-worm-turret", "small-worm-turret", "small-worm-turret", "small-worm-turret", "small-worm-turret", "small-worm-turret" },
[2] = { "small-worm-turret", "small-worm-turret", "small-worm-turret", "small-worm-turret", "small-worm-turret", "medium-worm-turret" },
[3] = { "small-worm-turret", "small-worm-turret", "small-worm-turret", "small-worm-turret", "medium-worm-turret", "medium-worm-turret" },
[4] = { "small-worm-turret", "small-worm-turret", "small-worm-turret", "medium-worm-turret", "medium-worm-turret", "medium-worm-turret" },
[5] = { "small-worm-turret", "small-worm-turret", "medium-worm-turret", "medium-worm-turret", "medium-worm-turret", "big-worm-turret" },
[6] = { "small-worm-turret", "medium-worm-turret", "medium-worm-turret", "medium-worm-turret", "medium-worm-turret", "big-worm-turret" },
[7] = { "medium-worm-turret", "medium-worm-turret", "medium-worm-turret", "medium-worm-turret", "big-worm-turret", "big-worm-turret" },
[8] = { "medium-worm-turret", "medium-worm-turret", "medium-worm-turret", "medium-worm-turret", "big-worm-turret", "big-worm-turret" },
[9] = { "medium-worm-turret", "medium-worm-turret", "medium-worm-turret", "big-worm-turret", "big-worm-turret", "big-worm-turret" },
[10] = { "medium-worm-turret", "medium-worm-turret", "medium-worm-turret", "big-worm-turret", "big-worm-turret", "big-worm-turret" }
}
local raffle = worm_raffle_table[evolution_index]
local worm_name = raffle[math_random(1, #raffle)]
surface.create_entity({ name = worm_name, position = position })
end
local function unearthing_worm(surface, position, relative_evolution)
local ffatable = Table.get_table()
if not surface then return end
if not position then return end
if not position.x then return end
if not position.y then return end
local evolution_index = math.ceil(relative_evolution * 10)
if evolution_index < 1 then evolution_index = 1 end
for t = 1, 330, 1 do
if not ffatable.on_tick_schedule[game.tick + t] then ffatable.on_tick_schedule[game.tick + t] = {} end
ffatable.on_tick_schedule[game.tick + t][#ffatable.on_tick_schedule[game.tick + t] + 1] = {
func = create_particles,
args = { surface, { x = position.x, y = position.y }, math_ceil(t * 0.05) }
}
if t == 330 then
ffatable.on_tick_schedule[game.tick + t][#ffatable.on_tick_schedule[game.tick + t] + 1] = {
func = spawn_worm,
args = { surface, { x = position.x, y = position.y }, evolution_index }
}
end
end
end
return unearthing_worm

View File

@ -0,0 +1,159 @@
--wreckage yields scrap
local table_insert = table.insert
local Scrap = require 'modules.scrap_towny_ffa.scrap'
-- loot chances and amounts for scrap entities
local entity_loot_chance = {
{name = "advanced-circuit", chance = 5},
--{name = "artillery-shell", chance = 1},
{name = "battery", chance = 20},
{name = "cannon-shell", chance = 2},
--{name = "cluster-grenade", chance = 2},
{name = "construction-robot", chance = 1},
{name = "copper-cable", chance = 250},
{name = "copper-plate", chance = 500},
{name = "crude-oil-barrel", chance = 30},
{name = "defender-capsule", chance = 5},
{name = "destroyer-capsule", chance = 1},
{name = "distractor-capsule", chance = 2},
{name = "electric-engine-unit", chance = 2},
{name = "electronic-circuit", chance = 200},
{name = "empty-barrel", chance = 10},
{name = "engine-unit", chance = 4},
{name = "explosive-cannon-shell", chance = 2},
--{name = "explosive-rocket", chance = 3},
--{name = "explosive-uranium-cannon-shell", chance = 1},
{name = "explosives", chance = 5},
{name = "green-wire", chance = 10},
{name = "grenade", chance = 10},
{name = "heat-pipe", chance = 1},
{name = "heavy-oil-barrel", chance = 15},
{name = "iron-gear-wheel", chance = 500},
{name = "iron-plate", chance = 750},
{name = "iron-stick", chance = 50},
{name = "land-mine", chance = 3},
{name = "light-oil-barrel", chance = 15},
{name = "logistic-robot", chance = 1},
{name = "low-density-structure", chance = 1},
{name = "lubricant-barrel", chance = 20},
--{name = "nuclear-fuel", chance = 1},
{name = "petroleum-gas-barrel", chance = 15},
{name = "pipe", chance = 100},
{name = "pipe-to-ground", chance = 10},
{name = "plastic-bar", chance = 5},
{name = "processing-unit", chance = 2},
{name = "red-wire", chance = 10},
--{name = "rocket", chance = 3},
--{name = "rocket-control-unit", chance = 1},
--{name = "rocket-fuel", chance = 3},
{name = "solid-fuel", chance = 100},
{name = "steel-plate", chance = 150},
{name = "sulfuric-acid-barrel", chance = 15},
--{name = "uranium-cannon-shell", chance = 1},
--{name = "uranium-fuel-cell", chance = 1},
--{name = "used-up-uranium-fuel-cell", chance = 1},
{name = "water-barrel", chance = 10},
{name = "tank", chance = 1},
{name = "car", chance = 1}
}
local entity_loot_amounts = {
["advanced-circuit"] = 2,
--["artillery-shell"] = 0.3,
["battery"] = 2,
["cannon-shell"] = 2,
--["cluster-grenade"] = 0.3,
["construction-robot"] = 0.3,
["copper-cable"] = 24,
["copper-plate"] = 16,
["crude-oil-barrel"] = 3,
["defender-capsule"] = 2,
["destroyer-capsule"] = 0.3,
["distractor-capsule"] = 0.3,
["electric-engine-unit"] = 2,
["electronic-circuit"] = 8,
["empty-barrel"] = 3,
["engine-unit"] = 2,
["explosive-cannon-shell"] = 2,
--["explosive-rocket"] = 2,
--["explosive-uranium-cannon-shell"] = 2,
["explosives"] = 4,
["green-wire"] = 8,
["grenade"] = 2,
["heat-pipe"] = 1,
["heavy-oil-barrel"] = 3,
["iron-gear-wheel"] = 8,
["iron-plate"] = 16,
["iron-stick"] = 16,
["land-mine"] = 1,
["light-oil-barrel"] = 3,
["logistic-robot"] = 0.3,
["low-density-structure"] = 0.3,
["lubricant-barrel"] = 3,
--["nuclear-fuel"] = 0.1,
["petroleum-gas-barrel"] = 3,
["pipe"] = 8,
["pipe-to-ground"] = 1,
["plastic-bar"] = 4,
["processing-unit"] = 1,
["red-wire"] = 8,
--["rocket"] = 2,
--["rocket-control-unit"] = 0.3,
--["rocket-fuel"] = 0.3,
["solid-fuel"] = 4,
["steel-plate"] = 4,
["sulfuric-acid-barrel"] = 3,
--["uranium-cannon-shell"] = 2,
--["uranium-fuel-cell"] = 0.3,
--["used-up-uranium-fuel-cell"] = 1,
["water-barrel"] = 3,
["tank"] = 1,
["car"] = 1,
}
local scrap_raffle = {}
for _, t in pairs (entity_loot_chance) do
for _ = 1, t.chance, 1 do
table_insert(scrap_raffle, t.name)
end
end
local size_of_scrap_raffle = #scrap_raffle
local function on_player_mined_entity(event)
local entity = event.entity
if not entity.valid then return end
local position = entity.position
if Scrap.is_scrap(entity) == false then return end
if entity.name == 'crash-site-chest-1' or entity.name == 'crash-site-chest-2' then return end
-- scrap entities drop loot
event.buffer.clear()
local scrap = scrap_raffle[math.random(1, size_of_scrap_raffle)]
local amount_bonus = (game.forces.enemy.evolution_factor * 2) + (game.forces.player.mining_drill_productivity_bonus * 2)
local r1 = math.ceil(entity_loot_amounts[scrap] * (0.3 + (amount_bonus * 0.3)))
local r2 = math.ceil(entity_loot_amounts[scrap] * (1.7 + (amount_bonus * 1.7)))
local amount = math.random(r1, r2)
local player = game.players[event.player_index]
local inserted_count = player.insert({name = scrap, count = amount})
if inserted_count ~= amount then
local amount_to_spill = amount - inserted_count
entity.surface.spill_item_stack(position, {name = scrap, count = amount_to_spill}, true)
end
entity.surface.create_entity({
name = "flying-text",
position = position,
text = "+" .. amount .. " [img=item/" .. scrap .. "]",
color = {r=0.98, g=0.66, b=0.22}
})
end
local Event = require 'utils.event'
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)

View File

@ -1,4 +1,5 @@
local WD = require 'modules.wave_defense.table'
local BiterHealthBooster = require 'modules.biter_health_booster_v2'
local function create_gui(player)
local frame = player.gui.top.add({type = 'frame', name = 'wave_defense'})
@ -68,8 +69,9 @@ local function update_gui(player)
end
local gui = player.gui.top.wave_defense
local biter_health_boost = 1
if global.biter_health_boost then
biter_health_boost = global.biter_health_boost
local biter_health_boosts = BiterHealthBooster.get('biter_health_boost')
if biter_health_boost then
biter_health_boost = biter_health_boosts
end
local wave_number = WD.get('wave_number')

View File

@ -1,5 +1,5 @@
local Event = require 'utils.event'
local BiterHealthBooster = require 'modules.biter_health_booster'
local BiterHealthBooster = require 'modules.biter_health_booster_v2'
local BiterRolls = require 'modules.wave_defense.biter_rolls'
local SideTargets = require 'modules.wave_defense.side_targets'
local ThreatEvent = require 'modules.wave_defense.threat_events'
@ -238,7 +238,8 @@ local function refresh_active_unit_threat()
active_biters[k] = nil
end
end
WD.set('active_biter_threat', math_round(biter_threat * global.biter_health_boost, 2))
local biter_health_boost = BiterHealthBooster.get('biter_health_boost')
WD.set('active_biter_threat', math_round(biter_threat * biter_health_boost, 2))
debug_print('refresh_active_unit_threat - new value ' .. active_biter_threat)
end
@ -251,12 +252,14 @@ local function time_out_biters()
WD.set('active_biter_count', 50)
end
local biter_health_boost = BiterHealthBooster.get('biter_health_boost')
for k, biter in pairs(active_biters) do
if not is_unit_valid(biter) then
WD.set('active_biter_count', active_biter_count - 1)
if biter.entity then
if biter.entity.valid then
WD.set('active_biter_threat', active_biter_threat - math_round(threat_values[biter.entity.name] * global.biter_health_boost, 2))
WD.set('active_biter_threat', active_biter_threat - math_round(threat_values[biter.entity.name] * biter_health_boost, 2))
if biter.entity.force.index == 2 then
biter.entity.destroy()
end
@ -373,7 +376,7 @@ local function set_enemy_evolution()
end
--damage_increase = math_round(damage_increase + threat * 0.0000025, 3)
global.biter_health_boost = biter_h_boost
BiterHealthBooster.set('biter_health_boost', biter_h_boost)
--game.forces.enemy.set_ammo_damage_modifier("melee", damage_increase)
--game.forces.enemy.set_ammo_damage_modifier("biological", damage_increase)
game.forces.enemy.evolution_factor = evolution_factor
@ -440,7 +443,7 @@ local function spawn_biter(surface, is_boss_biter)
end
end
local boosted_health = global.biter_health_boost
local boosted_health = BiterHealthBooster.get('biter_health_boost')
local name
if math_random(1, 100) > 73 then
@ -455,26 +458,25 @@ local function spawn_biter(surface, is_boss_biter)
biter.ai_settings.allow_try_return_to_spawner = true
biter.ai_settings.do_separation = true
local increase_health_per_wave = WD.get('increase_health_per_wave')
if increase_health_per_wave and not is_boss_biter then
local modified_unit_health = WD.get('modified_unit_health')
BiterHealthBooster.add_unit(biter, modified_unit_health)
end
if is_boss_biter then
local modified_boss_health = WD.get('modified_boss_health')
if modified_boss_health then
local wave_number = WD.get('wave_number')
if boosted_health == 1 then
boosted_health = 1.25
end
boosted_health = boosted_health * (wave_number * 0.04)
local sum = boosted_health * 5
debug_print('Boss Health Boosted: ' .. sum)
if sum >= 150 then
sum = 150
end
BiterHealthBooster.add_boss_unit(biter, sum, 0.55)
local increase_boss_health_per_wave = WD.get('increase_boss_health_per_wave')
if increase_boss_health_per_wave then
local modified_boss_unit_health = WD.get('modified_boss_unit_health')
BiterHealthBooster.add_boss_unit(biter, modified_boss_unit_health, 0.55)
else
local sum = boosted_health * 5
debug_print('Boss Health Boosted: ' .. sum)
BiterHealthBooster.add_boss_unit(biter, sum, 0.55)
end
end
WD.set('active_biters')[biter.unit_number] = {entity = biter, spawn_tick = game.tick}
local active_biter_count = WD.get('active_biter_count')
WD.set('active_biter_count', active_biter_count + 1)
@ -509,6 +511,37 @@ local function increase_biter_damage()
e.set_ammo_damage_modifier('biological', new + e_old_biological)
end
local function increase_biters_health()
local increase_health_per_wave = WD.get('increase_health_per_wave')
if not increase_health_per_wave then
return
end
local boosted_health = BiterHealthBooster.get('biter_health_boost')
local wave_number = WD.get('wave_number')
-- this sets normal units health
local modified_unit_health = WD.get('modified_unit_health')
if modified_unit_health > 30 then
modified_unit_health = 30
end
debug_print('[HEALTHBOOSTER] > Normal Units Health Boosted: ' .. modified_unit_health)
WD.set('modified_unit_health', modified_unit_health + 0.02)
-- this sets boss units health
if boosted_health == 1 then
boosted_health = 1.20
end
boosted_health = boosted_health * (wave_number * 0.03)
local sum = boosted_health * 4
debug_print('[HEALTHBOOSTER] > Boss Health Boosted: ' .. sum)
if sum >= 100 then
sum = 100
end
WD.set('modified_boss_unit_health', sum)
end
local function set_next_wave()
local wave_number = WD.get('wave_number')
WD.set('wave_number', wave_number + 1)
@ -521,6 +554,7 @@ local function set_next_wave()
end
if wave_number % 25 == 0 then
increase_biter_damage()
increase_biters_health()
WD.set('boss_wave', true)
WD.set('boss_wave_warning', true)
local alert_boss_wave = WD.get('alert_boss_wave')

View File

@ -15,6 +15,7 @@ function Public.debug_module()
this.next_wave = 1000
this.wave_interval = 500
this.wave_enforced = true
this.debug = true
end
function Public.reset_wave_defense()
@ -70,10 +71,12 @@ function Public.reset_wave_defense()
this.enable_threat_log = true
this.disable_threat_below_zero = false
this.check_collapse_position = true
this.modified_boss_health = true
this.resolve_pathing = true
this.increase_damage_per_wave = false
this.increase_boss_health_per_wave = true
this.increase_health_per_wave = false
this.fill_tiles_so_biter_can_path = true
this.modified_unit_health = 1.02
end
function Public.get(key)
@ -150,6 +153,13 @@ function Public.remove_entities(boolean)
return this.remove_entities
end
function Public.increase_health_per_wave(boolean)
if (boolean or boolean == false) then
this.increase_health_per_wave = boolean
end
return this.increase_health_per_wave
end
function Public.enable_threat_log(boolean)
if (boolean or boolean == false) then
this.enable_threat_log = boolean
@ -171,11 +181,11 @@ function Public.enable_side_target(boolean)
return this.enable_side_target
end
function Public.modified_boss_health(boolean)
function Public.increase_boss_health_per_wave(boolean)
if (boolean or boolean == false) then
this.modified_boss_health = boolean
this.increase_boss_health_per_wave = boolean
end
return this.modified_boss_health
return this.increase_boss_health_per_wave
end
function Public.resolve_pathing(boolean)

View File

@ -2,6 +2,7 @@ local WD = require 'modules.wave_defense.table'
local threat_values = require 'modules.wave_defense.threat_values'
local Event = require 'utils.event'
local BiterRolls = require 'modules.wave_defense.biter_rolls'
local BiterHealthBooster = require 'modules.biter_health_booster_v2'
local math_random = math.random
local Public = {}
@ -13,8 +14,9 @@ local function remove_unit(entity)
return
end
local m = 1
if global.biter_health_boost_units[unit_number] then
m = 1 / global.biter_health_boost_units[unit_number][2]
local biter_health_boost_units = BiterHealthBooster.get('biter_health_boost_units')
if biter_health_boost_units[unit_number] then
m = 1 / biter_health_boost_units[unit_number][2]
end
local active_threat_loss = math.round(threat_values[entity.name] * m, 2)
local active_biter_threat = WD.get('active_biter_threat')
@ -230,6 +232,8 @@ local function on_entity_died(event)
end
local disable_threat_below_zero = WD.get('disable_threat_below_zero')
local biter_health_boost = BiterHealthBooster.get('biter_health_boost')
if entity.type == 'unit' then
--acid_nova(entity)
if not threat_values[entity.name] then
@ -241,11 +245,11 @@ local function on_entity_died(event)
WD.set('threat', 0)
threat = WD.get('threat')
end
WD.set('threat', math.round(threat - threat_values[entity.name] * global.biter_health_boost, 2))
WD.set('threat', math.round(threat - threat_values[entity.name] * biter_health_boost, 2))
remove_unit(entity)
else
local threat = WD.get('threat')
WD.set('threat', math.round(threat - threat_values[entity.name] * global.biter_health_boost, 2))
WD.set('threat', math.round(threat - threat_values[entity.name] * biter_health_boost, 2))
remove_unit(entity)
end
else
@ -253,7 +257,7 @@ local function on_entity_died(event)
if entity.health then
if threat_values[entity.name] then
local threat = WD.get('threat')
WD.set('threat', math.round(threat - threat_values[entity.name] * global.biter_health_boost, 2))
WD.set('threat', math.round(threat - threat_values[entity.name] * biter_health_boost, 2))
end
spawn_unit_spawner_inhabitants(entity)
end

View File

@ -0,0 +1,104 @@
local math_random = math.random
local Global = require 'utils.global'
local tick_schedule = {}
Global.register(
tick_schedule,
function(t)
tick_schedule = t
end
)
local death_animation_ticks = 120
local decay_ticks = 2
local worms = {
["small-worm-turret"] = { corpse="small-worm-corpse", patch_size = { min=30000, max=90000} },
["medium-worm-turret"] = { corpse="medium-worm-corpse", patch_size = { min=60000, max=120000 } },
["big-worm-turret"] = { corpse="big-worm-corpse", patch_size = { min=90000, max=300000 } },
["behemoth-worm-turret"] = { corpse="behemoth-worm-corpse", patch_size = { min=120000, max=600000 } }
}
local function destroy_worm(name, position, surface)
local entity = surface.find_entity(name, position)
if entity ~= nil and entity.valid then entity.destroy() end
local corpse = worms[name].corpse
local remains = surface.find_entity(corpse, position)
if remains ~= nil and remains.valid then
-- show an animation
if math_random(1,40) == 1 then surface.create_entity({name = "explosion", position = {x = position.x + (3 - (math_random(1,60) * 0.1)), y = position.y + (3 - (math_random(1,60) * 0.1))}}) end
if math_random(1,32) == 1 then surface.create_entity({name = "blood-explosion-huge", position = position}) end
if math_random(1,16) == 1 then surface.create_entity({name = "blood-explosion-big", position = position}) end
if math_random(1,8) == 1 then surface.create_entity({name = "blood-explosion-small", position = position}) end
end
end
local function remove_corpse(name, position, surface)
local corpse = worms[name].corpse
local remains = surface.find_entity(corpse, position)
if remains ~= nil and remains.valid then remains.destroy() end
end
-- place an oil patch at the worm location
local function create_oil_patch(name, position, surface)
local min = worms[name].patch_size.min
local max = worms[name].patch_size.max
surface.create_entity({name="crude-oil", position=position, amount=math_random(min,max)})
end
-- worms create oil patches when killed
local function process_worm(entity)
local name = entity.name
local position = entity.position
local surface = entity.surface
local tick1 = game.tick + death_animation_ticks
if not tick_schedule[tick1] then tick_schedule[tick1] = {} end
tick_schedule[tick1][#tick_schedule[tick1] + 1] = {
callback = 'destroy_worm',
params = {name, position, surface}
}
local tick2 = game.tick + death_animation_ticks + decay_ticks
if not tick_schedule[tick2] then tick_schedule[tick2] = {} end
tick_schedule[tick2][#tick_schedule[tick2] + 1] = {
callback = 'remove_corpse',
params = {name, position, surface}
}
if math_random(1,4) == 1 then
local tick3 = game.tick + death_animation_ticks + decay_ticks + 1
if not tick_schedule[tick3] then tick_schedule[tick3] = {} end
tick_schedule[tick3][#tick_schedule[tick3] + 1] = {
callback = 'create_oil_patch',
params = {name, position, surface}
}
end
end
local function on_entity_died(event)
local entity = event.entity
local test = {
["small-worm-turret"] = true,
["medium-worm-turret"] = true,
["big-worm-turret"] = true,
["behemoth-worm-turret"] = true
}
if test[entity.name] ~= nil then
process_worm(entity)
end
end
local function on_tick()
if not tick_schedule[game.tick] then return end
for _, token in pairs(tick_schedule[game.tick]) do
local callback = token.callback
local params = token.params
if callback == 'destroy_worm' then destroy_worm(params[1], params[2], params[3]) end
if callback == 'remove_corpse' then remove_corpse(params[1], params[2], params[3]) end
if callback == 'create_oil_patch' then create_oil_patch(params[1], params[2], params[3]) end
end
tick_schedule[game.tick] = nil
end
local Event = require 'utils.event'
Event.add(defines.events.on_tick, on_tick)
Event.add(defines.events.on_entity_died, on_entity_died)

View File

@ -0,0 +1,330 @@
local table_insert = table.insert
local math_random = math.random
local math_floor = math.floor
local math_abs = math.abs
local get_noise = require 'utils.get_noise'
local Scrap = require 'modules.scrap_towny_ffa.scrap'
require 'modules.no_deconstruction_of_neutral_entities'
local scrap_entities = {
-- simple entity
{name = "small-ship-wreck"}, -- these are not mineable normally
{name = "small-ship-wreck"}, -- these are not mineable normally
{name = "small-ship-wreck"}, -- these are not mineable normally
{name = "small-ship-wreck"}, -- these are not mineable normally
{name = "small-ship-wreck"}, -- these are not mineable normally
{name = "small-ship-wreck"}, -- these are not mineable normally
{name = "small-ship-wreck"}, -- these are not mineable normally
{name = "small-ship-wreck"}, -- these are not mineable normally
{name = "medium-ship-wreck"}, -- these are not mineable normally
{name = "medium-ship-wreck"}, -- these are not mineable normally
{name = "medium-ship-wreck"}, -- these are not mineable normally
{name = "medium-ship-wreck"}, -- these are not mineable normally
-- simple entity with owner
{name = "crash-site-spaceship-wreck-small-1"}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-small-1"}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-small-2"}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-small-3"}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-small-4"}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-small-5"}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-small-6"} -- these do not have mining animation
}
local scrap_entities_index = table.size(scrap_entities)
local scrap_containers = {
-- containers
{name = "big-ship-wreck-1", size = 3}, -- these are not mineable normally
{name = "big-ship-wreck-1", size = 3}, -- these are not mineable normally
{name = "big-ship-wreck-1", size = 3}, -- these are not mineable normally
{name = "big-ship-wreck-2", size = 3}, -- these are not mineable normally
{name = "big-ship-wreck-2", size = 3}, -- these are not mineable normally
{name = "big-ship-wreck-2", size = 3}, -- these are not mineable normally
{name = "big-ship-wreck-3", size = 3}, -- these are not mineable normally
{name = "big-ship-wreck-3", size = 3}, -- these are not mineable normally
{name = "big-ship-wreck-3", size = 3}, -- these are not mineable normally
{name = "crash-site-chest-1", size = 8}, -- these do not have mining animation
{name = "crash-site-chest-2", size = 8}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-medium-1", size = 1}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-medium-1", size = 1}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-medium-1", size = 1}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-medium-1", size = 1}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-medium-2", size = 1}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-medium-2", size = 1}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-medium-2", size = 1}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-medium-2", size = 1}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-medium-3", size = 1}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-medium-3", size = 1}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-medium-3", size = 1}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-medium-3", size = 1}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-big-1", size = 2}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-big-1", size = 2}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-big-1", size = 2}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-big-2", size = 2}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-big-2", size = 2}, -- these do not have mining animation
{name = "crash-site-spaceship-wreck-big-2", size = 2}, -- these do not have mining animation
}
local scrap_containers_index = table.size(scrap_containers)
-- loot chances and amounts for scrap containers
local container_loot_chance = {
{name = "advanced-circuit", chance = 5},
{name = "artillery-shell", chance = 1},
{name = "cannon-shell", chance = 2},
{name = "cliff-explosives", chance = 5},
--{name = "cluster-grenade", chance = 2},
{name = "construction-robot", chance = 1},
{name = "copper-cable", chance = 250},
{name = "copper-plate", chance = 500},
{name = "crude-oil-barrel", chance = 30},
{name = "defender-capsule", chance = 5},
{name = "destroyer-capsule", chance = 1},
{name = "distractor-capsule", chance = 2},
{name = "electric-engine-unit", chance = 2},
{name = "electronic-circuit", chance = 200},
{name = "empty-barrel", chance = 10},
{name = "engine-unit", chance = 7},
{name = "explosive-cannon-shell", chance = 2},
--{name = "explosive-rocket", chance = 3},
{name = "explosive-uranium-cannon-shell", chance = 1},
{name = "explosives", chance = 5},
{name = "green-wire", chance = 10},
{name = "grenade", chance = 10},
{name = "heat-pipe", chance = 1},
{name = "heavy-oil-barrel", chance = 15},
{name = "iron-gear-wheel", chance = 500},
{name = "iron-plate", chance = 750},
{name = "iron-stick", chance = 50},
{name = "land-mine", chance = 3},
{name = "light-oil-barrel", chance = 15},
{name = "logistic-robot", chance = 1},
{name = "low-density-structure", chance = 1},
{name = "lubricant-barrel", chance = 20},
{name = "nuclear-fuel", chance = 1},
{name = "petroleum-gas-barrel", chance = 15},
{name = "pipe", chance = 100},
{name = "pipe-to-ground", chance = 10},
{name = "plastic-bar", chance = 5},
{name = "processing-unit", chance = 2},
{name = "red-wire", chance = 10},
--{name = "rocket", chance = 3}, {name = "battery", chance = 20},
{name = "rocket-control-unit", chance = 1},
{name = "rocket-fuel", chance = 3},
{name = "solid-fuel", chance = 100},
{name = "steel-plate", chance = 150},
{name = "sulfuric-acid-barrel", chance = 15},
{name = "uranium-cannon-shell", chance = 1},
{name = "uranium-fuel-cell", chance = 1},
{name = "used-up-uranium-fuel-cell", chance = 1},
{name = "water-barrel", chance = 10}
}
local container_loot_amounts = {
["advanced-circuit"] = 2,
["artillery-shell"] = 0.3,
["battery"] = 2,
["cannon-shell"] = 2,
["cliff-explosives"] = 2,
--["cluster-grenade"] = 0.3,
["construction-robot"] = 0.3,
["copper-cable"] = 24,
["copper-plate"] = 16,
["crude-oil-barrel"] = 3,
["defender-capsule"] = 2,
["destroyer-capsule"] = 0.3,
["distractor-capsule"] = 0.3,
["electric-engine-unit"] = 2,
["electronic-circuit"] = 8,
["empty-barrel"] = 3,
["engine-unit"] = 2,
["explosive-cannon-shell"] = 2,
--["explosive-rocket"] = 2,
["explosive-uranium-cannon-shell"] = 2,
["explosives"] = 4,
["green-wire"] = 8,
["grenade"] = 2,
["heat-pipe"] = 1,
["heavy-oil-barrel"] = 3,
["iron-gear-wheel"] = 8,
["iron-plate"] = 16,
["iron-stick"] = 16,
["land-mine"] = 1,
["light-oil-barrel"] = 3,
["logistic-robot"] = 0.3,
["low-density-structure"] = 0.3,
["lubricant-barrel"] = 3,
["nuclear-fuel"] = 0.1,
["petroleum-gas-barrel"] = 3,
["pipe"] = 8,
["pipe-to-ground"] = 1,
["plastic-bar"] = 4,
["processing-unit"] = 1,
["red-wire"] = 8,
--["rocket"] = 2,
["rocket-control-unit"] = 0.3,
["rocket-fuel"] = 0.3,
["solid-fuel"] = 4,
["steel-plate"] = 4,
["sulfuric-acid-barrel"] = 3,
["uranium-cannon-shell"] = 2,
["uranium-fuel-cell"] = 0.3,
["used-up-uranium-fuel-cell"] = 1,
["water-barrel"] = 3
}
local scrap_raffle = {}
for _, t in pairs(container_loot_chance) do
for _ = 1, t.chance, 1 do
table_insert(scrap_raffle, t.name)
end
end
local size_of_scrap_raffle = #scrap_raffle
local function place_scrap(surface, position)
-- place turrets
if math_random(1, 700) == 1 then
if position.x ^ 2 + position.x ^ 2 > 4096 then
local e = surface.create_entity({name = "gun-turret", position = position, force = "enemy"})
e.minable = false
e.operable = false
e.insert({name = "piercing-rounds-magazine", count = 100})
return
end
end
-- place spaceship with loot
if math_random(1, 8192) == 1 then
local e = surface.create_entity({name = 'crash-site-spaceship', position = position, force = "neutral"})
e.minable = true
local i = e.get_inventory(defines.inventory.chest)
if i then
for _ = 1, math_random(1, 5), 1 do
local loot = scrap_raffle[math_random(1, size_of_scrap_raffle)]
local amount = container_loot_amounts[loot]
local count = math_floor(amount * math_random(5, 35) * 0.1) + 1
i.insert({name = loot, count = count})
end
end
return
end
-- place scrap containers with loot
if math_random(1, 128) == 1 then
local scrap = scrap_containers[math_random(1, scrap_containers_index)]
local e = surface.create_entity({name = scrap.name, position = position, force = "neutral"})
e.minable = true
local i = e.get_inventory(defines.inventory.chest)
if i then
local size = scrap.size
for _ = 1, math_random(1, size), 1 do
local loot = scrap_raffle[math_random(1, size_of_scrap_raffle)]
local amount = container_loot_amounts[loot]
local count = math_floor(amount * math_random(5, 35) * 0.1) + 1
i.insert({name = loot, count = count})
end
end
return
end
-- place scrap entities with loot
local scrap = scrap_entities[math_random(1, scrap_entities_index)]
local e = surface.create_entity({name = scrap.name, position = position, force = "neutral"})
e.minable = true
end
local function is_scrap_area(n)
if n > 0.5 then return true end
if n < -0.5 then return true end
end
local function move_away_biteys(surface, area)
for _, e in pairs(surface.find_entities_filtered({type = {"unit-spawner", "turret", "unit"}, area = area})) do
local position = surface.find_non_colliding_position(e.name, e.position, 96, 4)
if position then
surface.create_entity({name = e.name, position = position, force = "enemy"})
e.destroy()
end
end
end
local vectors = {{0,0}, {1,0}, {-1,0}, {0,1}, {0,-1}}
local function landfill_under(entity)
-- landfill the area under the entity
local surface = entity.surface
for _, v in pairs(vectors) do
local position = {entity.position.x + v[1], entity.position.y + v[2]}
if not surface.get_tile(position).collides_with("resource-layer") then
surface.set_tiles({{name = "landfill", position = position}}, true)
end
end
end
local function on_player_mined_entity(event)
local entity = event.entity
if not entity.valid then return end
if Scrap.is_scrap(entity) then landfill_under(entity) end
end
local function on_entity_died(event)
local entity = event.entity
if not entity.valid then return end
if Scrap.is_scrap(entity) then landfill_under(entity) end
end
--local function on_init(event)
--
--end
local function on_chunk_generated(event)
--log("scrap_towny_ffa::on_chunk_generated")
local surface = event.surface
local seed = surface.map_gen_settings.seed
local left_top_x = event.area.left_top.x
local left_top_y = event.area.left_top.y
--log(" chunk = {" .. left_top_x/32 .. ", " .. left_top_y/32 .. "}")
local position
local noise
for x = 0, 31, 1 do
for y = 0, 31, 1 do
if math_random(1, 3) > 1 then
position = {x = left_top_x + x, y = left_top_y + y}
if not surface.get_tile(position).collides_with("resource-layer") then
noise = get_noise("scrap_towny_ffa", position, seed)
if is_scrap_area(noise) then
surface.set_tiles({{name = "dirt-" .. math_floor(math_abs(noise) * 6) % 6 + 2, position = position}}, true)
place_scrap(surface, position)
end
end
end
end
end
move_away_biteys(surface, event.area)
--ffatable.chunk_generated[key] = true
end
local function on_chunk_charted(event)
local force = event.force
local surface = game.surfaces[event.surface_index]
if force.valid then
if force == game.forces["player"] or force == game.forces["rogue"] then
force.clear_chart(surface)
end
end
end
-- local on_init = function ()
-- local ffatable = Table.get_table()
-- ffatable.chunk_generated = {}
-- end
local Event = require 'utils.event'
-- Event.on_init(on_init)
Event.add(defines.events.on_chunk_generated, on_chunk_generated)
Event.add(defines.events.on_chunk_charted, on_chunk_charted)
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)
Event.add(defines.events.on_entity_died, on_entity_died)

View File

@ -156,9 +156,11 @@ local function handler_factory(event_id)
return
end
local is_spamming = SpamProtection.is_spamming(player, nil, 'UtilsGUI Handler')
if is_spamming and player.name ~= 'Gerkiz' then
return
if not event.text then
local is_spamming = SpamProtection.is_spamming(player, nil, 'UtilsGUI Handler')
if is_spamming then
return
end
end
event.player = player

View File

@ -4,7 +4,7 @@ local Public = {}
local this = {
prevent_spam = {}, -- the default table where all player indexes will be stored
default_tick = 15, -- this defines the default tick to check weather or not a user is spamming a button.
default_tick = 10, -- this defines the default tick to check weather or not a user is spamming a button.
_DEBUG = false
}