Add playerphysics framework

This commit is contained in:
Wuzzy 2018-05-07 19:40:30 +02:00
parent 7a208e3cd8
commit da03b6af6a
3 changed files with 124 additions and 0 deletions

@ -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