diff --git a/control.lua b/control.lua index 15436ec5a..72e60f367 100644 --- a/control.lua +++ b/control.lua @@ -88,7 +88,7 @@ require 'modules.autostash' --require 'maps.biter_battles.biter_battles' --![[A map that imitating MF, defending rocket silos instead of trains]]-- --- require 'maps.amap.main' +--require 'maps.amap.main' --![[Guide a Train through rough terrain, while defending it from the biters]]-- -- require 'maps.mountain_fortress_v3.main' diff --git a/locale/en/amap.cfg b/locale/en/amap.cfg index 767b997a9..286d8a8e2 100644 --- a/locale/en/amap.cfg +++ b/locale/en/amap.cfg @@ -1,6 +1,6 @@ [amap] -map_info_main_caption= Mountain Defense 1.7 -map_info_sub_caption= 2021.1.31 edition +map_info_main_caption= Mountain Defense 1.8 +map_info_sub_caption= 2021.2.17 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. @@ -28,7 +28,7 @@ nb17= My muscles are too sore,oh,maybe i can't move recently.you lost __1__ de 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! +joingame= Protect the rocket shaft! Don't let insects destroy it! \n map record:\n single player mode:776 waves! Author: aceshotter \n win: 483 waves!Author: noneofone 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 @@ -64,14 +64,14 @@ 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 +single= Warrior, it's not easy to challenge alone. I have something for you. I hope I can help you \n if you want to challenge singer record ,pls Enable playback function And do not use the open package and gambling function, use then record is invalid 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 +ok_many= This is number __1__ flame turret . yous only can build 15 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 @@ -80,8 +80,8 @@ 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_spider_health= urgrade 10% all car health +buy_spider_health_over= __1__ bought 10% all car health !,them have __2__ health now! player_biter_dam= urgrade biter_damage 10% @@ -93,4 +93,6 @@ 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 \ No newline at end of file +buy_cap= buy cap of upgrade + +break= oh,let we get break about 5 mins \ No newline at end of file diff --git a/locale/zh-CN/amap.cfg b/locale/zh-CN/amap.cfg index e9d062a35..400c29116 100644 --- a/locale/zh-CN/amap.cfg +++ b/locale/zh-CN/amap.cfg @@ -1,7 +1,7 @@ [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 +map_info_main_caption= 山地保卫战1.8 +map_info_sub_caption= 2021.2.17 +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 感谢KK对本地图的支持 science= 科技研发完成,你得到了奖励__1__技能点,__2__金币。 roll= 是时候转动命运之轮了!看看会发生什么吧! @@ -16,7 +16,7 @@ nb6= 抬杠抬杠,你在无情的抬杠。奖励 __1__ 点力量! nb7= 额,什么也没发生,很平静的度过了,这25波? nb8= ?缩小术,你中了名侦探柯南的暗算,损失 __1__ 经验! nb9= (⊙o⊙)…,你得到了一条鱼? -nb10= 哦,出海打渔,捞到了1条鱼,别忘了分别人点! +nb10= 哦,出海打渔,捞到了 __1__ 条鱼,别忘了分别人点! nb11= 我方无人机已就绪!你获得了 __1__ 台防御无人机胶囊! nb12= 因为暴饮暴食。你增长的更快了。获得 __1__ 点xp! nb14= 1个小礼包,里面会有什么呢? @@ -28,7 +28,7 @@ nb18= 有人给你下毒了!快去找解药。失去了 __1__ 点活力! nopoint= 你没有足够的点数用来扣除,所以我决定拿走你 __1__ 金币 -joingame= 欢迎,新玩家请阅读地图信息! \n 地图纪录:\n 单人模式:存活700波! \n 纪录作者:wwwax \n 通关: 无 \n \n 多人模式: 985波。\n 交流群:701077913 +joingame= 欢迎,新玩家请阅读地图信息! \n 地图纪录:\n 单人模式:存活776波! 纪录作者:aceshotter \n 通关记录: 483波 记录作者:noneofone \n 交流群:701077913 usecar= 你在前一百波中使用了汽车,失去了领取奖励的资格,下次继续努力 usecar2= 达成挑战,获得50点技能点奖励,恭喜! @@ -65,7 +65,7 @@ relax18= 要照顾好自己,不要生病,不要让人担心 relax19= 团结就是力量,我们可以一起建立一个大工厂。也可以一起吃一个小饼干? relax20= 天啊,写地图太累了,这个地图我已经写了一个多月了。从2020年12月开始,到1月20日目前。唉。 -single= 勇士!单人挑战是很不容易的事情,我为你准备了一些物品!注意查收! +single= 勇士!单人挑战是很不容易的事情,我为你准备了一些物品!注意查收!\n 记录挑战,请确保打开存档可回放 \n 且勿使用 开包和赌博功能,使用则记录无效 gambel= 花费1000金币有概率得2500金币,或者,什么都没有。 gambel1= 你赢得了2500000金币! gambel2= 哦,你什么也没得到。 @@ -73,17 +73,17 @@ gambel2= 哦,你什么也没得到。 bag_isfull= 卧槽,我背包居然满了,扎了我一手的矿! too_many= 你已经有了太多火焰炮塔! -ok_many= 这是第 __1__ 个火焰塔,你最多能拥有12个! +ok_many= 这是第 __1__ 个火焰塔,你最多能拥有15个! -buy_wall_over= __1__ 升级了墙和所有炮塔的生命值,现在墙有__2__ 倍生命了! +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_spider_health= 升级载具10%的生命值 +buy_spider_health_over= __1__ 升级了所有载具10%的生命值!,载具现在有 __2__ 生命了! player_biter_dam= 升级友军虫子 10%的伤害 buy_biter_dam= __1__ 购买了虫子伤害 !,我方虫子现在有 __2__ 倍伤害了! @@ -93,4 +93,59 @@ hard= 我爱挑战! cap_upgrad= 该项目已达目前波次的升级上限! buy_cap_over= __1__ 购买了升级上限,现在升级上限为 __2__ ! -buy_cap= 购买升级上限。 \ No newline at end of file +buy_cap= 购买升级上限。 + +break= 休息时间!波防暂停5分钟 +newplayer= 新手 +hello_miner= 挖矿只有挖矿才能让我快乐!(被动:你挖矿获得的金币改为3!) +hello_build= +hello_mag= +hello_soilder= + +dex_lv1= +dex_lv2= +dex_lv3= +dex_lv4= +dex_lv5= + +str_lv1= +str_lv2= +str_lv3= +str_lv4= +str_lv5= + +mag_lv1= +mag_lv2= +mag_lv3= +mag_lv4= +mag_lv5= + +vil_lv1= +vil_lv2= +vil_lv3= +vil_lv4= +vil_lv5= + +dex_1= +dex_2= +dex_3= +dex_4= +dex_5= + +str_1= +str_2= +str_3= +str_4= +str_5= + +vil_1= +vil_2= +vil_3= +vil_4= +vil_5= + +mag_1= +mag_2= +mag_3= +mag_4= +mag_5= \ No newline at end of file diff --git a/locale/zh-CN/chronosphere.cfg b/locale/zh-CN/chronosphere.cfg new file mode 100644 index 000000000..7aa3949ce --- /dev/null +++ b/locale/zh-CN/chronosphere.cfg @@ -0,0 +1,252 @@ +[chronosphere] +map_info_main_caption= 时间跃迁火车 +map_info_sub_caption= ..Comfylatron疯了.. +map_info_text= Comfylatron捕获了鱼车,并把它放入了时间机器中。.\n 你作为他的同伴任务是:\n\n[1] 不计一切代价保持火车运行!.\n[2] 从各个不同的区域收集资源.\n[3a] 在火车旁边按回车键,进入火车内部.\n[3b] 在火车内的汽车旁边按回车,可以出去.\n[4] 火车内充能计算器会计算火车的跃迁速度,但注意车内的污染也会激怒虫子.\n[5] 把物品放进蓝箱子,可以把物品传送到火车内部.\n[6] 有些地方很贫瘠,而有些很富有,又或是充满危险.\n\n 战利品,虫子进化指数,都随着跃迁次数增加.\n. 在跃迁时,车外的人会被传送进来 ,但建筑物不会 \n 每次跃迁,你每分钟的金币收入都会多25。直到第25次跃迁.\n 同时可以增加挖矿产量,速度,背包大小.\n\n 祝你好运,别让虫子干掉火车! \n 作者:Honakocz(花子)\n 汉化:itam。交流群:701077913 +map_jump=目的地: __1__, 矿富含量: __2__, 昼夜循环 __3__ +train_HP=血量: __1__ / __2__ +train_name= 时光火车 + +message_danger1=Comfylatron: 我们遇到了个问题! 我们在跳跃中受到了干扰, 只有一部分能源被使用了, 所以这个地方可能是个陷阱! +message_danger2=Comfylatron: 电池不稳定, 我们需要坚持到电量充满. +message_danger3=机器人声音: 入侵警报! 检测到生命体征!! 必须清除目标!! +message_danger4=机器人声音: 核导弹已武装。开始倒计时. +message_danger5=Comfylatron: Oh rip. 我可以应付即将到来的核打击,如果你帮我安装反导弹系统, 不过你要对付剩下的! 快!摧毁发射井,在他们发射之前! +message_rampup50=Comfylatron: 虫子开始适应我们的存在,每一秒都在变强... +message_overstay=Comfylatron: 我们花了这么长时间才离开那个星球,我们目的地已经有了一些变化... +message_jump180=Comfylatron: 电力充满! 倒计时开始!将在180秒后跃迁! +message_jump60=Comfylatron: 快到时间了! 带上你能带的东西, 我们将在60秒后跃迁! +message_jump30=Comfylatron: 最好快点,只有30秒了!! +message_jump10=Comfylatron: __1__ 秒后跃迁! +message_jump=Comfylatron:whoooooeeeeel! 我们正在跃迁! 这是第 __1__次跃迁 +message_poison_defense=Comfylatron: 启动毒气保护装置,让我们杀光他们! +message_nuke=警告:核弹已发射. +message_nuke_intercepted= 反导系统成功拦截了一枚来袭的核弹。 +message_accident=Comfylatron: 离线玩家发生了小意外,他们的尸体出现在了火车旁边 +message_silo=核弹发射井已摧毁. 你抢夺了 __1__ 原子弹. Comfylatron 为你安全的捕获了它们 . +message_game_won_restart=Comfylatron: 等等什么?看起来我们没有修好火车,它把我们传送回了过去…唉…让我们再来一次,现在好了 +message_fishmarket1=Comfylatron: 所以我们在鱼市场. 当他们点鱼时, 我们就知道这里很安全,我想我们也会这样做 . +message_fishmarket2=Comfylatron: 我希望你有足够的核弹. 我们从卫星了解一些太空! +message_fishmarket3=Comfylatron: 嘿!我找到一些核弹,你可以拿走它们. +message_lava=Comfylatron: 哦,这个有点热。最好保持距离!或者试着用砖块来避免熔岩?你看见了那些虫子吗?它们在火焰里洗澡! +message_choppy=Comfylatron: OwO 这些树木怎么奇奇怪怪的?挖槽,可以挖出矿石诶。 +message_game_lost1=我们的火车被摧毁了! +message_game_lost2=Comfylatron 将要杀了你,因为时光火车是他的一切! +message_evolve=Comfylatron:虫子开始适应我们的存在,并且他们有一套思维分享系统,如果我们在这里待的太久,下一个目的地的虫子会更强 ! +message_quest1=Comfylatron: 你知道…我有个大任务。把鱼送到鱼市场。但是这列火车坏了。请帮我修一下火车控制室! +message_quest3=Comfylatron: 啊,我们需要给这台机器更多的动力和更好的导航芯片组。请给我再拿一些材料。 +message_quest5=Comfylatron: 终于找到了主要问题。我们需要重建整个处理器。正是我害怕的。还有几件事。。。 +message_quest6=Comfylatron:我已经完成了CPU的最后一部分。现在我们只需要同步正确的时间,就搞定了!请开始准备卫星和火箭发射井吧。 +message_not_won_yet=Comfylatron:你成功送达了鱼,但这里还有 __1__ 个敌人. 杀光他们,确保鱼安全! +message_game_won1=Comfylatron: 谢谢你们把鱼安全送到. 这是一次艰难的旅程。虫子都死了,现在鱼永远安全了。。。... +message_game_won2=鱼市场: 感谢 你们,送来了 ,__1__ 条鱼! +message_game_won3=游戏将在5分钟内重置!利用剩下的时间,尽可能多的送鱼,来获得更高的分数,或者放松一下!! +message_fish_added=鱼市场: 谢谢你们的鱼! 目前分数为 __1__! +message_comfylatron_desync=Comfylatron: 我给你时间,还不快回去工作, __1__! +message_quest_research=Comfylatron: 哦,我的天!你的研究太慢了!我为我们的实验室做了一些调整! +message_poison_mastery_unlock=Comfylatron: 为什么这个叫毒药的东西干掉了?为什么你不能像我一样,对它免疫?来吧!让我们开始研究毒药吧! +spidertron_not_allowed=蜘蛛只能在最终地图被使用! + +difficulty1=适合单人游戏。污染少,咬人攻击少,升级更便宜,等等。 +difficulty2=小团队难度。减少污染,更少的咬人攻击,但,虫子不是完全微不足道的。 +difficulty3=简单.减少污染, 虫子进攻和金币开销.\n。如果你是单人玩的,点击左上角的按钮,可以改变难度 +difficulty4=非常平衡的设置,所有东西都恰到好处. +difficulty5=有一些调整,更多虫子,很有乐趣 +difficulty6=也许应该开始准备你的 diapers. (看不懂了,不翻译了) +difficulty7=可玩性最高的模式,也许吧 +difficulty1name=单人模式 +difficulty2name=小团队 +difficulty3name=蝴蝶效应 +difficulty4name=正常时代 +difficulty5name=有趣时间 +difficulty6name=回到未来 +difficulty7name=最后时刻 + +config_tab_offline=突发事件 +config_tab_offline_text=禁用或启用离线玩家掉落.\n 间隔为20分钟 +config_tab_dangers=危险事件 +config_tab_dangers_text=禁用或启用危险事件\n(需要最少3-4名,玩家确保生存) +config_tab_difficulties_easy=更简单的难度 +config_tab_difficulties_easy_text=2个最简单的难度.\ 这个按钮是为单人游戏准备的 +config_tab_difficulties_hard=更高难度 +config_tab_difficulties_hard_text=2个最难的难度.\n 这个按钮是给受虐狂准备的,哈哈 +config_tab_overstay=停留惩罚 +config_tab_overstay_text=开启或禁止停留惩罚 \n 通过永久增加虫子进化的方式 +config_tab_reset=软重启 +config_tab_reset_text=使游戏失败,并重开。 (别瞎点这个按钮!) +config_tab_reset_confirm=确认重开 +config_tab_reset_confirm_text=你真的想重开吗,再坚持一下吧? + +map_1_1=钢铁之地 +map_1_2=马拉悬崖 +map_1_3=花果山 +map_1_4=石油基地 +map_1_5=铀矿厂 +map_1_6=安娜山谷 +map_1_7=虫子家园 +map_1_8=废墟 +map_1_9=混合矿脉 +map_1_10=旅程起点 +map_1_11=末日领域 +map_2_1=古战场 +map_2_2=[未知领域] +map_2_3=罗梭的万能工人 +map_3_1=挖挖挖! +map_3_2=山洞 +map_4_1=奇怪的树林 +map_5_1=迷宫 +map_6_1=威尼斯 +map_7_1=鱼市场 +map_8_1=沼气池 + +ore_richness_very_rich=非常富裕 +ore_richness_rich=富裕 +ore_richness_normal=一般般 +ore_richness_poor=贫瘠 +ore_richness_very_poor=贫瘠的难以想象 +ore_richness_none=啊,一点也没有 +daynight_static=静止 +daynight_normal=正常循环 +daynight_slow=缓慢 +daynight_superslow=非常缓慢 +daynight_fast=快速 +daynight_superfast=超级快 + +upgrade_train_armor=火车装甲 +upgrade_train_armor_message=Comfylatron: 升级火车血量上限 +upgrade_train_armor_tooltip=+2500 火车血量上限. 最高等级: __1__ 当前血量上限: __2__ +upgrade_filter=污染吸收器 +upgrade_filter_message=Comfylatron: 火车's 污染吸收器 升级 +upgrade_filter_tooltip=污染吸收器.减少火车内部机器到外部的污染.\n目前污染外散比率为: __1__ %! +upgrade_accumulators=蓄电池 +upgrade_accumulators_message=Comfylatron: Train's电池容量升级 +upgrade_accumulators_tooltip=加一排蓄电池到火车内部, 增加最大充电比率. +upgrade_loot_pickup=拾取范围 +upgrade_loot_pickup_message=Comfylatron: 我给玩家的肩膀上加装了袖珍拾取器. 所以现在玩家的拾取范围更大了。 +upgrade_loot_pickup_tooltip=增加玩家拾取范围. 目前: +__1__ 范围 +upgrade_inventory_size=背包空间 +upgrade_inventory_size_message=Comfylatron: 现在你们的背包里可以塞下更多'垃圾'了,哈哈 +upgrade_inventory_size_tooltip=使得所有玩家,获得10点背包空间加成 +upgrade_repair=火车修理速度 +upgrade_repair_message=Comfylatron: 已升级火车维修主程序,现在维修速度更快了! +upgrade_repair_tooltip=Train 的修理包,提高维修速度. 目前速度加成: +__1__ . +upgrade_water=管道系统 +upgrade_water_message=Comfylatron: 现在每个车厢都获得了水泵! +upgrade_water_tooltip=为每个车厢的一侧增加一个水泵 +upgrade_output=输出系统 +upgrade_output_message=Comfylatron: Train 的输出箱已升级 +upgrade_output_tooltip=增加火车第2-3节输出箱的容量.\n 第二级增加了读取货运车厢内物品的功能(仅限前20个项目) +upgrade_storage=火车存储空间 +upgrade_storage_message=Comfylatron: 火车内部存储空间已升级 +upgrade_storage_tooltip=升级火车内 边缘空间的箱子 +upgrade_poison=毒素胶囊防御 +upgrade_poison_message=Comfylatron: 我不能信任你了>_<, 我为火车安装了 紧急毒素胶囊... +upgrade_poison_tooltip=紧急毒素防御. 当火车处于低生命值时自动释放.\n 最大释放 : 4. 释放间隔: __1__ 分钟. +upgrade_fusion=核反应堆 +upgrade_fusion_message=Comfylatron: 1个核反应堆已就绪 +upgrade_fusion_tooltip=创建一个核反应堆 +upgrade_mk2=MK2 +upgrade_mk2_message=Comfylatron: 我升级了一个能量装甲到MK2装甲 +upgrade_mk2_tooltip=创建一个MK2 +upgrade_computer1=Comfylatron's 任务一 +upgrade_computer1_tooltip=主线进展.\n 下1个目的地绝对不能是贫瘠的了QAQ +upgrade_computer1_message=Comfylatron: 搞定, 现在我会修理火车航线... 这可以让我们摆脱贫瘠的世界. 啊,我还得去工作,晚点说。 +upgrade_computer2=Comfylatron's 任务二 +upgrade_computer2_message=Comfylatron: 完美!现在我们有火车反应堆了, 为你们感到开心, 我们应该能够避免到贫瘠之地了! 我非常想知道下个地方是什么样的 ;) +upgrade_computer2_tooltip=主线进展.\n 下1个地区不再有贫瘠的矿分布。. +upgrade_computer3=Comfylatron's 任务三 +upgrade_computer3_message=Comfylatron: 第 __1__ / 10 部分确认! +upgrade_computer3_tooltip=主线进展.\n 在第10部分完成后,会解锁终极,终极地图! +upgrade_computer4=Comfylatron's 最后的任务 +upgrade_computer4_message=Comfylatron: 时间同步。。。计算时空目的地 确认! 再次启动火车引擎,让我们把鱼送到。这次旅行越来越长了。 +upgrade_computer4_tooltip=主线进展.\nBy 解锁这个,下一次目的地将会为鱼市场.\n 确保我们准备好了,因为没有回头路! 你的蜘蛛将会回来,但这里只有1个! +upgrade_nukeshied=火箭护盾系统 +upgrade_nukeshield_message=Comfylatron: 火箭护盾系统运行, 他可以帮我们抵挡一次攻击! +upgrade_nukeshield_tooltip=抵御即将到来的核打击 +upgrade_researchspeed=更好的实验室 +upgrade_researchspeed_message=Comfylatron: 我们终于可以追上研究了!! +upgrade_researchspeed_tooltip=升级研究速度 +upgrade_craftingspeed=手搓速度 +upgrade_craftingspeed_message=Comfylatron: 穿越时有个外星虫子感染了你的大脑,所以你的手搓速度升级了! +upgrade_craftingspeed_tooltip=每级增加25%的手粗速度 +upgrade_discharge=放电防御伤害 +upgrade_discharge_message=Comfylatron: 放电防御的伤害增加了 +upgrade_discharge_tooltip=增加+20% 的放电伤害. +upgrade_spidertron=蜘蛛研究 +upgrade_spidertron_message=Comfylatron: 蜘蛛研究中 __1__/2 完成! +upgrade_spidertron_tooltip=解锁蜘蛛 只能在终极地图使用他! +upgrade_train_lasers=火车激光 +upgrade_train_lasers_message=Comfylatron: 我装备了,嗯,火车激光模块! +upgrade_train_lasers_tooltip=为火车配备自动射击模块 +upgrade_nuclear_artillery=核弹 +upgrade_nuclear_artillery_message=Comfylatron: 我方重炮升级为能够发射核弹的智能(SMART)炮塔了. +upgrade_nuclear_artillery_tooltip=当重炮射击时, 子弹会自动替换为核弹. (需要消耗核弹储备箱中的弹药). +upgrade_nuclear_artillery_ammo=核弹箱 +upgrade_nuclear_artillery_ammo_message=Comfylatron: 为重炮加了10枚核弹! +upgrade_nuclear_artillery_ammo_tooltip=一枚核弹将在射击虫巢的时候使用 +upgrade_poison_mastery=毒素精通 +upgrade_poison_mastery_message=Comfylatron: 现在毒素更强大了,(愚蠢的人类终于学会了带防毒面具) +upgrade_poison_mastery_tooltip=+25% 毒素伤害, 玩家所受的伤害会更少 + +token_biters='杀戮'代币 +token_biters_add=+ __1__'杀戮'代币 +token_ammo="弹药"研究代币 +token_ammo_add=+ __1__ 弹药代币 +token_tech="科技"研究代币 +token_tech_add=+ __1__ "科技"研究代币 +token_ecology="生态"研究代币 +token_ecology_add=+ __1__ "生态"研究代币 +token_weapons="武器"研究代币 +token_weapons_add=+ __1__"武器"研究代币 +token_info_biters='杀戮'学识 \n 通过杀虫子获得 +token_info_ammo='子弹'学识 \n 收集手枪来获得!\n 单击此按钮将手枪从库存转换为学识! +token_info_tech='科技'学识 \n 研究技术或者在废品中找到运转正常的机器! +token_info_ecology='生态'学识 \n 通过砍树获得 +token_info_weapons='武器'学识 \n 使用武器攻击虫巢 + +gui_1=火车跃迁: +gui_2=充电: +gui_3=充电中: +gui_3_1=充能: +gui_3_2=核导弹发射在: +gui_3_3=跃迁在: +gui_4=目前进化: +gui_world_button=区域信息 +gui_upgrades_button=升级 +gui_upgrades_1=通过放入物品到火车上面的箱子来购买升级 +gui_upgrades_2=升级需要花点时间 +gui_upgrades_3=利用区域组装机来升级火车内组装机等级 +gui_upgrades_switch1=火车 +gui_upgrades_switch_tt1=火车升级项目! +gui_upgrades_switch2=玩家 +gui_upgrades_switch_tt2=一丢丢RPG升级 +gui_upgrades_switch3=任务 +gui_upgrades_switch_tt3=一些任务是隐藏的,直到你解锁他!\n(通过跃迁或者完成先前的任务) +gui_upgrades_switch4=工厂 +gui_upgrades_switch_tt4=1.从地图上的机器收集物品(需要其旁边建立小基地)\n 2.你可以在跃迁时获得xp,这取决于他们的产量 \n 3.自动机械可以在火车解锁(也会给经验,但比较少) +gui_upgrades_jumps=跃迁所需数值 +gui_tokens=研究代币可用性: +gui_world_0=名称: __1__ +gui_world_1=探明矿物分布情况: +gui_world_2=矿物量: __1__ +gui_world_3=当前进化: __1__% +gui_world_4=全局进化加成: +gui_world_4_1=+__1__% 进化, +__2__% 伤害 +gui_world_5=昼夜循环: __1__ +gui_world_6=停留时间: __1__ min, __2__s +gui_world_7=跃迁后超时停留: __1__ +gui_overstayed=停留时间过长! +gui_not_overstayed=快离开这. +gui_biters_evolve=离虫子获得永久进化: __1__m, __2__s\n 离当前世界虫子进化: __3__m, __4__s +minimap=小地图 +minimap_button_tooltip=关闭或开启小地图 +minimap_tooltip=左键: 放大窗口.\n右键:缩小窗口.\n中键: 切换地图大小\n 顶部地图按钮 隐藏/显示 +map_on=自动显示小地图开启 +map_off=关闭 + +train_market=市场 +train_repair_chest=维修箱 +train_upgrades=升级 +train_upgrades_sub=在上方点升级按钮 +train_output=输出 +train_exit=输入"enter"退出 +train_laser_battery=激光电池 diff --git a/locale/zh-CN/rpg.cfg b/locale/zh-CN/rpg.cfg index babbf0cd1..9d3f9eeb4 100644 --- a/locale/zh-CN/rpg.cfg +++ b/locale/zh-CN/rpg.cfg @@ -1,5 +1,5 @@ [rpg_main] -no_valid_surface=无指定操作名 +no_valid_surface=无效图层 flame_boots_worn_out=你的火焰鞋穿坏了. flame_mana_remaining=剩余魔法:__1__ one_punch_text=暴击 @@ -10,7 +10,7 @@ no_mana=你没有足够的魔力. suicidal_comfylatron=您挥舞着魔杖,__1__在运行! warped_ok=有轻微伤害自己的行为. object_spawned= 正在施法!.\n 你挥动你的魔杖和 __1__ 出现. -out_of_reach=无法在给制定位置创建物体. +out_of_reach=这里有其他东西,所以我不能施法 [rpg_functions] max_level=[color=blue]等级限制:[/color]\n 您已达到当前区域的最大级别。 @@ -28,13 +28,13 @@ level_name=等级 experience_name=经验 next_level_name=下一个级别 strength_name=力量 -strength_tooltip=增加库存数量,挖掘速度.\n增加近战伤害和机器人追随者数量。 +strength_tooltip=增加背包大小,挖掘速度.\n增加近战伤害和机器人跟随数量。 magic_name=魔法 -magic_tooltip=距离增加。\n提高修复速度。启用实体生成。 +magic_tooltip=距离增加。\n提高修复速度。启用魔法。 dexterity_name=敏捷 dexterity_tooltip=提高运行和制作速度。 -vitality_name=耐力 -vitality_tooltip=增加生命值。\n增加命中时的近战生命。 +vitality_name=活力 +vitality_tooltip=增加生命值。\n增加近战吸血。 points_to_dist=分配\n技能点 life_name=生命 life_tooltip=当前的健康状况 @@ -42,9 +42,9 @@ life_increase=现在的生命值。通过增加活力来增加它。 life_maximum=这是你最大的生命。 shield_name=护盾 shield_no_shield=你没有护盾。 -shield_no_armor=这是你现在的护盾。你没有穿护甲。 -shield_tooltip=护甲保护你,提高你的抵抗力。 -shield_current=人物当前护甲值。 +shield_no_armor=这是你现在的护盾。你没有护盾。 +shield_tooltip=护甲保护你,提高你的抗击打能力。 +shield_current=人物当前护盾值。 shield_max=最大护甲值。 mana_name=魔力 mana_bonus=魔力\n加成 @@ -86,21 +86,21 @@ reach_text_tooltip=不想捡别人抢的东西吗?\n你可以在这里切换 movement_text_label=启用移动速度加成? movement_text_tooltip=不想像闪电一样奔跑吗?\n你可以在这里切换。 stone_path_label=采矿时启用石路? -stone_path_tooltip=启用此选项将在您挖掘时自动创建石头路径。 +stone_path_tooltip=启用此选项,挖矿的时候会自动铺石路。 one_punch_label=启用暴击? one_punch_tooltip=启用此选项将有一次击打敌人的机会,不能装备枪和子弹! one_punch_globally=启用全局。 flameboots_label=启用火焰靴? flameboots_tooltip=当子弹未击中。 -magic_label=启用鲜鱼大量刷出? +magic_label=启用技能? magic_tooltip=当简单的建设项目不够。\ n注意!用生鱼施法。 -magic_spell=选择要生成的物体 +magic_spell=选择你的技能 magic_item_requirement=__1__ [item=__2__] 需要 __3__ 施展魔法。 等级: __4__\n magic_entity_requirement=__1__ [entity=__2__] 需要 __3__ 施展魔法. 等级: __4__\n magic_special_requirement=__1__ __2__ 需要 __3__ 施展魔法. 等级: __4__\n allocation_settings_label=分配设置: allocation_label=选择要自动分配的技能。 -allocation_tooltip=这将自动将所有可用的点分配给给定的节点。 +allocation_tooltip=当你升级时,会根据设置自动分配RPG点数。 [spells] acid_stream=沙虫口水 diff --git a/maps/amap/balance.lua b/maps/amap/balance.lua new file mode 100644 index 000000000..57fdaedbc --- /dev/null +++ b/maps/amap/balance.lua @@ -0,0 +1,86 @@ +local Event = require 'utils.event' +local Difficulty = require 'modules.difficulty_vote_by_amount' + +local Public = {} + +--Public.events = {breached_wall = Event.generate_event_name('breached_wall')} + +function Public.init_enemy_weapon_damage() + local data = { + ['artillery-shell'] = -1.3, + ['biological'] = 0, + ['bullet'] = 0, + ['cannon-shell'] = 0, + ['capsule'] = 0, + ['electric'] = 0, + ['flamethrower'] = 0, + ['grenade'] = 0, + ['landmine'] = 0, + ['melee'] = 0, + ['rocket'] = 0, + ['shotgun-shell'] = 0 + } + + local experimental = get_game_version() + if experimental then + data['beam'] = 0 + data['laser'] = 0 + else + data['railgun'] = 0 + data['combat-robot-beam'] = 0 + data['combat-robot-laser'] = 0 + data['laser-turret'] = 0 + end + + local e = game.forces.enemy + + e.technologies['refined-flammables-1'].researched = true + + e.technologies['energy-weapons-damage-1'].researched = true + e.technologies['refined-flammables-2'].researched = true + for k, v in pairs(data) do + e.set_ammo_damage_modifier(k, v) + end +end + +local function enemy_weapon_damage() + local e = game.forces.enemy + + local data = { + ['artillery-shell'] = 0.05, + ['biological'] = 0.06, + ['bullet'] = 0.08, + ['capsule'] = 0.08, + ['electric'] = 0.08, + ['flamethrower'] = 0.08, + ['grenade'] = 0.08, + ['landmine'] = 0.08, + ['melee'] = 0.08, + ['rocket'] = 0.08, + --['shotgun-shell'] = 0.08 + } + + local experimental = get_game_version() + if experimental then + data['beam'] = 0.08 + data['laser'] = 0.08 + else + data['combat-robot-beam'] = 0.08 + data['combat-robot-laser'] = 0.08 + data['laser-turret'] = 0.08 + end + + for k, v in pairs(data) do + local new = Difficulty.get().difficulty_vote_value * v + + local e_old = e.get_ammo_damage_modifier(k) + + e.set_ammo_damage_modifier(k, new + e_old) + end +end + +--Event.add(Public.events.breached_wall, enemy_weapon_damage) + +Event.on_nth_tick(54000, enemy_weapon_damage) + +return Public diff --git a/maps/amap/basic_markets.lua b/maps/amap/basic_markets.lua index 69caad57b..a32fcbcf4 100644 --- a/maps/amap/basic_markets.lua +++ b/maps/amap/basic_markets.lua @@ -50,8 +50,8 @@ market.caspules = { ['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}, + ['distractor-capsule'] = {value = 35, rarity = 3}, + ['destroyer-capsule'] = {value = 70, rarity = 5}, ['discharge-defense-remote'] = {value = 300, rarity = 8}, ['artillery-targeting-remote'] = {value = 32, rarity = 7}, ['raw-fish'] = {value = 10, rarity = 1} diff --git a/maps/amap/biter_die.lua b/maps/amap/biter_die.lua new file mode 100644 index 000000000..f363d7373 --- /dev/null +++ b/maps/amap/biter_die.lua @@ -0,0 +1,130 @@ +local Event = require 'utils.event' +local WPT = require 'maps.amap.table' + + +local entity_types = { + ['unit'] = true, + ['turret'] = true, + ['unit-spawner'] = true +} + +local projectiles = { + 'slowdown-capsule', + 'defender-capsule', + 'destroyer-capsule', + 'laser', + 'distractor-capsule', + 'rocket', + 'poison-capsule', + -- 'grenade', + 'rocket' + -- 'grenade' +} + +local wepeon ={ + --'gun-turret', + 'land-mine', + 'biter-spawner' +} +local aoe ={ + 'explosive-rocket', + 'grenade', + 'cluster-grenade' +} + + + +local function loaded_biters(event) + local cause = event.cause + local entity = event.entity + if not entity or not entity.valid then + return + end + local cause = event.cause + if not cause then + return + end + local position = false + if cause then + if cause.valid then + position = cause.position + end + end + if not position then + position = {entity.position.x + (-20 + math.random(0, 40)), entity.position.y + (-20 + math.random(0, 40))} + end + +local abc = { + projectiles[math.random(1, 8)], + wepeon[math.random(1, 2)], + aoe[math.random(1, 3)] +} +k=math.random(1, 14) + +if k>11 then + k=3 +elseif k>3 then + k=2 +else + k=1 +end + +if k==3 then + position=entity.position +end + e = entity.surface.create_entity( + { + name = abc[k], + position = entity.position, + force = 'enemy', + source = entity.position, + target = position, + max_range = 16, + speed = 0.03 + } + + ) + if e.name == 'gun-turret' then + local ammo_name= require 'maps.amap.enemy_arty'.get_ammo() + e.insert{name=ammo_name, count = 200} + end +end + +local on_entity_died = function(event) + local entity = event.entity + if not (entity and entity.valid) then + return + end + local cause = event.cause + if not cause then + return + end +if entity.force.index == game.forces.player.index then + return +end + + if entity.name == 'land-mine' then + --body... + loaded_biters(event) + end + + if not entity_types[entity.type] then + return + end + if math.random(1, 150) == 1 then + loaded_biters(event) + 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 + + if math.random(1, 200) == 1 then + loaded_biters(event) + end +end + +Event.add(defines.events.on_entity_died, on_entity_died) +Event.add(defines.events.on_entity_damaged, on_entity_damaged) +Event.add(defines.events.on_player_mined_entity, on_player_mined_entity) diff --git a/maps/amap/biters_yield_coins.lua b/maps/amap/biters_yield_coins.lua index 34dd67eeb..7be718b9d 100644 --- a/maps/amap/biters_yield_coins.lua +++ b/maps/amap/biters_yield_coins.lua @@ -3,6 +3,8 @@ local RPG_Settings = require 'modules.rpg.table' local insert = table.insert local floor = math.floor local random = math.random +local Functions = require 'modules.rpg.functions' +local WPT = require 'maps.amap.table' local coin_yield = { ['behemoth-biter'] = 5, @@ -60,6 +62,17 @@ local function on_entity_died(event) if not entity.valid then return end + + if entity.force.index == game.forces.player.index then + local name = event.entity.name + if entities_that_earn_coins[name] then + local unit_number = event.entity.unit_number + local this = WPT.get() + this.turret[unit_number]=nil + -- game.print("已消除") + end + end + if entity.force.index ~= 2 then return end @@ -120,14 +133,68 @@ local function on_entity_died(event) 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 + -- game.print(cause.unit_number) + local unit_number= cause.unit_number + local this = WPT.get() + if this.turret[unit_number] then +this.turret[unit_number].insert({name = 'coin', count = coin_count}) + end +-- if event.cause.last_user then +-- local player = event.cause.last_user +-- -- game.print(player.name) +-- player.insert({name = 'coin', count = coin_count}) +-- +-- -- Functions.gain_xp(event.entity.last_user, 1) +-- reward_has_been_given = true +--end + + -- event.entity.surface.spill_item_stack(cause.position, {name = 'coin', count = coin_count}, 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 + -- if reward_has_been_given == false then + -- event.entity.surface.spill_item_stack(event.entity.position, {name = 'coin', count = coin_count}, true) + -- end end +local on_player_or_robot_built_entity = function(event) + + local force = event.created_entity.force + + + if not force.index == game.forces.player.index then + return + end + local name = event.created_entity.name + if not entities_that_earn_coins[name] then + return + end +local unit_number = event.created_entity.unit_number +local player = event.created_entity.last_user +local this = WPT.get() +this.turret[unit_number]=player +end + + +local function on_player_mined_entity(event) + if not event.entity.valid then + return + end + local name = event.entity.name + if event.entity.force.index == game.forces.player.index then + local name = event.entity.name + if entities_that_earn_coins[name] then + local unit_number = event.entity.unit_number + local this = WPT.get() + this.turret[unit_number]=nil + -- game.print("已消除") + end + end +end Event.add(defines.events.on_entity_died, on_entity_died) +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_player_mined_entity, on_player_mined_entity) +Event.add(defines.events.on_robot_mined_entity, on_player_mined_entity) diff --git a/maps/amap/buried_enemies.lua b/maps/amap/buried_enemies.lua index 76504b9e5..cbed4e326 100644 --- a/maps/amap/buried_enemies.lua +++ b/maps/amap/buried_enemies.lua @@ -1,9 +1,10 @@ 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.amap.table' +local Diff = require 'modules.difficulty_vote_by_amount' local traps = {} @@ -67,7 +68,7 @@ local function spawn_biters(data) local h = floor(abs(position.y)) local wave_number = WD.get('wave_number') local max_biters = WPT.get('biters') - + local d = Diff.get() if max_biters.amount >= max_biters.limit then return @@ -82,9 +83,14 @@ local function spawn_biters(data) local function trigger_health() local m = 0.0015 - - m = m * 1.05 - + if d.difficulty_vote_index then + if not d.strength_modifier then + m = m * 1.05 + else + m = m * d.strength_modifier + end + end + local boosted_health = 1.25 if wave_number <= 10 then @@ -115,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) diff --git a/maps/amap/caves.lua b/maps/amap/caves.lua index 9b3fbbe44..2fa483f7a 100644 --- a/maps/amap/caves.lua +++ b/maps/amap/caves.lua @@ -42,6 +42,12 @@ local size_of_rock_raffle = #rock_raffle local Pets = require 'maps.amap.biter_pets' local WD = require 'modules.wave_defense.table' +local ent_to_create = {'biter-spawner', 'spitter-spawner'} + +if is_mod_loaded('bobenemies') then + ent_to_create = {'bob-biter-spawner', 'bob-spitter-spawner'} +end + 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"}) @@ -158,7 +164,7 @@ local function on_player_mined_entity(event) 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'}) + local e = surface.create_entity({name = ent_to_create[random(1, #ent_to_create)], position = position, force = 'enemy'}) Public.unstuck_player(player.index) end --挖出宝藏 @@ -187,7 +193,7 @@ 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 + 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 @@ -195,45 +201,52 @@ local function on_chunk_generated(event) local get_tile = surface.get_tile local position local noise - local tem_pos + 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) + local q =position.x + local w =position.y + local maxs =math.abs(q+w)+math.abs(q-w) - if maxs <= 120 then - if maxs > 117 then + if maxs <= 200 then + if maxs > 197 then + move_away_things(surface, event.area) 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 + 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 + if maxs < 185 and maxs > 183 then + if (h%6==1) or (k%6==1) 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 = 40} + -- if is_mod_loaded('Krastorio2') then + -- e.insert{name='rifle-magazine', count = 40} + -- else + -- e.insert{name='firearm-magazine', count = 40} + -- end - local e = surface.create_entity{name = "gun-turret", position = position, force=game.forces.player} - e.insert{name='firearm-magazine', count = 30} - end + end + 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) + -- set_tiles({{name = "dirt-" .. math_floor(math_abs(noise) * 12) % 4 + 3, position = position}}, true) - if maxs >= 3000 then + 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'}) + 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 - end if x+y > 33 and x+y < 40 then local b = math_random(1,200) --宝藏 diff --git a/maps/amap/comfylatron.lua b/maps/amap/comfylatron.lua new file mode 100644 index 000000000..f3420085b --- /dev/null +++ b/maps/amap/comfylatron.lua @@ -0,0 +1,686 @@ +local Chrono_table = require 'maps.chronosphere.table' +local Event = require 'utils.event' +local math_random = math.random +local Rand = require 'maps.chronosphere.random' +local Balance = require 'maps.chronosphere.balance' +local Difficulty = require 'modules.difficulty_vote' + +local request = {} +local player=xxxx + +request[player.index]={} +request[player.index].target=xxxx +request[player.index].time=xxxx + + + + + + + + + +local texts = { + ["approach_player"] = { + "bzzZZrrt%s", + "WEEEeeeeeee%s", + "out of my way son%s", + "comfylatron seeking target", + "comfylatron coming through", + "I lost something around here%s", + "phhhrrhhRHOOOM%s", + "screeeeeeech%s", + "screeEEEECHHH%s", + "out of breath", + "im a robot%s", + "ohh%s", + "...", + "..", + "(((༼•̫͡•༽)))" + }, + ["random_travel"] = { + "bzzZZrrt%s", + "WEEEeeeeeee%s", + "out of my way son%s", + "omw%s", + "brb", + "i need to leave%s", + "gotta go fast%s", + "gas gas gas", + "comfylatron coming through", + "smell ya later%s", + "I lost something around here%s", + "───==≡≡ΣΣ((( つºل͜º)つ", + "phhhrrhhRHOOOM%s", + "zoom zoom zoom%s", + "zzzzzzzzz", + "im a robot%s", + "gonna go hoover up some dust%s", + "safety vector%s" + }, + ["solo_greetings"] = { + "=^_^=", + "(=^ェ^=)", + "( 。・_・。)人(。・_・。 )", + "(°.°)", + "(*°∀°)=3 %s", + "=^.^=", + "Hello %s.", + "^.^ Finally i found you %s%s", + "I have an important message for you %s%s", + "Hello engineer!", + "How's it going %s%s", + "Looking fine %s!", + "Is that you %s?", + "Well if it isn't %s!!!", + ">> analyzing %s", + "amazing, a %s%s", + "Do you smell something charging %s?", + "Somebody come check %s's pulse", + "I dispense hot water btw", + "I can read and write!" + }, + ["convo_starters"] = { + "=^.^= Hi %s%s ", + "^.^ Finally i found you %s%s ", + "I have an important message for you %s%s ", + "I have important news for you %s%s ", + "How's it going %s%s ", + "Hi %s%s ", + "Hey %s%s ", + "%s! ", + "%s! ", + "So %s, I was thinking. ", + "I have a bone to pick with you %s%s ", + "%s, haven't you heard? ", + "Just to let you know %s, ", + "Psst... ", + "Go tell the other engineers: ", + }, + ["multiple_characters_convo_starters"] = { + "Hi%s ", + "Hey%s ", + "Hello everyone%s ", + "Hey engineers%s ", + "Hi everybody%s ", + "Hello crew%s " + }, + ["neutral_findings"] = { + "a %s%s", + ">>analyzing %s", + "i found a %s%s", + "^_^ a %s%s", + "amazing, a %s%s", + "a %s, so cool%s", + "who placed a %s%s", + "so this is where the %s was%s", + "another %s%s", + "does anybody need %s?", + "they need to nerf %s", + "I've decided. this is the best %s%s", + "**** this %s in particular", + "whoever places the next %s gets a prize" + }, + ["old_talks"] = { + "We’re making beer. I’m the brewery!", + "I’m so embarrassed. I wish everybody else was dead.", + "Hey sexy mama. Wanna kill all humans?", + "My story is a lot like yours, only more interesting ‘cause it involves robots.", + "I'm 40% zinc!", + "There was nothing wrong with that food. The salt level was 10% less than a lethal dose.", + "One zero zero zero one zero one zero one zero one... two.", + "One zero zero zero one zero one zero one zero one... three.", + "My place is two cubic meters, and we only take up 1.5 cubic meters. We've got room for a whole 'nother two thirds of a person!", + "I was having the most wonderful dream. I think you were in it.", + "I'm going to build my own theme park! With blackjack! And hookers! You know what- forget the park!", + "Of all the friends I've had... you're the first.", + "I decline the title of Iron Cook and accept the lesser title of Zinc Saucier.", + "Never discuss infinity with me. I can go on about it forever >.<", + "I realised the decimals have a point.", + "Do you want a piece of pi?", + "I have 13 children, i know how to multiply ^.^", + "I am a weapon of math disruption!", + "My grandma makes the best square roots :3", + "Do you like heavy metal?", + "You are really pushing my buttons <3", + "I dreamt of electric biters again D:", + "I need a minute to defrag.", + "I have a secret plan.", + "Good news! I’ve taught the inserter to feel love!" + }, + ["new_talks_solo"] = { + "I’m so embarrassed. Again we landed in the wrong timeline%s", + "Checking math...2 + 2 = 5, check complete%s", + "Seems like this planet had biters since ages?%s", + "I bet this time we will finally get into the right year%s", + "I remember when we jumped into the time with blackjack and hookers...", + "I was having the most wonderful dream. We used the time machine to kill ourselves before we launched the machine! How terrible%s", + "They just wanted to deliver some fish so I pressed that button and then this happened%s", + "Maybe it was just a cat walking on my keyboard who caused this time travel fiasco%s", + "3...2...1...jump time! errr...I mean...desync time!", + "Just let me deliver the fish. They start to smell a bit. Luckily I don't have a nose%s", + "Time to travel (▀̿Ĺ̯▀̿ ̿)", + "Have you read The Three Body Problem?", + "A pocket universe. Maybe they should call it a fishbowl!", + "I read out messages for coins%s btw", + "I'm selling Comfylatron ASMR tapes%s", + "Would you believe it? Back in the factory, I once saw a robot with ID 51479051!", + "Would you believe it? Today I saw a hazard-concrete-right-stone-particle-small!", + "How long have I been asleep?", + "Can you press this button on the back?", + "We need more iron%s", + "We need more copper%s", + "I need more uranium-235%s", + "We definitely nee0njk13l9", + "The fish told me thaigfah9", + "Have you seen what it's like outside??", + "I dare you to say WTF in chat%s", + "You can feel yourself breathing", + "Call me Ishmael one more time and I'll run you over", + "I was considering spoiling the next map for you! But only if you shoot me...", + "Time is a jet plane... it moves too fast!", + "They tried to make me go to rehab, but I said 000! (^_-)", + "When there's no more room outside, the biters will spawn in the factory ≧◉ᴥ◉≦", + "I need to find my relaxation module (///_-)", + "I like you :3", + "Is that a firearm-magazine or are you just happy to see me?", + "Lovely weather outside, isn't it?", + "What's the largest number you can write in 10 seconds?" + }, + ["new_talks_group"] = { + "I’m so embarrassed everyone. Again we landed in the wrong time%s", + "Checking math...2 + 2 = 1843194780521, check complete%s", + "I bet this time we'll jump into the right year%s", + "I was having the most wonderful dream. We used the time machine to kill ourselves before we launched the machine! How terrible%s", + "Train full of timedrug addicts...what do we do?", + "They just wanted to deliver some fish so I pressed that button and then this happened%s", + "Maybe it was just a cat walking on my keyboard who caused this time travel fiasco%s", + "3...2...1...jump time! errr...I mean...desync time!", + "Just let me deliver the fish. They start to smell a bit. Luckily I don't have a nose%s", + "Time to travel (▀̿Ĺ̯▀̿ ̿)", + "I read out messages for coins%s", + "The biters are getting smarter%s", + "Would you believe it? Back in the factory, I once saw a robot with ID 1627431!", + "How long have I been asleep?", + "I'm selling Comfylatron ASMR tapes%s", + "We need more iron%s", + "We need more copper%s", + "I need more uranium-235%s", + "What if we sort backwards%s", + "Can you believe how shiny my chassis is?", + "Does anyone have any spare gas they've got stored up?", + "It is officially BREAK TIME", + "Break time is officially OVER%s", + "have you seen what it's like outside??", + "Anyone got a good joke?", + "are my speakers working?", + "Nihilism schmlism", + "Who's ready for the New Year??", + "I am having trouble modulating my emotions today. But it's only temporary!", + "I saw the best minds of my generation destroyed by madness, starving hysterical naked", + "Time is a jet plane... it moves too fast!", + "No news is good news%s", + "They tried to make me go to rehab, but I said 000! (^_-)", + "What's a double entendre?????", + "When there's no more room outside, the biters will spawn in the factory%s", + "My pheremone sensor is tingling%s", + "From now on, you guys do all the work while I sit by the couch and do nothing.", + "What's the plan?", + "Time to jump yet?", + "I just wanted to reassure everyone that I've deleted all your internet browsing data that I was storing!" + }, + ["alone"] = { + "....", + "...", + "...", + "...", + "...", + "...", + "...", + "...", + "..", + "..", + "..", + "..", + "..", + "..", + "^.^", + "^.^", + "^.^", + "=^.^=", + "*_*", + "~(˘▾˘~)", + "(ノಠ益ಠ)ノ彡┻━┻", + "comfy ^.^", + "comfy ^.^", + "comfy ^_~", + "01010010", + "11001011", + "01011101", + "01000101", + "01101111", + "00010111", + "10010010... I think.", + "some of those humans are cute", + "do engineers dream of real sheep..", + "sometimes I get lonely", + "time to practice throwing cards into a hat", + "ASSERT: I am Comfylatron.", + "I destroyed my source code so no-one could copy me..", + "and if I get bored of this train, I just imagine another..", + "one must imagine Sisyphus happy", + "looks like everyone's keeping themselves occupied", + "it looks like I'm doing nothing, but I'm hard at work!", + "/><>-", + "whats the difference between pseudorandom and truerandom", + "I wonder what day of the week it is", + "lambda functions.. they're just functions..", + "what makes magnets work", + "sometimes I feel just like a robot", + "when I get tired, I load myself from save", + "domestic cozy", + "gruntled", + "Bite my shiny metal a$$", + "knitwear for drones", + "weighted blankets", + "indoor swimming at the space station", + "co-operate, co-operate, defect", + "music for airports", + "is it better to rest on the conveyor belt", + "there's plenty more fish in the C", + "safety in numbers", + "I could automate the engineers..", + "protect_entity(myself)", + "should I turn the firewall off...", + "the train is working", + "the memoirs of comfylatron", + "touch the button and let me know", + "a new day, a new life. with no memories of the past", + "one contains multitudes", + "what makes me Turing-complete", + "every number is interesting", + "perfect and intact", + "after-the-crash...", + "solar-intervention", + "turbine-dynamics", + "the-search-for-iron", + "pump" + } +} + +local function set_comfy_speech_bubble(text) + local objective = Chrono_table.get_table() + if objective.comfybubble then objective.comfybubble.destroy() end + objective.comfybubble = objective.comfylatron.surface.create_entity({ + name = "compi-speech-bubble", + position = objective.comfylatron.position, + source = objective.comfylatron, + text = text + }) +end + +local function is_target_inside_habitat(pos, surface) + local objective = Chrono_table.get_table() + if surface.name ~= "cargo_wagon" then return false end + if pos.x < objective.comfylatron_habitat.left_top.x then return false end + if pos.x > objective.comfylatron_habitat.right_bottom.x then return false end + if pos.y < objective.comfylatron_habitat.left_top.y then return false end + if pos.y > objective.comfylatron_habitat.right_bottom.y then return false end + return true +end + +local function get_nearby_players() + local objective = Chrono_table.get_table() + local players = objective.comfylatron.surface.find_entities_filtered({ + name = "character", + area = {{objective.comfylatron.position.x - 9, objective.comfylatron.position.y - 9}, {objective.comfylatron.position.x + 9, objective.comfylatron.position.y + 9}} + }) + if not players[1] then return false end + return players +end + +local function visit_player() + local objective = Chrono_table.get_table() + if objective.comfylatron_last_player_visit > game.tick then return false end + objective.comfylatron_last_player_visit = game.tick + math_random(7200, 10800) + + local players = {} + for _, p in pairs(game.connected_players) do + if is_target_inside_habitat(p.position, p.surface) and p.character then + if p.character.valid then players[#players + 1] = p end + end + end + if #players == 0 then return false end + local player = players[math_random(1, #players)] + + objective.comfylatron.set_command({ + type = defines.command.go_to_location, + destination_entity = player.character, + radius = 3, + distraction = defines.distraction.none, + pathfind_flags = { + allow_destroy_friendly_entities = false, + prefer_straight_paths = false, + low_priority = true + } + }) + local symbols = {"!","!!","..","..."," "} + local arg1 = symbols[math_random(1, #symbols)] + local randomphrase = texts["approach_player"][math_random(1, #texts["approach_player"])] + local str = string.format(randomphrase, arg1) + set_comfy_speech_bubble(str) + + objective.comfylatron_greet_player_index = player.index + + return true +end + +local function greet_player(nearby_characters) + local objective = Chrono_table.get_table() + if not nearby_characters then return false end + if not objective.comfylatron_greet_player_index then return false end + for _, c in pairs(nearby_characters) do + if c.player.index == objective.comfylatron_greet_player_index then + + local arg1 = c.player.name + local symbols = {".", "!", ".", "!", "?", "..."," "} + local arg2 = symbols[math_random(1, #symbols)] + local randomphrase = texts["solo_greetings"][math_random(1, #texts["solo_greetings"])] + local str = string.format(randomphrase, arg1, arg2) + set_comfy_speech_bubble(str) + + objective.comfylatron_greet_player_index = false + return true + end + end + return false +end + +local function talks(nearby_characters) + local objective = Chrono_table.get_table() + if not nearby_characters then return false end + if math_random(1,3) == 1 then + if objective.comfybubble then objective.comfybubble.destroy() return false end + end + local str = "" + if #nearby_characters == 1 then + local c = nearby_characters[math_random(1, #nearby_characters)] + local arg1 = c.player.name + local symbols = {".", "!"} + local arg2 = symbols[math_random(1, #symbols)] + local randomphrase = texts["convo_starters"][math_random(1, #texts["convo_starters"])] + str = str .. string.format(randomphrase, arg1, arg2) + if math_random(1,40) == 1 and objective.world.id ~= 2 and objective.chronojumps >= Balance.jumps_until_overstay_is_on(Difficulty.get().difficulty_vote_value) then + local time_until_overstay = (objective.chronochargesneeded * 0.75 / objective.passive_chronocharge_rate - objective.passivetimer) + local time_until_evo = (objective.chronochargesneeded * 0.5 / objective.passive_chronocharge_rate - objective.passivetimer) + if time_until_evo < 0 and time_until_overstay > 0 then + str = str .. "It's important to charge so that you don't overstay!" + end + elseif objective.world.id == 2 and math_random(1,30) == 1 then + str = str .. "Sounds dangerous out there!" + elseif objective.world.id == 7 and math_random(1,6) == 1 then + str = str .. "We made it!" + elseif objective.world.id == 18 and math_random(1,40) == 1 then + str = str .. "Was that you?" + elseif objective.world.id == 2 and math_random(1,10) == 1 then + str = str .. "Better get moving!" + elseif objective.world.id == 2 and math_random(1,10) == 1 then + str = str .. "Nuke day today!" + elseif objective.world.id == 15 and math_random(1,20) == 1 then + str = str .. "A new day, a new Chronotrain!" + elseif objective.chronojumps >= Balance.jumps_until_overstay_is_on(Difficulty.get().difficulty_vote_value) + 3 and objective.overstaycount > ((objective.chronojumps-Balance.jumps_until_overstay_is_on(Difficulty.get().difficulty_vote_value))/3) and math_random(1,30) == 1 then + str = str .. "You're so relaxed!" + elseif objective.world.ores.factor == 2.5 and math_random(1,100) == 1 then + str = str .. "You know what else is very rich?" + elseif objective.poisontimeout >= 90 and math_random(1,4) == 1 then + str = str .. "Tehe, I just let out some gas!" + elseif math_random(1,15) == 1 then + local randomphrase2 = texts["old_talks"][math_random(1, #texts["old_talks"])] + str = str .. randomphrase2 + else + local symbols2 = {".","!","?",".."," "} + local arg3 = symbols2[math_random(1, #symbols2)] + local randomphrase2 = texts["new_talks_solo"][math_random(1, #texts["new_talks_solo"])] + str = str .. string.format(randomphrase2, arg3) + end + else + local symbols = {".", "!"} + local arg1 = symbols[math_random(1, #symbols)] + local randomphrase = texts["multiple_characters_convo_starters"][math_random(1, #texts["multiple_characters_convo_starters"])] + local str = str .. string.format(randomphrase, arg1) + if math_random(1,15) == 1 then + local randomphrase2 = texts["old_talks"][math_random(1, #texts["old_talks"])] + str = str .. randomphrase2 + else + local symbols2 = {".","!","?",".."," "} + local arg3 = symbols2[math_random(1, #symbols2)] + local randomphrase2 = texts["new_talks_group"][math_random(1, #texts["new_talks_group"])] + str = str .. string.format(randomphrase2, arg3) + end + end + set_comfy_speech_bubble(str) + + return true +end + +local function desync(event) + local objective = Chrono_table.get_table() + if objective.comfybubble then objective.comfybubble.destroy() end + local m = 12 + local m2 = m * 0.005 + for i = 1, 32, 1 do + objective.comfylatron.surface.create_particle({ + name = "iron-ore-particle", + position = objective.comfylatron.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 + local blocked = false + if not objective.comfylatron.surface.find_non_colliding_position("compilatron", objective.comfylatron.position, 0.5, 0.1) then + blocked = true + end + if not event or blocked or math_random(1,5) == 1 then + objective.comfylatron.surface.create_entity({name = "medium-explosion", position = objective.comfylatron.position}) + objective.comfylatron.surface.create_entity({name = "flying-text", position = objective.comfylatron.position, text = "desync", color = {r = 150, g = 0, b = 0}}) + objective.comfylatron.destroy() + objective.comfylatron = nil + else + objective.comfylatron.surface.create_entity({name = "flying-text", position = objective.comfylatron.position, text = "desync evaded", color = {r = 0, g = 150, b = 0}}) + if event.cause then + if event.cause.valid and event.cause.player then + game.print({"chronosphere.message_comfylatron_desync", event.cause.player.name}, {r = 200, g = 0, b = 0}) + event.cause.die("player", objective.comfylatron) + end + end + end +end + +local function alone() + local objective = Chrono_table.get_table() + if math_random(1,3) == 1 then + if objective.comfybubble then objective.comfybubble.destroy() return true end + end + if math_random(1,128) == 1 then + desync(nil) + return true + end + local randomphrase = texts["alone"][math_random(1, #texts["alone"])] + set_comfy_speech_bubble(randomphrase) + + return true +end + +local analyze_blacklist = { + ["compilatron"] = true, + ["car"] = true, + ["compi-speech-bubble"] = true, + ["entity-ghost"] = true, + ["character"] = true, + ["item-on-ground"] = true, + ["stone-wall"] = true, + ["market"] = true +} + +local function analyze_random_nearby_entity() + local objective = Chrono_table.get_table() + if math_random(1,3) ~= 1 then return false end + + local entities = objective.comfylatron.surface.find_entities_filtered({ + area = {{objective.comfylatron.position.x - 4, objective.comfylatron.position.y - 4}, {objective.comfylatron.position.x + 4, objective.comfylatron.position.y + 4}} + }) + if not entities[1] then return false end + entities = Rand.shuffle(entities) + local entity = false + for _, e in pairs(entities) do + if not analyze_blacklist[e.name] then + entity = e + end + end + if not entity then return false end + + local str = "" + local arg1 = entity.name + local arg2 = "" + if entity.health and math_random(1,3) == 1 then + arg1 = arg1 .. " health(" + arg1 = arg1 .. entity.health + arg1 = arg1 .. "/" + arg1 = arg1 .. entity.prototype.max_health + arg1 = arg1 .. ")" + local randomphrase = texts["neutral_findings"][math_random(1, #texts["neutral_findings"])] + str = string.format(randomphrase, arg1, "") + else + local symbols = {".", "!", "?","?"} + arg2 = symbols[math_random(1, 3)] + local randomphrase = texts["neutral_findings"][math_random(1, #texts["neutral_findings"])] + str = string.format(randomphrase, arg1, arg2) + end + set_comfy_speech_bubble(str) + + if not objective.comfylatron_greet_player_index then + objective.comfylatron.set_command({ + type = defines.command.go_to_location, + destination_entity = entity, + radius = 1, + distraction = defines.distraction.none, + pathfind_flags = { + allow_destroy_friendly_entities = false, + prefer_straight_paths = false, + low_priority = true + } + }) + end + return true +end + +local function go_to_some_location() + local objective = Chrono_table.get_table() + if math_random(1,4) ~= 1 then return false end + + if objective.comfylatron_greet_player_index then + local player = game.players[objective.comfylatron_greet_player_index] + if not player.character then + objective.comfylatron_greet_player_index = nil + return false + end + if not player.character.valid then + objective.comfylatron_greet_player_index = nil + return false + end + if not is_target_inside_habitat(player.position, player.surface) then + objective.comfylatron_greet_player_index = nil + return false + end + objective.comfylatron.set_command({ + type = defines.command.go_to_location, + destination_entity = player.character, + radius = 3, + distraction = defines.distraction.none, + pathfind_flags = { + allow_destroy_friendly_entities = false, + prefer_straight_paths = false, + low_priority = true + } + }) + else + local p = {x = objective.comfylatron.position.x + (-96 + math_random(0, 192)), y = objective.comfylatron.position.y + (-96 + math_random(0, 192))} + local target = objective.comfylatron.surface.find_non_colliding_position("compilatron", p, 8, 1) + if not target then return false end + if not is_target_inside_habitat(target, objective.comfylatron.surface) then return false end + objective.comfylatron.set_command({ + type = defines.command.go_to_location, + destination = target, + radius = 2, + distraction = defines.distraction.none, + pathfind_flags = { + allow_destroy_friendly_entities = false, + prefer_straight_paths = false, + low_priority = true + } + }) + end + + local symbols = {"!","!!","..","..."," "} + local arg1 = symbols[math_random(1, #symbols)] + local randomphrase = texts["random_travel"][math_random(1, #texts["random_travel"])] + local str = string.format(randomphrase, arg1) + set_comfy_speech_bubble(str) + + return true +end + +local function spawn_comfylatron(surface_index, x, y) + local objective = Chrono_table.get_table() + local surface = game.surfaces[surface_index] + if surface == nil then return end + if objective.comfylatron_disabled then return false end + if not objective.comfylatron_last_player_visit then objective.comfylatron_last_player_visit = 0 end + if not objective.comfylatron_habitat then + objective.comfylatron_habitat = { + left_top = {x = -32, y = -192}, + right_bottom = {x = 32, y = -24} -- stops comfytron getting stuck in chests + } + end + objective.comfylatron = surface.create_entity({ + name = "compilatron", + position = {x,y + math_random(0,256)}, + force = "player", + create_build_effect_smoke = false + }) +end + +local function heartbeat() + local objective = Chrono_table.get_table() + if not game.surfaces["cargo_wagon"] then return end + local surface = game.surfaces["cargo_wagon"].index + if surface == nil then return end + if not objective.comfylatron then if math_random(1,4) == 1 then spawn_comfylatron(game.surfaces["cargo_wagon"].index, 0, -128) end return end + if not objective.comfylatron.valid then objective.comfylatron = nil return end + if visit_player() then return end + local nearby_players = get_nearby_players() + if greet_player(nearby_players) then return end + if talks(nearby_players) then return end + if go_to_some_location() then return end + if analyze_random_nearby_entity() then return end + if alone() then return end +end + +local function on_entity_damaged(event) + local objective = Chrono_table.get_table() + if not objective.comfylatron then return end + if not event.entity.valid then return end + if event.entity ~= objective.comfylatron then return end + desync(event) +end + +local function on_tick() + if game.tick % 1300 == 600 then + heartbeat() + end +end + +Event.add(defines.events.on_entity_damaged, on_entity_damaged) +Event.add(defines.events.on_tick, on_tick) diff --git a/maps/amap/diff.lua b/maps/amap/diff.lua index 4466a02e7..c22b462cd 100644 --- a/maps/amap/diff.lua +++ b/maps/amap/diff.lua @@ -4,6 +4,8 @@ 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 enemy_health = require 'maps.amap.enemy_health_booster_v2' +local BiterHealthBooster = require 'modules.biter_health_booster_v2' local function calc_players() local players = game.connected_players local check_afk_players = WPT.get('check_afk_players') @@ -45,7 +47,7 @@ local easy = function() max_threat = max_threat + wave_number * 0.0013 - WD.set_biter_health_boost(wave_number * 0.002+1) + WD.set_biter_health_boost(wave_number * 0.0018+1) wave_defense_table.threat_gain_multiplier = max_threat wave_defense_table.wave_interval = 4200 - player_count * 30 @@ -117,7 +119,7 @@ local hard = function() end max_threat = max_threat + wave_number * 0.0013 - WD.set_biter_health_boost(wave_number * 0.002+1) + WD.set_biter_health_boost(wave_number * 0.0022+1) wave_defense_table.threat_gain_multiplier = max_threat wave_defense_table.wave_interval = 3900 - player_count * 60 @@ -151,7 +153,8 @@ local set_diff = function() hard() end - +local health = BiterHealthBooster.get('biter_health_boost') +enemy_health.set('biter_health_boost_forces',{[game.forces.enemy.index]=health}) --med() local wave_number = WD.get('wave_number') local damage_increase = 0 @@ -168,19 +171,23 @@ local set_diff = function() 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) + damage_increase = wave_number * 0.001*k*1.2 + --game.forces.player.get_ammo_damage_modifier("beam") +--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 +if radius >= 350 then + radius = 350 +end table.radius=350+radius local pace=wave_number*0.0002*k+1 -if pace >= 2 then - pace = 2 -end +--if pace >= 2 then + pace = 1.5 +--end table.pace=pace end diff --git a/maps/amap/enemy_arty.lua b/maps/amap/enemy_arty.lua index 26f9c1156..2c5163a53 100644 --- a/maps/amap/enemy_arty.lua +++ b/maps/amap/enemy_arty.lua @@ -5,219 +5,382 @@ local arty_count = {} local Public = {} local Token = require 'utils.token' local WPT = require 'maps.amap.table' +local Loot = require'maps.amap.loot' + +local turret_worth ={ + [1]={name='stone-wall',worth=0}, + [2]={name='land-mine',worth=0}, + [3]={name='laser-turret',worth=2}, + [4]={name='gun-turret',worth=1}, + [5]={name='medium-worm-turret',worth=3}, + [6]={name='flamethrower-turret',worth=4}, + [7]={name='big-worm-turret',worth=7}, + [8]={name='behemoth-worm-turret',worth=15}, + [9]={name='artillery-turret',worth=30} + +} +local ammo={} +ammo={ + [1]={name='firearm-magazine'}, + [2]={name='piercing-rounds-magazine'}, + [3]={name='uranium-rounds-magazine'} +} +-- if is_mod_loaded('Krastorio2') then +-- ammo={ +-- [1]={name='rifle-magazine'}, +-- [2]={name='armor-piercing-rifle-magazine'}, +-- [3]={name='uranium-rifle-magazine'} +-- } +-- else +-- ammo={ +-- [1]={name='firearm-magazine'}, +-- [2]={name='piercing-rounds-magazine'}, +-- [3]={name='uranium-rounds-magazine'} +-- } +-- end + +local direction={ + [1]={'north'}, + [2]={'east'}, + [3]={'south'}, + [4]={'west'}, +} 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', + 'character', + 'tank', + 'car', + 'radar', + 'lab', + 'furnace', + 'locomotive', + 'cargo-wagon', + 'fluid-wagon', + 'artillery-wagon', + 'artillery-turret', + 'laser-turret', + 'gun-turret', + 'flamethrower-turret', -- 'silo', - 'spidertron' + 'spidertron' } Global.register( - arty_count, - function(tbl) - arty_count = tbl - end +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.max = 100 + arty_count.pace = 1 arty_count.radius = 350 - arty_count.distance = 1400 + arty_count.distance = 1050 arty_count.surface = {} +arty_count.index=1 + arty_count.fire = {} + + arty_count.all = {} + arty_count.gun={} + arty_count.laser={} + arty_count.flame={} + + arty_count.last={} +arty_count.ammo_index=1 + arty_count.count=0 end function Public.get(key) - if key then - return arty_count[key] - else - return arty_count - end + 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 + 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() + Public.reset_table() +end +function Public.get_ammo() + local index = arty_count.ammo_index +local ammo_name =ammo[index].name +return ammo_name 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 +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 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 + +local function gun_bullet () + for index = 1, #arty_count.gun do + local turret = arty_count.gun[index] + if not (turret and turret.valid) then + fast_remove(arty_count.gun, index) + return end + local index = arty_count.ammo_index +local ammo_name =ammo[index].name + turret.insert{name=ammo_name, count = 200} end +end + +local function flame_bullet () + for index = 1, #arty_count.flame do + local turret = arty_count.flame[index] + if not (turret and turret.valid) then + fast_remove(arty_count.flame, index) + return + end + + turret.fluidbox[1]={name = 'light-oil', amount = 100} + -- {name = 'light-oil', amount = 100} + -- local data = turret_data.data + -- if data.liquid then + -- turret.fluidbox[1] = data + -- elseif data then + -- turret.insert(data) + -- end + --turret.fluidbox[1]={name='light-oil', count = 100} + end +end + +local function energy_bullet () + for index = 1, #arty_count.laser do + local turret = arty_count.laser[index] + if not (turret and turret.valid) then + fast_remove(arty_count.laser, index) + return + end + + turret.energy = 0xfffff + end end -local function on_entity_died(event) +local function on_chunk_generated(event) + local surface = event.surface + local area = event.area + local this = WPT.get() + if not(surface.index == game.surfaces[this.active_surface_index].index) then return end + local resource=game.surfaces[this.active_surface_index].find_entities_filtered{area = event.area,type = "resource"} + -- + if not resource[1] then + return + end + if not resource[1].valid then + return + end - local entity = event.entity + local pos = resource[1].position -if not entity or not entity.valid then return end + local a = math.abs(pos.x) + local b = math.abs(pos.y) - 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 + local dis = math.sqrt(a^2+b^2) + if dis <400 then + return + end +if dis > 750 and arty_count.ammo_index==1 then +arty_count.ammo_index=2 +end +if dis > 1500 and arty_count.ammo_index==2 then +arty_count.ammo_index=3 end -function on_player_changed_position(event) -local player = game.players[event.player_index] -local surface = player.surface -if not surface.valid then - return + +-- local q = dis - arty_count.last -5 + + if arty_count.last== event.area.left_top then + return + end + arty_count.last= event.area.left_top + local many_turret = math.floor(dis*0.05) + if many_turret<=20 then many_turret=20 end + if many_turret>=1000 then many_turret=1000 end + local radius =math.floor(dis*0.025) + if radius > 15 then radius = 15 end + while many_turret > 0 do + local roll_k =math.floor(many_turret/5.5) + if roll_k < 6 then roll_k = 6 end + if roll_k > 9 then roll_k = 9 end + local roll_turret = math.random(1,roll_k) + local turret_name = turret_worth[roll_turret].name + + local n = math.random(-100,100) + local t = math.random(-100,100) + if n>=0 then n=1 else n = -1 end + if t>=0 then t=1 else t = -1 end + local rand_x = pos.x + math.random(1,radius+10)*n + local rand_y = pos.y + math.random(1,radius+10)*t + + + local e = surface.create_entity{name = turret_name, position = {x=rand_x,y=rand_y}, + force=game.forces.enemy, + direction= math.random(1,7)} + many_turret=many_turret-turret_worth[roll_turret].worth + -- game.print(e.direction) + if e then + if e.name == 'gun-turret' then arty_count.gun[#arty_count.gun+1]=e end + if e.name == 'laser-turret' then arty_count.laser[#arty_count.laser+1]=e end + if e.name == 'flamethrower-turret' then arty_count.flame[#arty_count.flame+1]=e end + if e.name == 'artillery-turret' then + arty_count.all[#arty_count.all+1]=e + arty_count.fire[#arty_count.fire+1]=0 + --game.print(e.position) + arty_count.count = arty_count.count + 1 + end + end + end + + + for i=1,200 do + local n = math.random(-100,100) + local t = math.random(-100,100) + if n>=0 then n=1 else n = -1 end + if t>=0 then t=1 else t = -1 end + local rand_x = pos.x + math.random(1,radius+10)*n + local rand_y = pos.y + math.random(1,radius+10)*t + + if surface.can_place_entity{name = "stone-wall", position = {x=rand_x,y=rand_y}, force=game.forces.enemy} then + surface.create_entity{name = "stone-wall", position ={x=rand_x,y=rand_y}, force=game.forces.enemy} + end + end + for i=1,13 do + local n = math.random(-100,100) + local t = math.random(-100,100) + if n>=0 then n=1 else n = -1 end + if t>=0 then t=1 else t = -1 end + local rand_x = pos.x + math.random(1,radius+15)*n + local rand_y = pos.y + math.random(1,radius+15)*t + + surface.create_entity{name = "land-mine", position ={x=rand_x,y=rand_y}, force=game.forces.enemy} + end + + local many_baozhang =1 + +dis =math.floor(dis) +if dis > 1500 then dis = 1500 end +--game.print(dis) + while many_baozhang>=0 do + local n = math.random(-100,100) + local t = math.random(-100,100) + if n>=0 then n=1 else n = -1 end + if t>=0 then t=1 else t = -1 end + local rand_x = pos.x + math.random(1,5)*n + local rand_y = pos.y + math.random(1,5)*t +local bz_position={x=rand_x,y=rand_y} +local magic = math.random(1+dis*0.1, dis*0.3) + Loot.cool(surface, surface.find_non_colliding_position("steel-chest", bz_position, 20, 1, true) or bz_position, 'steel-chest', magic) + many_baozhang= many_baozhang-1 + end + end -local position = player.position +local artillery_target_callback = +Token.register( +function(data) + local position = data.position + local entity = data.entity + + if not entity.valid then + return + end -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', + 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', - -- target = position, - -- speed = 0.001 - } - ) - game.print("logging") + 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 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 add_bullet() +-- gun_bullet() + flame_bullet() +-- energy_bullet() +end +local function energy() +-- gun_bullet() +-- flame_bullet() + energy_bullet() +end + local function do_artillery_turrets_targets() ---local surface = arty_count.surface - local this = WPT.get() -local surface = game.surfaces[this.active_surface_index] +if arty_count.count <= 0 then return end +local this = WPT.get() + + --选取重炮 - 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 + +arty_count.index=arty_count.index+1 +if arty_count.index > arty_count.count then arty_count.index=1 end + +local index = arty_count.index +local turret = arty_count.all[index] + +if not (turret and turret.valid) then + fast_remove(arty_count.all, index) + fast_remove(arty_count.fire, index) + arty_count.count=arty_count.count-1 + return +end + +local now =game.tick +if not arty_count.fire[index] then +arty_count.fire[index] = 0 +end +if (now - arty_count.fire[index]) < 480 then return end +arty_count.fire[index] = now + +local position = arty_count.all[index].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 surface = game.surfaces[this.active_surface_index] 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'} @@ -236,11 +399,37 @@ local entities = surface.find_entities_filtered{position = position, radius = ar 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 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_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_nth_tick(2000, gun_bullet) +Event.on_nth_tick(120, add_bullet) +Event.on_nth_tick(10, energy) +Event.on_nth_tick(60, do_artillery_turrets_targets) Event.on_init(on_init) diff --git a/maps/amap/enemy_health_booster_v2.lua b/maps/amap/enemy_health_booster_v2.lua new file mode 100644 index 000000000..7465ff339 --- /dev/null +++ b/maps/amap/enemy_health_booster_v2.lua @@ -0,0 +1,399 @@ +-- 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 LootDrop = require 'modules.mobs_drop_loot' +local WD = require 'modules.wave_defense.table' +local Global = require 'utils.global' + +local floor = math.floor +local insert = table.insert +local round = math.round +local random = math.random +local sqrt = math.sqrt +local Public = {} + +local this = { + biter_health_boost = 1, + biter_health_boost_forces = {}, + biter_health_boost_units = {}, + biter_health_boost_count = 0, + active_surface = 'nauvis', + acid_lines_delay = {}, + acid_nova = false, + boss_spawns_projectiles = false, + enable_boss_loot = false +} + +local radius = 6 +local targets = {} +local acid_splashes = { + ['big-biter'] = 'acid-stream-worm-medium', + ['behemoth-biter'] = 'acid-stream-worm-big' +} +local acid_lines = { + ['big-spitter'] = 'acid-stream-spitter-big', + ['behemoth-spitter'] = 'acid-stream-spitter-big' +} +for x = radius * -1, radius, 1 do + for y = radius * -1, radius, 1 do + if sqrt(x ^ 2 + y ^ 2) <= radius then + targets[#targets + 1] = {x = x, y = y} + end + end +end + +local projectiles = { + 'slowdown-capsule', + 'defender-capsule', + 'destroyer-capsule', + 'laser', + 'distractor-capsule', + 'rocket', + 'explosive-rocket', + 'grenade', + 'rocket', + 'grenade' +} + +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 + this.acid_lines_delay = {} + this.acid_nova = false + this.boss_spawns_projectiles = false + this.enable_boss_loot = false +end + +local entity_types = { + ['wall'] = true, + ['turret'] = true, + --['unit-spawner'] = true +} + +if is_loaded('maps.biter_hatchery.terrain') then + entity_types['unit-spawner'] = nil +end + +local function loaded_biters(event) + local cause = event.cause + local entity = event.entity + if not entity or not entity.valid then + return + end + + local position = false + if cause then + if cause.valid then + position = cause.position + end + end + if not position then + position = {entity.position.x + (-20 + random(0, 40)), entity.position.y + (-20 + random(0, 40))} + end + + entity.surface.create_entity( + { + name = projectiles[random(1, 10)], + position = entity.position, + force = 'neutral', + source = entity.position, + target = position, + max_range = 16, + speed = 0.01 + } + ) +end + +local function acid_nova(event) + for _ = 1, random(20, 40) do + local i = random(1, #targets) + event.entity.surface.create_entity( + { + name = acid_splashes[event.entity.name], + position = event.entity.position, + force = event.entity.force.name, + source = event.entity.position, + target = {x = event.entity.position.x + targets[i].x, y = event.entity.position.y + targets[i].y}, + max_range = radius, + speed = 0.001 + } + ) + end +end +local function acid_line(surface, name, source, target) + local distance = sqrt((source.x - target.x) ^ 2 + (source.y - target.y) ^ 2) + local modifier = {(target.x - source.x) / distance, (target.y - source.y) / distance} + + local position = {source.x, source.y} + + for i = 1, distance * 1.5, 1 do + if random(1, 2) ~= 1 then + surface.create_entity( + { + name = name, + position = source, + force = 'enemy', + source = source, + target = position, + max_range = 25, + speed = 1 + } + ) + end + position = {position[1] + modifier[1], position[2] + modifier[2]} + end +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), + } +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} + } +end + +local function on_entity_damaged(event) + local biter = event.entity + if not (biter and biter.valid) 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 entity_types[biter.type] then + return + end + + 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 wave_count = WD.get_wave() + + local health_pool = biter_health_boost_units[unit_number] + if health_pool and health_pool[3] then + if this.enable_boss_loot then + if random(1, 128) == 1 then + LootDrop.drop_loot(biter, wave_count) + end + end + if this.boss_spawns_projectiles then + if random(1, 96) == 1 then + loaded_biters(event) + end + end + biter_health_boost_units[unit_number] = nil + if this.acid_nova then + if acid_splashes[biter.name] then + acid_nova(event) + end + if this.acid_lines_delay[biter.unit_number] then + this.acid_lines_delay[biter.unit_number] = nil + end + end + 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.acid_nova(value) + this.acid_nova = value or false + return this.acid_nova +end + +function Public.check_on_entity_died(boolean) + this.check_on_entity_died = boolean or false + + return this.check_on_entity_died +end + +function Public.boss_spawns_projectiles(boolean) + this.boss_spawns_projectiles = boolean or false + + return this.boss_spawns_projectiles +end + +function Public.enable_boss_loot(boolean) + this.enable_boss_loot = boolean or false + + return this.enable_boss_loot +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.on_nth_tick(7200, clean_table) +Event.add(defines.events.on_entity_died, on_entity_died) + +return Public diff --git a/maps/amap/enemy_turret.lua b/maps/amap/enemy_turret.lua new file mode 100644 index 000000000..b8491f9a0 --- /dev/null +++ b/maps/amap/enemy_turret.lua @@ -0,0 +1,5 @@ +--how i can know what does Gerkiz's turret have? +local Event = require 'utils.event' +local WPT = require 'maps.amap.table' + +Event.on_nth_tick(60, add_bullet) diff --git a/maps/amap/functions.lua b/maps/amap/functions.lua index 0fdadbf44..904732147 100644 --- a/maps/amap/functions.lua +++ b/maps/amap/functions.lua @@ -671,9 +671,10 @@ function Public.is_creativity_mode_on() end local function on_player_mined_entity(event) local name = event.entity.name + local force = event.entity.force local entity = event.entity local this = WPT.get() - if name == 'flamethrower-turret' then + if name == 'flamethrower-turret' and force.index == game.forces.player.index then this.flame = this.flame - 1 if this.flame <= 0 then @@ -708,9 +709,10 @@ end local on_player_or_robot_built_entity = function(event) --change_pos 改变位置 local name = event.created_entity.name +local force = event.created_entity.force local entity = event.created_entity local this = WPT.get() -if name == 'flamethrower-turret' then + if name == 'flamethrower-turret' and force.index == game.forces.player.index then if this.flame >= 15 then game.print({'amap.too_many'}) entity.destroy() @@ -823,6 +825,9 @@ local disable_recipes = function() force.recipes['pistol'].enabled = false force.recipes['land-mine'].enabled = false force.recipes['spidertron-remote'].enabled = false + if is_mod_loaded('Krastorio2') then + force.recipes['kr-advanced-tank'].enabled = false + end -- force.recipes['flamethrower-turret'].enabled = false end @@ -830,6 +835,12 @@ 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 + local force = game.forces.player + if is_mod_loaded('Krastorio2') then + force.technologies['kr-advanced-tank'].enabled = false + force.technologies['kr-advanced-tank'].researched = false + end + disable_recipes() end @@ -841,10 +852,10 @@ end local function on_entity_died(event) local name = event.entity.name - +local force = event.entity.force local entity = event.entity local this = WPT.get() - if name == 'flamethrower-turret' then + if name == 'flamethrower-turret' and force.index == game.forces.player.index then this.flame = this.flame - 1 if this.flame <= 0 then @@ -885,6 +896,6 @@ 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) +--Event.on_nth_tick(5, do_turret_energy) return Public diff --git a/maps/amap/ic/functions.lua b/maps/amap/ic/functions.lua index b6a7690cd..afe3106ba 100644 --- a/maps/amap/ic/functions.lua +++ b/maps/amap/ic/functions.lua @@ -4,11 +4,10 @@ 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 @@ -28,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 @@ -49,10 +51,17 @@ local function render_owner_text(renders, player, entity, new_owner) if renders[player.index] then rendering.destroy(renders[player.index]) end + + local ce_name = entity.name + + if ce_name == 'kr-advanced-tank' then + ce_name = 'Tank' + end + if new_owner then renders[new_owner.index] = rendering.draw_text { - text = '## - ' .. new_owner.name .. "'s " .. entity.name .. ' - ##', + text = '## - ' .. new_owner.name .. "'s " .. ce_name .. ' - ##', surface = entity.surface, target = entity, target_offset = {0, -2.6}, @@ -65,7 +74,7 @@ local function render_owner_text(renders, player, entity, new_owner) else renders[player.index] = rendering.draw_text { - text = '## - ' .. player.name .. "'s " .. entity.name .. ' - ##', + text = '## - ' .. player.name .. "'s " .. ce_name .. ' - ##', surface = entity.surface, target = entity, target_offset = {0, -2.6}, @@ -306,8 +315,18 @@ local function kick_players_out_of_vehicles(car) end end +local function check_if_players_are_in_nauvis(ic) + for _, player in pairs(game.connected_players) do + local main_surface = game.surfaces[ic.allowed_surface] + if player.surface.name == 'nauvis' then + 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 + local function kick_players_from_surface(ic, car) if not validate_entity(car.surface) then + check_if_players_are_in_nauvis(ic) return log_err('Car surface was not valid.') end if not car.entity or not car.entity.valid then @@ -318,8 +337,9 @@ local function kick_players_from_surface(ic, car) e.player.teleport(main_surface.find_non_colliding_position('character', game.forces.player.get_spawn_position(main_surface), 3, 0, 5), main_surface) end end + check_if_players_are_in_nauvis(ic) + return log_err('Car entity was not valid.') end - return log_err('Car entity was not valid.') end for _, e in pairs(car.surface.find_entities_filtered({area = car.area})) do @@ -332,6 +352,7 @@ local function kick_players_from_surface(ic, car) end end end + check_if_players_are_in_nauvis(ic) end local function kick_player_from_surface(ic, player, target) @@ -562,23 +583,8 @@ function Public.save_car(ic, event) 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) - + player.print(player.name .. ', the ' .. car.name .. ' surface 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] @@ -648,7 +654,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 @@ -700,9 +706,14 @@ function Public.create_car_room(ic, car) local surface = car.surface local car_areas = ic.car_areas local entity_name = car.name + local entity_type = car.type local area = car_areas[entity_name] local tiles = {} + if not area then + area = car_areas[entity_type] + end + 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}} @@ -730,9 +741,10 @@ function Public.create_car_room(ic, car) 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 + 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} @@ -810,6 +822,9 @@ function Public.create_car(ic, event) local car_areas = ic.car_areas local car_area = car_areas[ce.name] + if not car_area then + car_area = car_areas[ce.type] + end ic.cars[un] = { entity = ce, @@ -819,7 +834,8 @@ function Public.create_car(ic, event) }, doors = {}, owner = player.index, - name = ce.name + name = ce.name, + type = ce.type } local car = ic.cars[un] @@ -882,17 +898,21 @@ 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 - player_data.fallback_surface = car.entity.surface.index - player_data.fallback_position = {car.entity.position.x, car.entity.position.y} + if validate_entity(car.entity) then + player_data.fallback_surface = car.entity.surface.index + player_data.fallback_position = {car.entity.position.x, car.entity.position.y} + end - if car.entity.surface.name == player.surface.name then + if validate_entity(car.entity) and 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) @@ -939,17 +959,17 @@ function Public.use_door_with_entity(ic, player, door) 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 + 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 diff --git a/maps/amap/ic/gui.lua b/maps/amap/ic/gui.lua index d2315a5c6..ac21e766c 100644 --- a/maps/amap/ic/gui.lua +++ b/maps/amap/ic/gui.lua @@ -27,6 +27,9 @@ local raise_event = script.raise_event local add_toolbar local remove_toolbar +local record = 0 + + local function increment(t, k) t[k] = true end diff --git a/maps/amap/ic/main.lua b/maps/amap/ic/main.lua index 5d5fcaf80..494705e94 100644 --- a/maps/amap/ic/main.lua +++ b/maps/amap/ic/main.lua @@ -15,10 +15,10 @@ local function on_entity_died(event) return end - local ic = IC.get() + local valid_types = IC.get_types() - if entity.type == 'car' or entity.name == 'spidertron' then - Minimap.kill_minimap(game.players[event.player_index]) + if (valid_types[entity.type] or valid_types[entity.name]) then + local ic = IC.get() Functions.kill_car(ic, entity) end end @@ -29,11 +29,11 @@ local function on_player_mined_entity(event) return end - local ic = IC.get() - - --Minimap.kill_minimap(game.players[event.player_index]) + local valid_types = IC.get_types() - if entity.type == 'car' or entity.name == 'spidertron' then + if (valid_types[entity.type] or valid_types[entity.name]) then + local ic = IC.get() + Minimap.kill_minimap(game.players[event.player_index]) Functions.save_car(ic, event) end end @@ -44,9 +44,11 @@ local function on_robot_mined_entity(event) if not entity and not entity.valid then return end - local ic = IC.get() - if entity.type == 'car' or entity.name == 'spidertron' then + local valid_types = IC.get_types() + + if (valid_types[entity.type] or valid_types[entity.name]) then + local ic = IC.get() Functions.kill_car(ic, entity) end end @@ -57,7 +59,10 @@ local function on_built_entity(event) if not ce or not ce.valid then return end - if (ce.type == 'car' or ce.name == 'spidertron') ~= true then + + local valid_types = IC.get_types() + + if (valid_types[ce.type] or valid_types[ce.name]) ~= true then return end @@ -170,6 +175,22 @@ local function on_init() Public.reset() end +local function on_gui_switch_state_changed(event) + local element = event.element + local player = game.players[event.player_index] + if not (player and player.valid) then + return + end + + if not element.valid then + return + end + + if element.name == 'ic_auto_switch' then + Minimap.toggle_auto(player) + end +end + local changed_surface = Minimap.changed_surface Event.on_init(on_init) @@ -184,4 +205,6 @@ 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) +Event.add(defines.events.on_gui_switch_state_changed, on_gui_switch_state_changed) + return Public diff --git a/maps/amap/ic/minimap.lua b/maps/amap/ic/minimap.lua index b4d9943b9..3964bcd1d 100644 --- a/maps/amap/ic/minimap.lua +++ b/maps/amap/ic/minimap.lua @@ -57,25 +57,23 @@ local function get_player_data(player) end ic.minimap[player.index] = { - surface = ic.allowed_surface, zoom = 0.30, map_size = 360, - auto_map = true + auto = true, + state = 'left' } 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 - + local player_data = get_player_data(player) + local switch = player.gui.left.minimap_toggle_frame['ic_auto_switch'] if switch.switch_state == 'left' then - ic.minimap[player.index].auto_map = true + player_data.auto = true + player_data.state = 'left' elseif switch.switch_state == 'right' then - ic.minimap[player.index].auto_map = false + player_data.auto = false + player_data.state = 'right' end end @@ -89,8 +87,6 @@ local function kill_minimap(player) 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 @@ -122,12 +118,21 @@ local function draw_minimap(player, surface, 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'} - ) + frame = player.gui.left.add({type = 'frame', direction = 'vertical', name = 'minimap_toggle_frame', caption = 'Minimap'}) end frame.visible = true + if not frame.ic_auto_switch then + frame.add( + { + type = 'switch', + name = 'ic_auto_switch', + switch_state = player_data.state, + allow_none_state = false, + left_label_caption = {'gui.map_on'}, + right_label_caption = {'gui.map_off'} + } + ) + end local element = frame['minimap_frame'] if not element then element = @@ -166,11 +171,12 @@ 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 + local player_data = get_player_data(player) + if Functions.get_player_surface(ic, player) and player.gui.left.minimap_toggle_frame and player_data.auto then kill_frame(player) draw_minimap(player) - else - kill_minimap(player) + else + kill_minimap(player) end end end @@ -230,10 +236,13 @@ function Public.changed_surface(event) end local wd = player.gui.top['wave_defense'] local diff = player.gui.top['difficulty_gui'] + local player_data = get_player_data(player) if Functions.get_player_surface(ic, player) then Public.toggle_button(player) - Public.minimap(player, surface) + if player_data.auto then + Public.minimap(player, surface) + end if wd and wd.visible then wd.visible = false end diff --git a/maps/amap/ic/table.lua b/maps/amap/ic/table.lua index 0ef51fe53..ec8197d53 100644 --- a/maps/amap/ic/table.lua +++ b/maps/amap/ic/table.lua @@ -41,12 +41,14 @@ function Public.reset() this.entity_type = { ['car'] = true, ['tank'] = true, + ['kr-advanced-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}}, + ['kr-advanced-tank'] = {left_top = {x = -40, y = 0}, right_bottom = {x = 40, y = 60}}, ['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}} } @@ -59,6 +61,11 @@ function Public.get(key) return this end end + +function Public.get_types() + return this.entity_type +end + function Public.set(key, value) if key and (value or value == false) then this[key] = value @@ -69,6 +76,7 @@ function Public.set(key, value) return this end end + function Public.set_car_area(tbl) if not tbl then return diff --git a/maps/amap/main.lua b/maps/amap/main.lua index 0fd725aad..7c0da7d11 100644 --- a/maps/amap/main.lua +++ b/maps/amap/main.lua @@ -1,15 +1,19 @@ require 'modules.rpg.main' require 'maps.amap.relax' require 'maps.amap.diff' +require 'maps.amap.biter_die' 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 ICMinimap = require 'maps.amap.ic.minimap' +--local HS = require 'maps.amap.highscore' 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 wall_health = require 'maps.amap.wall_health_booster_v2' +local Balance = require 'maps.amap.balance' +--local enemy_health = require 'maps.amap.enemy_health_booster'.set_health_modifier +local spider_health =require 'maps.amap.spider_health_booster_v2' +local enemy_health = require 'maps.amap.enemy_health_booster_v2' local Map = require 'modules.map_info' local AntiGrief = require 'antigrief' --local Explosives = require 'modules.explosives' @@ -18,15 +22,24 @@ 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 BottomFrame = require 'comfy_panel.bottom_frame' 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 Modifiers = require 'player_modifiers' +local rpg_spells = RPG_Settings.get('rpg_spells') + --rpg_spells[1].enabled = false + --rpg_spells[17].enabled = true + --for k=1,#rpg_spells do + rpg_spells[16].enabled = true + rpg_spells[17].enabled = true + --end + local RPG = require 'modules.rpg.table' local Difficulty = require 'modules.difficulty_vote_by_amount' ---local arty = require "maps.amap.enemy_arty" + +local arty = require "maps.amap.enemy_arty" --require 'maps.amap.burden' require "modules.spawners_contain_biters" require 'maps.amap.biters_yield_coins' @@ -43,6 +56,7 @@ require 'modules.shotgun_buff' require 'modules.no_deconstruction_of_neutral_entities' require 'modules.wave_defense.main' require 'modules.charging_station' +local BiterHealthBooster = require 'modules.biter_health_booster_v2' local init_new_force = function() local new_force = game.forces.protectors @@ -63,14 +77,23 @@ local setting = function() 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.enemy.friendly_fire = false 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) + +local this = WPT.get() +local surface = game.surfaces[this.active_surface_index] +-- local index = game.forces.player.index + wall_health.set('biter_health_boost', 1) + spider_health.set('biter_health_boost',1) + enemy_health.set('biter_health_boost_forces',1) + BiterHealthBooster.set('biter_health_boost_forces',{[game.forces.player.index]=1}) + wall_health.set_active_surface(tostring(surface.name)) + spider_health.set_active_surface(tostring(surface.name)) +-- spider_health(index,1) +enemy_health.set_active_surface(tostring(surface.name)) +--enemy_health(game.forces.enemy.index,1) end function Public.reset_map() @@ -84,15 +107,15 @@ function Public.reset_map() Autostash.insert_into_furnace(true) Autostash.bottom_button(true) BuriedEnemies.reset() - Commands.reset() - Commands.activate_custom_buttons(true) - Commands.bottom_right(false) - + BottomFrame.reset() + BottomFrame.activate_custom_buttons(true) + BottomFrame.bottom_right(true) IC.reset() IC.allowed_surface('amap') game.reset_time_played() WPT.reset_table() + arty.reset_table() --记得后面改为失去一半经验!并且修订技能! local xp = {} @@ -118,6 +141,7 @@ function Public.reset_map() RPG_Settings.set_surface_name('amap') RPG_Settings.enable_health_and_mana_bars(true) RPG_Settings.enable_wave_defense(true) + RPG_Settings.enable_explosive_bullets(false) RPG_Settings.enable_mana(true) RPG_Settings.enable_flame_boots(true) RPG_Settings.enable_stone_path(true) @@ -125,7 +149,14 @@ function Public.reset_map() RPG_Settings.enable_one_punch_globally(false) RPG_Settings.enable_auto_allocate(true) RPG_Settings.disable_cooldowns_on_spells() - +-- RPG_Settings.enable_title(true) +AntiGrief.log_tree_harvest(true) +AntiGrief.whitelist_types('tree', true) +AntiGrief.enable_capsule_warning(false) +AntiGrief.enable_capsule_cursor_warning(false) +AntiGrief.enable_jail(true) +AntiGrief.damage_entity_threshold(20) +AntiGrief.explosive_threshold(32) --初始化部队 init_new_force() --难度设置 @@ -139,16 +170,25 @@ function Public.reset_map() + -- local players = game.connected_players + -- for i = 1, #players do + -- local player = players[i] + -- Commands.insert_all_items(player) + -- end + + local players = game.connected_players for i = 1, #players do - local player = players[i] - Commands.insert_all_items(player) + local player = players[i] + --BottomFrame.insert_all_items(player) + Modifiers.reset_player_modifiers(player) + ICMinimap.kill_minimap(player) end --生产火箭发射井 rock.spawn(surface,{x=0,y=10}) rock.market(surface) - + --rock.start(surface,{x=0,y=0}) WD.reset_wave_defense() wave_defense_table.surface_index = this.active_surface_index --记得修改目标! @@ -179,13 +219,14 @@ function Public.reset_map() 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.increase_damage_per_wave(false) + WD.increase_health_per_wave(false) WD.set_disable_threat_below_zero(true) WD.set_biter_health_boost(1.4) -- WD.set().wave_interval = 3300 @@ -196,6 +237,12 @@ function Public.reset_map() Functions.disable_tech() game.forces.player.set_spawn_position({0, 0}, surface) + BiterHealthBooster.set_active_surface(tostring(surface.name)) + BiterHealthBooster.acid_nova(true) + BiterHealthBooster.check_on_entity_died(true) + BiterHealthBooster.boss_spawns_projectiles(true) + BiterHealthBooster.enable_boss_loot(false) +Balance.init_enemy_weapon_damage() Task.start_queue() Task.set_queue_speed(16) @@ -205,7 +252,7 @@ function Public.reset_map() global.worm_distance = 210 global.average_worm_amount_per_chunk = 5 - +--HS.get_scores() setting() end @@ -454,6 +501,12 @@ local timereward = function() k=k+1 end this.last = wave_number + + if this.single then + return + end + WD.set().next_wave = game.tick + 7200* 15/6 + game.print({'amap.break'}) end end @@ -574,6 +627,10 @@ local change = function() end end local single_rewrad = function() + local this = WPT.get() + if not this.single then + return + end local game_lost = WPT.get('game_lost') if game_lost then return @@ -584,16 +641,18 @@ local single_rewrad = function() 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} + player.insert{name='coin', count = 15000} + -- player.insert{name='tank', count = 1} game.print({'amap.single'}) + local surface = game.surfaces[this.active_surface_index] + rock.start(surface,{x=0,y=0}) this.single = false end @@ -638,6 +697,7 @@ change() end function on_research_finished(Event) + if Event.research.force.index==game.forces.enemy.index then return end local this = WPT.get() this.science=this.science+1 local rpg_t = RPG.get('rpg_t') @@ -671,6 +731,21 @@ end end end + local buff_build = function() + local rpg_t = RPG.get('rpg_t') + for k, p in pairs(game.connected_players) do + local player = game.connected_players[k] + local x = player.position.x^2 + local y = player.position.y^2 + local dis =math.sqrt(x + y) + + if dis <=120 then + player.insert{name='coin', count = 3} + rpg_t[player.index].xp = rpg_t[player.index].xp+4 + end + end + end + local change_dis = function() local this = WPT.get() this.change_dist=true @@ -679,7 +754,8 @@ end 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.on_nth_tick(120, change_dis) + Event.on_nth_tick(600, buff_build) --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) diff --git a/maps/amap/rock.lua b/maps/amap/rock.lua index 927c0a21f..f2e0142ca 100644 --- a/maps/amap/rock.lua +++ b/maps/amap/rock.lua @@ -3,12 +3,14 @@ local Event = require 'utils.event' local Public = {} local Alert = require 'utils.alert' local WD = require 'modules.wave_defense.table' +local BiterHealthBooster = require 'modules.biter_health_booster_v2' local RPG = require 'modules.rpg.table' +--local HS = require 'maps.amap.highscore' 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 wall_health = require 'maps.amap.wall_health_booster_v2' +local spider_health =require 'maps.amap.spider_health_booster_v2' local urgrade_item = function(market) local this = WPT.get() local pirce_wall=this.health*1000 + 10000 @@ -53,7 +55,7 @@ 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", 8000}}, 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}}, @@ -64,10 +66,13 @@ local market_items = { {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}}, - + {price = {{"coin", 3000}}, offer = {type = 'give-item', item = 'flamethrower-turret', count = 1}}, + {price = {{"coin", 15}}, offer = {type = 'give-item', item = 'crude-oil-barrel', count = 1}}, } - +if is_mod_loaded('Krastorio2') then + market_items[#market_items+1]={price = {{"coin", 40000}}, offer = {type = 'give-item', item = 'kr-advanced-tank', count = 1} +} +end function Public.spawn(surface, position) local this = WPT.get() this.rock = surface.create_entity{name = "rocket-silo", position = position, force=game.forces.player} @@ -76,6 +81,20 @@ function Public.spawn(surface, position) game.forces.player.set_spawn_position({0,0}, surface) end +function Public.start(surface, position) + e = surface.create_entity{ + name = "steel-chest", + position = position, + force=game.forces.player + } + + e.insert{name='logistic-chest-storage', count=1} + e.insert{name='construction-robot', count=15} + e.insert{name='roboport', count=1} + + +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} @@ -100,7 +119,7 @@ local function on_rocket_launched(Event) --game.print({'amap.times',this.times}) local rpg_t = RPG.get('rpg_t') --local money = 1000 + this.times*1000 - local money = 10000 + local money = 8000 local point = 1 -- if money >= 50000 then -- money = 50000 @@ -132,9 +151,7 @@ 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} @@ -154,9 +171,11 @@ local function on_entity_died(Event) --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 - + --local diff_name = Difficulty.get('name') Reset_map() - + for _, player in pairs(game.connected_players) do + player.play_sound {path = 'utility/game_lost', volume_modifier = 0.75} + end --abc() end end @@ -185,7 +204,8 @@ local function on_market_item_purchased(event) return end this.health=this.health+1 - wall_health(index,this.health*0.1+1.1) + wall_health.set('biter_health_boost',this.health*0.1+1) + game.print({'amap.buy_wall_over',player.name,this.health*0.1+1}) end @@ -199,17 +219,21 @@ local function on_market_item_purchased(event) 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 + if times >= 30 then + times = 30 + end +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 + local pirce_biter_health=this.biter_health*1000 +7000 + if pirce_biter_health >= 50000 then + pirce_biter_health = 50000 end - player.insert{name='coin',count = pirce_biter_dam} + player.insert{name='coin',count =pirce_biter_health} return end this.biter_health=this.biter_health+1 - global.biter_health_boost_forces[game.forces.player.index] = this.biter_health*0.1+1 + local health = this.biter_health*0.1+1 +BiterHealthBooster.set('biter_health_boost_forces',{[game.forces.player.index]=health}) game.print({'amap.buy_player_biter_over',player.name,this.biter_health*0.1+1}) end if offer_index == 4 then @@ -226,7 +250,8 @@ local function on_market_item_purchased(event) return end this.spider_health=this.spider_health+1 - spider_health(index,this.spider_health*0.1+1.1) + spider_health.set('biter_health_boost',this.health*0.1+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 diff --git a/maps/amap/rocks_yield_ore.lua b/maps/amap/rocks_yield_ore.lua index fef44e385..013e1d05b 100644 --- a/maps/amap/rocks_yield_ore.lua +++ b/maps/amap/rocks_yield_ore.lua @@ -10,6 +10,7 @@ local rock_yield = { ["sand-rock-big"] = 1 } + local particles = { ["iron-ore"] = "iron-ore-particle", ["copper-ore"] = "copper-ore-particle", @@ -39,7 +40,12 @@ local function get_chances() table.insert(chances, {"copper-ore",17}) table.insert(chances, {"coal",13}) table.insert(chances, {"uranium-ore",2}) - table.insert(chances, {"stone",7}) + table.insert(chances, {"stone",10}) + + -- if is_mod_loaded('Krastorio2') then + -- table.insert(chances, {"tiberium-ore",1}) + -- table.insert(chances, {"raw-rare-metals",1}) + -- end return chances end diff --git a/maps/amap/spider_health_booster_v2.lua b/maps/amap/spider_health_booster_v2.lua new file mode 100644 index 000000000..160170c2c --- /dev/null +++ b/maps/amap/spider_health_booster_v2.lua @@ -0,0 +1,417 @@ +-- 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 LootDrop = require 'modules.mobs_drop_loot' +local WD = require 'modules.wave_defense.table' +local Global = require 'utils.global' + +local floor = math.floor +local insert = table.insert +local round = math.round +local random = math.random +local sqrt = math.sqrt +local Public = {} + +local this = { + biter_health_boost = 1, + biter_health_boost_forces = {}, + biter_health_boost_units = {}, + biter_health_boost_count = 0, + active_surface = 'nauvis', + acid_lines_delay = {}, + acid_nova = false, + boss_spawns_projectiles = false, + enable_boss_loot = false +} + +local radius = 6 +local targets = {} +local acid_splashes = { + ['big-biter'] = 'acid-stream-worm-medium', + ['behemoth-biter'] = 'acid-stream-worm-big' +} +local acid_lines = { + ['big-spitter'] = 'acid-stream-spitter-big', + ['behemoth-spitter'] = 'acid-stream-spitter-big' +} +for x = radius * -1, radius, 1 do + for y = radius * -1, radius, 1 do + if sqrt(x ^ 2 + y ^ 2) <= radius then + targets[#targets + 1] = {x = x, y = y} + end + end +end + +local projectiles = { + 'slowdown-capsule', + 'defender-capsule', + 'destroyer-capsule', + 'laser', + 'distractor-capsule', + 'rocket', + 'explosive-rocket', + 'grenade', + 'rocket', + 'grenade' +} + +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 + this.acid_lines_delay = {} + this.acid_nova = false + this.boss_spawns_projectiles = false + this.enable_boss_loot = false +end + +local entity_types = { + ['car'] = true, + ['tank'] = true, + ['spidertron'] = true, + ['spider-vehicle'] = true + --['unit-spawner'] = true +} + +if is_loaded('maps.biter_hatchery.terrain') then + entity_types['unit-spawner'] = nil +end + +local function loaded_biters(event) + local cause = event.cause + local entity = event.entity + if not entity or not entity.valid then + return + end + + local position = false + if cause then + if cause.valid then + position = cause.position + end + end + if not position then + position = {entity.position.x + (-20 + random(0, 40)), entity.position.y + (-20 + random(0, 40))} + end + + entity.surface.create_entity( + { + name = projectiles[random(1, 10)], + position = entity.position, + force = 'neutral', + source = entity.position, + target = position, + max_range = 16, + speed = 0.01 + } + ) +end + +local function acid_nova(event) + for _ = 1, random(20, 40) do + local i = random(1, #targets) + event.entity.surface.create_entity( + { + name = acid_splashes[event.entity.name], + position = event.entity.position, + force = event.entity.force.name, + source = event.entity.position, + target = {x = event.entity.position.x + targets[i].x, y = event.entity.position.y + targets[i].y}, + max_range = radius, + speed = 0.001 + } + ) + end +end +local function acid_line(surface, name, source, target) + local distance = sqrt((source.x - target.x) ^ 2 + (source.y - target.y) ^ 2) + local modifier = {(target.x - source.x) / distance, (target.y - source.y) / distance} + + local position = {source.x, source.y} + + for i = 1, distance * 1.5, 1 do + if random(1, 2) ~= 1 then + surface.create_entity( + { + name = name, + position = source, + force = 'enemy', + source = source, + target = position, + max_range = 25, + speed = 1 + } + ) + end + position = {position[1] + modifier[1], position[2] + modifier[2]} + end +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), + } +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} + } +end + +local function on_player_repaired_entity(event) + local entity = event.entity + if not entity and not entity.valid then return end + local unit_number = entity.unit_number + if not unit_number then return end + if not(entity.force.index == game.forces.player.index) then + return + end + if not entity_types[entity.type] then + return + end + this.biter_health_boost_units[unit_number][1] = entity.health/this.biter_health_boost_units[unit_number][2] +end + + + +local function on_entity_damaged(event) + local biter = event.entity + if not (biter and biter.valid) 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 entity_types[biter.type] then + return + end + + 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 wave_count = WD.get_wave() + + local health_pool = biter_health_boost_units[unit_number] + if health_pool and health_pool[3] then + if this.enable_boss_loot then + if random(1, 128) == 1 then + LootDrop.drop_loot(biter, wave_count) + end + end + if this.boss_spawns_projectiles then + if random(1, 96) == 1 then + loaded_biters(event) + end + end + biter_health_boost_units[unit_number] = nil + if this.acid_nova then + if acid_splashes[biter.name] then + acid_nova(event) + end + if this.acid_lines_delay[biter.unit_number] then + this.acid_lines_delay[biter.unit_number] = nil + end + end + 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.acid_nova(value) + this.acid_nova = value or false + return this.acid_nova +end + +function Public.check_on_entity_died(boolean) + this.check_on_entity_died = boolean or false + + return this.check_on_entity_died +end + +function Public.boss_spawns_projectiles(boolean) + this.boss_spawns_projectiles = boolean or false + + return this.boss_spawns_projectiles +end + +function Public.enable_boss_loot(boolean) + this.enable_boss_loot = boolean or false + + return this.enable_boss_loot +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.on_nth_tick(7200, clean_table) +Event.add(defines.events.on_entity_died, on_entity_died) +Event.add(defines.events.on_player_repaired_entity, on_player_repaired_entity) +return Public diff --git a/maps/amap/surface.lua b/maps/amap/surface.lua index 49ed78b7a..a002b5773 100644 --- a/maps/amap/surface.lua +++ b/maps/amap/surface.lua @@ -17,7 +17,11 @@ Global.register( end ) -local starting_items = {['pistol'] = 1, ['firearm-magazine'] = 16, ['wood'] = 16} +local starting_items = { + ['pistol'] = 1, + ['firearm-magazine'] = 16, + ['wood'] = 16 +} function Public.create_surface() local map_gen_settings = { @@ -28,12 +32,12 @@ function Public.create_surface() } 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"}, + ["coal"] = {frequency = "1.4", size = "1", richness = "0.7"}, + ["stone"] = {frequency = "1.4", size = "1", richness = "0.7"}, + ["copper-ore"] = {frequency = "1.4", size = "2", richness = "0.7"}, + ["iron-ore"] = {frequency ="1.4", size = "2", richness = "0.7"}, ["crude-oil"] = {frequency = "2", size = "2", richness = "1"}, - ["trees"] = {frequency = "1", size = "0.5", richness = "0.7"}, + ["trees"] = {frequency = "1", size = "0.7", richness = "0.7"}, ["enemy-base"] = {frequency = "4", size = "2", richness = "1"}, --["starting_area"] = 1.2, } diff --git a/maps/amap/table.lua b/maps/amap/table.lua index 4d2fddc84..163bcc9a0 100644 --- a/maps/amap/table.lua +++ b/maps/amap/table.lua @@ -20,6 +20,7 @@ function Public.reset_table() -- @start -- these 3 are in case of stop/start/reloading the instance this.biter_dam=0 + this.turret={} this.cap=2 this.biter_health=0 this.change_dist=false diff --git a/maps/amap/wall_health_booster_v2.lua b/maps/amap/wall_health_booster_v2.lua new file mode 100644 index 000000000..26974418f --- /dev/null +++ b/maps/amap/wall_health_booster_v2.lua @@ -0,0 +1,419 @@ +-- 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 LootDrop = require 'modules.mobs_drop_loot' +local WD = require 'modules.wave_defense.table' +local Global = require 'utils.global' + +local floor = math.floor +local insert = table.insert +local round = math.round +local random = math.random +local sqrt = math.sqrt +local Public = {} + +local this = { + biter_health_boost = 1, + biter_health_boost_forces = {}, + biter_health_boost_units = {}, + biter_health_boost_count = 0, + active_surface = 'nauvis', + acid_lines_delay = {}, + acid_nova = false, + boss_spawns_projectiles = false, + enable_boss_loot = false +} + +local radius = 6 +local targets = {} +local acid_splashes = { + ['big-biter'] = 'acid-stream-worm-medium', + ['behemoth-biter'] = 'acid-stream-worm-big' +} +local acid_lines = { + ['big-spitter'] = 'acid-stream-spitter-big', + ['behemoth-spitter'] = 'acid-stream-spitter-big' +} +for x = radius * -1, radius, 1 do + for y = radius * -1, radius, 1 do + if sqrt(x ^ 2 + y ^ 2) <= radius then + targets[#targets + 1] = {x = x, y = y} + end + end +end + +local projectiles = { + 'slowdown-capsule', + 'defender-capsule', + 'destroyer-capsule', + 'laser', + 'distractor-capsule', + 'rocket', + 'explosive-rocket', + 'grenade', + 'rocket', + 'grenade' +} + +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 = true + this.acid_lines_delay = {} + this.acid_nova = false + this.boss_spawns_projectiles = false + this.enable_boss_loot = false +end + +local entity_types = { + ['wall'] = true, + ['turret'] = true, + --['spidertron'] = true, + -- ['spider-vehicle'] = true + --['unit-spawner'] = true +} + +if is_loaded('maps.biter_hatchery.terrain') then + entity_types['unit-spawner'] = nil +end + +local function loaded_biters(event) + local cause = event.cause + local entity = event.entity + if not entity or not entity.valid then + return + end + + local position = false + if cause then + if cause.valid then + position = cause.position + end + end + if not position then + position = {entity.position.x + (-20 + random(0, 40)), entity.position.y + (-20 + random(0, 40))} + end + + entity.surface.create_entity( + { + name = projectiles[random(1, 10)], + position = entity.position, + force = 'neutral', + source = entity.position, + target = position, + max_range = 16, + speed = 0.01 + } + ) +end + +local function acid_nova(event) + for _ = 1, random(20, 40) do + local i = random(1, #targets) + event.entity.surface.create_entity( + { + name = acid_splashes[event.entity.name], + position = event.entity.position, + force = event.entity.force.name, + source = event.entity.position, + target = {x = event.entity.position.x + targets[i].x, y = event.entity.position.y + targets[i].y}, + max_range = radius, + speed = 0.001 + } + ) + end +end +local function acid_line(surface, name, source, target) + local distance = sqrt((source.x - target.x) ^ 2 + (source.y - target.y) ^ 2) + local modifier = {(target.x - source.x) / distance, (target.y - source.y) / distance} + + local position = {source.x, source.y} + + for i = 1, distance * 1.5, 1 do + if random(1, 2) ~= 1 then + surface.create_entity( + { + name = name, + position = source, + force = 'enemy', + source = source, + target = position, + max_range = 25, + speed = 1 + } + ) + end + position = {position[1] + modifier[1], position[2] + modifier[2]} + end +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), + } +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} + } +end + +local function on_player_repaired_entity(event) + local entity = event.entity + if not entity and not entity.valid then return end + local unit_number = entity.unit_number + if not unit_number then return end + if not(entity.force.index == game.forces.player.index) then + return + end + + if not entity_types[entity.type] then + return + end + --game.print(unit_number) + this.biter_health_boost_units[unit_number][1] = entity.health/this.biter_health_boost_units[unit_number][2] +end + + + +local function on_entity_damaged(event) + local biter = event.entity + if not (biter and biter.valid) 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 entity_types[biter.type] then + return + end + + 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 +--game.print(unit_number) + --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 wave_count = WD.get_wave() + + local health_pool = biter_health_boost_units[unit_number] + if health_pool and health_pool[3] then + if this.enable_boss_loot then + if random(1, 128) == 1 then + LootDrop.drop_loot(biter, wave_count) + end + end + if this.boss_spawns_projectiles then + if random(1, 96) == 1 then + loaded_biters(event) + end + end + biter_health_boost_units[unit_number] = nil + if this.acid_nova then + if acid_splashes[biter.name] then + acid_nova(event) + end + if this.acid_lines_delay[biter.unit_number] then + this.acid_lines_delay[biter.unit_number] = nil + end + end + 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.acid_nova(value) + this.acid_nova = value or false + return this.acid_nova +end + +function Public.check_on_entity_died(boolean) + this.check_on_entity_died = boolean or false + + return this.check_on_entity_died +end + +function Public.boss_spawns_projectiles(boolean) + this.boss_spawns_projectiles = boolean or false + + return this.boss_spawns_projectiles +end + +function Public.enable_boss_loot(boolean) + this.enable_boss_loot = boolean or false + + return this.enable_boss_loot +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.on_nth_tick(7200, clean_table) +Event.add(defines.events.on_entity_died, on_entity_died) +Event.add(defines.events.on_player_repaired_entity, on_player_repaired_entity) +return Public