GithubHelp home page GithubHelp logo

nwnxee / unified Goto Github PK

View Code? Open in Web Editor NEW
128.0 128.0 91.0 296.46 MB

Binaries available under the Releases tab on Github

Home Page: https://nwnxee.github.io/unified

License: GNU General Public License v3.0

CMake 2.08% Shell 0.17% C++ 53.16% Ruby 0.12% C 0.25% PowerShell 0.01% Lua 9.27% Dockerfile 0.07% CSS 0.26% HTML 0.06% C# 16.62% NWScript 16.94% SWIG 0.98%

unified's People

Contributors

1d3s avatar baaleos avatar bhaalm avatar cjreek avatar daztek avatar dparoli avatar drake127 avatar eladner avatar golot avatar hendrikgit avatar henningkoehlernz avatar jakkn avatar jd28 avatar jhett12321 avatar julien-lecomte avatar kmsheehan avatar liareth avatar morderon avatar mtijanic avatar niv avatar plenarius avatar qowyn avatar stenly87 avatar summonfox avatar urothis avatar varenx avatar virusman avatar weavejester avatar williamdraco avatar zunath avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

unified's Issues

Request - NWNX Damages

Hello everybody,

I was looking around and I found out that it has not been implemented yet NWNX - Damages.

This plugin is really useful because it allows us to handle a script each time a damaged is applied.

In particular:
"This plugin hooks the EffectList_OnApplyDamage method inside the nwserver process on linux."

Here the link:
https://neverwintervault.org/project/nwn1/other/nwnxdamage-linux

The source code has been released too.
I tried it and work pretty well.
It allows to do many many things.

Are you interested to implement it on NWNX EE unified?
https://github.com/nwnxee/unified

Thank you so much

Administration: Bug Delete Bic File

Server crashes when using this function, both with the TRUE and FALSE option, and after the bic has been previously saved(the file bic is present in the servervault folder). This is the log

=== Crash
What you see below is debug info that will help us fix a crash you have
encountered. Please create a new public ticket for NWN on

http://redmine.beamdog.com

and attach all of it. This will help us figure out what went wrong.
We can fix issues best when you include all relevant info that led to
this crash so we can reproduce it - the more the better.

