Repository files navigation

alt text

alt text

Watch Video Demo Here

Lua Physics for OpenMW

A deranged mod that implements a somewhat simple and naive physics engine in pure lua and exposes a rich interface for developers.

Think Half-Life 1 level of physics, maybe a bit better.

Apart from being mostly developer-centered API - this mod also enables physics all of the items in the game (things you can put in you inventory). You can drag them around, throw them and break bottles. But be warned - messing around with someone's property too much - will not be tolerated (if noticed, which depends on your sneak skill, proximity and sheer luck)

Credits

Sound Effects: Sound effects were recorded, scavenged from freesound.org or otherwise produced by NimSound and myself. Additionally a sound library "Lesser Vibes" by Sergey Eybog was used.

Separate thanks to taitechnic for exposing a series of convenient interface functions from OpenMW Impact Effects and helping with visual effects.

Installation


Install dependencies: OpenMW Impact Effects Highly recommended, but probably not required.


Use Mod Organiser 2 - if you downloaded mod archive manually (e.g from Git) - drag-n-drop it into the Mod Organiser 2

Or, if you want to install manually:

Extract contents into your Data Files


Enable LuaPhysicsEngine.omwscripts in the Launcher


How to use

Set up a key bind for dragging items around in settings->scripts->LuaPhysics. Drag items around by holding that key. While dragging - press attack key to throw. Hitting items with a weapon or fists will send them flying or even break some of them (some bottles).

Ranged attacks or spells currently DO NOT AFFECT physics objects, since there no OpenMW api exposed yet to manage those. Actors moving through stationary physics objects also will not affect them.

Developer API

Apart from playing around with physics items - primary purpose of this mod is to expose a set of methods that other developers can use to implement physics-based mods.

Every item in a game is physics-enabeld by default.

Local script of that object exposes the LuaPhysics interface

localI=require('openmw.interfaces')
localphysObject=I.LuaPhysics.physicsObject

physObject is a representation of a physics object which drives this gameObject. Through this instance you have access to all the physics object properties and functions. See PhysicsObject.lua for a full list. Most likely you would want to use the following methods:

physObject:applyImpulse(impulse, culprit)
-- Applies a vec3 impulse to an object instantly altering it's velocity. Culprit is a gameobject (NPC) responsible for this impulse application - culprit is used by the crime detections system. If necessary - it's probably safe to set it to nil.physObject:updateProperties(properties)
-- properties is a table of properties mathing property keys found on an instance of physObject (see physicsObject:new() in PhysicsObject.lua for a list of possible properties). It's HIGHLY recommended to use this method to update object's physical properties, instead of setting them directly on an instance. Properties you might be interested in are:weight: number, -- Initially weights is determined automatically, but can be overriden using this propertybounce: number-- 0 - 1: how bouncy is this object?---- Some properties of the physObject that you might want to read:physObject.velocity-- vec3 currently velocity of the physics objectphysObject.isSleeping-- if true - object is in a sleep state, its not being simulated, unless acted upon by a player or hit by another object, every object starts in a sleeping state

Same methods can be triggered by sending an openmw event to a gameObject on which PhysicsEngineLocal.lua is running, such as:

object:sendEvent("LuaPhysics_ApplyImpulse",{
impulse=impulse,
culprit=culprit
})
-- To trigger an applyImpulse method on an object (if such an object is a physics object)-- See eventHandlers of PhysicsEngineLocal.lua for a full list of events. As a general rule all events are names "LuaPhysics_EventName" 

If you want to remove a physicsObject from the world - it's paramount to use a special global event for that, instead of gameObject:remove() :

core.sendGlobalEvent("LuaPhysics_RemoveObject",{
object=gameObject
})

This will ensure that correct cleanup procedures are executed.

Additionally you might want to catch collision events. Every object, even non-physics ones - will receive collision events through the openmw event system. The regular way of catching such events applies:

eventHandlers= {
LuaPhysics_CollidingWithPhysObj=function(eData)
eData.other-- This is a serialised data of a physics object which triggered the collision, it's a read-only data, no changes to this data will affect the original physics objectend
}

More importantly a set of custom event exposed on a I.LuaPhysics.physicsObject, note that those are NOT a part of an OpenMW event system. They are only accessible from a local script throug the exposed inteface:

localphysObject=I.LuaPhysics.physicsObjectlocalfunctiononCollision(collisionData)
-- Following fields are available on collisionDatacollisionData.hitPoscollisionData.hitObjectcollisionData.hitNormalcollisionData.hitPhysObject--If collided with another physics object - this will be a serialised data of that other physics object, again - changing this serialised data will not affect another physics object in any wayendphysObject.onCollision:addEventHandler(onCollision)
physObject.onPhysObjectCollision:addEventHandler(onCollision)

You might also want to attach a handler to physObject.onIntersection - this event supposed to trigger in cases when physicsObject passes through another object without triggering a collision, such as an object spawned inside a collider of another object and passing through from withing onto the outside. That was the intent, but to my knowledge this event is never triggered and from-within passing through a collider is not even possible.

