FurryEskimo

  • Content Count

    282
  • Joined

  • Last visited

Community Reputation

30 Excellent

About FurryEskimo

  • Rank
    Member
...

Recent Profile Visitors

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

Enable
  1. Congrats!! I think you can get away with putting it in the character’s prefab, in the ‘master_postinit’
  2. I've been working on editing the player's starting inventory and have been finding some unusual properties. TUNING.GAMEMODE_STARTING_ITEMS.DEFAULT.CHARACTER_PREFAB_NAME = { "ITEM_PREFAB_NAME", } for k, v in pairs(TUNING.GAMEMODE_STARTING_ITEMS) do start_inv[string.lower(k)] = v.FURRYESKIMO print("TESTING TABLE 2") print(start_inv[string.lower(k)]) end local prefabs = FlattenTree(start_inv, true) --Sets starting inventory. inst.starting_inventory = start_inv[TheNet:GetServerGameMode()] or start_inv.default print("start_inv 2: ", start_inv.default) --Test code [00:00:09]: TESTING TABLE 2 [00:00:09]: table: 0F03FFD8 [00:00:09]: TESTING TABLE 2 [00:00:09]: nil [00:00:09]: TESTING TABLE 2 [00:00:09]: nil [00:00:45]: start_inv 2: table: 0F03FFD8 I've tested my own tables and can extract data, but the default code seems to reference a table ID that's generated each time the game runs, not the actual data in the table. It also seems like the default inventory table can store more data but is compressed? I have partially overcome this issue and can now store data in a table and then reference the seemingly random table ID. local people = { --Test code. { test = "nightmarefuel", }, } for k, v in pairs(people ) do --Test code. print("NEW INVENTORY TEST") print(k, v) -- inst.starting_inventory = start_inv[TheNet:GetServerGameMode()] or (k, v) --Error: ')' expected near ',' inst.starting_inventory = start_inv[TheNet:GetServerGameMode()] or people.test end This appears to almost work, giving the player a different inventory on spawn than what was shown to them. Trouble is, the player currently spawns with no items, even though I've listed an item in the table. Does anyone know what I've missed? I suspect it's at the very end, "people.test" is somehow wrong, but I don't how how to replace it with the "(k, v)" that references the table's random ID.
  3. @Earthyburt I think you're using the right code. inst.components.sanity.night_drain_mult = It's the same as what I use. I suspect something else is causing a sanity drain, or else it's defaulting to telling you it's dropping even when it isn't. I made a sleeping bag that had no hunger drain but it still claims there's a drain.
  4. @IronHunter I've tried a few different attempts, and I think I understand the gist of what you've explained now, but the new table keeps failing to be created. I've attached the character's prefab and the most recent error log. if startinginventory == 1 then TUNING.TEST.DEFAULT.FURRYESKIMO = { --Nothing } elseif startinginventory == 2 then TUNING.TEST.DEFAULT.FURRYESKIMO = { "heatrock", } for k, v in pairs(TUNING.TEST) do start_inv[string.lower(k)] = v.FURRYESKIMO end :70: attempt to index field 'TEST' (a nil value) LUA ERROR stack traceback: I'll keep trying, but I'm almost certain the error lies in the way I'm saving data in the new table. furryeskimo.lua server_log_2021-02-28-19-56-18.txt Update: No luck so far. I've tried over and over to do as you suggested (replace the 'TUNING.TABLE' part) but it hasn't worked, each time producing an error claiming the table name isn't defined. I have managed to code tables, and insert/extract some information, sort of, but it appears to be, wrong.. local people = { --Test code. { name = "Fred", address = "16 Long Street", phone = "123456" }, { name = "Wilma", address = "16 Long Street", phone = "123456" }, { name = "Barney", address = "17 Long Street", phone = "123457" } } for k, v in pairs(people ) do --Test code. --Note: REMOVE. print("TABLE DUMP") print(k, v) end [00:00:48]: TABLE DUMP [00:00:48]: 1 table: 0F12F3B0 [00:00:48]: TABLE DUMP [00:00:48]: 2 table: 0F12F630 [00:00:48]: TABLE DUMP [00:00:48]: 3 table: 0F12F3D8 The table's data appears to be random, and changes each time I restart the server. I get a similar result however when I print the table the game's using: print("start_inv 2: ", start_inv.default) --Test code I'll keep trying to figure this out, but my instincts are telling me there's more going on here that I'm not aware of.
  5. @IronHunter I can copy the contents, yes, but do I need to flatten the table afterwards? Can I really just make a table, tell it to store this data like before, remove this code: --Prepares a table of values for the character's starting inventory. local start_inv = {} for k, v in pairs(TUNING.GAMEMODE_STARTING_ITEMS) do start_inv[string.lower(k)] = v.FURRYESKIMO end local prefabs = FlattenTree(start_inv, true) --Sets starting inventory. inst.starting_inventory = start_inv[TheNet:GetServerGameMode()] or start_inv.default and replace it with something as simple as: --Prepares a table of values for the character's starting inventory. local start_inv_images = {} if startinginventory == 1 then start_inv_images[k] = { --Nothing } elseif startinginventory == 2 then start_inv_images[k] = { "heatrock", } end --Sets starting inventory. inst.starting_inventory = start_inv_images[k] or start_inv.default It's that basic?
  6. @IronHunter I've been studying how tables are handled in lua and making some progress with what I understand. Tables Guide: https://www.lua.org/pil/2.5.html Flattening Guide: https://rosettacode.org/wiki/Flatten_a_list -- Defines starting inventory if startinginventory == 1 then TUNING.GAMEMODE_STARTING_ITEMS.DEFAULT.FURRYESKIMO = { --Nothing } elseif startinginventory == 2 then TUNING.GAMEMODE_STARTING_ITEMS.DEFAULT.FURRYESKIMO = { "heatrock", } end --Prepares a table of values for the character's starting inventory. local start_inv = {} for k, v in pairs(TUNING.GAMEMODE_STARTING_ITEMS) do start_inv[string.lower(k)] = v.FURRYESKIMO end local prefabs = FlattenTree(start_inv, true) local master_postinit = function(inst) --Set player's abilities here.. --Sets starting inventory. inst.starting_inventory = start_inv[TheNet:GetServerGameMode()] or start_inv.default Seems pretty simple. A table is created using the player's 'GAMEMODE_STARTING_ITEMS', which is then also assigned as what's displayed on the character select screen. The trouble I'm having is making an entirely new table. The actual table is easy ( local start_inv_images = {} ) but how do get data into/out of the table without using 'GAMEMODE_STARTING_ITEMS'? I think I know ( start_inv_images[k] = "heatrock", ) but I know there's more to it. The whole section that originally used 'GAMEMODE_STARTING_ITEMS' to flatten the tree is, well I'm not entirely sure how to adapt it to the new table.. I'm still studying this, so maybe it'll be obvious soon why and how the table is being flattened, but for right now it's confused me. Edit: Maybe I just need to enter something other than 'default' in "TUNING.GAMEMODE_STARTING_ITEMS.DEFAULT.FURRYESKIMO = {" ? I'm not sure where the 'tuning' values are all stored, but I'll give it a try regardless. If I'm lucky 'default' won't be a special term, but one that can be Any term, and I can reuse the 'GAMEMODE_STARTING_ITEMS' code. I suspect this won't work, but it's just an idea.
  7. @penguin0616 Huh, weird.. So,, If a hound tamer is nearby, the hound (which is already known to be following a player) won’t attack players or companions. It seems really redundant to me. I’ll review the code again later, maybe I’m overlooking something. I spent tonight reviewing the code, cleaning it up, and now players can’t attack Trained hounds, and even pigmen will ignore them unless a fight breaks out!
  8. @Dogmeat8990 Try @ me so I'm notified. ^-^ The recipe I posted requires you to unlock the tech, and that requires you to be at a science station. You'll receive an intelligence bonus for doing so. You also need to enter the character's name at the end if only one character can make the item. This is what's in my modmain: local require = GLOBAL.require local STRINGS = GLOBAL.STRINGS local Recipe = GLOBAL.Recipe --(Test code) local RECIPETABS = GLOBAL.RECIPETABS local TECH = GLOBAL.TECH --AddRecipe(self, name, ingredients, tab, level, placer, min_spacing, nounlock, numtogive, builder_tag, atlas, image) local ice_den = AddRecipe("ice_den",{ Ingredient("twigs", 6), Ingredient("cutgrass", 8), Ingredient("ice", 12) }, RECIPETABS.SURVIVAL, TECH.SCIENCE_ONE, "ice_den_placer", nil, nil, nil, "furryeskimo") ice_den.atlas = "images/inventoryimages/ice_den.xml" local cheapbirdtrap = AddRecipe("cheapbirdtrap",{ Ingredient("twigs", 3), Ingredient("papyrus", 2) }, RECIPETABS.SURVIVAL, TECH.SCIENCE_ONE, nil, nil, nil, nil, "furryeskimo") --Cheap bird trap. cheapbirdtrap.atlas = "images/inventoryimages/cheapbirdtrap.xml" GLOBAL.STRINGS.NAMES.CHEAPBIRDTRAP = "Cheap Bird Trap" --Test code. STRINGS.RECIPE_DESC.CHEAPBIRDTRAP = "Easy to carry,\nbut very delicate." STRINGS.CHARACTERS.GENERIC.DESCRIBE.CHEAPBIRDTRAP= "If a trap goes off, and noone is around to hear it, do I still get dinner?" --Allows the cheap bird cages to be displayed correctly on the character select screen. TUNING.STARTING_ITEM_IMAGE_OVERRIDE["cheapbirdtrap"] = {atlas = "images/inventoryimages/cheapbirdtrap.xml", image = "cheapbirdtrap.tex"} --Hound whistle if GetModConfigData("whistlemaker") == 2 then AddRecipe("houndwhistle", {Ingredient("goldnugget", 4), Ingredient("nightmarefuel", 2), Ingredient(GLOBAL.CHARACTER_INGREDIENT.HEALTH, 50) }, RECIPETABS.MAGIC, TECH.MAGIC_TWO, nil, nil, nil, nil, "furryeskimo") end I've attached the Recipes file, which is how Klei adds all their recipes. recipes[1].lua
  9. I've been poking around some old code of mine, making updates and general improvements, and I found this in the hound's updated combat AI for target sharing. The rest of the code basically says 'is this hound's leader a player', 'is the target a hound tamer', 'is the target a follower of your leader', but then this comes up. -- Prevents players and companions from being shared as a target. --Note: Redundant? if target:HasTag("player") or target:HasTag("companion") then local houndtamer = GLOBAL.FindEntity(inst, 20, function(guy) return guy:HasTag("houndtamer") end) if houndtamer ~= nil then return end end It happens if the target is a player or companion, but what is it doing? I think it checks if there are any hound tamers on the server, and if there are the hound won't attack the target. Am I understanding this code correctly? With all my other checks this comes across as extremely strange and redundant. I can't even imagine under what circumstances this would apply, so I'm trying to figure out what it applies to.
  10. @Pinkamena11FazP Usually I get that error because I've forgotten to update the mod's version number. Have you made sure to do that? I also have the upload version in a separate file location, so it never gets overwritten by accident. Might help.
  11. @CarlZalph Wow, cool! I'll give that a try soon! Edit 1: It appears to be working! Edit 2: I actually did manage to figure out a general solution to this. I can now compare the name of the player against a hound's follower, and vise-versa. This made it so I can cause a penalty for killing wild hounds or another player's hounds, and a heavier penalty for killing your own, discouraging players from summoning and killing their pet hounds (which has been an issue in the beta, as players could farm hounds for food.) local function onkilled(inst, data) --Negative sanity penalty when you kill hounds. print("Hound killed!") --Test code. local victim = data.victim if victim and victim:HasTag("hound") and not victim:HasTag("companion") then print("Killed a wild hound.") --Test code. inst.components.sanity:DoDelta(victim.sanityreward or -TUNING.SANITY_SMALL) --Note: Tiny=5 Sanity, Small=10 Sanity, Med=15 Sanity, MED_LARGE=XXX Sanity, Large=33 Sanity, Huge=50 Sanity, Superhuge=XXX Sanity elseif victim and victim:HasTag("hound") and victim:HasTag("companion") then if inst.name == victim.components.follower.leader.name then print("Killed your own trained hound.") --Test code. inst.components.sanity:DoDelta(victim.sanityreward or -TUNING.SANITY_MED) --Note: Tiny=5 Sanity, Small=10 Sanity, Med=15 Sanity, MED_LARGE=XXX Sanity, Large=33 Sanity, Huge=50 Sanity, Superhuge=XXX Sanity else print("Killed someone else's trained hound.") --Test code. inst.components.sanity:DoDelta(victim.sanityreward or -TUNING.SANITY_SMALL) --Note: Tiny=5 Sanity, Small=10 Sanity, Med=15 Sanity, MED_LARGE=XXX Sanity, Large=33 Sanity, Huge=50 Sanity, Superhuge=XXX Sanity end print("Player's name: ", inst.name) --Test code. print("Victim's Leader: ", victim.components.follower.leader.name) end end I've reviewing this old hound AI code though and wow, it's a little weird. The hounds are generally well behaved, but they can get into fights with one another, and PvP with the hounds wasn't possible before now. I think I can tell them not to attack targets with the same leader as they have, but for some reason I can't remember what code prevents the hounds attacking players.. I was hoping to remove that code and replace it with new, updated code. if inst.components.combat then -- Prevent hounds from attacking other players local targetfn_orig = inst.components.combat.targetfn local targetfn_new = function(inst) local target = nil -- Choose target normally if targetfn_orig then target = targetfn_orig(inst) end -- Check if this hound has a hound tamer as a leader. if target ~= nil and inst.components.follower and inst.components.follower.leader and inst.components.follower.leader:HasTag("player") then -- Check if target should be kept Note: Hounds are mostly useless in PvP? if target:HasTag("player") or target:HasTag("companion") -- or target:HasTag("trainedhound") --Redundant? or target:HasTag("character") --Prevents hounds starting fights with pigs, bunnymen, and rock lobsters, but they will still attack trained hounds. or target:AddTag("largecreature") --Usually prevents hounds starting fights with larger enemies, like beefalo. --Note: Hounds attacking targets (like birds) very close to a beefalo often go on to attack the beefalo. -- or target:AddTag("epic") --Prevents hounds starting fights with giants, but these are also taged with 'largecreature' so this would be redundant. or target:HasTag("insect") --Prevents hounds starting fights with bees, mosquitos, and butterflies. This is mostly to prevent hounds resulting in endless loot when players stand next to flowers. or target:HasTag("hive") --Prevents hounds attacking beehives, spider dens. -- or target:HasTag("prey") -- or target:HasTag("structure") -- or target.name == inst.components.follower.leader.name --Test code. --Note: Walruses have the tag 'houndfriend', meaning they may be partially immune to these trained hounds. then print("Hound's Target: Not Valid") print("Target's Name: ", target.name) --Test code. print("Hound's Leader's Name: ", inst.components.follower.leader.name) target = nil else print("Hound's Target: Valid") print("Target's Name: ", target.name) --Test code. print("Hound's Leader's Name: ", inst.components.follower.leader.name) end end return target end inst.components.combat.targetfn = targetfn_new local ShareTarget_prev = inst.components.combat.ShareTarget function inst.components.combat:ShareTarget(target, ...) -- Share target normally if being led by someone other than hound tamer. if inst.components.follower and inst.components.follower.leader and not inst.components.follower.leader:HasTag("player") then return ShareTarget_prev(self, target, ...) end -- Prevents hound tamers from being shared as a target. if target:HasTag("houndtamer") then --Note: "inst.components.follower.leader.name == target.components.follower.leader.name" return end -- Prevents players and companions from being shared as a target. if target:HasTag("player") or target:HasTag("companion") then local houndtamer = GLOBAL.FindEntity(inst, 20, function(guy) return guy:HasTag("houndtamer") end) if houndtamer ~= nil then return end end return ShareTarget_prev(self, target, ...) end end My memory is hazy, but I thought I coded it to act normally with normally hounds, not to pick fights with players or big monsters, and not to gang up on players if a fight did start. hound_ai.lua
  12. I think I know how to do this, but it's not working the way I expect it to. print("Entity Tracker: ", inst.components.entitytracker:GetEntity("leader")) print("Combat Target: ", inst.components.combat.target) print("Attacker: ", inst.components.combat.attacker) I've coded some dogs to follow the player as followers, and when they stop following the player they die. This was meant to keep the hounds from going feral once the player exits the game. To my surprise, these hounds 'stop following the player' if the leader punches the dogs. This has resulted in some of my testers punching and resummoning the dogs for infinite meat. I'm sort of fixed this by limiting the likelihood of respawning to 80% as well as another punishment, but I figured I'd just make the respawn rate super low if the leader was the attacker. Well, for some reason the hounds consistently register 'nil' as an attacker. Does anyone know why this might be? function Follower:StopFollowing() if self.inst:IsValid() then self.inst:PushEvent("loseloyalty", { leader = self.leader }) self:SetLeader(nil) end end I've been looking through the code to figure out exactly why the hounds stop following the player when punched, but it's a little weird. I figure they're likely rejecting the player as their leader before registering the player as an attacker, but there may be something else going on, since I think I told the hounds they can't attack the player. hound_ai.lua
  13. @Dogmeat8990 I think you're looking for something like this: --AddRecipe(self, name, ingredients, tab, level, placer, min_spacing, nounlock, numtogive, builder_tag, atlas, image) AddRecipe("twigs", {Ingredient("flint", 1), Ingredient("log", 1), Ingredient(GLOBAL.CHARACTER_INGREDIENT.HEALTH, 50) }, RECIPETABS.SURVIVAL, TECH.SCIENCE_ONE, nil, nil, nil, 3, "YOURPLAYERSNAME")
  14. @IronHunter Well that explains a thing or two. The character prefab I downloaded originally makes these the same, so what's displayed is exactly the same as what I assign as the inventory.
  15. @TheSkylarr It's spawning two because one is in the 'starting inventory' code which makes the item displayed on the character select screen, and that item is spawned near spawn but never given to the player. The code we've been discussing gives the player a backpack, but doesn't display it on the character select screen. Edit: I'm trying to find the code that causes images to appear on the inventory screen, but no luck yet. I was thinking I might be able to force an image to appear. This isn't a big deal whether I figure it out or not, but it is a little frustrating.