Thank you.
=== Props
target = nwserver
time = 1517777980
exception = b
g_sBuildNumber = 8156
g_sVersionNumber = 74
&GenericCrashHandler = 0x568ebf70
=== Backtrace
./nwserver-linux(+0x394990)[0x568ec990]
./nwserver-linux(+0x3944a0)[0x568ec4a0]
./nwserver-linux(+0x394a31)[0x568eca31]
linux-gate.so.1(__kernel_sigreturn+0x0)[0xf77afbc0]
./nwserver-linux(+0x258ee4)[0x567b0ee4]
./nwserver-linux(+0x1e6a68)[0x5673ea68]
./nwserver-linux(+0x1a449d)[0x566fc49d]
./nwserver-linux(+0x1b7e3e)[0x5670fe3e]
./nwserver-linux(+0xb55ef)[0x5660d5ef]
./nwserver-linux(+0xb1a29)[0x56609a29]
./nwserver-linux(+0x4e24c)[0x565a624c]
./nwserver-linux(+0x4e606)[0x565a6606]
./nwserver-linux(+0x5c06b)[0x565b406b]
./nwserver-linux(+0x4b04f)[0x565a304f]
./nwserver-linux(+0xc999e)[0x5662199e]
/nwn/nwnx/NWNX_Core.so(ZN7NWNXLib8Services9HooksImpl23HookLandingHolderSharedINS_7Hooking17CallingConvention8ThisCallEE11HookLandingILj825648EiPNS_3API21CServerExoAppInternalEJEEET0_T1_DpT2+0x53)[0xf7619494]
./nwserver-linux(+0xb2acd)[0x5660aacd]
./nwserver-linux(+0x249b1)[0x5657c9b1]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf6)[0xf7145276]
./nwserver-linux(+0x276ed)[0x5657f6ed]
=== File: /proc/self/status
Name: nwserver-linux
State: R (running)
Tgid: 7
Ngid: 0
Pid: 7
PPid: 5
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 256
Groups:
NStgid: 7
NSpid: 7
NSpgid: 1
NSsid: 1
VmPeak: 240608 kB
VmSize: 240608 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 103692 kB
VmRSS: 103692 kB
VmData: 228256 kB
VmStk: 132 kB
VmExe: 4520 kB
VmLib: 7444 kB
VmPTE: 252 kB
VmPMD: 8 kB
VmSwap: 0 kB
HugetlbPages: 0 kB
Threads: 6
SigQ: 0/3795
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000400
SigIgn: 0000000000000000
SigCgt: 00000001800044a2
CapInh: 00000000a80425fb
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000
Seccomp: 2
Cpus_allowed: 00000001
Cpus_allowed_list: 0
Mems_allowed: 00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 608
nonvoluntary_ctxt_switches: 18837
=== File: /proc/self/maps
56558000-569c2000 r-xp 00000000 fc:00 1050832 /nwn/data/bin/linux-x86/nwserver-linux
569c3000-569c6000 r--p 0046a000 fc:00 1050832 /nwn/data/bin/linux-x86/nwserver-linux
569c6000-569cb000 rw-p 0046d000 fc:00 1050832 /nwn/data/bin/linux-x86/nwserver-linux
569cb000-5c24f000 rw-p 00000000 00:00 0
5d61b000-5d620000 rw-p 00000000 00:00 0 [heap]
5d620000-5d621000 rwxp 00000000 00:00 0 [heap]
5d621000-5daa2000 rw-p 00000000 00:00 0 [heap]
5daa2000-5daa3000 rwxp 00000000 00:00 0 [heap]
5daa3000-5daac000 rw-p 00000000 00:00 0 [heap]
5daac000-5daad000 rwxp 00000000 00:00 0 [heap]
5daad000-5dab0000 rw-p 00000000 00:00 0 [heap]
5dab0000-5dab1000 rwxp 00000000 00:00 0 [heap]
5dab1000-5dac7000 rw-p 00000000 00:00 0 [heap]
5dac7000-5dac8000 rwxp 00000000 00:00 0 [heap]
5dac8000-5dad2000 rw-p 00000000 00:00 0 [heap]
5dad2000-5dad3000 rwxp 00000000 00:00 0 [heap]
5dad3000-5db08000 rw-p 00000000 00:00 0 [heap]
5db08000-5db0a000 rwxp 00000000 00:00 0 [heap]
5db0a000-5db0f000 rw-p 00000000 00:00 0 [heap]
5db0f000-5db11000 rwxp 00000000 00:00 0 [heap]
5db11000-62b8e000 rw-p 00000000 00:00 0 [heap]
f3d00000-f3d21000 rw-p 00000000 00:00 0
f3d21000-f3e00000 ---p 00000000 00:00 0
f3ea4000-f3ea5000 ---p 00000000 00:00 0
f3ea5000-f48e6000 rw-p 00000000 00:00 0
f4a88000-f4ab4000 rw-p 00000000 00:00 0
f4ad3000-f4c1e000 rw-p 00000000 00:00 0
f4c1e000-f4c1f000 ---p 00000000 00:00 0
f4c1f000-f541f000 rw-p 00000000 00:00 0
f541f000-f5424000 r-xp 00000000 fc:00 1055590 /nwn/nwnx/NWNX_ThreadWatchdog.so
f5424000-f5425000 r--p 00004000 fc:00 1055590 /nwn/nwnx/NWNX_ThreadWatchdog.so
f5425000-f5426000 rw-p 00005000 fc:00 1055590 /nwn/nwnx/NWNX_ThreadWatchdog.so
f5426000-f542b000 r-xp 00000000 fc:00 1055589 /nwn/nwnx/NWNX_ServerLogRedirector.so
f542b000-f542c000 ---p 00005000 fc:00 1055589 /nwn/nwnx/NWNX_ServerLogRedirector.so
f542c000-f542d000 r--p 00005000 fc:00 1055589 /nwn/nwnx/NWNX_ServerLogRedirector.so
f542d000-f542e000 rw-p 00006000 fc:00 1055589 /nwn/nwnx/NWNX_ServerLogRedirector.so
f542e000-f5436000 r-xp 00000000 fc:00 1055584 /nwn/nwnx/NWNX_Player.so
f5436000-f5437000 r--p 00007000 fc:00 1055584 /nwn/nwnx/NWNX_Player.so
f5437000-f5438000 rw-p 00008000 fc:00 1055584 /nwn/nwnx/NWNX_Player.so
f5438000-f5446000 r-xp 00000000 fc:00 1055583 /nwn/nwnx/NWNX_Object.so
f5446000-f5447000 r--p 0000d000 fc:00 1055583 /nwn/nwnx/NWNX_Object.so
f5447000-f5448000 rw-p 0000e000 fc:00 1055583 /nwn/nwnx/NWNX_Object.so
f5448000-f5460000 r-xp 00000000 fc:00 1055580 /nwn/nwnx/NWNX_Events.so
f5460000-f5461000 r--p 00017000 fc:00 1055580 /nwn/nwnx/NWNX_Events.so
f5461000-f5462000 rw-p 00018000 fc:00 1055580 /nwn/nwnx/NWNX_Events.so
f5462000-f547c000 r-xp 00000000 fc:00 1055579 /nwn/nwnx/NWNX_Data.so
f547c000-f547d000 r--p 00019000 fc:00 1055579 /nwn/nwnx/NWNX_Data.so
f547d000-f547e000 rw-p 0001a000 fc:00 1055579 /nwn/nwnx/NWNX_Data.so
f547e000-f5491000 r-xp 00000000 fc:00 1055578 /nwn/nwnx/NWNX_Creature.so
f5491000-f5492000 r--p 00012000 fc:00 1055578 /nwn/nwnx/NWNX_Creature.so
f5492000-f5493000 rw-p 00013000 fc:00 1055578 /nwn/nwnx/NWNX_Creature.so
f5493000-f549d000 r-xp 00000000 fc:00 1055576 /nwn/nwnx/NWNX_Chat.so
f549d000-f549e000 r--p 00009000 fc:00 1055576 /nwn/nwnx/NWNX_Chat.so
f549e000-f549f000 rw-p 0000a000 fc:00 1055576 /nwn/nwnx/NWNX_Chat.so
f549f000-f54a9000 r-xp 00000000 fc:00 1055574 /nwn/nwnx/NWNX_Administration.so
f54a9000-f54aa000 r--p 00009000 fc:00 1055574 /nwn/nwnx/NWNX_Administration.so
f54aa000-f54ab000 rw-p 0000a000 fc:00 1055574 /nwn/nwnx/NWNX_Administration.so
f54ab000-f56c7000 rw-p 00000000 00:00 0
f56c7000-f56db000 r-xp 00000000 fc:00 919064 /lib/i386-linux-gnu/libresolv-2.24.so
f56db000-f56dc000 r--p 00013000 fc:00 919064 /lib/i386-linux-gnu/libresolv-2.24.so
f56dc000-f56dd000 rw-p 00014000 fc:00 919064 /lib/i386-linux-gnu/libresolv-2.24.so
f56dd000-f56df000 rw-p 00000000 00:00 0
f56df000-f56e4000 r-xp 00000000 fc:00 919043 /lib/i386-linux-gnu/libnss_dns-2.24.so
f56e4000-f56e5000 r--p 00004000 fc:00 919043 /lib/i386-linux-gnu/libnss_dns-2.24.so
f56e5000-f56e6000 rw-p 00005000 fc:00 919043 /lib/i386-linux-gnu/libnss_dns-2.24.so
f56e6000-f56e7000 ---p 00000000 00:00 0
f56e7000-f60e3000 rw-p 00000000 00:00 0
f60e3000-f60ee000 r-xp 00000000 fc:00 919045 /lib/i386-linux-gnu/libnss_files-2.24.so
f60ee000-f60ef000 r--p 0000a000 fc:00 919045 /lib/i386-linux-gnu/libnss_files-2.24.so
f60ef000-f60f0000 rw-p 0000b000 fc:00 919045 /lib/i386-linux-gnu/libnss_files-2.24.so
f60f0000-f60f6000 rw-p 00000000 00:00 0
f60f6000-f6101000 r-xp 00000000 fc:00 919049 /lib/i386-linux-gnu/libnss_nis-2.24.so
f6101000-f6102000 r--p 0000a000 fc:00 919049 /lib/i386-linux-gnu/libnss_nis-2.24.so
f6102000-f6103000 rw-p 0000b000 fc:00 919049 /lib/i386-linux-gnu/libnss_nis-2.24.so
f6103000-f6119000 r-xp 00000000 fc:00 919039 /lib/i386-linux-gnu/libnsl-2.24.so
f6119000-f611a000 r--p 00016000 fc:00 919039 /lib/i386-linux-gnu/libnsl-2.24.so
f611a000-f611b000 rw-p 00017000 fc:00 919039 /lib/i386-linux-gnu/libnsl-2.24.so
f611b000-f611d000 rw-p 00000000 00:00 0
f611d000-f6125000 r-xp 00000000 fc:00 919041 /lib/i386-linux-gnu/libnss_compat-2.24.so
f6125000-f6126000 r--p 00007000 fc:00 919041 /lib/i386-linux-gnu/libnss_compat-2.24.so
f6126000-f6127000 rw-p 00008000 fc:00 919041 /lib/i386-linux-gnu/libnss_compat-2.24.so
f6127000-f6128000 ---p 00000000 00:00 0
f6128000-f6928000 rw-p 00000000 00:00 0
f6928000-f6929000 ---p 00000000 00:00 0
f6929000-f712d000 rw-p 00000000 00:00 0
f712d000-f72de000 r-xp 00000000 fc:00 919007 /lib/i386-linux-gnu/libc-2.24.so
f72de000-f72df000 ---p 001b1000 fc:00 919007 /lib/i386-linux-gnu/libc-2.24.so
f72df000-f72e1000 r--p 001b1000 fc:00 919007 /lib/i386-linux-gnu/libc-2.24.so
f72e1000-f72e2000 rw-p 001b3000 fc:00 919007 /lib/i386-linux-gnu/libc-2.24.so
f72e2000-f72e5000 rw-p 00000000 00:00 0
f72e5000-f72fe000 r-xp 00000000 fc:00 919062 /lib/i386-linux-gnu/libpthread-2.24.so
f72fe000-f72ff000 r--p 00018000 fc:00 919062 /lib/i386-linux-gnu/libpthread-2.24.so
f72ff000-f7300000 rw-p 00019000 fc:00 919062 /lib/i386-linux-gnu/libpthread-2.24.so
f7300000-f7302000 rw-p 00000000 00:00 0
f7302000-f731e000 r-xp 00000000 fc:00 919025 /lib/i386-linux-gnu/libgcc_s.so.1
f731e000-f731f000 r--p 0001b000 fc:00 919025 /lib/i386-linux-gnu/libgcc_s.so.1
f731f000-f7320000 rw-p 0001c000 fc:00 919025 /lib/i386-linux-gnu/libgcc_s.so.1
f7320000-f7373000 r-xp 00000000 fc:00 919032 /lib/i386-linux-gnu/libm-2.24.so
f7373000-f7374000 r--p 00052000 fc:00 919032 /lib/i386-linux-gnu/libm-2.24.so
f7374000-f7375000 rw-p 00053000 fc:00 919032 /lib/i386-linux-gnu/libm-2.24.so
f7375000-f74e5000 r-xp 00000000 fc:00 919802 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.22
f74e5000-f74eb000 r--p 0016f000 fc:00 919802 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.22
f74eb000-f74ec000 rw-p 00175000 fc:00 919802 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.22
f74ec000-f74ef000 rw-p 00000000 00:00 0
f74ef000-f74f2000 r-xp 00000000 fc:00 919017 /lib/i386-linux-gnu/libdl-2.24.so
f74f2000-f74f3000 r--p 00002000 fc:00 919017 /lib/i386-linux-gnu/libdl-2.24.so
f74f3000-f74f4000 rw-p 00003000 fc:00 919017 /lib/i386-linux-gnu/libdl-2.24.so
f74f6000-f77a6000 r-xp 00000000 fc:00 1055577 /nwn/nwnx/NWNX_Core.so
f77a6000-f77a7000 r--p 002af000 fc:00 1055577 /nwn/nwnx/NWNX_Core.so
f77a7000-f77aa000 rw-p 002b0000 fc:00 1055577 /nwn/nwnx/NWNX_Core.so
f77aa000-f77ad000 rw-p 00000000 00:00 0
f77ad000-f77af000 r--p 00000000 00:00 0 [vvar]
f77af000-f77b0000 r-xp 00000000 00:00 0 [vdso]
f77b0000-f77d3000 r-xp 00000000 fc:00 918989 /lib/i386-linux-gnu/ld-2.24.so
f77d3000-f77d4000 r--p 00022000 fc:00 918989 /lib/i386-linux-gnu/ld-2.24.so
f77d4000-f77d5000 rw-p 00023000 fc:00 918989 /lib/i386-linux-gnu/ld-2.24.so
ff7ef000-ff810000 rw-p 00000000 00:00 0 [stack]
=== End

