Skip to content

Commit

Permalink
Workspace wind setting (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
boatbomber authored Jun 19, 2023
1 parent 5f115d1 commit cfd1643
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 31 deletions.
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,21 @@ number WindShake.MaxRefreshRate
## Functions

```Lua
function WindShake:Init()
function WindShake:Init(config: {
MatchWorkspaceWind: boolean?,
}?)
```
*Initializes the wind shake logic and adds shake to all tagged objects*

**Parameters:**
- `config` *[Optional Dictionary]*

Configuration for the initialization
- `MatchWorkspaceWind` *[Optional Boolean]*

Whether to match the wind settings to the Workspace's GlobalWind setting. Default false


**Returns:**
* `void`

Expand Down Expand Up @@ -151,6 +162,16 @@ The settings to apply to all objects' shake (See below for Settings structure)
**Returns:**
* `void`

```Lua
function WindShake:MatchWorkspaceWind()
```
*Sets the wind settings to match the current workspace GlobalWind*

> When `:Init()` is called with the `MatchWorkspaceWind` config set to true, this is called automatically
**Returns:**
* `void`

## Events

```Lua
Expand Down
4 changes: 3 additions & 1 deletion demo/client/WindController/init.client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ WindShake:SetDefaultSettings({
WindDirection = WIND_DIRECTION,
WindPower = WIND_POWER,
})
WindShake:Init()
WindShake:Init({
MatchWorkspaceWind = true,
})

-- Demo dynamic settings

Expand Down
37 changes: 21 additions & 16 deletions src/Settings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,60 +7,65 @@ local SettingTypes = {
PivotOffset = "CFrame",
}

function Settings.new(object: BasePart | Bone, base)
local inst = {}
function Settings.new(object: BasePart | Bone | ModuleScript)
local objectSettings = {}

-- Initial settings

local WindPower = object:GetAttribute("WindPower")
local WindSpeed = object:GetAttribute("WindSpeed")
local WindDirection = object:GetAttribute("WindDirection")

inst.WindPower = typeof(WindPower) == SettingTypes.WindPower and WindPower or base.WindPower
inst.WindSpeed = typeof(WindSpeed) == SettingTypes.WindSpeed and WindSpeed or base.WindSpeed
inst.WindDirection = typeof(WindDirection) == SettingTypes.WindDirection and WindDirection or base.WindDirection
inst.PivotOffset = if object:IsA("BasePart") then object.PivotOffset else (base.PivotOffset or CFrame.new())
inst.PivotOffsetInverse = inst.PivotOffset:Inverse()
objectSettings.WindPower = if typeof(WindPower) == SettingTypes.WindPower then WindPower else nil
objectSettings.WindSpeed = if typeof(WindSpeed) == SettingTypes.WindSpeed then WindSpeed else nil
objectSettings.WindDirection = if typeof(WindDirection) == SettingTypes.WindDirection
then WindDirection.Unit
else nil
objectSettings.PivotOffset = if object:IsA("BasePart") then object.PivotOffset else nil
objectSettings.PivotOffsetInverse = if typeof(objectSettings.PivotOffset) == "CFrame"
then objectSettings.PivotOffset:Inverse()
else nil

-- Update settings on event

local PowerConnection = object:GetAttributeChangedSignal("WindPower"):Connect(function()
WindPower = object:GetAttribute("WindPower")
inst.WindPower = typeof(WindPower) == SettingTypes.WindPower and WindPower or base.WindPower
objectSettings.WindPower = if typeof(WindPower) == SettingTypes.WindPower then WindPower else nil
end)

local SpeedConnection = object:GetAttributeChangedSignal("WindSpeed"):Connect(function()
WindSpeed = object:GetAttribute("WindSpeed")
inst.WindSpeed = typeof(WindSpeed) == SettingTypes.WindSpeed and WindSpeed or base.WindSpeed
objectSettings.WindSpeed = if typeof(WindSpeed) == SettingTypes.WindSpeed then WindSpeed else nil
end)

local DirectionConnection = object:GetAttributeChangedSignal("WindDirection"):Connect(function()
WindDirection = object:GetAttribute("WindDirection")
inst.WindDirection = typeof(WindDirection) == SettingTypes.WindDirection and WindDirection or base.WindDirection
objectSettings.WindDirection = if typeof(WindDirection) == SettingTypes.WindDirection
then WindDirection.Unit
else nil
end)

local PivotConnection
if object:IsA("BasePart") then
PivotConnection = object:GetPropertyChangedSignal("PivotOffset"):Connect(function()
inst.PivotOffset = object.PivotOffset
inst.PivotOffsetInverse = inst.PivotOffset:Inverse()
objectSettings.PivotOffset = object.PivotOffset
objectSettings.PivotOffsetInverse = objectSettings.PivotOffset:Inverse()
end)
end

-- Cleanup function for when shake is removed or object is unloaded

function inst:Destroy()
function objectSettings:Destroy()
PowerConnection:Disconnect()
SpeedConnection:Disconnect()
DirectionConnection:Disconnect()
if PivotConnection then
PivotConnection:Disconnect()
end

table.clear(inst)
table.clear(objectSettings)
end

return inst
return objectSettings
end

return Settings
70 changes: 57 additions & 13 deletions src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ local COLLECTION_TAG = "WindShake" -- The CollectionService tag to be watched an
-- The table provided is a fallback if the attributes
-- are undefined or using the wrong value types.

local DEFAULT_SETTINGS = Settings.new(script, {
local FALLBACK_SETTINGS = {
WindDirection = Vector3.new(0.5, 0, 0.5),
WindSpeed = 20,
WindPower = 0.5,
})
}

-----------------------------------------------------------------------------------------------------------------

Expand All @@ -35,6 +35,7 @@ local ResumedEvent = Instance.new("BindableEvent")
local WindShake = {
RenderDistance = 150,
MaxRefreshRate = 1 / 60,
SharedSettings = Settings.new(script),

ObjectMetadata = {},
VectorMap = VectorMap.new(),
Expand Down Expand Up @@ -89,7 +90,7 @@ function WindShake:AddObjectShake(object: BasePart | Bone, settingsTable: WindSh
if object:IsA("Bone") then object.WorldPosition else object.Position,
object
),
Settings = Settings.new(object, DEFAULT_SETTINGS),
Settings = Settings.new(object),

Seed = math.random(5000) * 0.32,
Origin = if object:IsA("Bone") then object.WorldCFrame else object.CFrame,
Expand Down Expand Up @@ -151,6 +152,10 @@ function WindShake:Update(deltaTime: number)
local cameraPos = camera.CFrame.Position
local renderDistance = self.RenderDistance
local maxRefreshRate = self.MaxRefreshRate
local sharedSettings = self.SharedSettings
local sharedWindPower = sharedSettings.WindPower
local sharedWindSpeed = sharedSettings.WindSpeed
local sharedWindDirection = sharedSettings.WindDirection

-- Update objects in view at their respective refresh rates
self.VectorMap:ForEachObjectInView(camera, renderDistance, function(className: string, object: BasePart | Bone)
Expand All @@ -174,15 +179,23 @@ function WindShake:Update(deltaTime: number)
active += 1

local objSettings = objMeta.Settings
local amp = (objSettings.WindPower or sharedWindPower) * 0.2
if amp < 1e-5 then
return
end

local freq = now * ((objSettings.WindSpeed or sharedWindSpeed) * 0.08)
if freq < 1e-5 then
return
end

local seed = objMeta.Seed
local amp = objSettings.WindPower * 0.2
local lowAmp = amp / 3
local freq = now * (objSettings.WindSpeed * 0.08)
local animValue = (math.noise(freq, 0, seed) + 0.4) * amp
local lerpAlpha = math.clamp(step + distanceAlphaSq, 0.1, 0.5)
local lowAmp = amp / 3

local origin = objMeta.Origin * objSettings.PivotOffset
local windDirection = objSettings.WindDirection.Unit
local origin = objMeta.Origin * (objSettings.PivotOffset or CFrame.identity)
local windDirection = (objSettings.WindDirection or sharedWindDirection)
local localWindDirection = origin:VectorToObjectSpace(windDirection)

if isBone then
Expand Down Expand Up @@ -210,7 +223,7 @@ function WindShake:Update(deltaTime: number)
math.noise(seed, freq, 0) * lowAmp,
math.noise(freq, seed, 0) * lowAmp
)
* objSettings.PivotOffsetInverse
* (objSettings.PivotOffsetInverse or CFrame.identity)
) + (windDirection * animValue * (amp * 2)),
lerpAlpha
)
Expand Down Expand Up @@ -251,7 +264,7 @@ function WindShake:Resume()
ResumedEvent:Fire()
end

function WindShake:Init()
function WindShake:Init(config: { MatchWorkspaceWind: boolean? })
if self.Initialized then
return
end
Expand All @@ -262,15 +275,15 @@ function WindShake:Init()
local direction = script:GetAttribute("WindDirection")

if typeof(power) ~= "number" then
script:SetAttribute("WindPower", DEFAULT_SETTINGS.WindPower)
script:SetAttribute("WindPower", FALLBACK_SETTINGS.WindPower)
end

if typeof(speed) ~= "number" then
script:SetAttribute("WindSpeed", DEFAULT_SETTINGS.WindSpeed)
script:SetAttribute("WindSpeed", FALLBACK_SETTINGS.WindSpeed)
end

if typeof(direction) ~= "Vector3" then
script:SetAttribute("WindDirection", DEFAULT_SETTINGS.WindDirection)
script:SetAttribute("WindDirection", FALLBACK_SETTINGS.WindDirection)
end

-- Clear any old stuff.
Expand All @@ -288,6 +301,14 @@ function WindShake:Init()
self:AddObjectShake(object)
end

-- Wire up workspace wind.
if config and config.MatchWorkspaceWind then
self:MatchWorkspaceWind()
self.WorkspaceWindConnection = workspace:GetPropertyChangedSignal("GlobalWind"):Connect(function()
self:MatchWorkspaceWind()
end)
end

-- Automatically start.
self:Resume()
end
Expand All @@ -309,6 +330,11 @@ function WindShake:Cleanup()
self.RemovedConnection = nil
end

if self.WorkspaceWindConnection then
self.WorkspaceWindConnection:Disconnect()
self.WorkspaceWindConnection = nil
end

table.clear(self.ObjectMetadata)
self.VectorMap:ClearAll()

Expand Down Expand Up @@ -354,4 +380,22 @@ function WindShake:SetDefaultSettings(settingsTable: WindShakeSettings)
self:UpdateObjectSettings(script, settingsTable)
end

function WindShake:MatchWorkspaceWind()
local workspaceWind = workspace.GlobalWind
local windDirection = workspaceWind.Unit
local windSpeed, windPower = 0, 0

local windMagnitude = workspaceWind.Magnitude
if windMagnitude > 0 then
windPower = if windMagnitude > 1 then math.log10(windMagnitude) + 0.2 else 0.3
windSpeed = if windMagnitude < 100 then (windMagnitude * 1.2) + 5 else 125
end

self:SetDefaultSettings({
WindDirection = windDirection,
WindSpeed = windSpeed,
WindPower = windPower,
})
end

return WindShake

0 comments on commit cfd1643

Please sign in to comment.