require "Tutorial/TutorialStep" local FLOOR_HIGHLIGHT_COLOR = ColorInfo.new(0,1,0,1.0); local OBJECT_HIGHLIGHT_COLOR = ColorInfo.new(0,1,0,1); TutorialTests = {} TutorialTests.klight_x = 160; TutorialTests.klight_y = 156; TutorialTests.llight_x = 151; TutorialTests.llight_y = 151; TutorialTests.addHoming = function(sq, yoffset, xoffset, color) if not color then color = {r=0.8,g=0.8,b=0}; end if not TutorialTests.homing1 then TutorialTests.homing1 = Tutorial1.marker:addPlayerHomingPoint(getPlayer(), sq:getX(), sq:getY(), color.r, color.g, color.b, 1); if yoffset then TutorialTests.homing1:setYOffsetScaled(yoffset); end if xoffset then TutorialTests.homing1:setXOffsetScaled(xoffset); end elseif not TutorialTests.homing2 then TutorialTests.homing2 = Tutorial1.marker:addPlayerHomingPoint(getPlayer(), sq:getX(), sq:getY(), color.r, color.g, color.b, 1); if yoffset then TutorialTests.homing2:setYOffsetScaled(yoffset); end if xoffset then TutorialTests.homing2:setXOffsetScaled(xoffset); end end end TutorialTests.addMarker = function(sq, size) if not TutorialTests.marker1 and not TutorialTests.homing1 then TutorialTests.marker1 = Tutorial1.marker:addGridSquareMarker("circle_center", "circle_only_highlight", sq, 0.8, 0.8,0,true, size, 0.02, 0.2, 1.0); TutorialTests.homing1 = Tutorial1.marker:addPlayerHomingPoint(getPlayer(), sq:getX(), sq:getY(), 0.8, 0.8, 0, 1); end end TutorialTests.stopHighlight = function(obj) obj:setHighlighted(false); obj:setBlink(false); obj:setOutlineHighlight(false); obj:setOutlineHlBlink(false); end TutorialTests.highlight = function(obj, thickness) obj:setHighlighted(true, false); obj:setHighlightColor(OBJECT_HIGHLIGHT_COLOR); obj:setBlink(true); obj:setOutlineHighlight(true); obj:setOutlineHlBlink(true); obj:setOutlineHighlightCol(1.0, 1.0, 1.0, 1.0); if thickness then obj:setOutlineThickness(thickness); end end TutorialTests.RemoveMarkers = function() if TutorialTests.homing1 then TutorialTests.homing1:remove(); TutorialTests.homing1 = nil; end if TutorialTests.homing2 then TutorialTests.homing2:remove(); TutorialTests.homing2 = nil; end if TutorialTests.marker1 then TutorialTests.marker1:remove(); TutorialTests.marker1 = nil; end end TutorialTests.ZoomedIn = function() ISBackButtonWheel.disableZoomOut = true; ISBackButtonWheel.disableZoomIn = false; local complete = false; if JoypadState.players[1] then complete = getCore():getZoom(0) == 1; else complete = getCore():getZoom(0) == getCore():getMinZoom(); end if complete then ISBackButtonWheel.disableZoomOut = true; ISBackButtonWheel.disableZoomIn = true; ISBackButtonWheel.disablePlayerInfo = false; end return complete; end TutorialTests.ZoomedOut = function() ISBackButtonWheel.disableZoomOut = false; local complete = getCore():getZoom(0) == getCore():getMaxZoom(); if JoypadState.players[1] then complete = TutorialTests.currentZoom ~= getCore():getZoom(0); end if complete then TutorialTests.currentZoom = getCore():getZoom(0); end return complete; end TutorialTests.PlayerInfoOpen = function() ISBackButtonWheel.disablePlayerInfo = false; local complete = false; if ISCharacterInfoWindow.instance ~= nil and ISCharacterInfoWindow.instance:isReallyVisible() then complete = true; local characterInfo = getPlayerInfoPanel(0); characterInfo:toggleView(xpSystemText.health); setJoypadFocus(0, characterInfo.panel:getActiveView()) updateJoypadFocus(JoypadState.players[1]) end return complete; end TutorialTests.HealthOpen = function() -- if JoypadState.players[1] then -- local focus = getPlayerInfoPanel(0).panel:getActiveView() -- setJoypadFocus(0, focus) -- end ISEquippedItem.instance.healthBtn:setVisible(true); ISCharacterInfoWindow.instance.closeButton:setVisible(false); ISEquippedItem.instance.healthBtn.blinkImage = true; if ISHealthPanel.instance ~= nil and ISHealthPanel.instance:isReallyVisible() then ISEquippedItem.instance.healthBtn.blinkImage = false; ISEquippedItem.instance.healthBtn:setVisible(false); return true; end return false; end TutorialTests.SkillsPage = function() local focus = getPlayerInfoPanel(0).panel:getActiveView() if JoypadState.players[1] and getJoypadFocus(0) ~= getPlayerInfoPanel(0).panel:getActiveView() then Tutorial1.disableMsgFocus = true; setJoypadFocus(0, focus) end if ISCharacterInfoWindow.instance then ISCharacterInfoWindow.instance.panel.blinkTab = xpSystemText.skills; end if ISCharacterInfo.instance ~= nil and ISCharacterInfo.instance:isReallyVisible() then ISCharacterInfoWindow.instance.panel.blinkTab = nil; Tutorial1.disableMsgFocus = false; return true; end return false; end TutorialTests.NotSkillsPage = function() local focus = getPlayerInfoPanel(0).panel:getActiveView() if JoypadState.players[1] and getJoypadFocus(0) ~= getPlayerInfoPanel(0).panel:getActiveView() then Tutorial1.disableMsgFocus = true; setJoypadFocus(0, focus) end ISCharacterInfoWindow.instance.closeButton:setVisible(true); if ISCharacterInfoWindow.instance then ISCharacterInfoWindow.instance.closeButton.blinkImage = true; end if not ISCharacterInfoWindow.instance or not ISCharacterInfoWindow.instance:isReallyVisible() then if ISCharacterInfoWindow.instance then ISCharacterInfoWindow.instance.closeButton.blinkImage = false; end Tutorial1.disableMsgFocus = false; if JoypadState.players[1] then setJoypadFocus(0, nil); end return true; end return false; end TutorialTests.LookedAround = function() JoypadState.disableMovement = false; if getPlayer(0):getDir() == IsoDirections.W then return true; end return false; end WelcomeStep = TutorialStep:derive("WelcomeStep"); function WelcomeStep:new () local o = {} setmetatable(o, self) self.__index = self return o end function WelcomeStep:begin() getPlayer():setAllowRun(false); ISEquippedItem.instance.healthBtn:setVisible(false); local klightSquare = getCell():getGridSquare(TutorialTests.klight_x, TutorialTests.klight_y, 0); local llightSquare = getCell():getGridSquare(TutorialTests.llight_x, TutorialTests.llight_y, 0); klightSquare:switchLight(true); llightSquare:switchLight(false); getPlayer():setIgnoreAutoVault(true); getPlayer():setAuthorizeMeleeAction(false); getPlayer():setIgnoreInputsForDirection(true); getPlayer():setIgnoreContextKey(true); self:addMessage(getText("IGUI_Tutorial1_Welcome1"), getCore():getScreenWidth()/2, getCore():getScreenHeight()/2, 500, 160, true); if JoypadState.players[1] then self:addMessage(getText("IGUI_Tutorial1_Welcome3Joypad"), getCore():getScreenWidth()/2, 400, 500, 500, false, TutorialTests.PlayerInfoOpen); self:addMessage(getText("IGUI_Tutorial1_Welcome4"), 870, 460, 410, 170, true); self:addMessage(getText("IGUI_Tutorial1_Welcome5Joypad"), 870, 300, 290, 90, false, TutorialTests.SkillsPage); self:addMessage(getText("IGUI_Tutorial1_Welcome6"), 870, 300, 340, 120, true); self:addMessage(getText("IGUI_Tutorial1_Welcome7"), 870, 300, 310, 210, true); self:addMessage(getText("IGUI_Tutorial1_Welcome8Joypad"), 870, 300, 300, 100, false, TutorialTests.NotSkillsPage); self:addMessage(getText("IGUI_Tutorial1_Welcome9Joypad"), 300, 620, 420, 100, false, TutorialTests.LookedAround); else self:addMessage(getText("IGUI_Tutorial1_Welcome2",string.lower(getKeyName(getCore():getKey("Zoom in"))),string.lower(getKeyName(getCore():getKey("Zoom out")))), 300, 620, 420, 150, false, TutorialTests.ZoomedOut); self:addMessage(getText("IGUI_Tutorial1_Welcome2bis"), 300, 620, 420, 80, false, TutorialTests.ZoomedIn); self:addMessage(getText("IGUI_Tutorial1_Welcome3"), 250, 100, 300, 130, false, TutorialTests.HealthOpen); self:addMessage(getText("IGUI_Tutorial1_Welcome4"), 670, 460, 410, 170, true); self:addMessage(getText("IGUI_Tutorial1_Welcome5"), 650, 300, 290, 90, false, TutorialTests.SkillsPage); self:addMessage(getText("IGUI_Tutorial1_Welcome6"), 660, 290, 340, 120, true); self:addMessage(getText("IGUI_Tutorial1_Welcome7"), 580, 450, 310, 210, true); self:addMessage(getText("IGUI_Tutorial1_Welcome8"), 580, 420, 300, 100, false, TutorialTests.NotSkillsPage); self:addMessage(getText("IGUI_Tutorial1_Welcome9"), 300, 620, 420, 100, false, TutorialTests.LookedAround); end self:addMessage(getText("IGUI_Tutorial1_Welcome10"), 300, 620, 420, 160, true); self:doMessage(); end function WelcomeStep:isComplete() return TutorialStep.isComplete(self); end function WelcomeStep:finish() WelcomeStep.finished = true; TutorialStep.finish(self); end WalkToAdjacent = TutorialStep:derive("WalkToAdjacent"); function WalkToAdjacent:new () local o = {} setmetatable(o, self) self.__index = self return o end WalkToAdjacent.otherRoomInLocX = 152; WalkToAdjacent.otherRoomInLocY = 153; WalkToAdjacent.otherRoomY1 = 156; WalkToAdjacent.otherRoomX1 = 153; WalkToAdjacent.otherRoomY1 = 156; WalkToAdjacent.otherRoomX2 = 155; WalkToAdjacent.otherRoomY2 = 158; WalkToAdjacent.highlightFloor = nil WalkToAdjacent.lastPlayerX = -1; WalkToAdjacent.lastPlayerY = -1; WalkToAdjacent.runned = false; WalkToAdjacent.x2 = 157; WalkToAdjacent.y2 = 153; WalkToAdjacent.sneaked = false; WalkToAdjacent.appleContainer = nil; WalkToAdjacent.z = 0; function WalkToAdjacent:begin() getPlayer():setAllowRun(false); if not WelcomeStep.finished and getCore():getDebug() then JoypadState.disableControllerPrompt = true; JoypadState.disableMovement = false; getPlayer():setAllowRun(true); end getPlayer():setIgnoreInputsForDirection(false); getPlayer():setAuthorizeMeleeAction(false); ISEquippedItem.instance.healthBtn:setVisible(true); TutorialTests.addMarker(getSquare(WalkToAdjacent.otherRoomInLocX, WalkToAdjacent.otherRoomInLocY, 0), 2); if JoypadState.players[1] then self:addMessage(getText("IGUI_Tutorial1_WalkTo1Joypad"), 300, 620, 420, 130, false, WalkToAdjacent.inLoc); self:addMessage(getText("IGUI_Tutorial1_WalkTo2Joypad"), 300, 620, 420, 130, false, WalkToAdjacent.strafed); else self:addMessage(getText("IGUI_Tutorial1_WalkTo1", Tutorial1.moveKeys), 300, 620, 420, 130, false, WalkToAdjacent.inLoc); self:addMessage(getText("IGUI_Tutorial1_WalkTo2", Tutorial1.moveKeys), 300, 620, 420, 130, false, WalkToAdjacent.strafed); end self:addMessage(getText("IGUI_Tutorial1_WalkTo3"), 300, 620, 420, 130, false, WalkToAdjacent.inLoc2); local shiftKey = getKeyName(getCore():getKey("Run")) local llightSquare = getCell():getGridSquare(TutorialTests.llight_x, TutorialTests.llight_y, 0); llightSquare:switchLight(true); self:doMessage(); end function WalkToAdjacent:inLoc() local complete = getPlayer():getCurrentSquare():getX() == WalkToAdjacent.otherRoomInLocX and getPlayer():getCurrentSquare():getY() == WalkToAdjacent.otherRoomInLocY and getPlayer():getZ() == 0; if complete then TutorialTests.RemoveMarkers(); end return complete; end function WalkToAdjacent:strafed() if not WalkToAdjacent.sneaked and getPlayer():isAiming() then WalkToAdjacent.sneaked = true; WalkToAdjacent.lastPlayerX = getPlayer():getX(); WalkToAdjacent.lastPlayerY = getPlayer():getY(); end if getPlayer():isAiming() or WalkToAdjacent.sneaked then getPlayer():setIgnoreInputsForDirection(false); else getPlayer():setIgnoreInputsForDirection(true); end -- highlight the corner the player has to stand near if not WalkToAdjacent.appleContainer and (math.abs(WalkToAdjacent.lastPlayerX - getPlayer():getX()) > 1 or math.abs(WalkToAdjacent.lastPlayerY - getPlayer():getY()) > 1) and getPlayer():isAiming() then local sq = getCell():getGridSquare(156, 154, 0); local objs = sq:getObjects(); for i = 0, objs:size()-1 do local o = objs:get(i); local c = o:getContainer(); if c ~= nil then WalkToAdjacent.appleContainer = o; TutorialTests.highlight(WalkToAdjacent.appleContainer, 0.3); end end getSoundManager():PlayWorldSoundImpl("TutorialZombie", false, FightStep.zombieMomSpawnX, FightStep.zombieMomSpawnY, 0, 0, 20, 1, false); TutorialTests.addHoming(getSquare(156, 154, 0), -50); return true; end return false; end function WalkToAdjacent:inLoc2() local complete = math.abs(getPlayer():getX() - WalkToAdjacent.x2) > 0 and math.abs(getPlayer():getX() - WalkToAdjacent.x2) < 0.9 and math.abs(getPlayer():getCurrentSquare():getY() - WalkToAdjacent.y2) <= 1 and getPlayer():getZ() == 0; if complete then TutorialTests.RemoveMarkers(); TutorialTests.stopHighlight(WalkToAdjacent.appleContainer); getPlayer():setIgnoreInputsForDirection(true); end return complete; end function WalkToAdjacent:isComplete() return TutorialStep.isComplete(self); end function WalkToAdjacent:finish() WalkToAdjacent.finished = true; TutorialStep.finish(self); end InventoryLootingStep = TutorialStep:derive("InventoryLootingStep"); InventoryLootingStep.itemToEat = "DeadMouse"; function InventoryLootingStep:new () local o = {} setmetatable(o, self) self.__index = self return o end function InventoryLootingStep:begin() if not WalkToAdjacent.finished and getCore():getDebug() then JoypadState.disableMovement = false; getPlayer():setAllowRun(false); getPlayer():setAuthorizeMeleeAction(false); getPlayer():setX(157); getPlayer():setY(154); end ISInventoryPaneContextMenu.dontCreateMenu = true; getPlayer():setDir(IsoDirections.W); local sq = getCell():getGridSquare(156, 154, 0); if sq ~= nil then local objs = sq:getObjects(); for i = 0, objs:size()-1 do local o = objs:get(i); local c = o:getContainer(); if c ~= nil then local mouse = c:AddItem("Base.DeadMouse"); mouse:setAge(17); Tutorial1.DeadMouse = mouse; c:AddItem("Base.WaterBottleEmpty"); InventoryLootingStep.container = o getPlayerLoot(0).inventoryPane.highlightItem = "DeadMouse"; break; end end end local sw = getCore():getScreenWidth() local sh = getCore():getScreenHeight() if JoypadState.players[1] then JoypadState.disableYInventory = false; JoypadState.disableControllerPrompt = false; self:addMessage(getText("IGUI_Tutorial1_InvLoot1Joypad"), math.min(700, sw / 2), 120, 520, 80, false, InventoryLootingStep.openInventoryJoypad); self:addMessage(getText("IGUI_Tutorial1_InvLoot2Joypad"), math.min(700, sw / 2 + 420 / 2), math.min(420, sh / 2 - 200), 420, 100, false, InventoryLootingStep.focusCorrectPanel); self:addMessage(getText("IGUI_Tutorial1_InvLoot3Joypad"), math.min(700, sw / 2 + 420 / 2), math.min(420, sh / 2 - 200), 420, 100, false, InventoryLootingStep.haveItem); self:addMessage(getText("IGUI_Tutorial1_InvLoot4Joypad"), math.min(700, sw / 2 + 420 / 2), math.min(420, sh / 2 - 200), 420, 100, false, InventoryLootingStep.haveWater); else self:addMessage(getText("IGUI_Tutorial1_InvLoot1"), 700, 120, 520, 80, false, InventoryLootingStep.focusLootingPanel); self:addMessage(getText("IGUI_Tutorial1_InvLoot2"), 700, 420, 420, 100, false, InventoryLootingStep.haveItem); self:addMessage(getText("IGUI_Tutorial1_InvLoot3"), 700, 420, 420, 90, false, InventoryLootingStep.haveWater); getPlayerInventory(0):setVisible(true); getPlayerLoot(0):setVisible(true); getPlayerLoot(0).blink = true; end self:doMessage(); end function InventoryLootingStep:openInventoryJoypad() local complete = getPlayerLoot(0) ~= nil and getPlayerLoot(0):isVisible(); if complete then getPlayerLoot(0):setBlinkingContainer(true); JoypadState.disableYInventory = true; JoypadState.disableControllerPrompt = true; end return complete; end function InventoryLootingStep:focusCorrectPanel() for i,v in ipairs(getPlayerLoot(0).backpacks) do if v.inventory:contains(InventoryLootingStep.itemToEat) and getPlayerLoot(0).inventoryPane.inventory == v.inventory then return true; end end return false; end function InventoryLootingStep:focusLootingPanel() local isOpen = getPlayerLoot(0) ~= nil and not getPlayerLoot(0).isCollapsed; if isOpen then getPlayerLoot(0).blink = false; if not JoypadState.players[1] then getPlayerLoot(0):setPinned(); end for i,v in ipairs(getPlayerLoot(0).backpacks) do if v.inventory:contains(InventoryLootingStep.itemToEat) then getPlayerLoot(0).inventoryPane.inventory = v.inventory; getPlayerLoot(0).title = v.name; getPlayerLoot(0).capacity = v.capacity; getPlayerLoot(0):refreshBackpacks(); end end end return isOpen; end function InventoryLootingStep:haveItem() getPlayer():setIgnoreAimingInput(true); getPlayer():faceThisObject(Tutorial1.DeadMouseContainer); JoypadState.disableGrab = false; getPlayerLoot(0).inventoryPane.highlightItem = InventoryLootingStep.itemToEat; if getPlayer():getInventory():contains(InventoryLootingStep.itemToEat) then if not JoypadState.players[1] then getPlayerInventory(0):setPinned(); end getPlayerLoot(0).inventoryPane.highlightItem = ""; getPlayerLoot(0).inventoryPane.selected = {}; return true; end return false; end function InventoryLootingStep:haveWater() getPlayer():faceThisObject(Tutorial1.DeadMouseContainer); getPlayerLoot(0).inventoryPane.highlightItem = "WaterBottleEmpty"; if getPlayer():getInventory():contains("WaterBottleEmpty") then getPlayerLoot(0).inventoryPane.highlightItem = ""; getPlayerLoot(0).inventoryPane.selected = {}; getPlayer():setIgnoreInputsForDirection(false); getPlayer():setIgnoreAimingInput(false); return true; end return false; end function InventoryLootingStep:isComplete() return TutorialStep.isComplete(self); end function InventoryLootingStep:finish() TutorialStep.finish(self); InventoryLootingStep.finished = true; end InventoryUseStep = TutorialStep:derive("InventoryUseStep"); InventoryUseStep.sinkX = 156; InventoryUseStep.sinkY = 154; InventoryUseStep.sink = nil; InventoryUseStep.lastInventory = nil; InventoryUseStep.clickedOnInventory = false; InventoryUseStep.panContainer = nil; function InventoryUseStep:new () local o = {} setmetatable(o, self) self.__index = self return o end function InventoryUseStep:begin() if getCore():getDebug() and not InventoryLootingStep.finished then getPlayer():setAuthorizeMeleeAction(false); getPlayer():setIgnoreInputsForDirection(false); Tutorial1.DeadMouse = getPlayer():getInventory():AddItem("Base.DeadMouse"); getPlayer():getInventory():AddItem("Base.WaterBottleEmpty"); if not JoypadState.players[1] then getPlayerInventory(0):setVisible(true); getPlayerLoot(0):setVisible(true); end getPlayerLoot(0).lootAll:setVisible(false); end ISInventoryPaneContextMenu.dontCreateMenu = false; Tutorial1.contextMenuEat = true; JoypadState.disableGrab = true; local sw = getCore():getScreenWidth() if JoypadState.players[1] then JoypadState.disableYInventory = false; JoypadState.disableControllerPrompt = false; JoypadState.disableInvInteraction = false; self:addMessage(getText("IGUI_Tutorial1_InvUse1Joypad"), getCore():getScreenWidth() - 430, 160, 420, 130, false, InventoryUseStep.selectInventory); self:addMessage(getText("IGUI_Tutorial1_InvUse1BisJoypad"), getCore():getScreenWidth() - 430, 160, 420, 130, false, InventoryUseStep.eat); self:addMessage(getText("IGUI_Tutorial1_InvUse2Joypad"), getCore():getScreenWidth() - 430, 160, 260, 80, true); self:addMessage(getText("IGUI_Tutorial1_InvUse2BisJoypad"), 300, 520, 320, 130, false, InventoryUseStep.fillBottle); self:addMessage(getText("IGUI_Tutorial1_InvUse3Joypad"), 300, 520, 470, 110, false, InventoryUseStep.InLocJoypad); self:addMessage(getText("IGUI_Tutorial1_InvUse3BisJoypad"), 300, 520, 470, 110, false, InventoryLootingStep.openInventoryJoypad); self:addMessage(getText("IGUI_Tutorial1_InvUse4Joypad"), math.min(300, sw / 2 - (450 - 320 / 2)), 520, 320, 130, false, InventoryUseStep.seeWeapon); self:addMessage(getText("IGUI_Tutorial1_InvUse5Joypad"), math.min(500, sw / 2 - (450 - 320 / 2)), 450, 320, 100, false, InventoryUseStep.lootWeapon); else self:addMessage(getText("IGUI_Tutorial1_InvUse1"), getCore():getScreenWidth() - 430, 160, 420, 130, false, InventoryUseStep.eat); self:addMessage(getText("IGUI_Tutorial1_InvUse2"), getCore():getScreenWidth() - 430, 160, 260, 80, true); self:addMessage(getText("IGUI_Tutorial1_InvUse2Bis"), 300, 520, 320, 130, false, InventoryUseStep.fillBottle); self:addMessage(getText("IGUI_Tutorial1_InvUse3"), 300, 520, 470, 110, false, InventoryUseStep.focusLootingPanel); self:addMessage(getText("IGUI_Tutorial1_InvUse4"), 300, 520, 320, 130, false, InventoryUseStep.seeWeapon); self:addMessage(getText("IGUI_Tutorial1_InvUse5"), 500, 450, 320, 100, false, InventoryUseStep.lootWeapon); end getPlayer():getStats():setHunger(0.2); self:doMessage(); end function InventoryUseStep:InLocJoypad() local complete = getPlayer():getCurrentSquare():getX() == 159 and getPlayer():getCurrentSquare():getY() == 153 and getPlayer():getZ() == 0; if complete then TutorialTests.RemoveMarkers(); JoypadState.disableYInventory = false; end return complete; end function InventoryUseStep:selectInventory() local complete = getJoypadFocus(0) == getPlayerInventory(0); if complete then JoypadState.disableInvInteraction = false; end return complete; end function InventoryUseStep:focusLootingPanel() local isOpen = getPlayerLoot(0) ~= nil and not getPlayerLoot(0).isCollapsed; if isOpen then getPlayerLoot(0).blink = false; if not JoypadState.players[1] then getPlayerLoot(0):setPinned(); end else getPlayerLoot(0).blink = true; end return isOpen; end function InventoryUseStep:eat() getCore():setBlinkingMoodle("Hungry"); ISInventoryPaneContextMenu.blinkOption = getText("ContextMenu_Eat"); getPlayer():getBodyDamage():setBoredomLevel(0); getPlayer():getBodyDamage():setUnhappynessLevel(0); local itemToEat = getPlayer():getInventory():FindAndReturn(InventoryLootingStep.itemToEat); if not InventoryUseStep.dontTurn and getPlayer():getVariableString("PerformingAction") == "Eat" then SneakStep.setZoom(0.25); getPlayer():setDir(IsoDirections.SE); InventoryUseStep.dontTurn = true; end -- add BLOOD! if getPlayer():getVariableString("PerformingAction") == "Eat" then if itemToEat:getJobDelta() > 0.12 and not InventoryUseStep.bloodMouse1 then getPlayer():addBlood(BloodBodyPartType.Head, true, true, false); getPlayer():addBlood(BloodBodyPartType.Neck, true, true, false); getPlayer():addBlood(BloodBodyPartType.Hand_R, true, true, false); getPlayer():addBlood(BloodBodyPartType.Hand_L, true, true, false); getPlayer():addBlood(BloodBodyPartType.Torso_Upper, true, true, false); InventoryUseStep.bloodMouse1 = true; end end if itemToEat and InventoryUseStep.dontTurn then if math.abs(itemToEat:getHungChange()) < 0.09 then -- eat 1/4 if TutorialMessage.instance then TutorialMessage.instance.richtext.text = getText("IGUI_Tutorial1_InvUse6"); TutorialMessage.instance.richtext:paginate(); end end if math.abs(itemToEat:getHungChange()) < 0.051 then -- eat 1/2 if TutorialMessage.instance then TutorialMessage.instance.richtext.text = getText("IGUI_Tutorial1_InvUse7"); TutorialMessage.instance.richtext:paginate(); end end end local isOpen = getPlayerInventory(0) ~= nil and not getPlayerInventory(0).isCollapsed; if isOpen then getPlayerInventory(0).blink = false; else getPlayerInventory(0).blink = true; end getPlayerInventory(0).inventoryPane.highlightItem = InventoryLootingStep.itemToEat; local complete = not itemToEat; if complete then Tutorial1.closeBothInv(); JoypadState.disableYInventory = true; getPlayer():getBodyDamage():setFoodSicknessLevel(40); getCore():setBlinkingMoodle("Sick"); end return complete; end function InventoryUseStep:fillBottle() if not TutorialTests.homing1 then TutorialTests.addHoming(getSquare(InventoryUseStep.sinkX, InventoryUseStep.sinkY, 0), -55); end getCore():setBlinkingMoodle(nil); Tutorial1.contextMenuFillBottle = true; ISInventoryPaneContextMenu.blinkOption = nil; local emptybottle = getPlayer():getInventory():FindAndReturn("WaterBottleEmpty") or getPlayer():getInventory():FindAndReturn("WaterBottleFull"); if emptybottle then ISWorldObjectContextMenu.blinkOption = getText("ContextMenu_Fill") .. emptybottle:getName(); end if not InventoryUseStep.sink then local sq = getCell():getGridSquare(InventoryUseStep.sinkX, InventoryUseStep.sinkY, 0); local objs = sq:getObjects(); for i = 0, objs:size()-1 do local o = objs:get(i); if o:getSprite():getName() == "fixtures_sinks_01_16" then InventoryUseStep.sink = o; TutorialTests.highlight(InventoryUseStep.sink, 0.1); break end end end local bottle = getPlayer():getInventory():FindAndReturn("WaterBottleFull"); if bottle and bottle:getUsedDelta() == 1 then InventoryUseStep.lastInventory = getPlayerLoot(0).inventoryPane.inventory; Tutorial1.contextMenuFillBottle = false; TutorialTests.RemoveMarkers(); TutorialTests.stopHighlight(InventoryUseStep.sink); local sq = getCell():getGridSquare(159, 152, 0); if sq ~= nil then local objs = sq:getObjects(); for i = 0, objs:size()-1 do local o = objs:get(i); local c = o:getContainer(); if c ~= nil then c:AddItem(InventoryUseStep.spawnPan()); InventoryUseStep.panContainer = o; getPlayerLoot(0).inventoryPane.highlightItem = "Pan"; TutorialTests.addHoming(getSquare(159, 152, 0), -50); TutorialTests.highlight(InventoryUseStep.panContainer, 0.3); break; end end end return true; end return false; end function InventoryUseStep.spawnPan() local pan = InventoryItemFactory.CreateItem("Base.Pan"); pan:setMinDamage(0.1); pan:setMaxDamage(0.1); pan:setCondition(3); return pan; end function InventoryUseStep:seeWeapon() ISWorldObjectContextMenu.blinkOption = nil; Tutorial1.contextMenuEquipPrimary = true; local isOpen = getPlayerLoot(0) ~= nil and not getPlayerLoot(0).isCollapsed; if isOpen then getPlayerLoot(0).blink = false; -- if not InventoryUseStep.clickedOnInventory then getPlayerLoot(0):setBlinkingContainer(true); -- end else getPlayerLoot(0).blink = true; end local complete = getPlayerLoot(0).inventoryPane.inventory:contains("Pan") and not getPlayerLoot(0).isCollapsed; if complete then -- TutorialTests.RemoveMarkers(); -- TutorialTests.stopHighlight(InventoryUseStep.panContainer); end return complete; end function InventoryUseStep:lootWeapon() ISInventoryPaneContextMenu.blinkOption = getText("ContextMenu_Equip_Primary"); local playerLootOpen = not getPlayerLoot(0).isCollapsed and getPlayerLoot(0).inventoryPane.inventory:contains("Pan"); local playerInvOpen = not getPlayerInventory(0).isCollapsed; getPlayerLoot(0).inventoryPane.highlightItem = "Pan"; getPlayerInventory(0).inventoryPane.highlightItem = "Pan"; getPlayerLoot(0):setBlinkingContainer(false); if playerLootOpen then getPlayerLoot(0).blink = false; elseif getPlayerLoot(0).inventoryPane.inventory:contains("Pan") then getPlayerLoot(0).blink = true; end if playerInvOpen then getPlayerInventory(0).blink = false; elseif getPlayerInventory(0).inventoryPane.inventory:contains("Pan") then getPlayerInventory(0).blink = true; end if getPlayer():getInventory():contains("Pan") then TutorialTests.RemoveMarkers(); TutorialTests.stopHighlight(InventoryUseStep.panContainer); end if getPlayer():getPrimaryHandItem() and getPlayer():getPrimaryHandItem():getType() == "Pan" then getPlayerLoot(0).inventoryPane.highlightItem = nil; getPlayerInventory(0).inventoryPane.highlightItem = nil; TutorialTests.stopHighlight(InventoryUseStep.panContainer); Tutorial1.closeBothInv(); JoypadState.disableYInventory = false; return true; end return false; end function InventoryUseStep:isComplete() return TutorialStep.isComplete(self); end function InventoryUseStep:finish() InventoryUseStep.finished = true; ISInventoryPaneContextMenu.blinkOption = nil; TutorialStep.finish(self); end FightStep = TutorialStep:derive("FightStep"); FightStep.windowX = 162; FightStep.windowY = 154; FightStep.window = nil; FightStep.climbThrough = false; FightStep.zombieMomSpawnX = 165; FightStep.zombieMomSpawnY = 154; FightStep.momzombie = nil; FightStep.zombieSawYou = false; FightStep.highlightFloor = nil; function FightStep:new () local o = {} setmetatable(o, self) self.__index = self return o end function FightStep:begin() JoypadState.disableControllerPrompt = false; JoypadState.disableMovement = false; getPlayer():setIgnoreAutoVault(true); getPlayer():setAuthorizeMeleeAction(false); getPlayer():setIgnoreContextKey(true); JoypadState.disableInvInteraction = false; if getCore():getDebug() and not InventoryUseStep.finished then getPlayer():setIgnoreInputsForDirection(false); local pan = getPlayer():getInventory():AddItem(InventoryUseStep.spawnPan()); getPlayer():setPrimaryHandItem(pan); if not JoypadState.players[1] then getPlayerInventory(0):setVisible(true); getPlayerLoot(0):setVisible(true); end getPlayerLoot(0).lootAll:setVisible(false); end FightStep:spawnMom(); if JoypadState.players[1] then self:addMessage(getText("IGUI_Tutorial1_Fight1"), 300, 500, 520, 110, false, FightStep.WalkToWindow); self:addMessage(getText("IGUI_Tutorial1_Fight2Joypad"), 300, 520, 520, 100, false, FightStep.OpenWindow); self:addMessage(getText("IGUI_Tutorial1_Fight3Joypad"), getCore():getScreenWidth()/2, getCore():getScreenHeight()/2 + 250, 520, 85, false, FightStep.ClimbThroughWindow); self:addMessage(getText("IGUI_Tutorial1_Fight4Joypad"), getCore():getScreenWidth()/2, getCore():getScreenHeight()/2 + 350, 520, 120, false, FightStep.IsAiming); self:addMessage(getText("IGUI_Tutorial1_Fight5Joypad"), getCore():getScreenWidth()/2, getCore():getScreenHeight()/2 + 350, 520, 90, false, FightStep.HitZombie); self:addMessage(getText("IGUI_Tutorial1_Fight7Joypad"), getCore():getScreenWidth()/2, getCore():getScreenHeight()/2 + 350, 520, 100, false, FightStep.KillZombie); self:addMessage(getText("IGUI_Tutorial1_Fight8NewJoypad"), getCore():getScreenWidth()/2, getCore():getScreenHeight()/2 + 350, 520, 100, false, FightStep.LootKnife); else self:addMessage(getText("IGUI_Tutorial1_Fight1"), 300, 500, 520, 110, false, FightStep.WalkToWindow); self:addMessage(getText("IGUI_Tutorial1_Fight2", getKeyName(getCore():getKey("Interact"))), 300, 520, 520, 100, false, FightStep.OpenWindow); self:addMessage(getText("IGUI_Tutorial1_Fight3", getKeyName(getCore():getKey("Interact"))), getCore():getScreenWidth()/2, getCore():getScreenHeight()/2 + 250, 520, 85, false, FightStep.ClimbThroughWindow); self:addMessage(getText("IGUI_Tutorial1_Fight4"), getCore():getScreenWidth()/2, getCore():getScreenHeight()/2 + 350, 520, 120, false, FightStep.IsAiming); self:addMessage(getText("IGUI_Tutorial1_Fight5", Tutorial1.moveKeys), getCore():getScreenWidth()/2, getCore():getScreenHeight()/2 + 350, 520, 90, false, FightStep.HitZombie); self:addMessage(getText("IGUI_Tutorial1_Fight7", getKeyName(getCore():getKey("Melee"))), getCore():getScreenWidth()/2, getCore():getScreenHeight()/2 + 350, 520, 100, true); self:addMessage(getText("IGUI_Tutorial1_Fight7B"), getCore():getScreenWidth()/2, getCore():getScreenHeight()/2 + 350, 520, 100, false, FightStep.KillZombie); self:addMessage(getText("IGUI_Tutorial1_Fight8New"), getCore():getScreenWidth()/2, getCore():getScreenHeight()/2 + 350, 520, 100, false, FightStep.LootKnife); end local sq = getCell():getGridSquare(FightStep.windowX, FightStep.windowY, 0); if sq ~= nil then local objs = sq:getObjects(); for i = 0, objs:size()-1 do local o = objs:get(i); if instanceof(o, "IsoWindow") then FightStep.window = o; TutorialTests.highlight(FightStep.window, 0.1); FightStep.floor = o:getOppositeSquare():getFloor(); break; end end end TutorialTests.addHoming(getSquare(162, 154, 0), -60, -20); self:doMessage(); end function FightStep:WalkToWindow() -- OpenWindowState will slide the player to the center of the window local complete = math.abs(getPlayer():getX() - FightStep.windowX) <= 0.6 and (math.abs(getPlayer():getY() - FightStep.windowY) > 0.20 and math.abs(getPlayer():getY() - FightStep.windowY) < 0.8); if complete then TutorialTests.RemoveMarkers(); -- TutorialTests.addHoming(getSquare(161, 154, 0), true); end return complete; end function FightStep:spawnMom() FightStep.momzombie = addZombiesInOutfit(FightStep.zombieMomSpawnX, FightStep.zombieMomSpawnY, 0, 1, "TutorialMom", 100):get(0); FightStep.momzombie:setDir(IsoDirections.E) FightStep.momzombie:getVisual():setHairModel("Bob"); local immutableColor = ImmutableColor.new(0.805, 0.750, 0.850, 1) FightStep.momzombie:getVisual():setHairColor(immutableColor) FightStep.momzombie:getVisual():setSkinTextureIndex(2); local knife = InventoryItemFactory.CreateItem("Base.HuntingKnife"); FightStep.momzombie:setAttachedItem("Knife in Back", knife); FightStep.momzombie:resetModelNextFrame(); Events.OnZombieDead.Add(FightStep.OnMomDead); for i=0, 10 do FightStep.momzombie:addBlood(nil, false, true, false); FightStep.momzombie:addHole(nil); end FightStep.momzombie:setUseless(true); FightStep.momzombie:setNoDamage(true); end function FightStep:OpenWindow() getPlayer():setDir(IsoDirections.E); getPlayer():setIgnoreContextKey(false); if FightStep.window:IsOpen() then FightStep.window:setHighlighted(false) FightStep.floor:setHighlighted(false) return true; end return false; end FightStep.wasOpen = true; function FightStep:ClimbThroughWindow() if not FightStep.climbThrough then getPlayer():setIgnoreInputsForDirection(true); getPlayer():setDir(IsoDirections.E); else getPlayer():setIgnoreInputsForDirection(false); end if not FightStep.window:IsOpen() then FightStep.wasOpen = false; if TutorialMessage.instance then if JoypadState.players[1] then TutorialMessage.instance.richtext.text = getText("IGUI_Tutorial1_Fight3BisJoypad"); else TutorialMessage.instance.richtext.text = getText("IGUI_Tutorial1_Fight3Bis", getKeyName(getCore():getKey("Interact"))); end TutorialMessage.instance.richtext:paginate(); end end if not FightStep.wasOpen and FightStep.window:IsOpen() then FightStep.wasOpen = true; TutorialMessage.instance.richtext.text = getText("IGUI_Tutorial1_Fight3", getKeyName(getCore():getKey("Interact"))); TutorialMessage.instance.richtext:paginate(); end if getPlayer():getCurrentState():equals(ClimbThroughWindowState.instance()) then FightStep.climbThrough = true; end if FightStep.climbThrough and getPlayer():getCurrentState():equals(IdleState.instance()) and getPlayer():getCurrentSquare():getX() == 162 and getPlayer():getCurrentSquare():getY() == 154 then TutorialTests.RemoveMarkers(); TutorialTests.stopHighlight(FightStep.window); return true; end FightStep.playerX = getPlayer():getX(); FightStep.playerY = getPlayer():getY(); return false; end function FightStep:IsAiming() getPlayer():setIgnoreContextKey(true); local complete = getPlayer():isAiming(); if complete then TutorialTests.addHoming(FightStep.momzombie:getCurrentSquare(), -20); end return complete; end function FightStep:OnMomDead(zed) Events.OnZombieDead.Remove(FightStep.OnMomDead); FightStep.momDead = true; end function FightStep:HitZombie() getPlayer():setBannedAttacking(false); getPlayer():setAuthorizeMeleeAction(true); getPlayer():setAuthorizeShoveStomp(false); FightStep.momzombie:setReanimateTimer(999); FightStep.momzombie:setAlwaysKnockedDown(true); FightStep.momzombie:setImmortalTutorialZombie(false); if (FightStep.momzombie:getCurrentState() == nil) then return false; end local complete = FightStep.momzombie:getCurrentState() == ZombieOnGroundState.instance(); if FightStep.momzombie:getHitReaction() ~= "" then getPlayer():setAuthorizeMeleeAction(false); end if complete then getPlayer():setAuthorizeMeleeAction(false); FightStep.momzombie:setImmortalTutorialZombie(true); local floor = getCell():getGridSquare(164, 154, 0):getFloor(); floor:setHighlighted(false); end return complete; end function FightStep:KillZombie() if not getPlayer():getPrimaryHandItem() then for i=0,getPlayer():getInventory():getItems():size()-1 do local pan = getPlayer():getInventory():getItems():get(i); if pan:getType() == "Pan" then getPlayer():getInventory():Remove(pan); end; end; local pan = getPlayer():getInventory():AddItem(InventoryUseStep.spawnPan()); getPlayer():setPrimaryHandItem(pan); end; getPlayer():getPrimaryHandItem():setCondition(3); getPlayer():getPrimaryHandItem():setMinDamage(3); getPlayer():getPrimaryHandItem():setMaxDamage(3); local floor = getCell():getGridSquare(164, 154, 0):getFloor(); floor:setHighlighted(false); FightStep.momzombie:setImmortalTutorialZombie(false); FightStep.momzombie:setNoDamage(false); getCore():setFlashIsoCursor(true); getPlayer():setAuthorizeMeleeAction(true); FightStep.stopHighlight = true; FightStep.momzombie:setReanimateTimer(300); local complete = FightStep.momDead; if complete then getCore():setFlashIsoCursor(false); for i=0,getPlayer():getInventory():getItems():size()-1 do local pan = getPlayer():getInventory():getItems():get(i); if pan:getType() == "Pan" then pan:setCondition(0); getSoundManager():PlayWorldSoundImpl("BreakMetalItem", false, FightStep.zombieMomSpawnX, FightStep.zombieMomSpawnY, 0, 0, 20, 1, false); break; end end for i=0, 7 do getPlayer():addBlood(nil, true, false, false); end getPlayer():setAuthorizeMeleeAction(false); getPlayer():setAuthorizeShoveStomp(true); JoypadState.disableYInventory = false; end return complete; end function FightStep:LootKnife() -- print(FightStep.momzombie:isDead(), FightStep.momzombie:getHealth(), FightStep.momzombie:getCurrentState()) getPlayerLoot(0).inventoryPane.highlightItem = "HuntingKnife"; getPlayerLoot(0):setBlinkingContainer(true, "inventoryfemale"); Tutorial1.contextMenuEquipPrimary = true; if not JoypadState.players[1] then if not FightStep.pinInv then FightStep.pinInv = true; getPlayerLoot(0):setPinned(); end getPlayerLoot(0).blink = true; getPlayerInventory(0).inventoryPane.highlightItem = "Pan"; end if JoypadState.players[1] and getPlayerLoot(0):isReallyVisible() then TutorialMessage.instance:setY(40) end local complete = getPlayer():getPrimaryHandItem() and getPlayer():getPrimaryHandItem():getType() == "HuntingKnife"; if getPlayer():getInventory():contains("HuntingKnife", false, false) then getPlayerInventory(0).inventoryPane.highlightItem = "HuntingKnife"; if not JoypadState.players[1] then Tutorial1.collapseInv(getPlayerLoot(0)); getPlayerInventory(0).blink = true; getPlayerInventory(0):setPinned(); getPlayerLoot(0).blink = false; end end if complete then Tutorial1.contextMenuEquipPrimary = false; Tutorial1.closeBothInv(); getPlayerLoot(0).inventoryPane.highlightItem = nil; getPlayerLoot(0).blink = false; getPlayerInventory(0).inventoryPane.highlightItem = nil; getPlayerLoot(0):setBlinkingContainer(false); getSoundManager():PlayWorldSoundImpl("UnlockDoor", false, FightStep.lockedDoor:getX(), FightStep.lockedDoor:getY(), 0, 0, 20, 3, false); FightStep.lockedDoor:setLockedByKey(false); FightStep.lockedDoor2:setLockedByKey(false); if not JoypadState.players[1] then Tutorial1.collapseInv(getPlayerLoot(0)); Tutorial1.collapseInv(getPlayerInventory(0)); end getPlayerInventory(0).blink = false; TutorialTests.RemoveMarkers(); end return complete; end function FightStep:isComplete() return TutorialStep.isComplete(self); end function FightStep:finish() FightStep.finished = true; TutorialStep.finish(self); end SneakStep = TutorialStep:derive("SneakStep"); SneakStep.zombieDadSpawnX = 166; SneakStep.zombieDadSpawnY = 147; --SneakStep.gateX = function SneakStep:new () local o = {} setmetatable(o, self) self.__index = self return o end function SneakStep:begin() Tutorial1.contextMenuEquipPrimary = false; getPlayer():setAuthorizeMeleeAction(false); getPlayer():setIgnoreContextKey(true); JoypadState.disableControllerPrompt = false; JoypadState.disableMovement = false; JoypadState.disableYInventory = false; JoypadState.disableInvInteraction = false; if getCore():getDebug() and not FightStep.finished then getPlayer():setX(165); getPlayer():setY(154); getPlayer():setIgnoreAutoVault(true); getPlayer():setIgnoreInputsForDirection(false); local pan = getPlayer():getInventory():AddItem("Base.HuntingKnife"); getPlayer():setPrimaryHandItem(pan); if not JoypadState.players[1] then getPlayerInventory(0):setVisible(true); getPlayerLoot(0):setVisible(true); end getPlayerLoot(0).lootAll:setVisible(false); getPlayer():setZombieKills(1); end FightStep.lockedDoor:setLockedByKey(false); FightStep.lockedDoor:setLocked(false); FightStep.lockedDoor2:setLocked(false); FightStep.lockedDoor2:setLockedByKey(false); local sq = getCell():getGridSquare(163, 152, 0); FightStep.floor1SQ = sq; sq = getCell():getGridSquare(164, 152, 0); FightStep.floor2SQ = sq; getSoundManager():PlayWorldSoundImpl("MaleZombieAttack", false, FightStep.zombieMomSpawnX, FightStep.zombieMomSpawnY, 0, 0, 20, 1, false); SneakStep:spawnDad(); local zombie = createZombie(SneakStep.zombieDadSpawnX - 1, SneakStep.zombieDadSpawnY, 0, nil, 0,IsoDirections.S); while not zombie:isFemale() do zombie:removeFromWorld(); zombie:removeFromSquare(); zombie = createZombie(SneakStep.zombieDadSpawnX - 1, SneakStep.zombieDadSpawnY, 0, nil, 0,IsoDirections.S); end zombie:dressInRandomOutfit(); zombie:DoZombieInventory(); local body = IsoDeadBody.new(zombie, false); body:setX(SneakStep.dadzombie:getX() - 0.4); body:setY(SneakStep.dadzombie:getY()); SneakStep.dadzombie:setForceEatingAnimation(true); SneakStep.dadzombie:setOnlyJawStab(true); for i=0, 7 do SneakStep.dadzombie:addBlood(nil, false, true, false); SneakStep.dadzombie:addHole(nil); end SneakStep.dadzombie:setUseless(true); getPlayer():setDir(IsoDirections.NW); TutorialTests.addHoming(FightStep.floor1SQ); TutorialTests.highlight(FightStep.lockedDoor, 0.2); TutorialTests.highlight(FightStep.lockedDoor2, 0.2); if JoypadState.players[1] then self:addMessage(getText("IGUI_Tutorial1_Sneak1Joypad"), 300, 500, 320, 250, false, SneakStep.GoThroughDoor); self:addMessage(getText("IGUI_Tutorial1_Sneak1BisJoypad"), 300, 500, 520, 110, false, SneakStep.Sneak); self:addMessage(getText("IGUI_Tutorial1_Sneak2"), getCore():getScreenWidth() - 400, 150, 520, 110, false, SneakStep.SneakingGate); self:addMessage(getText("IGUI_Tutorial1_Sneak3Joypad"), getCore():getScreenWidth() - 400, 400, 520, 110, false, SneakStep.OpenGate); self:addMessage(getText("IGUI_Tutorial1_Sneak4Joypad"), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 520, 110, false, SneakStep.DadDead); self:addMessage(getText("IGUI_Tutorial1_Sneak5Joypad"), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 520, 110, false, SneakStep.EquippedBag); self:addMessage(getText("IGUI_Tutorial1_Sneak6Joypad"), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 520, 110, false, SneakStep.CheckBag); self:addMessage(getText("IGUI_Tutorial1_Sneak7Joypad"), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 520, 110, false, SneakStep.EquipShotgun); else self:addMessage(getText("IGUI_Tutorial1_Sneak1", getKeyName(getCore():getKey("Interact"))), 300, 500, 320, 250, false, SneakStep.GoThroughDoor); self:addMessage(getText("IGUI_Tutorial1_Sneak1Bis", getKeyName(getCore():getKey("Crouch"))), 300, 500, 520, 110, false, SneakStep.Sneak); self:addMessage(getText("IGUI_Tutorial1_Sneak2"), getCore():getScreenWidth() - 400, 200, 520, 110, false, SneakStep.SneakingGate); self:addMessage(getText("IGUI_Tutorial1_Sneak3", getKeyName(getCore():getKey("Interact"))), getCore():getScreenWidth() - 400, 400, 520, 110, false, SneakStep.OpenGate); self:addMessage(getText("IGUI_Tutorial1_Sneak4"), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 520, 110, false, SneakStep.DadDead); self:addMessage(getText("IGUI_Tutorial1_Sneak5"), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 520, 110, false, SneakStep.EquippedBag); self:addMessage(getText("IGUI_Tutorial1_Sneak6"), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 520, 110, false, SneakStep.CheckBag); self:addMessage(getText("IGUI_Tutorial1_Sneak7"), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 520, 110, false, SneakStep.EquipShotgun); end self:doMessage(); end function SneakStep:spawnDad() SneakStep.dadzombie = addZombiesInOutfit(SneakStep.zombieDadSpawnX, SneakStep.zombieDadSpawnY, 0, 1, "TutorialDad", 0):get(0); SneakStep.dadzombie:setDir(IsoDirections.W); -- SneakStep.loopedSound = SneakStep.dadzombie:getEmitter():playSound("MaleZombieCombined"); Events.OnZombieDead.Add(SneakStep.OnDadDead); -- zombie.getEmitter().playSound(soundName); SneakStep.dadzombie:setDressInRandomOutfit(false); SneakStep.dadzombie:dressInNamedOutfit("TutorialDad"); SneakStep.dadzombie:getVisual():setHairModel("Baldspot"); SneakStep.dadzombie:getVisual():setBeardModel("Full"); local immutableColor = ImmutableColor.new(0.105, 0.09, 0.086, 1) SneakStep.dadzombie:getVisual():setHairColor(immutableColor) SneakStep.dadzombie:getVisual():setBeardColor(immutableColor) SneakStep.dadzombie:getVisual():setSkinTextureIndex(2); SneakStep.dadzombie:setAlwaysKnockedDown(true); SneakStep.dadzombie:resetModelNextFrame(); SneakStep.dadzombie:setX(SneakStep.dadzombie:getX() + 0.5); end function SneakStep:OnDadDead() SneakStep.isDadDead = true; Events.OnZombieDead.Remove(SneakStep.OnDadDead); end function SneakStep:GoThroughDoor() getPlayer():setIgnoreContextKey(false); if FightStep.lockedDoor:IsOpen() and not FightStep.markerDone then FightStep.markerDone = true; getPlayer():setIgnoreContextKey(true); TutorialTests.stopHighlight(FightStep.lockedDoor); TutorialTests.stopHighlight(FightStep.lockedDoor2); TutorialTests.RemoveMarkers(); TutorialTests.addMarker(getSquare(163, 150, 0), 2); -- FightStep.lockedDoor:setHighlighted(false); -- FightStep.lockedDoor2:setHighlighted(false); elseif FightStep.markerDone then getPlayer():setIgnoreContextKey(false); end local complete = getPlayer():getCurrentSquare() == FightStep.floor1SQ or getPlayer():getCurrentSquare() == FightStep.floor2SQ; if complete then TutorialTests.RemoveMarkers(); TutorialTests.stopHighlight(FightStep.lockedDoor); TutorialTests.stopHighlight(FightStep.lockedDoor2); getPlayer():setDir(IsoDirections.NE); getPlayer():setIgnoreContextKey(true); SneakStep.setZoom(1.5); end return complete; end function SneakStep.setZoom(depth) local mod = (depth - getCore():getZoom(0)) / 0.25; local unzoom = true; if mod < 0 then mod = math.abs(mod); unzoom = false; end for i=1, mod do if unzoom then getCore():doZoomScroll(0, 1); else getCore():doZoomScroll(0, -1); end end end function SneakStep.Sneak() getPlayer():setIgnoreInputsForDirection(true); if getPlayer():isSneaking() then getPlayer():setIgnoreInputsForDirection(false); return true; end return false; end function SneakStep:SneakingGate() TutorialTests.highlight(SneakStep.fenceGate, 0.2); SneakStep.sqGate = getCell():getGridSquare(169, 144, 0); TutorialTests.addHoming(SneakStep.sqGate); if not getPlayer():isSneaking() and (SneakStep.wasSneaking or getPlayer():getCurrentSquare():getY() < 148) then if TutorialMessage.instance then if JoypadState.players[1] then TutorialMessage.instance.richtext.text = getText("IGUI_Tutorial1_Sneak2BisJoypad", getKeyName(getCore():getKey("Crouch"))); else TutorialMessage.instance.richtext.text = getText("IGUI_Tutorial1_Sneak2Bis", getKeyName(getCore():getKey("Crouch"))); end TutorialMessage.instance.richtext:paginate(); TutorialMessage.instance:setX(300 - getCore():getScreenWidth()/2); TutorialMessage.instance:setY(80 + getCore():getScreenHeight()/2); end elseif getPlayer():isSneaking() then SneakStep.wasSneaking = true; SneakStep.fenceGate:setLockedByKey(false); getPlayer():setIgnoreContextKey(false); end if not getPlayer():isSneaking() then SneakStep.fenceGate:setLockedByKey(true); getPlayer():setIgnoreInputsForDirection(true); else getPlayer():setIgnoreInputsForDirection(false); end local complete = getPlayer():getCurrentSquare() == SneakStep.sqGate; return complete; end function SneakStep:OpenGate() getPlayer():setIgnoreContextKey(false); local complete = SneakStep.fenceGate:IsOpen(); if complete then TutorialTests.stopHighlight(SneakStep.fenceGate); TutorialTests.RemoveMarkers(); getPlayer():setIgnoreContextKey(true); SneakStep.setZoom(0.5); Events.OnWeaponHitXp.Add(SneakStep.OnSwingAtDad); TutorialTests.addHoming(SneakStep.dadzombie:getCurrentSquare(), -20); end return complete; end function SneakStep.OnSwingAtDad(owner, weapon, zed, dmg) if not zed:isCloseKilled() then if TutorialMessage.instance then if JoypadState.players[1] then TutorialMessage.instance.richtext.text = getText("IGUI_Tutorial1_Sneak4BisJoypad"); else TutorialMessage.instance.richtext.text = getText("IGUI_Tutorial1_Sneak4Bis"); end TutorialMessage.instance.richtext:paginate(); TutorialMessage.instance:setX(20 - getCore():getScreenWidth()/2); TutorialMessage.instance:setY(80 + getCore():getScreenHeight()/2); end end end function SneakStep:DadDead() TutorialTests.addMarker(SneakStep.dadzombie:getCurrentSquare(), 1); SneakStep.dadzombie:setForceEatingAnimation(false); getPlayer():setAuthorizeMeleeAction(true); getPlayer():setAuthorizeShoveStomp(false); SneakStep.fenceGate:setHighlighted(false); SneakStep.dadzombie:setReanimateTimer(30); local complete = SneakStep.isDadDead; if complete then Events.OnWeaponHitXp.Remove(SneakStep.OnSwingAtDad); -- SneakStep.dadzombie:getEmitter():stopSound(SneakStep.loopedSound) getPlayer():setAuthorizeMeleeAction(false); getPlayer():setAuthorizeShoveStomp(true); SneakStep.fenceGate:ToggleDoorSilent(); SneakStep.fenceGate:setLocked(true); SneakStep.fenceGate:setLockedByKey(true); for i=0, 7 do getPlayer():addBlood(nil, true, false, false); end if not JoypadState.players[1] then getPlayerLoot(0):setPinned(); end end return complete; end function SneakStep:EquippedBag() if not getPlayer():getInventory():contains("Bag_ALICEpack") then getPlayerLoot(0).blink = true; Tutorial1.contextMenuEquipBag = true; getPlayerLoot(0):setBlinkingContainer(true, "inventorymale"); getPlayerLoot(0).inventoryPane.highlightItem = "Bag_ALICEpack"; else TutorialTests.RemoveMarkers(); getPlayerLoot(0).blink = false; getPlayerInventory(0).blink = true; Tutorial1.contextMenuEquipBag = true; getPlayerLoot(0).inventoryPane.highlightItem = nil; getPlayerInventory(0).inventoryPane.highlightItem = "Bag_ALICEpack"; getPlayerLoot(0):setBlinkingContainer(false); if not SneakStep.pinInv and not JoypadState.players[1] then SneakStep.pinInv = true; getPlayerInventory(0):setPinned(); end end local isOpen = getPlayerLoot(0) ~= nil and not getPlayerLoot(0).isCollapsed; if isOpen and not SneakStep.bag then getPlayerLoot(0).blink = false; for i,v in ipairs(getPlayerLoot(0).backpacks) do local bag = v.inventory:FindAndReturn("Bag_ALICEpack") if bag then SneakStep.bag = bag; bag:getItemContainer():AddItem(SneakStep.spawnShotgun()); bag:getItemContainer():AddItem("Base.Bandage"); return; end end end if SneakStep.bag and getPlayer():isEquipped(SneakStep.bag) then getPlayerLoot(0).inventoryPane.highlightItem = nil; getPlayerLoot(0).blink = false; getPlayerInventory(0).inventoryPane.highlightItem = nil; getPlayerInventory(0).blink = false; Tutorial1.contextMenuEquipBag = false; getPlayerLoot(0):setBlinkingContainer(false); if JoypadState.players[1] then JoypadState.players[1].focus = getPlayerInventory(0); updateJoypadFocus(JoypadState.players[1]); getPlayerLoot(0):setVisible(false); else getPlayerLoot(0):setVisible(false); Tutorial1.collapseInv(getPlayerInventory(0)); Tutorial1.collapseInv(getPlayerLoot(0)); end return true; end return false; end function SneakStep:CheckBag() getPlayerInventory(0).blink = true; if not JoypadState.players[1] then getPlayerInventory(0):setPinned(); end getPlayerInventory(0):setBlinkingContainer(true, "Bag_ALICEpack"); if not getPlayerInventory(0).isCollapsed then getPlayerInventory(0).blink = false; if getPlayerInventory(0).inventory == SneakStep.bag:getItemContainer() then getPlayerInventory(0):setBlinkingContainer(false); return true; end end return false; end function SneakStep:EquipShotgun() Tutorial1.contextMenuEquip2Hand = true; getPlayerInventory(0).inventoryPane.highlightItem = "Shotgun"; if getPlayer():getPrimaryHandItem() == SneakStep.shotgun then Tutorial1.contextMenuEquip2Hand = false; getPlayer():LevelPerk(Perks.Aiming);getPlayer():LevelPerk(Perks.Aiming);getPlayer():LevelPerk(Perks.Aiming);getPlayer():LevelPerk(Perks.Aiming);getPlayer():LevelPerk(Perks.Aiming);getPlayer():LevelPerk(Perks.Aiming);getPlayer():LevelPerk(Perks.Aiming);getPlayer():LevelPerk(Perks.Aiming); Tutorial1.contextMenuEquip2Hand = false; Tutorial1.closeBothInv(); SneakStep.setZoom(1.5); getPlayer():setIgnoreInputsForDirection(false); return true; end return false; end function SneakStep.spawnShotgun() local shotgun = InventoryItemFactory.CreateItem("Base.Shotgun"); shotgun:setCurrentAmmoCount(6); shotgun:setRoundChambered(true); shotgun:setMinDamage(1); shotgun:setMaxDamage(2); shotgun:setMaxRange(20); shotgun:setActualWeight(0.5); SneakStep.shotgun = shotgun; return shotgun; end function SneakStep:isComplete() return TutorialStep.isComplete(self); end function SneakStep:finish() SneakStep.finished = true; TutorialStep.finish(self); end BandageStep = TutorialStep:derive("BandageStep"); BandageStep.brotherX = 182; BandageStep.brotherY = 147; function BandageStep:new () local o = {} setmetatable(o, self) self.__index = self return o end function BandageStep:begin() getPlayerLoot(0):setVisible(true); JoypadState.disableControllerPrompt = false; JoypadState.disableMovement = false; JoypadState.disableYInventory = false; ISBackButtonWheel.disablePlayerInfo = false; JoypadState.disableInvInteraction = false; if getCore():getDebug() and not SneakStep.finished then getPlayer():setAuthorizeMeleeAction(false); getPlayer():setIgnoreInputsForDirection(false); local bag = InventoryItemFactory.CreateItem("Base.Bag_ALICEpack"); SneakStep.bag = bag; local shotgun = SneakStep.spawnShotgun(); getPlayer():getInventory():AddItem(shotgun); getPlayer():getInventory():AddItem(bag); bag:getItemContainer():AddItem("Base.Bandage"); getPlayer():setWornItem("Back", bag); getPlayer():setPrimaryHandItem(shotgun); getPlayer():setSecondaryHandItem(shotgun); getPlayer():setX(166); getPlayer():setY(147); if not JoypadState.players[1] then getPlayerInventory(0):setVisible(true); getPlayerLoot(0):setVisible(true); end getPlayer():setZombieKills(2); end getPlayer():setDir(IsoDirections.E); getPlayer():setIgnoreContextKey(true); getPlayer():setIgnoreAutoVault(false); getPlayer():setAllowRun(true); getSoundManager():PlayWorldSoundImpl("SmashWindow", false, getPlayer():getX(), getPlayer():getY(), 0, 0, 20, 1, false); local sq = getSquare(175, 150, 0); for i=0, sq:getObjects():size() -1 do local obj = sq:getObjects():get(i); if instanceof(obj, "IsoWindow") then obj:smashWindow(false, false); obj:addBrokenGlass(getPlayer()); BandageStep.window = obj; break; end end BandageStep.fences = {}; for y=145, 152 do sq = getSquare(173, y, 0); for i=0, sq:getObjects():size() -1 do local obj = sq:getObjects():get(i); obj:setHighlighted(true, false); obj:setBlink(true); obj:setHighlightColor(OBJECT_HIGHLIGHT_COLOR); table.insert(BandageStep.fences, obj); end sq:getFloor():setHighlightColor(FLOOR_HIGHLIGHT_COLOR); end TutorialTests.addHoming(getSquare(173, 149, 0)); if JoypadState.players[1] then self:addMessage(getText("IGUI_Tutorial1_Bandage1Joypad"), 100, 150 + getCore():getScreenHeight()/2, 420, 110, false, BandageStep.Vault); self:addMessage(getText("IGUI_Tutorial1_Bandage2Joypad"), 400, 200, 420, 110, false, BandageStep.ThroughWindow); self:addMessage(getText("IGUI_Tutorial1_Bandage3Joypad"), 300, getCore():getScreenHeight() - 200, 500, 110, false, TutorialTests.PlayerInfoOpen); self:addMessage(getText("IGUI_Tutorial1_Bandage4Joypad"), 300, 300 + getCore():getScreenHeight()/2, 420, 110, false, BandageStep.BandageYourself); self:addMessage(getText("IGUI_Tutorial1_Bandage5"), getCore():getScreenWidth() - 600, math.max(getCore():getScreenHeight() - 400, getCore():getScreenHeight() / 2 + 150), 320, 110, false, BandageStep.CheckWindow); self:addMessage(getText("IGUI_Tutorial1_Bandage6Joypad"), getCore():getScreenWidth() - 500, math.max(getCore():getScreenHeight() - 500, getCore():getScreenHeight() / 2 + 150), 320, 110, false, BandageStep.OpenCurtain); self:addMessage(getText("IGUI_Tutorial1_Bandage7"), 300, getCore():getScreenHeight() - 200, 420, 110, true); self:addMessage(getText("IGUI_Tutorial1_Bandage8"), 300, getCore():getScreenHeight() - 200, 420, 110, false, BandageStep.ThroughDoor); else self:addMessage(getText("IGUI_Tutorial1_Bandage1", getKeyName(getCore():getKey("Run")), Tutorial1.moveKeys), 100, 150 + getCore():getScreenHeight()/2, 420, 110, false, BandageStep.Vault); self:addMessage(getText("IGUI_Tutorial1_Bandage2", getKeyName(getCore():getKey("Interact"))), 400, 200, 420, 110, false, BandageStep.ThroughWindow); self:addMessage(getText("IGUI_Tutorial1_Bandage3", getKeyName(getCore():getKey("Toggle Health Panel"))), 300, getCore():getScreenHeight() - 200, 500, 110, false, BandageStep.HealthOpen); self:addMessage(getText("IGUI_Tutorial1_Bandage4"), 300, 300 + getCore():getScreenHeight()/2, 420, 110, false, BandageStep.BandageYourself); self:addMessage(getText("IGUI_Tutorial1_Bandage5"), getCore():getScreenWidth() - 600, getCore():getScreenHeight() - 400, 320, 110, false, BandageStep.CheckWindow); self:addMessage(getText("IGUI_Tutorial1_Bandage6"), getCore():getScreenWidth() - 500, getCore():getScreenHeight() - 500, 320, 110, false, BandageStep.OpenCurtain); self:addMessage(getText("IGUI_Tutorial1_Bandage7"), 300, getCore():getScreenHeight() - 200, 420, 110, true); self:addMessage(getText("IGUI_Tutorial1_Bandage8"), 300, getCore():getScreenHeight() - 200, 420, 110, false, BandageStep.ThroughDoor); end self:doMessage(); end function BandageStep.Vault() getPlayer():setSneaking(false); if not getPlayer():getCurrentState() then -- for when debug force step return false; end if JoypadState.players[1] then if not BandageStep.runned and isJoypadRTPressed(0) then getPlayer():setIgnoreInputsForDirection(false); BandageStep.runned = true; end else if not BandageStep.runned and isKeyDown(getCore():getKey("Run")) then getPlayer():setIgnoreInputsForDirection(false); BandageStep.runned = true; end end if not BandageStep.runned then getPlayer():setIgnoreInputsForDirection(true); end local complete = false; if not BandageStep.vaulted and getPlayer():getCurrentState():equals(ClimbOverFenceState.instance()) then BandageStep.vaulted = true; end if BandageStep.vaulted and getPlayer():getCurrentState():equals(IdleState.instance()) and getPlayer():getCurrentSquare():getX() ~= 173 then BandageStep.vaultedWrong = true; complete = true; end if BandageStep.vaulted and getPlayer():getCurrentSquare():getX() == 173 then complete = true; end if complete then TutorialTests.RemoveMarkers(); TutorialTests.highlight(BandageStep.window, 0.1); TutorialTests.addHoming(BandageStep.window:getSquare(), -60, -20); getPlayer():setIgnoreAutoVault(true); for i,v in ipairs(BandageStep.fences) do v:setHighlighted(false); end BandageStep.fences = {}; end return complete; end function BandageStep.ThroughWindow() if BandageStep.vaultedWrong and TutorialMessage.instance then getPlayer():setIgnoreAutoVault(false); if JoypadState.players[1] then TutorialMessage.instance.richtext.text = getText("IGUI_Tutorial1_Bandage2BisJoypad"); else TutorialMessage.instance.richtext.text = getText("IGUI_Tutorial1_Bandage2Bis", getKeyName(getCore():getKey("Interact"))); end TutorialMessage.instance.richtext:paginate(); if not BandageStep.vaultedWrongZoom then SneakStep.setZoom(2); getPlayer():setDir(IsoDirections.E); BandageStep.vaultedWrongZoom = true; end end getPlayer():setSneaking(false); getPlayer():setIgnoreContextKey(false); if not BandageStep.vaultedWindow and getPlayer():isCurrentState(ClimbThroughWindowState.instance()) then BandageStep.vaultedWindow = true; getPlayer():setIgnoreAutoVault(true); BandageStep.spawnBrothers(); end if BandageStep.vaultedWindow and not getPlayer():isCurrentState(ClimbThroughWindowState.instance()) and getPlayer():getCurrentSquare() == BandageStep.window:getSquare() then getPlayer():getBodyDamage():RestoreToFullHealth(); getPlayer():getBodyDamage():getBodyPart(BodyPartType.Hand_L):setScratched(true, true); getPlayer():addBlood(BloodBodyPartType.Hand_L, false, true, false); BandageStep.window:setHighlighted(false); BandageStep.window:removeBrokenGlass(); getPlayer():setIgnoreContextKey(true); SneakStep.setZoom(0.5); BandageStep.extTimer = 10; getSoundManager():PlayWorldSoundImpl("WalkOnBrokenGlass", false, getPlayer():getX(), getPlayer():getY(), 0, 0, 20, 1, false); getPlayer():setIgnoreContextKey(true); getPlayer():setIgnoreInputsForDirection(true); TutorialTests.stopHighlight(BandageStep.window); TutorialTests.RemoveMarkers(); return true; end return false; end function BandageStep.CheckWindow() getPlayer():setSneaking(false); local complete = getPlayer():getCurrentSquare() == BandageStep.sqWindow; if complete then getPlayer():setDir(IsoDirections.E); TutorialTests.RemoveMarkers(); TutorialTests.addHoming(BandageStep.barricadedWindow1:getSquare(), -60, -20); TutorialTests.stopHighlight(BandageStep.barricadedWindow1); TutorialTests.highlight(BandageStep.curtain, 0.1); end return complete; end function BandageStep.OpenCurtain() getPlayer():setIgnoreContextKey(false); getPlayer():setDir(IsoDirections.E); Tutorial1.contextMenuOpenCurtain = true; ISInventoryPaneContextMenu.blinkOption = nil; getPlayer():setIgnoreInputsForDirection(true); local complete = BandageStep.curtain:IsOpen(); if complete then Tutorial1.contextMenuOpenCurtain = false; getPlayer():setIgnoreContextKey(false); TutorialTests.RemoveMarkers(); TutorialTests.stopHighlight(BandageStep.curtain); getPlayer():getBodyDamage():IncreasePanic(10); getPlayer():playSound("ZombieSurprisedPlayer"); end return complete; end BandageStep.HealthOpen = function() ISEquippedItem.instance.healthBtn.blinkImage = true; getPlayer():setIgnoreInputsForDirection(true); BandageStep.extTimer = BandageStep.extTimer - 1; if BandageStep.extTimer == 0 then BandageStep.extTimer = 50; getPlayer():setVariable("Ext", "PainHandL"); getPlayer():reportEvent("EventDoExt"); end if ISHealthPanel.instance ~= nil and ISHealthPanel.instance:isReallyVisible() then ISEquippedItem.instance.healthBtn.blinkImage = false; ISEquippedItem.instance.healthBtn:setVisible(false); return true; end return false; end function BandageStep:OnBrothersDead() if BandageStep.oneDead then BandageStep.isBrothersDead = true; Events.OnZombieDead.Remove(BandageStep.OnBrothersDead); else BandageStep.oneDead = true; end end function BandageStep.spawnBrothers() BandageStep.brother1 = addZombiesInOutfit(BandageStep.brotherX, BandageStep.brotherY, 0, 1, "TutorialBrother1", 0):get(0); BandageStep.brother1:setDir(IsoDirections.W); BandageStep.brother1:setDressInRandomOutfit(false); -- BandageStep.brother1:dressInNamedOutfit("TutorialBrother1"); BandageStep.brother1:getVisual():setSkinTextureIndex(2); BandageStep.brother1:resetModelNextFrame(); BandageStep.brother1:setForceEatingAnimation(true); BandageStep.brother1:setImmortalTutorialZombie(true); for i=0, 7 do BandageStep.brother1:addBlood(nil, false, true, false); BandageStep.brother1:addHole(nil); end BandageStep.brother2 = addZombiesInOutfit(BandageStep.brotherX - 1, BandageStep.brotherY, 0, 1, "TutorialBrother2", 0):get(0); BandageStep.brother2:setDir(IsoDirections.E); BandageStep.brother2:setDressInRandomOutfit(false); -- BandageStep.brother2:dressInNamedOutfit("TutorialBrother2"); BandageStep.brother2:getVisual():setSkinTextureIndex(2); BandageStep.brother2:resetModelNextFrame(); BandageStep.brother2:setForceEatingAnimation(true); BandageStep.brother2:setX(BandageStep.brother1:getX() - 1); BandageStep.brother2:setY(BandageStep.brother1:getY()); BandageStep.brother2:setImmortalTutorialZombie(true); BandageStep.brother1:setUseless(true); BandageStep.brother2:setUseless(true); BandageStep.brother1:setNoTeeth(true); BandageStep.brother2:setNoTeeth(true); for i=0, 7 do BandageStep.brother2:addBlood(nil, false, true, false); BandageStep.brother2:addHole(nil); end local zombie = createZombie(BandageStep.brotherX - 1, BandageStep.brotherY, 0, nil, 0,IsoDirections.S); while not zombie:isFemale() do zombie:removeFromWorld(); zombie:removeFromSquare(); zombie = createZombie(BandageStep.brotherX - 1, BandageStep.brotherY, 0, nil, 0,IsoDirections.S); end zombie:setDressInRandomOutfit(false); zombie:dressInNamedOutfit("DressLong"); zombie:getVisual():setSkinTextureIndex(2); zombie:resetModelNextFrame(); zombie:DoZombieInventory(); for i=0, 15 do zombie:addBlood(nil, false, true, false); end local body = IsoDeadBody.new(zombie, false); body:setX(BandageStep.brother1:getX() - 0.3); body:setY(BandageStep.brother1:getY() + 0.5); Events.OnZombieDead.Add(BandageStep.OnBrothersDead); end function BandageStep.BandageYourself() BandageStep.extTimer = BandageStep.extTimer - 1; if BandageStep.extTimer == 0 then BandageStep.extTimer = 50; getPlayer():setVariable("Ext", "PainHandL"); getPlayer():reportEvent("EventDoExt"); end getPlayer():setIgnoreInputsForDirection(true); getPlayer():setSneaking(false); if getPlayer():getBodyDamage():getBodyPart(BodyPartType.Hand_L):getBandageLife() > 0 then getSoundManager():PlayWorldSoundImpl("MaleZombieAttack", false, getPlayer():getX() + 2, getPlayer():getY() + 1, 0, 0, 20, 1, false); BandageStep.sqDoor = getSquare(176, 153, 0); local charInfo = getPlayerInfoPanel(getPlayer():getPlayerNum()); if charInfo then charInfo:setVisible(false); if JoypadState.players[1] then setJoypadFocus(0, nil) updateJoypadFocus(JoypadState.players[1]) end end SneakStep.setZoom(1); getPlayer():setIgnoreInputsForDirection(false); getPlayer():setDir(IsoDirections.E); BandageStep.sqWindow = getCell():getGridSquare(178, 147, 0); TutorialTests.addMarker(BandageStep.sqWindow, 1); TutorialTests.highlight(BandageStep.barricadedWindow1, 0.1); return true; end return false; end function BandageStep.ThroughDoor() getPlayer():setIgnoreInputsForDirection(false); getPlayer():setIgnoreContextKey(false); if not BandageStep.spawnedItems then TutorialTests.highlight(BandageStep.lockedDoor, 0.3); TutorialTests.addHoming(BandageStep.lockedDoor:getSquare(), -60); BandageStep.lockedDoor:setLockedByKey(false); BandageStep.lockedDoor:setLocked(false); getPlayer():setIgnoreContextKey(false); BandageStep.containers = {}; Tutorial1.contextMenuWear = true; local sq = getSquare(175, 147, 0); for i=0, sq:getObjects():size() -1 do local obj = sq:getObjects():get(i); if obj:getContainer() then TutorialTests.highlight(obj, 0.3); TutorialTests.addHoming(sq, nil, nil, {r=0,g=1,b=0}); obj:getContainer():AddItem("Base.Hat_BaseballCap_Reverse"); obj:getContainer():AddItem("Base.Hat_Bandana"); obj:getContainer():AddItem("Base.Trousers_CamoDesert"); obj:getContainer():AddItem("Base.Shorts_CamoGreenLong"); obj:getContainer():AddItem("Base.Vest_Hunting_Orange"); obj:getContainer():AddItem("Base.Dungarees"); obj:getContainer():AddItem("Base.Tshirt_Rock"); obj:getContainer():AddItem("Base.Shirt_Denim"); obj:getContainer():AddItem("Base.Shirt_Lumberjack"); obj:getContainer():AddItem("Base.Jacket_Black"); obj:getContainer():AddItem("Base.HoodieUP_WhiteTINT"); obj:getContainer():AddItem("Base.Shoes_ArmyBoots"); table.insert(BandageStep.containers, obj); end end BandageStep.spawnedItems = true; end getPlayer():setSneaking(false); local complete = BandageStep.lockedDoor:IsOpen() and getPlayer():getCurrentSquare() == BandageStep.sqDoor; if BandageStep.lockedDoor:IsOpen() and not BandageStep.blink then BandageStep.blink = true; TutorialTests.RemoveMarkers(); TutorialTests.stopHighlight(BandageStep.lockedDoor); for i,v in ipairs(BandageStep.containers) do TutorialTests.stopHighlight(v); end TutorialTests.addMarker(getSquare(176, 154, 0), 1) end if complete then BandageStep.lockedDoor:ToggleDoorSilent(); TutorialTests.RemoveMarkers(); getPlayer():setIgnoreContextKey(true); SneakStep.setZoom(1.5); getPlayer():setDir(IsoDirections.E); getPlayerInventory(0).isCollapsed = true; getPlayerInventory(0):setMaxDrawHeight(getPlayerInventory(0):titleBarHeight()); getPlayerLoot(0).isCollapsed = true; getPlayerLoot(0):setMaxDrawHeight(getPlayerInventory(0):titleBarHeight()); end return complete; end function BandageStep:isComplete() return TutorialStep.isComplete(self); end function BandageStep:finish() BandageStep.finished = true; TutorialStep.finish(self); end ShotgunStep = TutorialStep:derive("ShotgunStep"); ShotgunStep.tickBeforeHordeSpawn = 0; ShotgunStep.hassprintedTimer = 0; ShotgunStep.soundTimer = 0; function ShotgunStep:new () local o = {} setmetatable(o, self) self.__index = self return o end function ShotgunStep:begin() JoypadState.disableControllerPrompt = false; JoypadState.disableMovement = false; JoypadState.disableYInventory = false; ISBackButtonWheel.disablePlayerInfo = false; JoypadState.disableInvInteraction = false; JoypadState.disableClimbOver = false; if getCore():getDebug() and not BandageStep.finished then getPlayer():setAuthorizeMeleeAction(false); getPlayer():setIgnoreInputsForDirection(false); local bag = InventoryItemFactory.CreateItem("Base.Bag_ALICEpack"); SneakStep.bag = bag; local shotgun = SneakStep.spawnShotgun(); getPlayer():getInventory():AddItem(shotgun); getPlayer():getInventory():AddItem(bag); bag:getItemContainer():AddItem("Base.Bandage"); getPlayer():setWornItem("Back", bag); getPlayer():setPrimaryHandItem(shotgun); getPlayer():setSecondaryHandItem(shotgun); BandageStep.spawnBrothers(); getPlayer():setX(180); getPlayer():setY(155); if not JoypadState.players[1] then getPlayerInventory(0):setVisible(true); getPlayerLoot(0):setVisible(true); end getPlayer():setZombieKills(2); end getPlayer():setAllowRun(true); getPlayer():setIgnoreContextKey(true); ShotgunStep.lockedX = getPlayer():getX(); ShotgunStep.lockedY = getPlayer():getY(); getPlayer():LevelPerk(Perks.Fitness);getPlayer():LevelPerk(Perks.Fitness);getPlayer():LevelPerk(Perks.Fitness);getPlayer():LevelPerk(Perks.Fitness);getPlayer():LevelPerk(Perks.Fitness);getPlayer():LevelPerk(Perks.Fitness); ShotgunStep.squares = {}; for x=183, 185 do local sq = getSquare(x, 153, 0); local objs = sq:getObjects(); local obj = sq:getWall(true); if obj then TutorialTests.highlight(obj, 0.1); end table.insert(ShotgunStep.squares, sq); end TutorialTests.addMarker(getSquare(184, 154, 0), 2); ShotgunStep.outhouseSQ = {}; for x=178, 184 do for y=162, 168 do local sq = getSquare(x, y, 0); table.insert(ShotgunStep.outhouseSQ, sq); end end if JoypadState.players[1] then self:addMessage(getText("IGUI_Tutorial1_Shotgun1Joypad"), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.OnSquare); self:addMessage(getText("IGUI_Tutorial1_Shotgun1bJoypad"), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.ClimbedFence); self:addMessage(getText("IGUI_Tutorial1_Shotgun2Joypad"), getCore():getScreenWidth()/2, 150 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.Aiming); self:addMessage(getText("IGUI_Tutorial1_Shotgun3Joypad"):gsub("GHCR", getCore():getGoodHighlitedColor():getR()):gsub("GHCG", getCore():getGoodHighlitedColor():getG()):gsub("GHCB", getCore():getGoodHighlitedColor():getB()), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.BrothersDead); self:addMessage(getText("IGUI_Tutorial1_Shotgun4Joypad"), getCore():getScreenWidth()/2, 300 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.BackOverFence); self:addMessage(getText("IGUI_Tutorial1_Shotgun5Joypad"), getCore():getScreenWidth()/2, 150 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.Sprinted); self:addMessage(getText("IGUI_Tutorial1_Shotgun6Joypad"), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 420, 110, true); self:addMessage(getText("IGUI_Tutorial1_Shotgun7Joypad"), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.isPlayedDeadJoypad); self:addMessage(getText("IGUI_Tutorial1_Shotgun8Joypad"), getCore():getScreenWidth()/2, 50 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.TheEnd); else self:addMessage(getText("IGUI_Tutorial1_Shotgun1", getKeyName(getCore():getKey("Crouch"))), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.OnSquare); self:addMessage(getText("IGUI_Tutorial1_Shotgun1b", getKeyName(getCore():getKey("Interact"))), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.ClimbedFence); self:addMessage(getText("IGUI_Tutorial1_Shotgun2"), getCore():getScreenWidth()/2, 150 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.Aiming); self:addMessage(getText("IGUI_Tutorial1_Shotgun3"):gsub("GHCR", getCore():getGoodHighlitedColor():getR()):gsub("GHCG", getCore():getGoodHighlitedColor():getG()):gsub("GHCB", getCore():getGoodHighlitedColor():getB()), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.BrothersDead); self:addMessage(getText("IGUI_Tutorial1_Shotgun4", getKeyName(getCore():getKey("Interact"))), getCore():getScreenWidth()/2, 300 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.BackOverFence); local sprintText = getText("IGUI_Tutorial1_Shotgun5", Tutorial1.moveKeys, getKeyName(getCore():getKey("Sprint"))) if getCore():getKey("Sprint") == 0 then if getCore():isOptiondblTapJogToSprint() then sprintText = getText("IGUI_Tutorial1_Shotgun5a", Tutorial1.moveKeys, getKeyName(getCore():getKey("Run"))) else -- impossible to sprint end end self:addMessage(sprintText, getCore():getScreenWidth()/2, 150 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.Sprinted); self:addMessage(getText("IGUI_Tutorial1_Shotgun6", getKeyName(getCore():getKey("Shout"))), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.Shout); self:addMessage(getText("IGUI_Tutorial1_Shotgun7"), getCore():getScreenWidth()/2, 250 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.isPlayedDead); self:addMessage(getText("IGUI_Tutorial1_Shotgun8", getKeyName(getCore():getKey("Toggle Survival Guide"))), getCore():getScreenWidth()/2, 50 + getCore():getScreenHeight()/2, 420, 110, false, ShotgunStep.TheEnd); end self:doMessage(); end function ShotgunStep.TheEnd() if not ShotgunStep.timeOfDeath then ShotgunStep.timeOfDeath = getTimestamp() end if not ShotgunStep.soundDone and ShotgunStep.timeOfDeath + 15 > getTimestamp() then addSound(getPlayer(), getPlayer():getX() + 20, getPlayer():getY() + 20, 0, 100, 100); -- Move the zed away to see the reanimation ShotgunStep.soundDone = true; end end function ShotgunStep.Outhouse() return false; end function ShotgunStep.BackOverFence() getPlayer():setIgnoreContextKey(false); if not ShotgunStep.vaulted and getPlayer():getCurrentState():equals(ClimbOverWallState.instance()) then ShotgunStep.vaulted = true; end local complete = ShotgunStep.vaulted and (getPlayer():getCurrentSquare():getY() == 153 or getPlayer():getCurrentSquare():getY() == 154) and getPlayer():getCurrentState():equals(IdleState.instance()); if complete then SneakStep.setZoom(1.5); for x,v in ipairs(ShotgunStep.squares) do local objs = v:getObjects(); for i = 0, objs:size()-1 do TutorialTests.stopHighlight(objs:get(i)); end end TutorialTests.RemoveMarkers(); TutorialTests.addMarker(getSquare(181, 165, 0), 4) end return complete; end function ShotgunStep.ClimbedFence() getPlayer():setIgnoreAutoVault(false); getPlayer():setIgnoreContextKey(false); -- if getPlayer():getDir() ~= IsoDirections.N then -- getPlayer():setIgnoreInputsForDirection(false); -- getPlayer():setDir(IsoDirections.N); -- else -- getPlayer():setIgnoreInputsForDirection(true); -- ShotgunStep.block = true; -- end -- if ShotgunStep.block then -- getPlayer():setIgnoreInputsForDirection(true); -- end if not ShotgunStep.vaulted and getPlayer():getCurrentState():equals(ClimbOverWallState.instance()) then ShotgunStep.vaulted = true; end local complete = ShotgunStep.vaulted and (getPlayer():getCurrentSquare():getY() == 152 or getPlayer():getCurrentSquare():getY() == 151) and getPlayer():getCurrentState():equals(IdleState.instance()); if complete then getPlayer():setIgnoreContextKey(true); getPlayer():setSneaking(false); for x,v in ipairs(ShotgunStep.squares) do local objs = v:getObjects(); for i = 0, objs:size()-1 do TutorialTests.stopHighlight(objs:get(i)); end end TutorialTests.RemoveMarkers(); BandageStep.brother1:setForceEatingAnimation(false); end return complete; end function ShotgunStep.Sprinted() getPlayer():setSneaking(false); getPlayer():setIgnoreContextKey(true); getPlayer():setAllowSprint(true); getPlayer():setIgnoreInputsForDirection(false); local complete = getPlayer():isSprinting(); if complete then ShotgunStep.hassprintedTimer = ShotgunStep.hassprintedTimer + 1; end local onSQ = false; if ShotgunStep.hassprintedTimer >= 5 then for i,v in ipairs(ShotgunStep.outhouseSQ) do if v == getPlayer():getCurrentSquare() then onSQ = true; break; end end end if onSQ then SneakStep.setZoom(1); getPlayer():setIgnoreContextKey(false); TutorialTests.RemoveMarkers(); getPlayer():setIgnoreInputsForDirection(true); end return onSQ; end function ShotgunStep.OnSquare() if getPlayer():isSneaking() then getPlayer():setIgnoreInputsForDirection(false); ShotgunStep.sneaked = true; end if not ShotgunStep.sneaked then getPlayer():setIgnoreInputsForDirection(true); end local complete = false; for i,v in ipairs(ShotgunStep.squares) do if getPlayer():getSquare() == v then complete = true; break; end end if complete then TutorialTests.RemoveMarkers(); getPlayer():setDir(IsoDirections.N); end return complete; end function ShotgunStep:Aiming() local complete = getPlayer():isAiming(); getPlayer():setSneaking(false); if complete then getSoundManager():playMusic("NewMusic_Surrounded"); BandageStep.brother2:setForceEatingAnimation(false); getPlayer():setIgnoreInputsForDirection(false); ShotgunStep.brotherWakeupTimer = 25; BandageStep.brother1:setImmortalTutorialZombie(false); BandageStep.brother2:setImmortalTutorialZombie(false); end return complete; end function ShotgunStep.BrothersDead() ShotgunStep.brotherWakeupTimer = ShotgunStep.brotherWakeupTimer-1; if ShotgunStep.brotherWakeupTimer == 0 then BandageStep.brother1:setUseless(false); BandageStep.brother2:setUseless(false); getCore():setCollideZombies(true); addSound(getPlayer(), getPlayer():getX(), getPlayer():getY(), 0, 100, 100); end getPlayer():setSneaking(false); getPlayer():setAuthorizeMeleeAction(true); SneakStep.shotgun:setCurrentAmmoCount(6); SneakStep.shotgun:setCondition(SneakStep.shotgun:getConditionMax()); local complete = BandageStep.isBrothersDead; if complete then getPlayer():setAuthorizeMeleeAction(false); getCore():setCollideZombies(false); getPlayer():setDir(IsoDirections.S); ShotgunStep.squares = {}; for x=183, 185 do local sq = getSquare(x, 153, 0); local objs = sq:getObjects(); local obj = sq:getWall(true); if obj then TutorialTests.highlight(obj, 0.2); end table.insert(ShotgunStep.squares, sq); end TutorialTests.addMarker(getSquare(184, 154, 0), 2); for i=0, 8 do getPlayer():addBlood(nil, false, true, false); end end return complete; end function ShotgunStep:Shout() getPlayer():setSneaking(false); getPlayer():setCanShout(true); getPlayer():setIgnoreInputsForDirection(true); local complete = getPlayer():isSpeaking() or ShotgunStep.forceSpawnHorde; if complete then spawnHorde(200, 141, 210, 165, 0, 100); spawnHorde(176, 190, 202, 202, 0, 100); spawnHorde(169, 130, 195, 115, 0, 100); spawnHorde(154, 164, 162, 186, 0, 100); getPlayer():setInvincible(false); getPlayer():setUnlimitedEndurance(false); -- open easter egges door Tutorial1.openDoor(193, 194, 0, true) Tutorial1.openDoor(192, 199, 0, false) Tutorial1.openDoor(106, 128, 0, true) Tutorial1.openDoor(103, 124, 0, true) addZombiesInOutfitArea(103, 120, 105, 122, 0, 3, "Doctor", nil); addZombiesInOutfitArea(193, 197, 196, 201, 0, 2, "HospitalPatient", nil); getPlayer():setIgnoreInputsForDirection(false); getPlayer():setAuthorizeMeleeAction(true); getPlayer():setIgnoreContextKey(false); getPlayer():setIgnoreAutoVault(false); getCore():setCollideZombies(true); getCore():setTutorialDone(true); getCore():saveOptions(); Tutorial1.unlockDoor(182, 165, 0); JoypadState.disableClimbOver = false; JoypadState.disableSmashWindow = false; JoypadState.disableReload = false; JoypadState.disableGrab = false; JoypadState.disableInvInteraction = false; JoypadState.disableYInventory = false; JoypadState.disableControllerPrompt = false; JoypadState.disableMovement = false; ISBackButtonWheel.disablePlayerInfo = false; ISBackButtonWheel.disableCrafting = false; ISBackButtonWheel.disableTime = false; ISBackButtonWheel.disableMoveable = false; ISBackButtonWheel.disableZoomOut = false; ISBackButtonWheel.disableZoomIn = false; -- end end return complete; end function ShotgunStep.SurvivalGuideOpen() getPlayer():setSneaking(false); ShotgunStep.soundTimer = ShotgunStep.soundTimer + 1; if ShotgunStep.soundTimer == 100 then addSound(getPlayer(), getPlayer():getX(), getPlayer():getY(), 0, 100, 100); ShotgunStep.soundTimer = 0; end getPlayer():setSprinting(false); SurvivalGuideManager.blockSurvivalGuide = false; if SurvivalGuideManager.instance and SurvivalGuideManager.instance.panel:isVisible() then return true; end return false; end function ShotgunStep:isComplete() return TutorialStep.isComplete(self); end function ShotgunStep:finish() ShotgunStep.finished = true; TutorialStep.finish(self); end function ShotgunStep:isPlayedDead() ShotgunStep.soundTimer = ShotgunStep.soundTimer + 1; if ShotgunStep.soundTimer == 100 then addSound(getPlayer(), getPlayer():getX(), getPlayer():getY(), 0, 100, 100); ShotgunStep.soundTimer = 0; end getPlayer():setIgnoreContextKey(false); getPlayer():setIgnoreAutoVault(false); if getPlayer():isDead() then -- if FightStep.timeOfDeath + 200 > getTimestamp() then -- TutorialMessage.instance:setVisible(false) -- end return true; else addSound(getPlayer(), getPlayer():getX(), getPlayer():getY(), 0, 100, 100); end return false; end function ShotgunStep:isPlayedDeadJoypad() getPlayer():setCanShout(true); if not ShotgunStep.spawnedHorde then getPlayer():Callout(); ShotgunStep.forceSpawnHorde = true; ShotgunStep:Shout(); ShotgunStep.spawnedHorde = true; end ShotgunStep.soundTimer = ShotgunStep.soundTimer + 1; if ShotgunStep.soundTimer == 100 then addSound(getPlayer(), getPlayer():getX(), getPlayer():getY(), 0, 100, 100); ShotgunStep.soundTimer = 0; end getPlayer():setIgnoreContextKey(false); getPlayer():setIgnoreAutoVault(false); if getPlayer():isDead() then -- if FightStep.timeOfDeath + 200 > getTimestamp() then -- TutorialMessage.instance:setVisible(false) -- end return true; else addSound(getPlayer(), getPlayer():getX(), getPlayer():getY(), 0, 100, 100); end return false; end