PKEURO Twitter

Guys, long time no post – I thought I would let you know that I have set up pkeuro on twitter at @pkeuro. Feel free to follow and I will try and keep you updated on all things I am doing PK-wise and also post events from here.

Live Painkiller Server List

Can someone check that this Painkiller Server list is accurate? I would like to keep an eye on things 🙂


I am also trying to get a feel for how many people are playing PK these days, and justify any PK++ work.

If you cant post here, email me at dundarach ( at )

Posted in Uncategorized | 1 Reply

Painkiller MP Video

With the difficulties of making a video from PK, it is always good to see impressively put together videos. Paindemonium has given us exactly this, in the form of a video focusing on MP with some excellent frags and gameplay. Take a look and post your comments!


Also here :

<iframe width=”560″ height=”315″ src=”;controls=0&amp;showinfo=0″ frameborder=”0″ allow=”autoplay; encrypted-media” allowfullscreen></iframe>

Painkiller SP Map Support

For those that want it, here is a version of Painkiller.exe which supports listing SP maps for MP loading!

This is not essential for PKBeta testing, but useful if you like doing everything through the dedicated server interface / listen server menu ui. It goes without saying that this also does not require the game cd, and is fully compatible with Vanilla Painkiller.

PK++ Beta On Steamfish Updated

Right, we are now updated with the following changes. If they do not appear correctly, please communicate that HERE (in comments):

FIX: Player models now show correct weapon
FIX: Teleporter prediction turned off, was causing issues
FIX: Ravens/barrel removed
FIX: Loading times fixed
FIX: Local player jump sounds
FIX: Kill/out of level should work in warmup
FIX: Dedicated server now loads monsters
FIX: Clan arena and COOP modes shown in server create menu
FIX: Most monsters (90%) should work now on listen and dedicated
FIX: AI Brain changed for basic handling of multiple players
FIX: Respawnable on SP maps
ADD: Loc files for most maps! THANKS SYS!
ADD: Waypoint files for most maps! THANKS SYS!
ADD: Mapview files for most maps! THANKS SYS!


Weapon prediction issues
Interpolation model hovering
Item handling from SP maps for MP

If you get LScript errors, I need the name of the lua file, and the line number! LOOK AT YOUR script_error.log (and paste it here)!


PK++ Beta On Steamfish

