--*********************************************************** --** ROBERT JOHNSON ** --*********************************************************** require "TimedActions/ISBaseTimedAction" ISBuildAction = ISBaseTimedAction:derive("ISBuildAction"); -- The FMOD events have approx. 10-second duration even though the sounds are shorter. ISBuildAction.soundDelay = 6 function ISBuildAction:isReachableThroughWindow(_square) local objects = _square:getObjects(); for i = 0, objects:size() - 1 do local object = objects:get(i); if object and instanceof(object, "IsoWindow") then local curtains = object:HasCurtains(); if curtains then if curtains:IsOpen() then if object:canClimbThrough(self.character) then return true; end; end; else if object:canClimbThrough(self.character) then return true; end; end; end; end; return false; end function ISBuildAction:isValid() local plSquare = self.character:getSquare(); if (plSquare and self.square) and (plSquare:getZ() == self.square:getZ()) then if self.square:isSomethingTo(plSquare) then if (not luautils.isSquareAdjacentToSquare(plSquare, self.square)) then self:stop(); return false; end; if not (self:isReachableThroughWindow(self.square) or self:isReachableThroughWindow(plSquare)) then self:stop(); return false; end; end; else self:stop(); return false; end; --- if not self.item.noNeedHammer and self.hammer then return self.hammer:getCondition() > 0; end return true; end function ISBuildAction:waitToStart() if ISBuildMenu.cheat then return false end self:faceLocation() return self.character:shouldBeTurning() end function ISBuildAction:update() local worldSoundRadius = 0 -- Players with the Deaf trait don't play sounds. In multiplayer, we mustn't send multiple sounds to other clients. if self.soundTime + ISBuildAction.soundDelay < getTimestamp() then self.soundTime = getTimestamp() if not self.item.noNeedHammer then local playingSaw = self.sawSound ~= 0 and self.character:getEmitter():isPlaying(self.sawSound) local playingHammer = self.hammerSound ~= 0 and self.character:getEmitter():isPlaying(self.hammerSound) if not playingSaw and not playingHammer then if self.doSaw == true and self.character:getInventory():containsTag("Saw") then self.sawSound = self.character:getEmitter():playSound("Sawing"); worldSoundRadius = 15 self.doSaw = false; else self.hammerSound = self.character:getEmitter():playSound("Hammering"); worldSoundRadius = math.ceil(20 * self.character:getHammerSoundMod()) self.doSaw = true; end end end if self.craftingBank then local playingCrafting = self.craftingSound ~= 0 and self.character:getEmitter():isPlaying(self.craftingSound) if not playingCrafting then self.craftingSound = self.character:getEmitter():playSound(self.craftingBank); end worldSoundRadius = 15 end end if worldSoundRadius > 0 then ISBuildAction.worldSoundTime = getTimestamp() addSound(self.character, self.character:getX(), self.character:getY(), self.character:getZ(), worldSoundRadius, worldSoundRadius) end self.character:setMetabolicTarget(Metabolics.HeavyWork); self:faceLocation(); end function ISBuildAction:start() if not self.item.noNeedHammer then self.sawSound = 0 self.hammer = self.character:getPrimaryHandItem(); self.hammerSound = 0 end if self.craftingBank then self.craftingSound = 0 end self.soundTime = 0 self.item.ghostSprite = IsoSprite.new(); self.item.ghostSprite:LoadFramesNoDirPageSimple(self.spriteName); self.item.ghostSpriteX = self.x; self.item.ghostSpriteY = self.y; self.item.ghostSpriteZ = self.z; self.item:onTimedActionStart(self) -- self.character:reportEvent("EventCrafting"); end function ISBuildAction:stop() self.item:onTimedActionStop(self) self.item.ghostSprite = nil; if self.sawSound and self.sawSound ~= 0 and self.character:getEmitter():isPlaying(self.sawSound) then self.character:getEmitter():stopSound(self.sawSound); end if self.hammerSound and self.hammerSound ~= 0 and self.character:getEmitter():isPlaying(self.hammerSound) then self.character:getEmitter():stopSound(self.hammerSound); end if self.craftingSound and self.craftingSound ~= 0 and self.character:getEmitter():isPlaying(self.craftingSound) then self.character:stopOrTriggerSound(self.craftingSound); end ISBaseTimedAction.stop(self); end function ISBuildAction:perform() self.item.ghostSprite = nil; if self.sawSound and self.sawSound ~= 0 and self.character:getEmitter():isPlaying(self.sawSound) then self.character:getEmitter():stopSound(self.sawSound); end if self.hammerSound and self.hammerSound ~= 0 and self.character:getEmitter():isPlaying(self.hammerSound) then self.character:getEmitter():stopSound(self.hammerSound); end if self.craftingSound and self.craftingSound ~= 0 and self.character:getEmitter():isPlaying(self.craftingSound) then self.character:getEmitter():stopSound(self.craftingSound); end -- reduce the condition of the hammer if it's a stone hammer local hammer = self.character:getPrimaryHandItem() if hammer and hammer:getType() == "HammerStone" and ZombRand(hammer:getConditionLowerChance()) == 0 then hammer:setCondition(hammer:getCondition() - 1) ISWorldObjectContextMenu.checkWeapon(self.character); end self.item.character = self.character; self.item:create(self.x, self.y, self.z, self.north, self.spriteName); self.square:RecalcAllWithNeighbours(true); if self.item.completionSound ~= nil and self.item.completionSound ~= "" then self.character:playSound(self.item.completionSound) end buildUtil.setHaveConstruction(self.square, true); -- needed to remove from queue / start next. ISBaseTimedAction.perform(self); end function ISBuildAction:faceLocation() if self.item.isWallLike then if self.item.north then self.character:faceLocationF(self.x + 0.5, self.y) else self.character:faceLocationF(self.x, self.y + 0.5) end else self.character:faceLocation(self.x, self.y) end end function ISBuildAction:new(character, item, x, y, z, north, spriteName, time) local o = {} setmetatable(o, self) self.__index = self o.character = character; o.item = item; o.x = x; o.y = y; o.z = z; o.north = north; o.spriteName = spriteName; o.stopOnWalk = true; o.stopOnRun = true; o.maxTime = time; o.craftingBank = item.craftingBank; if character:HasTrait("Handy") then o.maxTime = time - 50; end -- o.maxTime = 500; o.square = getCell():getGridSquare(x,y,z); o.doSaw = false; o.caloriesModifier = 8; return o; end