Locke_C Posted July 16, 2024 Share Posted July 16, 2024 (edited) Hello, I have been trying to implement a custom badge for my character. It is essentially a meter to keep track of his "barrier", but before I can try to implement this I would like to make a badge for it. I looked through other modded characters and forum posts and ended up using most of my code from "ink sans". However, when in game the badge doesn't show. I can't tell if the issue is based from my 'anim' file, or something in the code. I looked through each and every function in "ink sans" emotion badge code, through a component, a badge widget, and a "display" widget that seems unorthodox. I checked through my character prefab, gave the correct components, added the functions that were in "ink sans" character prefab, renamed all of the variables accordingly. I also added in the emotions.zip anim file from "ink sans" and renamed it to my corresponding component. I can't tell what specifically goes wrong, and why the badge won't show, if it is an anim zip file issue I do not know where to start to make a custom badge's anim file, as I can't find any proper guides or forum posts on the topic. There is also a second issue as well, in which barrierstrong.lua (my component file) loads data incorrectly. I don't know why this is happening, I don't fully understand the component's code and I don't see why the data messes up when I look at it. This is the error: [string "../mods/Ward Rowan/scripts/components/barri..."]:99: attempt to index local 'data' (a number value) If anyone here can figure out the problem I would appreciate it very much. I have been stuck with these two issues for days and cannot figure it out. Below are the 4 lua files I believe to be relevant to the issue, and if there isn't anything wrong then the entire character is attached as a zip file. Apologies for leftover code staying commented out at certain places, and for the mess. barrierbadge.lua (widget) Spoiler local Badge = require "widgets/badge" local UIAnim = require "widgets/uianim" local BarrierBadge = Class(Badge, function(self, owner) Badge._ctor(self, "barrierstrong", owner) self.barriersarrow = self.underNumber:AddChild(UIAnim()) self.barriersarrow:GetAnimState():SetBank("sanity_arrow") self.barriersarrow:GetAnimState():SetBuild("sanity_arrow") self.barriersarrow:GetAnimState():PlayAnimation("neutral") self.barriersarrow:SetClickable(false) self.owner = owner owner.barriersarrow = self.barriersarrow self.val = 0 self.max = 100 self.arrowdir = nil self:StartUpdating() end) function BarrierBadge:SetPercent(val, max, penaltypercent) self.val = val self.max = max Badge.SetPercent(self, self.val, self.max) end function BarrierBadge:OnUpdate(dt) local percent = self.owner.currentbarriers:value() / self.owner.maxbarriers:value() local GetPercent = TheWorld.ismastersim and self.owner.components.barrierstrong ~= nil and self.owner.components.barrierstrong:GetPercent() or percent local anim = nil anim = "neutral" if anim and self.arrowdir ~= anim then self.arrowdir = anim self.barriersarrow:GetAnimState():PlayAnimation(anim, true) end end return BarrierBadge barrierdisplay.lua (widget) Spoiler local function BarriersStatusDisplays(self) if self.owner.prefab == "wardrowan" then local BarrierBadge = GLOBAL.require "widgets/barrierbadge" self.barrierstrong = self:AddChild(BarrierBadge(self.owner)) self.owner.barrierbadge = self.barrierstrong self._custombadge = self.barrierstrong --For the Status Announcements mod local BP = self.brain:GetPosition() local AOS = false for k,v in ipairs(GLOBAL.KnownModIndex:GetModsToLoad()) do local Mod = GLOBAL.KnownModIndex:GetModInfo(v).name if Mod == "Combined Status" then AOS = true end end if AOS then self.barrierstrong:SetPosition(-62, -52, 0) else self.barrierstrong:SetPosition(-40,-50,0) self.brain:SetPosition(BP.x + 40, BP.y - 10, 0) end local function OnSetPlayerMode(self) if self.onbarriersdelta == nil then self.onbarriersdelta = function(owner, data) self:BarriersDelta(data) end self.inst:ListenForEvent("barrierstrongdelta", self.onbarriersdelta, self.owner) if self.owner.components.barrierstrong ~= nil then self:SetBarriersPercent(self.owner.components.barrierstrong:GetPercent()) end end end local function OnSetGhostMode(self) if self.onbarriersdelta ~= nil then self.inst:RemoveEventCallback("barriersdelta", self.onbarriersdelta, self.owner) self.onbarriersdelta = nil end end self._SetGhostMode = self.SetGhostMode function self:SetGhostMode( ghostmode ) self._SetGhostMode( self, ghostmode ) if ghostmode then self.barrierstrong:Hide() OnSetGhostMode(self) else self.barrierstrong:Show() OnSetPlayerMode(self) end end function self:SetBarriersPercent(pct) if self.owner.components.barrierstrong ~= nil then self.barrierstrong:SetPercent(pct, self.owner.components.barrierstrong.max) end --[[ if pct <= 0.2 then self.emotions:StartWarning() else self.emotions:StopWarning() end ]]-- end function self:BarriersDelta(data) self:SetBarriersPercent(data.newpercent) if not data.overtime then if data.newpercent > data.oldpercent then self.barrierstrong:PulseGreen() GLOBAL.TheFrontEnd:GetSound():PlaySound("dontstarve/HUD/health_up") elseif data.newpercent < data.oldpercent then GLOBAL.TheFrontEnd:GetSound():PlaySound("dontstarve/HUD/health_down") self.barrierstrong:PulseRed() end end end OnSetPlayerMode(self) end end AddClassPostConstruct("widgets/statusdisplays", BarriersStatusDisplays) barrierstrong.lua (component file) Spoiler local function onmax(self, max) if self.inst ~= nil then assert(max >= 0 and max <= 65535, "Player maxbarriers out of range: "..tostring(max)) self.inst.maxbarriers:set(math.ceil(max)) end end local function oncurrent(self, current) if self.inst ~= nil then assert(current >= 0 and current <= 65535, "Player currentbarriers out of range: "..tostring(current)) self.inst.currentbarriers:set(math.ceil(current)) end end local BarrierStrong = Class(function(self, inst) self.inst = inst inst:AddTag("barrierstrong") self.max = 100 self.current = self.max self._old = self.current self.rate = 0 self.inst:StartUpdatingComponent(self) end, nil, { max = onmax, current = oncurrent, }) function BarrierStrong:GetMax() return self.max end function BarrierStrong:GetDelta() return self.rate end function BarrierStrong:GetRate() return self.rate end function BarrierStrong:DoDelta(delta, overtime, ignore_invincible) local old = self._old self.current = math.clamp(self.current + delta, 0, self.max) self._old = self.current if self.current < 0 then self.current = 0 elseif self.current > self:GetMax() then self.current = self:GetMax() end self.inst:PushEvent("barrierstrongdelta", { oldpercent = old / self.max, newpercent = self.current / self.max, overtime = overtime }) end function BarrierStrong:GetPercent() return self.current / self.max end function BarrierStrong:SetPercent(percent, overtime) self.current = self.max * percent self:DoDelta(0, overtime) end function BarrierStrong:OnUpdate(dt) self:Recalc(dt) end function BarrierStrong:Recalc(dt) local barrierstrong_supply = self.barrierstrong_supply or 0 local supply_delta = barrierstrong_supply*1 self.rate = -0.1 if self.custom_rate_fn then self.rate = self.rate + self.custom_rate_fn(self.inst) end self:DoDelta(self.rate*dt, true) end function BarrierStrong:LongUpdate(dt) self:OnUpdate(dt) end function BarrierStrong:OnSave() return { current = self.current } end function BarrierStrong:OnLoad(data) if data ~= nil and data.current ~= nil then self.current = data.current self:DoDelta(0, true) end end function BarrierStrong:GetDebugString() return string.format("%2.2f / %2.2f at %2.4f", self.current, self.max, self.rate) end function BarrierStrong:SetMax(amount) self.max = amount self:DoDelta(0, true) end return BarrierStrong wardrowan.lua (prefab file) Spoiler local MakePlayerCharacter = require "prefabs/player_common" local assets = { Asset("SCRIPT", "scripts/prefabs/player_common.lua"), } -- Your character's stats TUNING.WARDROWAN_HEALTH = 200 TUNING.WARDROWAN_HUNGER = 150 TUNING.WARDROWAN_SANITY = 150 TUNING.WARDROWAN_DAMAGE_MULT = 1.1 TUNING.WARDROWAN_DAMAGE_ABSORB = 0.1 TUNING.WARDROWAN_HUNGER_RATE = 1 TUNING.WARDROWAN_DAPPERNESS = 3.3 TUNING.WARDROWAN_SANITY_DAMAGE_RATE = 1 TUNING.WARDROWAN_SANITY_DAMAGE_OVERTIME_RATE = 0 -- Custom starting inventory TUNING.GAMEMODE_STARTING_ITEMS.DEFAULT.WARDROWAN = { "flint", "flint", "twigs", "twigs", } local start_inv = {} for k, v in pairs(TUNING.GAMEMODE_STARTING_ITEMS) do start_inv[string.lower(k)] = v.WARDROWAN end local prefabs = FlattenTree(start_inv, true) local function onbarriersdelta(inst, data) if inst:HasTag("playerghost") or inst.components.health:IsDead() then return end end -- When the character is revived from human local function onbecamehuman(inst) -- Set speed when not a ghost (optional) inst.components.locomotor:SetExternalSpeedMultiplier(inst, "wardrowan_speed_mod", 1) end local function onbecameghost(inst) -- Remove speed modifier when becoming a ghost inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "wardrowan_speed_mod") inst.components.barrierstrong:SetPercent(0.4333) end local function onbarriersdeltaNet(parent, data) if data.overtime then elseif data.newpercent > data.oldpercent then SetDirty(parent.isbarrierspulseup, true) elseif data.newpercent < data.oldpercent then SetDirty(parent.isbarrierspulsedown, true) end end local function OnBarriersDirty(inst) if not TheWorld.ismastersim and inst.barrierbadge ~= nil then local oldpercent = inst._oldbarrierspercent if oldpercent == nil then oldpercent = 0 end local percent = inst.currentbarriers:value() / inst.maxbarriers:value() local data = { oldpercent = oldpercent, newpercent = percent, overtime = not (inst.isbarrierspulseup:value() and percent > oldpercent) and not (inst.isbarrierspulsedown:value() and percent < oldpercent), } inst._oldbarrierspercent = percent inst.isbarrierspulseup:set_local(false) inst.isbarrierspulsedown:set_local(false) inst:PushEvent("barriersdelta", data) inst.barrierbadge:SetPercent(percent, inst.maxbarriers:value()) end end -- When loading or spawning the character local function onload(inst, data) inst:ListenForEvent("ms_respawnedfromghost", onbecamehuman) inst:ListenForEvent("ms_becameghost", onbecameghost) if inst:HasTag("playerghost") then onbecameghost(inst) else onbecamehuman(inst) end end local function OnSave(inst,data) data.barrierstrong = inst.barrierstrong:value() end local function OnBarriersDirty(inst) if not TheWorld.ismastersim and inst.barrierbadge ~= nil then local oldpercent = inst._oldbarrierspercent if oldpercent == nil then oldpercent = 0 end local percent = inst.currentbarriers:value() / inst.maxbarriers:value() local data = { oldpercent = oldpercent, newpercent = percent, overtime = not (inst.isbarrierspulseup:value() and percent > oldpercent) and not (inst.isbarrierspulsedown:value() and percent < oldpercent), } inst._oldbarrierspercent = percent inst.isbarrierspulseup:set_local(false) inst.isbarrierspulsedown:set_local(false) inst:PushEvent("barrierstrongdelta", data) inst.barrierbadge:SetPercent(percent, inst.maxbarriers:value()) end end local function OnEquip(inst, data) if data ~= nil and data.item ~= nil then if data.item.components.armor ~= nil then inst.components.inventory:DropItem(data.item) inst.components.talker:Say(({"That will not be necessary.", "I don't have any need for armor.", "My barrier is far better."})[math.random(3)]) -- inst.components.inventory:Unequip(data.item.components.equippable.equipslot) end end end local function OnHealthDelta(inst, data) if data.amount < 0 then inst.components.sanity:DoDelta(data.amount * ((data ~= nil and data.overtime) and TUNING.WARDROWAN_SANITY_DAMAGE_OVERTIME_RATE or TUNING.WARDROWAN_SANITY_DAMAGE_RATE)) inst.components.barrierstrong:DoDelta(data.amount * ((data ~= nil and data.overtime) and TUNING.WARDROWAN_SANITY_DAMAGE_OVERTIME_RATE or TUNING.WARDROWAN_SANITY_DAMAGE_RATE)) end end -- This initializes for both the server and client. Tags can be added here. local common_postinit = function(inst) -- Minimap icon inst.MiniMapEntity:SetIcon( "wardrowan.tex" ) -- Tags inst:AddTag("nowormholesanityloss") inst.currentbarriers = net_ushortint(inst.GUID, "barrierstrong.current", "barrierstrongdirty") inst.maxbarriers = net_ushortint(inst.GUID, "barrierstrong.max", "barrierstrongdirty") inst.isbarrierspulseup = net_bool(inst.GUID, "barrierstrong.dodeltaovertime(up)", "barrierstrongdirty") inst.isbarrierspulsedown = net_bool(inst.GUID, "barrierstrong.dodeltaovertime(down)", "barrierstrongdirty") if not TheWorld.ismastersim then inst:ListenForEvent("barriersdirty", OnBarriersDirty) else inst:ListenForEvent("barriersdelta", onbarriersdeltaNet, inst.entity:GetParent()) end inst.barrierstrong = net_ushortint(inst.GUID, "barrierstrong", "barrierstrongdirty" ) --net_ushortint is the typical use of stats --"name" is the name of the netvariable --"namesdirty" is an Event which is called whenever this is changed inst.barrierstrong:set(100) -- inst.name:set(number) [same as] inst.name = number inst.barrierstrong:value() --getting the value of the net_variable end -- This initializes for the server only. Components are added here. local master_postinit = function(inst) -- Set starting inventory inst.starting_inventory = start_inv[TheNet:GetServerGameMode()] or start_inv.default -- choose which sounds this character will play inst.soundsname = "willow" -- Uncomment if "wathgrithr"(Wigfrid) or "webber" voice is used --inst.talker_path_override = "dontstarve_DLC001/characters/" -- Setting Basic Stats inst.components.health:SetMaxHealth(TUNING.WARDROWAN_HEALTH) inst.components.hunger:SetMax(TUNING.WARDROWAN_HUNGER) inst.components.sanity:SetMax(TUNING.WARDROWAN_SANITY) inst:AddComponent("barrierstrong") -- Listen for events inst:ListenForEvent("healthdelta", OnHealthDelta) -- Damage on hit sanity loss inst:ListenForEvent("equip", OnEquip) -- Damage Dealt and Taken Modifiers inst.components.combat.damagemultiplier = 1 * TUNING.WARDROWAN_DAMAGE_MULT inst.components.health.absorb = 1 * TUNING.WARDROWAN_DAMAGE_ABSORB -- Hunger Rate and Favorite Food inst.components.hunger.hungerrate = TUNING.WILSON_HUNGER_RATE * TUNING.WARDROWAN_HUNGER_RATE inst.components.foodaffinity:AddPrefabAffinity("honeyham", TUNING.AFFINITY_15_CALORIES_HUGE) -- Sanity Regen inst.components.sanity.dapperness = 0.016 * TUNING.WARDROWAN_DAPPERNESS inst.components.sanity:SetNegativeAuraImmunity(true) inst.OnLoad = onload inst.OnSave = OnSave inst.OnNewSpawn = onload end return MakePlayerCharacter("wardrowan", prefabs, assets, common_postinit, master_postinit, prefabs) Also, in modmain.lua I have this snippet of code at the bottom of the file, as the other mod had it. Spoiler modimport("scripts/widgets/barrierdisplay.lua") Again, sorry for the messy bloated code, and I would be grateful for help. Thank you. Ward Rowan.zip Edited July 16, 2024 by Locke_C Link to comment https://forums.kleientertainment.com/forums/topic/158309-custom-badge-code-doesnt-work/ Share on other sites More sharing options...
Locke_C Posted July 17, 2024 Author Share Posted July 17, 2024 bump Link to comment https://forums.kleientertainment.com/forums/topic/158309-custom-badge-code-doesnt-work/#findComment-1736001 Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now