mirror of
https://github.com/t-affeldt/climate_api.git
synced 2024-12-22 08:50:37 +01:00
Various adjustments and fixes
This commit is contained in:
parent
4df9a61374
commit
f42b4183e5
152
api_doc.md
Normal file
152
api_doc.md
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
# API Documentation
|
||||||
|
|
||||||
|
## How to read this document
|
||||||
|
If a function states multiple parameters of the same name then either of them has to be passed on function call. Look at the function signature to determine the order of required parameters.
|
||||||
|
|
||||||
|
## Custom Weather Registration
|
||||||
|
|
||||||
|
### Register Weather Preset
|
||||||
|
``climate_api.register_weather(name, conditions, effects)``
|
||||||
|
|
||||||
|
Invoke this function in order to create and register a new weather preset. Presets control which effects are to be applied to a player under specific circumstances. As an example, a preset for rain could require a high level of humidity and apply particle and sound effects.
|
||||||
|
|
||||||
|
__Parameters__:
|
||||||
|
- ``name <string>``: A unique identifier resembling the new weather preset.
|
||||||
|
Should be prefixed with the mod's name in a way that could look like ``mymod:awesome_weather``. This name should only be used once.
|
||||||
|
- ``conditions <table>``: An associative array that checks weather influences for specified values. Keys should be the name of an influence, values should be of matching type for repective influence. Keys can be prefixed with ``min_`` to accept any value equal or higher than influence value. A prefix of ``max_`` will accept any value lesser than influence value. A prefix of ``has_`` can be used in conjunction with a numeric array as a value. It will accept any influence value that is present in the specified table. Omitting a prefix will accept the specified value only. All table entries have to be matched positively for the weather preset to be applied.
|
||||||
|
- ``conditions <function>``: For more control, a function can be specified instead of a conditions table. The function will receive a table as its first parameter, consisting of key-value pairs indicating the current value for each weather influence. The function is expected to return true if the weather preset is to be applied or false otherwise.
|
||||||
|
- ``effects <table>``: An associative array indicating which weather effects are to be applied whenever the weather preset is active. The key should be a registered weather effect name. The value will be passed as a parameter to the effect. Look at the documentation of individual effects to determine valid values.
|
||||||
|
- ``effects <function>``: A generator function that returns a set of weather effects and its parameters. This function will receive a table as its first parameter, consisting of key-value pairs indicating the current value for each weather influence. It is expected to return a table in the same fashion as ``effects <table>`` would have looked like.
|
||||||
|
|
||||||
|
__Returns__: ``nil``
|
||||||
|
|
||||||
|
|
||||||
|
### Register Weather Effect
|
||||||
|
``climate_api.register_effect(name, handler, htype)``
|
||||||
|
|
||||||
|
__Parameters__:
|
||||||
|
- ``name <string>``: A unique identifier resembling the new weather effect.
|
||||||
|
Should be prefixed with the mod's name in a way that could look like ``mymod:special_effect``. Call this function multiple times with the same name in order to apply multiple handler methods to the same effect.
|
||||||
|
- ``handler <function>``: This function will be called whenever players are affected by the registered effect. It receives a single parameter containing an accociative array. The keys represent player names and the values represent the set of applied preset parameters. This set is an accociative array as well with the keys representing the names of applied weather presets and the values representing the supplied data from those presets. This parameter could look like this:
|
||||||
|
``{ singleplayer = {"mymod:awesome_weather" = "a", "mymod:amazing_weather" = "b"} }``. If ``htype`` is ``tick`` then the list of players represents all currently affected players. If it is ``start`` or ``end`` then the list contains all players going though that change.
|
||||||
|
- ``htype <"start" | "tick" | "end">``: Determines when the handler will be called. ``start`` results in a callback whenever an effect is applied to at least one player, meaning that the very first weather preset applies it. ``tick`` results in a callback every update cycle as long as at least one player has the effect from at least one preset. ``end`` results in a callback whenever at least one player loses the effect completely.
|
||||||
|
|
||||||
|
__Returns__: ``nil``
|
||||||
|
|
||||||
|
|
||||||
|
### Set Update Cycle for Effect
|
||||||
|
``climate_api.set_effect_cycle(name, cycle)``
|
||||||
|
|
||||||
|
__Parameters__:
|
||||||
|
- ``name <string>``: The identifier of a registered weather effect
|
||||||
|
- ``cycle <number>``: The minimal time between update calls to registered effect handlers in seconds. This value defaults to ``climate_api.DEFAULT_CYCLE`` (2.0s). Other values are ``climate_api.SHORT_CYCLE`` (0s) for frequent update calls (like for particle effects) and ``climate_api.LONG_CYCLE`` (5.0s) for ressource intensive tasks and timed effects (like lightning strikes). You can also use any other custom number representing the amount of time in seconds.
|
||||||
|
|
||||||
|
__Returns__: ``nil``
|
||||||
|
|
||||||
|
### Register Global Environment Influence
|
||||||
|
``climate_api.register_global_influence(name, func)``
|
||||||
|
|
||||||
|
__Parameters__:
|
||||||
|
- ``name <string>`` A unique name identifying the registered influence
|
||||||
|
- ``func <function>``: A generator function that returns some value which is in turn supplied to weather presets and can be used as a condition.
|
||||||
|
|
||||||
|
__Returns__: ``nil``
|
||||||
|
|
||||||
|
### Register Local Environment Influence
|
||||||
|
``climate_api.register_influence(name, func)``
|
||||||
|
|
||||||
|
__Parameters__:
|
||||||
|
- ``name <string>`` A unique name identifying the registered influence
|
||||||
|
- ``func <function>``: A generator function that returns some value which is in turn supplied to weather presets and can be used as a condition. This function will receive a vector as its single parameter indicating the current position.
|
||||||
|
|
||||||
|
__Returns__: ``nil``
|
||||||
|
|
||||||
|
### Register Active Block Modifier
|
||||||
|
``climate_api.register_abm(config)``
|
||||||
|
|
||||||
|
|
||||||
|
## Environment Access
|
||||||
|
|
||||||
|
### Get Temperature At Position
|
||||||
|
``climate_api.environment.get_heat(pos)``
|
||||||
|
|
||||||
|
__Parameter__: ``pos <vector>``: Coordinates of requested location
|
||||||
|
|
||||||
|
__Returns__: ``<number>`` indicating current temperature in °F
|
||||||
|
|
||||||
|
### Get Humidity At Position
|
||||||
|
``climate_api.environment.get_humidity(pos)``
|
||||||
|
|
||||||
|
__Parameter__: ``pos <vector>``: Coordinates of requested location
|
||||||
|
|
||||||
|
__Returns__: ``<number>`` indicating current humidity
|
||||||
|
|
||||||
|
### Get Current Windspeed
|
||||||
|
``climate_api.environment.get_wind()``
|
||||||
|
|
||||||
|
__Returns__: ``<vector>`` indicating speed and direction
|
||||||
|
|
||||||
|
### ``climate_api.environment.get_weather_presets(player)``
|
||||||
|
|
||||||
|
### ``climate_api.environment.get_effects(player)``
|
||||||
|
|
||||||
|
|
||||||
|
## Skybox Modification
|
||||||
|
|
||||||
|
### ``climate_api.skybox.add(playername, name, sky)``
|
||||||
|
|
||||||
|
### ``climate_api.skybox.remove(playername, name)``
|
||||||
|
|
||||||
|
### ``climate_api.skybox.update(playername)``
|
||||||
|
|
||||||
|
|
||||||
|
## Player Physics Modifications
|
||||||
|
Climate API provides an easy way of modfying player physics in a compatible way.
|
||||||
|
The API is similar to those of ``player_monoids`` or ``playerphysics`` because it also uses multiplication to account for multiple modifiers.
|
||||||
|
In fact, these functions use ``player_monoids`` under the hud if that mod is available. If not, they will fall back to ``playerphysics``, ``pova``, or native overrides in that order.
|
||||||
|
|
||||||
|
### Add Physics Modifier
|
||||||
|
``climate_api.player_physics.add(id, player, effect, value)``
|
||||||
|
|
||||||
|
Register a new modifier that will be multiplied with the current value to set the new physics factor. Call this function again with the same id in order to change an existing modifier.
|
||||||
|
|
||||||
|
__Parameters__:
|
||||||
|
- ``id <string>``: A unique name used to identify the modifier. Should be prefixed with the mod's name.
|
||||||
|
- ``player <ObjectRef>``: The player affected by the physics change
|
||||||
|
- ``effect <"speed" | "jump" | "gravity">``: The type of physics to be changed
|
||||||
|
- ``value <number>``: The multiplicator. Use values between 0 and 1 to reduce physics attribute. Use values above 1 to increase it.
|
||||||
|
|
||||||
|
__Returns__: ``nil``
|
||||||
|
|
||||||
|
### Remove Physics Modifier
|
||||||
|
``climate_api.player_physics.remove(id, player, effect)``
|
||||||
|
|
||||||
|
Use this function to completely remove a physics modifer from the attribute calculation.
|
||||||
|
|
||||||
|
__Parameters__:
|
||||||
|
- ``id <string>``: The name used in ``player_physics.add`` that identifies a registered modifier
|
||||||
|
- ``player <ObjectRef>``: The player affected by the physics change
|
||||||
|
- ``effect <"speed" | "jump" | "gravity">``: The type of physics to be changed
|
||||||
|
|
||||||
|
__Returns__: ``nil``
|
||||||
|
|
||||||
|
|
||||||
|
## Utility Functions
|
||||||
|
|
||||||
|
### Merge Tables
|
||||||
|
``climate_api.utility.merge_tables(a, b)``
|
||||||
|
|
||||||
|
This function will merge two given accociative tables and return the result.
|
||||||
|
If in conflict, attributes of table B will override those of table A.
|
||||||
|
This is especially useful when assigning default values to a specified configuration with possibly missing entries.
|
||||||
|
Note that this function will also modify table A. If you want to prevent that, you should copy the table first: ``climate_api.utility.merge_tables(table.copy(a), b)``.
|
||||||
|
|
||||||
|
__Parameters__:
|
||||||
|
- ``a <table>``: The base table consisting of default values or other data
|
||||||
|
- ``b <table>``: The prioritized table to merge with, and possibly override A
|
||||||
|
|
||||||
|
__Returns__: ``<table>`` consisting of all attributes from A and B.
|
||||||
|
|
||||||
|
### ``climate_api.utility.sigmoid(value, max, growth, midpoint)``
|
||||||
|
|
||||||
|
### ``climate_api.utility.normalized_cycle(value)``
|
@ -3,7 +3,7 @@
|
|||||||
Use this effect to damage a player during dangerous weather events.
|
Use this effect to damage a player during dangerous weather events.
|
||||||
Expects a table as the parameter containing the following values:
|
Expects a table as the parameter containing the following values:
|
||||||
- value <int> [1]: The amount of damage to be applied per successful roll.
|
- value <int> [1]: The amount of damage to be applied per successful roll.
|
||||||
- chance <int> [1]: Defines a 1/x roll per cycle for the player to get damaged. Higher values result in less frequent damage.
|
- rarity <int> [1]: Defines a 1/x chance per cycle for the player to get damaged. Higher values result in less frequent damage.
|
||||||
- check <table> [nil]: Use an additional outdoors check before applying damage. Consists of the following values:
|
- check <table> [nil]: Use an additional outdoors check before applying damage. Consists of the following values:
|
||||||
- type <"light"|"raycast"> ["light"] (Whether the light level should be used a raycast should be performed)
|
- type <"light"|"raycast"> ["light"] (Whether the light level should be used a raycast should be performed)
|
||||||
- height <number> [0] (Height offset of weather origin from the player. Only used for raycasts)
|
- height <number> [0] (Height offset of weather origin from the player. Only used for raycasts)
|
||||||
@ -58,9 +58,9 @@ end
|
|||||||
|
|
||||||
local function calc_damage(player, dmg)
|
local function calc_damage(player, dmg)
|
||||||
if dmg.value == nil then dmg.value = 1 end
|
if dmg.value == nil then dmg.value = 1 end
|
||||||
if dmg.chance == nil then dmg.chance = 1 end
|
if dmg.rarity == nil then dmg.rarity = 1 end
|
||||||
-- check if damage should be applied
|
-- check if damage should be applied
|
||||||
if rng:next(1, dmg.chance) ~= 1 then return 0 end
|
if rng:next(1, dmg.rarity) ~= 1 then return 0 end
|
||||||
if dmg.check ~= nil then
|
if dmg.check ~= nil then
|
||||||
-- check for obstacles in the way
|
-- check for obstacles in the way
|
||||||
if not check_hit(player, dmg.check) then return 0 end
|
if not check_hit(player, dmg.check) then return 0 end
|
||||||
@ -81,4 +81,3 @@ local function handle_effect(player_data)
|
|||||||
end
|
end
|
||||||
|
|
||||||
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
|
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
|
||||||
climate_api.set_effect_cycle(EFFECT_NAME, climate_api.MEDIUM_CYCLE)
|
|
@ -95,4 +95,3 @@ end
|
|||||||
climate_api.register_effect(EFFECT_NAME, start_effect, "start")
|
climate_api.register_effect(EFFECT_NAME, start_effect, "start")
|
||||||
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
|
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
|
||||||
climate_api.register_effect(EFFECT_NAME, stop_effect, "stop")
|
climate_api.register_effect(EFFECT_NAME, stop_effect, "stop")
|
||||||
climate_api.set_effect_cycle(EFFECT_NAME, climate_api.MEDIUM_CYCLE)
|
|
@ -10,29 +10,33 @@ Furthermore, the following default values have been changed:
|
|||||||
- collisiondetection <bool> [true]
|
- collisiondetection <bool> [true]
|
||||||
- collision_removal <bool> [true]
|
- collision_removal <bool> [true]
|
||||||
- playername <string> [current player] (Set to empty string to show for everyone)
|
- playername <string> [current player] (Set to empty string to show for everyone)
|
||||||
|
- vertical <bool> [nil] (Unless explicitly set, particle facing rotation will be automatically set based on direction of velocity)
|
||||||
|
|
||||||
The following optional values have been introduced or expanded for convenience:
|
The following optional values have been introduced for convenience:
|
||||||
- size <int> [nil] (Overrides both minsize and maxsize if set)
|
|
||||||
- boxsize <vector> [nil] (Overrides minpos and maxpos based on specified sizes per direction with the player in the center)
|
- boxsize <vector> [nil] (Overrides minpos and maxpos based on specified sizes per direction with the player in the center)
|
||||||
- boxsize <number> [nil] (If set to a number, the resulting vector will have the specified size in all directions)
|
- boxsize <number> [nil] (If set to a number, the resulting vector will have the specified size in all directions)
|
||||||
- v_offset <int> [0] (Use in conjunctin with boxsize. Adds specified height to minpos and maxpos y-coordinates)
|
- v_offset <int> [0] (Use in conjunctin with boxsize. Adds specified height to minpos and maxpos y-coordinates)
|
||||||
|
- attach_to_player <bool> [false] (Overrides attached object with current player)
|
||||||
|
|
||||||
|
The following optional values have been expanded with additional value types for convenience:
|
||||||
|
- size <int> [nil] (Overrides both minsize and maxsize if set)
|
||||||
- minvel <int> [nil] (Overrides minvel with a downward facing vector of specified length)
|
- minvel <int> [nil] (Overrides minvel with a downward facing vector of specified length)
|
||||||
- maxvel <int> [nil] (Overrides maxvel with a downward facing vector of specified length)
|
- maxvel <int> [nil] (Overrides maxvel with a downward facing vector of specified length)
|
||||||
- velocity <vector | int> [nil] (Overrides both minvel and maxvel if set)
|
- velocity <vector | int> [nil] (Overrides both minvel and maxvel if set)
|
||||||
- minacc <int> [nil] (Overrides minacc with a downward facing vector of specified length)
|
- minacc <int> [nil] (Overrides minacc with a downward facing vector of specified length)
|
||||||
- maxacc <int> [nil] (Overrides maxacc with a downward facing vector of specified length)
|
- maxacc <int> [nil] (Overrides maxacc with a downward facing vector of specified length)
|
||||||
- acceleration <vector | int> [nil] (Overrides both minacc and maxacc if set)
|
- acceleration <vector | int> [nil] (Overrides both minacc and maxacc if set)
|
||||||
- attach_to_player <bool> [false] (Overrides attached object with current player)
|
|
||||||
|
|
||||||
The following new behaviours have been introduced:
|
The following new behaviours have been introduced:
|
||||||
- use_wind <bool> [true] (Adjusts velocity and position for current windspeed)
|
- use_wind <bool> [true] (Adjusts velocity and position for current windspeed)
|
||||||
- detached <bool> [false] (Unless enabled, considers positions as relative to current player like being attached)
|
- detach <bool> [false] (Unless enabled, considers positions as relative to current player as if spawner's position would be attached)
|
||||||
- vertical <bool> [nil] (Unless explicitly set, will be automatically set based on direction of velocity)
|
- adjust_for_velocity <bool> [true] (Corrects position of particle spawner by player's movement speed. Only applicable if detach = false and not manually attached)
|
||||||
]]
|
]]
|
||||||
|
|
||||||
if not climate_mod.settings.particles then return end
|
if not climate_mod.settings.particles then return end
|
||||||
|
|
||||||
local EFFECT_NAME = "climate_api:particles"
|
local EFFECT_NAME = "climate_api:particles"
|
||||||
|
local CYCLE_LENGTH = climate_api.SHORT_CYCLE
|
||||||
|
|
||||||
-- parse config by injecting default values and adding additional parameters
|
-- parse config by injecting default values and adding additional parameters
|
||||||
local function parse_config(player, particles)
|
local function parse_config(player, particles)
|
||||||
@ -44,7 +48,8 @@ local function parse_config(player, particles)
|
|||||||
playername = player:get_player_name(),
|
playername = player:get_player_name(),
|
||||||
use_wind = true,
|
use_wind = true,
|
||||||
attach_to_player = false,
|
attach_to_player = false,
|
||||||
detached = false
|
detach = false,
|
||||||
|
adjust_for_velocity = true
|
||||||
}
|
}
|
||||||
|
|
||||||
-- inject missing default values into specified config
|
-- inject missing default values into specified config
|
||||||
@ -153,12 +158,20 @@ local function parse_config(player, particles)
|
|||||||
config.attach_to_player = nil
|
config.attach_to_player = nil
|
||||||
|
|
||||||
-- attach coordinates to player unless specified or already attached
|
-- attach coordinates to player unless specified or already attached
|
||||||
if (not config.detached) and config.attached == nil then
|
if (not config.detach) and config.attached == nil then
|
||||||
local ppos = player:get_pos()
|
local ppos = player:get_pos()
|
||||||
config.minpos = vector.add(config.minpos, ppos)
|
config.minpos = vector.add(config.minpos, ppos)
|
||||||
config.maxpos = vector.add(config.maxpos, ppos)
|
config.maxpos = vector.add(config.maxpos, ppos)
|
||||||
|
|
||||||
|
-- correct spawn coordinates to adjust for player movement
|
||||||
|
if config.adjust_for_velocity then
|
||||||
|
local velocity = player:get_player_velocity()
|
||||||
|
config.minpos = vector.add(config.minpos, velocity)
|
||||||
|
config.maxpos = vector.add(config.maxpos, velocity)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
config.detached = nil
|
config.detach = nil
|
||||||
|
config.adjust_for_velocity = nil
|
||||||
|
|
||||||
-- move particles in wind direction
|
-- move particles in wind direction
|
||||||
if config.use_wind then
|
if config.use_wind then
|
||||||
@ -198,4 +211,4 @@ local function handle_effect(player_data)
|
|||||||
end
|
end
|
||||||
|
|
||||||
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
|
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
|
||||||
climate_api.set_effect_cycle(EFFECT_NAME, climate_api.SHORT_CYCLE)
|
climate_api.set_effect_cycle(EFFECT_NAME, CYCLE_LENGTH)
|
@ -18,26 +18,26 @@ local function handle_effect(player_data, prev_data)
|
|||||||
for playername, data in pairs(prev_data) do
|
for playername, data in pairs(prev_data) do
|
||||||
for weather, _ in pairs(data) do
|
for weather, _ in pairs(data) do
|
||||||
if player_data[playername] == nil or player_data[playername][weather] == nil then
|
if player_data[playername] == nil or player_data[playername][weather] == nil then
|
||||||
climate_api.skybox.remove_layer(playername, weather)
|
climate_api.skybox.remove(playername, weather)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for playername, data in pairs(player_data) do
|
for playername, data in pairs(player_data) do
|
||||||
for weather, value in pairs(data) do
|
for weather, value in pairs(data) do
|
||||||
climate_api.skybox.add_layer(playername, weather, value)
|
climate_api.skybox.add(playername, weather, value)
|
||||||
end
|
end
|
||||||
climate_api.skybox.update_skybox(playername)
|
climate_api.skybox.update(playername)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function remove_effect(player_data)
|
local function remove_effect(player_data)
|
||||||
for playername, data in pairs(player_data) do
|
for playername, data in pairs(player_data) do
|
||||||
for weather, _ in pairs(data) do
|
for weather, _ in pairs(data) do
|
||||||
climate_api.skybox.remove_layer(playername, weather)
|
climate_api.skybox.remove(playername, weather)
|
||||||
end
|
end
|
||||||
|
climate_api.skybox.update(playername)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
|
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
|
||||||
climate_api.register_effect(EFFECT_NAME, remove_effect, "stop")
|
climate_api.register_effect(EFFECT_NAME, remove_effect, "stop")
|
||||||
climate_api.set_effect_cycle("climate_api:skybox", climate_api.MEDIUM_CYCLE)
|
|
@ -60,4 +60,3 @@ end
|
|||||||
climate_api.register_effect(EFFECT_NAME, start_effect, "start")
|
climate_api.register_effect(EFFECT_NAME, start_effect, "start")
|
||||||
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
|
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
|
||||||
climate_api.register_effect(EFFECT_NAME, stop_effect, "stop")
|
climate_api.register_effect(EFFECT_NAME, stop_effect, "stop")
|
||||||
climate_api.set_effect_cycle(EFFECT_NAME, climate_api.MEDIUM_CYCLE)
|
|
1
init.lua
1
init.lua
@ -62,6 +62,7 @@ climate_mod.state = dofile(modpath .. "/lib/datastorage.lua")
|
|||||||
climate_api = dofile(modpath .. "/lib/api.lua")
|
climate_api = dofile(modpath .. "/lib/api.lua")
|
||||||
climate_api.utility = dofile(modpath .. "/lib/api_utility.lua")
|
climate_api.utility = dofile(modpath .. "/lib/api_utility.lua")
|
||||||
climate_api.skybox = dofile(modpath .. "/lib/skybox_merger.lua")
|
climate_api.skybox = dofile(modpath .. "/lib/skybox_merger.lua")
|
||||||
|
climate_api.player_physics = dofile(modpath .. "/lib/player_physics.lua")
|
||||||
climate_api.environment = dofile(modpath .. "/lib/environment.lua")
|
climate_api.environment = dofile(modpath .. "/lib/environment.lua")
|
||||||
climate_mod.world = dofile(modpath .. "/lib/world.lua")
|
climate_mod.world = dofile(modpath .. "/lib/world.lua")
|
||||||
climate_mod.trigger = dofile(modpath .. "/lib/trigger.lua")
|
climate_mod.trigger = dofile(modpath .. "/lib/trigger.lua")
|
||||||
|
@ -3,9 +3,8 @@ local api = {}
|
|||||||
|
|
||||||
-- define various standard effect cycle lengths
|
-- define various standard effect cycle lengths
|
||||||
api.SHORT_CYCLE = 0 -- for particles and fast animations (use GSCYCLE)
|
api.SHORT_CYCLE = 0 -- for particles and fast animations (use GSCYCLE)
|
||||||
api.DEFAULT_CYCLE = 0.1 -- for most effect types
|
api.DEFAULT_CYCLE = 2.0 -- for most effect types
|
||||||
api.MEDIUM_CYCLE = 2.0 -- for ressource intensive tasks
|
api.LONG_CYCLE = 5.0 -- for ressource intensive tasks or timed effects
|
||||||
api.LONG_CYCLE = 5.0 -- for write operations and skybox changes
|
|
||||||
|
|
||||||
-- register new weather presets (like rain)
|
-- register new weather presets (like rain)
|
||||||
-- @param name <string> Unique preset name, ideally prefixed
|
-- @param name <string> Unique preset name, ideally prefixed
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
local mod_player_monoids = minetest.get_modpath("player_monoids") ~= nil
|
local mod_player_monoids = minetest.get_modpath("player_monoids") ~= nil
|
||||||
local mod_playerphysics = minetest.get_modpath("playerphysics") ~= nil
|
local mod_playerphysics = minetest.get_modpath("playerphysics") ~= nil
|
||||||
|
local mod_pova = minetest.get_modpath("pova") ~= nil
|
||||||
|
|
||||||
local utility = {}
|
local utility = {}
|
||||||
|
|
||||||
@ -33,31 +34,5 @@ function utility.normalized_cycle(value)
|
|||||||
return math.cos((2 * value + 1) * math.pi) / 2 + 0.5
|
return math.cos((2 * value + 1) * math.pi) / 2 + 0.5
|
||||||
end
|
end
|
||||||
|
|
||||||
-- override player physics
|
|
||||||
-- use utility mod if possible to avoid conflict
|
|
||||||
function utility.add_physics(id, player, effect, value)
|
|
||||||
if mod_player_monoids then
|
|
||||||
player_monoids[effect]:add_change(player, value, id)
|
|
||||||
elseif mod_playerphysics then
|
|
||||||
playerphysics.add_physics_factor(player, effect, id, value)
|
|
||||||
else
|
|
||||||
local override = {}
|
|
||||||
override[effect] = value
|
|
||||||
player:set_physics_override(override)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- reset player phsysics to normal
|
|
||||||
function utility.remove_physics(id, player, effect)
|
|
||||||
if mod_player_monoids then
|
|
||||||
player_monoids[effect]:del_change(player, id)
|
|
||||||
elseif mod_playerphysics then
|
|
||||||
playerphysics.remove_physics_factor(player, effect, id)
|
|
||||||
else
|
|
||||||
local override = {}
|
|
||||||
override[effect] = 1
|
|
||||||
player:set_physics_override(override)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return utility
|
return utility
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
local state = minetest.get_mod_storage()
|
local state = minetest.get_mod_storage()
|
||||||
|
|
||||||
if not state:contains("noise_timer") then
|
if not state:contains("heat_random") then
|
||||||
state:from_table({
|
state:from_table({
|
||||||
heat_random = 1,
|
heat_random = 1,
|
||||||
humidity_random = 1,
|
humidity_random = 1,
|
||||||
humidity_base = 50,
|
humidity_base = 50,
|
||||||
wind_x = 0.5,
|
wind_x = 0.5,
|
||||||
wind_z = 0.5,
|
wind_z = 0.5
|
||||||
noise_timer = 0
|
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
climate_api.register_influence("heat", function(pos)
|
climate_api.register_influence("heat",
|
||||||
return climate_api.environment.get_heat(pos)
|
climate_api.environment.get_heat
|
||||||
end)
|
)
|
||||||
|
|
||||||
climate_api.register_influence("base_heat", function(pos)
|
climate_api.register_influence("base_heat",
|
||||||
return minetest.get_heat(pos)
|
minetest.get_heat
|
||||||
end)
|
)
|
||||||
|
|
||||||
climate_api.register_influence("humidity", function(pos)
|
climate_api.register_influence("humidity",
|
||||||
return climate_api.environment.get_humidity(pos)
|
climate_api.environment.get_humidity
|
||||||
end)
|
)
|
||||||
|
|
||||||
climate_api.register_influence("base_humidity", function(pos)
|
climate_api.register_influence("base_humidity",
|
||||||
return minetest.get_humidity(pos)
|
minetest.get_humidity
|
||||||
end)
|
)
|
||||||
|
|
||||||
-- see https://en.wikipedia.org/wiki/Dew_point#Simple_approximation
|
-- see https://en.wikipedia.org/wiki/Dew_point#Simple_approximation
|
||||||
climate_api.register_influence("dewpoint", function(pos)
|
climate_api.register_influence("dewpoint", function(pos)
|
||||||
@ -58,6 +58,6 @@ climate_api.register_influence("daylight", function(pos)
|
|||||||
return minetest.env:get_node_light(pos, 0.5)
|
return minetest.env:get_node_light(pos, 0.5)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
climate_api.register_global_influence("time", function()
|
climate_api.register_global_influence("time",
|
||||||
return minetest.get_timeofday()
|
minetest.get_timeofday()
|
||||||
end)
|
)
|
@ -1,5 +1,5 @@
|
|||||||
local GSCYCLE = 0.03 * climate_mod.settings.tick_speed -- only process event loop after this time amount
|
local GSCYCLE = 0.03 * climate_mod.settings.tick_speed -- only process event loop after this amount of time
|
||||||
local WORLD_CYCLE = 15.00 * climate_mod.settings.tick_speed -- only update global environment influences after this time amount
|
local WORLD_CYCLE = 15.00 * climate_mod.settings.tick_speed -- only update global environment influences after this amount of time
|
||||||
|
|
||||||
local gs_timer = 0
|
local gs_timer = 0
|
||||||
local world_timer = 0
|
local world_timer = 0
|
||||||
@ -10,10 +10,8 @@ minetest.register_globalstep(function(dtime)
|
|||||||
if gs_timer + dtime < GSCYCLE then return else gs_timer = 0 end
|
if gs_timer + dtime < GSCYCLE then return else gs_timer = 0 end
|
||||||
|
|
||||||
if world_timer >= WORLD_CYCLE then
|
if world_timer >= WORLD_CYCLE then
|
||||||
local noise_timer = climate_mod.state:get_float("noise_timer") + world_timer
|
|
||||||
world_timer = 0
|
world_timer = 0
|
||||||
climate_mod.state:set_float("noise_timer", noise_timer)
|
climate_mod.world.update_status(minetest.get_gametime())
|
||||||
climate_mod.world.update_status(noise_timer)
|
|
||||||
climate_mod.global_environment = climate_mod.trigger.get_global_environment()
|
climate_mod.global_environment = climate_mod.trigger.get_global_environment()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
88
lib/player_physics.lua
Normal file
88
lib/player_physics.lua
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
local mod_player_monoids = minetest.get_modpath("player_monoids") ~= nil
|
||||||
|
local mod_playerphysics = minetest.get_modpath("playerphysics") ~= nil
|
||||||
|
local mod_pova = minetest.get_modpath("pova") ~= nil
|
||||||
|
|
||||||
|
local physics = {}
|
||||||
|
|
||||||
|
-- use player monoids if available
|
||||||
|
if mod_player_monoids then
|
||||||
|
function physics.add(id, player, effect, value)
|
||||||
|
player_monoids[effect]:add_change(player, value, id)
|
||||||
|
end
|
||||||
|
|
||||||
|
function physics.remove(id, player, effect)
|
||||||
|
player_monoids[effect]:del_change(player, id)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- fallback to playerphysics if available
|
||||||
|
elseif mod_playerphysics then
|
||||||
|
function physics.add(id, player, effect, value)
|
||||||
|
playerphysics.add_physics_factor(player, effect, id, value)
|
||||||
|
end
|
||||||
|
|
||||||
|
function physics.remove(id, player, effect)
|
||||||
|
playerphysics.remove_physics_factor(player, effect, id)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- fallback to pova if available
|
||||||
|
-- pova uses additive effect modifiers
|
||||||
|
-- this tries to simulate multiplication
|
||||||
|
-- by including the default value in modifier calculation
|
||||||
|
elseif mod_pova then
|
||||||
|
function physics.add(id, player, effect, value)
|
||||||
|
local playername = player:get_player_name()
|
||||||
|
local defaults = pova.get_override(playername, "default")
|
||||||
|
local default
|
||||||
|
if defaults == nil or defaults[effect] == nil then default = 1
|
||||||
|
else default = defaults[effect] end
|
||||||
|
local override = {}
|
||||||
|
override[effect] = (value * default) - default
|
||||||
|
pova.add_override(playername, id, override)
|
||||||
|
pova.do_override(playername)
|
||||||
|
end
|
||||||
|
|
||||||
|
function physics.remove(id, player, effect)
|
||||||
|
local playername = player:get_player_name()
|
||||||
|
pova.del_override(playername, id)
|
||||||
|
pova.do_override(playername)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- fallback to vanilla override as last resort
|
||||||
|
else
|
||||||
|
local physics = {}
|
||||||
|
local function apply_physics(player)
|
||||||
|
local playername = player:get_player_name()
|
||||||
|
local override = { speed = 1, jump = 1, gravity = 1 }
|
||||||
|
for effect, modifiers in pairs(physics[playername]) do
|
||||||
|
override[effect] = 1
|
||||||
|
for _, modifier in pairs(modifiers) do
|
||||||
|
override[effect] = override[effect] * modifier
|
||||||
|
end
|
||||||
|
end
|
||||||
|
player:set_physics_override(override)
|
||||||
|
end
|
||||||
|
|
||||||
|
function physics.add(id, player, effect, value)
|
||||||
|
local playername = player:get_player_name()
|
||||||
|
if physics[playername] == nil then physics[playername] = {} end
|
||||||
|
if physics[playername][effect] == nil then physics[playername][effect] = {} end
|
||||||
|
physics[playername][effect][id] = value
|
||||||
|
apply_physics(player)
|
||||||
|
end
|
||||||
|
|
||||||
|
function physics.remove(id, player, effect)
|
||||||
|
local playername = player:get_player_name()
|
||||||
|
if physics[playername] == nil then return end
|
||||||
|
if physics[playername][effect] == nil then return end
|
||||||
|
if physics[playername][effect][id] == nil then return end
|
||||||
|
physics[playername][effect][id] = nil
|
||||||
|
apply_physics(player)
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_on_leaveplayer(function(player)
|
||||||
|
local playername = player:get_player_name()
|
||||||
|
physics[playername] = nil
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return physics
|
@ -72,7 +72,7 @@ local function set_skybox(playername, sky)
|
|||||||
player:set_stars(sky.star_data)
|
player:set_stars(sky.star_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function skybox.update_skybox(playername)
|
function skybox.update(playername)
|
||||||
local p_layers = layers[playername]
|
local p_layers = layers[playername]
|
||||||
local sky = table.copy(default_sky)
|
local sky = table.copy(default_sky)
|
||||||
if p_layers == nil then p_layers = {} end
|
if p_layers == nil then p_layers = {} end
|
||||||
@ -91,12 +91,12 @@ function skybox.update_skybox(playername)
|
|||||||
set_skybox(playername, sky)
|
set_skybox(playername, sky)
|
||||||
end
|
end
|
||||||
|
|
||||||
function skybox.add_layer(playername, name, sky)
|
function skybox.add(playername, name, sky)
|
||||||
if layers[playername] == nil then layers[playername] = {} end
|
if layers[playername] == nil then layers[playername] = {} end
|
||||||
layers[playername][name] = sky
|
layers[playername][name] = sky
|
||||||
end
|
end
|
||||||
|
|
||||||
function skybox.remove_layer(playername, name)
|
function skybox.remove(playername, name)
|
||||||
if layers[playername] == nil or layers[playername][name] == nil then return end
|
if layers[playername] == nil or layers[playername][name] == nil then return end
|
||||||
layers[playername][name] = nil
|
layers[playername][name] = nil
|
||||||
end
|
end
|
||||||
|
2
mod.conf
2
mod.conf
@ -2,7 +2,7 @@ name = climate_api
|
|||||||
title = Climate API
|
title = Climate API
|
||||||
author = TestificateMods
|
author = TestificateMods
|
||||||
release = 2
|
release = 2
|
||||||
optional_depends = skylayer, player_monoids, playerphysics
|
optional_depends = player_monoids, playerphysics, pova
|
||||||
description = """
|
description = """
|
||||||
A powerful engine for weather presets and visual effects.
|
A powerful engine for weather presets and visual effects.
|
||||||
Use the regional climate to set up different effects for different regions.
|
Use the regional climate to set up different effects for different regions.
|
||||||
|
Loading…
Reference in New Issue
Block a user