Events: Skip executing event

We need to allow the Events plugin to skip events.

  1. Switch all shared hooks to exclusive hooks.
  2. Come up with the API. void NWNX_Events_SkipEvent() maybe. Possibly add a comment explaining event skipping is only valid on NWNX events and not user defined events, or do extra work to check if an event has been skipped between invoking each subscribing script.
  3. If the API is called, set a flag.
  4. Clear the flag on event completion. Figure out a clean way to do this, maybe Events::StartEvent() and Events::FinishEvent() between Events::SignalEvent().
  5. If the flag is set, skip calling the original function.

Core API improvement

  • Come up with a solution to allow plugins to access their individual proxy through a global variable or function, without specifying information about the plugin. Like TRACE("This is a debug message") which automatically determines that the caller is NWNX_SQL and uses that proxy. There are cross-platform difficulties here due to how global symbols are handled between loaded binaries.

(up for grabs?)

  • Implement a proper ASSERT macro. (@Liareth)

BUG: Crash when NWNX_CORE_SKIP=Y

I'm consistently crashing when loading the DockerDemo module that comes inside the nwnxee/nwserver:8164 docker container (https://hub.docker.com/r/nwnxee/nwserver/). NWNX_Core.so is being preloaded, but it's being skipped with the NWNX_CORE_SKIP=Y environmental variable, which is set in the attached config.txt file that contains the environmental variables passed to docker (with --env-file).

