forked from Mineclonia/Mineclonia
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