From fda92dd3935e6eea36b161e28efcf23ed7a82d8c Mon Sep 17 00:00:00 2001 From: secXsQuared Date: Mon, 22 Jan 2018 23:35:36 -0500 Subject: [PATCH] Natural regrowth done. --- modicon.tex | Bin 0 -> 16402 bytes modicon.xml | 3 + modinfo.lua | 15 ++ modmain.lua | 26 +++ scripts/components/natural_regrowth.lua | 212 ++++++++++++++++++++++++ 5 files changed, 256 insertions(+) create mode 100644 modicon.tex create mode 100644 modicon.xml create mode 100644 modinfo.lua create mode 100644 modmain.lua create mode 100644 scripts/components/natural_regrowth.lua diff --git a/modicon.tex b/modicon.tex new file mode 100644 index 0000000000000000000000000000000000000000..01e48fa5bafbf3e38b54b92bcdde6320df509aa8 GIT binary patch literal 16402 zcmcgze_T^nmVZDi0SaWaoyKlIL#Po9Dk0Ts)0wsetqRscDG`TK`Jq+~Wu%}pEwmCK z{h?xuh_5$TF{Tq#t*YNxSEePU+~(pmzI8q^V?8Aao+i!bMCqK-ONpSW`XpPt4uvlYY41hZi=5Ccm9XKl0I1Nt3eWeWJ1UZiHUp7Mp?WsTb zmyJ_u>>TbZ1neb;_Et`AHNyNbK92W;09%c|a=yH;(0l&ALSL`(`$~UeKHmI&g??V` ztw#6z;rxB2AUE>$gYn((4}5@q1n=Khnk6RoaNDy|e`4n%6~Fz7ouCiz{Z8zJ_ow4k zR`r!GQWN{Q`^Qc5FN6L(eMQ8+U@y0P%i>-6Sz?Vt7d1RW!u#p(-_}Y+nvB98)IZ$i zkEt}Cc>Hf#2^7y+mn9BZvu2Im$wce{ygOel*6Gqy?9RnsM*w~~TPiXbG#VT)B26vw z_2pyYfrC^oFH?K9j~C!sX+#6(n>gOAv~aKfv(m_TU35Hm`(ldMg1_?h$#`C1L|Jk>XGj!GVJ~euY`D zax#HUh#Sov@t_aQKO4*eMH*(pW|UX3Gn8Eh#)f!hrOqT4F8c{K*m@F3KD%dJ*O83t&Cb3{w4L^kjVrqWUJ4XNfcyhADnF=cr_r zCM_NNm&w(lLtAWLaX4Hwy?bX4;)oozs4KN=24b?_rqq5qgg61>Bl{&TUUsRZq+WR+ z^G;=qDZv2Il=onIyo7cE=$=08wg4e=u_{>S5pj{-i@)qM)_s06i$ZF=i5 z#1RQu;;v~QUZpr$DjKwXS&n#ALaA7jW@tk^EA2b!=YRTv)(fWgQOTP|f_zXOV*2aW zN1Mk}dqtZ$A1KB_a&cuXocB!fHaP@Yu&wi0xp{{BkUMahK)XHTHKzWJh5 z!#H0Bw2;}Va_1OM=@l0r6(01Q64y#3Bxlauvu2q$a zuQq>LjQF^=RQ%q$P#W*E!5V7<0x6#-kBkd%2@Bhf?L$m&sY6HoE(UQl8)DL=7Sr)U zOqY-7;6XX^|DywfKliDtZ)?B%W$`b_|NVma4>8R<5)cqT^J7Ryo8-*7qy;#CUim%Y z_l^&y{*hF!&@(#e7bv$Cm55vS-V58pKPJ+a%*3NTq!B zYyHA^hXijz`TCks3BVN1mzOqTCIpl z{wMK2H1bTCCEno#{wMJBKiRMR-1;xN3;zmsAK^a$=My(SBTqkba5v(l@}NaNz6|xp z#PUqBt~Jw+@~@hgD3@Q+Ttxh?^P<$$#MO5-HQ!3-Etya4m(V>SDT)ElvVBjg*+p|1)MN5)AR z`;B^$Z3X{`eAIA2?A66F@ zY7r-T_;=;^+(%=C{FC+S=lL)3TK@xzyz_qy+t7aE1jm13d6qad*gpd2AKdnRw$*B- zeE(-lGZue&rwkUw|ecAR1 z6L7*#*VC^$o{>Kowxtl;?{kiq-#mZ53$a4qCdoOqjgEJ^YFWan3t`k>57b*!X}6qC zY(FQiT3j*JpXQs2^2oTy#=q5p@?{BalGn12mLi_Js7+!uPNeZrp5r(6+ppF}p*-rv z$hcIEhWb}b({~chP$cyyW7&7o`i3vQ#P$INmGYTqDi!kZ~a!oL;q zt8BEXxVU&V@Vy203pL39HAl+RG51VSzAT7;HPlD*;lcjG_20it$iGy?U;iuElkN5O za+=>am@Y~VR&As8Pqcn^!hYGk)L)bIA^J}awNSnlAZHj|CeFXdGEP3-f6WQRy8$11 zU=xjxpaH0#(ih~Rys`UxN%kryjo%o3pDN#ej?S;pzpNZD_oe*o&5?yi_y<#d_U6ugUe?J>fcT1=-}3)y*ZI_#o4V4_AiI}Gaz_8<+D8J zM6xp$tm@$_2lB%@|LHQsEA%tvVGFrZ_8ee%3|F32Cw32wQ0T)PQ)vo-1&2i5R<^5A)Ue5N;|99hGB;a3OB=xHQ zPMbqJ>fu5CHn1{zUaXGl3#&cj>lYA$a)ll$u8Nqch)))kihEw`zKQtDj_)P&H0&Va z<;kUDt+kqt_nz|^dG?w?nqQO3t0gc#jfbRi|F}~h{%#cZC+kmZY-}vzD+O=K*OZi$ zAP#=xm}>orMcIfYLy-x=5MGF{ZL_HQcJHb|{6cNui}PmBruo8Duq=V`^`U$uVwM8@K0l^W}KJtPNwXbH+OE~`qcAPvk z*zaD%r_CE!2QU5`%?eYY*4hvJf2ark-#5GYcU*q*v^e;*_?Ple&iDBHKY5vV{9iMN zn(BG^oakeWilX`My4gRjDv$Grzq65XHqCTu-xN!mWYr(f(|RgKe^CPPT? z+CC5X{JUf-kKZ-Pj4n14?V-@mNqArRhzM~~d2UW@D>r}i8~22llmyWIooeWqa(meH zNNlefk_;JOd%|J=CvM#0^2xQT@|*|5F04j*^c!;*eGnz0^Ia*ZmK^!;6kU%l7hRP4 zKh;V1C(8e@sH_IV9`D}%Lm$K9+;2!M1Lhm0JsF?OJ;u}peIh0>?{`i8WX`K~^>3-yL z**N+53psSXdQN{)s`G7Li2Z|Cl8Vfi*1J(T_~P00E6SuY7sJ&Az{=5I0u6l4B$R>RAtozkFJIiS|#_`xUhI zoTB~|t$$m2y{Cu9)1S`HlrR0@P3R8P4YN)v2ml)yUw@^EiG$jwRj?9>l~y3gJO4%DFeenzTcQICon_ z^8A#Pbi}WkA`+(a>Y*_f693kIloS4~{TTmSYDU}K`Tw$`?NQ+W7q9>1dyjYgd-H!< z5dUL<@A{^uCe$Yd@I-hJ6aJeU8X6EQ^v6_dgWjX-Ya-Ndv6%~KyjN6BT2$LmSI4#g zB8`zs==uoRB8}1MD8HflU1bl9=juC!{!$t&|8dxVtMhYJBs_?P{QgorY^znBOPWvj zm;1|)N*TXH7jXO)5Z~vn#{LztC`TrT<8qq6`n3_sJ-qrvUQn04>=Kth?yIU%ee%gE zTF-7U!TCTj`v8td;tT4()rdRId2ByC?)*>q_lo~J@=x-GEUOX@5I#a zQ$e3Wcu=2}mN6D64{5w_2L4-GS}6bbpKOyHfCUrVC&K!@J<^~03)wFmdBTu@@@SBc z3WWl}qn|?m7VxX1@u<)TE-H!Zp*U3Er!Iv92W)@NA`AET52p4P@~s+JA_oi5cvTIN z6GDcr55o43Hg%|noT(`|{v?R^uqQT|5wEZD3;&~o`~Fa01N;904xilHtA?*vG~a|Y z?atO{L>k(ETd%tFg#{UiLz@>X!!+D^-{|g9P=ET-_vwWA=kx!lC;soW{%3jie|Bfq z=xJGFrop?qpF8j`7x3R{7JIG#uK4He2U0AfEt4ltrhIO;q*x&QDgT=+St9=W8mjjT ze?%^i#`o=Mf8oUz#Q?QWRr$;UBP;+YSAc&Q_Sr``41C2%==tmXlUbs|zx{^ByJ|ot z_akrUc|ReaV+Tehq|Q%ILiy(IUbX+Uv2=XZ(EPKoUybGDiG?T Vvs_&(BwJHr;7=-ema=@wV8N{L-z)l0t z9~LWH-~s{4Lz}B5>(tktM675YmGJuC=0E7l=dk~~)>|r0%}7so49xp%%v5zK)_+7! zzBhCH1NqB0Mvzx`J$H3Q$(hpHu!a2$YgA-}&ApR+7h#Z7^ukBDf*=PJ_+`R_xel@Bk?Z-et%_g*MB!0ZE@F@ zWLS`YY>)i^=;$kUbQRx1`cW=i|4+jA`#-~j^4sgbPIFUJZ7s@4J_rot{9zO1e||l1 z5b{AF@4TSPcF-0W#MO&kwwdyzR?y00&&}PX;^Ivl9t-(Am?-U$r@{W+Xl$YW^#tta zoX&sH@3p^_|Fj{QJX6OXAM&wg{sNpYzCf=si0r2klY9>R)Aee7)9hr`h-xg#uQboe z(Q0BTe_u9F$T4cT{eY?Yc=lm-|9))0wyZ;K9Mn+%npCw|Ss3=%J1Bo|uU>WQ=9^)N zPs8~j@qf(!SpV6bFSNPu>s<8u{)7Avj{x~y#SUUh*Yi)t|D%@oj~L;>`N{r2Xd<`1 zPqB2G6%#r6O3PHs#L45Eusz{_qLFLgW!r2E3aTGO`S8syTT>Iao;*Hu&So&SPBS&bMCKrdOF>O?w0TH?kdSI9;dt;WVlLty(Sef6a6LgYAX!kKh0Bej?J3 z?fr|q_kY6r?|I7#FaF8-pKstqy55s|a8G?L?` zl)po^=qiRup!N7c%M!RBP)E<3hi(1|P%ix%$8-Awx4sDdft>FJ^3D$kW_|`gLHx(S zod=Ni2CKn}^F46VSDx;?Mb`(C|3yL9cBA}@b$;Pi1Lt4HvRZXns^$>NFRk;FGfud{ z=kdSe*?!@HaQz7JrFAov4?We9i1@GTI@AZ7bN>zT23E?1265}1_xazJn*CaSy=aKyS4$h}o-yqH($bNOAg8N>OVu>mMpX)*W zR$0jTmz3_OKd@wpul6jY`>$KwCE~6tkLa-dwW2K151PyL{I$!rQ{q?8W}tl72Iqgi z6RE#Q27Xl!^U-*5`v;dF+!$^;)p`7dw0)v8HLY!=wsf2u_K}_xgFuK-Fh%c?HQC<7`jr$Q_H}|Ti2g44=GauRS z+2KKanw_1DCO9yPTmL)FYLO0>KWsl5_{?Cr`(G(gudf1kM)~2hC1S=Wg1-NMoz*7n zFsz<{@=u!fC=Hp+kBE!=+9esOic5$c-EiM0<2A}>ezRH>7}Ug~Tr#jGjfq;j8S&#o zUBK@p+Fk^Akze|*(SCaA_ z=UZL`{sJ3B#9u&u2%CP4#``45_uJoGLF2vA4EciheT01f>n~hQ*OLnP{?`xZiNGJ+ zFD2jq-0^RBzT&zcF1-Kay8W7(O4l3E%=NhVhb_U~`EO{S%-io*ut{vts32X2jn#&6aoPH}oMsvn^Ycs>$4o_-j+OQX2ckZa#%0aj7EDH zac)hA`Wy2fA4J><_gVS-8FIec?{KU}c?Fxu>UxH0{KNO(4*q$v!oxqd7vBFM{KMz} z6qJMJt_SJ?vLA%|<=*!{e-PaNQkdR50_mUTXL26}%D)yIuaV7TCr;+#jrfDHf%Av! zP%pr8PuF|0J~WK5)V>7!1{&#j?ocbEd zf2A)IKfm@<7V*iVY|*dH^Z$f+71S4j6H4iM+9BH}n~`^aoYW^f4BYy#88FlbRG%i> zRExpBn)<^O3*>`XPM@TX4)q|bIfL_&`(1|*uXqY^r+KDwJa7L>>}9apDc_Ay-`O1* zH2)BL*Y$JvYw}oAJAVJuL;mLC|JhEm9~9pI!1^EO2Tfg%i+@-C_vT-C|4(6B?{)v{ zdANT9>5|4f(GSW&${(pu8%74H{fR#ZLIS|~UG;*o!HJmUhZg4uZBKBN!N`+eH#5Fm zy-)IoFRy=!MO&aFZ{+chDc#wku2}es2UnWfB=B=3`h6wEvQy#{eD7l@C+AgA{!xC3 z|1mvw$}gFZu{x+eQ!S&rbq0e2`xAZZ3|1=dG)E+ys`!L{@2G(9In$yadI;OQ__jNW z5tI1oDdhZ#*mFmnosOSqQkZ(|-290g|0Lhj`yV)-F#fUrM>#Q->+#skp)J%2yKT+c4nm4?#wbzedPkfkuvh*Zl#W|9JKjG(U8jPq9o?R0HZe2JCAT z_y?qmL6npH5oK(knDA3=Fi`)TVu?&{B`@rG-_cNSw(v0N&*-@QAHfj+H2$VoJ~r>* z@lW(IIJotJ@CoO|bibfzUYcC9?<49@^^otY<65bIRIqi~P@dBKfpWce?+La`Nh~=MMbew>L|?86IrEf}M9@&mO-k zh!ffM2cVka>36anFn!-V_Prx~c^+$P59G<=K9R}L!kwQd+maxk7-;|Nz2Xjj|IwBh zFI-^T!1CL#ym>o@^HVzB6w3ydub&YARDb^X!udv9y!8|6d%ZVzZz}Kia24#N8gLL= z{}FqX@$8WV^>rN&@9(v>^XI?a-fsJo`mF}?H{Abm-T(j5@#BSC=}%q$#rz9?|4|3O z|4K<8ruqh~gI{Yw0gL?0H+tiE0baY+TfSBxKMwhYKi*RKeOZIX8HMA|hUhTBb{Vm8 ztJJH#acj7U-~V>`ZS4j9z30DsfA8_u3G@-_E5z#r_7GyBy|e;*3GFKv@S%s($Zi&X zU^#T3GPHVsAgupn|CfpOyW8)-mTiRJ{{__3c-dW8EvW+r-2Syi_Bmj1XTZ60D`o#K z`#c|U{C_9GPu39s=vXpwPG?okZjXHAX6KFX9l^}*{G+b^&f%^1ABz0#a+Je(k4(!x z3coj`<5eDjpV;ooKPn~jq5ja{3!|LqN7}zFkQ4uR>lgqi=59!Npr;$2{|cJZ{?Jjnv*a{^vYiM1?_z9UOzsExTpOV7eugCO{^8arvg$XqpuHO1-%&o8gs(wE`{@v#P Zzm~s5`T1Ah?@s;g&h!~mmvF!D{~sbPVR--m literal 0 HcmV?d00001 diff --git a/modicon.xml b/modicon.xml new file mode 100644 index 0000000..122e546 --- /dev/null +++ b/modicon.xml @@ -0,0 +1,3 @@ + + + diff --git a/modinfo.lua b/modinfo.lua new file mode 100644 index 0000000..81cf80c --- /dev/null +++ b/modinfo.lua @@ -0,0 +1,15 @@ +name = "World Regrowth Ex" +description = "Advanced world regrowth" +author = "lolo" +version = "0.0.1" + +forumthread = "" + +api_version = 10 + +icon_atlas = "modicon.xml" +icon = "modicon.tex" + +all_clients_require_mod = false +client_only_mod = false +dst_compatible = true \ No newline at end of file diff --git a/modmain.lua b/modmain.lua new file mode 100644 index 0000000..b91cbd1 --- /dev/null +++ b/modmain.lua @@ -0,0 +1,26 @@ +if GLOBAL.STRINGS.NAMES.MIGRATION_PORTAL then + AddPrefabPostInit("world", function(inst) + if inst.ismastersim then + inst:AddComponent("natural_regrowth") + end + end) +else + AddPrefabPostInit("forest", function(inst) + if inst.ismastersim then + inst:AddComponent("natural_regrowth") + end + end) +end + +AddComponentPostInit("natural_regrowth", function(component) + component:RegisterRegrowth("grass", "grass") +end) + +AddComponentPostInit("natural_regrowth", function(component) + component:RegisterRegrowth("evergreen", "evergreen") +end) + + +--"forest" for the overworld +--"cave" for the caves. +--No more "world" prefab. \ No newline at end of file diff --git a/scripts/components/natural_regrowth.lua b/scripts/components/natural_regrowth.lua new file mode 100644 index 0000000..6449914 --- /dev/null +++ b/scripts/components/natural_regrowth.lua @@ -0,0 +1,212 @@ +-------------------------------------------------------------------------- +--[[ NaturalRegrowth class definition ]] +-- A modified version of the original desolationspawner.lua +-- It acts as a standalone regrowth manager and is in dependent of the 3 existing ones +-- It's unlikely affected by game updates as long as Klei doesn't change the API (they shouldn't) +-- Klei has copyright over existing code used in this file. +-- by lolo Jan. 2018. +-------------------------------------------------------------------------- + +return Class(function(self, inst) + + assert(TheWorld.ismastersim, "natrual_regrowth should not exist on client") + + require "map/terrain" + + -------------------------------------------------------------------------- + --[[ Constants ]] + -------------------------------------------------------------------------- + local RETRY_PER_PREFAB = 5 -- retry 5 times for each prefab + local DEBUG = true + local UPDATE_PERIOD = 31 -- less likely to update on the same frame as others + local BASE_RADIUS = 20 + local EXCLUDE_RADIUS = 3 + local MIN_PLAYER_DISTANCE = 64 * 1.2 -- this is our "outer" sleep radius + + -------------------------------------------------------------------------- + --[[ Member variables ]] + -------------------------------------------------------------------------- + + --Public + self.inst = inst + + --Private + local regrowth_table = {} + local area_data = {} + + -------------------------------------------------------------------------- + --[[ Private member functions ]] + -------------------------------------------------------------------------- + + local function CanRegrow(x, y, z, prefab) + + if IsAnyPlayerInRange(x,y,z, MIN_PLAYER_DISTANCE, nil) then + return false + end + + local ents = TheSim:FindEntities(x,y,z, EXCLUDE_RADIUS) + if #ents > 0 then + -- Too dense + return false + end + + local ents = TheSim:FindEntities(x,y,z, BASE_RADIUS, nil, nil, { "structure", "wall" }) + if #ents > 0 then + -- Don't spawn inside bases + return false + end + + if not (TheWorld.Map:CanPlantAtPoint(x, y, z) and + TheWorld.Map:CanPlacePrefabFilteredAtPoint(x, y, z, prefab)) + or (RoadManager ~= nil and RoadManager:IsOnRoad(x, 0, z)) then + -- Not ground we can grow on + return false + end + return true + end + + local function TryRegrowth(area, prefab, product) + if TheWorld.topology.nodes[area] == nil then + return false + end + + local points_x, points_y = TheWorld.Map:GetRandomPointsForSite(TheWorld.topology.nodes[area].x, TheWorld.topology.nodes[area].y, TheWorld.topology.nodes[area].poly, 1) + if #points_x < 1 or #points_y < 1 then + return + end + local x = points_x[1] + local z = points_y[1] + + if CanRegrow(x,0,z, product) then + local instance = SpawnPrefab(product) + + if instance ~= nil then + instance.Transform:SetPosition(x,0,z) + end + + if DEBUG then + print("[RegrowthEx] Spawned a ",product," for prefab ",prefab," at ", "(", x,0,z, ")", " in ", area) + c_teleport(x,0,z) + end + + return true + else + + return false + end + end + + local function PopulateAreaData(prefab) + if TheWorld.generated == nil then + -- Still starting up, not ready yet. + return + end + + for area, densities in pairs(TheWorld.generated.densities) do + if densities[prefab] ~= nil then + for id, v in ipairs(TheWorld.topology.ids) do + if v == area then + if area_data[prefab] == nil then + area_data[prefab] = {} + end + + table.insert(area_data[prefab], id) + break + end + end + end + end + end + + local function PopulateAllAreaData() + -- This has to be run after 1 frame from startup + for prefab, _ in pairs(regrowth_table) do + PopulateAreaData(prefab) + end + end + + -------------------------------------------------------------------------- + --[[ Public member functions ]] + -------------------------------------------------------------------------- + + function self:RegisterRegrowth(prefab, product) + if DEBUG then + print("Registered ", product, " for prefab " ,prefab ) + end + regrowth_table[prefab] = product + PopulateAreaData(prefab) + end + + -------------------------------------------------------------------------- + --[[ Initialization ]] + -------------------------------------------------------------------------- + + inst:DoPeriodicTask(UPDATE_PERIOD, function() self:LongUpdate(UPDATE_PERIOD) end) + + inst:DoTaskInTime(0, PopulateAllAreaData) + + -------------------------------------------------------------------------- + --[[ Update ]] + -------------------------------------------------------------------------- + + function self:LongUpdate(dt) + for prefab in pairs(area_data) do + + if DEBUG then + print("[RegrowthEx] Regrowing ", prefab, "...") + end + + local areas = area_data[prefab] + local rand = math.random(1, #areas) + local attempts = 0 + + while attempts < RETRY_PER_PREFAB do + local success = TryRegrowth(areas[rand], prefab, regrowth_table[prefab]) + attempts = attempts + 1 + + if success then + print("[RegrowthEx] Succeeded after ", attempts, " attempts.") + break + end + end + + if DEBUG and attempts == RETRY_PER_PREFAB then + print("[RegrowthEx] Failed after ", attempts, " attempts.") + end + + end + end + + -------------------------------------------------------------------------- + --[[ Save/Load ]] + -------------------------------------------------------------------------- + + function self:OnSave() + local data = { + areas = {} + } + for prefab in pairs(area_data) do + data.areas[prefab] = {} + for area in pairs(area_data[prefab]) do + table.insert(data.areas[prefab], area) + end + end + return data + end + + function self:OnLoad(data) + for prefab in pairs(data.areas) do + for area in pairs(data.areas) do + if area_data[prefab] == nil then + area_data[prefab] = {} + end + table.insert(area_data[prefab], area) + end + end + end + + -------------------------------------------------------------------------- + --[[ End ]] + -------------------------------------------------------------------------- + +end)