This crash does not happen when NWNX_Core.so is not LD_PRELOAD'ed.

This crash does not happen if NWNX_Core.so is LD_PRELOAD'ed and NWNX_CORE_SKIP=N

I've attached nwserver-crash-1521259791.log.

Creature: Override BAB

Request new function to set the BAB of a creature overriding the current one.
This function was implemented in funcs plugins for windows, here is the original description

// Sets the Base Attack Bonus Override of oObject to iBaB
// If BAB Override is greater than zero GetBaseAttackBonus will return this instead
// The original BAB can be restored by setting the BAB Override to zero
// The range of iBab is 0 to 254
// Unfortunately this is not a permanent setting as the game calculates the BaB every time a player logs in
void NWNXFuncs_SetBaseAttackBonusOverride(object oCreature, int iBaB);

Replace the Tasks subsystem

Problems with it:

  • It's limited to one thread.
  • The locking implementation is weird and ... weird.
  • It pulls in a dependency on GCC 6.2+ due to std::shared_mutex, which we could drop.

I will do this. I have a nice implementation I wrote for fun that I will port over.

Events Plugin - Trap Trigger Event

The events plugin is missing hooks for:

  • Skill Use
  • Polymorph
  • Unpolymorph
  • Action Mode Toggle (only has stealth)
  • Crit/Dev Crit (dev crit should also be cancellable - see other issue!)
  • Trap Trigger
  • Trap Set

SQL: Asynchronous query support

While an SQL query is running, the main server thread is suspended. It's not unheard of for queries to take seconds to complete, which causes huge lag spikes, and in extreme cases can even disconnect the clients.

We need a way to queue up a query on the Async thread, and register a callback nwscript to deal with the results afterwards.

Should wait for #5 first before implementing.

On the API side, we'll need to explicitly specify which query we're operating on (because now we can have multiple active queries).