If you want to physics-enable other object types (e.g a Container type) - assign PhysicsEngineLocal.lua to that type via your .omwscripts mod file. Note that default config of the physics object works only with collider-less game objects (those objects don't have a grid around them when tcb console command is active). It is possible to use PhysicsEngineLocal.lua with collider objects, but that support is experimental and is slower than the default. To enable it - in a local script of such object set physObject.collisionMode = "aabb" (default is "sphere").

Destructible objects are also supported given one provides appropriate destroyed object chunk meshes - I currently don't feel like describing that system, so if you are interested in using it - look at PhysicsDestructibleGlobal.lua and meshes\debris folder. In short - if theres a collection of debri meshes matching specifi object's mesh name - then this object will be destructible. I.LuaPhysicsDestructibles.onPreFracture event emitter can be used to get notified and to control destructibility of specific objects (e.g to prevent an object from being destroying, even though it has debri meshes).

This is hopefully enough info to implement practically anything. Its totally possible that I've made a crytical typo here or there or forgot to mention something. In that case I can only suggest looking into the source files.

About

A neat pure-lua physics engine for OpenMW made by MaxYari - updated for Projectile Physics mod

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

alt text

alt text

Watch Video Demo Here

Lua Physics for OpenMW

A deranged mod that implements a somewhat simple and naive physics engine in pure lua and exposes a rich interface for developers.

Think Half-Life 1 level of physics, maybe a bit better.

Apart from being mostly developer-centered API - this mod also enables physics all of the items in the game (things you can put in you inventory). You can drag them around, throw them and break bottles. But be warned - messing around with someone's property too much - will not be tolerated (if noticed, which depends on your sneak skill, proximity and sheer luck)

Credits

Sound Effects: Sound effects were recorded, scavenged from freesound.org or otherwise produced by NimSound and myself. Additionally a sound library "Lesser Vibes" by Sergey Eybog was used.

Separate thanks to taitechnic for exposing a series of convenient interface functions from OpenMW Impact Effects and helping with visual effects.

Installation


Install dependencies: OpenMW Impact Effects Highly recommended, but probably not required.


Use Mod Organiser 2 - if you downloaded mod archive manually (e.g from Git) - drag-n-drop it into the Mod Organiser 2

Or, if you want to install manually:

Extract contents into your Data Files


Enable LuaPhysicsEngine.omwscripts in the Launcher


How to use

Set up a key bind for dragging items around in settings->scripts->LuaPhysics. Drag items around by holding that key. While dragging - press attack key to throw. Hitting items with a weapon or fists will send them flying or even break some of them (some bottles).

Ranged attacks or spells currently DO NOT AFFECT physics objects, since there no OpenMW api exposed yet to manage those. Actors moving through stationary physics objects also will not affect them.

Developer API

Apart from playing around with physics items - primary purpose of this mod is to expose a set of methods that other developers can use to implement physics-based mods.

Every item in a game is physics-enabeld by default.

Local script of that object exposes the LuaPhysics interface

localI=require('openmw.interfaces')
localphysObject=I.LuaPhysics.physicsObject

physObject is a representation of a physics object which drives this gameObject. Through this instance you have access to all the physics object properties and functions. See PhysicsObject.lua for a full list. Most likely you would want to use the following methods:

physObject:applyImpulse(impulse, culprit)
-- Applies a vec3 impulse to an object instantly altering it's velocity. Culprit is a gameobject (NPC) responsible for this impulse application - culprit is used by the crime detections system. If necessary - it's probably safe to set it to nil.physObject:updateProperties(properties)
-- properties is a table of properties mathing property keys found on an instance of physObject (see physicsObject:new() in PhysicsObject.lua for a list of possible properties). It's HIGHLY recommended to use this method to update object's physical properties, instead of setting them directly on an instance. Properties you might be interested in are:weight: number, -- Initially weights is determined automatically, but can be overriden using this propertybounce: number-- 0 - 1: how bouncy is this object?---- Some properties of the physObject that you might want to read:physObject.velocity-- vec3 currently velocity of the physics objectphysObject.isSleeping-- if true - object is in a sleep state, its not being simulated, unless acted upon by a player or hit by another object, every object starts in a sleeping state

Same methods can be triggered by sending an openmw event to a gameObject on which PhysicsEngineLocal.lua is running, such as:

object:sendEvent("LuaPhysics_ApplyImpulse",{
impulse=impulse,
culprit=culprit
})
-- To trigger an applyImpulse method on an object (if such an object is a physics object)-- See eventHandlers of PhysicsEngineLocal.lua for a full list of events. As a general rule all events are names "LuaPhysics_EventName" 

If you want to remove a physicsObject from the world - it's paramount to use a special global event for that, instead of gameObject:remove() :

core.sendGlobalEvent("LuaPhysics_RemoveObject",{
object=gameObject
})

This will ensure that correct cleanup procedures are executed.

Additionally you might want to catch collision events. Every object, even non-physics ones - will receive collision events through the openmw event system. The regular way of catching such events applies:

eventHandlers= {
LuaPhysics_CollidingWithPhysObj=function(eData)
eData.other-- This is a serialised data of a physics object which triggered the collision, it's a read-only data, no changes to this data will affect the original physics objectend
}

More importantly a set of custom event exposed on a I.LuaPhysics.physicsObject, note that those are NOT a part of an OpenMW event system. They are only accessible from a local script throug the exposed inteface:

localphysObject=I.LuaPhysics.physicsObjectlocalfunctiononCollision(collisionData)
-- Following fields are available on collisionDatacollisionData.hitPoscollisionData.hitObjectcollisionData.hitNormalcollisionData.hitPhysObject--If collided with another physics object - this will be a serialised data of that other physics object, again - changing this serialised data will not affect another physics object in any wayendphysObject.onCollision:addEventHandler(onCollision)
physObject.onPhysObjectCollision:addEventHandler(onCollision)

You might also want to attach a handler to physObject.onIntersection - this event supposed to trigger in cases when physicsObject passes through another object without triggering a collision, such as an object spawned inside a collider of another object and passing through from withing onto the outside. That was the intent, but to my knowledge this event is never triggered and from-within passing through a collider is not even possible.

If you want to physics-enable other object types (e.g a Container type) - assign PhysicsEngineLocal.lua to that type via your .omwscripts mod file. Note that default config of the physics object works only with collider-less game objects (those objects don't have a grid around them when tcb console command is active). It is possible to use PhysicsEngineLocal.lua with collider objects, but that support is experimental and is slower than the default. To enable it - in a local script of such object set physObject.collisionMode = "aabb" (default is "sphere").

Destructible objects are also supported given one provides appropriate destroyed object chunk meshes - I currently don't feel like describing that system, so if you are interested in using it - look at PhysicsDestructibleGlobal.lua and meshes\debris folder. In short - if theres a collection of debri meshes matching specifi object's mesh name - then this object will be destructible. I.LuaPhysicsDestructibles.onPreFracture event emitter can be used to get notified and to control destructibility of specific objects (e.g to prevent an object from being destroying, even though it has debri meshes).

This is hopefully enough info to implement practically anything. Its totally possible that I've made a crytical typo here or there or forgot to mention something. In that case I can only suggest looking into the source files.

About

A neat pure-lua physics engine for OpenMW made by MaxYari - updated for Projectile Physics mod

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

alt text

alt text

Watch Video Demo Here

Lua Physics for OpenMW

A deranged mod that implements a somewhat simple and naive physics engine in pure lua and exposes a rich interface for developers.

Think Half-Life 1 level of physics, maybe a bit better.

Apart from being mostly developer-centered API - this mod also enables physics all of the items in the game (things you can put in you inventory). You can drag them around, throw them and break bottles. But be warned - messing around with someone's property too much - will not be tolerated (if noticed, which depends on your sneak skill, proximity and sheer luck)

Credits

Sound Effects: Sound effects were recorded, scavenged from freesound.org or otherwise produced by NimSound and myself. Additionally a sound library "Lesser Vibes" by Sergey Eybog was used.

Separate thanks to taitechnic for exposing a series of convenient interface functions from OpenMW Impact Effects and helping with visual effects.

Installation


Install dependencies: OpenMW Impact Effects Highly recommended, but probably not required.


Use Mod Organiser 2 - if you downloaded mod archive manually (e.g from Git) - drag-n-drop it into the Mod Organiser 2

Or, if you want to install manually:

Extract contents into your Data Files


Enable LuaPhysicsEngine.omwscripts in the Launcher


How to use

Set up a key bind for dragging items around in settings->scripts->LuaPhysics. Drag items around by holding that key. While dragging - press attack key to throw. Hitting items with a weapon or fists will send them flying or even break some of them (some bottles).

Ranged attacks or spells currently DO NOT AFFECT physics objects, since there no OpenMW api exposed yet to manage those. Actors moving through stationary physics objects also will not affect them.

Developer API

Apart from playing around with physics items - primary purpose of this mod is to expose a set of methods that other developers can use to implement physics-based mods.

Every item in a game is physics-enabeld by default.

Local script of that object exposes the LuaPhysics interface

localI=require('openmw.interfaces')
localphysObject=I.LuaPhysics.physicsObject

physObject is a representation of a physics object which drives this gameObject. Through this instance you have access to all the physics object properties and functions. See PhysicsObject.lua for a full list. Most likely you would want to use the following methods:

physObject:applyImpulse(impulse, culprit)
-- Applies a vec3 impulse to an object instantly altering it's velocity. Culprit is a gameobject (NPC) responsible for this impulse application - culprit is used by the crime detections system. If necessary - it's probably safe to set it to nil.physObject:updateProperties(properties)
-- properties is a table of properties mathing property keys found on an instance of physObject (see physicsObject:new() in PhysicsObject.lua for a list of possible properties). It's HIGHLY recommended to use this method to update object's physical properties, instead of setting them directly on an instance. Properties you might be interested in are:weight: number, -- Initially weights is determined automatically, but can be overriden using this propertybounce: number-- 0 - 1: how bouncy is this object?---- Some properties of the physObject that you might want to read:physObject.velocity-- vec3 currently velocity of the physics objectphysObject.isSleeping-- if true - object is in a sleep state, its not being simulated, unless acted upon by a player or hit by another object, every object starts in a sleeping state

Same methods can be triggered by sending an openmw event to a gameObject on which PhysicsEngineLocal.lua is running, such as:

object:sendEvent("LuaPhysics_ApplyImpulse",{
impulse=impulse,
culprit=culprit
})
-- To trigger an applyImpulse method on an object (if such an object is a physics object)-- See eventHandlers of PhysicsEngineLocal.lua for a full list of events. As a general rule all events are names "LuaPhysics_EventName" 

If you want to remove a physicsObject from the world - it's paramount to use a special global event for that, instead of gameObject:remove() :

core.sendGlobalEvent("LuaPhysics_RemoveObject",{
object=gameObject
})

This will ensure that correct cleanup procedures are executed.

Additionally you might want to catch collision events. Every object, even non-physics ones - will receive collision events through the openmw event system. The regular way of catching such events applies:

eventHandlers= {
LuaPhysics_CollidingWithPhysObj=function(eData)
eData.other-- This is a serialised data of a physics object which triggered the collision, it's a read-only data, no changes to this data will affect the original physics objectend
}

More importantly a set of custom event exposed on a I.LuaPhysics.physicsObject, note that those are NOT a part of an OpenMW event system. They are only accessible from a local script throug the exposed inteface:

localphysObject=I.LuaPhysics.physicsObjectlocalfunctiononCollision(collisionData)
-- Following fields are available on collisionDatacollisionData.hitPoscollisionData.hitObjectcollisionData.hitNormalcollisionData.hitPhysObject--If collided with another physics object - this will be a serialised data of that other physics object, again - changing this serialised data will not affect another physics object in any wayendphysObject.onCollision:addEventHandler(onCollision)
physObject.onPhysObjectCollision:addEventHandler(onCollision)

You might also want to attach a handler to physObject.onIntersection - this event supposed to trigger in cases when physicsObject passes through another object without triggering a collision, such as an object spawned inside a collider of another object and passing through from withing onto the outside. That was the intent, but to my knowledge this event is never triggered and from-within passing through a collider is not even possible.

If you want to physics-enable other object types (e.g a Container type) - assign PhysicsEngineLocal.lua to that type via your .omwscripts mod file. Note that default config of the physics object works only with collider-less game objects (those objects don't have a grid around them when tcb console command is active). It is possible to use PhysicsEngineLocal.lua with collider objects, but that support is experimental and is slower than the default. To enable it - in a local script of such object set physObject.collisionMode = "aabb" (default is "sphere").

Destructible objects are also supported given one provides appropriate destroyed object chunk meshes - I currently don't feel like describing that system, so if you are interested in using it - look at PhysicsDestructibleGlobal.lua and meshes\debris folder. In short - if theres a collection of debri meshes matching specifi object's mesh name - then this object will be destructible. I.LuaPhysicsDestructibles.onPreFracture event emitter can be used to get notified and to control destructibility of specific objects (e.g to prevent an object from being destroying, even though it has debri meshes).

This is hopefully enough info to implement practically anything. Its totally possible that I've made a crytical typo here or there or forgot to mention something. In that case I can only suggest looking into the source files.

About

A neat pure-lua physics engine for OpenMW made by MaxYari - updated for Projectile Physics mod

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

alt text

alt text

Watch Video Demo Here

Lua Physics for OpenMW

A deranged mod that implements a somewhat simple and naive physics engine in pure lua and exposes a rich interface for developers.

Think Half-Life 1 level of physics, maybe a bit better.

Apart from being mostly developer-centered API - this mod also enables physics all of the items in the game (things you can put in you inventory). You can drag them around, throw them and break bottles. But be warned - messing around with someone's property too much - will not be tolerated (if noticed, which depends on your sneak skill, proximity and sheer luck)

Credits

Sound Effects: Sound effects were recorded, scavenged from freesound.org or otherwise produced by NimSound and myself. Additionally a sound library "Lesser Vibes" by Sergey Eybog was used.

Separate thanks to taitechnic for exposing a series of convenient interface functions from OpenMW Impact Effects and helping with visual effects.

Installation


Install dependencies: OpenMW Impact Effects Highly recommended, but probably not required.


Use Mod Organiser 2 - if you downloaded mod archive manually (e.g from Git) - drag-n-drop it into the Mod Organiser 2

Or, if you want to install manually:

Extract contents into your Data Files


Enable LuaPhysicsEngine.omwscripts in the Launcher


How to use

Set up a key bind for dragging items around in settings->scripts->LuaPhysics. Drag items around by holding that key. While dragging - press attack key to throw. Hitting items with a weapon or fists will send them flying or even break some of them (some bottles).

Ranged attacks or spells currently DO NOT AFFECT physics objects, since there no OpenMW api exposed yet to manage those. Actors moving through stationary physics objects also will not affect them.

Developer API

Apart from playing around with physics items - primary purpose of this mod is to expose a set of methods that other developers can use to implement physics-based mods.

Every item in a game is physics-enabeld by default.

Local script of that object exposes the LuaPhysics interface

localI=require('openmw.interfaces')
localphysObject=I.LuaPhysics.physicsObject

physObject is a representation of a physics object which drives this gameObject. Through this instance you have access to all the physics object properties and functions. See PhysicsObject.lua for a full list. Most likely you would want to use the following methods:

physObject:applyImpulse(impulse, culprit)
-- Applies a vec3 impulse to an object instantly altering it's velocity. Culprit is a gameobject (NPC) responsible for this impulse application - culprit is used by the crime detections system. If necessary - it's probably safe to set it to nil.physObject:updateProperties(properties)
-- properties is a table of properties mathing property keys found on an instance of physObject (see physicsObject:new() in PhysicsObject.lua for a list of possible properties). It's HIGHLY recommended to use this method to update object's physical properties, instead of setting them directly on an instance. Properties you might be interested in are:weight: number, -- Initially weights is determined automatically, but can be overriden using this propertybounce: number-- 0 - 1: how bouncy is this object?---- Some properties of the physObject that you might want to read:physObject.velocity-- vec3 currently velocity of the physics objectphysObject.isSleeping-- if true - object is in a sleep state, its not being simulated, unless acted upon by a player or hit by another object, every object starts in a sleeping state

Same methods can be triggered by sending an openmw event to a gameObject on which PhysicsEngineLocal.lua is running, such as:

object:sendEvent("LuaPhysics_ApplyImpulse",{
impulse=impulse,
culprit=culprit
})
-- To trigger an applyImpulse method on an object (if such an object is a physics object)-- See eventHandlers of PhysicsEngineLocal.lua for a full list of events. As a general rule all events are names "LuaPhysics_EventName" 

If you want to remove a physicsObject from the world - it's paramount to use a special global event for that, instead of gameObject:remove() :

core.sendGlobalEvent("LuaPhysics_RemoveObject",{
object=gameObject
})

This will ensure that correct cleanup procedures are executed.

Additionally you might want to catch collision events. Every object, even non-physics ones - will receive collision events through the openmw event system. The regular way of catching such events applies:

eventHandlers= {
LuaPhysics_CollidingWithPhysObj=function(eData)
eData.other-- This is a serialised data of a physics object which triggered the collision, it's a read-only data, no changes to this data will affect the original physics objectend
}

More importantly a set of custom event exposed on a I.LuaPhysics.physicsObject, note that those are NOT a part of an OpenMW event system. They are only accessible from a local script throug the exposed inteface:

localphysObject=I.LuaPhysics.physicsObjectlocalfunctiononCollision(collisionData)
-- Following fields are available on collisionDatacollisionData.hitPoscollisionData.hitObjectcollisionData.hitNormalcollisionData.hitPhysObject--If collided with another physics object - this will be a serialised data of that other physics object, again - changing this serialised data will not affect another physics object in any wayendphysObject.onCollision:addEventHandler(onCollision)
physObject.onPhysObjectCollision:addEventHandler(onCollision)

You might also want to attach a handler to physObject.onIntersection - this event supposed to trigger in cases when physicsObject passes through another object without triggering a collision, such as an object spawned inside a collider of another object and passing through from withing onto the outside. That was the intent, but to my knowledge this event is never triggered and from-within passing through a collider is not even possible.

If you want to physics-enable other object types (e.g a Container type) - assign PhysicsEngineLocal.lua to that type via your .omwscripts mod file. Note that default config of the physics object works only with collider-less game objects (those objects don't have a grid around them when tcb console command is active). It is possible to use PhysicsEngineLocal.lua with collider objects, but that support is experimental and is slower than the default. To enable it - in a local script of such object set physObject.collisionMode = "aabb" (default is "sphere").

Destructible objects are also supported given one provides appropriate destroyed object chunk meshes - I currently don't feel like describing that system, so if you are interested in using it - look at PhysicsDestructibleGlobal.lua and meshes\debris folder. In short - if theres a collection of debri meshes matching specifi object's mesh name - then this object will be destructible. I.LuaPhysicsDestructibles.onPreFracture event emitter can be used to get notified and to control destructibility of specific objects (e.g to prevent an object from being destroying, even though it has debri meshes).

This is hopefully enough info to implement practically anything. Its totally possible that I've made a crytical typo here or there or forgot to mention something. In that case I can only suggest looking into the source files.

About

A neat pure-lua physics engine for OpenMW made by MaxYari - updated for Projectile Physics mod

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

alt text

alt text

Watch Video Demo Here

Lua Physics for OpenMW

A deranged mod that implements a somewhat simple and naive physics engine in pure lua and exposes a rich interface for developers.

Think Half-Life 1 level of physics, maybe a bit better.

Apart from being mostly developer-centered API - this mod also enables physics all of the items in the game (things you can put in you inventory). You can drag them around, throw them and break bottles. But be warned - messing around with someone's property too much - will not be tolerated (if noticed, which depends on your sneak skill, proximity and sheer luck)

Credits

Sound Effects: Sound effects were recorded, scavenged from freesound.org or otherwise produced by NimSound and myself. Additionally a sound library "Lesser Vibes" by Sergey Eybog was used.

Separate thanks to taitechnic for exposing a series of convenient interface functions from OpenMW Impact Effects and helping with visual effects.

Installation


Install dependencies: OpenMW Impact Effects Highly recommended, but probably not required.


Use Mod Organiser 2 - if you downloaded mod archive manually (e.g from Git) - drag-n-drop it into the Mod Organiser 2

Or, if you want to install manually:

Extract contents into your Data Files


Enable LuaPhysicsEngine.omwscripts in the Launcher


How to use

Set up a key bind for dragging items around in settings->scripts->LuaPhysics. Drag items around by holding that key. While dragging - press attack key to throw. Hitting items with a weapon or fists will send them flying or even break some of them (some bottles).

Ranged attacks or spells currently DO NOT AFFECT physics objects, since there no OpenMW api exposed yet to manage those. Actors moving through stationary physics objects also will not affect them.

Developer API

Apart from playing around with physics items - primary purpose of this mod is to expose a set of methods that other developers can use to implement physics-based mods.

Every item in a game is physics-enabeld by default.

Local script of that object exposes the LuaPhysics interface

localI=require('openmw.interfaces')
localphysObject=I.LuaPhysics.physicsObject

physObject is a representation of a physics object which drives this gameObject. Through this instance you have access to all the physics object properties and functions. See PhysicsObject.lua for a full list. Most likely you would want to use the following methods:

physObject:applyImpulse(impulse, culprit)
-- Applies a vec3 impulse to an object instantly altering it's velocity. Culprit is a gameobject (NPC) responsible for this impulse application - culprit is used by the crime detections system. If necessary - it's probably safe to set it to nil.physObject:updateProperties(properties)
-- properties is a table of properties mathing property keys found on an instance of physObject (see physicsObject:new() in PhysicsObject.lua for a list of possible properties). It's HIGHLY recommended to use this method to update object's physical properties, instead of setting them directly on an instance. Properties you might be interested in are:weight: number, -- Initially weights is determined automatically, but can be overriden using this propertybounce: number-- 0 - 1: how bouncy is this object?---- Some properties of the physObject that you might want to read:physObject.velocity-- vec3 currently velocity of the physics objectphysObject.isSleeping-- if true - object is in a sleep state, its not being simulated, unless acted upon by a player or hit by another object, every object starts in a sleeping state

Same methods can be triggered by sending an openmw event to a gameObject on which PhysicsEngineLocal.lua is running, such as:

object:sendEvent("LuaPhysics_ApplyImpulse",{
impulse=impulse,
culprit=culprit
})
-- To trigger an applyImpulse method on an object (if such an object is a physics object)-- See eventHandlers of PhysicsEngineLocal.lua for a full list of events. As a general rule all events are names "LuaPhysics_EventName" 

If you want to remove a physicsObject from the world - it's paramount to use a special global event for that, instead of gameObject:remove() :

core.sendGlobalEvent("LuaPhysics_RemoveObject",{
object=gameObject
})

This will ensure that correct cleanup procedures are executed.

Additionally you might want to catch collision events. Every object, even non-physics ones - will receive collision events through the openmw event system. The regular way of catching such events applies:

eventHandlers= {
LuaPhysics_CollidingWithPhysObj=function(eData)
eData.other-- This is a serialised data of a physics object which triggered the collision, it's a read-only data, no changes to this data will affect the original physics objectend
}

More importantly a set of custom event exposed on a I.LuaPhysics.physicsObject, note that those are NOT a part of an OpenMW event system. They are only accessible from a local script throug the exposed inteface:

localphysObject=I.LuaPhysics.physicsObjectlocalfunctiononCollision(collisionData)
-- Following fields are available on collisionDatacollisionData.hitPoscollisionData.hitObjectcollisionData.hitNormalcollisionData.hitPhysObject--If collided with another physics object - this will be a serialised data of that other physics object, again - changing this serialised data will not affect another physics object in any wayendphysObject.onCollision:addEventHandler(onCollision)
physObject.onPhysObjectCollision:addEventHandler(onCollision)

You might also want to attach a handler to physObject.onIntersection - this event supposed to trigger in cases when physicsObject passes through another object without triggering a collision, such as an object spawned inside a collider of another object and passing through from withing onto the outside. That was the intent, but to my knowledge this event is never triggered and from-within passing through a collider is not even possible.

If you want to physics-enable other object types (e.g a Container type) - assign PhysicsEngineLocal.lua to that type via your .omwscripts mod file. Note that default config of the physics object works only with collider-less game objects (those objects don't have a grid around them when tcb console command is active). It is possible to use PhysicsEngineLocal.lua with collider objects, but that support is experimental and is slower than the default. To enable it - in a local script of such object set physObject.collisionMode = "aabb" (default is "sphere").

Destructible objects are also supported given one provides appropriate destroyed object chunk meshes - I currently don't feel like describing that system, so if you are interested in using it - look at PhysicsDestructibleGlobal.lua and meshes\debris folder. In short - if theres a collection of debri meshes matching specifi object's mesh name - then this object will be destructible. I.LuaPhysicsDestructibles.onPreFracture event emitter can be used to get notified and to control destructibility of specific objects (e.g to prevent an object from being destroying, even though it has debri meshes).

This is hopefully enough info to implement practically anything. Its totally possible that I've made a crytical typo here or there or forgot to mention something. In that case I can only suggest looking into the source files.

About

A neat pure-lua physics engine for OpenMW made by MaxYari - updated for Projectile Physics mod

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

alt text

alt text

Watch Video Demo Here

Lua Physics for OpenMW

A deranged mod that implements a somewhat simple and naive physics engine in pure lua and exposes a rich interface for developers.

Think Half-Life 1 level of physics, maybe a bit better.

Apart from being mostly developer-centered API - this mod also enables physics all of the items in the game (things you can put in you inventory). You can drag them around, throw them and break bottles. But be warned - messing around with someone's property too much - will not be tolerated (if noticed, which depends on your sneak skill, proximity and sheer luck)

Credits

Sound Effects: Sound effects were recorded, scavenged from freesound.org or otherwise produced by NimSound and myself. Additionally a sound library "Lesser Vibes" by Sergey Eybog was used.

Separate thanks to taitechnic for exposing a series of convenient interface functions from OpenMW Impact Effects and helping with visual effects.

Installation


Install dependencies: OpenMW Impact Effects Highly recommended, but probably not required.


Use Mod Organiser 2 - if you downloaded mod archive manually (e.g from Git) - drag-n-drop it into the Mod Organiser 2

Or, if you want to install manually:

Extract contents into your Data Files


Enable LuaPhysicsEngine.omwscripts in the Launcher


How to use

Set up a key bind for dragging items around in settings->scripts->LuaPhysics. Drag items around by holding that key. While dragging - press attack key to throw. Hitting items with a weapon or fists will send them flying or even break some of them (some bottles).

Ranged attacks or spells currently DO NOT AFFECT physics objects, since there no OpenMW api exposed yet to manage those. Actors moving through stationary physics objects also will not affect them.

Developer API

Apart from playing around with physics items - primary purpose of this mod is to expose a set of methods that other developers can use to implement physics-based mods.

Every item in a game is physics-enabeld by default.

Local script of that object exposes the LuaPhysics interface

localI=require('openmw.interfaces')
localphysObject=I.LuaPhysics.physicsObject

physObject is a representation of a physics object which drives this gameObject. Through this instance you have access to all the physics object properties and functions. See PhysicsObject.lua for a full list. Most likely you would want to use the following methods:

physObject:applyImpulse(impulse, culprit)
-- Applies a vec3 impulse to an object instantly altering it's velocity. Culprit is a gameobject (NPC) responsible for this impulse application - culprit is used by the crime detections system. If necessary - it's probably safe to set it to nil.physObject:updateProperties(properties)
-- properties is a table of properties mathing property keys found on an instance of physObject (see physicsObject:new() in PhysicsObject.lua for a list of possible properties). It's HIGHLY recommended to use this method to update object's physical properties, instead of setting them directly on an instance. Properties you might be interested in are:weight: number, -- Initially weights is determined automatically, but can be overriden using this propertybounce: number-- 0 - 1: how bouncy is this object?---- Some properties of the physObject that you might want to read:physObject.velocity-- vec3 currently velocity of the physics objectphysObject.isSleeping-- if true - object is in a sleep state, its not being simulated, unless acted upon by a player or hit by another object, every object starts in a sleeping state

Same methods can be triggered by sending an openmw event to a gameObject on which PhysicsEngineLocal.lua is running, such as:

object:sendEvent("LuaPhysics_ApplyImpulse",{
impulse=impulse,
culprit=culprit
})
-- To trigger an applyImpulse method on an object (if such an object is a physics object)-- See eventHandlers of PhysicsEngineLocal.lua for a full list of events. As a general rule all events are names "LuaPhysics_EventName" 

If you want to remove a physicsObject from the world - it's paramount to use a special global event for that, instead of gameObject:remove() :

core.sendGlobalEvent("LuaPhysics_RemoveObject",{
object=gameObject
})

This will ensure that correct cleanup procedures are executed.

Additionally you might want to catch collision events. Every object, even non-physics ones - will receive collision events through the openmw event system. The regular way of catching such events applies:

eventHandlers= {
LuaPhysics_CollidingWithPhysObj=function(eData)
eData.other-- This is a serialised data of a physics object which triggered the collision, it's a read-only data, no changes to this data will affect the original physics objectend
}

More importantly a set of custom event exposed on a I.LuaPhysics.physicsObject, note that those are NOT a part of an OpenMW event system. They are only accessible from a local script throug the exposed inteface:

localphysObject=I.LuaPhysics.physicsObjectlocalfunctiononCollision(collisionData)
-- Following fields are available on collisionDatacollisionData.hitPoscollisionData.hitObjectcollisionData.hitNormalcollisionData.hitPhysObject--If collided with another physics object - this will be a serialised data of that other physics object, again - changing this serialised data will not affect another physics object in any wayendphysObject.onCollision:addEventHandler(onCollision)
physObject.onPhysObjectCollision:addEventHandler(onCollision)

You might also want to attach a handler to physObject.onIntersection - this event supposed to trigger in cases when physicsObject passes through another object without triggering a collision, such as an object spawned inside a collider of another object and passing through from withing onto the outside. That was the intent, but to my knowledge this event is never triggered and from-within passing through a collider is not even possible.

If you want to physics-enable other object types (e.g a Container type) - assign PhysicsEngineLocal.lua to that type via your .omwscripts mod file. Note that default config of the physics object works only with collider-less game objects (those objects don't have a grid around them when tcb console command is active). It is possible to use PhysicsEngineLocal.lua with collider objects, but that support is experimental and is slower than the default. To enable it - in a local script of such object set physObject.collisionMode = "aabb" (default is "sphere").

Destructible objects are also supported given one provides appropriate destroyed object chunk meshes - I currently don't feel like describing that system, so if you are interested in using it - look at PhysicsDestructibleGlobal.lua and meshes\debris folder. In short - if theres a collection of debri meshes matching specifi object's mesh name - then this object will be destructible. I.LuaPhysicsDestructibles.onPreFracture event emitter can be used to get notified and to control destructibility of specific objects (e.g to prevent an object from being destroying, even though it has debri meshes).

This is hopefully enough info to implement practically anything. Its totally possible that I've made a crytical typo here or there or forgot to mention something. In that case I can only suggest looking into the source files.

About

A neat pure-lua physics engine for OpenMW made by MaxYari - updated for Projectile Physics mod

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

alt text

alt text

Watch Video Demo Here

Lua Physics for OpenMW

A deranged mod that implements a somewhat simple and naive physics engine in pure lua and exposes a rich interface for developers.

Think Half-Life 1 level of physics, maybe a bit better.

Apart from being mostly developer-centered API - this mod also enables physics all of the items in the game (things you can put in you inventory). You can drag them around, throw them and break bottles. But be warned - messing around with someone's property too much - will not be tolerated (if noticed, which depends on your sneak skill, proximity and sheer luck)

Credits

Sound Effects: Sound effects were recorded, scavenged from freesound.org or otherwise produced by NimSound and myself. Additionally a sound library "Lesser Vibes" by Sergey Eybog was used.

Separate thanks to taitechnic for exposing a series of convenient interface functions from OpenMW Impact Effects and helping with visual effects.

Installation


Install dependencies: OpenMW Impact Effects Highly recommended, but probably not required.


Use Mod Organiser 2 - if you downloaded mod archive manually (e.g from Git) - drag-n-drop it into the Mod Organiser 2

Or, if you want to install manually:

Extract contents into your Data Files


Enable LuaPhysicsEngine.omwscripts in the Launcher


How to use

Set up a key bind for dragging items around in settings->scripts->LuaPhysics. Drag items around by holding that key. While dragging - press attack key to throw. Hitting items with a weapon or fists will send them flying or even break some of them (some bottles).

Ranged attacks or spells currently DO NOT AFFECT physics objects, since there no OpenMW api exposed yet to manage those. Actors moving through stationary physics objects also will not affect them.

Developer API

Apart from playing around with physics items - primary purpose of this mod is to expose a set of methods that other developers can use to implement physics-based mods.

Every item in a game is physics-enabeld by default.

Local script of that object exposes the LuaPhysics interface

localI=require('openmw.interfaces')
localphysObject=I.LuaPhysics.physicsObject

physObject is a representation of a physics object which drives this gameObject. Through this instance you have access to all the physics object properties and functions. See PhysicsObject.lua for a full list. Most likely you would want to use the following methods:

physObject:applyImpulse(impulse, culprit)
-- Applies a vec3 impulse to an object instantly altering it's velocity. Culprit is a gameobject (NPC) responsible for this impulse application - culprit is used by the crime detections system. If necessary - it's probably safe to set it to nil.physObject:updateProperties(properties)
-- properties is a table of properties mathing property keys found on an instance of physObject (see physicsObject:new() in PhysicsObject.lua for a list of possible properties). It's HIGHLY recommended to use this method to update object's physical properties, instead of setting them directly on an instance. Properties you might be interested in are:weight: number, -- Initially weights is determined automatically, but can be overriden using this propertybounce: number-- 0 - 1: how bouncy is this object?---- Some properties of the physObject that you might want to read:physObject.velocity-- vec3 currently velocity of the physics objectphysObject.isSleeping-- if true - object is in a sleep state, its not being simulated, unless acted upon by a player or hit by another object, every object starts in a sleeping state

Same methods can be triggered by sending an openmw event to a gameObject on which PhysicsEngineLocal.lua is running, such as:

object:sendEvent("LuaPhysics_ApplyImpulse",{
impulse=impulse,
culprit=culprit
})
-- To trigger an applyImpulse method on an object (if such an object is a physics object)-- See eventHandlers of PhysicsEngineLocal.lua for a full list of events. As a general rule all events are names "LuaPhysics_EventName" 

If you want to remove a physicsObject from the world - it's paramount to use a special global event for that, instead of gameObject:remove() :

core.sendGlobalEvent("LuaPhysics_RemoveObject",{
object=gameObject
})

This will ensure that correct cleanup procedures are executed.

Additionally you might want to catch collision events. Every object, even non-physics ones - will receive collision events through the openmw event system. The regular way of catching such events applies:

eventHandlers= {
LuaPhysics_CollidingWithPhysObj=function(eData)
eData.other-- This is a serialised data of a physics object which triggered the collision, it's a read-only data, no changes to this data will affect the original physics objectend
}

More importantly a set of custom event exposed on a I.LuaPhysics.physicsObject, note that those are NOT a part of an OpenMW event system. They are only accessible from a local script throug the exposed inteface:

localphysObject=I.LuaPhysics.physicsObjectlocalfunctiononCollision(collisionData)
-- Following fields are available on collisionDatacollisionData.hitPoscollisionData.hitObjectcollisionData.hitNormalcollisionData.hitPhysObject--If collided with another physics object - this will be a serialised data of that other physics object, again - changing this serialised data will not affect another physics object in any wayendphysObject.onCollision:addEventHandler(onCollision)
physObject.onPhysObjectCollision:addEventHandler(onCollision)

You might also want to attach a handler to physObject.onIntersection - this event supposed to trigger in cases when physicsObject passes through another object without triggering a collision, such as an object spawned inside a collider of another object and passing through from withing onto the outside. That was the intent, but to my knowledge this event is never triggered and from-within passing through a collider is not even possible.

If you want to physics-enable other object types (e.g a Container type) - assign PhysicsEngineLocal.lua to that type via your .omwscripts mod file. Note that default config of the physics object works only with collider-less game objects (those objects don't have a grid around them when tcb console command is active). It is possible to use PhysicsEngineLocal.lua with collider objects, but that support is experimental and is slower than the default. To enable it - in a local script of such object set physObject.collisionMode = "aabb" (default is "sphere").

Destructible objects are also supported given one provides appropriate destroyed object chunk meshes - I currently don't feel like describing that system, so if you are interested in using it - look at PhysicsDestructibleGlobal.lua and meshes\debris folder. In short - if theres a collection of debri meshes matching specifi object's mesh name - then this object will be destructible. I.LuaPhysicsDestructibles.onPreFracture event emitter can be used to get notified and to control destructibility of specific objects (e.g to prevent an object from being destroying, even though it has debri meshes).

This is hopefully enough info to implement practically anything. Its totally possible that I've made a crytical typo here or there or forgot to mention something. In that case I can only suggest looking into the source files.

About

A neat pure-lua physics engine for OpenMW made by MaxYari - updated for Projectile Physics mod

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

alt text

alt text

Watch Video Demo Here

Lua Physics for OpenMW

A deranged mod that implements a somewhat simple and naive physics engine in pure lua and exposes a rich interface for developers.

Think Half-Life 1 level of physics, maybe a bit better.

Apart from being mostly developer-centered API - this mod also enables physics all of the items in the game (things you can put in you inventory). You can drag them around, throw them and break bottles. But be warned - messing around with someone's property too much - will not be tolerated (if noticed, which depends on your sneak skill, proximity and sheer luck)

Credits

Sound Effects: Sound effects were recorded, scavenged from freesound.org or otherwise produced by NimSound and myself. Additionally a sound library "Lesser Vibes" by Sergey Eybog was used.

Separate thanks to taitechnic for exposing a series of convenient interface functions from OpenMW Impact Effects and helping with visual effects.

Installation


Install dependencies: OpenMW Impact Effects Highly recommended, but probably not required.


Use Mod Organiser 2 - if you downloaded mod archive manually (e.g from Git) - drag-n-drop it into the Mod Organiser 2

Or, if you want to install manually:

Extract contents into your Data Files


Enable LuaPhysicsEngine.omwscripts in the Launcher


How to use

Set up a key bind for dragging items around in settings->scripts->LuaPhysics. Drag items around by holding that key. While dragging - press attack key to throw. Hitting items with a weapon or fists will send them flying or even break some of them (some bottles).

Ranged attacks or spells currently DO NOT AFFECT physics objects, since there no OpenMW api exposed yet to manage those. Actors moving through stationary physics objects also will not affect them.

Developer API

Apart from playing around with physics items - primary purpose of this mod is to expose a set of methods that other developers can use to implement physics-based mods.

Every item in a game is physics-enabeld by default.

Local script of that object exposes the LuaPhysics interface

localI=require('openmw.interfaces')
localphysObject=I.LuaPhysics.physicsObject

physObject is a representation of a physics object which drives this gameObject. Through this instance you have access to all the physics object properties and functions. See PhysicsObject.lua for a full list. Most likely you would want to use the following methods:

physObject:applyImpulse(impulse, culprit)
-- Applies a vec3 impulse to an object instantly altering it's velocity. Culprit is a gameobject (NPC) responsible for this impulse application - culprit is used by the crime detections system. If necessary - it's probably safe to set it to nil.physObject:updateProperties(properties)
-- properties is a table of properties mathing property keys found on an instance of physObject (see physicsObject:new() in PhysicsObject.lua for a list of possible properties). It's HIGHLY recommended to use this method to update object's physical properties, instead of setting them directly on an instance. Properties you might be interested in are:weight: number, -- Initially weights is determined automatically, but can be overriden using this propertybounce: number-- 0 - 1: how bouncy is this object?---- Some properties of the physObject that you might want to read:physObject.velocity-- vec3 currently velocity of the physics objectphysObject.isSleeping-- if true - object is in a sleep state, its not being simulated, unless acted upon by a player or hit by another object, every object starts in a sleeping state

Same methods can be triggered by sending an openmw event to a gameObject on which PhysicsEngineLocal.lua is running, such as:

object:sendEvent("LuaPhysics_ApplyImpulse",{
impulse=impulse,
culprit=culprit
})
-- To trigger an applyImpulse method on an object (if such an object is a physics object)-- See eventHandlers of PhysicsEngineLocal.lua for a full list of events. As a general rule all events are names "LuaPhysics_EventName" 

If you want to remove a physicsObject from the world - it's paramount to use a special global event for that, instead of gameObject:remove() :

core.sendGlobalEvent("LuaPhysics_RemoveObject",{
object=gameObject
})

This will ensure that correct cleanup procedures are executed.

Additionally you might want to catch collision events. Every object, even non-physics ones - will receive collision events through the openmw event system. The regular way of catching such events applies:

eventHandlers= {
LuaPhysics_CollidingWithPhysObj=function(eData)
eData.other-- This is a serialised data of a physics object which triggered the collision, it's a read-only data, no changes to this data will affect the original physics objectend
}

More importantly a set of custom event exposed on a I.LuaPhysics.physicsObject, note that those are NOT a part of an OpenMW event system. They are only accessible from a local script throug the exposed inteface:

localphysObject=I.LuaPhysics.physicsObjectlocalfunctiononCollision(collisionData)
-- Following fields are available on collisionDatacollisionData.hitPoscollisionData.hitObjectcollisionData.hitNormalcollisionData.hitPhysObject--If collided with another physics object - this will be a serialised data of that other physics object, again - changing this serialised data will not affect another physics object in any wayendphysObject.onCollision:addEventHandler(onCollision)
physObject.onPhysObjectCollision:addEventHandler(onCollision)

You might also want to attach a handler to physObject.onIntersection - this event supposed to trigger in cases when physicsObject passes through another object without triggering a collision, such as an object spawned inside a collider of another object and passing through from withing onto the outside. That was the intent, but to my knowledge this event is never triggered and from-within passing through a collider is not even possible.

If you want to physics-enable other object types (e.g a Container type) - assign PhysicsEngineLocal.lua to that type via your .omwscripts mod file. Note that default config of the physics object works only with collider-less game objects (those objects don't have a grid around them when tcb console command is active). It is possible to use PhysicsEngineLocal.lua with collider objects, but that support is experimental and is slower than the default. To enable it - in a local script of such object set physObject.collisionMode = "aabb" (default is "sphere").

Destructible objects are also supported given one provides appropriate destroyed object chunk meshes - I currently don't feel like describing that system, so if you are interested in using it - look at PhysicsDestructibleGlobal.lua and meshes\debris folder. In short - if theres a collection of debri meshes matching specifi object's mesh name - then this object will be destructible. I.LuaPhysicsDestructibles.onPreFracture event emitter can be used to get notified and to control destructibility of specific objects (e.g to prevent an object from being destroying, even though it has debri meshes).

This is hopefully enough info to implement practically anything. Its totally possible that I've made a crytical typo here or there or forgot to mention something. In that case I can only suggest looking into the source files.

About

A neat pure-lua physics engine for OpenMW made by MaxYari - updated for Projectile Physics mod

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages