Serpens

  • Content Count

    1341
  • Joined

  • Last visited

Community Reputation

551 Excellent

About Serpens

  • Rank
    Senior Member
...

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

Enable
  1. see here, but expect it to be not working correctly: https://steamcommunity.com/sharedfiles/filedetails/?id=1882705336 https://github.com/Serpens66/DSTHamletHouse https://steamcommunity.com/sharedfiles/filedetails/?id=1505270912 I already tried to make the house fully working and spent over 500 hours on it (no camparison to what "vagnerdarochasantos" spent on Tropical mod, that is really heavy). But finally I gave up because I even though I already spent that much time, there is still at least twice this time needed to finish it. This is mostly because of the differences between DS and DST. Especially the interior, which is in fact outside of the map, is the most difficult. I tried to rewrite it, to adjust it to DST, but it is a horrible task. (the interior component) So right now I gave up on this and are waiting for the devs of DST to add something similar, so I don't have to "invent the wheel from scratch." edit: If you just need the house, without interior, then it is easy of course and you should find what you are looking for in bakus mod.
  2. look at the script, or is there none? read and understand the script and what function is making him active. You can also take a look at the forge mod in workshop, if/how they made him do sth.
  3. 1) write what the problem was so other with the same problem can read it. 2) Don't overwerite the whole mole prefab file, unless you want your mod be broken everytime the devs change sth within that file. Use AddPrefabPostInit("mole"function(inst) yourcode end) within modmain instead.
  4. see my comment here for an example: but try to think carefully, how you could make your mod compatible to game updates and also other mods (since foodtpye seems to exclusive). Unfortunately, as written in my comment there, I don't have a good idea for that right now.
  5. I will write here some stuff I explained via PM: sceanrio within static_layout, goal is to connect a blocker object for example with an enemy to remove the blocker after the enemy died. Both are placed within a static_layout file: ok, this will make it alot easier. Because within such a layout, you can use so called "scenarios", which are functions, bound to an entity you placed in the layout. I already did this within this mod: https://steamcommunity.com/sharedfiles/filedetails/?id=758921911 There we have in the scrpts/scenarios folder a scenario file called chest_totalrandom.lua, that add random loot to a chest, that was placed via a static_layout. within the static_layout file you use sth like this: objects = { { name = "", type = "chest", shape = "rectangle", x = 312, y = 232, width = 0, height = 0, visible = true, properties = { ["scenario"] = "chest_totalrandom" } }, -- ... The chest_totalrandom.lua need to return 3 functions: return { OnCreate = OnCreate, OnLoad = OnLoad, OnDestroy = OnDestroy } You can define these function within that file. So you can tell the game what should happen with that chest, when it is first created, what happens when the game is loaded and what happens when the chest is destroyed. We should be able to apply the same to eg. "basalt" blocker right now I don't know a really good way how to connect the blocker with the enemy... You could create a global list within modmain (make sure you name it unique) and in OnLoad of the enemy and the blockers you can add their inst to that global list. And OnDestroy of enemy (not sure if this is also called on death, you have to find out. if not you need to do ListenForEvent), you then could look in this global list to find out which blockers are linked to that enemy and do blocket:Remove(), to remove them. Or you could add tags to enemy and blokcer to identify them and use TheSim:FindEntities(x, y, z, radius, nil, nil, {"Tag"}) to find the entities of blockers after the enemy was destroyed. Event Listeners and how to use them: You dont need eventhandler. You only need PushEvent, if you want to create your own event, most of the time this is not needed. ListeForEvent listens for any PushEvent. Simply search the game code for "PushEvent" and you will find plenty results. These commands are always executed on an instance, so eg. inst:ListenForEvent("death",OnDeath). This Listener will call the local OnDeath function that you define within your script, as soon anyone does inst:PushEvent("death") for this inst. When you search for inst:PushEvent("death" (without the closing paranthese) you will find it most likely within the health component I guess. And you also will see what information is passed along for example: inst:PushEvent("death", { cause = cause, afflicter = afflicter }). Your OnDeath function, that is called from your ListenForEvent, will always get the inst, and any additional data that was given to Pushevent, usually all within one table. So your OnDeath funciton could look like this: local function OnDeath(inst,data) if data~=nil then local killer = data.afflicter print(tostring(killer).." killed "..tostring(inst)) end end The same applies to all other events. So first of all clarify on what kind of event you want to be notified. Then either search the relevant component or any other code for PushEvent, if there is already such a PushEvent, you could use. or use the script-wide notepad++ search for all PushEvent and see if you find one you can use. In 99% of the cases you will find one and then you only need to add a listener inst:ListenForEvent for this within your modmain (or scenario).
  6. yes.... but I think AddPrefabPostInit is only executed at server... So maybe try PlayerPostInit instead and check for inst.prefab=="wathgrithr". Please test if it works
  7. guess like this: inst.AnimState:AddOverrideBuild("wathgrithr_sing") inst.AnimState:AddOverrideBuild("player_idles_wathgrithr") inst.customidleanim = "idle_wathgrithr" (see wigrfid game file)
  8. when I look at the stategraphs , it seems it should be enough to do "inst.customidleanim = nil" within AddPrefabPostInit("wathgrithr"... Unless the devs deleted their old animation.
  9. ask the mod author. most likeyl that mod is not functional anymore. (or incompatible to other mods you use)
  10. just skimmed through these old comments: My adventure mod meanwhile a sort of a framework, you can add your own worlds to it easily (at least if you know how to create a custom world, rooms,tasks,set_peices...)
  11. I think this will do it:, using the upvaluehacker to change a local function, will already solve all run states. local UpvalueHacker = GLOBAL.require("upvaluehacker") AddStategraphPostInit("wilson", function(sg) if sg.states.run ~= nil then local old_GetRunStateAnim = UpvalueHacker.GetUpvalue(sg.states.run.onenter, "GetRunStateAnim") local function new_GetRunStateAnim(inst,...) if not inst.sg.statemem.heavy and inst.prefab=="wilson" then return "sand_walk" else return old_GetRunStateAnim(inst,...) end end UpvalueHacker.SetUpvalue(sg.states.run.onenter, new_GetRunStateAnim, "GetRunStateAnim") -- this will overwrite that local function, working for run_start,run and run_stop at once end if sg.states.idle ~= nil then local old_onenter = sg.states.idle.onenter local function new_onenter(inst,pushanim,...) old_onenter(inst,pushanim,...) if inst.prefab == "wilson" then if inst.sg.currentstate.name=="idle" then -- if we not left the idle state if not inst.components.inventory:IsHeavyLifting() then local anims = {} if not (inst.AnimState:IsCurrentAnimation("sand_walk_pst") or inst.AnimState:IsCurrentAnimation("sand_walk") or inst.AnimState:IsCurrentAnimation("sand_walk_pre")) then table.insert(anims, "sand_idle_pre") end table.insert(anims, "sand_idle_loop") if pushanim then for k, v in pairs(anims) do inst.AnimState:PushAnimation(v, k == #anims) end else inst.AnimState:PlayAnimation(anims[1], #anims == 1) for k, v in pairs(anims) do if k > 1 then inst.AnimState:PushAnimation(v, k == #anims) end end end end end end end sg.states.idle.onenter = new_onenter end end) AddStategraphPostInit("wilson_client", function(sg) if sg.states.run ~= nil then local old_GetRunStateAnim = UpvalueHacker.GetUpvalue(sg.states.run.onenter, "GetRunStateAnim") local function new_GetRunStateAnim(inst,...) if not inst.sg.statemem.heavy and inst.prefab=="wilson" then return "sand_walk" else return old_GetRunStateAnim(inst,...) end end UpvalueHacker.SetUpvalue(sg.states.run.onenter, new_GetRunStateAnim, "GetRunStateAnim") end if sg.states.idle ~= nil then local old_onenter = sg.states.idle.onenter local function new_onenter(inst,pushanim,...) old_onenter(inst,pushanim,...) if inst.prefab == "wilson" then if inst.sg.currentstate.name=="idle" then -- if we not left the idle state if (inst.replica.inventory ~= nil and inst.replica.inventory:IsHeavyLifting()) then return elseif pushanim == "cancel" then return elseif inst:HasTag("nopredict") or inst:HasTag("pausepredict") then return elseif pushanim == "noanim" then return end if inst.replica.rider ~= nil and inst.replica.rider:IsRiding() then return end if ( inst.AnimState:IsCurrentAnimation("sand_walk_pst") or inst.AnimState:IsCurrentAnimation("sand_walk") or inst.AnimState:IsCurrentAnimation("sand_walk_pre") ) then if pushanim then inst.AnimState:PushAnimation("sand_idle_loop", true) else inst.AnimState:PlayAnimation("sand_idle_loop", true) end end end end end sg.states.idle.onenter = new_onenter end end) If you don't want the "funny_idle" animation to play, you can overwrite ontimeout within the idle state, or change the funnyidle itself. I tried to overwrite as less as possible. The idle state is quite important, it is not only for simple animation change. So if we break it somehow (or eg a game update changes it a bit, while we overwrote it) alot can break. So it is quite dangerous to change it. Therefore I first call the old_onenter within the new_onenter, to eg. trigger a state change and other stuffs. After that I only change the animation to sand, if we not already switched state and if the first few conditions from the old_onenter are not true. This last part is problematic, because if the devs change the onenter function and add some additional animations that have priority over the sand animation, then this will break our code. But this code is still better than overwriting (coyp/pasting) the whole onenter function. This is the best way I found, although it is by far not perfect, since a game update could break it.
  12. for map coordinates and stuff like this, you will find alot of sample functions within scripts/components/map.lua from the game. So there you see how to get coordinates of a point and how to measure distance and how to get the turf type and so on. But not sure if you will need this, but since you want to learn So again, it does depend on what exactly you want. You could use the normal one-time world with locks/keys and such stuff, to create two landmasses that are seperated by a small landbridge, that i blocked by eg sanity-obelisks (like found in the DS adventure). These obelisk will let you pass if your anity is high/low (depending on the obelisk-type). Now you could create your own obelisks, that let one pass if a certain action was done before, or you could place undestroyable "basalt" stone instead and remove it via script, if the action was done. Instead of using keys/locks, you can also use your static_layout you had above, and directly place obeliks/basalt at a specific position. But this only works for very small worlds, like this prison island. To be able to remove eg. the basalt after a certain action was done, do need to save that basalt entity within modmain. If the basalt was placed within the worldgeneration, you could do AddPrefabPostInit("basalt"...) in which you could check the x,y coordinates and also alot more, to find out which of your multiple blocked ways this basalt is blocking. When you found out, you can save the entities sorted, so you will know which basalt belongs to which way, without checking it again. Then you can listen for your specific action. Most of the devs code is already Pushing Events. Eg. an event on death and so on. So lets say you want to clear one of the ways as soon as a special pig died. Then you do AddPrefabPostInit for this pg (you need to identify the correct one, eg. via a Tag) and add inst:ListenForEvent(death,OnDeath). And in this OnDeath function you have to write, you can remove the basalt. This is only one of many possible ways. I don't know what you know, so not sure how familar you are already with AddPrefabPostInit and ListenForEvent and such. If you give me a real example, that we could live test, I can write it for you and you see how that example exactly works. The most complicated part of this, is to place these blockers exactly at the right position with help of worldgeneration, to block a way. I mostly copy/pasted the DS adventure code, for my adventure mod, but there it still happens frequently, that you can walk beside the blockers, so the way is not really blocked =/
  13. I never used such map editors and I don't know if they are still working or if they require a server restart everytime the land changes (Ithink I heard sth like that,but not sure). Anyway, you should really think about what exactly you want to achieve, and if you can achieve this alot easier. For example to "open a new way to walk", instead of spawning a land bridge, you can block the path with sth. undestroyable and after interaction with the torch, you can remove the block via script. This is thousand times easier for sure.
  14. dont know much about ktools, only used them once, but I did not need cmd or sth like this, simply creating and executing a new .bat file with this code (and put into the ktools folder): krane SourceBin/anim.bin SourceBin/build.bin OutputScml will convert from the SourceBin folder into the OutputScml folder and finished. Or is this a different problem? (I'm not even sure if this bat file is already shipped with modtools, but since everyone is talking about cmd, I guess it is not)