My mod currently provides spawned pets that use the Cat's behaviors and whatnot. They're literal copy-pastes with different sprites and filenames, which worked on Stable. On Unstable/Nightly, there's an updated AI for the cat, so I went to test out what needed changing. Again, I made a complete copy/paste of the cat, and changed the names and directories. When I load the game and spawn the critter, it dies instantly and cannot be captured. The log file only has one error, and points to groundpet.lua. Here's the lua: Code: function init() self.pathing = {} self.pathing.stuckTimer = 0 self.pathing.maxStuckTime = 2 self.jumpCooldown = 0 self.jumpMaxCooldown = 1 self.movementParameters = mcontroller.baseParameters() self.jumpHoldTime = self.movementParameters.airJumpProfile.jumpHoldTime self.jumpSpeed = self.movementParameters.airJumpProfile.jumpSpeed self.runSpeed = self.movementParameters.runSpeed self.stuckPosition = mcontroller.position() self.stuckCount = 0 self.scriptDelta = 5 storage.petResources = storage.petResources or entity.configParameter("petResources") self.petResourceDeltas = entity.configParameter("petResourceDeltas") setPetResources(storage.petResources) self.state = stateMachine.create({ "idleState", "wanderState" }) local actionStates = {} local actions = stateMachine.scanScripts(entity.configParameter("scripts"), "(%a+Action)%.lua") for _, action in pairs(actions) do table.insert(actionStates, 1, action) end self.actionState = stateMachine.create(actionStates) self.followTarget = 0 self.behaviorName = entity.configParameter("behavior") self.behavior = _ENV[self.behaviorName] storage.behaviorParams = storage.behaviorParams or entity.configParameter("behaviorParams") self.querySurroundingsCooldown = entity.configParameter("querySurroundingsCooldown", 3) self.querySurroundingsTimer = 1 self.querySurroundingsRange = entity.configParameter("querySurroundingsRange", 50) self.debug = true if capturepod and capturepod.onInit then capturepod.onInit() end if self.behavior and self.behavior.init then self.behavior.init() end end function update(dt) if self.actionState.stateDesc() ~= "" or self.actionState.pickState() then self.actionState.update(dt) end --Some action states are triggered by resources if self.actionState.stateDesc() == "" and not self.state.update(dt) then self.state.pickState() end if self.querySurroundingsTimer <= 0 then querySurroundings() self.querySurroundingsTimer = self.querySurroundingsTimer + self.querySurroundingsCooldown end if self.debug then script.setUpdateDelta(1) if self.actionState.stateDesc() ~= "" then world.debugText(self.actionState.stateDesc(), mcontroller.position(), "blue") else world.debugText(self.state.stateDesc(), mcontroller.position(), "blue") end drawDebugResources() end tickResources(dt) decrementTimers(dt) if not self.moved then resetPathing() end end function damage(args) if capturepod ~= nil and capturepod.onDamage(args) then return end end function die() if capturepod ~= nil then capturepod.onDie() end end function querySurroundings() local nearEntities = world.entityQuery(mcontroller.position(), self.querySurroundingsRange, {includedTypes={"player", "itemDrop"}}) --Queue up reactions for _,entityId in ipairs(nearEntities) do self.behavior.reactTo(entityId) end --Run actions self.behavior.run() return false end function emote(emoteType) entity.burstParticleEmitter("emote"..emoteType) end function itemFoodLiking(entityName) if not entityName or root.itemType(entityName) ~= "consumable" then return false end local foodLiking = storage.behaviorParams.food[entityName] if foodLiking == nil then return nil end --How much does it like the food if foodLiking == true or foodLiking == false then if foodLiking == true then foodLiking = math.random(50, 100) elseif foodLiking == false then foodLiking = math.random(0, 50) end storage.behaviorParams.food[entityName] = foodLiking end return foodLiking end function petResources() local resources = {} for resourceName, resourceValue in pairs(storage.petResources) do resources[resourceName] = status.resource(resourceName) end return resources end function setPetResources(resources) for resourceName, resourceValue in pairs(resources) do status.setResource(resourceName, resourceValue) end end function tickResources(dt) for resourceName, resourceDelta in pairs(self.petResourceDeltas) do status.modifyResource(resourceName, resourceDelta * dt) end end function drawDebugResources() local resources = storage.petResources local position = mcontroller.position() local y = 2 for resourceName, resourceValue in pairs(storage.petResources) do --Border world.debugLine(vec2.add(position, {-2, y+0.125}), vec2.add(position, {-2, y + 0.75}), "black") world.debugLine(vec2.add(position, {-2, y + 0.75}), vec2.add(position, {2, y + 0.75}), "black") world.debugLine(vec2.add(position, {2, y + 0.75}), vec2.add(position, {2, y+0.125}), "black") world.debugLine(vec2.add(position, {2, y+0.125}), vec2.add(position, {-2, y+0.125}), "black") local width = 3.75 * status.resource(resourceName) / 100 world.debugLine(vec2.add(position, {-1.875, y + 0.25}), vec2.add(position, {-1.875 + width, y + 0.25}), "green") world.debugLine(vec2.add(position, {-1.875, y + 0.375}), vec2.add(position, {-1.875 + width, y + 0.375}), "green") world.debugLine(vec2.add(position, {-1.875, y + 0.5}), vec2.add(position, {-1.875 + width, y + 0.5}), "green") world.debugLine(vec2.add(position, {-1.875, y + 0.625}), vec2.add(position, {-1.875 + width, y + 0.625}), "green") world.debugText(resourceName, vec2.add(position, {2.25, y - 0.125}), "blue") y = y + 1 end end function decrementTimers(dt) self.querySurroundingsTimer = self.querySurroundingsTimer - dt self.jumpCooldown = self.jumpCooldown - dt end function setMovementState(running) if not mcontroller.onGround() then setJumpState() else if running then entity.setAnimationState("movement", "run") else entity.setAnimationState("movement", "walk") end end end function setIdleState() if not mcontroller.onGround() then setJumpState() else entity.setAnimationState("movement", "idle") end end function setJumpState() if mcontroller.yVelocity() > 0 then entity.setAnimationState("movement", "jumping") else entity.setAnimationState("movement", "falling") end end function boundingBox(force) if self.boundingBox and not force then return self.boundingBox end local collisionPoly = mcontroller.collisionPoly() local bounds = {0, 0, 0, 0} for _,point in pairs(collisionPoly) do if point[1] < bounds[1] then bounds[1] = point[1] end if point[2] < bounds[2] then bounds[2] = point[2] end if point[1] > bounds[3] then bounds[3] = point[1] end if point[2] > bounds[4] then bounds[4] = point[2] end end self.boundingBox = bounds return bounds end -------------------------------------------------------------------------------- -- draw lines to display the specified rect {x1, y1, x2, y2} in the specified color, optionally offset by basePos function drawDebugRect(rect, color, basePos) if basePos then rect = translate(rect, basePos) end world.debugLine({rect[1], rect[2]}, {rect[1], rect[4]}, color) world.debugLine({rect[1], rect[2]}, {rect[3], rect[2]}, color) world.debugLine({rect[3], rect[4]}, {rect[1], rect[4]}, color) world.debugLine({rect[3], rect[4]}, {rect[3], rect[2]}, color) end -------------------------------------------------------------------------------- -- draw lines and points to show the current path function drawDebugPath(goalDelta) local position = mcontroller.position() local step = 0 local prevStep = position while true do local nextStep = entity.pathLookahead(step) if nextStep then world.debugLine(prevStep, vec2.add(position, nextStep), "blue") world.debugPoint(vec2.add(position, nextStep), "blue") prevStep = vec2.add(position, nextStep) step = step + 1 else break end end if goalDelta then local goalPosition = vec2.add(goalDelta, position) world.debugLine(position, goalPosition, "green") world.debugPoint(goalPosition, "green") end end -------------------------------------------------------------------------------- --MOVEMENT--------------------------------------------------------------------- -------------------------------------------------------------------------------- function approachPoint(dt, targetPosition, stopDistance, running) local toTarget = world.distance(targetPosition, mcontroller.position()) local targetDistance = world.magnitude(targetPosition, mcontroller.position()) local groundPosition = findGroundPosition(targetPosition, -20, 1, util.toDirection(-toTarget[1])) if groundPosition then self.approachPosition = groundPosition end if self.approachPosition and targetDistance > stopDistance then if moveTo(self.approachPosition, dt, {run = running}) then mcontroller.controlFace(self.pathing.deltaX or toTarget[1]) setMovementState(running) else entity.setAnimationState("movement", "idle") end return false elseif targetDistance <= stopDistance then return true end end -------------------------------------------------------------------------------- function moveX(direction, run) mcontroller.controlMove(direction, run) self.pathing.deltaX = direction end -------------------------------------------------------------------------------- function move(direction, options) if options == nil then options = {} end if options.run == nil then options.run = false end direction = util.toDirection(direction) local position = mcontroller.position() local boundsEdge = 0 local bounds = boundingBox() local tilePosition if direction > 0 then tilePosition = {math.ceil(position[1]), position[2]} boundsEdge = bounds[3] else tilePosition = {math.floor(position[1]), position[2]} boundsEdge = bounds[1] end --Stop at walls if world.lineCollision({position[1], position[2] + bounds[2] + 1.5}, { position[1] + boundsEdge + direction, position[2] + bounds[2] + 1.5}, true) then return false, "wall" end --Check if the position ahead is valid, including slopes local yDirs = {0, 1, -1} for _,yDir in ipairs(yDirs) do if findValidStandingPosition({tilePosition[1] + direction, tilePosition[2] + yDir}, direction) then moveX(direction, options.run) return true end end return false, "ledge" end -------------------------------------------------------------------------------- -- Valid options: -- openDoorCallback: function that will be passed a door entity id and should -- return true if the door can be opened -- run: whether npc should run function moveTo(targetPosition, dt, options) if options == nil then options = {} end if options.run == nil then options.run = false end self.moved = true targetPosition = { math.floor(targetPosition[1]) + 0.5, math.floor(targetPosition[2]) + 0.5 } local toTargetPosition = world.distance(targetPosition, mcontroller.position()) if math.abs(toTargetPosition[1]) < 2 and math.abs(toTargetPosition[2]) < 2 then moveX(toTargetPosition[1], options.run) return true end --Find new path if target position has changed local pathTargetPosition = self.pathing.targetPosition if pathTargetPosition == nil or targetPosition[1] ~= pathTargetPosition[1] or targetPosition[2] ~= pathTargetPosition[2] then local innerRadius = -1 local outerRadius = 1 if entity.findPath(targetPosition, innerRadius, outerRadius) then self.pathing.targetPosition = targetPosition else return false end self.pathing.delta = nil end if self.debug then drawDebugPath() end -- Store the path delta in case pathfinding doesn't succeed on the next try local pathDelta = entity.followPath() if pathDelta == nil then self.pathing.targetPosition = nil else self.pathing.delta = pathDelta end --New path and we can't move on it, try new path if self.pathing.delta == nil then self.pathing.targetPosition = nil return false end local position = mcontroller.position() local verticalPathUp = verticalPathLength("up") local verticalPathDown = verticalPathLength("down") --Keep jumping if (self.pathing.jumpHoldTimer ~= nil and verticalPathUp > 0) or self.pathing.goalJumpPosition then keepJumping(dt, options) return true end self.pathing.jumpHoldTimer = nil --Keep dropping if (self.pathing.downHoldTimer ~= nil and verticalPathDown > 0) or self.pathing.goalJumpPosition then keepDropping(dt, options) return true end self.pathing.downHoldTimer = nil script.setUpdateDelta(self.scriptDelta) local delta = entity.pathLookahead(0) or self.pathing.delta local nextPathPosition = vec2.add(position, delta) local goalPosition, forwardPosition, backwardPosition = findValidStandingPosition(nextPathPosition, util.toDirection(delta[1])) --Swimming if goalPosition and mcontroller.liquidMovement() and world.liquidAt(goalPosition) then local goalDelta = world.distance(goalPosition, position) if goalDelta[2] > 0 then mcontroller.controlJump() mcontroller.controlHoldJump() end moveX(goalDelta[1], options.run) return true end --If there is a ledge, don't use this position if goalPosition and not forwardPosition then goalPosition = nil end local nextDelta = entity.pathLookahead(1) --If very close to a path node, or between two path nodes, use the next if goalPosition and nextDelta and (delta[1] * nextDelta[1] < 0 or world.magnitude(delta) < 0.5) then goalPosition = nil end --If the next path node isn't valid (can't stand there), search the path for a valid one local step = 1 local maxSteps = 30 local deltaStep = 0 local deltaDir = delta[1] local goalPathNode = entity.pathLookahead(step) while not goalPosition and step < maxSteps do goalPathNode = entity.pathLookahead(step) if goalPathNode then nextPathPosition = vec2.add(position, goalPathNode) goalPosition, forwardPosition, backwardPosition = findValidStandingPosition(nextPathPosition, util.toDirection(goalPathNode[1])) local nextDeltaDir = goalPathNode[1] - delta[1] if deltaStep == 0 or (deltaStep == step - 1 and nextDeltaDir * deltaDir >= 0) then if nextDeltaDir ~= 0 or deltaStep == 0 then deltaDir = nextDeltaDir end deltaStep = step delta = goalPathNode end step = step + 1 else break end end --No valid position found, stop moving and find new path if not goalPosition then self.pathing.targetPosition = nil return false end if checkPathStuck(dt, goalPathNode) then return false else self.pathing.stuckTimer = self.pathing.stuckTimer + dt end if self.debug then world.debugLine(position, goalPosition, "green") world.debugPoint(goalPosition, "green") world.debugLine(position, vec2.add(position, delta), "yellow") world.debugPoint(vec2.add(position, delta), "yellow") end --Move on path local goalDelta = world.distance(goalPosition, position) local verticalMovementRatio = math.abs(goalDelta[2] / goalDelta[1]) if goalDelta[1] == 0 then verticalMovementRatio = 10 end local maxVerticalRatio = 1.25 --Enough to not drop down or jump up stairs --Keep from dropping or jumping in stairs if we don't need to if verticalMovementRatio > maxVerticalRatio and forwardPosition then goalDelta = world.distance(forwardPosition, position) verticalMovementRatio = math.abs(goalDelta[2] / goalDelta[1]) end --Path wants to take us steeply up, jump if ((verticalMovementRatio > maxVerticalRatio and goalDelta[2] > 0) or verticalPathUp > 1) then if (not closeToCeiling() or mcontroller.xVelocity() == 0) and delta[1] * goalDelta[1] > 0 and delta[1] * mcontroller.xVelocity() >= 0 then local jumpHold = math.max(verticalPathUp / self.jumpSpeed, distanceJumpTime(goalDelta)) timedJump(math.max(jumpHold, 0.02), backwardPosition or forwardPosition, goalDelta[1]) else moveX(delta[1], options.run) self.pathing.deltaX = util.toDirection(goalDelta[1]) end return true end --Path is taking us steeply down, drop if ((verticalMovementRatio > maxVerticalRatio and goalDelta[2] < 0) or verticalPathDown > 1) and not onSolidGround() then local dropHold = timeToFall(math.max(-goalDelta[2], verticalPathDown)) timedDrop(dropHold) return true end --Jump over gaps local deltaDir = util.toDirection(goalDelta[1]) local nextStepPosition = {position[1] + deltaDir, position[2]} if deltaDir > 0 then nextStepPosition[1] = math.ceil(nextStepPosition[1]) else nextStepPosition[1] = math.floor(nextStepPosition[1]) end if (verticalMovementRatio < 0.5 or goalDelta[2] > 0) and math.abs(goalDelta[1]) > 1.5 then --Could be stairs, check diagonally if not findValidStandingPosition({nextStepPosition[1], nextStepPosition[2]}, deltaDir) and not findValidStandingPosition({nextStepPosition[1], nextStepPosition[2] - 1}, deltaDir) and not findValidStandingPosition({nextStepPosition[1], nextStepPosition[2] + 1}, deltaDir) then timedJump(distanceJumpTime(goalDelta), forwardPosition or backwardPosition, deltaDir) return true end end --Edge case - jump over small bumps that aren't slopes local bounds = boundingBox() local groundTestRegion = { position[1] - 0.95, position[2] + bounds[2] - 0.95, position[1] - 0.05, position[2] + bounds[2] - 0.05 } local wallTestRegion = { position[1] - 0.95, position[2] + bounds[2] + 0.05, position[1] - 0.05, position[2] + bounds[2] + 0.95 } if deltaDir > 0 then groundTestRegion[1] = groundTestRegion[1] + bounds[3] groundTestRegion[3] = groundTestRegion[3] + bounds[3] wallTestRegion[1] = groundTestRegion[1] + 1 wallTestRegion[3] = groundTestRegion[3] + 1 else groundTestRegion[1] = groundTestRegion[1] + bounds[1] + 1 groundTestRegion[3] = groundTestRegion[3] + bounds[1] + 1 wallTestRegion[1] = groundTestRegion[1] - 1 wallTestRegion[3] = groundTestRegion[3] - 1 end drawDebugRect(groundTestRegion, "blue") drawDebugRect(wallTestRegion, "blue") if verticalMovementRatio > 0.5 and not world.rectCollision(groundTestRegion, false) and world.rectCollision(wallTestRegion, false) then timedJump(0.02, {position[1] + deltaDir * 2, position[2] + 1}) return true end moveX(goalDelta[1], options.run) return true end --PATHING-- -------------------------------------------------------------------------------- -- Get total length of a vertical path, step by step function verticalPathLength(yDirection) local direction = {up = 1, down = -1} local step = 1 local firstDelta = entity.pathLookahead(0) local lastDelta = entity.pathLookahead(step) local length = 0 while lastDelta do local deltaDiff = lastDelta[2] - firstDelta[2] if deltaDiff * direction[yDirection] > 0 and lastDelta[1] == firstDelta[1] then length = math.abs(deltaDiff) step = step + 1 lastDelta = entity.pathLookahead(step) else break end end return length end --JUMPING AND DROPPING-- -------------------------------------------------------------------------------- --Jump and hold jump for holdTime, also approach goalPosition function timedJump(holdTime, goalPosition, facingDirection) if self.jumpCooldown > 0 then entity.setAnimationState("movement", "idle") self.stuckCount = 0 return true end if not mcontroller.onGround() and not mcontroller.liquidMovement() then return nil end if holdTime == nil then holdTime = 0 end holdTime = math.min(holdTime, self.jumpHoldTime) if mcontroller.liquidMovement() then holdTime = holdTime + self.jumpHoldTime end mcontroller.controlJump() self.pathing.jumpHoldTimer = holdTime self.pathing.goalJumpPosition = goalPosition self.pathing.jumpFacingDirection = facingDirection script.setUpdateDelta(1) self.jumpCooldown = self.jumpMaxCooldown end --Keep holding jump for the duration of the timed jump function keepJumping(dt, options) if self.pathing.jumpHoldTimer ~= nil then mcontroller.controlHoldJump() self.pathing.jumpHoldTimer = self.pathing.jumpHoldTimer - dt if self.pathing.jumpHoldTimer <= 0 then self.pathing.jumpHoldTimer = nil end end if (mcontroller.onGround() or mcontroller.liquidMovement()) and not self.pathing.jumpHoldTimer then self.pathing.goalJumpPosition = nil self.pathing.jumpFacingDirection = nil end if self.pathing.goalJumpPosition then local goalDelta = world.distance(self.pathing.goalJumpPosition, mcontroller.position()) moveX(goalDelta[1], options.run) end if self.pathing.jumpFacingDirection then mcontroller.controlFace(self.pathing.jumpFacingDirection) self.pathing.deltaX = self.pathing.jumpFacingDirection end end --Drop and hold down for holdTime, also approach goalPosition function timedDrop(holdTime, goalPosition) if holdTime == nil then holdTime = 0 end holdTime = math.min(holdTime, 0.5) mcontroller.controlDown() self.pathing.downHoldTimer = holdTime self.pathing.goalJumpPosition = goalPosition script.setUpdateDelta(1) end --Keep holding down function keepDropping(dt, options) if self.pathing.downHoldTimer ~= nil then mcontroller.controlDown() self.pathing.downHoldTimer = self.pathing.downHoldTimer - dt if self.pathing.downHoldTimer <= 0 then self.pathing.downHoldTimer = nil end end if self.pathing.goalJumpPosition then local goalDelta = world.distance(self.pathing.goalJumpPosition, mcontroller.position()) moveX(goalDelta[1], options.run) end end --Returns the time the entity needs to hold jump to reach the specified distance --TODO: Make this not bad by using math function distanceJumpTime(distance) local position = mcontroller.position() local gravity = world.gravity(mcontroller.position()) local fallDistanceTime = (math.abs(distance[1]) / 2) / self.runSpeed local fallDistance = (gravity / 2) * fallDistanceTime * fallDistanceTime fallDistance = fallDistance + distance[2] local holdTime = fallDistance / self.jumpSpeed return holdTime end --The time it would take to fall distance function timeToFall(distance) local gravity = world.gravity(mcontroller.position()) return math.sqrt(2 * distance / gravity) end --POSITIONING-- -------------------------------------------------------------------------------- --Finds a position on top of a tile (rather than in between tiles) that the entity can stand on function findValidStandingPosition(nodePosition, direction) if forceDirection == nil then forceDirection = false end local forwardCollisionResolve = validStandingPosition(nodePosition, direction) local backwardCollisionResolve = validStandingPosition(nodePosition, -direction) if forwardCollisionResolve or backwardCollisionResolve then return nodePosition, forwardCollisionResolve, backwardCollisionResolve end end --Checks if the entity can stand in this position --Or if it can swim there function validStandingPosition(position, direction) direction = util.toDirection(direction) local collisionPoly = mcontroller.collisionPoly() local bounds = boundingBox() local groundRegion = { position[1] + math.min(direction * math.max(-bounds[1], 1), 0) + 0.05, position[2] + bounds[2] - 0.1, position[1] + math.max(direction * math.max(bounds[3], 1), 0) - 0.05, position[2] + bounds[2] } local collisionResolve = world.resolvePolyCollision(collisionPoly, {position[1] + direction/2, position[2]}, 0.2) if (world.rectCollision(groundRegion, false) or world.liquidAt(position)) and collisionResolve and (world.material({groundRegion[1], groundRegion[2]}, "foreground") or world.material({groundRegion[3], groundRegion[4]}, "foreground")) then if self.debug then drawDebugRect(groundRegion, "blue") end return collisionResolve end end --Find a valid ground position function findGroundPosition(position, minHeight, maxHeight, direction) local bounds = boundingBox() position[2] = math.floor(position[2] + bounds[2] % 1) if direction == nil then direction = 1 end --Check upward for y = 0, maxHeight do local validPosition, forwardPosition, backwardPosition = findValidStandingPosition({position[1], position[2] + y}, direction) if validPosition then return validPosition, forwardPosition, backwardPosition end end --Check downward for y = -1, minHeight, -1 do local validPosition, forwardPosition, backwardPosition = findValidStandingPosition({position[1], position[2] + y}, direction) if validPosition then return validPosition, forwardPosition, backwardPosition end end return false end --Check if entity is right under a solid block ceiling function closeToCeiling() local position = mcontroller.position() local bounds = boundingBox() local ceilingRegion = { position[1] + bounds[1], position[2] + 1, position[1] + bounds[3], position[2] + 6 } return world.rectCollision(ceilingRegion, true) end --Check if entity is on solid ground (not platforms) function onSolidGround() local position = mcontroller.position() local bounds = boundingBox() local groundRegion = { position[1] + bounds[1] - 0.05, position[2] + bounds[2] - 0.95, position[1] + bounds[3] + 0.05, position[2] + bounds[2] + 0.05 } return world.rectCollision(groundRegion, true) end function checkPathStuck(dt, goalNode) if self.pathing.stuckNode == nil then self.pathing.stuckNode = vec2.add(mcontroller.position(), goalNode or entity.pathLookahead(0)) end --Search path for stuck check node local step = 0 local checkNode = nil while step do nextPathNode = entity.pathLookahead(step) if nextPathNode then nextPathNode = vec2.add(mcontroller.position(), nextPathNode) if self.pathing.stuckNode[1] == nextPathNode[1] and self.pathing.stuckNode[2] == nextPathNode[2] then checkNode = nextPathNode end step = step + 1 else step = nil end end if checkNode then --The node is still in the path meaning we haven't reached it yet. Maybe stuck if self.pathing.stuckTimer > self.pathing.maxStuckTime then return true end return false end --The node is not in the path, we've probably passed it self.pathing.stuckNode = nil self.pathing.stuckTimer = 0 return false end function resetPathing() self.pathing.stuckNode = nil self.pathing.stuckTimer = 0 end The error says; Code: [12:45:42.534] Error: Exception while invoking lua function 'init'. (LuaException) Error code 2, [string "/monsters/pets/groundPet.lua"]:150: bad argument #1 to 'pairs' (table expected, got nil) 000000001896CB60 000000001896C510 The cat works on unstable/nightly, so whatever is wrong doesn't affect the cat. What can I do to fix this? EDIT: Forgot to note, JSON validators all say this: Code: Parse error on line 1: functioninit()self.p ^ Expecting '{', '[' But adding those does nothing.[DOUBLEPOST=1424023512][/DOUBLEPOST]Quick update; I added a space between "function init()" and "self.pathing = {}", so that error ended. Now I get this error: Code: [13:01:16.940] Error: Exception while invoking lua function 'init'. (LuaException) Error code 2, [string "/monsters/pets/groundPet.lua"]:151: bad argument #1 to 'pairs' (table expected, got nil) 0000000008E4CB60 0000000008E4C510 Line 151 is as such; Code: for resourceName, resourceValue in pairs(resources) do Again, not sure what I should do to fix this.
Lua isn't Json, don't use a json checker on lua code, it won't tell you anything worthwile (on any other file, it's a good reflex though). The error suggests that storage.petResources hasn't been properly set line 19, which means that "petResources" isn't defined in your pet .monstertype file. My groundpet.lua file however is different and doesn't need some "petResources" parameter (maybe because my version isn't totally up to date, i'll update it) so i can't help you much more for now.
I'm still wet behind the ears on coding, so I didn't know that lua didn't involve JSON. That helped a good deal in helping me find the problem. Looking into it, the cat's new monstertype file had some extra stuff that I didn't notice. All the issues led to the monstertype file, and now I have it fixed. Thank you for pointing me in the right direction!