forked from VoxeLibre/VoxeLibre
Add playerphysics framework
This commit is contained in:
parent
7a208e3cd8
commit
da03b6af6a
|
@ -0,0 +1,80 @@
|
||||||
|
# Player Physics API.
|
||||||
|
|
||||||
|
This mod simplifies the setting of player physics (speed, jumping height, gravity).
|
||||||
|
|
||||||
|
The problem with `set_physics_override` is that is sets a raw value.
|
||||||
|
As soon as two independent mods want to mess with player physics, this is a problem.
|
||||||
|
|
||||||
|
This has a different approach in that you add and remove an arbitrary number of factors for each attribute.
|
||||||
|
The actual player attribute will be the product of all factors which have been added.
|
||||||
|
|
||||||
|
## Preconditions
|
||||||
|
There is only one precondition to using this mod, but it is important:
|
||||||
|
Mods *MUST NOT* call `set_physics_override` directly! Instead, to modify player physics, use this API.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
### `mcl_playerphysics.add_physics_factor(player, physic, id, value)`
|
||||||
|
Adds a factor for a player physic and updates the player physics immeiately.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
* `player`: Player object
|
||||||
|
* `physic`: Type of player physic to change. Any of the numeric values of `set_physics_override` (e.g. `speed`, `jump`, `gravity`)
|
||||||
|
* `id`: Unique identifier for this factor. Identifiers are stored on a per-player per-physics type basis
|
||||||
|
* `value`: The factor to add to the list of products
|
||||||
|
|
||||||
|
### `mcl_playerphysics.remove_physics_factor(player, physic, id)`
|
||||||
|
Removes the physics factor of the given ID and updates the player's physics.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
* `player`: Player object
|
||||||
|
* `physic`: Type of player physic to change. Any of the numeric values of `set_physics_override` (e.g. `speed`, `jump`, `gravity`)
|
||||||
|
* `id`: Unique identifier for the factor to remove
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
### Speed changes
|
||||||
|
Let's assume this mod is used by multiple different mods all trying to change the speed.
|
||||||
|
Here's what it could look like:
|
||||||
|
|
||||||
|
Potions mod:
|
||||||
|
```
|
||||||
|
mcl_playerphysics.add_physics_factor(player, "speed", "run_potion", 2)
|
||||||
|
```
|
||||||
|
|
||||||
|
Exhaustion mod:
|
||||||
|
```
|
||||||
|
mcl_playerphysics.add_physics_factor(player, "jump", "exhausted", 0.75)
|
||||||
|
```
|
||||||
|
|
||||||
|
Electrocution mod:
|
||||||
|
```
|
||||||
|
mcl_playerphysics.add_physics_factor(player, "jump", "shocked", 0.9)
|
||||||
|
```
|
||||||
|
|
||||||
|
When the 3 mods have done their change, the real player speed is simply the product of all factors, that is:
|
||||||
|
|
||||||
|
2 * 0.75 * 0.9 = 1.35
|
||||||
|
|
||||||
|
The final player speed is thus 135%.
|
||||||
|
|
||||||
|
### Speed changes, part 2
|
||||||
|
|
||||||
|
Let's take the example above.
|
||||||
|
Now if the Electrocution mod is done with shocking the player, it just needs to call:
|
||||||
|
|
||||||
|
```
|
||||||
|
mcl_playerphysics.remove_physics_factor(player, "jump", "shocked")
|
||||||
|
```
|
||||||
|
|
||||||
|
The effect is now gone, so the new player speed will be:
|
||||||
|
|
||||||
|
2 * 0.75 = 1.5
|
||||||
|
|
||||||
|
### Sleeping
|
||||||
|
To simulate sleeping by preventing all player movement, this can be done with this easy trick:
|
||||||
|
|
||||||
|
```
|
||||||
|
mcl_playerphysics.add_physics_factor(player, "speed", "sleeping", 0)
|
||||||
|
mcl_playerphysics.add_physics_factor(player, "jump", "sleeping", 0)
|
||||||
|
```
|
||||||
|
|
||||||
|
This works regardless of the other factors because mathematics tell us that the factor 0 forces the product to be 0.
|
|
@ -0,0 +1,43 @@
|
||||||
|
mcl_playerphysics = {}
|
||||||
|
|
||||||
|
local function calculate_physic_product(player, physic)
|
||||||
|
local a = minetest.deserialize(player:get_attribute("mcl_playerphysics:physics"))
|
||||||
|
local product = 1
|
||||||
|
if a == nil or a[physic] == nil then
|
||||||
|
return product
|
||||||
|
end
|
||||||
|
local factors = a[physic]
|
||||||
|
if type(factors) == "table" then
|
||||||
|
for id, factor in pairs(factors) do
|
||||||
|
product = product * factor
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return product
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_playerphysics.add_physics_factor(player, physic, id, value)
|
||||||
|
local a = minetest.deserialize(player:get_attribute("mcl_playerphysics:physics"))
|
||||||
|
if a == nil then
|
||||||
|
a = { [physic] = { [id] = value } }
|
||||||
|
elseif a[physic] == nil then
|
||||||
|
a[physic] = { [id] = value }
|
||||||
|
else
|
||||||
|
a[physic][id] = value
|
||||||
|
end
|
||||||
|
player:set_attribute("mcl_playerphysics:physics", minetest.serialize(a))
|
||||||
|
local raw_value = calculate_physic_product(player, physic)
|
||||||
|
player:set_physics_override({[physic] = raw_value})
|
||||||
|
end
|
||||||
|
|
||||||
|
function mcl_playerphysics.remove_physics_factor(player, physic, id)
|
||||||
|
local a = minetest.deserialize(player:get_attribute("mcl_playerphysics:physics"))
|
||||||
|
if a == nil or a[physic] == nil then
|
||||||
|
-- Nothing to remove
|
||||||
|
return
|
||||||
|
else
|
||||||
|
a[physic][id] = nil
|
||||||
|
end
|
||||||
|
player:set_attribute("mcl_playerphysics:physics", minetest.serialize(a))
|
||||||
|
local raw_value = calculate_physic_product(player, physic)
|
||||||
|
player:set_physics_override({[physic] = raw_value})
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
name=mcl_playerphysics
|
Loading…
Reference in New Issue