From 4afab13b6b2cff847cc22af1f80318a6842b8203 Mon Sep 17 00:00:00 2001 From: Sh1p*nfire <73347888+Sh1penfire@users.noreply.github.com> Date: Wed, 15 Apr 2026 00:51:45 +1000 Subject: [PATCH 1/5] v157 time babeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeEEEEEEEEEEEEEE --- mod.hjson | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod.hjson b/mod.hjson index 6ca2d3f..7bf29ac 100644 --- a/mod.hjson +++ b/mod.hjson @@ -17,7 +17,7 @@ description: "Meld Java.\n\n[[]accent]Only has custom game content! (play the in version: gameplay expirimental v3 #the minimum game build required to run this mod -minGameVersion: 154 +minGameVersion: 157 #this is a java mod java: true From 148264315aad3c045b409900d29b424b7d520239 Mon Sep 17 00:00:00 2001 From: Sh1p*nfire <73347888+Sh1penfire@users.noreply.github.com> Date: Wed, 15 Apr 2026 01:13:16 +1000 Subject: [PATCH 2/5] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3e0318f..25208d5 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,5 @@ dumbass who was in school now isn't, look at how time's passed This is the java repo for Meld (I might make the original repo for Meld the java edition) Still in alpha and in active development, each gameplay test will likely not be backwards compatable for a long while -for feedback, check the hjson repo's README for the link to the discord server +for feedback, come to the discord server +https://discord.gg/eNynvuJXud From 2782bb89230422a98dba620a59b606bb3784b1f4 Mon Sep 17 00:00:00 2001 From: Sh1p*nfire <73347888+Sh1penfire@users.noreply.github.com> Date: Mon, 20 Apr 2026 01:21:00 +1000 Subject: [PATCH 3/5] Nuke bulbhead's boosting when you forget boost isn't tilda ` and actually l-shift --- src/meld/content/MeldUnits.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/meld/content/MeldUnits.java b/src/meld/content/MeldUnits.java index 5f915e5..2ddb4bc 100644 --- a/src/meld/content/MeldUnits.java +++ b/src/meld/content/MeldUnits.java @@ -291,7 +291,6 @@ public static void load(){ mineRange = IR; fogRadius = IR/ Vars.tilesize; - canBoost = true; boostMultiplier = 0.1f; shadowElevation = 0; shadowElevationScl = 0f; From 1f7153277de9a5942ef68fcd2c12ecf5de1b3327 Mon Sep 17 00:00:00 2001 From: Sh1p*nfire <73347888+Sh1penfire@users.noreply.github.com> Date: Mon, 20 Apr 2026 01:24:44 +1000 Subject: [PATCH 4/5] wawabotomy --- src/meld/entities/unit/BulbheadEntity.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/meld/entities/unit/BulbheadEntity.java b/src/meld/entities/unit/BulbheadEntity.java index fb29658..1ac1e6c 100644 --- a/src/meld/entities/unit/BulbheadEntity.java +++ b/src/meld/entities/unit/BulbheadEntity.java @@ -44,15 +44,6 @@ public class BulbheadEntity extends UnitWaterMove { //Actually counts upwards... kinda counter intuitively named public float corelinkGrace = 0; - - @Override - public EntityCollisions.SolidPred solidity() { - return (x, y) -> { - Tile tile = Vars.world.tile(x, y); - return tile == null || tile.solid(); - }; - } - //skip all the logic involved and just give rotation @Override public float prefRotation() { From bdf70f281b540a0f4cb2a409172fb2ed0fbdca25 Mon Sep 17 00:00:00 2001 From: Sh1p*nfire Date: Tue, 21 Apr 2026 15:56:00 +1000 Subject: [PATCH 5/5] Spritework, bulbhead beaching, RecipeCraftre rework -Bulbhead can now beach and (after a seccond) return to the last safe liquid tile facing towards it from the point it teleported from. -Fixed melting -Sprite + effect for Bruisekit, potential nerfs incoming -Sprites for the Gas-kiln and Pneumatic Extruder -Rotary Kiln switched over to RecipeCrafter for now -Gauze is solid now -RecipeCrafter now uses a system of producers and consumers similar to vanilla, allowing it to produce fluids continuosuly --- assets/bundles/bundle.properties | 12 +- .../earthbound-infuser-bottom.png | Bin .../earthbound-infuser-full.png | Bin .../earthbound-infuser-mixer.png | Bin .../earthbound-infuser.png | Bin assets/sprites/blocks/crafting/gas-kiln.png | Bin 0 -> 5520 bytes .../blocks/crafting/pneumatic-extruder.png | Bin 0 -> 2913 bytes .../sprites/blocks/effect/bruisekit-base.png | Bin 0 -> 2334 bytes .../blocks/effect/bruisekit-turret.png | Bin 0 -> 2899 bytes assets/sprites/blocks/effect/gauze.png | Bin 0 -> 2493 bytes .../items/heavy ind/likestone-sediments.png | Bin 0 -> 340 bytes assets/sprites/units/bulbhead-cell.png | Bin 364 -> 370 bytes assets/sprites/units/bulbhead.png | Bin 1580 -> 1935 bytes src/meld/Meld.java | 1 + src/meld/content/MeldBlocks.java | 315 +++++------------- src/meld/content/MeldBullets.java | 4 +- src/meld/content/MeldEnvironment.java | 9 +- src/meld/content/MeldFx.java | 113 +++++++ src/meld/content/MeldItems.java | 4 +- src/meld/content/MeldLiquids.java | 6 + src/meld/content/MeldRecipes.java | 58 ++++ src/meld/content/MeldUnits.java | 16 +- src/meld/core/Melting.java | 2 + src/meld/entities/unit/BulbheadEntity.java | 126 ++++++- .../unit/abilities/BeachedAbility.java | 14 + src/meld/fluid/AspectGroup.java | 7 + src/meld/meta/MeldStats.java | 2 + src/meld/world/blocks/Bruisekit.java | 125 ++++++- src/meld/world/blocks/Gauze.java | 1 + src/meld/world/blocks/MeldNode.java | 10 +- .../consumers/StupidConsumeAspects.java | 10 +- .../world/blocks/crafting/RecipeCrafter.java | 35 +- .../blocks/crafting/recipe/TimedRecipe.java | 68 +++- src/meld/world/blocks/producer/Produce.java | 36 ++ .../world/blocks/producer/ProduceItem.java | 22 ++ .../world/blocks/producer/ProduceLiquid.java | 33 ++ .../blocks/production/SingleBeamDrill.java | 5 +- 37 files changed, 738 insertions(+), 296 deletions(-) rename assets/sprites/blocks/{production => crafting}/earthbound-infuser-bottom.png (100%) rename assets/sprites/blocks/{production => crafting}/earthbound-infuser-full.png (100%) rename assets/sprites/blocks/{production => crafting}/earthbound-infuser-mixer.png (100%) rename assets/sprites/blocks/{production => crafting}/earthbound-infuser.png (100%) create mode 100644 assets/sprites/blocks/crafting/gas-kiln.png create mode 100644 assets/sprites/blocks/crafting/pneumatic-extruder.png create mode 100644 assets/sprites/blocks/effect/bruisekit-base.png create mode 100644 assets/sprites/blocks/effect/bruisekit-turret.png create mode 100644 assets/sprites/blocks/effect/gauze.png create mode 100644 assets/sprites/items/heavy ind/likestone-sediments.png create mode 100644 src/meld/content/MeldRecipes.java create mode 100644 src/meld/entities/unit/abilities/BeachedAbility.java create mode 100644 src/meld/world/blocks/producer/ProduceItem.java create mode 100644 src/meld/world/blocks/producer/ProduceLiquid.java diff --git a/assets/bundles/bundle.properties b/assets/bundles/bundle.properties index c720038..3adb752 100644 --- a/assets/bundles/bundle.properties +++ b/assets/bundles/bundle.properties @@ -2,7 +2,7 @@ block.meld-sunder.name = Sunder block.meld-sunder.description = Fires clumps of Debris flak at enemy targets.\n[accent]Sticks shrapnel in targets![] block.meld-shredstorm.name = Shredstorm -block.meld-shredstorm.description = Sprays debris shrapnel or silver buckshot at enemy targets..\n[accent]Spread is focused towards the aim direction. +block.meld-shredstorm.description = Sprays debris shrapnel or silver buckshot at enemy targets.\n[accent]Spread is focused towards the aim direction. block.meld-flurry.name = Flurry block.meld-flurry.description = Charges and flings canisters of sticky Carbolith dust which spark on a delay.\n[accent]High damage vs force projectors[]\n\n[red]Warning: Putting hard matterials with sludge in will clog the machinery![]\n\n[accent]Armored![] @@ -30,13 +30,15 @@ block.meld-earthbound-infuser.name = Earthbound Infuser block.meld-earthbound-infuser.description = Infuses Debris with vent fumes to synthesize Carbolith.\n\nRequires [#cbdbfc]Aspect[] to run, can siphon [#5b4739]Fumes[] from vents. block.meld-gas-kiln.name = Gas-fired Kiln -block.meld-gas-kiln.description = Heats materials using [#cbdbfc]Aspect[][accent]\n\nCarbolith + Tenbris -> Shadesteel + [#5b4739]Fumes[]\nClay-Mallows -> Glass-Mallows\nSilver -> Annealed Silver\nDebris + Glass-Mallows -> Crucible Platings\nDebris + Shadesteel -> Crucible Platings +block.meld-gas-kiln.description = Heats materials using [#cbdbfc]Aspect[], often used for [red]primitive[] refinement processes like smelting or ceramic blasting.\n\n[accent]Carbolith + Tenbris -> Shadesteel + [#5b4739]Fumes[]\nSilver -> Annealed Silver\n\nClay-Mallows + Quartz Strata + Likestone Sediments -> Glassy-Mallows\n\nClay-Mallows + Likestone Sediments + Likestone Sediments + Debris -> Crucible-Plating\nDebris + Shadesteel -> Crucible Platings + + block.meld-rotary-kiln.name = Rotary Kiln -block.meld-rotary-kiln.description = Constantly burns [#cbdbfc]Aspect[] as fuel, heats materials to process them in bulk. [accent]\n\nTenbris -> Shadesteel\nClay-Mallows -> Glass-Mallows\nSilver -> Annealed Silver\nDebris + Glass-Mallows -> Crucible Platings\nDebris + Shadesteel -> Crucible Platings +block.meld-rotary-kiln.description = Burns mass amounts of [#cbdbfc]Aspect[] as fuel, heats materials to process them in bulk.\n\n[accent]Carbolith + Tenbris -> Shadesteel + [#5b4739]Fumes[]\nSilver -> Annealed Silver\n\nClay-Mallows + Quartz Strata + Likestone Sediments -> Glassy-Mallows\n\nClay-Mallows + Likestone Sediments + Likestone Sediments + Debris -> Crucible-Plating\nDebris + Shadesteel -> Crucible Platings block.meld-pneumatic-extruder.name = Pneumatic Extruder -block.meld-pneumatic-extruder.description = Extrudes insulated pipes, uses[#cbdbfc]Aspect[] to run. [accent]\n\nShadesteel + Elnar -> Aspect Pipe\n\nAnnealed Silver + Debris -> Aspect Pipe +block.meld-pneumatic-extruder.description = Extrudes material into pipes, uses [#cbdbfc]Aspect[] to run. [accent]\n\nDebris + Elnar -> Aspect Pipe\n\nSilver/Annealed Silver + Debris -> Aspect Pipe block.meld-heating-basin.name = Heating Basin @@ -101,7 +103,7 @@ block.meld-gauze.name = Gauze block.meld-gauze.description = Weaves a [accent]Resonarum[] thread using [#5b4739]Fumes[], automatically applying it to connected blocks. block.meld-bruisekit.name = Bruisekit -block.meld-bruisekit.description = Regenerates target block's health.\n\nPrioritises large, functional blocks and works at half speed on 1x1s. +block.meld-bruisekit.description = Regenerates target block's health.\n\nPrioritises large, functional blocks and works at half speed on 1x1s.\n\nHeals up to 4x more health based on how low target health% is, down to 50%. block.meld-mercurial-diffuser.name = Mercurial Diffuser block.meld-mercurial-diffuser.description = Puffs clouds which intoxicate [#ea9ad6]Meld[] units. Applies a coating of [#89828c]Mercury[] to allied units. diff --git a/assets/sprites/blocks/production/earthbound-infuser-bottom.png b/assets/sprites/blocks/crafting/earthbound-infuser-bottom.png similarity index 100% rename from assets/sprites/blocks/production/earthbound-infuser-bottom.png rename to assets/sprites/blocks/crafting/earthbound-infuser-bottom.png diff --git a/assets/sprites/blocks/production/earthbound-infuser-full.png b/assets/sprites/blocks/crafting/earthbound-infuser-full.png similarity index 100% rename from assets/sprites/blocks/production/earthbound-infuser-full.png rename to assets/sprites/blocks/crafting/earthbound-infuser-full.png diff --git a/assets/sprites/blocks/production/earthbound-infuser-mixer.png b/assets/sprites/blocks/crafting/earthbound-infuser-mixer.png similarity index 100% rename from assets/sprites/blocks/production/earthbound-infuser-mixer.png rename to assets/sprites/blocks/crafting/earthbound-infuser-mixer.png diff --git a/assets/sprites/blocks/production/earthbound-infuser.png b/assets/sprites/blocks/crafting/earthbound-infuser.png similarity index 100% rename from assets/sprites/blocks/production/earthbound-infuser.png rename to assets/sprites/blocks/crafting/earthbound-infuser.png diff --git a/assets/sprites/blocks/crafting/gas-kiln.png b/assets/sprites/blocks/crafting/gas-kiln.png new file mode 100644 index 0000000000000000000000000000000000000000..938942a14449ae651f39da7c7cd3d2f78be6f728 GIT binary patch literal 5520 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 LNkvXXu0mjfu5op8 literal 0 HcmV?d00001 diff --git a/assets/sprites/blocks/effect/bruisekit-base.png b/assets/sprites/blocks/effect/bruisekit-base.png new file mode 100644 index 0000000000000000000000000000000000000000..776aa866dd51333826f07b0148b028c6d10deb3c GIT binary patch literal 2334 zcmV+(3E}pMP)Px-*hxe|RCt`-TTO@@#})qSRdvsfq68a3VvMoZC`$;@B>^3R5tfnnV8}gpW8`2= z&?$%HoLqb{vM@LfI^~jkAYdg#K{yZuxkNd{n-EzsCKnM!7TKNdu6jAt&-6@J*Hm}U zN=Ofy-JYqR_kH#1)vJ0n;={}DFxF&$m)1XeBIMd_)A=llG*<9&mp)9rL;WO?kiwF* z^(TRZO&C;8135n7xXBvhmvVHXo3{=oH}o(pWoREc<@a~VPJyW;JgikCmxNsKX#0T2 zg@jEq1U%NA;NwohQ1AdCE?&IY353p`*&EzYTYmV9KR_uJ9w{Y=DEt*dKnSr?hnd05 zFvdV@9sV{=6Q0X&yxiO881U#@2B%uWB*eb+@9(~TZj=sQQr4QBwA)xB(E^eyx#g#V$0h=hNkX3t1-|Y2IZiptZI2}( z=IkC;{oEBPd)?|IA*Z9EKyu6X^*v-c?v(uQGyU^worIgW4tnR|rK>kOK>T|QT+3IIRu(7<_b3IaB&3v(M1h311n>^HZZztqL0#9V>l%xy#+7Raczb_y zkTyg*_A;Lpn9oYgX9dnZmv03(Zyn&hk3Mmu?!dYcCnAs#AR&O%+;(M1h)~bBqm+bF z3h#aN$!M@K=@9TQd<{Egft^`_`K-YC=kw;&S7wBwD57RBNI-bgPqZQYyeEPnvC@Wb zw)-EynFF~>sa83{Pk!}h{Pg?Z8BV~gP>>{`q=YdBWk~=t*v(h0IjrEc$c?

