10

Average: 10 (2 votes)

Submitted by:

Submitted by NWShacker on 2019-02-05 13:09.

Last modified:

2019-02-05 13:09

Version:

1.0

Game:

Category:

Requirements:

Language:

This project provides a library of several useful mathematical functions which are not readily available in vanilla NWScript. They mostly operate on floats and vectors, originating from math fields like linear algebra (rotations, projections) and pseudo-random number generation (uniform or normal distributions). Other uses include value rounding, comparisons, conversions and debugging. All functions are fast and well documented.

A demo module is provided.

**DESCRIPTION**

Functions provided by this project are divided between several groups:

- Variable storage functions: conversion of vectors into strings and setting / getting / deleting them as local variables.
- Variable debug functions: quick displaying and logging of all basic variable types (string, int, float, vector, location and object).
- Random sample functions: fast pseudo-random generation of ints and floats from uniform and normal (Gaussian / bell curve) distributions, way beyond capabilities of vanilla NWN's Random function.
- Rounding functions: float and vector component truncation, rounding, flooring and ceiling.
- Comparison functions: sign, min, max and clipping (making sure they belong to certain range) of ints, floats and vector components.
- Vector arithmetic functions: component-wise sum and multiplication between vectors or vectors and scalars.
- Linear algebra functions: vector dot and cross products, 2D and 3D rotations, planar angle, orthogonal projection and line intersection calculations.
- Algorithmic functions: ready algorithms using above functions:
- Projection of a vertex onto a set of line segments.
- Check whether a vertex lies inside a polygon.

These functions mostly work in the way their name suggest. With vectors there is usually an option for extra handling of their Z components.

**INSTALLATION**

This project is aimed at module builders only. Players will not benefit from it directly (if some module uses it, it will contain it already). Though even if you are a player, be sure to check out the demo module for examples of some amusing use cases of this project.

Files:

Attachment | Size |
---|---|

auxiliary_math_library_1.0.7z (29) | 24.11 KB |

auxiliary_math_library_1.0.txt | 14.45 KB |

Permissions & licensing:

Permission Detail:

You may use any file from this project in your project (modified or not) only if you correctly and sufficiently credit authors of this project.

Over 1000 lines of enterprise-level code only because some time ago I decided to make a bit more useful random function.

Be sure to check out the demo module, but watch out for you CPU as some of the scripts have sub-second call intervals.

really great work. you get my vote for king. :D

these will be very useful, i've no longer got an excuse to put off some of my projects.

i'm glad to see you've included stuff to work around the max int/float conversion bug... ['how/why could they have ever allowed that?!' he asks incredulously.]

thank you !

Thanks. Hopefully somebody can put this to some good use in a real module.

I did a bit of research before and it appears NWN's PRNG is not skewed (i.e. a C rand() passthrough, no dirty tricks), so the MATH_Rand* function family provided here should work flawlessly under "normal" conditions.

But to clarify, the problems with floats aren't really bugs

per se,though from user's persepective they definitely can be seen as such. In order to save CPU ticks, NWN uses single-precision (32-bit) float, which can represent ints exactly only in -2^{24}to 2^{24}range (assuming IEEE 754) and will start rounding numbers above that. You may also end up in a + b = a situations. With doubles we'd be hitting problems much later, but then not many people are going to need to go over 16 millions, so no big deal.Guess I spoke too soon. Like usual, bugs show up after release.

There is a minor issue in MATH_RandInt. Fixed version should be out by the weekend... probably with something extra.

This library is a beautiful thing. High five for being capslock prefix buddies!

Here to drop off ideas and suggestions, for this or for future projects (take with grain of salt, is likely to be 90% nonsense):

- Catapult / Boomerang trajectories.

A "location GetProjectileNextStep()" function could be used to step-by-step generate a flight path for simulating throwing a placeable or applying VFX and damage in spells.

- Percentages.

Percentage calculation functions would go well with the idea of having a comprehensive math library.

- High score sorting, or sorting algorithms in general.

I could see functions to sort objects or strings according to some determinant value being very useful to people. Think: Add 10 objects to a list. Call function to retrieve the object that, among them, has the highest value of local int "CAKE" set on it. Or, add 10 strings to a list. Check local ints stored on module under the names of the strings on the list, return the name for the string with the highest (or lowest) value. Optionally, remove string from list.

- Collision detection / Object-to-Object proximity detection.