Option 1: Pass the query ID manually to all functions. We can remain compatible with the existing API by having the default query ID of 0 (never a valid ID) refer to the last one used by nwscript. For existing usecases nothing changes, but script callbacks will need to manually specify the ID (which they'd get as a local var on OBJECT_SELF).

Option 2: Expose a SetActiveQuery(int id) to manually switch the states for the current script. A PrepareQuery() or ExecuteQuery() call automatically switch the active query as well.

Server list syncing

The ability to sync player lists between servers (and allow cross-server tells as if they were native) would be very useful to many major servers.

  • Server list must be shared between servers. Cross server tells and shouts must be allowed. Cross server party invites (or appearing on DM list) don't matter.

This will probably require a separate server binary which handled synchronising the player list and communicating cross-server tells and shouts. The flow being:

  • User connects to server.
  • Server notifies sync server.
  • Sync server notifies other servers.
  • Other servers fake a login.

Rinse and repeat for disconnected users and for sending tell/shout messages.

Sync server must receive a heartbeat every seconds or it will trigger disconnect notification for that server's players to all other servers.

It's pretty complicated but up for grabs if anyone wants to work on something like this.

Need a way to selectively disable building some plugins

Right now, we build all or nothing, with cmake being able to skip the few plugins that have external dependencies (e.g. JVM, SQL), if those dependencies are not found.

It'd be nice if there was a way to blacklist (and/or whitelist) plugins to be built using the environment or make arguments, regardless of external libraries present.
Most noticeable is probably the i386 version of ruby on amd64 systems, which if present causes the ruby plugin to build, but cannot actually compile it, resulting in a build failure.

Documentation Request: Minimal Startup File, or instructions for one

I'm trying to get a basic setup working with the core library and SQL, but I'm having some difficulty.

I'm able to compile the .so files based on the info found in README.md, but I'm not really sure what to do next. Based on my brief experience with the old NWNX, I've put the .so files in my base server directory, /opt/nwn. I've altered my startup script (in the same directory) to preload the core file (though this isn't stated anywhere, but I think that's how the old version worked).

export LD_PRELOAD=./NWNX_Core.so

I've added the following for SQL:

export NWNX_SQL_HOST=localhost
export NWNX_SQL_DATABASE=nwn
export NWNX_SQL_USERNAME=root
export NWNX_SQL_PASSWORD=<mypassword>

I get the following when I run the startup script:

Build:8156
Copyright BioWare Corp 1998-2004
Registering crash signal handlers.

Server: Loading...
Working Directory For Game Install Is: 
Working Directory For Your Resources Is: /home/user/.local/share/Neverwinter Nights
I [16:40:10] NWNX_Core: Server is running version 8156.
I [16:40:10] NWNX_Core: Loading plugins from: .
I [16:40:10] NWNX_SQL: Connecting to type MYSQL
E [16:40:10] NWNX_Core: Failed to load plugin (NWNX_SQL.so) because 'Targeting MySQL, but no MySQL support built in.'.
F [16:40:10] NWNX_Core: The server encountered a fatal error 'Targeting MySQL, but no MySQL support built in.' during setup and must now terminate.
terminate called after throwing an instance of 'std::runtime_error'
  what():  Targeting MySQL, but no MySQL support built in.
We just crashed hard. :( Sorry about that. But you can help us fix this! Please consider reporting this crash at http://redmine.beamdog.com with the relevant information attached.

A log file has been written to /home/user/.local/share/Neverwinter Nights/nwserver-crash-1518136810.log containing further diagnostic information.
Aborted (core dumped)

The log file doesn't contain anything that I can make much sense of. I have verified that I can access the database directly via the mysql command:
mysql -u root -p

Any ideas?

NWN_Object crash

When you attempt to use the NWNX_Object_Deserialize or NWNX_Object_Serialize function, it causes nwserver to crash with a segmentation fault. This appeared after the 8164 update.

Something strange with SQL plugin

When entering the init area of my module different scripts checks at "the same time" the same variable on the database. I know I should reconsider the way I'm doing this but anyway, what is strange is that although the query is always the same, the last one gives a "Syntax error" :/

Maybe its my fault, please tell me if you need more info.

[19:24:24] NWNX_SQL: Successful SQL query. Query ID: '109', Query: 'SELECT val FROM misc WHERE player='bhaal' AND tag='Prueba' AND name='VERSION_PJ'', Results Count: '1'.
I [19:24:24] NWNX_SQL: Successful SQL query. Query ID: '110', Query: 'SELECT val FROM misc WHERE player='bhaal' AND tag='Prueba' AND name='ROL_BONUS'', Results Count: '0'.
I [19:24:24] NWNX_SQL: Successful SQL query. Query ID: '111', Query: 'SELECT val FROM misc WHERE player='bhaal' AND tag='Prueba' AND name='VERSION_PJ'', Results Count: '1'.
I [19:24:24] NWNX_SQL: Successful SQL query. Query ID: '112', Query: 'SELECT val FROM misc WHERE player='bhaal' AND tag='Prueba' AND name='VERSION_PJ'', Results Count: '1'.
W [19:24:24] NWNX_SQL: Failed to prepare statement: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'player='bhaal' AND tag='Prueba' AND name='VERSION_PJ'' at line 1

Console commands

We need the following commands to be enterable in the console:

  • load : loads the plugin.
  • unload : if loaded, unloads the plugin.
  • reload : unloads then loads the plugin

It would also be cool to have the ability to set config options from the console. Imagine ... :

  • set NWNX_CHAT_LOG_LEVEL=7
  • reload NWNX_Chat
    (now you have debug info, you debug on the fly to find an issue on a live server)
  • unset NWNX_CHAT_LOG_LEVEL
  • reload NWNX_Chat
    (back to normal)

Help should output info on these additional commands. It should be implemented through a service so other plugins can add their own custom commands.

  • GetServices()->m_Commands->RegisterCommand(std::string command, std::function<bool(std::string)>) is an example API that could be used.

This is important for the profiler and could be very useful for many other plugins. I want people to be able to selectively load it during laggy times to get 30 seconds - 1 minute of important metrics then unload it again.

Error in Plugins/Creature/Creature.cpp

Line 509:
const auto offset = Services::Events::ExtractArgument<int32_t>(args); assert(value <= 255);

Should be:
const auto offset = Services::Events::ExtractArgument<int32_t>(args); assert(offset <= 255);

Thank you for your work!

JVM: nwnx_jvm_token wrong?

I noticed that nwnx_jvm_token.nss:5 and nwnx_jvm_token.nss:6 push an argument for the Event function but then call the Token function. I don't fully understand what this function does nor do I have the knowledge or setup to test it, but this seems wrong to me. It looks like every time call_token is called, 2 more arguments get pushed onto the Event stack, and Token gets called with nothing. Can someone (@niv @zunath) who knows about JVM investigate when you get a chance?

PostgreSQL compilation issue

Something in commit 9f45d71 broke finding the libpq includes and libraries on my system. Not sure where to start but find_packge isn't finding PostgreSQL for some reason.

NWNX_Weapon: SetWeaponFineese

Used the command to make katana's & quarterstaff's fineeseable for medium creatures.

Such worked, but somehow rapier, which is fineeseable in vanilla, became unfineeseable.

Using the setweaponfineese function for the rapier did fix the issue.

Other fineeseable weapons remained working.

nwnx connection to mysql database

I've been at this all day. Trying to get nwnx to work with MySQL. At this point, I think I'm the closest I've been..I'm using the latest docker image from Glorwinger. It seems to be fine, except it cannot connect to the mysql server. I've verified that the mysql server is running, and I can connect to it. Could this be because the path to the mysql socket doesn't exist within the docker image? If so, how can I make the docker image look in the right location? Any insight? Here's what the output of docker looks like:

`/var/nwn_ee$ docker run --rm -it -p 5121:5121 -p 5121:5121/udp --env-file docker_env.ini -v $(pwd):/nwn/home nwnxee/nwserver:8164[] Copying any custom NWNX plugins
'/nwn/home/nwnx/NWNX_Administration.so' -> '/nwn/nwnx/NWNX_Administration.so'
'/nwn/home/nwnx/NWNX_BehaviourTree.so' -> '/nwn/nwnx/NWNX_BehaviourTree.so'
'/nwn/home/nwnx/NWNX_Chat.so' -> '/nwn/nwnx/NWNX_Chat.so'
'/nwn/home/nwnx/NWNX_Core.so' -> '/nwn/nwnx/NWNX_Core.so'
'/nwn/home/nwnx/NWNX_Creature.so' -> '/nwn/nwnx/NWNX_Creature.so'
'/nwn/home/nwnx/NWNX_Data.so' -> '/nwn/nwnx/NWNX_Data.so'
'/nwn/home/nwnx/NWNX_Events.so' -> '/nwn/nwnx/NWNX_Events.so'
'/nwn/home/nwnx/NWNX_Item.so' -> '/nwn/nwnx/NWNX_Item.so'
'/nwn/home/nwnx/NWNX_JVM.so' -> '/nwn/nwnx/NWNX_JVM.so'
'/nwn/home/nwnx/NWNX_Metrics_InfluxDB.so' -> '/nwn/nwnx/NWNX_Metrics_InfluxDB.so'
'/nwn/home/nwnx/NWNX_Object.so' -> '/nwn/nwnx/NWNX_Object.so'
'/nwn/home/nwnx/NWNX_Player.so' -> '/nwn/nwnx/NWNX_Player.so'
'/nwn/home/nwnx/NWNX_Profiler.so' -> '/nwn/nwnx/NWNX_Profiler.so'
'/nwn/home/nwnx/NWNX_Redis.so' -> '/nwn/nwnx/NWNX_Redis.so'
'/nwn/home/nwnx/NWNX_Ruby.so' -> '/nwn/nwnx/NWNX_Ruby.so'
'/nwn/home/nwnx/NWNX_SQL.so' -> '/nwn/nwnx/NWNX_SQL.so'
'/nwn/home/nwnx/NWNX_ServerLogRedirector.so' -> '/nwn/nwnx/NWNX_ServerLogRedirector.so'
'/nwn/home/nwnx/NWNX_ThreadWatchdog.so' -> '/nwn/nwnx/NWNX_ThreadWatchdog.so'
'/nwn/home/nwnx/NWNX_Time.so' -> '/nwn/nwnx/NWNX_Time.so'
'/nwn/home/nwnx/NWNX_Tracking.so' -> '/nwn/nwnx/NWNX_Tracking.so'
[
] Linking in user home
'/nwn/run/database' -> '/nwn/home/database'
'/nwn/run/hak' -> '/nwn/home/hak'
'/nwn/run/modules' -> '/nwn/home/modules'
'/nwn/run/override' -> '/nwn/home/override'
'/nwn/run/portraits' -> '/nwn/home/portraits'
'/nwn/run/saves' -> '/nwn/home/saves'
'/nwn/run/servervault' -> '/nwn/home/servervault'
'/nwn/run/tlk' -> '/nwn/home/tlk'
'/nwn/run/dialog.tlk' -> '/nwn/home/dialog.tlk'
'/nwn/run/dialogf.tlk' -> '/nwn/home/dialogf.tlk'
[] Importing configuration
[
] Port: 5121/udp
Neverwinter Nights Server
Build:8164
Copyright BioWare Corp 1998-2004
Registering crash signal handlers.

Server: Loading...
I [03:19:21] [NWNXCore.cpp:184] NWNX_Core: Loading plugins from: /nwn/nwnx/
I [03:19:21] [NWNXCore.cpp:212] NWNX_Core: Skipping plugin NWNX_Administration due to configuration.
I [03:19:21] [NWNXCore.cpp:212] NWNX_Core: Skipping plugin NWNX_BehaviourTree due to configuration.
I [03:19:21] [NWNXCore.cpp:212] NWNX_Core: Skipping plugin NWNX_Chat due to configuration.
I [03:19:21] [NWNXCore.cpp:212] NWNX_Core: Skipping plugin NWNX_Creature due to configuration.
I [03:19:21] [NWNXCore.cpp:212] NWNX_Core: Skipping plugin NWNX_Data due to configuration.
I [03:19:21] [NWNXCore.cpp:212] NWNX_Core: Skipping plugin NWNX_Events due to configuration.
D [03:19:21] [NWNXCore.cpp:218] NWNX_Core: Loading plugin NWNX_Item.so
I [03:19:21] [NWNXCore.cpp:221] NWNX_Core: Loaded plugin 0 (Item) v2 by Various / sherincall / Bhaal.
I [03:19:21] [NWNXCore.cpp:212] NWNX_Core: Skipping plugin NWNX_JVM due to configuration.
I [03:19:21] [NWNXCore.cpp:212] NWNX_Core: Skipping plugin NWNX_Metrics_InfluxDB due to configuration.
I [03:19:21] [NWNXCore.cpp:212] NWNX_Core: Skipping plugin NWNX_Object due to configuration.
I [03:19:21] [NWNXCore.cpp:212] NWNX_Core: Skipping plugin NWNX_Player due to configuration.
I [03:19:21] [NWNXCore.cpp:212] NWNX_Core: Skipping plugin NWNX_Profiler due to configuration.
I [03:19:21] [NWNXCore.cpp:212] NWNX_Core: Skipping plugin NWNX_Redis due to configuration.
I [03:19:21] [NWNXCore.cpp:212] NWNX_Core: Skipping plugin NWNX_Ruby due to configuration.
D [03:19:21] [NWNXCore.cpp:218] NWNX_Core: Loading plugin NWNX_SQL.so
I [03:19:21] [SQL.cpp:81] NWNX_SQL: Connecting to type MYSQL
I [03:19:21] [MySQL.cpp:34] NWNX_SQL: Connection info: host=localhost username=nwn
D [03:19:21] [MySQL.cpp:35] NWNX_SQL: : password=SJ--------------------Q
E [03:19:21] [NWNXCore.cpp:226] NWNX_Core: Failed to load plugin (NWNX_SQL.so) because 'Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2 "No such file or directory")'.
F [03:19:21] [NWNXCore.cpp:353] NWNX_Core: The server encountered a fatal error 'Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2 "No such file or directory")' during setup and must now terminate.
We just crashed hard. :( Sorry about that. But you can help us fix this! Please consider reporting this crash at http://redmine.beamdog.com with the relevant information attached.

A log file has been written to /nwn/run/nwserver-crash-1521429561.log containing further diagnostic information.
/nwn/run-server.sh: line 63: 19 Aborted (core dumped) LD_PRELOAD=$NWN_LD_PRELOAD LD_LIBRARY_PATH=$NWN_LD_LIBRARY_PATH ./nwserver-linux $NWN_EXTRA_ARGS -port ${NWN_PORT:-5121} -interactive -servername "${NWN_SERVERNAME:-I was too lazy to configure my server.}" -module "${NWN_MODULE:-DockerDemo}" -publicserver "${NWN_PUBLICSERVER:-0}" -maxclients "${NWN_MAXCLIENTS:-96}" -minlevel "${NWN_MINLEVEL:-1}" -maxlevel "${NWN_MAXLEVEL:-40}" -pauseandplay "${NWN_PAUSEANDPLAY:-1}" -pvp "${NWN_PVP:-2}" -servervault "${NWN_SERVERVAULT:-1}" -elc "${NWN_ELC:-1}" -ilr "${NWN_ILR:-1}" -gametype "${NWN_GAMETYPE:-0}" -oneparty "${NWN_ONEPARTY:-0}" -difficulty "${NWN_DIFFICULTY:-3}" -autosaveinterval "${NWN_AUTOSAVEINTERVAL:-0}" -playerpassword "${NWN_PLAYERPASSWORD}" -dmpassword "${NWN_DMPASSWORD}" -adminpassword "${NWN_ADMINPASSWORD}" -reloadwhenempty "${NWN_RELOADWHENEMPTY:-0}"
The server crashed with return code 134. Trying to save crash data into your mounted server home.
'/nwn/run/nwserver-crash-1521429561.log' -> '/nwn/home/nwserver-crash-1521429561.log'`

NWNX_SQL_TYPE=MYSQL NWNX_SQL_HOSTNAME=localhost NWNX_SQL_USERNAME=nwn NWNX_SQL_PASSWORD=SJ--------------------Q

Events Plugin - Allow to Cancel Events

None of the original code can be cancelled. This used to be a feature on NWN1 with the NWNXCool library for example. Calling ClearAllActions() doesn't help with examine or anything that happens instantly (like DM events).

Just noticed this was already opened by Liareth in another issue...bah. :D

NWNXHaks - Allow to Log into server without haks/custom TLK

int SetHakHidden(string sHak, int nLevel = 1);
void SetPlayerEnhanced(object oPC, int nEnhanced);
int SetFallBackTLK(string sTLK);

from: https://github.com/jd28/nwnx-haks

Basically, allow players to log into servers with haks without having any haks or custom TLK installed or having to download any such. This would make it MUCH easier for players to get into the server's lobby room to read up on the server rules etc before actually starting playing.

Events: Toggle mode

The StickyCombatModes plugin used to use the messaging bus to add two events - NWNX_ON_MODE_ON and NWNX_ON_MODE_OFF.

The code looked like this:

GetServices()->m_hooks->RequestExclusiveHook<API::Functions::CNWSCreature__SetCombatMode>(&SetCombatModeHook);

... later ...

void StickyCombatModes::SetCombatModeHook(API::CNWSCreature* thisPtr, uint8_t newMode, bool forceNewMode)
{
    if (thisPtr->m_bPlayerCharacter)
    {
        const uint8_t currentMode = thisPtr->m_nCombatMode;

        if (g_plugin->m_dispatchMessages && currentMode != newMode)
        {
            // ToggleMode gets called with modes which are +1 to what the script constants expect.
            // It then calls SetCombatMode with the 'proper' modes.
            // To simplify things, we just correct the mode we dispatch here, so the game events
            // receive what they expect to.
            auto messaging = g_plugin->GetServices()->m_messaging.get();

            if (currentMode != 0)
            {
                messaging->BroadcastMessage("NWNX_EVENT_PUSH_EVENT_DATA", { "MODE", std::to_string(currentMode + 1) } );
                messaging->BroadcastMessage("NWNX_EVENT_SIGNAL_EVENT", { "NWNX_ON_MODE_OFF", ObjectIDToString(thisPtr->m_idSelf) });
            }

            if (newMode != 0)
            {
                messaging->BroadcastMessage("NWNX_EVENT_PUSH_EVENT_DATA", { "MODE", std::to_string(newMode + 1) } );
                messaging->BroadcastMessage("NWNX_EVENT_SIGNAL_EVENT", { "NWNX_ON_MODE_ON", ObjectIDToString(thisPtr->m_idSelf) });
            }
        }
    }

    return g_setCombatModeHook->CallOriginal<void>(thisPtr, newMode, forceNewMode);
}

Now that we no longer have the StickyCombatModes plugin, we need to move this event to the Events plugin with the same effective outputs as above.

Administrator: Set server name, ban IP/playername

Setting the server name is useful for example to version the server automatically so players know when patches have hit the server.

Also, how about ban/unban IP/playername? Would make sense in an administration plugin.

DM Events

A few more things I need as part of my server migration:

  • DM Give XP
  • DM Take XP
  • DM Give Level
  • DM Take Level
  • On pause event

Error in Plugins/Chat/Chat.cpp

Line 49
m_chatScript = GetServices()->m_config->Getstd::string("CHAT_SCRIPT", "");

Should be (?)
m_chatScript = GetServices()->m_config->Getstd::string("SCRIPT", "");

Constants missing in Constants.hpp

int ITEM_APPR_TYPE_SIMPLE_MODEL         = 0;
int ITEM_APPR_TYPE_WEAPON_COLOR         = 1;
int ITEM_APPR_TYPE_WEAPON_MODEL         = 2;
int ITEM_APPR_TYPE_ARMOR_MODEL          = 3;
int ITEM_APPR_TYPE_ARMOR_COLOR          = 4;
int ITEM_APPR_NUM_TYPES                 = 5;

I can add theem myself, but I don't know if I'm allowed to do it

SetAbilityScore Applying Racial Bonuses

As discussed with @mtijanic on Discord...

The SetAbilityScore method appears to be applying racial bonuses which is throwing off calculations.

Example:

Changing DEX from 12 to 13 causes an Elf to receive 15 DEX because the racial bonus is applied again.
Changing STRfrom 8 to 9 causes a Halfling to receive 7 STR because the racial penalty is applied again.

NWNX_Structs

https://github.com/NWNX/nwnx2-linux/blob/master/plugins/structs/nwnx_structs.nss

In the old NWNX_Structs plugin we had the ability to do a lot of things which manipulated internal structures. One feature in particular that I need is a way to add custom item properties onto items. I was able to do it before using code like this:


itemproperty ItemPropertyDirect (int nType, int nSubType, int nCostTable, int nCostValue, int nParamTable, int nParamValue)
{
    itemproperty ip = ItemPropertyAdditional(0);

    SetItemPropertyInteger(ip, 0, nType);
    SetItemPropertyInteger(ip, 1, nSubType);
    SetItemPropertyInteger(ip, 2, nCostTable);
    SetItemPropertyInteger(ip, 3, nCostValue);
    SetItemPropertyInteger(ip, 4, nParamTable);
    SetItemPropertyInteger(ip, 5, nParamValue);

    return ip;
}

Which created a normal item property and then turned around and overwrote its settings. It was a really good workaround for adding custom item properties to items.

CNWSCombatRound__StartCombatRound Possible issue with core API

I think there's a problem hooking the method CNWSCombatRound__StartCombatRound.

I'm getting crashes when the method fires on the server using the following code:

CombatEvents.hpp


#pragma once

#include "API/Types.hpp"
#include "Common.hpp"
#include "Services/Hooks/Hooks.hpp"
#include "ViewPtr.hpp"

namespace Events {

class CombatEvents
{
public:
    CombatEvents(NWNXLib::ViewPtr<NWNXLib::Services::HooksProxy> hooker);

private:
    static void StartCombatRoundHook(NWNXLib::API::CNWSCreature const*, uint32_t);
    static void StartCombatRoundHookShared
    (
        NWNXLib::Services::Hooks::CallType, 
        NWNXLib::API::CNWSCombatRound*,
        uint32_t
    );
    static NWNXLib::ViewPtr<NWNXLib::Hooking::FunctionHook> m_hook;
};

}

CombatEvents.cpp


#include "Events/CombatEvents.hpp"
#include "API/CNWSCreature.hpp"
#include "API/Functions.hpp"
#include "API/Globals.hpp"
#include "Events.hpp"
#include "Helpers.hpp"
#include "Services/Log/Log.hpp"
#include "ViewPtr.hpp"

namespace Events {

using namespace NWNXLib;
using namespace NWNXLib::API;
using namespace NWNXLib::Services;

NWNXLib::ViewPtr<NWNXLib::Hooking::FunctionHook> CombatEvents::m_hook;

CombatEvents::CombatEvents(ViewPtr<HooksProxy> hooker)
{
    hooker->RequestSharedHook<
        API::Functions::CNWSCombatRound__StartCombatRound, 
        int32_t, 
        API::CNWSCombatRound*,
        uint32_t>
        (
            &StartCombatRoundHookShared
        );

    // hooker->RequestExclusiveHook<API::Functions::CNWSCombatRound__StartCombatRound>(&CombatEvents::StartCombatRoundHook);
    // m_hook = hooker->FindHookByAddress(API::Functions::CNWSCombatRound__StartCombatRound);
}

void CombatEvents::StartCombatRoundHook(API::CNWSCreature const* thisPtr, uint32_t val)
{
    m_hook->CallOriginal<void>(thisPtr, val);
}


void CombatEvents::StartCombatRoundHookShared(
    Hooks::CallType type, 
    API::CNWSCombatRound* thisPtr,
    uint32_t val)
{
    // const bool before = type == Hooks::CallType::BEFORE_ORIGINAL;

    // if (before)
    // {
    //     //Events::SignalEvent("NWNX_ON_START_COMBAT_ROUND_BEFORE" , oid);
    //     // NOTE: Events won't be processed for disconnecting characters, e.g. RemoveEffect events.
    //     // If we wanted that to happen, we'd need to process the event like CServerAIMaster__GetPendingEvent.
    // }
    // else
    // {
    //     //Events::SignalEvent("NWNX_ON_START_COMBAT_ROUND_AFTER", oid);
    // }

}

}

To confirm it wasn't something I was doing, I swapped out the method I was trying to hook as well as its signature and it worked fine.

This is the version of my test that works.

CombatEvents.hpp (With the swapped out signature that works)


#pragma once

#include "API/Types.hpp"
#include "Common.hpp"
#include "Services/Hooks/Hooks.hpp"
#include "ViewPtr.hpp"

namespace Events {

class CombatEvents
{
public:
    CombatEvents(NWNXLib::ViewPtr<NWNXLib::Services::HooksProxy> hooker);

private:
    static void StartCombatRoundHook(NWNXLib::API::CNWSCreature const*, uint32_t);
    static void StartCombatRoundHookShared
    (
        NWNXLib::Services::Hooks::CallType, 
        NWNXLib::API::CNWSCreature*,
        uint16_t
    );
    static NWNXLib::ViewPtr<NWNXLib::Hooking::FunctionHook> m_hook;
};

}

CombatEvents.cpp (With the swapped out signature that works)


#include "Events/CombatEvents.hpp"
#include "API/CNWSCreature.hpp"
#include "API/Functions.hpp"
#include "API/Globals.hpp"
#include "Events.hpp"
#include "Helpers.hpp"
#include "Services/Log/Log.hpp"
#include "ViewPtr.hpp"

namespace Events {

using namespace NWNXLib;
using namespace NWNXLib::API;
using namespace NWNXLib::Services;

CombatEvents::CombatEvents(ViewPtr<HooksProxy> hooker)
{
    hooker->RequestSharedHook<
        API::Functions::CNWSCreature__CancelRest, 
        int32_t, 
        API::CNWSCreature*,
        uint16_t>
        (
            CombatEvents::StartCombatRoundHookShared
        );
}

void CombatEvents::StartCombatRoundHookShared(
    Hooks::CallType type, 
    API::CNWSCreature* thisPtr,
    uint16_t val)
{
    const bool before = type == Hooks::CallType::BEFORE_ORIGINAL;

    if (before)
    {
        Events::SignalEvent("NWNX_ON_START_COMBAT_ROUND_BEFORE" , thisPtr->m_idSelf);
    }
    else
    {
        Events::SignalEvent("NWNX_ON_START_COMBAT_ROUND_AFTER", thisPtr->m_idSelf);
    }

}


}

It's still possible there's something I'm doing wrong but I'm not sure what it could be. If you guys could point me in the direction to fix this I'm happy to give it a shot, I just don't know where to begin. :)

NWNX_Chat Skip

It looks like if you call SkipMessage, and later call SendMessage within the same event, it actually skips both messages instead of just the original.

In 1.69, you could do a SkipMessage and then immediately send a different message and have the new one go through.

I ran into this when I tried to do SkipMessage on a party chat message, and then sent a message by tell from an NPC to a player.

NWNX_Administration_DeletePlayerCharacter Setup to find .bic Directory by CD Key

I've been working to re-enable self-deletion of PCs for players in our mod. It appears that the NWNX_Administration_DeletePlayerCharacter is coded to go to the servervault\CDKey directory to find the .bic file.

    std::string bicname     = player->m_resFileName.GetResRefStr();
    std::string servervault = CExoString(Globals::ExoBase()->m_pcExoAliasList->GetAliasPath("SERVERVAULT", 0)).CStr();
    std::string cdkey       = exoApp->GetNetLayer()->GetPlayerInfo(player->m_nPlayerID)->GetPublicCDKey(0).CStr();

std::string filename = servervault + cdkey + "/" + bicname + ".bic";

However, since I prefer the old way of organizing the servervault by Player Name, I have this set in the nwnplayer.ini: Server Vault By Player Name=1
As a result, the NWNX_Administration_DeletePlayerCharacter doesn't work. Could this be modified/fixed to check by player name if the .bic doesn't exist in the CD Key directory, or instead use player name by default instead if that setting is enabled in the nwnplayer.ini?

Event Handler Bypassing

It'd be helpful to have a means of bypassing an event handler. My specific thought is in regards to the examine, with my current intent being to simply skip the examining and instead giving the player a message in their combat log.

However, wherever this idea can apply works for me!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.