i1(w0?NXUq+OZ} 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 literal 0 HcmV?d00001 diff --git a/assets/sprites/blocks/effect/gauze.png b/assets/sprites/blocks/effect/gauze.png new file mode 100644 index 0000000000000000000000000000000000000000..8fafab2e5e0a6a524742b7fdf93b9b787ba55a7b GIT binary patch literal 2493 zcmV;u2}1UXP)Px;cS%G+RCt{2T~BCKM;QNHy@XN_Ob%rUq(U?p7xt2b-Xt_=K`;ci|!?m7}S7WC?SVLC3wZMBXRQAhR@Q3pU~XP4Lmv@_ z0{{RkYc+tmdGJ|+O{l(8L+Nt&9>B&)h({@?FFs57XeD%na8=NMxJ1Aby!O|_(ERNg zV9!n!Vc(Z02H%q0SbycYlfMtTaFbBndQ_gr;#JxRVkIq)Cp zI-fhT3IMwzghE;bMZSVgv?7>tPFe&i`3jf_*`gDPljEZ>cJ72!avAbLBi1C?cg~hp zES^7GeiyU^0P`YN0YXc^uCRm%7-3iMKNU}tis#Rk8{efw$haU5`BM0IWy5-0cO@b2 zN#X9jIk7w{aQSMofEd63U~XPKMC~pWGsi;wxUEu_Cckv7Cz>xEjhx0Lh9%5}E<#Kt zs*8|7YG60duqOtIp!0^CxRq$5rEp^ zrC=jX5-NR6h`dBd))}V|LjKfzB{})#{V;?UoEWezfSbuY3CHg5vIgJtajk?U0Ec`D z;+M9o*5kvS15x=2t*}ABRYeQX3i4fqQ?8?k(h3ox>VQ1SU)ruVJ{(Zfh%Fqkoa7P( zDTF+ni>&oKG$DG=*-QM=cGYVQv6c{n+ytPI?<=7$^6ML~8s7`Wj?A^D80tPTb%iu? zwE!1lh}TKSju(m@jsM$(XtfB*+X3Jy{TTV{cd8lk>l?3}M$`jo@895k9-A_@a>H)G~Lc(SJUtM#;YdR;sKyR zXb2|DgK&HK5o~X4Wn7XJY+SgwbBPcX1-S-6EzF#CPMqk!JWNhsihKnnf_aaS`oKmq zhLN5ET7XSh8MXN=-v~6$+bPo>_{a~L$vIgb^j6vs(9J=CjVl*_P7A26uA?&)ZJ0iN zG)vPhteDCH zD-4w;dbo4I8+V_-GTl@UgoK^uL_xiuC3aH zKeivp#)XTwcl~Nv%OQoK3f-k5%wE5ge2D=?m=Z#Xpm2Nnk@c0NUeax@Mv{CRX0KlY zu&j54MU&nzREc0)!-oUCEnr%Kf^H3_8~Og%pPPPn7Q0aYp2v%Lh3-uhD)2a zWTVlXY;CT06#A?bumo^rAn%dODO>JJgjCNOEr9RFdr1TzIM3=8z_wK%^@e*v1nTO! zwr8bm=Yk5rAwTwdE+j<=UAj0%1g8MDP0HGRR*FKqxg%`bE2{vCd@KTJceINL>bpyX zi~#0^T;jR0vTf`Q6`?a6O-QdCZ}TdRZLCskQh#uMRH^)TPE!i6Gt?7wYpd5v1O@Nv;36vQ`s!N1_%W z-FtZP!We5*_F}CL7cY#7=1JNTns(IYK$?7gd}WLX=2AP7kmM?}qjpSUDals|5y7?8 zjwI9){h=_qa_*?jNwjZgGdN=kSMNVX$;O7x`&KI9Zh7_1Pj{PsOYA&r%@Jp>TrT;* zm>h^rqLbKfOyAB$YTI9Du3|)xAYZ{If;tv@PHM9^*cCxC5<+tpB7$w(D=J(iS0~dX zmU>Q-e1(u_^=;>3tpiN>6vy_-+RMOtIl)qZOUHWf9krG)8|2hX$HII~#-**;sj zZPoh*-<~?U2qYJTfwEcIUdHoh%TfPR?x-!+j{Xp##vT0+mXA21QNU0j00000NkvXX Hu0mjfyW*79 literal 0 HcmV?d00001 diff --git a/assets/sprites/items/heavy ind/likestone-sediments.png b/assets/sprites/items/heavy ind/likestone-sediments.png new file mode 100644 index 0000000000000000000000000000000000000000..28bb2d78b25a9da8276083c2b98dffc10a9c9ebd GIT binary patch literal 340 zcmV-a0jvIrP)Px$4oO5oR9J=Wm9Y+jFc5}M<11i7On3zcC*OfLU}AS*Gfu?GxH+&h`361_2{FNk zz^UXccl6pi-Z#?H|La`~0E(h0N+3;Jk4;;TvFoftf~n`H^6I^ow}52Fz9L?eiz*+F z`-5n%R75OLRQa^~EKOjy&Hf@G62RdYNi|#&Yl#3wmL|{-opYY++-#NxFZXhKxqE-6 zV1uL$E=jUHrsO8fg!>BM@Y}g1vt}*e`fb26-0u3Jn~mXWVt%ZsaHyTVnARV5m^nj=3=`F*}*ALr4*FGsqUiNMI34g1eIJXEIcR m;`w;7IZ^+D*lr0000fR+z~ao5*aK0YZO-@G&0n_is`XZ_vXwubmkZny`IYmzT~Bd~Mp5qPc0R=^ z`UTma+g~Z}NfrNapHpEb!=$PA?+|R3PuHWt7EI;=h zzopr03dUfUjP6A delta 324 zcmeyw^oD7IVZEBCi(^Q|oVV8<^A0)ium&s-&(vr99=?Oc)_a!}=fVJ^%nLWZ?3ER2 zmZ`T^5oCaa_L*+t8?JBCIsNu|<}9x`?~{w(&%PhRvoPjh|E&8V+zUfCo(Ixg50gt6 z|HsbsylM5{iR!`Ox}2H!`|%+q9x50@3QSFiZae~+Qo3~i{Jly z#>!JT9?a!T*dWBX=I_FNkIrzYGF7CfGQF7jLhG`8;0xOYmETG}M}Icn$G${+h2^iA zw#lEBh1dlOV{ADhXUk8tY3SJBK4It2)R^a$FF6-|{|)yhl(FF`|M|yhMmr1*Wk4dH Lu6{1-oD!M diff --git a/assets/sprites/units/bulbhead.png b/assets/sprites/units/bulbhead.png index 08b49752b99142ec92159eee14e3110efdfd0f3c..68b39ec50a1ff0ab42a837e10df7e39b4edaf290 100644 GIT binary patch delta 1908 zcmV-)2aEWu437_xFnwl33sXtX>w--Az%n< zV_c+A${i6p7P{fIt|8PHFz$utOEKE8f=LkElBe-mSATOAJmfDxdocGmZJ8L9Ij3!v`BCy`PdF`Ys1n zK5|h!+k6G*U`OL@{+^j{AD4j~Mqk zDRHT?TptjnBB6*;3-aCP-QVB)HbD`G2%b$Zi{8CO~SnKzkJZ93m!% z{8U+5SIRdE%au{B5r7Tjl3x-b5v(?JT+}`UNyxVlMqBxH+C5co+!8~wsT=BKyJ?%j>Z*oN)Scu=T7j} zJ7Mz(kbgSZqK5{@~}>3RLH zpQ?S}*ogU3`b4bwp*%LgeSgx1p@(8P8dsL4rHMxruf$D58Jt{r$&U>YKYsK9001n1 z_MWKT7r*@t003Y8{%7!+>+etQ1y&a4E3cV_QO+&!Myh3@PhO+4o#jvEC&v3!wm`_|3M=iz7!-+%g{*Ji0mC}K3#YkY4V zT@f_oBT^zz@_~`kQbGjtAt*Owx7K?A8AFByXdCO2qQr1yDuDK+C`633_s7cQl8>;? z6Mw4hNb*fW>y9KP4mEM=#D&B+D-qNJxQ?VIu}}k3lH5}Z5mW+L^!z5% z%5z0bmSI6Yfr4$^Ru zwXtw3h9COO$N&75<600@SWf0Or+*#ptBc1!|0L#9909%l>ZSYg%=dmL)S%($ z^-*AofLJ6*;j`t|iN3i0#hypF&z_x*q1Rs(M}kNIw*u)QM<_otHY8Yx5VPUdt;rvC zxsZy$J`c!I7a@rfio@yI?3I${M$K?EhW>*8#as%#{_5qyV2?E%nXH0hJ!W(FSbt?( zvrN@4abvz)9V(eELnXbOn-pcSN8s8B`IH*_wNME_=K=26&Vl6yO=~MOSAfBRzd8bZ zB1n4(EmLB5?Ao;O5sWf7*aE~R73zp2?~<-QIOOAXQ~Hxae_ z-ZR-4B*YF*F2wW5&i;`%O~q%YztDqwj}9u|<&Y1WN!YD0cFY&bGVo`igbSVIlrtRgf+3a4zyhZy;Yt@WOYe9#IY$r8W@(SHWVM6ejo zV>Uv*aL7k!GbOSGuuRc7I~~`0d&Rmw4HvasQNne4YLzs6{w!%Lw29(wu2OZZEY4^B zS({vBjb9SQQ(16`^Yd4g&)XZHC+`%aprP*({e>A=yZ>wDySce*6F%f*%elzOoGTgu z++IY<2Y?B}B)y(~M{R}b^namrB!~sz_WqdTZcpP7k+WmwlyU2h?Mt{K$n3}`eHXltWBC|U@e>IJui+^z<+o<`snd?<#Viu z(idfv^wjTN(79**&RWz@Njs(Y%h(Y>Rc38^M&sZZE*;xbJzf(LF(0|@L`b87B>+{D zJH#Lnw1MvAD8cagvnaV|r(@P`+C^xx$Io0bDJR@bnP}(s@WIBVl>8Lj;UFdmK9>@W z^BlKM7rwIsA66FUMSpjU#am}iBC2!a>)mai`poHWvWI9ToE+nyNC&aB5i2M2dkU%AxEucXDi<}T)7^DpiyuYdp~p$&_RWz ufVtCw##?PIgX<$ng=MXN+KXOwi{U9?6- zGsb8K-bE`!G+{*P-~(D9p}GMn!T#&USIey{v;_UVJ_aC#TlhI)M*Zfb>3n;M`R2c!j zAPmP7v%ax4`#Ytu=E9b-zOiM7;|a?qZ4@T}b96YKpnri`S^ko(50l~3SA&G=yC7di z?swgQssywUfZ8?`CjeXQY}~(eMoo82cFZ;nR2cymPA^u^JR8IDq)PCOXB?vIan0H5xb4^kuL2U|>9Ksqm zVjO5rM=AuAT*OL2%O`OH_G9n?8or4VpcVX-UVk60{vc@|n<~crk0{<5=a!+*t)3)3 zHyTW{8ndMBk%IX4Dl|lWcL3*BPyW*l;X_VqqT3x2vd0JMEvd@>79+vutgj3$-QVx4 z3E5p3HZT%2&I2lIfNLl>_{O9im{Mf^pyXHw) zO@AEyMJM5$L=7joGPHq81+k<2O%#+I4@4tHyUnj9+M~wk?Y6ZK>aYaSvs$?wnxhdH$9*W8S>@gC+Oc zlh1$sjg=v^zCj~)xUfkGWhs!r3I1p>W$)|Hf8AwWO9Ba@LYz&4)WJ+_5njD~`+orC z8;{&_Z_dRE_t}_j;Gg8FxXLbwn*9>DT2vX_=}-#IY(qzbX_229D5ZxA@q<`w3c?mh zJ0LJ`yFp4>18iV&u{9#L(7TIq)q@ze`{8cc+(2U)n$lqFK7+~Sjs(oN+>%5x0U^ac z65RJG0m%8TFy&d-2CD5ga!62H1AknD;cuwJaD&eoS@vf+B!F!`+cl6he@RpVQ+|GO zePb)SRUD2dXdzAG=Pq5OtOwP0K|Y5U)|P_72wic8{uh!f5&TrJ8I!F2+gbVe)3@1c zEQ7g4vzUy#rw-3vOA^2x1y!n{v#sjyt)-i}P$iXwOW@;A-~LQzzwMdZFMn#o5uH-~ z#6E+~>vq6WO2)D0F`ZQVslHN>y$EB5_%ex7q$>q#(alE8*J6t>D60KyQ!M~uka{9c zo`NJRf;E0OLQ-c=EV6^>_JM+9?jj2Fusifafq4D$#mv5|*Ke?PU({!P_E7E5?V1zG zVj#f{COF|Pg5U%-_y8&i+<#|%_QdR$Xjv4SMz|Ro0v153o}6bn27@6O>rv65lI4KGNt7Epw^zQ5u}iOExFS2U8w$4 zf$fZz16r78+dDcsIyyQ!IyyQ!IyyQ!Iy&0KFUaFt8Hbj5@Bjb+00>D%PDHLkV1kUR B^ilu- diff --git a/src/meld/Meld.java b/src/meld/Meld.java index 3b39f84..7affe5f 100644 --- a/src/meld/Meld.java +++ b/src/meld/Meld.java @@ -7,6 +7,7 @@ import arc.math.geom.Point2; import arc.struct.IntSeq; import arc.struct.Seq; +import arc.util.Log; import arc.util.Time; import arc.util.Tmp; import meld.content.*; diff --git a/src/meld/content/MeldBlocks.java b/src/meld/content/MeldBlocks.java index cb4f1b0..5921046 100644 --- a/src/meld/content/MeldBlocks.java +++ b/src/meld/content/MeldBlocks.java @@ -6,14 +6,12 @@ import arc.math.Interp; import arc.math.Mathf; import arc.math.geom.Vec2; -import arc.util.Log; import arc.util.Tmp; import meld.*; import meld.entities.bullet.OutflowBulletType; import meld.entities.bullet.TransitionBulletType; import meld.fluid.AspectGroup; import meld.graphics.*; -import meld.world.blocks.consumers.ConsumeAspects; import meld.world.blocks.*; import meld.world.blocks.consumers.StupidConsumeAspects; import meld.world.blocks.crafting.ModularCrafter; @@ -22,19 +20,17 @@ import meld.world.blocks.crafting.recipe.ItemRecipe; import meld.world.blocks.crafting.recipe.SpoolRecipe; import meld.world.blocks.crafting.modules.*; -import meld.world.blocks.crafting.modules.GateModule.ConsumeCondition; -import meld.world.blocks.crafting.modules.GateModule.OutputCondition; import meld.world.blocks.crafting.recipe.TimedRecipe; import meld.world.blocks.fluid.*; import meld.world.blocks.items.PriorityInputSplitter; +import meld.world.blocks.producer.ProduceItem; +import meld.world.blocks.producer.ProduceLiquid; import meld.world.blocks.production.SingleBeamDrill; import meld.world.meta.*; import mindustry.Vars; -import mindustry.content.Blocks; import mindustry.content.Fx; import mindustry.content.StatusEffects; import mindustry.entities.bullet.*; -import mindustry.entities.effect.MultiEffect; import mindustry.entities.effect.ParticleEffect; import mindustry.entities.part.DrawPart; import mindustry.entities.part.HaloPart; @@ -56,13 +52,13 @@ import mindustry.world.blocks.defense.turrets.ItemTurret; import mindustry.world.blocks.defense.turrets.LiquidTurret; import mindustry.world.blocks.distribution.*; -import mindustry.world.blocks.liquid.ArmoredConduit; import mindustry.world.blocks.liquid.Conduit; import mindustry.world.blocks.liquid.LiquidJunction; import mindustry.world.blocks.liquid.LiquidRouter; import mindustry.world.blocks.production.*; import mindustry.world.blocks.storage.Unloader; import mindustry.world.blocks.units.UnitFactory; +import mindustry.world.consumers.ConsumeItems; import mindustry.world.consumers.ConsumeLiquid; import mindustry.world.draw.*; import mindustry.world.meta.Attribute; @@ -92,7 +88,7 @@ public class MeldBlocks { public static Block aetherAccumulator, elementalBlaster, pneumaticPulsear, earthboundInfuser, fumehood, sharkFactory; - public static ModularCrafter gasKiln, rotaryKiln, pneumaticExtruder; + public static Block gasKiln, metalworks, rotaryKiln, pneumaticExtruder; public static Block channelNode, channelHub, channelFace, aspectOutlet, aspectChannel, channelDirector, channelVent, manualValve, intakeValve, valveController, pipebox; @@ -121,7 +117,6 @@ public static Item item(String name){ } public static void load(){ - int channelHealth = 100; channelFace = new FlexibleSizeJunction("channel-face"){{ @@ -179,42 +174,44 @@ public static void load(){ new DrawSideRegion() ); - //consumeLiquid(MeldLiquids.aether, outletRate/10); - - - liquidCapacity = 100; + //Bit sloppy but it'll work + Vars.content.liquids().each(l -> { + if(AspectGroup.aether.stats.containsKey(l)) inputLiquids.add(l); + }); + Vars.content.liquids().each(l -> { + if(AspectGroup.aspect.stats.containsKey(l)) outputLiquids.add(l); + }); + inputLiquidSlots = 1; outputLiquidSlots = 1; + recipes.addAll( new TimedRecipe(){{ - craftTime = 10; float multi = AspectGroup.aether.getEfficiency(MeldLiquids.aether); float density = AspectGroup.aether.getDensity(MeldLiquids.aether); - inputLiquids = LiquidStack.with(MeldLiquids.aether, outletRate/density); - outputLiquids = LiquidStack.with(MeldLiquids.aspect, outletRate * multi * 10 * density); + consumers.add(new ConsumeLiquid(MeldLiquids.aether, outletRate/density/10)); + producers.add(new ProduceLiquid(MeldLiquids.aspect, outletRate * multi * density)); }}, new TimedRecipe(){{ - craftTime = 10; float multi = AspectGroup.aether.getEfficiency(MeldLiquids.pollutantMixture); float density = AspectGroup.aether.getDensity(MeldLiquids.pollutantMixture); - inputLiquids = LiquidStack.with(MeldLiquids.pollutantMixture, outletRate); - outputLiquids = LiquidStack.with(MeldLiquids.boundAspect, outletRate * multi * 10 * density); + consumers.add(new ConsumeLiquid(MeldLiquids.pollutantMixture, outletRate/density/10)); + producers.add(new ProduceLiquid(MeldLiquids.boundAspect, outletRate * multi * density)); }}, new TimedRecipe(){{ - craftTime = 10; float multi = AspectGroup.aether.getEfficiency(MeldLiquids.thunderingAether); float density = AspectGroup.aether.getDensity(MeldLiquids.thunderingAether); - inputLiquids = LiquidStack.with(MeldLiquids.thunderingAether, outletRate/density); - outputLiquids = LiquidStack.with(MeldLiquids.stormingAspect, outletRate * multi * 10 * density); + consumers.add(new ConsumeLiquid(MeldLiquids.thunderingAether, outletRate/density/10)); + producers.add(new ProduceLiquid(MeldLiquids.stormingAspect, outletRate * multi * density)); }} ); }}; aspectChannel = new VisualAspectPipe("aspect-channel"){{ requirements(Category.liquid, with( - MeldItems.annealedSilver, 5, MeldItems.aspectPipe, 2 + MeldItems.aspectPipe, 4 )); underBullets = false; leaks = false; @@ -330,6 +327,8 @@ public static void load(){ range = 200; fogRadiusMultiplier = 0.25f; + buildTime = 45; + reload = 30; shootEffect = Fx.shootBig; shootWarmupSpeed = 0.09f; @@ -391,6 +390,8 @@ public static void load(){ health = 450; range = 200; + buildTime = 30; + fogRadiusMultiplier = 0.25f; reload = 120; shootEffect = Fx.shootBig; @@ -1124,6 +1125,9 @@ public void update(Bullet b){ drillMultipliers.put( MeldItems.electrumSheets, 2 ); + drillMultipliers.put( + MeldItems.likestoneSediments, 0.5f + ); consume(new StupidConsumeAspects( outletRate, AspectGroup.aspect @@ -1150,6 +1154,7 @@ public void update(Bullet b){ baseProductivity = 50; drillTime = 360; range = 8; + selfDamage = 250; transformItems.putAll( MeldItems.clayMallows, MeldItems.glassMallows, @@ -1159,7 +1164,7 @@ public void update(Bullet b){ liquidCapacity = 50; - consume(new ConsumeAspects(outletRate/2, MeldLiquids.outletEfficiencies, MeldLiquids.outletDensities)); + consume(new StupidConsumeAspects(outletRate/2, AspectGroup.outlet)); }}; earthboundInfuser = new ModularCrafter("earthbound-infuser"){{ @@ -1212,7 +1217,7 @@ public void update(Bullet b){ */ }}; - gasKiln = new ModularCrafter("gas-kiln"){{ + gasKiln = new RecipeCrafter("gas-kiln"){{ requirements(Category.crafting, with(MeldItems.debris, 80)); size = 3; @@ -1222,82 +1227,22 @@ public void update(Bullet b){ itemCapacity = 10; - acceptedLiquids.addAll(MeldLiquids.aspect, MeldLiquids.boundAspect); - acceptedItems.addAll(MeldItems.tenbris, MeldItems.clayMallows, MeldItems.carbolith, MeldItems.debris, MeldItems.shadesteel, MeldItems.glassMallows, MeldItems.silver); - dumpedItems.addAll(MeldItems.cruciblePlating, MeldItems.shadesteel, MeldItems.glassMallows, MeldItems.annealedSilver); - dumpedLiquids.addAll(MeldLiquids.fumes); - - ItemRecipe - shadesteel = new ItemRecipe(with(MeldItems.tenbris, 2, MeldItems.carbolith, 2), with(MeldItems.shadesteel, 2)).output(LiquidStack.with(MeldLiquids.fumes, 60)), - glass = new ItemRecipe(with(MeldItems.clayMallows, 2), with(MeldItems.glassMallows, 2)), - silver = new ItemRecipe(with(MeldItems.silver, 1), with(MeldItems.annealedSilver, 2)), - platings1 = new ItemRecipe(with(MeldItems.shadesteel, 4, MeldItems.debris, 2), with(MeldItems.cruciblePlating, 4)), - platings2 = new ItemRecipe(with(MeldItems.glassMallows, 4, MeldItems.debris, 2), with(MeldItems.cruciblePlating, 4)); + inputLiquids.addAll(MeldLiquids.aspect, MeldLiquids.boundAspect, MeldLiquids.stormingAspect); + inputItems.addAll(MeldItems.tenbris, MeldItems.clayMallows, MeldItems.carbolith, MeldItems.debris, MeldItems.shadesteel, MeldItems.glassMallows, MeldItems.silver, MeldItems.likestoneSediments, MeldItems.quartzStrata); + outputItems.addAll(MeldItems.cruciblePlating, MeldItems.shadesteel, MeldItems.glassMallows, MeldItems.annealedSilver); + outputLiquids.addAll(MeldLiquids.fumes); - float produceTime = 60; - - modules.addAll( - new GateModule( - ModOUT.ZERO, new GateModule.RecipeCondition(shadesteel) - ), - new GateModule( - ModOUT.ONE, new GateModule.RecipeCondition(glass) - ), - new GateModule( - ModOUT.TWO, new GateModule.RecipeCondition(silver) - ), - new GateModule( - ModOUT.THREE, new GateModule.RecipeCondition(platings1) - ), - new GateModule( - ModOUT.FOUR, new GateModule.RecipeCondition(platings2) - ), - new LambdaModule(){{ - //Set every pin after the first one found as 1 to zero - updater = b -> { - int a = 0; - for(int i = 0; i < 5; i++){ - b.setPin(i, Math.max(b.getPin(i) - a, 0)); - a = (int)Math.max(a, b.getPin(i)); - } - b.setPin(ModOUT.FIVE, a); - }; - }}, - new ConsumeAspectModule(outletRate * 2, AspectGroup.aspect, ModIN.FIVE, ModOUT.SIX), - new RecipeCraftingModule(){{ - recipe = shadesteel; - efficiencyPins = new int[]{ModIN.SIX, ModIN.ZERO}; - progressPin = ModOUT.SEVEN; - craftTime = produceTime; - }}, - new RecipeCraftingModule(){{ - recipe = glass; - efficiencyPins = new int[]{ModIN.SIX, ModIN.ONE}; - progressPin = ModOUT.EIGHT; - craftTime = produceTime; - }}, - new RecipeCraftingModule(){{ - recipe = silver; - efficiencyPins = new int[]{ModIN.SIX, ModIN.TWO}; - progressPin = ModOUT.NINE; - craftTime = produceTime; - }}, - new RecipeCraftingModule(){{ - recipe = platings1; - efficiencyPins = new int[]{ModIN.SIX, ModIN.THREE}; - progressPin = ModOUT.TEN; - craftTime = produceTime; - }}, - new RecipeCraftingModule(){{ - recipe = platings2; - efficiencyPins = new int[]{ModIN.SIX, ModIN.FOUR}; - progressPin = ModOUT.ELEVEN; - craftTime = produceTime; - }} - ); + inputLiquidSlots = 1; + outputLiquidSlots = 1; + recipes = MeldRecipes.kilnRecipies(2, 1); + }}; + /* + metalworks = new RecipeCrafter("metalworks"){{ + requirements(Category.crafting, with(MeldItems.debris, 350, MeldItems.cruciblePlating, 150)); }}; - rotaryKiln = new ModularCrafter("rotary-kiln"){{ + */ + rotaryKiln = new RecipeCrafter("rotary-kiln"){{ requirements(Category.crafting, with(MeldItems.debris, 350, MeldItems.cruciblePlating, 150)); size = 5; @@ -1306,101 +1251,18 @@ public void update(Bullet b){ liquidCapacity = outletRate * 60 * 2; itemCapacity = 48; + inputLiquidSlots = 1; + outputLiquidSlots = 1; - acceptedLiquids.addAll(MeldLiquids.aspect, MeldLiquids.boundAspect); - acceptedItems.addAll(MeldItems.tenbris, MeldItems.clayMallows, MeldItems.carbolith, MeldItems.debris, MeldItems.shadesteel, MeldItems.glassMallows, MeldItems.silver); - dumpedItems.addAll(MeldItems.cruciblePlating, MeldItems.shadesteel, MeldItems.glassMallows, MeldItems.annealedSilver); - - defaultData.put(0, 1); - - ItemRecipe shadesteel = new ItemRecipe(with(MeldItems.tenbris, 12), with(MeldItems.shadesteel, 12)); - ItemRecipe glass = new ItemRecipe(with(MeldItems.clayMallows, 12), with(MeldItems.glassMallows, 12)); - ItemRecipe silver = new ItemRecipe(with(MeldItems.silver, 1), with(MeldItems.annealedSilver, 2)); - ItemRecipe platings1 = new ItemRecipe(with(MeldItems.shadesteel, 4, MeldItems.debris, 2), with(MeldItems.cruciblePlating, 4)); - ItemRecipe platings2 = new ItemRecipe(with(MeldItems.glassMallows, 4, MeldItems.debris, 2), with(MeldItems.cruciblePlating, 4)); - - //The max crafting speed when boosted - float craftingTime = 120; + inputLiquids.addAll(MeldLiquids.aspect, MeldLiquids.boundAspect, MeldLiquids.stormingAspect); + inputItems.addAll(MeldItems.tenbris, MeldItems.clayMallows, MeldItems.carbolith, MeldItems.debris, MeldItems.shadesteel, MeldItems.glassMallows, MeldItems.silver, MeldItems.likestoneSediments, MeldItems.quartzStrata); + outputItems.addAll(MeldItems.cruciblePlating, MeldItems.shadesteel, MeldItems.glassMallows, MeldItems.annealedSilver); + outputLiquids.addAll(MeldLiquids.fumes); - modules.addAll( - //Set the base rate based on aspect intake - new ConsumeAspectModule(outletRate * 8, AspectGroup.aspect, 0, 1), - //Setup the flags for possible recipies - new GateModule( - ModOUT.TWO, - new ConsumeCondition(shadesteel.inputItems), - new OutputCondition(shadesteel.outputItems) - ), - new GateModule( - ModOUT.THREE, - new ConsumeCondition(glass.inputItems), - new OutputCondition(glass.outputItems) - ), - new GateModule( - ModOUT.FOUR, - new ConsumeCondition(platings1.inputItems), - new OutputCondition(platings1.outputItems) - ), - new GateModule( - ModOUT.FIVE, - new ConsumeCondition(platings2.inputItems), - new OutputCondition(platings2.outputItems) - ), - new GateModule( - ModOUT.SIX, - new ConsumeCondition(silver.inputItems), - new OutputCondition(silver.outputItems) - ), - //Take the average efficiency - new LambdaModule(){{ - int[] gatePins = new int[]{2, 3, 4, 5, 6}; - float drums = 3; - int outPin = 7; - - updater = build -> { - float total = 0; - for(int i: gatePins){ - total += build.data.get(i); - } - float out = drums/Math.max(total, 1); - build.setPin(outPin, out); - }; - }}, - //Recipies - new RecipeCraftingModule(){{ - recipe = shadesteel; - efficiencyPins = new int[]{1, 2, 7}; - progressPin = 8; - craftTime = craftingTime; - }}, - new RecipeCraftingModule(){{ - recipe = glass; - efficiencyPins = new int[]{1, 3, 7}; - progressPin = 9; - craftTime = craftingTime; - }}, - new RecipeCraftingModule(){{ - recipe = platings1; - efficiencyPins = new int[]{1, 4, 7}; - progressPin = 10; - craftTime = craftingTime; - }}, - new RecipeCraftingModule(){{ - recipe = platings2; - efficiencyPins = new int[]{1, 5, 7}; - progressPin = 11; - craftTime = craftingTime; - }}, - new RecipeCraftingModule(){{ - recipe = silver; - efficiencyPins = new int[]{1, 6, 7}; - progressPin = 12; - craftTime = craftingTime/8f; - }} - ); + recipes = MeldRecipes.kilnRecipies(12, 8); }}; - pneumaticExtruder = new ModularCrafter("pneumatic-extruder"){{ + pneumaticExtruder = new RecipeCrafter("pneumatic-extruder"){{ requirements(Category.crafting, with(MeldItems.debris, 120)); size = 3; @@ -1410,56 +1272,39 @@ public void update(Bullet b){ itemCapacity = 10; - acceptedLiquids.addAll(MeldLiquids.aspect, MeldLiquids.boundAspect); - acceptedItems.addAll(MeldItems.shadesteel, MeldItems.elnarDust, MeldItems.debris, MeldItems.silver, MeldItems.annealedSilver); - dumpedItems.addAll(MeldItems.aspectPipe); - - ItemRecipe - aspectPipe1 = new ItemRecipe(with(MeldItems.shadesteel, 2, MeldItems.elnarDust, 4), with(MeldItems.aspectPipe, 2)), - aspectPipe2 = new ItemRecipe(with(MeldItems.debris, 1, MeldItems.annealedSilver, 2), with(MeldItems.aspectPipe, 2)), - aspectPipe3 = new ItemRecipe(with(MeldItems.debris, 1, MeldItems.silver, 2), with(MeldItems.aspectPipe, 2));; + inputLiquids.addAll(MeldLiquids.aspect, MeldLiquids.boundAspect, MeldLiquids.stormingAspect); + inputItems.addAll(MeldItems.shadesteel, MeldItems.elnarDust, MeldItems.debris, MeldItems.silver, MeldItems.annealedSilver); + outputItems.addAll(MeldItems.aspectPipe); - float produceTime = 30; + inputLiquidSlots = 1; - modules.addAll( - new GateModule( - ModOUT.ZERO, new GateModule.RecipeCondition(aspectPipe1) - ), - new GateModule( - ModOUT.ONE, new GateModule.RecipeCondition(aspectPipe2) - ), - new GateModule( - ModOUT.TWO, new GateModule.RecipeCondition(aspectPipe3) - ), - new LambdaModule(){{ - //Set every ping after the first one found as 1 to zero - updater = b -> { - int a = 0; - for(int i = 0; i < 3; i++){ - b.setPin(i, Math.max(b.getPin(i) - a, 0)); - a = (int)Math.max(a, b.getPin(i)); - } - b.setPin(ModOUT.THREE, a); - }; - }}, - new ConsumeLiquidModule(LiquidStack.with(MeldLiquids.aspect, outletRate * 2), ModIN.THREE, ModOUT.FOUR), - new RecipeCraftingModule(){{ - recipe = aspectPipe1; - efficiencyPins = new int[]{ModIN.FOUR, ModIN.ZERO}; - progressPin = ModOUT.FOUR; - craftTime = produceTime; + recipes.addAll( + new TimedRecipe(){{ + consumers.addAll( + new ConsumeItems(with(MeldItems.annealedSilver, 2, MeldItems.debris, 2)), + new StupidConsumeAspects(outletRate * 2, AspectGroup.aspect) + ); + producers.addAll( + new ProduceItem(new ItemStack(MeldItems.aspectPipe, 2)) + ); }}, - new RecipeCraftingModule(){{ - recipe = aspectPipe2; - efficiencyPins = new int[]{ModIN.FOUR, ModIN.ONE}; - progressPin = ModOUT.FIVE; - craftTime = produceTime; + new TimedRecipe(){{ + consumers.addAll( + new ConsumeItems(with(MeldItems.silver, 2, MeldItems.debris, 2)), + new StupidConsumeAspects(outletRate * 2, AspectGroup.aspect) + ); + producers.addAll( + new ProduceItem(new ItemStack(MeldItems.aspectPipe, 2)) + ); }}, - new RecipeCraftingModule(){{ - recipe = aspectPipe3; - efficiencyPins = new int[]{ModIN.FOUR, ModIN.TWO}; - progressPin = ModOUT.SIX; - craftTime = produceTime; + new TimedRecipe(){{ + consumers.addAll( + new ConsumeItems(with(MeldItems.elnarDust, 2, MeldItems.debris, 2)), + new StupidConsumeAspects(outletRate * 2, AspectGroup.aspect) + ); + producers.addAll( + new ProduceItem(new ItemStack(MeldItems.aspectPipe, 2)) + ); }} ); }}; diff --git a/src/meld/content/MeldBullets.java b/src/meld/content/MeldBullets.java index 72a5aa0..09f2887 100644 --- a/src/meld/content/MeldBullets.java +++ b/src/meld/content/MeldBullets.java @@ -143,6 +143,8 @@ public static void load(){ collidesGround = true; scaleLife = true; + ammoMultiplier = 1; + reloadMultiplier = 2; rangeChange = -80; @@ -270,11 +272,11 @@ public static void load(){ shredSilver = new TransitionBulletType(){{ fragLifeMin = 0.8f; - ammoMultiplier = 2; reloadMultiplier = 2f; fragRandomSpread = 5; fragBullets = 1; + ammoMultiplier = 1; fragBullet = new RicochetBulletType(8, 10, "shell"){{ frontColor = Color.white; diff --git a/src/meld/content/MeldEnvironment.java b/src/meld/content/MeldEnvironment.java index 7bdfd66..57612d4 100644 --- a/src/meld/content/MeldEnvironment.java +++ b/src/meld/content/MeldEnvironment.java @@ -283,7 +283,7 @@ public static void load(){ meldCrystalFloor = new Floor("meld-crystal-floor", 3){{ }}; - meldCrystalFloor = new Floor("meld-hard-crystal-floor", 3){{ + meldCrystalHardFloor = new Floor("meld-hard-crystal-floor", 3){{ }}; carbonicVent = new SteamVent("carbonic-vent"){{ @@ -321,6 +321,10 @@ public static void load(){ likesand = new Floor("likesand", 3); likestone = new Floor("likestone", 3); likesalt = new Floor("likesalt", 3); + + likesand.itemDrop = likestone.itemDrop = MeldItems.likestoneSediments; + likesand.playerUnmineable = likestone.playerUnmineable = true; + redSilt = new Floor("red-silt", 3); aspectSoil = new Floor("aspect-soil", 3); softSand = new Floor("soft-sand", 3); @@ -402,10 +406,12 @@ public static void load(){ likesandWall = new StaticTree("likesand-wall"){{ variants = 2; + itemDrop = MeldItems.likestoneSediments; }}; likestoneWall = new StaticTree("likestone-wall"){{ variants = 2; + itemDrop = MeldItems.likestoneSediments; }}; likesaltWall= new StaticTree("likesalt-wall"){{ @@ -472,6 +478,7 @@ public static void load(){ buildVisibility = BuildVisibility.sandboxOnly; + buildTime = 120; }}; meldCrystal = new WobbleProp("meld-crystal"){{ diff --git a/src/meld/content/MeldFx.java b/src/meld/content/MeldFx.java index 9dcbef9..6218160 100644 --- a/src/meld/content/MeldFx.java +++ b/src/meld/content/MeldFx.java @@ -1,6 +1,8 @@ package meld.content; import arc.Core; +import arc.func.Floatp; +import arc.graphics.Blending; import arc.graphics.Color; import arc.graphics.g2d.Draw; import arc.graphics.g2d.Fill; @@ -9,16 +11,127 @@ import arc.math.Interp; import arc.math.Mathf; import arc.math.geom.Position; +import arc.math.geom.Vec2; import arc.util.Tmp; import meld.graphics.Draww; import meld.Meld; import mindustry.Vars; import mindustry.entities.Effect; import mindustry.gen.Healthc; +import mindustry.graphics.Drawf; import mindustry.graphics.Layer; +import static mindustry.content.Fx.rand; + public class MeldFx { + private static float percent = 0; + + public static Effect + + chainLightning = new Effect(15, 500 * 500/2 * Vars.tilesize, e -> { + if(!(e.data instanceof VisualLightningHolder)) return; + VisualLightningHolder p = (VisualLightningHolder) e.data; + + Draw.blend(Blending.additive); + + int seed = e.id; + //get the start and ends of the lightning, then the distance between them + float tx = Tmp.v1.set(p.start()).x, ty = Tmp.v1.y, dst = Tmp.v1.dst(Tmp.v2.set(p.end())); + + //Get the direction towards the endpoint from the start + Tmp.v3.set(p.end()).sub(p.start()).nor(); + float normx = Tmp.v3.x, normy = Tmp.v3.y; + + rand.setSeed(seed); + + //Set arc width before rand gets based on time + float arcWidth = rand.range(dst * p.arc()); + + seed = e.id - (int) (e.time * 2); + + float angle = Tmp.v1.angleTo(Tmp.v2); + + //How offset each point is from the line based on an arc + Floatp arcX = () -> Mathf.sinDeg(percent * 180) * arcWidth; + + //range of lightning strike's vary depending on turret + float range = p.segLength(); + int links = Mathf.ceil(dst / p.segLength()); + float spacing = dst / links; + + Lines.stroke(p.width() * e.fout()); + Draw.color(Color.white, e.color, e.finpow()); + Fill.circle(Tmp.v2.x, Tmp.v2.y, p.width() * e.fout()/2); + + //begin the line + //Lines.beginLine(); + + //Lines.linePoint(Tmp.v1.x, Tmp.v1.y); + + //Join the links together + + int coils = p.coils(); + for(int u = 0; u < coils; u++){ + int coil = u + 1; + float coilSpacing = spacing/coil; + + //Make the lower numbered, less eratic coils travel quicker + float travelPercent = Mathf.clamp(e.finpow() * (coils - coil + 1)); + + + int coilLinks = links * coil; + + float lastx = Tmp.v1.x, lasty = Tmp.v1.y; + for(int i = 0; i < Mathf.ceil(coilLinks * travelPercent); i++){ + float nx, ny; + //Only put an endpoint at the very end of the lightning, ending early shoudn't end it at the end point + if(i == links * coil - 1){ + //line at end + nx = Tmp.v2.x; + ny = Tmp.v2.y; + }else{ + float len = (i) * coilSpacing + rand.range(coilSpacing/2) + coilSpacing; + rand.setSeed(seed + i); + + //Gets more random with each coil + Tmp.v3.trns(rand.random(360), range/2/(coils - coil + 1)); + percent = ((float) (i + 1))/coilLinks; + + nx = tx + normx * len + Tmp.v3.x + Tmp.v4.set(0, arcX.get()).rotate(angle).x; + ny = ty + normy * len + Tmp.v3.y + Tmp.v4.y; + } + + Drawf.light(lastx, lasty, nx, ny, Lines.getStroke(), Draw.getColor(), Draw.getColor().a); + + //Using a quad instead of just a line so that the edges can join together + Lines.line(lastx, lasty, nx, ny); + + lastx = nx; + lasty = ny; + //Lines.linePoint(nx, ny); + } + } + + + //ines.endLine(); + Draw.blend(); + }); + + public interface VisualLightningHolder{ + Vec2 start(); + + Vec2 end(); + + float width(); + + float segLength(); + + float arc(); + + int coils(); + } + public static float root2 = Mathf.sqrt(2); public static Effect diff --git a/src/meld/content/MeldItems.java b/src/meld/content/MeldItems.java index 0f295de..52bf984 100644 --- a/src/meld/content/MeldItems.java +++ b/src/meld/content/MeldItems.java @@ -28,10 +28,10 @@ public class MeldItems { public static void load(){ debris = new Item("debris"){{ - cost = 0.5f; + cost = 1; }}; carbolith = new Item("carbolith"){{ - cost = 0.8f; + cost = 1.2f; }}; silver = new Item("silver"){{ cost = 0.3f; diff --git a/src/meld/content/MeldLiquids.java b/src/meld/content/MeldLiquids.java index 03a3667..a0d0e04 100644 --- a/src/meld/content/MeldLiquids.java +++ b/src/meld/content/MeldLiquids.java @@ -105,6 +105,12 @@ public static void load(){ } public static void mapOutlet(Liquid input, Liquid output){ + + put(input, AspectGroup.outlet, new AspectStats( + AspectGroup.aether.getEfficiency(input) * AspectGroup.aspect.getEfficiency(output), + AspectGroup.aether.getDensity(input) * AspectGroup.aspect.getDensity(output) + )); + outletMapping.putAll(input, output); outletEfficiencies.put(input, AspectGroup.aether.getEfficiency(input) * AspectGroup.aspect.getEfficiency(output)); diff --git a/src/meld/content/MeldRecipes.java b/src/meld/content/MeldRecipes.java new file mode 100644 index 0000000..d48017c --- /dev/null +++ b/src/meld/content/MeldRecipes.java @@ -0,0 +1,58 @@ +package meld.content; + +import arc.struct.Seq; +import meld.fluid.AspectGroup; +import meld.world.blocks.consumers.StupidConsumeAspects; +import meld.world.blocks.crafting.recipe.TimedRecipe; +import meld.world.blocks.producer.ProduceItem; +import meld.world.blocks.producer.ProduceLiquid; +import mindustry.type.ItemStack; +import mindustry.type.LiquidStack; +import mindustry.world.consumers.ConsumeItems; + +import static meld.content.MeldBlocks.outletRate; +import static mindustry.type.ItemStack.with; + +public class MeldRecipes { + public static Seq kilnRecipies(float outlets, float speedMultiplier){ + return Seq.with( + new TimedRecipe(120/speedMultiplier){{ + consumers.addAll( + new ConsumeItems(with(MeldItems.tenbris, 2, MeldItems.carbolith, 2)), + new StupidConsumeAspects(outletRate * outlets, AspectGroup.aspect) + ); + producers.addAll( + new ProduceItem(new ItemStack(MeldItems.shadesteel, 2)), + new ProduceLiquid(new LiquidStack(MeldLiquids.fumes, 1 * speedMultiplier)) + ); + }}, + new TimedRecipe(30/speedMultiplier){{ + consumers.addAll( + new ConsumeItems(with(MeldItems.silver, 2)), + new StupidConsumeAspects(outletRate * outlets, AspectGroup.aspect) + ); + producers.addAll( + new ProduceItem(new ItemStack(MeldItems.annealedSilver, 3)) + ); + }}, + new TimedRecipe(240/speedMultiplier){{ + consumers.addAll( + new ConsumeItems(with(MeldItems.clayMallows, 2, MeldItems.likestoneSediments, 2, MeldItems.quartzStrata, 4)), + new StupidConsumeAspects(outletRate * outlets, AspectGroup.aspect) + ); + producers.addAll( + new ProduceItem(new ItemStack(MeldItems.glassMallows, 4)) + ); + }}, + new TimedRecipe(240/speedMultiplier){{ + consumers.addAll( + new ConsumeItems(with(MeldItems.clayMallows, 4, MeldItems.likestoneSediments, 2, MeldItems.debris, 2)), + new StupidConsumeAspects(outletRate * outlets, AspectGroup.aspect) + ); + producers.addAll( + new ProduceItem(new ItemStack(MeldItems.cruciblePlating, 4)) + ); + }} + ); + } +} diff --git a/src/meld/content/MeldUnits.java b/src/meld/content/MeldUnits.java index 2ddb4bc..6b3bf94 100644 --- a/src/meld/content/MeldUnits.java +++ b/src/meld/content/MeldUnits.java @@ -262,15 +262,16 @@ public static void load(){ bulbhead = new UnitType("bulbhead"){{ float IR = 120; + outlineColor = Color.clear; health = 290; - speed = 2.55f; - drag = 0.15f; - accel = 0.8f; + speed = 4.55f; + drag = 0.1f; + accel = 0.09f; - rotateSpeed = 9; - trailLength = 18; + rotateSpeed = 7; + trailLength = 80; trailScl = 1.2f; hitSize = 10; @@ -291,7 +292,7 @@ public static void load(){ mineRange = IR; fogRadius = IR/ Vars.tilesize; - boostMultiplier = 0.1f; + canBoost = false; shadowElevation = 0; shadowElevationScl = 0f; @@ -444,7 +445,8 @@ public static void load(){ new StatusFieldAbility(MeldStatusEffects.rally, 120, 5, IR){{ activeEffect = Fx.none; }}, - new SlipstreamHullAbility() + new SlipstreamHullAbility(), + new BeachedAbility() ); //can't rally yourself goober >w< immunities.addAll( diff --git a/src/meld/core/Melting.java b/src/meld/core/Melting.java index 625d9ab..7093239 100644 --- a/src/meld/core/Melting.java +++ b/src/meld/core/Melting.java @@ -28,6 +28,7 @@ public Melting(){ } public void start(Tile start){ + Log.info("Starting!"); start.getLinkedTiles(toSpread::add); if(!running){ @@ -38,6 +39,7 @@ public void start(Tile start){ @Override public void run(){ + Log.info("ticking"); toMelt // TODO: this check might not be necessary .select(it -> it.floor() != melted) diff --git a/src/meld/entities/unit/BulbheadEntity.java b/src/meld/entities/unit/BulbheadEntity.java index 1ac1e6c..b10313b 100644 --- a/src/meld/entities/unit/BulbheadEntity.java +++ b/src/meld/entities/unit/BulbheadEntity.java @@ -12,6 +12,7 @@ import arc.math.geom.Geometry; import arc.math.geom.Point2; import arc.math.geom.Position; +import arc.math.geom.Vec2; import arc.util.*; import meld.content.MeldUnits; import meld.graphics.Draww; @@ -44,6 +45,71 @@ public class BulbheadEntity extends UnitWaterMove { //Actually counts upwards... kinda counter intuitively named public float corelinkGrace = 0; + //Goes up to 1 and once it's at one, well... stuck... + public float beached = 0; + + public float standstillDrag = 1; + public boolean controllerMoved = false; + + public Vec2 lastSafe = new Vec2(); + + //It's a d8 but I shoved several hamburgors in it + public final static Point2[] d8Expanded = { + new Point2(1, 0), + new Point2(1, 1), + new Point2(0, 1), + new Point2(-1, 1), + new Point2(-1, 0), + new Point2(-1, -1), + new Point2(0, -1), + new Point2(1, -1), + + new Point2(2, 0), + new Point2(2, 1), + new Point2(2, -1), + new Point2(2, 2), + new Point2(2, -2), + + new Point2(-2, 0), + new Point2(-2, 1), + new Point2(-2, -1), + new Point2(-2, 2), + new Point2(-2, -2), + + new Point2(0, 2), + new Point2(1, 2), + new Point2(-1, 2), + + new Point2(0, -2), + new Point2(1, -2), + new Point2(-1, -2), + }; + @Override + public EntityCollisions.SolidPred solidity() { + return (x, y) -> { + Tile tile = Vars.world.tile(x, y); + + //If the tile is out of bounds or solid, then yeah it's solid + if(tile == null || tile.solid()) return true; + return false; + + /* + //If the current floor is a liquid then we're good + if(tile.floor().isLiquid) return false; + + for(int i = 0; i < 24; i++){ + Point2 offset = d8Expanded[i]; + Tile other = tile.nearby(offset); + if(other != null && !other.solid() && other.floor().isLiquid) return false; + } + + //If we can't find a nearby liquid tile, return true + return true; + + */ + }; + } + //skip all the logic involved and just give rotation @Override public float prefRotation() { @@ -61,6 +127,23 @@ public void update() { Tile tile = this.tileOn(); + + if(tile != null && !tile.floor().isLiquid){ + if(Mathf.chance(vel.len()/speed())) Fx.unitLandSmall.at(x, y, type.hitSize/Vars.tilesize, tile.floor().mapColor); + + beached = Mathf.approachDelta(beached, 1, 1/60f); + + if(beached == 1){ + float exitAngle = angleTo(lastSafe); + set(lastSafe); + rotation(exitAngle); + } + } + else { + beached = 0; + lastSafe.set(this); + } + if (tile != null && !this.canPassOn()) { for(int i = 0; i < 4; i++){ Tile other = tile.nearby(i); @@ -72,8 +155,26 @@ public void update() { } } } + super.update(); + speedMultiplier *= Mathf.lerp(1, 0f, beached * beached); + if(beached > 0){ + drag *= Mathf.clamp(Mathf.lerp(1, 10, beached * 5), 1, 10); + drag *= Mathf.lerp(1, 5, beached * beached); + } + + if(!controllerMoved) standstillDrag = Mathf.approachDelta(standstillDrag, 10, 1); + else standstillDrag = 1; + + drag *= standstillDrag; + controllerMoved = false; + } + + @Override + public void rotateMove(Vec2 vec) { + super.rotateMove(vec); + controllerMoved = true; } public void getNearbyLink(){ @@ -245,8 +346,6 @@ public void updateBuildLogic() { public void draw(){ super.draw(); - float actualElevation = elevation; - elevation /= 2; //Draww.drawChain(chain, x, y, Core.input.mouseWorldX(), Core.input.mouseWorldY(), 0); @@ -270,7 +369,28 @@ public void draw(){ Draw.blend(Blending.normal); } - elevation = actualElevation; + if(beached > 0 && beached != 1){ + float fout = 1 - beached; + + Draw.alpha(beached * beached); + Draw.mixcol(Pal.accent, 1 - beached); + + //Get the bloom, kinda crappy but this is a way of doing it + Draw.z(Layer.effect); + Draw.rect(type.fullIcon, lastSafe.x, lastSafe.y, angleTo(lastSafe) - 90); + + Draw.z(Layer.weather + 1); + Draw.rect(type.fullIcon, lastSafe.x, lastSafe.y, angleTo(lastSafe) - 90); + + Draw.reset(); + + if(Vars.player.unit() == this){ + Lines.stroke(fout * 8); + Draw.color(Pal.accent); + Draw.alpha(beached); + Lines.circle(lastSafe.x, lastSafe.y, Vars.tilesize * 8 * (1 - beached * beached)); + } + } } //Attempt to draw the build beam from the unit itself. If that fails, draw it to the core instead, then draw the build beam from the core diff --git a/src/meld/entities/unit/abilities/BeachedAbility.java b/src/meld/entities/unit/abilities/BeachedAbility.java new file mode 100644 index 0000000..d62c9af --- /dev/null +++ b/src/meld/entities/unit/abilities/BeachedAbility.java @@ -0,0 +1,14 @@ +package meld.entities.unit.abilities; + +import mindustry.entities.abilities.Ability; +import mindustry.gen.Unit; + +public class BeachedAbility extends Ability { + @Override + public void update(Unit unit) { + super.update(unit); + if(unit.tileOn() != null && !unit.tileOn().floor().isLiquid){ + unit.reloadMultiplier = unit.buildSpeedMultiplier = 0; + } + } +} diff --git a/src/meld/fluid/AspectGroup.java b/src/meld/fluid/AspectGroup.java index d76282b..bc33b80 100644 --- a/src/meld/fluid/AspectGroup.java +++ b/src/meld/fluid/AspectGroup.java @@ -12,6 +12,8 @@ public class AspectGroup { public static Seq groups = new Seq<>(); public String name, localizedName; + public boolean hidden = false; + public AspectGroup(String name){ //hgjkgvjgfh this.name = Vars.content.transformName(name); @@ -33,6 +35,11 @@ public static void put(Liquid liquid, AspectGroup group, AspectStats stats){ group.stats.put(liquid, stats); } + public AspectGroup hide(){ + hidden = true; + return this; + } + public static AspectGroup aether = new AspectGroup("aether"), aspect = new AspectGroup("aspect"), diff --git a/src/meld/meta/MeldStats.java b/src/meld/meta/MeldStats.java index 7a4afbd..19b754c 100644 --- a/src/meld/meta/MeldStats.java +++ b/src/meld/meta/MeldStats.java @@ -24,6 +24,8 @@ public static void aspectStats(Liquid aspect, Stats stats){ table.row(); AspectGroup.groups.each(g -> { + if(g.hidden) return; + AspectGroup.AspectStats aspectStat = g.stats.get(aspect); if(aspectStat == null) return; table.table(Styles.grayPanel, pannel -> { diff --git a/src/meld/world/blocks/Bruisekit.java b/src/meld/world/blocks/Bruisekit.java index c07fa71..2961852 100644 --- a/src/meld/world/blocks/Bruisekit.java +++ b/src/meld/world/blocks/Bruisekit.java @@ -1,12 +1,22 @@ package meld.world.blocks; +import arc.Core; import arc.graphics.g2d.Draw; import arc.graphics.g2d.Lines; +import arc.graphics.g2d.TextureRegion; +import arc.math.Angles; import arc.math.Mathf; +import arc.math.geom.Vec2; import arc.struct.Seq; import arc.util.Log; +import arc.util.Time; +import arc.util.Tmp; +import meld.content.MeldFx; +import mindustry.content.Fx; import mindustry.entities.Units; import mindustry.gen.Building; +import mindustry.graphics.Layer; +import mindustry.graphics.Pal; public class Bruisekit extends FieldPulsar{ @@ -14,10 +24,32 @@ public class Bruisekit extends FieldPulsar{ int targetTimer = timers++; - public float healSpeed = 2; + public float rotateSpeed = 2f; + public float shootCone = 10f; + public float shootY = 6; + + public float healAmount = 20; public float retargetInterval = 5; - public float recentDamageMultiplier = 0.1f, smallMultiplier = 0.5f; + public float recentDamageMultiplier = 0.5f, smallMultiplier = 0.25f; + + public float bruiseMulti = 4; + + public TextureRegion baseRegion, turretRegion; + + public float reload = 90; + + @Override + public void load() { + super.load(); + baseRegion = Core.atlas.find(name + "-base", name); + turretRegion = Core.atlas.find(name + "-turret", name); + } + + @Override + protected TextureRegion[] icons() { + return new TextureRegion[]{baseRegion, turretRegion}; + } public Bruisekit(String name) { super(name); @@ -26,6 +58,10 @@ public Bruisekit(String name) { public class BruisekitBuild extends PulsarBuild{ public Building target; + public float rotation = 90; + public float reloadTime = 0; + public boolean shooting = false; + public Vec2 shootOffset = new Vec2(); @Override public boolean shouldConsume() { @@ -35,15 +71,75 @@ public boolean shouldConsume() { @Override public void updateTile() { super.updateTile(); + shooting = false; + shootOffset.trns(rotation, shootY).add(x, y); + + reloadTime = Math.min(reloadTime + edelta(), reload); + if(timer.get(targetTimer, retargetInterval)) findTarget(); - if(target != null){ - if(target.isValid() && target.damaged()) { - float healAmount = healSpeed * edelta(); - if(target.wasRecentlyDamaged()) healAmount *= recentDamageMultiplier; - if(target.block.size == 0) healAmount *= smallMultiplier; - target.heal(healAmount); + if(target != null && target.isValid()) { + + if(target.damaged()){ + float angleTowards = angleTo(target); + rotation = Angles.moveToward(rotation, angleTowards, rotateSpeed); + + if(Angles.angleDist(rotation, angleTowards) <= shootCone){ + + + shooting = true; + + if(reloadTime >= reload) { + reloadTime = 0; + Vec2 end = new Vec2(target.x, target.y); + + MeldFx.chainLightning.at(target.x, target.y, 0, Pal.heal, + new MeldFx.VisualLightningHolder(){ + @Override + public Vec2 start() { + return shootOffset; + } + + @Override + public Vec2 end() { + return end; + } + + @Override + public float width() { + return 4; + } + + @Override + public float segLength() { + return 8; + } + + @Override + public float arc() { + return 0.2f; + } + + @Override + public int coils() { + return 2; + } + }); + + float healed = healAmount * edelta(); + if(target.wasRecentlyDamaged()) healed *= recentDamageMultiplier; + if(target.block.size == 0) healed *= smallMultiplier; + + healed *= Mathf.lerp(1, bruiseMulti, Math.min(2 - 2 * target.healthf(), 1)); + + target.heal(healed); + + Fx.healBlockFull.at(target.x, target.y, 0, Pal.heal, target.block); + } + + } } + else target = null; } } @@ -55,15 +151,22 @@ public void findTarget(){ if(b.team == team() && b.damaged()) tmpDamaged.add(b); }); - tmpDamaged.sort(b -> b.block.size * 10 + (1 - b.healthf()) + Mathf.log(10, b.block.health)/10); + tmpDamaged.sort(b -> b.block.size * 10 + (1 - b.healthf()) + Mathf.log(10, b.block.health)/10 + b.block.priority); if(!tmpDamaged.isEmpty()) target = tmpDamaged.pop(); } @Override public void draw() { super.draw(); - Draw.alpha(1); - if(target != null) Lines.line(x, y, target.x, target.y); + Draw.reset(); + Draw.z(Layer.blockOver); + Draw.rect(baseRegion, x, y); + Draw.z(Layer.turret); + Draw.rect(turretRegion, x, y, rotation - 90); + Draw.z(Layer.buildBeam); + if(target != null && shooting){ + Lines.line(shootOffset.x, shootOffset.y, target.x, target.y); + } } } } diff --git a/src/meld/world/blocks/Gauze.java b/src/meld/world/blocks/Gauze.java index aff2d37..436c0e7 100644 --- a/src/meld/world/blocks/Gauze.java +++ b/src/meld/world/blocks/Gauze.java @@ -38,6 +38,7 @@ public class Gauze extends Block { public Gauze(String name) { super(name); update = true; + solid = true; } @Override diff --git a/src/meld/world/blocks/MeldNode.java b/src/meld/world/blocks/MeldNode.java index de904dc..4b77b91 100644 --- a/src/meld/world/blocks/MeldNode.java +++ b/src/meld/world/blocks/MeldNode.java @@ -1,9 +1,13 @@ package meld.world.blocks; import arc.func.*; +import arc.util.Log; import meld.*; import meld.core.*; +import mindustry.Vars; import mindustry.content.Blocks; +import mindustry.content.Fx; +import mindustry.gen.Unit; import mindustry.world.blocks.storage.CoreBlock; //Like a core but spawns melting overlays near it on destruction @@ -13,12 +17,10 @@ public MeldNode(String name) { } public class MeldNodeBuild extends CoreBuild{ + @Override public void killed() { - /// start melting before killing - /// otherwise {@link mindustry.world.Tile#getLinkedTiles(Cons)} won't work - Meld.melting.start(tileOn()); - + Meld.melting.start(tile); super.killed(); } } diff --git a/src/meld/world/blocks/consumers/StupidConsumeAspects.java b/src/meld/world/blocks/consumers/StupidConsumeAspects.java index 551711b..0e63f1a 100644 --- a/src/meld/world/blocks/consumers/StupidConsumeAspects.java +++ b/src/meld/world/blocks/consumers/StupidConsumeAspects.java @@ -7,6 +7,7 @@ import arc.struct.IntMap; import arc.struct.ObjectFloatMap; import arc.util.Log; +import arc.util.Time; import meld.fluid.AspectGroup; import meld.world.blocks.crafting.MeldGenericCrafter; import mindustry.Vars; @@ -68,20 +69,17 @@ public Liquid getConsumed(Building build){ @Override public float efficiency(Building build) { Liquid liq = this.getConsumed(build); - float ed = build.edelta(); + float ed = build.timeScale() * Time.delta; if(Mathf.zero(ed) || liq == null) return 0; else { - - float multi = group.getEfficiency(liq); - - return Math.min(build.liquids.get(liq) / (this.amount * ed * multi), multi); + return Math.min(build.liquids.get(liq) / (this.amount * ed), 1); } } @Override public float efficiencyMultiplier(Building build) { Liquid liq = this.getConsumed(build); - return liq == null ? 0.0f : group.getEfficiency(liq); + return liq == null ? 1 : group.getEfficiency(liq); } @Override diff --git a/src/meld/world/blocks/crafting/RecipeCrafter.java b/src/meld/world/blocks/crafting/RecipeCrafter.java index 80527b5..418cc10 100644 --- a/src/meld/world/blocks/crafting/RecipeCrafter.java +++ b/src/meld/world/blocks/crafting/RecipeCrafter.java @@ -81,23 +81,13 @@ public void getRegionsToOutline(Seq out){ @Override public void init() { super.init(); + //TODO: let the recipies tell the block which items and liquids can be used as I/O - //MeldBlocks.aspectOutlet.inputLiquids.add(MeldLiquids.aether);MeldBlocks.aspectOutlet.outputLiquids.add(MeldLiquids.aspect) - recipes.each(recipe -> { - if(recipe.inputItems != null) for(ItemStack item: recipe.inputItems){ - inputItems.add(item.item); - itemFilter[item.item.id] = true; - } - if(recipe.outputItems != null) for(ItemStack item: recipe.outputItems){ - outputItems.add(item.item); - } - if(recipe.inputLiquids != null) for(LiquidStack item: recipe.inputLiquids){ - inputLiquids.add(item.liquid); - liquidFilter[item.liquid.id] = true; - } - if(recipe.outputLiquids != null) for(LiquidStack item: recipe.outputLiquids){ - outputLiquids.add(item.liquid); - } + inputItems.each(i -> { + itemFilter[i.id] = true; + }); + inputLiquids.each(i -> { + liquidFilter[i.id] = true; }); } @@ -218,24 +208,33 @@ public void updateTile() { if(recipe != null && recipe.valid(block, this)){ recipe.update(block, this); + float time = times[last]; time += efficiency; + if(time >= recipe.craftTime){ recipe.apply(crafter, this); time %= recipe.craftTime; + findRecipe(); } times[last] = time; } else { - recipe = recipes.find(r -> r.valid(crafter, this)); - if(recipe != null) last = recipes.indexOf(recipe); + findRecipe(); } dumpOutputs(); } + public void findRecipe(){ + recipe = recipes.find(r -> r.valid(crafter, this)); + if(recipe != null) last = recipes.indexOf(recipe); + } + public void dumpOutputs(){ + outputItems.each(this::dump); + if(outputSlots.size > 0){ for(Liquid output: outputSlots){ diff --git a/src/meld/world/blocks/crafting/recipe/TimedRecipe.java b/src/meld/world/blocks/crafting/recipe/TimedRecipe.java index f935a84..89382b0 100644 --- a/src/meld/world/blocks/crafting/recipe/TimedRecipe.java +++ b/src/meld/world/blocks/crafting/recipe/TimedRecipe.java @@ -1,10 +1,76 @@ package meld.world.blocks.crafting.recipe; +import arc.struct.Seq; import meld.world.blocks.crafting.RecipeCrafter; +import meld.world.blocks.producer.Produce; +import mindustry.gen.Building; +import mindustry.world.Block; +import mindustry.world.consumers.Consume; -public class TimedRecipe extends ItemRecipe { +public class TimedRecipe extends Recipe { + public Seq consumers = new Seq<>(); + public Seq producers = new Seq<>(); public float craftTime = 60; + public TimedRecipe() { + } + public TimedRecipe(float craftTime){ + this.craftTime = craftTime; + } + + public TimedRecipe addConsumers(Consume... list){ + consumers.addAll(list); + return this; + } + public TimedRecipe addProducers(Produce... list){ + producers.addAll(list); + return this; + } + + @Override + public void update(Block block, Building building) { + + building.efficiency = efficiency(block, building); + + consumers.each(c -> c.update(building)); + producers.each(p -> p.update(building)); + + building.efficiency = building.efficiency * boostEfficiency(block, building); + } + + public float efficiency(Block block, Building building){ + float minEfficiency = 1; + + for(Consume consumer: consumers){ + minEfficiency = Math.min(consumer.efficiency(building), minEfficiency); + } + for(Produce producer: producers){ + minEfficiency = Math.min(producer.efficiency(building), minEfficiency); + } + + return minEfficiency; + } + + public float boostEfficiency(Block block, Building building){ + float efficiency = 1; + + for(Consume consumer: consumers){ + efficiency *= consumer.efficiencyMultiplier(building); + } + + return efficiency; + } + + @Override + public void apply(Block block, Building building) { + consumers.each(c -> c.trigger(building)); + producers.each(p -> p.trigger(building)); + } + + @Override + public boolean valid(Block block, Building build) { + return efficiency(block, build) > 0; + } } diff --git a/src/meld/world/blocks/producer/Produce.java b/src/meld/world/blocks/producer/Produce.java index 15476b0..c6d2e64 100644 --- a/src/meld/world/blocks/producer/Produce.java +++ b/src/meld/world/blocks/producer/Produce.java @@ -1,4 +1,40 @@ package meld.world.blocks.producer; +import arc.scene.ui.layout.Table; +import mindustry.gen.Building; +import mindustry.world.Block; +import mindustry.world.consumers.Consume; +import mindustry.world.meta.Stats; + +/** + * A copy of Consume but for production + */ public class Produce { + + /** @return if true, this consumer will be ignored in the production list (no updates or valid() checks) */ + public boolean ignore(){ + return false; + } + + public void build(Building build, Table table){ + + } + + /** Called when a production is triggered manually. */ + public void trigger(Building build){ + + } + + public void update(Building build){ + + } + + /** @return [0, 1] efficiency multiplier based on input. Returns 0 if not valid in subclasses. Should return fraction it can partially output. */ + public float efficiency(Building build){ + return 1f; + } + + public void display(Stats stats){ + + } } diff --git a/src/meld/world/blocks/producer/ProduceItem.java b/src/meld/world/blocks/producer/ProduceItem.java new file mode 100644 index 0000000..e0ee284 --- /dev/null +++ b/src/meld/world/blocks/producer/ProduceItem.java @@ -0,0 +1,22 @@ +package meld.world.blocks.producer; + +import mindustry.gen.Building; +import mindustry.type.ItemStack; + +public class ProduceItem extends Produce{ + public ItemStack output; + + public ProduceItem(ItemStack output){ + this.output = output; + } + + @Override + public float efficiency(Building build) { + return build.getMaximumAccepted(output.item) - build.items.get(output.item) >= output.amount ? 1 : 0; + } + + @Override + public void trigger(Building build) { + build.items.add(output.item, output.amount); + } +} diff --git a/src/meld/world/blocks/producer/ProduceLiquid.java b/src/meld/world/blocks/producer/ProduceLiquid.java new file mode 100644 index 0000000..81b74c7 --- /dev/null +++ b/src/meld/world/blocks/producer/ProduceLiquid.java @@ -0,0 +1,33 @@ +package meld.world.blocks.producer; + +import arc.math.Mathf; +import mindustry.gen.Building; +import mindustry.type.ItemStack; +import mindustry.type.Liquid; +import mindustry.type.LiquidStack; + +//Continuously produces liquid +public class ProduceLiquid extends Produce{ + + public LiquidStack output; + + public ProduceLiquid(Liquid liquid, float amount){ + output = new LiquidStack(liquid, amount); + } + + public ProduceLiquid(LiquidStack output){ + this.output = output; + } + + @Override + public float efficiency(Building build) { + return Mathf.clamp(build.block.liquidCapacity - build.liquids.get(output.liquid) / output.amount); + } + + + @Override + public void update(Building build) { + super.update(build); + build.handleLiquid(build, output.liquid, output.amount); + } +} diff --git a/src/meld/world/blocks/production/SingleBeamDrill.java b/src/meld/world/blocks/production/SingleBeamDrill.java index eea2d9f..faadb00 100644 --- a/src/meld/world/blocks/production/SingleBeamDrill.java +++ b/src/meld/world/blocks/production/SingleBeamDrill.java @@ -38,7 +38,7 @@ public class SingleBeamDrill extends Block { //Additional items mined for each tile unused in the range public int distanceProductivity = 5; - public float selfDamage = 400; + public float selfDamage; public float targetDamage = 2400; public ObjectFloatMap itemMultipliers = new ObjectFloatMap<>(); public ObjectMap transformItems = new ObjectMap<>(); @@ -62,6 +62,7 @@ public SingleBeamDrill(String name) { envEnabled |= 2; flags = EnumSet.of(new BlockFlag[]{BlockFlag.drill}); bigExplosion = MeldBullets.pulsarBlast; + selfDamage = 400; } public class SingleBeamBuild extends Building{ @@ -75,7 +76,7 @@ public boolean shouldConsume() { @Override public void updateTile() { super.updateTile(); - if(healthf() >= minHealthf) time += efficiency; + if(healthf() >= minHealthf) time += edelta(); if(time >= drillTime){ drill(); time %= drillTime;