I have put the PK++ beta version ( onto Steamfish and will maintain it from there. NOTE: This is in addition to PK++, so that I can do more testing without spoiling PK++ for the non-testers.

Simply run the updater twice and answer yes to adding desktop icons. You will find a new shortcut on the desktop to run PK++ BETA TEST.



ADD: Console now bound to F1 (may make key configurable later)
CHANGE: Console now completes on settings as well as commands
ADD: DeferLoadingPlayers and DeferLoadingRest for faster load times
FIX: Teleporters and Jumppads now work based on client, rather than server
CHANGE: Converted PK++ over to easier-to-maintain format

Have fun 🙂

About Demos

Demos were the original reason I started looking at PK, but in fixing demos a lot of other things need to be in place first. But before I explain that let me give an overview of demos as they are now.

Firstly when existing demos are played, they are simply rendering the few entities that you can see and nothing else. There is no game running, the player objects arent real, items/models are only there when you can see them, local player has no model. Also names are left out, comments, there is NO health or armour information. When you do not see the opponent, there is no way of telling where he is (I believe – need to check that).

This is slightly annoying, since I had planned to at least write a converter into any new/improved format. The fact a lot of the information I want is not there stored, or cannot be determined from the gameplay, is frustrating.

However, in order to create a new demo format – one where, say, you can run it at any speed, switch POVS, go spec, make movies from it. Effectively what I need is to write the netcode to file, and replay it. Obviously I would not want to store it at rendering fps, or even at netcode fps. To play it back, everything needs to be smooth, being played from any framerate. Of course this is where interpolation comes into play, and why it is so very important. With smooth interpolation I can replay demos and fill in the missing information.

The only thin I have yet to do is to tie up some loose ends of an initial snapshot of the level (item respawn times, etc), although in truth, this can just be captured from the netcode.

Another Small Update

This weekend was particularly productive, mainly because I provided a test version to some players who seemed happy with the progress.

As you may imagine, from tweaking the code I ended up with a version very far away from PK++. This step change is not ideal for testing properly, so it is important to trickle the changes into PK++ over a length of time.

My main objective was to put a lot of the netcode fixes into PK++. This is mainly concerned with interpolation, and determining where issues are in PK netcode and gameplay.

Before I add more, understand that interpolation is important because it allows players to run at much lower data rates from the server. This is important:

1. If you want the game to be stable with lots of players on the server.
2. If you want to add lots of monsters.
3. If you have demos of low quality and want to watch it smoothly.

Firstly before anything else in added a netgraph. This plots (much like Q3), ping over time (indicating packet loss too), as well as interpolation deltas (basically indicating how much interpolation is taking place). Testing indicated that PK suffers from a degree of flux in ping, with occasional lags due to certain events. On the whole though it didnt look that bad. Command is \drawlatencygraph 1. Obviously there is a lot of processing for this, so fps is damaged.

Next for interpolation, I wrote three methods. The first is linear interpolation for each player. I decided that it is possible that lagging players on bad connection might not update the server at the same rate, so would still move badly if interpolation was done on a per-game-frame basis. Instead what I decided to do was look for updates on players themselves, and have each player in their own interpolation space-time. The second and third methods are quadratic, and the average of linear and quadratic, respectively. At very low update rates I would suspect the quadratic to be slightly better (mainly on vertical movement). Command is \interpolation 1/2/3. Testing showed that it was playable at \serverframerate 15 (equivalent to snaps), although 30 was playable. Remember \netstats 1 to view what is going on.

Here I also added timenudge (which qw and q3 players will know). This moves the interpolation forward or backwards in time. A positive timenudge can allow more for variations in ping, whereas a negative timenudge may draw the players closer to their actual position.

Next I added an option to interpolate from the previous position or from the last interpolation position. What I found was that the last interpolated position method gave worse results.

Next I added a method to automatically adjust timenudge for latency variation. Although this was damped quite heavily, it looks to be unstable on first testing at certain times. I would be a nice method if it works.

Next I tweaked teleport behaviour on the client. Up until now on higher pings, teleporting would either result in a judder or double teleport. Teleporting is now entirely predicted on the client, so server updates are ignored (mistakes are captured in synchronisation frames anyway). Likewise the jumppad was updated. Both methods help reduce the feeling of lag on the client which is important for movement. Weapon prediction needs to be completed, and possibly zero ping at some stage soon.

Console commands were altered slightly so that settings could be edited. This will mean less actual code, and less inconsistency between what is seen in the console between commands.

Finally I will update you on my next task – looking at rendering framerate. I was aware testing that my fps dropped heavily in FFA once it got above 10 players. Without players on the server I get 190fps on sacred, but it can drop as low as 40 in FFA. As a quick test it seems that 90fps of the drop might be from drawing items which arent required for rendering (which can be fixed by hiding things you cannot see), and 60fps from the game ticks themselves (although admittedly I was testing with bots). I have already done some work on improving ticks, so will migrate that across and test. I would suggest that even saving 10 or 20 fps might have a real impact on game playability.

For a test version I will provide this soon, but please do not expect too much yet since it is work in progress and most of the work is elsewhere and yet to be transferred. You can download a test version always here:


which you pop into \Data\ (remember to back up the old one. Then run normal (not PK++), or alternatively rename this file to PKPlus.pak and use PK++. Please set \interpolationnosmooth 1 though or you will have issues. If you do not understand it, or have issues, I am not yet helping you fix them until I reach a beta test phase. You are welcome to paste feedback though, positive or negative (if it is negative – remember it is work in progress!). Also fixes/bugs/suggestions are more than welcome, either here or direct email to

I am grateful for any help from now on, be it images/sounds/code/testing/ideas. I am more than willing to accept help in any way since my free time is limited.

Have fun and happy fragging!

A Small Update

I have not had time to work on it recently, but the last series of tests were promising.

Running PK online at a 6th of the bandwidth and still relatively smooth gameplay. There may still be some issues created by the server not running at a constant rate, which in itself might resolve a lot of the issues. Other things which need attention are:

1. Local client prediction of events (item, teleport, weapon).
2. Item events in PK code are not specified by time (PCF themselves criticised this!). What it means is if you have an update every 50ms, then all events over that last 50ms happen all at once. This is not particularly healthy for the code where 50ms can easily represent 6 or so frames of gameplay. At lower update rates this becomes signifcantly stuttery.
3. Local client anti-lag test, i.e. what you hit on the client is what you hit on the server.

I will keep you updated soon and hopefully issue a early test version. Do not forget that perfection is iterative and it will take time with your help to improve.

PK++ Progress 14/02/07


Firstly PCF did not write interpolation properly, on mouse, on animations, or anything. What they typically did was:

rotation = m_lastRotation + rotationDelta*0.33

where rotationDelta = m_lastRotation – m_nextRotation

Whereas what they should have is:

rotation = m_lastRotation + rotationDeltaRate*deltatime

where rotationDeltaRate = (m_lastRotation – m_nextRotation) / deltatimeperiod

They have made this mistake lots. Fixing interpolation in the bits we can see is straightforward. As I discussed with PeTjA, we can apply this interpolation to ALL items on the map, so that everything moves smoothly.

Typically linear interpolation is used for unpredictable items, and Catmull-Rom (cubic) splines for predictable movement (e.g. any mass subjected to constant or continuous accelerations.)


Yikes! This is an important one. Ever since I improved item spawn times for PK++, I have always been suspicious of how accurate PKs timing is. We all know it has the ability to run too fast/slow at times. To test this I relied on the LUA os.clock() and os.time(). os.time() gives tick time (since 1982 or so) in seconds, whereas os.clock() gives seconds fractions since the code begins. It should be noted that math.floor(os.time()-os.clock()) is constant and remains constant.

The first problem is that PK works out time by adding deltas. This is CRAZY, since floating point (even double) will exhibit rounding errors quite quickly through any addition.

To test this, I set up the delta addition in comparison to os.time and os.clock. They were WAY off. Particularly because my machine is slow and does not always achieve the 45 FPS of the server. When the machine is slow it ASSUMES that the delta is 1.0/FPS regardless of whether it achieves that or not.

It gets worse though…

The MEASURED delta used varies by a huge amount, but dependent on it trying to hit a certain FPS. This is because they have imposed a minimum loop period of 30FPS or 0.0167secs. What this means is that loops can only occur in multiples of 30FPS, but such that over a second or so, they will meet the total FPS.

Say for example the desired FPS is 45. For PK this will run like this:

30,60,30,60,30,60,30,60,30,60,30,60,30,60 etc.

Of course the average delta for 45FPS is correct.

In other words the loops are not evenly spaced in time. What is terrible for netcode and interpolation and ANYTHING else.

This explains why 30 and 60 FPS seem to be smoothest. Iterations seem to only occur in 0-30, 30 or 62.5 FPS steps.

It is possible to stall the frames so they become evenly spaced (by setting FPS very very high and limiting within the LUA). But the issue is not that a frame goes too quickly, but too slowly, to average.

The maximum speed at which Havok can run is also set, at 62.5 FPS (or rather, this is the minimum time step it can accept).

Finally we can address these issues by setting the frame rate to zero (so max speed), then controlling the actual tickrate through the LUA. A suitable tickrate is 62.5 FPS providing one tick per physics iteration. This has already been tested for CPU usage and is very low.

Given this, the number of updates a client can recieve (q3s snaps) MUST be limited on the client. After testing, somewhere between 10 and 20 gives reasonable looking gameplay. As a current rule of thumb, the data is :

= number of players * update rate (serverframerate on client) * 30

So 32 players at 10fps is around 9KBps which is reasonable.

Additional work needs to be completed before reducing the update data further. This should be possible without access to the source code.

PK++ Progress 07/02/07


Interpolation FIXED! (finally)

What seems to be the case, is that part of the player animation was causing a glitch which resulted in the player location on receiving the player frame to be mislocated. This is now fixed by turning off animation until I get more time to look at it. Right now animation is synchronised, but I am considering having this predicted on the client.

What this means in real terms is that gameplay at low data rates will be smooth. Since PCF did not understand what interpolation was, it broke as you set serverframerate(client) less than the actual server frame rate. This meant that low serverframerate(client) looks very jerky/choppy. It should be noted too that enemyprediction also damages movement on the server.

Given this, I can now interpolate ALL moving items between frames, so everything is smooth.

The important part here is that serverframerate(client) can be much less than the server tick rate. It is considered that good physics occurs on servers set to 60 fps, but 60fps of data for ffa is too much. By lowering serverframerate(client) you can still have 60fps on the server, and still have smooth, low bandwidth gameplay.

By comparison, Q3 and CS both use 20 updates to the client per second (although due to server tickrate), although HPBs can lessen this if required. Gameplay is still smooth on both these games, and no one notices the additional latency caused by the interpolation. It is possible to correct for this using unlagged/anti-lag which PK has the foundations for already. Whether we go for full client-side anti-lag or not will be decided in due course.

Where PK loses out is hiding things you cannot see from the update. The way Q3 works is to only update players which you might be able to see/hear, and not ones way off in the distance. We cannot yet do this in PK, and cannot without the source code. I may have to think of other ways to reduce data if required. If the main issue is reducing data for COOP, then simply I can not update monsters which NO ONE can see or hear – they will still be there on the server though.

I also loaded up Q3 to compare upstream and downstream packet sizes, and PK and Q3 are now similar.


SP maps are beautiful, and if in any doubt load up C2L5_Town or any and see how good they look on full detail. However, a number of the maps do not work on dedicated server – and in fact crash PK out completely. This is the reason, for example, why there are no conversions of City on the Water which is a great map.

The loading problem is now FIXED! (this is important!)

ALL SP maps can now be used on dedicated server, which should also fix some issues found by mappers 🙂

Also when loading SP maps in MP now, the items which do not belong in MP are not loaded (such as monster Ambush). Player respawning can now take place from monster respawn points which seem nicely distributed. The intention is that for SP maps which are obviously not set up for MP, items will be placed by code. Generally the level exit will be replaced by a teleport to start – much like Q1 did. This forms a loop of what is initially a linear map. Other item placement issues will be considered later – but what is most important is that the loading of ALL maps into MP works and makes sense.


More work was completed on AI Brain, but essentially I need to work through each monster, making sure they do not assume a single SP player, and can instead attack one of a group of players. I am not worried about this at all.

I suggest that we have around three type of COOP: SP COOP (SP game with more than one player), MP COOP (ffa with monsters), and COOP Arena (all vs. monsters).


I have written my own mouse code, which reduces mouse lag, and adds mouse acceleration and smoothing as required.


I added two more parameters to the \addthing and \addmonster commands, firstly the number of things/monsters added at once. This seems to lag out clients with larger numbers, so I may have to add them over several frames.

Secondly I added scale to both. It is great fun playing with the scale of various items. In fact our test map, DM_Boss, can quickly become too small, so Killua has made another test map without walls. A 200xscale Panzer_Demon for example is awesomely impressive. Even normal monsters resized to boss-size are worth seeing.


With interpolation out of the way, other fixes are relatively easy, so I should be quicker with them. There may be some hacks of the exe/dll I might want to do, but other than that you should see more progress soon!

PK++ Progress 15/01/07


Interpolation now works, although there is a small glitch I need to resolve which might be a rendering issue. Other than that play is smooth at 1 network frame per second, but much more reasonable at about 10-20. PCFs interpolation appears to be very wrong, and it is worth noting that it screws up servers to have it enabled too. Player pitch/yaw is also being interpolated but needs more work.

Extrapolation was added too, although we will need to play with this. It may be possible to auto-compensate for lag, both on the server and client. Extrapolation of course makes things slightly less smooth, but this can be controlled.

I have yet to play with item/weapon prediction.

I have to look at whether I can reduce the amount of data per player.

I also added all the netcode commands to console.


Killua-chan provided an excellent map, although I believe PeTjA has some minor alterations.

It is possible to add a lot of the monsters already, but their code requires a listen server. Once I have perfected how to deal with multiple players using one monster, I will duplicate to all (probably via the AI Brain code).

My thoughts for COOP are basically either SP COOP or MP COOP, MP COOP perhaps more like ffa with monsters. I also thought about a COOP Arena gamemode.. where as a group of players you have to make it through progressively more difficult levels. Imagine DM_Boss with Thor to start, you have to kill him without you all dying, then level 2 is the same map, but with Thor and Panzer_Demon, and so on…


Now is a good time to work on structuring the code better – so this is what I am doing, mainly the game and player code. I wish to use polymorphism rather than conditionals for custom gamemode responses (if you know what I mean). This will make thing a lot easier to make new custom gamemodes without screwing up existing code – an important method


At a glance it might be possible to try some new movement code, but we can try this later.


I am still yet to confirm whether I can obtain the CDKEY to MD5/RSA. Without it, making something unqiue generated from the game might be difficult.


Netcode improvements make writing this easier.

Progress on PK++

Guys, I thought it would be sensible to make more visable some of the progress being made on PK++. A small few were aware of the work going on, albeit slow, but there is no harm in making it more public.

My intention is to fix some of the issues as quickly as possible and update via PK++. My motivation is to add to the game as much as fix some of the important remaining issues.

If anyone is willing to help out, any contribution is more than welcome! Please contact me through or add me on msn from that address.

Progress on PK++

Guys, I thought it would be sensible to make more visable some of the progress being made on PK++. A small few were aware of the work going on, albeit slow, but there is no harm in making it more public.

My intention is to fix some of the issues as quickly as possible and update via PK++. My motivation is to add to the game as much as fix some of the important remaining issues.

If anyone is willing to help out, any contribution is more than welcome! Please contact me through or add me on msn from that address.

Running PK on a Laptop!!!

Well, based on a lot of frustrated posts on the DC Forum, a lot of SP and MP gamers have had problems running PK on laptops with integrated graphics cards (namely Intel). The reason for this is that Intel do not support T&L (transform and lighting) required for many DirectX games.

Since what PK requires is T&L hardware support, to get around this, all you need to do is emulate that support in software. Since it doesnt use it much, you do not get much drop in performance.

A tool exists for doing this; namely 3DAnalyze made by TOMMTI Systems. You can download that HERE. Their website is here

Download it, unzip it (basically run it), then run the App (3DAnalyze.exe) and you should see something like this:

Firstly select the Painkiller.exe, then tick the Emulate HW TnL caps box, then click Run.

There are other options of running in a Window etc. but you can try those out for yourselves.

PK Command Line Options

Since I have never seen this anywhere else, I thought I would post ALL the valid PK commandline options. The most interesting is probably the optional hardware class option (+hwclass). The rest are fairly well known. +speed is your connection speed, 0=modem, etc.


+connect [xx.xx.xx.xx>]
+playrecording [demo name]
+name [player name]
+map [map name]
+interface [xx.xx.xx.xx]
+speed [0,1,2,3]
+port [xxxx]
+maxfps [xx]
+password [xxxxxx]
+hwclass [tnl, nv20, nv25, r200, nv30, nv40]

Steamfish Maps Added

Just a quick note to say that I have added the following maps to Steamfish:

DM_Vengeance.pkm (BETA)

Which hopefully will not kill pkeuro bandwidth. If someone has other hosting, please let me know. Run your Steamfishes now!