meta data for this page
Objects/DoorController.lua
This script is used for all static in-game doors (i.e. all doors except vehicle or ropeway carrier doors). In theory, you can also use the script on vehicles, but we recommend to use AnimatedParts instead in that case.
24 DoorController = DoorController or {}; 25 local DoorControllerClass = Class(DoorController);
DoorController:load(collisionId, doorId, textOn, textOff, doorCloser, enableRwTimescale, soundConfiguration)
Gets called for each new DoorController, i.e. by the onCreate event.
collisionId
(transform id): Object id of the door collision. This will be the control element of the door (which can be clicked by the player).doorId
(transform id): Object id of the Animation component. Make sure this is not the same object as the collision, i.e. collision and Animation must be separated.textOn
(string): Text that will be shown when the player hovers the collision and the door is closed (animation position = 0 %).textOff
(string): Text that will be shown when the player hovers the collision and the door is opened (animation position = 100 %).doorCloser
(optional bool):true
if the door should close itself automatically if the player is more than 2 metres awayenableRwTimescale
(optional bool):true
if the door should be accelerated by ropeway timescale (will not be accelerated otherwise)soundConfiguration
(optional datatable): Configuration of sounds that should be played if the player interacts with the door. This is usually a lot of work and not necessary for mods.
37 function DoorController:load(collisionId, doorId, textOn, textOff, doorCloser, enableRwTimescale, soundConfiguration) 38 -- first store the main id 39 self.collisionId = collisionId; 40 self.doorId = doorId; 41 self.animLength = Animation.getLength(self.doorId); 42 Animation.setAutoPlay(self.doorId, false); 43 44 local x,y,z = getWorldPosition(doorId); 45 self.savegameKey = "doorController" .. string.format(":%s @ (%.4f, %.4f, %.4f)", getName(self.doorId), x,y,z); 46 47 self.textOn = l10n.getDollar(textOn or ""); 48 self.textOff = l10n.getDollar(textOff or textOn); 49 50 self.state = false; 51 self.position = 0; 52 self.enableRwTimescale = enableRwTimescale; -- defines whether the door is influenced by the ropeway timescale (false or nil: real time only, not depending on timescale) 53 self.targetPosition = self.state and self.animLength or 0; 54 self.doorCloser = getNoNil(doorCloser, true); -- closes the door automatically if player is more than 2 metres away 55 56 if soundConfiguration ~= nil then 57 self.soundConfiguration = {}; 58 59 for n, v in pairs(soundConfiguration) do 60 -- get all audio source lengths 61 if 62 v.id ~= nil and v.id ~= 0 and 63 (v.triggerTime ~= nil or v.finishTime ~= nil) 64 then 65 local tbl = {}; 66 tbl.id = v.id; 67 tbl.direction = getNoNil(v.direction, 1); -- 1: state 0=>1, 2: state 1=>0 68 69 if v.triggerOnPress then 70 tbl.triggerOnPress = true; 71 72 elseif v.triggerTime ~= nil then 73 tbl.triggerTime = v.triggerTime; -- time in seconds! 74 75 else 76 tbl.triggerTime = (v.finishTime - AudioSource.getLength(tbl.id) * (tbl.direction == 1 and 1 or -1)); 77 end; 78 79 if tbl.triggerTime ~= nil then 80 tbl.triggerTime = clamp(tbl.triggerTime, 0, self.animLength); 81 end; 82 83 AudioSource.stop(tbl.id); 84 table.insert(self.soundConfiguration, tbl); 85 end; 86 end; 87 end; 88 89 Animation.sampleTime(self.doorId, self.position); 90 91 if self.collisionId == 0 then 92 print("Error while loading Door " .. tostring(getName(self.doorId)) .. ". Collision index is invalid."); 93 end; 94 self.buttonId = ControlElement.new(self.collisionId); 95 ControlElement.setCallback(self.buttonId, 1, function() self:setState(not self.state); end); 96 97 self:setState(false); 98 99 -- load the state from savegame 100 -- we will also be registered to a destroy listener 101 -- BUT as always: we will have to deregister the object ourselves 102 g_scenario:addObjectAndLoad(self, self.doorId); 103 end;
DoorController:destroy()
Is called if the door is destroyed (e.g. if the ropeway or prefab containing the door is deleted).
107 function DoorController:destroy() 108 g_scenario:removeObject(self); 109 end;
DoorController:saveToTable(savegame)
Saves the door state to the savegame. Note that this method is designed for static prefabs (used in in-game editor prefabs or ropeways), but not for physics-dependent objects (e.g. vehicles, carriers). This is also the reason why we recommend not to use DoorController
inside vehicles.
113 function DoorController:saveToTable(savegame) 114 if savegame[self.savegameKey] ~= nil then 115 print("Warning while saving to table: Multiple DoorControllers are using the key " .. tostring(self.savegameKey) .. ". All of them will have the same state when loading the savegame. Please avoid DoorControllers that are named the same and placed at the same spot."); 116 return; 117 end; 118 savegame[self.savegameKey] = self.state; 119 end;
DoorController:loadFromTable(savegame)
Retrieves the information stored in the savegame and applies it to the door.
123 function DoorController:loadFromTable(savegame) 124 if savegame == nil then return end; 125 126 local state = savegame[self.savegameKey]; 127 if state ~= nil then 128 self:setState(state, true); 129 end; 130 end;
DoorController:setState(state, jump)
Sets the state of the door controller.
state
(bool):true
if the door shall be open, otherwisefalse
.jump
(optional bool):true
if you want the door to jump to the new position.
If necessary, updating the object is resumed (g_scenario:resumeUpdatingObject(self)
).
138 function DoorController:setState(state, jump) 139 self.state = state; 140 self.targetPosition = self.state and self.animLength or 0; 141 142 -- jump there 143 if jump then 144 self.position = self.targetPosition; 145 Animation.sampleTime(self.doorId, self.position); 146 end; 147 148 ControlElement.setName(self.buttonId, self.state and self.textOff or self.textOn); 149 150 g_scenario:resumeUpdatingObject(self); 151 152 if self.soundConfiguration ~= nil then 153 for k, v in pairs(self.soundConfiguration) do 154 if v.triggerOnPress then 155 AudioSource.play(v.id); 156 end; 157 end; 158 end; 159 end;
DoorController:update(dt)
Update function for updating the animation and handling the door closer (depending on self.doorCloser
and the gameplay settings). If the call is no longer necessary (e.g. if no animation is taking place any more), the object will no longer be updated (g_scenario:pauseUpdatingObject(self)
).
163 function DoorController:update(dt) 164 if self.doorCloser and GameplaySettings.autoCloseDoors and self.state then 165 -- close door if player is too far away 166 if (VectorUtils.getWorldPosition(g_scenario.player.transformId) - VectorUtils.getWorldPosition(self.doorId)):sqrMagnitude() > 25 then 167 self:setState(false); 168 end; 169 end; 170 171 if self.position == self.targetPosition then 172 173 if not (self.doorCloser and GameplaySettings.autoCloseDoors and self.state) then 174 g_scenario:pauseUpdatingObject(self); 175 end; 176 return; 177 end; 178 179 -- we need to move 180 if self.enableRwTimescale then 181 dt = dt * g_scenario.environment.activeRwTimescale; 182 end; 183 local oldPosition = self.position; 184 self.position = Utils.moveTowards(self.position, self.targetPosition, dt); 185 186 -- update sounds 187 if self.soundConfiguration ~= nil then 188 local direction = oldPosition < self.position and 1 or 2; 189 for k, v in pairs(self.soundConfiguration) do 190 191 if v.triggerTime ~= nil and v.direction == direction then 192 if (oldPosition <= v.triggerTime and self.position >= v.triggerTime) or (oldPosition >= v.triggerTime and self.position <= v.triggerTime) then 193 AudioSource.play(v.id); 194 end; 195 end; 196 end; 197 end; 198 199 200 Animation.sampleTime(self.doorId, self.position); 201 end;
Copyright
All contents of this page may be used for modding use for Winter Resort Simulator only. Any use exceeding this regulation is not permitted.
Copyright (C) HR Innoways, 2020. All Rights Reserved.