This is already demonstrated in the demo module, but explicit convenience functions for it might be nice to have even so. A lot of newbie modulebuilders struggle with scripting as is; a "GetIsObjectBetween(object oCheckFor, location lStart, location lEnd, float fRadius=0.5)" function would be easier for the user than having to learn linear algebra if they aren't already familiar with it. Same thing with "GetIsObjectInFrontOf(object oCheck, object oTarget, float fDistance=1.0)", or "GetIsObjectBehind()", or "GetIsObjectToLeftOf()"/"GetIsObjectToRightOf()"; those are difficult to set up for newbie scripters.

- "Safe" incrementing and decrementing, with an optional cap.

Incrementing and decrementing functions for incrementing/decrementing local integers, with maximum or minimum values. I've got these in my data management library, to handle local values that go from 0-100 or -100 to 100, and I've grown very fond of them. Capping values is all over the place in the Bioware spell scripts, too; having the cap be automatic part of the incrementation/decrementation saves a few lines of code over and over again.

- "Default to" values.

Another thing I found very practical was a function to set up "default to" values during setup/initialization of placeables. If the builder did not specify a value for local int/string/float, but that variable is required for the whatever-it-is to work as planned, default to value X. This isn't exactly the direction you're going in, but it's a thought.

- Random positions in shapes.

Running with the thought of making the random position generation functions easier to use, setting up a "GetRandomPositionInShape" function might work well, too. Expand the Bioware SHAPE_* constants, make retrieving a random position within a given shape of a given size a one-line kind of thing. It'd simplify the code on the "practical ingame application"-end, and make it immediately and unambiguously readable to anyone. One of the biggest problems of some of the best libraries for NWN is that they're too difficult for newbies to figure out how to use, so they often lie around underutilized.

I'll drop off a couple of links to things you might enjoy taking a look at if you haven't already:

https://neverwintervault.org/project/nwn1/script/psc-pentagrams-summonin...

https://neverwintervault.org/project/nwn1/script/gestalt-cutscene-script...

Thanks for suggestions and the links, Barbar. I actually got inspired by your function names to do the CAPS_ style prefix. I even went back and modified NCTS to have them too... It

reallyimproves readability.I'm almost done with adding a list support to the module. I rewrote the line intersection and projection algorithms to accept lists of vertices instead of tags. This is much better - you'll be able to test multiple shapes at once, with self-intersecting segments or not. I have a quicksort implementation (tried mergesort too, but it was hitting TMI before that), so the lists will be sortable. Direct lexicographic string sorting is technically possible via extra 2DA but its performance will probably be very poor...

Calculating trajectories (or curves in general) may be possible. Same with collision detection... Colliding with polygons is done, but I may add sphere / circle collision / intersection - good suggestion.

I think the safe incrementation can be already done with:

You are correct that functions need to usable as is. If you have any suggestions, you can post or PM me their declarations. I'll also think of some.

I'll try to post 2.0 version (with list support) in this week. Then I'll look into your timestamp library.

giantholes in all aspects of formal knowledge), and whether it would hold up under multiplayer or PW conditions.time. ::ba-dumm-tss!:: ^^You are correct - checking clicks on ground (or triggers) is possible with AML. You still need to keep the zone vertices somewhere... Too bad its not possible to retrieve the vertices of a trigger with NWScript. Technically, someone could write a program that extracts them from module binary and produce a parseable list...

Thanks for the link to that projectile detection script. At glance, it may be doing something similar to me, but it's core logic seems to be quite... intertwined with the spellcasting. I haven't tried the demo yet.

I have an idea for a check if object is between other objects using the line projection. It can even accept a tolerance parameter (i.e. how far you are from the line). I'll also add sphere collision and intersection functions (perhaps with cone parameters). Compared to the polygon-related ones, these are easy.

Unlike real sorting, in NWN we are bound by Too Many Instructions, which is highly dependant on how we sort but also how much extra work we need to perform while doing so. If you don't plan on sorting thousands of items at once, then everything should be fine (i.e. stay at several hundreds).

Yes, I promised to look at your library. But I'll be mostly focusing on timestamp algebra, if you don't mind. I plan on releasing the update to AML on this Sunday. Let me know if there are any special list functions you may find useful.

BTW: NWN call stack limit is 127 (i.e. 125 recursive functions calls from main are OK, next one fails).